SimpleAudio


#1

I’ve used Juce for a long time now, and feel like i’m probably the only one who hasn’t been interested in doing audio stuff with it!

I’m still not really (one day…), but i wanted a way to put sounds into my programs. As easy as juce is to use, i think the audio stuff is probably the scariest part of it! :-o

So i’ve made this. It’s called SimpleAudio. It’s a really basic (probably a bit crude… feel free to improve it, this is literally my first ever audio coding) way to add simple sound-file playback to an app.

Here are the files.

Steps to use:

[list]
#include “SimpleAudio.h”, and make sure the files are in your project.

Create a SimpleAudioManager. Either make your base Component inherit SimpleAudioManager, or give it a member SimpleAudioManager [it just needs to exist, outside the scope of all SimpleAudioObjects]

Then it’s just a simple case of creating and using SimpleAudioObjects. Give your Components a member SimpleAudioObject for each sound you want to play. Set their files, and call myAudioObject.play() to play the sound.
[/list]

That’s all there is to it.

The SimpleAudioPlayer is a Singleton, so the SimpleAudioObjects can find it themselves. The SimpleAudioManager is simply there to ensure that the SimpleAudioPlayer instance is created and destroyed properly at each end of the program’s duration. However, it could be enhanced to allow for event callbacks from the player (e.g. audioObjectPlaybackStarted (SimpleAudioObject*)).

For now though, this will do! Hopefully it should be sufficient for newbies to get basic sound events in their apps.


#2

[quote=“haydxn”]I’ve used Juce for a long time now, and feel like i’m probably the only one who hasn’t been interested in doing audio stuff with it!
[/quote]

Not really. I write medical research apps with it. Your stuff is at least fun. Mine’s boring. :wink:


#3

yeah, but noone wants to pay me for my stuff, fun or not! :cry: one day i’ll be able to make a living doing this stuff…

… one day!

Heck, if it didn’t change so bloody much all the time, i’d probably be motivated enough to write a proper guide book for it! :hihi:


#4

I get paid to do audio/graphical fun with JUCE. 8)

But I also have databasey (audio database though!) crap to do though.


#5

probably we will adopt juce to port a GIS maintenance application… so i should get paid for trickling with it in the next weeks :wink:


#6

No web space at the moment, so i thought i’d post the code for this as text to copy/paste (it’s a rubbish substitute but it’ll do for now). sorry it makes for long posts!

Note: These files assume a structure like this…

FOLDER: /./

  • SimpleAudio.h
    FOLDER: /./SimpleAudio
  • SimpleAudioPlayer.h
  • SimpleAudioPlayer.cpp
  • SimpleAudioObject.h
  • SimpleAudioObject.cpp

#7

./SimpleAudio.h

#ifndef _SIMPLEAUDIO_H_
#define _SIMPLEAUDIO_H_

#include "./SimpleAudio/SimpleAudioPlayer.h"
#include "./SimpleAudio/SimpleAudioObject.h"

#endif//_SIMPLEAUDIO_H_

#8

./SimpleAudio/SimpleAudioPlayer.h

#ifndef _SIMPLEAUDIOPLAYER_H_
#define _SIMPLEAUDIOPLAYER_H_

#include "juce.h"

class SimpleAudioObject;

//===================================================================
class SimpleAudioPlayer	:	public AudioIODeviceCallback
{
public:

	SimpleAudioPlayer ();
	~SimpleAudioPlayer ();

	//============================
	// Controls
	//============================
	void play (SimpleAudioObject* audio);
	void stop (SimpleAudioObject* audio);

	bool isAudioEnabled ();
	bool isBeingManaged ();

	//============================
	// Audio callbacks...
	//============================
    void audioDeviceIOCallback (const float** inputChannelData,
                                int totalNumInputChannels,
                                float** outputChannelData,
                                int totalNumOutputChannels,
                                int numSamples);
    void audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock);
    void audioDeviceStopped();

	friend class SimpleAudioManager;

	juce_DeclareSingleton (SimpleAudioPlayer, false);

private:

	AudioDeviceManager	deviceManager;
	AudioSourcePlayer	player;
	MixerAudioSource	mixer;

	Array<SimpleAudioObject*> activeAudio;

	bool hasDevice;
	SimpleAudioManager* manager;

};

class SimpleAudioManager
{
public:

	SimpleAudioManager ();
	~SimpleAudioManager ();

private:

};

#endif//_SIMPLEAUDIOPLAYER_H_

#9

./SimpleAudio/SimpleAudioObject.h

#ifndef _SIMPLEAUDIOOBJECT_H_
#define _SIMPLEAUDIOOBJECT_H_

#include "juce.h"

class SimpleAudioPlayer;

//===================================================================
class SimpleAudioObject
{
public:

	SimpleAudioObject ();
	~SimpleAudioObject ();

	//============================
	// File handling
	//============================
	void setFile (const File& thisFile);
	File getFile ();

	//============================
	void play ();
	void stop ();

	//============================
	void clear ();

	friend class SimpleAudioPlayer;

private:

	//============================
	// Audio preparation
	//============================
	void prepare ();
	void release ();

	AudioFormatReaderSource* audioSource;
	AudioTransportSource transport;
	File currentFile;

	double sampleRate;
	int blockSamples;
};

#endif//_SIMPLEAUDIOOBJECT_H_

#10

./SimpleAudio/SimpleAudioPlayer.cpp

#include "SimpleAudioPlayer.h"
#include "SimpleAudioObject.h"

