107 lines
2.5 KiB
C++
107 lines
2.5 KiB
C++
#include "FilterVad.h"
|
|
#include "../AudioMerger.h"
|
|
#include "../../logger.h"
|
|
|
|
using namespace std;
|
|
using namespace tc::audio;
|
|
using namespace tc::audio::filter;
|
|
|
|
VadFilter::VadFilter(size_t channels, size_t rate, size_t frames) : Filter(channels, rate, frames) { }
|
|
|
|
VadFilter::~VadFilter() {
|
|
this->cleanup_buffer();
|
|
if(this->_vad_handle) {
|
|
fvad_free(this->_vad_handle);
|
|
this->_vad_handle = nullptr;
|
|
}
|
|
}
|
|
|
|
void VadFilter::cleanup_buffer() {
|
|
lock_guard lock(this->_buffer_lock);
|
|
if(this->_buffer)
|
|
free(this->_buffer);
|
|
this->_buffer = nullptr;
|
|
this->_buffer_size = 0;
|
|
}
|
|
|
|
bool VadFilter::initialize(std::string &error, size_t mode, size_t margin) {
|
|
|
|
this->_vad_handle = fvad_new();
|
|
if(!this->_vad_handle) {
|
|
error = "failed to allocate handle";
|
|
return false;
|
|
}
|
|
|
|
if(fvad_set_sample_rate(this->_vad_handle, (int) this->_sample_rate) != 0) {
|
|
error = "invalid sample rate. Sample rate must be one of [8000, 16000, 32000 and 48000]";
|
|
return false;
|
|
}
|
|
|
|
if(fvad_set_mode(this->_vad_handle, (int) mode) != 0) {
|
|
error = "failed to set mode";
|
|
return false;
|
|
}
|
|
|
|
this->_mode = mode;
|
|
this->_margin_samples = margin;
|
|
if(this->_channels > 1) {
|
|
this->ensure_buffer(this->_frame_size * this->_channels * 4); /* buffer to merge the channels into one channel */
|
|
} else {
|
|
this->ensure_buffer(this->_frame_size * 2);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VadFilter::process(const void *buffer) {
|
|
if(!this->_vad_handle) {
|
|
log_warn(category::audio, tr("Vad filter hasn't been initialized!"));
|
|
return false;
|
|
}
|
|
|
|
lock_guard lock(this->_buffer_lock);
|
|
if(this->_channels > 1) {
|
|
if(!merge::merge_channels_interleaved(this->_buffer, 1, buffer, this->_channels, this->_frame_size)) {
|
|
log_warn(category::audio, tr("Failed to merge channels"));
|
|
return false;
|
|
}
|
|
buffer = this->_buffer;
|
|
}
|
|
|
|
/* convert float32 samples to signed int16 */
|
|
{
|
|
auto target = (int16_t*) this->_buffer;
|
|
auto source = (float*) buffer;
|
|
auto sample = this->_frame_size;
|
|
|
|
float tmp;
|
|
while(sample-- > 0) {
|
|
tmp = *source++;
|
|
tmp *= 32768;
|
|
|
|
if(tmp > 32767)
|
|
tmp = 32767;
|
|
|
|
if(tmp < -32768)
|
|
tmp = -32768;
|
|
|
|
*target++ = (int16_t) tmp;
|
|
}
|
|
}
|
|
|
|
auto result = fvad_process(this->_vad_handle, (int16_t*) this->_buffer, this->_frame_size);
|
|
if(result == -1) {
|
|
log_warn(category::audio, tr("Invalid frame length"));
|
|
return false;
|
|
}
|
|
|
|
auto flag_vad = result == 1;
|
|
|
|
if(!flag_vad) {
|
|
this->_margin_processed_samples += this->_frame_size;
|
|
return this->_margin_processed_samples <= this->_margin_samples;
|
|
} else {
|
|
this->_margin_processed_samples = 0;
|
|
}
|
|
return flag_vad;
|
|
} |