From 56c0d87bbf7b3f1869386648592263f7fde26ae6 Mon Sep 17 00:00:00 2001 From: c vw Date: Mon, 16 Dec 2019 15:38:39 +0100 Subject: [PATCH] small fixes --- audio.c | 32 +++++++++++++++++++++++++++----- ext.c | 5 +++++ ext.h | 1 + midi3.c | 1 + portaudio.c | 36 +++++++++++++++++++++++++++++++----- receiver.c | 25 +++++++++++++------------ transmitter.c | 2 ++ vfo.c | 3 +-- 8 files changed, 81 insertions(+), 24 deletions(-) diff --git a/audio.c b/audio.c index a55aad1..3ea1be7 100644 --- a/audio.c +++ b/audio.c @@ -282,6 +282,7 @@ g_print("audio_close_output: rx=%d handle=%p buffer=%p\n",rx->id,rx->playback_ha } void audio_close_input() { + void *p; g_print("audio_close_input\n"); running=FALSE; if(mic_read_thread_id!=NULL) { @@ -299,9 +300,18 @@ g_print("audio_close_input: free mic buffer\n"); g_free(mic_buffer); mic_buffer=NULL; } + // + // We do not want to do a mutex lock/unlock for every single mic sample + // accessed. Since only the ring buffer is maintained by the functions + // audio_get_next_mic_sample() and in the "mic read thread", + // it is more than enough to wait 2 msec after setting mic_ring_buffer to NULL + // before actually releasing the storage. + // if (mic_ring_buffer != NULL) { - free(mic_ring_buffer); + p=mic_ring_buffer; mic_ring_buffer=NULL; + usleep(2); + g_free(p); } } @@ -321,6 +331,7 @@ int cw_audio_write(float sample){ RECEIVER *rx = active_receiver; + g_mutex_lock(&rx->local_audio_mutex); if(rx->playback_handle!=NULL && rx->local_audio_buffer!=NULL) { switch(rx->local_audio_format) { @@ -360,6 +371,7 @@ g_print("audio delay=%ld trim=%ld\n",delay,trim); if(rc==-EPIPE) { if ((rc = snd_pcm_prepare (rx->playback_handle)) < 0) { g_print("audio_write: cannot prepare audio interface for use %ld (%s)\n", rc, snd_strerror (rc)); + g_mutex_unlock(&rx->local_audio_mutex); return rc; } else { // ignore short write @@ -371,6 +383,7 @@ g_print("audio delay=%ld trim=%ld\n",delay,trim); rx->local_audio_buffer_offset=0; } } + g_mutex_unlock(&rx->local_audio_mutex); return 0; } @@ -388,8 +401,6 @@ int audio_write(RECEIVER *rx,float left_sample,float right_sample) { gint32 *long_buffer; gint16 *short_buffer; - g_mutex_lock(&rx->local_audio_mutex); - if(can_transmit) { mode=transmitter->mode; } @@ -404,10 +415,12 @@ int audio_write(RECEIVER *rx,float left_sample,float right_sample) { // if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) { - g_mutex_unlock(&rx->local_audio_mutex); return 0; } + // lock AFTER checking the "quick return" condition but BEFORE checking the pointers + g_mutex_lock(&rx->local_audio_mutex); + if(rx->playback_handle!=NULL && rx->local_audio_buffer!=NULL) { switch(rx->local_audio_format) { case SND_PCM_FORMAT_S16_LE: @@ -515,7 +528,9 @@ g_print("mic_read_thread: snd_pcm_start\n"); // // put sample into ring buffer // - if (mic_ring_buffer) { + if (mic_ring_buffer != NULL) { + // the "existence" of the ring buffer is now guaranteed for 1 msec, + // see audio_close_input(). newpt=mic_ring_write_pt +1; if (newpt == MICRINGLEN) newpt=0; if (newpt != mic_ring_read_pt) { @@ -553,6 +568,8 @@ float audio_get_next_mic_sample() { // no buffer, or nothing in buffer: insert silence sample=0.0; } else { + // the "existence" of the ring buffer is now guaranteed for 1 msec, + // see audio_close_input(), newpt = mic_ring_read_pt+1; if (newpt == MICRINGLEN) newpt=0; sample=mic_ring_buffer[mic_ring_read_pt]; @@ -685,6 +702,11 @@ g_print("input_device: name=%s descr=%s\n",name,descr); #endif } +// +// For these three items, use free() instead of g_free(), +// since these have been allocated by ALSA via +// snd_device_name_get_hint() +// if (name != NULL) free(name); if (descr != NULL) diff --git a/ext.c b/ext.c index 6feb74d..15d9b6f 100644 --- a/ext.c +++ b/ext.c @@ -39,6 +39,7 @@ #include "filter.h" #include "band.h" #include "bandstack.h" +#include "noise_menu.h" #include "wdsp.h" // The following calls functions can be called usig g_idle_add @@ -613,3 +614,7 @@ int ext_set_rf_gain(void *data) { return 0; } +int ext_update_noise(void *data) { + update_noise(); + return 0; +} diff --git a/ext.h b/ext.h index 8e69e95..6fe1858 100644 --- a/ext.h +++ b/ext.h @@ -107,3 +107,4 @@ int ext_diversity_update(void *data); int ext_sat_update(void *data); int ext_set_rf_gain(void *data); +int ext_update_noise(void *data); diff --git a/midi3.c b/midi3.c index 45df600..505ea0d 100644 --- a/midi3.c +++ b/midi3.c @@ -367,6 +367,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) { active_receiver->nr = 1; active_receiver->nr2= 0; } + g_idle_add(ext_update_noise, NULL); g_idle_add(ext_vfo_update, NULL); } break; diff --git a/portaudio.c b/portaudio.c index 23122e8..3073ece 100644 --- a/portaudio.c +++ b/portaudio.c @@ -222,6 +222,8 @@ int pa_mic_cb(const void *inputBuffer, void *outputBuffer, unsigned long framesP // put sample into ring buffer // if (mic_ring_buffer != NULL) { + // the "existence" of the ring buffer is now guaranteed for 1 msec, + // see audio_close_input(), newpt=mic_ring_write_pt +1; if (newpt == MICRINGLEN) newpt=0; if (newpt != mic_ring_read_pt) { @@ -256,6 +258,8 @@ float audio_get_next_mic_sample() { // no buffer, or nothing in buffer: insert silence sample=0.0; } else { + // the "existence" of the ring buffer is now guaranteed for 1 msec, + // see audio_close_input(), newpt = mic_ring_read_pt+1; if (newpt == MICRINGLEN) newpt=0; sample=mic_ring_buffer[mic_ring_read_pt]; @@ -300,7 +304,7 @@ int audio_open_output(RECEIVER *rx) return -1; } - + g_mutex_lock(&rx->local_audio_mutex); bzero( &outputParameters, sizeof( outputParameters ) ); //not necessary if you are filling in all the fields outputParameters.channelCount = 1; // Always MONO outputParameters.device = padev; @@ -319,6 +323,7 @@ int audio_open_output(RECEIVER *rx) rx->playback_handle = NULL; if (rx->local_audio_buffer) g_free(rx->local_audio_buffer); rx->local_audio_buffer = NULL; + g_mutex_unlock(&rx->local_audio_mutex); return -1; } @@ -328,12 +333,14 @@ int audio_open_output(RECEIVER *rx) rx->playback_handle=NULL; if (rx->local_audio_buffer) g_free(rx->local_audio_buffer); rx->local_audio_buffer = NULL; + g_mutex_unlock(&rx->local_audio_mutex); return -1; } // Write one buffer to avoid under-flow errors // (this gives us 5 msec to pass before we have to call audio_write the first time) bzero(rx->local_audio_buffer, (size_t) BUFFER_SIZE*sizeof(float)); err=Pa_WriteStream(rx->playback_handle, rx->local_audio_buffer, (unsigned long) BUFFER_SIZE); + g_mutex_unlock(&rx->local_audio_mutex); return 0; } @@ -345,6 +352,7 @@ int audio_open_output(RECEIVER *rx) void audio_close_input() { PaError err; + void *p; fprintf(stderr,"AudioCloseInput: %s\n", transmitter->microphone_name); @@ -359,9 +367,18 @@ void audio_close_input() } record_handle=NULL; } + // + // We do not want to do a mutex lock/unlock for every single mic sample + // accessed. Since only the ring buffer is maintained by the functions + // audio_get_next_mic_sample() and in the "mic callback" function, + // it is more than enough to wait 2 msec after setting mic_ring_buffer to NULL + // before actually releasing the storage. + // if (mic_ring_buffer != NULL) { - g_free(mic_ring_buffer); + p=mic_ring_buffer; mic_ring_buffer=NULL; + usleep(2); + g_free(p); } } @@ -375,7 +392,7 @@ void audio_close_output(RECEIVER *rx) { fprintf(stderr,"AudioCloseOutput: %s\n", rx->audio_name); -// free the buffer first, this then indicates to audio_write to do nothing + g_mutex_lock(&rx->local_audio_mutex); if(rx->local_audio_buffer!=NULL) { g_free(rx->local_audio_buffer); rx->local_audio_buffer=NULL; @@ -392,6 +409,7 @@ void audio_close_output(RECEIVER *rx) { } rx->playback_handle=NULL; } + g_mutex_unlock(&rx->local_audio_mutex); } // @@ -404,8 +422,12 @@ void audio_close_output(RECEIVER *rx) { int audio_write (RECEIVER *rx, float left, float right) { PaError err; - int mode=transmitter->mode; + int mode=modeUSB; float *buffer = rx->local_audio_buffer; + + if (can_transmit) { + mode=transmitter->mode; + } // // We have to stop the stream here if a CW side tone may occur. // This might cause underflows, but we cannot use audio_write @@ -414,8 +436,11 @@ int audio_write (RECEIVER *rx, float left, float right) // If *not* doing CW, the stream continues because we might wish // to listen to this rx while transmitting. // - if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) return 0; + if (rx == active_receiver && isTransmitting() && (mode==modeCWU || mode==modeCWL)) { + return 0; + } + g_mutex_lock(&rx->local_audio_mutex); if (rx->playback_handle != NULL && rx->local_audio_buffer != NULL) { buffer[rx->local_audio_buffer_offset++] = (left+right)*0.5; // mix to MONO if (rx->local_audio_buffer_offset == BUFFER_SIZE) { @@ -424,6 +449,7 @@ int audio_write (RECEIVER *rx, float left, float right) // do not check on errors, there will be underflows every now and then } } + g_mutex_unlock(&rx->local_audio_mutex); return 0; } diff --git a/receiver.c b/receiver.c index 46bb5b0..a0cfeda 100644 --- a/receiver.c +++ b/receiver.c @@ -813,10 +813,13 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s // // need a buffer for pixels for the spectrum of the feedback // signal (MON button). - // NewProtocol: Since we want to display only 48 kHz instead of - // 192 kHz, we make a spectrum with four times the pixels and then + // NewProtocol: Since we want to display only 24 kHz instead of + // 192 kHz, we make a spectrum with eight times the pixels and then // display only the central part. + // + // Also need a mutex, when changing sample rate // + g_mutex_init(&rx->mutex); if (protocol == ORIGINAL_PROTOCOL) { rx->pixels=(sample_rate/24000) * width; } else { @@ -828,7 +831,7 @@ fprintf(stderr,"create_pure_signal_receiver: id=%d buffer_size=%d\n",id,buffer_s rx->iq_input_buffer=g_new(double,2*rx->buffer_size); //rx->audio_buffer=NULL; rx->audio_sequence=0L; - rx->pixel_samples=malloc(sizeof(float)*(rx->pixels)); + rx->pixel_samples=g_new(float,rx->pixels); rx->samples=0; rx->displaying=0; @@ -1179,13 +1182,11 @@ void receiver_change_sample_rate(RECEIVER *rx,int sample_rate) { rx->sample_rate=sample_rate; int scale=rx->sample_rate/48000; rx->output_samples=rx->buffer_size/scale; - rx->audio_output_buffer=g_new(gdouble,2*rx->output_samples); rx->hz_per_pixel=(double)rx->sample_rate/(double)rx->width; g_print("receiver_change_sample_rate: id=%d rate=%d scale=%d buffer_size=%d output_samples=%d\n",rx->id,sample_rate,scale,rx->buffer_size,rx->output_samples); #ifdef PURESIGNAL if (rx->id == PS_RX_FEEDBACK) { - float *fp, *ofp; if (protocol == ORIGINAL_PROTOCOL) { rx->pixels = 2* scale * rx->width; } else { @@ -1193,12 +1194,8 @@ g_print("receiver_change_sample_rate: id=%d rate=%d scale=%d buffer_size=%d outp // PS feedback receiver is fixed. rx->pixels = 8 * rx->width; } - // make sure pixel_samples is always a valid pointer - // ... probably pure DL1YCF's paranoia - fp=malloc(sizeof(float)*rx->pixels); - ofp=rx->pixel_samples; - rx->pixel_samples=fp; - free(ofp); + g_free(rx->pixel_samples); + rx->pixel_samples=g_new(float,rx->pixels); init_analyzer(rx); fprintf(stderr,"PS FEEDBACK change sample rate:id=%d rate=%d buffer_size=%d output_samples=%d\n", rx->id, rx->sample_rate, rx->buffer_size, rx->output_samples); @@ -1206,6 +1203,10 @@ g_print("receiver_change_sample_rate: id=%d rate=%d scale=%d buffer_size=%d outp return; } #endif + if (rx->audio_output_buffer != NULL) { + g_free(rx->audio_output_buffer); + } + rx->audio_output_buffer=g_new(gdouble,2*rx->output_samples); SetChannelState(rx->id,0,1); init_analyzer(rx); @@ -1460,7 +1461,7 @@ void full_rx_buffer(RECEIVER *rx) { g_mutex_lock(&rx->mutex); - // noise blanker works on origianl IQ samples + // noise blanker works on original IQ samples if(rx->nb) { xanbEXT (rx->id, rx->iq_input_buffer, rx->iq_input_buffer); } diff --git a/transmitter.c b/transmitter.c index 6425ee7..c554d91 100644 --- a/transmitter.c +++ b/transmitter.c @@ -386,6 +386,7 @@ static gboolean update_display(gpointer data) { #ifdef PURESIGNAL if(tx->puresignal && tx->feedback) { RECEIVER *rx_feedback=receiver[PS_RX_FEEDBACK]; + g_mutex_lock(&rx_feedback->mutex); GetPixels(rx_feedback->id,0,rx_feedback->pixel_samples,&rc); int full = rx_feedback->pixels; // number of pixels in the feedback spectrum int width = tx->pixels; // number of pixels to copy from the feedback spectrum @@ -394,6 +395,7 @@ static gboolean update_display(gpointer data) { float *rfp=rx_feedback->pixel_samples+start; // if full == width, then we just copy all samples memcpy(tfp, rfp, width*sizeof(float)); + g_mutex_unlock(&rx_feedback->mutex); } else { #endif GetPixels(tx->id,0,tx->pixel_samples,&rc); diff --git a/vfo.c b/vfo.c index bcd2f69..e227faa 100644 --- a/vfo.c +++ b/vfo.c @@ -50,7 +50,6 @@ #include "new_menu.h" #include "rigctl.h" #include "ext.h" -#include "noise_menu.h" #ifdef FREEDV #include "freedv.h" #endif @@ -400,7 +399,7 @@ void vfo_mode_changed(int m) { active_receiver->snb=mode_settings[m].snb; // make changes effective - update_noise(); + g_idle_add(ext_update_noise, NULL); switch(id) { case 0: receiver_mode_changed(receiver[0]); -- 2.45.2