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.

552 lines
18KB

  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::addFrom (const int destChannel,
  244. const int destStartSample,
  245. const AudioSampleBuffer& source,
  246. const int sourceChannel,
  247. const int sourceStartSample,
  248. int numSamples,
  249. const float gain) noexcept
  250. {
  251. jassert (&source != this || sourceChannel != destChannel);
  252. jassert (isPositiveAndBelow (destChannel, numChannels));
  253. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  254. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  255. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  256. if (gain != 0.0f && numSamples > 0)
  257. {
  258. float* d = channels [destChannel] + destStartSample;
  259. const float* s = source.channels [sourceChannel] + sourceStartSample;
  260. if (gain != 1.0f)
  261. {
  262. while (--numSamples >= 0)
  263. *d++ += gain * *s++;
  264. }
  265. else
  266. {
  267. while (--numSamples >= 0)
  268. *d++ += *s++;
  269. }
  270. }
  271. }
  272. void AudioSampleBuffer::addFrom (const int destChannel,
  273. const int destStartSample,
  274. const float* source,
  275. int numSamples,
  276. const float gain) noexcept
  277. {
  278. jassert (isPositiveAndBelow (destChannel, numChannels));
  279. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  280. jassert (source != nullptr);
  281. if (gain != 0.0f && numSamples > 0)
  282. {
  283. float* d = channels [destChannel] + destStartSample;
  284. if (gain != 1.0f)
  285. {
  286. while (--numSamples >= 0)
  287. *d++ += gain * *source++;
  288. }
  289. else
  290. {
  291. while (--numSamples >= 0)
  292. *d++ += *source++;
  293. }
  294. }
  295. }
  296. void AudioSampleBuffer::addFromWithRamp (const int destChannel,
  297. const int destStartSample,
  298. const float* source,
  299. int numSamples,
  300. float startGain,
  301. const float endGain) noexcept
  302. {
  303. jassert (isPositiveAndBelow (destChannel, numChannels));
  304. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  305. jassert (source != nullptr);
  306. if (startGain == endGain)
  307. {
  308. addFrom (destChannel,
  309. destStartSample,
  310. source,
  311. numSamples,
  312. startGain);
  313. }
  314. else
  315. {
  316. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  317. {
  318. const float increment = (endGain - startGain) / numSamples;
  319. float* d = channels [destChannel] + destStartSample;
  320. while (--numSamples >= 0)
  321. {
  322. *d++ += startGain * *source++;
  323. startGain += increment;
  324. }
  325. }
  326. }
  327. }
  328. void AudioSampleBuffer::copyFrom (const int destChannel,
  329. const int destStartSample,
  330. const AudioSampleBuffer& source,
  331. const int sourceChannel,
  332. const int sourceStartSample,
  333. int numSamples) noexcept
  334. {
  335. jassert (&source != this || sourceChannel != destChannel);
  336. jassert (isPositiveAndBelow (destChannel, numChannels));
  337. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  338. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  339. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  340. if (numSamples > 0)
  341. {
  342. memcpy (channels [destChannel] + destStartSample,
  343. source.channels [sourceChannel] + sourceStartSample,
  344. sizeof (float) * (size_t) numSamples);
  345. }
  346. }
  347. void AudioSampleBuffer::copyFrom (const int destChannel,
  348. const int destStartSample,
  349. const float* source,
  350. int numSamples) noexcept
  351. {
  352. jassert (isPositiveAndBelow (destChannel, numChannels));
  353. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  354. jassert (source != nullptr);
  355. if (numSamples > 0)
  356. {
  357. memcpy (channels [destChannel] + destStartSample,
  358. source,
  359. sizeof (float) * (size_t) numSamples);
  360. }
  361. }
  362. void AudioSampleBuffer::copyFrom (const int destChannel,
  363. const int destStartSample,
  364. const float* source,
  365. int numSamples,
  366. const float gain) noexcept
  367. {
  368. jassert (isPositiveAndBelow (destChannel, numChannels));
  369. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  370. jassert (source != nullptr);
  371. if (numSamples > 0)
  372. {
  373. float* d = channels [destChannel] + destStartSample;
  374. if (gain != 1.0f)
  375. {
  376. if (gain == 0)
  377. {
  378. zeromem (d, sizeof (float) * (size_t) numSamples);
  379. }
  380. else
  381. {
  382. while (--numSamples >= 0)
  383. *d++ = gain * *source++;
  384. }
  385. }
  386. else
  387. {
  388. memcpy (d, source, sizeof (float) * (size_t) numSamples);
  389. }
  390. }
  391. }
  392. void AudioSampleBuffer::copyFromWithRamp (const int destChannel,
  393. const int destStartSample,
  394. const float* source,
  395. int numSamples,
  396. float startGain,
  397. float endGain) noexcept
  398. {
  399. jassert (isPositiveAndBelow (destChannel, numChannels));
  400. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  401. jassert (source != nullptr);
  402. if (startGain == endGain)
  403. {
  404. copyFrom (destChannel,
  405. destStartSample,
  406. source,
  407. numSamples,
  408. startGain);
  409. }
  410. else
  411. {
  412. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  413. {
  414. const float increment = (endGain - startGain) / numSamples;
  415. float* d = channels [destChannel] + destStartSample;
  416. while (--numSamples >= 0)
  417. {
  418. *d++ = startGain * *source++;
  419. startGain += increment;
  420. }
  421. }
  422. }
  423. }
  424. void AudioSampleBuffer::findMinMax (const int channel,
  425. const int startSample,
  426. int numSamples,
  427. float& minVal,
  428. float& maxVal) const noexcept
  429. {
  430. jassert (isPositiveAndBelow (channel, numChannels));
  431. jassert (startSample >= 0 && startSample + numSamples <= size);
  432. findMinAndMax (channels [channel] + startSample, numSamples, minVal, maxVal);
  433. }
  434. float AudioSampleBuffer::getMagnitude (const int channel,
  435. const int startSample,
  436. const int numSamples) const noexcept
  437. {
  438. jassert (isPositiveAndBelow (channel, numChannels));
  439. jassert (startSample >= 0 && startSample + numSamples <= size);
  440. float mn, mx;
  441. findMinMax (channel, startSample, numSamples, mn, mx);
  442. return jmax (mn, -mn, mx, -mx);
  443. }
  444. float AudioSampleBuffer::getMagnitude (const int startSample,
  445. const int numSamples) const noexcept
  446. {
  447. float mag = 0.0f;
  448. for (int i = 0; i < numChannels; ++i)
  449. mag = jmax (mag, getMagnitude (i, startSample, numSamples));
  450. return mag;
  451. }
  452. float AudioSampleBuffer::getRMSLevel (const int channel,
  453. const int startSample,
  454. const int numSamples) const noexcept
  455. {
  456. jassert (isPositiveAndBelow (channel, numChannels));
  457. jassert (startSample >= 0 && startSample + numSamples <= size);
  458. if (numSamples <= 0 || channel < 0 || channel >= numChannels)
  459. return 0.0f;
  460. const float* const data = channels [channel] + startSample;
  461. double sum = 0.0;
  462. for (int i = 0; i < numSamples; ++i)
  463. {
  464. const float sample = data [i];
  465. sum += sample * sample;
  466. }
  467. return (float) std::sqrt (sum / numSamples);
  468. }