From 3f0bb8a8bbb58df0bea38f460005f6f252171303 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 29 Nov 2012 17:33:58 +0100 Subject: [PATCH 1/5] Added music class Former-commit-id: 5288191ecea17cb81e30a175869a2b4ea29dbc2f --- include/Nazara/Audio.hpp | 2 + include/Nazara/Audio/Music.hpp | 70 +++++++ include/Nazara/Audio/SoundStream.hpp | 28 +++ src/Nazara/Audio/Music.cpp | 278 +++++++++++++++++++++++++++ src/Nazara/Audio/SoundStream.cpp | 7 + 5 files changed, 385 insertions(+) create mode 100644 include/Nazara/Audio/Music.hpp create mode 100644 include/Nazara/Audio/SoundStream.hpp create mode 100644 src/Nazara/Audio/Music.cpp create mode 100644 src/Nazara/Audio/SoundStream.cpp diff --git a/include/Nazara/Audio.hpp b/include/Nazara/Audio.hpp index c1381421f..9b0e7d732 100644 --- a/include/Nazara/Audio.hpp +++ b/include/Nazara/Audio.hpp @@ -32,8 +32,10 @@ #include #include #include +#include #include #include #include +#include #endif // NAZARA_GLOBAL_AUDIO_HPP diff --git a/include/Nazara/Audio/Music.hpp b/include/Nazara/Audio/Music.hpp new file mode 100644 index 000000000..766b23514 --- /dev/null +++ b/include/Nazara/Audio/Music.hpp @@ -0,0 +1,70 @@ +// 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_MUSIC_HPP +#define NAZARA_MUSIC_HPP + +#include +#include +#include +#include + +struct NzMusicParams +{ + bool IsValid() const; +}; + +class NzMusic; +class NzSoundStream; +class NzThread; + +using NzMusicLoader = NzResourceLoader; + +struct NzMusicImpl; + +class NAZARA_API NzMusic : public NzSoundEmitter +{ + friend NzMusicLoader; + + public: + NzMusic() = default; + ~NzMusic(); + + bool Create(NzSoundStream* soundStream); + void Destroy(); + + void EnableLooping(bool loop); + + nzUInt32 GetDuration() const; + nzAudioFormat GetFormat() const; + nzUInt32 GetPlayingOffset() const; + unsigned int GetSampleCount() const; + unsigned int GetSampleRate() const; + nzSoundStatus GetStatus() const; + + bool IsLooping() const; + + bool OpenFromFile(const NzString& filePath, const NzMusicParams& params = NzMusicParams()); + bool OpenFromMemory(const void* data, std::size_t size, const NzMusicParams& params = NzMusicParams()); + bool OpenFromStream(NzInputStream& stream, const NzMusicParams& params = NzMusicParams()); + + void Pause(); + bool Play(); + + void SetPlayingOffset(nzUInt32 offset); + + void Stop(); + + private: + NzMusicImpl* m_impl = nullptr; + + bool FillBuffer(unsigned int buffer); + void MusicThread(); + + static NzMusicLoader::LoaderList s_loaders; +}; + +#endif // NAZARA_MUSIC_HPP diff --git a/include/Nazara/Audio/SoundStream.hpp b/include/Nazara/Audio/SoundStream.hpp new file mode 100644 index 000000000..7a0c98705 --- /dev/null +++ b/include/Nazara/Audio/SoundStream.hpp @@ -0,0 +1,28 @@ +// 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_SOUNDSTREAM_HPP +#define NAZARA_SOUNDSTREAM_HPP + +#include +#include + +class NAZARA_API NzSoundStream +{ + public: + NzSoundStream() = default; + virtual ~NzSoundStream(); + + virtual nzUInt32 GetDuration() const = 0; + virtual nzAudioFormat GetFormat() const = 0; + virtual unsigned int GetSampleCount() const = 0; + virtual unsigned int GetSampleRate() const = 0; + + virtual unsigned int Read(void* buffer, unsigned int sampleCount) = 0; + virtual void Seek(nzUInt32 offset) = 0; +}; + +#endif // NAZARA_SOUNDSTREAM_HPP diff --git a/src/Nazara/Audio/Music.cpp b/src/Nazara/Audio/Music.cpp new file mode 100644 index 000000000..1c4a5b4df --- /dev/null +++ b/src/Nazara/Audio/Music.cpp @@ -0,0 +1,278 @@ +// 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 +#include +#include +#include +#include +#include +#include + +bool NzMusicParams::IsValid() const +{ + return true; +} + +struct NzMusicImpl +{ + ALenum audioFormat; + std::vector chunkSamples; + NzSoundStream* stream; + NzThread* thread = nullptr; + bool loop = false; + bool playing = false; + bool paused = false; + unsigned int sampleRate; +}; + +NzMusic::~NzMusic() +{ + Destroy(); +} + +bool NzMusic::Create(NzSoundStream* soundStream) +{ + Destroy(); + + #if NAZARA_AUDIO_SAFE + if (!soundStream) + { + NazaraError("Sound stream must be valid"); + return false; + } + #endif + + nzAudioFormat format = soundStream->GetFormat(); + + m_impl = new NzMusicImpl; + m_impl->sampleRate = soundStream->GetSampleRate(); + m_impl->audioFormat = NzAudio::GetOpenALFormat(format); + m_impl->chunkSamples.resize(format * m_impl->sampleRate); // Une seconde de samples + m_impl->stream = soundStream; + + return true; +} + +void NzMusic::Destroy() +{ + if (m_impl) + { + Stop(); + + delete m_impl; + m_impl = nullptr; + } +} + +void NzMusic::EnableLooping(bool loop) +{ + #if NAZARA_AUDIO_SAFE + if (!m_impl) + { + NazaraError("Music not created"); + return; + } + #endif + + m_impl->loop = loop; +} + +nzUInt32 NzMusic::GetDuration() const +{ + #if NAZARA_AUDIO_SAFE + if (!m_impl) + { + NazaraError("Music not created"); + return 0; + } + #endif + + return m_impl->stream->GetDuration(); +} + +nzUInt32 NzMusic::GetPlayingOffset() const +{ + #if NAZARA_AUDIO_SAFE + if (!m_impl) + { + NazaraError("Music not created"); + return 0; + } + #endif + + return 0; +} + +nzSoundStatus NzMusic::GetStatus() const +{ + #if NAZARA_AUDIO_SAFE + if (!m_impl) + { + NazaraError("Music not created"); + return nzSoundStatus_Stopped; + } + #endif + + nzSoundStatus status = GetInternalStatus(); + + if (m_impl->playing && status == nzSoundStatus_Stopped) + status = nzSoundStatus_Playing; + + return status; +} + +bool NzMusic::IsLooping() const +{ + #if NAZARA_AUDIO_SAFE + if (!m_impl) + { + NazaraError("Music not created"); + return false; + } + #endif + + return m_impl->loop; +} + +bool NzMusic::OpenFromFile(const NzString& filePath, const NzMusicParams& params) +{ + return NzMusicLoader::LoadFromFile(this, filePath, params); +} + +bool NzMusic::OpenFromMemory(const void* data, std::size_t size, const NzMusicParams& params) +{ + return NzMusicLoader::LoadFromMemory(this, data, size, params); +} + +bool NzMusic::OpenFromStream(NzInputStream& stream, const NzMusicParams& params) +{ + return NzMusicLoader::LoadFromStream(this, stream, params); +} + +void NzMusic::Pause() +{ + return; +} + +bool NzMusic::Play() +{ + #if NAZARA_AUDIO_SAFE + if (!m_impl) + { + NazaraError("Music not created"); + return false; + } + #endif + + /*if (m_impl->playing) + { + if (m_impl->paused) + alSourcePlay(m_source); + else + // On repositionne au début + m_impl->stream->Seek(0); + + return true; + }*/ + + m_impl->playing = true; + m_impl->thread = new NzThread(&NzMusic::MusicThread, this); + m_impl->thread->Launch(); + + return true; +} + +void NzMusic::Stop() +{ + #if NAZARA_AUDIO_SAFE + if (!m_impl) + { + NazaraError("Music not created"); + return; + } + #endif + + if (m_impl->playing) + { + m_impl->playing = false; + m_impl->thread->Join(); + delete m_impl->thread; + m_impl->thread = nullptr; + } +} + +bool NzMusic::FillBuffer(unsigned int buffer) +{ + unsigned int sampleRead = m_impl->stream->Read(&m_impl->chunkSamples[0], m_impl->chunkSamples.size()); + if (sampleRead > 0) + alBufferData(buffer, m_impl->audioFormat, &m_impl->chunkSamples[0], sampleRead*sizeof(nzInt16), m_impl->sampleRate); + + return sampleRead != m_impl->chunkSamples.size(); // Fin du fichier +} + +void NzMusic::MusicThread() +{ + ALuint buffers[NAZARA_AUDIO_STREAMEDBUFFERCOUNT]; + alGenBuffers(NAZARA_AUDIO_STREAMEDBUFFERCOUNT, buffers); + + for (unsigned int i = 0; i < NAZARA_AUDIO_STREAMEDBUFFERCOUNT; ++i) + { + FillBuffer(buffers[i]); + alSourceQueueBuffers(m_source, 1, &buffers[i]); + } + + alSourcePlay(m_source); + + while (m_impl->playing) + { + nzSoundStatus status = GetInternalStatus(); + if (status == nzSoundStatus_Stopped) + { + NazaraError("Stopped !"); + if (m_impl->loop) + { + m_impl->stream->Seek(0); + for (unsigned int i = 0; i < NAZARA_AUDIO_STREAMEDBUFFERCOUNT; ++i) + { + FillBuffer(buffers[i]); + alSourceQueueBuffers(m_source, 1, &buffers[i]); + } + + alSourcePlay(m_source); + } + else + m_impl->playing = false; + + break; + } + + ALint processedCount = 0; + alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processedCount); + + if (processedCount > 0) + NazaraWarning(NzString::Number(processedCount)); + + ALuint buffer; + while (processedCount--) + { + alSourceUnqueueBuffers(m_source, 1, &buffer); + FillBuffer(buffer); + alSourceQueueBuffers(m_source, 1, &buffer); + } + + NzThread::Sleep(NAZARA_AUDIO_STREAMEDBUFFERCOUNT*500); + } + + ALint queuedBufferCount; + alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queuedBufferCount); + + ALuint buffer; + for (ALint i = 0; i < queuedBufferCount; ++i) + alSourceUnqueueBuffers(m_source, 1, &buffer); + + alDeleteBuffers(NAZARA_AUDIO_STREAMEDBUFFERCOUNT, buffers); +} + +NzMusicLoader::LoaderList NzMusic::s_loaders; diff --git a/src/Nazara/Audio/SoundStream.cpp b/src/Nazara/Audio/SoundStream.cpp new file mode 100644 index 000000000..bc56f1d1a --- /dev/null +++ b/src/Nazara/Audio/SoundStream.cpp @@ -0,0 +1,7 @@ +// 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 + +NzSoundStream::~NzSoundStream() = default; From 7754ca36a46c5ab9947907a0023827b7261a1064 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 2 Dec 2012 21:09:59 +0100 Subject: [PATCH 2/5] Added Music loader Former-commit-id: b0f1415a9fbc84152fa716c58794228d38c0bc63 --- src/Nazara/Audio/Loaders/sndfile/Loader.cpp | 159 ++++++++++++++++---- 1 file changed, 130 insertions(+), 29 deletions(-) diff --git a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp index c925e6fa6..dccf2d6cc 100644 --- a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp +++ b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp @@ -4,7 +4,9 @@ #include #include +#include #include +#include #include #include #include @@ -15,6 +17,8 @@ namespace { + const char* supportedFormats = "aiff,au,avr,caf,flac,htk,ircam,mat4,mat5,mpc2k,nist,ogg,paf,pvf,raw,rf64,sd2,sds,svx,voc,w64,wav,wve"; + sf_count_t GetSize(void* user_data) { NzInputStream* stream = static_cast(user_data); @@ -59,7 +63,90 @@ namespace static SF_VIRTUAL_IO callbacks = {GetSize, Seek, Read, nullptr, Tell}; - bool NzLoader_sndfile_Check(NzInputStream& stream, const NzSoundBufferParams& parameters) + class sndfileStream : public NzSoundStream + { + public: + sndfileStream() = default; + + ~sndfileStream() + { + if (m_file) + sf_close(m_file); + } + + nzUInt32 GetDuration() const + { + return m_duration; + } + + nzAudioFormat GetFormat() const + { + return m_format; + } + + unsigned int GetSampleCount() const + { + return m_sampleCount; + } + + unsigned int GetSampleRate() const + { + return m_sampleRate; + } + + bool Open(NzInputStream& stream) + { + SF_INFO infos; + m_file = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream); + if (!m_file) + { + NazaraError("Failed to open sound: " + NzString(sf_strerror(m_file))); + return false; + } + + m_format = NzAudio::GetAudioFormat(infos.channels); + if (m_format == nzAudioFormat_Unknown) + { + NazaraError("Channel count not handled"); + sf_close(m_file); + m_file = nullptr; + + return false; + } + + m_sampleCount = infos.channels*infos.frames; + m_sampleRate = infos.samplerate; + + m_duration = 1000*m_sampleCount / (m_format*m_sampleRate); + + // https://github.com/LaurentGomila/SFML/issues/271 + // http://www.mega-nerd.com/libsndfile/command.html#SFC_SET_SCALE_FLOAT_INT_READ + ///FIXME: Seulement le Vorbis ? + /*if (infos.format & SF_FORMAT_VORBIS) + sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);*/ + + return true; + } + + unsigned int Read(void* buffer, unsigned int sampleCount) + { + return sf_read_short(m_file, reinterpret_cast(buffer), sampleCount); + } + + void Seek(nzUInt32 offset) + { + sf_seek(m_file, offset*m_sampleRate / 1000, SEEK_SET); + } + + private: + nzAudioFormat m_format; + SNDFILE* m_file = nullptr; + unsigned int m_duration; + unsigned int m_sampleCount; + unsigned int m_sampleRate; + }; + + bool NzLoader_sndfile_Check_Music(NzInputStream& stream, const NzMusicParams& parameters) { NazaraUnused(parameters); @@ -74,51 +161,65 @@ namespace return false; } - bool NzLoader_sndfile_Load(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters) + bool NzLoader_sndfile_Load_Music(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) { NazaraUnused(parameters); - SF_INFO infos; - SNDFILE* file = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream); - if (!file) + sndfileStream* musicStream = new sndfileStream; + if (!musicStream->Open(stream)) { - NazaraError("Failed to load sound file: " + NzString(sf_strerror(file))); + // L'erreur a déjà été signalée par la méthode + delete musicStream; + return false; } - nzAudioFormat format = NzAudio::GetAudioFormat(infos.channels); - if (format == nzAudioFormat_Unknown) + if (!music->Create(musicStream)) + { + NazaraError("Failed to create music"); + delete musicStream; + + return false; + } + + return true; + } + + bool NzLoader_sndfile_Check_SoundBuffer(NzInputStream& stream, const NzSoundBufferParams& parameters) + { + NazaraUnused(parameters); + + SF_INFO info; + SNDFILE* file = sf_open_virtual(&callbacks, SFM_READ, &info, &stream); + if (file) { - NazaraError("Channel count not handled"); sf_close(file); - - return false; + return true; } + else + return false; + } - // https://github.com/LaurentGomila/SFML/issues/271 - // http://www.mega-nerd.com/libsndfile/command.html#SFC_SET_SCALE_FLOAT_INT_READ - ///FIXME: Seulement le Vorbis ? - if (infos.format & SF_FORMAT_VORBIS) - sf_command(file, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE); + bool NzLoader_sndfile_Load_SoundBuffer(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters) + { + NazaraUnused(parameters); - unsigned int sampleCount = infos.frames*infos.channels; + sndfileStream musicStream; + if (!musicStream.Open(stream)) + return false; // L'erreur a déjà été envoyée par la méthode + + unsigned int sampleCount = musicStream.GetSampleCount(); nzInt16* samples = new nzInt16[sampleCount]; - if (sf_read_short(file, samples, sampleCount) != sampleCount) + if (musicStream.Read(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)) + if (!soundBuffer->Create(musicStream.GetFormat(), sampleCount, musicStream.GetSampleRate(), samples)) { NazaraError("Failed to create sound buffer"); - delete[] samples; - sf_close(file); return false; } @@ -131,12 +232,12 @@ namespace 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); + NzMusicLoader::RegisterLoader(supportedFormats, NzLoader_sndfile_Check_Music, NzLoader_sndfile_Load_Music); + NzSoundBufferLoader::RegisterLoader(supportedFormats, NzLoader_sndfile_Check_SoundBuffer, NzLoader_sndfile_Load_SoundBuffer); } 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); + NzMusicLoader::UnregisterLoader(supportedFormats, NzLoader_sndfile_Check_Music, NzLoader_sndfile_Load_Music); + NzSoundBufferLoader::UnregisterLoader(supportedFormats, NzLoader_sndfile_Check_SoundBuffer, NzLoader_sndfile_Load_SoundBuffer); } From b4c7818200878a26243d120864c4e374e1660217 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 23 Mar 2013 22:49:06 +0100 Subject: [PATCH 3/5] CherryPicked commit "Reworked ResourceLoader" Conflicts: src/Nazara/Utility/Loaders/MD2/Loader.cpp Former-commit-id: 708c34c80f78cca224012149cf1d8faf37922463 --- include/Nazara/Core/ResourceLoader.hpp | 15 ++- include/Nazara/Core/ResourceLoader.inl | 112 +++++++++++------ src/Nazara/Audio/Loaders/sndfile/Loader.cpp | 119 ++++++++++++------ src/Nazara/Audio/Music.cpp | 9 +- .../Renderer/Loaders/Texture/Loader.cpp | 5 +- src/Nazara/Utility/Loaders/MD2/Loader.cpp | 14 ++- src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp | 9 +- src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp | 9 +- src/Nazara/Utility/Loaders/PCX/Loader.cpp | 9 +- src/Nazara/Utility/Loaders/STB/Loader.cpp | 10 +- 10 files changed, 209 insertions(+), 102 deletions(-) diff --git a/include/Nazara/Core/ResourceLoader.hpp b/include/Nazara/Core/ResourceLoader.hpp index a1a5e8ecf..0fa307769 100644 --- a/include/Nazara/Core/ResourceLoader.hpp +++ b/include/Nazara/Core/ResourceLoader.hpp @@ -9,7 +9,6 @@ #include #include -#include #include class NzInputStream; @@ -18,17 +17,21 @@ template class NzResourceLoader { public: - using CheckFunction = bool (*)(NzInputStream& stream, const Parameters& parameters); - using LoadFunction = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters); + using ExtensionGetter = bool (*)(const NzString& extension); + using FileLoader = bool (*)(Type* resource, const NzString& filePath, const Parameters& parameters); + using StreamChecker = bool (*)(NzInputStream& stream, const Parameters& parameters); + using StreamLoader = bool (*)(Type* resource, NzInputStream& stream, const Parameters& parameters); + + static bool IsExtensionSupported(const NzString& extension); static bool LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters = Parameters()); static bool LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters = Parameters()); static bool LoadFromStream(Type* resource, NzInputStream& stream, const Parameters& parameters = Parameters()); - static void RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadfunc); - static void UnregisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadfunc); + static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); + static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr); - using Loader = std::tuple, CheckFunction, LoadFunction>; + using Loader = std::tuple; using LoaderList = std::list; }; diff --git a/include/Nazara/Core/ResourceLoader.inl b/include/Nazara/Core/ResourceLoader.inl index 659d3dd24..6444c928c 100644 --- a/include/Nazara/Core/ResourceLoader.inl +++ b/include/Nazara/Core/ResourceLoader.inl @@ -9,6 +9,20 @@ #include #include +template +bool NzResourceLoader::IsExtensionSupported(const NzString& extension) +{ + for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader) + { + ExtensionGetter isExtensionSupported = std::get<0>(*loader); + + if (isExtensionSupported && isExtensionSupported(extension)) + return true; + } + + return false; +} + template bool NzResourceLoader::LoadFromFile(Type* resource, const NzString& filePath, const Parameters& parameters) { @@ -28,38 +42,54 @@ bool NzResourceLoader::LoadFromFile(Type* resource, const NzSt return false; } - NzFile file(path, NzFile::ReadOnly); - if (!file.IsOpen()) - { - NazaraError("Failed to open \"" + path + '"'); - return false; - } + NzFile file(path); // Ouvert seulement en cas de besoin for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader) { - for (const NzString& loaderExt : std::get<0>(*loader)) + ExtensionGetter isExtensionSupported = std::get<0>(*loader); + if (!isExtensionSupported || !isExtensionSupported(ext)) + continue; + + StreamChecker checkFunc = std::get<1>(*loader); + StreamLoader streamLoader = std::get<2>(*loader); + FileLoader fileLoader = std::get<3>(*loader); + + if (checkFunc && !file.IsOpen()) { - int cmp = NzString::Compare(loaderExt, ext); - if (cmp == 0) + if (!file.Open(NzFile::ReadOnly)) + { + NazaraError("Failed to load file: unable to open file"); + return false; + } + } + + if (fileLoader) + { + if (checkFunc) { file.SetCursorPos(0); - if (!std::get<1>(*loader)(file, parameters)) + if (!checkFunc(file, parameters)) continue; - - file.SetCursorPos(0); - - // Chargement de la ressource - if (std::get<2>(*loader)(resource, file, parameters)) - return true; - - NazaraWarning("Loader failed"); } - else if (cmp < 0) // S'il est encore possible que l'extension se situe après + + if (fileLoader(resource, filePath, parameters)) + return true; + } + else + { + file.SetCursorPos(0); + + if (!checkFunc(file, parameters)) continue; - break; + file.SetCursorPos(0); + + if (streamLoader(resource, file, parameters)) + return true; } + + NazaraWarning("Loader failed"); } NazaraError("Failed to load file: no loader"); @@ -95,17 +125,20 @@ bool NzResourceLoader::LoadFromStream(Type* resource, NzInputS nzUInt64 streamPos = stream.GetCursorPos(); for (auto loader = Type::s_loaders.begin(); loader != Type::s_loaders.end(); ++loader) { + StreamChecker checkFunc = std::get<1>(*loader); + StreamLoader streamLoader = std::get<2>(*loader); + stream.SetCursorPos(streamPos); // Le loader supporte-t-il les données ? - if (!std::get<1>(*loader)(stream, parameters)) + if (!checkFunc(stream, parameters)) continue; // On repositionne le stream à son ancienne position stream.SetCursorPos(streamPos); // Chargement de la ressource - if (std::get<2>(*loader)(resource, stream, parameters)) + if (streamLoader(resource, stream, parameters)) return true; NazaraWarning("Loader failed"); @@ -116,28 +149,31 @@ bool NzResourceLoader::LoadFromStream(Type* resource, NzInputS } template -void NzResourceLoader::RegisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc) +void NzResourceLoader::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) { - ///FIXME: Trouver une alternative à ce code monstrueux - std::vector exts; - fileExtensions.SplitAny(exts, " /\\.,;|-_"); + #if NAZARA_CORE_SAFE + if (streamLoader) + { + if (!checkFunc) + { + NazaraError("StreamLoader present without StreamChecker"); + return; + } + } + else if (!fileLoader) + { + NazaraError("Neither FileLoader nor StreamLoader were found"); + return; + } + #endif - std::set extensions; - std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin())); - - Type::s_loaders.push_front(std::make_tuple(std::move(extensions), checkFunc, loadFunc)); + Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); } template -void NzResourceLoader::UnregisterLoader(const NzString& fileExtensions, CheckFunction checkFunc, LoadFunction loadFunc) +void NzResourceLoader::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader) { - std::vector exts; - fileExtensions.SplitAny(exts, " /\\.,;|-_"); - - std::set extensions; - std::copy(exts.begin(), exts.end(), std::inserter(extensions, extensions.begin())); - - Type::s_loaders.remove(std::make_tuple(std::move(extensions), checkFunc, loadFunc)); + Type::s_loaders.remove(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader)); } #include diff --git a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp index dccf2d6cc..a9761aa74 100644 --- a/src/Nazara/Audio/Loaders/sndfile/Loader.cpp +++ b/src/Nazara/Audio/Loaders/sndfile/Loader.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -12,13 +13,13 @@ #include #include #include +#include +#include #include #include namespace { - const char* supportedFormats = "aiff,au,avr,caf,flac,htk,ircam,mat4,mat5,mpc2k,nist,ogg,paf,pvf,raw,rf64,sd2,sds,svx,voc,w64,wav,wve"; - sf_count_t GetSize(void* user_data) { NzInputStream* stream = static_cast(user_data); @@ -66,12 +67,19 @@ namespace class sndfileStream : public NzSoundStream { public: - sndfileStream() = default; + sndfileStream() : + m_file(nullptr), + m_handle(nullptr) + { + } ~sndfileStream() { + if (m_handle) + sf_close(m_handle); + if (m_file) - sf_close(m_file); + delete m_file; } nzUInt32 GetDuration() const @@ -94,13 +102,25 @@ namespace return m_sampleRate; } + bool Open(const NzString& filePath) + { + m_file = new NzFile(filePath); + if (!m_file->Open(NzFile::ReadOnly)) + { + NazaraError("Failed to open file " + filePath); + return false; + } + + return Open(*m_file); + } + bool Open(NzInputStream& stream) { SF_INFO infos; - m_file = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream); - if (!m_file) + m_handle = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream); + if (!m_handle) { - NazaraError("Failed to open sound: " + NzString(sf_strerror(m_file))); + NazaraError("Failed to open sound: " + NzString(sf_strerror(m_handle))); return false; } @@ -108,8 +128,8 @@ namespace if (m_format == nzAudioFormat_Unknown) { NazaraError("Channel count not handled"); - sf_close(m_file); - m_file = nullptr; + sf_close(m_handle); + m_handle = nullptr; return false; } @@ -123,30 +143,40 @@ namespace // http://www.mega-nerd.com/libsndfile/command.html#SFC_SET_SCALE_FLOAT_INT_READ ///FIXME: Seulement le Vorbis ? /*if (infos.format & SF_FORMAT_VORBIS) - sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);*/ + sf_command(m_handle, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);*/ return true; } unsigned int Read(void* buffer, unsigned int sampleCount) { - return sf_read_short(m_file, reinterpret_cast(buffer), sampleCount); + return sf_read_short(m_handle, reinterpret_cast(buffer), sampleCount); } void Seek(nzUInt32 offset) { - sf_seek(m_file, offset*m_sampleRate / 1000, SEEK_SET); + sf_seek(m_handle, offset*m_sampleRate / 1000, SEEK_SET); } private: nzAudioFormat m_format; - SNDFILE* m_file = nullptr; + NzFile* m_file; + SNDFILE* m_handle; unsigned int m_duration; unsigned int m_sampleCount; unsigned int m_sampleRate; }; - bool NzLoader_sndfile_Check_Music(NzInputStream& stream, const NzMusicParams& parameters) + bool IsSupported(const NzString& extension) + { + static std::set supportedExtensions = { + "aiff", "au", "avr", "caf", "flac", "htk", "ircam", "mat4", "mat5", "mpc2k", + "nist","ogg", "pvf", "raw", "rf64", "sd2", "sds", "svx", "voc", "w64", "wav", "wve"}; + + return supportedExtensions.find(extension) != supportedExtensions.end(); + } + + bool CheckMusic(NzInputStream& stream, const NzMusicParams& parameters) { NazaraUnused(parameters); @@ -161,31 +191,51 @@ namespace return false; } - bool NzLoader_sndfile_Load_Music(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) + bool LoadMusicFile(NzMusic* music, const NzString& filePath, const NzMusicParams& parameters) { NazaraUnused(parameters); - sndfileStream* musicStream = new sndfileStream; - if (!musicStream->Open(stream)) + std::unique_ptr musicStream(new sndfileStream); + if (!musicStream->Open(filePath)) { - // L'erreur a déjà été signalée par la méthode - delete musicStream; - + NazaraError("Failed to open music stream"); return false; } - if (!music->Create(musicStream)) + if (!music->Create(musicStream.get())) { NazaraError("Failed to create music"); - delete musicStream; - return false; } + musicStream.release(); + return true; } - bool NzLoader_sndfile_Check_SoundBuffer(NzInputStream& stream, const NzSoundBufferParams& parameters) + bool LoadMusicStream(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr musicStream(new sndfileStream); + if (!musicStream->Open(stream)) + { + NazaraError("Failed to open music stream"); + return false; + } + + if (!music->Create(musicStream.get())) + { + NazaraError("Failed to create music"); + return false; + } + + musicStream.release(); + + return true; + } + + bool CheckSoundBuffer(NzInputStream& stream, const NzSoundBufferParams& parameters) { NazaraUnused(parameters); @@ -200,7 +250,7 @@ namespace return false; } - bool NzLoader_sndfile_Load_SoundBuffer(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters) + bool LoadSoundBuffer(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters) { NazaraUnused(parameters); @@ -209,35 +259,32 @@ namespace return false; // L'erreur a déjà été envoyée par la méthode unsigned int sampleCount = musicStream.GetSampleCount(); - nzInt16* samples = new nzInt16[sampleCount]; - if (musicStream.Read(samples, sampleCount) != sampleCount) + std::unique_ptr samples(new nzInt16[sampleCount]); + + if (musicStream.Read(samples.get(), sampleCount) != sampleCount) { NazaraError("Failed to read samples"); return false; } - if (!soundBuffer->Create(musicStream.GetFormat(), sampleCount, musicStream.GetSampleRate(), samples)) + if (!soundBuffer->Create(musicStream.GetFormat(), sampleCount, musicStream.GetSampleRate(), samples.get())) { NazaraError("Failed to create sound buffer"); - delete[] samples; - return false; } - delete[] samples; - return true; } } void NzLoaders_sndfile_Register() { - NzMusicLoader::RegisterLoader(supportedFormats, NzLoader_sndfile_Check_Music, NzLoader_sndfile_Load_Music); - NzSoundBufferLoader::RegisterLoader(supportedFormats, NzLoader_sndfile_Check_SoundBuffer, NzLoader_sndfile_Load_SoundBuffer); + NzMusicLoader::RegisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); + NzSoundBufferLoader::RegisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); } void NzLoaders_sndfile_Unregister() { - NzMusicLoader::UnregisterLoader(supportedFormats, NzLoader_sndfile_Check_Music, NzLoader_sndfile_Load_Music); - NzSoundBufferLoader::UnregisterLoader(supportedFormats, NzLoader_sndfile_Check_SoundBuffer, NzLoader_sndfile_Load_SoundBuffer); + NzMusicLoader::UnregisterLoader(IsSupported, CheckMusic, LoadMusicStream, LoadMusicFile); + NzSoundBufferLoader::UnregisterLoader(IsSupported, CheckSoundBuffer, LoadSoundBuffer); } diff --git a/src/Nazara/Audio/Music.cpp b/src/Nazara/Audio/Music.cpp index 1c4a5b4df..ebb6837ad 100644 --- a/src/Nazara/Audio/Music.cpp +++ b/src/Nazara/Audio/Music.cpp @@ -20,7 +20,7 @@ struct NzMusicImpl ALenum audioFormat; std::vector chunkSamples; NzSoundStream* stream; - NzThread* thread = nullptr; + NzThread thread; bool loop = false; bool playing = false; bool paused = false; @@ -178,8 +178,7 @@ bool NzMusic::Play() }*/ m_impl->playing = true; - m_impl->thread = new NzThread(&NzMusic::MusicThread, this); - m_impl->thread->Launch(); + m_impl->thread = NzThread(&NzMusic::MusicThread, this); return true; } @@ -197,9 +196,7 @@ void NzMusic::Stop() if (m_impl->playing) { m_impl->playing = false; - m_impl->thread->Join(); - delete m_impl->thread; - m_impl->thread = nullptr; + m_impl->thread.Join(); } } diff --git a/src/Nazara/Renderer/Loaders/Texture/Loader.cpp b/src/Nazara/Renderer/Loaders/Texture/Loader.cpp index 902609f87..a3688083c 100644 --- a/src/Nazara/Renderer/Loaders/Texture/Loader.cpp +++ b/src/Nazara/Renderer/Loaders/Texture/Loader.cpp @@ -38,11 +38,10 @@ namespace void NzLoaders_Texture_Register() { - ///FIXME: Pas bon - NzMaterialLoader::RegisterLoader("bmp,gif,hdr,jpg,jpeg,pic,png,psd,tga", Check, Load); + NzMaterialLoader::RegisterLoader(NzImageLoader::IsExtensionSupported, Check, Load); } void NzLoaders_Texture_Unregister() { - NzMaterialLoader::UnregisterLoader("bmp,gif,hdr,jpg,jpeg,pic,png,psd,tga", Check, Load); + NzMaterialLoader::UnregisterLoader(NzImageLoader::IsExtensionSupported, Check, Load); } diff --git a/src/Nazara/Utility/Loaders/MD2/Loader.cpp b/src/Nazara/Utility/Loaders/MD2/Loader.cpp index c4cc78ce8..c1532550c 100644 --- a/src/Nazara/Utility/Loaders/MD2/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD2/Loader.cpp @@ -19,7 +19,11 @@ namespace { - /// Loader de mesh + bool IsSupported(const NzString& extension) + { + return (extension == "md2"); + } + bool CheckMesh(NzInputStream& stream, const NzMeshParams& parameters) { NazaraUnused(parameters); @@ -330,12 +334,12 @@ namespace void NzLoaders_MD2_Register() { - NzAnimationLoader::RegisterLoader("md2", CheckAnim, LoadAnim); - NzMeshLoader::RegisterLoader("md2", CheckMesh, LoadMesh); + NzAnimationLoader::RegisterLoader(IsSupported, CheckAnim, LoadAnim); + NzMeshLoader::RegisterLoader(IsSupported, CheckMesh, LoadMesh); } void NzLoaders_MD2_Unregister() { - NzAnimationLoader::UnregisterLoader("md2", CheckAnim, LoadAnim); - NzMeshLoader::UnregisterLoader("md2", CheckMesh, LoadMesh); + NzAnimationLoader::UnregisterLoader(IsSupported, CheckAnim, LoadAnim); + NzMeshLoader::UnregisterLoader(IsSupported, CheckMesh, LoadMesh); } diff --git a/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp b/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp index 58d9dba49..f48192e95 100644 --- a/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD5Anim/Loader.cpp @@ -8,6 +8,11 @@ namespace { + bool IsSupported(const NzString& extension) + { + return (extension == "md5anim"); + } + bool Check(NzInputStream& stream, const NzAnimationParams& parameters) { NzMD5AnimParser parser(stream, parameters); @@ -23,10 +28,10 @@ namespace void NzLoaders_MD5Anim_Register() { - NzAnimationLoader::RegisterLoader("md5anim", Check, Load); + NzAnimationLoader::RegisterLoader(IsSupported, Check, Load); } void NzLoaders_MD5Anim_Unregister() { - NzAnimationLoader::UnregisterLoader("md5anim", Check, Load); + NzAnimationLoader::UnregisterLoader(IsSupported, Check, Load); } diff --git a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp index c4f84c578..a9848c65f 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh/Loader.cpp @@ -8,6 +8,11 @@ namespace { + bool IsSupported(const NzString& extension) + { + return (extension == "md5mesh"); + } + bool Check(NzInputStream& stream, const NzMeshParams& parameters) { NzMD5MeshParser parser(stream, parameters); @@ -23,10 +28,10 @@ namespace void NzLoaders_MD5Mesh_Register() { - NzMeshLoader::RegisterLoader("md5mesh", Check, Load); + NzMeshLoader::RegisterLoader(IsSupported, Check, Load); } void NzLoaders_MD5Mesh_Unregister() { - NzMeshLoader::UnregisterLoader("md5mesh", Check, Load); + NzMeshLoader::UnregisterLoader(IsSupported, Check, Load); } diff --git a/src/Nazara/Utility/Loaders/PCX/Loader.cpp b/src/Nazara/Utility/Loaders/PCX/Loader.cpp index ee9a20cbc..579b9ca6f 100644 --- a/src/Nazara/Utility/Loaders/PCX/Loader.cpp +++ b/src/Nazara/Utility/Loaders/PCX/Loader.cpp @@ -39,6 +39,11 @@ namespace //static_assert(sizeof(pcx_header) == 1024, "PCX header must be 1024 bytes sized"); + bool IsSupported(const NzString& extension) + { + return (extension == "pcx"); + } + bool Check(NzInputStream& stream, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -339,10 +344,10 @@ namespace void NzLoaders_PCX_Register() { - NzImageLoader::RegisterLoader("pcx", Check, Load); + NzImageLoader::RegisterLoader(IsSupported, Check, Load); } void NzLoaders_PCX_Unregister() { - NzImageLoader::UnregisterLoader("pcx", Check, Load); + NzImageLoader::UnregisterLoader(IsSupported, Check, Load); } diff --git a/src/Nazara/Utility/Loaders/STB/Loader.cpp b/src/Nazara/Utility/Loaders/STB/Loader.cpp index 6baad965a..7b75d33c7 100644 --- a/src/Nazara/Utility/Loaders/STB/Loader.cpp +++ b/src/Nazara/Utility/Loaders/STB/Loader.cpp @@ -37,6 +37,12 @@ namespace static stbi_io_callbacks callbacks = {Read, Skip, Eof}; + bool IsSupported(const NzString& extension) + { + static std::set supportedExtensions = {"bmp", "gif", "hdr", "jpg", "jpeg", "pic", "png", "psd", "tga"}; + return supportedExtensions.find(extension) != supportedExtensions.end(); + } + bool Check(NzInputStream& stream, const NzImageParams& parameters) { NazaraUnused(parameters); @@ -117,10 +123,10 @@ namespace void NzLoaders_STB_Register() { - NzImageLoader::RegisterLoader("bmp,gif,hdr,jpg,jpeg,pic,png,psd,tga", Check, Load); + NzImageLoader::RegisterLoader(IsSupported, Check, Load); } void NzLoaders_STB_Unregister() { - NzImageLoader::UnregisterLoader("bmp,gif,hdr,jpg,jpeg,pic,png,psd,tga", Check, Load); + NzImageLoader::UnregisterLoader(IsSupported, Check, Load); } From 2fb46d6317261e4633f76dac3257b5b1f1f722bf Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 1 Apr 2013 23:23:47 +0200 Subject: [PATCH 4/5] Fixed some leaks Former-commit-id: 77aca881473ddd034355248052b5d0ce627cc9bb --- src/Nazara/Audio/Music.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Nazara/Audio/Music.cpp b/src/Nazara/Audio/Music.cpp index ebb6837ad..ac2d856b8 100644 --- a/src/Nazara/Audio/Music.cpp +++ b/src/Nazara/Audio/Music.cpp @@ -61,6 +61,7 @@ void NzMusic::Destroy() { Stop(); + delete m_impl->stream; delete m_impl; m_impl = nullptr; } From d98906933619b6a5023c00afb6c182903a4fa5aa Mon Sep 17 00:00:00 2001 From: Lynix Date: Tue, 2 Apr 2013 01:40:19 +0200 Subject: [PATCH 5/5] Fixed music looping Former-commit-id: 2484c81da5e2f0c0ef72cfbad26e53df129662e7 --- include/Nazara/Audio/Music.hpp | 2 +- include/Nazara/Audio/Sound.hpp | 2 +- include/Nazara/Audio/SoundEmitter.hpp | 2 +- src/Nazara/Audio/Music.cpp | 79 +++++++++++++-------------- src/Nazara/Audio/Sound.cpp | 6 +- 5 files changed, 43 insertions(+), 48 deletions(-) diff --git a/include/Nazara/Audio/Music.hpp b/include/Nazara/Audio/Music.hpp index 766b23514..2191003b8 100644 --- a/include/Nazara/Audio/Music.hpp +++ b/include/Nazara/Audio/Music.hpp @@ -52,7 +52,7 @@ class NAZARA_API NzMusic : public NzSoundEmitter bool OpenFromStream(NzInputStream& stream, const NzMusicParams& params = NzMusicParams()); void Pause(); - bool Play(); + void Play(); void SetPlayingOffset(nzUInt32 offset); diff --git a/include/Nazara/Audio/Sound.hpp b/include/Nazara/Audio/Sound.hpp index 1b2ac77e6..d4c670839 100644 --- a/include/Nazara/Audio/Sound.hpp +++ b/include/Nazara/Audio/Sound.hpp @@ -34,7 +34,7 @@ class NAZARA_API NzSound : public NzSoundEmitter bool LoadFromStream(NzInputStream& stream, const NzSoundBufferParams& params = NzSoundBufferParams()); void Pause(); - bool Play(); + void Play(); void SetBuffer(const NzSoundBuffer* buffer); void SetPlayingOffset(nzUInt32 offset); diff --git a/include/Nazara/Audio/SoundEmitter.hpp b/include/Nazara/Audio/SoundEmitter.hpp index 7d4d41d6a..84d9d5f9b 100644 --- a/include/Nazara/Audio/SoundEmitter.hpp +++ b/include/Nazara/Audio/SoundEmitter.hpp @@ -35,7 +35,7 @@ class NAZARA_API NzSoundEmitter bool IsSpatialized() const; virtual void Pause() = 0; - virtual bool Play() = 0; + virtual void Play() = 0; void SetAttenuation(float attenuation); void SetMinDistance(float minDistance); diff --git a/src/Nazara/Audio/Music.cpp b/src/Nazara/Audio/Music.cpp index ac2d856b8..d098970c8 100644 --- a/src/Nazara/Audio/Music.cpp +++ b/src/Nazara/Audio/Music.cpp @@ -22,7 +22,7 @@ struct NzMusicImpl NzSoundStream* stream; NzThread thread; bool loop = false; - bool playing = false; + bool streaming = false; bool paused = false; unsigned int sampleRate; }; @@ -118,7 +118,7 @@ nzSoundStatus NzMusic::GetStatus() const nzSoundStatus status = GetInternalStatus(); - if (m_impl->playing && status == nzSoundStatus_Stopped) + if (m_impl->streaming && status == nzSoundStatus_Stopped) status = nzSoundStatus_Playing; return status; @@ -154,34 +154,32 @@ bool NzMusic::OpenFromStream(NzInputStream& stream, const NzMusicParams& params) void NzMusic::Pause() { - return; + alSourcePause(m_source); } -bool NzMusic::Play() +void NzMusic::Play() { #if NAZARA_AUDIO_SAFE if (!m_impl) { NazaraError("Music not created"); - return false; + return; } #endif - /*if (m_impl->playing) + if (m_impl->streaming) { - if (m_impl->paused) + if (GetStatus() != nzSoundStatus_Playing) alSourcePlay(m_source); - else - // On repositionne au début - m_impl->stream->Seek(0); - return true; - }*/ + return; + } - m_impl->playing = true; + m_impl->stream->Seek(0); + m_impl->streaming = true; m_impl->thread = NzThread(&NzMusic::MusicThread, this); - return true; + return; } void NzMusic::Stop() @@ -194,20 +192,31 @@ void NzMusic::Stop() } #endif - if (m_impl->playing) + if (m_impl->streaming) { - m_impl->playing = false; + m_impl->streaming = false; m_impl->thread.Join(); } } bool NzMusic::FillBuffer(unsigned int buffer) { - unsigned int sampleRead = m_impl->stream->Read(&m_impl->chunkSamples[0], m_impl->chunkSamples.size()); + unsigned int sampleCount = m_impl->chunkSamples.size(); + unsigned int sampleRead = 0; + + for (;;) + { + sampleRead += m_impl->stream->Read(&m_impl->chunkSamples[sampleRead], sampleCount-sampleRead); + if (sampleRead != sampleCount && m_impl->loop) + m_impl->stream->Seek(0); + else + break; + } + if (sampleRead > 0) alBufferData(buffer, m_impl->audioFormat, &m_impl->chunkSamples[0], sampleRead*sizeof(nzInt16), m_impl->sampleRate); - return sampleRead != m_impl->chunkSamples.size(); // Fin du fichier + return sampleRead != sampleCount; // Fin du fichier (N'arrive pas en cas de loop) } void NzMusic::MusicThread() @@ -217,52 +226,40 @@ void NzMusic::MusicThread() for (unsigned int i = 0; i < NAZARA_AUDIO_STREAMEDBUFFERCOUNT; ++i) { - FillBuffer(buffers[i]); + bool eof = FillBuffer(buffers[i]); alSourceQueueBuffers(m_source, 1, &buffers[i]); + + if (eof) + break; // Nous avons fini, nous ne continuons pas } alSourcePlay(m_source); - while (m_impl->playing) + while (m_impl->streaming) { nzSoundStatus status = GetInternalStatus(); if (status == nzSoundStatus_Stopped) { - NazaraError("Stopped !"); - if (m_impl->loop) - { - m_impl->stream->Seek(0); - for (unsigned int i = 0; i < NAZARA_AUDIO_STREAMEDBUFFERCOUNT; ++i) - { - FillBuffer(buffers[i]); - alSourceQueueBuffers(m_source, 1, &buffers[i]); - } - - alSourcePlay(m_source); - } - else - m_impl->playing = false; - + m_impl->streaming = false; break; } ALint processedCount = 0; alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processedCount); - if (processedCount > 0) - NazaraWarning(NzString::Number(processedCount)); - ALuint buffer; while (processedCount--) { alSourceUnqueueBuffers(m_source, 1, &buffer); - FillBuffer(buffer); - alSourceQueueBuffers(m_source, 1, &buffer); + if (!FillBuffer(buffer)) // Fin du fichier ? + alSourceQueueBuffers(m_source, 1, &buffer); } - NzThread::Sleep(NAZARA_AUDIO_STREAMEDBUFFERCOUNT*500); + NzThread::Sleep(50); } + alSourceStop(m_source); + ALint queuedBufferCount; alGetSourcei(m_source, AL_BUFFERS_QUEUED, &queuedBufferCount); diff --git a/src/Nazara/Audio/Sound.cpp b/src/Nazara/Audio/Sound.cpp index 9f21e3b57..009957a40 100644 --- a/src/Nazara/Audio/Sound.cpp +++ b/src/Nazara/Audio/Sound.cpp @@ -133,19 +133,17 @@ void NzSound::Pause() alSourcePause(m_source); } -bool NzSound::Play() +void NzSound::Play() { #if NAZARA_AUDIO_SAFE if (!m_buffer) { NazaraError("No sound buffer to play"); - return false; + return; } #endif alSourcePlay(m_source); - - return true; } void NzSound::SetBuffer(const NzSoundBuffer* buffer)