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.

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