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.

AudioSampleBuffer.h 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. /*
  2. ==============================================================================
  3. This file is part of the Water library.
  4. Copyright (c) 2016 ROLI Ltd.
  5. Copyright (C) 2017-2018 Filipe Coelho <falktx@falktx.com>
  6. Permission is granted to use this software under the terms of the ISC license
  7. http://www.isc.org/downloads/software-support-policy/isc-license/
  8. Permission to use, copy, modify, and/or distribute this software for any
  9. purpose with or without fee is hereby granted, provided that the above
  10. copyright notice and this permission notice appear in all copies.
  11. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
  12. TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  13. FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
  14. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  15. USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  16. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  17. OF THIS SOFTWARE.
  18. ==============================================================================
  19. */
  20. #ifndef WATER_AUDIOSAMPLEBUFFER_H_INCLUDED
  21. #define WATER_AUDIOSAMPLEBUFFER_H_INCLUDED
  22. #include "../memory/HeapBlock.h"
  23. #include "CarlaMathUtils.hpp"
  24. namespace water {
  25. //==============================================================================
  26. /**
  27. A multi-channel buffer of floating point audio samples.
  28. @see AudioSampleBuffer
  29. */
  30. class AudioSampleBuffer
  31. {
  32. public:
  33. //==============================================================================
  34. /** Creates an empty buffer with 0 channels and 0 length. */
  35. AudioSampleBuffer() noexcept
  36. : numChannels (0), size (0), allocatedBytes (0),
  37. channels (static_cast<float**> (preallocatedChannelSpace)),
  38. isClear (false)
  39. {
  40. }
  41. //==============================================================================
  42. /** Creates a buffer with a specified number of channels and samples.
  43. The contents of the buffer will initially be undefined, so use clear() to
  44. set all the samples to zero.
  45. The buffer will allocate its memory internally, and this will be released
  46. when the buffer is deleted. If the memory can't be allocated, this will
  47. throw a std::bad_alloc exception.
  48. */
  49. AudioSampleBuffer (int numChannelsToAllocate,
  50. int numSamplesToAllocate) noexcept
  51. : numChannels (numChannelsToAllocate),
  52. size (numSamplesToAllocate)
  53. {
  54. CARLA_SAFE_ASSERT_RETURN (size >= 0,);
  55. CARLA_SAFE_ASSERT_RETURN (numChannels >= 0,);
  56. allocateData();
  57. }
  58. /** Creates a buffer using a pre-allocated block of memory.
  59. Note that if the buffer is resized or its number of channels is changed, it
  60. will re-allocate memory internally and copy the existing data to this new area,
  61. so it will then stop directly addressing this memory.
  62. @param dataToReferTo a pre-allocated array containing pointers to the data
  63. for each channel that should be used by this buffer. The
  64. buffer will only refer to this memory, it won't try to delete
  65. it when the buffer is deleted or resized.
  66. @param numChannelsToUse the number of channels to use - this must correspond to the
  67. number of elements in the array passed in
  68. @param numSamples the number of samples to use - this must correspond to the
  69. size of the arrays passed in
  70. */
  71. AudioSampleBuffer (float* const* dataToReferTo,
  72. int numChannelsToUse,
  73. int numSamples) noexcept
  74. : numChannels (numChannelsToUse),
  75. size (numSamples),
  76. allocatedBytes (0)
  77. {
  78. CARLA_SAFE_ASSERT_RETURN (dataToReferTo != nullptr,);
  79. CARLA_SAFE_ASSERT_RETURN (numChannelsToUse >= 0 && numSamples >= 0,);
  80. allocateChannels (dataToReferTo, 0);
  81. }
  82. /** Creates a buffer using a pre-allocated block of memory.
  83. Note that if the buffer is resized or its number of channels is changed, it
  84. will re-allocate memory internally and copy the existing data to this new area,
  85. so it will then stop directly addressing this memory.
  86. @param dataToReferTo a pre-allocated array containing pointers to the data
  87. for each channel that should be used by this buffer. The
  88. buffer will only refer to this memory, it won't try to delete
  89. it when the buffer is deleted or resized.
  90. @param numChannelsToUse the number of channels to use - this must correspond to the
  91. number of elements in the array passed in
  92. @param startSample the offset within the arrays at which the data begins
  93. @param numSamples the number of samples to use - this must correspond to the
  94. size of the arrays passed in
  95. */
  96. AudioSampleBuffer (float* const* dataToReferTo,
  97. int numChannelsToUse,
  98. int startSample,
  99. int numSamples) noexcept
  100. : numChannels (numChannelsToUse),
  101. size (numSamples),
  102. allocatedBytes (0),
  103. isClear (false)
  104. {
  105. CARLA_SAFE_ASSERT_RETURN (dataToReferTo != nullptr,);
  106. CARLA_SAFE_ASSERT_RETURN (numChannelsToUse >= 0 && startSample >= 0 && numSamples >= 0,);
  107. allocateChannels (dataToReferTo, startSample);
  108. }
  109. /** Copies another buffer.
  110. This buffer will make its own copy of the other's data, unless the buffer was created
  111. using an external data buffer, in which case boths buffers will just point to the same
  112. shared block of data.
  113. */
  114. AudioSampleBuffer (const AudioSampleBuffer& other) noexcept
  115. : numChannels (other.numChannels),
  116. size (other.size),
  117. allocatedBytes (other.allocatedBytes)
  118. {
  119. if (allocatedBytes == 0)
  120. {
  121. allocateChannels (other.channels, 0);
  122. }
  123. else
  124. {
  125. allocateData();
  126. if (other.isClear)
  127. {
  128. clear();
  129. }
  130. else
  131. {
  132. for (int i = 0; i < numChannels; ++i)
  133. carla_copyFloats (channels[i], other.channels[i], size);
  134. }
  135. }
  136. }
  137. /** Destructor.
  138. This will free any memory allocated by the buffer.
  139. */
  140. ~AudioSampleBuffer() noexcept {}
  141. #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS
  142. /** Move constructor */
  143. AudioSampleBuffer (AudioSampleBuffer&& other) noexcept
  144. : numChannels (other.numChannels),
  145. size (other.size),
  146. allocatedBytes (other.allocatedBytes),
  147. channels (other.channels),
  148. allocatedData (static_cast<HeapBlock<char>&&> (other.allocatedData)),
  149. isClear (other.isClear)
  150. {
  151. memcpy (preallocatedChannelSpace, other.preallocatedChannelSpace, sizeof (preallocatedChannelSpace));
  152. other.numChannels = 0;
  153. other.size = 0;
  154. other.allocatedBytes = 0;
  155. }
  156. /** Move assignment */
  157. AudioSampleBuffer& operator= (AudioSampleBuffer&& other) noexcept
  158. {
  159. numChannels = other.numChannels;
  160. size = other.size;
  161. allocatedBytes = other.allocatedBytes;
  162. channels = other.channels;
  163. allocatedData = static_cast<HeapBlock<char>&&> (other.allocatedData);
  164. isClear = other.isClear;
  165. memcpy (preallocatedChannelSpace, other.preallocatedChannelSpace, sizeof (preallocatedChannelSpace));
  166. other.numChannels = 0;
  167. other.size = 0;
  168. other.allocatedBytes = 0;
  169. return *this;
  170. }
  171. #endif
  172. //==============================================================================
  173. /** Returns the number of channels of audio data that this buffer contains.
  174. @see getSampleData
  175. */
  176. int getNumChannels() const noexcept { return numChannels; }
  177. /** Returns the number of samples allocated in each of the buffer's channels.
  178. @see getSampleData
  179. */
  180. int getNumSamples() const noexcept { return size; }
  181. /** Returns a pointer to an array of read-only samples in one of the buffer's channels.
  182. For speed, this doesn't check whether the channel number is out of range,
  183. so be careful when using it!
  184. If you need to write to the data, do NOT call this method and const_cast the
  185. result! Instead, you must call getWritePointer so that the buffer knows you're
  186. planning on modifying the data.
  187. */
  188. const float* getReadPointer (int channelNumber) const noexcept
  189. {
  190. CARLA_SAFE_ASSERT_RETURN (isPositiveAndBelow (channelNumber, numChannels), nullptr);
  191. return channels [channelNumber];
  192. }
  193. /** Returns a pointer to an array of read-only samples in one of the buffer's channels.
  194. For speed, this doesn't check whether the channel number or index are out of range,
  195. so be careful when using it!
  196. If you need to write to the data, do NOT call this method and const_cast the
  197. result! Instead, you must call getWritePointer so that the buffer knows you're
  198. planning on modifying the data.
  199. */
  200. const float* getReadPointer (int channelNumber, int sampleIndex) const noexcept
  201. {
  202. CARLA_SAFE_ASSERT_RETURN (isPositiveAndBelow (channelNumber, numChannels), nullptr);
  203. CARLA_SAFE_ASSERT_RETURN (isPositiveAndBelow (sampleIndex, size), nullptr);
  204. return channels [channelNumber] + sampleIndex;
  205. }
  206. /** Returns a writeable pointer to one of the buffer's channels.
  207. For speed, this doesn't check whether the channel number is out of range,
  208. so be careful when using it!
  209. Note that if you're not planning on writing to the data, you should always
  210. use getReadPointer instead.
  211. */
  212. float* getWritePointer (int channelNumber) noexcept
  213. {
  214. CARLA_SAFE_ASSERT_RETURN (isPositiveAndBelow (channelNumber, numChannels), nullptr);
  215. isClear = false;
  216. return channels [channelNumber];
  217. }
  218. /** Returns a writeable pointer to one of the buffer's channels.
  219. For speed, this doesn't check whether the channel number or index are out of range,
  220. so be careful when using it!
  221. Note that if you're not planning on writing to the data, you should
  222. use getReadPointer instead.
  223. */
  224. float* getWritePointer (int channelNumber, int sampleIndex) noexcept
  225. {
  226. CARLA_SAFE_ASSERT_RETURN (isPositiveAndBelow (channelNumber, numChannels), nullptr);
  227. CARLA_SAFE_ASSERT_RETURN (isPositiveAndBelow (sampleIndex, size), nullptr);
  228. isClear = false;
  229. return channels [channelNumber] + sampleIndex;
  230. }
  231. /** Returns an array of pointers to the channels in the buffer.
  232. Don't modify any of the pointers that are returned, and bear in mind that
  233. these will become invalid if the buffer is resized.
  234. */
  235. const float** getArrayOfReadPointers() const noexcept { return const_cast<const float**> (channels); }
  236. /** Returns an array of pointers to the channels in the buffer.
  237. Don't modify any of the pointers that are returned, and bear in mind that
  238. these will become invalid if the buffer is resized.
  239. */
  240. float** getArrayOfWritePointers() noexcept { isClear = false; return channels; }
  241. //==============================================================================
  242. /** Changes the buffer's size or number of channels.
  243. This can expand the buffer's length, and add or remove channels.
  244. */
  245. bool setSize (int newNumChannels, int newNumSamples) noexcept
  246. {
  247. CARLA_SAFE_ASSERT_RETURN (newNumChannels >= 0, false);
  248. CARLA_SAFE_ASSERT_RETURN (newNumSamples >= 0, false);
  249. if (newNumSamples != size || newNumChannels != numChannels)
  250. {
  251. const size_t allocatedSamplesPerChannel = ((size_t) newNumSamples + 3) & ~3u;
  252. const size_t channelListSize = ((sizeof (float*) * (size_t) (newNumChannels + 1)) + 15) & ~15u;
  253. const size_t newTotalBytes = ((size_t) newNumChannels * (size_t) allocatedSamplesPerChannel * sizeof (float))
  254. + channelListSize + 32;
  255. if (allocatedBytes >= newTotalBytes)
  256. {
  257. if (isClear)
  258. allocatedData.clear (newTotalBytes);
  259. }
  260. else
  261. {
  262. CARLA_SAFE_ASSERT_RETURN (allocatedData.allocate (newTotalBytes, isClear), false);
  263. allocatedBytes = newTotalBytes;
  264. channels = reinterpret_cast<float**> (allocatedData.getData());
  265. }
  266. float* chan = reinterpret_cast<float*> (allocatedData + channelListSize);
  267. for (int i = 0; i < newNumChannels; ++i)
  268. {
  269. channels[i] = chan;
  270. chan += allocatedSamplesPerChannel;
  271. }
  272. channels [newNumChannels] = 0;
  273. size = newNumSamples;
  274. numChannels = newNumChannels;
  275. }
  276. return true;
  277. }
  278. //==============================================================================
  279. /** Changes the buffer's size in a real-time safe manner.
  280. Returns true if the required memory is available.
  281. */
  282. bool setSizeRT (int newNumSamples) noexcept
  283. {
  284. CARLA_SAFE_ASSERT_RETURN (newNumSamples >= 0, false);
  285. CARLA_SAFE_ASSERT_RETURN (numChannels >= 0, false);
  286. if (newNumSamples != size)
  287. {
  288. const size_t allocatedSamplesPerChannel = ((size_t) newNumSamples + 3) & ~3u;
  289. const size_t channelListSize = ((sizeof (float*) * (size_t) (numChannels + 1)) + 15) & ~15u;
  290. const size_t newTotalBytes = ((size_t) numChannels * (size_t) allocatedSamplesPerChannel * sizeof (float))
  291. + channelListSize + 32;
  292. CARLA_SAFE_ASSERT_RETURN(allocatedBytes >= newTotalBytes, false);
  293. float* chan = reinterpret_cast<float*> (allocatedData + channelListSize);
  294. for (int i = 0; i < numChannels; ++i)
  295. {
  296. channels[i] = chan;
  297. chan += allocatedSamplesPerChannel;
  298. }
  299. size = newNumSamples;
  300. }
  301. return true;
  302. }
  303. /** Makes this buffer point to a pre-allocated set of channel data arrays.
  304. There's also a constructor that lets you specify arrays like this, but this
  305. lets you change the channels dynamically.
  306. Note that if the buffer is resized or its number of channels is changed, it
  307. will re-allocate memory internally and copy the existing data to this new area,
  308. so it will then stop directly addressing this memory.
  309. @param dataToReferTo a pre-allocated array containing pointers to the data
  310. for each channel that should be used by this buffer. The
  311. buffer will only refer to this memory, it won't try to delete
  312. it when the buffer is deleted or resized.
  313. @param newNumChannels the number of channels to use - this must correspond to the
  314. number of elements in the array passed in
  315. @param newNumSamples the number of samples to use - this must correspond to the
  316. size of the arrays passed in
  317. */
  318. bool setDataToReferTo (float** dataToReferTo,
  319. const int newNumChannels,
  320. const int newNumSamples) noexcept
  321. {
  322. CARLA_SAFE_ASSERT_RETURN (dataToReferTo != nullptr, false);
  323. CARLA_SAFE_ASSERT_RETURN (newNumChannels >= 0 && newNumSamples >= 0, false);
  324. if (allocatedBytes != 0)
  325. {
  326. allocatedBytes = 0;
  327. allocatedData.free();
  328. }
  329. numChannels = newNumChannels;
  330. size = newNumSamples;
  331. return allocateChannels (dataToReferTo, 0);
  332. }
  333. //==============================================================================
  334. /** Clears all the samples in all channels. */
  335. void clear() noexcept
  336. {
  337. if (! isClear)
  338. {
  339. for (int i = 0; i < numChannels; ++i)
  340. carla_zeroFloats (channels[i], size);
  341. isClear = true;
  342. }
  343. }
  344. /** Clears a specified region of all the channels.
  345. For speed, this doesn't check whether the channel and sample number
  346. are in-range, so be careful!
  347. */
  348. void clear (int startSample,
  349. int numSamples) noexcept
  350. {
  351. jassert (startSample >= 0 && startSample + numSamples <= size);
  352. if (! isClear)
  353. {
  354. if (startSample == 0 && numSamples == size)
  355. isClear = true;
  356. for (int i = 0; i < numChannels; ++i)
  357. carla_zeroFloats (channels[i] + startSample, numSamples);
  358. }
  359. }
  360. /** Clears a specified region of just one channel.
  361. For speed, this doesn't check whether the channel and sample number
  362. are in-range, so be careful!
  363. */
  364. void clear (int channel,
  365. int startSample,
  366. int numSamples) noexcept
  367. {
  368. jassert (isPositiveAndBelow (channel, numChannels));
  369. jassert (startSample >= 0 && startSample + numSamples <= size);
  370. if (! isClear)
  371. carla_zeroFloats (channels [channel] + startSample, numSamples);
  372. }
  373. /** Returns true if the buffer has been entirely cleared.
  374. Note that this does not actually measure the contents of the buffer - it simply
  375. returns a flag that is set when the buffer is cleared, and which is reset whenever
  376. functions like getWritePointer() are invoked. That means the method does not take
  377. any time, but it may return false negatives when in fact the buffer is still empty.
  378. */
  379. bool hasBeenCleared() const noexcept { return isClear; }
  380. //==============================================================================
  381. /** Adds samples from another buffer to this one.
  382. @param destChannel the channel within this buffer to add the samples to
  383. @param destStartSample the start sample within this buffer's channel
  384. @param source the source buffer to add from
  385. @param sourceChannel the channel within the source buffer to read from
  386. @param sourceStartSample the offset within the source buffer's channel to start reading samples from
  387. @param numSamples the number of samples to process
  388. @param gainToApplyToSource an optional gain to apply to the source samples before they are
  389. added to this buffer's samples
  390. @see copyFrom
  391. */
  392. void addFrom (int destChannel,
  393. int destStartSample,
  394. const AudioSampleBuffer& source,
  395. int sourceChannel,
  396. int sourceStartSample,
  397. int numSamples,
  398. float gainToApplyToSource = (float) 1) noexcept
  399. {
  400. jassert (&source != this || sourceChannel != destChannel);
  401. jassert (isPositiveAndBelow (destChannel, numChannels));
  402. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  403. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  404. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  405. if (gainToApplyToSource != 0.0f && numSamples > 0 && ! source.isClear)
  406. {
  407. float* const d = channels [destChannel] + destStartSample;
  408. const float* const s = source.channels [sourceChannel] + sourceStartSample;
  409. if (isClear)
  410. {
  411. isClear = false;
  412. if (gainToApplyToSource != 1.0f)
  413. carla_copyWithMultiply (d, s, gainToApplyToSource, numSamples);
  414. else
  415. carla_copyFloats (d, s, numSamples);
  416. }
  417. else
  418. {
  419. if (gainToApplyToSource != 1.0f)
  420. carla_addWithMultiply (d, s, gainToApplyToSource, numSamples);
  421. else
  422. carla_add (d, s, numSamples);
  423. }
  424. }
  425. }
  426. /** Adds samples from an array of floats to one of the channels.
  427. @param destChannel the channel within this buffer to add the samples to
  428. @param destStartSample the start sample within this buffer's channel
  429. @param source the source data to use
  430. @param numSamples the number of samples to process
  431. @param gainToApplyToSource an optional gain to apply to the source samples before they are
  432. added to this buffer's samples
  433. @see copyFrom
  434. */
  435. void addFrom (int destChannel,
  436. int destStartSample,
  437. const float* source,
  438. int numSamples,
  439. float gainToApplyToSource = (float) 1) noexcept
  440. {
  441. jassert (isPositiveAndBelow (destChannel, numChannels));
  442. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  443. jassert (source != nullptr);
  444. if (gainToApplyToSource != 0.0f && numSamples > 0)
  445. {
  446. float* const d = channels [destChannel] + destStartSample;
  447. if (isClear)
  448. {
  449. isClear = false;
  450. if (gainToApplyToSource != 1.0f)
  451. carla_copyWithMultiply (d, source, gainToApplyToSource, numSamples);
  452. else
  453. carla_copyFloats (d, source, numSamples);
  454. }
  455. else
  456. {
  457. if (gainToApplyToSource != 1.0f)
  458. carla_addWithMultiply (d, source, gainToApplyToSource, numSamples);
  459. else
  460. carla_add (d, source, numSamples);
  461. }
  462. }
  463. }
  464. /** Copies samples from another buffer to this one.
  465. @param destChannel the channel within this buffer to copy the samples to
  466. @param destStartSample the start sample within this buffer's channel
  467. @param source the source buffer to read from
  468. @param sourceChannel the channel within the source buffer to read from
  469. @param sourceStartSample the offset within the source buffer's channel to start reading samples from
  470. @param numSamples the number of samples to process
  471. @see addFrom
  472. */
  473. void copyFrom (int destChannel,
  474. int destStartSample,
  475. const AudioSampleBuffer& source,
  476. int sourceChannel,
  477. int sourceStartSample,
  478. int numSamples) noexcept
  479. {
  480. jassert (&source != this || sourceChannel != destChannel);
  481. jassert (isPositiveAndBelow (destChannel, numChannels));
  482. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  483. jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
  484. jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
  485. if (numSamples > 0)
  486. {
  487. if (source.isClear)
  488. {
  489. if (! isClear)
  490. carla_zeroFloats (channels [destChannel] + destStartSample, numSamples);
  491. }
  492. else
  493. {
  494. isClear = false;
  495. carla_copyFloats (channels [destChannel] + destStartSample,
  496. source.channels [sourceChannel] + sourceStartSample,
  497. numSamples);
  498. }
  499. }
  500. }
  501. /** Copies samples from an array of floats into one of the channels.
  502. @param destChannel the channel within this buffer to copy the samples to
  503. @param destStartSample the start sample within this buffer's channel
  504. @param source the source buffer to read from
  505. @param numSamples the number of samples to process
  506. @see addFrom
  507. */
  508. void copyFrom (int destChannel,
  509. int destStartSample,
  510. const float* source,
  511. int numSamples) noexcept
  512. {
  513. jassert (isPositiveAndBelow (destChannel, numChannels));
  514. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  515. jassert (source != nullptr);
  516. if (numSamples > 0)
  517. {
  518. isClear = false;
  519. carla_copyFloats (channels [destChannel] + destStartSample, source, numSamples);
  520. }
  521. }
  522. /** Copies samples from an array of floats into one of the channels, applying a gain to it.
  523. @param destChannel the channel within this buffer to copy the samples to
  524. @param destStartSample the start sample within this buffer's channel
  525. @param source the source buffer to read from
  526. @param numSamples the number of samples to process
  527. @param gain the gain to apply
  528. @see addFrom
  529. */
  530. void copyFrom (int destChannel,
  531. int destStartSample,
  532. const float* source,
  533. int numSamples,
  534. float gain) noexcept
  535. {
  536. jassert (isPositiveAndBelow (destChannel, numChannels));
  537. jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
  538. jassert (source != nullptr);
  539. if (numSamples > 0)
  540. {
  541. float* const d = channels [destChannel] + destStartSample;
  542. if (gain != 1.0f)
  543. {
  544. if (gain == 0)
  545. {
  546. if (! isClear)
  547. carla_zeroFloats (d, numSamples);
  548. }
  549. else
  550. {
  551. isClear = false;
  552. carla_copyWithMultiply (d, source, gain, numSamples);
  553. }
  554. }
  555. else
  556. {
  557. isClear = false;
  558. carla_copyFloats (d, source, numSamples);
  559. }
  560. }
  561. }
  562. private:
  563. //==============================================================================
  564. int numChannels, size;
  565. size_t allocatedBytes;
  566. float** channels;
  567. HeapBlock<char> allocatedData;
  568. float* preallocatedChannelSpace [32];
  569. bool isClear;
  570. bool allocateData()
  571. {
  572. const size_t channelListSize = sizeof (float*) * (size_t) (numChannels + 1);
  573. const size_t nextAllocatedBytes = (size_t) numChannels * (size_t) size * sizeof (float) + channelListSize + 32;
  574. CARLA_SAFE_ASSERT_RETURN (allocatedData.malloc (nextAllocatedBytes), false);
  575. allocatedBytes = nextAllocatedBytes;
  576. channels = reinterpret_cast<float**> (allocatedData.getData());
  577. float* chan = (float*) (allocatedData + channelListSize);
  578. for (int i = 0; i < numChannels; ++i)
  579. {
  580. channels[i] = chan;
  581. chan += size;
  582. }
  583. channels [numChannels] = nullptr;
  584. isClear = false;
  585. return true;
  586. }
  587. bool allocateChannels (float* const* const dataToReferTo, int offset)
  588. {
  589. CARLA_SAFE_ASSERT_RETURN (offset >= 0, false);
  590. // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
  591. if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
  592. {
  593. channels = static_cast<float**> (preallocatedChannelSpace);
  594. }
  595. else
  596. {
  597. CARLA_SAFE_ASSERT_RETURN( allocatedData.malloc ((size_t) numChannels + 1, sizeof (float*)), false);
  598. channels = reinterpret_cast<float**> (allocatedData.getData());
  599. }
  600. for (int i = 0; i < numChannels; ++i)
  601. {
  602. // you have to pass in the same number of valid pointers as numChannels
  603. CARLA_SAFE_ASSERT_CONTINUE (dataToReferTo[i] != nullptr);
  604. channels[i] = dataToReferTo[i] + offset;
  605. }
  606. channels [numChannels] = nullptr;
  607. isClear = false;
  608. return true;
  609. }
  610. };
  611. }
  612. #endif // WATER_AUDIOSAMPLEBUFFER_H_INCLUDED