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.

667 lines
22KB

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