audio:: source review

This commit is contained in:
James Turk 2005-07-18 05:14:18 +00:00
parent 6380437fde
commit ba332196d2
10 changed files with 172 additions and 45 deletions

View File

@ -5,7 +5,7 @@
# James Turk (jpt2433@rit.edu) # James Turk (jpt2433@rit.edu)
# #
# Version: # 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 os,os.path
import glob import glob
@ -77,6 +77,7 @@ if not env.GetOption('clean'):
conf.env.Append(CPPFLAGS='-DPHOTON_USE_OPENAL') conf.env.Append(CPPFLAGS='-DPHOTON_USE_OPENAL')
else: else:
print 'OpenAL not found, continuing without OpenAL support.' print 'OpenAL not found, continuing without OpenAL support.'
OAL_LIB = '' # no OpenAL library name
env = conf.Finish() env = conf.Finish()
env.Append(CPPFLAGS='-pedantic') # tests fail pedantic, so add after tests 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: for test_src in test_srcs:
test_name = test_src.replace('_test.cpp','') test_name = test_src.replace('_test.cpp','')
tests.append(env.Program(test_name, source=test_src, LIBPATH='./lib', 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'])) 'physfs','corona','freetype']))
env.Alias('test',tests) env.Alias('test',tests)

View File

@ -5,7 +5,7 @@
// James Turk (jpt2433@rit.edu) // James Turk (jpt2433@rit.edu)
// //
// Version: // 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 #ifdef PHOTON_USE_OPENAL
@ -67,13 +67,31 @@ public:
// Group: Error Checking // Group: Error Checking
public: 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(); static std::string checkOpenALError();
// Function: throwOpenALError
// Checks for OpenAL internal errors, throwing an <APIError> 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:
// <APIError> if an OpenAL error state has been set.
static void throwOpenALError(const std::string& func); static void throwOpenALError(const std::string& func);
// OpenAL specifics // OpenAL specifics
private: private:
util::VersionInfo initOpenAL(); util::VersionInfo initOpenAL();
// data members // data members
private: private:

View File

@ -5,7 +5,9 @@
// James Turk (jpt2433@rit.edu) // James Turk (jpt2433@rit.edu)
// //
// Version: // 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 #ifndef PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP
#define PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP #define PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP
@ -18,6 +20,7 @@ namespace photon
namespace audio namespace audio
{ {
// All that a Sample is is a bufferID, extremely simple resource management
class SampleResource : public Resource class SampleResource : public Resource
{ {
public: public:
@ -35,9 +38,12 @@ private:
virtual void freeResourceData(SampleResource &res); virtual void freeResourceData(SampleResource &res);
}; };
// Allow users to simply call a Sample a Sample
typedef Source<SampleResourceManager> Sample; typedef Source<SampleResourceManager> Sample;
} }
} }
#endif //PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP #endif //PHOTON_AUDIO_SAMPLERESOURCEMANAGER_HPP
#endif //PHOTON_USE_OPENAL

View File

