Ok, I added an additional AudioSampleBuffer to the MixerAudioSource to cache the input data and now it works. Just in case anybody else shares this problem, I post my code for the InputCachingMixerAudioSource here:
InputCachingMixerAudioSource.h
[code]#include “juce.h”
//==============================================================================
/**
An AudioSource that mixes together the output of a set of other AudioSources and feeds them with input.
Same as MixerAudioSource, it just has an extra AudioSamplebuffer for caching the input data
in order to provide it to all attached 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 InputCachingMixerAudioSource : public AudioSource
{
public:
//==============================================================================
/* Creates a InputCachingMixerAudioSource.
*/
InputCachingMixerAudioSource();
/** Destructor. */
~InputCachingMixerAudioSource();
//==============================================================================
/** 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
the mixer is deleted or when removeAllInputs() is
called (unless the source is previously removed
with the removeInputSource method)
*/
void addInputSource (AudioSource* newInput,
const bool deleteWhenRemoved);
/** Removes an input source.
If the mixer is running, this will remove the source but not call its
releaseResources() method, so the caller might want to do this manually.
@param input the source to remove
@param deleteSource whether to delete this source after it's been removed
*/
void removeInputSource (AudioSource* input,
const bool deleteSource);
/** Removes all the input sources.
If the mixer is running, this will remove the sources but not call their
releaseResources() method, so the caller might want to do this manually.
Any sources which were added 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);
//==============================================================================
juce_UseDebuggingNewOperator
private:
//==============================================================================
VoidArray inputs;
BitArray inputsToDelete;
CriticalSection lock;
AudioSampleBuffer tempBuffer;
AudioSampleBuffer cacheBuffer;
double currentSampleRate;
int bufferSizeExpected;
InputCachingMixerAudioSource (const InputCachingMixerAudioSource&);
const InputCachingMixerAudioSource& operator= (const InputCachingMixerAudioSource&);
};[/code]
InputCachingMixerAudioSource.cpp
[code]#include “juce.h”
#include “InputCachingMixerAudioSource.h”
//==============================================================================
InputCachingMixerAudioSource::InputCachingMixerAudioSource()
: tempBuffer (2, 0),
cacheBuffer (2, 0),
currentSampleRate (0.0),
bufferSizeExpected (0)
{
}
InputCachingMixerAudioSource::~InputCachingMixerAudioSource()
{
removeAllInputs();
}
//==============================================================================
void InputCachingMixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhenRemoved)
{
if (input != 0 && ! inputs.contains (input))
{
lock.enter();
double localRate = currentSampleRate;
int localBufferSize = bufferSizeExpected;
lock.exit();
if (localRate != 0.0)
input->prepareToPlay (localBufferSize, localRate);
const ScopedLock sl (lock);
inputsToDelete.setBit (inputs.size(), deleteWhenRemoved);
inputs.add (input);
}
}
void InputCachingMixerAudioSource::removeInputSource (AudioSource* input, const bool deleteInput)
{
if (input != 0)
{
lock.enter();
const int index = inputs.indexOf ((void*) input);
if (index >= 0)
{
inputsToDelete.shiftBits (index, 1);
inputs.remove (index);
}
lock.exit();
if (index >= 0)
{
input->releaseResources();
if (deleteInput)
delete input;
}
}
}
void InputCachingMixerAudioSource::removeAllInputs()
{
lock.enter();
VoidArray inputsCopy (inputs);
BitArray inputsToDeleteCopy (inputsToDelete);
inputs.clear();
lock.exit();
for (int i = inputsCopy.size(); --i >= 0;)
if (inputsToDeleteCopy[i])
delete (AudioSource*) inputsCopy[i];
}
void InputCachingMixerAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
tempBuffer.setSize (2, samplesPerBlockExpected);
cacheBuffer.setSize (2, samplesPerBlockExpected);
const ScopedLock sl (lock);
currentSampleRate = sampleRate;
bufferSizeExpected = samplesPerBlockExpected;
for (int i = inputs.size(); --i >= 0;)
((AudioSource*) inputs.getUnchecked(i))->prepareToPlay (samplesPerBlockExpected,
sampleRate);
}
void InputCachingMixerAudioSource::releaseResources()
{
const ScopedLock sl (lock);
for (int i = inputs.size(); --i >= 0;)
((AudioSource*) inputs.getUnchecked(i))->releaseResources();
tempBuffer.setSize (2, 0);
cacheBuffer.setSize (2, 0);
currentSampleRate = 0;
bufferSizeExpected = 0;
}
void InputCachingMixerAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
const ScopedLock sl (lock);
// if mixer has inputs, call their getNextAudioBlock()
if (inputs.size() > 0) // mixer has at least one source attached
{
// store the info.buffer so all audioSources get the inputData. cacheBuffer's size will automatically be changed to that of info.buffer by [=]
cacheBuffer = *info.buffer;
((AudioSource*) inputs.getUnchecked(0))->getNextAudioBlock (info);
if (inputs.size() > 1) // mixer has more than one source attached
{
tempBuffer.setSize (jmax (1, info.buffer->getNumChannels()),
info.buffer->getNumSamples());
AudioSourceChannelInfo info2;
info2.buffer = &tempBuffer;
info2.numSamples = info.numSamples;
info2.startSample = 0;
for (int i = 1; i < inputs.size(); ++i)
{
((AudioSource*) 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);
tempBuffer = cacheBuffer;
}
}
}
// mixer has no inputs, so returns an empty buffer to the AudioSourcePlayer
else
{
info.clearActiveBufferRegion();
}
}[/code]