]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
NR4: libspecbleach based noise reduction
authorRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Fri, 23 Dec 2022 11:27:17 +0000 (16:57 +0530)
committerRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Fri, 23 Dec 2022 11:51:04 +0000 (17:21 +0530)
Makefile
dsp_menu.c
noise_menu.c
receiver.c
receiver.h
vfo.c
vfo.h

index f1ccaec642934bf3a09e137099bd6e65d00164a5..09cda291873b9ea05c0f3e69a1155d49b3a24a0b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ ifeq ($(UNAME_S), Linux)
 RT_OPTION=-lrt
 endif
 
-LIBS=$(RT_OPTION) -lm -lwdsp -lrnnoise -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(GTKLIBS) $(GPIO_LIBS) $(MIDI_LIBS)
+LIBS=$(RT_OPTION) -lm -lwdsp -lrnnoise -lspecbleach -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(GTKLIBS) $(GPIO_LIBS) $(MIDI_LIBS)
 INCLUDES=$(GTKINCLUDES)
 
 COMPILE=$(CC) $(CFLAGS) $(OPTIONS) $(INCLUDES)
index c02b631e7ff1e4927286fe2ca689186241b9b3e0..26112df3fe9ded6b7b902f509b294a2c926f86b4 100644 (file)
@@ -63,6 +63,36 @@ static void agc_hang_threshold_value_changed_cb(GtkWidget *widget, gpointer data
   }
 }
 
+static void nr4_reduction_amount_scale_changed_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nr4_reduction_amount=(int)gtk_range_get_value(GTK_RANGE(widget));
+
+  SetRXASBNRreductionAmount(active_receiver->id, (int)active_receiver->nr4_reduction_amount);
+}
+
+static void nr4_smoothing_factor_scale_changed_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nr4_smoothing_factor=(int)gtk_range_get_value(GTK_RANGE(widget));
+
+  SetRXASBNRsmoothingFactor(active_receiver->id, (int)active_receiver->nr4_smoothing_factor);
+}
+
+static void nr4_whitening_factor_scale_changed_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nr4_whitening_factor = (int)gtk_range_get_value(GTK_RANGE(widget));
+
+  SetRXASBNRwhiteningFactor(active_receiver->id, (int)active_receiver->nr4_whitening_factor);
+}
+
+static void nr4_noise_rescale_scale_changed_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nr4_noise_rescale=(int)gtk_range_get_value(GTK_RANGE(widget));
+
+  SetRXASBNRnoiseRescale(active_receiver->id, (int)active_receiver->nr4_noise_rescale);
+}
+
+static void nr4_post_filter_threshold_scale_changed_cb(GtkWidget *widget, gpointer data) {
+  active_receiver->nr4_post_filter_threshold=(int)gtk_range_get_value(GTK_RANGE(widget));
+
+  SetRXASBNRpostFilterThreshold(active_receiver->id, (int)active_receiver->nr4_post_filter_threshold);
+}
+
 static void pre_post_agc_cb(GtkToggleButton *widget, gpointer data) {
   if(gtk_toggle_button_get_active(widget)) {
     active_receiver->nr_agc=GPOINTER_TO_UINT(data);
@@ -125,6 +155,7 @@ void dsp_menu(GtkWidget *parent) {
   gtk_label_set_markup(GTK_LABEL(agc_hang_threshold_label), "<b>AGC Hang Threshold</b>");
   gtk_widget_show(agc_hang_threshold_label);
   gtk_grid_attach(GTK_GRID(grid),agc_hang_threshold_label,0,1,1,1);
+
   GtkWidget *agc_hang_threshold_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0.0, 100.0, 1.0);
   gtk_range_set_increments (GTK_RANGE(agc_hang_threshold_scale),1.0,1.0);
   gtk_range_set_value (GTK_RANGE(agc_hang_threshold_scale),active_receiver->agc_hang_threshold);
@@ -199,6 +230,66 @@ void dsp_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),ae_b,0,5,1,1);
   g_signal_connect(ae_b,"toggled",G_CALLBACK(ae_cb),NULL);
 
