@@ -0,0 +1,281 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__
#define __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__

#include "juce_MidiMessage.h"


//==============================================================================
/**
A sequence of timestamped midi messages.
This allows the sequence to be manipulated, and also to be read from and
written to a standard midi file.
@see MidiMessage, MidiFile
*/
class JUCE_API MidiMessageSequence
{
public:
//==============================================================================
/** Creates an empty midi sequence object. */
MidiMessageSequence();

/** Creates a copy of another sequence. */
MidiMessageSequence (const MidiMessageSequence& other);

/** Replaces this sequence with another one. */
MidiMessageSequence& operator= (const MidiMessageSequence& other);

/** Destructor. */
~MidiMessageSequence();

//==============================================================================
/** Structure used to hold midi events in the sequence.
These structures act as 'handles' on the events as they are moved about in
the list, and make it quick to find the matching note-offs for note-on events.
@see MidiMessageSequence::getEventPointer
*/
class MidiEventHolder
{
public:
//==============================================================================
/** Destructor. */
~MidiEventHolder();

/** The message itself, whose timestamp is used to specify the event's time.
*/
MidiMessage message;

/** The matching note-off event (if this is a note-on event).
If this isn't a note-on, this pointer will be null.
Use the MidiMessageSequence::updateMatchedPairs() method to keep these
note-offs up-to-date after events have been moved around in the sequence
or deleted.
*/
MidiEventHolder* noteOffObject;

private:
//==============================================================================
friend class MidiMessageSequence;
MidiEventHolder (const MidiMessage& message);
JUCE_LEAK_DETECTOR (MidiEventHolder)
};

//==============================================================================
/** Clears the sequence. */
void clear();

/** Returns the number of events in the sequence. */
int getNumEvents() const;

/** Returns a pointer to one of the events. */
MidiEventHolder* getEventPointer (int index) const;

/** Returns the time of the note-up that matches the note-on at this index.
If the event at this index isn't a note-on, it'll just return 0.
@see MidiMessageSequence::MidiEventHolder::noteOffObject
*/
double getTimeOfMatchingKeyUp (int index) const;

/** Returns the index of the note-up that matches the note-on at this index.
If the event at this index isn't a note-on, it'll just return -1.
@see MidiMessageSequence::MidiEventHolder::noteOffObject
*/
int getIndexOfMatchingKeyUp (int index) const;

/** Returns the index of an event. */
int getIndexOf (MidiEventHolder* event) const;

/** Returns the index of the first event on or after the given timestamp.
If the time is beyond the end of the sequence, this will return the
number of events.
*/
int getNextIndexAtTime (double timeStamp) const;

//==============================================================================
/** Returns the timestamp of the first event in the sequence.
@see getEndTime
*/
double getStartTime() const;

/** Returns the timestamp of the last event in the sequence.
@see getStartTime
*/
double getEndTime() const;

/** Returns the timestamp of the event at a given index.
If the index is out-of-range, this will return 0.0
*/
double getEventTime (int index) const;

//==============================================================================
/** Inserts a midi message into the sequence.
The index at which the new message gets inserted will depend on its timestamp,
because the sequence is kept sorted.
Remember to call updateMatchedPairs() after adding note-on events.
@param newMessage the new message to add (an internal copy will be made)
@param timeAdjustment an optional value to add to the timestamp of the message
that will be inserted
@see updateMatchedPairs
*/
MidiEventHolder* addEvent (const MidiMessage& newMessage,
double timeAdjustment = 0);

/** Deletes one of the events in the sequence.
Remember to call updateMatchedPairs() after removing events.
@param index the index of the event to delete
@param deleteMatchingNoteUp whether to also remove the matching note-off
if the event you're removing is a note-on
*/
void deleteEvent (int index, bool deleteMatchingNoteUp);

/** Merges another sequence into this one.
Remember to call updateMatchedPairs() after using this method.
@param other the sequence to add from
@param timeAdjustmentDelta an amount to add to the timestamps of the midi events
as they are read from the other sequence
@param firstAllowableDestTime events will not be added if their time is earlier
than this time. (This is after their time has been adjusted
by the timeAdjustmentDelta)
@param endOfAllowableDestTimes events will not be added if their time is equal to
or greater than this time. (This is after their time has
been adjusted by the timeAdjustmentDelta)
*/
void addSequence (const MidiMessageSequence& other,
double timeAdjustmentDelta,
double firstAllowableDestTime,
double endOfAllowableDestTimes);

//==============================================================================
/** Makes sure all the note-on and note-off pairs are up-to-date.
Call this after moving messages about or deleting/adding messages, and it
will scan the list and make sure all the note-offs in the MidiEventHolder
structures are pointing at the correct ones.
*/
void updateMatchedPairs();

/** Forces a sort of the sequence.
You may need to call this if you've manually modified the timestamps of some
events such that the overall order now needs updating.
*/
void sort();

//==============================================================================
/** Copies all the messages for a particular midi channel to another sequence.
@param channelNumberToExtract the midi channel to look for, in the range 1 to 16
@param destSequence the sequence that the chosen events should be copied to
@param alsoIncludeMetaEvents if true, any meta-events (which don't apply to a specific
channel) will also be copied across.
@see extractSysExMessages
*/
void extractMidiChannelMessages (int channelNumberToExtract,
MidiMessageSequence& destSequence,
bool alsoIncludeMetaEvents) const;

/** Copies all midi sys-ex messages to another sequence.
@param destSequence this is the sequence to which any sys-exes in this sequence
will be added
@see extractMidiChannelMessages
*/
void extractSysExMessages (MidiMessageSequence& destSequence) const;

/** Removes any messages in this sequence that have a specific midi channel.
@param channelNumberToRemove the midi channel to look for, in the range 1 to 16
*/
void deleteMidiChannelMessages (int channelNumberToRemove);

/** Removes any sys-ex messages from this sequence.
*/
void deleteSysExMessages();

/** Adds an offset to the timestamps of all events in the sequence.
@param deltaTime the amount to add to each timestamp.
*/
void addTimeToMessages (double deltaTime);

//==============================================================================
/** Scans through the sequence to determine the state of any midi controllers at
a given time.
This will create a sequence of midi controller changes that can be
used to set all midi controllers to the state they would be in at the
specified time within this sequence.
As well as controllers, it will also recreate the midi program number
and pitch bend position.
@param channelNumber the midi channel to look for, in the range 1 to 16. Controllers
for other channels will be ignored.
@param time the time at which you want to find out the state - there are
no explicit units for this time measurement, it's the same units
as used for the timestamps of the messages
@param resultMessages an array to which midi controller-change messages will be added. This
will be the minimum number of controller changes to recreate the
state at the required time.
*/
void createControllerUpdatesForTime (int channelNumber, double time,
OwnedArray<MidiMessage>& resultMessages);

//==============================================================================
/** Swaps this sequence with another one. */
void swapWith (MidiMessageSequence& other) noexcept;

private:
//==============================================================================
friend class MidiFile;
OwnedArray <MidiEventHolder> list;

JUCE_LEAK_DETECTOR (MidiMessageSequence)
};