SimpleAudioPlayer::SimpleAudioPlayer ()
{
    AudioFormatManager formatManager;
    formatManager.registerBasicFormats();

	String error = deviceManager.initialise (1,2,0);
	if (error != String::empty)
	{
		// failed to initialise default device!
		hasDevice = false;
	}
	else
	{
		hasDevice = true;
		// link the mixer to the player...
		player.setSource (&mixer);
		// get the audio device to use our callback...			
		deviceManager.setAudioCallback (this);			
	}
}

SimpleAudioPlayer::~SimpleAudioPlayer ()
{
	mixer.removeAllInputs ();
	deviceManager.setAudioCallback (0);
	player.setSource (0);

	clearSingletonInstance ();
}

//============================
// Controls
//============================
void SimpleAudioPlayer::play (SimpleAudioObject* audio)
{
	if (!isBeingManaged ())
	{
		jassertfalse;
		// The SimpleAudioPlayer engine has no manager. You should ensure
		// that one exists at the base of your program to ensure that
		// the player will be tidied away correctly. Either add a member
		// SimpleAudioManager to your base Component, or subclass it.
		return;
	}
	if (activeAudio.contains (audio))
	{
		// audio is already playing...
		audio->transport.setPosition (0.0);
		audio->transport.start ();
	}
	else
	{
		// audio is not currently playing
		activeAudio.add (audio);
		audio->prepare ();
		mixer.addInputSource (&(audio->transport), false);
		audio->transport.setPosition (0.0);
		audio->transport.start ();
	}
}

void SimpleAudioPlayer::stop (SimpleAudioObject* audio)
{
	if (activeAudio.contains (audio))
	{
		audio->transport.stop ();
		mixer.removeInputSource (&(audio->transport), false);
		activeAudio.removeValue (audio);
		audio->release ();
	}
}

bool SimpleAudioPlayer::isAudioEnabled ()
{
	return hasDevice;
}

bool SimpleAudioPlayer::isBeingManaged ()
{
	return (manager != 0);
}

//============================
// Audio callbacks...
//============================
void SimpleAudioPlayer::audioDeviceIOCallback (	const float** inputChannelData,
											    int totalNumInputChannels,
					                            float** outputChannelData,
												int totalNumOutputChannels,
					                            int numSamples)
{
    // pass the audio callback on to our player...
    player.audioDeviceIOCallback (
		inputChannelData, 
		totalNumInputChannels, 
		outputChannelData, 
		totalNumOutputChannels, 
		numSamples);
}

void SimpleAudioPlayer::audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock)
{
    player.audioDeviceAboutToStart (sampleRate, numSamplesPerBlock);
}

void SimpleAudioPlayer::audioDeviceStopped()
{
    player.audioDeviceStopped();
}

juce_ImplementSingleton (SimpleAudioPlayer);


//===================================================================
SimpleAudioManager::SimpleAudioManager ()
{
	DBG (T("Starting audio manager..."));
	SimpleAudioPlayer* player = SimpleAudioPlayer::getInstance ();
	if (player == 0)
	{
		// failed to create SimpleAudioPlayer!
		DBG (T("[SimpleAudioManager] failed to create SimpleAudioPlayer!"));
	}
	else
	{
		player->manager = this;

		if (player->isAudioEnabled ())
		{
			// device successfully opened

		}
		else
		{
			// failed to open device...

		}
	}
}

SimpleAudioManager::~SimpleAudioManager ()
{
	SimpleAudioPlayer::deleteInstance ();
}

#11

./SimpleAudio/SimpleAudioObject.cpp

#include "SimpleAudioObject.h"
#include "SimpleAudioPlayer.h"

const int numBufferSamples = 32768;
const int defaultBlockSamples = 1024;

//===================================================================
SimpleAudioObject::SimpleAudioObject ()
{
	audioSource = 0;
}

SimpleAudioObject::~SimpleAudioObject ()
{
	clear ();
}

//===================================================================
void SimpleAudioObject::setFile (const File& thisFile)
{
	clear ();

    AudioFormatManager formatManager;
    formatManager.registerBasicFormats();

    AudioFormatReader* reader = formatManager.createReaderFor (thisFile);

    if (reader != 0)
    {
		// success in reading the file!
		DBG (T("[SimpleAudioObject] File load success : ") + thisFile.getFileName());
        currentFile = thisFile;
		// create the audio source from the file...
        audioSource = new AudioFormatReaderSource (reader, true);
        transport.setSource (audioSource,
                             numBufferSamples,
                             reader->sampleRate);
		sampleRate = reader->sampleRate;
		blockSamples = defaultBlockSamples;
    }
	else
	{
		// failed to read file!
		DBG (T("[SimpleAudioObject] File load failed : ") + thisFile.getFileName ());
	}
}

File SimpleAudioObject::getFile () 
{
	return currentFile;
}

//===================================================================
void SimpleAudioObject::play ()
{
	SimpleAudioPlayer::getInstance ()->play (this);
}

void SimpleAudioObject::stop ()
{
	SimpleAudioPlayer::getInstance ()->stop (this);
}

//===================================================================
void SimpleAudioObject::clear ()
{
	currentFile = File::nonexistent;
	transport.stop ();
	transport.setSource (0);
	if (audioSource)
		deleteAndZero (audioSource);
}

//===================================================================
void SimpleAudioObject::prepare ()
{
	transport.prepareToPlay (blockSamples, sampleRate);
}

void SimpleAudioObject::release ()
{
	transport.releaseResources ();
}

#12

Replacing local file with an http URL?


#13