AudioGrabber.C

Go to the documentation of this file.
00001 /*!@file Devices/AudioGrabber.C Grab audio samples from /dev/dsp */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/AudioGrabber.C $
00035 // $Id: AudioGrabber.C 14757 2011-04-29 06:33:32Z farhan $
00036 //
00037 
00038 #include "Devices/AudioGrabber.H"
00039 
00040 #include "Component/OptionManager.H"
00041 #include "Component/ModelOptionDef.H"
00042 #include "Devices/DeviceOpts.H"
00043 #include "Image/Image.H"
00044 #include "Image/MatrixOps.H"
00045 #include "Util/Assert.H"
00046 #include "Util/Types.H"
00047 #include "Util/log.H"
00048 #include <fcntl.h>
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #include <sys/ioctl.h>
00052 #ifdef HAVE_SYS_SOUNDCARD_H
00053 #  include <sys/soundcard.h>
00054 #endif
00055 #include <unistd.h>
00056 
00057 // ######################################################################
00058 AudioGrabber::AudioGrabber(OptionManager& mgr, const std::string& descrName,
00059                            const std::string& tagName) :
00060   ModelComponent(mgr, descrName, tagName),
00061   itsDevName(&OPT_AudioGrabberDevice, this), // see Devices/DeviceOpts.{H,C}
00062   itsBits(&OPT_AudioGrabberBits, this), // see Devices/DeviceOpts.{H,C}
00063   itsFreq(&OPT_AudioGrabberFreq, this), // see Devices/DeviceOpts.{H,C}
00064   itsBufsamples(&OPT_AudioGrabberBufSamples, this), // idem
00065   itsChans(&OPT_AudioGrabberChans, this), // see Devices/DeviceOpts.{H,C}
00066   itsInterleaved(&OPT_AudioGrabberInterleaved,this), 
00067   itsFd(-1)
00068 {  }
00069 
00070 // ######################################################################
00071 void AudioGrabber::start2()
00072 {
00073 #ifndef HAVE_SYS_SOUNDCARD_H
00074   LFATAL("Oops! I need to have <sys/soundcard.h>");
00075 #else
00076   // open and reset device:
00077   const char *device = itsDevName.getVal().c_str();
00078   itsFd = open(device, O_RDONLY);
00079   if (itsFd == -1) LFATAL("Cannot open device %s", device);
00080 
00081   // setup grab buffer
00082   uint bufsiz = itsBufsamples.getVal() * (itsBits.getVal() / 8);
00083   uint numChans = itsChans.getVal();
00084   bufsiz *= numChans;
00085   
00086   if (bufsiz > 65534) LFATAL("Maximum buffer size of 64k bytes exceeded");
00087 
00088   // configure the device:
00089   int32 x = (bufsiz << 16) | 1;
00090   if (ioctl(itsFd, SNDCTL_DSP_SETFRAGMENT, &x) == -1)
00091     PLFATAL("Cannot SetFragment to %d buffers of %d samples",
00092             1, itsBufsamples.getVal());
00093   if (ioctl(itsFd, SOUND_PCM_RESET) == -1)
00094     PLFATAL("Cannot reset device %s", device);
00095   if (ioctl(itsFd, SOUND_PCM_SYNC) == -1)
00096     PLFATAL("Cannot sync device %s", device);
00097 
00098   const int bits = itsBits.getVal();
00099   if (ioctl(itsFd, SOUND_PCM_WRITE_BITS, &bits) == -1)
00100     PLFATAL("Cannot set bits to %d", bits);
00101   
00102   if (ioctl(itsFd, SOUND_PCM_WRITE_CHANNELS, &numChans) == -1)
00103     LFATAL("Cannot set number of channels to %d ", numChans);
00104 
00105   if (ioctl(itsFd, SOUND_PCM_SYNC) == -1)
00106     PLFATAL("Cannot sync device %s", device);
00107   
00108   const int freq = itsFreq.getVal();
00109   if (ioctl(itsFd, SOUND_PCM_WRITE_RATE, &freq) == -1)
00110     PLFATAL("Cannot set write rate to %d", freq);
00111 
00112   // print some info about the device:
00113   int rate, channels, nbbits, blocksize;
00114   if (ioctl(itsFd, SOUND_PCM_READ_CHANNELS, &channels) == -1)
00115     PLERROR("Cannot read nb channels");
00116   if (ioctl(itsFd, SOUND_PCM_READ_BITS, &nbbits) == -1)
00117     PLERROR("Cannot read nb bits");
00118   if (ioctl(itsFd, SOUND_PCM_READ_RATE, &rate) == -1)
00119     PLERROR("Cannot read sampling rate");
00120   if (ioctl(itsFd, SNDCTL_DSP_GETBLKSIZE, &blocksize) == -1)
00121     PLERROR("Cannot read blocksize");
00122   LDEBUG("%s: %d Hz, %d ch, %d bits, %db blocks", device, rate,
00123          channels, nbbits, blocksize);
00124   LINFO("its rate: %d, its channels: %d, its bits: %d, its block: %d",
00125         rate, channels, nbbits, blocksize);
00126   LINFO("Ready to grab...");
00127 #endif // HAVE_SYS_SOUNDCARD_H
00128 }
00129 
00130 // ######################################################################
00131 void AudioGrabber::stop1()
00132 {
00133 #ifdef HAVE_SYS_SOUNDCARD_H
00134   if (ioctl(itsFd, SOUND_PCM_SYNC) == -1)
00135     PLFATAL("Cannot sync audio device");
00136   if (ioctl(itsFd, SOUND_PCM_RESET) == -1)
00137     PLFATAL("Cannot reset audio device");
00138 #endif
00139 
00140   if (itsFd > -1) { close(itsFd); itsFd = -1; }
00141 }
00142 
00143 // ######################################################################
00144 AudioGrabber::~AudioGrabber()
00145 {  }
00146 
00147 // ######################################################################
00148 template <class T>
00149 void AudioGrabber::grab(AudioBuffer<T>& buf) const
00150 {
00151   ASSERT(itsFd != -1);
00152   ASSERT(itsBits.getVal() == sizeof(T) * 8);
00153 
00154   int myBufSamp = itsBufsamples.getVal();
00155   int myChans  = itsChans.getVal();
00156 
00157   AudioBuffer<T> b(myBufSamp,
00158                    myChans,
00159                    float(itsFreq.getVal()),
00160                    NO_INIT);
00161 
00162   int got = read(itsFd, b.getDataPtr(), b.sizeBytes());
00163   if (got != int(b.sizeBytes()))
00164     PLERROR("Error reading from device: got %d of %u requested bytes",
00165             got, b.sizeBytes());
00166  
00167   if(itsInterleaved.getVal())
00168     {
00169       ASSERT(myChans > 1);
00170      
00171        // data comes in as c1s0 c2s0 ... cNs0, c1s1 c1s2 ... cNs2, etc but we want it transposed for storage into
00172        // AudioBuffer: c1s0 ... c1sN, c2s0 ... c2sN, etc
00173 
00174       // reorganize data in buf
00175       Image<T> interleaved;
00176       interleaved.attach(b.getDataPtr(), myChans, myBufSamp);
00177       Image<T> chunked = transpose(interleaved); 
00178           
00179       AudioBuffer<T> tposed(chunked.getArrayPtr(), myBufSamp, myChans, itsFreq.getVal());
00180           
00181       buf = tposed;
00182       interleaved.detach();
00183 
00184     }
00185   else
00186     buf=b;
00187   
00188 }
00189 
00190 // template instantiations:
00191 template void AudioGrabber::grab(AudioBuffer<byte>& buf) const;
00192 template void AudioGrabber::grab(AudioBuffer<uint16>& buf) const;
00193 template void AudioGrabber::grab(AudioBuffer<int16>& buf) const;
00194 
00195 // ######################################################################
00196 /* So things look consistent in everyone's emacs... */
00197 /* Local Variables: */
00198 /* indent-tabs-mode: nil */
00199 /* End: */
Generated on Sun May 8 08:04:44 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3