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.

536 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. for (int i = 0; i < numChannels; ++i)
  33. FloatVectorOperations::copy (channels[i], other.channels[i], size);
  34. }
  35. void AudioSampleBuffer::allocateData()
  36. {
  37. const size_t channelListSize = sizeof (float*) * (size_t) (numChannels + 1);
  38. allocatedBytes = (size_t) numChannels * (size_t) size * sizeof (float) + channelListSize + 32;
  39. allocatedData.malloc (allocatedBytes);
  40. channels = reinterpret_cast <float**> (allocatedData.getData());
  41. float* chan = (float*) (allocatedData + channelListSize);
  42. for (int i = 0; i < numChannels; ++i)
  43. {
  44. channels[i] = chan;
  45. chan += size;
  46. }
  47. channels [numChannels] = 0;
  48. }
  49. AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
  50. const int numChannels_,
  51. const int numSamples) noexcept
  52. : numChannels (numChannels_),
  53. size (numSamples),
  54. allocatedBytes (0)
  55. {
  56. jassert (numChannels_ > 0);
  57. allocateChannels (dataToReferTo, 0);
  58. }
  59. AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
  60. const int numChannels_,
  61. const int startSample,
  62. const int numSamples) noexcept
  63. : numChannels (numChannels_),
  64. size (numSamples),
  65. allocatedBytes (0)
  66. {
  67. jassert (numChannels_ > 0);
  68. allocateChannels (dataToReferTo, startSample);
  69. }
  70. void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
  71. const int newNumChannels,
  72. const int newNumSamples) noexcept
  73. {
  74. jassert (newNumChannels > 0);
  75. allocatedBytes = 0;
  76. allocatedData.free();
  77. numChannels = newNumChannels;
  78. size = newNumSamples;
  79. allocateChannels (dataToReferTo, 0);
  80. }
  81. void AudioSampleBuffer::allocateChannels (float* const* const dataToReferTo, int offset)
  82. {
  83. // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
  84. if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
  85. {
  86. channels = static_cast <float**> (preallocatedChannelSpace);
  87. }
  88. else
  89. {
  90. allocatedData.malloc ((size_t) numChannels + 1, sizeof (float*));
  91. channels = reinterpret_cast <float**> (allocatedData.getData());
  92. }
  93. for (int i = 0; i < numChannels; ++i)
  94. {
  95. // you have to pass in the same number of valid pointers as numChannels
  96. jassert (dataToReferTo[i] != nullptr);
  97. channels[i] = dataToReferTo[i] + offset;
  98. }
  99. channels [numChannels] = 0;
  100. }
  101. AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) noexcept
  102. {
  103. if (this != &other)
  104. {
  105. setSize (other.getNumChannels(), other.getNumSamples(), false, false, false);
  106. for (int i = 0; i < numChannels; ++i)
  107. FloatVectorOperations::copy (channels[i], other.channels[i], size);
  108. }
  109. return *this;
  110. }
  111. AudioSampleBuffer::~AudioSampleBuffer() noexcept
  112. {
  113. }
  114. void AudioSampleBuffer::setSize (const int newNumChannels,
  115. const int newNumSamples,
  116. const bool keepExistingContent,
  117. const bool clearExtraSpace,
  118. const bool avoidReallocating) noexcept
  119. {
  120. jassert (newNumChannels > 0);
  121. jassert (newNumSamples >= 0);
  122. if (newNumSamples != size || newNumChannels != numChannels)
  123. {
  124. const size_t allocatedSamplesPerChannel = (newNumSamples + 3) & ~3;
  125. const size_t channelListSize = ((sizeof (float*) * (size_t) (newNumChannels + 1)) + 15) & ~15;
  126. const size_t newTotalBytes = ((size_t) newNumChannels * (size_t) allocatedSamplesPerChannel * sizeof (float))
  127. + channelListSize + 32;
  128. if (keepExistingContent)
  129. {
  130. HeapBlock <char, true> newData;
  131. newData.allocate (newTotalBytes, clearExtraSpace);
  132. const size_t numSamplesToCopy = 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 += allocatedSamplesPerChannel;
  139. }
  140. const int numChansToCopy = jmin (numChannels, newNumChannels);
  141. for (int i = 0; i < numChansToCopy; ++i)
  142. FloatVectorOperations::copy (newChannels[i], channels[i], numSamplesToCopy);
  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 += allocatedSamplesPerChannel;
  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. FloatVectorOperations::clear (channels[i], 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. FloatVectorOperations::clear (channels[i] + startSample, 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. FloatVectorOperations::clear (channels [channel] + startSample, 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* const d = channels [channel] + startSample;
  202. if (gain == 0.0f)
  203. FloatVectorOperations::clear (d, numSamples);
  204. else
  205. FloatVectorOperations::multiply (d, gain, numSamples);
  206. }
  207. }
  208. void AudioSampleBuffer::applyGainRamp (const int channel,
  209. const int startSample,
  210. int numSamples,
  211. float startGain,
  212. float endGain) noexcept
  213. {
  214. if (startGain == endGain)
  215. {
  216. applyGain (channel, startSample, numSamples, startGain);
  217. }
  218. else
  219. {
  220. jassert (isPositiveAndBelow (channel, numChannels));
  221. jassert (startSample >= 0 && startSample + numSamples <= size);
  222. const float increment = (endGain - startGain) / numSamples;
  223. float* d = channels [channel] + startSample;
  224. while (--numSamples >= 0)
  225. {
  226. *d++ *= startGain;
  227. startGain += increment;
  228. }
  229. }
  230. }
  231. void AudioSampleBuffer::applyGain (const int startSample,
  232. const int numSamples,
  233. const float gain) noexcept
  234. {
  235. for (int i = 0; i < numChannels; ++i)
  236. applyGain (i, startSample, numSamples, gain);
  237. }
  238. void AudioSampleBuffer::applyGain (const float gain) noexcept
  239. {
  240. applyGain (0, size, gain);
  241. }
  242. void AudioSampleBuffer::applyGainRamp (const int startSample,
  243. const int numSamples,
  244. const float startGain,
  245. const float endGain) noexcept
  246. {
  247. for (int i = 0; i < numChannels; ++i)
  248. applyGainRamp (i, startSample, numSamples, startGain, endGain);
  249. }
  250. void AudioSampleBuffer::addFrom (const int destChannel,
  251. const int destStartSample,
  252. const AudioSampleBuffer& source,
  253. const int sourceChannel,
  254. const int sourceStartSample,
  255. int numSamples,
  256. const float gain) noexcept
  257. {
  258. jassert (&source != this || sourceChannel != destChannel);
  259. jassert (isPositiveAndBelow (destChannel, numChannels));
  260. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  261. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  262. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  263. if (gain != 0.0f && numSamples > 0)
  264. {
  265. float* const d = channels [destChannel] + destStartSample;
  266. const float* const s = source.channels [sourceChannel] + sourceStartSample;
  267. if (gain != 1.0f)
  268. FloatVectorOperations::addWithMultiply (d, s, gain, numSamples);
  269. else
  270. FloatVectorOperations::add (d, s, numSamples);
  271. }
  272. }
  273. void AudioSampleBuffer::addFrom (const int destChannel,
  274. const int destStartSample,
  275. const float* source,
  276. int numSamples,
  277. const float gain) noexcept
  278. {
  279. jassert (isPositiveAndBelow (destChannel, numChannels));
  280. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  281. jassert (source != nullptr);
  282. if (gain != 0.0f && numSamples > 0)
  283. {
  284. float* const d = channels [destChannel] + destStartSample;
  285. if (gain != 1.0f)
  286. FloatVectorOperations::addWithMultiply (d, source, gain, numSamples);
  287. else
  288. FloatVectorOperations::add (d, source, numSamples);
  289. }
  290. }
  291. void AudioSampleBuffer::addFromWithRamp (const int destChannel,
  292. const int destStartSample,
  293. const float* source,
  294. int numSamples,
  295. float startGain,
  296. const float endGain) noexcept
  297. {
  298. jassert (isPositiveAndBelow (destChannel, numChannels));
  299. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  300. jassert (source != nullptr);
  301. if (startGain == endGain)
  302. {
  303. addFrom (destChannel, destStartSample, source, numSamples, startGain);
  304. }
  305. else
  306. {
  307. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  308. {
  309. const float increment = (endGain - startGain) / numSamples;
  310. float* d = channels [destChannel] + destStartSample;
  311. while (--numSamples >= 0)
  312. {
  313. *d++ += startGain * *source++;
  314. startGain += increment;
  315. }
  316. }
  317. }
  318. }
  319. void AudioSampleBuffer::copyFrom (const int destChannel,
  320. const int destStartSample,
  321. const AudioSampleBuffer& source,
  322. const int sourceChannel,
  323. const int sourceStartSample,
  324. int numSamples) noexcept
  325. {
  326. jassert (&source != this || sourceChannel != destChannel);
  327. jassert (isPositiveAndBelow (destChannel, numChannels));
  328. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  329. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  330. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  331. if (numSamples > 0)
  332. {
  333. FloatVectorOperations::copy (channels [destChannel] + destStartSample,
  334. source.channels [sourceChannel] + sourceStartSample,
  335. numSamples);
  336. }
  337. }
  338. void AudioSampleBuffer::copyFrom (const int destChannel,
  339. const int destStartSample,
  340. const float* source,
  341. int numSamples) noexcept
  342. {
  343. jassert (isPositiveAndBelow (destChannel, numChannels));
  344. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  345. jassert (source != nullptr);
  346. if (numSamples > 0)
  347. {
  348. FloatVectorOperations::copy (channels [destChannel] + destStartSample,
  349. source,
  350. numSamples);
  351. }
  352. }
  353. void AudioSampleBuffer::copyFrom (const int destChannel,
  354. const int destStartSample,
  355. const float* source,
  356. int numSamples,
  357. const float gain) noexcept
  358. {
  359. jassert (isPositiveAndBelow (destChannel, numChannels));
  360. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  361. jassert (source != nullptr);
  362. if (numSamples > 0)
  363. {
  364. float* d = channels [destChannel] + destStartSample;
  365. if (gain != 1.0f)
  366. {
  367. if (gain == 0)
  368. FloatVectorOperations::clear (d, numSamples);
  369. else
  370. FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples);
  371. }
  372. else
  373. {
  374. FloatVectorOperations::copy (d, source, numSamples);
  375. }
  376. }
  377. }
  378. void AudioSampleBuffer::copyFromWithRamp (const int destChannel,
  379. const int destStartSample,
  380. const float* source,
  381. int numSamples,
  382. float startGain,
  383. float endGain) noexcept
  384. {
  385. jassert (isPositiveAndBelow (destChannel, numChannels));
  386. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  387. jassert (source != nullptr);
  388. if (startGain == endGain)
  389. {
  390. copyFrom (destChannel, destStartSample, source, numSamples, startGain);
  391. }
  392. else
  393. {
  394. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  395. {
  396. const float increment = (endGain - startGain) / numSamples;
  397. float* d = channels [destChannel] + destStartSample;
  398. while (--numSamples >= 0)
  399. {
  400. *d++ = startGain * *source++;
  401. startGain += increment;
  402. }
  403. }
  404. }
  405. }
  406. void AudioSampleBuffer::findMinMax (const int channel,
  407. const int startSample,
  408. int numSamples,
  409. float& minVal,
  410. float& maxVal) const noexcept
  411. {
  412. jassert (isPositiveAndBelow (channel, numChannels));
  413. jassert (startSample >= 0 && startSample + numSamples <= size);
  414. FloatVectorOperations::findMinAndMax (channels [channel] + startSample,
  415. numSamples, minVal, maxVal);
  416. }
  417. float AudioSampleBuffer::getMagnitude (const int channel,
  418. const int startSample,
  419. const int numSamples) const noexcept
  420. {
  421. jassert (isPositiveAndBelow (channel, numChannels));
  422. jassert (startSample >= 0 && startSample + numSamples <= size);
  423. float mn, mx;
  424. findMinMax (channel, startSample, numSamples, mn, mx);
  425. return jmax (mn, -mn, mx, -mx);
  426. }
  427. float AudioSampleBuffer::getMagnitude (const int startSample,
  428. const int numSamples) const noexcept
  429. {
  430. float mag = 0.0f;
  431. for (int i = 0; i < numChannels; ++i)
  432. mag = jmax (mag, getMagnitude (i, startSample, numSamples));
  433. return mag;
  434. }
  435. float AudioSampleBuffer::getRMSLevel (const int channel,
  436. const int startSample,
  437. const int numSamples) const noexcept
  438. {
  439. jassert (isPositiveAndBelow (channel, numChannels));
  440. jassert (startSample >= 0 && startSample + numSamples <= size);
  441. if (numSamples <= 0 || channel < 0 || channel >= numChannels)
  442. return 0.0f;
  443. const float* const data = channels [channel] + startSample;
  444. double sum = 0.0;
  445. for (int i = 0; i < numSamples; ++i)
  446. {
  447. const float sample = data [i];
  448. sum += sample * sample;
  449. }
  450. return (float) std::sqrt (sum / numSamples);
  451. }