Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

VrAudioSource.h

Go to the documentation of this file.
00001 /* -*- Mode: c++ -*- */
00002 /*
00003  * Copyright 2001 Free Software Foundation, Inc.
00004  * 
00005  * This file is part of GNU Radio
00006  * 
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2, or (at your option)
00010  * any later version.
00011  * 
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020  * Boston, MA 02111-1307, USA.
00021  */
00022 /*
00023  *  Copyright 1997 Massachusetts Institute of Technology
00024  * 
00025  *  Permission to use, copy, modify, distribute, and sell this software and its
00026  *  documentation for any purpose is hereby granted without fee, provided that
00027  *  the above copyright notice appear in all copies and that both that
00028  *  copyright notice and this permission notice appear in supporting
00029  *  documentation, and that the name of M.I.T. not be used in advertising or
00030  *  publicity pertaining to distribution of the software without specific,
00031  *  written prior permission.  M.I.T. makes no representations about the
00032  *  suitability of this software for any purpose.  It is provided "as is"
00033  *  without express or implied warranty.
00034  * 
00035  */
00036 
00037 #ifndef _VRAUDIOSOURCE_H_
00038 #define _VRAUDIOSOURCE_H_
00039 
00040 #define AUDIOINCHUNKSIZE 200
00041 
00042 extern "C" {
00043 #include <sys/soundcard.h>
00044 #include <sys/ioctl.h>
00045 #include <fcntl.h>
00046 #include <unistd.h>
00047 }
00048 
00049 #include <VrSource.h>
00050 #include <fstream>
00051 #include <algorithm>
00052 #include <string>
00053 
00054 template<class oType>
00055 class VrAudioSource : public VrSource<oType> {
00056 protected:
00057   int         audiofd;
00058   long        format;
00059   bool        decimate;
00060   std::string device_name;
00061 public: 
00062   virtual int work2(VrSampleRange output, void *o[]);
00063   virtual void initialize();
00064 
00065   VrAudioSource(double sampling_freq, const char* dev = "/dev/dsp")
00066     : audiofd(-1), decimate(false), device_name(dev){
00067 
00068     setSamplingFrequency (sampling_freq);
00069     setOutputSize (AUDIOINCHUNKSIZE);
00070   }
00071 
00072   virtual const char *name() { return "VrAudioSource"; }
00073 
00074   virtual ~VrAudioSource() {close(audiofd);}
00075 };
00076 
00077 
00078 template<class oType> void
00079 VrAudioSource<oType>::initialize() 
00080 {
00081   int temp = 0x7fff0004;
00082   if(audiofd==-1) {
00083     if ((audiofd = open(device_name.c_str(), O_RDONLY)) < 0) {
00084       cerr << "VrAudioSource: ";
00085       perror (device_name.c_str ());
00086       exit(1);
00087     }
00088     if ((ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&temp)) < 0) {
00089       fprintf (stderr, "VrAudioSource: set fragment returned %d\n", errno);
00090       exit(1);
00091     }
00092   }
00093 
00094   if(sizeof(oType)==1) {
00095     format=AFMT_MU_LAW;
00096   } else if(sizeof(oType)==2) {
00097     printf("setting to 16 bits \n");
00098     format = AFMT_S16_LE;
00099   } else {
00100     fprintf (stderr,
00101              "VrAudioSource: cannot handle data type of size %d\n",
00102              sizeof(oType));
00103     exit(1);
00104   }
00105 
00106   ioctl(audiofd,SNDCTL_DSP_RESET);
00107 
00108   int origf=format;
00109   if((ioctl(audiofd,SNDCTL_DSP_SETFMT,&format)) < 0) {
00110     cerr << "VrAudioSource: " << device_name << " IOCTL failed with errno " << errno << "\n";
00111     exit(1);
00112   }
00113   if(origf!=format) {
00114     fprintf (stderr, "VrAudioSource: Warning: unable to support format %d\n", origf);
00115     fprintf (stderr, "  card requested %ld instead.\n", format);
00116   }
00117 
00118   // set number of channels no matter what.  Some hardware only does stereo
00119 
00120   int noutputs = 1;     // number of outputs
00121   int channels = noutputs;
00122   if (ioctl (audiofd, SNDCTL_DSP_CHANNELS, &channels) < 0){
00123     perror ("VrAudioSink: SNDCTL_DSP_CHANNELS failed");
00124     exit (1);
00125   }
00126     
00127   if (channels != noutputs){
00128     if (noutputs == 2){
00129       fprintf(stderr, "VrAudioSource: could not set STEREO mode\n");
00130       // FIXME, could fix this by duplicating mono input, or zeroing other channel
00131       exit(1);
00132     }
00133     else {
00134       // user asked for MONO, but got STEREO.  We can work around this...
00135       fprintf (stderr, "VrAudioSource: could not set MONO mode\n");
00136       decimate = true;
00137     }
00138   }
00139 
00140   int sf = (int)getSamplingFrequency();
00141   //cout <<"Sampling frequency = "<<sf<<endl;
00142   if ((ioctl(audiofd,SNDCTL_DSP_SPEED,&sf)) < 0) {
00143     cerr << device_name << ": Invalid sampling frequency...defaulting to 8 Khz\n";
00144     sf = 8000;
00145     if ((ioctl(audiofd,SNDCTL_DSP_SPEED,&sf)) < 0) {
00146       fprintf (stderr, "Couldn't even manage that...aborting\n");
00147       exit(1);
00148     }
00149   }
00150   if(sf!=getSamplingFrequency())
00151     fprintf(stderr, "VrAudioSource Warning: soundcard defaulted to %d Hz\n", sf);
00152 }
00153 
00154 
00155 template<class oType> int 
00156 VrAudioSource<oType>::work2(VrSampleRange output, void *ao[])
00157 {
00158   unsigned units=output.size;
00159   oType **o= (oType **)ao;
00160   oType *curPos=o[0];
00161 
00162   if (decimate){
00163     // convert STEREO input from sound card to MONO output
00164     while(units > 0) {
00165       const unsigned N = 2048;
00166       oType     tmp[N*2];
00167       
00168       int nbytes =  std::min (units, N) * (sizeof(oType) * 2);
00169       int count = read(audiofd, tmp, nbytes);
00170 
00171       if(count < 0) {
00172         perror ("VrAudioSource");
00173         exit(1);
00174       }
00175 
00176       assert ((count & ((sizeof(oType) * 2) - 1)) == 0);
00177 
00178       for (unsigned int i = 0; i < count / (sizeof (oType) * 2); i++){
00179         curPos[i] = tmp[2*i];
00180       }
00181 
00182       units -= count / (sizeof (oType) * 2);
00183       curPos += count / (sizeof (oType) * 2);
00184     }
00185     return output.size;
00186   }
00187 
00188   else {        // normal
00189     while(units > 0) {
00190       int nbytes =  units * sizeof(oType);
00191       int count = read(audiofd, curPos, nbytes);
00192 
00193       if(count < 0) {
00194         perror ("VrAudioSource");
00195         exit(1);
00196       }
00197 
00198       assert ((count & (sizeof(oType) - 1)) == 0);
00199 
00200       units -= count / sizeof (oType);
00201       curPos += count / sizeof (oType);
00202     }
00203     return output.size;
00204   }
00205 }
00206 
00207 #endif

Generated on Tue Mar 15 23:46:36 2005 for GNU Radio by  doxygen 1.4.0