@ -5,14 +5,14 @@
// James Turk (jpt2433@rit.edu) // James Turk (jpt2433@rit.edu)
// //
// Version: // 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 #ifndef PHOTON_AUDIO_SOURCE_HPP
#define PHOTON_AUDIO_SOURCE_HPP #define PHOTON_AUDIO_SOURCE_HPP
#include "AL/al.h" #include "AL/al.h"
#include "AL/alc.h"
#include "AL/alut.h"
#include "ResourceManaged.hpp" #include "ResourceManaged.hpp"
#include "audio/AudioCore.hpp" #include "audio/AudioCore.hpp"
@ -23,9 +23,12 @@ namespace audio
{ {
// Class: Source // Class: Source
// Simple OO wrapper around an OpenAL source. // Simple OO wrapper around an OpenAL source, defines the interface used for
// // Sample and Music.
// Children: //
// 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: // Operators:
// - Source = Source // - Source = Source
@ -74,7 +77,7 @@ public:
Source& operator=(const Source& rhs); Source& operator=(const Source& rhs);
operator bool() const; operator bool() const;
// Group: Source Control // Group: Source Control
public: public:
@ -104,6 +107,27 @@ public:
// Group: Accessors // Group: Accessors
public: 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); //friend std::ostream& operator<<(std::ostream& o, const Source& rhs);
// Group: Resource Creation // Group: Resource Creation
@ -130,9 +154,9 @@ public:
static void addResource(const std::string& path); static void addResource(const std::string& path);
private: 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<class ResMgrT> template<class ResMgrT>
@ -215,47 +239,101 @@ Source<ResMgrT>& Source<ResMgrT>::operator=(const Source<ResMgrT>& rhs)
template<class ResMgrT> template<class ResMgrT>
Source<ResMgrT>::operator bool() const Source<ResMgrT>::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<class ResMgrT> template<class ResMgrT>
void Source<ResMgrT>::play() void Source<ResMgrT>::play()
{ {
if(!isValid())
{
throw PreconditionException("Invalid Source::play call.");
}
alSourcePlay(sourceID_); alSourcePlay(sourceID_);
} }
template<class ResMgrT> template<class ResMgrT>
void Source<ResMgrT>::stop() void Source<ResMgrT>::stop()
{ {
if(!isValid())
{
throw PreconditionException("Invalid Source::stop call.");
}
alSourceStop(sourceID_); alSourceStop(sourceID_);
} }
template<class ResMgrT> template<class ResMgrT>
void Source<ResMgrT>::pause() void Source<ResMgrT>::pause()
{ {
if(!isValid())
{
throw PreconditionException("Invalid Source::pause call.");
}
alSourcePause(sourceID_); alSourcePause(sourceID_);
} }
template<class ResMgrT> template<class ResMgrT>
void Source<ResMgrT>::rewind() void Source<ResMgrT>::rewind()
{ {
if(!isValid())
{
throw PreconditionException("Invalid Source::rewind call.");
}
alSourceRewind(sourceID_); alSourceRewind(sourceID_);
} }
template<class ResMgrT> template<class ResMgrT>
void Source<ResMgrT>::setLooping(bool loop) void Source<ResMgrT>::setLooping(bool loop)
{ {
if(!isValid())
{
throw PreconditionException("Invalid Source::setLooping call.");
}
alSourcei(sourceID_, AL_LOOPING, loop); alSourcei(sourceID_, AL_LOOPING, loop);
} }
template<class ResMgrT> template<class ResMgrT>
void Source<ResMgrT>::addResource(const std::string& name, const std::string& path) bool Source<ResMgrT>::isValid() const
{
return alIsSource(sourceID_) == AL_TRUE;
}
template<class ResMgrT>
bool Source<ResMgrT>::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<class ResMgrT>
bool Source<ResMgrT>::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<class ResMgrT>
void Source<ResMgrT>::addResource(const std::string& name,
const std::string& path)
{ {
resMgr_.newResource(name, ResourceDescriptor(path)); resMgr_.newResource(name, ResourceDescriptor(path));
} }
@ -270,3 +348,5 @@ void Source<ResMgrT>::addResource(const std::string& path)
} }
#endif //PHOTON_AUDIO_SOURCE_HPP #endif //PHOTON_AUDIO_SOURCE_HPP
#endif //PHOTON_USE_OPENAL

View File

@ -16,7 +16,6 @@
#include "audio/SampleResourceManager.hpp" #include "audio/SampleResourceManager.hpp"
#include "audio/Source.hpp" #include "audio/Source.hpp"
#include "audio/AudioCore.hpp" #include "audio/AudioCore.hpp"
#include "audio/MusicResourceManager.hpp"
#include "math/math.hpp" #include "math/math.hpp"
#include "math/Rect.hpp" #include "math/Rect.hpp"
#include "math/Vector2.hpp" #include "math/Vector2.hpp"

View File

@ -5,7 +5,7 @@
// James Turk (jpt2433@rit.edu) // James Turk (jpt2433@rit.edu)
// //
// Version: // 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 #ifndef PHOTON_VIDEO_FONT_HPP
#define PHOTON_VIDEO_FONT_HPP #define PHOTON_VIDEO_FONT_HPP
@ -70,6 +70,11 @@ public:
// name - Name of the Font <Resource> to open. // name - Name of the Font <Resource> to open.
void open(const std::string& name); 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; bool isValid() const;
Font& operator=(const Font &rhs); Font& operator=(const Font &rhs);

View File

