Added Audio module

Fixed examples resources not being commited
Temporary removed static build configurations
This commit is contained in:
Lynix 2012-08-21 15:04:00 +02:00
parent 71b777e732
commit 40ec2003b4
28 changed files with 1541 additions and 13 deletions

2
.gitignore vendored
View File

@ -1,5 +1,6 @@
# Codeblocks
*.cbp
*.cbTemp
*.cscope_file_list
*.depend
*.layout
@ -126,7 +127,6 @@ publish
*.Publish.xml
# Others
[Bb]in
[Oo]bj
sql
TestResults

View File

@ -1,8 +1,8 @@
-- Configuration générale
configurations
{
"DebugStatic",
"ReleaseStatic",
-- "DebugStatic",
-- "ReleaseStatic",
"DebugDLL",
"ReleaseDLL"
}

View File

@ -1,8 +1,8 @@
-- Configuration générale
configurations
{
"DebugStatic",
"ReleaseStatic",
-- "DebugStatic",
-- "ReleaseStatic",
"DebugDLL",
"ReleaseDLL"
}
@ -10,10 +10,18 @@ configurations
language "C++"
location("../examples/build/" .. _ACTION)
debugdir "../examples/bin"
includedirs "../include"
debugdir "../examples/bin"
libdirs "../lib"
if (_OPTIONS["x64"]) then
libdirs "../extlibs/lib/x64"
end
libdirs "../extlibs/lib/x86"
targetdir "../examples/bin"
configuration "Debug*"

View File

@ -0,0 +1,36 @@
if (not _OPTIONS["one-library"]) then
project "NazaraAudio"
end
files
{
"../include/Nazara/Audio/**.hpp",
"../include/Nazara/Audio/**.inl",
"../src/Nazara/Audio/**.hpp",
"../src/Nazara/Audio/**.cpp"
}
if (os.is("windows")) then
excludes { "../src/Nazara/Audio/Posix/*.hpp", "../src/Nazara/Audio/Posix/*.cpp" }
links "OpenAL32"
links "sndfile-1"
else
excludes { "../src/Nazara/Audio/Win32/*.hpp", "../src/Nazara/Audio/Win32/*.cpp" }
-- Link posix ?
end
if (_OPTIONS["one-library"]) then
excludes "../src/Nazara/Audio/Debug/Leaks.cpp"
else
configuration "DebugStatic"
links "NazaraCore-s-d"
configuration "ReleaseStatic"
links "NazaraCore-s"
configuration "DebugDLL"
links "NazaraCore-d"
configuration "ReleaseDLL"
links "NazaraCore"
end

View File

@ -27,8 +27,8 @@ else
configuration "DebugDLL"
links "NazaraRenderer-d"
links "NazaraCore-d"
links "NazaraUtility-d"
links "NazaraCore-d"
configuration "ReleaseDLL"
links "NazaraRenderer"

View File

@ -0,0 +1,37 @@
kind "ConsoleApp"
files "main.cpp"
if (_OPTIONS["one-library"]) then
configuration "DebugStatic"
links "NazaraEngine-s-d"
configuration "ReleaseStatic"
links "NazaraEngine-s"
configuration "DebugDLL"
links "NazaraEngine-d"
configuration "ReleaseDLL"
links "NazaraEngine"
else
configuration "DebugStatic"
links "NazaraAudio-s-d"
links "NazaraUtility-s-d"
links "NazaraCore-s-d"
configuration "ReleaseStatic"
links "NazaraAudio-s"
links "NazaraUtility-s"
links "NazaraCore-s"
configuration "DebugDLL"
links "NazaraAudio-d"
links "NazaraUtility-d"
links "NazaraCore-d"
configuration "ReleaseDLL"
links "NazaraAudio"
links "NazaraUtility"
links "NazaraCore"
end

View File

