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

GrAudioSink.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 _GRAUDIOSINK_H_
00038 #define _GRAUDIOSINK_H_
00039 
00040 #define AUDIOOUTCHUNKSIZE 64
00041 
00042 extern "C" {
00043 #include <sys/soundcard.h>
00044 #include <sys/ioctl.h>
00045 #include <fcntl.h>
00046 #include <unistd.h>
00047 #include <assert.h>
00048 }
00049 #include <VrSink.h>
00050 #include <fstream>
00051 #include <string>
00052 
00053 template<class iType>
00054 class GrAudioSink : public VrSink<iType> {
00055 protected:
00056   int         audiofd;
00057   short       *buffer;
00058   std::string device_name;
00059   iType       scale_factor;     
00060 public:
00061   virtual const char *name() { return "GrAudioSink"; }
00062 
00063   virtual int work3(VrSampleRange output,
00064                     VrSampleRange inputs[], void *i[]);
00065 
00066   virtual void initialize();
00067 
00068   GrAudioSink(iType input_range = 32767, const char* dev = "/dev/dsp")
00069     : audiofd(-1), device_name(dev) {
00070     setOutputSize (AUDIOOUTCHUNKSIZE);
00071     scale_factor = 32767 / input_range;
00072   }
00073 
00074   virtual ~GrAudioSink() {
00075     delete [] buffer;
00076     close(audiofd);
00077   }
00078 };
00079 
00080 
00081 template<class iType> void
00082 GrAudioSink<iType>::initialize()
00083 {
00084   if(audiofd==-1) {
00085     int temp = 0x7fff0004;
00086 
00087     if ((audiofd = open(device_name.c_str(), O_WRONLY/*|O_NONBLOCK*/)) < 0) {
00088       cerr << "GrAudioSink: ";
00089       perror (device_name.c_str ());
00090       exit(1);
00091     }
00092     if ((ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&temp)) < 0) {
00093       fprintf(stderr, "GrAudioSink: set fragment returned %d\n", errno);
00094       exit(1);
00095     }
00096   }
00097 
00098   // -eb docs say not to do this...
00099   // ioctl(audiofd,SNDCTL_DSP_RESET);
00100 
00101   int format = AFMT_S16_NE;  // FIXME check endianness
00102   int origf=format;
00103   if((ioctl(audiofd,SNDCTL_DSP_SETFMT,&format)) < 0) {
00104     cerr << "GrAudioSink: " << device_name << " IOCTL failed with " << errno << "\n";
00105     exit(1);
00106   }
00107 
00108   if(origf!=format) {
00109     fprintf(stderr, "GrAudioSink: Warning: unable to support format %d\n", origf);
00110     fprintf(stderr, "  card requested %d instead.\n", format);
00111   }
00112 
00113   // set to stereo no matter what.  Some hardware only does stereo
00114   int channels = 2;
00115   if (ioctl (audiofd, SNDCTL_DSP_CHANNELS, &channels) < 0){
00116     perror ("GrAudioSink: SNDCTL_DSP_CHANNELS failed");
00117     exit (1);
00118   }
00119     
00120   if (channels != 2) {
00121     fprintf(stderr, "GrAudioSink: could not set STEREO mode\n");
00122     exit(1);
00123   }
00124 
00125   buffer = new short[getOutputSize() * 2];   
00126 
00127   int n = getNumberInputs ();
00128   assert (n >= 1 && n <= 2);
00129 
00130   if(n==2) 
00131     if(getInputSamplingFrequencyN(0)!=getInputSamplingFrequencyN(1))
00132       fprintf(stderr, "GrAudioSink Warning: left and right at different freq\n");
00133   
00134   int sf = (int) getSamplingFrequency();
00135   printf("GrAudioSink: sampling frequency is %d\n",sf);
00136 
00137   if ((ioctl(audiofd, SNDCTL_DSP_SPEED, &sf)) < 0) {
00138     cerr << device_name << ": invalid sampling frequency...defaulting to 8 Khz\n";
00139     sf = 8000;
00140     if ((ioctl(audiofd,SNDCTL_DSP_SPEED, &sf)) < 0) {
00141       fprintf(stderr, "Couldn't even manage that...aborting\n");
00142       exit(1);
00143     }
00144   }
00145   if (sf != getSamplingFrequency ())
00146     fprintf (stderr, "GrAudioSink Warning: sound card default to %d Hz\n", sf);
00147 }
00148 
00149 template<class iType> int
00150 GrAudioSink<iType>::work3(VrSampleRange output, VrSampleRange inputs[], void *ai[])
00151 {
00152   iType **i = (iType **)ai;
00153   unsigned size = output.size;
00154   
00155   // size is guaranteed to be a multple of getOutputSize
00156   assert ((size % getOutputSize()) == 0);
00157 
00158   while(size > 0) {
00159     if(getNumberInputs()==1) {
00160       for(unsigned int k=0;k<getOutputSize();k++) {
00161         buffer[2*k] = (short)(scale_factor * i[0][k]);
00162         buffer[2*k+1] = (short)(scale_factor * i[0][k]);
00163       }
00164     }
00165     else { 
00166       for(unsigned int k=0;k<getOutputSize();k++) {
00167         buffer[2*k] = (short)(scale_factor * i[0][k]);
00168         buffer[2*k+1] = (short)(scale_factor * i[1][k]);
00169       }
00170     }                        
00171           
00172     unsigned int count =  write(audiofd,buffer,4*getOutputSize());
00173     // 2 for stereo times 2 bytes in a short
00174     if(count<0) {
00175       printf("AudioSink write error, errno: %d\n", errno);
00176       exit(1);
00177     } 
00178     else {
00179       if(count!=4*getOutputSize())
00180         printf("AudioSink: warning: not all bytes written!\n");
00181     }
00182     size-=getOutputSize();
00183     i[0]+=getOutputSize();
00184     if(getNumberInputs()==2)
00185       i[1]+=getOutputSize();
00186   }
00187   return output.size;
00188 }
00189 
00190 template<> int
00191 GrAudioSink<VrComplex>::work3(VrSampleRange output, VrSampleRange inputs[], void *ai[])
00192 {
00193   VrComplex **i = (VrComplex **)ai;
00194   unsigned size = output.size;
00195   
00196   // size is guaranteed to be a multple of getOutputSize
00197   assert ((size % getOutputSize()) == 0);
00198 
00199   if(getNumberInputs()!=1)
00200     {
00201       cerr << "GrAudioSink:  Can only output one VrComplex stream\n";
00202       exit(-1);      
00203     }
00204 
00205   while(size > 0) {
00206     for(unsigned int k=0;k<getOutputSize();k++) {
00207       buffer[2*k] = (short)real(scale_factor * i[0][k]);
00208       buffer[2*k+1] = (short)imag(scale_factor * i[0][k]);
00209     }
00210           
00211     unsigned int count =  write(audiofd,buffer,4*getOutputSize());
00212     // 2 for stereo times 2 bytes in a short
00213     if(count<0) {
00214       printf("AudioSink write error, errno: %d\n", errno);
00215       exit(1);
00216     } 
00217     else {
00218       if(count!=4*getOutputSize())
00219         printf("AudioSink: warning: not all bytes written!\n");
00220     }
00221     size-=getOutputSize();
00222     i[0]+=getOutputSize();
00223     if(getNumberInputs()==2)
00224       i[1]+=getOutputSize();
00225   }
00226   return output.size;
00227 }
00228 
00229 #endif

Generated on Wed Mar 23 12:30:23 2005 for GNU Radio by  doxygen 1.4.0