diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 22193e3..cc0dc35 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -392,7 +392,8 @@ void AppFrame::OnMenu(wxCommandEvent& event) { if (evId == menu_id + j) { //audioSampleRateMenuItems[menu_id+j]; - std::cout << "Would set audio sample rate on device " << mdevices_i->second.name << " (" << mdevices_i->first << ") to " << (*srate) << "Hz" << std::endl; + //std::cout << "Would set audio sample rate on device " << mdevices_i->second.name << " (" << mdevices_i->first << ") to " << (*srate) << "Hz" << std::endl; + AudioThread::setDeviceSampleRate(mdevices_i->first, *srate); } j++; diff --git a/src/audio/AudioThread.cpp b/src/audio/AudioThread.cpp index f22a3d0..59d9220 100644 --- a/src/audio/AudioThread.cpp +++ b/src/audio/AudioThread.cpp @@ -6,11 +6,12 @@ #include std::map AudioThread::deviceController; +std::map AudioThread::deviceSampleRate; std::map AudioThread::deviceThread; AudioThread::AudioThread(AudioThreadInputQueue *inputQueue, DemodulatorThreadCommandQueue* threadQueueNotify) : currentInput(NULL), inputQueue(inputQueue), audioQueuePtr(0), underflowCount(0), terminated(false), active(false), outputDevice(-1), gain( - 1.0), threadQueueNotify(threadQueueNotify) { + 1.0), threadQueueNotify(threadQueueNotify), sampleRate(DEFAULT_AUDIO_SAMPLE_RATE), nBufferFrames(256) { boundThreads = new std::vector; } @@ -217,18 +218,32 @@ void AudioThread::enumerateDevices(std::vector &devs) { } } +void AudioThread::setDeviceSampleRate(int deviceId, int sampleRate) { + if (deviceController.find(deviceId) != deviceController.end()) { + AudioThreadCommand refreshDevice; + refreshDevice.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_SAMPLE_RATE; + refreshDevice.int_value = sampleRate; + deviceController[deviceId]->getCommandQueue()->push(refreshDevice); + } +} + +void AudioThread::setSampleRate(int sampleRate) { + deviceSampleRate[outputDevice] = sampleRate; + this->sampleRate = sampleRate; + dac.stopStream(); + dac.closeStream(); + dac.openStream(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &nBufferFrames, &audioCallback, (void *) this, &opts); + dac.startStream(); +} + void AudioThread::setupDevice(int deviceId) { parameters.deviceId = deviceId; parameters.nChannels = 2; parameters.firstChannel = 0; - unsigned int sampleRate = DEFAULT_AUDIO_SAMPLE_RATE; - unsigned int bufferFrames = 256; - RtAudio::StreamOptions opts; opts.streamName = "CubicSDR Audio Output"; try { - if (deviceController.find(outputDevice.load()) != deviceController.end()) { deviceController[outputDevice.load()]->removeThread(this); } @@ -240,11 +255,18 @@ void AudioThread::setupDevice(int deviceId) { if (deviceController.find(parameters.deviceId) == deviceController.end()) { deviceController[parameters.deviceId] = new AudioThread(NULL, NULL); - deviceController[parameters.deviceId]->setInitOutputDevice(parameters.deviceId); + int srate = DEFAULT_AUDIO_SAMPLE_RATE; + if (deviceSampleRate.find(parameters.deviceId) != deviceSampleRate.end()) { + srate = deviceSampleRate[parameters.deviceId]; + } else { + deviceSampleRate[parameters.deviceId] = srate; + } + deviceController[parameters.deviceId]->setInitOutputDevice(parameters.deviceId, srate); deviceController[parameters.deviceId]->bindThread(this); + deviceThread[parameters.deviceId] = new std::thread(&AudioThread::threadMain, deviceController[parameters.deviceId]); } else if (deviceController[parameters.deviceId] == this) { - dac.openStream(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &bufferFrames, &audioCallback, (void *) this, &opts); + dac.openStream(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &nBufferFrames, &audioCallback, (void *) this, &opts); dac.startStream(); } else { deviceController[parameters.deviceId]->bindThread(this); @@ -267,8 +289,16 @@ int AudioThread::getOutputDevice() { return outputDevice; } -void AudioThread::setInitOutputDevice(int deviceId) { +void AudioThread::setInitOutputDevice(int deviceId, int sampleRate) { outputDevice = deviceId; + if (sampleRate == -1) { + if (deviceSampleRate.find(parameters.deviceId) != deviceSampleRate.end()) { + sampleRate = deviceSampleRate[deviceId]; + } + } else { + deviceSampleRate[deviceId] = sampleRate; + } + this->sampleRate = sampleRate; } void AudioThread::threadMain() { @@ -299,6 +329,9 @@ void AudioThread::threadMain() { if (command.cmd == AudioThreadCommand::AUDIO_THREAD_CMD_SET_DEVICE) { setupDevice(command.int_value); } + if (command.cmd == AudioThreadCommand::AUDIO_THREAD_CMD_SET_SAMPLE_RATE) { + setSampleRate(command.int_value); + } } if (deviceController[parameters.deviceId] != this) { diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index 58e8d7b..b28f022 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -32,7 +32,7 @@ public: class AudioThreadCommand { public: enum AudioThreadCommandEnum { - AUDIO_THREAD_CMD_NULL, AUDIO_THREAD_CMD_SET_DEVICE + AUDIO_THREAD_CMD_NULL, AUDIO_THREAD_CMD_SET_DEVICE, AUDIO_THREAD_CMD_SET_SAMPLE_RATE }; AudioThreadCommand() : @@ -65,8 +65,9 @@ public: static void enumerateDevices(std::vector &devs); void setupDevice(int deviceId); - void setInitOutputDevice(int deviceId); + void setInitOutputDevice(int deviceId, int sampleRate=-1); int getOutputDevice(); + void setSampleRate(int sampleRate); void threadMain(); void terminate(); @@ -80,17 +81,22 @@ public: private: RtAudio dac; + unsigned int nBufferFrames; + RtAudio::StreamOptions opts; RtAudio::StreamParameters parameters; AudioThreadCommandQueue cmdQueue; DemodulatorThreadCommandQueue* threadQueueNotify; + int sampleRate; public: void bindThread(AudioThread *other); void removeThread(AudioThread *other); static std::map deviceController; + static std::map deviceSampleRate; static std::map deviceThread; static void deviceCleanup(); + static void setDeviceSampleRate(int deviceId, int sampleRate); std::atomic *> boundThreads; };