Mercurial > hg > svcore
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 } |