AudioTransportSource + AudioSubsectionReader, how do?


#1

I’m trying to make a sampler that plays back cropped sections of an audio file, however I have had no luck integrating an AudioSubsectionReader with an AudioTransportSource. Has anyone tried this and could provide me with an example bit of code, or just explain roughly how to go about it?

TransportSource may be a bit of a red herring with getting playback to work in this fashion but I am not sure. Why does AudioSubsectionReader’s readSample function take an int** as an argument for the destination buffer when the buffer used by AudioSource (and in all other instances I have found) Juce audio buffers are float**? Is it possible (or advised) to do some kind of cast between the two and if so how?


#2

There’s a good example in the JuceDemo application - check it out.

About the AudioSubsectionReader, after you created an AudioFormatReader, just pass it in the const. to the new AudioSubsectionReader.

Then pass the AudioSubsectionReader to the transportSource in setSource().


#3

Ok, Its been a real battle but I am getting there.The basic goal is polyphonic playback of subsections of a single audio file.

There is basically an array of objects that hold various bits of data, startpoints end points and so on. They each contain an instance of the following class.

/**PolyPlayerVoice is a class designed to convert an AudioSubsectionReader into an AudioTransportSource.
*/

class PolyPlayerVoice
{
public:
    PolyPlayerVoice(AudioFormatReader &MasterReader,
                    TimeSliceThread &Thread
                    )
    :   thread(&Thread),
        masterReader(&MasterReader){
    }
    
    ~PolyPlayerVoice(){
        
    }

    void initialise(int64 StartSample, int64 Length){
        
        reader = new AudioSubsectionReader(masterReader,StartSample, Length, false);
        audioFileSource = new AudioFormatReaderSource (reader,true);
        audioTransportSource.setSource(audioFileSource,32768, thread);
        
    }
    
    inline AudioTransportSource* getAudioSource(){ return &audioTransportSource; }
    
private:
    AudioFormatReader       *masterReader;
    TimeSliceThread         *thread;
    AudioSubsectionReader   *reader;
    AudioTransportSource    audioTransportSource;
    AudioFormatReaderSource *audioFileSource;
};

Am I correct in passing a shared TimeSliceThread to all instances of them or should I be creating a seperate thread for each one? (As they only need to read ahead when they are actually played right?)

As it stands I am getting a “bad access” crash in the getNextAudioBlock() function of the MixerAudioSource that each TransportAudioSource is passed into fairly quickly once I have created a couple of them here