@ -0,0 +1,68 @@
#include <Nazara/Audio.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Thread.hpp> // Thread::Sleep
#include <Nazara/Utility/Keyboard.hpp>
#include <iostream>
int main()
{
// NzKeyboard ne nécessite pas l'initialisation d'Utility
NzInitializer<NzAudio> audio;
if (!audio)
{
std::cout << "Failed to initialize audio module" << std::endl;
std::getchar();
return 1;
}
NzSound sound;
if (!sound.LoadFromFile("resources/siren.wav"))
{
std::cout << "Failed to load sound" << std::endl;
std::getchar();
return 1;
}
std::cout << "Demonstration de l'effet doppler avec Nazara" << std::endl;
std::cout << "Appuyez sur entree pour demarrer" << std::endl;
std::cout << "Appuyez sur echap pour arreter" << std::endl;
std::getchar();
// On fait en sorte de répéter le son
sound.EnableLooping(true);
// La source du son se situe en (50, 0, 5)
sound.SetPosition(50, 0, 5);
// Et possède une vitesse de -10 par seconde sur l'axe X
sound.SetVelocity(-10, 0, 0);
// On joue le son
sound.Play();
// La boucle du programme (Pour déplacer le son)
NzClock clock;
while (sound.GetStatus() == nzSoundStatus_Playing)
{
// Comme le son se joue dans un thread séparé, on peut mettre en pause celui-ci régulièrement
int sleepTime = 1000/60 - clock.GetMilliseconds(); // 60 FPS
if (sleepTime > 0)
NzThread::Sleep(sleepTime);
// On bouge la source du son en fonction du au temps depuis chaque mise à jour
NzVector3f pos = sound.GetPosition() + sound.GetVelocity()*clock.GetSeconds();
sound.SetPosition(pos);
std::cout << "Sound position: " << pos << std::endl;
// Si la position de la source atteint une certaine position, ou si l'utilisateur appuie sur echap
if (pos.x < -50.f || NzKeyboard::IsKeyPressed(NzKeyboard::Escape))
sound.Stop(); // On arrête le son (Stoppant également la boucle)
clock.Restart();
}
return 0;
}

View File

@ -16,18 +16,18 @@ if (_OPTIONS["one-library"]) then
links "NazaraEngine"
else
configuration "DebugStatic"
links "NazaraCore-s-d"
links "NazaraUtility-s-d"
links "NazaraCore-s-d"
configuration "ReleaseStatic"
links "NazaraCore-s"
links "NazaraUtility-s"
links "NazaraCore-s"
configuration "DebugDLL"
links "NazaraCore-d"
links "NazaraUtility-d"
links "NazaraCore-d"
configuration "ReleaseDLL"
links "NazaraCore"
links "NazaraUtility"
links "NazaraCore"
end

View File

@ -0,0 +1,10 @@
#version 110
varying vec2 TexCoord;
uniform sampler2D texture;
void main()
{
gl_FragColor = texture2D(texture, TexCoord);
}

View File

@ -0,0 +1,14 @@
#version 110
attribute vec3 Position;
attribute vec2 TexCoord0;
uniform mat4 WorldViewProjMatrix;
varying vec2 TexCoord;
void main()
{
gl_Position = WorldViewProjMatrix * vec4(Position, 1.0);
TexCoord = TexCoord0;
}

36
include/Nazara/Audio.hpp Normal file
View File

