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;
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);
g_free(mic_buffer);
mic_buffer=NULL;
}
+ if (mic_ring_buffer != NULL) {
+ free(mic_ring_buffer);
+ mic_ring_buffer=NULL;
+ }
}
//
}
}
} else {
+ int newpt;
// process the mic input
for(i=0;i<mic_buffer_size;i++) {
switch(record_audio_format) {
}
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
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;
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
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);
}
}
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);
}
}
-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;
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);
}
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);
}
}
-//
-// 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) {
}
#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
//
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));
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
//
}
record_handle=NULL;
}
+ if (mic_ring_buffer != NULL) {
+ free(mic_ring_buffer);
+ mic_ring_buffer=NULL;
+ }
}
//