Add noise-suppression solution from SRID 23/295423/7
authorJaechul Lee <jcsing.lee@samsung.com>
Fri, 7 Jul 2023 02:30:16 +0000 (11:30 +0900)
committerJaechul Lee <jcsing.lee@samsung.com>
Mon, 10 Jul 2023 08:08:24 +0000 (17:08 +0900)
[Version] 0.0.5
[Issue Type] New feature

Change-Id: I86cadff67e20e08ae440ffdbf52cfc1fa9c4c861
Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
12 files changed:
README.md
include/audio_effect.h
include/audio_effect_log.h
meson.build
meson_options.txt
packaging/libaudio-effect.spec
src/audio_effect_interface.c
src/plugin_ns_versatile.c [new file with mode: 0644]
test/amplify_test.c
test/meson.build
test/ns_rnnoise_test.c
test/ns_versatile_test.c [new file with mode: 0644]

index d9344d1e973bdf03fa3d1cfb777487ab4ac7a6b1..c577979122b1e6f1dd1d0700c3bb9afb6ca4950f 100644 (file)
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@ Additional audio pre-process methods.
 
 ## How to build
  * local : meson build --reconfigure [-Dtestsuite=enabled]  && ninja -C build clean && ninja -C build/
-   e.g) meson build --reconfigure -Db_sanitize=address -Db_coverage=true -Dtestsuite=enabled -Damplify=enabled -Dspeex-agc=enabled -Dns-rnnoise=enabled -Daec-refcopy=enabled -Daec-speex=enabled -Daec-webrtc=enabled && ninja -C build clean && ninja -C build/
+   e.g) meson build --reconfigure -Db_sanitize=address -Db_coverage=true -Dtestsuite=enabled -Damplify=enabled -Dspeex-agc=enabled -Dns-rnnoise=enabled -Dns-versatile=enabled -Daec-refcopy=enabled -Daec-speex=enabled -Daec-webrtc=enabled && ninja -C build clean && ninja -C build/
  * GBS : gbs build -A aarch64 --include-all
 
 ## How to test
