From 36fcb937e385cfd452c901d62d338a395d3ae2a5 Mon Sep 17 00:00:00 2001 From: Diane Bruce Date: Sat, 14 Jan 2006 15:47:35 +0000 Subject: [PATCH] - change from start_threads.c to start_alsa.c start_portaudio.c etc. - split start_threads.c into start_alsa.c and start_portaudio.c - make configure/Makefile add start_alsa or start_portaudio as needed instead of start_threads Untested on ALSA, works fine with PORTAUDIO git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/trunk@100 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- Makefile.in | 6 +- configure | 12 +- configure.ac | 9 +- start_alsa.c | 540 ++++++++++++++++++++++++++++++++++++++++++++++ start_portaudio.c | 27 +++ 5 files changed, 583 insertions(+), 11 deletions(-) create mode 100644 start_alsa.c create mode 100644 start_portaudio.c diff --git a/Makefile.in b/Makefile.in index 3d21cf93d..9716d9381 100644 --- a/Makefile.in +++ b/Makefile.in @@ -67,10 +67,10 @@ OBJS2C = ${SRCS2C:.c=.o} # ok, so far for now # Windows @AUDIO@ will be jtaudio.c since it uses portaudio -# for *nix @AUDIO@ will also be jtaudio.c and start_threads.c +# for *nix @AUDIO@ will also be jtaudio.c and start_portaudio.c # for portaudio -# for *nix @AUDIO@ will be start_threads.c for alsa -# for *nix @AUDIO@ will be ?? for oss +# for *nix @AUDIO@ will be start_alsa.c for alsa +# for *nix @AUDIO@ will be start_oss.c for oss # # ptt_unix.c vs. ptt.c I'll sort out later. # ditto for cutil.c (only used on *nix) diff --git a/configure b/configure index 3f2247535..25839794d 100755 --- a/configure +++ b/configure @@ -2,7 +2,7 @@ # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.53 for wsjt 0.9. # -# $Id: configure.ac 76 2006-01-10 16:36:04Z va3db $ +# $Id: configure.ac 82 2006-01-10 21:35:37Z va3db $ # # Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. @@ -924,7 +924,7 @@ Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. -$Id: configure.ac 76 2006-01-10 16:36:04Z va3db $ +$Id: configure.ac 82 2006-01-10 21:35:37Z va3db $ _ACEOF exit 0 fi @@ -5729,7 +5729,7 @@ cat >>confdefs.h <<\_ACEOF #define USE_ALSA 1 _ACEOF - AUDIO="start_threads.c" + AUDIO="start_alsa.c" LDFLAGS="${LDFLAGS} -lasound" CFLAGS="${CFLAGS} -DUSE_ALSA" @@ -5742,8 +5742,10 @@ cat >>confdefs.h <<\_ACEOF #define USE_OSS 1 _ACEOF - AUDIO="jtaudio.c" + AUDIO="jtaudio.c start_oss.c" + CFLAGS="${CFLAGS} -DUSE_OSS" + CPPFLAGS="${CPPFLAGS} -DUSE_OSS" fi if test "$portaudio" = yes; then @@ -5752,7 +5754,7 @@ cat >>confdefs.h <<\_ACEOF #define USE_PORTAUDIO 1 _ACEOF - AUDIO="jtaudio.c start_threads.c" + AUDIO="jtaudio.c start_portaudio.c" LDFLAGS="${LDFLAGS} -lportaudio -lsamplerate" CFLAGS="${CFLAGS} -DUSE_PORTAUDIO" diff --git a/configure.ac b/configure.ac index 2876e5a69..b4a273793 100644 --- a/configure.ac +++ b/configure.ac @@ -233,21 +233,24 @@ fi if test "$alsa" = yes; then AC_DEFINE(USE_ALSA, 1, [Define if you want ALSA used.]) - AC_SUBST(AUDIO, "start_threads.c") + AC_SUBST(AUDIO, "start_alsa.c") LDFLAGS="${LDFLAGS} -lasound" CFLAGS="${CFLAGS} -DUSE_ALSA" CPPFLAGS="${CPPFLAGS} -DUSE_ALSA" fi +dnl still not sure what OSS will require, but heres a first guess -db if test "$oss" = yes; then AC_DEFINE(USE_OSS, 1, [Define if you want OSS used.]) - AC_SUBST(AUDIO, "jtaudio.c") + AC_SUBST(AUDIO, "jtaudio.c start_oss.c") + CFLAGS="${CFLAGS} -DUSE_OSS" + CPPFLAGS="${CPPFLAGS} -DUSE_OSS" fi dnl XXX if test "$portaudio" = yes; then AC_DEFINE(USE_PORTAUDIO, 1, [Define if you want PORTAUDIO used.]) - AC_SUBST(AUDIO, "jtaudio.c start_threads.c") + AC_SUBST(AUDIO, "jtaudio.c start_portaudio.c") LDFLAGS="${LDFLAGS} -lportaudio -lsamplerate" CFLAGS="${CFLAGS} -DUSE_PORTAUDIO" CPPFLAGS="${CPPFLAGS} -DUSE_PORTAUDIO" diff --git a/start_alsa.c b/start_alsa.c new file mode 100644 index 000000000..c067c79ba --- /dev/null +++ b/start_alsa.c @@ -0,0 +1,540 @@ +#include +#include +#include +#include +#include +#include +#include "conf.h" + +#if 0 +#define ALSA_LOG +#define ALSA_LOG_BUFFERS +#endif +#if 0 +#define ALSA_PLAYBACK_LOG +#define ALSA_CAPTURE_LOG +#endif +#define BUFFER_TIME 2000*1000 + + +typedef struct alsa_driver_s { + snd_pcm_t *audio_fd; + int capabilities; + int open_mode; + int has_pause_resume; + int is_paused; + int32_t output_sample_rate, input_sample_rate; + double sample_rate_factor; + uint32_t num_channels; + uint32_t bits_per_sample; + uint32_t bytes_per_frame; + uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */ + int16_t *app_buffer_y1; + int16_t *app_buffer_y2; + int *app_buffer_offset; + int app_buffer_length; + double *Tsec; + double *tbuf; + int *ibuf; + int *ndsec; + int *tx_ok; + int tx_starting; + int tx_offset; + int *tr_period; + int *nwave; + int *nmode; + int *transmitting; + + snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; + int32_t mmap; +} alsa_driver_t; + +alsa_driver_t alsa_driver_playback; +alsa_driver_t alsa_driver_capture; +void *alsa_capture_buffers[2]; +void *alsa_playback_buffers[2]; + +static snd_output_t *jcd_out; + +/* + * open the audio device for writing to + */ +static int ao_alsa_open(alsa_driver_t *this_gen, int32_t *input_rate, snd_pcm_stream_t direction ) { + alsa_driver_t *this = (alsa_driver_t *) this_gen; + char *pcm_device; + snd_pcm_hw_params_t *params; + snd_pcm_sw_params_t *swparams; + snd_pcm_access_mask_t *mask; + snd_pcm_uframes_t period_size_min; + snd_pcm_uframes_t period_size_max; + snd_pcm_uframes_t buffer_size_min; + snd_pcm_uframes_t buffer_size_max; + snd_pcm_format_t format; + uint32_t buffer_time=BUFFER_TIME; + snd_pcm_uframes_t buffer_time_to_size; + int err, dir; + int open_mode=1; /* NONBLOCK */ + /* int open_mode=0; BLOCK */ + int32_t rate=*input_rate; + this->input_sample_rate=*input_rate; + + snd_pcm_hw_params_alloca(¶ms); + snd_pcm_sw_params_alloca(&swparams); + err = snd_output_stdio_attach(&jcd_out, stdout, 0); + + this->num_channels = 2; + pcm_device="default"; +#ifdef ALSA_LOG + printf("audio_alsa_out: Audio Device name = %s\n",pcm_device); + printf("audio_alsa_out: Number of channels = %d\n",this->num_channels); +#endif + + if (this->audio_fd) { + printf("audio_alsa_out:Already open...WHY!"); + snd_pcm_close (this->audio_fd); + this->audio_fd = NULL; + } + + this->bytes_in_buffer = 0; + /* + * open audio device + */ + err=snd_pcm_open(&this->audio_fd, pcm_device, direction, open_mode); + if(err <0 ) { + printf ("audio_alsa_out: snd_pcm_open() of %s failed: %s\n", pcm_device, snd_strerror(err)); + printf ("audio_alsa_out: >>> check if another program already uses PCM <<<\n"); + return 0; + } + /* printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); */ + /* We wanted non blocking open but now put it back to normal */ + //snd_pcm_nonblock(this->audio_fd, 0); + snd_pcm_nonblock(this->audio_fd, 1); + /* + * configure audio device + */ + err = snd_pcm_hw_params_any(this->audio_fd, params); + if (err < 0) { + printf ("audio_alsa_out: broken configuration for this PCM: no configurations available: %s\n"), + snd_strerror(err); + goto close; + } + /* set interleaved access */ + if (this->mmap != 0) { + mask = alloca(snd_pcm_access_mask_sizeof()); + snd_pcm_access_mask_none(mask); + snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED); + snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); + snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX); + err = snd_pcm_hw_params_set_access_mask(this->audio_fd, params, mask); + if (err < 0) { + printf ( "audio_alsa_out: mmap not availiable, falling back to compatiblity mode\n"); + this->mmap=0; + err = snd_pcm_hw_params_set_access(this->audio_fd, params, + SND_PCM_ACCESS_RW_NONINTERLEAVED); + } + } else { + err = snd_pcm_hw_params_set_access(this->audio_fd, params, + SND_PCM_ACCESS_RW_NONINTERLEAVED); + } + + if (err < 0) { + printf ( "audio_alsa_out: access type not available: %s\n", snd_strerror(err)); + goto close; + } + /* set the sample format S16 */ + /* ALSA automatically appends _LE or _BE depending on the CPU */ + format = SND_PCM_FORMAT_S16; + err = snd_pcm_hw_params_set_format(this->audio_fd, params, format ); + if (err < 0) { + printf ( "audio_alsa_out: sample format non available: %s\n", snd_strerror(err)); + goto close; + } + /* set the number of channels */ + err = snd_pcm_hw_params_set_channels(this->audio_fd, params, this->num_channels); + if (err < 0) { + printf ( "audio_alsa_out: Cannot set number of channels to %d (err=%d:%s)\n", + this->num_channels, err, snd_strerror(err)); + goto close; + } +#if SND_LIB_VERSION >= 0x010009 + /* Restrict a configuration space to contain only real hardware rates */ + err = snd_pcm_hw_params_set_rate_resample(this->audio_fd, params, 0); +#endif + /* set the stream rate [Hz] */ + dir=0; + err = snd_pcm_hw_params_set_rate_near(this->audio_fd, params, &rate, &dir); + if (err < 0) { + printf ( "audio_alsa_out: rate not available: %s\n", snd_strerror(err)); + goto close; + } + this->output_sample_rate = (uint32_t)rate; + if (this->input_sample_rate != this->output_sample_rate) { + printf ( "audio_alsa_out: audio rate : %d requested, %d provided by device/sec\n", + this->input_sample_rate, this->output_sample_rate); + } + buffer_time_to_size = ( (uint64_t)buffer_time * rate) / 1000000; + err = snd_pcm_hw_params_get_buffer_size_min(params, &buffer_size_min); + err = snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size_max); + dir=0; + err = snd_pcm_hw_params_get_period_size_min(params, &period_size_min,&dir); + dir=0; + err = snd_pcm_hw_params_get_period_size_max(params, &period_size_max,&dir); +#ifdef ALSA_LOG_BUFFERS + printf("Buffer size range from %lu to %lu\n",buffer_size_min, buffer_size_max); + printf("Period size range from %lu to %lu\n",period_size_min, period_size_max); + printf("Buffer time size %lu\n",buffer_time_to_size); +#endif + this->buffer_size = buffer_time_to_size; + if (buffer_size_max < this->buffer_size) + this->buffer_size = buffer_size_max; + if (buffer_size_min > this->buffer_size) + this->buffer_size = buffer_size_min; + this->period_size = this->buffer_size/8; + if (this->period_size > 2048) + this->period_size = 2048; + this->buffer_size = this->period_size*8; +#ifdef ALSA_LOG_BUFFERS + printf("To choose buffer_size = %ld\n",this->buffer_size); + printf("To choose period_size = %ld\n",this->period_size); +#endif + +#if 0 + /* Set period to buffer size ratios at 8 periods to 1 buffer */ + dir=-1; + periods=8; + err = snd_pcm_hw_params_set_periods_near(this->audio_fd, params, &periods ,&dir); + if (err < 0) { + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + "audio_alsa_out: unable to set any periods: %s\n", snd_strerror(err)); + goto close; + } + /* set the ring-buffer time [us] (large enough for x us|y samples ...) */ + dir=0; + err = snd_pcm_hw_params_set_buffer_time_near(this->audio_fd, params, &buffer_time, &dir); + if (err < 0) { + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + "audio_alsa_out: buffer time not available: %s\n", snd_strerror(err)); + goto close; + } +#endif +#if 1 + /* set the period time [us] (interrupt every x us|y samples ...) */ + dir=0; + err = snd_pcm_hw_params_set_period_size_near(this->audio_fd, params, &(this->period_size), &dir); + if (err < 0) { + printf ( "audio_alsa_out: period time not available: %s\n", snd_strerror(err)); + goto close; + } +#endif + dir=0; + err = snd_pcm_hw_params_get_period_size(params, &(this->period_size), &dir); + + dir=0; + err = snd_pcm_hw_params_set_buffer_size_near(this->audio_fd, params, &(this->buffer_size)); + if (err < 0) { + printf ( "audio_alsa_out: buffer time not available: %s\n", snd_strerror(err)); + goto close; + } + err = snd_pcm_hw_params_get_buffer_size(params, &(this->buffer_size)); +#ifdef ALSA_LOG_BUFFERS + printf("was set period_size = %ld\n",this->period_size); + printf("was set buffer_size = %ld\n",this->buffer_size); +#endif + if (2*this->period_size > this->buffer_size) { + printf ( "audio_alsa_out: buffer to small, could not use\n"); + goto close; + } + + /* write the parameters to device */ + err = snd_pcm_hw_params(this->audio_fd, params); + if (err < 0) { + printf ( "audio_alsa_out: pcm hw_params failed: %s\n", snd_strerror(err)); + goto close; + } + /* Check for pause/resume support */ + this->has_pause_resume = ( snd_pcm_hw_params_can_pause (params) + && snd_pcm_hw_params_can_resume (params) ); + // printf( "audio_alsa_out:open pause_resume=%d\n", this->has_pause_resume); + this->sample_rate_factor = (double) this->output_sample_rate / (double) this->input_sample_rate; + this->bytes_per_frame = snd_pcm_frames_to_bytes (this->audio_fd, 1); + /* + * audio buffer size handling + */ + /* Copy current parameters into swparams */ + err = snd_pcm_sw_params_current(this->audio_fd, swparams); + if (err < 0) { + printf ( "audio_alsa_out: Unable to determine current swparams: %s\n", snd_strerror(err)); + goto close; + } + /* align all transfers to 1 sample */ + err = snd_pcm_sw_params_set_xfer_align(this->audio_fd, swparams, 1); + if (err < 0) { + printf ( "audio_alsa_out: Unable to set transfer alignment: %s\n", snd_strerror(err)); + goto close; + } + /* allow the transfer when at least period_size samples can be processed */ + err = snd_pcm_sw_params_set_avail_min(this->audio_fd, swparams, this->period_size); + if (err < 0) { + printf ( "audio_alsa_out: Unable to set available min: %s\n", snd_strerror(err)); + goto close; + } + if (direction == SND_PCM_STREAM_PLAYBACK) { + /* start the transfer when the buffer contains at least period_size samples */ + err = snd_pcm_sw_params_set_start_threshold(this->audio_fd, swparams, this->buffer_size); + } else { + err = snd_pcm_sw_params_set_start_threshold(this->audio_fd, swparams, -1); + } + if (err < 0) { + printf ( "audio_alsa_out: Unable to set start threshold: %s\n", snd_strerror(err)); + goto close; + } + + if (direction == SND_PCM_STREAM_PLAYBACK) { + /* never stop the transfer, even on xruns */ + err = snd_pcm_sw_params_set_stop_threshold(this->audio_fd, swparams, this->buffer_size); + } else { + err = snd_pcm_sw_params_set_stop_threshold(this->audio_fd, swparams, this->buffer_size); + } + if (err < 0) { + printf ( "audio_alsa_out: Unable to set stop threshold: %s\n", snd_strerror(err)); + goto close; + } + + /* Install swparams into current parameters */ + err = snd_pcm_sw_params(this->audio_fd, swparams); + if (err < 0) { + printf ( "audio_alsa_out: Unable to set swparams: %s\n", snd_strerror(err)); + goto close; + } +#ifdef ALSA_LOG + snd_pcm_dump_setup(this->audio_fd, jcd_out); + snd_pcm_sw_params_dump(swparams, jcd_out); +#endif + + return this->output_sample_rate; + +close: + snd_pcm_close (this->audio_fd); + this->audio_fd=NULL; + return 0; +} + +int16_t zero_buffer[65536]; + +int playback_callback(alsa_driver_t *alsa_driver_playback) { + alsa_driver_t *this = alsa_driver_playback; + int result; + struct timeval tv; + double stime; + int nsec; + int i,n; + static int ic; + int16_t b0[2048]; + +// printf("playback callback\n"); + gettimeofday(&tv, NULL); + stime = (double) tv.tv_sec + ((double)tv.tv_usec / 1000000.0) + + *(this->ndsec) * 0.1; + *(this->Tsec) = stime; + if(!(this->tx_starting) && (*(this->tx_ok)) ) { + nsec = (int)stime; + n = nsec / *(this->tr_period); + ic = (int)(stime - *(this->tr_period) * n) * this->output_sample_rate; + ic = ic % *(this->nwave); + this->tx_offset = ic; + } + this->tx_starting = *(this->tx_ok); + *(this->transmitting) = *(this->tx_ok); + if(*(this->tx_ok)) { + /* + alsa_playback_buffers[0] = this->app_buffer_y1 + this->tx_offset; + alsa_playback_buffers[1] = this->app_buffer_y1 + this->tx_offset; + */ + alsa_playback_buffers[0] = b0; + alsa_playback_buffers[1] = b0; + for(i=0; iperiod_size; i++) { + b0[i]=this->app_buffer_y1[ic]; + ic++; + if(ic >= *this->nwave) { + ic=ic % *this->nwave; + if(*this->nmode == 2) + *this->tx_ok=0; + } + } + } else { + alsa_playback_buffers[0] = zero_buffer; + alsa_playback_buffers[1] = zero_buffer; + } + result = snd_pcm_writen(this->audio_fd, alsa_playback_buffers, this->period_size); + this->tx_offset += this->period_size; + if (result != this->period_size) { + printf("playback writei failed. Expected %d samples, sent only %d\n", this->period_size, result); +#ifdef ALSA_PLAYBACK_LOG + snd_pcm_status_t *pcm_stat; + snd_pcm_status_alloca(&pcm_stat); + snd_pcm_status(this->audio_fd, pcm_stat); + snd_pcm_status_dump(pcm_stat, jcd_out); +#endif + } + fivehztx_(); //Call fortran routine +} + +int capture_callback(alsa_driver_t *alsa_driver_capture) { + alsa_driver_t *this = alsa_driver_capture; + int result; + struct timeval tv; + double stime; + int ib; +#ifdef ALSA_CAPTURE_LOG + printf("capture callback %d samples\n", this->period_size); +#endif +#ifdef ALSA_CAPTURE_LOG + snd_pcm_status_t *pcm_stat; + snd_pcm_status_alloca(&pcm_stat); + snd_pcm_status(this->audio_fd, pcm_stat); + snd_pcm_status_dump(pcm_stat, jcd_out); +#endif + gettimeofday(&tv, NULL); + stime = (double) tv.tv_sec + ((double)tv.tv_usec / 1000000.0) + + *(this->ndsec) * 0.1; + *(this->Tsec) = stime; + ib=*(this->ibuf); + this->tbuf[ib++] = stime; + if(ib>=1024) + ib = 0; + *(this->ibuf) = ib; + + alsa_capture_buffers[0]=this->app_buffer_y1 + *(this->app_buffer_offset); + alsa_capture_buffers[1]=this->app_buffer_y2 + *(this->app_buffer_offset); + result = snd_pcm_readn(this->audio_fd, alsa_capture_buffers, this->period_size); + *(this->app_buffer_offset) += this->period_size; + if ( *(this->app_buffer_offset) >= this->app_buffer_length ) + *(this->app_buffer_offset)=0; /* FIXME: implement proper wrapping */ +#ifdef ALSA_CAPTURE_LOG + printf("result=%d\n",result); + snd_pcm_status(this->audio_fd, pcm_stat); + snd_pcm_status_dump(pcm_stat, jcd_out); +#endif + fivehz_(); //Call fortran routine +} + +int playback_xrun(alsa_driver_t *alsa_driver_playback) { + alsa_driver_t *this = alsa_driver_playback; + snd_pcm_status_t *pcm_stat; + snd_pcm_status_alloca(&pcm_stat); + printf("playback xrun\n"); + snd_pcm_status(this->audio_fd, pcm_stat); + snd_pcm_status_dump(pcm_stat, jcd_out); + snd_pcm_prepare(this->audio_fd); +} + +int capture_xrun(alsa_driver_t *alsa_driver_capture) { + alsa_driver_t *this = alsa_driver_capture; + snd_pcm_status_t *pcm_stat; + snd_pcm_status_alloca(&pcm_stat); + printf("capture xrun\n"); + snd_pcm_status(this->audio_fd, pcm_stat); + snd_pcm_status_dump(pcm_stat, jcd_out); +} + +void ao_alsa_loop(void *iarg) { + int playback_nfds; + int capture_nfds; + struct pollfd *pfd; + int nfds; + int capture_index; + unsigned short playback_revents; + unsigned short capture_revents; + playback_nfds = snd_pcm_poll_descriptors_count ( + alsa_driver_playback.audio_fd); + capture_nfds = snd_pcm_poll_descriptors_count ( + alsa_driver_capture.audio_fd); + pfd = (struct pollfd *) malloc (sizeof (struct pollfd) * + (playback_nfds + capture_nfds)); + + nfds=0; + snd_pcm_poll_descriptors (alsa_driver_playback.audio_fd, + &pfd[0], + playback_nfds); + nfds += playback_nfds; + snd_pcm_poll_descriptors (alsa_driver_capture.audio_fd, + &pfd[nfds], + capture_nfds); + capture_index = nfds; + nfds += capture_nfds; + while(1) { + if (poll (pfd, nfds, 100000) < 0) { + printf("poll failed\n"); + return; + } + snd_pcm_poll_descriptors_revents(alsa_driver_playback.audio_fd, &pfd[0], playback_nfds, &playback_revents); + snd_pcm_poll_descriptors_revents(alsa_driver_capture.audio_fd, &pfd[capture_index], capture_nfds, &capture_revents); + //if ((playback_revents & POLLERR) || ((capture_revents) & POLLERR)) { + if (((capture_revents) & POLLERR)) { + printf("pollerr\n"); + capture_xrun(&alsa_driver_capture); + return; + } + if (((playback_revents) & POLLERR)) { + printf("pollerr\n"); + playback_xrun(&alsa_driver_capture); + return; + } + if (playback_revents & POLLOUT) { + playback_callback(&alsa_driver_playback); + } + if (capture_revents & POLLIN) { + capture_callback(&alsa_driver_capture); + } + } + + return; +} + +extern void decode1_(int *iarg); + +int start_threads_(int *ndevin, int *ndevout, short y1[], short y2[], + int *nbuflen, int *iwrite, short iwave[], + int *nwave, int *nfsample, int *nsamperbuf, + int *TRPeriod, int *TxOK, int *ndebug, + int *Transmitting, double *Tsec, int *ngo, int *nmode, + double tbuf[], int *ibuf, int *ndsec) +{ + pthread_t thread1,thread2; + int iret1,iret2; + int iarg1 = 1,iarg2 = 2; + //int32_t rate=11025; + int32_t rate=*nfsample; + alsa_driver_capture.app_buffer_y1 = y1; + alsa_driver_capture.app_buffer_y2 = y2; + alsa_driver_capture.app_buffer_offset = iwrite; + alsa_driver_capture.app_buffer_length = *nbuflen; + alsa_driver_capture.Tsec = Tsec; + alsa_driver_capture.tbuf = tbuf; + alsa_driver_capture.ibuf = ibuf; + alsa_driver_capture.ndsec = ndsec; + alsa_driver_playback.Tsec = Tsec; + alsa_driver_playback.app_buffer_y1 = iwave; + alsa_driver_playback.tx_ok = TxOK; + alsa_driver_playback.tr_period = TRPeriod; + alsa_driver_playback.nwave = nwave; + alsa_driver_playback.nmode = nmode; + alsa_driver_playback.transmitting = Transmitting; + alsa_driver_playback.ndsec = ndsec; + // printf("start_threads: creating thread for decode1\n"); + iret1 = pthread_create(&thread1,NULL,decode1_,&iarg1); +/* Open audio card. */ + printf("Starting alsa routines.\n"); + ao_alsa_open(&alsa_driver_playback, &rate, SND_PCM_STREAM_PLAYBACK); + ao_alsa_open(&alsa_driver_capture, &rate, SND_PCM_STREAM_CAPTURE); + +/* + * Start audio io thread + */ + iret2 = pthread_create(&thread2, NULL, ao_alsa_loop, NULL); + snd_pcm_prepare(alsa_driver_capture.audio_fd); + snd_pcm_start(alsa_driver_capture.audio_fd); + snd_pcm_prepare(alsa_driver_playback.audio_fd); + //snd_pcm_start(alsa_driver_playback.audio_fd); +} diff --git a/start_portaudio.c b/start_portaudio.c new file mode 100644 index 000000000..5a845a222 --- /dev/null +++ b/start_portaudio.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include "conf.h" + +extern void decode1_(int *iarg); +extern void a2d_(int *iarg); + +int start_threads_(int *ndevin, int *ndevout, short y1[], short y2[], + int *nbuflen, int *iwrite, short iwave[], + int *nwave, int *nfsample, int *nsamperbuf, + int *TRPeriod, int *TxOK, int *ndebug, + int *Transmitting, double *Tsec, int *ngo, int *nmode, + double tbuf[], int *ibuf, int *ndsec) +{ + pthread_t thread1,thread2; + int iret1,iret2; + int iarg1 = 1,iarg2 = 2; + + /* snd_pcm_start */ + // printf("start_threads: creating thread for a2d\n"); + iret1 = pthread_create(&thread1,NULL,a2d_,&iarg1); + // printf("start_threads: creating thread for decode1_\n"); + iret2 = pthread_create(&thread2,NULL,decode1_,&iarg2); +}