fix: mutex fun: ensure a: stretcher for oboe_cb MusicProvider::onAudioReady, b: musicFile for musicFeedThread
This commit is contained in:
@@ -157,6 +157,13 @@ void PlaybackEngine::initRubberBand() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlaybackEngine::closeRubberBand() {
|
void PlaybackEngine::closeRubberBand() {
|
||||||
|
if (mPlayer) {
|
||||||
|
LOGI("PlaybackEngine: mPlayer->stopAudio() ...");
|
||||||
|
mPlayer->stopAudio();
|
||||||
|
LOGI("PlaybackEngine: mPlayer->stopAudio() done.");
|
||||||
|
delete mPlayer;
|
||||||
|
mPlayer = nullptr;
|
||||||
|
}
|
||||||
if(musicFeed) {
|
if(musicFeed) {
|
||||||
exitMusicFeedThread.store(true);
|
exitMusicFeedThread.store(true);
|
||||||
LOGI("PlaybackEngine: musicFeed->join() ...");
|
LOGI("PlaybackEngine: musicFeed->join() ...");
|
||||||
@@ -164,7 +171,6 @@ void PlaybackEngine::closeRubberBand() {
|
|||||||
LOGI("PlaybackEngine: musicFeed->join() done.");
|
LOGI("PlaybackEngine: musicFeed->join() done.");
|
||||||
musicFeed = nullptr;
|
musicFeed = nullptr;
|
||||||
}
|
}
|
||||||
closeMusicFile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaybackEngine::closeMusicFile() {
|
void PlaybackEngine::closeMusicFile() {
|
||||||
@@ -209,6 +215,7 @@ void PlaybackEngine::musicFeedThread() {
|
|||||||
std::mt19937 mt(42);
|
std::mt19937 mt(42);
|
||||||
std::uniform_real_distribution<double> dist(0.98, 1.0);
|
std::uniform_real_distribution<double> dist(0.98, 1.0);
|
||||||
*/
|
*/
|
||||||
|
bool isOnTrackFinished = false;
|
||||||
LOGI("starting musicFeedThread()");
|
LOGI("starting musicFeedThread()");
|
||||||
|
|
||||||
// strecher num channels: same as output num channels
|
// strecher num channels: same as output num channels
|
||||||
@@ -243,6 +250,11 @@ void PlaybackEngine::musicFeedThread() {
|
|||||||
// thread 2: polling for decoding more mp3 -> process() -- getSamplesRequired()
|
// thread 2: polling for decoding more mp3 -> process() -- getSamplesRequired()
|
||||||
while(!exitMusicFeedThread.load()) {
|
while(!exitMusicFeedThread.load()) {
|
||||||
|
|
||||||
|
if(isOnTrackFinished) {
|
||||||
|
if(listener) listener->onTrackFinished();
|
||||||
|
isOnTrackFinished = false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!haveMusicFile.load()) {
|
if(!haveMusicFile.load()) {
|
||||||
// while no MusicProvider is connected, no samples will be read from 'stretcher'
|
// while no MusicProvider is connected, no samples will be read from 'stretcher'
|
||||||
// therefore, we do not write any samples into it!
|
// therefore, we do not write any samples into it!
|
||||||
@@ -325,6 +337,11 @@ void PlaybackEngine::musicFeedThread() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t num_decoded_samples;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mMusicLock);
|
||||||
|
if(!haveMusicFile.load()) continue;
|
||||||
|
|
||||||
if(idebug++ < 10) {
|
if(idebug++ < 10) {
|
||||||
pr = std::max(1L, musicFile->rate);
|
pr = std::max(1L, musicFile->rate);
|
||||||
loop_delay_us = std::min((size_t) 50000, (size_t) 1000000 * num_samples / pr);
|
loop_delay_us = std::min((size_t) 50000, (size_t) 1000000 * num_samples / pr);
|
||||||
@@ -399,6 +416,8 @@ void PlaybackEngine::musicFeedThread() {
|
|||||||
stretcher.setPitchScale(1.0);
|
stretcher.setPitchScale(1.0);
|
||||||
stretcher.process(buf_ptr, 0, true); // set end of playback
|
stretcher.process(buf_ptr, 0, true); // set end of playback
|
||||||
mPlayer->stopAudio();
|
mPlayer->stopAudio();
|
||||||
|
// TODO: raise error
|
||||||
|
//if(listener) listener->onError(1, "mpg123_read() error");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(err == MPG123_DONE) {
|
if(err == MPG123_DONE) {
|
||||||
@@ -407,11 +426,12 @@ void PlaybackEngine::musicFeedThread() {
|
|||||||
LOGI("finished reading mp3 file (MPG123_DONE)");
|
LOGI("finished reading mp3 file (MPG123_DONE)");
|
||||||
idebug = 0;
|
idebug = 0;
|
||||||
closeMusicFile();
|
closeMusicFile();
|
||||||
if(listener) listener->onTrackFinished();
|
//if(listener) listener->onTrackFinished();
|
||||||
|
isOnTrackFinished = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t num_decoded_samples = done / sizeof(int16_t) / num_ch_in;
|
num_decoded_samples = done / sizeof(int16_t) / num_ch_in;
|
||||||
//LOGD("num_decoded_samples = %d", num_decoded_samples);
|
//LOGD("num_decoded_samples = %d", num_decoded_samples);
|
||||||
|
|
||||||
// * convert interleaved int16 to de-interleaved float [-1.0, 1.0] format
|
// * convert interleaved int16 to de-interleaved float [-1.0, 1.0] format
|
||||||
@@ -421,11 +441,17 @@ void PlaybackEngine::musicFeedThread() {
|
|||||||
buf[i + buf_stride * j] = static_cast<float>(*(reinterpret_cast<int16_t*>(cbuf) + i * num_ch_in + channel_map[j])) / 32768.0f;
|
buf[i + buf_stride * j] = static_cast<float>(*(reinterpret_cast<int16_t*>(cbuf) + i * num_ch_in + channel_map[j])) / 32768.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//LOGD("calling stretcher.process()");
|
//LOGD("calling stretcher.process()");
|
||||||
stretcher.process(buf_ptr, num_decoded_samples, false);
|
stretcher.process(buf_ptr, num_decoded_samples, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isOnTrackFinished) {
|
||||||
|
if(listener) listener->onTrackFinished();
|
||||||
|
//isOnTrackFinished = false;
|
||||||
|
}
|
||||||
|
|
||||||
LOGI("musicFeedThread() exiting ...");
|
LOGI("musicFeedThread() exiting ...");
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
@@ -462,12 +488,9 @@ void PlaybackEngine::seekTo(double markerPosSec) {
|
|||||||
void PlaybackEngine::stop() {
|
void PlaybackEngine::stop() {
|
||||||
LOGI("PlaybackEngine::stop()");
|
LOGI("PlaybackEngine::stop()");
|
||||||
closeRubberBand();
|
closeRubberBand();
|
||||||
if (mPlayer) {
|
{
|
||||||
LOGI("PlaybackEngine: mPlayer->stopAudio() ...");
|
std::lock_guard<std::mutex> lock(mMusicLock);
|
||||||
mPlayer->stopAudio();
|
closeMusicFile();
|
||||||
LOGI("PlaybackEngine: mPlayer->stopAudio() done.");
|
|
||||||
delete mPlayer;
|
|
||||||
mPlayer = nullptr;
|
|
||||||
}
|
}
|
||||||
markerPos.store(0.0);
|
markerPos.store(0.0);
|
||||||
duration.store(0.0);
|
duration.store(0.0);
|
||||||
@@ -476,10 +499,9 @@ void PlaybackEngine::stop() {
|
|||||||
PlaybackEngine::~PlaybackEngine() {
|
PlaybackEngine::~PlaybackEngine() {
|
||||||
LOGI("~PlaybackEngine()");
|
LOGI("~PlaybackEngine()");
|
||||||
closeRubberBand();
|
closeRubberBand();
|
||||||
if (mPlayer) {
|
{
|
||||||
mPlayer->stopAudio();
|
std::lock_guard<std::mutex> lock(mMusicLock);
|
||||||
delete mPlayer;
|
closeMusicFile();
|
||||||
mPlayer = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,25 +512,33 @@ void PlaybackEngine::playBeat() {
|
|||||||
void PlaybackEngine::playMusic(int fd, long long offset, long long length) {
|
void PlaybackEngine::playMusic(int fd, long long offset, long long length) {
|
||||||
if(!mPlayer) return;
|
if(!mPlayer) return;
|
||||||
LOGI("PlaybackEngine::playMusic(fd=%d)", fd);
|
LOGI("PlaybackEngine::playMusic(fd=%d)", fd);
|
||||||
if(musicFile) {
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mMusicLock);
|
||||||
|
|
||||||
|
if (musicFile) {
|
||||||
|
if (fd == android_fd)
|
||||||
|
android_fd = 0; // HACK: avoid closing the 'fd' if re-opening the same file
|
||||||
// when changing tracks in the UI, close the previous file
|
// when changing tracks in the UI, close the previous file
|
||||||
closeMusicFile();
|
closeMusicFile();
|
||||||
}
|
}
|
||||||
android_fd = fd;
|
android_fd = fd;
|
||||||
if(fd != 0)
|
if (fd != 0)
|
||||||
musicFile.reset(mp3file_open_fd(android_fd, offset, length, 0));
|
musicFile.reset(mp3file_open_fd(android_fd, offset, length, 0));
|
||||||
if(musicFile) {
|
if (musicFile) {
|
||||||
timeRatio.store(((double) playbackRate.load()) / ((double) musicFile->rate));
|
timeRatio.store(((double) playbackRate.load()) / ((double) musicFile->rate));
|
||||||
haveTimeRatio.store(true);
|
haveTimeRatio.store(true);
|
||||||
numInChannels.store(musicFile->channels);
|
numInChannels.store(musicFile->channels);
|
||||||
haveMusicFile.store(true);
|
haveMusicFile.store(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool is_finished = (stretcher.available() == -1);
|
bool is_finished = (stretcher.available() == -1);
|
||||||
if(is_finished) {
|
if(is_finished) {
|
||||||
LOGE("stretcher.available() == -1, this should not happen anymore with current wiring");
|
LOGE("stretcher.available() == -1, this should not happen anymore with current wiring");
|
||||||
// so that we may play again after "final chunk"
|
// so that we may play again after "final chunk"
|
||||||
closeRubberBand();
|
closeRubberBand();
|
||||||
|
// do not closeMusicFile() here, it would close the very file we want to be playing
|
||||||
initRubberBand();
|
initRubberBand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ private:
|
|||||||
RubberBand::RubberBandStretcher stretcher;
|
RubberBand::RubberBandStretcher stretcher;
|
||||||
MixingPlayer *mPlayer;
|
MixingPlayer *mPlayer;
|
||||||
std::string mFilesDir;
|
std::string mFilesDir;
|
||||||
|
std::mutex mMusicLock;
|
||||||
std::unique_ptr<MP3File> musicFile;
|
std::unique_ptr<MP3File> musicFile;
|
||||||
std::atomic<bool> haveMusicFile;
|
std::atomic<bool> haveMusicFile;
|
||||||
std::unique_ptr<std::thread> musicFeed;
|
std::unique_ptr<std::thread> musicFeed;
|
||||||
|
|||||||
Reference in New Issue
Block a user