rnnoise: Support mono and stereo 33/299833/9
authorJaechul Lee <jcsing.lee@samsung.com>
Wed, 11 Oct 2023 02:47:08 +0000 (11:47 +0900)
committerJaechul Lee <jcsing.lee@samsung.com>
Wed, 18 Oct 2023 02:22:10 +0000 (11:22 +0900)
[Version] 0.0.14
[Issue Type] Update

Change-Id: I37c2ed1f43f9631813e2966c07523dd100a7c472
Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
meson.build
packaging/libaudio-effect.spec
src/plugin_ns_rnnoise.c
test/ns_rnnoise_test.c

index 8e9a6cb3d1741ec121b182d84912d85709bb5755..4682d0138e46a93e3a8a8cd3941ad171dd53fa2b 100644 (file)
@@ -143,6 +143,7 @@ if get_option('testsuite').enabled()
   configure_file(input: './test/resources/ref.raw',  output: 'ref.raw',  copy: true)
   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)
 endif
 
 # --- install pkg-config ---
index c822476bd9ad410d000806e3cb54a85a0462bd00..d0d4ebc729f864b9f02d263a2fe81e637762b81f 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libaudio-effect
 Summary:    audio effect library
-Version:    0.0.13
+Version:    0.0.14
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index 9de572d899c402c458374c8418fea646460300be..1bf3a1c55dceaf7ebb6f290621f8c60e6c46483a 100644 (file)
 #include <assert.h>
 #include <audio_effect_interface.h>
 #include <audio_effect_log.h>
+#include <audio_effect_util.h>
 
 #include <rnnoise.h>
 
-#define FIXED_FRAME_SIZE 480
+#define FIXED_FRAME_SIZE       480
+#define MAX_CHANNELS           2
 
 struct userdata {
-       DenoiseState *st;
+       DenoiseState *st[MAX_CHANNELS];
        int rate;
        int channels;
        audio_effect_format_e format;
        size_t frames;
 
-       float *buffer;
+       float *fbuffer;
+       float *d_fbuffer[MAX_CHANNELS];
 };
 