@ -6,10 +6,11 @@
<node ID="Freemind_Link_682620075" POSITION="right" TEXT="0.1 Release"> <node ID="Freemind_Link_682620075" POSITION="right" TEXT="0.1 Release">
<font BOLD="true" NAME="SansSerif" SIZE="12"/> <font BOLD="true" NAME="SansSerif" SIZE="12"/>
<node ID="Freemind_Link_1479941799" TEXT="Clean up source"> <node ID="Freemind_Link_1479941799" TEXT="Clean up source">
<node ID="Freemind_Link_1271859141" TEXT="math::"/>
<node ID="Freemind_Link_510494143" TEXT="util::"/>
<node ID="Freemind_Link_1243282886" TEXT="video::"/>
<node ID="Freemind_Link_327905180" TEXT="photon:: (general)"/>
<node ID="Freemind_Link_1716705807" TEXT="clean up naturaldocs"/> <node ID="Freemind_Link_1716705807" TEXT="clean up naturaldocs"/>
<node ID="Freemind_Link_1080393911" TEXT="audio:: could using some cleaning">
<node ID="Freemind_Link_632977685" TEXT="make compilation succeed without OpenAL"/>
</node>
</node> </node>
<node ID="Freemind_Link_1153941464" TEXT="test compilation on fresh systems"> <node ID="Freemind_Link_1153941464" TEXT="test compilation on fresh systems">
<node ID="Freemind_Link_1403005191" TEXT="test compilation on clean linux system"/> <node ID="Freemind_Link_1403005191" TEXT="test compilation on clean linux system"/>
@ -42,7 +43,7 @@
<icon BUILTIN="help"/> <icon BUILTIN="help"/>
</node> </node>
</node> </node>
<node COLOR="#147f1e" ID="Freemind_Link_438641521" POSITION="left" TEXT="Version: $Id: photon.mm,v 1.19 2005/07/17 22:41:03 cozman Exp $"> <node COLOR="#147f1e" ID="Freemind_Link_438641521" POSITION="left" TEXT="Version: $Id: photon.mm,v 1.20 2005/07/18 05:14:18 cozman Exp $">
<font ITALIC="true" NAME="SansSerif" SIZE="12"/> <font ITALIC="true" NAME="SansSerif" SIZE="12"/>
</node> </node>
</node> </node>

View File

@ -5,7 +5,7 @@
// James Turk (jpt2433@rit.edu) // James Turk (jpt2433@rit.edu)
// //
// Version: // 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 #ifdef PHOTON_USE_OPENAL
@ -21,8 +21,10 @@ namespace audio
AudioCore::AudioCore() AudioCore::AudioCore()
{ {
util::VersionInfo oalReq(0,0,7); // requires OpenAL 1.0 (TODO: check?) //util::VersionInfo oalReq(0,0,7); // requires OpenAL 1.0 (TODO: check?)
util::ensureVersion("OpenAL", initOpenAL(), oalReq); //util::ensureVersion("OpenAL", initOpenAL(), oalReq);
initOpenAL(); // don't check version for now
} }
AudioCore::~AudioCore() AudioCore::~AudioCore()
@ -50,9 +52,10 @@ std::string AudioCore::getAudioDeviceName() const
std::string AudioCore::checkOpenALError() std::string AudioCore::checkOpenALError()
{ {
ALenum errCode = alGetError(); ALenum errCode = alGetError(); // fetch error code
std::string err; std::string err;
// interpret error code
switch(errCode) switch(errCode)
{ {
case AL_NO_ERROR: case AL_NO_ERROR:
@ -73,7 +76,7 @@ std::string AudioCore::checkOpenALError()
case AL_OUT_OF_MEMORY: case AL_OUT_OF_MEMORY:
err = "OpenAL out of memory"; err = "OpenAL out of memory";
break; break;
default: default: // not sure how conforming implementations are with error codes
err = "Unknown OpenAL error"; err = "Unknown OpenAL error";
break; break;
} }
@ -84,7 +87,7 @@ std::string AudioCore::checkOpenALError()
void AudioCore::throwOpenALError(const std::string& func) void AudioCore::throwOpenALError(const std::string& func)
{ {
std::string err( checkOpenALError() ); std::string err( checkOpenALError() );
if(err.length()) if(err.length()) // throw exception if non-empty string
{ {
throw APIError(err + " within " + func); throw APIError(err + " within " + func);
} }
@ -127,6 +130,7 @@ util::VersionInfo AudioCore::initOpenAL()
alListenerfv(AL_VELOCITY, posvel); alListenerfv(AL_VELOCITY, posvel);
alListenerfv(AL_ORIENTATION, ori); alListenerfv(AL_ORIENTATION, ori);
// OpenAL needs a standard version string format badly
ss << alGetString(AL_VERSION); ss << alGetString(AL_VERSION);
#if defined(WINVER) #if defined(WINVER)
ss >> junks >> major >> junkc >> minor; // format is "OpenAL 1.0" ss >> junks >> major >> junkc >> minor; // format is "OpenAL 1.0"
@ -146,6 +150,7 @@ void AudioCore::setDesiredDevice(const std::string& name)
deviceName_ = name; deviceName_ = name;
} }
// static instance
std::string AudioCore::deviceName_; std::string AudioCore::deviceName_;
} }

View File

