About AudioSourcePlayer::audioDeviceIOCallback()


#1

About AudioSourcePlayer::audioDeviceIOCallback()

in this method, I got confused about the variable numActiveChans. In lastest jucedemo from subversion,
In the Audio Demo, I use my line6 box as device. I did the following test.In we I choose 0 input channels,
the numActiveChans is 2. when I choose 2 avtiveinputchannels(1+2), the numActiveChans is
also 2. I also changed the avtiveinputchannels to 1,3,4 in the audiodeviceIOCallback in AudioSourcePlayer,
I get the numActiveChans is always 2.
So could anyone explain this for me? why numActiveChans do not change for all the settings? does it equal to
the numOutPutChannles?

Best,
Chengyu
I attach the code below for convenience

void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData,
int totalNumInputChannels,
float** outputChannelData,
int totalNumOutputChannels,
int numSamples)
{
// these should have been prepared by audioDeviceAboutToStart()…
jassert (sampleRate > 0 && bufferSize > 0);

const ScopedLock sl (readLock);

if (source != 0)
{
    AudioSourceChannelInfo info;
    int i, numActiveChans = 0, numInputs = 0, numOutputs = 0;

    // messy stuff needed to compact the channels down into an array
    // of non-zero pointers..
    for (i = 0; i < totalNumInputChannels; ++i)
    {
        if (inputChannelData[i] != 0)
        {
            inputChans [numInputs++] = inputChannelData[i];
            if (numInputs >= numElementsInArray (inputChans))
                break
        }
    }
    for (i = 0; i < totalNcumOutputChannels; ++i)
    {
        if (outputChannelData[i] != 0)
        {
            outputChans [numOutputs++] = outputChannelData[i];
            if (numOutputs >= numElementsInArray (outputChans))
                break;
       
    }

    if (numInputs > numOutputs)
    {
        // if there aren't enough output channels for the number of
        // inputs, we need to create some temporary extra ones (can't
        // use the input data in case it gets written to)
        tempBuffer.setSize (numInputs - numOutputs, numSamples,
                            false, false, true);

        for (i = 0; i < numOutputs; ++i)
        {
            channels[numActiveChans] = outputChans[i];
            memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
            ++numActiveChans;
        }

        for (i = numOutputs; i < numInputs; ++i)
        {
            channels[numActiveChans] = tempBuffer.getSampleData (i - numOutputs, 0);
            memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
            ++numActiveChans;
        }
    }
    else
    {
        for (i = 0; i < numInputs; ++i)
        {
            channels[numActiveChans] = outputChans[i];
            memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples);
            ++numActiveChans;
        }

        for (i = numInputs; i < numOutputs; ++i)
        {
            channels[numActiveChans] = outputChans[i];
            zeromem (channels[numActiveChans], sizeof (float) * numSamples);
            ++numActiveChans;
        }
    }

    AudioSampleBuffer buffer (channels, numActiveChans, numSamples);

    info.buffer = &buffer;
    info.startSample = 0;
    info.numSamples = numSamples;

    source->getNextAudioBlock (info);

    for (i = info.buffer->getNumChannels(); --i >= 0;)
        info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);

    lastGain = gain;
}
else
{
    for (int i = 0; i < totalNumOutputChannels; ++i)
        if (outputChannelData[i] != 0)
            zeromem (outputChannelData[i], sizeof (float) * numSamples);
}

}


#2

Well, it’s sort of “max (num inputs channels, num output channels)”. You shouldn’t need to care about what happens in that method though… What’s the problem that made you start looking in there?


#3

Hi,jules
In the jucedemo, audio part. when we play a wav file, and the final step is to use AudioSourcePlayer::audioDeviceIOCallback()
to get the inputChannelData and numberInputChannels , and send to the outputChannelData array.
In the audioDeviceIOCallback(), what you did is to match the input and output channles in case the numinput not equal to numoutput.
and then to decide the right buffer size.
What I am concerned is where is the inputChannelData comes from originally when we play wave file, because I need
to implement my audioDeviceIOCallback(). At the same time, I can not trace back to find where this array come from?

I got confused about what the difference between the input is micro phone and the input is wav file. I just want to send the both input to speakers by implementing audioDeviceIOCallback().
in microphone case, we need to choose activeinputChannels for the reason that we need it to get the mic input. what’s the scenario if the input is wav?
I do not think we need any activeinputChannels. because the source is wav.

That’s why I need more details about this method.

Could you give me some clue?
Best
Leon


#4

Sorry - you’ve lost me there…

[quote]What I am concerned is where is the inputChannelData comes from originally when we play wave file, because I need
to implement my audioDeviceIOCallback(). At the same time, I can not trace back to find where this array come from?[/quote]

Hard to understand exactly what you’re asking, but if you mean that you want to know which physical input a particular channel comes from, then it’ll depend on the channels you specified when you opened the device. (I thought the comments for audioDeviceIOCallback() already explained all of this pretty well?)


#5

Hi,jules,
Thank you for your reply.
Sorry for making confuse, and I may not get the idea of AudioDeviceIOCallback(). I understand the manipulation inside this method, however, I do not know the data in inputChannelData which is one of input parameters of this method.
I know the outputChannelData will be sent out from device, right?

void AudioSourcePlayer::audioDeviceIOCallback (
const float** inputChannelData,
int totalNumInputChannels,
float** outputChannelData,
int totalNumOutputChannels,
int numSamples)

Best,
Leon


#6

I still don’t understand what your problem is… You select some input and output channels when you open the device, and those inputs and outputs are delivered in the two arrays. It’s as simple as that!


#7

How are the input and output go to the two arrays?
Is this process done by driver? I do not find the code that implements sending device input to input array as well as for output.

Thank you!
Best
Leon


#8

You don’t have to know how the data gets there! Just use it and don’t worry about it!