Added Audio module
Fixed examples resources not being commited Temporary removed static build configurations
This commit is contained in:
285
src/Nazara/Audio/Audio.cpp
Normal file
285
src/Nazara/Audio/Audio.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Audio module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Audio/Audio.hpp>
|
||||
#include <Nazara/Core/Core.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Audio/Config.hpp>
|
||||
#include <Nazara/Audio/Enums.hpp>
|
||||
#include <Nazara/Audio/Loaders/sndfile.hpp>
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <Nazara/Audio/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
ALenum formats[nzAudioFormat_Max+1] = {0};
|
||||
ALCdevice* device = nullptr;
|
||||
ALCcontext* context = nullptr;
|
||||
}
|
||||
|
||||
nzAudioFormat NzAudio::GetAudioFormat(unsigned int channelCount)
|
||||
{
|
||||
switch (channelCount)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
return static_cast<nzAudioFormat>(channelCount);
|
||||
|
||||
default:
|
||||
NazaraError("Invalid channel count: " + NzString::Number(channelCount));
|
||||
return nzAudioFormat_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
float NzAudio::GetDopplerFactor()
|
||||
{
|
||||
return alGetFloat(AL_DOPPLER_FACTOR);
|
||||
}
|
||||
|
||||
float NzAudio::GetGlobalVolume()
|
||||
{
|
||||
ALfloat gain = 0.f;
|
||||
alGetListenerf(AL_GAIN, &gain);
|
||||
|
||||
return gain*100.f;
|
||||
}
|
||||
|
||||
NzVector3f NzAudio::GetListenerDirection()
|
||||
{
|
||||
ALfloat orientation[6];
|
||||
alGetListenerfv(AL_ORIENTATION, orientation);
|
||||
|
||||
return NzVector3f(orientation[0], orientation[1], orientation[2]);
|
||||
}
|
||||
|
||||
NzVector3f NzAudio::GetListenerPosition()
|
||||
{
|
||||
NzVector3f position;
|
||||
alGetListenerfv(AL_POSITION, position);
|
||||
|
||||
return position;
|
||||
}
|
||||
/*
|
||||
NzQuaternionf NzAudio::GetListenerRotation()
|
||||
{
|
||||
// http://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another
|
||||
float orientation[6];
|
||||
alGetListenerfv(AL_ORIENTATION, orientation);
|
||||
|
||||
NzVector3f forward(orientation[0], orientation[1], orientation[2]);
|
||||
NzVector3f up(orientation[3], orientation[4], orientation[5]);
|
||||
|
||||
NzQuaternionf rotation;
|
||||
NzVector3f a = NzVector3f::CrossProduct(forward, up);
|
||||
rotation.x = a.x;
|
||||
rotation.y = a.y;
|
||||
rotation.z = a.z;
|
||||
rotation.w = std::sqrt(forward.SquaredLength() * up.SquaredLength()) + NzVector3f::DotProduct(forward, up);
|
||||
|
||||
return rotation;
|
||||
}
|
||||
*/
|
||||
NzVector3f NzAudio::GetListenerVelocity()
|
||||
{
|
||||
NzVector3f velocity;
|
||||
alGetListenerfv(AL_VELOCITY, velocity);
|
||||
|
||||
return velocity;
|
||||
}
|
||||
|
||||
float NzAudio::GetSpeedOfSound()
|
||||
{
|
||||
return alGetFloat(AL_SPEED_OF_SOUND);
|
||||
}
|
||||
|
||||
bool NzAudio::Initialize()
|
||||
{
|
||||
if (s_moduleReferenceCouter++ != 0)
|
||||
return true; // Déjà initialisé
|
||||
|
||||
// Initialisation des dépendances
|
||||
if (!NzCore::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize core module");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialisation du module
|
||||
device = alcOpenDevice(nullptr); // On choisit le device par défaut
|
||||
if (!device)
|
||||
{
|
||||
NazaraError("Failed to open default device");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Un seul contexte nous suffira
|
||||
context = alcCreateContext(device, nullptr);
|
||||
if (!context)
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
|
||||
alcCloseDevice(device);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!alcMakeContextCurrent(context))
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
|
||||
alcDestroyContext(context);
|
||||
alcCloseDevice(device);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Définition de l'orientation
|
||||
/*{
|
||||
NzVector3f forward = NzVector3f::Forward();
|
||||
NzVector3f up = NzVector3f::Up();
|
||||
|
||||
ALfloat orientation[6] =
|
||||
{
|
||||
forward.x, forward.y, forward.z,
|
||||
up.x, up.y, up.z
|
||||
};
|
||||
|
||||
alListenerfv(AL_ORIENTATION, orientation);
|
||||
}*/
|
||||
|
||||
formats[nzAudioFormat_Mono] = AL_FORMAT_MONO16;
|
||||
formats[nzAudioFormat_Stereo] = AL_FORMAT_STEREO16;
|
||||
formats[nzAudioFormat_Quad] = alGetEnumValue("AL_FORMAT_QUAD16");
|
||||
formats[nzAudioFormat_5_1] = alGetEnumValue("AL_FORMAT_51CHN16");
|
||||
formats[nzAudioFormat_6_1] = alGetEnumValue("AL_FORMAT_61CHN16");
|
||||
formats[nzAudioFormat_7_1] = alGetEnumValue("AL_FORMAT_71CHN16");
|
||||
|
||||
NzLoaders_sndfile_Register();
|
||||
|
||||
NazaraNotice("Initialized: Audio module");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzAudio::IsFormatSupported(nzAudioFormat format)
|
||||
{
|
||||
if (format == nzAudioFormat_Unknown)
|
||||
return false;
|
||||
|
||||
return formats[format] != 0;
|
||||
}
|
||||
|
||||
bool NzAudio::IsInitialized()
|
||||
{
|
||||
return s_moduleReferenceCouter != 0;
|
||||
}
|
||||
|
||||
void NzAudio::SetDopplerFactor(float dopplerFactor)
|
||||
{
|
||||
alDopplerFactor(dopplerFactor);
|
||||
}
|
||||
|
||||
void NzAudio::SetGlobalVolume(float volume)
|
||||
{
|
||||
alListenerf(AL_GAIN, volume*0.01f);
|
||||
}
|
||||
|
||||
void NzAudio::SetListenerDirection(const NzVector3f& direction)
|
||||
{
|
||||
ALfloat orientation[6] =
|
||||
{
|
||||
direction.x, direction.y, direction.z,
|
||||
0.f, 1.f, 0.f
|
||||
};
|
||||
|
||||
alListenerfv(AL_ORIENTATION, orientation);
|
||||
}
|
||||
|
||||
void NzAudio::SetListenerDirection(float dirX, float dirY, float dirZ)
|
||||
{
|
||||
ALfloat orientation[6] =
|
||||
{
|
||||
dirX, dirY, dirZ,
|
||||
0.f, 1.f, 0.f
|
||||
};
|
||||
|
||||
alListenerfv(AL_ORIENTATION, orientation);
|
||||
}
|
||||
|
||||
void NzAudio::SetListenerPosition(const NzVector3f& position)
|
||||
{
|
||||
alListenerfv(AL_POSITION, position);
|
||||
}
|
||||
|
||||
void NzAudio::SetListenerPosition(float x, float y, float z)
|
||||
{
|
||||
alListener3f(AL_POSITION, x, y, z);
|
||||
}
|
||||
/*
|
||||
void NzAudio::SetListenerRotation(const NzQuaternionf& rotation)
|
||||
{
|
||||
NzVector3f forward = rotation * NzVector3f::Forward();
|
||||
NzVector3f up = NzVector3f::Up();
|
||||
|
||||
ALfloat orientation[6] =
|
||||
{
|
||||
forward.x, forward.y, forward.z,
|
||||
up.x, up.y, up.z
|
||||
};
|
||||
|
||||
alListenerfv(AL_ORIENTATION, orientation);
|
||||
}
|
||||
*/
|
||||
void NzAudio::SetListenerVelocity(const NzVector3f& velocity)
|
||||
{
|
||||
alListenerfv(AL_VELOCITY, velocity);
|
||||
}
|
||||
|
||||
void NzAudio::SetListenerVelocity(float velX, float velY, float velZ)
|
||||
{
|
||||
alListener3f(AL_VELOCITY, velX, velY, velZ);
|
||||
}
|
||||
|
||||
void NzAudio::SetSpeedOfSound(float speed)
|
||||
{
|
||||
alSpeedOfSound(speed);
|
||||
}
|
||||
|
||||
void NzAudio::Uninitialize()
|
||||
{
|
||||
if (--s_moduleReferenceCouter != 0)
|
||||
return; // Encore utilisé
|
||||
|
||||
// Libération du module
|
||||
alcMakeContextCurrent(nullptr);
|
||||
alcDestroyContext(context);
|
||||
|
||||
if (!alcCloseDevice(device))
|
||||
// Nous n'avons pas pu fermer le device, ce qui signifie qu'il est en cours d'utilisation
|
||||
NazaraWarning("Failed to close device");
|
||||
|
||||
NazaraNotice("Uninitialized: Audio module");
|
||||
|
||||
// Libération des dépendances
|
||||
NzCore::Uninitialize();
|
||||
}
|
||||
|
||||
unsigned int NzAudio::GetOpenALFormat(nzAudioFormat format)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (format == nzAudioFormat_Unknown)
|
||||
{
|
||||
NazaraInternalError("Invalid audio format");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return formats[format];
|
||||
}
|
||||
|
||||
unsigned int NzAudio::s_moduleReferenceCouter = 0;
|
||||
15
src/Nazara/Audio/Loaders/sndfile.hpp
Normal file
15
src/Nazara/Audio/Loaders/sndfile.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_LOADERS_SNDFILE_HPP
|
||||
#define NAZARA_LOADERS_SNDFILE_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
|
||||
void NzLoaders_sndfile_Register();
|
||||
void NzLoaders_sndfile_Unregister();
|
||||
|
||||
#endif // NAZARA_LOADERS_SNDFILE_HPP
|
||||
135
src/Nazara/Audio/Loaders/sndfile/Loader.cpp
Normal file
135
src/Nazara/Audio/Loaders/sndfile/Loader.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Audio module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Audio/Loaders/sndfile.hpp>
|
||||
#include <Nazara/Audio/Audio.hpp>
|
||||
#include <Nazara/Audio/SoundBuffer.hpp>
|
||||
#include <Nazara/Core/Endianness.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/InputStream.hpp>
|
||||
#include <Nazara/Core/MemoryStream.hpp>
|
||||
#include <sndfile/sndfile.h>
|
||||
#include <Nazara/Audio/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
sf_count_t GetSize(void* user_data)
|
||||
{
|
||||
NzInputStream* stream = reinterpret_cast<NzInputStream*>(user_data);
|
||||
return stream->GetSize();
|
||||
}
|
||||
|
||||
sf_count_t Read(void* ptr, sf_count_t count, void* user_data)
|
||||
{
|
||||
NzInputStream* stream = reinterpret_cast<NzInputStream*>(user_data);
|
||||
return stream->Read(ptr, count);
|
||||
}
|
||||
|
||||
sf_count_t Seek(sf_count_t offset, int whence, void* user_data)
|
||||
{
|
||||
NzInputStream* stream = reinterpret_cast<NzInputStream*>(user_data);
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
stream->Read(nullptr, offset);
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
stream->SetCursorPos(stream->GetSize()+offset);
|
||||
break;
|
||||
|
||||
case SEEK_SET:
|
||||
stream->SetCursorPos(offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraInternalError("Seek mode not handled");
|
||||
}
|
||||
|
||||
return stream->GetCursorPos();
|
||||
}
|
||||
|
||||
sf_count_t Tell(void* user_data)
|
||||
{
|
||||
NzInputStream* stream = reinterpret_cast<NzInputStream*>(user_data);
|
||||
return stream->GetCursorPos();
|
||||
}
|
||||
|
||||
static SF_VIRTUAL_IO callbacks = {GetSize, Seek, Read, nullptr, Tell};
|
||||
|
||||
bool NzLoader_sndfile_Check(NzInputStream& stream, const NzSoundBufferParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
SF_INFO info;
|
||||
SNDFILE* file = sf_open_virtual(&callbacks, SFM_READ, &info, &stream);
|
||||
if (file)
|
||||
{
|
||||
sf_close(file);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzLoader_sndfile_Load(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
SF_INFO infos;
|
||||
SNDFILE* file = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream);
|
||||
if (!file)
|
||||
{
|
||||
NazaraError("Failed to load sound file: " + NzString(sf_strerror(file)));
|
||||
return false;
|
||||
}
|
||||
|
||||
nzAudioFormat format = NzAudio::GetAudioFormat(infos.channels);
|
||||
if (format == nzAudioFormat_Unknown)
|
||||
{
|
||||
NazaraError("Channel count not handled");
|
||||
sf_close(file);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int sampleCount = infos.frames*infos.channels;
|
||||
nzInt16* samples = new nzInt16[sampleCount];
|
||||
if (sf_read_short(file, samples, sampleCount) != sampleCount)
|
||||
{
|
||||
NazaraError("Failed to read samples");
|
||||
delete[] samples;
|
||||
sf_close(file);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!soundBuffer->Create(format, infos.frames*infos.channels, infos.samplerate, samples))
|
||||
{
|
||||
NazaraError("Failed to create sound buffer");
|
||||
sf_close(file);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
delete[] samples;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void NzLoaders_sndfile_Register()
|
||||
{
|
||||
NzSoundBufferLoader::RegisterLoader("aiff,au,avr,caf,flac,htk,ircam,mat4,mat5,mpc2k,nist,ogg,paf,pvf,raw,rf64,sd2,sds,svx,voc,w64,wav,wve",
|
||||
NzLoader_sndfile_Check,
|
||||
NzLoader_sndfile_Load);
|
||||
}
|
||||
|
||||
void NzLoaders_sndfile_Unregister()
|
||||
{
|
||||
NzSoundBufferLoader::UnregisterLoader("aiff,au,avr,caf,flac,htk,ircam,mat4,mat5,mpc2k,nist,ogg,paf,pvf,raw,rf64,sd2,sds,svx,voc,w64,wav,wve",
|
||||
NzLoader_sndfile_Check,
|
||||
NzLoader_sndfile_Load);
|
||||
}
|
||||
180
src/Nazara/Audio/Sound.cpp
Normal file
180
src/Nazara/Audio/Sound.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Audio module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Audio/Sound.hpp>
|
||||
#include <Nazara/Audio/Audio.hpp>
|
||||
#include <Nazara/Audio/Config.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <AL/al.h>
|
||||
#include <Nazara/Audio/Debug.hpp>
|
||||
|
||||
NzSound::NzSound(const NzSoundBuffer* soundBuffer)
|
||||
{
|
||||
SetBuffer(soundBuffer);
|
||||
}
|
||||
|
||||
NzSound::NzSound(const NzSound& sound) :
|
||||
NzSoundEmitter(sound)
|
||||
{
|
||||
SetBuffer(sound.m_buffer);
|
||||
}
|
||||
|
||||
NzSound::~NzSound()
|
||||
{
|
||||
Stop();
|
||||
|
||||
if (m_buffer)
|
||||
m_buffer->RemoveResourceReference();
|
||||
}
|
||||
|
||||
void NzSound::EnableLooping(bool loop)
|
||||
{
|
||||
alSourcei(m_source, AL_LOOPING, loop);
|
||||
}
|
||||
|
||||
const NzSoundBuffer* NzSound::GetBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
nzUInt32 NzSound::GetDuration() const
|
||||
{
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("No sound buffer");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->GetDuration();
|
||||
}
|
||||
|
||||
nzUInt32 NzSound::GetPlayingOffset() const
|
||||
{
|
||||
ALfloat seconds = -1.f;
|
||||
alGetSourcef(m_source, AL_SEC_OFFSET, &seconds);
|
||||
|
||||
return static_cast<nzUInt32>(seconds*1000);
|
||||
}
|
||||
|
||||
nzSoundStatus NzSound::GetStatus() const
|
||||
{
|
||||
return GetInternalStatus();
|
||||
}
|
||||
|
||||
bool NzSound::IsLooping() const
|
||||
{
|
||||
ALint loop;
|
||||
alGetSourcei(m_source, AL_LOOPING, &loop);
|
||||
|
||||
return loop != AL_FALSE;
|
||||
}
|
||||
|
||||
bool NzSound::LoadFromFile(const NzString& filePath, const NzSoundBufferParams& params)
|
||||
{
|
||||
NzSoundBuffer* buffer = new NzSoundBuffer;
|
||||
if (!buffer->LoadFromFile(filePath, params))
|
||||
{
|
||||
NazaraError("Failed to load buffer from file (" + filePath + ')');
|
||||
delete buffer;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SetBuffer(buffer);
|
||||
|
||||
buffer->SetPersistent(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzSound::LoadFromMemory(const void* data, std::size_t size, const NzSoundBufferParams& params)
|
||||
{
|
||||
NzSoundBuffer* buffer = new NzSoundBuffer;
|
||||
if (!buffer->LoadFromMemory(data, size, params))
|
||||
{
|
||||
NazaraError("Failed to load buffer from memory (" + NzString::Pointer(data) + ')');
|
||||
delete buffer;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SetBuffer(buffer);
|
||||
|
||||
buffer->SetPersistent(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzSound::LoadFromStream(NzInputStream& stream, const NzSoundBufferParams& params)
|
||||
{
|
||||
NzSoundBuffer* buffer = new NzSoundBuffer;
|
||||
if (!buffer->LoadFromStream(stream, params))
|
||||
{
|
||||
NazaraError("Failed to load buffer from stream");
|
||||
delete buffer;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SetBuffer(buffer);
|
||||
|
||||
buffer->SetPersistent(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzSound::Pause()
|
||||
{
|
||||
alSourcePause(m_source);
|
||||
}
|
||||
|
||||
bool NzSound::Play()
|
||||
{
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("No sound buffer to play");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
alSourcePlay(m_source);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzSound::SetBuffer(const NzSoundBuffer* buffer)
|
||||
{
|
||||
if (m_buffer == buffer)
|
||||
return;
|
||||
|
||||
Stop();
|
||||
|
||||
if (m_buffer)
|
||||
m_buffer->RemoveResourceReference();
|
||||
|
||||
m_buffer = buffer;
|
||||
|
||||
if (m_buffer)
|
||||
{
|
||||
m_buffer->AddResourceReference();
|
||||
alSourcei(m_source, AL_BUFFER, m_buffer->GetOpenALBuffer());
|
||||
}
|
||||
else
|
||||
alSourcei(m_source, AL_BUFFER, AL_NONE);
|
||||
}
|
||||
|
||||
void NzSound::SetPlayingOffset(nzUInt32 offset)
|
||||
{
|
||||
alSourcef(m_source, AL_SEC_OFFSET, offset/1000.f);
|
||||
}
|
||||
|
||||
void NzSound::Stop()
|
||||
{
|
||||
alSourceStop(m_source);
|
||||
}
|
||||
223
src/Nazara/Audio/SoundBuffer.cpp
Normal file
223
src/Nazara/Audio/SoundBuffer.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Audio module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Audio/SoundBuffer.hpp>
|
||||
#include <Nazara/Audio/Audio.hpp>
|
||||
#include <Nazara/Audio/Config.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <AL/al.h>
|
||||
#include <Nazara/Audio/Debug.hpp>
|
||||
|
||||
///FIXME: Adapter la création
|
||||
|
||||
bool NzSoundBufferParams::IsValid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
struct NzSoundBufferImpl
|
||||
{
|
||||
ALuint buffer;
|
||||
nzAudioFormat format;
|
||||
nzUInt32 duration;
|
||||
nzInt16* samples;
|
||||
unsigned int sampleCount;
|
||||
unsigned int sampleRate;
|
||||
};
|
||||
|
||||
NzSoundBuffer::NzSoundBuffer(nzAudioFormat format, unsigned int sampleCount, unsigned int sampleRate, const nzInt16* samples)
|
||||
{
|
||||
Create(format, sampleCount, sampleRate, samples);
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Failed to create sound buffer");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NzSoundBuffer::~NzSoundBuffer()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool NzSoundBuffer::Create(nzAudioFormat format, unsigned int sampleCount, unsigned int sampleRate, const nzInt16* samples)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
if (sampleCount == 0)
|
||||
return true;
|
||||
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!IsFormatSupported(format))
|
||||
{
|
||||
NazaraError("Audio format is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sampleRate == 0)
|
||||
{
|
||||
NazaraError("Sample rate must be different from zero");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!samples)
|
||||
{
|
||||
NazaraError("Invalid sample source");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// On vide le stack d'erreurs
|
||||
while (alGetError() != AL_NO_ERROR);
|
||||
|
||||
ALuint buffer;
|
||||
alGenBuffers(1, &buffer);
|
||||
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
NazaraError("Failed to create OpenAL buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
alBufferData(buffer, NzAudio::GetOpenALFormat(format), samples, sampleCount*sizeof(nzInt16), sampleRate);
|
||||
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
NazaraError("Failed to set OpenAL buffer");
|
||||
alDeleteBuffers(1, &buffer);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl = new NzSoundBufferImpl;
|
||||
m_impl->buffer = buffer;
|
||||
m_impl->duration = 1000 * (sampleCount / (format * sampleRate));
|
||||
m_impl->format = format;
|
||||
m_impl->sampleCount = sampleCount;
|
||||
m_impl->sampleRate = sampleRate;
|
||||
m_impl->samples = new nzInt16[sampleCount];
|
||||
std::memcpy(&m_impl->samples[0], samples, sampleCount*sizeof(nzInt16));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzSoundBuffer::Destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
delete[] m_impl->samples;
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nzUInt32 NzSoundBuffer::GetDuration() const
|
||||
{
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Sound buffer not created");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->duration;
|
||||
}
|
||||
|
||||
nzAudioFormat NzSoundBuffer::GetFormat() const
|
||||
{
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Sound buffer not created");
|
||||
return nzAudioFormat_Unknown;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->format;
|
||||
}
|
||||
|
||||
const nzInt16* NzSoundBuffer::GetSamples() const
|
||||
{
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Sound buffer not created");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->samples;
|
||||
}
|
||||
|
||||
unsigned int NzSoundBuffer::GetSampleCount() const
|
||||
{
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Sound buffer not created");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->sampleCount;
|
||||
}
|
||||
|
||||
unsigned int NzSoundBuffer::GetSampleRate() const
|
||||
{
|
||||
#if NAZARA_AUDIO_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Sound buffer not created");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->sampleRate;
|
||||
}
|
||||
|
||||
bool NzSoundBuffer::IsValid() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool NzSoundBuffer::LoadFromFile(const NzString& filePath, const NzSoundBufferParams& params)
|
||||
{
|
||||
return NzSoundBufferLoader::LoadFromFile(this, filePath, params);
|
||||
}
|
||||
|
||||
bool NzSoundBuffer::LoadFromMemory(const void* data, std::size_t size, const NzSoundBufferParams& params)
|
||||
{
|
||||
return NzSoundBufferLoader::LoadFromMemory(this, data, size, params);
|
||||
}
|
||||
|
||||
bool NzSoundBuffer::LoadFromStream(NzInputStream& stream, const NzSoundBufferParams& params)
|
||||
{
|
||||
return NzSoundBufferLoader::LoadFromStream(this, stream, params);
|
||||
}
|
||||
|
||||
bool NzSoundBuffer::IsFormatSupported(nzAudioFormat format)
|
||||
{
|
||||
return NzAudio::IsFormatSupported(format);
|
||||
}
|
||||
|
||||
unsigned int NzSoundBuffer::GetOpenALBuffer() const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraInternalError("Sound buffer not created");
|
||||
return AL_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->buffer;
|
||||
}
|
||||
|
||||
NzSoundBufferLoader::LoaderList NzSoundBuffer::s_loaders;
|
||||
156
src/Nazara/Audio/SoundEmitter.cpp
Normal file
156
src/Nazara/Audio/SoundEmitter.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Audio module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// http://connect.creativelabs.com/openal/Documentation/OpenAL_Programmers_Guide.pdf
|
||||
|
||||
#include <Nazara/Audio/SoundEmitter.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <AL/al.h>
|
||||
#include <Nazara/Audio/Debug.hpp>
|
||||
|
||||
NzSoundEmitter::NzSoundEmitter()
|
||||
{
|
||||
alGenSources(1, &m_source);
|
||||
}
|
||||
|
||||
NzSoundEmitter::NzSoundEmitter(const NzSoundEmitter& emitter)
|
||||
{
|
||||
alGenSources(1, &m_source);
|
||||
|
||||
SetAttenuation(emitter.GetAttenuation());
|
||||
SetMinDistance(emitter.GetMinDistance());
|
||||
SetPitch(emitter.GetPitch());
|
||||
// Pas de copie de position ou de vitesse
|
||||
SetVolume(emitter.GetVolume());
|
||||
}
|
||||
|
||||
NzSoundEmitter::~NzSoundEmitter()
|
||||
{
|
||||
alDeleteSources(1, &m_source);
|
||||
}
|
||||
|
||||
void NzSoundEmitter::EnableSpatialization(bool spatialization)
|
||||
{
|
||||
alSourcei(m_source, AL_SOURCE_RELATIVE, spatialization);
|
||||
}
|
||||
|
||||
float NzSoundEmitter::GetAttenuation() const
|
||||
{
|
||||
ALfloat attenuation;
|
||||
alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation);
|
||||
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
float NzSoundEmitter::GetMinDistance() const
|
||||
{
|
||||
ALfloat distance;
|
||||
alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance);
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
float NzSoundEmitter::GetPitch() const
|
||||
{
|
||||
ALfloat pitch;
|
||||
alGetSourcef(m_source, AL_PITCH, &pitch);
|
||||
|
||||
return pitch;
|
||||
}
|
||||
|
||||
NzVector3f NzSoundEmitter::GetPosition() const
|
||||
{
|
||||
NzVector3f position;
|
||||
alGetSourcefv(m_source, AL_POSITION, position);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
NzVector3f NzSoundEmitter::GetVelocity() const
|
||||
{
|
||||
NzVector3f velocity;
|
||||
alGetSourcefv(m_source, AL_VELOCITY, velocity);
|
||||
|
||||
return velocity;
|
||||
}
|
||||
|
||||
float NzSoundEmitter::GetVolume() const
|
||||
{
|
||||
ALfloat gain;
|
||||
alGetSourcef(m_source, AL_GAIN, &gain);
|
||||
|
||||
return gain * 100.f;
|
||||
}
|
||||
|
||||
bool NzSoundEmitter::IsSpatialized() const
|
||||
{
|
||||
ALint relative;
|
||||
alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative);
|
||||
|
||||
return relative != AL_FALSE;
|
||||
}
|
||||
|
||||
void NzSoundEmitter::SetAttenuation(float attenuation)
|
||||
{
|
||||
alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation);
|
||||
}
|
||||
|
||||
void NzSoundEmitter::SetMinDistance(float minDistance)
|
||||
{
|
||||
alSourcef(m_source, AL_REFERENCE_DISTANCE, minDistance);
|
||||
}
|
||||
|
||||
void NzSoundEmitter::SetPitch(float pitch)
|
||||
{
|
||||
alSourcef(m_source, AL_PITCH, pitch);
|
||||
}
|
||||
|
||||
void NzSoundEmitter::SetPosition(const NzVector3f& position)
|
||||
{
|
||||
alSourcefv(m_source, AL_POSITION, position);
|
||||
}
|
||||
|
||||
void NzSoundEmitter::SetPosition(float x, float y, float z)
|
||||
{
|
||||
alSource3f(m_source, AL_POSITION, x, y, z);
|
||||
}
|
||||
|
||||
void NzSoundEmitter::SetVelocity(const NzVector3f& velocity)
|
||||
{
|
||||
alSourcefv(m_source, AL_VELOCITY, velocity);
|
||||
}
|
||||
|
||||
void NzSoundEmitter::SetVelocity(float velX, float velY, float velZ)
|
||||
{
|
||||
alSource3f(m_source, AL_VELOCITY, velX, velY, velZ);
|
||||
}
|
||||
|
||||
void NzSoundEmitter::SetVolume(float volume)
|
||||
{
|
||||
alSourcef(m_source, AL_GAIN, volume*0.01f);
|
||||
}
|
||||
|
||||
nzSoundStatus NzSoundEmitter::GetInternalStatus() const
|
||||
{
|
||||
ALint state;
|
||||
alGetSourcei(m_source, AL_SOURCE_STATE, &state);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case AL_INITIAL:
|
||||
case AL_STOPPED:
|
||||
return nzSoundStatus_Stopped;
|
||||
|
||||
case AL_PAUSED:
|
||||
return nzSoundStatus_Paused;
|
||||
|
||||
case AL_PLAYING:
|
||||
return nzSoundStatus_Playing;
|
||||
|
||||
default:
|
||||
NazaraInternalError("Source state unrecognized");
|
||||
}
|
||||
|
||||
return nzSoundStatus_Stopped;
|
||||
}
|
||||
Reference in New Issue
Block a user