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.

535 lines
19KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. AudioSampleBuffer::AudioSampleBuffer (const int numChannels_,
  18. const int numSamples) noexcept
  19. : numChannels (numChannels_),
  20. size (numSamples)
  21. {
  22. jassert (numSamples >= 0);
  23. jassert (numChannels_ > 0);
  24. allocateData();
  25. }
  26. AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer& other) noexcept
  27. : numChannels (other.numChannels),
  28. size (other.size)
  29. {
  30. allocateData();
  31. for (int i = 0; i < numChannels; ++i)
  32. FloatVectorOperations::copy (channels[i], other.channels[i], size);
  33. }
  34. void AudioSampleBuffer::allocateData()
  35. {
  36. const size_t channelListSize = sizeof (float*) * (size_t) (numChannels + 1);
  37. allocatedBytes = (size_t) numChannels * (size_t) size * sizeof (float) + channelListSize + 32;
  38. allocatedData.malloc (allocatedBytes);
  39. channels = reinterpret_cast <float**> (allocatedData.getData());
  40. float* chan = (float*) (allocatedData + channelListSize);
  41. for (int i = 0; i < numChannels; ++i)
  42. {
  43. channels[i] = chan;
  44. chan += size;
  45. }
  46. channels [numChannels] = nullptr;
  47. }
  48. AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
  49. const int numChannels_,
  50. const int numSamples) noexcept
  51. : numChannels (numChannels_),
  52. size (numSamples),
  53. allocatedBytes (0)
  54. {
  55. jassert (numChannels_ > 0);
  56. allocateChannels (dataToReferTo, 0);
  57. }
  58. AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
  59. const int numChannels_,
  60. const int startSample,
  61. const int numSamples) noexcept
  62. : numChannels (numChannels_),
  63. size (numSamples),
  64. allocatedBytes (0)
  65. {
  66. jassert (numChannels_ > 0);
  67. allocateChannels (dataToReferTo, startSample);
  68. }
  69. void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
  70. const int newNumChannels,
  71. const int newNumSamples) noexcept
  72. {
  73. jassert (newNumChannels > 0);
  74. allocatedBytes = 0;
  75. allocatedData.free();
  76. numChannels = newNumChannels;
  77. size = newNumSamples;
  78. allocateChannels (dataToReferTo, 0);
  79. }
  80. void AudioSampleBuffer::allocateChannels (float* const* const dataToReferTo, int offset)
  81. {
  82. // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
  83. if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
  84. {
  85. channels = static_cast <float**> (preallocatedChannelSpace);
  86. }
  87. else
  88. {
  89. allocatedData.malloc ((size_t) numChannels + 1, sizeof (float*));
  90. channels = reinterpret_cast <float**> (allocatedData.getData());
  91. }
  92. for (int i = 0; i < numChannels; ++i)
  93. {
  94. // you have to pass in the same number of valid pointers as numChannels
  95. jassert (dataToReferTo[i] != nullptr);
  96. channels[i] = dataToReferTo[i] + offset;
  97. }
  98. channels [numChannels] = nullptr;
  99. }
  100. AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) noexcept
  101. {
  102. if (this != &other)
  103. {
  104. setSize (other.getNumChannels(), other.getNumSamples(), false, false, false);
  105. for (int i = 0; i < numChannels; ++i)
  106. FloatVectorOperations::copy (channels[i], other.channels[i], size);
  107. }
  108. return *this;
  109. }
  110. AudioSampleBuffer::~AudioSampleBuffer() noexcept
  111. {
  112. }
  113. void AudioSampleBuffer::setSize (const int newNumChannels,
  114. const int newNumSamples,
  115. const bool keepExistingContent,
  116. const bool clearExtraSpace,
  117. const bool avoidReallocating) noexcept
  118. {
  119. jassert (newNumChannels > 0);
  120. jassert (newNumSamples >= 0);
  121. if (newNumSamples != size || newNumChannels != numChannels)
  122. {
  123. const size_t allocatedSamplesPerChannel = (newNumSamples + 3) & ~3;
  124. const size_t channelListSize = ((sizeof (float*) * (size_t) (newNumChannels + 1)) + 15) & ~15;
  125. const size_t newTotalBytes = ((size_t) newNumChannels * (size_t) allocatedSamplesPerChannel * sizeof (float))
  126. + channelListSize + 32;
  127. if (keepExistingContent)
  128. {
  129. HeapBlock <char, true> newData;
  130. newData.allocate (newTotalBytes, clearExtraSpace);
  131. const size_t numSamplesToCopy = jmin (newNumSamples, size);
  132. float** const newChannels = reinterpret_cast <float**> (newData.getData());
  133. float* newChan = reinterpret_cast <float*> (newData + channelListSize);
  134. for (int j = 0; j < newNumChannels; ++j)
  135. {
  136. newChannels[j] = newChan;
  137. newChan += allocatedSamplesPerChannel;
  138. }
  139. const int numChansToCopy = jmin (numChannels, newNumChannels);
  140. for (int i = 0; i < numChansToCopy; ++i)
  141. FloatVectorOperations::copy (newChannels[i], channels[i], (int) numSamplesToCopy);
  142. allocatedData.swapWith (newData);
  143. allocatedBytes = newTotalBytes;
  144. channels = newChannels;
  145. }
  146. else
  147. {
  148. if (avoidReallocating && allocatedBytes >= newTotalBytes)
  149. {
  150. if (clearExtraSpace)
  151. allocatedData.clear (newTotalBytes);
  152. }
  153. else
  154. {
  155. allocatedBytes = newTotalBytes;
  156. allocatedData.allocate (newTotalBytes, clearExtraSpace);
  157. channels = reinterpret_cast <float**> (allocatedData.getData());
  158. }
  159. float* chan = reinterpret_cast <float*> (allocatedData + channelListSize);
  160. for (int i = 0; i < newNumChannels; ++i)
  161. {
  162. channels[i] = chan;
  163. chan += allocatedSamplesPerChannel;
  164. }
  165. }
  166. channels [newNumChannels] = 0;
  167. size = newNumSamples;
  168. numChannels = newNumChannels;
  169. }
  170. }
  171. void AudioSampleBuffer::clear() noexcept
  172. {
  173. for (int i = 0; i < numChannels; ++i)
  174. FloatVectorOperations::clear (channels[i], size);
  175. }
  176. void AudioSampleBuffer::clear (const int startSample,
  177. const int numSamples) noexcept
  178. {
  179. jassert (startSample >= 0 && startSample + numSamples <= size);
  180. for (int i = 0; i < numChannels; ++i)
  181. FloatVectorOperations::clear (channels[i] + startSample, numSamples);
  182. }
  183. void AudioSampleBuffer::clear (const int channel,
  184. const int startSample,
  185. const int numSamples) noexcept
  186. {
  187. jassert (isPositiveAndBelow (channel, numChannels));
  188. jassert (startSample >= 0 && startSample + numSamples <= size);
  189. FloatVectorOperations::clear (channels [channel] + startSample, numSamples);
  190. }
  191. void AudioSampleBuffer::applyGain (const int channel,
  192. const int startSample,
  193. int numSamples,
  194. const float gain) noexcept
  195. {
  196. jassert (isPositiveAndBelow (channel, numChannels));
  197. jassert (startSample >= 0 && startSample + numSamples <= size);
  198. if (gain != 1.0f)
  199. {
  200. float* const d = channels [channel] + startSample;
  201. if (gain == 0.0f)
  202. FloatVectorOperations::clear (d, numSamples);
  203. else
  204. FloatVectorOperations::multiply (d, gain, numSamples);
  205. }
  206. }
  207. void AudioSampleBuffer::applyGainRamp (const int channel,
  208. const int startSample,
  209. int numSamples,
  210. float startGain,
  211. float endGain) noexcept
  212. {
  213. if (startGain == endGain)
  214. {
  215. applyGain (channel, startSample, numSamples, startGain);
  216. }
  217. else
  218. {
  219. jassert (isPositiveAndBelow (channel, numChannels));
  220. jassert (startSample >= 0 && startSample + numSamples <= size);
  221. const float increment = (endGain - startGain) / numSamples;
  222. float* d = channels [channel] + startSample;
  223. while (--numSamples >= 0)
  224. {
  225. *d++ *= startGain;
  226. startGain += increment;
  227. }
  228. }
  229. }
  230. void AudioSampleBuffer::applyGain (const int startSample,
  231. const int numSamples,
  232. const float gain) noexcept
  233. {
  234. for (int i = 0; i < numChannels; ++i)
  235. applyGain (i, startSample, numSamples, gain);
  236. }
  237. void AudioSampleBuffer::applyGain (const float gain) noexcept
  238. {
  239. applyGain (0, size, gain);
  240. }
  241. void AudioSampleBuffer::applyGainRamp (const int startSample,
  242. const int numSamples,
  243. const float startGain,
  244. const float endGain) noexcept
  245. {
  246. for (int i = 0; i < numChannels; ++i)
  247. applyGainRamp (i, startSample, numSamples, startGain, endGain);
  248. }
  249. void AudioSampleBuffer::addFrom (const int destChannel,
  250. const int destStartSample,
  251. const AudioSampleBuffer& source,
  252. const int sourceChannel,
  253. const int sourceStartSample,
  254. int numSamples,
  255. const float gain) noexcept
  256. {
  257. jassert (&source != this || sourceChannel != destChannel);
  258. jassert (isPositiveAndBelow (destChannel, numChannels));
  259. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  260. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  261. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  262. if (gain != 0.0f && numSamples > 0)
  263. {
  264. float* const d = channels [destChannel] + destStartSample;
  265. const float* const s = source.channels [sourceChannel] + sourceStartSample;
  266. if (gain != 1.0f)
  267. FloatVectorOperations::addWithMultiply (d, s, gain, numSamples);
  268. else
  269. FloatVectorOperations::add (d, s, numSamples);
  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* const d = channels [destChannel] + destStartSample;
  284. if (gain != 1.0f)
  285. FloatVectorOperations::addWithMultiply (d, source, gain, numSamples);
  286. else
  287. FloatVectorOperations::add (d, source, numSamples);
  288. }
  289. }
  290. void AudioSampleBuffer::addFromWithRamp (const int destChannel,
  291. const int destStartSample,
  292. const float* source,
  293. int numSamples,
  294. float startGain,
  295. const float endGain) noexcept
  296. {
  297. jassert (isPositiveAndBelow (destChannel, numChannels));
  298. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  299. jassert (source != nullptr);
  300. if (startGain == endGain)
  301. {
  302. addFrom (destChannel, destStartSample, source, numSamples, startGain);
  303. }
  304. else
  305. {
  306. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  307. {
  308. const float increment = (endGain - startGain) / numSamples;
  309. float* d = channels [destChannel] + destStartSample;
  310. while (--numSamples >= 0)
  311. {
  312. *d++ += startGain * *source++;
  313. startGain += increment;
  314. }
  315. }
  316. }
  317. }
  318. void AudioSampleBuffer::copyFrom (const int destChannel,
  319. const int destStartSample,
  320. const AudioSampleBuffer& source,
  321. const int sourceChannel,
  322. const int sourceStartSample,
  323. int numSamples) noexcept
  324. {
  325. jassert (&source != this || sourceChannel != destChannel);
  326. jassert (isPositiveAndBelow (destChannel, numChannels));
  327. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  328. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  329. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  330. if (numSamples > 0)
  331. {
  332. FloatVectorOperations::copy (channels [destChannel] + destStartSample,
  333. source.channels [sourceChannel] + sourceStartSample,
  334. numSamples);
  335. }
  336. }
  337. void AudioSampleBuffer::copyFrom (const int destChannel,
  338. const int destStartSample,
  339. const float* source,
  340. int numSamples) noexcept
  341. {
  342. jassert (isPositiveAndBelow (destChannel, numChannels));
  343. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  344. jassert (source != nullptr);
  345. if (numSamples > 0)
  346. {
  347. FloatVectorOperations::copy (channels [destChannel] + destStartSample,
  348. source,
  349. numSamples);
  350. }
  351. }
  352. void AudioSampleBuffer::copyFrom (const int destChannel,
  353. const int destStartSample,
  354. const float* source,
  355. int numSamples,
  356. const float gain) noexcept
  357. {
  358. jassert (isPositiveAndBelow (destChannel, numChannels));
  359. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  360. jassert (source != nullptr);
  361. if (numSamples > 0)
  362. {
  363. float* d = channels [destChannel] + destStartSample;
  364. if (gain != 1.0f)
  365. {
  366. if (gain == 0)
  367. FloatVectorOperations::clear (d, numSamples);
  368. else
  369. FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples);
  370. }
  371. else
  372. {
  373. FloatVectorOperations::copy (d, source, numSamples);
  374. }
  375. }
  376. }
  377. void AudioSampleBuffer::copyFromWithRamp (const int destChannel,
  378. const int destStartSample,
  379. const float* source,
  380. int numSamples,
  381. float startGain,
  382. float endGain) noexcept
  383. {
  384. jassert (isPositiveAndBelow (destChannel, numChannels));
  385. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  386. jassert (source != nullptr);
  387. if (startGain == endGain)
  388. {
  389. copyFrom (destChannel, destStartSample, source, numSamples, startGain);
  390. }
  391. else
  392. {
  393. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  394. {
  395. const float increment = (endGain - startGain) / numSamples;
  396. float* d = channels [destChannel] + destStartSample;
  397. while (--numSamples >= 0)
  398. {
  399. *d++ = startGain * *source++;
  400. startGain += increment;
  401. }
  402. }
  403. }
  404. }
  405. void AudioSampleBuffer::findMinMax (const int channel,
  406. const int startSample,
  407. int numSamples,
  408. float& minVal,
  409. float& maxVal) const noexcept
  410. {
  411. jassert (isPositiveAndBelow (channel, numChannels));
  412. jassert (startSample >= 0 && startSample + numSamples <= size);
  413. FloatVectorOperations::findMinAndMax (channels [channel] + startSample,
  414. numSamples, minVal, maxVal);
  415. }
  416. float AudioSampleBuffer::getMagnitude (const int channel,
  417. const int startSample,
  418. const int numSamples) const noexcept
  419. {
  420. jassert (isPositiveAndBelow (channel, numChannels));
  421. jassert (startSample >= 0 && startSample + numSamples <= size);
  422. float mn, mx;
  423. findMinMax (channel, startSample, numSamples, mn, mx);
  424. return jmax (mn, -mn, mx, -mx);
  425. }
  426. float AudioSampleBuffer::getMagnitude (const int startSample,
  427. const int numSamples) const noexcept
  428. {
  429. float mag = 0.0f;
  430. for (int i = 0; i < numChannels; ++i)
  431. mag = jmax (mag, getMagnitude (i, startSample, numSamples));
  432. return mag;
  433. }
  434. float AudioSampleBuffer::getRMSLevel (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. if (numSamples <= 0 || channel < 0 || channel >= numChannels)
  441. return 0.0f;
  442. const float* const data = channels [channel] + startSample;
  443. double sum = 0.0;
  444. for (int i = 0; i < numSamples; ++i)
  445. {
  446. const float sample = data [i];
  447. sum += sample * sample;
  448. }
  449. return (float) std::sqrt (sum / numSamples);
  450. }