#include "Streamer.hpp" typedef u_int8_t uint8_t; typedef u_int16_t uint16_t; typedef u_int32_t uint32_t; #define DR_FLAC_IMPLEMENTATION #include "dr_flac.h" #include class Context { public: Context() = default; bool preloadInfo(const tp::String& path, MusicStream* owner) { mOwner = owner; pFlac = drflac_open_file((path + ".flac").read(), NULL); if (pFlac == NULL) { return false; } if (pFlac->channels != 2) { drflac_close(pFlac); return false; } mOwner->mLengthFrames = pFlac->totalPCMFrameCount; mOwner->mChanels = pFlac->channels; mOwner->mRate = pFlac->sampleRate; mOwner->mBuffer.reserve(mOwner->mLengthFrames * 2); return true; } void runThread() { if (threadRunning) return; threadRunning = true; threadObj = std::thread(&Context::threadWorkStatic, this); } void stop() { if (threadRunning) { exitThread = true; threadObj.join(); threadRunning = false; exitThread = false; } if (pFlac) drflac_close(pFlac); pFlac = nullptr; } ~Context() { stop(); } private: std::thread threadObj; bool threadRunning = false; bool exitThread = false; void threadWork() { int framesRead = 0; while (!exitThread && (framesRead = drflac_read_pcm_frames_f32(pFlac, mOwner->mRate, mOwner->mBuffer.getBuff() + mOwner->mProgress * 2)) > 0) { mOwner->mProgress += framesRead; // drflac_seek_to_pcm_frame(pFlac, mOwner->mProgress); // tp::sleep(500); } } static void threadWorkStatic(void* p) { ((Context*) p)->threadWork(); } public: drflac* pFlac = nullptr; MusicStream* mOwner; }; MusicStream::MusicStream() { mContext = new Context(); } MusicStream::~MusicStream() { delete mContext; } bool MusicStream::openStream(SongId id) { closeStream(); auto const path = getSongLocalPath(id); auto format = getSongFormat(path); if (format != SONG_FORMAT::FLAC) return false; return mContext->preloadInfo(path, this); } void MusicStream::closeStream() { mContext->stop(); mProgress = 0; } tp::halnf* MusicStream::getBuffer() { return mBuffer.getBuff(); } tp::ualni* MusicStream::getProgressLive() { return &mProgress; } tp::uhalni MusicStream::getRate() const { return mRate; } void MusicStream::continueStream() { mContext->runThread(); } tp::ualni MusicStream::getFramesLength() const { return mLengthFrames; } tp::ualni MusicStream::getFramesLoaded() const { return mProgress; }