125 lines
No EOL
2.3 KiB
C++
125 lines
No EOL
2.3 KiB
C++
#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 <thread>
|
|
|
|
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;
|
|
} |