#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;
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;
}
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 = {
.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,
},
#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)
{
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;
}