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 _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)) < 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
00110
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
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
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) {
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)
00180 bytes*=2;
00181
00182
00183 assert ((size % getOutputSize()) == 0);
00184
00185 while(size > 0) {
00186 myPtr = i[0];
00187
00188 if(getNumberInputs()==2) {
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();
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