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 _GRAUDIOSOURCE_H_
00038 #define _GRAUDIOSOURCE_H_
00039
00040 #define AUDIOINCHUNKSIZE 200
00041
00042 extern "C" {
00043 #include <sys/soundcard.h>
00044 #include <sys/ioctl.h>
00045 #include <fcntl.h>
00046 #include <unistd.h>
00047 }
00048
00049 #include <VrSource.h>
00050 #include <fstream>
00051 #include <algorithm>
00052 #include <string>
00053
00054 template<class oType>
00055 class GrAudioSource : public VrSource<oType> {
00056 protected:
00057 int audiofd;
00058 long format;
00059 std::string device_name;
00060 oType scale_factor;
00061 int num_streams;
00062 public:
00063 virtual int work2(VrSampleRange output, void *o[]);
00064 virtual void initialize();
00065
00066 GrAudioSource(double sampling_freq, int streams, double output_range = 32767,
00067 const char* dev = "/dev/dsp")
00068 : VrSource<oType>(streams),audiofd(-1), device_name(dev),num_streams(streams) {
00069 setSamplingFrequency (sampling_freq);
00070 setOutputSize (AUDIOINCHUNKSIZE);
00071 scale_factor = (oType) (32767 / output_range);
00072 }
00073
00074 virtual const char *name() { return "GrAudioSource"; }
00075
00076 virtual ~GrAudioSource() {close(audiofd);}
00077 };
00078
00079
00080 template<class oType> void
00081 GrAudioSource<oType>::initialize()
00082 {
00083 int temp = 0x7fff0004;
00084 if(audiofd==-1) {
00085 if ((audiofd = open(device_name.c_str(), O_RDONLY)) < 0) {
00086 cerr << "GrAudioSource: ";
00087 perror (device_name.c_str ());
00088 exit(1);
00089 }
00090 if ((ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&temp)) < 0) {
00091 fprintf (stderr, "GrAudioSource: set fragment returned %d\n", errno);
00092 exit(1);
00093 }
00094 }
00095
00096
00097
00098 int format=AFMT_S16_NE;
00099 int origf=format;
00100 if((ioctl(audiofd,SNDCTL_DSP_SETFMT,&format)) < 0) {
00101 cerr << "GrAudioSource: " << device_name << " IOCTL failed with errno " << errno << "\n";
00102 exit(1);
00103 }
00104 if(origf!=format) {
00105 fprintf (stderr, "GrAudioSource: Warning: unable to support format %d\n", origf);
00106 fprintf (stderr, " card requested %d instead.\n", format);
00107 }
00108
00109
00110 int channels = 2;
00111 if (ioctl (audiofd, SNDCTL_DSP_CHANNELS, &channels) < 0){
00112 perror ("GrAudioSink: SNDCTL_DSP_CHANNELS failed");
00113 exit (1);
00114 }
00115
00116 if (channels != 2){
00117 fprintf(stderr, "GrAudioSource: could not set STEREO mode\n");
00118 exit(1);
00119 }
00120
00121
00122
00123
00124 int sf = (int)getSamplingFrequency();
00125 cerr <<"GrAudioSource: Sampling frequency = "<<sf<<endl;
00126
00127 if ((ioctl(audiofd,SNDCTL_DSP_SPEED,&sf)) < 0) {
00128 cerr << device_name << ": Invalid sampling frequency...defaulting to 8 Khz\n";
00129 sf = 8000;
00130 if ((ioctl(audiofd,SNDCTL_DSP_SPEED,&sf)) < 0) {
00131 fprintf (stderr, "Couldn't even manage that...aborting\n");
00132 exit(1);
00133 }
00134 }
00135 if(sf!=getSamplingFrequency())
00136 fprintf(stderr, "GrAudioSource Warning: soundcard defaulted to %d Hz\n", sf);
00137 }
00138
00139
00140 template<class oType> int
00141 GrAudioSource<oType>::work2(VrSampleRange output, void *ao[])
00142 {
00143 sync (output.index);
00144
00145 unsigned size = output.size;
00146 oType **o = (oType **)ao;
00147
00148 while(size > 0) {
00149 const unsigned N = 2048;
00150 short tmp[N*2];
00151 int nbytes = std::min (size, N) * (sizeof(short) * 2);
00152
00153 int count = read(audiofd, tmp, nbytes);
00154
00155 if(count < 0) {
00156 perror ("GrAudioSource");
00157 exit(1);
00158 }
00159
00160 assert ((count & ((sizeof(short) * 2) - 1)) == 0);
00161
00162 if(num_streams == 1)
00163 for (unsigned int i = 0; i < count / (sizeof (short) * 2); i++) {
00164 o[0][i] = (oType)tmp[2*i]/scale_factor;
00165 }
00166 else
00167 for (unsigned int i = 0; i < count / (sizeof (short) * 2); i++) {
00168 o[0][i] = (oType)tmp[2*i]/scale_factor;
00169 o[1][i] = (oType)tmp[2*i+1]/scale_factor;
00170 }
00171
00172 size -= count / (sizeof (short) * 2);
00173 o[0] += count / (sizeof (short) * 2);
00174 if(num_streams==2)
00175 o[1] += count / (sizeof (short) * 2);
00176 }
00177 return output.size;
00178 }
00179
00180 template<> int
00181 GrAudioSource<VrComplex>::work2(VrSampleRange output, void *ao[])
00182 {
00183 unsigned size = output.size;
00184 VrComplex **o = (VrComplex **)ao;
00185
00186 while(size > 0) {
00187 const unsigned N = 2048;
00188 short tmp[N*2];
00189 int nbytes = std::min (size, N) * (sizeof(short) * 2);
00190
00191 int count = read(audiofd, tmp, nbytes);
00192
00193 if(count < 0) {
00194 perror ("GrAudioSource");
00195 exit(1);
00196 }
00197
00198 assert ((count & ((sizeof(short) * 2) - 1)) == 0);
00199
00200 for (unsigned int i = 0; i < count / (sizeof (short) * 2); i++)
00201 o[0][i] = VrComplex (tmp[2*i],tmp[2*i+1]) / scale_factor;
00202
00203 size -= count / (sizeof (short) * 2);
00204 o[0] += count / (sizeof (short) * 2);
00205 }
00206 return output.size;
00207 }
00208
00209 #endif