@ -0,0 +1,36 @@
// This file was automatically generated by Nazara
/*
Nazara Engine - Audio module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <Nazara/Audio/Audio.hpp>
#include <Nazara/Audio/Config.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Audio/Music.hpp>
#include <Nazara/Audio/Sound.hpp>
#include <Nazara/Audio/SoundBuffer.hpp>
#include <Nazara/Audio/SoundEmitter.hpp>
#include <Nazara/Audio/SoundStream.hpp>

View File

@ -0,0 +1,58 @@
// 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
#pragma once
#ifndef NAZARA_AUDIO_HPP
#define NAZARA_AUDIO_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Core/Initializer.hpp>
#include <Nazara/Math/Quaternion.hpp>
#include <Nazara/Math/Vector3.hpp>
class NAZARA_API NzAudio
{
friend class NzMusic;
friend class NzSoundBuffer;
public:
NzAudio() = delete;
~NzAudio() = delete;
static nzAudioFormat GetAudioFormat(unsigned int channelCount);
static float GetDopplerFactor();
static float GetGlobalVolume();
static NzVector3f GetListenerDirection();
static NzVector3f GetListenerPosition();
//static NzQuaternionf GetListenerRotation();
static NzVector3f GetListenerVelocity();
static float GetSpeedOfSound();
static bool Initialize();
static bool IsFormatSupported(nzAudioFormat format);
static bool IsInitialized();
static void SetDopplerFactor(float dopplerFactor);
static void SetGlobalVolume(float volume);
static void SetListenerDirection(const NzVector3f& direction);
static void SetListenerDirection(float dirX, float dirY, float dirZ);
static void SetListenerPosition(const NzVector3f& position);
static void SetListenerPosition(float x, float y, float z);
//static void SetListenerRotation(const NzQuaternionf& rotation);
static void SetListenerVelocity(const NzVector3f& velocity);
static void SetListenerVelocity(float velX, float velY, float velZ);
static void SetSpeedOfSound(float speed);
static void Uninitialize();
private:
static unsigned int GetOpenALFormat(nzAudioFormat format);
static unsigned int s_moduleReferenceCouter;
};
#endif // NAZARA_AUDIO_HPP

View File

@ -0,0 +1,41 @@
/*
Nazara Engine - Audio module
Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_CONFIG_AUDIO_HPP
#define NAZARA_CONFIG_AUDIO_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Utilise un tracker pour repérer les éventuels leaks (Ralentit l'exécution)
#define NAZARA_AUDIO_MEMORYLEAKTRACKER 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_AUDIO_SAFE 1
// Le nombre de buffers utilisés lors du streaming d'objets audio (Au moins deux)
#define NAZARA_AUDIO_STREAMEDBUFFERCOUNT 2
#endif // NAZARA_CONFIG_AUDIO_HPP

View File

@ -0,0 +1,11 @@
// 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/Config.hpp>
#if NAZARA_AUDIO_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
#define delete NzMemoryManager::NextFree(__FILE__, __LINE__), delete
#define new new(__FILE__, __LINE__)
#endif

View File

@ -0,0 +1,8 @@
// 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
#if NAZARA_AUDIO_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
#undef delete
#undef new
#endif

View File

@ -0,0 +1,32 @@
// 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
#pragma once
#ifndef NAZARA_ENUMS_HPP
#define NAZARA_ENUMS_HPP
enum nzAudioFormat
{
nzAudioFormat_Unknown = -1,
// La valeur entière est le nombre de canaux possédés par ce format
nzAudioFormat_Mono = 1,
nzAudioFormat_Stereo = 2,
nzAudioFormat_Quad = 4,
nzAudioFormat_5_1 = 6,
nzAudioFormat_6_1 = 7,
nzAudioFormat_7_1 = 8,
nzAudioFormat_Max = nzAudioFormat_7_1
};
enum nzSoundStatus
{
nzSoundStatus_Playing,
nzSoundStatus_Paused,
nzSoundStatus_Stopped
};
#endif // NAZARA_ENUMS_HPP

View File

@ -0,0 +1,48 @@
// 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
#pragma once
#ifndef NAZARA_SOUND_HPP
#define NAZARA_SOUND_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Audio/SoundBuffer.hpp>
#include <Nazara/Audio/SoundEmitter.hpp>
class NAZARA_API NzSound : public NzSoundEmitter
{
public:
NzSound() = default;
NzSound(const NzSoundBuffer* soundBuffer);
NzSound(const NzSound& sound);
~NzSound();
void EnableLooping(bool loop);
const NzSoundBuffer* GetBuffer() const;
nzUInt32 GetDuration() const;
nzUInt32 GetPlayingOffset() const;
nzSoundStatus GetStatus() const;
bool IsLooping() const;
bool LoadFromFile(const NzString& filePath, const NzSoundBufferParams& params = NzSoundBufferParams());
bool LoadFromMemory(const void* data, std::size_t size, const NzSoundBufferParams& params = NzSoundBufferParams());
bool LoadFromStream(NzInputStream& stream, const NzSoundBufferParams& params = NzSoundBufferParams());
void Pause();
bool Play();
void SetBuffer(const NzSoundBuffer* buffer);
void SetPlayingOffset(nzUInt32 offset);
void Stop();
private:
const NzSoundBuffer* m_buffer = nullptr;
};
#endif // NAZARA_SOUND_HPP

View File

@ -0,0 +1,64 @@
// 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
#pragma once
#ifndef NAZARA_SOUNDBUFFER_HPP
#define NAZARA_SOUNDBUFFER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
struct NzSoundBufferParams
{
bool IsValid() const;
};
class NzSound;
class NzSoundBuffer;
using NzSoundBufferLoader = NzResourceLoader<NzSoundBuffer, NzSoundBufferParams>;
struct NzSoundBufferImpl;
class NAZARA_API NzSoundBuffer : public NzResource, public NzNonCopyable
{
friend NzSound;
friend NzSoundBufferLoader;
public:
NzSoundBuffer() = default;
NzSoundBuffer(nzAudioFormat format, unsigned int sampleCount, unsigned int sampleRate, const nzInt16* samples);
~NzSoundBuffer();
bool Create(nzAudioFormat format, unsigned int sampleCount, unsigned int sampleRate, const nzInt16* samples);
void Destroy();
nzUInt32 GetDuration() const;
nzAudioFormat GetFormat() const;
const nzInt16* GetSamples() const;
unsigned int GetSampleCount() const;
unsigned int GetSampleRate() const;
bool IsValid() const;
bool LoadFromFile(const NzString& filePath, const NzSoundBufferParams& params = NzSoundBufferParams());
bool LoadFromMemory(const void* data, std::size_t size, const NzSoundBufferParams& params = NzSoundBufferParams());
bool LoadFromStream(NzInputStream& stream, const NzSoundBufferParams& params = NzSoundBufferParams());
static bool IsFormatSupported(nzAudioFormat format);
private:
unsigned int GetOpenALBuffer() const;
NzSoundBufferImpl* m_impl = nullptr;
static NzSoundBufferLoader::LoaderList s_loaders;
};
#endif // NAZARA_SOUNDBUFFER_HPP

View File

@ -0,0 +1,60 @@
// 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
#pragma once
#ifndef NAZARA_SOUNDEMITTER_HPP
#define NAZARA_SOUNDEMITTER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Math/Vector3.hpp>
class NAZARA_API NzSoundEmitter
{
public:
virtual ~NzSoundEmitter();
virtual void EnableLooping(bool loop) = 0;
void EnableSpatialization(bool spatialization);
float GetAttenuation() const;
virtual nzUInt32 GetDuration() const = 0;
float GetMinDistance() const;
float GetPitch() const;
virtual nzUInt32 GetPlayingOffset() const = 0;
NzVector3f GetPosition() const;
NzVector3f GetVelocity() const;
virtual nzSoundStatus GetStatus() const = 0;
float GetVolume() const;
virtual bool IsLooping() const = 0;
bool IsSpatialized() const;
virtual void Pause() = 0;
virtual bool Play() = 0;
void SetAttenuation(float attenuation);
void SetMinDistance(float minDistance);
void SetPitch(float pitch);
void SetPosition(const NzVector3f& position);
void SetPosition(float x, float y, float z);
void SetVelocity(const NzVector3f& velocity);
void SetVelocity(float velX, float velY, float velZ);
void SetVolume(float volume);
virtual void Stop() = 0;
protected:
NzSoundEmitter();
NzSoundEmitter(const NzSoundEmitter& emitter);
nzSoundStatus GetInternalStatus() const;
unsigned int m_source;
};
#endif // NAZARA_SOUNDEMITTER_HPP

View File

@ -7,6 +7,8 @@
#ifndef NAZARA_INITIALIZER_HPP
#define NAZARA_INITIALIZER_HPP
///TODO: Utiliser les variadic template pour initialiser plusieurs modules à la fois ?
#include <Nazara/Prerequesites.hpp>
template<typename T>

View File

@ -17,7 +17,8 @@ NzInitializer<T>::NzInitializer(Args... args)
template<typename T>
NzInitializer<T>::~NzInitializer()
{
T::Uninitialize();
if (T::IsInitialized())
T::Uninitialize();
}
template<typename T>

View File

@ -193,7 +193,7 @@ T NzNormalizeAngle(T angle)
template<typename T>
bool NzNumberEquals(T a, T b)
{
return std::fabs(a-b) <= std::numeric_limits<T>::epsilon();
return std::fabs(a-b) < std::numeric_limits<T>::epsilon();
}
NzString NzNumberToString(long long number, nzUInt8 radix)

285
src/Nazara/Audio/Audio.cpp Normal file
View 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;

View 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

View 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
View 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);
}

View 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;

View 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;
}