Guitarix
gx_convolver.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3  * Copyright (C) 2011 Pete Shorthose
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  * --------------------------------------------------------------------------
19  */
20 
21 /* ------- This is the guitarix convolver, part of gx_engine_audio ------- */
22 
23 #include "engine.h"
24 
25 /****************************************************************
26  ** some pieces in this file are copied from jconvolver
27  */
28 
29 /****************************************************************
30  ** AudioFile
31  */
32 
33 namespace gx_engine {
34 
36  reset();
37 }
38 
39 
41  close();
42 }
43 
44 
45 void Audiofile::reset(void) {
46  _sndfile = 0;
47  _type = TYPE_OTHER;
48  _form = FORM_OTHER;
49  _rate = 0;
50  _chan = 0;
51  _size = 0;
52 }
53 
54 
55 int Audiofile::open_read(string name) {
56  SF_INFO I;
57 
58  reset();
59 
60  if ((_sndfile = sf_open(name.c_str(), SFM_READ, &I)) == 0) return ERR_OPEN;
61 
62  switch (I.format & SF_FORMAT_TYPEMASK) {
63  case SF_FORMAT_CAF:
64  _type = TYPE_CAF;
65  break;
66  case SF_FORMAT_WAV:
67  _type = TYPE_WAV;
68  break;
69  case SF_FORMAT_AIFF:
70  _type = TYPE_AIFF;
71  break;
72  case SF_FORMAT_WAVEX:
73 #ifdef SFC_WAVEX_GET_AMBISONIC
74  if (sf_command(_sndfile, SFC_WAVEX_GET_AMBISONIC, 0, 0) == SF_AMBISONIC_B_FORMAT)
75  _type = TYPE_AMB;
76  else
77 #endif
78  _type = TYPE_WAV;
79  }
80 
81  switch (I.format & SF_FORMAT_SUBMASK) {
82  case SF_FORMAT_PCM_16:
83  _form = FORM_16BIT;
84  break;
85  case SF_FORMAT_PCM_24:
86  _form = FORM_24BIT;
87  break;
88  case SF_FORMAT_PCM_32:
89  _form = FORM_32BIT;
90  break;
91  case SF_FORMAT_FLOAT:
92  _form = FORM_FLOAT;
93  break;
94  }
95 
96  _rate = I.samplerate;
97  _chan = I.channels;
98  _size = I.frames;
99 
100  return 0;
101 }
102 
103 
104 int Audiofile::close(void) {
105  if (_sndfile) sf_close(_sndfile);
106  reset();
107  return 0;
108 }
109 
110 
111 int Audiofile::seek(uint32_t posit) {
112  if (!_sndfile) return ERR_MODE;
113  if (sf_seek(_sndfile, posit, SEEK_SET) != posit) return ERR_SEEK;
114  return 0;
115 }
116 
117 
118 int Audiofile::read(float *data, uint32_t frames) {
119  return sf_readf_float(_sndfile, data, frames);
120 }
121 
122 bool read_audio(const std::string& filename, unsigned int *audio_size, int *audio_chan,
123  int *audio_type, int *audio_form, int *audio_rate, float **buffer) {
124  Audiofile audio;
125  if (audio.open_read(filename)) {
126  gx_print_error("jconvolver", "Unable to open '" + filename + "'");
127  *audio_size = *audio_chan = *audio_type = *audio_form = *audio_rate = 0;
128  *buffer = 0;
129  return false;
130  }
131  *audio_size = audio.size();
132  *audio_chan = audio.chan();
133  *audio_type = audio.type();
134  *audio_form = audio.form();
135  *audio_rate = audio.rate();
136  const unsigned int limit = 2000000; // arbitrary size limit
137  if (*audio_size > limit) {
139  "jconvolver", (boost::format(_("too many samples (%1%), truncated to %2%"))
140  % *audio_size % limit).str());
141  *audio_size = limit;
142  }
143  if (*audio_size * *audio_chan == 0) {
144  gx_print_error("jconvolver", "No samples found");
145  *audio_size = *audio_chan = *audio_type = *audio_form = *audio_rate = 0;
146  *buffer = 0;
147  return false;
148  }
149  *buffer = new float[*audio_size * *audio_chan];
150  if (audio.read(*buffer, *audio_size) != static_cast<int>(*audio_size)) {
151  delete[] *buffer;
152  gx_print_error("jconvolver", "Error reading file");
153  *audio_size = *audio_chan = *audio_type = *audio_form = *audio_rate = 0;
154  *buffer = 0;
155  return false;
156  }
157  return true;
158 }
159 
160 /****************************************************************
161  ** GxConvolverBase
162  */
163 
165  if (is_runnable()) {
166  stop_process();
167  }
168 }
169 
171  unsigned int audio_size, unsigned int& count, unsigned int& offset,
172  unsigned int& delay, unsigned int& ldelay, unsigned int& length,
173  unsigned int& size, unsigned int& bufsize) {
174 
175  if (bufsize < count) {
176  bufsize = count;
177  }
178  if (bufsize < Convproc::MINPART) {
179  bufsize = Convproc::MINPART;
180  }
181  if (offset > audio_size) {
182  offset = audio_size;
183  }
184  if (!size) {
185  if (offset + length > audio_size) {
187  "convolver",
188  (boost::format("length adjusted (%1% + %2% > %3%")
189  % offset % length % audio_size).str());
190  length = audio_size - offset;
191  }
192  if (!length) {
193  length = audio_size - offset;
194  }
195  size = max(delay, ldelay) + offset + length;
196  } else {
197  if (delay > size) {
198  delay = size;
199  }
200  if (ldelay > size) {
201  ldelay = size;
202  }
203  if (offset > size - max(delay, ldelay)) {
204  offset = size - max(delay, ldelay);
205  }
206  if (length > size - max(delay, ldelay) - offset) {
207  length = size - max(delay, ldelay) - offset;
208  gx_print_warning("convolver", "data truncated");
209  }
210  if (!length) {
211  length = size - max(delay, ldelay) - offset;
212  }
213  }
214 }
215 
216 bool GxConvolverBase::start(int policy, int priority) {
217  int rc = start_process(priority, policy);
218  if (rc != 0) {
219  gx_print_error("convolver", "can't start convolver");
220  return false;
221  }
222  ready = true;
223  return true;
224 }
225 
227  if (state() == Convproc::ST_WAIT) {
228  if (check_stop()) {
229  ready = false;
230  } else {
231  return false;
232  }
233  } else if (state() == ST_STOP) {
234  ready = false;
235  }
236  return true;
237 }
238 
239 /****************************************************************
240  ** GxConvolver
241  */
242 
243 /*
244 ** GxConvolver::read_sndfile()
245 **
246 ** read samples from soundfile into convolver
247 ** the convolver is working at rate samplerate, the audio file has audio.rate
248 **
249 ** offset, length, points are based on audio.rate, delay and the count of
250 ** samples written into the convolver are based on samplerate.
251 **
252 ** Arguments:
253 ** Audiofile& audio already opened, will be converted to samplerate
254 ** on the fly
255 ** int nchan channel count for convolver (can be less
256 ** or more than audio.chan())
257 ** int samplerate current engine samplerate
258 ** const float *gain array[nchan] of gains to be applied
259 ** unsigned int *delay array[nchan], starting sample index for values
260 ** stored into convolver
261 ** unsigned int offset offset into audio file
262 ** unsigned int length number of samples to be read from audio
263 ** const Gainline& points gain line to be applied
264 **
265 ** returns false if some error occurred, else true
266 */
267 bool GxConvolver::read_sndfile(
268  Audiofile& audio, int nchan, int samplerate, const float *gain,
269  unsigned int *delay, unsigned int offset, unsigned int length,
270  const Gainline& points) {
271  int nfram;
272  float *buff;
273  float *rbuff = 0;
274  float *bufp;
275  // keep BSIZE big enough so that resamp.flush() doesn't cause overflow
276  // (> 100 should be enough, and should be kept bigger anyhow)
277  const unsigned int BSIZE = 0x8000; // 0x4000;
278 
279 
280  if (offset && audio.seek(offset)) {
281  gx_print_error("convolver", "Can't seek to offset");
282  audio.close();
283  return false;
284  }
285  try {
286  buff = new float[BSIZE * audio.chan()];
287  } catch(...) {
288  audio.close();
289  gx_print_error("convolver", "out of memory");
290  return false;
291  }
292  if (samplerate != audio.rate()) {
294  "convolver", Glib::ustring::compose(
295  _("resampling from %1 to %2"), audio.rate(), samplerate));
296  if (!resamp.setup(audio.rate(), samplerate, audio.chan())) {
297  gx_print_error("convolver", "resample failure");
298  assert(false);
299  return false;
300  }
301  try {
302  rbuff = new float[resamp.get_max_out_size(BSIZE)*audio.chan()];
303  } catch(...) {
304  audio.close();
305  gx_print_error("convolver", "out of memory");
306  return false;
307  }
308  bufp = rbuff;
309  } else {
310  bufp = buff;
311  }
312  bool done = false;
313  unsigned int idx = 0; // current index in gainline point array
314  double gp = 0.0, fct = 0.0; // calculated parameter of interpolation line
315  if (points.size()) {
316  while ((unsigned int)points[idx].i < offset) {
317  idx++;
318  assert(idx < points.size());
319  }
320  if ((unsigned int)points[idx].i > offset) {
321  idx--;
322  compute_interpolation(fct, gp, idx, points, offset);
323  }
324  }
325 
326  while (!done) {
327  unsigned int cnt;
328  nfram = (length > BSIZE) ? BSIZE : length;
329  if (length) {
330  nfram = audio.read(buff, nfram);
331  if (nfram < 0) {
332  gx_print_error("convolver", "Error reading file");
333  audio.close();
334  delete[] buff;
335  delete[] rbuff;
336  return false;
337  }
338  for (int ix = 0; ix < nfram; ix++) {
339  if (idx+1 < points.size() && (unsigned int)points[idx].i == offset + ix) {
340  compute_interpolation(fct, gp, idx, points, offset);
341  }
342 
343  for (int ichan = 0; ichan < min(audio.chan(), nchan); ichan++) {
344  buff[ix*audio.chan()+ichan] *= pow(10, gp + ix*fct) * gain[ichan];
345  }
346  }
347  offset += nfram;
348  gp += nfram*fct;
349  cnt = nfram;
350  if (rbuff) {
351  cnt = resamp.process(nfram, buff, rbuff);
352  }
353  } else {
354  if (rbuff) {
355  cnt = resamp.flush(rbuff);
356  done = true;
357  } else {
358  break;
359  }
360  }
361  if (cnt) {
362 
363  for (int ichan = 0; ichan < nchan; ichan++) {
364  int rc;
365  if (ichan >= audio.chan()) {
366  rc = impdata_copy(0, 0, ichan, ichan);
367  } else {
368  rc = impdata_create(ichan, ichan, audio.chan(), bufp + ichan,
369  delay[ichan], delay[ichan] + cnt);
370  }
371  if (rc) {
372  audio.close();
373  delete[] buff;
374  delete[] rbuff;
375  gx_print_error("convolver", "out of memory");
376  return false;
377  }
378  delay[ichan] += cnt;
379  }
380  length -= nfram;
381  }
382  }
383 
384  audio.close();
385  delete[] buff;
386  delete[] rbuff;
387 
388  return true;
389 }
390 
392  string fname, float gain, float lgain,
393  unsigned int delay, unsigned int ldelay, unsigned int offset,
394  unsigned int length, unsigned int size, unsigned int bufsize,
395  const Gainline& points) {
396  Audiofile audio;
397  cleanup();
398  if (fname.empty()) {
399  return false;
400  }
401  if (audio.open_read(fname)) {
402  gx_print_error("convolver", Glib::ustring::compose("Unable to open '%1'", fname));
403  return false;
404  }
405  if (audio.chan() > 2) {
407  "convolver",
408  Glib::ustring::compose("only taking first 2 of %1 channels in impulse response", audio.chan()));
409  return false;
410  }
411  adjust_values(audio.size(), buffersize, offset, delay, ldelay, length, size, bufsize);
412 
413  if (samplerate != static_cast<unsigned int>(audio.rate())) {
414  float f = float(samplerate) / audio.rate();
415  size = round(size * f) + 2; // 2 is safety margin for rounding differences
416  delay = round(delay * f);
417  ldelay = round(ldelay * f);
418  }
419 #if ZITA_CONVOLVER_VERSION == 4
420  if (Convproc::configure(2, 2, size, buffersize, bufsize, Convproc::MAXPART, 0.0)) {
421  gx_print_error("convolver", "error in Convproc::configure ");
422  return false;
423  }
424 #else
425  if (Convproc::configure(2, 2, size, buffersize, bufsize, Convproc::MAXPART)) {
426  gx_print_error("convolver", "error in Convproc::configure ");
427  return false;
428  }
429 #endif
430 
431  float gain_a[2] = {gain, lgain};
432  unsigned int delay_a[2] = {delay, ldelay};
433  return read_sndfile(audio, 2, samplerate, gain_a, delay_a, offset, length, points);
434 }
435 
436 bool __rt_func GxConvolver::compute(int count, float* input1, float *input2,
437  float *output1, float *output2) {
438  if (state() != Convproc::ST_PROC) {
439  if (input1 != output1) {
440  memcpy(output1, input1, count * sizeof(float));
441  }
442  if (input2 != output2) {
443  memcpy(output2, input2, count * sizeof(float));
444  }
445  if (state() == Convproc::ST_WAIT) {
446  check_stop();
447  }
448  if (state() == ST_STOP) {
449  ready = false;
450  }
451  return true;
452  }
453  memcpy(inpdata(0), input1, count * sizeof(float));
454  memcpy(inpdata(1), input2, count * sizeof(float));
455 
456  int flags = process(sync);
457 
458  memcpy(output1, outdata(0), count * sizeof(float));
459  memcpy(output2, outdata(1), count * sizeof(float));
460  return flags == 0;
461 }
462 
463 bool GxConvolver::configure(string fname, float gain, unsigned int delay, unsigned int offset,
464  unsigned int length, unsigned int size, unsigned int bufsize,
465  const Gainline& points) {
466  Audiofile audio;
467  cleanup();
468  if (fname.empty()) {
469  return false;
470  }
471  if (audio.open_read(fname)) {
472  gx_print_error("convolver", Glib::ustring::compose("Unable to open '%1'", fname));
473  return false;
474  }
475  if (audio.chan() > 1) {
477  "convolver",
478  Glib::ustring::compose("only taking first channel of %1 channels in impulse response", audio.chan()));
479  return false;
480  }
481  unsigned int ldelay = delay;
482  adjust_values(audio.size(), buffersize, offset, delay, ldelay, length, size, bufsize);
483 
484  if (samplerate != static_cast<unsigned int>(audio.rate())) {
485  float f = float(samplerate) / audio.rate();
486  size = round(size * f) + 2; // 2 is safety margin for rounding differences
487  delay = round(delay * f);
488  }
489 #if ZITA_CONVOLVER_VERSION == 4
490  if (Convproc::configure(1, 1, size, buffersize, bufsize, Convproc::MAXPART,0.0)) {
491  gx_print_error("convolver", "error in Convproc::configure ");
492  return false;
493  }
494 #else
495  if (Convproc::configure(1, 1, size, buffersize, bufsize, Convproc::MAXPART)) {
496  gx_print_error("convolver", "error in Convproc::configure ");
497  return false;
498  }
499 #endif
500 
501  float gain_a[1] = {gain};
502  unsigned int delay_a[1] = {delay};
503  return read_sndfile(audio, 1, samplerate, gain_a, delay_a, offset, length, points);
504 }
505 
506 bool __rt_func GxConvolver::compute(int count, float* input, float *output) {
507  if (state() != Convproc::ST_PROC) {
508  if (input != output) {
509  memcpy(output, input, count * sizeof(float));
510  }
511  if (state() == Convproc::ST_WAIT) {
512  check_stop();
513  }
514  if (state() == ST_STOP) {
515  ready = false;
516  }
517  return true;
518  }
519  memcpy(inpdata(0), input, count * sizeof(float));
520 
521  int flags = process(sync);
522 
523  memcpy(output, outdata(0), count * sizeof(float));
524  return flags == 0;
525 }
526 
527 
528 /****************************************************************
529  ** GxSimpleConvolver
530  */
531 
533 private:
534  float *vec;
536 public:
537  CheckResample(gx_resample::BufferResampler& resamp_): vec(0), resamp(resamp_) {}
538  float *resample(int *count, float *impresp, unsigned int imprate, unsigned int samplerate) {
539  if (imprate != samplerate) {
540  vec = resamp.process(imprate, *count, impresp, samplerate, count);
541  if (!vec) {
542  boost::format msg = boost::format("failed to resample %1% -> %2%") % imprate % samplerate;
543  if (samplerate) {
544  gx_print_error("convolver", msg);
545  } else {
546  // not need for extra error when no samplerate (probably not connected to jack)
547  gx_print_warning("convolver", msg);
548  }
549  return 0;
550  }
551  return vec;
552  }
553  return impresp;
554  }
556  if (vec) {
557  delete vec;
558  }
559  }
560 };
561 
562 bool GxSimpleConvolver::configure(int count, float *impresp, unsigned int imprate) {
563  CheckResample r(resamp);
564  impresp = r.resample(&count, impresp, imprate, samplerate);
565  if (!impresp) {
566  return false;
567  }
568  cleanup();
569  unsigned int bufsize = buffersize;
570  if (bufsize < Convproc::MINPART) {
571  bufsize = Convproc::MINPART;
572  }
573 #if ZITA_CONVOLVER_VERSION == 4
574  if (Convproc::configure(1, 1, count, buffersize,
575  bufsize, Convproc::MAXPART,0.0)) {
576  gx_print_error("convolver", "error in Convproc::configure");
577  return false;
578  }
579 #else
580  if (Convproc::configure(1, 1, count, buffersize,
581  bufsize, Convproc::MAXPART)) {
582  gx_print_error("convolver", "error in Convproc::configure");
583  return false;
584  }
585 #endif
586  if (impdata_create(0, 0, 1, impresp, 0, count)) {
587  gx_print_error("convolver", "out of memory");
588  return false;
589  }
590  return true;
591 }
592 
593 bool GxSimpleConvolver::update(int count, float *impresp, unsigned int imprate) {
594  CheckResample r(resamp);
595  impresp = r.resample(&count, impresp, imprate, samplerate);
596  if (!impresp) {
597  return false;
598  }
599 #if ZITA_CONVOLVER_VERSION == 4
600  impdata_clear(0, 0);
601 #endif
602  if (impdata_update(0, 0, 1, impresp, 0, count)) {
603  gx_print_error("convolver", "update: internal error");
604  return false;
605  }
606  return true;
607 }
608 
609 bool __rt_func GxSimpleConvolver::compute(int count, float* input, float *output) {
610  if (state() != Convproc::ST_PROC) {
611  if (input != output) {
612  memcpy(output, input, count * sizeof(float));
613  }
614  if (state() == Convproc::ST_WAIT) {
615  check_stop();
616  }
617  if (state() == ST_STOP) {
618  ready = false;
619  }
620  return true;
621  }
622  memcpy(inpdata(0), input, count * sizeof(float));
623 
624  int flags = process(sync);
625 
626  memcpy(output, outdata(0), count * sizeof(float));
627  return flags == 0;
628 }
629 
631 
632 bool GxSimpleConvolver::configure_stereo(int count, float *impresp, unsigned int imprate)
633 {
634  //printf("try configure()\n");
635  CheckResample r(resamp);
636  impresp = r.resample(&count, impresp, imprate, samplerate);
637  if (!impresp)
638  {
639  printf("no impresp\n");
640  return false;
641  }
642  cleanup();
643  unsigned int bufsize = buffersize;
644  if (bufsize < Convproc::MINPART)
645  {
646  bufsize = Convproc::MINPART;
647  }
648 #if ZITA_CONVOLVER_VERSION == 4
649  if (Convproc::configure(2, 2, count, buffersize,
650  bufsize, bufsize,0.0)) // Convproc::MAXPART
651  {
652  printf("no configure\n");
653  return false;
654  }
655 
656 #else
657  if (Convproc::configure(2, 2, count, buffersize,
658  bufsize, bufsize)) // Convproc::MAXPART
659  {
660  printf("no configure\n");
661  return false;
662  }
663 #endif
664  if (impdata_create(0, 0, 1, impresp, 0, count) & impdata_create(1, 1, 1, impresp, 0, count))
665  {
666  printf("no impdata_create()\n");
667  return false;
668  }
669  //printf("configure()\n");
670 
671  return true;
672 }
673 
674 bool GxSimpleConvolver::update_stereo(int count, float *impresp, unsigned int imprate)
675 {
676  CheckResample r(resamp);
677  impresp = r.resample(&count, impresp, imprate, samplerate);
678  if (!impresp)
679  {
680  return false;
681  }
682 #if ZITA_CONVOLVER_VERSION == 4
683  impdata_clear(0, 0);
684  impdata_clear(1, 1);
685 #endif
686  if (impdata_update(0, 0, 1, impresp, 0, count) & impdata_update(1, 1, 1, impresp, 0, count))
687  {
688  return false;
689  }
690  return true;
691 }
692 
693 bool __rt_func GxSimpleConvolver::compute_stereo(int count, float* input, float* input1, float *output, float *output1)
694 {
695  // printf("try run\n");
696  if (state() != Convproc::ST_PROC)
697  {
698  //printf("state() != ST_PROC\n");
699  if (input != output)
700  {
701  memcpy(output, input, count * sizeof(float));
702  memcpy(output1, input1, count * sizeof(float));
703  }
704  if (state() == Convproc::ST_WAIT)
705  {
706  //printf("state() == ST_WAIT\n");
707  check_stop();
708  }
709  if (state() == ST_STOP)
710  {
711  //printf("state() == ST_STOP\n");
712  ready = false;
713  }
714  return true;
715  }
716  int flags = 0;
717  if (static_cast<unsigned int>(count) == buffersize)
718  {
719  memcpy(inpdata(0), input, count * sizeof(float));
720  memcpy(inpdata(1), input1, count * sizeof(float));
721 
722  flags = process(sync);
723 
724  memcpy(output, outdata(0), count * sizeof(float));
725  memcpy(output1, outdata(1), count * sizeof(float));
726  } else {
727  float *in, *in1, *out, *out1;
728  in = inpdata(0);
729  in1 = inpdata(1);
730  out = outdata(0);
731  out1 = outdata(1);
732  unsigned int b = 0;
733  unsigned int c = 1;
734  for(int i = 0; i<count; ++i){
735  in[b] = input[i];
736  in1[b] = input1[i];
737  if(++b == buffersize) {
738  b=0;
739  flags = process();
740  for(unsigned int d = 0; d<buffersize; ++d) {
741  output[d*c] = out[d];
742  output1[d*c] = out1[d];
743  }
744  ++c;
745  }
746  }
747  }
748  return flags == 0;
749 }
750 
751 }
void gx_print_info(const char *, const std::string &)
Definition: gx_logging.cpp:183
bool update_stereo(int count, float *impresp, unsigned int imprate)
int chan(void) const
Definition: gx_convolver.h:74
bool start(int policy, int priority)
bool configure(int count, float *impresp, unsigned int imprate)
#define __rt_func
Definition: gx_compiler.h:7
bool compute(int count, float *input, float *output)
int open_read(string name)
bool read_audio(const std::string &filename, unsigned int *audio_size, int *audio_chan, int *audio_type, int *audio_form, int *audio_rate, float **buffer)
float * process(int fs_inp, int ilen, float *input, int fs_outp, int *olen)
void adjust_values(unsigned int audio_size, unsigned int &count, unsigned int &offset, unsigned int &delay, unsigned int &ldelay, unsigned int &length, unsigned int &size, unsigned int &bufsize)
void gx_print_error(const char *, const std::string &)
Definition: gx_logging.cpp:166
unsigned int size(void) const
Definition: gx_convolver.h:75
int seek(unsigned int posit)
#define min(x, y)
bool compute(int count, float *input1, float *input2, float *output1, float *output2)
bool update(int count, float *impresp, unsigned int imprate)
#define max(x, y)
bool configure(string fname, float gain, float lgain, unsigned int delay, unsigned int ldelay, unsigned int offset, unsigned int length, unsigned int size, unsigned int bufsize, const Gainline &gainline)
int type(void) const
Definition: gx_convolver.h:71
bool compute_stereo(int count, float *input, float *input1, float *output, float *output1)
int rate(void) const
Definition: gx_convolver.h:73
void gx_print_warning(const char *, const std::string &)
Definition: gx_logging.cpp:161
bool configure_stereo(int count, float *impresp, unsigned int imprate)
float * resample(int *count, float *impresp, unsigned int imprate, unsigned int samplerate)
CheckResample(gx_resample::BufferResampler &resamp_)
int form(void) const
Definition: gx_convolver.h:72
int read(float *data, unsigned int frames)