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
Audiofile(void)35 Audiofile::Audiofile(void) {
36 reset();
37 }
38
39
~Audiofile(void)40 Audiofile::~Audiofile(void) {
41 close();
42 }
43
44
reset(void)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
open_read(string name)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
close(void)104 int Audiofile::close(void) {
105 if (_sndfile) sf_close(_sndfile);
106 reset();
107 return 0;
108 }
109
110
seek(uint32_t posit)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
read(float * data,uint32_t frames)118 int Audiofile::read(float *data, uint32_t frames) {
119 return sf_readf_float(_sndfile, data, frames);
120 }
121
read_audio(const std::string & filename,unsigned int * audio_size,int * audio_chan,int * audio_type,int * audio_form,int * audio_rate,float ** buffer)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) {
138 gx_print_warning(
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
~GxConvolverBase()164 GxConvolverBase::~GxConvolverBase() {
165 if (is_runnable()) {
166 stop_process();
167 }
168 }
169
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)170 void GxConvolverBase::adjust_values(
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) {
186 gx_print_warning(
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
start(int policy,int priority)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
checkstate()226 bool GxConvolverBase::checkstate() {
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 */
read_sndfile(Audiofile & audio,int nchan,int samplerate,const float * gain,unsigned int * delay,unsigned int offset,unsigned int length,const Gainline & points)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()) {
293 gx_print_info(
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
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 & points)391 bool GxConvolver::configure(
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() || !samplerate) {
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) {
406 gx_print_error(
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
compute(int count,float * input1,float * input2,float * output1,float * output2)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
configure(string fname,float gain,unsigned int delay,unsigned int offset,unsigned int length,unsigned int size,unsigned int bufsize,const Gainline & points)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() || !samplerate) {
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) {
476 gx_print_error(
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
compute(int count,float * input,float * output)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
532 class CheckResample {
533 private:
534 float *vec;
535 gx_resample::BufferResampler& resamp;
536 public:
CheckResample(gx_resample::BufferResampler & resamp_)537 CheckResample(gx_resample::BufferResampler& resamp_): vec(0), resamp(resamp_) {}
resample(int * count,float * impresp,unsigned int imprate,unsigned int samplerate)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 }
~CheckResample()555 ~CheckResample() {
556 if (vec) {
557 delete[] vec;
558 }
559 }
560 };
561
configure(int count,float * impresp,unsigned int imprate)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
update(int count,float * impresp,unsigned int imprate)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
compute(int count,float * input,float * output)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 int flags = 0;
623 if (static_cast<unsigned int>(count) == buffersize)
624 {
625 memcpy(inpdata(0), input, count * sizeof(float));
626
627 flags = process(sync);
628
629 memcpy(output, outdata(0), count * sizeof(float));
630 } else {
631 float *in, *out;
632 in = inpdata(0);
633 out = outdata(0);
634 unsigned int b = 0;
635 unsigned int c = 1;
636 for(int i = 0; i<count; ++i){
637 in[b] = input[i];
638 if(++b == buffersize) {
639 b=0;
640 flags = process();
641 for(unsigned int d = 0; d<buffersize; ++d) {
642 output[d*c] = out[d];
643 }
644 ++c;
645 }
646 }
647 }
648 return flags == 0;
649 }
650
651 //////////////stero/////////////////
652
configure_stereo(int count,float * impresp,unsigned int imprate)653 bool GxSimpleConvolver::configure_stereo(int count, float *impresp, unsigned int imprate)
654 {
655 //printf("try configure()\n");
656 CheckResample r(resamp);
657 impresp = r.resample(&count, impresp, imprate, samplerate);
658 if (!impresp)
659 {
660 printf("no impresp\n");
661 return false;
662 }
663 cleanup();
664 unsigned int bufsize = buffersize;
665 if (bufsize < Convproc::MINPART)
666 {
667 bufsize = Convproc::MINPART;
668 }
669 #if ZITA_CONVOLVER_VERSION == 4
670 if (Convproc::configure(2, 2, count, buffersize,
671 bufsize, bufsize,0.0)) // Convproc::MAXPART
672 {
673 printf("no configure\n");
674 return false;
675 }
676
677 #else
678 if (Convproc::configure(2, 2, count, buffersize,
679 bufsize, bufsize)) // Convproc::MAXPART
680 {
681 printf("no configure\n");
682 return false;
683 }
684 #endif
685 if (impdata_create(0, 0, 1, impresp, 0, count) & impdata_create(1, 1, 1, impresp, 0, count))
686 {
687 printf("no impdata_create()\n");
688 return false;
689 }
690 //printf("configure()\n");
691
692 return true;
693 }
694
update_stereo(int count,float * impresp,unsigned int imprate)695 bool GxSimpleConvolver::update_stereo(int count, float *impresp, unsigned int imprate)
696 {
697 CheckResample r(resamp);
698 impresp = r.resample(&count, impresp, imprate, samplerate);
699 if (!impresp)
700 {
701 return false;
702 }
703 #if ZITA_CONVOLVER_VERSION == 4
704 impdata_clear(0, 0);
705 impdata_clear(1, 1);
706 #endif
707 if (impdata_update(0, 0, 1, impresp, 0, count) & impdata_update(1, 1, 1, impresp, 0, count))
708 {
709 return false;
710 }
711 return true;
712 }
713
compute_stereo(int count,float * input,float * input1,float * output,float * output1)714 bool __rt_func GxSimpleConvolver::compute_stereo(int count, float* input, float* input1, float *output, float *output1)
715 {
716 // printf("try run\n");
717 if (state() != Convproc::ST_PROC)
718 {
719 //printf("state() != ST_PROC\n");
720 if (input != output)
721 {
722 memcpy(output, input, count * sizeof(float));
723 memcpy(output1, input1, count * sizeof(float));
724 }
725 if (state() == Convproc::ST_WAIT)
726 {
727 //printf("state() == ST_WAIT\n");
728 check_stop();
729 }
730 if (state() == ST_STOP)
731 {
732 //printf("state() == ST_STOP\n");
733 ready = false;
734 }
735 return true;
736 }
737 int flags = 0;
738 if (static_cast<unsigned int>(count) == buffersize)
739 {
740 memcpy(inpdata(0), input, count * sizeof(float));
741 memcpy(inpdata(1), input1, count * sizeof(float));
742
743 flags = process(sync);
744
745 memcpy(output, outdata(0), count * sizeof(float));
746 memcpy(output1, outdata(1), count * sizeof(float));
747 } else {
748 float *in, *in1, *out, *out1;
749 in = inpdata(0);
750 in1 = inpdata(1);
751 out = outdata(0);
752 out1 = outdata(1);
753 unsigned int b = 0;
754 unsigned int c = 1;
755 for(int i = 0; i<count; ++i){
756 in[b] = input[i];
757 in1[b] = input1[i];
758 if(++b == buffersize) {
759 b=0;
760 flags = process();
761 for(unsigned int d = 0; d<buffersize; ++d) {
762 output[d*c] = out[d];
763 output1[d*c] = out1[d];
764 }
765 ++c;
766 }
767 }
768 }
769 return flags == 0;
770 }
771
772 }
773