diff --git a/native/serverconnection/src/audio/driver/AudioDriver.cpp b/native/serverconnection/src/audio/driver/AudioDriver.cpp index c168e6e..91f1188 100644 --- a/native/serverconnection/src/audio/driver/AudioDriver.cpp +++ b/native/serverconnection/src/audio/driver/AudioDriver.cpp @@ -217,7 +217,10 @@ namespace tc::audio { bool AudioDeviceRecord::start(std::string &error) { std::lock_guard lock{this->state_lock}; - if(this->running && !this->stream_invalid) return true; + if(this->running && !this->stream_invalid) { + return true; + } + if(this->stream_invalid) { this->impl_stop(); this->running = false; diff --git a/native/serverconnection/src/audio/driver/PortAudio.cpp b/native/serverconnection/src/audio/driver/PortAudio.cpp index 4d260f7..30bbda7 100644 --- a/native/serverconnection/src/audio/driver/PortAudio.cpp +++ b/native/serverconnection/src/audio/driver/PortAudio.cpp @@ -92,8 +92,9 @@ namespace tc::audio::pa { } std::lock_guard lock{this->io_lock}; - if(!this->_playback) + if(!this->_playback) { this->_playback = std::make_shared(this->_index, this->_info); + } return this->_playback; } diff --git a/native/serverconnection/src/audio/driver/PortAudio.h b/native/serverconnection/src/audio/driver/PortAudio.h index 3743231..0e7b4fc 100644 --- a/native/serverconnection/src/audio/driver/PortAudio.h +++ b/native/serverconnection/src/audio/driver/PortAudio.h @@ -28,6 +28,8 @@ namespace tc::audio::pa { PaDeviceIndex index; const PaDeviceInfo* info; PaStream* stream{nullptr}; + + size_t source_channel_count{0}; }; class PortAudioRecord : public AudioDeviceRecord { diff --git a/native/serverconnection/src/audio/driver/PortAudioPlayback.cpp b/native/serverconnection/src/audio/driver/PortAudioPlayback.cpp index 493bd41..9845606 100644 --- a/native/serverconnection/src/audio/driver/PortAudioPlayback.cpp +++ b/native/serverconnection/src/audio/driver/PortAudioPlayback.cpp @@ -32,7 +32,8 @@ bool PortAudioPlayback::impl_start(std::string &error) { unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, - void *userData) { + void *userData + ) { assert(output); auto player = reinterpret_cast(userData); @@ -44,10 +45,19 @@ bool PortAudioPlayback::impl_start(std::string &error) { PaStreamParameters parameters{}; memset(¶meters, 0, sizeof(parameters)); - parameters.channelCount = (int) kChannelCount; parameters.device = this->index; parameters.sampleFormat = paFloat32; parameters.suggestedLatency = this->info->defaultLowInputLatency; + + if(this->info->maxOutputChannels < kChannelCount) { + parameters.channelCount = (int) 1; + this->source_channel_count = 1; + } else { + parameters.channelCount = (int) kChannelCount; + this->source_channel_count = kChannelCount; + } + log_debug(category::audio, "Opening playback device {} (MaxChannels: {}, Channels: {})", this->info->name, this->info->maxOutputChannels, this->source_channel_count); + auto err = Pa_OpenStream( &this->stream, nullptr, @@ -56,7 +66,8 @@ bool PortAudioPlayback::impl_start(std::string &error) { (unsigned long) (kSampleRate * kTimeSpan), paClipOff, proxied_write_callback, - this); + this + ); if(err != paNoError) { this->stream = nullptr; @@ -68,20 +79,23 @@ bool PortAudioPlayback::impl_start(std::string &error) { if(err != paNoError) { error = std::string{Pa_GetErrorText(err)} + "(start stream: " + std::to_string(err) + ")"; err = Pa_CloseStream(this->stream); - if(err != paNoError) + if(err != paNoError) { log_critical(category::audio, tr("Failed to close opened pa stream. This will cause memory leaks. Error: {}/{}"), err, Pa_GetErrorText(err)); + } return false; } return true; } void PortAudioPlayback::impl_stop() { - if(Pa_IsStreamActive(this->stream)) + if(Pa_IsStreamActive(this->stream)) { Pa_AbortStream(this->stream); + } auto error = Pa_CloseStream(this->stream); - if(error != paNoError) + if(error != paNoError) { log_error(category::audio, tr("Failed to close PA stream: {}"), error); + } this->stream = nullptr; } @@ -91,5 +105,5 @@ size_t PortAudioPlayback::sample_rate() const { void PortAudioPlayback::write_callback(void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) { - this->fill_buffer(output, frameCount, kChannelCount); + this->fill_buffer(output, frameCount, this->source_channel_count); } \ No newline at end of file diff --git a/native/serverconnection/src/audio/driver/PortAudioRecord.cpp b/native/serverconnection/src/audio/driver/PortAudioRecord.cpp index 7b1c2a0..b9c2d63 100644 --- a/native/serverconnection/src/audio/driver/PortAudioRecord.cpp +++ b/native/serverconnection/src/audio/driver/PortAudioRecord.cpp @@ -49,7 +49,7 @@ bool PortAudioRecord::impl_start(std::string &error) { parameters.channelCount = (int) kChannelCount; this->source_channel_count = kChannelCount; } - log_debug(category::audio, "Opening device {} (MaxChannels: {}, MinChannels: {}, Channels: {})", this->info->name, this->info->maxInputChannels, this->info->maxInputChannels, this->source_channel_count); + log_debug(category::audio, "Opening record device {} (MaxChannels: {}, Channels: {})", this->info->name, this->info->maxInputChannels, this->source_channel_count); parameters.device = this->index; parameters.sampleFormat = paFloat32;