aboutsummaryrefslogtreecommitdiffstats
path: root/alsa-dabplus-zmq.c
diff options
context:
space:
mode:
Diffstat (limited to 'alsa-dabplus-zmq.c')
-rw-r--r--alsa-dabplus-zmq.c332
1 files changed, 104 insertions, 228 deletions
diff --git a/alsa-dabplus-zmq.c b/alsa-dabplus-zmq.c
index 14e6aa8..9fecc58 100644
--- a/alsa-dabplus-zmq.c
+++ b/alsa-dabplus-zmq.c
@@ -1,6 +1,6 @@
/* ------------------------------------------------------------------
* Copyright (C) 2011 Martin Storsjo
- * Copyright (C) 2013 Matthias P. Braendli
+ * Copyright (C) 2013,2014 Matthias P. Braendli
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,222 +69,124 @@ void usage(const char* name) {
}
-static int in_aborting = 0;
static snd_pcm_t *alsa_handle = NULL;
static void prg_exit(int code)
{
- if (alsa_handle)
- snd_pcm_close(alsa_handle);
+ if (alsa_handle) {
+ //snd_pcm_close(alsa_handle);
+ }
exit(code);
}
-static void signal_handler(int sig)
+static void alsa_prepare(const char* alsa_dev, unsigned int rate, unsigned int channels)
{
- if (in_aborting)
- return;
+ int err;
+ snd_pcm_hw_params_t *hw_params;
- in_aborting = 1;
- if (alsa_handle)
- snd_pcm_abort(alsa_handle);
+ fprintf(stderr, "Initialising ALSA...\n");
- if (sig == SIGABRT) {
- /* do not call snd_pcm_close() and abort immediately */
- alsa_handle = NULL;
- exit(EXIT_FAILURE);
+ const int open_mode = 0; //|= SND_PCM_NONBLOCK;
+
+ if ((err = snd_pcm_open(&alsa_handle, alsa_dev, SND_PCM_STREAM_CAPTURE, open_mode)) < 0) {
+ fprintf (stderr, "cannot open audio device %s (%s)\n",
+ alsa_dev, snd_strerror(err));
+ prg_exit(1);
+ }
+
+ const int nonblock = 0; //TODO remove dead code
+ if (nonblock) {
+ err = snd_pcm_nonblock(alsa_handle, 1);
+ if (err < 0) {
+ fprintf(stderr, "nonblock setting error: %s", snd_strerror(err));
+ prg_exit(1);
+ }
+ }
+
+ if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
+ fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
+ snd_strerror(err));
+ prg_exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_any(alsa_handle, hw_params)) < 0) {
+ fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
+ snd_strerror(err));
+ prg_exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_set_access(alsa_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ fprintf (stderr, "cannot set access type (%s)\n",
+ snd_strerror(err));
+ prg_exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_set_format(alsa_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+ fprintf (stderr, "cannot set sample format (%s)\n",
+ snd_strerror(err));
+ prg_exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_set_rate_near(alsa_handle, hw_params, &rate, 0)) < 0) {
+ fprintf (stderr, "cannot set sample rate (%s)\n",
+ snd_strerror(err));
+ prg_exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_set_channels(alsa_handle, hw_params, channels)) < 0) {
+ fprintf (stderr, "cannot set channel count (%s)\n",
+ snd_strerror(err));
+ prg_exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params(alsa_handle, hw_params)) < 0) {
+ fprintf (stderr, "cannot set parameters (%s)\n",
+ snd_strerror(err));
+ prg_exit(1);
+ }
+
+ snd_pcm_hw_params_free (hw_params);
+
+ if ((err = snd_pcm_prepare(alsa_handle)) < 0) {
+ fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
+ snd_strerror(err));
+ prg_exit(1);
}
- signal(sig, signal_handler);
-}
-const static int dump_hw_params = 0;
+ fprintf(stderr, "ALSA init done.\n");
+}
-// Set Alsa hardware parameters
-static void set_params(void)
+static size_t alsa_read(uint8_t* buf, snd_pcm_uframes_t length)
{
- snd_pcm_hw_params_t *params;
- snd_pcm_sw_params_t *swparams;
- snd_pcm_uframes_t buffer_size;
+ int i;
int err;
- size_t n;
- unsigned int rate;
- snd_pcm_uframes_t start_threshold, stop_threshold;
- snd_pcm_hw_params_alloca(&params);
- snd_pcm_sw_params_alloca(&swparams);
- err = snd_pcm_hw_params_any(alsa_handle, params);
- if (err < 0) {
- fprintf(stderr, "Broken configuration for this PCM: no configurations available");
- prg_exit(EXIT_FAILURE);
- }
- if (dump_hw_params) {
- fprintf(stderr, "HW Params of device \"%s\":\n",
- snd_pcm_name(alsa_handle));
- fprintf(stderr, "--------------------\n");
- // TODO log should be a snd_output_t *log;
- snd_pcm_hw_params_dump(params, log);
- fprintf(stderr, "--------------------\n");
- }
- err = snd_pcm_hw_params_set_access(alsa_handle, params,
- SND_PCM_ACCESS_RW_INTERLEAVED);
- if (err < 0) {
- fprintf(stderr, "Access type not available");
- prg_exit(EXIT_FAILURE);
- }
- err = snd_pcm_hw_params_set_format(alsa_handle, params, hwparams.format);
- if (err < 0) {
- fprintf(stderr, "Sample format non available");
- snd_pcm_format_t format;
-
- fprintf(stderr, "Available formats:\n");
- for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
- if (snd_pcm_hw_params_test_format(alsa_handle, params, format) == 0)
- fprintf(stderr, "- %s\n", snd_pcm_format_name(format));
- }
- prg_exit(EXIT_FAILURE);
- }
- err = snd_pcm_hw_params_set_channels(alsa_handle, params, hwparams.channels);
- if (err < 0) {
- fprintf(stderr, "Channels count non available");
- prg_exit(EXIT_FAILURE);
+
+ if ((err = snd_pcm_readi(alsa_handle, buf, length)) != length) {
+ fprintf (stderr, "read from audio interface failed (%s)\n",
+ snd_strerror(err));
}
-#if 0
- err = snd_pcm_hw_params_set_periods_min(alsa_handle, params, 2);
- assert(err >= 0);
-#endif
- rate = hwparams.rate;
- err = snd_pcm_hw_params_set_rate_near(alsa_handle, params, &hwparams.rate, 0);
- assert(err >= 0);
- if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) {
- char plugex[64];
- const char *pcmname = snd_pcm_name(alsa_handle);
- fprintf(stderr, "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n", rate, hwparams.rate);
- if (! pcmname || strchr(snd_pcm_name(alsa_handle), ':')) {
- *plugex = 0;
- }
- else {
- snprintf(plugex, sizeof(plugex), "(-Dplug:%s)",
- snd_pcm_name(alsa_handle));
- }
- fprintf(stderr, " please, try the plug plugin %s\n",
- plugex);
- }
- rate = hwparams.rate;
- if (buffer_time == 0 && buffer_frames == 0) {
- err = snd_pcm_hw_params_get_buffer_time_max(params,
- &buffer_time, 0);
- assert(err >= 0);
- if (buffer_time > 500000)
- buffer_time = 500000;
- }
- if (period_time == 0 && period_frames == 0) {
- if (buffer_time > 0)
- period_time = buffer_time / 4;
- else
- period_frames = buffer_frames / 4;
- }
- if (period_time > 0)
- err = snd_pcm_hw_params_set_period_time_near(alsa_handle, params,
- &period_time, 0);
- else
- err = snd_pcm_hw_params_set_period_size_near(alsa_handle, params,
- &period_frames, 0);
- assert(err >= 0);
- if (buffer_time > 0) {
- err = snd_pcm_hw_params_set_buffer_time_near(alsa_handle, params,
- &buffer_time, 0);
- } else {
- err = snd_pcm_hw_params_set_buffer_size_near(alsa_handle, params,
- &buffer_frames);
- }
- assert(err >= 0);
- monotonic = snd_pcm_hw_params_is_monotonic(params);
- can_pause = snd_pcm_hw_params_can_pause(params);
- err = snd_pcm_hw_params(alsa_handle, params);
- if (err < 0) {
- fprintf(stderr, "Unable to install hw params:");
- snd_pcm_hw_params_dump(params, log);
- prg_exit(EXIT_FAILURE);
- }
- snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
- snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
- if (chunk_size == buffer_size) {
- fprintf(stderr, "Can't use period equal to buffer size (%lu == %lu)",
- chunk_size, buffer_size);
- prg_exit(EXIT_FAILURE);
- }
- snd_pcm_sw_params_current(alsa_handle, swparams);
- if (avail_min < 0)
- n = chunk_size;
- else
- n = (double) rate * avail_min / 1000000;
- err = snd_pcm_sw_params_set_avail_min(alsa_handle, swparams, n);
-
- /* round up to closest transfer boundary */
- n = buffer_size;
- if (start_delay <= 0) {
- start_threshold = n + (double) rate * start_delay / 1000000;
- } else
- start_threshold = (double) rate * start_delay / 1000000;
- if (start_threshold < 1)
- start_threshold = 1;
- if (start_threshold > n)
- start_threshold = n;
- err = snd_pcm_sw_params_set_start_threshold(alsa_handle, swparams, start_threshold);
- assert(err >= 0);
- if (stop_delay <= 0)
- stop_threshold = buffer_size + (double) rate * stop_delay / 1000000;
- else
- stop_threshold = (double) rate * stop_delay / 1000000;
- err = snd_pcm_sw_params_set_stop_threshold(alsa_handle, swparams, stop_threshold);
- assert(err >= 0);
-
- if (snd_pcm_sw_params(alsa_handle, swparams) < 0) {
- fprintf(stderr, "unable to install sw params:");
- snd_pcm_sw_params_dump(swparams, log);
- prg_exit(EXIT_FAILURE);
- }
-
- if (setup_chmap())
- prg_exit(EXIT_FAILURE);
-
- if (verbose)
- snd_pcm_dump(alsa_handle, log);
-
- bits_per_sample = snd_pcm_format_physical_width(hwparams.format);
- bits_per_frame = bits_per_sample * hwparams.channels;
- chunk_bytes = chunk_size * bits_per_frame / 8;
- audiobuf = realloc(audiobuf, chunk_bytes);
- if (audiobuf == NULL) {
- fprintf(stderr, "not enough memory");
- prg_exit(EXIT_FAILURE);
- }
- // fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size);
-
- /* stereo VU-meter isn't always available... */
- if (vumeter == VUMETER_STEREO) {
- if (hwparams.channels != 2 || !interleaved || verbose > 2)
- vumeter = VUMETER_MONO;
- }
-
- /* show mmap buffer arragment */
- if (mmap_flag && verbose) {
- const snd_pcm_channel_area_t *areas;
- snd_pcm_uframes_t offset, size = chunk_size;
- int i;
- err = snd_pcm_mmap_begin(alsa_handle, &areas, &offset, &size);
- if (err < 0) {
- fprintf(stderr, "snd_pcm_mmap_begin problem: %s", snd_strerror(err));
- prg_exit(EXIT_FAILURE);
- }
- for (i = 0; i < hwparams.channels; i++)
- fprintf(stderr, "mmap_area[%i] = %p,%u,%u (%u)\n", i, areas[i].addr, areas[i].first, areas[i].step, snd_pcm_format_physical_width(hwparams.format));
- /* not required, but for sure */
- snd_pcm_mmap_commit(alsa_handle, offset, 0);
+ return err;
+}
+
+static void signal_handler(int sig)
+{
+ fprintf(stderr, "Caught signal %d\n", sig);
+ if (alsa_handle) {
+ snd_pcm_abort(alsa_handle);
+ alsa_handle = NULL;
}
- buffer_frames = buffer_size; /* for position test */
+ if (sig == SIGABRT) {
+ /* do not call snd_pcm_close() and abort immediately */
+ alsa_handle = NULL;
+ exit(EXIT_FAILURE);
+ }
+ signal(sig, signal_handler);
}
+
+
#define no_argument 0
#define required_argument 1
#define optional_argument 2
@@ -296,7 +198,7 @@ int main(int argc, char *argv[]) {
const char *alsa_device = "default";
const char *outuri = NULL;
int sample_rate=48000, channels=2;
- const int bits_per_sample = 16;
+ const int bytes_per_sample = 2;
uint8_t* input_buf;
int16_t* convert_buf;
void *rs_handler = NULL;
@@ -355,6 +257,7 @@ int main(int argc, char *argv[]) {
return 1;
}
+ fprintf(stderr, "Setting up ZeroMQ socket\n");
if (outuri) {
zmq_sock = zmq_socket(zmq_context, ZMQ_PUB);
if (zmq_sock == NULL) {
@@ -370,30 +273,7 @@ int main(int argc, char *argv[]) {
return 1;
}
-
- const int open_mode = 0; //|= SND_PCM_NONBLOCK;
- const snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
- const int nonblock = 0;
- snd_pcm_info_t *alsa_info;
-
- err = snd_pcm_open(&alsa_handle, alsa_device, stream, open_mode);
- if (err < 0) {
- fprintf(stderr, "audio open error: %s", snd_strerror(err));
- return 1;
- }
-
- if ((err = snd_pcm_info(alsa_handle, alsa_info)) < 0) {
- fprintf(stderr, "info error: %s", snd_strerror(err));
- prg_exit(1);
- }
-
- if (nonblock) {
- err = snd_pcm_nonblock(alsa_handle, 1);
- if (err < 0) {
- fprintf(stderr, "nonblock setting error: %s", snd_strerror(err));
- prg_exit(1);
- }
- }
+ alsa_prepare(alsa_device, sample_rate, channels);
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
@@ -498,7 +378,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "outbuf_size: %d\n", outbuf_size);
//outbuf_size += (4 * subchannel_index * (8*8)/8) - outbuf_size/5;
- fprintf(stderr, "outbuf_size: %d\n", outbuf_size);
+ //fprintf(stderr, "outbuf_size: %d\n", outbuf_size);
int frame=0;
int send_error_count = 0;
@@ -517,10 +397,8 @@ int main(int argc, char *argv[]) {
void *in_ptr, *out_ptr;
AACENC_ERROR err;
- // raw input
- if(fread(input_buf, input_size, 1, in_fh) == 1) {
- read = input_size;
- } else {
+ read = alsa_read(input_buf, input_size/bytes_per_sample) * bytes_per_sample;
+ if (read != input_size) {
fprintf(stderr, "Unable to read from input!\n");
break;
}
@@ -608,8 +486,6 @@ int main(int argc, char *argv[]) {
// break;
frame++;
}
- free(input_buf);
- free(convert_buf);
zmq_close(zmq_sock);
free_rs_char(rs_handler);