Trying thread trick for preventing audio underrun..

This commit is contained in:
Charles J. Cliffe 2014-12-15 20:47:46 -05:00
parent cd5f43d5c4
commit 65ae1de36d
2 changed files with 37 additions and 62 deletions

View File

@ -20,63 +20,26 @@ static int audioCallback(void *outputBuffer, void *inputBuffer, unsigned int nBu
std::cout << "Audio buffer underflow.." << (src->underflow_count++) << std::endl; std::cout << "Audio buffer underflow.." << (src->underflow_count++) << std::endl;
} }
std::queue<std::vector<float> > *audio_queue = src->audio_queue.load(); if (src->audio_queue_ptr == src->currentInput.data.size()) {
if (src->terminated) {
#ifdef __APPLE__ // Crude re-sync return 1;
int wait_for_it = 0;
if (audio_queue->empty()) {
while (wait_for_it++ < 5) { // Can we wait it out?
std::this_thread::sleep_for(std::chrono::microseconds(100000));
// std::this_thread::yield();
if (!audio_queue->empty()) {
std::cout << "Buffer recovery.." << std::endl;
break;
}
}
}
#endif
if (audio_queue->empty()) {
for (int i = 0; i < nBufferFrames * 2; i++) {
out[i] = 0;
} }
return 0; src->inputQueue->pop(src->currentInput);
src->audio_queue_ptr = 0;
} }
std::vector<float> nextBuffer = audio_queue->front();
int nextBufferSize = nextBuffer.size();
for (int i = 0; i < nBufferFrames * 2; i++) { for (int i = 0; i < nBufferFrames * 2; i++) {
out[i] = nextBuffer[src->audio_queue_ptr]; out[i] = src->currentInput.data[src->audio_queue_ptr];
src->audio_queue_ptr++; src->audio_queue_ptr++;
if (src->audio_queue_ptr == nextBufferSize) { if (src->audio_queue_ptr == src->currentInput.data.size()) {
audio_queue->pop(); if (src->terminated) {
src->audio_queue_ptr = 0; return 1;
if (audio_queue->empty()) {
#ifdef __APPLE__
wait_for_it = 0;
while (wait_for_it++ < 5) { // Can we wait it out?
std::this_thread::sleep_for(std::chrono::microseconds(100000));
if (!audio_queue->empty()) {
std::cout << "Buffer recovery.." << std::endl;
break;
}
}
#endif
if (audio_queue->empty()) {
std::cout << "Audio buffer underflow mid request.." << (src->underflow_count++) << std::endl;
for (int j = i; j < nBufferFrames * 2; j++) {
out[i] = 0;
}
return 0;
}
} }
nextBuffer = audio_queue->front(); src->inputQueue->pop(src->currentInput);
src->audio_queue_ptr = 0;
} }
} }
return 0; return 0;
} }
@ -105,8 +68,6 @@ void AudioThread::threadMain() {
opts.streamName = "CubicSDR Audio Output"; opts.streamName = "CubicSDR Audio Output";
opts.priority = sched_get_priority_max(SCHED_FIFO); opts.priority = sched_get_priority_max(SCHED_FIFO);
audio_queue = new std::queue<std::vector<float> >;
try { try {
dac.openStream(&parameters, NULL, RTAUDIO_FLOAT32, sampleRate, &bufferFrames, &audioCallback, (void *) this, &opts); dac.openStream(&parameters, NULL, RTAUDIO_FLOAT32, sampleRate, &bufferFrames, &audioCallback, (void *) this, &opts);
dac.startStream(); dac.startStream();
@ -116,12 +77,8 @@ void AudioThread::threadMain() {
} }
while (!terminated) { while (!terminated) {
AudioThreadInput inp; AudioThreadCommand command;
inputQueue->pop(inp); cmdQueue.pop(command);
if (inp.data.size()) {
audio_queue.load()->push(inp.data);
}
// std::this_thread::yield();
} }
try { try {
@ -144,6 +101,6 @@ void AudioThread::threadMain() {
void AudioThread::terminate() { void AudioThread::terminate() {
terminated = true; terminated = true;
AudioThreadInput endCond; // push an empty input to bump the queue AudioThreadCommand endCond; // push an empty input to bump the queue
inputQueue->push(endCond); cmdQueue.push(endCond);
} }

View File

@ -25,13 +25,32 @@ public:
std::vector<float> data; std::vector<float> data;
}; };
class AudioThreadCommand {
public:
enum AudioThreadCommandEnum {
AUTIO_THREAD_CMD_NULL,
AUTIO_THREAD_CMD_SET_DEVICE,
};
AudioThreadCommand() :
cmd(AUTIO_THREAD_CMD_NULL), int_value(0) {
}
AudioThreadCommandEnum cmd;
int int_value;
};
typedef ThreadQueue<AudioThreadInput> AudioThreadInputQueue; typedef ThreadQueue<AudioThreadInput> AudioThreadInputQueue;
typedef ThreadQueue<AudioThreadCommand> AudioThreadCommandQueue;
class AudioThread { class AudioThread {
public: public:
std::atomic< std::queue<std::vector<float> > *> audio_queue;
AudioThreadInput currentInput;
AudioThreadInputQueue *inputQueue;
std::atomic<unsigned int> audio_queue_ptr; std::atomic<unsigned int> audio_queue_ptr;
std::atomic<unsigned int> underflow_count; std::atomic<unsigned int> underflow_count;
std::atomic<bool> terminated;
AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify); AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify);
~AudioThread(); ~AudioThread();
@ -40,9 +59,8 @@ public:
void terminate(); void terminate();
private: private:
AudioThreadInputQueue *inputQueue;
RtAudio dac; RtAudio dac;
std::atomic<bool> terminated; AudioThreadCommandQueue cmdQueue;
DemodulatorThreadCommandQueue* threadQueueNotify; DemodulatorThreadCommandQueue* threadQueueNotify;
}; };