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 "./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<AudioConsumer> &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<std::chrono::milliseconds>(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<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; }
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;

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);
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;
}

View File

@ -3,7 +3,8 @@
#include <cstring>
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 */);

View File

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

View File

@ -42,7 +42,15 @@ bool PortAudioRecord::impl_start(std::string &error) {
PaStreamParameters 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.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);
}

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_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());