Skip to content

Commit

Permalink
Merge pull request #3 from daschuer/1.12-shoutcast-fixes
Browse files Browse the repository at this point in the history
Merging Shoutcast thread fixes
  • Loading branch information
illuusio committed Aug 31, 2015
2 parents 3779b56 + aa441ce commit 5309349
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 176 deletions.
51 changes: 38 additions & 13 deletions src/engine/sidechain/enginenetworkstream.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#ifdef __WINDOWS__
#include <windows.h>
#include <mmsystem.h>
#else
#include <sys/time.h>
#include <unistd.h>
Expand All @@ -11,7 +10,15 @@

#include "sampleutil.h"

unsigned int kBufferFrames = 32768; // 743 ms @ 44100 Hz
const int kBufferFrames = 32768; // 743 ms @ 44100 Hz
const int kNetworkLatencyFrames = 8192; // 743 ms @ 44100 Hz
// Related chunk sizes:
// Mp3 frames = 1152 samples
// Ogg frames = 64 to 8192 samples.
// In Mixxx 1.11 we transmit every decoder-frames at once,
// Which results in case of ogg in a dynamic latency from 0.14 ms to to 180 ms
// Now we have switched to a fixed latency of 8192 frames (stereo samples) =
// which is 185 @ 44100 ms and twice the maximum of the max mixxx audio buffer

EngineNetworkStream::EngineNetworkStream(int numOutputChannels,
int numInputChannels)
Expand All @@ -20,7 +27,7 @@ EngineNetworkStream::EngineNetworkStream(int numOutputChannels,
m_numOutputChannels(numOutputChannels),
m_numInputChannels(numInputChannels),
m_sampleRate(0),
m_streamStartTimeMs(-1),
m_streamStartTimeUs(-1),
m_streamFramesWritten(0),
m_streamFramesRead(0) {
if (numOutputChannels) {
Expand All @@ -32,7 +39,7 @@ EngineNetworkStream::EngineNetworkStream(int numOutputChannels,
}

EngineNetworkStream::~EngineNetworkStream() {
if (m_streamStartTimeMs >= 0) {
if (m_streamStartTimeUs >= 0) {
stopStream();
}
delete m_pOutputFifo;
Expand All @@ -41,12 +48,12 @@ EngineNetworkStream::~EngineNetworkStream() {

void EngineNetworkStream::startStream(double sampleRate) {
m_sampleRate = sampleRate;
m_streamStartTimeMs = getNetworkTimeMs();
m_streamStartTimeUs = getNetworkTimeUs();
m_streamFramesWritten = 0;
}

void EngineNetworkStream::stopStream() {
m_streamStartTimeMs = -1;
m_streamStartTimeUs = -1;
}

int EngineNetworkStream::getWriteExpected() {
Expand All @@ -73,6 +80,7 @@ void EngineNetworkStream::write(const CSAMPLE* buffer, int frames) {
(void)m_pOutputFifo->write(buffer, copyCount);
}
m_streamFramesWritten += frames;
scheduleWorker();
}

void EngineNetworkStream::writeSilence(int frames) {
Expand Down Expand Up @@ -101,6 +109,14 @@ void EngineNetworkStream::writeSilence(int frames) {
m_pOutputFifo->releaseWriteRegions(clearCount);
}
m_streamFramesWritten += frames;
scheduleWorker();
}

void EngineNetworkStream::scheduleWorker() {
if (m_pOutputFifo->readAvailable()
>= m_numOutputChannels * kNetworkLatencyFrames) {
m_pWorker->outputAvailabe(m_pOutputFifo);
}
}

void EngineNetworkStream::read(CSAMPLE* buffer, int frames) {
Expand All @@ -120,23 +136,32 @@ void EngineNetworkStream::read(CSAMPLE* buffer, int frames) {
}
}

qint64 EngineNetworkStream::getStreamTimeMs() {
return getNetworkTimeMs() - m_streamStartTimeMs;
qint64 EngineNetworkStream::getStreamTimeFrames() {
return static_cast<double>(getStreamTimeUs()) * m_sampleRate / 1000000.0;
}

qint64 EngineNetworkStream::getStreamTimeFrames() {
return static_cast<double>(getStreamTimeMs()) * m_sampleRate / 1000;
qint64 EngineNetworkStream::getStreamTimeUs() {
return getNetworkTimeUs() - m_streamStartTimeUs;
}

// static
qint64 EngineNetworkStream::getNetworkTimeMs() {
qint64 EngineNetworkStream::getNetworkTimeUs() {
// This matches the GPL2 implementation found in
// https://github.com/codders/libshout/blob/a17fb84671d3732317b0353d7281cc47e2df6cf6/src/timing/timing.c
// Instead of ms resuolution we use a us resolution to allow low latency settings
// will overflow > 200,000 years
#ifdef __WINDOWS__
return timeGetTime();
FILETIME ft;
int64_t t;
GetSystemTimeAsFileTime(&ft);
return ((qint64)ft.dwHighDateTime << 32 | ft.dwLowDateTime) / 10;
#else
struct timeval mtv;
gettimeofday(&mtv, NULL);
return (qint64)(mtv.tv_sec) * 1000 + (qint64)(mtv.tv_usec) / 1000;
return (qint64)(mtv.tv_sec) * 1000000 + mtv.tv_usec;
#endif
}

void EngineNetworkStream::addWorker(QSharedPointer<SideChainWorker> pWorker) {
m_pWorker = pWorker;
}
15 changes: 7 additions & 8 deletions src/engine/sidechain/enginenetworkstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@

#include "util/types.h"
#include "util/fifo.h"

class SideChainWorker;
#include "engine/sidechain/sidechainworker.h"

class EngineNetworkStream {
public:
Expand All @@ -22,7 +21,7 @@ class EngineNetworkStream {
void read(CSAMPLE* buffer, int frames);
void writeSilence(int frames);

qint64 getStreamTimeMs();
qint64 getStreamTimeUs();
qint64 getStreamTimeFrames();

int getNumOutputChannels() {
Expand All @@ -33,19 +32,19 @@ class EngineNetworkStream {
return m_numInputChannels;
}

static qint64 getNetworkTimeMs();
static qint64 getNetworkTimeUs();

void addWorker(QSharedPointer<SideChainWorker> pWorker) {
m_pWorker = pWorker;
}
void addWorker(QSharedPointer<SideChainWorker> pWorker);

private:
void scheduleWorker();

FIFO<CSAMPLE>* m_pOutputFifo;
FIFO<CSAMPLE>* m_pInputFifo;
int m_numOutputChannels;
int m_numInputChannels;
double m_sampleRate;
qint64 m_streamStartTimeMs;
qint64 m_streamStartTimeUs;
qint64 m_streamFramesWritten;
qint64 m_streamFramesRead;
QSharedPointer<SideChainWorker> m_pWorker;
Expand Down
Loading

0 comments on commit 5309349

Please sign in to comment.