#endif // __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__
@@ -0,0 +1,184 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_AUDIOSOURCE_JUCEHEADER__
#define __JUCE_AUDIOSOURCE_JUCEHEADER__

#include "../buffers/juce_AudioSampleBuffer.h"


//==============================================================================
/**
Used by AudioSource::getNextAudioBlock().
*/
struct JUCE_API AudioSourceChannelInfo
{
/** Creates an uninitialised AudioSourceChannelInfo. */
AudioSourceChannelInfo() noexcept
{
}

/** Creates an AudioSourceChannelInfo. */
AudioSourceChannelInfo (AudioSampleBuffer* bufferToUse,
int startSampleOffset, int numSamplesToUse) noexcept
: buffer (bufferToUse),
startSample (startSampleOffset),
numSamples (numSamplesToUse)
{
}

/** Creates an AudioSourceChannelInfo that uses the whole of a buffer.
Note that the buffer provided must not be deleted while the
AudioSourceChannelInfo is still using it.
*/
explicit AudioSourceChannelInfo (AudioSampleBuffer& bufferToUse) noexcept
: buffer (&bufferToUse),
startSample (0),
numSamples (bufferToUse.getNumSamples())
{
}

/** The destination buffer to fill with audio data.
When the AudioSource::getNextAudioBlock() method is called, the active section
of this buffer should be filled with whatever output the source produces.
Only the samples specified by the startSample and numSamples members of this structure
should be affected by the call.
The contents of the buffer when it is passed to the the AudioSource::getNextAudioBlock()
method can be treated as the input if the source is performing some kind of filter operation,
but should be cleared if this is not the case - the clearActiveBufferRegion() is
a handy way of doing this.
The number of channels in the buffer could be anything, so the AudioSource
must cope with this in whatever way is appropriate for its function.
*/
AudioSampleBuffer* buffer;

/** The first sample in the buffer from which the callback is expected
to write data. */
int startSample;

/** The number of samples in the buffer which the callback is expected to
fill with data. */
int numSamples;

/** Convenient method to clear the buffer if the source is not producing any data. */
void clearActiveBufferRegion() const
{
if (buffer != nullptr)
buffer->clear (startSample, numSamples);
}
};


//==============================================================================
/**
Base class for objects that can produce a continuous stream of audio.
An AudioSource has two states: 'prepared' and 'unprepared'.
When a source needs to be played, it is first put into a 'prepared' state by a call to
prepareToPlay(), and then repeated calls will be made to its getNextAudioBlock() method to
process the audio data.
Once playback has finished, the releaseResources() method is called to put the stream
back into an 'unprepared' state.
@see AudioFormatReaderSource, ResamplingAudioSource
*/
class JUCE_API AudioSource
{
protected:
//==============================================================================
/** Creates an AudioSource. */
AudioSource() noexcept {}

public:
/** Destructor. */
virtual ~AudioSource() {}

//==============================================================================
/** Tells the source to prepare for playing.
An AudioSource has two states: prepared and unprepared.
The prepareToPlay() method is guaranteed to be called at least once on an 'unpreprared'
source to put it into a 'prepared' state before any calls will be made to getNextAudioBlock().
This callback allows the source to initialise any resources it might need when playing.
Once playback has finished, the releaseResources() method is called to put the stream
back into an 'unprepared' state.
Note that this method could be called more than once in succession without
a matching call to releaseResources(), so make sure your code is robust and
can handle that kind of situation.
@param samplesPerBlockExpected the number of samples that the source
will be expected to supply each time its
getNextAudioBlock() method is called. This
number may vary slightly, because it will be dependent
on audio hardware callbacks, and these aren't
guaranteed to always use a constant block size, so
the source should be able to cope with small variations.
@param sampleRate the sample rate that the output will be used at - this
is needed by sources such as tone generators.
@see releaseResources, getNextAudioBlock
*/
virtual void prepareToPlay (int samplesPerBlockExpected,
double sampleRate) = 0;

/** Allows the source to release anything it no longer needs after playback has stopped.
This will be called when the source is no longer going to have its getNextAudioBlock()
method called, so it should release any spare memory, etc. that it might have
allocated during the prepareToPlay() call.
Note that there's no guarantee that prepareToPlay() will actually have been called before
releaseResources(), and it may be called more than once in succession, so make sure your
code is robust and doesn't make any assumptions about when it will be called.
@see prepareToPlay, getNextAudioBlock
*/
virtual void releaseResources() = 0;

/** Called repeatedly to fetch subsequent blocks of audio data.
After calling the prepareToPlay() method, this callback will be made each
time the audio playback hardware (or whatever other destination the audio
data is going to) needs another block of data.
It will generally be called on a high-priority system thread, or possibly even
an interrupt, so be careful not to do too much work here, as that will cause
audio glitches!
@see AudioSourceChannelInfo, prepareToPlay, releaseResources
*/
virtual void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) = 0;
};


#endif // __JUCE_AUDIOSOURCE_JUCEHEADER__
@@ -0,0 +1,262 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

BufferingAudioSource::BufferingAudioSource (PositionableAudioSource* source_,
TimeSliceThread& backgroundThread_,
const bool deleteSourceWhenDeleted,
const int numberOfSamplesToBuffer_,
const int numberOfChannels_)
: source (source_, deleteSourceWhenDeleted),
backgroundThread (backgroundThread_),
numberOfSamplesToBuffer (jmax (1024, numberOfSamplesToBuffer_)),
numberOfChannels (numberOfChannels_),
buffer (numberOfChannels_, 0),
bufferValidStart (0),
bufferValidEnd (0),
nextPlayPos (0),
wasSourceLooping (false),
isPrepared (false)
{
jassert (source_ != nullptr);

jassert (numberOfSamplesToBuffer_ > 1024); // not much point using this class if you're
// not using a larger buffer..
}

