Added automated channel detection for speaker devices

This commit is contained in:
WolverinDEV 2021-03-27 21:25:16 +01:00
parent da07595337
commit 768e9b7bbb
5 changed files with 30 additions and 10 deletions

View File

@ -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;

View File

@ -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<PortAudioPlayback>(this->_index, this->_info);
}
return this->_playback;
}

View File

@ -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 {

View File

@ -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<PortAudioPlayback*>(userData);
@ -44,10 +45,19 @@ bool PortAudioPlayback::impl_start(std::string &error) {
PaStreamParameters parameters{};
memset(&parameters, 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);
}

View File

@ -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;