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

VrAudioSink.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 _VRAUDIOSINK_H_
00038 #define _VRAUDIOSINK_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 VrAudioSink : public VrSink<iType> {
00055 protected:
00056   int         audiofd;
00057   iType       *mixArray;
00058   bool        convert_mono_to_stereo_p;
00059   std::string device_name;
00060   
00061 public:
00062   virtual const char *name() { return "VrAudioSink"; }
00063 
00064   virtual int work3(VrSampleRange output,
00065                     VrSampleRange inputs[], void *i[]);
00066 
00067   virtual void initialize();
00068 
00069   VrAudioSink(const char* dev = "/dev/dsp")
00070     : audiofd(-1), convert_mono_to_stereo_p(false), device_name(dev) {
00071     setOutputSize (AUDIOOUTCHUNKSIZE);
00072   }
00073 
00074   virtual ~VrAudioSink() {
00075     delete [] mixArray;
00076     close(audiofd);
00077   }
00078 };
00079 
00080 
00081 template<class iType> void
00082 VrAudioSink<iType>::initialize()
00083 {
00084   long format;
00085 
00086   if(audiofd==-1) {
00087     int temp = 0x7fff0004;
00088 
00089     if ((audiofd = open(device_name.c_str(), O_WRONLY/*|O_NONBLOCK*/)) < 0) {
00090       cerr << "VrAudioSink: ";
00091       perror (device_name.c_str ());
00092       exit(1);
00093     }
00094     if ((ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&temp)) < 0) {
00095       fprintf(stderr, "VrAudioSink: set fragment returned %d\n", errno);
00096       exit(1);
00097     }
00098   }
00099 
00100   if(sizeof(iType)==1)
00101     format = AFMT_MU_LAW;
00102   if(sizeof(iType)==2)
00103     format = AFMT_S16_NE;
00104   else {
00105     fprintf(stderr, "VrAudioSink: cannot handle data type of size %d\n", sizeof (iType));
00106     exit(1);
00107   }
00108 
00109   // -eb docs say not to do this...
00110   // ioctl(audiofd,SNDCTL_DSP_RESET);
00111 
00112   int origf=format;
00113   if((ioctl(audiofd,SNDCTL_DSP_SETFMT,&format)) < 0) {
00114     cerr << "VrAudioSink: " << device_name << " IOCTL failed with " << errno << "\n";
00115     exit(1);
00116   }
00117 
00118   if(origf!=format) {
00119     fprintf(stderr, "VrAudioSink: Warning: unable to support format %d\n", origf);
00120     fprintf(stderr, "  card requested %ld instead.\n", format);
00121   }
00122 
00123 
00124   int n = getNumberInputs ();
00125   assert (n >= 1 && n <= 2);
00126 
00127   // set number of channels no matter what.  Some hardware only does stereo
00128 
00129   int channels = n;
00130   if (ioctl (audiofd, SNDCTL_DSP_CHANNELS, &channels) < 0){
00131     perror ("VrAudioSink: SNDCTL_DSP_CHANNELS failed");
00132     exit (1);
00133   }
00134     
00135   if (channels != n){
00136     if (n == 2){
00137       fprintf(stderr, "VrAudioSink: could not set STEREO mode\n");
00138       exit(1);
00139     }
00140     else {
00141       // user asked for MONO, but got STEREO.  We can work around this...
00142       convert_mono_to_stereo_p = true;
00143     }
00144   }
00145 
00146   if (convert_mono_to_stereo_p)
00147     mixArray=new iType[getOutputSize()*2];
00148   else if(getNumberInputs()==2) {               //Stereo
00149     mixArray=new iType[getOutputSize()*2];
00150     if(getInputSamplingFrequencyN(0)!=getInputSamplingFrequencyN(1))
00151       fprintf(stderr, "VrAudioSink Warning: left and right at different freq\n");
00152   } else
00153     mixArray = NULL;
00154 
00155 
00156   int sf = (int) getSamplingFrequency();
00157   printf("VrAudioSink: sampling frequency is %d\n",sf);
00158 
00159   if ((ioctl(audiofd, SNDCTL_DSP_SPEED, &sf)) < 0) {
00160     cerr << device_name << ": invalid sampling frequency...defaulting to 8 Khz\n";
00161     sf = 8000;
00162     if ((ioctl(audiofd,SNDCTL_DSP_SPEED, &sf)) < 0) {
00163       fprintf(stderr, "Couldn't even manage that...aborting\n");
00164       exit(1);
00165     }
00166   }
00167   if (sf != getSamplingFrequency ())
00168     fprintf (stderr, "VrAudioSink Warning: sound card default to %d Hz\n", sf);
00169 }
00170 
00171 template<class iType> int
00172 VrAudioSink<iType>::work3(VrSampleRange output, VrSampleRange inputs[], void *ai[])
00173 {
00174   iType **i = (iType **)ai;
00175   unsigned size = output.size;
00176   int bytes = getOutputSize()*sizeof(iType);
00177   iType *myPtr;
00178 
00179   if(getNumberInputs()==2 || convert_mono_to_stereo_p)          //Stereo
00180       bytes*=2;
00181 
00182   // size is guaranteed to be a multple of getOutputSize
00183   assert ((size % getOutputSize()) == 0);
00184 
00185   while(size > 0) {
00186     myPtr = i[0];
00187 
00188     if(getNumberInputs()==2) {                                  //Stereo
00189       for(unsigned int ii=0;ii<getOutputSize();ii++) {
00190         mixArray[ii*2]  =i[0][ii];
00191         mixArray[ii*2+1]=i[1][ii];
00192       }
00193       myPtr=mixArray;
00194       i[1]+=getOutputSize();    // advance channel 1 here, channel 0 at bottom
00195     }
00196 
00197     else if (convert_mono_to_stereo_p){
00198       for(unsigned int ii=0;ii<getOutputSize();ii++) {
00199         mixArray[ii*2]  =i[0][ii];
00200         mixArray[ii*2+1]=i[0][ii];
00201       }
00202       myPtr=mixArray;
00203     }
00204     
00205     int count =  write(audiofd,myPtr,bytes);
00206     if(count<0) {
00207       printf("AudioSink write error, errno: %d\n", errno);
00208       exit(1);
00209     } else {
00210       if(count!=bytes)
00211         printf("AudioSink: warning: not all bytes written!\n");
00212     }
00213     size-=getOutputSize();
00214     i[0]+=getOutputSize();
00215   }
00216   return output.size;
00217 }
00218 #endif

Generated on Tue Mar 30 21:31:51 2004 for GNU Radio by doxygen 1.3.2