BufferingAudioSource::~BufferingAudioSource()
{
releaseResources();
}

//==============================================================================
void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate_)
{
const int bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer);

if (sampleRate_ != sampleRate
|| bufferSizeNeeded != buffer.getNumSamples()
|| ! isPrepared)
{
backgroundThread.removeTimeSliceClient (this);

isPrepared = true;
sampleRate = sampleRate_;

source->prepareToPlay (samplesPerBlockExpected, sampleRate_);

buffer.setSize (numberOfChannels, bufferSizeNeeded);
buffer.clear();

bufferValidStart = 0;
bufferValidEnd = 0;

backgroundThread.addTimeSliceClient (this);

while (bufferValidEnd - bufferValidStart < jmin (((int) sampleRate_) / 4,
buffer.getNumSamples() / 2))
{
backgroundThread.moveToFrontOfQueue (this);
Thread::sleep (5);
}
}
}

void BufferingAudioSource::releaseResources()
{
isPrepared = false;
backgroundThread.removeTimeSliceClient (this);

buffer.setSize (numberOfChannels, 0);
source->releaseResources();
}

void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
const ScopedLock sl (bufferStartPosLock);

const int validStart = (int) (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos);
const int validEnd = (int) (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos);

if (validStart == validEnd)
{
// total cache miss
info.clearActiveBufferRegion();
}
else
{
if (validStart > 0)
info.buffer->clear (info.startSample, validStart); // partial cache miss at start

if (validEnd < info.numSamples)
info.buffer->clear (info.startSample + validEnd,
info.numSamples - validEnd); // partial cache miss at end

if (validStart < validEnd)
{
for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;)
{
jassert (buffer.getNumSamples() > 0);
const int startBufferIndex = (int) ((validStart + nextPlayPos) % buffer.getNumSamples());
const int endBufferIndex = (int) ((validEnd + nextPlayPos) % buffer.getNumSamples());

if (startBufferIndex < endBufferIndex)
{
info.buffer->copyFrom (chan, info.startSample + validStart,
buffer,
chan, startBufferIndex,
validEnd - validStart);
}
else
{
const int initialSize = buffer.getNumSamples() - startBufferIndex;

info.buffer->copyFrom (chan, info.startSample + validStart,
buffer,
chan, startBufferIndex,
initialSize);

info.buffer->copyFrom (chan, info.startSample + validStart + initialSize,
buffer,
chan, 0,
(validEnd - validStart) - initialSize);
}
}
}

nextPlayPos += info.numSamples;
}
}

int64 BufferingAudioSource::getNextReadPosition() const
{
jassert (source->getTotalLength() > 0);
return (source->isLooping() && nextPlayPos > 0)
? nextPlayPos % source->getTotalLength()
: nextPlayPos;
}

void BufferingAudioSource::setNextReadPosition (int64 newPosition)
{
const ScopedLock sl (bufferStartPosLock);

nextPlayPos = newPosition;
backgroundThread.moveToFrontOfQueue (this);
}

bool BufferingAudioSource::readNextBufferChunk()
{
int64 newBVS, newBVE, sectionToReadStart, sectionToReadEnd;

{
const ScopedLock sl (bufferStartPosLock);

if (wasSourceLooping != isLooping())
{
wasSourceLooping = isLooping();
bufferValidStart = 0;
bufferValidEnd = 0;
}

newBVS = jmax ((int64) 0, nextPlayPos);
newBVE = newBVS + buffer.getNumSamples() - 4;
sectionToReadStart = 0;
sectionToReadEnd = 0;

const int maxChunkSize = 2048;

if (newBVS < bufferValidStart || newBVS >= bufferValidEnd)
{
newBVE = jmin (newBVE, newBVS + maxChunkSize);

sectionToReadStart = newBVS;
sectionToReadEnd = newBVE;

bufferValidStart = 0;
bufferValidEnd = 0;
}
else if (std::abs ((int) (newBVS - bufferValidStart)) > 512
|| std::abs ((int) (newBVE - bufferValidEnd)) > 512)
{
newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize);

sectionToReadStart = bufferValidEnd;
sectionToReadEnd = newBVE;

bufferValidStart = newBVS;
bufferValidEnd = jmin (bufferValidEnd, newBVE);
}
}

if (sectionToReadStart != sectionToReadEnd)
{
jassert (buffer.getNumSamples() > 0);
const int bufferIndexStart = (int) (sectionToReadStart % buffer.getNumSamples());
const int bufferIndexEnd = (int) (sectionToReadEnd % buffer.getNumSamples());

if (bufferIndexStart < bufferIndexEnd)
{
readBufferSection (sectionToReadStart,
(int) (sectionToReadEnd - sectionToReadStart),
bufferIndexStart);
}
else
{
const int initialSize = buffer.getNumSamples() - bufferIndexStart;

readBufferSection (sectionToReadStart,
initialSize,
bufferIndexStart);

readBufferSection (sectionToReadStart + initialSize,
(int) (sectionToReadEnd - sectionToReadStart) - initialSize,
0);
}

const ScopedLock sl2 (bufferStartPosLock);

bufferValidStart = newBVS;
bufferValidEnd = newBVE;

return true;
}
else
{
return false;
}
}

void BufferingAudioSource::readBufferSection (const int64 start, const int length, const int bufferOffset)
{
if (source->getNextReadPosition() != start)
source->setNextReadPosition (start);

AudioSourceChannelInfo info (&buffer, bufferOffset, length);
source->getNextAudioBlock (info);
}

int BufferingAudioSource::useTimeSlice()
{
return readNextBufferChunk() ? 1 : 100;
}
@@ -0,0 +1,114 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__
#define __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__

#include "juce_PositionableAudioSource.h"


