Custom AudioFormat readSamples


#1

So I have a custom AudioFormat and I’m creating a reader for it… in my CustomReader class which is derived from AudioFormatReader I’ve put all the audio sample data into an AudioSampleBuffer.

Any tips for implementing readSamples() where it copies data from the AudioSampleBuffer into the array of destination buffers?

Do I just getArrayOfReadPointers() and memcpy the data to destSamples ? Is the destination always going to expect floats?

Cheers,

Rail


#2

I was thinking something like:

bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
{
    if (numDestChannels >= 65)
        numDestChannels = 64;       // Either limit it to the destSamples max channels or return false

    clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
                                       startSampleInFile, numSamples, lengthInSamples);

    int iTotalSamples = m_pBuffer->getNumSamples();

    while (numSamples > 0)
        {
        int numThisTime = numSamples;
        
        if (numThisTime + startSampleInFile > iTotalSamples)
            numThisTime = iTotalSamples - startSampleInFile;
        
        for (int j = 0; j < numDestChannels; ++j)
            {
            const int* pSourceChannel = reinterpret_cast<const int*> (m_pBuffer->getReadPointer (j, startSampleInFile + (j * numThisTime)));
            
            memcpy (destSamples + startOffsetInDestBuffer + (j * numThisTime), pSourceChannel, numThisTime);
            }
        
        startOffsetInDestBuffer += numThisTime;
        startSampleInFile += numThisTime;
        numSamples -= numThisTime;
        }
    
    return true;
}

I see that the WAvAudioFormatReader uses a ReadHelper but it’s set to interleaved…

Cheers,

Rail


#3

So I’m wondering if AudioFormatReader::ReadHelper() should allow us to set if the Source is interleaved or not?

template <class DestSampleType, class SourceSampleType, class SourceEndianness, class SourceInterleaviness = AudioData::Interleaved>

struct ReadHelper
{
    typedef AudioData::Pointer<DestSampleType, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst>    DestType;
    typedef AudioData::Pointer<SourceSampleType, SourceEndianness, SourceInterleaviness, AudioData::Const>                 SourceType;

   : 
}

Cheers,

Rail


#4

So this seems to do the job…

bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
{
    numDestChannels = jlimit (0, 64, numDestChannels); // Either limit it to the destSamples max channels or return false to avoid a bounds error

    clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
                                       startSampleInFile, numSamples, lengthInSamples);

    int iTotalSamples = m_pBuffer->getNumSamples();

    while (numSamples > 0)
        {
        int numThisTime = numSamples;
        
        if (numThisTime + startSampleInFile > iTotalSamples)
            numThisTime = iTotalSamples - startSampleInFile;
        
        for (int i = numDestChannels; --i >= 0;)
            {
            if (destSamples[i] != nullptr)
                {
                if (i < (int) numChannels)
                    {
                    const float* data = m_pBuffer->getReadPointer (i, startSampleInFile);

                    ReadHelper<AudioData::Int32, AudioData::Float32, AudioData::LittleEndian>
                    ::read (&destSamples[i], startOffsetInDestBuffer, 1, data, (int) 1, numThisTime);
                    }
                else
                    {
                    const size_t numBytes = sizeof (int) * (size_t) numThisTime;
                    
                    zeromem (destSamples[i] + startOffsetInDestBuffer, numBytes);
                    }
                }
            }

        startOffsetInDestBuffer += numThisTime;
        startSampleInFile += numThisTime;
        numSamples -= numThisTime;
        }
    
    return true;
}

Rail