| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2022 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - MemoryAudioSource::MemoryAudioSource (AudioBuffer<float>& bufferToUse, bool copyMemory, bool shouldLoop)
 -     : isCurrentlyLooping (shouldLoop)
 - {
 -     if (copyMemory)
 -         buffer.makeCopyOf (bufferToUse);
 -     else
 -         buffer.setDataToReferTo (bufferToUse.getArrayOfWritePointers(),
 -                                  bufferToUse.getNumChannels(),
 -                                  bufferToUse.getNumSamples());
 - }
 - 
 - //==============================================================================
 - void MemoryAudioSource::prepareToPlay (int /*samplesPerBlockExpected*/, double /*sampleRate*/)
 - {
 -     position = 0;
 - }
 - 
 - void MemoryAudioSource::releaseResources()   {}
 - 
 - void MemoryAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
 - {
 -     if (buffer.getNumSamples() == 0)
 -     {
 -         bufferToFill.clearActiveBufferRegion();
 -         return;
 -     }
 - 
 -     auto& dst = *bufferToFill.buffer;
 -     auto channels = jmin (dst.getNumChannels(), buffer.getNumChannels());
 -     int max = 0, pos = 0;
 -     auto n = buffer.getNumSamples();
 -     auto m = bufferToFill.numSamples;
 - 
 -     int i = position;
 -     for (; (i < n || isCurrentlyLooping) && (pos < m); i += max)
 -     {
 -         max = jmin (m - pos, n - (i % n));
 - 
 -         int ch = 0;
 -         for (; ch < channels; ++ch)
 -             dst.copyFrom (ch, bufferToFill.startSample + pos, buffer, ch, i % n, max);
 - 
 -         for (; ch < dst.getNumChannels(); ++ch)
 -             dst.clear (ch, bufferToFill.startSample + pos, max);
 - 
 -         pos += max;
 -     }
 - 
 -     if (pos < m)
 -         dst.clear (bufferToFill.startSample + pos, m - pos);
 - 
 -     position = i;
 - }
 - 
 - //==============================================================================
 - void MemoryAudioSource::setNextReadPosition (int64 newPosition)
 - {
 -     position = (int) newPosition;
 - }
 - 
 - int64 MemoryAudioSource::getNextReadPosition() const
 - {
 -     return position;
 - }
 - 
 - int64 MemoryAudioSource::getTotalLength() const
 - {
 -     return buffer.getNumSamples();
 - }
 - 
 - //==============================================================================
 - bool MemoryAudioSource::isLooping() const
 - {
 -     return isCurrentlyLooping;
 - }
 - 
 - void MemoryAudioSource::setLooping (bool shouldLoop)
 - {
 -     isCurrentlyLooping = shouldLoop;
 - }
 - 
 - //==============================================================================
 - //==============================================================================
 - #if JUCE_UNIT_TESTS
 - 
 - static bool operator== (const AudioBuffer<float>& a, const AudioBuffer<float>& b)
 - {
 -     if (a.getNumChannels() != b.getNumChannels())
 -         return false;
 - 
 -     for (int channel = 0; channel < a.getNumChannels(); ++channel)
 -     {
 -         auto* aPtr = a.getReadPointer (channel);
 -         auto* bPtr = b.getReadPointer (channel);
 - 
 -         if (std::vector<float> (aPtr, aPtr + a.getNumSamples())
 -             != std::vector<float> (bPtr, bPtr + b.getNumSamples()))
 -         {
 -             return false;
 -         }
 -     }
 - 
 -     return true;
 - }
 - 
 - struct MemoryAudioSourceTests  : public UnitTest
 - {
 -     MemoryAudioSourceTests()  : UnitTest ("MemoryAudioSource", UnitTestCategories::audio)  {}
 - 
 -     void runTest() override
 -     {
 -         constexpr int blockSize = 512;
 -         AudioBuffer<float> bufferToFill { 2, blockSize };
 -         AudioSourceChannelInfo channelInfo { bufferToFill };
 - 
 -         beginTest ("A zero-length buffer produces silence, whether or not looping is enabled");
 -         {
 -             for (const bool enableLooping : { false, true })
 -             {
 -                 AudioBuffer<float> buffer;
 -                 MemoryAudioSource source { buffer, true, false };
 -                 source.setLooping (enableLooping);
 -                 source.prepareToPlay (blockSize, 44100.0);
 - 
 -                 for (int i = 0; i < 2; ++i)
 -                 {
 -                     play (source, channelInfo);
 -                     expect (isSilent (bufferToFill));
 -                 }
 -             }
 -         }
 - 
 -         beginTest ("A short buffer without looping is played once and followed by silence");
 -         {
 -             auto buffer = getShortBuffer();
 -             MemoryAudioSource source { buffer, true, false };
 -             source.setLooping (false);
 -             source.prepareToPlay (blockSize, 44100.0);
 - 
 -             play (source, channelInfo);
 - 
 -             auto copy = buffer;
 -             copy.setSize (buffer.getNumChannels(), blockSize, true, true, false);
 - 
 -             expect (bufferToFill == copy);
 - 
 -             play (source, channelInfo);
 - 
 -             expect (isSilent (bufferToFill));
 -         }
 - 
 -         beginTest ("A short buffer with looping is played multiple times");
 -         {
 -             auto buffer = getShortBuffer();
 -             MemoryAudioSource source { buffer, true, false };
 -             source.setLooping (true);
 -             source.prepareToPlay (blockSize, 44100.0);
 - 
 -             play (source, channelInfo);
 - 
 -             for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
 -                 expect (bufferToFill.getSample (0, sample + buffer.getNumSamples()) == buffer.getSample (0, sample));
 - 
 -             expect (! isSilent (bufferToFill));
 -         }
 - 
 -         beginTest ("A long buffer without looping is played once");
 -         {
 -             auto buffer = getLongBuffer();
 -             MemoryAudioSource source { buffer, true, false };
 -             source.setLooping (false);
 -             source.prepareToPlay (blockSize, 44100.0);
 - 
 -             play (source, channelInfo);
 - 
 -             auto copy = buffer;
 -             copy.setSize (buffer.getNumChannels(), blockSize, true, true, false);
 - 
 -             expect (bufferToFill == copy);
 - 
 -             for (int i = 0; i < 10; ++i)
 -                 play (source, channelInfo);
 - 
 -             expect (isSilent (bufferToFill));
 -         }
 - 
 -         beginTest ("A long buffer with looping is played multiple times");
 -         {
 -             auto buffer = getLongBuffer();
 -             MemoryAudioSource source { buffer, true, false };
 -             source.setLooping (true);
 -             source.prepareToPlay (blockSize, 44100.0);
 - 
 -             for (int i = 0; i < 100; ++i)
 -             {
 -                 play (source, channelInfo);
 -                 expect (bufferToFill.getSample (0, 0) == buffer.getSample (0, (i * blockSize) % buffer.getNumSamples()));
 -             }
 -         }
 -     }
 - 
 -     static AudioBuffer<float> getTestBuffer (int length)
 -     {
 -         AudioBuffer<float> buffer { 2, length };
 - 
 -         for (int channel = 0; channel < buffer.getNumChannels(); ++channel)
 -             for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
 -                 buffer.setSample (channel, sample, jmap ((float) sample, 0.0f, (float) length, -1.0f, 1.0f));
 - 
 -         return buffer;
 -     }
 - 
 -     static AudioBuffer<float> getShortBuffer()  { return getTestBuffer (5); }
 -     static AudioBuffer<float> getLongBuffer()   { return getTestBuffer (1000); }
 - 
 -     static void play (MemoryAudioSource& source, AudioSourceChannelInfo& info)
 -     {
 -         info.clearActiveBufferRegion();
 -         source.getNextAudioBlock (info);
 -     }
 - 
 -     static bool isSilent (const AudioBuffer<float>& b)
 -     {
 -         for (int channel = 0; channel < b.getNumChannels(); ++channel)
 -             if (b.findMinMax (channel, 0, b.getNumSamples()) != Range<float>{})
 -                 return false;
 - 
 -         return true;
 -     }
 - };
 - 
 - static MemoryAudioSourceTests memoryAudioSourceTests;
 - 
 - #endif
 - 
 - } // namespace juce
 
 
  |