+  GtkWidget *nr4_reduction_amount_label=gtk_label_new("NR4 Reduction Amount");
+  gtk_label_set_markup(GTK_LABEL(nr4_reduction_amount_label), "<b>NR4 Reduction Amount</b>");
+  gtk_widget_show(nr4_reduction_amount_label);
+  gtk_grid_attach(GTK_GRID(grid),nr4_reduction_amount_label,0,6,1,1);
+
+  GtkWidget *nr4_reduction_amount_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0.0, 20.0, 1.0);
+  gtk_range_set_increments (GTK_RANGE(nr4_reduction_amount_scale),1.0,1.0);
+  gtk_range_set_value (GTK_RANGE(nr4_reduction_amount_scale),active_receiver->nr4_reduction_amount);
+  gtk_widget_show(nr4_reduction_amount_scale);
+  gtk_grid_attach(GTK_GRID(grid),nr4_reduction_amount_scale,1,6,2,1);
+  g_signal_connect(G_OBJECT(nr4_reduction_amount_scale),"value_changed",G_CALLBACK(nr4_reduction_amount_scale_changed_cb),NULL);
+
+  GtkWidget *nr4_smoothing_factor_label=gtk_label_new("NR4 Smoothing factor");
+  gtk_label_set_markup(GTK_LABEL(nr4_smoothing_factor_label), "<b>NR4 Smoothing factor</b>");
+  gtk_widget_show(nr4_smoothing_factor_label);
+  gtk_grid_attach(GTK_GRID(grid),nr4_smoothing_factor_label,0,7,1,1);
+
+  GtkWidget *nr4_smoothing_factor_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0.0, 100.0, 1.0);
+  gtk_range_set_increments (GTK_RANGE(nr4_smoothing_factor_scale),1.0,1.0);
+  gtk_range_set_value (GTK_RANGE(nr4_smoothing_factor_scale),active_receiver->nr4_smoothing_factor);
+  gtk_widget_show(nr4_smoothing_factor_scale);
+  gtk_grid_attach(GTK_GRID(grid),nr4_smoothing_factor_scale,1,7,2,1);
+  g_signal_connect(G_OBJECT(nr4_smoothing_factor_scale),"value_changed",G_CALLBACK(nr4_smoothing_factor_scale_changed_cb),NULL);
+
+  GtkWidget *nr4_whitening_factor_label=gtk_label_new("NR4 Whitening factor");
+  gtk_label_set_markup(GTK_LABEL(nr4_whitening_factor_label), "<b>NR4 Whitening factor</b>");
+  gtk_widget_show(nr4_whitening_factor_label);
+  gtk_grid_attach(GTK_GRID(grid),nr4_whitening_factor_label,0,8,1,1);
+
+  GtkWidget *nr4_whitening_factor_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0.0, 100.0, 1.0);
+  gtk_range_set_increments (GTK_RANGE(nr4_whitening_factor_scale),1.0,1.0);
+  gtk_range_set_value (GTK_RANGE(nr4_whitening_factor_scale),active_receiver->nr4_whitening_factor);
+  gtk_widget_show(nr4_whitening_factor_scale);
+  gtk_grid_attach(GTK_GRID(grid),nr4_whitening_factor_scale,1,8,2,1);
+  g_signal_connect(G_OBJECT(nr4_whitening_factor_scale),"value_changed",G_CALLBACK(nr4_whitening_factor_scale_changed_cb),NULL);
+
+  GtkWidget *nr4_noise_rescale_label=gtk_label_new("NR4 noise Rescale");
+  gtk_label_set_markup(GTK_LABEL(nr4_noise_rescale_label), "<b>NR4 noise rescale</b>");
+  gtk_widget_show(nr4_noise_rescale_label);
+  gtk_grid_attach(GTK_GRID(grid),nr4_noise_rescale_label,0,9,1,1);
+
+  GtkWidget *nr4_noise_rescale_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0.0, 12.0, 1.0);
+  gtk_range_set_increments (GTK_RANGE(nr4_noise_rescale_scale),1.0,1.0);
+  gtk_range_set_value (GTK_RANGE(nr4_noise_rescale_scale),active_receiver->nr4_noise_rescale);
+  gtk_widget_show(nr4_noise_rescale_scale);
+  gtk_grid_attach(GTK_GRID(grid),nr4_noise_rescale_scale,1,9,2,1);
+  g_signal_connect(G_OBJECT(nr4_noise_rescale_scale),"value_changed",G_CALLBACK(nr4_noise_rescale_scale_changed_cb),NULL);
+
+  GtkWidget *nr4_post_filter_threshold_label=gtk_label_new("NR4 post filter threshold");
+  gtk_label_set_markup(GTK_LABEL(nr4_post_filter_threshold_label), "<b>NR4 post filter threshold</b>");
+  gtk_widget_show(nr4_post_filter_threshold_label);
+  gtk_grid_attach(GTK_GRID(grid),nr4_post_filter_threshold_label,0,10,1,1);
+
+  GtkWidget *nr4_post_filter_threshold_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, -10.0, 10.0, 1.0);
+  gtk_range_set_increments (GTK_RANGE(nr4_post_filter_threshold_scale),1.0,1.0);
+  gtk_range_set_value (GTK_RANGE(nr4_post_filter_threshold_scale),active_receiver->nr4_post_filter_threshold);
+  gtk_widget_show(nr4_post_filter_threshold_scale);
+  gtk_grid_attach(GTK_GRID(grid),nr4_post_filter_threshold_scale,1,10,2,1);
+  g_signal_connect(G_OBJECT(nr4_post_filter_threshold_scale),"value_changed",G_CALLBACK(nr4_post_filter_threshold_scale_changed_cb),NULL);
+
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index 05c4d40cf039ad309f09b87df64ef9d7ca0ada5d..deafed7d284753eee76457f16c84a87272514011 100644 (file)
@@ -86,6 +86,7 @@ void set_noise() {
   SetRXAANRRun(active_receiver->id, active_receiver->nr);
   SetRXAEMNRRun(active_receiver->id, active_receiver->nr2);
   SetRXARNNRRun(active_receiver->id, active_receiver->nr3);
+  SetRXASBNRRun(active_receiver->id, active_receiver->nr4);
   SetRXAANFRun(active_receiver->id, active_receiver->anf);
   SetRXASNBARun(active_receiver->id, active_receiver->snb);
   g_idle_add(ext_vfo_update,NULL);
@@ -128,9 +129,11 @@ static void nr_none_cb(GtkToggleButton *widget, gpointer data) {
     active_receiver->nr=0;
     active_receiver->nr2=0;
     active_receiver->nr3=0;
+    active_receiver->nr4=0;
     mode_settings[vfo[active_receiver->id].mode].nr=0;
     mode_settings[vfo[active_receiver->id].mode].nr2=0;
     mode_settings[vfo[active_receiver->id].mode].nr3=0;
+    mode_settings[vfo[active_receiver->id].mode].nr4=0;
     update_noise();
   }
 }
