git-svn-id: svn://elaine/murooma/trunk@70 d8a302eb-03bc-478d-80e4-98257eca68ef
This commit is contained in:
(no author) 2014-07-05 13:20:19 +00:00
parent 071405049e
commit 858e49a3ed
4 changed files with 117 additions and 61 deletions

View file

@ -16,6 +16,10 @@
template <size_t T> template <size_t T>
struct ChunkT struct ChunkT
{ {
// ChunkT()
// {
// memset(&payload[0], 0, T);
// }
int32_t tv_sec; int32_t tv_sec;
int32_t tv_usec; int32_t tv_usec;
int32_t idx; int32_t idx;

View file

@ -50,14 +50,14 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer,
(void) statusFlags; (void) statusFlags;
(void) inputBuffer; (void) inputBuffer;
std::vector<short> s = stream->getChunk(timeInfo->outputBufferDacTime, framesPerBuffer); PlayerChunk* playerChunk = stream->getChunk(timeInfo->outputBufferDacTime, framesPerBuffer);
for (size_t n=0; n<framesPerBuffer; n++) for (size_t n=0; n<framesPerBuffer; n++)
{ {
*out++ = s[2*n]; *out++ = playerChunk->payload[2*n];
*out++ = s[2*n+1]; *out++ = playerChunk->payload[2*n+1];
} }
// delete chunk; delete playerChunk;
return paContinue; return paContinue;
} }

148
stream.h
View file

