audio_demo/agcm.h
2025-02-14 08:58:27 +08:00

174 lines
5.2 KiB
C++

#pragma once
#include <stdint.h>
#include <stdio.h>
#include <cmath>
#include "agc.h"
// #ifndef min
// #define min(A, B) ((A) < (B) ? (A) : (B))
// #endif
inline int vad_frame_process(void *state, int16_t *buffer, int frame_size)
{
VadEnergy *st = (VadEnergy *)state;
int i, VAD_amp = 0, buf_mean = 0;
for (i = 0; i < frame_size; i++)
{
buf_mean += buffer[i];
}
buf_mean = buf_mean / frame_size;
for (i = 0; i < frame_size; i++)
{
VAD_amp = VAD_amp + abs(buffer[i] - buf_mean);
}
VAD_amp = VAD_amp / frame_size;
if (st->VAD == 0)
{
if (VAD_amp > st->amth)
{
st->specnt = st->specnt + 1;
if (st->specnt >= st->sil2spe)
{
st->VAD = 1;
st->silcnt = 0;
}
}
else
{
st->specnt = 0;
st->silcnt++;
}
}
else
{
if (VAD_amp < st->amth)
{
st->silcnt = st->silcnt + 1;
if (st->silcnt >= st->spe2sil)
{
st->VAD = 0;
}
}
else
{
st->silcnt = 0;
st->specnt = 0;
}
}
return 0;
}
inline void* agc_init(uint32_t sampleRate, int16_t agcMode, int gaindb, int tlevel)
{
WebRtcAgcConfig agcConfig;
agcConfig.compressionGaindB = gaindb; // default 9 dB
agcConfig.limiterEnable = 1; // default kAgcTrue (on)
agcConfig.targetLevelDbfs = tlevel; // default 3 (-3 dBOv)
int minLevel = 0;
int maxLevel = 255;
void *agcInst = WebRtcAgc_Create();
if (agcInst == NULL) return 0;
int status = WebRtcAgc_Init(agcInst, minLevel, maxLevel, agcMode, sampleRate);
if (status != 0) {
printf("WebRtcAgc_Init fail\n");
WebRtcAgc_Free(agcInst);
return 0;
}
status = WebRtcAgc_set_config(agcInst, agcConfig);
if (status != 0) {
printf("WebRtcAgc_set_config fail\n");
WebRtcAgc_Free(agcInst);
return 0;
}
return agcInst;
}
inline void agc_destory(void *agcInst)
{
WebRtcAgc_Free(agcInst);
}
inline int agc_sample_process(void *agcInst, int16_t *in_buffer, int16_t *out_buffer, uint32_t sampleRate, uint32_t in_buffer_len)
{
int i;
LegacyAgc *stt = (LegacyAgc *)agcInst;
if (in_buffer == NULL || in_buffer_len < 160)
return -1;
int samples = std::min(160, (int)sampleRate / 100);
if (samples == 0)
return -1;
int16_t *input = in_buffer;
size_t num_bands = 1;
int inMicLevel, outMicLevel = -1;
int16_t *out16 = out_buffer;
uint8_t saturationWarning = 1;
int16_t echo = 0;
int nAgcRet = 0;
int time , process_len;
time = in_buffer_len / samples;
process_len = samples * time;
for (i = 0; i < time; i++)
{
inMicLevel = 127;
vad_frame_process(&stt->vad_energy, input, samples);
if (stt->agcMode == kAgcModeAdaptiveDigital && stt->vad_energy.VAD == 1)
{
if (WebRtcAgc_VirtualMic(stt, (int16_t *const *)&input, num_bands, samples, inMicLevel, &outMicLevel))
{
return -1;
}
nAgcRet = WebRtcAgc_Process(stt, (int16_t *const *)&input, num_bands, samples,
(int16_t *const *)&out16, outMicLevel, &outMicLevel, echo,
&saturationWarning);
}
else if (stt->agcMode == kAgcModeFixedDigital && stt->vad_energy.VAD == 1)
{
nAgcRet = WebRtcAgc_Process(stt, (int16_t *const *)&input, num_bands, samples,
(int16_t *const *)&out16, inMicLevel, &outMicLevel, echo,
&saturationWarning);
}
else
{
memcpy(out16, input, samples * sizeof(int16_t));
}
if (nAgcRet != 0)
{
printf("failed in Agc_Process\n");
return -1;
}
input += samples;
out16 += samples;
}
return process_len;
}
inline int agc_process(void *agcInst, int16_t *in, int16_t *out, uint32_t sampleRate, uint32_t frame_size)
{
int i, process_len = 0;
LegacyAgc *st = (LegacyAgc *)agcInst;
size_t samplesCount;
size_t samples = std::min(160, (int)sampleRate / 100);
if (samples == 0) return -1;
st->bufferAgc.frame_size = frame_size;
memcpy(&st->bufferAgc.buffer_in[st->bufferAgc.in_uselen], in, sizeof(int16_t) * frame_size);
st->bufferAgc.in_uselen += frame_size;
process_len = agc_sample_process(agcInst, st->bufferAgc.buffer_in, &st->bufferAgc.buffer_out[st->bufferAgc.out_uselen], sampleRate, st->bufferAgc.in_uselen);
if (process_len > 0)
{
memcpy(st->bufferAgc.buffer_in, &st->bufferAgc.buffer_in[process_len], sizeof(int16_t) * (st->bufferAgc.in_uselen - process_len));
st->bufferAgc.in_uselen -= process_len;
st->bufferAgc.out_uselen += process_len;
}
if (st->bufferAgc.out_uselen >= frame_size)
{
memcpy(out, st->bufferAgc.buffer_out, sizeof(int16_t) * frame_size);
memcpy(st->bufferAgc.buffer_out, &st->bufferAgc.buffer_out[frame_size], sizeof(int16_t) * (st->bufferAgc.out_uselen - frame_size));
st->bufferAgc.out_uselen -= frame_size;
}
return 0;
}