#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <string.h>
#include <speex/speex_preprocess.h>
#include <audio_effect_interface.h>
+#include <audio_effect_util.h>
+#include <audio_effect_log.h>
+
+#define MAX_CHANNELS 2
+#define AGC_SPEEX_FRAME_MSEC 10
struct userdata {
- SpeexPreprocessState *st;
+ SpeexPreprocessState *st[MAX_CHANNELS];
size_t frames;
int channels;
int rate;
audio_effect_format_e format;
+ int sample_size;
+
+ char *buffer[MAX_CHANNELS];
};
static void *agc_speex_create(int rate, int channels, audio_effect_format_e format, size_t frames)
{
struct userdata *u;
-
- u = (struct userdata *)malloc(sizeof(struct userdata));
-
- int denoise_enabled = 1;
int agc_enabled = 1;
+ float agc_target = 20000;
+ int i;
- SpeexPreprocessState *st;
-
- st = speex_preprocess_state_init(frames, rate);
-
- speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &denoise_enabled);
- speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &agc_enabled);
+ u = (struct userdata *)calloc(1, sizeof(struct userdata));
+ if (!u) {
+ LOG_ERROR("Failed to allocate userdata");
+ return NULL;
+ }
u->frames = frames;
- u->st = st;
u->rate = rate;
u->channels = channels;
u->format = format;
+ u->sample_size = audio_effect_util_get_sample_size(format);
+
+ for (i = 0; i < u->channels; i++) {
+ u->st[i] = speex_preprocess_state_init(frames, rate);
+ if (!u->st[i]) {
+ LOG_ERROR("Failed speex_preprocess_state_init");
+ goto fail;
+ }
+
+ speex_preprocess_ctl(u->st[i], SPEEX_PREPROCESS_SET_AGC, &agc_enabled);
+ speex_preprocess_ctl(u->st[i], SPEEX_PREPROCESS_SET_AGC_TARGET, &agc_target);
+ }
+
+ if (u->channels >= 2) {
+ for (i = 0; i < u->channels; i++) {
+ u->buffer[i] = (char *)malloc(u->sample_size * u->frames);
+ if (!u->buffer[i]) {
+ LOG_ERROR("Failed to allocate fbuffer");
+ goto fail;
+ }
+ }
+ }
+
+ LOG_INFO("speex agc created. rate(%d), ch(%d), sample_size(%d), frames(%zu)",
+ u->rate, u->channels, u->sample_size, u->frames);
return u;
+
+fail:
+ for (i = 0; i < u->channels; i++) {
+ if (u->buffer[i])
+ free(u->buffer[i]);
+ if (u->st[i])
+ speex_preprocess_state_destroy(u->st[i]);
+ }
+
+ free(u);
+
+ return NULL;
}
static int agc_speex_process(void *priv, char *in, char *out)
{
- size_t i;
- short *src = (short *)in;
- short *dst = (short *)out;
+ int i;
+ char *src = in;
+ char *dst = out;
struct userdata *u = (struct userdata *)priv;
+ assert(u);
assert(src);
assert(dst);
- assert(out);
- speex_preprocess_run(u->st, (spx_int16_t *)src);
+ if (u->channels == 1) {
+ memcpy(dst, src, u->frames * u->sample_size);
+ speex_preprocess_run(u->st[0], (spx_int16_t *)dst);
+ } else {
+ audio_effect_util_deinterleave(in, (void **)u->buffer, u->channels, u->sample_size, u->frames);
+
+ for (i = 0; i < u->channels; i++)
+ speex_preprocess_run(u->st[i], (spx_int16_t *)u->buffer[i]);
- for (i = 0; i < u->frames; i++) {
- dst[i] = src[i];
+ audio_effect_util_interleave((const void **)u->buffer, out, u->channels, u->sample_size, u->frames);
}
return 0;
static void agc_speex_destroy(void *priv)
{
struct userdata *u = (struct userdata *)priv;
+ int i;
assert(u);
- speex_preprocess_state_destroy(u->st);
+ for (i = 0; i < u->channels; i++) {
+ if (u->st[i])
+ speex_preprocess_state_destroy(u->st[i]);
+ if (u->buffer[i])
+ free(u->buffer[i]);
+ }
+
free(u);
}
.destroy = agc_speex_destroy,
},
.constraint = {
+ .frames_msec = AGC_SPEEX_FRAME_MSEC,
.min_rate = 8000,
.max_rate = 48000,
.min_channels = 1,
- .max_channels = 1,
+ .max_channels = MAX_CHANNELS,
.min_format = AUDIO_EFFECT_FORMAT_S16,
.max_format = AUDIO_EFFECT_FORMAT_S16,
},
#include "audio_effect.h"
-#define FRAME_SIZE (160)
+#define FORMAT_SIZE 2
int main(void)
{
audio_effect_s *ae;
FILE *fin;
FILE *fout;
- short in[FRAME_SIZE];
- short out[FRAME_SIZE];
- size_t framesize = FRAME_SIZE;
+ int i;
+ int n = 0;
- int i=0;
+ char *input_file[] = { "agc_speex_in.raw", "agc_speex_in_2ch.raw", "agc_speex_in_48k_2ch.raw" };
+ char *output_file[] = { "agc_speex_out.raw", "agc_speex_out_2ch.raw", "agc_speex_out_48k_2ch.raw" };
+
+ char *in;
+ char *out;
+
+ int rate[] = { 16000, 16000, 48000 };
+ int channels[] = { 1, 2, 2 };
+ int frames[] = { 160, 160, 480 };
+ size_t fs;
printf("--- agc speex start ---\n");
- fin = fopen("obama.raw", "r");
- if (!fin) {
- printf("failed to find airport_48k.raw\n");
- exit(-1);
- }
+ for (i = 0; i < sizeof(rate)/sizeof(rate[0]); i++) {
+ fin = fopen(input_file[i], "r");
+ if (!fin) {
+ printf("failed to open the source file(%s)\n", input_file[i]);
+ exit(-1);
+ }
- fout = fopen("agc_speex_out.raw", "wb");
- if (!fout) {
- printf("failed to open raw\n");
- exit(-1);
- }
+ fout = fopen(output_file[i], "wb");
+ if (!fout) {
+ printf("failed to open raw\n");
+ exit(-1);
+ }
- ae = audio_effect_create(AUDIO_EFFECT_METHOD_AGC_SPEEX, 16000, 1, AUDIO_EFFECT_FORMAT_S16, framesize);
- assert(ae);
+ ae = audio_effect_create(AUDIO_EFFECT_METHOD_AGC_SPEEX, rate[i], channels[i], AUDIO_EFFECT_FORMAT_S16, frames[i]);
+ assert(ae);
- framesize = audio_effect_get_process_framesize(ae);
- printf("frame size %zu\n", framesize);
+ fs = audio_effect_get_process_framesize(ae);
+ printf("frame size %zu\n", fs);
- while (!feof(fin)) {
- if (fread(in, sizeof(short), FRAME_SIZE, fin) < 0)
- break;
+ in = (char *)malloc(fs * channels[i] * FORMAT_SIZE);
+ assert(in);
- printf("#%d frame. ", i++);
+ out = (char *)malloc(fs * channels[i] * FORMAT_SIZE);
+ assert(out);
- if (audio_effect_process(ae, in, out) < 0) {
- printf("(failed!)\n");
- } else {
- printf("(success!)\n");
- fwrite(out, sizeof(short), FRAME_SIZE, fout);
+ while (!feof(fin)) {
+ if (fread(in, channels[i] * FORMAT_SIZE, fs, fin) < 0)
+ break;
+
+ printf("#%d frame. ", n++);
+
+ if (audio_effect_process(ae, in, out) < 0) {
+ printf("(failed!)\n");
+ } else {
+ printf("(success!)\n");
+ fwrite(out, channels[i] * FORMAT_SIZE, fs, fout);
+ }
}
- }
- audio_effect_destroy(ae);
+ audio_effect_destroy(ae);
- fclose(fin);
- fclose(fout);
+ free(in);
+ free(out);
+
+ fclose(fin);
+ fclose(fout);
+ }
printf("--- agc speex end ---\n");