00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "WAVAudioFileSource.hh"
00022 #include "InputFile.hh"
00023 #include "GroupsockHelper.hh"
00024
00026
00027 WAVAudioFileSource*
00028 WAVAudioFileSource::createNew(UsageEnvironment& env, char const* fileName) {
00029 do {
00030 FILE* fid = OpenInputFile(env, fileName);
00031 if (fid == NULL) break;
00032
00033 WAVAudioFileSource* newSource = new WAVAudioFileSource(env, fid);
00034 if (newSource != NULL && newSource->bitsPerSample() == 0) {
00035
00036 Medium::close(newSource);
00037 break;
00038 }
00039
00040 newSource->fFileSize = (unsigned)GetFileSize(fileName, fid);
00041
00042 return newSource;
00043 } while (0);
00044
00045 return NULL;
00046 }
00047
00048 unsigned WAVAudioFileSource::numPCMBytes() const {
00049 if (fFileSize < fWAVHeaderSize) return 0;
00050 return fFileSize - fWAVHeaderSize;
00051 }
00052
00053 void WAVAudioFileSource::setScaleFactor(int scale) {
00054 fScaleFactor = scale;
00055
00056 if (fScaleFactor < 0 && ftell(fFid) > 0) {
00057
00058
00059
00060 int const bytesPerSample = (fNumChannels*fBitsPerSample)/8;
00061 fseek(fFid, -bytesPerSample, SEEK_CUR);
00062 }
00063 }
00064
00065 void WAVAudioFileSource::seekToPCMByte(unsigned byteNumber) {
00066 byteNumber += fWAVHeaderSize;
00067 if (byteNumber > fFileSize) byteNumber = fFileSize;
00068
00069 fseek(fFid, byteNumber, SEEK_SET);
00070 }
00071
00072 #define nextc fgetc(fid)
00073 #define ucEOF ((unsigned char)EOF)
00074
00075 static Boolean get4Bytes(FILE* fid, unsigned& result) {
00076 unsigned char c0, c1, c2, c3;
00077 if ((c0 = nextc) == ucEOF || (c1 = nextc) == ucEOF ||
00078 (c2 = nextc) == ucEOF || (c3 = nextc) == ucEOF) return False;
00079 result = (c3<<24)|(c2<<16)|(c1<<8)|c0;
00080 return True;
00081 }
00082
00083 static Boolean get2Bytes(FILE* fid, unsigned short& result) {
00084 unsigned char c0, c1;
00085 if ((c0 = nextc) == ucEOF || (c1 = nextc) == ucEOF) return False;
00086 result = (c1<<8)|c0;
00087 return True;
00088 }
00089
00090 static Boolean skipBytes(FILE* fid, int num) {
00091 while (num-- > 0) {
00092 if (nextc == ucEOF) return False;
00093 }
00094 return True;
00095 }
00096
00097 WAVAudioFileSource::WAVAudioFileSource(UsageEnvironment& env, FILE* fid)
00098 : AudioInputDevice(env, 0, 0, 0, 0),
00099 fFid(fid), fLastPlayTime(0), fWAVHeaderSize(0), fFileSize(0), fScaleFactor(1) {
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 Boolean success = False;
00110 do {
00111
00112 if (nextc != 'R' || nextc != 'I' || nextc != 'F' || nextc != 'F') break;
00113 if (!skipBytes(fid, 4)) break;
00114 if (nextc != 'W' || nextc != 'A' || nextc != 'V' || nextc != 'E') break;
00115
00116
00117 if (nextc != 'f' || nextc != 'm' || nextc != 't' || nextc != ' ') break;
00118 unsigned formatLength;
00119 if (!get4Bytes(fid, formatLength)) break;
00120 unsigned short audioFormat;
00121 if (!get2Bytes(fid, audioFormat)) break;
00122 if (audioFormat != 1) {
00123 env.setResultMsg("Audio format is not PCM");
00124 break;
00125 }
00126 unsigned short numChannels;
00127 if (!get2Bytes(fid, numChannels)) break;
00128 fNumChannels = (unsigned char)numChannels;
00129 if (fNumChannels < 1 || fNumChannels > 2) {
00130 char errMsg[100];
00131 sprintf(errMsg, "Bad # channels: %d", fNumChannels);
00132 env.setResultMsg(errMsg);
00133 break;
00134 }
00135 if (!get4Bytes(fid, fSamplingFrequency)) break;
00136 if (fSamplingFrequency == 0) {
00137 env.setResultMsg("Bad sampling frequency: 0");
00138 break;
00139 }
00140 if (!skipBytes(fid, 6)) break;
00141 unsigned short bitsPerSample;
00142 if (!get2Bytes(fid, bitsPerSample)) break;
00143 fBitsPerSample = (unsigned char)bitsPerSample;
00144 if (fBitsPerSample == 0) {
00145 env.setResultMsg("Bad bits-per-sample: 0");
00146 break;
00147 }
00148 if (!skipBytes(fid, formatLength - 16)) break;
00149
00150
00151 unsigned char c = nextc;
00152 if (c == 'f') {
00153 if (nextc != 'a' || nextc != 'c' || nextc != 't') break;
00154 unsigned factLength;
00155 if (!get4Bytes(fid, factLength)) break;
00156 if (!skipBytes(fid, factLength)) break;
00157 c = nextc;
00158 }
00159
00160
00161 if (c != 'd' || nextc != 'a' || nextc != 't' || nextc != 'a') break;
00162 if (!skipBytes(fid, 4)) break;
00163
00164
00165 fWAVHeaderSize = ftell(fid);
00166 success = True;
00167 } while (0);
00168
00169 if (!success) {
00170 env.setResultMsg("Bad WAV file format");
00171
00172 fBitsPerSample = 0;
00173 return;
00174 }
00175
00176 fPlayTimePerSample = 1e6/(double)fSamplingFrequency;
00177
00178
00179
00180
00181
00182 unsigned maxSamplesPerFrame = (1400*8)/(fNumChannels*fBitsPerSample);
00183 unsigned desiredSamplesPerFrame = (unsigned)(0.02*fSamplingFrequency);
00184 unsigned samplesPerFrame = desiredSamplesPerFrame < maxSamplesPerFrame
00185 ? desiredSamplesPerFrame : maxSamplesPerFrame;
00186 fPreferredFrameSize = (samplesPerFrame*fNumChannels*fBitsPerSample)/8;
00187 }
00188
00189 WAVAudioFileSource::~WAVAudioFileSource() {
00190 CloseInputFile(fFid);
00191 }
00192
00193 void WAVAudioFileSource::doGetNextFrame() {
00194 if (feof(fFid) || ferror(fFid)) {
00195 handleClosure(this);
00196 return;
00197 }
00198
00199
00200
00201 if (fPreferredFrameSize < fMaxSize) {
00202 fMaxSize = fPreferredFrameSize;
00203 }
00204 unsigned const bytesPerSample = (fNumChannels*fBitsPerSample)/8;
00205 unsigned bytesToRead = fMaxSize - fMaxSize%bytesPerSample;
00206 if (fScaleFactor == 1) {
00207
00208 fFrameSize = fread(fTo, 1, bytesToRead, fFid);
00209 } else {
00210
00211 fFrameSize = 0;
00212 while (bytesToRead > 0) {
00213 size_t bytesRead = fread(fTo, 1, bytesPerSample, fFid);
00214 if (bytesRead <= 0) break;
00215 fTo += bytesRead;
00216 fFrameSize += bytesRead;
00217 bytesToRead -= bytesRead;
00218
00219
00220 fseek(fFid, (fScaleFactor-1)*bytesPerSample, SEEK_CUR);
00221 }
00222 }
00223
00224
00225 if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
00226
00227 gettimeofday(&fPresentationTime, NULL);
00228 } else {
00229
00230 unsigned uSeconds = fPresentationTime.tv_usec + fLastPlayTime;
00231 fPresentationTime.tv_sec += uSeconds/1000000;
00232 fPresentationTime.tv_usec = uSeconds%1000000;
00233 }
00234
00235
00236 fDurationInMicroseconds = fLastPlayTime
00237 = (unsigned)((fPlayTimePerSample*fFrameSize)/bytesPerSample);
00238
00239
00240 #if defined(__WIN32__) || defined(_WIN32)
00241
00242
00243
00244
00245
00246
00247
00248 afterGetting(this);
00249 #else
00250 nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
00251 (TaskFunc*)FramedSource::afterGetting, this);
00252 #endif
00253 }
00254
00255 Boolean WAVAudioFileSource::setInputPort(int ) {
00256 return True;
00257 }
00258
00259 double WAVAudioFileSource::getAverageLevel() const {
00260 return 0.0;
00261 }