Including an Audio Waveform component into a Audio Plugin


#1

Hello so currently I am trying to test out putting the AudioWaveformTutorial into an Audio Plugin (end goal is to be able to have the user to import their own sound library to the plugin). Currently I have the following header file included in the PluginEditor.cpp .

#ifndef H_SAMPLELIBRARY
#define H_SAMPLELIBRARY

>  class SampleLibrary :   public AudioAppComponent,
>                         private ChangeListener,
>                         private ButtonListener
> {
> public: 
>     SampleLibrary()
>         :state (Stopped),
>         thumbnailCache (5),     //AudioThumbnailCache number of thumbnails to store
>         thumbnail (512, formatManager, thumbnailCache)      //AudioThumbnail how many source samples to create 
>     {
>         formatManager.registerBasicFormats();
>         transportSource.addChangeListener(this);
>         thumbnail.addChangeListener (this);
>         
>         setAudioChannels (2,2);
>     }
>     ~SampleLibrary()
>     {
>         shutdownAudio();
>     }
>     void prepareToPlay (int samplesPerBlockExpected, double sampleRate) 
>     {
>         transportSource.prepareToPlay (samplesPerBlockExpected, sampleRate);
>     }
>     void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) 
>     {
>         if (readerSource == nullptr)
>             bufferToFill.clearActiveBufferRegion();
>         else 
>             transportSource.getNextAudioBlock(bufferToFill);
>     }
>     void releaseResources()
>     {
>         transportSource.releaseResources();
>     }
>     void changeListenerCallback (ChangeBroadcaster* source)
>     {
>         if (source == &transportSource) transportSourceChanged();
>         if (source == &thumbnail)       thumbnailChanged();
>     }
>     void buttonClicked (Button* button) override
>     {
>         if (button == &openButton)  openButtonClicked();
>         if (button == &playButton)  playButtonClicked();
>         if (button == &stopButton)  stopButtonClicked();
>     }
>     
>     private:
    >     enum TransportState
    >     {
    >         Stopped,
    >         Starting,
    >         Playing,
    >         Stopping
>     };
>     void changeState (TransportState newState)
>     {
>         if (state != newState)
>         {
>             state = newState;

>             switch (state)
>             {
>                 case Stopped:
>                     stopButton.setEnabled (false);
>                     playButton.setEnabled (true);
>                     transportSource.setPosition (0.0);
>                     break;

>                 case Starting:
>                     playButton.setEnabled (false);
>                     transportSource.start();
>                     break;

>                 case Playing:
>                     stopButton.setEnabled (true);
>                     break;

>                 case Stopping:
>                     transportSource.stop();
>                     break;

>                 default:
>                     jassertfalse;
>                     break;
>             }
>         }
>     }
>     void transportSourceChanged()
>     {
>         changeState (transportSource.isPlaying() ? Playing : Stopped);
>     }

>     void thumbnailChanged()
>     {
>         repaint();
>     }

>     void paintIfNoFileLoaded (Graphics& g, const Rectangle<int>& thumbnailBounds)
>     {
>         g.setColour (Colours::darkgrey);
>         g.fillRect (thumbnailBounds);
>         g.setColour (Colours::white);
>         g.drawFittedText ("No File Loaded", thumbnailBounds, Justification::centred, 1.0f);
>     }

>     void paintIfFileLoaded (Graphics& g, const Rectangle<int>& thumbnailBounds)
>     {
>         g.setColour (Colours::white);
>         g.fillRect (thumbnailBounds);

>         g.setColour (Colours::red);                                     // [8]

>         thumbnail.drawChannels (g,                                      // [9]
>                                 thumbnailBounds,
>                                 0.0,                                    // start time
>                                 thumbnail.getTotalLength(),             // end time
>                                 1.0f);                                  // vertical zoom
>     }

>     void openButtonClicked()
>     {
>         FileChooser chooser ("Select a Wave file to play...",
>                              File::nonexistent,
>                              "*.wav");

>         if (chooser.browseForFileToOpen())
>         {
>             File file (chooser.getResult());
>             AudioFormatReader* reader = formatManager.createReaderFor (file);

>             if (reader != nullptr)
>             {
>                 ScopedPointer<AudioFormatReaderSource> newSource = new AudioFormatReaderSource (reader, true);
>                 transportSource.setSource (newSource, 0, nullptr, reader->sampleRate);
>                 playButton.setEnabled (true);
>                 thumbnail.setSource (new FileInputSource (file));          // [7]
>                 readerSource = newSource.release();
>             }
>         }
>     }

>     void playButtonClicked()
>     {
>         changeState (Starting);
>     }

>     void stopButtonClicked()
>     {
>         changeState (Stopping);
>     }

>     //==========================================================================
>     TextButton openButton;
>     TextButton playButton;
>     TextButton stopButton;

>     AudioFormatManager formatManager;                    // [3]
>     ScopedPointer<AudioFormatReaderSource> readerSource;
>     AudioTransportSource transportSource;
>     TransportState state;
>     AudioThumbnailCache thumbnailCache;                  // [1]
>     AudioThumbnail thumbnail;                            // [2]

> };

the current errors I have are:

  • several “undeclared identifiers” (shutdownAudio, transportSource, etc.)
  • “expected class name” for the public AudioAppComponent

#2

Sorry for that wild mess. Essentially I am having trouble using child components while developing a plugin. I need to input component to plugin to either open one wav file or to access a whole library already stored on the computer. I also want to display the waveform of the wav file. I am using the auto-generated PluginProcessor and PluginEditor components by JUCE (if this is not a good way to create a plugin using child components please do tell me). I have gotten a string of errors in my attempt including multiple “undeclared identifiers” as well as a “expected class name” error that points towards public AudioAppComponent


#3

where is your #include JuceHeader.h ?

Also, are you including the proper modules in your ProJucer project file before you save and open in the IDE?


#4
  • “expected class name” for the public AudioAppComponent

This is the problem. The other errors relate to this missing class…


#5

You don’t want to be using AudioAppComponent in a plugin. It’s not needed and likely just going to be harmful anyway because it accesses the audio IO hardware.


#6

So what would be a good way to display a waveform in a plugin?


#7

There’s the AudioVisualiserComponent class, and also the dRowAudio oscilloscope class. Rolling your own isn’t too hard either, both those classes should give you an idea of how to do it.


#8

For a simple waveform to be displayed is it not possible to use the AudioThumbnail and the AudioThumbnailCache classes in a component? I constantly get “unknown type name” errors when including them in my component.


#9

Have you added the Juce audio_utils module into your project?