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

GrAudioSource.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 _GRAUDIOSOURCE_H_
00038 #define _GRAUDIOSOURCE_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 GrAudioSource : public VrSource<oType> {
00056 protected:
00057   int         audiofd;
00058   long        format;
00059   std::string device_name;
00060   oType       scale_factor;
00061   int         num_streams;
00062 public: 
00063   virtual int work2(VrSampleRange output, void *o[]);
00064   virtual void initialize();
00065 
00066   GrAudioSource(double sampling_freq, int streams, double output_range = 32767,
00067                 const char* dev = "/dev/dsp")
00068     : VrSource<oType>(streams),audiofd(-1), device_name(dev),num_streams(streams) {
00069     setSamplingFrequency (sampling_freq);
00070     setOutputSize (AUDIOINCHUNKSIZE);
00071     scale_factor = (oType) (32767 / output_range);
00072   }
00073 
00074   virtual const char *name() { return "GrAudioSource"; }
00075 
00076   virtual ~GrAudioSource() {close(audiofd);}
00077 };
00078 
00079 
00080 template<class oType> void
00081 GrAudioSource<oType>::initialize() 
00082 {
00083   int temp = 0x7fff0004;
00084   if(audiofd==-1) {
00085     if ((audiofd = open(device_name.c_str(), O_RDONLY)) < 0) {
00086       cerr << "GrAudioSource: ";
00087       perror (device_name.c_str ());
00088       exit(1);
00089     }
00090     if ((ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&temp)) < 0) {
00091       fprintf (stderr, "GrAudioSource: set fragment returned %d\n", errno);
00092       exit(1);
00093     }
00094   }
00095   
00096   // ioctl(audiofd,SNDCTL_DSP_RESET);
00097   
00098   int format=AFMT_S16_NE;
00099   int origf=format;
00100   if((ioctl(audiofd,SNDCTL_DSP_SETFMT,&format)) < 0) {
00101     cerr << "GrAudioSource: " << device_name << " IOCTL failed with errno " << errno << "\n";
00102     exit(1);
00103   }
00104   if(origf!=format) {
00105     fprintf (stderr, "GrAudioSource: Warning: unable to support format %d\n", origf);
00106     fprintf (stderr, "  card requested %d instead.\n", format);
00107   }
00108   
00109   // set number of channels no matter what.  Some hardware only does stereo
00110   int channels = 2;
00111   if (ioctl (audiofd, SNDCTL_DSP_CHANNELS, &channels) < 0){
00112     perror ("GrAudioSink: SNDCTL_DSP_CHANNELS failed");
00113     exit (1);
00114   }
00115   
00116   if (channels != 2){
00117     fprintf(stderr, "GrAudioSource: could not set STEREO mode\n");
00118     exit(1);
00119   }
00120   
00121   //  if(getInputSamplingFrequencyN(0)!=getInputSamplingFrequencyN(1))
00122   //    fprintf(stderr, "GrAudioSink Warning: left and right at different freq\n");
00123 
00124   int sf = (int)getSamplingFrequency();
00125   cerr <<"GrAudioSource: Sampling frequency = "<<sf<<endl;
00126 
00127   if ((ioctl(audiofd,SNDCTL_DSP_SPEED,&sf)) < 0) {
00128     cerr << device_name << ": Invalid sampling frequency...defaulting to 8 Khz\n";
00129     sf = 8000;
00130     if ((ioctl(audiofd,SNDCTL_DSP_SPEED,&sf)) < 0) {
00131       fprintf (stderr, "Couldn't even manage that...aborting\n");
00132       exit(1);
00133     }
00134   }
00135   if(sf!=getSamplingFrequency())
00136     fprintf(stderr, "GrAudioSource Warning: soundcard defaulted to %d Hz\n", sf);
00137 }
00138 
00139 
00140 template<class oType> int 
00141 GrAudioSource<oType>::work2(VrSampleRange output, void *ao[])
00142 {
00143   sync (output.index);          // force in-order execution
00144 
00145   unsigned size = output.size;
00146   oType **o = (oType **)ao;
00147   
00148   while(size > 0) {
00149     const unsigned N = 2048;
00150     short tmp[N*2];
00151     int nbytes =  std::min (size, N) * (sizeof(short) * 2);
00152     
00153     int count = read(audiofd, tmp, nbytes);
00154     
00155     if(count < 0) {
00156       perror ("GrAudioSource");
00157       exit(1);
00158     }
00159     
00160     assert ((count & ((sizeof(short) * 2) - 1)) == 0);
00161     
00162     if(num_streams == 1)
00163       for (unsigned int i = 0; i < count / (sizeof (short) * 2); i++) {
00164         o[0][i] = (oType)tmp[2*i]/scale_factor;
00165       }
00166     else        
00167       for (unsigned int i = 0; i < count / (sizeof (short) * 2); i++) {
00168         o[0][i] = (oType)tmp[2*i]/scale_factor;
00169         o[1][i] = (oType)tmp[2*i+1]/scale_factor;
00170       }
00171     
00172     size -= count / (sizeof (short) * 2);
00173     o[0] += count / (sizeof (short) * 2);
00174     if(num_streams==2)
00175       o[1] += count / (sizeof (short) * 2);
00176   }
00177   return output.size;
00178 }
00179 
00180 template<> int 
00181 GrAudioSource<VrComplex>::work2(VrSampleRange output, void *ao[])
00182 {
00183   unsigned size = output.size;
00184   VrComplex **o = (VrComplex **)ao;
00185   
00186   while(size > 0) {
00187     const unsigned N = 2048;
00188     short tmp[N*2];
00189     int nbytes =  std::min (size, N) * (sizeof(short) * 2);
00190     
00191     int count = read(audiofd, tmp, nbytes);
00192     
00193     if(count < 0) {
00194       perror ("GrAudioSource");
00195       exit(1);
00196     }
00197     
00198     assert ((count & ((sizeof(short) * 2) - 1)) == 0);
00199     
00200     for (unsigned int i = 0; i < count / (sizeof (short) * 2); i++)
00201       o[0][i] = VrComplex (tmp[2*i],tmp[2*i+1]) / scale_factor;
00202     
00203     size -= count / (sizeof (short) * 2);
00204     o[0] += count / (sizeof (short) * 2);
00205   }
00206   return output.size;
00207 }
00208 
00209 #endif

Generated on Tue Mar 15 23:48:04 2005 for GNU Radio by  doxygen 1.4.0