From 947d2db4b8fd49227f8a2bbdf76d1a1fe12f523a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Miguel=20S=C3=A1nchez=20Garc=C3=ADa?= Date: Sat, 27 Jan 2018 00:06:11 +0000 Subject: [PATCH 1/3] Implement sndio backend --- configure.ac | 14 +++++ src/Makefile.am | 1 + src/minimodem.1.in | 4 ++ src/minimodem.c | 18 +++++- src/simpleaudio-sndio.c | 124 +++++++++++++++++++++++++++++++++++++ src/simpleaudio.c | 10 ++- src/simpleaudio.h | 1 + src/simpleaudio_internal.h | 1 + 8 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 src/simpleaudio-sndio.c diff --git a/configure.ac b/configure.ac index 8ba3e19..32a5830 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,19 @@ AS_IF([test "x$with_pulseaudio" == "xno"], [ AC_DEFINE_UNQUOTED([USE_PULSEAUDIO], [$use_pulseaudio], [Define to 1 to enable pulseaudio support]) +# sndio +AC_ARG_WITH([sndio], AS_HELP_STRING([--without-sndio], + [build without sndio support])) +AS_IF([test "x$with_sndio" == "xno"], [ + use_sndio=0 +], [ + use_sndio=1 + AC_LANG_PUSH(C) + AC_CHECK_LIB(sndio, sio_start) +]) +AC_DEFINE_UNQUOTED([USE_SNDIO], [$use_sndio], + [Define to 1 to enable sndio support]) + # sndfile AC_ARG_WITH([sndfile], AS_HELP_STRING([--without-sndfile], [build without sndfile support])) @@ -68,6 +81,7 @@ option summary: benchmarks $with_benchmarks ($use_benchmarks) pulseaudio $with_pulseaudio ($use_pulseaudio) sndfile $with_sndfile ($use_sndfile) + sndio $with_sndio ($use_sndio) ]) # Checks for libraries. diff --git a/src/Makefile.am b/src/Makefile.am index b517d5a..387732c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,6 +35,7 @@ SIMPLEAUDIO_SRC = \ simple-tone-generator.c \ simpleaudio-pulse.c \ simpleaudio-alsa.c \ + simpleaudio-sndio.c \ simpleaudio-benchmark.c \ simpleaudio-sndfile.c diff --git a/src/minimodem.1.in b/src/minimodem.1.in index 0347b03..69b9dc4 100644 --- a/src/minimodem.1.in +++ b/src/minimodem.1.in @@ -157,6 +157,10 @@ device alias "default" is used, if a specific device is not specified. For example, the following options all select ALSA device #1, sub-device #0: \-\-alsa=plughw:1,0 \-\-alsa=1,0 \-A1 .TP +.B \-s, \-\-sndio[=device] +Use sndio as the audio output system. The default device is used if no +device is not specified. +.TP .B \-\-lut={tx_sin_table_len} Minimodem uses a precomputed sine wave lookup table of 1024 elements, or the size specified here. Use \-\-lut=0 to disable the use of diff --git a/src/minimodem.c b/src/minimodem.c index 838b1d0..1bd6701 100644 --- a/src/minimodem.c +++ b/src/minimodem.c @@ -414,6 +414,7 @@ usage() " -R, --samplerate {rate}\n" " -V, --version\n" " -A, --alsa[=plughw:X,Y]\n" + " -s, --sndio[=device]\n" " --lut={tx_sin_table_len}\n" " --float-samples\n" " --rx-one\n" @@ -550,10 +551,10 @@ main( int argc, char*argv[] ) bfsk_databits_encode = databits_encode_ascii8; /* validate the default system audio mechanism */ -#if !(USE_PULSEAUDIO || USE_ALSA) +#if !(USE_SNDIO || USE_PULSEAUDIO || USE_ALSA) # define _MINIMODEM_NO_SYSTEM_AUDIO # if !USE_SNDFILE -# error At least one of {USE_PULSEAUDIO,USE_ALSA,USE_SNDFILE} must be enabled! +# error At least one of {USE_SNDIO,USE_PULSEAUDIO,USE_ALSA,USE_SNDFILE} must be enabled! # endif #endif @@ -613,6 +614,7 @@ main( int argc, char*argv[] ) { "sync-byte", 1, 0, MINIMODEM_OPT_SYNC_BYTE }, { "quiet", 0, 0, 'q' }, { "alsa", 2, 0, 'A' }, + { "sndio", 2, 0, 's' }, { "samplerate", 1, 0, 'R' }, { "lut", 1, 0, MINIMODEM_OPT_LUT }, { "float-samples", 0, 0, MINIMODEM_OPT_FLOAT_SAMPLES }, @@ -626,7 +628,7 @@ main( int argc, char*argv[] ) { "tx-carrier", 0, 0, MINIMODEM_OPT_TXCARRIER }, { 0 } }; - c = getopt_long(argc, argv, "Vtrc:l:ai875f:b:v:M:S:T:qA::R:", + c = getopt_long(argc, argv, "Vtrc:l:ai875f:b:v:M:S:T:qs::A::R:", long_options, &option_index); if ( c == -1 ) break; @@ -725,6 +727,16 @@ main( int argc, char*argv[] ) #else fprintf(stderr, "E: This build of minimodem was configured without alsa support.\n"); exit(1); +#endif + break; + case 's': +#if USE_SNDIO + sa_backend = SA_BACKEND_SNDIO; + if ( optarg ) + sa_backend_device = optarg; +#else + fprintf(stderr, "E: This build of minimodem was configured without sndio support.\n"); + exit(1); #endif break; case MINIMODEM_OPT_LUT: diff --git a/src/simpleaudio-sndio.c b/src/simpleaudio-sndio.c new file mode 100644 index 0000000..444f369 --- /dev/null +++ b/src/simpleaudio-sndio.c @@ -0,0 +1,124 @@ +/* + * simpleaudio-sndio.c + * + * Copyright (C) 2011-2012 Kamal Mostafa + * + * 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 3 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if USE_SNDIO + +#include +#include +#include + +#include + +#include "simpleaudio.h" +#include "simpleaudio_internal.h" + + +/* + * sndio backend for simpleaudio + */ + + +static ssize_t +sa_sndio_read( simpleaudio *sa, void *buf, size_t nframes ) +{ + size_t nbytes = nframes * sa->backend_framesize; + sio_read((struct sio_hdl *)sa->backend_handle, buf, nbytes); + return nframes; +} + + +static ssize_t +sa_sndio_write( simpleaudio *sa, void *buf, size_t nframes ) +{ + size_t nbytes = nframes * sa->backend_framesize; + sio_write((struct sio_hdl *)sa->backend_handle, buf, nbytes); + return nframes; +} + + +static void +sa_sndio_close( simpleaudio *sa ) +{ + sio_stop(sa->backend_handle); +} + + +static int +sa_sndio_open_stream( + simpleaudio *sa, + const char *backend_device, + sa_direction_t sa_stream_direction, + sa_format_t sa_format, + unsigned int rate, unsigned int channels, + char *app_name, char *stream_name ) +{ + struct sio_hdl *hdl; + struct sio_par par; + + const char *be_device; + if ( ! backend_device ) + be_device = SIO_DEVANY; + else + be_device = backend_device; + + hdl = sio_open( + be_device, + sa_stream_direction == SA_STREAM_RECORD ? SIO_REC : SIO_PLAY, + 0 /* nbio_flag */); + sio_initpar(&par); + + switch ( sa->format ) { + case SA_SAMPLE_FORMAT_S16: + par.bits = 16; + par.sig = 1; + par.le = SIO_LE_NATIVE; + par.rate = rate; + par.xrun = SIO_IGNORE; + if ( SA_STREAM_RECORD ) + par.rchan = channels; + else + par.pchan = channels; + break; + default: + assert(0); + } + + par.bps = SIO_BPS(par.bits); + sio_setpar(hdl, &par); + sio_start(hdl); + + sa->backend_handle = hdl; + sa->backend_framesize = sa->channels * sa->samplesize; + + return 1; +} + + +const struct simpleaudio_backend simpleaudio_backend_sndio = { + sa_sndio_open_stream, + sa_sndio_read, + sa_sndio_write, + sa_sndio_close, +}; + +#endif /* USE_SNDIO */ diff --git a/src/simpleaudio.c b/src/simpleaudio.c index fe7c8b4..c4ead3b 100644 --- a/src/simpleaudio.c +++ b/src/simpleaudio.c @@ -80,7 +80,9 @@ simpleaudio_open_stream( #endif case SA_BACKEND_SYSDEFAULT: -#if USE_PULSEAUDIO +#if USE_SNDIO + sa->backend = &simpleaudio_backend_sndio; +#elif USE_PULSEAUDIO sa->backend = &simpleaudio_backend_pulseaudio; #elif USE_ALSA sa->backend = &simpleaudio_backend_alsa; @@ -102,6 +104,12 @@ simpleaudio_open_stream( break; #endif +#if USE_SNDIO + case SA_BACKEND_SNDIO: + sa->backend = &simpleaudio_backend_sndio; + break; +#endif + default: fprintf(stderr, "simpleaudio_open_stream: no such sa_backend (%d). not configured at build?\n", sa_backend); goto err_out; diff --git a/src/simpleaudio.h b/src/simpleaudio.h index 675796c..0fb36bf 100644 --- a/src/simpleaudio.h +++ b/src/simpleaudio.h @@ -38,6 +38,7 @@ typedef enum { SA_BACKEND_BENCHMARK, SA_BACKEND_ALSA, SA_BACKEND_PULSEAUDIO, + SA_BACKEND_SNDIO, } sa_backend_t; /* sa_stream_direction */ diff --git a/src/simpleaudio_internal.h b/src/simpleaudio_internal.h index 6928a51..acb5ee1 100644 --- a/src/simpleaudio_internal.h +++ b/src/simpleaudio_internal.h @@ -63,5 +63,6 @@ extern const struct simpleaudio_backend simpleaudio_backend_benchmark; extern const struct simpleaudio_backend simpleaudio_backend_sndfile; extern const struct simpleaudio_backend simpleaudio_backend_alsa; extern const struct simpleaudio_backend simpleaudio_backend_pulseaudio; +extern const struct simpleaudio_backend simpleaudio_backend_sndio; #endif From b7011614766907e96f26fff7350040b438eca976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Miguel=20S=C3=A1nchez=20Garc=C3=ADa?= Date: Sat, 27 Jan 2018 17:38:49 +0000 Subject: [PATCH 2/3] Add FIXME for lacking SA_SAMPLE_FORMAT_FLOAT --- src/simpleaudio-sndio.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/simpleaudio-sndio.c b/src/simpleaudio-sndio.c index 444f369..d23221b 100644 --- a/src/simpleaudio-sndio.c +++ b/src/simpleaudio-sndio.c @@ -92,18 +92,21 @@ sa_sndio_open_stream( par.bits = 16; par.sig = 1; par.le = SIO_LE_NATIVE; - par.rate = rate; - par.xrun = SIO_IGNORE; - if ( SA_STREAM_RECORD ) - par.rchan = channels; - else - par.pchan = channels; break; + // FIXME: Add support for SA_SAMPLE_FORMAT_FLOAT default: assert(0); } par.bps = SIO_BPS(par.bits); + par.rate = rate; + par.xrun = SIO_IGNORE; + + if ( SA_STREAM_RECORD ) + par.rchan = channels; + else + par.pchan = channels; + sio_setpar(hdl, &par); sio_start(hdl); From 7c0910e5adcf204dc4fa449d7521fe036159bee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Miguel=20S=C3=A1nchez=20Garc=C3=ADa?= Date: Sat, 27 Jan 2018 18:00:40 +0000 Subject: [PATCH 3/3] Fix equality in command in configure.ac --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 32a5830..463095e 100644 --- a/configure.ac +++ b/configure.ac @@ -42,7 +42,7 @@ AC_DEFINE_UNQUOTED([USE_PULSEAUDIO], [$use_pulseaudio], # sndio AC_ARG_WITH([sndio], AS_HELP_STRING([--without-sndio], [build without sndio support])) -AS_IF([test "x$with_sndio" == "xno"], [ +AS_IF([test "x$with_sndio" = "xno"], [ use_sndio=0 ], [ use_sndio=1