1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#include "audio.hpp"
#include <cstring>
/// -----------------------------------------------------------------------------------
/// @class Audio (base & template class with specializations)
/// @brief General audio handling class, which both initializes & uninitializes audio.
/// -----------------------------------------------------------------------------------
/// Preprocessor definitions:
#define __glox_autocode(data)\
::fread(__ftype, sizeof(char), 4, __file); if(!::strcmp(__ftype, data)) return false;
#define __glox_autocode2(data)\
(__ftype[0] == data[0]) && (__ftype[1] == data[1]) && (__ftype[2] == data[2]) && (__ftype[3] == data[3])
/// Static variable initializations:
template<int I> ::ALCcontext* glox::Audio<I>::ms_opContext = nullptr;
template<int I> ::ALCdevice* glox::Audio<I>::ms_opDevice = nullptr;
/// Constructors & destructors:
template<int I>
glox::Audio<I>::Audio(const char* device){
Audio<I>::Init(*this, device);
}
template<int I>
glox::Audio<I>::~Audio(void){
Audio<I>::Close(*this);
}
/// Member functions:
template<int I>
void glox::Audio<I>::Close(Audio& audio){
::alcMakeContextCurrent(NULL);
::alcDestroyContext(ms_opContext);
::alcCloseDevice(ms_opDevice);
}
template<int I>
void glox::Audio<I>::Init(Audio& audio, const char* device){
ms_opDevice = ::alcOpenDevice(device);
ms_opContext = ::alcCreateContext(ms_opDevice, NULL);
::alcMakeContextCurrent(ms_opContext);
}
/// -------------------------------------------------------------
/// @class Audio<AUDIO_LISTENER> (template specialization)
/// @brief In-game audio listener from which audio can be heard.
/// -------------------------------------------------------------
/// Static member functions:
void glox::AudioListener_t::SetOrientation(::ALfloat x, ::ALfloat y, ::ALfloat z){
::alListener3f(AL_ORIENTATION, x, y, z);
}
void glox::AudioListener_t::SetPosition(::ALfloat x, ::ALfloat y, ::ALfloat z){
::alListener3f(AL_POSITION, x, y, z);
}
void glox::AudioListener_t::SetVelocity(::ALfloat x, ::ALfloat y, ::ALfloat z){
::alListener3f(AL_VELOCITY, x, y, z);
}
/// ----------------------------------------------------
/// @class Audio<AUDIO_SOUND> (template specialization)
/// @brief In-game sound source class.
/// ----------------------------------------------------
/// Constructors & destructors:
glox::AudioSound_t::Audio(const char* file) : m_fGain(1.0f), m_fPitch(1.0f), m_bLooping(false), m_cpFile(file){
m_fOri[0] = m_fOri[1] = m_fOri[2] = m_fPos[0] = m_fPos[1] = m_fPos[2] = m_fVel[0] = m_fVel[1] = m_fVel[2] = 0.0f;
}
glox::AudioSound_t::~Audio(void){
delete[] m_ucpBuffer;
::alDeleteBuffers(1, &m_uiBuffer);
::alDeleteSources(1, &m_uiSource);
}
/// Member variables:
void glox::AudioSound_t::Pause(void){
::alSourcePause(m_uiSource);
}
void glox::AudioSound_t::Play(void){
::alSourcePlay(m_uiSource);
system("PAUSE");
}
void glox::AudioSound_t::SetChanges(void){
AudioSound_t::LoadFile(*this);
}
void glox::AudioSound_t::Stop(void){
::alSourceStop(m_uiSource);
}
/// Static member functions:
bool glox::AudioSound_t::LoadFile(Audio& audio){
// Open requested file (if found):
::FILE* __file = ::fopen(audio.m_cpFile, "rb");
if(!__file) return false;
// Check .wav file validness:
char __ftype[4];
unsigned long __avg_bytes_psec, __rate_sample, __size = 0, __size_chunk, __size_data;
__glox_autocode("RIFF");
::fread(&__size, sizeof(unsigned long), 1, __file);
__glox_autocode("WAVE");
__glox_autocode("fmt ");
// Check & read .wav file data:
short __bits_psample, __bytes_psample, __channels, __type_format;
::fread(&__size_chunk, sizeof(unsigned long), 1, __file);
::fread(&__type_format, sizeof(short), 1, __file);
::fread(&__channels, sizeof(short), 1, __file);
::fread(&__rate_sample, sizeof(unsigned long), 1, __file);
::fread(&__avg_bytes_psec, sizeof(unsigned long), 1, __file);
::fread(&__bytes_psample, sizeof(short), 1, __file);
::fread(&__bits_psample, sizeof(short), 1, __file);
__glox_autocode("data");
// Read data into the buffer (memory allocation process) & generate both the buffers & the sources:
::fread(&__size_data, sizeof(unsigned long), 1, __file);
audio.m_ucpBuffer = new unsigned char[__size_data];
::fread(audio.m_ucpBuffer, sizeof(unsigned char), __size_data, __file);
::alGenBuffers(1, &audio.m_uiBuffer);
::alGenSources(1, &audio.m_uiSource);
::fclose(__file); // The file is not needed anymore (thanks to buffers), so it will be closed.
::ALenum __format = NULL;
if(__bits_psample == 8){
if(__channels == 1){
__format = AL_FORMAT_MONO8;
}
else if(__channels == 2){
__format = AL_FORMAT_STEREO8;
}
}
else if(__bits_psample == 16){
if(__channels == 1){
__format = AL_FORMAT_MONO16;
}
else if(__channels == 2){
__format = AL_FORMAT_STEREO16;
}
}
::alBufferData(audio.m_uiBuffer, __format, audio.m_ucpBuffer, __size_data, __rate_sample);
// Set source properties:
alSourcei(audio.m_uiSource, AL_BUFFER, audio.m_uiBuffer);
alSourcef(audio.m_uiSource, AL_PITCH, audio.m_fPitch);
alSourcef(audio.m_uiSource, AL_GAIN, audio.m_fGain);
alSourcefv(audio.m_uiSource, AL_ORIENTATION, audio.m_fOri);
alSourcefv(audio.m_uiSource, AL_POSITION, audio.m_fPos);
alSourcefv(audio.m_uiSource, AL_VELOCITY, audio.m_fVel);
alSourcei(audio.m_uiSource, AL_LOOPING, audio.m_bLooping);
return true;
}
#undef __glox_autocode
#undef __glox_autocode2
|