@ -5,14 +5,16 @@
// James Turk (jpt2433@rit.edu) // James Turk (jpt2433@rit.edu)
// //
// Version: // 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/SampleResourceManager.hpp"
#include "audio/AudioCore.hpp" #include "audio/AudioCore.hpp"
#include "util/FileBuffer.hpp" #include "util/FileBuffer.hpp"
#include "AL/al.h" #include "AL/al.h"
#include "AL/alut.h" #include "AL/alut.h" // used for loading WAVs, to be phased out
namespace photon namespace photon
{ {
@ -22,6 +24,7 @@ namespace audio
void SampleResourceManager::getAudioData(const std::string& name, void SampleResourceManager::getAudioData(const std::string& name,
uint& bufferID) uint& bufferID)
{ {
// not much to do here, get the resource, set the ID
SampleResource resource( getResource(name) ); SampleResource resource( getResource(name) );
bufferID = resource.bufferID; bufferID = resource.bufferID;
} }
@ -37,6 +40,7 @@ void SampleResourceManager::loadResourceData(SampleResource &res,
ALsizei freq; ALsizei freq;
ALboolean loop; ALboolean loop;
// load from FileBuffer (allows loading from zip via PhysFS)
std::vector<ubyte> filedata = buf.getData(); std::vector<ubyte> filedata = buf.getData();
size = filedata.size(); size = filedata.size();
@ -44,8 +48,9 @@ void SampleResourceManager::loadResourceData(SampleResource &res,
AudioCore::throwOpenALError("alGenBuffers"); AudioCore::throwOpenALError("alGenBuffers");
alutLoadWAVMemory((ALbyte*)&filedata[0], &format, &data, &size, &freq, &loop); // load WAV via alut
alutLoadWAVMemory(reinterpret_cast<ALbyte*>(&filedata[0]),
&format, &data, &size, &freq, &loop);
AudioCore::throwOpenALError("alutLoadWAVFile"); AudioCore::throwOpenALError("alutLoadWAVFile");
alBufferData(res.bufferID, format, data, size, freq); alBufferData(res.bufferID, format, data, size, freq);
@ -58,9 +63,12 @@ void SampleResourceManager::freeResourceData(SampleResource& res)
{ {
if(alIsBuffer(res.bufferID)) if(alIsBuffer(res.bufferID))
{ {
// delete buffers, just like textures in GL
alDeleteBuffers(1, &res.bufferID); alDeleteBuffers(1, &res.bufferID);
} }
} }
} }
} }
#endif //PHOTON_USE_OPENAL

View File

@ -5,7 +5,7 @@
// James Turk (jpt2433@rit.edu) // James Turk (jpt2433@rit.edu)
// //
// Version: // 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" #include "photon.hpp"
using namespace photon; using namespace photon;
@ -51,7 +51,10 @@ public:
rain.setLooping(true); rain.setLooping(true);
stream.setLooping(true); stream.setLooping(true);
thunder.setLooping(true); thunder.setLooping(true);
assert(!waterdrop.isLooping());
waterdrop.setLooping(true); waterdrop.setLooping(true);
assert(waterdrop.isLooping());
for(int i=0; i < 6; ++i) for(int i=0; i < 6; ++i)
status[i] = "NOT "; status[i] = "NOT ";
@ -68,7 +71,7 @@ public:
if(app.keyPressed(KEY_C)) if(app.keyPressed(KEY_C))
{ {
if(status[0] == NOT_PLAYING) if(!chimes.isPlaying())
{ {
chimes.play(); chimes.play();
status[0] = ""; status[0] = "";
@ -81,7 +84,7 @@ public:
} }
if(app.keyPressed(KEY_O)) if(app.keyPressed(KEY_O))
{ {
if(status[1] == NOT_PLAYING) if(!ocean.isPlaying())
{ {
ocean.play(); ocean.play();
status[1] = ""; status[1] = "";
@ -94,7 +97,7 @@ public:
} }
if(app.keyPressed(KEY_R)) if(app.keyPressed(KEY_R))
{ {
if(status[2] == NOT_PLAYING) if(!rain.isPlaying())
{ {
rain.play(); rain.play();
status[2] = ""; status[2] = "";
@ -107,7 +110,7 @@ public:
} }
if(app.keyPressed(KEY_S)) if(app.keyPressed(KEY_S))
{ {
if(status[3] == NOT_PLAYING) if(!stream.isPlaying())
{ {
stream.play(); stream.play();
status[3] = ""; status[3] = "";
@ -120,7 +123,7 @@ public:
} }
if(app.keyPressed(KEY_T)) if(app.keyPressed(KEY_T))
{ {
if(status[4] == NOT_PLAYING) if(!thunder.isPlaying())
{ {
thunder.play(); thunder.play();
status[4] = ""; status[4] = "";
@ -133,7 +136,7 @@ public:
} }
if(app.keyPressed(KEY_W)) if(app.keyPressed(KEY_W))
{ {
if(status[5] == NOT_PLAYING) if(!waterdrop.isPlaying())
{ {
waterdrop.play(); waterdrop.play();
status[5] = ""; status[5] = "";
@ -210,6 +213,7 @@ public:
ENTRYPOINT(AudioTest) ENTRYPOINT(AudioTest)
#else #else
#include <iostream>
int main() int main()
{ {