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