Trying to play an audiofile -- stumped!


#1

I have tried to play an audiofile by referring to the JUCE AudioDemoPlaybackPage module and adding to a barebones GUI window created by the IntroJucer. My intent is to see a window with "Hello, World!" and hear the audiofile (played automatically when run).

This compiles without error, and when I run it, I see "Hello, World!", but hear nothing. Am I getting close?

Here are my MainComponent.h and MainComponent.cpp files.

MainComponent.h:

class MainContentComponent   : public Component
{
public:
    MainContentComponent();
    ~MainContentComponent();
    void paint (Graphics&);
    void resized();
    void playAudioFile();
private:
    AudioDeviceManager deviceManager;
    AudioFormatManager formatManager;
    TimeSliceThread thread;
    AudioSourcePlayer audioSourcePlayer;
    AudioTransportSource transportSource;
    ScopedPointer<AudioFormatReaderSource> currentAudioFileSource;  
    File audioFile;
//==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};

Here is MainComponent.cpp:

#include "MainComponent.h
"MainContentComponent::MainContentComponent()  : thread("audio")
{
    setSize (500, 400);

    AudioDeviceManager deviceManager;
    deviceManager.initialise ( 2, 0, nullptr, true, "", 0 );
    
    formatManager.registerBasicFormats();

    deviceManager.addAudioCallback (&audioSourcePlayer);
    audioSourcePlayer.setSource (&transportSource);

    thread.startThread (3);
}

MainContentComponent::~MainContentComponent()
{
    transportSource.setSource (nullptr);
    audioSourcePlayer.setSource (nullptr);

    deviceManager.removeAudioCallback (&audioSourcePlayer);
}

void MainContentComponent::paint (Graphics& g)
{
    g.fillAll (Colour (0xffeeddff));
    g.setFont (Font (16.0f));
    g.setColour (Colours::black);
    g.drawText ("Hello World!", getLocalBounds(), Justification::centred, true);
}

void MainContentComponent::resized()
{
}

void MainContentComponent::playAudioFile()
{
    transportSource.stop();
    transportSource.setSource (nullptr);
    currentAudioFileSource = nullptr;

    const File& audioFile = String("~/Test.wav");
    AudioFormatReader* reader = formatManager.createReaderFor (audioFile);

    if (reader != nullptr)
    {
        currentAudioFileSource = new AudioFormatReaderSource (reader, true);

        transportSource.setSource (currentAudioFileSource, 32768, &thread, reader->sampleRate);
    }

    transportSource.setPosition (0);
    transportSource.start();
}

 


#2

 

Looks close.

 

First - you don't include the run() function (which is what the thread uses) so I'm not sure what you are doing in the thread.  There is no need to run the playAudioFile() routine in a separate thread though, you could just call that in the constructor.

 

Also - I don't think the "~" in the load file portion will be interpretted correctly.  Check out SpecialLocationTypes in File.

 

You're nearly threre!  You'll have it soon.

 


#3

Thank you, Aaron, for your kind and generous reply!

For the benefit of others, yes, as far as I can tell, in JUCE, only some OS (Linux is one) will interpret the '~' in '~/Test.wav' correctly as the 'home' directory, and that simplification shouldn't be used for 'universal' code.

And yes, I really don't understand TimeSliceThread. I am trying to 'run' TimeSliceThread 'thread' by saying

thread.startThread (3);

in the constructor MainContentComponent::MainContentComponent(), but that obviously doesn't work. All I know is that '&thread' is part of the crucial line:

transportSource.setSource (
   currentAudioFileSource,
   32768, // tells it to buffer this many samples ahead
   &thread, // this is the background thread to use for reading-ahead
   reader->sampleRate
);

I seriously don't understand what's going on with '&thread' in that line.

I've also tried to understand by paring down the JUCE demo until it ONLY plays an audiofile and that's all it does. But I'm stuck there, too. I can get it to play "~/Test.wav", but only by means of the "Play/Stop" button, and only then after (not before) a file is highlighted.

What I did was modify 'showFile' in AudioDemoPlaybackPage.cpp in this way:

void AudioDemoPlaybackPage::showFile (const File& file)
{
    // loadFileIntoTransport (file);
    loadFileIntoTransport (String("~/Test.wav") );
}

Then, after I highlight (any) file shown in the FileTreeComponent (it doesn't matter at all what file), the "Play/Stop" button will play "Test.wav", every time I push the button. But no sound plays until I first highlight some (any) file, which seems to activate 'showFile', and then all is good.

So there's something about loadFileIntoTransport that I can't reproduce manually. A button click has to be involved (through 'showFile'), and I don't understand why.

I will keep working!