Sound.h

#pragma once
#ifndef SOUND_H
#define SOUND_H

#include <allegro5/allegro_audio.h>
#include <allegro5/allegro_acodec.h>
#include <string>
#include <vector>

// Class for playing music and sound effects
// Requires Allegro5

class SoundPlayer {
public:
	SoundPlayer();
	void playEffect(std::string filename);
	void playMusic(std::string filename);
	bool musicIsPlaying();
	void stopMusic();
        void stopEffects();
	float getMusicVolume();
	float getEffectVolume();
	void setMusicVolume(float v);
	void setEffectVolume(float v);
private:
	float musicVolume;
	float effectVolume;
	ALLEGRO_SAMPLE_ID songID;
	ALLEGRO_SAMPLE *loadedSong;
	std::vector loadedFX;
};

#endif

Sound.cpp

#include "Sound.h"
#include <iostream>

// Sound volume configuration variables
const float DEFAULT_MUSIC_VOLUME = 1.0;
const float DEFAULT_SOUND_EFFECT_VOLUME = 1.0;
const int SOUND_CHANNEL_COUNT = 4;

// Constructor will reserve the sound channels
SoundPlayer::SoundPlayer() {
	al_reserve_samples(SOUND_CHANNEL_COUNT);
	loadedSong = NULL;
	musicVolume = DEFAULT_MUSIC_VOLUME;
	effectVolume = DEFAULT_SOUND_EFFECT_VOLUME;
}

// Begin looping a music file
void SoundPlayer::playMusic(std::string filename) {
	// Stop currently playing music if it exists
	stopMusic();
	// Try to load the music, with error checking
	loadedSong = al_load_sample(filename.c_str());
	if (!loadedSong) { std::cout << "Error: Unable to load sound file: " << filename << std::endl; }
	al_play_sample(loadedSong, musicVolume, 0.0, 1.0, ALLEGRO_PLAYMODE_LOOP, &songID);
}

// Stop playing music
void SoundPlayer::stopMusic() {
	// If the song isn't loaded, then it can't be stopped. Otherwise stop it
	if (loadedSong != NULL) { 
		loadedSong = NULL;
		al_stop_sample(&songID);
		al_destroy_sample(loadedSong); 
	}
}

// Stop playing sound effects
void SoundPlayer::stopEffects() {
	for (unsigned int i = 0; i < loadedFX.size(); i++) { al_destroy_sample(loadedFX.at(i)); }
	loadedFX.clear();
}

// Play a sound effect once
void SoundPlayer::playEffect(std::string filename) {
	// Try to load the music, with error checking
	ALLEGRO_SAMPLE *newFX = al_load_sample(filename.c_str());
	if (!newFX) { std::cout << "Error: Unable to load sound file: " << filename << std::endl; }
	// If too many samples are loaded, delete the oldest one
	if (loadedFX.size() >= SOUND_CHANNEL_COUNT - 1) { 
		al_destroy_sample(loadedFX.at(0)); 
		loadedFX.erase(loadedFX.begin());
	}
	loadedFX.push_back(newFX);
	// Finally, play the newly added effect
	al_play_sample(loadedFX.at(loadedFX.size()-1), effectVolume, 0.0, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL);
}

// Get whether or not music is playing
bool SoundPlayer::musicIsPlaying() { return (loadedSong != NULL); }

// Volume getter and setter methods
float SoundPlayer::getMusicVolume() { return musicVolume; }
float SoundPlayer::getEffectVolume() { return effectVolume; }
void SoundPlayer::setMusicVolume(float v) { musicVolume = v; }
void SoundPlayer::setEffectVolume(float v) { effectVolume = v; }