mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-07-15 16:15:16 -04:00
Trying thread trick for preventing audio underrun..
This commit is contained in:
parent
cd5f43d5c4
commit
65ae1de36d
@ -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(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &bufferFrames, &audioCallback, (void *) this, &opts);
|
dac.openStream(¶meters, 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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user