From df6083f572e49f2dea5febcc074f84992ee3e059 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Wed, 2 Dec 2020 19:29:03 +0100 Subject: [PATCH] Adding support for mono devices --- .../serverconnection/src/audio/AudioInput.cpp | 42 +++++++++++-------- .../serverconnection/src/audio/AudioInput.h | 1 + .../src/audio/AudioMerger.cpp | 11 +++-- .../serverconnection/src/audio/AudioMerger.h | 3 +- .../src/audio/driver/PortAudio.h | 2 + .../src/audio/driver/PortAudioRecord.cpp | 12 +++++- native/serverconnection/src/bindings.cpp | 5 +-- 7 files changed, 49 insertions(+), 27 deletions(-) diff --git a/native/serverconnection/src/audio/AudioInput.cpp b/native/serverconnection/src/audio/AudioInput.cpp index 7ce46c5..70ccd19 100644 --- a/native/serverconnection/src/audio/AudioInput.cpp +++ b/native/serverconnection/src/audio/AudioInput.cpp @@ -4,6 +4,7 @@ #include "./AudioInput.h" #include "./AudioReframer.h" #include "./AudioResampler.h" +#include "./AudioMerger.h" #include "../logger.h" #include "AudioGain.h" @@ -134,19 +135,19 @@ void AudioInput::delete_consumer(const std::shared_ptr &source) { void AudioInput::consume(const void *input, size_t frameCount, size_t channels) { if(channels != this->_channel_count) { - log_critical(category::audio, tr("Channel count miss match (input)! Fixme!")); - return; + if(channels < 1 || channels > 2) { + log_critical(category::audio, tr("Channel count miss match (Received: {})!"), channels); + } + + this->ensure_resample_buffer_capacity(frameCount * this->_channel_count * sizeof(float)); + audio::merge::merge_channels_interleaved(this->resample_buffer, this->_channel_count, input, channels, frameCount); + input = this->resample_buffer; } if(this->_resampler) { const auto expected_size = this->_resampler->estimated_output_size(frameCount); const auto expected_byte_size = expected_size * this->_channel_count * sizeof(float); - - if(this->resample_buffer_size < expected_byte_size) { - free(this->resample_buffer); - this->resample_buffer = malloc(expected_byte_size); - this->resample_buffer_size = expected_byte_size; - } + this->ensure_resample_buffer_capacity(expected_byte_size); auto result = this->_resampler->process(this->resample_buffer, input, frameCount); if(result < 0) { @@ -160,25 +161,32 @@ void AudioInput::consume(const void *input, size_t frameCount, size_t channels) audio::apply_gain(this->resample_buffer, this->_channel_count, frameCount, this->_volume); } else if(this->_volume != 1) { const auto byte_size = frameCount * this->_channel_count * sizeof(float); - if(this->resample_buffer_size < byte_size) { - free(this->resample_buffer); - this->resample_buffer = malloc(byte_size); - this->resample_buffer_size = byte_size; - } + this->ensure_resample_buffer_capacity(byte_size); - memcpy(this->resample_buffer, input, byte_size); - input = this->resample_buffer; + if(this->resample_buffer != input) { + memcpy(this->resample_buffer, input, byte_size); + input = this->resample_buffer; + } audio::apply_gain(this->resample_buffer, this->_channel_count, frameCount, this->_volume); } auto begin = std::chrono::system_clock::now(); - for(const auto& consumer : this->consumers()) - consumer->process_data(input, frameCount); + for(const auto& consumer : this->consumers()) { + consumer->process_data(input, frameCount); + } auto end = std::chrono::system_clock::now(); auto ms = std::chrono::duration_cast(end - begin).count(); if(ms > 5) { log_warn(category::audio, tr("Processing of audio input needed {}ms. This could be an issue!"), std::chrono::duration_cast(end - begin).count()); } +} + +void AudioInput::ensure_resample_buffer_capacity(size_t size) { + if(this->resample_buffer_size < size) { + free(this->resample_buffer); + this->resample_buffer = malloc(size); + this->resample_buffer_size = size; + } } \ No newline at end of file diff --git a/native/serverconnection/src/audio/AudioInput.h b/native/serverconnection/src/audio/AudioInput.h index debfdbb..4865314 100644 --- a/native/serverconnection/src/audio/AudioInput.h +++ b/native/serverconnection/src/audio/AudioInput.h @@ -65,6 +65,7 @@ namespace tc::audio { inline void set_volume(float value) { this->_volume = value; } private: void consume(const void *, size_t, size_t) override; + void ensure_resample_buffer_capacity(size_t); size_t const _channel_count; size_t const _sample_rate; diff --git a/native/serverconnection/src/audio/AudioMerger.cpp b/native/serverconnection/src/audio/AudioMerger.cpp index a85c46a..338b426 100644 --- a/native/serverconnection/src/audio/AudioMerger.cpp +++ b/native/serverconnection/src/audio/AudioMerger.cpp @@ -77,8 +77,10 @@ bool merge::merge_channels_interleaved(void *target, size_t target_channels, con assert(target_channels == 1 || target_channels == 2); if(src_channels == target_channels) { - if(src == target) - return true; + if(src == target) { + return true; + } + memcpy(target, src, samples * src_channels * 4); return true; } @@ -116,8 +118,9 @@ bool merge::merge_channels_interleaved(void *target, size_t target_channels, con *(target_array++) = merge_ab(*(source_array), *(source_array + 1)); source_array += 2; } - } else - return false; + } else { + return false; + } return true; } \ No newline at end of file diff --git a/native/serverconnection/src/audio/AudioMerger.h b/native/serverconnection/src/audio/AudioMerger.h index e473d7f..68dcc5b 100644 --- a/native/serverconnection/src/audio/AudioMerger.h +++ b/native/serverconnection/src/audio/AudioMerger.h @@ -3,7 +3,8 @@ #include namespace tc::audio::merge { - /* the result buffer could be equal to one of the source buffers to prevent unnecessary allocations + /* + * The result buffer could be equal to one of the source buffers to prevent unnecessary allocations * Note: The sample order is irrelevant */ extern bool merge_sources(void* /* result */, void* /* source a */, void* /* source b */, size_t /* channels */, size_t /* samples */); diff --git a/native/serverconnection/src/audio/driver/PortAudio.h b/native/serverconnection/src/audio/driver/PortAudio.h index 53c16df..3743231 100644 --- a/native/serverconnection/src/audio/driver/PortAudio.h +++ b/native/serverconnection/src/audio/driver/PortAudio.h @@ -46,6 +46,8 @@ namespace tc::audio::pa { private: void read_callback(const void *input, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags); + size_t source_channel_count{0}; + PaDeviceIndex index; const PaDeviceInfo* info; PaStream* stream{nullptr}; diff --git a/native/serverconnection/src/audio/driver/PortAudioRecord.cpp b/native/serverconnection/src/audio/driver/PortAudioRecord.cpp index 1364ea8..a03a829 100644 --- a/native/serverconnection/src/audio/driver/PortAudioRecord.cpp +++ b/native/serverconnection/src/audio/driver/PortAudioRecord.cpp @@ -42,7 +42,15 @@ bool PortAudioRecord::impl_start(std::string &error) { PaStreamParameters parameters{}; memset(¶meters, 0, sizeof(parameters)); - parameters.channelCount = (int) kChannelCount; + if(this->info->maxInputChannels < 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 device {} (MaxChannels: {}, MinChannels: {}, Channels: {})", this->info->name, this->info->maxInputChannels, this->info->maxInputChannels, this->source_channel_count); + parameters.device = this->index; parameters.sampleFormat = paFloat32; parameters.suggestedLatency = this->info->defaultLowInputLatency; @@ -95,5 +103,5 @@ void PortAudioRecord::read_callback(const void *input, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) { std::lock_guard consumer_lock{this->consumer_lock}; for(auto& consumer : this->_consumers) - consumer->consume(input, frameCount, kChannelCount); + consumer->consume(input, frameCount, this->source_channel_count); } \ No newline at end of file diff --git a/native/serverconnection/src/bindings.cpp b/native/serverconnection/src/bindings.cpp index 51abb01..96a78ed 100644 --- a/native/serverconnection/src/bindings.cpp +++ b/native/serverconnection/src/bindings.cpp @@ -70,9 +70,8 @@ tc::audio::AudioOutput* global_audio_output; Nan::Set(object, (uint32_t) value, Nan::New(key).ToLocalChecked()); NAN_MODULE_INIT(init) { - /* FIXME: Reenable */ - //logger::initialize_node(); - logger::initialize_raw(); + logger::initialize_node(); + //logger::initialize_raw(); #ifndef WIN32 logger::info(category::general, tr("Hello World from C. PPID: {}, PID: {}"), getppid(), getpid());