Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class 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 Wed Aug 4 02:22:05 2004 for GNU Radio by doxygen 1.3.8