174 lines
5.2 KiB
C++
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;
|
|
} |