//==============================================================================
/**
An AudioSource which takes another source as input, and buffers it using a thread.
Create this as a wrapper around another thread, and it will read-ahead with
a background thread to smooth out playback. You can either create one of these
directly, or use it indirectly using an AudioTransportSource.
@see PositionableAudioSource, AudioTransportSource
*/
class JUCE_API BufferingAudioSource : public PositionableAudioSource,
private TimeSliceClient
{
public:
//==============================================================================
/** Creates a BufferingAudioSource.
@param source the input source to read from
@param backgroundThread a background thread that will be used for the
background read-ahead. This object must not be deleted
until after any BufferedAudioSources that are using it
have been deleted!
@param deleteSourceWhenDeleted if true, then the input source object will
be deleted when this object is deleted
@param numberOfSamplesToBuffer the size of buffer to use for reading ahead
@param numberOfChannels the number of channels that will be played
*/
BufferingAudioSource (PositionableAudioSource* source,
TimeSliceThread& backgroundThread,
bool deleteSourceWhenDeleted,
int numberOfSamplesToBuffer,
int numberOfChannels = 2);

/** Destructor.
The input source may be deleted depending on whether the deleteSourceWhenDeleted
flag was set in the constructor.
*/
~BufferingAudioSource();

//==============================================================================
/** Implementation of the AudioSource method. */
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);

/** Implementation of the AudioSource method. */
void releaseResources();

/** Implementation of the AudioSource method. */
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);

//==============================================================================
/** Implements the PositionableAudioSource method. */
void setNextReadPosition (int64 newPosition);

/** Implements the PositionableAudioSource method. */
int64 getNextReadPosition() const;

/** Implements the PositionableAudioSource method. */
int64 getTotalLength() const { return source->getTotalLength(); }

/** Implements the PositionableAudioSource method. */
bool isLooping() const { return source->isLooping(); }

private:
//==============================================================================
OptionalScopedPointer<PositionableAudioSource> source;
TimeSliceThread& backgroundThread;
int numberOfSamplesToBuffer, numberOfChannels;
AudioSampleBuffer buffer;
CriticalSection bufferStartPosLock;
int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos;
double volatile sampleRate;
bool wasSourceLooping, isPrepared;

bool readNextBufferChunk();
void readBufferSection (int64 start, int length, int bufferOffset);
int useTimeSlice();

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BufferingAudioSource)
};


#endif // __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__
@@ -0,0 +1,186 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

ChannelRemappingAudioSource::ChannelRemappingAudioSource (AudioSource* const source_,
const bool deleteSourceWhenDeleted)
: source (source_, deleteSourceWhenDeleted),
requiredNumberOfChannels (2),
buffer (2, 16)
{
remappedInfo.buffer = &buffer;
remappedInfo.startSample = 0;
}

ChannelRemappingAudioSource::~ChannelRemappingAudioSource() {}

//==============================================================================
void ChannelRemappingAudioSource::setNumberOfChannelsToProduce (const int requiredNumberOfChannels_)
{
const ScopedLock sl (lock);
requiredNumberOfChannels = requiredNumberOfChannels_;
}

void ChannelRemappingAudioSource::clearAllMappings()
{
const ScopedLock sl (lock);

remappedInputs.clear();
remappedOutputs.clear();
}

void ChannelRemappingAudioSource::setInputChannelMapping (const int destIndex, const int sourceIndex)
{
const ScopedLock sl (lock);

while (remappedInputs.size() < destIndex)
remappedInputs.add (-1);

remappedInputs.set (destIndex, sourceIndex);
}

void ChannelRemappingAudioSource::setOutputChannelMapping (const int sourceIndex, const int destIndex)
{
const ScopedLock sl (lock);

while (remappedOutputs.size() < sourceIndex)
remappedOutputs.add (-1);

remappedOutputs.set (sourceIndex, destIndex);
}

int ChannelRemappingAudioSource::getRemappedInputChannel (const int inputChannelIndex) const
{
const ScopedLock sl (lock);

if (inputChannelIndex >= 0 && inputChannelIndex < remappedInputs.size())
return remappedInputs.getUnchecked (inputChannelIndex);

return -1;
}

int ChannelRemappingAudioSource::getRemappedOutputChannel (const int outputChannelIndex) const
{
const ScopedLock sl (lock);

if (outputChannelIndex >= 0 && outputChannelIndex < remappedOutputs.size())
return remappedOutputs .getUnchecked (outputChannelIndex);

return -1;
}

//==============================================================================
void ChannelRemappingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
source->prepareToPlay (samplesPerBlockExpected, sampleRate);
}

void ChannelRemappingAudioSource::releaseResources()
{
source->releaseResources();
}

void ChannelRemappingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
const ScopedLock sl (lock);

buffer.setSize (requiredNumberOfChannels, bufferToFill.numSamples, false, false, true);

const int numChans = bufferToFill.buffer->getNumChannels();

for (int i = 0; i < buffer.getNumChannels(); ++i)
{
const int remappedChan = getRemappedInputChannel (i);

if (remappedChan >= 0 && remappedChan < numChans)
{
buffer.copyFrom (i, 0, *bufferToFill.buffer,
remappedChan,
bufferToFill.startSample,
bufferToFill.numSamples);
}
else
{
buffer.clear (i, 0, bufferToFill.numSamples);
}
}

remappedInfo.numSamples = bufferToFill.numSamples;

source->getNextAudioBlock (remappedInfo);

bufferToFill.clearActiveBufferRegion();

for (int i = 0; i < requiredNumberOfChannels; ++i)
{
const int remappedChan = getRemappedOutputChannel (i);

if (remappedChan >= 0 && remappedChan < numChans)
{
bufferToFill.buffer->addFrom (remappedChan, bufferToFill.startSample,
buffer, i, 0, bufferToFill.numSamples);

}
}
}

//==============================================================================
XmlElement* ChannelRemappingAudioSource::createXml() const
{
XmlElement* e = new XmlElement ("MAPPINGS");
String ins, outs;

const ScopedLock sl (lock);

for (int i = 0; i < remappedInputs.size(); ++i)
ins << remappedInputs.getUnchecked(i) << ' ';

for (int i = 0; i < remappedOutputs.size(); ++i)
outs << remappedOutputs.getUnchecked(i) << ' ';

e->setAttribute ("inputs", ins.trimEnd());
e->setAttribute ("outputs", outs.trimEnd());

return e;
}

void ChannelRemappingAudioSource::restoreFromXml (const XmlElement& e)
{
if (e.hasTagName ("MAPPINGS"))
{
const ScopedLock sl (lock);

clearAllMappings();

StringArray ins, outs;
ins.addTokens (e.getStringAttribute ("inputs"), false);
outs.addTokens (e.getStringAttribute ("outputs"), false);

for (int i = 0; i < ins.size(); ++i)
remappedInputs.add (ins[i].getIntValue());

for (int i = 0; i < outs.size(); ++i)
remappedOutputs.add (outs[i].getIntValue());
}
}
@@ -0,0 +1,149 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__
#define __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__

