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.

juce_AudioSampleBuffer.cpp 19KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  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 (int startSample, int numSamples, float gain) noexcept
  239. {
  240. for (int i = 0; i < numChannels; ++i)
  241. applyGain (i, startSample, numSamples, gain);
  242. }
  243. void AudioSampleBuffer::applyGain (const float gain) noexcept
  244. {
  245. applyGain (0, size, gain);
  246. }
  247. void AudioSampleBuffer::applyGainRamp (int startSample, int numSamples,
  248. float startGain, float endGain) noexcept
  249. {
  250. for (int i = 0; i < numChannels; ++i)
  251. applyGainRamp (i, startSample, numSamples, startGain, endGain);
  252. }
  253. void AudioSampleBuffer::addFrom (const int destChannel,
  254. const int destStartSample,
  255. const AudioSampleBuffer& source,
  256. const int sourceChannel,
  257. const int sourceStartSample,
  258. int numSamples,
  259. const float gain) noexcept
  260. {
  261. jassert (&source != this || sourceChannel != destChannel);
  262. jassert (isPositiveAndBelow (destChannel, numChannels));
  263. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  264. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  265. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  266. if (gain != 0.0f && numSamples > 0)
  267. {
  268. float* const d = channels [destChannel] + destStartSample;
  269. const float* const s = source.channels [sourceChannel] + sourceStartSample;
  270. if (gain != 1.0f)
  271. FloatVectorOperations::addWithMultiply (d, s, gain, numSamples);
  272. else
  273. FloatVectorOperations::add (d, s, numSamples);
  274. }
  275. }
  276. void AudioSampleBuffer::addFrom (const int destChannel,
  277. const int destStartSample,
  278. const float* source,
  279. int numSamples,
  280. const float gain) noexcept
  281. {
  282. jassert (isPositiveAndBelow (destChannel, numChannels));
  283. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  284. jassert (source != nullptr);
  285. if (gain != 0.0f && numSamples > 0)
  286. {
  287. float* const d = channels [destChannel] + destStartSample;
  288. if (gain != 1.0f)
  289. FloatVectorOperations::addWithMultiply (d, source, gain, numSamples);
  290. else
  291. FloatVectorOperations::add (d, source, numSamples);
  292. }
  293. }
  294. void AudioSampleBuffer::addFromWithRamp (const int destChannel,
  295. const int destStartSample,
  296. const float* source,
  297. int numSamples,
  298. float startGain,
  299. const float endGain) noexcept
  300. {
  301. jassert (isPositiveAndBelow (destChannel, numChannels));
  302. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  303. jassert (source != nullptr);
  304. if (startGain == endGain)
  305. {
  306. addFrom (destChannel, destStartSample, source, numSamples, startGain);
  307. }
  308. else
  309. {
  310. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  311. {
  312. const float increment = (endGain - startGain) / numSamples;
  313. float* d = channels [destChannel] + destStartSample;
  314. while (--numSamples >= 0)
  315. {
  316. *d++ += startGain * *source++;
  317. startGain += increment;
  318. }
  319. }
  320. }
  321. }
  322. void AudioSampleBuffer::copyFrom (const int destChannel,
  323. const int destStartSample,
  324. const AudioSampleBuffer& source,
  325. const int sourceChannel,
  326. const int sourceStartSample,
  327. int numSamples) noexcept
  328. {
  329. jassert (&source != this || sourceChannel != destChannel);
  330. jassert (isPositiveAndBelow (destChannel, numChannels));
  331. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  332. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  333. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  334. if (numSamples > 0)
  335. FloatVectorOperations::copy (channels [destChannel] + destStartSample,
  336. source.channels [sourceChannel] + sourceStartSample,
  337. numSamples);
  338. }
  339. void AudioSampleBuffer::copyFrom (const int destChannel,
  340. const int destStartSample,
  341. const float* source,
  342. int numSamples) noexcept
  343. {
  344. jassert (isPositiveAndBelow (destChannel, numChannels));
  345. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  346. jassert (source != nullptr);
  347. if (numSamples > 0)
  348. FloatVectorOperations::copy (channels [destChannel] + destStartSample, source, numSamples);
  349. }
  350. void AudioSampleBuffer::copyFrom (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 (numSamples > 0)
  360. {
  361. float* d = channels [destChannel] + destStartSample;
  362. if (gain != 1.0f)
  363. {
  364. if (gain == 0)
  365. FloatVectorOperations::clear (d, numSamples);
  366. else
  367. FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples);
  368. }
  369. else
  370. {
  371. FloatVectorOperations::copy (d, source, numSamples);
  372. }
  373. }
  374. }
  375. void AudioSampleBuffer::copyFromWithRamp (const int destChannel,
  376. const int destStartSample,
  377. const float* source,
  378. int numSamples,
  379. float startGain,
  380. float endGain) noexcept
  381. {
  382. jassert (isPositiveAndBelow (destChannel, numChannels));
  383. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  384. jassert (source != nullptr);
  385. if (startGain == endGain)
  386. {
  387. copyFrom (destChannel, destStartSample, source, numSamples, startGain);
  388. }
  389. else
  390. {
  391. if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
  392. {
  393. const float increment = (endGain - startGain) / numSamples;
  394. float* d = channels [destChannel] + destStartSample;
  395. while (--numSamples >= 0)
  396. {
  397. *d++ = startGain * *source++;
  398. startGain += increment;
  399. }
  400. }
  401. }
  402. }
  403. void AudioSampleBuffer::reverse (int channel, int startSample, int numSamples) const noexcept
  404. {
  405. jassert (isPositiveAndBelow (channel, numChannels));
  406. jassert (startSample >= 0 && startSample + numSamples <= size);
  407. std::reverse (channels[channel] + startSample,
  408. channels[channel] + startSample + numSamples);
  409. }
  410. void AudioSampleBuffer::reverse (int startSample, int numSamples) const noexcept
  411. {
  412. for (int i = 0; i < numChannels; ++i)
  413. reverse (i, startSample, numSamples);
  414. }
  415. void AudioSampleBuffer::findMinMax (const int channel,
  416. const int startSample,
  417. int numSamples,
  418. float& minVal,
  419. float& maxVal) const noexcept
  420. {
  421. jassert (isPositiveAndBelow (channel, numChannels));
  422. jassert (startSample >= 0 && startSample + numSamples <= size);
  423. FloatVectorOperations::findMinAndMax (channels [channel] + startSample,
  424. numSamples, minVal, maxVal);
  425. }
  426. float AudioSampleBuffer::getMagnitude (const int channel,
  427. const int startSample,
  428. const int numSamples) const noexcept
  429. {
  430. jassert (isPositiveAndBelow (channel, numChannels));
  431. jassert (startSample >= 0 && startSample + numSamples <= size);
  432. float mn, mx;
  433. findMinMax (channel, startSample, numSamples, mn, mx);
  434. return jmax (mn, -mn, mx, -mx);
  435. }
  436. float AudioSampleBuffer::getMagnitude (int startSample, int numSamples) const noexcept
  437. {
  438. float mag = 0.0f;
  439. for (int i = 0; i < numChannels; ++i)
  440. mag = jmax (mag, getMagnitude (i, startSample, numSamples));
  441. return mag;
  442. }
  443. float AudioSampleBuffer::getRMSLevel (const int channel,
  444. const int startSample,
  445. const int numSamples) const noexcept
  446. {
  447. jassert (isPositiveAndBelow (channel, numChannels));
  448. jassert (startSample >= 0 && startSample + numSamples <= size);
  449. if (numSamples <= 0 || channel < 0 || channel >= numChannels)
  450. return 0.0f;
  451. const float* const data = channels [channel] + startSample;
  452. double sum = 0.0;
  453. for (int i = 0; i < numSamples; ++i)
  454. {
  455. const float sample = data [i];
  456. sum += sample * sample;
  457. }
  458. return (float) std::sqrt (sum / numSamples);
  459. }