Adding support for mono devices
This commit is contained in:
parent
804773f4eb
commit
df6083f572
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
@ -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 */);
|
||||
|
@ -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};
|
||||
|
@ -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);
|
||||
}
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user