Loading the File - passivist/GRNLR GitHub Wiki
Now we declare the function we will be loading the File with. In addition to loading the file into an AudioSampleBuffer the resulting buffer should also be made available to the AudioProcessor object. The function is a member of AudioProcessorEditor so we'll put the declaration in the header file for the class. The function will also have a String argument to pass the path of the sound file into:
void loadAudioFile(String);We'll put the definition of the function in the .cpp file for the AudioProcessorEditor Class:
void GrrnlrrAudioProcessorEditor::loadAudioFile(String path)
{
}Here we can see some properties of the function:
- the function is
void, it produces no return values - the function is a member of
GrrnlrrAudioProcessorEditor1 our AudioProcessorEditor class - the function takes an argument
pathof typeString
In the function body we declare a variable which will hold information about the audio file we are trying to load:
const File file (path);We don't want the variable to change after we define it so we make the variable const which disallows just that. For loading the contents of a file into a buffer we need to find out some of it's properties most notably it's length and number of channels. Most of these properties can be accessed with the AudioFormatManager class we introduced earlier. We use the AudioFormatManager too create a pointer to an object of another class the AudioFormatReader. The AudioFormatReader is used to read the contents of a specific audio format the information of which is provided by the AudioFormatManager:
ScopedPointer<AudioFormatReader> reader(formatManager.createReaderFor(file));The ScopedPointer class implements a pointer that is automatically deleted when the program leaves scope. When using a ScopedPointer we don't have to worry about the pointer being accessed in some illegal way (for example when the object it points to is already deleted). We need to access the AudioFormatReader with a pointer because it is an 'abstract class'.
Next we'll define a pointer to an AudioSampleBuffer which has the length and channel configuration of the file we are trying to load:
ScopedPointer<AudioSampleBuffer> newBuffer = new AudioSampleBuffer(reader->numChannels, reader->lengthInSamples);The -> operator is a useful access specifier. It allows us to access a member of the object the ScopedPointer reader is pointing to without first dereferencing the pointer 2.
Finally we read all the samples in the sound file into the AudioSampleBuffer:
reader->read(&newBuffer, 0, reader->lengthInSamples, 0, true, true)The read function takes a number of arguments:
AudioSampleBuffer* buffer,
int startSample,
int numSamples,
int64 readerStartSample,
bool useReaderLeftChan,
bool useReaderRightChanLastly for debugging purposes we put a cout statement after the buffer is read that outputs some values as text to our console:
std::cout << "samples in buffer: " << newBuffer->getNumSamples() << std::endl;This way we can check if everything is working at this point.
Because we don't really want to worry about the GUI or different threads at this point we define the path variable and execute the loadAudioFile function from the constructor of the AudioProcessorEditor class:
String path = "/Users/raffaelseyfried/dev/eigene/GRRNLRR/Resources/Piano_D11_High.wav";
loadSample(path);The program should compile at this point and print the number of samples in your buffer 3.
Next we will work on playing the buffer.
<<< last Chapter next Chapter >>>
1: As specified by the :: 'scope qualifier'. Which means: loadAudioFile is in the scope of class GrrnlrrAudioProcessorEditor
2: In this situation we want to access a member of the object reader is pointing to. For that to work correctly we first have to dereference the object reader is pointing to and then access this object. Verbosely we might write (*reader).numChannels. -> is just a shorthand for that.
3: Of course you'll need to substitute the path in my example for a suitable path to a sound file on your system.