1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4     Rosegarden
5     A sequencer and musical notation editor.
6     Copyright 2000-2021 the Rosegarden development team.
7     See the AUTHORS file for more details.
8 
9     This program is free software; you can redistribute it and/or
10     modify it under the terms of the GNU General Public License as
11     published by the Free Software Foundation; either version 2 of the
12     License, or (at your option) any later version.  See the file
13     COPYING included with this distribution for more information.
14 */
15 
16 #define RG_MODULE_STRING "[RIFFAudioFile]"
17 
18 #include "RIFFAudioFile.h"
19 #include "base/RealTime.h"
20 #include "base/Profiler.h"
21 #include "misc/Strings.h"
22 #include "misc/Debug.h"
23 
24 //#define DEBUG_RIFF
25 
26 // Constants related to RIFF/WAV files
27 //
28 static const char AUDIO_RIFF_ID[] = "RIFF";
29 static const char AUDIO_WAVE_ID[] = "WAVE";
30 static const char AUDIO_FORMAT_ID[] = "fmt ";    // Always four bytes
31 static const char AUDIO_BWF_ID[] = "bext";       // BWF chunk id
32 
33 namespace Rosegarden
34 {
35 
36 RIFFAudioFile::RIFFAudioFile(unsigned int id,
37                              const std::string &name,
38                              const QString &fileName):
39     AudioFile(id, name, fileName),
40     m_subFormat(PCM),
41     m_bytesPerSecond(0),
42     m_bytesPerFrame(0)
43 {}
44 
45 RIFFAudioFile::RIFFAudioFile(const QString &fileName,
46                              unsigned int channels = 1,
47                              unsigned int sampleRate = 48000,
48                              unsigned int bytesPerSecond = 6000,
49                              unsigned int bytesPerFrame = 2,
50                              unsigned int bitsPerSample = 16):
51         AudioFile(0, "", fileName)
52 {
53     m_bitsPerSample = bitsPerSample;
54     m_sampleRate = sampleRate;
55     m_bytesPerSecond = bytesPerSecond;
56     m_bytesPerFrame = bytesPerFrame;
57     m_channels = channels;
58 
59     if (bitsPerSample == 16)
60         m_subFormat = PCM;
61     else if (bitsPerSample == 32)
62         m_subFormat = FLOAT;
63     else
64         throw(BadSoundFileException(m_fileName, qstrtostr(tr("Rosegarden currently only supports 16 or 32-bit PCM or IEEE floating-point RIFF files for writing"))));
65 
66 }
67 
68 RIFFAudioFile::~RIFFAudioFile()
69 {}
70 
71 
72 // Show some stats on this file
73 //
74 void
75 RIFFAudioFile::printStats()
76 {
77     RG_DEBUG << "filename         : " << m_fileName << '\n'
78     << "channels         : " << m_channels << '\n'
79     << "sample rate      : " << m_sampleRate << '\n'
80     << "bytes per second : " << m_bytesPerSecond << '\n'
81     << "bits per sample  : " << m_bitsPerSample << '\n'
82     << "bytes per frame  : " << m_bytesPerFrame << '\n'
83     << "file length      : " << m_fileSize << " bytes" << '\n';
84 }
85 
86 bool
87 RIFFAudioFile::appendSamples(const std::string &buffer)
88 {
89     /*
90     if (m_outFile == 0 || m_type != WAV)
91         return false;
92         */
93 
94     // write out
95     putBytes(m_outFile, buffer);
96 
97     return true;
98 }
99 
100 bool
101 RIFFAudioFile::appendSamples(const char *buf, unsigned int frames)
102 {
103     putBytes(m_outFile, buf, frames * m_bytesPerFrame);
104     return true;
105 }
106 
107 // scan on from a descriptor position
108 bool
109 RIFFAudioFile::scanForward(std::ifstream *file, const RealTime &time)
110 {
111     // sanity
112     if (file == nullptr)
113         return false;
114 
115     unsigned int totalSamples = m_sampleRate * time.sec +
116                                 ( ( m_sampleRate * time.usec() ) / 1000000 );
117     unsigned int totalBytes = totalSamples * m_bytesPerFrame;
118 
119     m_loseBuffer = true;
120 
121     // do the seek
122     file->seekg(totalBytes, std::ios::cur);
123 
124     if (file->eof())
125         return false;
126 
127     return true;
128 }
129 
130 bool
131 RIFFAudioFile::scanForward(const RealTime &time)
132 {
133     if (*m_inFile)
134         return scanForward(m_inFile, time);
135     else
136         return false;
137 }
138 
139 bool
140 RIFFAudioFile::scanTo(const RealTime &time)
141 {
142     if (*m_inFile)
143         return scanTo(m_inFile, time);
144     else
145         return false;
146 
147 }
148 
149 bool
150 RIFFAudioFile::scanTo(std::ifstream *file, const RealTime &time)
151 {
152     // sanity
153     if (file == nullptr)
154         return false;
155 
156     // whatever we do here we invalidate the read buffer
157     //
158     m_loseBuffer = true;
159 
160     file->clear();
161 
162     // seek past header - don't hardcode this - use the file format
163     // spec to get header length and then scoot to that.
164     //
165     file->seekg(16, std::ios::beg);
166 
167     unsigned int lengthOfFormat = 0;
168 
169     try {
170         lengthOfFormat = getIntegerFromLittleEndian(getBytes(file, 4));
171         file->seekg(lengthOfFormat, std::ios::cur);
172 
173         // check we've got data chunk start
174 	std::string chunkName;
175 	int chunkLength = 0;
176 
177         while ((chunkName = getBytes(file, 4)) != "data") {
178 	    if (file->eof()) {
179 		RG_WARNING << "RIFFAudioFile::scanTo(): failed to find data";
180 		return false;
181 	    }
182 //#ifdef DEBUG_RIFF
183 	    RG_WARNING << "RIFFAudioFile::scanTo(): skipping chunk: " << chunkName;
184 //#endif
185 	    chunkLength = getIntegerFromLittleEndian(getBytes(file, 4));
186 	    if (chunkLength < 0) {
187 		RG_WARNING << "RIFFAudioFile::scanTo(): negative chunk length "
188 			  << chunkLength << " for chunk " << chunkName;
189 		return false;
190 	    }
191 	    file->seekg(chunkLength, std::ios::cur);
192         }
193 
194         // get the length of the data chunk, and scan past it as a side-effect
195 	chunkLength = getIntegerFromLittleEndian(getBytes(file, 4));
196 #ifdef DEBUG_RIFF
197         RG_DEBUG << "RIFFAudioFile::scanTo() - data chunk size =" << chunkLength;
198 #endif
199 
200     } catch (const BadSoundFileException &s) {
201 #ifdef DEBUG_RIFF
202         RG_WARNING << "RIFFAudioFile::scanTo - EXCEPTION - \"" << s.getMessage() << "\"";
203 #endif
204 
205         return false;
206     }
207 
208     // Ok, we're past all the header information in the data chunk.
209     // Now, how much do we scan forward?
210     //
211     size_t totalFrames = size_t(RealTime::realTime2Frame(time, m_sampleRate));
212 
213     unsigned int totalBytes = totalFrames * m_bytesPerFrame;
214 
215     // When using seekg we have to keep an eye on the boundaries ourselves
216     //
217     if (totalBytes > m_fileSize - (lengthOfFormat + 16 + 8)) {
218 #ifdef DEBUG_RIFF
219         RG_WARNING << "RIFFAudioFile::scanTo() - attempting to move past end of data block";
220 #endif
221 
222         return false;
223     }
224 
225 #ifdef DEBUG_RIFF
226     RG_DEBUG << "RIFFAudioFile::scanTo - seeking to " << time
227     << " (" << totalBytes << " bytes from current " << file->tellg()
228     << ")";
229 #endif
230 
231     file->seekg(totalBytes, std::ios::cur);
232 
233     return true;
234 }
235 
236 // Get a certain number of sample frames - a frame is a set
237 // of samples (all channels) for a given sample quanta.
238 //
239 // For example, getting one frame of 16-bit stereo will return
240 // four bytes of data (two per channel).
241 //
242 //
243 std::string
244 RIFFAudioFile::getSampleFrames(std::ifstream *file, unsigned int frames)
245 {
246     // sanity
247     if (file == nullptr)
248         return std::string("");
249 
250     // Bytes per sample already takes into account the number
251     // of channels we're using
252     //
253     long totalBytes = frames * m_bytesPerFrame;
254 
255     try {
256         return getBytes(file, totalBytes);
257     } catch (const BadSoundFileException &s) {
258         return "";
259     }
260 }
261 
262 unsigned int
263 RIFFAudioFile::getSampleFrames(std::ifstream *file, char *buf,
264                                unsigned int frames)
265 {
266     if (file == nullptr)
267         return 0;
268     try {
269         return getBytes(file, buf, frames * m_bytesPerFrame) / m_bytesPerFrame;
270     } catch (const BadSoundFileException &s) {
271         return 0;
272     }
273 }
274 
275 std::string
276 RIFFAudioFile::getSampleFrames(unsigned int frames)
277 {
278     if (*m_inFile) {
279         return getSampleFrames(m_inFile, frames);
280     } else {
281         return std::string("");
282     }
283 }
284 
285 // Return a slice of frames over a time period
286 //
287 std::string
288 RIFFAudioFile::getSampleFrameSlice(std::ifstream *file, const RealTime &time)
289 {
290     // sanity
291     if (file == nullptr)
292         return std::string("");
293 
294     long totalFrames = RealTime::realTime2Frame(time, m_sampleRate);
295     long totalBytes = totalFrames * m_bytesPerFrame;
296 
297     try {
298         return getBytes(file, totalBytes);
299     } catch (const BadSoundFileException &s) {
300         return "";
301     }
302 }
303 
304 std::string
305 RIFFAudioFile::getSampleFrameSlice(const RealTime &time)
306 {
307     if (*m_inFile) {
308         return getSampleFrameSlice(m_inFile, time);
309     } else {
310         return std::string("");
311     }
312 }
313 
314 RealTime
315 RIFFAudioFile::getLength()
316 {
317     // Fixed header size = 44 but prove by getting it from the file too
318     //
319     unsigned int headerLength = 44;
320 
321     if (m_inFile) {
322         m_inFile->seekg(16, std::ios::beg);
323         headerLength = getIntegerFromLittleEndian(getBytes(m_inFile, 4));
324         m_inFile->seekg(headerLength, std::ios::cur);
325         headerLength += (16 + 8);
326     }
327 
328     if (!m_bytesPerFrame || !m_sampleRate) return RealTime::zeroTime;
329 
330     double frames = (m_fileSize - headerLength) / m_bytesPerFrame;
331     double seconds = frames / ((double)m_sampleRate);
332 
333     int secs = int(seconds);
334     int nsecs = int((seconds - secs) * 1000000000.0);
335 
336     return RealTime(secs, nsecs);
337 }
338 
339 
340 // The RIFF file format chunk defines our internal meta data.
341 //
342 // Courtesy of:
343 //   http://www.technology.niagarac.on.ca/courses/comp630/WavFileFormat.html
344 //
345 // 'The WAV file itself consists of three "chunks" of information:
346 //  The RIFF chunk which identifies the file as a WAV file, The FORMAT
347 //  chunk which identifies parameters such as sample rate and the DATA
348 //  chunk which contains the actual data (samples).'
349 //
350 //
351 void
352 RIFFAudioFile::readFormatChunk()
353 {
354     if (m_inFile == nullptr)
355         return ;
356 
357     m_loseBuffer = true;
358 
359     // seek to beginning
360     m_inFile->seekg(0, std::ios::beg);
361 
362     // get the header string
363     //
364     std::string hS = getBytes(36);
365 
366     // Look for the RIFF identifier and bomb out if we don't find it
367     //
368     if (hS.compare(0, 4, AUDIO_RIFF_ID) != 0) {
369 #ifdef DEBUG_RIFF
370         RG_WARNING << "RIFFAudioFile::readFormatChunk - "
371         << "can't find RIFF identifier\n";
372 #endif
373 
374         throw(BadSoundFileException(m_fileName, qstrtostr(tr("Can't find RIFF identifier"))));
375     }
376 
377     // Look for the WAV identifier
378     //
379     if (hS.compare(8, 4, AUDIO_WAVE_ID) != 0) {
380 #ifdef DEBUG_RIFF
381         RG_WARNING << "Can't find WAV identifier\n";
382 #endif
383 
384         throw(BadSoundFileException(m_fileName, qstrtostr(tr("Can't find WAV identifier"))));
385     }
386 
387     // Look for the FORMAT identifier - note that this doesn't actually
388     // have to be in the first chunk we come across, but for the moment
389     // this is the only place we check for it because I'm lazy.
390     //
391     //
392     if (hS.compare(12, 4, AUDIO_FORMAT_ID) != 0) {
393 #ifdef DEBUG_RIFF
394         RG_WARNING << "Can't find FORMAT identifier\n";
395 #endif
396 
397         throw(BadSoundFileException(m_fileName, qstrtostr(tr("Can't find FORMAT identifier"))));
398     }
399 
400     // Little endian conversion of length bytes into file length
401     // (add on eight for RIFF id and length field and compare to
402     // real file size).
403     //
404     unsigned int length = getIntegerFromLittleEndian(hS.substr(4, 4)) + 8;
405 
406     if (length != m_fileSize) {
407         RG_WARNING << "WARNING: RIFFAudioFile: incorrect length ("
408         << length << ", file size is " << m_fileSize << "), ignoring";
409         length = m_fileSize;
410     }
411 
412     // Check the format length
413     //
414     unsigned int lengthOfFormat = getIntegerFromLittleEndian(hS.substr(16, 4));
415 
416     // Make sure we step to the end of the format chunk ignoring the
417     // tail if it exists
418     //
419     if (lengthOfFormat > 0x10) {
420 #ifdef DEBUG_RIFF
421         RG_WARNING << "RIFFAudioFile::readFormatChunk - "
422         << "extended Format Chunk (" << lengthOfFormat << ")";
423 #endif
424 
425         // ignore any overlapping bytes
426         m_inFile->seekg(lengthOfFormat - 0x10, std::ios::cur);
427     } else if (lengthOfFormat < 0x10) {
428 #ifdef DEBUG_RIFF
429         RG_WARNING << "RIFFAudioFile::readFormatChunk - "
430         << "truncated Format Chunk (" << lengthOfFormat << ")";
431 #endif
432 
433         m_inFile->seekg(lengthOfFormat - 0x10, std::ios::cur);
434         //throw(BadSoundFileException(m_fileName, "Format chunk too short"));
435     }
436 
437 
438     // Check sub format - we support PCM or IEEE floating point.
439     //
440     unsigned int subFormat = getIntegerFromLittleEndian(hS.substr(20, 2));
441 
442     if (subFormat == 0x01) {
443         m_subFormat = PCM;
444     } else if (subFormat == 0x03) {
445         m_subFormat = FLOAT;
446     } else {
447         throw(BadSoundFileException(m_fileName, qstrtostr(tr("Rosegarden currently only supports PCM or IEEE floating-point RIFF files"))));
448     }
449 
450     // We seem to have a good looking .WAV file - extract the
451     // sample information and populate this locally
452     //
453     unsigned int channelNumbers = getIntegerFromLittleEndian(hS.substr(22, 2));
454 
455     switch (channelNumbers) {
456     case 0x01:
457     case 0x02:
458         m_channels = channelNumbers;
459         break;
460 
461     default: {
462             throw(BadSoundFileException(m_fileName, qstrtostr(tr("Unsupported number of channels"))));
463         }
464         break;
465     }
466 
467     // Now the rest of the information
468     //
469     m_sampleRate = getIntegerFromLittleEndian(hS.substr(24, 4));
470     m_bytesPerSecond = getIntegerFromLittleEndian(hS.substr(28, 4));
471     m_bytesPerFrame = getIntegerFromLittleEndian(hS.substr(32, 2));
472     m_bitsPerSample = getIntegerFromLittleEndian(hS.substr(34, 2));
473 
474     if (m_subFormat == PCM) {
475         if (m_bitsPerSample != 8 && m_bitsPerSample != 16 && m_bitsPerSample != 24) {
476             throw BadSoundFileException(tr("Rosegarden currently only supports 8-, 16- or 24-bit PCM in RIFF files"));
477         }
478     } else if (m_subFormat == FLOAT) {
479         if (m_bitsPerSample != 32) {
480             throw BadSoundFileException(tr("Rosegarden currently only supports 32-bit floating-point in RIFF files"));
481         }
482     }
483 
484    // printStats();
485 
486 }
487 
488 // Write out the format chunk from our internal data
489 //
490 void
491 RIFFAudioFile::writeFormatChunk()
492 {
493     if (m_outFile == nullptr || m_type != WAV)
494         return ;
495 
496     std::string outString;
497 
498     // RIFF type is all we support for the moment
499     outString += AUDIO_RIFF_ID;
500 
501     // Now write the total length of the file minus these first 8 bytes.
502     // We won't know this until we've finished recording the file.
503     //
504     outString += "0000";
505 
506     // WAV file is all we support
507     //
508     outString += AUDIO_WAVE_ID;
509 
510     // Begin the format chunk
511     outString += AUDIO_FORMAT_ID;
512 
513     // length
514     //RG_DEBUG << "LENGTH = " << getLittleEndianFromInteger(0x10, 4);
515     outString += getLittleEndianFromInteger(0x10, 4);
516 
517     // 1 for PCM, 3 for float
518     if (m_subFormat == PCM) {
519         outString += getLittleEndianFromInteger(0x01, 2);
520     } else {
521         outString += getLittleEndianFromInteger(0x03, 2);
522     }
523 
524     // channel
525     outString += getLittleEndianFromInteger(m_channels, 2);
526 
527     // sample rate
528     outString += getLittleEndianFromInteger(m_sampleRate, 4);
529 
530     // bytes per second
531     outString += getLittleEndianFromInteger(m_bytesPerSecond, 4);
532 
533     // bytes per sample
534     outString += getLittleEndianFromInteger(m_bytesPerFrame, 2);
535 
536     // bits per sample
537     outString += getLittleEndianFromInteger(m_bitsPerSample, 2);
538 
539     // Now mark the beginning of the "data" chunk and leave the file
540     // open for writing.
541     outString += "data";
542 
543     // length of data to follow - again needs to be written after
544     // we've completed the file.
545     //
546     outString += "0000";
547 
548     // write out
549     //
550     putBytes(m_outFile, outString);
551 }
552 
553 
554 AudioFileType
555 RIFFAudioFile::identifySubType(const QString &filename)
556 {
557     std::ifstream *testFile =
558         new std::ifstream(filename.toLocal8Bit(), std::ios::in | std::ios::binary);
559 
560     if (!(*testFile)) {
561         delete testFile;
562         return UNKNOWN;
563     }
564 
565     std::string hS;
566     unsigned int numberOfBytes = 36;
567     char *bytes = new char[numberOfBytes];
568 
569     testFile->read(bytes, numberOfBytes);
570     for (unsigned int i = 0; i < numberOfBytes; i++)
571         hS += (unsigned char)bytes[i];
572 
573     AudioFileType type = UNKNOWN;
574 
575     // Test for BWF first because it's an extension of a plain WAV
576     //
577     if (hS.compare(0, 4, AUDIO_RIFF_ID) == 0 &&
578             hS.compare(8, 4, AUDIO_WAVE_ID) == 0 &&
579             hS.compare(12, 4, AUDIO_BWF_ID) == 0) {
580         type = BWF;
581     }
582     // Now for a WAV
583     else if (hS.compare(0, 4, AUDIO_RIFF_ID) == 0 &&
584              hS.compare(8, 4, AUDIO_WAVE_ID) == 0) {
585         type = WAV;
586     } else
587         type = UNKNOWN;
588 
589     testFile->close();
590     delete testFile;
591     delete [] bytes;
592 
593     return type;
594 }
595 
596 float
597 RIFFAudioFile::convertBytesToSample(const unsigned char *ubuf)
598 {
599     switch (getBitsPerSample()) {
600 
601     case 8: {
602             // WAV stores 8-bit samples unsigned, other sizes signed.
603             return (float)(ubuf[0] - 128.0) / 128.0;
604         }
605 
606     case 16: {
607             // Two's complement little-endian 16-bit integer.
608             // We convert endianness (if necessary) but assume 16-bit short.
609             unsigned char b2 = ubuf[0];
610             unsigned char b1 = ubuf[1];
611             unsigned int bits = (b1 << 8) + b2;
612             return (float)(short(bits)) / 32768.0;
613         }
614 
615     case 24: {
616             // Two's complement little-endian 24-bit integer.
617             // Again, convert endianness but assume 32-bit int.
618             unsigned char b3 = ubuf[0];
619             unsigned char b2 = ubuf[1];
620             unsigned char b1 = ubuf[2];
621             // Rotate 8 bits too far in order to get the sign bit
622             // in the right place; this gives us a 32-bit value,
623             // hence the larger float divisor
624             unsigned int bits = (b1 << 24) + (b2 << 16) + (b3 << 8);
625             return (float)(int(bits)) / 2147483648.0;
626         }
627 
628     case 32: {
629             // IEEE floating point
630             return *(float *)ubuf;
631         }
632 
633     default:
634         return 0.0f;
635     }
636 }
637 
638 }
639 
640