diff --git a/SConstruct b/SConstruct index 04ec7e8..fe611b6 100644 --- a/SConstruct +++ b/SConstruct @@ -5,7 +5,7 @@ # James Turk (jpt2433@rit.edu) # # Version: -# $Id: SConstruct,v 1.16 2005/07/04 06:33:06 cozman Exp $ +# $Id: SConstruct,v 1.17 2005/07/05 06:44:55 cozman Exp $ import os,os.path import glob @@ -73,7 +73,7 @@ if not env.GetOption('clean'): if not conf.CheckLibWithHeader('corona', 'corona.h', 'C++'): print 'Corona not found, exiting.' Exit(1) - if conf.CheckLibWithHeader(OAL_LIB, 'zAL/al.h', 'C++'): + if conf.CheckLibWithHeader(OAL_LIB, 'AL/al.h', 'C++'): conf.env.Append(CPPFLAGS='-DPHOTON_USE_OPENAL') else: print 'OpenAL not found, continuing without OpenAL support.' diff --git a/include/audio/AudioCore.hpp b/include/audio/AudioCore.hpp index ec876b7..6d48c5d 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.6 2005/07/04 03:06:48 cozman Exp $ +// $Id: AudioCore.hpp,v 1.7 2005/07/05 06:44:56 cozman Exp $ #ifdef PHOTON_USE_OPENAL @@ -64,15 +64,23 @@ public: // Parameters: // name - Name of audio device to use. static void setDesiredDevice(const std::string& name); + +// Group: Error Checking +public: + static std::string checkOpenALError(); + static void throwOpenALError(const std::string& func); // OpenAL specifics private: util::VersionInfo initOpenAL(); - static std::string checkOpenALError(); + // data members private: static std::string deviceName_; + ALfloat listenerPos_[3]; + ALfloat listenerVel_[3]; + ALfloat listenerOri_[6]; }; diff --git a/include/audio/SampleResourceManager.hpp b/include/audio/SampleResourceManager.hpp new file mode 100644 index 0000000..c5d2e73 --- /dev/null +++ b/include/audio/SampleResourceManager.hpp @@ -0,0 +1,43 @@ +//This file is part of Photon (http://photon.sourceforge.net) +//Copyright (C) 2004-2005 James Turk +// +// Author: +// James Turk (jpt2433@rit.edu) +// +// Version: +// $Id: SampleResourceManager.hpp,v 1.1 2005/07/05 06:44:56 cozman Exp $ + +#ifndef PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP +#define PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP + +#include "ResourceManager.hpp" +#include "audio/Source.hpp" + +namespace photon +{ +namespace audio +{ + +class SampleResource : public Resource +{ +public: + uint bufferID; +}; + +class SampleResourceManager : public ResourceManager +{ +public: + void getAudioData(const std::string& name, uint& bufferID); + +private: + virtual void loadResourceData(SampleResource &res, + const ResourceDescriptor& path); + virtual void freeResourceData(SampleResource &res); +}; + +typedef Source Sample; + +} +} + +#endif //PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP diff --git a/include/audio/Source.hpp b/include/audio/Source.hpp new file mode 100644 index 0000000..0c720b6 --- /dev/null +++ b/include/audio/Source.hpp @@ -0,0 +1,272 @@ +//This file is part of Photon (http://photon.sourceforge.net) +//Copyright (C) 2004-2005 James Turk +// +// Author: +// James Turk (jpt2433@rit.edu) +// +// Version: +// $Id: Source.hpp,v 1.1 2005/07/05 06:44:56 cozman Exp $ + +#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" + +namespace photon +{ +namespace audio +{ + +// Class: Source +// Simple OO wrapper around an OpenAL source. +// +// Children: +// +// Operators: +// - Source = Source +// - bool : True if source has loaded buffer, false if not. +// - ostream& << Source +template +class Source : public ResourceManaged +{ +// Group: (Con/De)structors +public: + + // Function: Source + // Default constructor, initalizes internal state of Source. + Source(); + + // Function: Source + // Copy constructor, copies another Source. + // + // Parameters: + // rhs - Source to construct copy of. + Source(const Source &rhs); + + // Function: Source + // Initializing constructor, loads Source via call to . + // + // Parameters: + // name - Name of the Source to open. + // + // See Also: + // + Source(const std::string& name); + + // Function: ~Source + // Destructor for source, frees the OpenAL source resource. + ~Source(); + +// Group: General +public: + + // Function: open + // Opens an audio file, supported formats are WAV and Ogg. + // + // Parameters: + // name - Name of the Source to open. + void open(const std::string& name); + + Source& operator=(const Source& rhs); + operator bool() const; + +// Group: Source Control +public: + + // Function: play + // Starts the playback of the sound attached to the source. + void play(); + + // Function: stop + // Stops the playback of the sound attached to the source. + void stop(); + + // Function: pause + // Pauses the playback of the sound attached to the source. + void pause(); + + // Function: rewind + // Rewinds the position of the sound attached to the source. + void rewind(); + + // Function: setLooping + // Sets if the source's sound is looping or is played only once. + // + // Parameters: + // loop - If true, will make sound loop, otherwise will play only once. + void setLooping(bool loop); + +// Group: Accessors +public: + + //friend std::ostream& operator<<(std::ostream& o, const Source& rhs); + +// Group: Resource Creation +public: + + // Function: addResource + // Define a new named resource. + // (Ex. Image::addResource("monkey","images/monkey.png") would + // make it so that any attempts to load "monkey" would load the image + // images/monkey.png) + // + // Parameters: + // name - Name to give to resource. + // path - Path of resource data file. + static void addResource(const std::string& name, const std::string& path); + + // Function: addResource + // Define a new unaliased resource. (name == path). + // (Ex. Image::addResource("images/monkey.png") is essentially the same as + // Image::addResource("images/monkey.png","images/monkey.png") + // + // Parameters:. + // path - Path of resource data file. + static void addResource(const std::string& path); + +private: + uint sourceID_; + + static const float ORIGIN[]; +}; + +template +const float Source::ORIGIN[] = {0, 0, 0}; + +// you know the drill, Template Implementation // + +template +Source::Source() +{ + alGenSources(1, &sourceID_); + AudioCore::throwOpenALError("Source::Source()"); +} + +template +Source::Source(const Source &rhs) : + ResourceManaged(rhs) +{ + alGenSources(1, &sourceID_); + AudioCore::throwOpenALError("Source::Source(const Source&)"); +} + +template +Source::Source(const std::string& name) +{ + alGenSources(1, &sourceID_); + AudioCore::throwOpenALError("Source::Source(const std::string&)"); + open(name); +} + +template +Source::~Source() +{ + if(alIsSource(sourceID_)) + { + alDeleteSources(1, &sourceID_); + } +} + +template +void Source::open(const std::string& name) +{ + uint bufferID; + + ResourceManaged::open(name); + resMgr_.getAudioData(getName(), bufferID); + + // attach buffer to source + alSourcei(sourceID_, AL_BUFFER, bufferID); + alSourcef(sourceID_, AL_PITCH, 1.0); + alSourcef(sourceID_, AL_GAIN, 1.0); + alSourcefv(sourceID_, AL_POSITION, ORIGIN); + alSourcefv(sourceID_, AL_VELOCITY, ORIGIN); + + AudioCore::throwOpenALError("Source::open"); +} + +template +Source& Source::operator=(const Source& rhs) +{ + if(&rhs != this) + { + uint bufferID; + + ResourceManaged::operator=(rhs); + resMgr_.getAudioData(getName(), bufferID); + + // attach buffer to source + alSourcei(sourceID_, AL_BUFFER, bufferID); + alSourcef(sourceID_, AL_PITCH, 1.0); + alSourcef(sourceID_, AL_GAIN, 1.0); + alSourcefv(sourceID_, AL_POSITION, ORIGIN); + alSourcefv(sourceID_, AL_VELOCITY, ORIGIN); + + AudioCore::throwOpenALError("Source::operator="); + } + return *this; +} + +template +Source::operator bool() const +{ + return alIsSource(sourceID_) == AL_TRUE; +} + +/*std::ostream& operator<<(std::ostream& o, const Source& rhs) +{ + return o << "Source: { Name: " << rhs.getName() << " BufferID: " + << rhs.bufferID_; +}*/ + +template +void Source::play() +{ + alSourcePlay(sourceID_); +} + +template +void Source::stop() +{ + alSourceStop(sourceID_); +} + +template +void Source::pause() +{ + alSourcePause(sourceID_); +} + +template +void Source::rewind() +{ + alSourceRewind(sourceID_); +} + +template +void Source::setLooping(bool loop) +{ + alSourcefv(sourceID_, AL_LOOPING, loop); +} + +template +void Source::addResource(const std::string& name, const std::string& path) +{ + resMgr_.newResource(name, ResourceDescriptor(path)); +} + +template +void Source::addResource(const std::string& path) +{ + resMgr_.newResource(path, ResourceDescriptor(path)); +} + +} +} + +#endif //PHOTON_AUDIO_SOURCE_HPP diff --git a/include/photon.hpp b/include/photon.hpp index 8610fb0..c7f577c 100644 --- a/include/photon.hpp +++ b/include/photon.hpp @@ -13,7 +13,10 @@ #include "Log.hpp" #include "ResourceManaged.hpp" #include "ResourceManager.hpp" +#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/util/ConfigFile.hpp b/include/util/ConfigFile.hpp index 4fc673b..1d4e46a 100644 --- a/include/util/ConfigFile.hpp +++ b/include/util/ConfigFile.hpp @@ -5,7 +5,7 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: ConfigFile.hpp,v 1.3 2005/03/03 09:25:19 cozman Exp $ +// $Id: ConfigFile.hpp,v 1.4 2005/07/05 06:44:56 cozman Exp $ #ifndef PHOTON_UTIL_CONFIGFILE_HPP #define PHOTON_UTIL_CONFIGFILE_HPP @@ -14,7 +14,6 @@ #include #include #include -#include namespace photon { diff --git a/ndoc/Menu.txt b/ndoc/Menu.txt index 2cd087a..0f3ead7 100644 --- a/ndoc/Menu.txt +++ b/ndoc/Menu.txt @@ -65,6 +65,8 @@ Group: photon:: { Group: Video { File: Color (video/Color.hpp) + File: Font (video/Font.hpp) + File: Image (video/Image.hpp) File: Pen (video/Pen.hpp) File: Texture (video/Texture.hpp) File: VideoCore (video/VideoCore.hpp) diff --git a/photon.mm b/photon.mm index 7b0efee..45069e4 100644 --- a/photon.mm +++ b/photon.mm @@ -7,11 +7,13 @@ + + @@ -22,14 +24,11 @@ - - - - - - - + + + + @@ -37,7 +36,9 @@ - + + + @@ -52,8 +53,9 @@ - + + @@ -63,21 +65,25 @@ - + + + + + + - - - + + - + diff --git a/src/Application.cpp b/src/Application.cpp index f13d0bd..938d483 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -5,7 +5,7 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: Application.cpp,v 1.10 2005/06/13 05:38:06 cozman Exp $ +// $Id: Application.cpp,v 1.11 2005/07/05 06:44:56 cozman Exp $ #include "Application.hpp" @@ -13,7 +13,6 @@ #include "GL/gl.h" #include -#include #include "exceptions.hpp" #include "Log.hpp" #include "Kernel.hpp" diff --git a/src/audio/AudioCore.cpp b/src/audio/AudioCore.cpp index 34022d6..1a01471 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.6 2005/07/04 03:06:48 cozman Exp $ +// $Id: AudioCore.cpp,v 1.7 2005/07/05 06:44:56 cozman Exp $ #ifdef PHOTON_USE_OPENAL @@ -19,7 +19,7 @@ namespace photon namespace audio { -AudioCore::AudioCore() +AudioCore::AudioCore() { util::VersionInfo oalReq(0,0,7); // requires OpenAL 1.0 (TODO: check?) util::ensureVersion("OpenAL", initOpenAL(), oalReq); @@ -48,51 +48,6 @@ std::string AudioCore::getAudioDeviceName() const return name; } -util::VersionInfo AudioCore::initOpenAL() -{ - ALCdevice* device(0); - ALCcontext* context(0); - std::stringstream ss; // stream for parsing version - std::string junks; // junk string for parsing - char junkc; // junk character for parsing - uint major,minor,patch; // version numbers - - // obtain default device if no deviceName is set, otherwise use deviceName - device = alcOpenDevice(deviceName_.empty() ? 0 : - reinterpret_cast(deviceName_.c_str()) ); - - if(device == 0) - { - throw APIError("Failed to obtain OpenAL device " + deviceName_ + ": " + - checkOpenALError()); - } - - // create context - context = alcCreateContext(device,0); - - if(context == 0) - { - throw APIError("Failed to obtain an OpenAL context: " + - checkOpenALError()); - } - - alcMakeContextCurrent(context); // context must be current to get version - - - ss << alGetString(AL_VERSION); -#if defined(WINVER) - ss >> junks >> major >> junkc >> minor; // format is "OpenAL 1.0" -#elif defined(linux) - ss >> major >> junkc >> minor >> junkc >> patch; -#else - #warning OpenAL only built on Windows/Linux, find out version on OSX -#endif - - - //std::cerr << util::VersionInfo(major,minor,patch); - return util::VersionInfo(major,minor,patch); -} - std::string AudioCore::checkOpenALError() { ALenum errCode = alGetError(); @@ -126,6 +81,64 @@ std::string AudioCore::checkOpenALError() return err; } +void AudioCore::throwOpenALError(const std::string& func) +{ + std::string err( checkOpenALError() ); + if(err.length()) + { + throw APIError(err + " within " + func); + } +} + +util::VersionInfo AudioCore::initOpenAL() +{ + ALCdevice* device(0); + ALCcontext* context(0); + std::stringstream ss; // stream for parsing version + std::string junks; // junk string for parsing + char junkc; // junk character for parsing + uint major,minor,patch; // version numbers + + // obtain default device if no deviceName is set, otherwise use deviceName + device = alcOpenDevice(deviceName_.empty() ? 0 : + reinterpret_cast(deviceName_.c_str()) ); + + if(device == 0) + { + throw APIError("Failed to obtain OpenAL device " + deviceName_ + ": " + + checkOpenALError()); + } + + // create context + context = alcCreateContext(device,0); + + if(context == 0) + { + throw APIError("Failed to obtain an OpenAL context: " + + checkOpenALError()); + } + + alcMakeContextCurrent(context); // context must be current to get version + + // setup listener to default position + ALfloat posvel[] = { 0.0, 0.0, 0.0 }; + ALfloat ori[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 }; + alListenerfv(AL_POSITION, posvel); + alListenerfv(AL_VELOCITY, posvel); + alListenerfv(AL_ORIENTATION, ori); + + ss << alGetString(AL_VERSION); +#if defined(WINVER) + ss >> junks >> major >> junkc >> minor; // format is "OpenAL 1.0" +#elif defined(linux) + ss >> major >> junkc >> minor >> junkc >> patch; +#else + #warning OpenAL only built on Windows/Linux, find out version on OSX +#endif + + return util::VersionInfo(major,minor,patch); +} + void AudioCore::setDesiredDevice(const std::string& name) { // deviceName_ is used inside initOpenAL, must be set prior to construction diff --git a/src/audio/SampleResourceManager.cpp b/src/audio/SampleResourceManager.cpp new file mode 100644 index 0000000..ca1278e --- /dev/null +++ b/src/audio/SampleResourceManager.cpp @@ -0,0 +1,65 @@ +//This file is part of Photon (http://photon.sourceforge.net) +//Copyright (C) 2004-2005 James Turk +// +// Author: +// James Turk (jpt2433@rit.edu) +// +// Version: +// $Id: SampleResourceManager.cpp,v 1.1 2005/07/05 06:44:56 cozman Exp $ + +#include "audio/SampleResourceManager.hpp" +#include "audio/AudioCore.hpp" +#include "util/FileBuffer.hpp" + +#include "AL/al.h" +#include "AL/alut.h" + +namespace photon +{ +namespace audio +{ + +void SampleResourceManager::getAudioData(const std::string& name, + uint& bufferID) +{ + SampleResource resource( getResource(name) ); + bufferID = resource.bufferID; +} + +void SampleResourceManager::loadResourceData(SampleResource &res, + const ResourceDescriptor& desc) +{ + //util::FileBuffer buf(path.path); + // OpenAL variables to load into. + ALenum format; + ALsizei size; + ALvoid* data; + ALsizei freq; + ALboolean loop; + + ///std::vector data = buf.getData(); + + alGenBuffers(1, &res.bufferID); // create OpenAL buffer + + AudioCore::throwOpenALError("alGenBuffers"); + + alutLoadWAVFile((ALbyte*)desc.path.c_str(), &format, &data, &size, &freq, &loop); + + AudioCore::throwOpenALError("alutLoadWAVFile"); + + alBufferData(res.bufferID, format, data, size, freq); + alutUnloadWAV(format, data, size, freq); + + AudioCore::throwOpenALError("SampleResourceManager::loadResourceData"); +} + +void SampleResourceManager::freeResourceData(SampleResource& res) +{ + if(alIsBuffer(res.bufferID)) + { + alDeleteBuffers(1, &res.bufferID); + } +} + +} +} diff --git a/test/AudioCore_test.cpp b/test/AudioCore_test.cpp index 9bbfda4..c174bc4 100644 --- a/test/AudioCore_test.cpp +++ b/test/AudioCore_test.cpp @@ -5,26 +5,72 @@ // James Turk (jpt2433@rit.edu) // // Version: -// $Id: AudioCore_test.cpp,v 1.2 2005/07/04 03:06:48 cozman Exp $ +// $Id: AudioCore_test.cpp,v 1.3 2005/07/05 06:44:56 cozman Exp $ #include "photon.hpp" -#include - using namespace photon; +#include #ifdef PHOTON_USE_OPENAL using namespace photon::audio; +class MainTask : public Task +{ + +public: + MainTask() : + Task("MainTask"), + app(AppCore::getInstance()), + video(video::VideoCore::getInstance()) + { + LogSinkPtr csp( new ConsoleSink("console") ); + log.addSink(csp); + + video.setOrthoView(800,600); + + Sample::addResource("wavdata/ocean.wav"); + sample.open("wavdata/ocean.wav"); + sample.play(); + } + + void update() + { + static double t=0; + + if(app.getTime() - t > 1.0) + { + app.setTitle("FPS: " + + boost::lexical_cast(app.getFramerate()) ); + t = app.getTime(); + } + + video.clear(); + + } + +private: + audio::Sample sample; + + Log log; + AppCore& app; + video::VideoCore& video; +}; + class AudioTest : public Application { public: int main(const StrVec& args) { + AppCore::getInstance().createDisplay(800,600,32,0,0,false); + + AudioCore::setDesiredDevice("OSS"); + new AudioCore; - AudioCore& audio(AudioCore::getInstance()); - std::cout << audio.getAudioDeviceName(); + Kernel::getInstance().addTask(TaskPtr(new MainTask())); + + Kernel::getInstance().run(); return 0; }