00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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)) < 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
00099
00100
00101 int format = AFMT_S16_NE;
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
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
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
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
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
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