@ -15,8 +15,9 @@
class Stream class Stream
{ {
public: public:
Stream() : median(0), shortMedian(0), lastUpdate(0), skip(0), idx(0) Stream() : lastPlayerChunk(NULL), median(0), shortMedian(0), lastUpdate(0), skip(0), idx(0)
{ {
silentPlayerChunk = new PlayerChunk();
pBuffer = new DoubleBuffer<int>(30000 / PLAYER_CHUNK_MS); pBuffer = new DoubleBuffer<int>(30000 / PLAYER_CHUNK_MS);
pShortBuffer = new DoubleBuffer<int>(5000 / PLAYER_CHUNK_MS); pShortBuffer = new DoubleBuffer<int>(5000 / PLAYER_CHUNK_MS);
pLock = new std::unique_lock<std::mutex>(mtx); pLock = new std::unique_lock<std::mutex>(mtx);
@ -33,24 +34,73 @@ public:
} }
Chunk* getNextChunk()
std::vector<short> getChunk(double outputBufferDacTime, unsigned long framesPerBuffer)
{ {
Chunk* chunk = NULL; Chunk* chunk = NULL;
if (chunks.empty()) if (chunks.empty())
cv.wait(*pLock); cv.wait(*pLock);
int age(0);
int chunkCount(0);
mutex.lock(); mutex.lock();
chunk = chunks.front(); chunk = chunks.front();
mutex.unlock(); mutex.unlock();
return chunk;
}
PlayerChunk* getNextPlayerChunk()
{
Chunk* chunk = getNextChunk();
// int age(0);
// age = getAge(*chunk) + outputBufferDacTime*1000 - bufferMs;
// std::cerr << "age: " << age << " \tidx: " << chunk->idx << "\n";
PlayerChunk* playerChunk = new PlayerChunk();
playerChunk->tv_sec = chunk->tv_sec;
playerChunk->tv_usec = chunk->tv_usec;
playerChunk->idx = 0;
age = getAge(*chunk) + outputBufferDacTime*1000 - bufferMs; size_t missing = PLAYER_CHUNK_SIZE;
if (age < -500) if (chunk->idx + PLAYER_CHUNK_SIZE > WIRE_CHUNK_SIZE)
{
std::cerr << "chunk->idx + PLAYER_CHUNK_SIZE >= WIRE_CHUNK_SIZE: " << chunk->idx + PLAYER_CHUNK_SIZE << " >= " << WIRE_CHUNK_SIZE << "\n";
memcpy(&(playerChunk->payload[0]), &chunk->payload[chunk->idx], sizeof(int16_t)*(WIRE_CHUNK_SIZE - chunk->idx));
missing = chunk->idx + PLAYER_CHUNK_SIZE - WIRE_CHUNK_SIZE;
chunks.pop_front();
delete chunk;
chunk = getNextChunk();
}
memcpy(&(playerChunk->payload[0]), &chunk->payload[chunk->idx], sizeof(int16_t)*missing);
addMs(chunk, -PLAYER_CHUNK_MS);
chunk->idx += missing;
if (chunk->idx >= WIRE_CHUNK_SIZE)
{
chunks.pop_front();
delete chunk;
}
return playerChunk;
}
PlayerChunk* getChunk(double outputBufferDacTime, unsigned long framesPerBuffer)
{
PlayerChunk* playerChunk = getNextPlayerChunk();
int age = getAge(playerChunk) + outputBufferDacTime*1000 - bufferMs;
// std::cerr << "Chunk: " << age << "\t" << outputBufferDacTime*1000 << "\n";
if (age < -100)
{
std::cerr << "Playing silence, age: " << age << "\n";
sleepMs(-age);
// *playerChunk = new PlayerChunk();
// return;
}
// int age = getAge(*lastPlayerChunk) + outputBufferDacTime*1000 - bufferMs;
return playerChunk;
}
/* if (age < -500)
{ {
std::vector<short> v; std::vector<short> v;
if (skip < 0) if (skip < 0)
@ -68,51 +118,50 @@ public:
time_t now = time(NULL); time_t now = time(NULL);
if (skip == 0) if (skip == 0)
{
if (now != lastUpdate)
{ {
if (now != lastUpdate) lastUpdate = now;
{ median = pBuffer->median();
lastUpdate = now; shortMedian = pShortBuffer->median();
median = pBuffer->median(); if (abs(age) > 500)
shortMedian = pShortBuffer->median(); skip = age / PLAYER_CHUNK_SIZE;
if (abs(age) > 500) if (pShortBuffer->full() && (abs(shortMedian) > WIRE_CHUNK_MS))
skip = age / PLAYER_CHUNK_SIZE; skip = shortMedian / PLAYER_CHUNK_SIZE;
if (pShortBuffer->full() && (abs(shortMedian) > WIRE_CHUNK_MS)) if (pBuffer->full() && (abs(median) > WIRE_CHUNK_MS))
skip = shortMedian / PLAYER_CHUNK_SIZE; skip = median / PLAYER_CHUNK_SIZE;
if (pBuffer->full() && (abs(median) > WIRE_CHUNK_MS))
skip = median / PLAYER_CHUNK_SIZE;
}
std::cerr << "Chunk: " << age << /*" \tidx: " << chunk->idx <<*/ "\t" << shortMedian << "\t" << median << "\t" << pBuffer->size() << "\t" << chunkCount << "\t" << outputBufferDacTime*1000 << "\n";
} }
std::cerr << "Chunk: " << age << "\t" << shortMedian << "\t" << median << "\t" << pBuffer->size() << "\t" << chunkCount << "\t" << outputBufferDacTime*1000 << "\n";
std::vector<short> v; }
if (skip < 0)
{ std::vector<short> v;
++skip; if (skip < 0)
std::cerr << "chunk too new, sleeping\n";//age > WIRE_CHUNK_MS (" << age << " ms)\n"; {
for (size_t n=0; n<(size_t)PLAYER_CHUNK_SIZE; ++n) ++skip;
v.push_back(chunk->payload[n]); std::cerr << "chunk too new, sleeping\n";//age > WIRE_CHUNK_MS (" << age << " ms)\n";
return v; for (size_t n=0; n<(size_t)PLAYER_CHUNK_SIZE; ++n)
}
for (size_t n=chunk->idx; n<chunk->idx + (size_t)PLAYER_CHUNK_SIZE; ++n)
{
v.push_back(chunk->payload[n]); v.push_back(chunk->payload[n]);
}
//std::cerr << "before: " << chunkTime(*chunk) << ", after: ";
addMs(*chunk, -PLAYER_CHUNK_MS);
//std::cerr << chunkTime(*chunk) << "\n";
chunk->idx += PLAYER_CHUNK_SIZE;
if (chunk->idx >= WIRE_CHUNK_SIZE)
{
//std::cerr << "Chunk played out, deleting\n";
chunks.pop_front();
delete chunk;
}
return v; return v;
} }
}
for (size_t n=chunk->idx; n<chunk->idx + (size_t)PLAYER_CHUNK_SIZE; ++n)
{
v.push_back(chunk->payload[n]);
}
//std::cerr << "before: " << chunkTime(*chunk) << ", after: ";
addMs(*chunk, -PLAYER_CHUNK_MS);
//std::cerr << chunkTime(*chunk) << "\n";
chunk->idx += PLAYER_CHUNK_SIZE;
if (chunk->idx >= WIRE_CHUNK_SIZE)
{
//std::cerr << "Chunk played out, deleting\n";
chunks.pop_front();
delete chunk;
}
return v;
}
*/
@ -304,6 +353,9 @@ private:
DoubleBuffer<int>* pBuffer; DoubleBuffer<int>* pBuffer;
DoubleBuffer<int>* pShortBuffer; DoubleBuffer<int>* pShortBuffer;
PlayerChunk* lastPlayerChunk;
PlayerChunk* silentPlayerChunk;
int median; int median;
int shortMedian; int shortMedian;
time_t lastUpdate; time_t lastUpdate;

View file

@ -34,13 +34,13 @@ long diff_ms(const timeval& t1, const timeval& t2)
template <typename T> template <typename T>
long getAge(const T& chunk) long getAge(const T* chunk)
{ {
timeval now; timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
timeval ts; timeval ts;
ts.tv_sec = chunk.tv_sec; ts.tv_sec = chunk->tv_sec;
ts.tv_usec = chunk.tv_usec; ts.tv_usec = chunk->tv_usec;
return diff_ms(now, ts); return diff_ms(now, ts);
} }
@ -69,14 +69,14 @@ inline void addMs(timeval& tv, int ms)
} }
template <typename T> template <typename T>
void addMs(T& chunk, int ms) void addMs(T* chunk, int ms)
{ {
timeval tv; timeval tv;
tv.tv_sec = chunk.tv_sec; tv.tv_sec = chunk->tv_sec;
tv.tv_usec = chunk.tv_usec; tv.tv_usec = chunk->tv_usec;
addMs(tv, ms); addMs(tv, ms);
chunk.tv_sec = tv.tv_sec; chunk->tv_sec = tv.tv_sec;
chunk.tv_usec = tv.tv_usec; chunk->tv_usec = tv.tv_usec;
} }