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