I’m making a sampler plugin with fixed .wav files included in it. It should be able to play these .wav files simultaneously according to MIDI messages received.
My question is If I put .wav files to Projucer how can I easily get the binary data from files and pass it on to AudioBuffer?
Totally untested, but it should work or be very close. At the end, buffer will contain a floating point copy the contents of the wav file in memory. Note that everything will be freed when leaving scope, so make sure to return buffer or something.
Thanks, but I am trying to see how the data_ptr to ‘static const unsigned char’ in my auto generated BinaryData.cpp can have flaoting point precision of say 16 bit?
Unsigned char has 0-255 range and is 8 bit right? I cannot figure that one out at all.
The data pointer is a binary file content, therefore it has the wave header included.
The AudioFormatReader uses that information. In the AudioBuffer it is always converted to float arrays.
If you want to use double arrays, you have to convert them yourself, since the AudioFormatReader doesn’t support double precision. At least that was stated in a recent thread, haven’t checked myself.
Very interesting.
I don’t have a quick way of listening to a sample played from such an array to judge, but did you hear the quality of such audio being played back? 8 bit audio is noticeably more noisy and distorted so you probably wouldn’t be too happy hearing it that way unless you work in audio designed in 8 bits (it’s a desired effect then).
If you did not hear any issues then most likely in some way it gets the source 16 or higher bit depth.
Like I said, the array from the binary data is not an audio stream. It is a file content of a WAV file, that is read and interpreted by the AudioFormatReader.
Yes, you are right, 8 bit audio would sound very different.
I am going to test the hell out of this as soon as I can to see how this conversion works.
"the array from the binary data is not an audio stream"
Yes, it is an array of unsigned char type values and audio stream would be signed floating point which could represent sinusoid with its positive and negative peaks. Projucer converts it from WAV file that way and then back if I understand correctly.
Sort of. Projucer is completely agnostic in terms of what you drag into the BinaryData file. There is the preview just for convenience. But in the array it is really the contents of the file, each byte a number.
There is no difference, if the AudioFormatReader reads from an actual file or from BinaryData, only that BinaryData is contained in the executable’s binary file.
I am struggling with this myself now, it’s crashing in wavFormat.createReaderFor as it seems to want to delete the inputstream object.
Just wondering if anyone can post another snippet?
Indeed, the createReaderFor is not yet converted to return an unique_ptr. But you can create one yourself:
void readAudioFile(AudioSampleBuffer& buffer, const void* data, size_t sizeBytes)
{
WavAudioFormat wavFormat;
auto* inputStream = new MemoryInputStream (data, sizeBytes, false); // createReaderFor will take ownership
std::unique_ptr<AudioFormatReader> reader (wavFormat.createReaderFor (inputStream, false));
if (reader.get() != nullptr)
{
buffer.setSize(reader->numChannels, reader->lengthInSamples);
reader->read(&buffer, 0, reader->lengthInSamples, 0, true, true);
}
else
{
// if createReaderFor failed, it will not delete, so you could use the inputStream in a fallback
delete inputStream;
}
// reader is automatically deleted by using uique_ptr
}
Hope that helps (and I didn’t make any typo / mistakes )
EDIT: and reading the docs simplifies things, the bool in createReaderFor allows the stream to be always deleted:
void readAudioFile(AudioSampleBuffer& buffer, const void* data, size_t sizeBytes)
{
WavAudioFormat wavFormat;
std::unique_ptr<AudioFormatReader> reader (wavFormat.createReaderFor (new MemoryInputStream (data, sizeBytes, false), true);
if (reader.get() != nullptr)
{
buffer.setSize(reader->numChannels, reader->lengthInSamples);
reader->read(&buffer, 0, reader->lengthInSamples, 0, true, true);
}
// reader is automatically deleted by using uique_ptr
}