diff options
-rw-r--r-- | src/soundplayer.cc | 123 | ||||
-rw-r--r-- | src/soundplayer.h | 15 |
2 files changed, 87 insertions, 51 deletions
diff --git a/src/soundplayer.cc b/src/soundplayer.cc index 2570f31..c170ff2 100644 --- a/src/soundplayer.cc +++ b/src/soundplayer.cc @@ -104,72 +104,97 @@ void SoundPlayer::run() ao_shutdown(); } -void SoundPlayer::playFile(QString file) +SoundPlayer::Samples SoundPlayer::getSampleData(QString file) { - printf(" - playFile(%s)\n", file.toStdString().c_str()); - - SNDFILE *fh; - SF_INFO sf_info; - - fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info); - if(!fh) + // Not yet in cache. Read it from file + if(!cache.contains(file)) { - printf("Load error '%s'\n", file.toStdString().c_str()); - return; - } + printf("Insert '%s' into cache\n", file.toStdString().data()); + SNDFILE *fh; + SF_INFO sf_info; - size_t size = sf_info.frames * sf_info.channels; - float *data = new float[size]; - sf_read_float(fh, data, size); - sf_close(fh); + fh = sf_open(file.toStdString().c_str(), SFM_READ, &sf_info); + if(!fh) + { + printf("Load error '%s'\n", file.toStdString().c_str()); + return {}; + } - if(sf_info.channels != 2) - { - float* stereo_data = new float[sf_info.frames * 2]; - for(int i = 0; i < sf_info.frames; ++i) + size_t size = sf_info.frames * sf_info.channels; + float *data = new float[size]; + sf_read_float(fh, data, size); + sf_close(fh); + + if(sf_info.channels != 2) { - int c = 0; - for(;c < sf_info.channels && c < 2; ++c) - { - stereo_data[i * 2 + c] = data[i * sf_info.channels + c]; - } - int last = c - 1; - for(;c < 2; ++c) + printf("channel convert %d => 2\n", (int)sf_info.channels); + float* stereo_data = new float[sf_info.frames * 2]; + for(int i = 0; i < sf_info.frames; ++i) { - stereo_data[i * 2 + c] = data[i * sf_info.channels + last]; + int c = 0; + for(;c < sf_info.channels && c < 2; ++c) + { + stereo_data[i * 2 + c] = data[i * sf_info.channels + c]; + } + int last = c - 1; + for(;c < 2; ++c) + { + stereo_data[i * 2 + c] = data[i * sf_info.channels + last]; + } } + delete[] data; + data = stereo_data; + size = sf_info.frames * 2; } - delete[] data; - data = stereo_data; - size = sf_info.frames * 2; - } - if(sf_info.samplerate != 48000) - { - double ratio = 48000.0 / sf_info.samplerate; - std::size_t resampled_size = sf_info.frames * 2 * ratio; - float *resampled_data = new float[resampled_size + 1]; + if(sf_info.samplerate != 48000) + { + printf("resample %d => 48000\n", (int)sf_info.samplerate); + double ratio = 48000.0 / sf_info.samplerate; + std::size_t resampled_frames = sf_info.frames * ratio; + float *resampled_data = new float[resampled_frames * 2]; + + SRC_DATA s{}; + s.data_in = data; + s.input_frames = sf_info.frames; - SRC_DATA s{}; - s.data_in = data; - s.input_frames = sf_info.frames; + s.data_out = resampled_data; + s.output_frames = resampled_frames; - s.data_out = resampled_data; - s.output_frames = resampled_size + 1; + s.src_ratio = ratio; - s.src_ratio = ratio; + int err = src_simple(&s, SRC_SINC_BEST_QUALITY, 2); + if(err) + { + printf("SRC error: %s\n", src_strerror(err)); + } + delete[] data; + data = resampled_data; + size = s.output_frames_gen * 2; + printf("size: %d\n", (int)size); + } - src_simple(&s, SRC_SINC_BEST_QUALITY, 2); - delete[] data; - data = resampled_data; - size = s.output_frames_gen * 2; - printf("size: %d\n", (int)size); + Samples s; + s.data = data; + s.size = size; + printf(" - %p %d\n", (void*)s.data, (int)s.size); + cache.insert(file, s); } + return cache[file]; +} + +void SoundPlayer::playFile(QString file) +{ + auto samples = getSampleData(file); + + printf(" - playFile(%s) [%p %d]\n", file.toStdString().c_str(), + (void*)samples.data, (int)samples.size); + QueueItem qi; - qi.samples = data; + qi.samples = samples.data; qi.pos = 0; - qi.size = size; + qi.size = samples.size; { QMutexLocker lock(&mutex); diff --git a/src/soundplayer.h b/src/soundplayer.h index 8502e6e..d8ba929 100644 --- a/src/soundplayer.h +++ b/src/soundplayer.h @@ -31,13 +31,16 @@ #include <QString> #include <QList> #include <QMutex> +#include <QMap> + +#include <cstdlib> class QueueItem { public: float *samples; - size_t pos; - size_t size; + std::size_t pos; + std::size_t size; }; class SoundPlayer @@ -57,4 +60,12 @@ private: QList<QueueItem> queue; QList<QueueItem> active; + + struct Samples + { + float *data; + std::size_t size; + }; + Samples getSampleData(QString file); + QMap<QString, Samples> cache; }; |