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
00038 #include "Devices/AudioGrabber.H"
00039
00040 #include "Component/OptionManager.H"
00041 #include "Component/ModelOptionDef.H"
00042 #include "Devices/DeviceOpts.H"
00043 #include "Image/Image.H"
00044 #include "Image/MatrixOps.H"
00045 #include "Util/Assert.H"
00046 #include "Util/Types.H"
00047 #include "Util/log.H"
00048 #include <fcntl.h>
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #include <sys/ioctl.h>
00052 #ifdef HAVE_SYS_SOUNDCARD_H
00053 # include <sys/soundcard.h>
00054 #endif
00055 #include <unistd.h>
00056
00057
00058 AudioGrabber::AudioGrabber(OptionManager& mgr, const std::string& descrName,
00059 const std::string& tagName) :
00060 ModelComponent(mgr, descrName, tagName),
00061 itsDevName(&OPT_AudioGrabberDevice, this),
00062 itsBits(&OPT_AudioGrabberBits, this),
00063 itsFreq(&OPT_AudioGrabberFreq, this),
00064 itsBufsamples(&OPT_AudioGrabberBufSamples, this),
00065 itsChans(&OPT_AudioGrabberChans, this),
00066 itsInterleaved(&OPT_AudioGrabberInterleaved,this),
00067 itsFd(-1)
00068 { }
00069
00070
00071 void AudioGrabber::start2()
00072 {
00073 #ifndef HAVE_SYS_SOUNDCARD_H
00074 LFATAL("Oops! I need to have <sys/soundcard.h>");
00075 #else
00076
00077 const char *device = itsDevName.getVal().c_str();
00078 itsFd = open(device, O_RDONLY);
00079 if (itsFd == -1) LFATAL("Cannot open device %s", device);
00080
00081
00082 uint bufsiz = itsBufsamples.getVal() * (itsBits.getVal() / 8);
00083 uint numChans = itsChans.getVal();
00084 bufsiz *= numChans;
00085
00086 if (bufsiz > 65534) LFATAL("Maximum buffer size of 64k bytes exceeded");
00087
00088
00089 int32 x = (bufsiz << 16) | 1;
00090 if (ioctl(itsFd, SNDCTL_DSP_SETFRAGMENT, &x) == -1)
00091 PLFATAL("Cannot SetFragment to %d buffers of %d samples",
00092 1, itsBufsamples.getVal());
00093 if (ioctl(itsFd, SOUND_PCM_RESET) == -1)
00094 PLFATAL("Cannot reset device %s", device);
00095 if (ioctl(itsFd, SOUND_PCM_SYNC) == -1)
00096 PLFATAL("Cannot sync device %s", device);
00097
00098 const int bits = itsBits.getVal();
00099 if (ioctl(itsFd, SOUND_PCM_WRITE_BITS, &bits) == -1)
00100 PLFATAL("Cannot set bits to %d", bits);
00101
00102 if (ioctl(itsFd, SOUND_PCM_WRITE_CHANNELS, &numChans) == -1)
00103 LFATAL("Cannot set number of channels to %d ", numChans);
00104
00105 if (ioctl(itsFd, SOUND_PCM_SYNC) == -1)
00106 PLFATAL("Cannot sync device %s", device);
00107
00108 const int freq = itsFreq.getVal();
00109 if (ioctl(itsFd, SOUND_PCM_WRITE_RATE, &freq) == -1)
00110 PLFATAL("Cannot set write rate to %d", freq);
00111
00112
00113 int rate, channels, nbbits, blocksize;
00114 if (ioctl(itsFd, SOUND_PCM_READ_CHANNELS, &channels) == -1)
00115 PLERROR("Cannot read nb channels");
00116 if (ioctl(itsFd, SOUND_PCM_READ_BITS, &nbbits) == -1)
00117 PLERROR("Cannot read nb bits");
00118 if (ioctl(itsFd, SOUND_PCM_READ_RATE, &rate) == -1)
00119 PLERROR("Cannot read sampling rate");
00120 if (ioctl(itsFd, SNDCTL_DSP_GETBLKSIZE, &blocksize) == -1)
00121 PLERROR("Cannot read blocksize");
00122 LDEBUG("%s: %d Hz, %d ch, %d bits, %db blocks", device, rate,
00123 channels, nbbits, blocksize);
00124 LINFO("its rate: %d, its channels: %d, its bits: %d, its block: %d",
00125 rate, channels, nbbits, blocksize);
00126 LINFO("Ready to grab...");
00127 #endif // HAVE_SYS_SOUNDCARD_H
00128 }
00129
00130
00131 void AudioGrabber::stop1()
00132 {
00133 #ifdef HAVE_SYS_SOUNDCARD_H
00134 if (ioctl(itsFd, SOUND_PCM_SYNC) == -1)
00135 PLFATAL("Cannot sync audio device");
00136 if (ioctl(itsFd, SOUND_PCM_RESET) == -1)
00137 PLFATAL("Cannot reset audio device");
00138 #endif
00139
00140 if (itsFd > -1) { close(itsFd); itsFd = -1; }
00141 }
00142
00143
00144 AudioGrabber::~AudioGrabber()
00145 { }
00146
00147
00148 template <class T>
00149 void AudioGrabber::grab(AudioBuffer<T>& buf) const
00150 {
00151 ASSERT(itsFd != -1);
00152 ASSERT(itsBits.getVal() == sizeof(T) * 8);
00153
00154 int myBufSamp = itsBufsamples.getVal();
00155 int myChans = itsChans.getVal();
00156
00157 AudioBuffer<T> b(myBufSamp,
00158 myChans,
00159 float(itsFreq.getVal()),
00160 NO_INIT);
00161
00162 int got = read(itsFd, b.getDataPtr(), b.sizeBytes());
00163 if (got != int(b.sizeBytes()))
00164 PLERROR("Error reading from device: got %d of %u requested bytes",
00165 got, b.sizeBytes());
00166
00167 if(itsInterleaved.getVal())
00168 {
00169 ASSERT(myChans > 1);
00170
00171
00172
00173
00174
00175 Image<T> interleaved;
00176 interleaved.attach(b.getDataPtr(), myChans, myBufSamp);
00177 Image<T> chunked = transpose(interleaved);
00178
00179 AudioBuffer<T> tposed(chunked.getArrayPtr(), myBufSamp, myChans, itsFreq.getVal());
00180
00181 buf = tposed;
00182 interleaved.detach();
00183
00184 }
00185 else
00186 buf=b;
00187
00188 }
00189
00190
00191 template void AudioGrabber::grab(AudioBuffer<byte>& buf) const;
00192 template void AudioGrabber::grab(AudioBuffer<uint16>& buf) const;
00193 template void AudioGrabber::grab(AudioBuffer<int16>& buf) const;
00194
00195
00196
00197
00198
00199