agc_speex: Support stereo 28/300328/4
authorJaechul Lee <jcsing.lee@samsung.com>
Fri, 13 Oct 2023 07:11:26 +0000 (16:11 +0900)
committerJaechul Lee <jcsing.lee@samsung.com>
Mon, 23 Oct 2023 08:41:49 +0000 (17:41 +0900)
[Version] 0.0.15
[Issue Type] Update

Change-Id: Icbc59f0a0f7461fed0421da60faada9a345e6704
Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
meson.build
packaging/libaudio-effect.spec
src/plugin_agc_speex.c
test/agc_speex_test.c
test/resources/airport_48k_2ch.raw [new file with mode: 0644]
test/resources/obama_2ch.raw [new file with mode: 0644]
test/resources/obama_48k_2ch.raw [new file with mode: 0644]

index 4682d0138e46a93e3a8a8cd3941ad171dd53fa2b..e6bfa5af3a872fe9fbf82e117b5d8d774926bdc9 100644 (file)
@@ -144,6 +144,9 @@ if get_option('testsuite').enabled()
   configure_file(input: './test/resources/rec_refcopy_5ch.raw',  output: 'rec_refcopy.raw',  copy: true)
   configure_file(input: './test/resources/airport_48k.raw',  output: 'airport_48k.raw',  copy: true)
   configure_file(input: './test/resources/airport_48k_2ch.raw',  output: 'airport_48k_2ch.raw',  copy: true)
+  configure_file(input: './test/resources/obama.raw',  output: 'agc_speex_in.raw',  copy: true)
+  configure_file(input: './test/resources/obama_2ch.raw',  output: 'agc_speex_in_2ch.raw',  copy: true)
+  configure_file(input: './test/resources/obama_48k_2ch.raw',  output: 'agc_speex_in_48k_2ch.raw',  copy: true)
 endif
 
 # --- install pkg-config ---
index d0d4ebc729f864b9f02d263a2fe81e637762b81f..b51e26deb0259d7623b3fefd6d7bab8d68ba768d 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libaudio-effect
 Summary:    audio effect library
-Version:    0.0.14
+Version:    0.0.15
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 2c4f02bbbccbe7690b6ed20fc01230cb8f1612bb..e0dcc0eb6ff033b081f135fa1f5fc733487867f1 100644 (file)
 #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;
@@ -76,10 +124,17 @@ static int agc_speex_process(void *priv, char *in, char *out)
 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);
 }
 
@@ -92,10 +147,11 @@ static audio_effect_plugin_info_s agc_speex_desc = {
                .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,
        },
index b46ea9194485c411391d9bad5b9204c1fbe712ca..95dd532125b3b9722fc993e3df0981d14c1d1046 100644 (file)
@@ -4,57 +4,76 @@
 
 #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");
 
diff --git a/test/resources/airport_48k_2ch.raw b/test/resources/airport_48k_2ch.raw
new file mode 100644 (file)
index 0000000..f2bab8a
Binary files /dev/null and b/test/resources/airport_48k_2ch.raw differ
diff --git a/test/resources/obama_2ch.raw b/test/resources/obama_2ch.raw
new file mode 100644 (file)
index 0000000..fccae1f
Binary files /dev/null and b/test/resources/obama_2ch.raw differ
diff --git a/test/resources/obama_48k_2ch.raw b/test/resources/obama_48k_2ch.raw
new file mode 100644 (file)
index 0000000..8e71b1e
Binary files /dev/null and b/test/resources/obama_48k_2ch.raw differ