From ba332196d2a36f2c022b685f0b6dab6c1cecb575 Mon Sep 17 00:00:00 2001 From: James Turk Date: Mon, 18 Jul 2005 05:14:18 +0000 Subject: [PATCH] audio:: source review --- SConstruct | 5 +- include/audio/AudioCore.hpp | 22 ++++- include/audio/SampleResourceManager.hpp | 8 +- include/audio/Source.hpp | 114 ++++++++++++++++++++---- include/photon.hpp | 1 - include/video/Font.hpp | 7 +- photon.mm | 9 +- src/audio/AudioCore.cpp | 17 ++-- src/audio/SampleResourceManager.cpp | 16 +++- test/Audio_test.cpp | 18 ++-- 10 files changed, 172 insertions(+), 45 deletions(-) diff --git a/SConstruct b/SConstruct index fe611b6..c58da00 100644 --- a/SConstruct +++ b/SConstruct @@ -5,7 +5,7 @@ # James Turk (jpt2433@rit.edu) # # Version: -# $Id: SConstruct,v 1.17 2005/07/05 06:44:55 cozman Exp $ +# $Id: SConstruct,v 1.18 2005/07/18 05:14:18 cozman Exp $ import os,os.path import glob @@ -77,6 +77,7 @@ if not env.GetOption('clean'): conf.env.Append(CPPFLAGS='-DPHOTON_USE_OPENAL') else: print 'OpenAL not found, continuing without OpenAL support.' + OAL_LIB = '' # no OpenAL library name env = conf.Finish() env.Append(CPPFLAGS='-pedantic') # tests fail pedantic, so add after tests @@ -102,7 +103,7 @@ test_srcs = glob.glob( os.path.join('test', '*_test.cpp') ) for test_src in test_srcs: test_name = test_src.replace('_test.cpp','') tests.append(env.Program(test_name, source=test_src, LIBPATH='./lib', - LIBS=['photon',OAL_LIB,'glfw',OGL_LIB,GLU_LIB, + LIBS=['photon','glfw',OAL_LIB,OGL_LIB,GLU_LIB, 'physfs','corona','freetype'])) env.Alias('test',tests) diff --git a/include/audio/AudioCore.hpp b/include/audio/AudioCore.hpp index 6d48c5d..89085a1 100644 --- a/include/audio/AudioCore.hpp +++ b/include/audio/AudioCore.hpp @@ -5,7 +5,7 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: AudioCore.hpp,v 1.7 2005/07/05 06:44:56 cozman Exp $ +// $Id: AudioCore.hpp,v 1.8 2005/07/18 05:14:18 cozman Exp $ #ifdef PHOTON_USE_OPENAL @@ -67,13 +67,31 @@ public: // Group: Error Checking public: + // Function: checkOpenALError + // Checks for OpenAL internal errors, returning a descriptive string if + // the OpenAL error state is currently set. Will return an empty string + // if there is no error set. + // + // Returns: + // String describing OpenAL error, empty string if no error exists. static std::string checkOpenALError(); + + // Function: throwOpenALError + // Checks for OpenAL internal errors, throwing an if the OpenAL + // error state is set and doing nothing if not. Optionally makes the + // thrown exception more descriptive by adding in a function string + // that describes then the OpenAL error was flagged. + // + // Parameters: + // func - Function in/after which the check for an OpenAL error takes place + // + // Throws: + // if an OpenAL error state has been set. static void throwOpenALError(const std::string& func); // OpenAL specifics private: util::VersionInfo initOpenAL(); - // data members private: diff --git a/include/audio/SampleResourceManager.hpp b/include/audio/SampleResourceManager.hpp index c5d2e73..3942fff 100644 --- a/include/audio/SampleResourceManager.hpp +++ b/include/audio/SampleResourceManager.hpp @@ -5,7 +5,9 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: SampleResourceManager.hpp,v 1.1 2005/07/05 06:44:56 cozman Exp $ +// $Id: SampleResourceManager.hpp,v 1.2 2005/07/18 05:14:18 cozman Exp $ + +#ifdef PHOTON_USE_OPENAL #ifndef PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP #define PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP @@ -18,6 +20,7 @@ namespace photon namespace audio { +// All that a Sample is is a bufferID, extremely simple resource management class SampleResource : public Resource { public: @@ -35,9 +38,12 @@ private: virtual void freeResourceData(SampleResource &res); }; +// Allow users to simply call a Sample a Sample typedef Source Sample; } } #endif //PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP + +#endif //PHOTON_USE_OPENAL diff --git a/include/audio/Source.hpp b/include/audio/Source.hpp index 9882683..3492108 100644 --- a/include/audio/Source.hpp +++ b/include/audio/Source.hpp @@ -5,14 +5,14 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: Source.hpp,v 1.2 2005/07/17 07:14:09 cozman Exp $ +// $Id: Source.hpp,v 1.3 2005/07/18 05:14:18 cozman Exp $ + +#ifdef PHOTON_USE_OPENAL #ifndef PHOTON_AUDIO_SOURCE_HPP #define PHOTON_AUDIO_SOURCE_HPP #include "AL/al.h" -#include "AL/alc.h" -#include "AL/alut.h" #include "ResourceManaged.hpp" #include "audio/AudioCore.hpp" @@ -23,9 +23,12 @@ namespace audio { // Class: Source -// Simple OO wrapper around an OpenAL source. -// -// Children: +// Simple OO wrapper around an OpenAL source, defines the interface used for +// Sample and Music. +// +// Source is a template class and can not be used directly, use either Sample +// or Music. Sample is for playing small files such as sound effects. Music +// is for streaming files such as background music. // // Operators: // - Source = Source @@ -74,7 +77,7 @@ public: Source& operator=(const Source& rhs); operator bool() const; - + // Group: Source Control public: @@ -104,6 +107,27 @@ public: // Group: Accessors public: + // Function: isValid + // Determine status of Source. + // + // Returns: + // True if source is loaded, false if source is not loaded/initialized. + bool isValid() const; + + // Function: isPlaying + // Determine if source is playing. + // + // Returns: + // True if source is playing, false if source is stopped. + bool isPlaying() const; + + // Function: isLooping + // Determine if source is looping. + // + // Returns: + // True if source is looping, false if source is not looping. + bool isLooping() const; + //friend std::ostream& operator<<(std::ostream& o, const Source& rhs); // Group: Resource Creation @@ -130,9 +154,9 @@ public: static void addResource(const std::string& path); private: - uint sourceID_; + uint sourceID_; // sources store their own sourceID (can't resource manage) - static const float ORIGIN[]; + static const float ORIGIN[]; // use origin }; template @@ -215,47 +239,101 @@ Source& Source::operator=(const Source& rhs) template Source::operator bool() const { - return alIsSource(sourceID_) == AL_TRUE; + return isValid(); } -/*std::ostream& operator<<(std::ostream& o, const Source& rhs) -{ - return o << "Source: { Name: " << rhs.getName() << " BufferID: " - << rhs.bufferID_; -}*/ - template void Source::play() { + if(!isValid()) + { + throw PreconditionException("Invalid Source::play call."); + } + alSourcePlay(sourceID_); } template void Source::stop() { + if(!isValid()) + { + throw PreconditionException("Invalid Source::stop call."); + } + alSourceStop(sourceID_); } template void Source::pause() { + if(!isValid()) + { + throw PreconditionException("Invalid Source::pause call."); + } + alSourcePause(sourceID_); } template void Source::rewind() { + if(!isValid()) + { + throw PreconditionException("Invalid Source::rewind call."); + } + alSourceRewind(sourceID_); } template void Source::setLooping(bool loop) { + if(!isValid()) + { + throw PreconditionException("Invalid Source::setLooping call."); + } + alSourcei(sourceID_, AL_LOOPING, loop); } template -void Source::addResource(const std::string& name, const std::string& path) +bool Source::isValid() const +{ + return alIsSource(sourceID_) == AL_TRUE; +} + +template +bool Source::isPlaying() const +{ + if(!isValid()) + { + throw PreconditionException("Invalid Source::isPlaying call."); + } + + // check state + int state; + alGetSourcei(sourceID_, AL_SOURCE_STATE, &state); + return state == AL_PLAYING; +} + +template +bool Source::isLooping() const +{ + if(!isValid()) + { + throw PreconditionException("Invalid Source::isLooping call."); + } + + // check looping status + int loop; + alGetSourcei(sourceID_, AL_LOOPING, &loop); + return loop == AL_TRUE; +} + +template +void Source::addResource(const std::string& name, + const std::string& path) { resMgr_.newResource(name, ResourceDescriptor(path)); } @@ -270,3 +348,5 @@ void Source::addResource(const std::string& path) } #endif //PHOTON_AUDIO_SOURCE_HPP + +#endif //PHOTON_USE_OPENAL diff --git a/include/photon.hpp b/include/photon.hpp index c7f577c..3cae671 100644 --- a/include/photon.hpp +++ b/include/photon.hpp @@ -16,7 +16,6 @@ #include "audio/SampleResourceManager.hpp" #include "audio/Source.hpp" #include "audio/AudioCore.hpp" -#include "audio/MusicResourceManager.hpp" #include "math/math.hpp" #include "math/Rect.hpp" #include "math/Vector2.hpp" diff --git a/include/video/Font.hpp b/include/video/Font.hpp index 5d0962a..cf96fc5 100644 --- a/include/video/Font.hpp +++ b/include/video/Font.hpp @@ -5,7 +5,7 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: Font.hpp,v 1.5 2005/07/17 07:14:09 cozman Exp $ +// $Id: Font.hpp,v 1.6 2005/07/18 05:14:18 cozman Exp $ #ifndef PHOTON_VIDEO_FONT_HPP #define PHOTON_VIDEO_FONT_HPP @@ -70,6 +70,11 @@ public: // name - Name of the Font to open. void open(const std::string& name); + // Function: isValid + // Determine status of Font. + // + // Returns: + // True if font is loaded, false if font is not loaded/initialized. bool isValid() const; Font& operator=(const Font &rhs); diff --git a/photon.mm b/photon.mm index 0e0ac4f..ba3d38c 100644 --- a/photon.mm +++ b/photon.mm @@ -6,10 +6,11 @@ + + + + - - - @@ -42,7 +43,7 @@ - + diff --git a/src/audio/AudioCore.cpp b/src/audio/AudioCore.cpp index 1a01471..cfcdb83 100644 --- a/src/audio/AudioCore.cpp +++ b/src/audio/AudioCore.cpp @@ -5,7 +5,7 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: AudioCore.cpp,v 1.7 2005/07/05 06:44:56 cozman Exp $ +// $Id: AudioCore.cpp,v 1.8 2005/07/18 05:14:18 cozman Exp $ #ifdef PHOTON_USE_OPENAL @@ -21,8 +21,10 @@ namespace audio AudioCore::AudioCore() { - util::VersionInfo oalReq(0,0,7); // requires OpenAL 1.0 (TODO: check?) - util::ensureVersion("OpenAL", initOpenAL(), oalReq); + //util::VersionInfo oalReq(0,0,7); // requires OpenAL 1.0 (TODO: check?) + //util::ensureVersion("OpenAL", initOpenAL(), oalReq); + + initOpenAL(); // don't check version for now } AudioCore::~AudioCore() @@ -50,9 +52,10 @@ std::string AudioCore::getAudioDeviceName() const std::string AudioCore::checkOpenALError() { - ALenum errCode = alGetError(); + ALenum errCode = alGetError(); // fetch error code std::string err; + // interpret error code switch(errCode) { case AL_NO_ERROR: @@ -73,7 +76,7 @@ std::string AudioCore::checkOpenALError() case AL_OUT_OF_MEMORY: err = "OpenAL out of memory"; break; - default: + default: // not sure how conforming implementations are with error codes err = "Unknown OpenAL error"; break; } @@ -84,7 +87,7 @@ std::string AudioCore::checkOpenALError() void AudioCore::throwOpenALError(const std::string& func) { std::string err( checkOpenALError() ); - if(err.length()) + if(err.length()) // throw exception if non-empty string { throw APIError(err + " within " + func); } @@ -127,6 +130,7 @@ util::VersionInfo AudioCore::initOpenAL() alListenerfv(AL_VELOCITY, posvel); alListenerfv(AL_ORIENTATION, ori); + // OpenAL needs a standard version string format badly ss << alGetString(AL_VERSION); #if defined(WINVER) ss >> junks >> major >> junkc >> minor; // format is "OpenAL 1.0" @@ -146,6 +150,7 @@ void AudioCore::setDesiredDevice(const std::string& name) deviceName_ = name; } +// static instance std::string AudioCore::deviceName_; } diff --git a/src/audio/SampleResourceManager.cpp b/src/audio/SampleResourceManager.cpp index 425abaf..eba4c5d 100644 --- a/src/audio/SampleResourceManager.cpp +++ b/src/audio/SampleResourceManager.cpp @@ -5,14 +5,16 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: SampleResourceManager.cpp,v 1.2 2005/07/06 02:10:07 cozman Exp $ +// $Id: SampleResourceManager.cpp,v 1.3 2005/07/18 05:14:18 cozman Exp $ + +#ifdef PHOTON_USE_OPENAL #include "audio/SampleResourceManager.hpp" #include "audio/AudioCore.hpp" #include "util/FileBuffer.hpp" #include "AL/al.h" -#include "AL/alut.h" +#include "AL/alut.h" // used for loading WAVs, to be phased out namespace photon { @@ -22,6 +24,7 @@ namespace audio void SampleResourceManager::getAudioData(const std::string& name, uint& bufferID) { + // not much to do here, get the resource, set the ID SampleResource resource( getResource(name) ); bufferID = resource.bufferID; } @@ -37,6 +40,7 @@ void SampleResourceManager::loadResourceData(SampleResource &res, ALsizei freq; ALboolean loop; + // load from FileBuffer (allows loading from zip via PhysFS) std::vector filedata = buf.getData(); size = filedata.size(); @@ -44,8 +48,9 @@ void SampleResourceManager::loadResourceData(SampleResource &res, AudioCore::throwOpenALError("alGenBuffers"); - alutLoadWAVMemory((ALbyte*)&filedata[0], &format, &data, &size, &freq, &loop); - + // load WAV via alut + alutLoadWAVMemory(reinterpret_cast(&filedata[0]), + &format, &data, &size, &freq, &loop); AudioCore::throwOpenALError("alutLoadWAVFile"); alBufferData(res.bufferID, format, data, size, freq); @@ -58,9 +63,12 @@ void SampleResourceManager::freeResourceData(SampleResource& res) { if(alIsBuffer(res.bufferID)) { + // delete buffers, just like textures in GL alDeleteBuffers(1, &res.bufferID); } } } } + +#endif //PHOTON_USE_OPENAL diff --git a/test/Audio_test.cpp b/test/Audio_test.cpp index bcf70e3..1860eeb 100644 --- a/test/Audio_test.cpp +++ b/test/Audio_test.cpp @@ -5,7 +5,7 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: Audio_test.cpp,v 1.2 2005/07/17 07:14:09 cozman Exp $ +// $Id: Audio_test.cpp,v 1.3 2005/07/18 05:14:19 cozman Exp $ #include "photon.hpp" using namespace photon; @@ -51,7 +51,10 @@ public: rain.setLooping(true); stream.setLooping(true); thunder.setLooping(true); + + assert(!waterdrop.isLooping()); waterdrop.setLooping(true); + assert(waterdrop.isLooping()); for(int i=0; i < 6; ++i) status[i] = "NOT "; @@ -68,7 +71,7 @@ public: if(app.keyPressed(KEY_C)) { - if(status[0] == NOT_PLAYING) + if(!chimes.isPlaying()) { chimes.play(); status[0] = ""; @@ -81,7 +84,7 @@ public: } if(app.keyPressed(KEY_O)) { - if(status[1] == NOT_PLAYING) + if(!ocean.isPlaying()) { ocean.play(); status[1] = ""; @@ -94,7 +97,7 @@ public: } if(app.keyPressed(KEY_R)) { - if(status[2] == NOT_PLAYING) + if(!rain.isPlaying()) { rain.play(); status[2] = ""; @@ -107,7 +110,7 @@ public: } if(app.keyPressed(KEY_S)) { - if(status[3] == NOT_PLAYING) + if(!stream.isPlaying()) { stream.play(); status[3] = ""; @@ -120,7 +123,7 @@ public: } if(app.keyPressed(KEY_T)) { - if(status[4] == NOT_PLAYING) + if(!thunder.isPlaying()) { thunder.play(); status[4] = ""; @@ -133,7 +136,7 @@ public: } if(app.keyPressed(KEY_W)) { - if(status[5] == NOT_PLAYING) + if(!waterdrop.isPlaying()) { waterdrop.play(); status[5] = ""; @@ -210,6 +213,7 @@ public: ENTRYPOINT(AudioTest) #else +#include int main() {