Adding support for mono devices
This commit is contained in:
parent
804773f4eb
commit
df6083f572
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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 */);
|
||||||
|
@ -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};
|
||||||
|
@ -42,7 +42,15 @@ bool PortAudioRecord::impl_start(std::string &error) {
|
|||||||
|
|
||||||
PaStreamParameters parameters{};
|
PaStreamParameters parameters{};
|
||||||
memset(¶meters, 0, sizeof(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.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);
|
||||||
}
|
}
|
@ -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());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user