aboutsummaryrefslogtreecommitdiffstats
path: root/src/AlsaInput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/AlsaInput.cpp')
-rw-r--r--src/AlsaInput.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/AlsaInput.cpp b/src/AlsaInput.cpp
new file mode 100644
index 0000000..fd1feec
--- /dev/null
+++ b/src/AlsaInput.cpp
@@ -0,0 +1,139 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2011 Martin Storsjo
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#include <cstdio>
+#include <string>
+
+#include <alsa/asoundlib.h>
+
+#include "AlsaInput.h"
+#include <sys/time.h>
+
+using namespace std;
+
+int AlsaInput::prepare()
+{
+ int err;
+ snd_pcm_hw_params_t *hw_params;
+
+ fprintf(stderr, "Initialising ALSA...\n");
+
+ const int open_mode = 0; //|= SND_PCM_NONBLOCK;
+
+ if ((err = snd_pcm_open(&m_alsa_handle, m_alsa_dev.c_str(),
+ SND_PCM_STREAM_CAPTURE, open_mode)) < 0) {
+ fprintf (stderr, "cannot open audio device %s (%s)\n",
+ m_alsa_dev.c_str(), snd_strerror(err));
+ return 1;
+ }
+
+ if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
+ fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
+ snd_strerror(err));
+ return 1;
+ }
+
+ if ((err = snd_pcm_hw_params_any(m_alsa_handle, hw_params)) < 0) {
+ fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
+ snd_strerror(err));
+ return 1;
+ }
+
+ if ((err = snd_pcm_hw_params_set_access(m_alsa_handle, hw_params,
+ SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ fprintf (stderr, "cannot set access type (%s)\n",
+ snd_strerror(err));
+ return 1;
+ }
+
+ if ((err = snd_pcm_hw_params_set_format(m_alsa_handle, hw_params,
+ SND_PCM_FORMAT_S16_LE)) < 0) {
+ fprintf (stderr, "cannot set sample format (%s)\n",
+ snd_strerror(err));
+ return 1;
+ }
+
+ if ((err = snd_pcm_hw_params_set_rate_near(m_alsa_handle,
+ hw_params, &m_rate, 0)) < 0) {
+ fprintf (stderr, "cannot set sample rate (%s)\n",
+ snd_strerror(err));
+ return 1;
+ }
+
+ if ((err = snd_pcm_hw_params_set_channels(m_alsa_handle,
+ hw_params, m_channels)) < 0) {
+ fprintf (stderr, "cannot set channel count (%s)\n",
+ snd_strerror(err));
+ return 1;
+ }
+
+ if ((err = snd_pcm_hw_params(m_alsa_handle, hw_params)) < 0) {
+ fprintf (stderr, "cannot set parameters (%s)\n",
+ snd_strerror(err));
+ return 1;
+ }
+
+ snd_pcm_hw_params_free (hw_params);
+
+ if ((err = snd_pcm_prepare(m_alsa_handle)) < 0) {
+ fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
+ snd_strerror(err));
+ return 1;
+ }
+
+ fprintf(stderr, "ALSA init done.\n");
+ return 0;
+}
+
+size_t AlsaInput::read(uint8_t* buf, snd_pcm_uframes_t length)
+{
+ int i;
+ int err;
+
+ err = snd_pcm_readi(m_alsa_handle, buf, length);
+
+ if (err != length) {
+ if (err < 0) {
+ fprintf (stderr, "read from audio interface failed (%s)\n",
+ snd_strerror(err));
+ }
+ else {
+ fprintf(stderr, "short alsa read: %d\n", err);
+ }
+ }
+
+ return err;
+}
+
+void AlsaInput::start()
+{
+ m_running = true;
+ m_thread = boost::thread(&AlsaInput::process, this);
+}
+
+void AlsaInput::process()
+{
+ uint8_t samplebuf[NUM_SAMPLES_PER_CALL * BYTES_PER_SAMPLE * m_channels];
+ while (m_running) {
+ size_t n = read(samplebuf, NUM_SAMPLES_PER_CALL);
+
+ m_queue.push(samplebuf, n);
+ }
+}
+