00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "SamplePlayer.h"
00021
00022 #include <dssi.h>
00023 #include <cmath>
00024
00025 #include <QMutexLocker>
00026 #include <QDir>
00027 #include <QFileInfo>
00028
00029 #include <sndfile.h>
00030 #include <samplerate.h>
00031 #include <iostream>
00032
00033 const char *const
00034 SamplePlayer::portNames[PortCount] =
00035 {
00036 "Output",
00037 "Tuned (on/off)",
00038 "Base Pitch (MIDI)",
00039 "Tuning of A (Hz)",
00040 "Sustain (on/off)",
00041 "Release time (s)"
00042 };
00043
00044 const LADSPA_PortDescriptor
00045 SamplePlayer::ports[PortCount] =
00046 {
00047 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
00048 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
00049 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
00050 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
00051 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL
00052 };
00053
00054 const LADSPA_PortRangeHint
00055 SamplePlayer::hints[PortCount] =
00056 {
00057 { 0, 0, 0 },
00058 { LADSPA_HINT_DEFAULT_MAXIMUM | LADSPA_HINT_INTEGER |
00059 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 1 },
00060 { LADSPA_HINT_DEFAULT_MIDDLE | LADSPA_HINT_INTEGER |
00061 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 120 },
00062 { LADSPA_HINT_DEFAULT_440 | LADSPA_HINT_LOGARITHMIC |
00063 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 400, 499 },
00064 { LADSPA_HINT_DEFAULT_MINIMUM | LADSPA_HINT_INTEGER |
00065 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0, 1 },
00066 { LADSPA_HINT_DEFAULT_MINIMUM | LADSPA_HINT_LOGARITHMIC |
00067 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, 0.001, 2.0 }
00068 };
00069
00070 const LADSPA_Properties
00071 SamplePlayer::properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
00072
00073 const LADSPA_Descriptor
00074 SamplePlayer::ladspaDescriptor =
00075 {
00076 0,
00077 "sample_player",
00078 properties,
00079 "Library Sample Player",
00080 "Chris Cannam",
00081 "GPL",
00082 PortCount,
00083 ports,
00084 portNames,
00085 hints,
00086 0,
00087 instantiate,
00088 connectPort,
00089 activate,
00090 run,
00091 0,
00092 0,
00093 deactivate,
00094 cleanup
00095 };
00096
00097 const DSSI_Descriptor
00098 SamplePlayer::dssiDescriptor =
00099 {
00100 2,
00101 &ladspaDescriptor,
00102 configure,
00103 getProgram,
00104 selectProgram,
00105 getMidiController,
00106 runSynth,
00107 0,
00108 0,
00109 0,
00110 receiveHostDescriptor
00111 };
00112
00113 const DSSI_Host_Descriptor *
00114 SamplePlayer::hostDescriptor = 0;
00115
00116
00117 const DSSI_Descriptor *
00118 SamplePlayer::getDescriptor(unsigned long index)
00119 {
00120 if (index == 0) return &dssiDescriptor;
00121 return 0;
00122 }
00123
00124 SamplePlayer::SamplePlayer(int sampleRate) :
00125 m_output(0),
00126 m_retune(0),
00127 m_basePitch(0),
00128 m_concertA(0),
00129 m_sustain(0),
00130 m_release(0),
00131 m_sampleData(0),
00132 m_sampleCount(0),
00133 m_sampleRate(sampleRate),
00134 m_sampleNo(0),
00135 m_sampleDir("samples"),
00136 m_sampleSearchComplete(false),
00137 m_pendingProgramChange(-1)
00138 {
00139 }
00140
00141 SamplePlayer::~SamplePlayer()
00142 {
00143 if (m_sampleData) free(m_sampleData);
00144 }
00145
00146 LADSPA_Handle
00147 SamplePlayer::instantiate(const LADSPA_Descriptor *, unsigned long rate)
00148 {
00149 if (!hostDescriptor || !hostDescriptor->request_non_rt_thread) {
00150 std::cerr << "SamplePlayer::instantiate: Host does not provide request_non_rt_thread, not instantiating" << std::endl;
00151 return 0;
00152 }
00153
00154 SamplePlayer *player = new SamplePlayer(rate);
00155
00156 if (hostDescriptor->request_non_rt_thread(player, workThreadCallback)) {
00157 std::cerr << "SamplePlayer::instantiate: Host rejected request_non_rt_thread call, not instantiating" << std::endl;
00158 delete player;
00159 return 0;
00160 }
00161
00162 return player;
00163 }
00164
00165 void
00166 SamplePlayer::connectPort(LADSPA_Handle handle,
00167 unsigned long port, LADSPA_Data *location)
00168 {
00169 SamplePlayer *player = (SamplePlayer *)handle;
00170
00171 float **ports[PortCount] = {
00172 &player->m_output,
00173 &player->m_retune,
00174 &player->m_basePitch,
00175 &player->m_concertA,
00176 &player->m_sustain,
00177 &player->m_release
00178 };
00179
00180 *ports[port] = (float *)location;
00181 }
00182
00183 void
00184 SamplePlayer::activate(LADSPA_Handle handle)
00185 {
00186 SamplePlayer *player = (SamplePlayer *)handle;
00187 QMutexLocker locker(&player->m_mutex);
00188
00189 player->m_sampleNo = 0;
00190
00191 for (size_t i = 0; i < Polyphony; ++i) {
00192 player->m_ons[i] = -1;
00193 player->m_offs[i] = -1;
00194 player->m_velocities[i] = 0;
00195 }
00196 }
00197
00198 void
00199 SamplePlayer::run(LADSPA_Handle handle, unsigned long samples)
00200 {
00201 runSynth(handle, samples, 0, 0);
00202 }
00203
00204 void
00205 SamplePlayer::deactivate(LADSPA_Handle handle)
00206 {
00207 activate(handle);
00208 }
00209
00210 void
00211 SamplePlayer::cleanup(LADSPA_Handle handle)
00212 {
00213 delete (SamplePlayer *)handle;
00214 }
00215
00216 char *
00217 SamplePlayer::configure(LADSPA_Handle handle, const char *key, const char *value)
00218 {
00219 if (key && !strcmp(key, "sampledir")) {
00220
00221 SamplePlayer *player = (SamplePlayer *)handle;
00222
00223 QMutexLocker locker(&player->m_mutex);
00224
00225 if (QFileInfo(value).exists() &&
00226 QFileInfo(value).isDir()) {
00227
00228 player->m_sampleDir = value;
00229
00230 if (player->m_sampleSearchComplete) {
00231 player->m_sampleSearchComplete = false;
00232 player->searchSamples();
00233 }
00234
00235 return 0;
00236
00237 } else {
00238 char *buffer = (char *)malloc(strlen(value) + 80);
00239 sprintf(buffer, "Sample directory \"%s\" does not exist, leaving unchanged", value);
00240 return buffer;
00241 }
00242 }
00243
00244 return strdup("Unknown configure key");
00245 }
00246
00247 const DSSI_Program_Descriptor *
00248 SamplePlayer::getProgram(LADSPA_Handle handle, unsigned long program)
00249 {
00250 SamplePlayer *player = (SamplePlayer *)handle;
00251
00252 if (!player->m_sampleSearchComplete) {
00253 QMutexLocker locker(&player->m_mutex);
00254 if (!player->m_sampleSearchComplete) {
00255 player->searchSamples();
00256 }
00257 }
00258 if (program >= player->m_samples.size()) return 0;
00259
00260 static DSSI_Program_Descriptor descriptor;
00261 static char name[60];
00262
00263 strncpy(name, player->m_samples[program].first.toLocal8Bit().data(), 60);
00264 name[59] = '\0';
00265
00266 descriptor.Bank = 0;
00267 descriptor.Program = program;
00268 descriptor.Name = name;
00269
00270 return &descriptor;
00271 }
00272
00273 void
00274 SamplePlayer::selectProgram(LADSPA_Handle handle,
00275 unsigned long,
00276 unsigned long program)
00277 {
00278 SamplePlayer *player = (SamplePlayer *)handle;
00279 player->m_pendingProgramChange = program;
00280 }
00281
00282 int
00283 SamplePlayer::getMidiController(LADSPA_Handle, unsigned long port)
00284 {
00285 int controllers[PortCount] = {
00286 DSSI_NONE,
00287 DSSI_CC(12),
00288 DSSI_CC(13),
00289 DSSI_CC(64),
00290 DSSI_CC(72)
00291 };
00292
00293 return controllers[port];
00294 }
00295
00296 void
00297 SamplePlayer::runSynth(LADSPA_Handle handle, unsigned long samples,
00298 snd_seq_event_t *events, unsigned long eventCount)
00299 {
00300 SamplePlayer *player = (SamplePlayer *)handle;
00301
00302 player->runImpl(samples, events, eventCount);
00303 }
00304
00305 void
00306 SamplePlayer::receiveHostDescriptor(const DSSI_Host_Descriptor *descriptor)
00307 {
00308 hostDescriptor = descriptor;
00309 }
00310
00311 void
00312 SamplePlayer::workThreadCallback(LADSPA_Handle handle)
00313 {
00314 SamplePlayer *player = (SamplePlayer *)handle;
00315
00316 if (player->m_pendingProgramChange >= 0) {
00317
00318
00319
00320 player->m_mutex.lock();
00321
00322 int program = player->m_pendingProgramChange;
00323 player->m_pendingProgramChange = -1;
00324
00325 if (!player->m_sampleSearchComplete) {
00326 player->searchSamples();
00327 }
00328
00329 if (program < int(player->m_samples.size())) {
00330 QString path = player->m_samples[program].second;
00331 QString programName = player->m_samples[program].first;
00332 if (programName != player->m_program) {
00333 player->m_program = programName;
00334 player->m_mutex.unlock();
00335 player->loadSampleData(path);
00336 } else {
00337 player->m_mutex.unlock();
00338 }
00339 }
00340 }
00341
00342 if (!player->m_sampleSearchComplete) {
00343
00344 QMutexLocker locker(&player->m_mutex);
00345
00346 if (!player->m_sampleSearchComplete) {
00347 player->searchSamples();
00348 }
00349 }
00350 }
00351
00352 void
00353 SamplePlayer::searchSamples()
00354 {
00355 if (m_sampleSearchComplete) return;
00356
00357 m_samples.clear();
00358
00359 std::cerr << "SamplePlayer::searchSamples: Directory is \""
00360 << m_sampleDir.toLocal8Bit().data() << "\"" << std::endl;
00361
00362 QDir dir(m_sampleDir, "*.wav");
00363
00364 for (unsigned int i = 0; i < dir.count(); ++i) {
00365 QFileInfo file(dir.filePath(dir[i]));
00366 if (file.isReadable()) {
00367 m_samples.push_back(std::pair<QString, QString>
00368 (file.baseName(), file.filePath()));
00369
00370 }
00371 }
00372
00373 m_sampleSearchComplete = true;
00374 }
00375
00376 void
00377 SamplePlayer::loadSampleData(QString path)
00378 {
00379 SF_INFO info;
00380 SNDFILE *file;
00381 size_t samples = 0;
00382 float *tmpFrames, *tmpSamples, *tmpResamples, *tmpOld;
00383 size_t i;
00384
00385 info.format = 0;
00386 file = sf_open(path.toLocal8Bit().data(), SFM_READ, &info);
00387 if (!file) {
00388 std::cerr << "SamplePlayer::loadSampleData: Failed to open file "
00389 << path.toLocal8Bit().data() << ": "
00390 << sf_strerror(file) << std::endl;
00391 return;
00392 }
00393
00394 samples = info.frames;
00395 tmpFrames = (float *)malloc(info.frames * info.channels * sizeof(float));
00396 if (!tmpFrames) return;
00397
00398 sf_readf_float(file, tmpFrames, info.frames);
00399 sf_close(file);
00400
00401 tmpResamples = 0;
00402
00403 if (info.samplerate != m_sampleRate) {
00404
00405 double ratio = (double)m_sampleRate / (double)info.samplerate;
00406 size_t target = (size_t)(info.frames * ratio);
00407 SRC_DATA data;
00408
00409 tmpResamples = (float *)malloc(target * info.channels * sizeof(float));
00410 if (!tmpResamples) {
00411 free(tmpFrames);
00412 return;
00413 }
00414
00415 memset(tmpResamples, 0, target * info.channels * sizeof(float));
00416
00417 data.data_in = tmpFrames;
00418 data.data_out = tmpResamples;
00419 data.input_frames = info.frames;
00420 data.output_frames = target;
00421 data.src_ratio = ratio;
00422
00423 if (!src_simple(&data, SRC_SINC_BEST_QUALITY, info.channels)) {
00424 free(tmpFrames);
00425 tmpFrames = tmpResamples;
00426 samples = target;
00427 } else {
00428 free(tmpResamples);
00429 }
00430 }
00431
00432
00433 tmpSamples = (float *)malloc((samples + 1) * sizeof(float));
00434 if (!tmpSamples) {
00435 free(tmpFrames);
00436 return;
00437 }
00438
00439 for (i = 0; i < samples; ++i) {
00440 int j;
00441 tmpSamples[i] = 0.0f;
00442 for (j = 0; j < info.channels; ++j) {
00443 tmpSamples[i] += tmpFrames[i * info.channels + j];
00444 }
00445 }
00446
00447 free(tmpFrames);
00448
00449
00450 tmpSamples[samples] = 0.0f;
00451
00452 QMutexLocker locker(&m_mutex);
00453
00454 tmpOld = m_sampleData;
00455 m_sampleData = tmpSamples;
00456 m_sampleCount = samples;
00457
00458 for (i = 0; i < Polyphony; ++i) {
00459 m_ons[i] = -1;
00460 m_offs[i] = -1;
00461 m_velocities[i] = 0;
00462 }
00463
00464 if (tmpOld) free(tmpOld);
00465
00466 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);
00467 }
00468
00469 void
00470 SamplePlayer::runImpl(unsigned long sampleCount,
00471 snd_seq_event_t *events,
00472 unsigned long eventCount)
00473 {
00474 unsigned long pos;
00475 unsigned long count;
00476 unsigned long event_pos;
00477 int i;
00478
00479 memset(m_output, 0, sampleCount * sizeof(float));
00480
00481 if (!m_mutex.tryLock()) return;
00482
00483 if (!m_sampleData || !m_sampleCount) {
00484 m_sampleNo += sampleCount;
00485 m_mutex.unlock();
00486 return;
00487 }
00488
00489 for (pos = 0, event_pos = 0; pos < sampleCount; ) {
00490
00491 while (event_pos < eventCount
00492 && pos >= events[event_pos].time.tick) {
00493
00494 if (events[event_pos].type == SND_SEQ_EVENT_NOTEON) {
00495 snd_seq_ev_note_t n = events[event_pos].data.note;
00496 if (n.velocity > 0) {
00497 m_ons[n.note] =
00498 m_sampleNo + events[event_pos].time.tick;
00499 m_offs[n.note] = -1;
00500 m_velocities[n.note] = n.velocity;
00501 } else {
00502 if (!m_sustain || (*m_sustain < 0.001)) {
00503 m_offs[n.note] =
00504 m_sampleNo + events[event_pos].time.tick;
00505 }
00506 }
00507 } else if (events[event_pos].type == SND_SEQ_EVENT_NOTEOFF &&
00508 (!m_sustain || (*m_sustain < 0.001))) {
00509 snd_seq_ev_note_t n = events[event_pos].data.note;
00510 m_offs[n.note] =
00511 m_sampleNo + events[event_pos].time.tick;
00512 }
00513
00514 ++event_pos;
00515 }
00516
00517 count = sampleCount - pos;
00518 if (event_pos < eventCount &&
00519 events[event_pos].time.tick < sampleCount) {
00520 count = events[event_pos].time.tick - pos;
00521 }
00522
00523 for (i = 0; i < Polyphony; ++i) {
00524 if (m_ons[i] >= 0) {
00525 addSample(i, pos, count);
00526 }
00527 }
00528
00529 pos += count;
00530 }
00531
00532 m_sampleNo += sampleCount;
00533 m_mutex.unlock();
00534 }
00535
00536 void
00537 SamplePlayer::addSample(int n, unsigned long pos, unsigned long count)
00538 {
00539 float ratio = 1.f;
00540 float gain = 1.f;
00541 unsigned long i, s;
00542
00543 if (m_retune && *m_retune) {
00544 if (m_concertA) {
00545 ratio *= *m_concertA / 440.f;
00546 }
00547 if (m_basePitch && n != *m_basePitch) {
00548 ratio *= powf(1.059463094f, n - *m_basePitch);
00549 }
00550 }
00551
00552 if (long(pos + m_sampleNo) < m_ons[n]) return;
00553
00554 gain = (float)m_velocities[n] / 127.0f;
00555
00556 for (i = 0, s = pos + m_sampleNo - m_ons[n];
00557 i < count;
00558 ++i, ++s) {
00559
00560 float lgain = gain;
00561 float rs = s * ratio;
00562 unsigned long rsi = lrintf(floor(rs));
00563
00564 if (rsi >= m_sampleCount) {
00565 m_ons[n] = -1;
00566 break;
00567 }
00568
00569 if (m_offs[n] >= 0 &&
00570 long(pos + i + m_sampleNo) > m_offs[n]) {
00571
00572 unsigned long dist =
00573 pos + i + m_sampleNo - m_offs[n];
00574
00575 unsigned long releaseFrames = 200;
00576 if (m_release) {
00577 releaseFrames = long(*m_release * m_sampleRate + 0.0001);
00578 }
00579
00580 if (dist > releaseFrames) {
00581 m_ons[n] = -1;
00582 break;
00583 } else {
00584 lgain = lgain * (float)(releaseFrames - dist) /
00585 (float)releaseFrames;
00586 }
00587 }
00588
00589 float sample = m_sampleData[rsi] +
00590 ((m_sampleData[rsi + 1] -
00591 m_sampleData[rsi]) *
00592 (rs - (float)rsi));
00593
00594 m_output[pos + i] += lgain * sample;
00595 }
00596 }