comparison plugin/plugins/SamplePlayer.cpp @ 1429:48e9f538e6e9

Untabify
author Chris Cannam
date Thu, 01 Mar 2018 18:02:22 +0000
parents 49b43306778b
children cee1be4fb8c1
comparison
equal deleted inserted replaced
1428:87ae75da6527 1429:48e9f538e6e9
155 155
156 LADSPA_Handle 156 LADSPA_Handle
157 SamplePlayer::instantiate(const LADSPA_Descriptor *, unsigned long rate) 157 SamplePlayer::instantiate(const LADSPA_Descriptor *, unsigned long rate)
158 { 158 {
159 if (!hostDescriptor || !hostDescriptor->request_non_rt_thread) { 159 if (!hostDescriptor || !hostDescriptor->request_non_rt_thread) {
160 SVDEBUG << "SamplePlayer::instantiate: Host does not provide request_non_rt_thread, not instantiating" << endl; 160 SVDEBUG << "SamplePlayer::instantiate: Host does not provide request_non_rt_thread, not instantiating" << endl;
161 return 0; 161 return 0;
162 } 162 }
163 163
164 SamplePlayer *player = new SamplePlayer(int(rate)); 164 SamplePlayer *player = new SamplePlayer(int(rate));
165 // std::cerr << "Instantiated sample player " << std::endl; 165 // std::cerr << "Instantiated sample player " << std::endl;
166 166
167 if (hostDescriptor->request_non_rt_thread(player, workThreadCallback)) { 167 if (hostDescriptor->request_non_rt_thread(player, workThreadCallback)) {
168 SVDEBUG << "SamplePlayer::instantiate: Host rejected request_non_rt_thread call, not instantiating" << endl; 168 SVDEBUG << "SamplePlayer::instantiate: Host rejected request_non_rt_thread call, not instantiating" << endl;
169 delete player; 169 delete player;
170 return 0; 170 return 0;
171 } 171 }
172 172
173 return player; 173 return player;
174 } 174 }
175 175
176 void 176 void
177 SamplePlayer::connectPort(LADSPA_Handle handle, 177 SamplePlayer::connectPort(LADSPA_Handle handle,
178 unsigned long port, LADSPA_Data *location) 178 unsigned long port, LADSPA_Data *location)
179 { 179 {
180 SamplePlayer *player = (SamplePlayer *)handle; 180 SamplePlayer *player = (SamplePlayer *)handle;
181 181
182 float **ports[PortCount] = { 182 float **ports[PortCount] = {
183 &player->m_output, 183 &player->m_output,
184 &player->m_retune, 184 &player->m_retune,
185 &player->m_basePitch, 185 &player->m_basePitch,
186 &player->m_concertA, 186 &player->m_concertA,
187 &player->m_sustain, 187 &player->m_sustain,
188 &player->m_release 188 &player->m_release
189 }; 189 };
190 190
191 *ports[port] = (float *)location; 191 *ports[port] = (float *)location;
192 } 192 }
193 193
198 QMutexLocker locker(&player->m_mutex); 198 QMutexLocker locker(&player->m_mutex);
199 199
200 player->m_sampleNo = 0; 200 player->m_sampleNo = 0;
201 201
202 for (size_t i = 0; i < Polyphony; ++i) { 202 for (size_t i = 0; i < Polyphony; ++i) {
203 player->m_ons[i] = -1; 203 player->m_ons[i] = -1;
204 player->m_offs[i] = -1; 204 player->m_offs[i] = -1;
205 player->m_velocities[i] = 0; 205 player->m_velocities[i] = 0;
206 } 206 }
207 } 207 }
208 208
209 void 209 void
210 SamplePlayer::run(LADSPA_Handle handle, unsigned long samples) 210 SamplePlayer::run(LADSPA_Handle handle, unsigned long samples)
229 { 229 {
230 if (key && !strcmp(key, "sampledir")) { 230 if (key && !strcmp(key, "sampledir")) {
231 231
232 SamplePlayer *player = (SamplePlayer *)handle; 232 SamplePlayer *player = (SamplePlayer *)handle;
233 233
234 QMutexLocker locker(&player->m_mutex); 234 QMutexLocker locker(&player->m_mutex);
235 235
236 if (QFileInfo(value).exists() && 236 if (QFileInfo(value).exists() &&
237 QFileInfo(value).isDir()) { 237 QFileInfo(value).isDir()) {
238 238
239 player->m_sampleDir = value; 239 player->m_sampleDir = value;
259 SamplePlayer::getProgram(LADSPA_Handle handle, unsigned long program) 259 SamplePlayer::getProgram(LADSPA_Handle handle, unsigned long program)
260 { 260 {
261 SamplePlayer *player = (SamplePlayer *)handle; 261 SamplePlayer *player = (SamplePlayer *)handle;
262 262
263 if (!player->m_sampleSearchComplete) { 263 if (!player->m_sampleSearchComplete) {
264 QMutexLocker locker(&player->m_mutex); 264 QMutexLocker locker(&player->m_mutex);
265 if (!player->m_sampleSearchComplete) { 265 if (!player->m_sampleSearchComplete) {
266 player->searchSamples(); 266 player->searchSamples();
267 } 267 }
268 } 268 }
269 if (program >= player->m_samples.size()) return 0; 269 if (program >= player->m_samples.size()) return 0;
270 270
271 static DSSI_Program_Descriptor descriptor; 271 static DSSI_Program_Descriptor descriptor;
272 static char name[60]; 272 static char name[60];
281 return &descriptor; 281 return &descriptor;
282 } 282 }
283 283
284 void 284 void
285 SamplePlayer::selectProgram(LADSPA_Handle handle, 285 SamplePlayer::selectProgram(LADSPA_Handle handle,
286 unsigned long, 286 unsigned long,
287 unsigned long program) 287 unsigned long program)
288 { 288 {
289 SamplePlayer *player = (SamplePlayer *)handle; 289 SamplePlayer *player = (SamplePlayer *)handle;
290 player->m_pendingProgramChange = (int)program; 290 player->m_pendingProgramChange = (int)program;
291 } 291 }
292 292
293 int 293 int
294 SamplePlayer::getMidiController(LADSPA_Handle, unsigned long port) 294 SamplePlayer::getMidiController(LADSPA_Handle, unsigned long port)
295 { 295 {
296 int controllers[PortCount] = { 296 int controllers[PortCount] = {
297 DSSI_NONE, 297 DSSI_NONE,
298 DSSI_CC(12), 298 DSSI_CC(12),
299 DSSI_CC(13), 299 DSSI_CC(13),
300 DSSI_CC(64), 300 DSSI_CC(64),
301 DSSI_CC(72) 301 DSSI_CC(72)
302 }; 302 };
303 303
304 return controllers[port]; 304 return controllers[port];
305 } 305 }
306 306
307 void 307 void
308 SamplePlayer::runSynth(LADSPA_Handle handle, unsigned long samples, 308 SamplePlayer::runSynth(LADSPA_Handle handle, unsigned long samples,
309 snd_seq_event_t *events, unsigned long eventCount) 309 snd_seq_event_t *events, unsigned long eventCount)
310 { 310 {
311 SamplePlayer *player = (SamplePlayer *)handle; 311 SamplePlayer *player = (SamplePlayer *)handle;
312 312
313 player->runImpl(samples, events, eventCount); 313 player->runImpl(samples, events, eventCount);
314 } 314 }
325 SamplePlayer *player = (SamplePlayer *)handle; 325 SamplePlayer *player = (SamplePlayer *)handle;
326 326
327 if (player->m_pendingProgramChange >= 0) { 327 if (player->m_pendingProgramChange >= 0) {
328 328
329 #ifdef DEBUG_SAMPLE_PLAYER 329 #ifdef DEBUG_SAMPLE_PLAYER
330 SVDEBUG << "SamplePlayer::workThreadCallback: pending program change " << player->m_pendingProgramChange << endl; 330 SVDEBUG << "SamplePlayer::workThreadCallback: pending program change " << player->m_pendingProgramChange << endl;
331 #endif 331 #endif
332 332
333 player->m_mutex.lock(); 333 player->m_mutex.lock();
334 334
335 int program = player->m_pendingProgramChange; 335 int program = player->m_pendingProgramChange;
336 player->m_pendingProgramChange = -1; 336 player->m_pendingProgramChange = -1;
337 337
338 if (!player->m_sampleSearchComplete) { 338 if (!player->m_sampleSearchComplete) {
339 player->searchSamples(); 339 player->searchSamples();
340 } 340 }
341 341
342 if (program < int(player->m_samples.size())) { 342 if (program < int(player->m_samples.size())) {
343 QString path = player->m_samples[program].second; 343 QString path = player->m_samples[program].second;
344 QString programName = player->m_samples[program].first; 344 QString programName = player->m_samples[program].first;
345 if (programName != player->m_program) { 345 if (programName != player->m_program) {
346 player->m_program = programName; 346 player->m_program = programName;
347 player->m_mutex.unlock(); 347 player->m_mutex.unlock();
348 player->loadSampleData(path); 348 player->loadSampleData(path);
349 } else { 349 } else {
350 player->m_mutex.unlock(); 350 player->m_mutex.unlock();
351 } 351 }
352 } 352 }
353 } 353 }
354 354
355 if (!player->m_sampleSearchComplete) { 355 if (!player->m_sampleSearchComplete) {
356 356
357 QMutexLocker locker(&player->m_mutex); 357 QMutexLocker locker(&player->m_mutex);
358 358
359 if (!player->m_sampleSearchComplete) { 359 if (!player->m_sampleSearchComplete) {
360 player->searchSamples(); 360 player->searchSamples();
361 } 361 }
362 } 362 }
363 } 363 }
364 364
365 void 365 void
366 SamplePlayer::searchSamples() 366 SamplePlayer::searchSamples()
369 369
370 m_samples.clear(); 370 m_samples.clear();
371 371
372 #ifdef DEBUG_SAMPLE_PLAYER 372 #ifdef DEBUG_SAMPLE_PLAYER
373 SVDEBUG << "SamplePlayer::searchSamples: Directory is \"" 373 SVDEBUG << "SamplePlayer::searchSamples: Directory is \""
374 << m_sampleDir << "\"" << endl; 374 << m_sampleDir << "\"" << endl;
375 #endif 375 #endif
376 376
377 QDir dir(m_sampleDir, "*.wav"); 377 QDir dir(m_sampleDir, "*.wav");
378 378
379 for (unsigned int i = 0; i < dir.count(); ++i) { 379 for (unsigned int i = 0; i < dir.count(); ++i) {
404 file = sf_wchar_open((LPCWSTR)path.utf16(), SFM_READ, &info); 404 file = sf_wchar_open((LPCWSTR)path.utf16(), SFM_READ, &info);
405 #else 405 #else
406 file = sf_open(path.toLocal8Bit().data(), SFM_READ, &info); 406 file = sf_open(path.toLocal8Bit().data(), SFM_READ, &info);
407 #endif 407 #endif
408 if (!file) { 408 if (!file) {
409 cerr << "SamplePlayer::loadSampleData: Failed to open file " 409 cerr << "SamplePlayer::loadSampleData: Failed to open file "
410 << path << ": " 410 << path << ": "
411 << sf_strerror(file) << endl; 411 << sf_strerror(file) << endl;
412 return; 412 return;
413 } 413 }
414 414
415 samples = info.frames; 415 samples = info.frames;
416 tmpFrames = (float *)malloc(info.frames * info.channels * sizeof(float)); 416 tmpFrames = (float *)malloc(info.frames * info.channels * sizeof(float));
417 if (!tmpFrames) return; 417 if (!tmpFrames) return;
420 sf_close(file); 420 sf_close(file);
421 421
422 tmpResamples = 0; 422 tmpResamples = 0;
423 423
424 if (info.samplerate != m_sampleRate) { 424 if (info.samplerate != m_sampleRate) {
425 425
426 double ratio = (double)m_sampleRate / (double)info.samplerate; 426 double ratio = (double)m_sampleRate / (double)info.samplerate;
427 size_t target = (size_t)(double(info.frames) * ratio); 427 size_t target = (size_t)(double(info.frames) * ratio);
428 SRC_DATA data; 428 SRC_DATA data;
429 429
430 tmpResamples = (float *)malloc(target * info.channels * sizeof(float)); 430 tmpResamples = (float *)malloc(target * info.channels * sizeof(float));
431 if (!tmpResamples) { 431 if (!tmpResamples) {
432 free(tmpFrames); 432 free(tmpFrames);
433 return; 433 return;
434 } 434 }
435 435
436 memset(tmpResamples, 0, target * info.channels * sizeof(float)); 436 memset(tmpResamples, 0, target * info.channels * sizeof(float));
437 437
438 data.data_in = tmpFrames; 438 data.data_in = tmpFrames;
439 data.data_out = tmpResamples; 439 data.data_out = tmpResamples;
440 data.input_frames = info.frames; 440 data.input_frames = info.frames;
441 data.output_frames = target; 441 data.output_frames = target;
442 data.src_ratio = ratio; 442 data.src_ratio = ratio;
443 443
444 if (!src_simple(&data, SRC_SINC_BEST_QUALITY, info.channels)) { 444 if (!src_simple(&data, SRC_SINC_BEST_QUALITY, info.channels)) {
445 free(tmpFrames); 445 free(tmpFrames);
446 tmpFrames = tmpResamples; 446 tmpFrames = tmpResamples;
447 samples = target; 447 samples = target;
448 } else { 448 } else {
449 free(tmpResamples); 449 free(tmpResamples);
450 } 450 }
451 } 451 }
452 452
453 /* add an extra sample for linear interpolation */ 453 /* add an extra sample for linear interpolation */
454 tmpSamples = (float *)malloc((samples + 1) * sizeof(float)); 454 tmpSamples = (float *)malloc((samples + 1) * sizeof(float));
455 if (!tmpSamples) { 455 if (!tmpSamples) {
456 free(tmpFrames); 456 free(tmpFrames);
457 return; 457 return;
458 } 458 }
459 459
460 for (i = 0; i < samples; ++i) { 460 for (i = 0; i < samples; ++i) {
461 int j; 461 int j;
462 tmpSamples[i] = 0.0f; 462 tmpSamples[i] = 0.0f;
463 for (j = 0; j < info.channels; ++j) { 463 for (j = 0; j < info.channels; ++j) {
464 tmpSamples[i] += tmpFrames[i * info.channels + j]; 464 tmpSamples[i] += tmpFrames[i * info.channels + j];
465 } 465 }
466 } 466 }
467 467
468 free(tmpFrames); 468 free(tmpFrames);
469 469
470 /* add an extra sample for linear interpolation */ 470 /* add an extra sample for linear interpolation */
475 tmpOld = m_sampleData; 475 tmpOld = m_sampleData;
476 m_sampleData = tmpSamples; 476 m_sampleData = tmpSamples;
477 m_sampleCount = samples; 477 m_sampleCount = samples;
478 478
479 for (i = 0; i < Polyphony; ++i) { 479 for (i = 0; i < Polyphony; ++i) {
480 m_ons[i] = -1; 480 m_ons[i] = -1;
481 m_offs[i] = -1; 481 m_offs[i] = -1;
482 m_velocities[i] = 0; 482 m_velocities[i] = 0;
483 } 483 }
484 484
485 if (tmpOld) free(tmpOld); 485 if (tmpOld) free(tmpOld);
486 486
487 printf("%s: loaded %s (%ld samples from original %ld channels resampled from %ld frames at %ld Hz)\n", "sampler", path.toLocal8Bit().data(), (long)samples, (long)info.channels, (long)info.frames, (long)info.samplerate); 487 printf("%s: loaded %s (%ld samples from original %ld channels resampled from %ld frames at %ld Hz)\n", "sampler", path.toLocal8Bit().data(), (long)samples, (long)info.channels, (long)info.frames, (long)info.samplerate);
488 } 488 }
489 489
490 void 490 void
491 SamplePlayer::runImpl(unsigned long sampleCount, 491 SamplePlayer::runImpl(unsigned long sampleCount,
492 snd_seq_event_t *events, 492 snd_seq_event_t *events,
493 unsigned long eventCount) 493 unsigned long eventCount)
494 { 494 {
495 unsigned long pos; 495 unsigned long pos;
496 unsigned long count; 496 unsigned long count;
497 unsigned long event_pos; 497 unsigned long event_pos;
498 int i; 498 int i;
500 memset(m_output, 0, sampleCount * sizeof(float)); 500 memset(m_output, 0, sampleCount * sizeof(float));
501 501
502 if (!m_mutex.tryLock()) return; 502 if (!m_mutex.tryLock()) return;
503 503
504 if (!m_sampleData || !m_sampleCount) { 504 if (!m_sampleData || !m_sampleCount) {
505 m_sampleNo += sampleCount; 505 m_sampleNo += sampleCount;
506 m_mutex.unlock(); 506 m_mutex.unlock();
507 return; 507 return;
508 } 508 }
509 509
510 for (pos = 0, event_pos = 0; pos < sampleCount; ) { 510 for (pos = 0, event_pos = 0; pos < sampleCount; ) {
511 511
512 while (event_pos < eventCount 512 while (event_pos < eventCount
513 && pos >= events[event_pos].time.tick) { 513 && pos >= events[event_pos].time.tick) {
514 514
515 if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) { 515 if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) {
516 #ifdef DEBUG_SAMPLE_PLAYER 516 #ifdef DEBUG_SAMPLE_PLAYER
517 cerr << "SamplePlayer: found NOTEON at time " 517 cerr << "SamplePlayer: found NOTEON at time "
518 << events[event_pos].time.tick << endl; 518 << events[event_pos].time.tick << endl;
519 #endif 519 #endif
520 snd_seq_ev_note_t n = events[event_pos].data.note; 520 snd_seq_ev_note_t n = events[event_pos].data.note;
521 if (n.velocity > 0) { 521 if (n.velocity > 0) {
522 m_ons[n.note] = 522 m_ons[n.note] =
523 m_sampleNo + events[event_pos].time.tick; 523 m_sampleNo + events[event_pos].time.tick;
524 m_offs[n.note] = -1; 524 m_offs[n.note] = -1;
525 m_velocities[n.note] = n.velocity; 525 m_velocities[n.note] = n.velocity;
526 } else { 526 } else {
527 if (!m_sustain || (*m_sustain < 0.001)) { 527 if (!m_sustain || (*m_sustain < 0.001)) {
528 m_offs[n.note] = 528 m_offs[n.note] =
529 m_sampleNo + events[event_pos].time.tick; 529 m_sampleNo + events[event_pos].time.tick;
530 } 530 }
531 } 531 }
532 } else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF && 532 } else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF &&
533 (!m_sustain || (*m_sustain < 0.001))) { 533 (!m_sustain || (*m_sustain < 0.001))) {
534 #ifdef DEBUG_SAMPLE_PLAYER 534 #ifdef DEBUG_SAMPLE_PLAYER
535 cerr << "SamplePlayer: found NOTEOFF at time " 535 cerr << "SamplePlayer: found NOTEOFF at time "
536 << events[event_pos].time.tick << endl; 536 << events[event_pos].time.tick << endl;
537 #endif 537 #endif
538 snd_seq_ev_note_t n = events[event_pos].data.note; 538 snd_seq_ev_note_t n = events[event_pos].data.note;
539 m_offs[n.note] = 539 m_offs[n.note] =
540 m_sampleNo + events[event_pos].time.tick; 540 m_sampleNo + events[event_pos].time.tick;
541 } 541 }
542 542
543 ++event_pos; 543 ++event_pos;
544 } 544 }
545 545
546 count = sampleCount - pos; 546 count = sampleCount - pos;
547 if (event_pos < eventCount && 547 if (event_pos < eventCount &&
548 events[event_pos].time.tick < sampleCount) { 548 events[event_pos].time.tick < sampleCount) {
549 count = events[event_pos].time.tick - pos; 549 count = events[event_pos].time.tick - pos;
550 } 550 }
551 551
552 int notecount = 0; 552 int notecount = 0;
553 553
554 for (i = 0; i < Polyphony; ++i) { 554 for (i = 0; i < Polyphony; ++i) {
555 if (m_ons[i] >= 0) { 555 if (m_ons[i] >= 0) {
556 ++notecount; 556 ++notecount;
557 addSample(i, pos, count); 557 addSample(i, pos, count);
558 } 558 }
559 } 559 }
560 560
561 #ifdef DEBUG_SAMPLE_PLAYER 561 #ifdef DEBUG_SAMPLE_PLAYER
562 cerr << "SamplePlayer: have " << notecount << " note(s) sounding currently" << endl; 562 cerr << "SamplePlayer: have " << notecount << " note(s) sounding currently" << endl;
563 #endif 563 #endif
564 564
565 pos += count; 565 pos += count;
566 } 566 }
567 567
568 m_sampleNo += sampleCount; 568 m_sampleNo += sampleCount;
569 m_mutex.unlock(); 569 m_mutex.unlock();
570 } 570 }
578 578
579 if (m_retune && *m_retune) { 579 if (m_retune && *m_retune) {
580 if (m_concertA) { 580 if (m_concertA) {
581 ratio *= *m_concertA / 440.f; 581 ratio *= *m_concertA / 440.f;
582 } 582 }
583 if (m_basePitch && float(n) != *m_basePitch) { 583 if (m_basePitch && float(n) != *m_basePitch) {
584 ratio *= powf(1.059463094f, float(n) - *m_basePitch); 584 ratio *= powf(1.059463094f, float(n) - *m_basePitch);
585 } 585 }
586 } 586 }
587 587
588 if (long(pos + m_sampleNo) < m_ons[n]) return; 588 if (long(pos + m_sampleNo) < m_ons[n]) return;
589 589
590 gain = (float)m_velocities[n] / 127.0f; 590 gain = (float)m_velocities[n] / 127.0f;
591 591
592 for (i = 0, s = pos + m_sampleNo - m_ons[n]; 592 for (i = 0, s = pos + m_sampleNo - m_ons[n];
593 i < count; 593 i < count;
594 ++i, ++s) { 594 ++i, ++s) {
595 595
596 float lgain = gain; 596 float lgain = gain;
597 float rs = float(s) * ratio; 597 float rs = float(s) * ratio;
598 unsigned long rsi = lrintf(floorf(rs)); 598 unsigned long rsi = lrintf(floorf(rs));
599 599
600 if (rsi >= m_sampleCount) { 600 if (rsi >= m_sampleCount) {
601 #ifdef DEBUG_SAMPLE_PLAYER 601 #ifdef DEBUG_SAMPLE_PLAYER
602 cerr << "Note " << n << " has run out of samples (were " << m_sampleCount << " available at ratio " << ratio << "), ending" << endl; 602 cerr << "Note " << n << " has run out of samples (were " << m_sampleCount << " available at ratio " << ratio << "), ending" << endl;
603 #endif 603 #endif
604 m_ons[n] = -1; 604 m_ons[n] = -1;
605 break; 605 break;
606 } 606 }
607 607
608 if (m_offs[n] >= 0 && 608 if (m_offs[n] >= 0 &&
609 long(pos + i + m_sampleNo) > m_offs[n]) { 609 long(pos + i + m_sampleNo) > m_offs[n]) {
610 610
611 unsigned long dist = 611 unsigned long dist =
612 pos + i + m_sampleNo - m_offs[n]; 612 pos + i + m_sampleNo - m_offs[n];
613 613
614 unsigned long releaseFrames = 200; 614 unsigned long releaseFrames = 200;
615 if (m_release) { 615 if (m_release) {
616 releaseFrames = long(*m_release * float(m_sampleRate) + 0.0001f); 616 releaseFrames = long(*m_release * float(m_sampleRate) + 0.0001f);
617 } 617 }
618 618
619 if (dist > releaseFrames) { 619 if (dist > releaseFrames) {
620 #ifdef DEBUG_SAMPLE_PLAYER 620 #ifdef DEBUG_SAMPLE_PLAYER
621 cerr << "Note " << n << " has expired its release time (" << releaseFrames << " frames), ending" << endl; 621 cerr << "Note " << n << " has expired its release time (" << releaseFrames << " frames), ending" << endl;
622 #endif 622 #endif
623 m_ons[n] = -1; 623 m_ons[n] = -1;
624 break; 624 break;
625 } else { 625 } else {
626 lgain = lgain * (float)(releaseFrames - dist) / 626 lgain = lgain * (float)(releaseFrames - dist) /
627 (float)releaseFrames; 627 (float)releaseFrames;
628 } 628 }
629 } 629 }
630 630
631 float sample = m_sampleData[rsi] + 631 float sample = m_sampleData[rsi] +
632 ((m_sampleData[rsi + 1] - 632 ((m_sampleData[rsi + 1] -
633 m_sampleData[rsi]) * 633 m_sampleData[rsi]) *
634 (rs - (float)rsi)); 634 (rs - (float)rsi));
635 635
636 m_output[pos + i] += lgain * sample; 636 m_output[pos + i] += lgain * sample;
637 } 637 }
638 } 638 }