foobar2000 SDK  2015-08-03
dsp.cpp
Go to the documentation of this file.
1 #include "foobar2000.h"
2 #include <math.h>
3 
5 
7 
9 {
10  if (idx<m_data.get_count())
12 }
13 
15 {
16  t_size n, m = m_data.get_count();
17  for(n=0;n<m;n++)
18  if (mask[m])
20  m_data.remove_mask(mask);
21 }
22 
24 {
25  t_size max = get_count();
26  if (idx>max) idx = max;
28  if (m_recycled.get_count()>0)
29  {
30  t_size best;
31  if (hint_size>0)
32  {
33  best = 0;
34  t_size best_found = m_recycled[0]->get_data_size(), n, total = m_recycled.get_count();
35  for(n=1;n<total;n++)
36  {
37  if (best_found==hint_size) break;
38  t_size size = m_recycled[n]->get_data_size();
39  int delta_old = abs((int)best_found - (int)hint_size), delta_new = abs((int)size - (int)hint_size);
40  if (delta_new < delta_old)
41  {
42  best_found = size;
43  best = n;
44  }
45  }
46  }
47  else best = m_recycled.get_count()-1;
48 
49  ret = m_recycled.remove_by_idx(best);
50  ret->set_sample_count(0);
51  ret->set_channels(0);
52  ret->set_srate(0);
53  }
54  else ret = pfc::rcnew_t<audio_chunk_impl>();
55  if (idx==max) m_data.add_item(ret);
56  else m_data.insert_item(ret,idx);
57  return &*ret;
58 }
59 
61 {
62  bool blah = false;
63  t_size idx;
64  for(idx=0;idx<get_count();)
65  {
66  audio_chunk * chunk = get_item(idx);
67  if (!chunk->is_valid())
68  {
69  chunk->reset();
70  remove_by_idx(idx);
71  blah = true;
72  }
73  else idx++;
74  }
75  if (blah) console::info("one or more bad chunks removed from dsp chunk list");
76 }
77 
78 
80 {
82  if (!g_get_interface(ptr,p_preset.get_owner())) return false;
83  return ptr->instantiate(p_out,p_preset);
84 }
85 
87 {
89  if (!g_get_interface(ptr,p_guid)) return false;
90  dsp_preset_impl preset;
91  if (!ptr->get_default_preset(preset)) return false;
92  return ptr->instantiate(p_out,preset);
93 }
94 
96 {
98  if (!g_get_interface(ptr,p_guid)) return false;
99  ptr->get_name(p_out);
100  return true;
101 }
102 
103 bool dsp_entry::g_dsp_exists(const GUID & p_guid)
104 {
106  return g_get_interface(blah,p_guid);
107 }
108 
109 bool dsp_entry::g_get_default_preset(dsp_preset & p_out,const GUID & p_guid)
110 {
112  if (!g_get_interface(ptr,p_guid)) return false;
113  return ptr->get_default_preset(p_out);
114 }
115 
117  t_size n, count = get_count();
118  p_stream->write_lendian_t(count,p_abort);
119  for(n=0;n<count;n++) {
120  get_item(n).contents_to_stream(p_stream,p_abort);
121  }
122 }
123 
125  t_uint32 n,count;
126 
127  remove_all();
128 
129  p_stream->read_lendian_t(count,p_abort);
130 
131  dsp_preset_impl temp;
132 
133  for(n=0;n<count;n++) {
134  temp.contents_from_stream(p_stream,p_abort);
135  add_item(temp);
136  }
137 }
138 
139 
141  p_data.copy(m_data);
142  return true;
143 }
144 
146  m_data.copy(p_data);
147 }
148 
150  m_data.remove_all();
151 }
152 
154  m_data.contents_to_stream(p_stream,p_abort);
155 }
156 
158  m_data.contents_from_stream(p_stream,p_abort);
159 }
160 
162 {
163  remove_mask(bit_array_one(p_index));
164 }
165 
167 {
168  insert_item(p_data,get_count());
169 }
170 
172 {
174 }
175 
177 {
178  p_out.remove_all();
179  t_size n, m = get_count();
180  for(n=0;n<m;n++)
181  {
182  service_ptr_t<dsp> temp;
183  if (dsp_entry::g_instantiate(temp,get_item(n)))
184  p_out.add_item(temp);
185  }
186 }
187 
189 {
190  return m_data.get_count();
191 }
192 
194 {
195  return *m_data[p_index];
196 }
197 
199 {
200  *m_data[p_index] = p_data;
201 }
202 
204 {
205  m_data.insert_item(new dsp_preset_impl(p_data),p_index);
206 }
207 
209 {
210  m_data.delete_mask(p_mask);
211 }
212 
214 {
215  m_data.delete_all();
216 }
217 
219  t_size size = get_data_size();
220  p_stream->write_lendian_t(get_owner(),p_abort);
221  p_stream->write_lendian_t(size,p_abort);
222  if (size > 0) {
223  p_stream->write_object(get_data(),size,p_abort);
224  }
225 }
226 
228  t_uint32 size;
229  GUID guid;
230  p_stream->read_lendian_t(guid,p_abort);
231  set_owner(guid);
232  p_stream->read_lendian_t(size,p_abort);
233  if (size > 1024*1024*32) throw exception_io_data();
234  set_data_from_stream(p_stream,size,p_abort);
235 }
236 
238  t_uint32 size;
239  GUID guid;
240  p_stream->read_lendian_t(guid,p_abort);
241  p_stream->read_lendian_t(size,p_abort);
242  if (size > 1024*1024*32) throw exception_io_data();
243  p_stream->skip_object(size,p_abort);
244 }
245 
247  m_data.set_size(p_bytes);
248  if (p_bytes > 0) p_stream->read_object(m_data.get_ptr(),p_bytes,p_abort);
249 }
250 
251 void dsp_chain_config::copy(const dsp_chain_config & p_source) {
252  remove_all();
253  t_size n, m = p_source.get_count();
254  for(n=0;n<m;n++)
255  add_item(p_source.get_item(n));
256 }
257 
259 {
261  if (!g_get_interface(entry,p_guid)) return false;
262  return entry->have_config_popup();
263 }
264 
266 {
267  return g_have_config_popup(p_preset.get_owner());
268 }
269 
270 bool dsp_entry::g_show_config_popup(dsp_preset & p_preset,HWND p_parent)
271 {
273  if (!g_get_interface(entry,p_preset.get_owner())) return false;
274  return entry->show_config_popup(p_preset,p_parent);
275 }
276 
277 void dsp_entry::g_show_config_popup_v2(const dsp_preset & p_preset,HWND p_parent,dsp_preset_edit_callback & p_callback) {
279  if (g_get_interface(entry,p_preset.get_owner())) {
281  if (entry->service_query_t(entry_v2)) {
282  entry_v2->show_config_popup_v2(p_preset,p_parent,p_callback);
283  } else {
284  dsp_preset_impl temp(p_preset);
285  if (entry->show_config_popup(temp,p_parent)) p_callback.on_preset_changed(temp);
286  }
287  }
288 }
289 
291 {
294  e.reset();
295  while(e.next(ptr))
296  {
297  if (ptr->get_guid() == p_guid)
298  {
299  p_out = ptr;
300  return true;
301  }
302  }
303  return false;
304 }
305 
306 bool resampler_entry::g_get_interface(service_ptr_t<resampler_entry> & p_out,unsigned p_srate_from,unsigned p_srate_to)
307 {
308  service_ptr_t<dsp_entry> ptr_dsp;
309  service_ptr_t<resampler_entry> ptr_resampler;
311  e.reset();
312  float found_priority = 0;
314  while(e.next(ptr_dsp))
315  {
316  if (ptr_dsp->service_query_t(ptr_resampler))
317  {
318  if (p_srate_from == 0 || ptr_resampler->is_conversion_supported(p_srate_from,p_srate_to))
319  {
320  float priority = ptr_resampler->get_priority();
321  if (found.is_empty() || priority > found_priority)
322  {
323  found = ptr_resampler;
324  found_priority = priority;
325  }
326  }
327  }
328  }
329  if (found.is_empty()) return false;
330  p_out = found;
331  return true;
332 }
333 
334 bool resampler_entry::g_create_preset(dsp_preset & p_out,unsigned p_srate_from,unsigned p_srate_to,float p_qualityscale)
335 {
337  if (!g_get_interface(entry,p_srate_from,p_srate_to)) return false;
338  return entry->create_preset(p_out,p_srate_to,p_qualityscale);
339 }
340 
341 bool resampler_entry::g_create(service_ptr_t<dsp> & p_out,unsigned p_srate_from,unsigned p_srate_to,float p_qualityscale)
342 {
344  if (!g_get_interface(entry,p_srate_from,p_srate_to)) return false;
345  dsp_preset_impl preset;
346  if (!entry->create_preset(preset,p_srate_to,p_qualityscale)) return false;
347  return entry->instantiate(p_out,preset);
348 }
349 
350 
352  const t_size count = v1.get_count();
353  if (count != v2.get_count()) return false;
354  for(t_size walk = 0; walk < count; ++walk) {
355  if (v1.get_item(walk) != v2.get_item(walk)) return false;
356  }
357  return true;
358 }
360 {
361  const t_size count = get_count();
362  bool added = false;
363  for(unsigned n=0;n<count;n++)
364  {
366  if (dsp_entry::g_get_interface(ptr,get_item(n).get_owner()))
367  {
368  if (added) p_out += ", ";
369  added = true;
370 
371  pfc::string8 temp;
372  ptr->get_name(temp);
373  p_out += temp;
374  }
375  }
376 }
377 
378 void dsp::run_abortable(dsp_chunk_list * p_chunk_list,const metadb_handle_ptr & p_cur_file,int p_flags,abort_callback & p_abort) {
379  service_ptr_t<dsp_v2> this_v2;
380  if (this->service_query_t(this_v2)) this_v2->run_v2(p_chunk_list,p_cur_file,p_flags,p_abort);
381  else run(p_chunk_list,p_cur_file,p_flags);
382 }
383 
384 namespace {
385  class dsp_preset_edit_callback_impl : public dsp_preset_edit_callback {
386  public:
387  dsp_preset_edit_callback_impl(dsp_preset & p_data) : m_data(p_data) {}
388  void on_preset_changed(const dsp_preset & p_data) {m_data = p_data;}
389  private:
390  dsp_preset & m_data;
391  };
392 };
393 
394 bool dsp_entry_v2::show_config_popup(dsp_preset & p_data,HWND p_parent) {
395  PFC_ASSERT(p_data.get_owner() == get_guid());
396  dsp_preset_impl temp(p_data);
397 
398  {
399  dsp_preset_edit_callback_impl cb(temp);
400  show_config_popup_v2(p_data,p_parent,cb);
401  }
402  PFC_ASSERT(temp.get_owner() == get_guid());
403  if (temp == p_data) return false;
404  p_data = temp;
405  return true;
406 }
static bool g_get_default_preset(dsp_preset &p_out, const GUID &p_guid)
Definition: dsp.cpp:109
virtual void on_preset_changed(const dsp_preset &)=0
void remove_all()
Definition: dsp.h:12
void contents_to_stream(stream_writer *p_stream, abort_callback &p_abort) const
Definition: dsp.cpp:116
Interface to a DSP chunk list. A DSP chunk list object is passed to the DSP chain each time...
Definition: dsp.h:2
static bool g_instantiate_default(service_ptr_t< dsp > &p_out, const GUID &p_guid)
Definition: dsp.cpp:86
void reset()
Definition: service.h:578
static bool g_show_config_popup(dsp_preset &p_preset, HWND p_parent)
Definition: dsp.cpp:270
void add_item(const dsp_preset &p_data)
Definition: dsp.cpp:166
static void g_contents_from_stream_skip(stream_reader *p_stream, abort_callback &p_abort)
Definition: dsp.cpp:237
virtual t_size get_count() const =0
Definition: pfc.h:71
bool is_empty() const
Definition: service.h:120
void remove_item(t_size p_index)
Definition: dsp.cpp:161
void reset()
Resets all audio_chunk data.
Definition: audio_chunk.h:140
virtual void set_srate(unsigned val)=0
Sets sample rate of contained audio data.
void info(const char *p_message)
Definition: console.cpp:4
Bit array interface class, constant version (you can only retrieve values). Range of valid indexes d...
Definition: bit_array.h:6
void set_data(const dsp_chain_config &p_data)
Definition: dsp.cpp:145
pfc::list_t< pfc::rcptr_t< audio_chunk > > m_data
Definition: dsp.h:34
void insert_item(const dsp_preset &p_data, t_size p_index)
Definition: dsp.cpp:203
Interface to container of a chunk of audio data. See audio_chunk_impl for an implementation.
Definition: audio_chunk.h:5
void instantiate(service_list_t< dsp > &p_out)
Definition: dsp.cpp:176
pfc::list_t< pfc::rcptr_t< audio_chunk > > m_recycled
Definition: dsp.h:34
virtual const dsp_preset & get_item(t_size p_index) const =0
void remove_all()
Definition: dsp.cpp:171
void remove_bad_chunks()
Definition: dsp.cpp:60
void replace_item(const dsp_preset &p_data, t_size p_index)
Definition: dsp.cpp:198
static bool g_create(service_ptr_t< dsp > &p_out, unsigned p_srate_from, unsigned p_srate_to, float p_qualityscale)
Definition: dsp.cpp:341
t_size get_count() const
Definition: list.h:365
const T * get_ptr() const
Definition: list.h:375
void remove_mask(const bit_array &mask)
Definition: dsp.cpp:14
void remove_mask(const bit_array &mask)
Definition: list.h:517
t_size get_count() const
Definition: dsp.cpp:4
void get_name_list(pfc::string_base &p_out) const
Definition: dsp.cpp:359
static bool equals(dsp_chain_config const &v1, dsp_chain_config const &v2)
Definition: dsp.cpp:351
void run_abortable(dsp_chunk_list *p_chunk_list, const metadb_handle_ptr &p_cur_file, int p_flags, abort_callback &p_abort)
Definition: dsp.cpp:378
audio_chunk * get_item(t_size n) const
Definition: dsp.cpp:6
static bool g_have_config_popup(const GUID &p_guid)
Definition: dsp.cpp:258
size_t t_size
Definition: int_types.h:48
static bool g_get_interface(service_ptr_t< dsp_entry > &p_out, const GUID &p_guid)
Definition: dsp.cpp:290
void set_data_from_stream(stream_reader *p_stream, t_size p_bytes, abort_callback &p_abort)
Definition: dsp.cpp:246
t_size add_item(const T &item)
Definition: list.h:522
bool show_config_popup(dsp_preset &p_data, HWND p_parent)
Definition: dsp.cpp:394
T remove_by_idx(t_size idx)
Definition: list.h:331
audio_chunk * insert_item(t_size idx, t_size hint_size=0)
Definition: dsp.cpp:23
audio_chunk * add_item(t_size hint_size=0)
Definition: dsp.h:10
static bool g_dsp_exists(const GUID &p_guid)
Definition: dsp.cpp:103
bool is_valid() const
Returns whether the chunk contents are valid (for bug check purposes).
static void g_show_config_popup_v2(const dsp_preset &p_preset, HWND p_parent, dsp_preset_edit_callback &p_callback)
Definition: dsp.cpp:277
void remove_all()
Definition: list.h:530
virtual GUID get_owner() const =0
void contents_from_stream(stream_reader *p_stream, abort_callback &p_abort)
Definition: dsp.cpp:124
virtual void set_channels(unsigned p_count, unsigned p_config)=0
Sets channel count / channel map.
void set_size(t_size p_count)
Definition: list.h:316
static bool g_instantiate(service_ptr_t< dsp > &p_out, const dsp_preset &p_preset)
Definition: dsp.cpp:79
void remove_by_idx(t_size idx)
Definition: dsp.cpp:8
t_size insert_item(const t_in &item, t_size idx)
Definition: list.h:323
void remove_mask(const bit_array &p_mask)
Definition: dsp.cpp:208
static bool g_create_preset(dsp_preset &p_out, unsigned p_srate_from, unsigned p_srate_to, float p_qualityscale)
Definition: dsp.cpp:334
void contents_from_stream(stream_reader *p_stream, abort_callback &p_abort)
Definition: dsp.cpp:227
bool get_data(dsp_chain_config &p_data) const
Definition: dsp.cpp:140
void copy(const dsp_chain_config &p_source)
Definition: dsp.cpp:251
t_size get_count() const
Definition: dsp.cpp:188
const dsp_preset & get_item(t_size p_index) const
Definition: dsp.cpp:193
static bool g_name_from_guid(pfc::string_base &p_out, const GUID &p_guid)
Definition: dsp.cpp:95
void contents_to_stream(stream_writer *p_stream, abort_callback &p_abort) const
Definition: dsp.cpp:218
bool next(service_ptr_t< t_query > &p_out)
Definition: service.h:587
virtual void set_sample_count(t_size val)=0
Sets number of valid samples in the buffer. WARNING: sample count * channel count should never be abo...
static bool g_get_interface(service_ptr_t< resampler_entry > &p_out, unsigned p_srate_from, unsigned p_srate_to)
Definition: dsp.cpp:306
void get_data_raw(stream_writer *p_stream, abort_callback &p_abort)
Retrieves state of the variable. Called only from main thread, when writing configuration file...
Definition: dsp.cpp:153
uint32_t t_uint32
Definition: int_types.h:5
void set_data_raw(stream_reader *p_stream, t_size p_sizehint, abort_callback &p_abort)
Sets state of the variable. Called only from main thread, when reading configuration file...
Definition: dsp.cpp:157