Amr Ezzat
Amr Ezzat

Reputation: 3

How to read the length of audio files using Juce "C++." Without playing the file

I'm trying to display the length of audio files in a Playlist component for an application. I've not used Juce or C++ before, and I can't understand how to do that from Juce documentation. I want to make a function that takes an audio file's URL and returns the length in seconds of that audio without playing that file or doing anything else with that file. I've tried a lot of things, and all of them didn't work, and this is the last thing I've tried:

void PlaylistComponent::trackStats(URL audioURL)
{
    AudioFormatManager formatManager;
    std::unique_ptr<AudioFormatReaderSource> readerSource;
    AudioTransportSource transportSource;

    auto* reader = formatManager.createReaderFor(audioURL.createInputStream(false));
    if (reader != nullptr) 
    {
        std::unique_ptr<AudioFormatReaderSource> newSource(new AudioFormatReaderSource(reader, true));
        transportSource.setSource(newSource.get(), 0, nullptr, reader->sampleRate);
        readerSource.reset(newSource.release());

        DBG("PlaylistComponent::trackStats(URL audioURL): " << transportSource.getLengthInSeconds());
    }
    else
    {
        DBG("Something went wrong loading the file");
    }
}

And this is the PlaylistComponent header file:

class PlaylistComponent  : public juce::Component, 
                           public juce::TableListBoxModel,
                           public Button::Listener,
                           public FileDragAndDropTarget
{
  ...
}

Upvotes: 0

Views: 1130

Answers (2)

WaterNotWords
WaterNotWords

Reputation: 1007

You can do this very early on in the audio file opening procedure. You only need an AudioFormatReader instance (no need to create an AudioFormatReaderSource):

    // create juce::File from a path juce::String (from a drag & drop event etc).
    File file{filePath};
    // make sure it is a file and not a directory, etc.
    if (!file.existsAsFile()) return;

    // create the AudioFormatReader that contains the data
    AudioFormatReader *reader = formatManagerInstance.createReaderFor(file);
    // make sure a valid reader can be created (not an unsupported file)
    if (reader == nullptr) return;

    // log the length in seconds
    std::cout << reader->lengthInSamples / reader->sampleRate << "\n";

Note: for this to work you will need to

  1. have access to your AudioFormatManager instance and
  2. have already registered the format(s) of the file type (usually through a .registerBasicFormats() call on your AudioFormatManager instance.

IMPORTANT: if successful the createReaderFor() method uses new to create a new AudioFormatReaderInstance, so make sure to use delete on it when you are finished using it to avoid memory leaks

Upvotes: 0

Ruurd Adema
Ruurd Adema

Reputation: 1025

juce::AudioFormatReaderSource has a method called getTotalLength() which returns the total amount of samples. Divide that by the sample rate of the file and you have the total length in seconds. Something like this:

if (auto* reader = audioFormatReaderSource->getAudioFormatReader())
    double lengthInSeconds = static_cast<double> (audioFormatReaderSource->getTotalLength()) / reader->sampleRate;

Upvotes: 1

Related Questions