#include "juce_AudioSource.h"


//==============================================================================
/**
An AudioSource that takes the audio from another source, and re-maps its
input and output channels to a different arrangement.
You can use this to increase or decrease the number of channels that an
audio source uses, or to re-order those channels.
Call the reset() method before using it to set up a default mapping, and then
the setInputChannelMapping() and setOutputChannelMapping() methods to
create an appropriate mapping, otherwise no channels will be connected and
it'll produce silence.
@see AudioSource
*/
class ChannelRemappingAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a remapping source that will pass on audio from the given input.
@param source the input source to use. Make sure that this doesn't
get deleted before the ChannelRemappingAudioSource object
@param deleteSourceWhenDeleted if true, the input source will be deleted
when this object is deleted, if false, the caller is
responsible for its deletion
*/
ChannelRemappingAudioSource (AudioSource* source,
bool deleteSourceWhenDeleted);

/** Destructor. */
~ChannelRemappingAudioSource();

//==============================================================================
/** Specifies a number of channels that this audio source must produce from its
getNextAudioBlock() callback.
*/
void setNumberOfChannelsToProduce (int requiredNumberOfChannels);

/** Clears any mapped channels.
After this, no channels are mapped, so this object will produce silence. Create
some mappings with setInputChannelMapping() and setOutputChannelMapping().
*/
void clearAllMappings();

/** Creates an input channel mapping.
When the getNextAudioBlock() method is called, the data in channel sourceChannelIndex of the incoming
data will be sent to destChannelIndex of our input source.
@param destChannelIndex the index of an input channel in our input audio source (i.e. the
source specified when this object was created).
@param sourceChannelIndex the index of the input channel in the incoming audio data buffer
during our getNextAudioBlock() callback
*/
void setInputChannelMapping (int destChannelIndex,
int sourceChannelIndex);

/** Creates an output channel mapping.
When the getNextAudioBlock() method is called, the data returned in channel sourceChannelIndex by
our input audio source will be copied to channel destChannelIndex of the final buffer.
@param sourceChannelIndex the index of an output channel coming from our input audio source
(i.e. the source specified when this object was created).
@param destChannelIndex the index of the output channel in the incoming audio data buffer
during our getNextAudioBlock() callback
*/
void setOutputChannelMapping (int sourceChannelIndex,
int destChannelIndex);

/** Returns the channel from our input that will be sent to channel inputChannelIndex of
our input audio source.
*/
int getRemappedInputChannel (int inputChannelIndex) const;

/** Returns the output channel to which channel outputChannelIndex of our input audio
source will be sent to.
*/
int getRemappedOutputChannel (int outputChannelIndex) const;


//==============================================================================
/** Returns an XML object to encapsulate the state of the mappings.
@see restoreFromXml
*/
XmlElement* createXml() const;

/** Restores the mappings from an XML object created by createXML().
@see createXml
*/
void restoreFromXml (const XmlElement& e);

//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
void releaseResources();
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);


private:
//==============================================================================
OptionalScopedPointer<AudioSource> source;
Array <int> remappedInputs, remappedOutputs;
int requiredNumberOfChannels;

AudioSampleBuffer buffer;
AudioSourceChannelInfo remappedInfo;

CriticalSection lock;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChannelRemappingAudioSource)
};


#endif // __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__
@@ -0,0 +1,72 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

IIRFilterAudioSource::IIRFilterAudioSource (AudioSource* const inputSource,
const bool deleteInputWhenDeleted)
: input (inputSource, deleteInputWhenDeleted)
{
jassert (inputSource != nullptr);

for (int i = 2; --i >= 0;)
iirFilters.add (new IIRFilter());
}

IIRFilterAudioSource::~IIRFilterAudioSource() {}

//==============================================================================
void IIRFilterAudioSource::setFilterParameters (const IIRFilter& newSettings)
{
for (int i = iirFilters.size(); --i >= 0;)
iirFilters.getUnchecked(i)->copyCoefficientsFrom (newSettings);
}

//==============================================================================
void IIRFilterAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
input->prepareToPlay (samplesPerBlockExpected, sampleRate);

for (int i = iirFilters.size(); --i >= 0;)
iirFilters.getUnchecked(i)->reset();
}

void IIRFilterAudioSource::releaseResources()
{
input->releaseResources();
}

void IIRFilterAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
input->getNextAudioBlock (bufferToFill);

const int numChannels = bufferToFill.buffer->getNumChannels();

while (numChannels > iirFilters.size())
iirFilters.add (new IIRFilter (*iirFilters.getUnchecked (0)));

for (int i = 0; i < numChannels; ++i)
iirFilters.getUnchecked(i)
->processSamples (bufferToFill.buffer->getSampleData (i, bufferToFill.startSample),
bufferToFill.numSamples);
}
@@ -0,0 +1,71 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_IIRFILTERAUDIOSOURCE_JUCEHEADER__
#define __JUCE_IIRFILTERAUDIOSOURCE_JUCEHEADER__

#include "juce_AudioSource.h"
#include "../effects/juce_IIRFilter.h"


//==============================================================================
/**
An AudioSource that performs an IIR filter on another source.
*/
class JUCE_API IIRFilterAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a IIRFilterAudioSource for a given input source.
@param inputSource the input source to read from - this must not be null
@param deleteInputWhenDeleted if true, the input source will be deleted when
this object is deleted
*/
IIRFilterAudioSource (AudioSource* inputSource,
bool deleteInputWhenDeleted);

/** Destructor. */
~IIRFilterAudioSource();

//==============================================================================
/** Changes the filter to use the same parameters as the one being passed in. */
void setFilterParameters (const IIRFilter& newSettings);

//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
void releaseResources();
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);

private:
//==============================================================================
OptionalScopedPointer<AudioSource> input;
OwnedArray <IIRFilter> iirFilters;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IIRFilterAudioSource)
};


#endif // __JUCE_IIRFILTERAUDIOSOURCE_JUCEHEADER__
@@ -0,0 +1,158 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

MixerAudioSource::MixerAudioSource()
: tempBuffer (2, 0),
currentSampleRate (0.0),
bufferSizeExpected (0)
{
}

MixerAudioSource::~MixerAudioSource()
{
removeAllInputs();
}

