The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

864 lines
31KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../../core/juce_StandardHeader.h"
  19. BEGIN_JUCE_NAMESPACE
  20. #include "juce_WavAudioFormat.h"
  21. #include "../../io/streams/juce_BufferedInputStream.h"
  22. #include "../../text/juce_LocalisedStrings.h"
  23. #include "../../io/files/juce_FileInputStream.h"
  24. #include "../../io/files/juce_TemporaryFile.h"
  25. //==============================================================================
  26. static const char* const wavFormatName = "WAV file";
  27. static const tchar* const wavExtensions[] = { T(".wav"), T(".bwf"), 0 };
  28. //==============================================================================
  29. const tchar* const WavAudioFormat::bwavDescription = T("bwav description");
  30. const tchar* const WavAudioFormat::bwavOriginator = T("bwav originator");
  31. const tchar* const WavAudioFormat::bwavOriginatorRef = T("bwav originator ref");
  32. const tchar* const WavAudioFormat::bwavOriginationDate = T("bwav origination date");
  33. const tchar* const WavAudioFormat::bwavOriginationTime = T("bwav origination time");
  34. const tchar* const WavAudioFormat::bwavTimeReference = T("bwav time reference");
  35. const tchar* const WavAudioFormat::bwavCodingHistory = T("bwav coding history");
  36. const StringPairArray WavAudioFormat::createBWAVMetadata (const String& description,
  37. const String& originator,
  38. const String& originatorRef,
  39. const Time& date,
  40. const int64 timeReferenceSamples,
  41. const String& codingHistory)
  42. {
  43. StringPairArray m;
  44. m.set (bwavDescription, description);
  45. m.set (bwavOriginator, originator);
  46. m.set (bwavOriginatorRef, originatorRef);
  47. m.set (bwavOriginationDate, date.formatted (T("%Y-%m-%d")));
  48. m.set (bwavOriginationTime, date.formatted (T("%H:%M:%S")));
  49. m.set (bwavTimeReference, String (timeReferenceSamples));
  50. m.set (bwavCodingHistory, codingHistory);
  51. return m;
  52. }
  53. //==============================================================================
  54. #if JUCE_MSVC
  55. #pragma pack (push, 1)
  56. #define PACKED
  57. #elif JUCE_GCC
  58. #define PACKED __attribute__((packed))
  59. #else
  60. #define PACKED
  61. #endif
  62. struct BWAVChunk
  63. {
  64. uint8 description [256];
  65. uint8 originator [32];
  66. uint8 originatorRef [32];
  67. uint8 originationDate [10];
  68. uint8 originationTime [8];
  69. uint32 timeRefLow;
  70. uint32 timeRefHigh;
  71. uint16 version;
  72. uint8 umid[64];
  73. uint8 reserved[190];
  74. uint8 codingHistory[1];
  75. void copyTo (StringPairArray& values) const
  76. {
  77. values.set (WavAudioFormat::bwavDescription, String::fromUTF8 (description, 256));
  78. values.set (WavAudioFormat::bwavOriginator, String::fromUTF8 (originator, 32));
  79. values.set (WavAudioFormat::bwavOriginatorRef, String::fromUTF8 (originatorRef, 32));
  80. values.set (WavAudioFormat::bwavOriginationDate, String::fromUTF8 (originationDate, 10));
  81. values.set (WavAudioFormat::bwavOriginationTime, String::fromUTF8 (originationTime, 8));
  82. const uint32 timeLow = ByteOrder::swapIfBigEndian (timeRefLow);
  83. const uint32 timeHigh = ByteOrder::swapIfBigEndian (timeRefHigh);
  84. const int64 time = (((int64)timeHigh) << 32) + timeLow;
  85. values.set (WavAudioFormat::bwavTimeReference, String (time));
  86. values.set (WavAudioFormat::bwavCodingHistory, String::fromUTF8 (codingHistory));
  87. }
  88. static MemoryBlock createFrom (const StringPairArray& values)
  89. {
  90. const size_t sizeNeeded = sizeof (BWAVChunk) + values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (0) - 1;
  91. MemoryBlock data ((sizeNeeded + 3) & ~3);
  92. data.fillWith (0);
  93. BWAVChunk* b = (BWAVChunk*) data.getData();
  94. // Allow these calls to overwrite an extra byte at the end, which is fine as long
  95. // as they get called in the right order..
  96. values [WavAudioFormat::bwavDescription].copyToUTF8 (b->description, 257);
  97. values [WavAudioFormat::bwavOriginator].copyToUTF8 (b->originator, 33);
  98. values [WavAudioFormat::bwavOriginatorRef].copyToUTF8 (b->originatorRef, 33);
  99. values [WavAudioFormat::bwavOriginationDate].copyToUTF8 (b->originationDate, 11);
  100. values [WavAudioFormat::bwavOriginationTime].copyToUTF8 (b->originationTime, 9);
  101. const int64 time = values [WavAudioFormat::bwavTimeReference].getLargeIntValue();
  102. b->timeRefLow = ByteOrder::swapIfBigEndian ((uint32) (time & 0xffffffff));
  103. b->timeRefHigh = ByteOrder::swapIfBigEndian ((uint32) (time >> 32));
  104. values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (b->codingHistory);
  105. if (b->description[0] != 0
  106. || b->originator[0] != 0
  107. || b->originationDate[0] != 0
  108. || b->originationTime[0] != 0
  109. || b->codingHistory[0] != 0
  110. || time != 0)
  111. {
  112. return data;
  113. }
  114. return MemoryBlock();
  115. }
  116. } PACKED;
  117. //==============================================================================
  118. struct SMPLChunk
  119. {
  120. struct SampleLoop
  121. {
  122. uint32 identifier;
  123. uint32 type;
  124. uint32 start;
  125. uint32 end;
  126. uint32 fraction;
  127. uint32 playCount;
  128. } PACKED;
  129. uint32 manufacturer;
  130. uint32 product;
  131. uint32 samplePeriod;
  132. uint32 midiUnityNote;
  133. uint32 midiPitchFraction;
  134. uint32 smpteFormat;
  135. uint32 smpteOffset;
  136. uint32 numSampleLoops;
  137. uint32 samplerData;
  138. SampleLoop loops[1];
  139. void copyTo (StringPairArray& values, const int totalSize) const
  140. {
  141. values.set (T("Manufacturer"), String (ByteOrder::swapIfBigEndian (manufacturer)));
  142. values.set (T("Product"), String (ByteOrder::swapIfBigEndian (product)));
  143. values.set (T("SamplePeriod"), String (ByteOrder::swapIfBigEndian (samplePeriod)));
  144. values.set (T("MidiUnityNote"), String (ByteOrder::swapIfBigEndian (midiUnityNote)));
  145. values.set (T("MidiPitchFraction"), String (ByteOrder::swapIfBigEndian (midiPitchFraction)));
  146. values.set (T("SmpteFormat"), String (ByteOrder::swapIfBigEndian (smpteFormat)));
  147. values.set (T("SmpteOffset"), String (ByteOrder::swapIfBigEndian (smpteOffset)));
  148. values.set (T("NumSampleLoops"), String (ByteOrder::swapIfBigEndian (numSampleLoops)));
  149. values.set (T("SamplerData"), String (ByteOrder::swapIfBigEndian (samplerData)));
  150. for (uint32 i = 0; i < numSampleLoops; ++i)
  151. {
  152. if ((uint8*) (loops + (i + 1)) > ((uint8*) this) + totalSize)
  153. break;
  154. values.set (String::formatted (T("Loop%dIdentifier"), i), String (ByteOrder::swapIfBigEndian (loops[i].identifier)));
  155. values.set (String::formatted (T("Loop%dType"), i), String (ByteOrder::swapIfBigEndian (loops[i].type)));
  156. values.set (String::formatted (T("Loop%dStart"), i), String (ByteOrder::swapIfBigEndian (loops[i].start)));
  157. values.set (String::formatted (T("Loop%dEnd"), i), String (ByteOrder::swapIfBigEndian (loops[i].end)));
  158. values.set (String::formatted (T("Loop%dFraction"), i), String (ByteOrder::swapIfBigEndian (loops[i].fraction)));
  159. values.set (String::formatted (T("Loop%dPlayCount"), i), String (ByteOrder::swapIfBigEndian (loops[i].playCount)));
  160. }
  161. }
  162. } PACKED;
  163. #if JUCE_MSVC
  164. #pragma pack (pop)
  165. #endif
  166. #undef PACKED
  167. //==============================================================================
  168. class WavAudioFormatReader : public AudioFormatReader
  169. {
  170. int bytesPerFrame;
  171. int64 dataChunkStart, dataLength;
  172. static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); }
  173. WavAudioFormatReader (const WavAudioFormatReader&);
  174. const WavAudioFormatReader& operator= (const WavAudioFormatReader&);
  175. public:
  176. int64 bwavChunkStart, bwavSize;
  177. //==============================================================================
  178. WavAudioFormatReader (InputStream* const in)
  179. : AudioFormatReader (in, TRANS (wavFormatName)),
  180. dataLength (0),
  181. bwavChunkStart (0),
  182. bwavSize (0)
  183. {
  184. if (input->readInt() == chunkName ("RIFF"))
  185. {
  186. const uint32 len = (uint32) input->readInt();
  187. const int64 end = input->getPosition() + len;
  188. bool hasGotType = false;
  189. bool hasGotData = false;
  190. if (input->readInt() == chunkName ("WAVE"))
  191. {
  192. while (input->getPosition() < end
  193. && ! input->isExhausted())
  194. {
  195. const int chunkType = input->readInt();
  196. uint32 length = (uint32) input->readInt();
  197. const int64 chunkEnd = input->getPosition() + length + (length & 1);
  198. if (chunkType == chunkName ("fmt "))
  199. {
  200. // read the format chunk
  201. const short format = input->readShort();
  202. const short numChans = input->readShort();
  203. sampleRate = input->readInt();
  204. const int bytesPerSec = input->readInt();
  205. numChannels = numChans;
  206. bytesPerFrame = bytesPerSec / (int)sampleRate;
  207. bitsPerSample = 8 * bytesPerFrame / numChans;
  208. if (format == 3)
  209. usesFloatingPointData = true;
  210. else if (format != 1)
  211. bytesPerFrame = 0;
  212. hasGotType = true;
  213. }
  214. else if (chunkType == chunkName ("data"))
  215. {
  216. // get the data chunk's position
  217. dataLength = length;
  218. dataChunkStart = input->getPosition();
  219. lengthInSamples = (bytesPerFrame > 0) ? (dataLength / bytesPerFrame) : 0;
  220. hasGotData = true;
  221. }
  222. else if (chunkType == chunkName ("bext"))
  223. {
  224. bwavChunkStart = input->getPosition();
  225. bwavSize = length;
  226. // Broadcast-wav extension chunk..
  227. HeapBlock <BWAVChunk> bwav;
  228. bwav.calloc (jmax ((size_t) length + 1, sizeof (BWAVChunk)), 1);
  229. input->read (bwav, length);
  230. bwav->copyTo (metadataValues);
  231. }
  232. else if (chunkType == chunkName ("smpl"))
  233. {
  234. HeapBlock <SMPLChunk> smpl;
  235. smpl.calloc (jmax ((size_t) length + 1, sizeof (SMPLChunk)), 1);
  236. input->read (smpl, length);
  237. smpl->copyTo (metadataValues, length);
  238. }
  239. else if (chunkEnd <= input->getPosition())
  240. {
  241. break;
  242. }
  243. input->setPosition (chunkEnd);
  244. }
  245. }
  246. }
  247. }
  248. ~WavAudioFormatReader()
  249. {
  250. }
  251. //==============================================================================
  252. bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
  253. int64 startSampleInFile, int numSamples)
  254. {
  255. const int64 samplesAvailable = lengthInSamples - startSampleInFile;
  256. if (samplesAvailable < numSamples)
  257. {
  258. for (int i = numDestChannels; --i >= 0;)
  259. if (destSamples[i] != 0)
  260. zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * numSamples);
  261. numSamples = (int) samplesAvailable;
  262. }
  263. if (numSamples <= 0)
  264. return true;
  265. input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame);
  266. const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3)
  267. char tempBuffer [tempBufSize];
  268. while (numSamples > 0)
  269. {
  270. int* left = destSamples[0];
  271. if (left != 0)
  272. left += startOffsetInDestBuffer;
  273. int* right = numDestChannels > 1 ? destSamples[1] : 0;
  274. if (right != 0)
  275. right += startOffsetInDestBuffer;
  276. const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples);
  277. const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame);
  278. if (bytesRead < numThisTime * bytesPerFrame)
  279. zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead);
  280. if (bitsPerSample == 16)
  281. {
  282. const short* src = (const short*) tempBuffer;
  283. if (numChannels > 1)
  284. {
  285. if (left == 0)
  286. {
  287. for (int i = numThisTime; --i >= 0;)
  288. {
  289. ++src;
  290. *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16;
  291. }
  292. }
  293. else if (right == 0)
  294. {
  295. for (int i = numThisTime; --i >= 0;)
  296. {
  297. *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16;
  298. ++src;
  299. }
  300. }
  301. else
  302. {
  303. for (int i = numThisTime; --i >= 0;)
  304. {
  305. *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16;
  306. *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16;
  307. }
  308. }
  309. }
  310. else
  311. {
  312. for (int i = numThisTime; --i >= 0;)
  313. {
  314. *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16;
  315. }
  316. }
  317. }
  318. else if (bitsPerSample == 24)
  319. {
  320. const char* src = (const char*) tempBuffer;
  321. if (numChannels > 1)
  322. {
  323. if (left == 0)
  324. {
  325. for (int i = numThisTime; --i >= 0;)
  326. {
  327. src += 3;
  328. *right++ = ByteOrder::littleEndian24Bit (src) << 8;
  329. src += 3;
  330. }
  331. }
  332. else if (right == 0)
  333. {
  334. for (int i = numThisTime; --i >= 0;)
  335. {
  336. *left++ = ByteOrder::littleEndian24Bit (src) << 8;
  337. src += 6;
  338. }
  339. }
  340. else
  341. {
  342. for (int i = 0; i < numThisTime; ++i)
  343. {
  344. *left++ = ByteOrder::littleEndian24Bit (src) << 8;
  345. src += 3;
  346. *right++ = ByteOrder::littleEndian24Bit (src) << 8;
  347. src += 3;
  348. }
  349. }
  350. }
  351. else
  352. {
  353. for (int i = 0; i < numThisTime; ++i)
  354. {
  355. *left++ = ByteOrder::littleEndian24Bit (src) << 8;
  356. src += 3;
  357. }
  358. }
  359. }
  360. else if (bitsPerSample == 32)
  361. {
  362. const unsigned int* src = (const unsigned int*) tempBuffer;
  363. unsigned int* l = (unsigned int*) left;
  364. unsigned int* r = (unsigned int*) right;
  365. if (numChannels > 1)
  366. {
  367. if (l == 0)
  368. {
  369. for (int i = numThisTime; --i >= 0;)
  370. {
  371. ++src;
  372. *r++ = ByteOrder::swapIfBigEndian (*src++);
  373. }
  374. }
  375. else if (r == 0)
  376. {
  377. for (int i = numThisTime; --i >= 0;)
  378. {
  379. *l++ = ByteOrder::swapIfBigEndian (*src++);
  380. ++src;
  381. }
  382. }
  383. else
  384. {
  385. for (int i = numThisTime; --i >= 0;)
  386. {
  387. *l++ = ByteOrder::swapIfBigEndian (*src++);
  388. *r++ = ByteOrder::swapIfBigEndian (*src++);
  389. }
  390. }
  391. }
  392. else
  393. {
  394. for (int i = numThisTime; --i >= 0;)
  395. {
  396. *l++ = ByteOrder::swapIfBigEndian (*src++);
  397. }
  398. }
  399. left = (int*)l;
  400. right = (int*)r;
  401. }
  402. else if (bitsPerSample == 8)
  403. {
  404. const unsigned char* src = (const unsigned char*) tempBuffer;
  405. if (numChannels > 1)
  406. {
  407. if (left == 0)
  408. {
  409. for (int i = numThisTime; --i >= 0;)
  410. {
  411. ++src;
  412. *right++ = ((int) *src++ - 128) << 24;
  413. }
  414. }
  415. else if (right == 0)
  416. {
  417. for (int i = numThisTime; --i >= 0;)
  418. {
  419. *left++ = ((int) *src++ - 128) << 24;
  420. ++src;
  421. }
  422. }
  423. else
  424. {
  425. for (int i = numThisTime; --i >= 0;)
  426. {
  427. *left++ = ((int) *src++ - 128) << 24;
  428. *right++ = ((int) *src++ - 128) << 24;
  429. }
  430. }
  431. }
  432. else
  433. {
  434. for (int i = numThisTime; --i >= 0;)
  435. {
  436. *left++ = ((int)*src++ - 128) << 24;
  437. }
  438. }
  439. }
  440. startOffsetInDestBuffer += numThisTime;
  441. numSamples -= numThisTime;
  442. }
  443. if (numSamples > 0)
  444. {
  445. for (int i = numDestChannels; --i >= 0;)
  446. if (destSamples[i] != 0)
  447. zeromem (destSamples[i] + startOffsetInDestBuffer,
  448. sizeof (int) * numSamples);
  449. }
  450. return true;
  451. }
  452. juce_UseDebuggingNewOperator
  453. };
  454. //==============================================================================
  455. class WavAudioFormatWriter : public AudioFormatWriter
  456. {
  457. MemoryBlock tempBlock, bwavChunk;
  458. uint32 lengthInSamples, bytesWritten;
  459. int64 headerPosition;
  460. bool writeFailed;
  461. static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); }
  462. WavAudioFormatWriter (const WavAudioFormatWriter&);
  463. const WavAudioFormatWriter& operator= (const WavAudioFormatWriter&);
  464. void writeHeader()
  465. {
  466. const bool seekedOk = output->setPosition (headerPosition);
  467. (void) seekedOk;
  468. // if this fails, you've given it an output stream that can't seek! It needs
  469. // to be able to seek back to write the header
  470. jassert (seekedOk);
  471. const int bytesPerFrame = numChannels * bitsPerSample / 8;
  472. output->writeInt (chunkName ("RIFF"));
  473. output->writeInt ((int) (lengthInSamples * bytesPerFrame
  474. + ((bwavChunk.getSize() > 0) ? (44 + bwavChunk.getSize()) : 36)));
  475. output->writeInt (chunkName ("WAVE"));
  476. output->writeInt (chunkName ("fmt "));
  477. output->writeInt (16);
  478. output->writeShort ((bitsPerSample < 32) ? (short) 1 /*WAVE_FORMAT_PCM*/
  479. : (short) 3 /*WAVE_FORMAT_IEEE_FLOAT*/);
  480. output->writeShort ((short) numChannels);
  481. output->writeInt ((int) sampleRate);
  482. output->writeInt (bytesPerFrame * (int) sampleRate);
  483. output->writeShort ((short) bytesPerFrame);
  484. output->writeShort ((short) bitsPerSample);
  485. if (bwavChunk.getSize() > 0)
  486. {
  487. output->writeInt (chunkName ("bext"));
  488. output->writeInt ((int) bwavChunk.getSize());
  489. output->write (bwavChunk.getData(), (int) bwavChunk.getSize());
  490. }
  491. output->writeInt (chunkName ("data"));
  492. output->writeInt (lengthInSamples * bytesPerFrame);
  493. usesFloatingPointData = (bitsPerSample == 32);
  494. }
  495. public:
  496. //==============================================================================
  497. WavAudioFormatWriter (OutputStream* const out,
  498. const double sampleRate_,
  499. const unsigned int numChannels_,
  500. const int bits,
  501. const StringPairArray& metadataValues)
  502. : AudioFormatWriter (out,
  503. TRANS (wavFormatName),
  504. sampleRate_,
  505. numChannels_,
  506. bits),
  507. lengthInSamples (0),
  508. bytesWritten (0),
  509. writeFailed (false)
  510. {
  511. if (metadataValues.size() > 0)
  512. bwavChunk = BWAVChunk::createFrom (metadataValues);
  513. headerPosition = out->getPosition();
  514. writeHeader();
  515. }
  516. ~WavAudioFormatWriter()
  517. {
  518. writeHeader();
  519. }
  520. //==============================================================================
  521. bool write (const int** data, int numSamples)
  522. {
  523. if (writeFailed)
  524. return false;
  525. const int bytes = numChannels * numSamples * bitsPerSample / 8;
  526. tempBlock.ensureSize (bytes, false);
  527. char* buffer = (char*) tempBlock.getData();
  528. const int* left = data[0];
  529. const int* right = data[1];
  530. if (right == 0)
  531. right = left;
  532. if (bitsPerSample == 16)
  533. {
  534. short* b = (short*) buffer;
  535. if (numChannels > 1)
  536. {
  537. for (int i = numSamples; --i >= 0;)
  538. {
  539. *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16));
  540. *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*right++ >> 16));
  541. }
  542. }
  543. else
  544. {
  545. for (int i = numSamples; --i >= 0;)
  546. {
  547. *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16));
  548. }
  549. }
  550. }
  551. else if (bitsPerSample == 24)
  552. {
  553. char* b = (char*) buffer;
  554. if (numChannels > 1)
  555. {
  556. for (int i = numSamples; --i >= 0;)
  557. {
  558. ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b);
  559. b += 3;
  560. ByteOrder::littleEndian24BitToChars ((*right++) >> 8, b);
  561. b += 3;
  562. }
  563. }
  564. else
  565. {
  566. for (int i = numSamples; --i >= 0;)
  567. {
  568. ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b);
  569. b += 3;
  570. }
  571. }
  572. }
  573. else if (bitsPerSample == 32)
  574. {
  575. unsigned int* b = (unsigned int*) buffer;
  576. if (numChannels > 1)
  577. {
  578. for (int i = numSamples; --i >= 0;)
  579. {
  580. *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++);
  581. *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *right++);
  582. }
  583. }
  584. else
  585. {
  586. for (int i = numSamples; --i >= 0;)
  587. {
  588. *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++);
  589. }
  590. }
  591. }
  592. else if (bitsPerSample == 8)
  593. {
  594. unsigned char* b = (unsigned char*) buffer;
  595. if (numChannels > 1)
  596. {
  597. for (int i = numSamples; --i >= 0;)
  598. {
  599. *b++ = (unsigned char) (128 + (*left++ >> 24));
  600. *b++ = (unsigned char) (128 + (*right++ >> 24));
  601. }
  602. }
  603. else
  604. {
  605. for (int i = numSamples; --i >= 0;)
  606. {
  607. *b++ = (unsigned char) (128 + (*left++ >> 24));
  608. }
  609. }
  610. }
  611. if (bytesWritten + bytes >= (uint32) 0xfff00000
  612. || ! output->write (buffer, bytes))
  613. {
  614. // failed to write to disk, so let's try writing the header.
  615. // If it's just run out of disk space, then if it does manage
  616. // to write the header, we'll still have a useable file..
  617. writeHeader();
  618. writeFailed = true;
  619. return false;
  620. }
  621. else
  622. {
  623. bytesWritten += bytes;
  624. lengthInSamples += numSamples;
  625. return true;
  626. }
  627. }
  628. juce_UseDebuggingNewOperator
  629. };
  630. //==============================================================================
  631. WavAudioFormat::WavAudioFormat()
  632. : AudioFormat (TRANS (wavFormatName), (const tchar**) wavExtensions)
  633. {
  634. }
  635. WavAudioFormat::~WavAudioFormat()
  636. {
  637. }
  638. const Array <int> WavAudioFormat::getPossibleSampleRates()
  639. {
  640. const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 };
  641. return Array <int> (rates);
  642. }
  643. const Array <int> WavAudioFormat::getPossibleBitDepths()
  644. {
  645. const int depths[] = { 8, 16, 24, 32, 0 };
  646. return Array <int> (depths);
  647. }
  648. bool WavAudioFormat::canDoStereo()
  649. {
  650. return true;
  651. }
  652. bool WavAudioFormat::canDoMono()
  653. {
  654. return true;
  655. }
  656. AudioFormatReader* WavAudioFormat::createReaderFor (InputStream* sourceStream,
  657. const bool deleteStreamIfOpeningFails)
  658. {
  659. ScopedPointer <WavAudioFormatReader> r (new WavAudioFormatReader (sourceStream));
  660. if (r->sampleRate != 0)
  661. return r.release();
  662. if (! deleteStreamIfOpeningFails)
  663. r->input = 0;
  664. return 0;
  665. }
  666. AudioFormatWriter* WavAudioFormat::createWriterFor (OutputStream* out,
  667. double sampleRate,
  668. unsigned int numChannels,
  669. int bitsPerSample,
  670. const StringPairArray& metadataValues,
  671. int /*qualityOptionIndex*/)
  672. {
  673. if (getPossibleBitDepths().contains (bitsPerSample))
  674. {
  675. return new WavAudioFormatWriter (out,
  676. sampleRate,
  677. numChannels,
  678. bitsPerSample,
  679. metadataValues);
  680. }
  681. return 0;
  682. }
  683. static bool juce_slowCopyOfWavFileWithNewMetadata (const File& file, const StringPairArray& metadata)
  684. {
  685. TemporaryFile tempFile (file);
  686. WavAudioFormat wav;
  687. ScopedPointer <AudioFormatReader> reader (wav.createReaderFor (file.createInputStream(), true));
  688. if (reader != 0)
  689. {
  690. ScopedPointer <OutputStream> outStream (tempFile.getFile().createOutputStream());
  691. if (outStream != 0)
  692. {
  693. ScopedPointer <AudioFormatWriter> writer (wav.createWriterFor (outStream, reader->sampleRate,
  694. reader->numChannels, reader->bitsPerSample,
  695. metadata, 0));
  696. if (writer != 0)
  697. {
  698. outStream.release();
  699. bool ok = writer->writeFromAudioReader (*reader, 0, -1);
  700. writer = 0;
  701. return ok && tempFile.overwriteTargetFileWithTemporary();
  702. }
  703. }
  704. }
  705. return false;
  706. }
  707. bool WavAudioFormat::replaceMetadataInFile (const File& wavFile, const StringPairArray& newMetadata)
  708. {
  709. ScopedPointer <WavAudioFormatReader> reader ((WavAudioFormatReader*) createReaderFor (wavFile.createInputStream(), true));
  710. if (reader != 0)
  711. {
  712. const int64 bwavPos = reader->bwavChunkStart;
  713. const int64 bwavSize = reader->bwavSize;
  714. reader = 0;
  715. if (bwavSize > 0)
  716. {
  717. MemoryBlock chunk = BWAVChunk::createFrom (newMetadata);
  718. if (chunk.getSize() <= (size_t) bwavSize)
  719. {
  720. // the new one will fit in the space available, so write it directly..
  721. const int64 oldSize = wavFile.getSize();
  722. {
  723. ScopedPointer <FileOutputStream> out (wavFile.createOutputStream());
  724. out->setPosition (bwavPos);
  725. out->write (chunk.getData(), (int) chunk.getSize());
  726. out->setPosition (oldSize);
  727. }
  728. jassert (wavFile.getSize() == oldSize);
  729. return true;
  730. }
  731. }
  732. }
  733. return juce_slowCopyOfWavFileWithNewMetadata (wavFile, newMetadata);
  734. }
  735. END_JUCE_NAMESPACE