@@ -140,6 +143,7 @@ static void nr_cb(GtkToggleButton *widget, gpointer data) {
     active_receiver->nr=1;
     active_receiver->nr2=0;
     active_receiver->nr3=0;
+    active_receiver->nr4=0;
     mode_settings[vfo[active_receiver->id].mode].nr=1;
     mode_settings[vfo[active_receiver->id].mode].nr2=0;
     mode_settings[vfo[active_receiver->id].mode].nr3=0;
@@ -162,9 +166,11 @@ static void nr2_cb(GtkToggleButton *widget, gpointer data) {
     active_receiver->nr=0;
     active_receiver->nr2=1;
     active_receiver->nr3=0;
+    active_receiver->nr4=0;
     mode_settings[vfo[active_receiver->id].mode].nr=0;
     mode_settings[vfo[active_receiver->id].mode].nr2=1;
     mode_settings[vfo[active_receiver->id].mode].nr3=0;
+    mode_settings[vfo[active_receiver->id].mode].nr4=0;
     update_noise();
   }
 }
@@ -174,9 +180,25 @@ static void nr3_cb(GtkToggleButton *widget, gpointer data) {
     active_receiver->nr=0;
     active_receiver->nr2=0;
     active_receiver->nr3=1;
+    active_receiver->nr4=0;
     mode_settings[vfo[active_receiver->id].mode].nr=0;
     mode_settings[vfo[active_receiver->id].mode].nr2=0;
     mode_settings[vfo[active_receiver->id].mode].nr3=1;
+    mode_settings[vfo[active_receiver->id].mode].nr4=0;
+    update_noise();
+  }
+}
+
+static void nr4_cb(GtkToggleButton *widget, gpointer data) {
+  if(gtk_toggle_button_get_active(widget)) {
+    active_receiver->nr=0;
+    active_receiver->nr2=0;
+    active_receiver->nr3=0;
+    active_receiver->nr4=1;
+    mode_settings[vfo[active_receiver->id].mode].nr=0;
+    mode_settings[vfo[active_receiver->id].mode].nr2=0;
+    mode_settings[vfo[active_receiver->id].mode].nr3=0;
+    mode_settings[vfo[active_receiver->id].mode].nr4=1;
     update_noise();
   }
 }
