Added automated channel detection for speaker devices
This commit is contained in:
parent
da07595337
commit
768e9b7bbb
@ -217,7 +217,10 @@ namespace tc::audio {
|
|||||||
|
|
||||||
bool AudioDeviceRecord::start(std::string &error) {
|
bool AudioDeviceRecord::start(std::string &error) {
|
||||||
std::lock_guard lock{this->state_lock};
|
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) {
|
if(this->stream_invalid) {
|
||||||
this->impl_stop();
|
this->impl_stop();
|
||||||
this->running = false;
|
this->running = false;
|
||||||
|
@ -92,8 +92,9 @@ namespace tc::audio::pa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard lock{this->io_lock};
|
std::lock_guard lock{this->io_lock};
|
||||||
if(!this->_playback)
|
if(!this->_playback) {
|
||||||
this->_playback = std::make_shared<PortAudioPlayback>(this->_index, this->_info);
|
this->_playback = std::make_shared<PortAudioPlayback>(this->_index, this->_info);
|
||||||
|
}
|
||||||
return this->_playback;
|
return this->_playback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ namespace tc::audio::pa {
|
|||||||
PaDeviceIndex index;
|
PaDeviceIndex index;
|
||||||
const PaDeviceInfo* info;
|
const PaDeviceInfo* info;
|
||||||
PaStream* stream{nullptr};
|
PaStream* stream{nullptr};
|
||||||
|
|
||||||
|
size_t source_channel_count{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
class PortAudioRecord : public AudioDeviceRecord {
|
class PortAudioRecord : public AudioDeviceRecord {
|
||||||
|
@ -32,7 +32,8 @@ bool PortAudioPlayback::impl_start(std::string &error) {
|
|||||||
unsigned long frameCount,
|
unsigned long frameCount,
|
||||||
const PaStreamCallbackTimeInfo* timeInfo,
|
const PaStreamCallbackTimeInfo* timeInfo,
|
||||||
PaStreamCallbackFlags statusFlags,
|
PaStreamCallbackFlags statusFlags,
|
||||||
void *userData) {
|
void *userData
|
||||||
|
) {
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
||||||
auto player = reinterpret_cast<PortAudioPlayback*>(userData);
|
auto player = reinterpret_cast<PortAudioPlayback*>(userData);
|
||||||
@ -44,10 +45,19 @@ bool PortAudioPlayback::impl_start(std::string &error) {
|
|||||||
|
|
||||||
PaStreamParameters parameters{};
|
PaStreamParameters parameters{};
|
||||||
memset(¶meters, 0, sizeof(parameters));
|
memset(¶meters, 0, sizeof(parameters));
|
||||||
parameters.channelCount = (int) kChannelCount;
|
|
||||||
parameters.device = this->index;
|
parameters.device = this->index;
|
||||||
parameters.sampleFormat = paFloat32;
|
parameters.sampleFormat = paFloat32;
|
||||||
parameters.suggestedLatency = this->info->defaultLowInputLatency;
|
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(
|
auto err = Pa_OpenStream(
|
||||||
&this->stream,
|
&this->stream,
|
||||||
nullptr,
|
nullptr,
|
||||||
@ -56,7 +66,8 @@ bool PortAudioPlayback::impl_start(std::string &error) {
|
|||||||
(unsigned long) (kSampleRate * kTimeSpan),
|
(unsigned long) (kSampleRate * kTimeSpan),
|
||||||
paClipOff,
|
paClipOff,
|
||||||
proxied_write_callback,
|
proxied_write_callback,
|
||||||
this);
|
this
|
||||||
|
);
|
||||||
|
|
||||||
if(err != paNoError) {
|
if(err != paNoError) {
|
||||||
this->stream = nullptr;
|
this->stream = nullptr;
|
||||||
@ -68,20 +79,23 @@ bool PortAudioPlayback::impl_start(std::string &error) {
|
|||||||
if(err != paNoError) {
|
if(err != paNoError) {
|
||||||
error = std::string{Pa_GetErrorText(err)} + "(start stream: " + std::to_string(err) + ")";
|
error = std::string{Pa_GetErrorText(err)} + "(start stream: " + std::to_string(err) + ")";
|
||||||
err = Pa_CloseStream(this->stream);
|
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));
|
log_critical(category::audio, tr("Failed to close opened pa stream. This will cause memory leaks. Error: {}/{}"), err, Pa_GetErrorText(err));
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PortAudioPlayback::impl_stop() {
|
void PortAudioPlayback::impl_stop() {
|
||||||
if(Pa_IsStreamActive(this->stream))
|
if(Pa_IsStreamActive(this->stream)) {
|
||||||
Pa_AbortStream(this->stream);
|
Pa_AbortStream(this->stream);
|
||||||
|
}
|
||||||
|
|
||||||
auto error = Pa_CloseStream(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);
|
log_error(category::audio, tr("Failed to close PA stream: {}"), error);
|
||||||
|
}
|
||||||
this->stream = nullptr;
|
this->stream = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,5 +105,5 @@ size_t PortAudioPlayback::sample_rate() const {
|
|||||||
|
|
||||||
void PortAudioPlayback::write_callback(void *output, unsigned long frameCount,
|
void PortAudioPlayback::write_callback(void *output, unsigned long frameCount,
|
||||||
const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) {
|
const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) {
|
||||||
this->fill_buffer(output, frameCount, kChannelCount);
|
this->fill_buffer(output, frameCount, this->source_channel_count);
|
||||||
}
|
}
|
@ -49,7 +49,7 @@ bool PortAudioRecord::impl_start(std::string &error) {
|
|||||||
parameters.channelCount = (int) kChannelCount;
|
parameters.channelCount = (int) kChannelCount;
|
||||||
this->source_channel_count = 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.device = this->index;
|
||||||
parameters.sampleFormat = paFloat32;
|
parameters.sampleFormat = paFloat32;
|
||||||
|
Loading…
Reference in New Issue
Block a user