Best way to read an audio file to memory

Hi all,

My intent, as a JUCE newbie, is to load an entire audio file to memory and then do some operations on it. During my experiments with the library I’ve come up with basically two ways: AudioFormatReader and MemoryMappedAudioFormatReader. This is how my code looks like, so far:

AudioFormatManager formatManager;
formatManager.registerBasicFormats();

AudioFormat *audioFormat = formatManager.getDefaultFormat();

#if MEMORY_MAPPED
MemoryMappedAudioFormatReader *reader = audioFormat->createMemoryMappedReader(File("/path/to/my/file.wav"));
reader->mapEntireFile();
#else
AudioFormatReader *reader = formatManager.createReaderFor(File("/path/to/my/file.wav"));
#endif

AudioSampleBuffer buffer;
reader->read(buffer, 0, reader->lengthInSamples, 0, true, true);
delete reader; 

Now my questions:

  • I just want to grab the file from disk and drop it into memory: is the MemoryMapped version the best choice?
  • Why do I need to fill an AudioSampleBuffer in case of the MemoryMapped version? Can I just read data straight from memory, instead?

Thanks in advance!

For you, there will be really no difference between the two. It’s probably easiest to use the AudioFormatReader and just read the entire file.

The distinction between the two becomes more important if you are streaming from audio files. “Memory mapped” in this case does not necessarily mean that the whole audio file is in physical memory. It means that the audio file will be “memory mapped” with native OS routines (see this article). It’s basically up to the operating system when to read in the data into physical memory and when to discard it again if it hasn’t been used in a while. OSes have lot’s of intelligent logic on how this is managed and having a MemoryMappedAudioFormatReader means you can make use of this.

Memory mapping files can be useful for samplers. As the OS will automatically keep the most used samples in memory and discard old unused ones if memory becomes tight.

Hi @fabian, thanks for the information, you definitely shed some light on the topic. So If I’ve understood correctly, a MemoryMappedAudioFormatReader is the right tool also if you have to manage large files but you don’t want to deal with the disk-streaming business: you basically let the OS do it for you, right?

However, according to this reply, a memory map seems helpful only on 64-bit systems. Does this still hold true?

Yes that’s true. MemoryMappedAudioFormatReader really only makes sense if you have a lot of virtual memory space.

Out of curiosity, what’s the best scenario for Multi-Track app?
Such as Tracktion, where you have a project that uses let say 20GB of audio files.

Since you don’t want to load everything to memory I guess.

I too would be interested… Any insight into this?

In tracktion on 64-bit systems, we just map everything into memory with MemoryMappedFileReaders.

On 32-bit systems (hopefully we can deprecate this one day!) we map large chunks of files that we need, and choose different chunks when the playhead moves.

In both cases we have a thread whose job it is to look slightly ahead of the play cursor and touch bits of files that may be played soon, so that the VM system will get those areas into memory ready for use.

4 Likes

Hey @jules, that’s interesting:

What do you mean by that? The first thing that comes to my mind is a simple “wake-up call” to the audio buffer with ``AudioBuffer::getSample (…)` (or similar). Would it be enough?

MemoryMappedAudioFormatReader::touchSample()

3 Likes