//==============================================================================
void MixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhenRemoved)
{
if (input != nullptr && ! inputs.contains (input))
{
double localRate;
int localBufferSize;

{
const ScopedLock sl (lock);
localRate = currentSampleRate;
localBufferSize = bufferSizeExpected;
}

if (localRate > 0.0)
input->prepareToPlay (localBufferSize, localRate);

const ScopedLock sl (lock);

inputsToDelete.setBit (inputs.size(), deleteWhenRemoved);
inputs.add (input);
}
}

void MixerAudioSource::removeInputSource (AudioSource* const input)
{
if (input != nullptr)
{
ScopedPointer<AudioSource> toDelete;

{
const ScopedLock sl (lock);
const int index = inputs.indexOf (input);

if (index < 0)
return;

if (inputsToDelete [index])
toDelete = input;

inputsToDelete.shiftBits (-1, index);
inputs.remove (index);
}

input->releaseResources();
}
}

void MixerAudioSource::removeAllInputs()
{
OwnedArray<AudioSource> toDelete;

{
const ScopedLock sl (lock);

for (int i = inputs.size(); --i >= 0;)
if (inputsToDelete[i])
toDelete.add (inputs.getUnchecked(i));

inputs.clear();
}

for (int i = toDelete.size(); --i >= 0;)
toDelete.getUnchecked(i)->releaseResources();
}

void MixerAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
tempBuffer.setSize (2, samplesPerBlockExpected);

const ScopedLock sl (lock);

currentSampleRate = sampleRate;
bufferSizeExpected = samplesPerBlockExpected;

for (int i = inputs.size(); --i >= 0;)
inputs.getUnchecked(i)->prepareToPlay (samplesPerBlockExpected, sampleRate);
}

void MixerAudioSource::releaseResources()
{
const ScopedLock sl (lock);

for (int i = inputs.size(); --i >= 0;)
inputs.getUnchecked(i)->releaseResources();

tempBuffer.setSize (2, 0);

currentSampleRate = 0;
bufferSizeExpected = 0;
}

void MixerAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
const ScopedLock sl (lock);

if (inputs.size() > 0)
{
inputs.getUnchecked(0)->getNextAudioBlock (info);

if (inputs.size() > 1)
{
tempBuffer.setSize (jmax (1, info.buffer->getNumChannels()),
info.buffer->getNumSamples());

AudioSourceChannelInfo info2 (&tempBuffer, 0, info.numSamples);

for (int i = 1; i < inputs.size(); ++i)
{
inputs.getUnchecked(i)->getNextAudioBlock (info2);

for (int chan = 0; chan < info.buffer->getNumChannels(); ++chan)
info.buffer->addFrom (chan, info.startSample, tempBuffer, chan, 0, info.numSamples);
}
}
}
else
{
info.clearActiveBufferRegion();
}
}
@@ -0,0 +1,104 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__
#define __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__

#include "juce_AudioSource.h"


//==============================================================================
/**
An AudioSource that mixes together the output of a set of other AudioSources.
Input sources can be added and removed while the mixer is running as long as their
prepareToPlay() and releaseResources() methods are called before and after adding
them to the mixer.
*/
class JUCE_API MixerAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a MixerAudioSource. */
MixerAudioSource();

/** Destructor. */
~MixerAudioSource();

//==============================================================================
/** Adds an input source to the mixer.
If the mixer is running you'll need to make sure that the input source
is ready to play by calling its prepareToPlay() method before adding it.
If the mixer is stopped, then its input sources will be automatically
prepared when the mixer's prepareToPlay() method is called.
@param newInput the source to add to the mixer
@param deleteWhenRemoved if true, then this source will be deleted when
no longer needed by the mixer.
*/
void addInputSource (AudioSource* newInput, bool deleteWhenRemoved);

/** Removes an input source.
If the source was added by calling addInputSource() with the deleteWhenRemoved
flag set, it will be deleted by this method.
*/
void removeInputSource (AudioSource* input);

/** Removes all the input sources.
Any sources which were added by calling addInputSource() with the deleteWhenRemoved
flag set will be deleted by this method.
*/
void removeAllInputs();

//==============================================================================
/** Implementation of the AudioSource method.
This will call prepareToPlay() on all its input sources.
*/
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);

/** Implementation of the AudioSource method.
This will call releaseResources() on all its input sources.
*/
void releaseResources();

/** Implementation of the AudioSource method. */
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);


private:
//==============================================================================
Array <AudioSource*> inputs;
BigInteger inputsToDelete;
CriticalSection lock;
AudioSampleBuffer tempBuffer;
double currentSampleRate;
int bufferSizeExpected;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MixerAudioSource)
};


#endif // __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__
@@ -0,0 +1,81 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__
#define __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__

#include "juce_AudioSource.h"


//==============================================================================
/**
A type of AudioSource which can be repositioned.
The basic AudioSource just streams continuously with no idea of a current
time or length, so the PositionableAudioSource is used for a finite stream
that has a current read position.
@see AudioSource, AudioTransportSource
*/
class JUCE_API PositionableAudioSource : public AudioSource
{
protected:
//==============================================================================
/** Creates the PositionableAudioSource. */
PositionableAudioSource() noexcept {}

public:
/** Destructor */
~PositionableAudioSource() {}

//==============================================================================
/** Tells the stream to move to a new position.
Calling this indicates that the next call to AudioSource::getNextAudioBlock()
should return samples from this position.
Note that this may be called on a different thread to getNextAudioBlock(),
so the subclass should make sure it's synchronised.
*/
virtual void setNextReadPosition (int64 newPosition) = 0;

/** Returns the position from which the next block will be returned.
@see setNextReadPosition
*/
virtual int64 getNextReadPosition() const = 0;

/** Returns the total length of the stream (in samples). */
virtual int64 getTotalLength() const = 0;

/** Returns true if this source is actually playing in a loop. */
virtual bool isLooping() const = 0;

/** Tells the source whether you'd like it to play in a loop. */
virtual void setLooping (bool shouldLoop) { (void) shouldLoop; }
};


#endif // __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__
@@ -0,0 +1,254 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

ResamplingAudioSource::ResamplingAudioSource (AudioSource* const inputSource,
const bool deleteInputWhenDeleted,
const int numChannels_)
: input (inputSource, deleteInputWhenDeleted),
ratio (1.0),
lastRatio (1.0),
buffer (numChannels_, 0),
sampsInBuffer (0),
numChannels (numChannels_)
{
jassert (input != nullptr);
}