+static void ns_rnnoise_process_mono(struct userdata *u, short *in, short *out)
+{
+       short *ptr = in;
+       int i;
+
+       for (i = 0; i < u->frames; i++)
+               u->fbuffer[i] = ptr[i];
+
+       rnnoise_process_frame(u->st[0], u->fbuffer, u->fbuffer);
+
+       ptr = out;
+       for (i = 0; i < u->frames; i++)
+               ptr[i] = u->fbuffer[i];
+}
+
+static void ns_rnnoise_process_stereo(struct userdata *u, short *in, short *out)
+{
+       size_t float_sample_size = audio_effect_util_get_sample_size(AUDIO_EFFECT_FORMAT_FLOAT);
+       short *ptr = in;
+       int i;
+
+       assert(u->channels > 1);
+
+       for (i = 0; i < u->frames * u->channels; i++)
+               u->fbuffer[i] = ptr[i];
+
+       audio_effect_util_deinterleave(u->fbuffer, (void **)u->d_fbuffer, u->channels, float_sample_size, u->frames);
+
+       for (i = 0; i < u->channels; i++)
+               rnnoise_process_frame(u->st[i], u->d_fbuffer[i], u->d_fbuffer[i]);
+
+       audio_effect_util_interleave((const void **)u->d_fbuffer, u->fbuffer, u->channels, float_sample_size, u->frames);
+
+       ptr = out;
+       for (i = 0; i < u->frames * u->channels; i++)
+               ptr[i] = u->fbuffer[i];
+}
+
 static void *ns_rnnoise_create(int rate, int channels, audio_effect_format_e format, size_t frames)
 {
        struct userdata *u;
+       int i;
 
-       u = (struct userdata *)malloc(sizeof(struct userdata));
+       u = (struct userdata *)calloc(1, sizeof(struct userdata));
 
-       u->st = rnnoise_create(NULL);
        u->rate = rate;
        u->channels = channels;
        u->format = format;
@@ -52,37 +93,64 @@ static void *ns_rnnoise_create(int rate, int channels, audio_effect_format_e for
 
        u->frames = FIXED_FRAME_SIZE;
 
-       u->buffer = (float *)malloc(sizeof(float) * u->frames * channels);
+       u->fbuffer = (float *)malloc(sizeof(float) * u->frames * channels);
+       if (!u->fbuffer) {
+               LOG_ERROR("Failed to allocate fbuffer");
+               goto fail;
+       }
+
+       for (i = 0; i < u->channels; i++) {
+               u->st[i] = rnnoise_create(NULL);
+               if (!u->st[i]) {
+                       LOG_ERROR("Failed to create rnnoise");
+                       goto fail;
+               }
+       }
+
+       /* it doesn't need d_fbuffer in case of mono */
+       if (u->channels > 1) {
+               for (i = 0; i < u->channels; i++) {
+                       u->d_fbuffer[i] = (float *)malloc(sizeof(float) * u->frames);
+                       if (!u->d_fbuffer[i]) {
+                               LOG_ERROR("Failed to allocate fbuffer");
+                               goto fail;
+                       }
+               }
+       }
 
        LOG_INFO("plugin rnnoise init. rate(%d), channels(%d), format(%d), frames(%zu)",
                                rate, channels, format, u->frames);
 
        return u;
+
+fail:
+       for (i = 0; i < u->channels; i++) {
+               if (u->st[i])
+                       rnnoise_destroy(u->st[i]);
+               if (u->d_fbuffer[i])
+                       free(u->d_fbuffer[i]);
+       }
+
+       if (u->fbuffer)
+               free(u->fbuffer);
+
+       free(u);
+
+       return NULL;
 }
 
 static int ns_rnnoise_process(void *priv, char *in, char *out)
 {
        struct userdata *u = (struct userdata *)priv;
-       int16_t *ptr;
-       int i;
 
        assert(u);
        assert(in);
        assert(out);
 
-       ptr = (int16_t *)in;
-       for (i = 0; i < u->frames; i++) {
-               u->buffer[i] = 0;
-               u->buffer[i] = ptr[i];
-       }
-
-       rnnoise_process_frame(u->st, u->buffer, u->buffer);
-
-       ptr = (int16_t *)out;
-       for (i = 0; i < u->frames; i++) {
-               ptr[i] = 0;
-               ptr[i] = u->buffer[i];
-       }
+       if (u->channels == 1)
+               ns_rnnoise_process_mono(u, (short *)in, (short *)out);
+       else
+               ns_rnnoise_process_stereo(u, (short *)in, (short *)out);
 
        return 0;
 }
@@ -90,14 +158,30 @@ static int ns_rnnoise_process(void *priv, char *in, char *out)
 static void ns_rnnoise_destroy(void *priv)
 {
        struct userdata *u = (struct userdata *)priv;
+       int i;
 
        assert(u);
-       assert(u->st);
-       assert(u->buffer);
 
-       rnnoise_destroy(u->st);
-       free(u->buffer);
+       for (i = 0; i < u->channels; i++) {
+               if (u->st[i]) {
+                       rnnoise_destroy(u->st[i]);
+                       u->st[i] = NULL;
+               }
+
+               if (u->d_fbuffer[i]) {
+                       free(u->d_fbuffer[i]);
+                       u->d_fbuffer[i] = NULL;
+               }
+       }
+
+       if (u->fbuffer) {
+               free(u->fbuffer);
+               u->fbuffer = NULL;
+       }
+
        free(u);
+
+       u = NULL;
 }
 
 static audio_effect_plugin_info_s ns_rnnoise_desc = {
@@ -113,7 +197,7 @@ static audio_effect_plugin_info_s ns_rnnoise_desc = {
                .min_rate = 48000,
                .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 5f7a90afe9a8ecb92303fe340ffccaceae2c3cdf..1a76f66f7e7440c5adc28861549d74c53ca6a7ea 100644 (file)
@@ -4,8 +4,9 @@
 
 #include "audio_effect.h"
 
-#define FRAME_SIZE 1024
+#define MAX_CHANNELS 2
 #define FIXED_FRAME_SIZE 480
+#define FRAME_SIZE FIXED_FRAME_SIZE * MAX_CHANNELS
 
 int main(void)
 {
@@ -16,49 +17,56 @@ int main(void)
        short out[FRAME_SIZE];
        size_t framesize = FRAME_SIZE;
 
-       int i=0;
+       int i;
+       int n = 0;
+
+       int channels[MAX_CHANNELS] = { 1, 2 };
+       char *test_file[] = { "airport_48k.raw", "airport_48k_2ch.raw" };
+       char *out_file[] = { "rnnoise_out.raw", "rnnoise_2ch_out.raw" };
 
        printf("--- rnnoise start ---\n");
 
-       fin = fopen("airport_48k.raw", "r");
-       if (!fin) {
-               printf("failed to find airport_48k.raw\n");
-               exit(-1);
-       }
+       for (i = 0; i < MAX_CHANNELS; i++) {
+               fin = fopen(test_file[i], "r");
+               if (!fin) {
+                       printf("failed to find airport_48k.raw\n");
+                       exit(-1);
+               }
 
-       fout = fopen("rnnoise_out.raw", "wb");
-       if (!fout) {
-               printf("failed to open raw\n");
-               exit(-1);
-       }
+               fout = fopen(out_file[i], "wb");
+               if (!fout) {
+                       printf("failed to open raw\n");
+                       exit(-1);
+               }
 
-       ae = audio_effect_create(AUDIO_EFFECT_METHOD_NS_RNNOISE, 48000, 1, AUDIO_EFFECT_FORMAT_S16, framesize);
-       assert(ae);
+               ae = audio_effect_create(AUDIO_EFFECT_METHOD_NS_RNNOISE, 48000, channels[i], AUDIO_EFFECT_FORMAT_S16, framesize);
+               assert(ae);
 
-       framesize = audio_effect_get_process_framesize(ae);
-       assert(framesize == FIXED_FRAME_SIZE);
-       printf("frame size %zu\n", framesize);
+               framesize = audio_effect_get_process_framesize(ae);
+               assert(framesize == FIXED_FRAME_SIZE);
+               printf("frame size %zu\n", framesize);
 
-       while (!feof(fin)) {
-               if (fread(in, sizeof(short), framesize, fin) < 0)
-                       break;
+               while (!feof(fin)) {
+                       if (fread(in, sizeof(short) * channels[i], framesize, fin) < 0)
+                               break;
 
-               printf("#%d frame. ", i++);
+                       printf("#%d frame. ", n++);
 
-               if (audio_effect_process(ae, in, out) < 0) {
-                       printf("(failed!)\n");
-               } else {
-                       printf("(success!)\n");
-                       fwrite(out, sizeof(short), framesize, fout);
+                       if (audio_effect_process(ae, in, out) < 0) {
+                               printf("(failed!)\n");
+                       } else {
+                               printf("(success!)\n");
+                               fwrite(out, sizeof(short) * channels[i], framesize, fout);
+                       }
                }
-       }
 
-       audio_effect_destroy(ae);
+               audio_effect_destroy(ae);
 
-       fclose(fin);
-       fclose(fout);
+               fclose(fin);
+               fclose(fout);
+       }
 
-       printf("--- Hello test end ---\n");
+       printf("--- rnnoise test end ---\n");
 
        return 0;
 }