From 933ba3c3c913beeda5b1b2efc382809dce4f3303 Mon Sep 17 00:00:00 2001 From: c vw <dl1ycf@darc.de> Date: Thu, 12 Dec 2019 16:46:12 +0100 Subject: [PATCH] tx heartbeat also for new protocol --- audio.c | 57 ++++++++++++++++++++++-- audio.h | 1 + new_protocol.c | 22 +++------- old_protocol.c | 37 +--------------- portaudio.c | 116 ++++++++++++++++++++++++++++++------------------- 5 files changed, 134 insertions(+), 99 deletions(-) diff --git a/audio.c b/audio.c index 832a8ea..f9312f3 100644 --- a/audio.c +++ b/audio.c @@ -73,6 +73,14 @@ AUDIO_DEVICE input_devices[MAX_AUDIO_DEVICES]; int n_output_devices; AUDIO_DEVICE output_devices[MAX_AUDIO_DEVICES]; +// +// Ring buffer for "local microphone" samples +// +#define MICRINGLEN 2048 +float *mic_ring_buffer=NULL; +int mic_ring_read_pt=0; +int mic_ring_write_pt=0; + int audio_open_output(RECEIVER *rx) { int err; snd_pcm_hw_params_t *hw_params; @@ -239,6 +247,13 @@ g_print("audio_open_input: mic_buffer: size=%d channels=%d sample=%ld bytes\n",m break; } +g_print("audio_open_input: allocating ring buffer\n"); + mic_ring_buffer=(float *) malloc(MICRINGLEN * sizeof(float)); + mic_ring_read_pt = mic_ring_write_pt=0; + if (mic_ring_buffer == NULL) { + return -1; + } + g_print("audio_open_input: creating mic_read_thread\n"); GError *error; mic_read_thread_id = g_thread_try_new("local mic",mic_read_thread,NULL,&error); @@ -281,6 +296,10 @@ g_print("audio_close_input: free mic buffer\n"); g_free(mic_buffer); mic_buffer=NULL; } + if (mic_ring_buffer != NULL) { + free(mic_ring_buffer); + mic_ring_buffer=NULL; + } } // @@ -470,6 +489,7 @@ g_print("mic_read_thread: snd_pcm_start\n"); } } } else { + int newpt; // process the mic input for(i=0;i<mic_buffer_size;i++) { switch(record_audio_format) { @@ -488,13 +508,24 @@ g_print("mic_read_thread: snd_pcm_start\n"); } switch(protocol) { case ORIGINAL_PROTOCOL: - old_protocol_process_local_mic(sample); - break; case NEW_PROTOCOL: - new_protocol_process_local_mic(sample); + // + // put sample into ring buffer + // + if (mic_ring_buffer) { + newpt=mic_ring_write_pt +1; + if (newpt == MICRINGLEN) newpt=0; + if (newpt != mic_ring_read_pt) { + // buffer space available, do the write + mic_ring_buffer[mic_ring_write_pt]=sample; + // atomic update of mic_ring_write_pt + mic_ring_write_pt=newpt; + } + } break; #ifdef SOAPYSDR case SOAPYSDR_PROTOCOL: + // Note that this call ends up deeply in the TX engine soapy_protocol_process_local_mic(sample); break; #endif @@ -508,6 +539,26 @@ g_print("mic_read_thread: exiting\n"); return NULL; } +// +// Utility function for retrieving mic samples +// from ring buffer +// +float audio_get_next_mic_sample() { + int newpt; + float sample; + if ((mic_ring_buffer == NULL) || (mic_ring_read_pt == mic_ring_write_pt)) { + // no buffer, or nothing in buffer: insert silence + sample=0.0; + } else { + newpt = mic_ring_read_pt+1; + if (newpt == MICRINGLEN) newpt=0; + sample=mic_ring_buffer[mic_ring_read_pt]; + // atomic update of read pointer + mic_ring_read_pt=newpt; + } + return sample; +} + void audio_get_cards() { snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; diff --git a/audio.h b/audio.h index a477b3d..234c184 100644 --- a/audio.h +++ b/audio.h @@ -45,4 +45,5 @@ extern int audio_write(RECEIVER *rx,float left_sample,float right_sample); extern int cw_audio_write(float sample); extern void audio_get_cards(); char * audio_get_error_string(int err); +float audio_get_next_mic_sample(); #endif diff --git a/new_protocol.c b/new_protocol.c index 4fe00bb..a43c961 100644 --- a/new_protocol.c +++ b/new_protocol.c @@ -1533,9 +1533,11 @@ fprintf(stderr,"mic_line_thread\n"); sem_post(&mic_line_sem_ready); sem_wait(&mic_line_sem_buffer); #endif - if(!transmitter->local_microphone) { - process_mic_data(mic_bytes_read); - } +// +// process mic data even if local mic is used, +// since this is our pace-maker +// + process_mic_data(mic_bytes_read); free(mic_line_buffer); } } @@ -1834,7 +1836,7 @@ static void process_mic_data(int bytes) { for(i=0;i<MIC_SAMPLES;i++) { sample=(short)(mic_line_buffer[b++]<<8); sample |= (short) (mic_line_buffer[b++]&0xFF); - fsample = (float) sample * 0.00003051; + fsample = transmitter->local_microphone ? audio_get_next_mic_sample() : (float) sample * 0.00003051; #ifdef FREEDV if(active_receiver->freedv) { add_freedv_mic_sample(transmitter,fsample); @@ -1847,18 +1849,6 @@ static void process_mic_data(int bytes) { } } -void new_protocol_process_local_mic(float sample) { -#ifdef FREEDV - if(active_receiver->freedv) { - add_freedv_mic_sample(transmitter,sample); - } else { -#endif - add_mic_sample(transmitter,sample); -#ifdef FREEDV - } -#endif -} - void new_protocol_cw_audio_samples(short left_audio_sample,short right_audio_sample) { int rc; int mode=transmitter->mode; diff --git a/old_protocol.c b/old_protocol.c index 4c05757..b804a92 100644 --- a/old_protocol.c +++ b/old_protocol.c @@ -252,11 +252,6 @@ static unsigned char ep6_inbuffer[EP6_BUFFER_SIZE]; static unsigned char usb_buffer_block = 0; #endif -#define MICRINGLEN 2048 -float mic_ring_buffer[MICRINGLEN]; -int mic_ring_read_pt=0; -int mic_ring_write_pt=0; - void old_protocol_stop() { metis_start_stop(0); } @@ -994,22 +989,7 @@ static void process_ozy_input_buffer(unsigned char *buffer) { mic_samples++; if(mic_samples>=mic_sample_divisor) { // reduce to 48000 - if (!transmitter->local_microphone) { - // take mic sample from SDR - fsample = (float) mic_sample * 0.00003051; - } else { - // take mic sample from local mic buffer - if (mic_ring_read_pt == mic_ring_write_pt) { - // nothing in buffer: insert silence - fsample=0.0; - } else { - int newpt = mic_ring_read_pt+1; - if (newpt == MICRINGLEN) newpt=0; - fsample=mic_ring_buffer[mic_ring_read_pt]; - // atomic update of read pointer - mic_ring_read_pt=newpt; - } - } + fsample = transmitter->local_microphone ? audio_get_next_mic_sample() : (float) mic_sample * 0.00003051; #ifdef FREEDV if(active_receiver->freedv) { add_freedv_mic_sample(transmitter,fsample); @@ -1096,21 +1076,6 @@ void old_protocol_iq_samples(int isample,int qsample) { } } -// -// This function now simply puts the mic sample -// into a ring buffer -// -void old_protocol_process_local_mic(float sample) { - int newpt; // value of write pointer after a successful write - newpt=mic_ring_write_pt +1; - if (newpt == MICRINGLEN) newpt=0; - if (newpt != mic_ring_read_pt) { - // buffer space available, do the write - mic_ring_buffer[mic_ring_write_pt]=sample; - mic_ring_write_pt=newpt; - } -} - /* static void process_bandscope_buffer(char *buffer) { } diff --git a/portaudio.c b/portaudio.c index 111a524..1e009a4 100644 --- a/portaudio.c +++ b/portaudio.c @@ -49,6 +49,14 @@ int n_output_devices=0; #define BUFFER_SIZE 256 +// +// Ring buffer for "local microphone" samples +// +#define MICRINGLEN 2048 +float *mic_ring_buffer=NULL; +int mic_ring_read_pt=0; +int mic_ring_write_pt=0; + // // AUDIO_GET_CARDS // @@ -171,6 +179,12 @@ int audio_open_input() return -1; } + mic_ring_buffer=(float *) malloc(MICRINGLEN * sizeof(float)); + mic_ring_read_pt = mic_ring_write_pt=0; + if (mic_ring_buffer == NULL) { + return -1; + } + err = Pa_StartStream(record_handle); if (err != paNoError) { fprintf(stderr, "PORTAUDIO ERROR: AOI start stream:%s\n",Pa_GetErrorText(err)); @@ -188,59 +202,69 @@ int pa_mic_cb(const void *inputBuffer, void *outputBuffer, unsigned long framesP void *userdata) { float *in = (float *)inputBuffer; - int i; - gfloat sample; - + int i, newpt; + float sample; if (in == NULL) { - // - // We could just do nothing, but rather send a bunch of silence - // Note the mic samples flying in are the "heart-beat" of the TX engine. - // - for (i=0; i<BUFFER_SIZE; i++) { - sample=0.0; - switch(protocol) { - case ORIGINAL_PROTOCOL: - old_protocol_process_local_mic(sample); - break; - case NEW_PROTOCOL: - new_protocol_process_local_mic(sample); - break; -#ifdef SOAPYSDR - case SOAPYSDR_PROTOCOL: - soapy_protocol_process_local_mic(sample); - break; -#endif - default: - break; - } - } - } else { - // - // send the samples in the buffer - // - for (i=0; i<framesPerBuffer; i++) { - sample=in[i]; - switch(protocol) { - case ORIGINAL_PROTOCOL: - old_protocol_process_local_mic(sample); - break; - case NEW_PROTOCOL: - new_protocol_process_local_mic(sample); - break; + // This should not happen, so we do not send silence etc. + g_print("PortAudio error: bogus audio buffer in callback\n"); + return paContinue; + } + // + // send the samples in the buffer + // + for (i=0; i<framesPerBuffer; i++) { + sample=in[i]; + switch(protocol) { + case ORIGINAL_PROTOCOL: + case NEW_PROTOCOL: + // + // put sample into ring buffer + // + if (mic_ring_buffer != NULL) { + newpt=mic_ring_write_pt +1; + if (newpt == MICRINGLEN) newpt=0; + if (newpt != mic_ring_read_pt) { + // buffer space available, do the write + mic_ring_buffer[mic_ring_write_pt]=sample; + // atomic update of mic_ring_write_pt + mic_ring_write_pt=newpt; + } + } + break; #ifdef SOAPYSDR - case SOAPYSDR_PROTOCOL: - soapy_protocol_process_local_mic(sample); - break; + case SOAPYSDR_PROTOCOL: + // Note that this call ends up deeply in the TX engine + soapy_protocol_process_local_mic(sample); + break; #endif - default: - break; - } + default: + break; } } return paContinue; } +// +// Utility function for retrieving mic samples +// from ring buffer +// +float audio_get_next_mic_sample() { + int newpt; + float sample; + if ((mic_ring_buffer == NULL) || (mic_ring_read_pt == mic_ring_write_pt)) { + // no buffer, or nothing in buffer: insert silence + sample=0.0; + } else { + newpt = mic_ring_read_pt+1; + if (newpt == MICRINGLEN) newpt=0; + sample=mic_ring_buffer[mic_ring_read_pt]; + // atomic update of read pointer + mic_ring_read_pt=newpt; + } + return sample; +} + // // AUDIO_OPEN_OUTPUT // @@ -335,6 +359,10 @@ void audio_close_input() } record_handle=NULL; } + if (mic_ring_buffer != NULL) { + free(mic_ring_buffer); + mic_ring_buffer=NULL; + } } // -- 2.45.2