Adding support for mono devices

This commit is contained in:
WolverinDEV 2020-12-02 19:29:03 +01:00
parent 804773f4eb
commit df6083f572
7 changed files with 49 additions and 27 deletions

View File

@ -4,6 +4,7 @@
#include "./AudioInput.h" #include "./AudioInput.h"
#include "./AudioReframer.h" #include "./AudioReframer.h"
#include "./AudioResampler.h" #include "./AudioResampler.h"
#include "./AudioMerger.h"
#include "../logger.h" #include "../logger.h"
#include "AudioGain.h" #include "AudioGain.h"
@ -134,19 +135,19 @@ void AudioInput::delete_consumer(const std::shared_ptr<AudioConsumer> &source) {
void AudioInput::consume(const void *input, size_t frameCount, size_t channels) { void AudioInput::consume(const void *input, size_t frameCount, size_t channels) {
if(channels != this->_channel_count) { if(channels != this->_channel_count) {
log_critical(category::audio, tr("Channel count miss match (input)! Fixme!")); if(channels < 1 || channels > 2) {
return; 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) { if(this->_resampler) {
const auto expected_size = this->_resampler->estimated_output_size(frameCount); const auto expected_size = this->_resampler->estimated_output_size(frameCount);
const auto expected_byte_size = expected_size * this->_channel_count * sizeof(float); const auto expected_byte_size = expected_size * this->_channel_count * sizeof(float);
this->ensure_resample_buffer_capacity(expected_byte_size);
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;
}
auto result = this->_resampler->process(this->resample_buffer, input, frameCount); auto result = this->_resampler->process(this->resample_buffer, input, frameCount);
if(result < 0) { 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); audio::apply_gain(this->resample_buffer, this->_channel_count, frameCount, this->_volume);
} else if(this->_volume != 1) { } else if(this->_volume != 1) {
const auto byte_size = frameCount * this->_channel_count * sizeof(float); const auto byte_size = frameCount * this->_channel_count * sizeof(float);
if(this->resample_buffer_size < byte_size) { this->ensure_resample_buffer_capacity(byte_size);
free(this->resample_buffer);
this->resample_buffer = malloc(byte_size);
this->resample_buffer_size = byte_size;
}
memcpy(this->resample_buffer, input, byte_size); if(this->resample_buffer != input) {
input = this->resample_buffer; memcpy(this->resample_buffer, input, byte_size);
input = this->resample_buffer;
}
audio::apply_gain(this->resample_buffer, this->_channel_count, frameCount, this->_volume); audio::apply_gain(this->resample_buffer, this->_channel_count, frameCount, this->_volume);
} }
auto begin = std::chrono::system_clock::now(); auto begin = std::chrono::system_clock::now();
for(const auto& consumer : this->consumers()) for(const auto& consumer : this->consumers()) {
consumer->process_data(input, frameCount); consumer->process_data(input, frameCount);
}
auto end = std::chrono::system_clock::now(); auto end = std::chrono::system_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count(); auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
if(ms > 5) { if(ms > 5) {
log_warn(category::audio, tr("Processing of audio input needed {}ms. This could be an issue!"), std::chrono::duration_cast<chrono::milliseconds>(end - begin).count()); log_warn(category::audio, tr("Processing of audio input needed {}ms. This could be an issue!"), std::chrono::duration_cast<chrono::milliseconds>(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;
}
} }

View File

@ -65,6 +65,7 @@ namespace tc::audio {
inline void set_volume(float value) { this->_volume = value; } inline void set_volume(float value) { this->_volume = value; }
private: private:
void consume(const void *, size_t, size_t) override; void consume(const void *, size_t, size_t) override;
void ensure_resample_buffer_capacity(size_t);
size_t const _channel_count; size_t const _channel_count;
size_t const _sample_rate; size_t const _sample_rate;

View File

@ -77,8 +77,10 @@ bool merge::merge_channels_interleaved(void *target, size_t target_channels, con
assert(target_channels == 1 || target_channels == 2); assert(target_channels == 1 || target_channels == 2);
if(src_channels == target_channels) { if(src_channels == target_channels) {
if(src == target) if(src == target) {
return true; return true;
}
memcpy(target, src, samples * src_channels * 4); memcpy(target, src, samples * src_channels * 4);
return true; 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)); *(target_array++) = merge_ab(*(source_array), *(source_array + 1));
source_array += 2; source_array += 2;
} }
} else } else {
return false; return false;
}
return true; return true;
} }

View File

@ -3,7 +3,8 @@
#include <cstring> #include <cstring>
namespace tc::audio::merge { 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 * Note: The sample order is irrelevant
*/ */
extern bool merge_sources(void* /* result */, void* /* source a */, void* /* source b */, size_t /* channels */, size_t /* samples */); extern bool merge_sources(void* /* result */, void* /* source a */, void* /* source b */, size_t /* channels */, size_t /* samples */);

View File

@ -46,6 +46,8 @@ namespace tc::audio::pa {
private: private:
void read_callback(const void *input, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags); void read_callback(const void *input, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags);
size_t source_channel_count{0};
PaDeviceIndex index; PaDeviceIndex index;
const PaDeviceInfo* info; const PaDeviceInfo* info;
PaStream* stream{nullptr}; PaStream* stream{nullptr};

View File

@ -42,7 +42,15 @@ bool PortAudioRecord::impl_start(std::string &error) {
PaStreamParameters parameters{}; PaStreamParameters parameters{};
memset(&parameters, 0, sizeof(parameters)); memset(&parameters, 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.device = this->index;
parameters.sampleFormat = paFloat32; parameters.sampleFormat = paFloat32;
parameters.suggestedLatency = this->info->defaultLowInputLatency; parameters.suggestedLatency = this->info->defaultLowInputLatency;
@ -95,5 +103,5 @@ void PortAudioRecord::read_callback(const void *input, unsigned long frameCount,
const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) { const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) {
std::lock_guard consumer_lock{this->consumer_lock}; std::lock_guard consumer_lock{this->consumer_lock};
for(auto& consumer : this->_consumers) for(auto& consumer : this->_consumers)
consumer->consume(input, frameCount, kChannelCount); consumer->consume(input, frameCount, this->source_channel_count);
} }

View File

@ -70,9 +70,8 @@ tc::audio::AudioOutput* global_audio_output;
Nan::Set(object, (uint32_t) value, Nan::New<v8::String>(key).ToLocalChecked()); Nan::Set(object, (uint32_t) value, Nan::New<v8::String>(key).ToLocalChecked());
NAN_MODULE_INIT(init) { NAN_MODULE_INIT(init) {
/* FIXME: Reenable */ logger::initialize_node();
//logger::initialize_node(); //logger::initialize_raw();
logger::initialize_raw();
#ifndef WIN32 #ifndef WIN32
logger::info(category::general, tr("Hello World from C. PPID: {}, PID: {}"), getppid(), getpid()); logger::info(category::general, tr("Hello World from C. PPID: {}, PID: {}"), getppid(), getpid());