ResamplingAudioSource::~ResamplingAudioSource() {}

void ResamplingAudioSource::setResamplingRatio (const double samplesInPerOutputSample)
{
jassert (samplesInPerOutputSample > 0);

const SpinLock::ScopedLockType sl (ratioLock);
ratio = jmax (0.0, samplesInPerOutputSample);
}

void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected,
double sampleRate)
{
const SpinLock::ScopedLockType sl (ratioLock);

input->prepareToPlay (samplesPerBlockExpected, sampleRate);

buffer.setSize (numChannels, roundToInt (samplesPerBlockExpected * ratio) + 32);
buffer.clear();
sampsInBuffer = 0;
bufferPos = 0;
subSampleOffset = 0.0;

filterStates.calloc ((size_t) numChannels);
srcBuffers.calloc ((size_t) numChannels);
destBuffers.calloc ((size_t) numChannels);
createLowPass (ratio);
resetFilters();
}

void ResamplingAudioSource::releaseResources()
{
input->releaseResources();
buffer.setSize (numChannels, 0);
}

void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
double localRatio;

{
const SpinLock::ScopedLockType sl (ratioLock);
localRatio = ratio;
}

if (lastRatio != localRatio)
{
createLowPass (localRatio);
lastRatio = localRatio;
}

const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 2;

int bufferSize = buffer.getNumSamples();

if (bufferSize < sampsNeeded + 8)
{
bufferPos %= bufferSize;
bufferSize = sampsNeeded + 32;
buffer.setSize (buffer.getNumChannels(), bufferSize, true, true);
}

bufferPos %= bufferSize;

int endOfBufferPos = bufferPos + sampsInBuffer;
const int channelsToProcess = jmin (numChannels, info.buffer->getNumChannels());

while (sampsNeeded > sampsInBuffer)
{
endOfBufferPos %= bufferSize;

int numToDo = jmin (sampsNeeded - sampsInBuffer,
bufferSize - endOfBufferPos);

AudioSourceChannelInfo readInfo (&buffer, endOfBufferPos, numToDo);
input->getNextAudioBlock (readInfo);

if (localRatio > 1.0001)
{
// for down-sampling, pre-apply the filter..

for (int i = channelsToProcess; --i >= 0;)
applyFilter (buffer.getSampleData (i, endOfBufferPos), numToDo, filterStates[i]);
}

sampsInBuffer += numToDo;
endOfBufferPos += numToDo;
}

for (int channel = 0; channel < channelsToProcess; ++channel)
{
destBuffers[channel] = info.buffer->getSampleData (channel, info.startSample);
srcBuffers[channel] = buffer.getSampleData (channel, 0);
}

int nextPos = (bufferPos + 1) % bufferSize;
for (int m = info.numSamples; --m >= 0;)
{
const float alpha = (float) subSampleOffset;

for (int channel = 0; channel < channelsToProcess; ++channel)
*destBuffers[channel]++ = srcBuffers[channel][bufferPos]
+ alpha * (srcBuffers[channel][nextPos] - srcBuffers[channel][bufferPos]);

subSampleOffset += localRatio;

jassert (sampsInBuffer > 0);

while (subSampleOffset >= 1.0)
{
if (++bufferPos >= bufferSize)
bufferPos = 0;

--sampsInBuffer;

nextPos = (bufferPos + 1) % bufferSize;
subSampleOffset -= 1.0;
}
}

if (localRatio < 0.9999)
{
// for up-sampling, apply the filter after transposing..
for (int i = channelsToProcess; --i >= 0;)
applyFilter (info.buffer->getSampleData (i, info.startSample), info.numSamples, filterStates[i]);
}
else if (localRatio <= 1.0001 && info.numSamples > 0)
{
// if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities
for (int i = channelsToProcess; --i >= 0;)
{
const float* const endOfBuffer = info.buffer->getSampleData (i, info.startSample + info.numSamples - 1);
FilterState& fs = filterStates[i];

if (info.numSamples > 1)
{
fs.y2 = fs.x2 = *(endOfBuffer - 1);
}
else
{
fs.y2 = fs.y1;
fs.x2 = fs.x1;
}

fs.y1 = fs.x1 = *endOfBuffer;
}
}

jassert (sampsInBuffer >= 0);
}

void ResamplingAudioSource::createLowPass (const double frequencyRatio)
{
const double proportionalRate = (frequencyRatio > 1.0) ? 0.5 / frequencyRatio
: 0.5 * frequencyRatio;

const double n = 1.0 / std::tan (double_Pi * jmax (0.001, proportionalRate));
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);

setFilterCoefficients (c1,
c1 * 2.0f,
c1,
1.0,
c1 * 2.0 * (1.0 - nSquared),
c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
}

void ResamplingAudioSource::setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6)
{
const double a = 1.0 / c4;

c1 *= a;
c2 *= a;
c3 *= a;
c5 *= a;
c6 *= a;

coefficients[0] = c1;
coefficients[1] = c2;
coefficients[2] = c3;
coefficients[3] = c4;
coefficients[4] = c5;
coefficients[5] = c6;
}

void ResamplingAudioSource::resetFilters()
{
filterStates.clear ((size_t) numChannels);
}

void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs)
{
while (--num >= 0)
{
const double in = *samples;

double out = coefficients[0] * in
+ coefficients[1] * fs.x1
+ coefficients[2] * fs.x2
- coefficients[4] * fs.y1
- coefficients[5] * fs.y2;

#if JUCE_INTEL
if (! (out < -1.0e-8 || out > 1.0e-8))
out = 0;
#endif

fs.x2 = fs.x1;
fs.x1 = in;
fs.y2 = fs.y1;
fs.y1 = out;

*samples++ = (float) out;
}
}
@@ -0,0 +1,106 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__
#define __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__

#include "juce_AudioSource.h"


//==============================================================================
/**
A type of AudioSource that takes an input source and changes its sample rate.
@see AudioSource
*/
class JUCE_API ResamplingAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a ResamplingAudioSource for a given input source.
@param inputSource the input source to read from
@param deleteInputWhenDeleted if true, the input source will be deleted when
this object is deleted
@param numChannels the number of channels to process
*/
ResamplingAudioSource (AudioSource* inputSource,
bool deleteInputWhenDeleted,
int numChannels = 2);

/** Destructor. */
~ResamplingAudioSource();

