1 /**********
2 This library is free software; you can redistribute it and/or modify it under
3 the terms of the GNU Lesser General Public License as published by the
4 Free Software Foundation; either version 3 of the License, or (at your
5 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6 
7 This library is distributed in the hope that it will be useful, but WITHOUT
8 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
10 more details.
11 
12 You should have received a copy of the GNU Lesser General Public License
13 along with this library; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
15 **********/
16 // "liveMedia"
17 // Copyright (c) 1996-2020 Live Networks, Inc.  All rights reserved.
18 // A WAV audio file source
19 // Implementation
20 
21 #include "WAVAudioFileSource.hh"
22 #include "InputFile.hh"
23 #include "GroupsockHelper.hh"
24 
25 ////////// WAVAudioFileSource //////////
26 
27 WAVAudioFileSource*
createNew(UsageEnvironment & env,char const * fileName)28 WAVAudioFileSource::createNew(UsageEnvironment& env, char const* fileName) {
29   do {
30     FILE* fid = OpenInputFile(env, fileName);
31     if (fid == NULL) break;
32 
33     WAVAudioFileSource* newSource = new WAVAudioFileSource(env, fid);
34     if (newSource != NULL && newSource->bitsPerSample() == 0) {
35       // The WAV file header was apparently invalid.
36       Medium::close(newSource);
37       break;
38     }
39 
40     newSource->fFileSize = (unsigned)GetFileSize(fileName, fid);
41 
42     return newSource;
43   } while (0);
44 
45   return NULL;
46 }
47 
numPCMBytes() const48 unsigned WAVAudioFileSource::numPCMBytes() const {
49   if (fFileSize < fWAVHeaderSize) return 0;
50   return fFileSize - fWAVHeaderSize;
51 }
52 
setScaleFactor(int scale)53 void WAVAudioFileSource::setScaleFactor(int scale) {
54   if (!fFidIsSeekable) return; // we can't do 'trick play' operations on non-seekable files
55 
56   fScaleFactor = scale;
57 
58   if (fScaleFactor < 0 && TellFile64(fFid) > 0) {
59     // Because we're reading backwards, seek back one sample, to ensure that
60     // (i)  we start reading the last sample before the start point, and
61     // (ii) we don't hit end-of-file on the first read.
62     int bytesPerSample = (fNumChannels*fBitsPerSample)/8;
63     if (bytesPerSample == 0) bytesPerSample = 1;
64     SeekFile64(fFid, -bytesPerSample, SEEK_CUR);
65   }
66 }
67 
seekToPCMByte(unsigned byteNumber)68 void WAVAudioFileSource::seekToPCMByte(unsigned byteNumber) {
69   byteNumber += fWAVHeaderSize;
70   if (byteNumber > fFileSize) byteNumber = fFileSize;
71 
72   SeekFile64(fFid, byteNumber, SEEK_SET);
73 }
74 
limitNumBytesToStream(unsigned numBytesToStream)75 void WAVAudioFileSource::limitNumBytesToStream(unsigned numBytesToStream) {
76   fNumBytesToStream = numBytesToStream;
77   fLimitNumBytesToStream = fNumBytesToStream > 0;
78 }
79 
getAudioFormat()80 unsigned char WAVAudioFileSource::getAudioFormat() {
81   return fAudioFormat;
82 }
83 
84 
85 #define nextc fgetc(fid)
86 
get4Bytes(FILE * fid,u_int32_t & result)87 static Boolean get4Bytes(FILE* fid, u_int32_t& result) { // little-endian
88   int c0, c1, c2, c3;
89   if ((c0 = nextc) == EOF || (c1 = nextc) == EOF ||
90       (c2 = nextc) == EOF || (c3 = nextc) == EOF) return False;
91   result = (c3<<24)|(c2<<16)|(c1<<8)|c0;
92   return True;
93 }
94 
get2Bytes(FILE * fid,u_int16_t & result)95 static Boolean get2Bytes(FILE* fid, u_int16_t& result) {//little-endian
96   int c0, c1;
97   if ((c0 = nextc) == EOF || (c1 = nextc) == EOF) return False;
98   result = (c1<<8)|c0;
99   return True;
100 }
101 
skipBytes(FILE * fid,int num)102 static Boolean skipBytes(FILE* fid, int num) {
103   while (num-- > 0) {
104     if (nextc == EOF) return False;
105   }
106   return True;
107 }
108 
WAVAudioFileSource(UsageEnvironment & env,FILE * fid)109 WAVAudioFileSource::WAVAudioFileSource(UsageEnvironment& env, FILE* fid)
110   : AudioInputDevice(env, 0, 0, 0, 0)/* set the real parameters later */,
111     fFid(fid), fFidIsSeekable(False), fLastPlayTime(0), fHaveStartedReading(False), fWAVHeaderSize(0), fFileSize(0),
112     fScaleFactor(1), fLimitNumBytesToStream(False), fNumBytesToStream(0), fAudioFormat(WA_UNKNOWN) {
113   // Check the WAV file header for validity.
114   // Note: The following web pages contain info about the WAV format:
115   // http://www.ringthis.com/dev/wave_format.htm
116   // http://www.lightlink.com/tjweber/StripWav/Canon.html
117   // http://www.onicos.com/staff/iz/formats/wav.html
118 
119   Boolean success = False; // until we learn otherwise
120   do {
121     // RIFF Chunk:
122     if (nextc != 'R' || nextc != 'I' || nextc != 'F' || nextc != 'F') break;
123     if (!skipBytes(fid, 4)) break;
124     if (nextc != 'W' || nextc != 'A' || nextc != 'V' || nextc != 'E') break;
125 
126     // Skip over any chunk that's not a FORMAT ('fmt ') chunk:
127     u_int32_t tmp;
128     if (!get4Bytes(fid, tmp)) break;
129     while (tmp != 0x20746d66/*'fmt ', little-endian*/) {
130       // Skip this chunk:
131       u_int32_t chunkLength;
132       if (!get4Bytes(fid, chunkLength)) break;
133       if (!skipBytes(fid, chunkLength)) break;
134       if (!get4Bytes(fid, tmp)) break;
135     }
136 
137     // FORMAT Chunk (the 4-byte header code has already been parsed):
138     unsigned formatLength;
139     if (!get4Bytes(fid, formatLength)) break;
140     unsigned short audioFormat;
141     if (!get2Bytes(fid, audioFormat)) break;
142 
143     fAudioFormat = (unsigned char)audioFormat;
144     if (fAudioFormat != WA_PCM && fAudioFormat != WA_PCMA && fAudioFormat != WA_PCMU && fAudioFormat != WA_IMA_ADPCM) {
145       // It's a format that we don't (yet) understand
146       env.setResultMsg("Audio format is not one that we handle (PCM/PCMU/PCMA or IMA ADPCM)");
147       break;
148     }
149     unsigned short numChannels;
150     if (!get2Bytes(fid, numChannels)) break;
151     fNumChannels = (unsigned char)numChannels;
152     if (fNumChannels < 1 || fNumChannels > 2) { // invalid # channels
153       char errMsg[100];
154       sprintf(errMsg, "Bad # channels: %d", fNumChannels);
155       env.setResultMsg(errMsg);
156       break;
157     }
158     if (!get4Bytes(fid, fSamplingFrequency)) break;
159     if (fSamplingFrequency == 0) {
160       env.setResultMsg("Bad sampling frequency: 0");
161       break;
162     }
163     if (!skipBytes(fid, 6)) break; // "nAvgBytesPerSec" (4 bytes) + "nBlockAlign" (2 bytes)
164     unsigned short bitsPerSample;
165     if (!get2Bytes(fid, bitsPerSample)) break;
166     fBitsPerSample = (unsigned char)bitsPerSample;
167     if (fBitsPerSample == 0) {
168       env.setResultMsg("Bad bits-per-sample: 0");
169       break;
170     }
171     if (!skipBytes(fid, formatLength - 16)) break;
172 
173     // FACT chunk (optional):
174     int c = nextc;
175     if (c == 'f') {
176       if (nextc != 'a' || nextc != 'c' || nextc != 't') break;
177       unsigned factLength;
178       if (!get4Bytes(fid, factLength)) break;
179       if (!skipBytes(fid, factLength)) break;
180       c = nextc;
181     }
182 
183     // EYRE chunk (optional):
184     if (c == 'e') {
185       if (nextc != 'y' || nextc != 'r' || nextc != 'e') break;
186       unsigned eyreLength;
187       if (!get4Bytes(fid, eyreLength)) break;
188       if (!skipBytes(fid, eyreLength)) break;
189       c = nextc;
190     }
191 
192     // DATA Chunk:
193     if (c != 'd' || nextc != 'a' || nextc != 't' || nextc != 'a') break;
194     if (!skipBytes(fid, 4)) break;
195 
196     // The header is good; the remaining data are the sample bytes.
197     fWAVHeaderSize = (unsigned)TellFile64(fid);
198     success = True;
199   } while (0);
200 
201   if (!success) {
202     env.setResultMsg("Bad WAV file format");
203     // Set "fBitsPerSample" to zero, to indicate failure:
204     fBitsPerSample = 0;
205     return;
206   }
207 
208   fPlayTimePerSample = 1e6/(double)fSamplingFrequency;
209 
210   // Although PCM is a sample-based format, we group samples into
211   // 'frames' for efficient delivery to clients.  Set up our preferred
212   // frame size to be close to 20 ms, if possible, but always no greater
213   // than 1400 bytes (to ensure that it will fit in a single RTP packet)
214   unsigned maxSamplesPerFrame = (1400*8)/(fNumChannels*fBitsPerSample);
215   unsigned desiredSamplesPerFrame = (unsigned)(0.02*fSamplingFrequency);
216   unsigned samplesPerFrame = desiredSamplesPerFrame < maxSamplesPerFrame ? desiredSamplesPerFrame : maxSamplesPerFrame;
217   fPreferredFrameSize = (samplesPerFrame*fNumChannels*fBitsPerSample)/8;
218 
219   fFidIsSeekable = FileIsSeekable(fFid);
220 #ifndef READ_FROM_FILES_SYNCHRONOUSLY
221   // Now that we've finished reading the WAV header, all future reads (of audio samples) from the file will be asynchronous:
222   makeSocketNonBlocking(fileno(fFid));
223 #endif
224 }
225 
~WAVAudioFileSource()226 WAVAudioFileSource::~WAVAudioFileSource() {
227   if (fFid == NULL) return;
228 
229 #ifndef READ_FROM_FILES_SYNCHRONOUSLY
230   envir().taskScheduler().turnOffBackgroundReadHandling(fileno(fFid));
231 #endif
232 
233   CloseInputFile(fFid);
234 }
235 
doGetNextFrame()236 void WAVAudioFileSource::doGetNextFrame() {
237   if (feof(fFid) || ferror(fFid) || (fLimitNumBytesToStream && fNumBytesToStream == 0)) {
238     handleClosure();
239     return;
240   }
241 
242   fFrameSize = 0; // until it's set later
243 #ifdef READ_FROM_FILES_SYNCHRONOUSLY
244   doReadFromFile();
245 #else
246   if (!fHaveStartedReading) {
247     // Await readable data from the file:
248     envir().taskScheduler().turnOnBackgroundReadHandling(fileno(fFid),
249 							 (TaskScheduler::BackgroundHandlerProc*)&fileReadableHandler, this);
250     fHaveStartedReading = True;
251   }
252 #endif
253 }
254 
doStopGettingFrames()255 void WAVAudioFileSource::doStopGettingFrames() {
256   envir().taskScheduler().unscheduleDelayedTask(nextTask());
257 #ifndef READ_FROM_FILES_SYNCHRONOUSLY
258   envir().taskScheduler().turnOffBackgroundReadHandling(fileno(fFid));
259   fHaveStartedReading = False;
260 #endif
261 }
262 
fileReadableHandler(WAVAudioFileSource * source,int)263 void WAVAudioFileSource::fileReadableHandler(WAVAudioFileSource* source, int /*mask*/) {
264   if (!source->isCurrentlyAwaitingData()) {
265     source->doStopGettingFrames(); // we're not ready for the data yet
266     return;
267   }
268   source->doReadFromFile();
269 }
270 
doReadFromFile()271 void WAVAudioFileSource::doReadFromFile() {
272   // Try to read as many bytes as will fit in the buffer provided (or "fPreferredFrameSize" if less)
273   if (fLimitNumBytesToStream && fNumBytesToStream < fMaxSize) {
274     fMaxSize = fNumBytesToStream;
275   }
276   if (fPreferredFrameSize < fMaxSize) {
277     fMaxSize = fPreferredFrameSize;
278   }
279   unsigned bytesPerSample = (fNumChannels*fBitsPerSample)/8;
280   if (bytesPerSample == 0) bytesPerSample = 1; // because we can't read less than a byte at a time
281 
282   // For 'trick play', read one sample at a time; otherwise (normal case) read samples in bulk:
283   unsigned bytesToRead = fScaleFactor == 1 ? fMaxSize - fMaxSize%bytesPerSample : bytesPerSample;
284   unsigned numBytesRead;
285   while (1) { // loop for 'trick play' only
286 #ifdef READ_FROM_FILES_SYNCHRONOUSLY
287     numBytesRead = fread(fTo, 1, bytesToRead, fFid);
288 #else
289     if (fFidIsSeekable) {
290       numBytesRead = fread(fTo, 1, bytesToRead, fFid);
291     } else {
292       // For non-seekable files (e.g., pipes), call "read()" rather than "fread()", to ensure that the read doesn't block:
293       numBytesRead = read(fileno(fFid), fTo, bytesToRead);
294     }
295 #endif
296     if (numBytesRead == 0) {
297      handleClosure();
298       return;
299     }
300     fFrameSize += numBytesRead;
301     fTo += numBytesRead;
302     fMaxSize -= numBytesRead;
303     fNumBytesToStream -= numBytesRead;
304 
305     // If we did an asynchronous read, and didn't read an integral number of samples, then we need to wait for another read:
306 #ifndef READ_FROM_FILES_SYNCHRONOUSLY
307     if (fFrameSize%bytesPerSample > 0) return;
308 #endif
309 
310     // If we're doing 'trick play', then seek to the appropriate place for reading the next sample,
311     // and keep reading until we fill the provided buffer:
312     if (fScaleFactor != 1) {
313       SeekFile64(fFid, (fScaleFactor-1)*bytesPerSample, SEEK_CUR);
314       if (fMaxSize < bytesPerSample) break;
315     } else {
316       break; // from the loop (normal case)
317     }
318   }
319 
320   // Set the 'presentation time' and 'duration' of this frame:
321   if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
322     // This is the first frame, so use the current time:
323     gettimeofday(&fPresentationTime, NULL);
324   } else {
325     // Increment by the play time of the previous data:
326     unsigned uSeconds = fPresentationTime.tv_usec + fLastPlayTime;
327     fPresentationTime.tv_sec += uSeconds/1000000;
328     fPresentationTime.tv_usec = uSeconds%1000000;
329   }
330 
331   // Remember the play time of this data:
332   fDurationInMicroseconds = fLastPlayTime
333     = (unsigned)((fPlayTimePerSample*fFrameSize)/bytesPerSample);
334 
335   // Inform the reader that he has data:
336 #ifdef READ_FROM_FILES_SYNCHRONOUSLY
337   // To avoid possible infinite recursion, we need to return to the event loop to do this:
338   nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
339                                 (TaskFunc*)FramedSource::afterGetting, this);
340 #else
341   // Because the file read was done from the event loop, we can call the
342   // 'after getting' function directly, without risk of infinite recursion:
343   FramedSource::afterGetting(this);
344 #endif
345 }
346 
setInputPort(int)347 Boolean WAVAudioFileSource::setInputPort(int /*portIndex*/) {
348   return True;
349 }
350 
getAverageLevel() const351 double WAVAudioFileSource::getAverageLevel() const {
352   return 0.0;//##### fix this later
353 }
354