summaryrefslogtreecommitdiff
path: root/src/audioin.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/audioin.cc')
-rw-r--r--src/audioin.cc445
1 files changed, 0 insertions, 445 deletions
diff --git a/src/audioin.cc b/src/audioin.cc
deleted file mode 100644
index cc6fffc..0000000
--- a/src/audioin.cc
+++ /dev/null
@@ -1,445 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/***************************************************************************
- * audioin.cc
- *
- * Wed Sep 30 11:36:18 CEST 2009
- * Copyright 2011 Bent Bisballe Nyeng
- * deva@aasimon.org
- ****************************************************************************/
-
-/*
- * This file is part of libaudioin.
- *
- * libaudioin 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.
- *
- * libaudioin 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 libaudioin; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-#include "audioin.h"
-
-// Use the newer ALSA API
-#define ALSA_PCM_NEW_HW_PARAMS_API
-
-#include <asoundlib.h>
-#include <exception>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string>
-
-class AudioIn {
-public:
- class CouldNotOpenPCMDevice : public std::exception {};
- class UnableToSetHWParams : public std::exception {};
- class PcmBufferTooSmall : public std::exception {};
- class OverRun : public std::exception {};
- class ReadError : public std::exception {};
- class ShortRead : public std::exception {};
- class CouldNotInitialiseParams : public std::exception {};
- class CouldNotSetAccessMode : public std::exception {};
- class CouldNotSetFormat : public std::exception {};
- class CouldNotSetChannelNumber : public std::exception {};
- class UnableToSetSampleRate : public std::exception {};
- class UnableToSetPeriodSize : public std::exception {};
- class MixerInitilisationFailed : public std::exception {};
- class MixerNotInitialised : public std::exception {};
- class InvalidMixerLevel : public std::exception {};
- class IllegalChannelNumber : public std::exception {};
- class CouldNotSetMixerLevel : public std::exception {};
-
- AudioIn(std::string device, std::string mixer, unsigned int srate, int ch);
- ~AudioIn();
-
- /**
- * Reads a number of samples from the soundcard.
- * The returned signal is a 16bit mono pcm signal.
- */
- size_t read(void *buf, size_t size);
-
- int set_level(unsigned int channel, float level);
-
- unsigned int get_samplerate();
-
- void set_enable_noise_fix(bool fixit);
-
-private:
- bool noisefix;
- unsigned int samplerate;
- int channels;
- snd_pcm_t *handle;
- snd_pcm_hw_params_t *params;
- unsigned int val;
- int dir;
- snd_pcm_uframes_t frames;
-
- snd_mixer_t *mixhnd;
- snd_mixer_elem_t *elem;
- long lvl_min, lvl_max;
-};
-
-AudioIn::AudioIn(std::string device, std::string mixer_interface,
- unsigned int srate, int ch)
-{
- int open_mode = 0;
- //open_mode |= SND_PCM_NONBLOCK;
- //open_mode |= SND_PCM_NO_AUTO_RESAMPLE;
- //open_mode |= SND_PCM_NO_AUTO_CHANNELS;
- //open_mode |= SND_PCM_NO_AUTO_FORMAT;
- //open_mode |= SND_PCM_NO_SOFTVOL;
- elem = NULL;
- mixhnd = NULL;
-
- noisefix = false;
-
- samplerate = 0;
-
- int rc;
-
- // Open PCM device for recording (capture).
- rc = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_CAPTURE, open_mode);
- if (rc < 0) throw CouldNotOpenPCMDevice();
-
- // Allocate a hardware parameters object.
- snd_pcm_hw_params_alloca(&params);
-
- // Fill it in with default values.
- rc = snd_pcm_hw_params_any(handle, params);
- if (rc < 0) throw CouldNotInitialiseParams();
-
- // Set the desired hardware parameters.
-
- // Interleaved mode
- rc = snd_pcm_hw_params_set_access(handle, params,
- SND_PCM_ACCESS_RW_INTERLEAVED);
- if (rc < 0) throw CouldNotSetAccessMode();
-
- // Signed 16-bit little-endian format
- rc = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
- if (rc < 0) throw CouldNotSetFormat();
-
- // Set channels (stereo/mono)
- rc = snd_pcm_hw_params_set_channels(handle, params, ch);
- channels = ch;
- if (rc < 0) throw CouldNotSetChannelNumber();
-
- // Set sampling rate
- samplerate = srate;
- rc = snd_pcm_hw_params_set_rate_near(handle, params, &samplerate, &dir);
- if(rc < 0) throw UnableToSetSampleRate();
- //if(samplerate != srate) throw UnableToSetSampleRate();
-
- // NOTE: Setting period size to 32 frames will force use of lowest possible value.
- frames = 512;
- rc = snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
- if(rc < 0) throw UnableToSetPeriodSize();
-
- // Write the parameters to the driver
- rc = snd_pcm_hw_params(handle, params);
- if (rc < 0) throw UnableToSetHWParams();
-
- if(mixer_interface == "") return;
-
- //
- // Set up mixer
- //
- snd_mixer_selem_id_t *mixer;
-
- // Open mixer device
- if(snd_mixer_open(&mixhnd, 0) != 0) throw MixerInitilisationFailed();
-
- if(snd_mixer_attach(mixhnd, device.c_str()) != 0)
- throw MixerInitilisationFailed();
-
- if(snd_mixer_selem_register(mixhnd, NULL, NULL) < 0)
- throw MixerInitilisationFailed();
-
- if(snd_mixer_load(mixhnd) < 0)
- throw MixerInitilisationFailed();
-
- // Obtain mixer element
- snd_mixer_selem_id_alloca(&mixer);
- if(mixer == NULL) throw MixerInitilisationFailed();
- snd_mixer_selem_id_set_name(mixer, mixer_interface.c_str());
-
- elem = snd_mixer_find_selem(mixhnd, mixer);
- if(elem == NULL) throw MixerInitilisationFailed();
-
- if(snd_mixer_selem_get_capture_volume_range(elem, &lvl_min, &lvl_max) != 0) {
- throw MixerInitilisationFailed();
- }
-
- if(snd_mixer_selem_set_capture_switch(elem,
- SND_MIXER_SCHN_FRONT_LEFT, 1) != 0) {
- throw MixerInitilisationFailed();
- }
-
- if(snd_mixer_selem_set_capture_switch(elem,
- SND_MIXER_SCHN_FRONT_RIGHT, 1) != 0) {
- throw MixerInitilisationFailed();
- }
-
- // Obtain mixer enumeration element "Input Source" and set it to 2 (line).
- snd_mixer_selem_id_set_name(mixer, "Input Source");
-
- snd_mixer_elem_t *iselem = snd_mixer_find_selem(mixhnd, mixer);
- if(iselem == NULL) return;
-
- if(snd_mixer_selem_is_enumerated(iselem)) {
- // Set to line-in
- for(int i = 0; i < 3; i++) {
- char name[16];
- snd_mixer_selem_get_enum_item_name(iselem, i, sizeof(name), name);
- if(std::string(name) == "Line") {
- snd_mixer_selem_set_enum_item(iselem, SND_MIXER_SCHN_MONO, i);
- }
- }
- }
-}
-
-AudioIn::~AudioIn()
-{
- if(handle) {
- snd_pcm_drain(handle);
- snd_pcm_close(handle);
- }
- if(mixhnd) snd_mixer_close(mixhnd);
-}
-
-size_t AudioIn::read(void *buf, size_t size)
-{
- int rc;
-
- if(size < frames * sizeof(short) * channels) {
- throw PcmBufferTooSmall();
- }
-
- rc = snd_pcm_readi(handle, buf, frames);
- if (rc == -EPIPE) {
- // EPIPE means overrun
- snd_pcm_prepare(handle);
- throw OverRun();
- return 0;
- } else if (rc < 0) {
- throw ReadError();
- } else if (rc != (int)frames) {
- throw ShortRead();
- }
-
- return rc * sizeof(short) * channels;
-}
-
-unsigned int AudioIn::get_samplerate()
-{
- return samplerate;
-}
-
-int AudioIn::set_level(unsigned int channel, float level)
-{
-
- if(!elem) throw MixerNotInitialised();
-
- if(level > 1.0 || level < 0.0) throw InvalidMixerLevel();
-
- long lvl = ((lvl_max - lvl_min) * level) + lvl_min;
-
- snd_mixer_selem_channel_id_t ch;
- switch(channel) {
- case 0:
- ch = SND_MIXER_SCHN_FRONT_LEFT;
- break;
- case 1:
- ch = SND_MIXER_SCHN_FRONT_RIGHT;
- break;
- default:
- throw IllegalChannelNumber();
- break;
- }
- if(snd_mixer_selem_set_capture_volume(elem, ch, lvl) != 0) {
- throw CouldNotSetMixerLevel();
- }
- return 0;
-}
-
-
-#define MAGIC 0xdeadbeef
-
-struct ai_t {
- unsigned int magic;
- AudioIn *ai;
-};
-
-struct ai_t *ai_init(int *err, const char *device, const char *mixer,
- unsigned int srate, unsigned int ch)
-{
- *err = NO_ERROR;
-
- struct ai_t *handle = new ai_t;
- handle->magic = MAGIC;
-
- if(handle == NULL) {
- *err = OUT_OF_MEMORY;
- return NULL;
- }
-
- try {
- handle->ai = new AudioIn(device, mixer, srate, ch);
- } catch(AudioIn::CouldNotOpenPCMDevice &e) { *err = COULD_NOT_OPEN_DEVICE;
- } catch(AudioIn::UnableToSetHWParams &e) { *err = COULD_NOT_SET_HW_PARAMS;
- } catch(AudioIn::CouldNotInitialiseParams &e) { *err = COULD_NOT_INIT_PARAMS;
- } catch(AudioIn::CouldNotSetAccessMode &e) { *err = COULD_NOT_SET_ACCESS_MODE;
- } catch(AudioIn::CouldNotSetFormat &e) { *err = COULD_NOT_SET_FORMAT;
- } catch(AudioIn::CouldNotSetChannelNumber &e) { *err = COULD_NOT_SET_CHANNELS;
- } catch(AudioIn::UnableToSetSampleRate &e) { *err = COULD_NOT_SET_SAMPLE_RATE;
- } catch(AudioIn::UnableToSetPeriodSize &e) { *err = COULD_NOT_SET_PERIOD_SIZE;
- } catch(AudioIn::MixerInitilisationFailed &e) { *err = MIXER_INIT_FAILED;
- }
-
- if(*err != NO_ERROR) {
- handle->magic = 0;
- delete handle;
- return NULL;
- }
-
- return handle;
-}
-
-int ai_read(int *err, struct ai_t *handle, void *pcm, unsigned int maxsize)
-{
- if(*err == 42) { // Magic debug function
- short *p = (short*)pcm;
- for(size_t i = 0; i < maxsize / sizeof(short); i++) {
- p[i] = i;
- }
- *err = NO_ERROR;
- return maxsize;
- }
-
- *err = NO_ERROR;
-
- if(handle == NULL || handle->magic != MAGIC || handle->ai == NULL) {
- *err = MISSING_HANDLE;
- return -1;
- }
-
- try {
- return handle->ai->read(pcm, maxsize);
- } catch(AudioIn::PcmBufferTooSmall &e) { *err = BUFFER_TOO_SMALL;
- } catch(AudioIn::OverRun &e) { *err = BUFFER_OVERRUN;
- } catch(AudioIn::ReadError &e) { *err = READ_ERROR;
- } catch(AudioIn::ShortRead &e) { *err = SHORT_READ;
- }
-
- return -1;
-}
-
-int ai_get_samplerate(int *err, struct ai_t *handle)
-{
- *err = NO_ERROR;
-
- if(handle == NULL || handle->magic != MAGIC || handle->ai == NULL) {
- *err = MISSING_HANDLE;
- return -1;
- }
-
- return (int)handle->ai->get_samplerate();
-}
-
-
-int ai_set_mixer_level(int *err, struct ai_t *handle, unsigned int channel,
- float level)
-{
- *err = NO_ERROR;
-
- if(handle == NULL || handle->magic != MAGIC || handle->ai == NULL) {
- *err = MISSING_HANDLE;
- return -1;
- }
-
- try {
- return handle->ai->set_level(channel, level);
- } catch(AudioIn::MixerNotInitialised &e) { *err = MIXER_NOT_INITIALISED;
- } catch(AudioIn::InvalidMixerLevel &e) { *err = INVALID_MIXER_LEVEL;
- } catch(AudioIn::IllegalChannelNumber &e) { *err = INVALID_CHANNEL_NUMBER;
- } catch(AudioIn::CouldNotSetMixerLevel &e) { *err = COULD_NOT_SET_MIXER_LEVEL;
- }
-
- return -1;
-}
-
-void ai_close(int *err, struct ai_t *handle)
-{
- *err = NO_ERROR;
-
- if(handle == NULL || handle->magic != MAGIC || handle->ai == NULL) {
- *err = MISSING_HANDLE;
- return;
- }
-
- delete handle->ai;
- handle->ai = NULL;
- handle->magic = 0;
- delete handle;
-}
-
-#ifdef TEST_AUDIOIN
-//deps:
-//cflags: $(ALSA_CFLAGS)
-//libs: $(ALSA_LIBS)
-
-#include <test.h>
-#include "test_audio.h"
-#include <string.h>
-
-TEST_BEGIN;
-int err;
-struct ai_t *h;
-
-h = ai_init(&err, "default", "H/W Multi", 44100, 2);
-TEST_EQUAL_INT(err, 0, "Check for errors.");
-TEST_NOTEQUAL(h, NULL, "Check handle.");
-
-ai_close(&err, h);
-TEST_EQUAL_INT(err, 0, "Check for errors.");
-
-h = ai_init(&err, "default", "H/W Multi", 22050, 1);
-TEST_EQUAL_INT(err, 0, "Check for errors.");
-TEST_NOTEQUAL(h, NULL, "Check handle.");
-
-char pcm[1880]; // Hold exactly one frame.
-int r;
-
-r = ai_read(&err, h, pcm, 0);
-TEST_EQUAL_INT(r, -1, "We should read something.");
-TEST_EQUAL_INT(err, BUFFER_TOO_SMALL, "Check for errors.");
-
-for(int i = 0; i < 100; i++) {
- r = ai_read(&err, h, pcm, sizeof(pcm));
-}
-TEST_EQUAL_INT(err, 0, "Check for errors.");
-TEST_NOTEQUAL_INT(r, 0, "We should read something.");
-
-char ref[sizeof(pcm)];
-memset(ref, 0, sizeof(ref));
-double diff = compareBuffers(r/sizeof(short), 1, pcm, ref);
-TEST_LESS_THAN_FLOAT(diff, 1000.0, "Compare buffers (with no mic on the soundcard)");
-
-short p[1024];
-err = 42;
-ai_read(&err, h, p, sizeof(p));
-for(size_t i = 0; i < sizeof(p) / sizeof(short); i++) {
- TEST_EQUAL_INT(p[i], i, "Compare slide.");
-}
-
-ai_close(&err, h);
-
-TEST_END;
-
-#endif/*TEST_AUDIOIN*/