2019-10-26 01:51:40 +02:00
|
|
|
#include <cstring>
|
|
|
|
#include "AudioResampler.h"
|
|
|
|
#include "../logger.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace tc::audio;
|
|
|
|
|
2021-03-25 15:21:47 +01:00
|
|
|
AudioResampler::AudioResampler(size_t irate, size_t orate, size_t channels) : input_rate_{irate}, output_rate_{orate}, channels_{channels} {
|
2019-10-26 01:51:40 +02:00
|
|
|
if(this->input_rate() != this->output_rate()) {
|
|
|
|
soxr_error_t error;
|
2021-03-25 15:21:47 +01:00
|
|
|
this->soxr_handle = soxr_create((double) this->input_rate_, (double) this->output_rate_, (unsigned) this->channels_, &error, nullptr, nullptr, nullptr);
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
if(!this->soxr_handle) {
|
2021-03-25 15:21:47 +01:00
|
|
|
log_error(category::audio, tr("Failed to create soxr resampler: {}. Input: {}; Output: {}; Channels: {}"), error, this->input_rate_, this->output_rate_, this->channels_);
|
2019-10-26 01:51:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioResampler::~AudioResampler() {
|
|
|
|
if(this->soxr_handle)
|
|
|
|
soxr_delete(this->soxr_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t AudioResampler::process(void *output, const void *input, size_t input_length) {
|
|
|
|
if(this->io_ratio() == 1) {
|
2021-03-25 15:21:47 +01:00
|
|
|
if(input != output) {
|
|
|
|
memcpy(output, input, input_length * this->channels_ * 4);
|
|
|
|
}
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
return input_length;
|
|
|
|
}
|
2021-03-25 15:21:47 +01:00
|
|
|
|
|
|
|
if(!this->soxr_handle) {
|
|
|
|
return -2;
|
|
|
|
}
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
size_t output_length = 0;
|
|
|
|
auto error = soxr_process(this->soxr_handle, input, input_length, nullptr, output, this->estimated_output_size(input_length), &output_length);
|
|
|
|
if(error) {
|
|
|
|
log_error(category::audio, tr("Failed to process resample: {}"), error);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return output_length;
|
|
|
|
}
|