feat: voice compressor with RMS+peak leveling, sliding window envelope, rate-limited gain
This commit is contained in:
1 parent
7004b110ae
commit
f1b599f0c0
8 files changed
+406
-9
No files matched your search
@@ -1,4 +1,5 @@
|
||||
#include "audiorecorder.h"
|
||||
#include "audiocompressor.h"
|
||||
#include "miniaudio.h"
|
||||
#include "sound_manager.h"
|
||||
|
||||
@@ -16,10 +17,15 @@ void audioCaptureCallback(ma_device* pDevice, void* pOutput, const void* pInput,
|
||||
if (!pInput) return;
|
||||
|
||||
const int16_t* src = (const int16_t*)pInput;
|
||||
size_t cur = self->m_pcmBuffer.size();
|
||||
size_t add = (size_t)frameCount * (size_t)self->m_channels;
|
||||
self->m_pcmBuffer.resize(cur + add);
|
||||
std::memcpy(self->m_pcmBuffer.data() + cur, src, add * sizeof(int16_t));
|
||||
|
||||
if (self->m_compressor && self->m_compressorEnabled) {
|
||||
self->m_compressor->push(src, add);
|
||||
} else {
|
||||
size_t cur = self->m_pcmBuffer.size();
|
||||
self->m_pcmBuffer.resize(cur + add);
|
||||
std::memcpy(self->m_pcmBuffer.data() + cur, src, add * sizeof(int16_t));
|
||||
}
|
||||
|
||||
float sumSq = 0.0f;
|
||||
for (unsigned int i = 0; i < frameCount * (unsigned int)self->m_channels; i++) {
|
||||
@@ -42,6 +48,11 @@ void audioCaptureCallback(ma_device* pDevice, void* pOutput, const void* pInput,
|
||||
AudioRecorder::AudioRecorder(QObject* parent)
|
||||
: QObject(parent) {
|
||||
g_recorder = this;
|
||||
m_compressor = new AudioCompressor;
|
||||
AudioCompressor::Config cfg;
|
||||
cfg.sampleRate = m_sampleRate;
|
||||
cfg.channels = m_channels;
|
||||
m_compressor->configure(cfg);
|
||||
m_durationTimer.setInterval(100);
|
||||
connect(&m_durationTimer, &QTimer::timeout, this, [this]() {
|
||||
if (m_recording) {
|
||||
@@ -53,6 +64,8 @@ AudioRecorder::AudioRecorder(QObject* parent)
|
||||
|
||||
AudioRecorder::~AudioRecorder() {
|
||||
shutdown();
|
||||
delete m_compressor;
|
||||
m_compressor = nullptr;
|
||||
if (g_recorder == this) g_recorder = nullptr;
|
||||
}
|
||||
|
||||
@@ -86,6 +99,8 @@ void AudioRecorder::startRecording() {
|
||||
m_rmsIdx = 0;
|
||||
m_elapsedMs = 0;
|
||||
|
||||
if (m_compressor) m_compressor->reset();
|
||||
|
||||
ma_context* ctx = SoundManager::instance()->context();
|
||||
if (!ctx) { qWarning("AudioRecorder: no audio context"); return; }
|
||||
|
||||
@@ -142,10 +157,14 @@ void AudioRecorder::stopRecording() {
|
||||
ma_device_uninit(m_device);
|
||||
m_deviceStarted = false;
|
||||
}
|
||||
|
||||
m_recording = false;
|
||||
|
||||
if (m_compressor && m_compressorEnabled) m_compressor->flush();
|
||||
|
||||
int duration = m_elapsedMs;
|
||||
qDebug("AudioRecorder: recording stopped, duration=%dms, pcmSamples=%zu", duration, m_pcmBuffer.size());
|
||||
size_t bufSize = (m_compressor && m_compressorEnabled) ? m_compressor->outputBuffer().size() : m_pcmBuffer.size();
|
||||
qDebug("AudioRecorder: recording stopped, duration=%dms, pcmSamples=%zu, compressor=%d",
|
||||
duration, bufSize, m_compressorEnabled ? 1 : 0);
|
||||
emit recordingStopped(duration);
|
||||
emit durationChanged(0);
|
||||
}
|
||||
@@ -159,3 +178,14 @@ float AudioRecorder::peakLevel() const {
|
||||
m_peakLevel = 0.0f;
|
||||
return v;
|
||||
}
|
||||
|
||||
const std::vector<int16_t>& AudioRecorder::buffer() const {
|
||||
if (m_compressor && m_compressorEnabled) return m_compressor->outputBuffer();
|
||||
return m_pcmBuffer;
|
||||
}
|
||||
|
||||
void AudioRecorder::setCompressorEnabled(bool enabled) {
|
||||
m_compressorEnabled = enabled;
|
||||
if (m_compressor) m_compressor->setEnabled(enabled);
|
||||
qDebug("AudioRecorder: compressor %s", enabled ? "enabled" : "disabled");
|
||||
}
|
||||
Reference in new issue
Block a user