diff --git a/src/HCADecodeService.cpp b/src/HCADecodeService.cpp index 6685664..a78ff84 100644 --- a/src/HCADecodeService.cpp +++ b/src/HCADecodeService.cpp @@ -3,25 +3,20 @@ #include "HCADecodeService.h" #include "clHCA.h" -// Currently multithreaded decode is bugged, please use single thread for now +// Currently multithreaded decode is bugged due to out of order decoding HCADecodeService::HCADecodeService(unsigned int numthreads) - : mainsem(numthreads), + : mainsem(1), + numthreads{1}, // Use single thread for now datasem{ 0 }, + finsem{0}, numchannels{0}, workingrequest{nullptr}, channels{nullptr}, shutdown{false} { - if(numthreads > 0) - { - this->numthreads = numthreads; - } - else - { - this->numthreads = 1; - } - workingblocks = new int[numthreads]; - for (unsigned int i = 0; i < numthreads; ++i) + workingblocks = new int[this->numthreads]; + channels = new clHCA::stChannel[0x10 * this->numthreads]; + for (unsigned int i = 0; i < this->numthreads; ++i) { workersem.emplace_back(0); worker_threads.emplace_back(&HCADecodeService::Decode_Thread, this, i); @@ -35,6 +30,7 @@ HCADecodeService::~HCADecodeService() shutdown = true; datasem.notify(); dispatchthread.join(); + delete[] channels; } void HCADecodeService::cancel_decode(void* ptr) @@ -59,6 +55,18 @@ void HCADecodeService::cancel_decode(void* ptr) } } +void HCADecodeService::wait_for_finish() +{ + mutex.lock(); + while(!filelist.empty() || !blocks.empty()) + { + mutex.unlock(); + finsem.wait(); + mutex.lock(); + } + mutex.unlock(); +} + std::pair HCADecodeService::decode(const std::string& filename, DWORD samplenum) { clHCA hca(0xBC731A85, 0x0002B875); @@ -91,11 +99,11 @@ void HCADecodeService::Main_Thread() workingfile = std::move(it->second); unsigned blocknum = it->first.second; filelist.erase(it); - numchannels = workingfile.get_channelCount(); - channels = new clHCA::stChannel[numchannels * numthreads]; + numchannels = workingfile.get_channelCount(); workingfile.PrepDecode(channels, numthreads); unsigned int blockCount = workingfile.get_blockCount(); - for (unsigned int i = blocknum, j = 0; j < blockCount; ++i, ++j) + // initiate playback right away, and patch up "blip" cause by out of order decoding + for (unsigned int i = blocknum, j = 0; j < blockCount + blocknum; ++i, ++j) { blocks.push_back(i % blockCount); } @@ -121,8 +129,8 @@ void HCADecodeService::Main_Thread() for (unsigned int i = 0; i < numthreads; ++i) { while (workingblocks[i] != -1); // busy wait until threads are finished - } - delete[] channels; + } + finsem.notify(); } for (int i = 0; i < numthreads; ++i) { diff --git a/src/HCADecodeService.h b/src/HCADecodeService.h index 94326cc..89f1cf7 100644 --- a/src/HCADecodeService.h +++ b/src/HCADecodeService.h @@ -14,7 +14,7 @@ class HCADecodeService ~HCADecodeService(); void cancel_decode(void* ptr); std::pair decode(const std::string& hcafilename, DWORD samplenum); - //void wait_for_finish(); + void wait_for_finish(); private: void Decode_Thread(int id); void Main_Thread(); @@ -27,7 +27,7 @@ class HCADecodeService std::deque blocks; int* workingblocks; std::deque workersem; - Semaphore mainsem, datasem; + Semaphore mainsem, datasem, finsem; std::mutex mutex; clHCA::stChannel* channels; bool shutdown; diff --git a/src/clHCA.cpp b/src/clHCA.cpp index 90d822b..1fad332 100644 --- a/src/clHCA.cpp +++ b/src/clHCA.cpp @@ -647,8 +647,9 @@ bool clHCA::Analyze(void*& wavptr, size_t& sz, const char* filenameHCA) void clHCA::AsyncDecode(stChannel* channelsOffset, unsigned int blocknum, unsigned char* outputwavptr) { int seekhead = 0; - outputwavptr += 2 * blocknum * 8 * 128 * _channelCount + 44; - unsigned char* data = (unsigned char*)hcafileptr + (blocknum * _blockSize); + outputwavptr += 2 * blocknum * 8 * 128 * _channelCount + 44; + unsigned char* data = new unsigned char[_blockSize]; + memcpy(data, (unsigned char*)hcafileptr + (blocknum * _blockSize), _blockSize); // if(((unsigned char *)data)[_blockSize-2]==0x5E)_asm int 3 _cipher.Mask(data, _blockSize); clData d(data, _blockSize); @@ -673,6 +674,7 @@ void clHCA::AsyncDecode(stChannel* channelsOffset, unsigned int blocknum, unsign } } } + delete[] data; } //-------------------------------------------------- diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 42c7234..4ef0117 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -190,6 +190,7 @@ void MainWindow::setBGM(const QString& qStr) std::string name = qStr.toUtf8().constData(); currSong = readablesong_to_filename[name]; BASS_ChannelPause(mix_stream); + dec.wait_for_finish(); BASS_Mixer_ChannelRemove(bgm->get_decode_channel()); bgm->unload(); bgm->load("res/" + currSong + "/bgm.hca");