/* -*- 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" AudioIn::AudioIn(std::string device, std::string mixer_interface, unsigned int srate, int ch) { /* frames = 940; elem = NULL; mixhnd = NULL; int rc; // Open PCM device for recording (capture). rc = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) throw CouldNotOpenPCMDevice(); // Allocate a hardware parameters object. snd_pcm_hw_params_alloca(¶ms); // 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_FLOAT); 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 unsigned int val = srate; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); printf("srate: %d\n", val); // if(val != srate) throw UnableToSetSampleRate(); // NOTE: Setting period size to 32 frames will force use of lowest possible value. 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(); mixhnd = NULL; */ /* // // 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 snd_mixer_selem_set_enum_item(iselem, SND_MIXER_SCHN_MONO, 2); } */ } AudioIn::~AudioIn() { if(handle) { snd_pcm_drain(handle); snd_pcm_close(handle); } if(mixhnd) snd_mixer_close(mixhnd); } #define TEST #ifdef TEST #include #endif/*TEST*/ size_t AudioIn::read(sample_t *buf, size_t size) { #ifdef TEST static unsigned int x = 0; for(size_t i = 0; i < size; i++) { buf[i] = sin((float)x / 50.0); x++; } return size; #else int rc; if(size < frames * 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(); } printf("rc: %d\n", rc); return rc * channels; #endif/*TEST*/ } 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; }