@@ -313,6 +335,14 @@ void noise_menu(GtkWidget *parent) {
   gtk_grid_attach(GTK_GRID(grid),b_nr3,col,row,1,1);
   g_signal_connect(b_nr3,"toggled",G_CALLBACK(nr3_cb),NULL);
 
+  row++;
+
+  GtkWidget *b_nr4=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(b_nr),"NR4");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_nr4), active_receiver->nr4);
+  gtk_widget_show(b_nr4);
+  gtk_grid_attach(GTK_GRID(grid),b_nr4,col,row,1,1);
+  g_signal_connect(b_nr4,"toggled",G_CALLBACK(nr4_cb),NULL);
+
   gtk_container_add(GTK_CONTAINER(content),grid);
 
   sub_menu=dialog;
index c8b56b564d4c8a9edaa0e9bc368f9f79a18c6979..29bf9ba61b86dba939b483db1f947afda758616f 100644 (file)
@@ -298,6 +298,10 @@ void receiver_save_state(RECEIVER *rx) {
     sprintf(value,"%d",rx->nr3);
     setProperty(name,value);
 
+    sprintf(name,"receiver.%d.nr4",rx->id);
+    sprintf(value,"%d",rx->nr4);
+    setProperty(name,value);
+
     sprintf(name,"receiver.%d.anf",rx->id);
     sprintf(value,"%d",rx->anf);
     setProperty(name,value);
@@ -519,6 +523,10 @@ g_print("%s: id=%d\n",__FUNCTION__,rx->id);
     value=getProperty(name);
     if(value) rx->nr3=atoi(value);
 
+    sprintf(name,"receiver.%d.nr4",rx->id);
+    value=getProperty(name);
+    if(value) rx->nr4=atoi(value);
+
     sprintf(name,"receiver.%d.anf",rx->id);
     value=getProperty(name);
     if(value) rx->anf=atoi(value);
@@ -933,6 +941,7 @@ g_print("%s: id=%d buffer_size=%d\n",__FUNCTION__,id,buffer_size);
   rx->nr=0;
   rx->nr2=0;
   rx->nr3=0;
+  rx->nr4=0;
   rx->anf=0;
   rx->snb=0;
 
@@ -941,6 +950,12 @@ g_print("%s: id=%d buffer_size=%d\n",__FUNCTION__,id,buffer_size);
   rx->nr2_npe_method=0;
   rx->nr2_ae=1;
 
+  rx->nr4_reduction_amount = 10.F;
+  rx->nr4_smoothing_factor = 0.F;
+  rx->nr4_whitening_factor = 0.F;
+  rx->nr4_noise_rescale = 2.F;
+  rx->nr4_post_filter_threshold = -10.F;
+
   rx->nb_lag_time = 0.0001;
   rx->nb_lead_time = 0.0001;
   rx->nb_transition_time = 0.0001;
@@ -1063,6 +1078,7 @@ g_print("%s: id=%d default adc=%d\n",__FUNCTION__,rx->id, rx->adc);
   rx->nr=0;
   rx->nr2=0;
   rx->nr3=0;
+  rx->nr4=0;
   rx->anf=0;
   rx->snb=0;
 
@@ -1071,6 +1087,12 @@ g_print("%s: id=%d default adc=%d\n",__FUNCTION__,rx->id, rx->adc);
   rx->nr2_npe_method=0;
   rx->nr2_ae=1;
 
+  rx->nr4_reduction_amount = 10.F;
+  rx->nr4_smoothing_factor = 0.F;
+  rx->nr4_whitening_factor = 0.F;
+  rx->nr4_noise_rescale = 2.F;
+  rx->nr4_post_filter_threshold = -10.F;
+
   rx->nb_lag_time = 0.0001;
   rx->nb_lead_time = 0.0001;
   rx->nb_transition_time = 0.0001;
@@ -1177,6 +1199,16 @@ g_print("%s: OpenChannel id=%d buffer_size=%d fft_size=%d sample_rate=%d\n",
 
   SetRXARNNRRun(rx->id, rx->nr3);
 
+  // nr4
+  SetRXASBNRreductionAmount(rx->id, rx->nr4_reduction_amount);
+  SetRXASBNRsmoothingFactor(rx->id, rx->nr4_smoothing_factor);
+  SetRXASBNRwhiteningFactor(rx->id, rx->nr4_whitening_factor);
+  SetRXASBNRnoiseRescale(rx->id, rx->nr4_noise_rescale);
+  SetRXASBNRpostFilterThreshold(rx->id, rx->nr4_post_filter_threshold);
+
+  SetRXASBNRRun(rx->id, rx->nr4);
+
+
   SetEXTANBRun(rx->id, rx->nb);
   SetEXTNOBRun(rx->id, rx->nb2);
 
index 6de1a1a563b7394b3bd96b4c234507d2045c60f8..0749ac9fae7998edc819f3469d9e1ec1f79235bc 100644 (file)
@@ -82,6 +82,7 @@ typedef struct _receiver {
   gint nr;
   gint nr2;
   gint nr3;
+  gint nr4;
   gint anf;
   gint snb;
 
@@ -90,6 +91,12 @@ typedef struct _receiver {
   int nr2_npe_method;
   int nr2_ae;
 
+  float nr4_reduction_amount;
+  float nr4_smoothing_factor;
+  float nr4_whitening_factor;
+  float nr4_noise_rescale;
+  float nr4_post_filter_threshold;
+
   double nb_lag_time;
   double nb_lead_time;
   double nb_transition_time;
diff --git a/vfo.c b/vfo.c
index 59ce9f907b4e7ccdd418517f7bc2cfbd12265f14..713e86dd37c6f5e240a56e4671301aeadc825c96 100644 (file)
--- a/vfo.c
+++ b/vfo.c
@@ -98,6 +98,10 @@ void modesettings_save_state() {
     sprintf(value,"%d", mode_settings[i].nr3);
     setProperty(name,value);
 
+    sprintf(name,"modeset.%d.nr4", i);
+    sprintf(value,"%d", mode_settings[i].nr4);
+    setProperty(name,value);
+
     sprintf(name,"modeset.%d.nb", i);
     sprintf(value,"%d", mode_settings[i].nb);
     setProperty(name,value);
@@ -125,6 +129,7 @@ void modesettings_restore_state() {
     mode_settings[i].nr=0;
     mode_settings[i].nr2=0;
     mode_settings[i].nr3=0;
+    mode_settings[i].nr4=0;
     mode_settings[i].nb=0;
     mode_settings[i].nb2=0;
     mode_settings[i].anf=0;
@@ -145,6 +150,10 @@ void modesettings_restore_state() {
     value=getProperty(name);
     if(value) mode_settings[i].nr3=atoi(value);
 
+    sprintf(name,"modeset.%d.nr4",i);
+    value=getProperty(name);
+    if(value) mode_settings[i].nr4=atoi(value);
+
     value=getProperty(name);
     if(value) mode_settings[i].nb=atoi(value);
     sprintf(name,"modeset.%d.nb2",i);
@@ -411,6 +420,7 @@ void vfo_mode_changed(int m) {
   active_receiver->nr =mode_settings[m].nr;
   active_receiver->nr2=mode_settings[m].nr2;
   active_receiver->nr3=mode_settings[m].nr3;
+  active_receiver->nr4=mode_settings[m].nr4;
   active_receiver->nb =mode_settings[m].nb;
   active_receiver->nb2=mode_settings[m].nb2;
   active_receiver->anf=mode_settings[m].anf;
@@ -1205,7 +1215,7 @@ void vfo_update() {
           cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
           cairo_show_text(cr, "NR");
         }
-        // XXX need to have a button for NR3
+        // XXX need to have a button for NR3 and NR4
 
         cairo_move_to(cr, 70, 20);
         if(active_receiver->anf) {
diff --git a/vfo.h b/vfo.h
index 3fef3e1acd58c3f9735c547a3c7404d35e2b5434..ede8fd59111b91fe3ff92c4d80565c9f441e8d07 100644 (file)
--- a/vfo.h
+++ b/vfo.h
@@ -61,6 +61,7 @@ struct _mode_settings {
   int nr;
   int nr2;
   int nr3;
+  int nr4;
   int anf;
   int snb;
 };