From b0618a25e23cc4a5bb42749a1302ae2bd133bc15 Mon Sep 17 00:00:00 2001 From: Ramakrishnan Muthukrishnan Date: Sun, 22 Oct 2023 15:20:46 +0530 Subject: [PATCH] clang-format -i audio.c --- audio.c | 1206 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 635 insertions(+), 571 deletions(-) diff --git a/audio.c b/audio.c index e6cda8c..7d9b895 100644 --- a/audio.c +++ b/audio.c @@ -1,71 +1,68 @@ /* Copyright (C) -* 2016 - John Melton, G0ORX/N6LYT -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ + * 2016 - John Melton, G0ORX/N6LYT + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ // // If PortAudio is used instead of ALSA (e.g. on MacOS), // this file is not used (and replaced by portaudio.c). -#ifndef PORTAUDIO +#ifndef PORTAUDIO #include -#include -#include -#include -#include #include #include #include #include +#include +#include +#include +#include #include -#include "radio.h" -#include "receiver.h" -#include "transmitter.h" #include "audio.h" #include "mode.h" #include "new_protocol.h" #include "old_protocol.h" +#include "radio.h" +#include "receiver.h" +#include "transmitter.h" #include "vfo.h" int audio = 0; int mic_buffer_size = 720; // samples (both left and right) -static snd_pcm_t *record_handle=NULL; +static snd_pcm_t *record_handle = NULL; static snd_pcm_format_t record_audio_format; -static void *mic_buffer=NULL; +static void *mic_buffer = NULL; -static GThread *mic_read_thread_id=NULL; +static GThread *mic_read_thread_id = NULL; -static int running=FALSE; +static int running = FALSE; #define FORMATS 3 -static snd_pcm_format_t formats[3]={ - SND_PCM_FORMAT_FLOAT_LE, - SND_PCM_FORMAT_S32_LE, - SND_PCM_FORMAT_S16_LE}; +static snd_pcm_format_t formats[3] = { + SND_PCM_FORMAT_FLOAT_LE, SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S16_LE}; static void *mic_read_thread(void *arg); - int n_input_devices; AUDIO_DEVICE input_devices[MAX_AUDIO_DEVICES]; int n_output_devices; @@ -77,227 +74,255 @@ AUDIO_DEVICE output_devices[MAX_AUDIO_DEVICES]; // samples in large chunks if fed from digimode programs. // #define MICRINGLEN 6000 -float *mic_ring_buffer=NULL; -int mic_ring_read_pt=0; -int mic_ring_write_pt=0; +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; - unsigned int rate=48000; - unsigned int channels=2; - int soft_resample=1; - unsigned int latency=125000; - - if(rx->audio_name==NULL) { - rx->local_audio=0; - return -1; - } - -g_print("audio_open_output: rx=%d %s buffer_size=%d\n",rx->id,rx->audio_name,rx->local_audio_buffer_size); - - int i; - char hw[128]; - - - i=0; - while(i<127 && rx->audio_name[i]!=' ') { - hw[i]=rx->audio_name[i]; - i++; - } - hw[i]='\0'; - -g_print("audio_open_output: hw=%s\n",hw); - - for(i=0;ilocal_audio_mutex); - if ((err = snd_pcm_open (&rx->playback_handle, hw, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { - g_print("audio_open_output: cannot open audio device %s (%s)\n", - hw, - snd_strerror (err)); - g_mutex_unlock(&rx->local_audio_mutex); - return err; + int err; + unsigned int rate = 48000; + unsigned int channels = 2; + int soft_resample = 1; + unsigned int latency = 125000; + + if (rx->audio_name == NULL) { + rx->local_audio = 0; + return -1; } -g_print("audio_open_output: handle=%p\n",rx->playback_handle); - -g_print("audio_open_output: trying format %s (%s)\n",snd_pcm_format_name(formats[i]),snd_pcm_format_description(formats[i])); - if ((err = snd_pcm_set_params (rx->playback_handle,formats[i],SND_PCM_ACCESS_RW_INTERLEAVED,channels,rate,soft_resample,latency)) < 0) { - g_print("audio_open_output: snd_pcm_set_params failed: %s\n",snd_strerror(err)); - g_mutex_unlock(&rx->local_audio_mutex); - audio_close_output(rx); - continue; - } else { -g_print("audio_open_output: using format %s (%s)\n",snd_pcm_format_name(formats[i]),snd_pcm_format_description(formats[i])); - rx->local_audio_format=formats[i]; - break; + + g_print("audio_open_output: rx=%d %s buffer_size=%d\n", rx->id, + rx->audio_name, rx->local_audio_buffer_size); + + int i; + char hw[128]; + + i = 0; + while (i < 127 && rx->audio_name[i] != ' ') { + hw[i] = rx->audio_name[i]; + i++; + } + hw[i] = '\0'; + + g_print("audio_open_output: hw=%s\n", hw); + + for (i = 0; i < FORMATS; i++) { + g_mutex_lock(&rx->local_audio_mutex); + if ((err = snd_pcm_open(&rx->playback_handle, hw, + SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < + 0) { + g_print("audio_open_output: cannot open audio device %s (%s)\n", hw, + snd_strerror(err)); + g_mutex_unlock(&rx->local_audio_mutex); + return err; + } + g_print("audio_open_output: handle=%p\n", rx->playback_handle); + + g_print("audio_open_output: trying format %s (%s)\n", + snd_pcm_format_name(formats[i]), + snd_pcm_format_description(formats[i])); + if ((err = snd_pcm_set_params(rx->playback_handle, formats[i], + SND_PCM_ACCESS_RW_INTERLEAVED, channels, + rate, soft_resample, latency)) < 0) { + g_print("audio_open_output: snd_pcm_set_params failed: %s\n", + snd_strerror(err)); + g_mutex_unlock(&rx->local_audio_mutex); + audio_close_output(rx); + continue; + } else { + g_print("audio_open_output: using format %s (%s)\n", + snd_pcm_format_name(formats[i]), + snd_pcm_format_description(formats[i])); + rx->local_audio_format = formats[i]; + break; + } } - } - if(i>=FORMATS) { - g_print("audio_open_output: cannot find usable format\n"); - return err; - } + if (i >= FORMATS) { + g_print("audio_open_output: cannot find usable format\n"); + return err; + } - rx->local_audio_buffer_offset=0; - switch(rx->local_audio_format) { + rx->local_audio_buffer_offset = 0; + switch (rx->local_audio_format) { case SND_PCM_FORMAT_S16_LE: -g_print("audio_open_output: local_audio_buffer: size=%d sample=%ld\n",rx->local_audio_buffer_size,sizeof(gint16)); - rx->local_audio_buffer=g_new(gint16,2*rx->local_audio_buffer_size); + g_print("audio_open_output: local_audio_buffer: size=%d sample=%ld\n", + rx->local_audio_buffer_size, sizeof(gint16)); + rx->local_audio_buffer = g_new(gint16, 2 * rx->local_audio_buffer_size); break; case SND_PCM_FORMAT_S32_LE: -g_print("audio_open_output: local_audio_buffer: size=%d sample=%ld\n",rx->local_audio_buffer_size,sizeof(gint32)); - rx->local_audio_buffer=g_new(gint32,2*rx->local_audio_buffer_size); - break; + g_print("audio_open_output: local_audio_buffer: size=%d sample=%ld\n", + rx->local_audio_buffer_size, sizeof(gint32)); + rx->local_audio_buffer = g_new(gint32, 2 * rx->local_audio_buffer_size); + break; case SND_PCM_FORMAT_FLOAT_LE: -g_print("audio_open_output: local_audio_buffer: size=%d sample=%ld\n",rx->local_audio_buffer_size,sizeof(gfloat)); - rx->local_audio_buffer=g_new(gfloat,2*rx->local_audio_buffer_size); - break; - } - - g_print("audio_open_output: rx=%d audio_device=%d handle=%p buffer=%p size=%d\n",rx->id,rx->audio_device,rx->playback_handle,rx->local_audio_buffer,rx->local_audio_buffer_size); - - g_mutex_unlock(&rx->local_audio_mutex); - return 0; + g_print("audio_open_output: local_audio_buffer: size=%d sample=%ld\n", + rx->local_audio_buffer_size, sizeof(gfloat)); + rx->local_audio_buffer = g_new(gfloat, 2 * rx->local_audio_buffer_size); + break; + } + + g_print("audio_open_output: rx=%d audio_device=%d handle=%p buffer=%p " + "size=%d\n", + rx->id, rx->audio_device, rx->playback_handle, + rx->local_audio_buffer, rx->local_audio_buffer_size); + + g_mutex_unlock(&rx->local_audio_mutex); + return 0; } - + int audio_open_input() { - int err; - unsigned int rate=48000; - unsigned int channels=1; - int soft_resample=1; - unsigned int latency=125000; - char hw[64]; - int i; - - if(transmitter->microphone_name==NULL) { - transmitter->local_microphone=0; - return -1; - } - -g_print("audio_open_input: %s\n",transmitter->microphone_name); - - mic_buffer_size = 256; - - g_print("audio_open_input: mic_buffer_size=%d\n",mic_buffer_size); - i=0; - while(i<63 && transmitter->microphone_name[i]!=' ') { - hw[i]=transmitter->microphone_name[i]; - i++; - } - hw[i]='\0'; - - - g_print("audio_open_input: hw=%s\n",hw); - - for(i=0;imicrophone_name == NULL) { + transmitter->local_microphone = 0; + return -1; } -g_print("audio_open_input: handle=%p\n",record_handle); -g_print("audio_open_input: trying format %s (%s)\n",snd_pcm_format_name(formats[i]),snd_pcm_format_description(formats[i])); - if ((err = snd_pcm_set_params (record_handle,formats[i],SND_PCM_ACCESS_RW_INTERLEAVED,channels,rate,soft_resample,latency)) < 0) { - g_print("audio_open_input: snd_pcm_set_params failed: %s\n",snd_strerror(err)); - audio_close_input(); - continue; - } else { -g_print("audio_open_input: using format %s (%s)\n",snd_pcm_format_name(formats[i]),snd_pcm_format_description(formats[i])); - record_audio_format=formats[i]; - break; + g_print("audio_open_input: %s\n", transmitter->microphone_name); + + mic_buffer_size = 256; + + g_print("audio_open_input: mic_buffer_size=%d\n", mic_buffer_size); + i = 0; + while (i < 63 && transmitter->microphone_name[i] != ' ') { + hw[i] = transmitter->microphone_name[i]; + i++; + } + hw[i] = '\0'; + + g_print("audio_open_input: hw=%s\n", hw); + + for (i = 0; i < FORMATS; i++) { + if ((err = snd_pcm_open(&record_handle, hw, SND_PCM_STREAM_CAPTURE, + SND_PCM_ASYNC)) < 0) { + g_print("audio_open_input: cannot open audio device %s (%s)\n", hw, + snd_strerror(err)); + return err; + } + g_print("audio_open_input: handle=%p\n", record_handle); + + g_print("audio_open_input: trying format %s (%s)\n", + snd_pcm_format_name(formats[i]), + snd_pcm_format_description(formats[i])); + if ((err = snd_pcm_set_params(record_handle, formats[i], + SND_PCM_ACCESS_RW_INTERLEAVED, channels, + rate, soft_resample, latency)) < 0) { + g_print("audio_open_input: snd_pcm_set_params failed: %s\n", + snd_strerror(err)); + audio_close_input(); + continue; + } else { + g_print("audio_open_input: using format %s (%s)\n", + snd_pcm_format_name(formats[i]), + snd_pcm_format_description(formats[i])); + record_audio_format = formats[i]; + break; + } } - } - if(i>=FORMATS) { - g_print("audio_open_input: cannot find usable format\n"); - audio_close_input(); - return err; - } + if (i >= FORMATS) { + g_print("audio_open_input: cannot find usable format\n"); + audio_close_input(); + return err; + } -g_print("audio_open_input: format=%d\n",record_audio_format); + g_print("audio_open_input: format=%d\n", record_audio_format); - switch(record_audio_format) { + switch (record_audio_format) { case SND_PCM_FORMAT_S16_LE: -g_print("audio_open_input: mic_buffer: size=%d channels=%d sample=%ld bytes\n",mic_buffer_size,channels,sizeof(gint16)); - mic_buffer=g_new(gint16,mic_buffer_size); - break; + g_print("audio_open_input: mic_buffer: size=%d channels=%d sample=%ld " + "bytes\n", + mic_buffer_size, channels, sizeof(gint16)); + mic_buffer = g_new(gint16, mic_buffer_size); + break; case SND_PCM_FORMAT_S32_LE: -g_print("audio_open_input: mic_buffer: size=%d channels=%d sample=%ld bytes\n",mic_buffer_size,channels,sizeof(gint32)); - mic_buffer=g_new(gint32,mic_buffer_size); - break; + g_print("audio_open_input: mic_buffer: size=%d channels=%d sample=%ld " + "bytes\n", + mic_buffer_size, channels, sizeof(gint32)); + mic_buffer = g_new(gint32, mic_buffer_size); + break; case SND_PCM_FORMAT_FLOAT_LE: -g_print("audio_open_input: mic_buffer: size=%d channels=%d sample=%ld bytes\n",mic_buffer_size,channels,sizeof(gfloat)); - mic_buffer=g_new(gfloat,mic_buffer_size); - break; - } - -g_print("audio_open_input: allocating ring buffer\n"); - mic_ring_buffer=(float *) g_new(float,MICRINGLEN); - mic_ring_read_pt = mic_ring_write_pt=0; - if (mic_ring_buffer == NULL) { - audio_close_input(); - return -1; - } - -g_print("audio_open_input: creating mic_read_thread\n"); - GError *error; - mic_read_thread_id = g_thread_try_new("microphone",mic_read_thread,NULL,&error); - if(!mic_read_thread_id ) { - g_print("g_thread_new failed on mic_read_thread: %s\n",error->message); - audio_close_input(); - return -1; - } - - return 0; + g_print("audio_open_input: mic_buffer: size=%d channels=%d sample=%ld " + "bytes\n", + mic_buffer_size, channels, sizeof(gfloat)); + mic_buffer = g_new(gfloat, mic_buffer_size); + break; + } + + g_print("audio_open_input: allocating ring buffer\n"); + mic_ring_buffer = (float *)g_new(float, MICRINGLEN); + mic_ring_read_pt = mic_ring_write_pt = 0; + if (mic_ring_buffer == NULL) { + audio_close_input(); + return -1; + } + + g_print("audio_open_input: creating mic_read_thread\n"); + GError *error; + mic_read_thread_id = + g_thread_try_new("microphone", mic_read_thread, NULL, &error); + if (!mic_read_thread_id) { + g_print("g_thread_new failed on mic_read_thread: %s\n", error->message); + audio_close_input(); + return -1; + } + + return 0; } void audio_close_output(RECEIVER *rx) { -g_print("audio_close_output: rx=%d handle=%p buffer=%p\n",rx->id,rx->playback_handle,rx->local_audio_buffer); - g_mutex_lock(&rx->local_audio_mutex); - if(rx->playback_handle!=NULL) { - snd_pcm_close (rx->playback_handle); - rx->playback_handle=NULL; - } - if(rx->local_audio_buffer!=NULL) { - g_free(rx->local_audio_buffer); - rx->local_audio_buffer=NULL; - } - g_mutex_unlock(&rx->local_audio_mutex); + g_print("audio_close_output: rx=%d handle=%p buffer=%p\n", rx->id, + rx->playback_handle, rx->local_audio_buffer); + g_mutex_lock(&rx->local_audio_mutex); + if (rx->playback_handle != NULL) { + snd_pcm_close(rx->playback_handle); + rx->playback_handle = NULL; + } + if (rx->local_audio_buffer != NULL) { + g_free(rx->local_audio_buffer); + rx->local_audio_buffer = NULL; + } + g_mutex_unlock(&rx->local_audio_mutex); } void audio_close_input() { - void *p; -g_print("audio_close_input\n"); - running=FALSE; - if(mic_read_thread_id!=NULL) { -g_print("audio_close_input: wait for thread to complete\n"); - g_thread_join(mic_read_thread_id); - mic_read_thread_id=NULL; - } - if(record_handle!=NULL) { -g_print("audio_close_input: snd_pcm_close\n"); - snd_pcm_close (record_handle); - record_handle=NULL; - } - if(mic_buffer!=NULL) { -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) { - p=mic_ring_buffer; - mic_ring_buffer=NULL; - usleep(2); - g_free(p); - } + void *p; + g_print("audio_close_input\n"); + running = FALSE; + if (mic_read_thread_id != NULL) { + g_print("audio_close_input: wait for thread to complete\n"); + g_thread_join(mic_read_thread_id); + mic_read_thread_id = NULL; + } + if (record_handle != NULL) { + g_print("audio_close_input: snd_pcm_close\n"); + snd_pcm_close(record_handle); + record_handle = NULL; + } + if (mic_buffer != NULL) { + 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) { + p = mic_ring_buffer; + mic_ring_buffer = NULL; + usleep(2); + g_free(p); + } } // @@ -306,70 +331,81 @@ g_print("audio_close_input: free mic buffer\n"); // Note that audio_write must be switched off for the // active_receiver when transmitting. // -int cw_audio_write(float sample){ - snd_pcm_sframes_t delay; - long rc; - long trim; - float *float_buffer; - gint32 *long_buffer; - gint16 *short_buffer; - - 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) { - case SND_PCM_FORMAT_S16_LE: - short_buffer=(gint16 *)rx->local_audio_buffer; - short_buffer[rx->local_audio_buffer_offset*2]=(gint16)(sample*32767.0F); - short_buffer[(rx->local_audio_buffer_offset*2)+1]=(gint16)(sample*32767.0F); - break; - case SND_PCM_FORMAT_S32_LE: - long_buffer=(gint32 *)rx->local_audio_buffer; - long_buffer[rx->local_audio_buffer_offset*2]=(gint32)(sample*4294967295.0F); - long_buffer[(rx->local_audio_buffer_offset*2)+1]=(gint32)(sample*4294967295.0F); - break; - case SND_PCM_FORMAT_FLOAT_LE: - float_buffer=(float *)rx->local_audio_buffer; - float_buffer[rx->local_audio_buffer_offset*2]=sample; - float_buffer[(rx->local_audio_buffer_offset*2)+1]=sample; - break; - } - rx->local_audio_buffer_offset++; - - if(rx->local_audio_buffer_offset>=rx->local_audio_buffer_size) { +int cw_audio_write(float sample) { + snd_pcm_sframes_t delay; + long rc; + long trim; + float *float_buffer; + gint32 *long_buffer; + gint16 *short_buffer; - trim=0; + RECEIVER *rx = active_receiver; - int max_delay=rx->local_audio_buffer_size*4; - if(snd_pcm_delay(rx->playback_handle,&delay)==0) { - if(delay>max_delay) { - trim=delay-max_delay; -g_print("audio delay=%ld trim=%ld audio_buffer_size=%d\n",delay,trim,rx->local_audio_buffer_size); + 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: + short_buffer = (gint16 *)rx->local_audio_buffer; + short_buffer[rx->local_audio_buffer_offset * 2] = + (gint16)(sample * 32767.0F); + short_buffer[(rx->local_audio_buffer_offset * 2) + 1] = + (gint16)(sample * 32767.0F); + break; + case SND_PCM_FORMAT_S32_LE: + long_buffer = (gint32 *)rx->local_audio_buffer; + long_buffer[rx->local_audio_buffer_offset * 2] = + (gint32)(sample * 4294967295.0F); + long_buffer[(rx->local_audio_buffer_offset * 2) + 1] = + (gint32)(sample * 4294967295.0F); + break; + case SND_PCM_FORMAT_FLOAT_LE: + float_buffer = (float *)rx->local_audio_buffer; + float_buffer[rx->local_audio_buffer_offset * 2] = sample; + float_buffer[(rx->local_audio_buffer_offset * 2) + 1] = sample; + break; } - } - - if(trimlocal_audio_buffer_size) { - if ((rc = snd_pcm_writei (rx->playback_handle, rx->local_audio_buffer, rx->local_audio_buffer_size-trim)) != rx->local_audio_buffer_size-trim) { - if(rc<0) { - 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 - } + rx->local_audio_buffer_offset++; + + if (rx->local_audio_buffer_offset >= rx->local_audio_buffer_size) { + + trim = 0; + + int max_delay = rx->local_audio_buffer_size * 4; + if (snd_pcm_delay(rx->playback_handle, &delay) == 0) { + if (delay > max_delay) { + trim = delay - max_delay; + g_print("audio delay=%ld trim=%ld audio_buffer_size=%d\n", + delay, trim, rx->local_audio_buffer_size); + } + } + + if (trim < rx->local_audio_buffer_size) { + if ((rc = snd_pcm_writei(rx->playback_handle, + rx->local_audio_buffer, + rx->local_audio_buffer_size - trim)) != + rx->local_audio_buffer_size - trim) { + if (rc < 0) { + 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 + } + } + } + } } - } + rx->local_audio_buffer_offset = 0; } - } - rx->local_audio_buffer_offset=0; } - } - g_mutex_unlock(&rx->local_audio_mutex); - return 0; + g_mutex_unlock(&rx->local_audio_mutex); + return 0; } // @@ -377,159 +413,176 @@ g_print("audio delay=%ld trim=%ld audio_buffer_size=%d\n",delay,trim,rx->local_a // since cw_audio_write may be active // -int audio_write(RECEIVER *rx,float left_sample,float right_sample) { - snd_pcm_sframes_t delay; - long rc; - long trim; - int txmode=get_tx_mode(); - float *float_buffer; - gint32 *long_buffer; - gint16 *short_buffer; - - // - // We have to stop the stream here if a CW side tone may occur. - // This might cause underflows, but we cannot use audio_write - // and cw_audio_write simultaneously on the same device. - // Instead, the side tone version will take over. - // If *not* doing CW, the stream continues because we might wish - // to listen to this rx while transmitting. - // - - if (rx == active_receiver && isTransmitting() && (txmode==modeCWU || txmode==modeCWL)) { - return 0; - } +int audio_write(RECEIVER *rx, float left_sample, float right_sample) { + snd_pcm_sframes_t delay; + long rc; + long trim; + int txmode = get_tx_mode(); + float *float_buffer; + gint32 *long_buffer; + gint16 *short_buffer; + + // + // We have to stop the stream here if a CW side tone may occur. + // This might cause underflows, but we cannot use audio_write + // and cw_audio_write simultaneously on the same device. + // Instead, the side tone version will take over. + // If *not* doing CW, the stream continues because we might wish + // to listen to this rx while transmitting. + // + + if (rx == active_receiver && isTransmitting() && + (txmode == modeCWU || txmode == modeCWL)) { + return 0; + } - // lock AFTER checking the "quick return" condition but BEFORE checking the pointers - g_mutex_lock(&rx->local_audio_mutex); + // 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: - short_buffer=(gint16 *)rx->local_audio_buffer; - short_buffer[rx->local_audio_buffer_offset*2]=(gint16)(left_sample*32767.0F); - short_buffer[(rx->local_audio_buffer_offset*2)+1]=(gint16)(right_sample*32767.0F); - break; - case SND_PCM_FORMAT_S32_LE: - long_buffer=(gint32 *)rx->local_audio_buffer; - long_buffer[rx->local_audio_buffer_offset*2]=(gint32)(left_sample*4294967295.0F); - long_buffer[(rx->local_audio_buffer_offset*2)+1]=(gint32)(right_sample*4294967295.0F); - break; - case SND_PCM_FORMAT_FLOAT_LE: - float_buffer=(float *)rx->local_audio_buffer; - float_buffer[rx->local_audio_buffer_offset*2]=left_sample; - float_buffer[(rx->local_audio_buffer_offset*2)+1]=right_sample; - break; - } - rx->local_audio_buffer_offset++; + if (rx->playback_handle != NULL && rx->local_audio_buffer != NULL) { + switch (rx->local_audio_format) { + case SND_PCM_FORMAT_S16_LE: + short_buffer = (gint16 *)rx->local_audio_buffer; + short_buffer[rx->local_audio_buffer_offset * 2] = + (gint16)(left_sample * 32767.0F); + short_buffer[(rx->local_audio_buffer_offset * 2) + 1] = + (gint16)(right_sample * 32767.0F); + break; + case SND_PCM_FORMAT_S32_LE: + long_buffer = (gint32 *)rx->local_audio_buffer; + long_buffer[rx->local_audio_buffer_offset * 2] = + (gint32)(left_sample * 4294967295.0F); + long_buffer[(rx->local_audio_buffer_offset * 2) + 1] = + (gint32)(right_sample * 4294967295.0F); + break; + case SND_PCM_FORMAT_FLOAT_LE: + float_buffer = (float *)rx->local_audio_buffer; + float_buffer[rx->local_audio_buffer_offset * 2] = left_sample; + float_buffer[(rx->local_audio_buffer_offset * 2) + 1] = + right_sample; + break; + } + rx->local_audio_buffer_offset++; - if(rx->local_audio_buffer_offset>=rx->local_audio_buffer_size) { + if (rx->local_audio_buffer_offset >= rx->local_audio_buffer_size) { - trim=0; + trim = 0; - int max_delay=rx->local_audio_buffer_size*4; - if(snd_pcm_delay(rx->playback_handle,&delay)==0) { - if(delay>max_delay) { - trim=delay-max_delay; -g_print("audio delay=%ld trim=%ld audio_buffer_size=%d\n",delay,trim,rx->local_audio_buffer_size); - } - } - - if(trimlocal_audio_buffer_size) { - if ((rc = snd_pcm_writei (rx->playback_handle, rx->local_audio_buffer, rx->local_audio_buffer_size-trim)) != rx->local_audio_buffer_size-trim) { - if(rc<0) { - 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)); - rx->local_audio_buffer_offset=0; - g_mutex_unlock(&rx->local_audio_mutex); - return rc; - } - } else { - // ignore short write + int max_delay = rx->local_audio_buffer_size * 4; + if (snd_pcm_delay(rx->playback_handle, &delay) == 0) { + if (delay > max_delay) { + trim = delay - max_delay; + g_print("audio delay=%ld trim=%ld audio_buffer_size=%d\n", + delay, trim, rx->local_audio_buffer_size); + } + } + + if (trim < rx->local_audio_buffer_size) { + if ((rc = snd_pcm_writei(rx->playback_handle, + rx->local_audio_buffer, + rx->local_audio_buffer_size - trim)) != + rx->local_audio_buffer_size - trim) { + if (rc < 0) { + 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)); + rx->local_audio_buffer_offset = 0; + g_mutex_unlock(&rx->local_audio_mutex); + return rc; + } + } else { + // ignore short write + } + } + } } - } + rx->local_audio_buffer_offset = 0; } - } - rx->local_audio_buffer_offset=0; } - } - g_mutex_unlock(&rx->local_audio_mutex); - return 0; + g_mutex_unlock(&rx->local_audio_mutex); + return 0; } static void *mic_read_thread(gpointer arg) { - int rc; - gfloat *float_buffer; - gint32 *long_buffer; - gint16 *short_buffer; - gfloat sample; - int i; - -g_print("mic_read_thread: mic_buffer_size=%d\n",mic_buffer_size); -g_print("mic_read_thread: snd_pcm_start\n"); - if ((rc = snd_pcm_start (record_handle)) < 0) { - g_print("mic_read_thread: cannot start audio interface for use (%s)\n", - snd_strerror (rc)); - return NULL; - } - - running=TRUE; - while(running) { - if ((rc = snd_pcm_readi (record_handle, mic_buffer, mic_buffer_size)) != mic_buffer_size) { - if(running) { - if(rc<0) { - g_print("mic_read_thread: read from audio interface failed (%s)\n", - snd_strerror (rc)); - //running=FALSE; + int rc; + gfloat *float_buffer; + gint32 *long_buffer; + gint16 *short_buffer; + gfloat sample; + int i; + + g_print("mic_read_thread: mic_buffer_size=%d\n", mic_buffer_size); + g_print("mic_read_thread: snd_pcm_start\n"); + if ((rc = snd_pcm_start(record_handle)) < 0) { + g_print("mic_read_thread: cannot start audio interface for use (%s)\n", + snd_strerror(rc)); + return NULL; + } + + running = TRUE; + while (running) { + if ((rc = snd_pcm_readi(record_handle, mic_buffer, mic_buffer_size)) != + mic_buffer_size) { + if (running) { + if (rc < 0) { + g_print("mic_read_thread: read from audio interface failed " + "(%s)\n", + snd_strerror(rc)); + // running=FALSE; + } else { + g_print("mic_read_thread: read %d\n", rc); + } + } } else { - g_print("mic_read_thread: read %d\n",rc); - } - } - } else { - int newpt; - // process the mic input - for(i=0;i= 0 && card >= 0) { - int err = 0; - snd_ctl_t *handle; - char name[20]; - snprintf(name, sizeof(name), "hw:%d", card); - if ((err = snd_ctl_open(&handle, name, 0)) < 0) { - continue; - } - - if ((err = snd_ctl_card_info(handle, info)) < 0) { - snd_ctl_close(handle); - continue; - } + snd_ctl_card_info_t *info; + snd_pcm_info_t *pcminfo; + snd_ctl_card_info_alloca(&info); + snd_pcm_info_alloca(&pcminfo); + int i; + char *device_id; + int card = -1; + + g_print("%s\n", __FUNCTION__); + + n_input_devices = 0; + n_output_devices = 0; + + snd_ctl_card_info_alloca(&info); + snd_pcm_info_alloca(&pcminfo); + while (snd_card_next(&card) >= 0 && card >= 0) { + int err = 0; + snd_ctl_t *handle; + char name[20]; + snprintf(name, sizeof(name), "hw:%d", card); + if ((err = snd_ctl_open(&handle, name, 0)) < 0) { + continue; + } - int dev = -1; - - while (snd_ctl_pcm_next_device(handle, &dev) >= 0 && dev >= 0) { - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - - // input devices - snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); - if ((err = snd_ctl_pcm_info(handle, pcminfo)) == 0) { - device_id=g_new(char,128); - snprintf(device_id, 128, "plughw:%d,%d %s", card, dev, snd_ctl_card_info_get_name(info)); - if(n_input_devices= 0 && dev >= 0) { + snd_pcm_info_set_device(pcminfo, dev); + snd_pcm_info_set_subdevice(pcminfo, 0); + + // input devices + snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); + if ((err = snd_ctl_pcm_info(handle, pcminfo)) == 0) { + device_id = g_new(char, 128); + snprintf(device_id, 128, "plughw:%d,%d %s", card, dev, + snd_ctl_card_info_get_name(info)); + if (n_input_devices < MAX_AUDIO_DEVICES) { + input_devices[n_input_devices].name = + g_new0(char, strlen(device_id) + 1); + strcpy(input_devices[n_input_devices].name, device_id); + input_devices[n_input_devices].description = + g_new0(char, strlen(device_id) + 1); + strcpy(input_devices[n_input_devices].description, + device_id); + input_devices[n_input_devices].index = 0; // not used + n_input_devices++; + g_print("input_device: %s\n", device_id); + } + g_free(device_id); + } + + // ouput devices + snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); + if ((err = snd_ctl_pcm_info(handle, pcminfo)) == 0) { + device_id = g_new(char, 128); + snprintf(device_id, 128, "plughw:%d,%d %s", card, dev, + snd_ctl_card_info_get_name(info)); + if (n_output_devices < MAX_AUDIO_DEVICES) { + output_devices[n_output_devices].name = + g_new0(char, strlen(device_id) + 1); + strcpy(output_devices[n_output_devices].name, device_id); + output_devices[n_output_devices].description = + g_new0(char, strlen(device_id) + 1); + strcpy(output_devices[n_output_devices].description, + device_id); + input_devices[n_output_devices].index = 0; // not used + n_output_devices++; + g_print("output_device: %s\n", device_id); + } + g_free(device_id); + } } - g_free(device_id); - } + snd_ctl_close(handle); } - snd_ctl_close(handle); - } - - // look for dmix and dsnoop - void **hints, **n; - char *name, *descr, *io; - - if (snd_device_name_hint(-1, "pcm", &hints) < 0) - return; - n = hints; - while (*n != NULL) { - name = snd_device_name_get_hint(*n, "NAME"); - descr = snd_device_name_get_hint(*n, "DESC"); - io = snd_device_name_get_hint(*n, "IOID"); - - if(strncmp("dmix:", name, 5)==0) { - if(n_output_devices