index d4ea45a43a07beb5f63884e0b3ae6cad35455084..61a65d421f0bfb9e2b185c631cb1bb608ac1d154 100644 (file)
@@ -29,6 +29,7 @@ typedef enum {
        /* Noise Suppression */
        AUDIO_EFFECT_METHOD_NS_PSE, /* SAIC NS solution */
        AUDIO_EFFECT_METHOD_NS_RNNOISE, /* RNNoise */
+       AUDIO_EFFECT_METHOD_NS_VERSATILE, /* SRID solution */
 
        /* Template */
        AUDIO_EFFECT_METHOD_AMPLIFY,
index 628140259de0adc715e5fee9bada4a2352ce4c54..18ad7230da165e548208ea0092ab716a802d2243 100644 (file)
 #undef LOG_TAG
 #endif
 #define LOG_TAG "AUDIO_EFFECT"
-#define LOG_ERROR(...)                 SLOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)
-#define LOG_WARN(...)                   SLOG(LOG_WARN, LOG_TAG, __VA_ARGS__)
-#define LOG_INFO(...)                   SLOG(LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define LOG_DEBUG(...)                 SLOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-#define LOG_VERBOSE(...)                 SLOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define LOG_ERROR(...)         SLOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#define LOG_WARN(...)          SLOG(LOG_WARN, LOG_TAG, __VA_ARGS__)
+#define LOG_INFO(...)          SLOG(LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define LOG_DEBUG(...)         SLOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define LOG_VERBOSE(...)       SLOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
 #else
 #include <stdio.h>
-#define LOG_ERROR(...)                 { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
-#define LOG_WARN(...)                   { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
-#define LOG_INFO(...)                   { fprintf(stdout, __VA_ARGS__); fprintf(stderr, "\n"); }
-#define LOG_DEBUG(...)                 { fprintf(stdout, __VA_ARGS__); fprintf(stderr, "\n"); }
-#define LOG_VERBOSE(...)                 { fprintf(stdout, __VA_ARGS__); fprintf(stderr, "\n"); }
+#define LOG_ERROR(...)         { printf(__VA_ARGS__); printf("\n"); }
+#define LOG_WARN(...)          { printf(__VA_ARGS__); printf("\n"); }
+#define LOG_INFO(...)          { printf(__VA_ARGS__); printf("\n"); }
+#define LOG_DEBUG(...)         { printf(__VA_ARGS__); printf("\n"); }
+#define LOG_VERBOSE(...)       { printf(__VA_ARGS__); printf("\n"); }
 #endif
 
 #endif
index cd3513de309a2de2f5e9c4ee2961c4d1bbb4dcca..6e09431f1fdea7d702bfcbf3dc9585dc68385cec 100644 (file)
@@ -48,6 +48,18 @@ shared_library('audio-effect-ns-rnnoise',
 )
 endif
 
+# --- srid plugin ---
+if get_option('ns-versatile').enabled()
+shared_library('audio-effect-ns-versatile',
+  sources: [ 'src/plugin_ns_versatile.c' ],
+  dependencies: [ dependency('noise-suppression'), platform_dep ],
+  include_directories: audio_effect_include_dir,
+  link_with: [audio_effect_shared],
+  install: true,
+  install_dir: audio_effect_plugins_install_dir,
+)
+endif
+
 # --- aec-refcopy plugin ---
 if get_option('aec-refcopy').enabled()
 shared_library('audio-effect-aec-refcopy',
index 8dcc1acaf5099cf2ab49bc828bf0d5a94f0e84c6..322933f533b6b4093c653303819f3013bdbe06e1 100644 (file)
@@ -2,6 +2,7 @@ option('version', type: 'string', value : '0.0.1', description: 'Project version
 option('tizen', type : 'feature', value : 'disabled', description : 'Tizen feature enable')
 option('testsuite', type : 'feature', value : 'disabled', description : 'Testsuite')
 option('ns-rnnoise', type : 'feature', value : 'disabled', description : 'rnnoise noise suppression')
+option('ns-versatile', type : 'feature', value : 'disabled', description : 'versatile noise suppression')
 option('aec-refcopy', type : 'feature', value : 'disabled', description : 'reference copy')
 option('aec-speex', type : 'feature', value : 'disabled', description : 'speex aec')
 option('aec-webrtc', type : 'feature', value : 'disabled', description : 'webrtc aec')
index fbe319c658755a5299b4fc565b4c2584c7ea5a80..d6d1cca49113f5bbc7b4f98e1e77f22bb6c1e4d8 100644 (file)
@@ -1,15 +1,18 @@
 Name:       libaudio-effect
 Summary:    audio effect library
-Version:    0.0.4
+Version:    0.0.5
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
 
+BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(speexdsp)
+BuildRequires:  pkgconfig(noise-suppression)
+%if "%{tizen_profile_name}" != "tv"
 BuildRequires:  pkgconfig(rnnoise)
 BuildRequires:  pkgconfig(webrtc-audio-processing)
-BuildRequires:  pkgconfig(dlog)
+%endif
 BuildRequires:  meson >= 0.53.0
 
 %description
@@ -27,7 +30,14 @@ MMSound development package for audio effect
 %setup -q
 
 %build
-%{meson} -Dtizen=enabled -Dns-rnnoise=enabled -Daec-refcopy=enabled -Daec-speex=enabled -Daec-webrtc=enabled
+%{meson} -Dtizen=enabled \
+%if "%{tizen_profile_name}" != "tv"
+       -Dns-rnnoise=enabled \
+       -Daec-webrtc=enabled \
+%endif
+       -Daec-refcopy=enabled \
+       -Daec-speex=enabled \
+       -Dns-versatile=enabled
 
 %{meson_build}
 
index 21e1e285b17e586dfc86c5f22209109337576975..d5512e670e7684173bfcff2e3826a8e94208272a 100644 (file)
@@ -24,6 +24,7 @@
  * ISO C forbids conversion of object pointer to function pointer type
  * when I convert void pointer to function pointer */
 #include <stdint.h>
+#include <string.h>
 
 #include <audio_effect_interface.h>
 #include <audio_effect_util.h>
@@ -35,6 +36,7 @@ static const char *effect_path_list[] = {
        [AUDIO_EFFECT_METHOD_AEC_REFCOPY] = DL_PLUGIN_PATH "libaudio-effect-aec-refcopy.so",
        [AUDIO_EFFECT_METHOD_NS_PSE] = DL_PLUGIN_PATH "libaudio-effect-ns-pse.so",
        [AUDIO_EFFECT_METHOD_NS_RNNOISE] = DL_PLUGIN_PATH "libaudio-effect-ns-rnnoise.so",
+       [AUDIO_EFFECT_METHOD_NS_VERSATILE] = DL_PLUGIN_PATH "libaudio-effect-ns-versatile.so",
        [AUDIO_EFFECT_METHOD_AMPLIFY] = DL_PLUGIN_PATH "libaudio-effect-amplify.so",
        [AUDIO_EFFECT_METHOD_AGC_SPEEX] = DL_PLUGIN_PATH "libaudio-effect-agc-speex.so",
 };
@@ -67,7 +69,7 @@ audio_effect_interface_s *audio_effect_interface_new(audio_effect_method_e metho
        if (!plugin_list[method].plugin_info && plugin_list[method].refcnt == 0) {
                handle = dlopen(effect_path_list[method], RTLD_LAZY);
                if (!handle) {
-                       LOG_INFO("Failed to open handle. path(%s) dlerror(%s)", get_plugin_name(effect_path_list[method]), dlerror());
+                       LOG_ERROR("Failed to open handle. path(%s) dlerror(%s)", get_plugin_name(effect_path_list[method]), dlerror());
                        return NULL;
                }
        }
diff --git a/src/plugin_ns_versatile.c b/src/plugin_ns_versatile.c
new file mode 100644 (file)
index 0000000..98d176a
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+* Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <audio_effect_interface.h>
+#include <audio_effect_log.h>
+
+#include <noise-suppression.h>
+
+#define MAX_DELAY_MSEC 20
+
+struct userdata {
+       noise_suppression_h handle;
+       float *buffer;
+       size_t frames;
+};
+
+void init_noise_suppression_versatile(void) __attribute__ ((constructor));
+void fini_noise_suppression_versatile(void) __attribute__ ((destructor));
+static audio_effect_plugin_info_s noise_suppression_versatile;
+
+void *noise_suppression_versatile_create(int rate, int channels, audio_effect_format_e format, size_t frames)
+{
+       struct userdata *u;
+       noise_suppression_h handle;
+       unsigned int frame_size = frames;
+
+       if (rate != 48000 && rate != 16000) {
+               LOG_ERROR("Not support rate %d", rate);
+               return NULL;
+       }
+
+       if (noise_suppression_initialize(NULL, rate, MAX_DELAY_MSEC, &handle, &frame_size) != NOISE_SUPPRESSION_ERROR_NONE) {
+               LOG_ERROR("Failed to init noise-suppression versatile");
+               return NULL;
+       }
+
+       if ((size_t)frame_size != frames) {
+               LOG_INFO("frames_size(%d) is not same with frame(%zu)", frame_size, frames);
+               noise_suppression_versatile.constraint.frames = frame_size;
+       }
+
+       u = (struct userdata *)malloc(sizeof(struct userdata));
+       u->handle = handle;
+       u->frames = frames;
+       u->buffer = (float *)malloc(sizeof(float) * frames);
+
+       noise_suppression_set_level(u->handle, NOISE_SUPPRESSION_LEVEL_MID);
+
+       LOG_INFO("plugin noise-suppression versatile init. rate(%d), channels(%d), format(%d), frames(%zu), frame_size(%d)",
+                               rate, channels, format, frames, frame_size);
+
+       return u;
+}
+
+int noise_suppression_versatile_process(void *priv, char *in, char *out)
+{
+       struct userdata *u = (struct userdata *)priv;
+       int16_t *rec = (int16_t *)in;
+       int16_t *result = (int16_t *)out;
+       int i;
+
+       assert(u);
+       assert(u->handle);
+       assert(u->buffer);
+       assert(rec);
+       assert(result);
+
+       for (i = 0; i < u->frames; i++)
+               u->buffer[i] = rec[i];
+
+       if (NOISE_SUPPRESSION_ERROR_NONE !=
+               noise_suppression_process_audio(u->handle, u->buffer, u->buffer)) {
+               LOG_ERROR("Failed to process noise suppression");
+               return -1;
+       }
+
+       for (i = 0; i < u->frames; i++)
+               result[i] = u->buffer[i];
+
+       return 0;
+}
+
+void noise_suppression_versatile_destroy(void *priv)
+{
+       struct userdata *u = (struct userdata *)priv;
+
+       if (u->buffer)
+               free(u->buffer);
+
+       if (u->handle)
+               noise_suppression_deinitialize(u->handle);
+
+       free(u);
+}
+
+static audio_effect_plugin_info_s noise_suppression_versatile = {
+       .name = "noise-suppression-versatile",
+       .interface = {
+               .method = AUDIO_EFFECT_METHOD_NS_VERSATILE,
+               .create = noise_suppression_versatile_create,
+               .process = noise_suppression_versatile_process,
+               .destroy = noise_suppression_versatile_destroy,
+       },
+       .constraint = {
+               .frames = 480,
+               .min_rate = 16000,
+               .max_rate = 48000,
+               .min_channels = 1,
+               .max_channels = 1,
+               .min_format = AUDIO_EFFECT_FORMAT_S16,
+               .max_format = AUDIO_EFFECT_FORMAT_S16,
+       },
+};
+
+void init_noise_suppression_versatile(void)
+{
+       audio_effect_register_module(&noise_suppression_versatile);
+}
+
+void fini_noise_suppression_versatile(void)
+{
+       audio_effect_unregister_module(&noise_suppression_versatile);
+}
+
index 74e4b81ec04224bd5520896eb552091e56690c81..b92ca860a58f972c4b8a7ea0175b47ea44699feb 100644 (file)
@@ -17,7 +17,7 @@ int main(void)
 
        int i=0;
 
-       printf("--- Hello test start ---\n");
+       printf("--- amplify start ---\n");
 
        fin = fopen("obama.raw", "r");
        if (!fin) {
@@ -26,14 +26,14 @@ int main(void)
        }
 
        fout = fopen("amplify_out.raw", "wb");
-       if (!fin) {
+       if (!fout) {
                printf("failed to open raw\n");
                exit(-1);
        }
 
        ae = audio_effect_create(AUDIO_EFFECT_METHOD_AMPLIFY, 16000, 1, AUDIO_EFFECT_FORMAT_S16, FRAME_SIZE);
        while (!feof(fin)) {
-               printf("#%d frame. \n", i++);
+               printf("#%d frame. ", i++);
                ret = fread(in, FRAME_SIZE*sizeof(short), 1, fin);
                if (audio_effect_process(ae, in, out) < 0) {
                        printf("(failed!)\n");
index 49a0bc91f49f30c4ae2406f260b47c2cc8eab763..a1da4b6f7ec2b10cb44d1d0dc5024b4cdc8a4dc5 100644 (file)
@@ -10,6 +10,10 @@ if get_option('ns-rnnoise').enabled()
   test_list += [[ 'ns_rnnoise_test', 'ns_rnnoise_test.c' ]]
 endif
 
+if get_option('ns-versatile').enabled()
+  test_list += [[ 'ns_versatile_test', 'ns_versatile_test.c' ]]
+endif
+
 if get_option('aec-refcopy').enabled()
   test_list += [[ 'aec_refcopy_test', 'aec_refcopy_test.c' ]]
 endif
index 06cea22deaa4b39647f043bed5ec675ad6858dc8..fdb1419d8ca051c13eaa85b03b0c29260e4bccab 100644 (file)
@@ -4,7 +4,7 @@
 
 #include "audio_effect.h"
 
-#define FRAME_SIZE 480
+#define FRAME_SIZE (480)
 
 int main(void)
 {
@@ -13,7 +13,6 @@ int main(void)
        FILE *fout;
        short in[FRAME_SIZE];
        short out[FRAME_SIZE];
-       size_t ret;
        size_t framesize = FRAME_SIZE;
 
        int i=0;
@@ -27,7 +26,7 @@ int main(void)
        }
 
        fout = fopen("rnnoise_out.raw", "wb");
-       if (!fin) {
+       if (!fout) {
                printf("failed to open raw\n");
                exit(-1);
        }
@@ -39,21 +38,24 @@ int main(void)
        printf("frame size %zu\n", framesize);
 
        while (!feof(fin)) {
-               printf("#%d frame. \n", i++);
-               ret = fread(in, sizeof(in), 1, fin);
+               if (fread(in, sizeof(short), FRAME_SIZE, fin) < 0)
+                       break;
+
+               printf("#%d frame. ", i++);
+
                if (audio_effect_process(ae, in, out) < 0) {
                        printf("(failed!)\n");
                } else {
-                       printf("(success!), ret(%zu)\n", ret);
-                       fwrite(out, framesize*sizeof(short), 1, fout);
+                       printf("(success!)\n");
+                       fwrite(out, sizeof(short), FRAME_SIZE, fout);
                }
        }
 
+       audio_effect_destroy(ae);
+
        fclose(fin);
        fclose(fout);
 
-       audio_effect_destroy(ae);
-
        printf("--- Hello test end ---\n");
 
        return 0;
diff --git a/test/ns_versatile_test.c b/test/ns_versatile_test.c
new file mode 100644 (file)
index 0000000..1dbe807
--- /dev/null
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "audio_effect.h"
+
+#define FRAME_SIZE (1024) /* 48KHz:960, 16KHz:320 */
+
+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, n = 0;
+
+       const char *source_file[] = { "airport_48k.raw", "obama.raw" };
+       const char *output_file[] = { "versatile_out_48k.raw", "versatile_out_16k.raw" };
+
+       int loop = sizeof(source_file) / sizeof(char *);
+       int rate[] = { 48000, 16000 };
+
+       for (i = 0; i < loop; i++) {
+               printf("--- versatile start ---\n");
+               printf("source file : %s\n", source_file[i]);
+               printf("output file : %s\n", output_file[i]);
+               printf("samplerate : %d\n", rate[i]);
+
+               fin = fopen(source_file[i], "r");
+               if (!fin) {
+                       printf("failed to find airport_48k.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_NS_VERSATILE, rate[i], 1, AUDIO_EFFECT_FORMAT_S16, framesize);
+               assert(ae);
+
+               framesize = audio_effect_get_process_framesize(ae);
+               printf("setting frame size %zu\n", framesize);
+
+               while (!feof(fin)) {
+                       if (fread(in, sizeof(short), framesize, fin) < 0)
+                               break;
+
+                       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);
+                       }
+               }
+
+               audio_effect_destroy(ae);
+
+               fclose(fin);
+               fclose(fout);
+
+       }
+
+       printf("--- test end ---\n");
+
+       return 0;
+}