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.

561 lines
19KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 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. AudioSampleBuffer::AudioSampleBuffer (const int numChannels_,
  19. const int numSamples) noexcept
  20. : numChannels (numChannels_),
  21. size (numSamples)
  22. {
  23. jassert (numSamples >= 0);
  24. jassert (numChannels_ > 0);
  25. allocateData();
  26. }
  27. AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer& other) noexcept
  28. : numChannels (other.numChannels),
  29. size (other.size)
  30. {
  31. allocateData();
  32. const size_t numBytes = sizeof (float) * (size_t) size;
  33. for (int i = 0; i < numChannels; ++i)
  34. memcpy (channels[i], other.channels[i], numBytes);
  35. }
  36. void AudioSampleBuffer::allocateData()
  37. {
  38. const size_t channelListSize = sizeof (float*) * (size_t) (numChannels + 1);
  39. allocatedBytes = (size_t) numChannels * (size_t) size * sizeof (float) + channelListSize + 32;
  40. allocatedData.malloc (allocatedBytes);
  41. channels = reinterpret_cast <float**> (allocatedData.getData());
  42. float* chan = (float*) (allocatedData + channelListSize);
  43. for (int i = 0; i < numChannels; ++i)
  44. {
  45. channels[i] = chan;
  46. chan += size;
  47. }
  48. channels [numChannels] = 0;
  49. }
  50. AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
  51. const int numChannels_,
  52. const int numSamples) noexcept
  53. : numChannels (numChannels_),
  54. size (numSamples),
  55. allocatedBytes (0)
  56. {
  57. jassert (numChannels_ > 0);
  58. allocateChannels (dataToReferTo, 0);
  59. }
  60. AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
  61. const int numChannels_,
  62. const int startSample,
  63. const int numSamples) noexcept
  64. : numChannels (numChannels_),
  65. size (numSamples),
  66. allocatedBytes (0)
  67. {
  68. jassert (numChannels_ > 0);
  69. allocateChannels (dataToReferTo, startSample);
  70. }
  71. void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
  72. const int newNumChannels,
  73. const int newNumSamples) noexcept
  74. {
  75. jassert (newNumChannels > 0);
  76. allocatedBytes = 0;
  77. allocatedData.free();
  78. numChannels = newNumChannels;
  79. size = newNumSamples;
  80. allocateChannels (dataToReferTo, 0);
  81. }
  82. void AudioSampleBuffer::allocateChannels (float* const* const dataToReferTo, int offset)
  83. {
  84. // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
  85. if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
  86. {
  87. channels = static_cast <float**> (preallocatedChannelSpace);
  88. }
  89. else
  90. {
  91. allocatedData.malloc ((size_t) numChannels + 1, sizeof (float*));
  92. channels = reinterpret_cast <float**> (allocatedData.getData());
  93. }
  94. for (int i = 0; i < numChannels; ++i)
  95. {
  96. // you have to pass in the same number of valid pointers as numChannels
  97. jassert (dataToReferTo[i] != nullptr);
  98. channels[i] = dataToReferTo[i] + offset;
  99. }
  100. channels [numChannels] = 0;
  101. }
  102. AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) noexcept
  103. {
  104. if (this != &other)
  105. {
  106. setSize (other.getNumChannels(), other.getNumSamples(), false, false, false);
  107. const size_t numBytes = sizeof (float) * (size_t) size;
  108. for (int i = 0; i < numChannels; ++i)
  109. memcpy (channels[i], other.channels[i], numBytes);
  110. }
  111. return *this;
  112. }
  113. AudioSampleBuffer::~AudioSampleBuffer() noexcept
  114. {
  115. }
  116. void AudioSampleBuffer::setSize (const int newNumChannels,
  117. const int newNumSamples,
  118. const bool keepExistingContent,
  119. const bool clearExtraSpace,
  120. const bool avoidReallocating) noexcept
  121. {
  122. jassert (newNumChannels > 0);
  123. jassert (newNumSamples >= 0);
  124. if (newNumSamples != size || newNumChannels != numChannels)
  125. {
  126. const size_t channelListSize = sizeof (float*) * (size_t) (newNumChannels + 1);
  127. const size_t newTotalBytes = ((size_t) newNumChannels * (size_t) newNumSamples * sizeof (float)) + channelListSize + 32;
  128. if (keepExistingContent)
  129. {
  130. HeapBlock <char, true> newData;
  131. newData.allocate (newTotalBytes, clearExtraSpace);
  132. const size_t numBytesToCopy = sizeof (float) * (size_t) jmin (newNumSamples, size);
  133. float** const newChannels = reinterpret_cast <float**> (newData.getData());
  134. float* newChan = reinterpret_cast <float*> (newData + channelListSize);
  135. for (int j = 0; j < newNumChannels; ++j)
  136. {
  137. newChannels[j] = newChan;
  138. newChan += newNumSamples;
  139. }
  140. const int numChansToCopy = jmin (numChannels, newNumChannels);
  141. for (int i = 0; i < numChansToCopy; ++i)
  142. memcpy (newChannels[i], channels[i], numBytesToCopy);
  143. allocatedData.swapWith (newData);
  144. allocatedBytes = newTotalBytes;
  145. channels = newChannels;
  146. }
  147. else
  148. {
  149. if (avoidReallocating && allocatedBytes >= newTotalBytes)
  150. {
  151. if (clearExtraSpace)
  152. allocatedData.clear (newTotalBytes);
  153. }
  154. else
  155. {
  156. allocatedBytes = newTotalBytes;
  157. allocatedData.allocate (newTotalBytes, clearExtraSpace);
  158. channels = reinterpret_cast <float**> (allocatedData.getData());
  159. }
  160. float* chan = reinterpret_cast <float*> (allocatedData + channelListSize);
  161. for (int i = 0; i < newNumChannels; ++i)
  162. {
  163. channels[i] = chan;
  164. chan += newNumSamples;
  165. }
  166. }
  167. channels [newNumChannels] = 0;
  168. size = newNumSamples;
  169. numChannels = newNumChannels;
  170. }
  171. }
  172. void AudioSampleBuffer::clear() noexcept
  173. {
  174. for (int i = 0; i < numChannels; ++i)
  175. zeromem (channels[i], sizeof (float) * (size_t) size);
  176. }
  177. void AudioSampleBuffer::clear (const int startSample,
  178. const int numSamples) noexcept
  179. {
  180. jassert (startSample >= 0 && startSample + numSamples <= size);
  181. for (int i = 0; i < numChannels; ++i)
  182. zeromem (channels [i] + startSample, sizeof (float) * (size_t) numSamples);
  183. }
  184. void AudioSampleBuffer::clear (const int channel,
  185. const int startSample,
  186. const int numSamples) noexcept
  187. {
  188. jassert (isPositiveAndBelow (channel, numChannels));
  189. jassert (startSample >= 0 && startSample + numSamples <= size);
  190. zeromem (channels [channel] + startSample, sizeof (float) * (size_t) numSamples);
  191. }
  192. void AudioSampleBuffer::applyGain (const int channel,
  193. const int startSample,
  194. int numSamples,
  195. const float gain) noexcept
  196. {
  197. jassert (isPositiveAndBelow (channel, numChannels));
  198. jassert (startSample >= 0 && startSample + numSamples <= size);
  199. if (gain != 1.0f)
  200. {
  201. float* d = channels [channel] + startSample;
  202. if (gain == 0.0f)
  203. {
  204. zeromem (d, sizeof (float) * (size_t) numSamples);
  205. }
  206. else
  207. {
  208. while (--numSamples >= 0)
  209. *d++ *= gain;
  210. }
  211. }
  212. }
  213. void AudioSampleBuffer::applyGainRamp (const int channel,
  214. const int startSample,
  215. int numSamples,
  216. float startGain,
  217. float endGain) noexcept
  218. {
  219. if (startGain == endGain)
  220. {
  221. applyGain (channel, startSample, numSamples, startGain);
  222. }
  223. else
  224. {
  225. jassert (isPositiveAndBelow (channel, numChannels));
  226. jassert (startSample >= 0 && startSample + numSamples <= size);
  227. const float increment = (endGain - startGain) / numSamples;
  228. float* d = channels [channel] + startSample;
  229. while (--numSamples >= 0)
  230. {
  231. *d++ *= startGain;
  232. startGain += increment;
  233. }
  234. }
  235. }
  236. void AudioSampleBuffer::applyGain (const int startSample,
  237. const int numSamples,
  238. const float gain) noexcept
  239. {
  240. for (int i = 0; i < numChannels; ++i)
  241. applyGain (i, startSample, numSamples, gain);
  242. }
  243. void AudioSampleBuffer::applyGainRamp (const int startSample,
  244. const int numSamples,
  245. const float startGain,
  246. const float endGain) noexcept
  247. {
  248. for (int i = 0; i < numChannels; ++i)
  249. applyGainRamp (i, startSample, numSamples, startGain, endGain);
  250. }
  251. void AudioSampleBuffer::addFrom (const int destChannel,
  252. const int destStartSample,
  253. const AudioSampleBuffer& source,
  254. const int sourceChannel,
  255. const int sourceStartSample,
  256. int numSamples,
  257. const float gain) noexcept
  258. {
  259. jassert (&source != this || sourceChannel != destChannel);
  260. jassert (isPositiveAndBelow (destChannel, numChannels));
  261. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  262. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  263. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  264. if (gain != 0.0f && numSamples > 0)
  265. {
  266. float* d = channels [destChannel] + destStartSample;
  267. const float* s = source.channels [sourceChannel] + sourceStartSample;
  268. if (gain != 1.0f)
  269. {
  270. while (--numSamples >= 0)
  271. *d++ += gain * *s++;
  272. }
  273. else
  274. {
  275. while (--numSamples >= 0)
  276. *d++ += *s++;
  277. }
  278. }
  279. }
  280. void AudioSampleBuffer::addFrom (const int destChannel,
  281. const int destStartSample,
  282. const float* source,
  283. int numSamples,
  284. const float gain) noexcept
  285. {
  286. jassert (isPositiveAndBelow (destChannel, numChannels));
  287. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  288. jassert (source != nullptr);
  289. if (gain != 0.0f && numSamples > 0)
  290. {
  291. float* d = channels [destChannel] + destStartSample;
  292. if (gain != 1.0f)
  293. {
  294. while (--numSamples >= 0)
  295. *d++ += gain * *source++;
  296. }
  297. else
  298. {
  299. while (--numSamples >= 0)
  300. *d++ += *source++;
  301. }
  302. }
  303. }
  304. void AudioSampleBuffer::addFromWithRamp (const int destChannel,
  305. const int destStartSample,
  306. const float* source,
  307. int numSamples,
  308. float startGain,
  309. const float endGain) noexcept
  310. {
  311. jassert (isPositiveAndBelow (destChannel, numChannels));
  312. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  313. jassert (source != nullptr);
  314. if (startGain == endGain)
  315. {
  316. addFrom (destChannel,
  317. destStartSample,
  318. source,
  319. numSamples,
  320. startGain);
  321. }
  322. else
  323. {
  324. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  325. {
  326. const float increment = (endGain - startGain) / numSamples;
  327. float* d = channels [destChannel] + destStartSample;
  328. while (--numSamples >= 0)
  329. {
  330. *d++ += startGain * *source++;
  331. startGain += increment;
  332. }
  333. }
  334. }
  335. }
  336. void AudioSampleBuffer::copyFrom (const int destChannel,
  337. const int destStartSample,
  338. const AudioSampleBuffer& source,
  339. const int sourceChannel,
  340. const int sourceStartSample,
  341. int numSamples) noexcept
  342. {
  343. jassert (&source != this || sourceChannel != destChannel);
  344. jassert (isPositiveAndBelow (destChannel, numChannels));
  345. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  346. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  347. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  348. if (numSamples > 0)
  349. {
  350. memcpy (channels [destChannel] + destStartSample,
  351. source.channels [sourceChannel] + sourceStartSample,
  352. sizeof (float) * (size_t) numSamples);
  353. }
  354. }
  355. void AudioSampleBuffer::copyFrom (const int destChannel,
  356. const int destStartSample,
  357. const float* source,
  358. int numSamples) noexcept
  359. {
  360. jassert (isPositiveAndBelow (destChannel, numChannels));
  361. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  362. jassert (source != nullptr);
  363. if (numSamples > 0)
  364. {
  365. memcpy (channels [destChannel] + destStartSample,
  366. source,
  367. sizeof (float) * (size_t) numSamples);
  368. }
  369. }
  370. void AudioSampleBuffer::copyFrom (const int destChannel,
  371. const int destStartSample,
  372. const float* source,
  373. int numSamples,
  374. const float gain) noexcept
  375. {
  376. jassert (isPositiveAndBelow (destChannel, numChannels));
  377. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  378. jassert (source != nullptr);
  379. if (numSamples > 0)
  380. {
  381. float* d = channels [destChannel] + destStartSample;
  382. if (gain != 1.0f)
  383. {
  384. if (gain == 0)
  385. {
  386. zeromem (d, sizeof (float) * (size_t) numSamples);
  387. }
  388. else
  389. {
  390. while (--numSamples >= 0)
  391. *d++ = gain * *source++;
  392. }
  393. }
  394. else
  395. {
  396. memcpy (d, source, sizeof (float) * (size_t) numSamples);
  397. }
  398. }
  399. }
  400. void AudioSampleBuffer::copyFromWithRamp (const int destChannel,
  401. const int destStartSample,
  402. const float* source,
  403. int numSamples,
  404. float startGain,
  405. float endGain) noexcept
  406. {
  407. jassert (isPositiveAndBelow (destChannel, numChannels));
  408. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  409. jassert (source != nullptr);
  410. if (startGain == endGain)
  411. {
  412. copyFrom (destChannel,
  413. destStartSample,
  414. source,
  415. numSamples,
  416. startGain);
  417. }
  418. else
  419. {
  420. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  421. {
  422. const float increment = (endGain - startGain) / numSamples;
  423. float* d = channels [destChannel] + destStartSample;
  424. while (--numSamples >= 0)
  425. {
  426. *d++ = startGain * *source++;
  427. startGain += increment;
  428. }
  429. }
  430. }
  431. }
  432. void AudioSampleBuffer::findMinMax (const int channel,
  433. const int startSample,
  434. int numSamples,
  435. float& minVal,
  436. float& maxVal) const noexcept
  437. {
  438. jassert (isPositiveAndBelow (channel, numChannels));
  439. jassert (startSample >= 0 && startSample + numSamples <= size);
  440. findMinAndMax (channels [channel] + startSample, numSamples, minVal, maxVal);
  441. }
  442. float AudioSampleBuffer::getMagnitude (const int channel,
  443. const int startSample,
  444. const int numSamples) const noexcept
  445. {
  446. jassert (isPositiveAndBelow (channel, numChannels));
  447. jassert (startSample >= 0 && startSample + numSamples <= size);
  448. float mn, mx;
  449. findMinMax (channel, startSample, numSamples, mn, mx);
  450. return jmax (mn, -mn, mx, -mx);
  451. }
  452. float AudioSampleBuffer::getMagnitude (const int startSample,
  453. const int numSamples) const noexcept
  454. {
  455. float mag = 0.0f;
  456. for (int i = 0; i < numChannels; ++i)
  457. mag = jmax (mag, getMagnitude (i, startSample, numSamples));
  458. return mag;
  459. }
  460. float AudioSampleBuffer::getRMSLevel (const int channel,
  461. const int startSample,
  462. const int numSamples) const noexcept
  463. {
  464. jassert (isPositiveAndBelow (channel, numChannels));
  465. jassert (startSample >= 0 && startSample + numSamples <= size);
  466. if (numSamples <= 0 || channel < 0 || channel >= numChannels)
  467. return 0.0f;
  468. const float* const data = channels [channel] + startSample;
  469. double sum = 0.0;
  470. for (int i = 0; i < numSamples; ++i)
  471. {
  472. const float sample = data [i];
  473. sum += sample * sample;
  474. }
  475. return (float) std::sqrt (sum / numSamples);
  476. }