Audio plugin host https://kx.studio/carla
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.

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