/** Changes the resampling ratio.
(This value can be changed at any time, even while the source is running).
@param samplesInPerOutputSample if set to 1.0, the input is passed through; higher
values will speed it up; lower values will slow it
down. The ratio must be greater than 0
*/
void setResamplingRatio (double samplesInPerOutputSample);

/** Returns the current resampling ratio.
This is the value that was set by setResamplingRatio().
*/
double getResamplingRatio() const noexcept { return ratio; }

//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
void releaseResources();
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);

private:
//==============================================================================
OptionalScopedPointer<AudioSource> input;
double ratio, lastRatio;
AudioSampleBuffer buffer;
int bufferPos, sampsInBuffer;
double subSampleOffset;
double coefficients[6];
SpinLock ratioLock;
const int numChannels;
HeapBlock<float*> destBuffers, srcBuffers;

void setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6);
void createLowPass (double proportionalRate);

struct FilterState
{
double x1, x2, y1, y2;
};

HeapBlock<FilterState> filterStates;
void resetFilters();

void applyFilter (float* samples, int num, FilterState& fs);

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ResamplingAudioSource)
};


#endif // __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__
@@ -0,0 +1,81 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

ReverbAudioSource::ReverbAudioSource (AudioSource* const inputSource, const bool deleteInputWhenDeleted)
: input (inputSource, deleteInputWhenDeleted),
bypass (false)
{
jassert (inputSource != nullptr);
}

ReverbAudioSource::~ReverbAudioSource() {}

void ReverbAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
const ScopedLock sl (lock);
input->prepareToPlay (samplesPerBlockExpected, sampleRate);
reverb.setSampleRate (sampleRate);
}

void ReverbAudioSource::releaseResources() {}

void ReverbAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
const ScopedLock sl (lock);

input->getNextAudioBlock (bufferToFill);

if (! bypass)
{
float* const firstChannel = bufferToFill.buffer->getSampleData (0, bufferToFill.startSample);

if (bufferToFill.buffer->getNumChannels() > 1)
{
reverb.processStereo (firstChannel,
bufferToFill.buffer->getSampleData (1, bufferToFill.startSample),
bufferToFill.numSamples);
}
else
{
reverb.processMono (firstChannel, bufferToFill.numSamples);
}
}
}

void ReverbAudioSource::setParameters (const Reverb::Parameters& newParams)
{
const ScopedLock sl (lock);
reverb.setParameters (newParams);
}

void ReverbAudioSource::setBypassed (bool b) noexcept
{
if (bypass != b)
{
const ScopedLock sl (lock);
bypass = b;
reverb.reset();
}
}
@@ -0,0 +1,80 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_REVERBAUDIOSOURCE_JUCEHEADER__
#define __JUCE_REVERBAUDIOSOURCE_JUCEHEADER__

#include "juce_AudioSource.h"
#include "../effects/juce_Reverb.h"


//==============================================================================
/**
An AudioSource that uses the Reverb class to apply a reverb to another AudioSource.
@see Reverb
*/
class JUCE_API ReverbAudioSource : public AudioSource
{
public:
/** Creates a ReverbAudioSource to process a given input source.
@param inputSource the input source to read from - this must not be null
@param deleteInputWhenDeleted if true, the input source will be deleted when
this object is deleted
*/
ReverbAudioSource (AudioSource* inputSource,
bool deleteInputWhenDeleted);

/** Destructor. */
~ReverbAudioSource();

//==============================================================================
/** Returns the parameters from the reverb. */
const Reverb::Parameters& getParameters() const noexcept { return reverb.getParameters(); }

/** Changes the reverb's parameters. */
void setParameters (const Reverb::Parameters& newParams);

void setBypassed (bool isBypassed) noexcept;
bool isBypassed() const noexcept { return bypass; }

//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
void releaseResources();
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);

private:
//==============================================================================
CriticalSection lock;
OptionalScopedPointer<AudioSource> input;
Reverb reverb;
volatile bool bypass;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ReverbAudioSource)
};


#endif // __JUCE_REVERBAUDIOSOURCE_JUCEHEADER__
@@ -0,0 +1,77 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

ToneGeneratorAudioSource::ToneGeneratorAudioSource()
: frequency (1000.0),
sampleRate (44100.0),
currentPhase (0.0),
phasePerSample (0.0),
amplitude (0.5f)
{
}

ToneGeneratorAudioSource::~ToneGeneratorAudioSource()
{
}

//==============================================================================
void ToneGeneratorAudioSource::setAmplitude (const float newAmplitude)
{
amplitude = newAmplitude;
}

void ToneGeneratorAudioSource::setFrequency (const double newFrequencyHz)
{
frequency = newFrequencyHz;
phasePerSample = 0.0;
}

//==============================================================================
void ToneGeneratorAudioSource::prepareToPlay (int /*samplesPerBlockExpected*/,
double sampleRate_)
{
currentPhase = 0.0;
phasePerSample = 0.0;
sampleRate = sampleRate_;
}

void ToneGeneratorAudioSource::releaseResources()
{
}

void ToneGeneratorAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
if (phasePerSample == 0.0)
phasePerSample = double_Pi * 2.0 / (sampleRate / frequency);

for (int i = 0; i < info.numSamples; ++i)
{
const float sample = amplitude * (float) std::sin (currentPhase);
currentPhase += phasePerSample;

for (int j = info.buffer->getNumChannels(); --j >= 0;)
*info.buffer->getSampleData (j, info.startSample + i) = sample;
}
}
@@ -0,0 +1,76 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/

#ifndef __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__
#define __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__

#include "juce_AudioSource.h"


//==============================================================================
/**
A simple AudioSource that generates a sine wave.
*/
class JUCE_API ToneGeneratorAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a ToneGeneratorAudioSource. */
ToneGeneratorAudioSource();

/** Destructor. */
~ToneGeneratorAudioSource();

//==============================================================================
/** Sets the signal's amplitude. */
void setAmplitude (float newAmplitude);

/** Sets the signal's frequency. */
void setFrequency (double newFrequencyHz);


//==============================================================================
/** Implementation of the AudioSource method. */
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);

/** Implementation of the AudioSource method. */
void releaseResources();

/** Implementation of the AudioSource method. */
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);


private:
//==============================================================================
double frequency, sampleRate;
double currentPhase, phasePerSample;
float amplitude;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToneGeneratorAudioSource)
};


#endif // __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__