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.

694 lines
22KB

  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_AudioSampleBuffer.h"
  21. #include "../audio_file_formats/juce_AudioFormatReader.h"
  22. #include "../audio_file_formats/juce_AudioFormatWriter.h"
  23. //==============================================================================
  24. AudioSampleBuffer::AudioSampleBuffer (const int numChannels_,
  25. const int numSamples) throw()
  26. : numChannels (numChannels_),
  27. size (numSamples)
  28. {
  29. jassert (numSamples >= 0);
  30. jassert (numChannels_ > 0);
  31. allocateData();
  32. }
  33. AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer& other) throw()
  34. : numChannels (other.numChannels),
  35. size (other.size)
  36. {
  37. allocateData();
  38. const size_t numBytes = size * sizeof (float);
  39. for (int i = 0; i < numChannels; ++i)
  40. memcpy (channels[i], other.channels[i], numBytes);
  41. }
  42. void AudioSampleBuffer::allocateData()
  43. {
  44. const size_t channelListSize = (numChannels + 1) * sizeof (float*);
  45. allocatedBytes = (int) (numChannels * size * sizeof (float) + channelListSize + 32);
  46. allocatedData.malloc (allocatedBytes);
  47. channels = (float**) allocatedData;
  48. float* chan = (float*) (allocatedData + channelListSize);
  49. for (int i = 0; i < numChannels; ++i)
  50. {
  51. channels[i] = chan;
  52. chan += size;
  53. }
  54. channels [numChannels] = 0;
  55. }
  56. AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo,
  57. const int numChannels_,
  58. const int numSamples) throw()
  59. : numChannels (numChannels_),
  60. size (numSamples),
  61. allocatedBytes (0)
  62. {
  63. jassert (numChannels_ > 0);
  64. allocateChannels (dataToReferTo);
  65. }
  66. void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
  67. const int newNumChannels,
  68. const int newNumSamples) throw()
  69. {
  70. jassert (newNumChannels > 0);
  71. allocatedBytes = 0;
  72. allocatedData.free();
  73. numChannels = newNumChannels;
  74. size = newNumSamples;
  75. allocateChannels (dataToReferTo);
  76. }
  77. void AudioSampleBuffer::allocateChannels (float** const dataToReferTo)
  78. {
  79. // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
  80. if (numChannels < numElementsInArray (preallocatedChannelSpace))
  81. {
  82. channels = (float**) preallocatedChannelSpace;
  83. }
  84. else
  85. {
  86. allocatedData.malloc (numChannels + 1, sizeof (float*));
  87. channels = (float**) allocatedData;
  88. }
  89. for (int i = 0; i < numChannels; ++i)
  90. {
  91. // you have to pass in the same number of valid pointers as numChannels
  92. jassert (dataToReferTo[i] != 0);
  93. channels[i] = dataToReferTo[i];
  94. }
  95. channels [numChannels] = 0;
  96. }
  97. AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) throw()
  98. {
  99. if (this != &other)
  100. {
  101. setSize (other.getNumChannels(), other.getNumSamples(), false, false, false);
  102. const size_t numBytes = size * sizeof (float);
  103. for (int i = 0; i < numChannels; ++i)
  104. memcpy (channels[i], other.channels[i], numBytes);
  105. }
  106. return *this;
  107. }
  108. AudioSampleBuffer::~AudioSampleBuffer() throw()
  109. {
  110. }
  111. void AudioSampleBuffer::setSize (const int newNumChannels,
  112. const int newNumSamples,
  113. const bool keepExistingContent,
  114. const bool clearExtraSpace,
  115. const bool avoidReallocating) throw()
  116. {
  117. jassert (newNumChannels > 0);
  118. if (newNumSamples != size || newNumChannels != numChannels)
  119. {
  120. const size_t channelListSize = (newNumChannels + 1) * sizeof (float*);
  121. const size_t newTotalBytes = (newNumChannels * newNumSamples * sizeof (float)) + channelListSize + 32;
  122. if (keepExistingContent)
  123. {
  124. HeapBlock <char> newData;
  125. newData.allocate (newTotalBytes, clearExtraSpace);
  126. const int numChansToCopy = jmin (numChannels, newNumChannels);
  127. const size_t numBytesToCopy = sizeof (float) * jmin (newNumSamples, size);
  128. float** const newChannels = (float**) newData;
  129. float* newChan = (float*) (newData + channelListSize);
  130. for (int i = 0; i < numChansToCopy; ++i)
  131. {
  132. memcpy (newChan, channels[i], numBytesToCopy);
  133. newChannels[i] = newChan;
  134. newChan += newNumSamples;
  135. }
  136. allocatedData.swapWith (newData);
  137. allocatedBytes = (int) newTotalBytes;
  138. channels = (float**) allocatedData;
  139. }
  140. else
  141. {
  142. if (avoidReallocating && allocatedBytes >= newTotalBytes)
  143. {
  144. if (clearExtraSpace)
  145. zeromem (allocatedData, newTotalBytes);
  146. }
  147. else
  148. {
  149. allocatedBytes = newTotalBytes;
  150. allocatedData.allocate (newTotalBytes, clearExtraSpace);
  151. channels = (float**) allocatedData;
  152. }
  153. float* chan = (float*) (allocatedData + channelListSize);
  154. for (int i = 0; i < newNumChannels; ++i)
  155. {
  156. channels[i] = chan;
  157. chan += newNumSamples;
  158. }
  159. }
  160. channels [newNumChannels] = 0;
  161. size = newNumSamples;
  162. numChannels = newNumChannels;
  163. }
  164. }
  165. void AudioSampleBuffer::clear() throw()
  166. {
  167. for (int i = 0; i < numChannels; ++i)
  168. zeromem (channels[i], size * sizeof (float));
  169. }
  170. void AudioSampleBuffer::clear (const int startSample,
  171. const int numSamples) throw()
  172. {
  173. jassert (startSample >= 0 && startSample + numSamples <= size);
  174. for (int i = 0; i < numChannels; ++i)
  175. zeromem (channels [i] + startSample, numSamples * sizeof (float));
  176. }
  177. void AudioSampleBuffer::clear (const int channel,
  178. const int startSample,
  179. const int numSamples) throw()
  180. {
  181. jassert (((unsigned int) channel) < (unsigned int) numChannels);
  182. jassert (startSample >= 0 && startSample + numSamples <= size);
  183. zeromem (channels [channel] + startSample, numSamples * sizeof (float));
  184. }
  185. void AudioSampleBuffer::applyGain (const int channel,
  186. const int startSample,
  187. int numSamples,
  188. const float gain) throw()
  189. {
  190. jassert (((unsigned int) channel) < (unsigned int) numChannels);
  191. jassert (startSample >= 0 && startSample + numSamples <= size);
  192. if (gain != 1.0f)
  193. {
  194. float* d = channels [channel] + startSample;
  195. if (gain == 0.0f)
  196. {
  197. zeromem (d, sizeof (float) * numSamples);
  198. }
  199. else
  200. {
  201. while (--numSamples >= 0)
  202. *d++ *= gain;
  203. }
  204. }
  205. }
  206. void AudioSampleBuffer::applyGainRamp (const int channel,
  207. const int startSample,
  208. int numSamples,
  209. float startGain,
  210. float endGain) throw()
  211. {
  212. if (startGain == endGain)
  213. {
  214. applyGain (channel, startSample, numSamples, startGain);
  215. }
  216. else
  217. {
  218. jassert (((unsigned int) channel) < (unsigned int) numChannels);
  219. jassert (startSample >= 0 && startSample + numSamples <= size);
  220. const float increment = (endGain - startGain) / numSamples;
  221. float* d = channels [channel] + startSample;
  222. while (--numSamples >= 0)
  223. {
  224. *d++ *= startGain;
  225. startGain += increment;
  226. }
  227. }
  228. }
  229. void AudioSampleBuffer::applyGain (const int startSample,
  230. const int numSamples,
  231. const float gain) throw()
  232. {
  233. for (int i = 0; i < numChannels; ++i)
  234. applyGain (i, startSample, numSamples, gain);
  235. }
  236. void AudioSampleBuffer::addFrom (const int destChannel,
  237. const int destStartSample,
  238. const AudioSampleBuffer& source,
  239. const int sourceChannel,
  240. const int sourceStartSample,
  241. int numSamples,
  242. const float gain) throw()
  243. {
  244. jassert (&source != this || sourceChannel != destChannel);
  245. jassert (((unsigned int) destChannel) < (unsigned int) numChannels);
  246. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  247. jassert (((unsigned int) sourceChannel) < (unsigned int) source.numChannels);
  248. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  249. if (gain != 0.0f && numSamples > 0)
  250. {
  251. float* d = channels [destChannel] + destStartSample;
  252. const float* s = source.channels [sourceChannel] + sourceStartSample;
  253. if (gain != 1.0f)
  254. {
  255. while (--numSamples >= 0)
  256. *d++ += gain * *s++;
  257. }
  258. else
  259. {
  260. while (--numSamples >= 0)
  261. *d++ += *s++;
  262. }
  263. }
  264. }
  265. void AudioSampleBuffer::addFrom (const int destChannel,
  266. const int destStartSample,
  267. const float* source,
  268. int numSamples,
  269. const float gain) throw()
  270. {
  271. jassert (((unsigned int) destChannel) < (unsigned int) numChannels);
  272. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  273. jassert (source != 0);
  274. if (gain != 0.0f && numSamples > 0)
  275. {
  276. float* d = channels [destChannel] + destStartSample;
  277. if (gain != 1.0f)
  278. {
  279. while (--numSamples >= 0)
  280. *d++ += gain * *source++;
  281. }
  282. else
  283. {
  284. while (--numSamples >= 0)
  285. *d++ += *source++;
  286. }
  287. }
  288. }
  289. void AudioSampleBuffer::addFromWithRamp (const int destChannel,
  290. const int destStartSample,
  291. const float* source,
  292. int numSamples,
  293. float startGain,
  294. const float endGain) throw()
  295. {
  296. jassert (((unsigned int) destChannel) < (unsigned int) numChannels);
  297. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  298. jassert (source != 0);
  299. if (startGain == endGain)
  300. {
  301. addFrom (destChannel,
  302. destStartSample,
  303. source,
  304. numSamples,
  305. startGain);
  306. }
  307. else
  308. {
  309. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  310. {
  311. const float increment = (endGain - startGain) / numSamples;
  312. float* d = channels [destChannel] + destStartSample;
  313. while (--numSamples >= 0)
  314. {
  315. *d++ += startGain * *source++;
  316. startGain += increment;
  317. }
  318. }
  319. }
  320. }
  321. void AudioSampleBuffer::copyFrom (const int destChannel,
  322. const int destStartSample,
  323. const AudioSampleBuffer& source,
  324. const int sourceChannel,
  325. const int sourceStartSample,
  326. int numSamples) throw()
  327. {
  328. jassert (&source != this || sourceChannel != destChannel);
  329. jassert (((unsigned int) destChannel) < (unsigned int) numChannels);
  330. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  331. jassert (((unsigned int) sourceChannel) < (unsigned int) source.numChannels);
  332. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  333. if (numSamples > 0)
  334. {
  335. memcpy (channels [destChannel] + destStartSample,
  336. source.channels [sourceChannel] + sourceStartSample,
  337. sizeof (float) * numSamples);
  338. }
  339. }
  340. void AudioSampleBuffer::copyFrom (const int destChannel,
  341. const int destStartSample,
  342. const float* source,
  343. int numSamples) throw()
  344. {
  345. jassert (((unsigned int) destChannel) < (unsigned int) numChannels);
  346. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  347. jassert (source != 0);
  348. if (numSamples > 0)
  349. {
  350. memcpy (channels [destChannel] + destStartSample,
  351. source,
  352. sizeof (float) * numSamples);
  353. }
  354. }
  355. void AudioSampleBuffer::copyFrom (const int destChannel,
  356. const int destStartSample,
  357. const float* source,
  358. int numSamples,
  359. const float gain) throw()
  360. {
  361. jassert (((unsigned int) destChannel) < (unsigned int) numChannels);
  362. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  363. jassert (source != 0);
  364. if (numSamples > 0)
  365. {
  366. float* d = channels [destChannel] + destStartSample;
  367. if (gain != 1.0f)
  368. {
  369. if (gain == 0)
  370. {
  371. zeromem (d, sizeof (float) * numSamples);
  372. }
  373. else
  374. {
  375. while (--numSamples >= 0)
  376. *d++ = gain * *source++;
  377. }
  378. }
  379. else
  380. {
  381. memcpy (d, source, sizeof (float) * numSamples);
  382. }
  383. }
  384. }
  385. void AudioSampleBuffer::copyFromWithRamp (const int destChannel,
  386. const int destStartSample,
  387. const float* source,
  388. int numSamples,
  389. float startGain,
  390. float endGain) throw()
  391. {
  392. jassert (((unsigned int) destChannel) < (unsigned int) numChannels);
  393. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  394. jassert (source != 0);
  395. if (startGain == endGain)
  396. {
  397. copyFrom (destChannel,
  398. destStartSample,
  399. source,
  400. numSamples,
  401. startGain);
  402. }
  403. else
  404. {
  405. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  406. {
  407. const float increment = (endGain - startGain) / numSamples;
  408. float* d = channels [destChannel] + destStartSample;
  409. while (--numSamples >= 0)
  410. {
  411. *d++ = startGain * *source++;
  412. startGain += increment;
  413. }
  414. }
  415. }
  416. }
  417. void AudioSampleBuffer::findMinMax (const int channel,
  418. const int startSample,
  419. int numSamples,
  420. float& minVal,
  421. float& maxVal) const throw()
  422. {
  423. jassert (((unsigned int) channel) < (unsigned int) numChannels);
  424. jassert (startSample >= 0 && startSample + numSamples <= size);
  425. if (numSamples <= 0)
  426. {
  427. minVal = 0.0f;
  428. maxVal = 0.0f;
  429. }
  430. else
  431. {
  432. const float* d = channels [channel] + startSample;
  433. float mn = *d++;
  434. float mx = mn;
  435. while (--numSamples > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
  436. {
  437. const float samp = *d++;
  438. if (samp > mx)
  439. mx = samp;
  440. if (samp < mn)
  441. mn = samp;
  442. }
  443. maxVal = mx;
  444. minVal = mn;
  445. }
  446. }
  447. float AudioSampleBuffer::getMagnitude (const int channel,
  448. const int startSample,
  449. const int numSamples) const throw()
  450. {
  451. jassert (((unsigned int) channel) < (unsigned int) numChannels);
  452. jassert (startSample >= 0 && startSample + numSamples <= size);
  453. float mn, mx;
  454. findMinMax (channel, startSample, numSamples, mn, mx);
  455. return jmax (mn, -mn, mx, -mx);
  456. }
  457. float AudioSampleBuffer::getMagnitude (const int startSample,
  458. const int numSamples) const throw()
  459. {
  460. float mag = 0.0f;
  461. for (int i = 0; i < numChannels; ++i)
  462. mag = jmax (mag, getMagnitude (i, startSample, numSamples));
  463. return mag;
  464. }
  465. float AudioSampleBuffer::getRMSLevel (const int channel,
  466. const int startSample,
  467. const int numSamples) const throw()
  468. {
  469. jassert (((unsigned int) channel) < (unsigned int) numChannels);
  470. jassert (startSample >= 0 && startSample + numSamples <= size);
  471. if (numSamples <= 0 || channel < 0 || channel >= numChannels)
  472. return 0.0f;
  473. const float* const data = channels [channel] + startSample;
  474. double sum = 0.0;
  475. for (int i = 0; i < numSamples; ++i)
  476. {
  477. const float sample = data [i];
  478. sum += sample * sample;
  479. }
  480. return (float) sqrt (sum / numSamples);
  481. }
  482. void AudioSampleBuffer::readFromAudioReader (AudioFormatReader* reader,
  483. const int startSample,
  484. const int numSamples,
  485. const int readerStartSample,
  486. const bool useLeftChan,
  487. const bool useRightChan) throw()
  488. {
  489. jassert (reader != 0);
  490. jassert (startSample >= 0 && startSample + numSamples <= size);
  491. if (numSamples > 0)
  492. {
  493. int* chans[3];
  494. if (useLeftChan == useRightChan)
  495. {
  496. chans[0] = (int*) getSampleData (0, startSample);
  497. chans[1] = (reader->numChannels > 1 && getNumChannels() > 1) ? (int*) getSampleData (1, startSample) : 0;
  498. }
  499. else if (useLeftChan || (reader->numChannels == 1))
  500. {
  501. chans[0] = (int*) getSampleData (0, startSample);
  502. chans[1] = 0;
  503. }
  504. else if (useRightChan)
  505. {
  506. chans[0] = 0;
  507. chans[1] = (int*) getSampleData (0, startSample);
  508. }
  509. chans[2] = 0;
  510. reader->read (chans, 2, readerStartSample, numSamples, true);
  511. if (! reader->usesFloatingPointData)
  512. {
  513. for (int j = 0; j < 2; ++j)
  514. {
  515. float* const d = (float*) (chans[j]);
  516. if (d != 0)
  517. {
  518. const float multiplier = 1.0f / 0x7fffffff;
  519. for (int i = 0; i < numSamples; ++i)
  520. d[i] = *(int*)(d + i) * multiplier;
  521. }
  522. }
  523. }
  524. if (numChannels > 1 && (chans[0] == 0 || chans[1] == 0))
  525. {
  526. // if this is a stereo buffer and the source was mono, dupe the first channel..
  527. memcpy (getSampleData (1, startSample),
  528. getSampleData (0, startSample),
  529. sizeof (float) * numSamples);
  530. }
  531. }
  532. }
  533. void AudioSampleBuffer::writeToAudioWriter (AudioFormatWriter* writer,
  534. const int startSample,
  535. const int numSamples) const throw()
  536. {
  537. jassert (startSample >= 0 && startSample + numSamples <= size);
  538. if (numSamples > 0)
  539. {
  540. int* chans [3];
  541. if (writer->isFloatingPoint())
  542. {
  543. chans[0] = (int*) getSampleData (0, startSample);
  544. if (numChannels > 1)
  545. chans[1] = (int*) getSampleData (1, startSample);
  546. else
  547. chans[1] = 0;
  548. chans[2] = 0;
  549. writer->write ((const int**) chans, numSamples);
  550. }
  551. else
  552. {
  553. HeapBlock <int> tempBuffer (numSamples * 2);
  554. chans[0] = tempBuffer;
  555. if (numChannels > 1)
  556. chans[1] = chans[0] + numSamples;
  557. else
  558. chans[1] = 0;
  559. chans[2] = 0;
  560. for (int j = 0; j < 2; ++j)
  561. {
  562. int* const dest = chans[j];
  563. if (dest != 0)
  564. {
  565. const float* const src = channels [j] + startSample;
  566. for (int i = 0; i < numSamples; ++i)
  567. {
  568. const double samp = src[i];
  569. if (samp <= -1.0)
  570. dest[i] = std::numeric_limits<int>::min();
  571. else if (samp >= 1.0)
  572. dest[i] = std::numeric_limits<int>::max();
  573. else
  574. dest[i] = roundToInt (std::numeric_limits<int>::max() * samp);
  575. }
  576. }
  577. }
  578. writer->write ((const int**) chans, numSamples);
  579. }
  580. }
  581. }
  582. END_JUCE_NAMESPACE