Implemented libsndfile loader in PhysFS
parent
2260f6bf4f
commit
1630cf0ed2
|
@ -77,6 +77,7 @@ common/stringutils.cpp
|
|||
common/resources/resourcemanager.cpp
|
||||
common/resources/resourcestreambuffer.cpp
|
||||
common/resources/inputstream.cpp
|
||||
common/resources/sndfile.cpp
|
||||
graphics/core/color.cpp
|
||||
graphics/engine/camera.cpp
|
||||
graphics/engine/cloud.cpp
|
||||
|
|
|
@ -124,7 +124,13 @@ SDL_RWops* CResourceManager::GetSDLFileHandler(const std::string &filename)
|
|||
}
|
||||
|
||||
|
||||
int CResourceManager::SDLClose(SDL_RWops* context)
|
||||
CSNDFile* CResourceManager::GetSNDFileHandler(const std::string &filename)
|
||||
{
|
||||
return new CSNDFile(filename);
|
||||
}
|
||||
|
||||
|
||||
int CResourceManager::SDLClose(SDL_RWops *context)
|
||||
{
|
||||
if (CheckSDLContext(context))
|
||||
{
|
||||
|
@ -138,7 +144,7 @@ int CResourceManager::SDLClose(SDL_RWops* context)
|
|||
}
|
||||
|
||||
|
||||
int CResourceManager::SDLRead(SDL_RWops* context, void* ptr, int size, int maxnum)
|
||||
int CResourceManager::SDLRead(SDL_RWops *context, void *ptr, int size, int maxnum)
|
||||
{
|
||||
if (CheckSDLContext(context))
|
||||
{
|
||||
|
@ -152,13 +158,13 @@ int CResourceManager::SDLRead(SDL_RWops* context, void* ptr, int size, int maxnu
|
|||
}
|
||||
|
||||
|
||||
int CResourceManager::SDLWrite(SDL_RWops* context, const void* ptr, int size, int num)
|
||||
int CResourceManager::SDLWrite(SDL_RWops *context, const void *ptr, int size, int num)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CResourceManager::SDLSeek(SDL_RWops* context, int offset, int whence)
|
||||
int CResourceManager::SDLSeek(SDL_RWops *context, int offset, int whence)
|
||||
{
|
||||
if (CheckSDLContext(context))
|
||||
{
|
||||
|
@ -188,7 +194,7 @@ int CResourceManager::SDLSeek(SDL_RWops* context, int offset, int whence)
|
|||
}
|
||||
|
||||
|
||||
bool CResourceManager::CheckSDLContext(SDL_RWops* context)
|
||||
bool CResourceManager::CheckSDLContext(SDL_RWops *context)
|
||||
{
|
||||
if (context->type != 0xc010b04f)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <string>
|
||||
#include <SDL.h>
|
||||
|
||||
#include "common/resources/sndfile.h"
|
||||
|
||||
class CResourceManager
|
||||
{
|
||||
public:
|
||||
|
@ -30,6 +32,7 @@ public:
|
|||
static bool SetSaveLocation(const std::string &location);
|
||||
static std::string GetLanguageLocation();
|
||||
static SDL_RWops* GetSDLFileHandler(const std::string &filename);
|
||||
static CSNDFile* GetSNDFileHandler(const std::string &filename);
|
||||
|
||||
private:
|
||||
static int SDLSeek(SDL_RWops *context, int offset, int whence);
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2014 Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
#include "common/resources/sndfile.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
CSNDFile::CSNDFile(const std::string& filename)
|
||||
{
|
||||
memset(&m_file_info, 0, sizeof(SF_INFO));
|
||||
|
||||
if (PHYSFS_isInit())
|
||||
{
|
||||
m_file = PHYSFS_openRead(filename.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_last_error = "Resource system not started!";
|
||||
}
|
||||
|
||||
if (m_file)
|
||||
{
|
||||
m_snd_file = sf_open_virtual(&snd_callbacks, SFM_READ, &m_file_info, m_file);
|
||||
if (!m_snd_file)
|
||||
{
|
||||
m_last_error = "Could not load file";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_last_error = std::string(PHYSFS_getLastError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSNDFile::~CSNDFile()
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
PHYSFS_close(m_file);
|
||||
}
|
||||
|
||||
if (m_snd_file)
|
||||
{
|
||||
sf_close(m_snd_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CSNDFile::IsOpen()
|
||||
{
|
||||
return m_snd_file;
|
||||
}
|
||||
|
||||
|
||||
SF_INFO &CSNDFile::GetFileInfo()
|
||||
{
|
||||
return m_file_info;
|
||||
}
|
||||
|
||||
|
||||
std::string& CSNDFile::GetLastError()
|
||||
{
|
||||
return m_last_error;
|
||||
}
|
||||
|
||||
|
||||
sf_count_t CSNDFile::Read(short int *ptr, sf_count_t items)
|
||||
{
|
||||
return sf_read_short(m_snd_file, ptr, items);
|
||||
}
|
||||
|
||||
|
||||
sf_count_t CSNDFile::SNDLength(void *data)
|
||||
{
|
||||
return PHYSFS_fileLength(static_cast<PHYSFS_File *>(data));
|
||||
}
|
||||
|
||||
|
||||
sf_count_t CSNDFile::SNDRead(void *ptr, sf_count_t count, void *data)
|
||||
{
|
||||
return PHYSFS_read(static_cast<PHYSFS_File *>(data), ptr, 1, count);
|
||||
}
|
||||
|
||||
|
||||
sf_count_t CSNDFile::SNDSeek(sf_count_t offset, int whence, void *data)
|
||||
{
|
||||
PHYSFS_File *file = static_cast<PHYSFS_File *>(data);
|
||||
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
PHYSFS_seek(file, PHYSFS_tell(file) + offset);
|
||||
break;
|
||||
case SEEK_SET:
|
||||
PHYSFS_seek(file, offset);
|
||||
break;
|
||||
case SEEK_END:
|
||||
PHYSFS_seek(file, PHYSFS_fileLength(file) + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
return PHYSFS_tell(file);
|
||||
}
|
||||
|
||||
|
||||
sf_count_t CSNDFile::SNDTell(void *data)
|
||||
{
|
||||
return PHYSFS_tell(static_cast<PHYSFS_File *>(data));
|
||||
}
|
||||
|
||||
|
||||
sf_count_t CSNDFile::SNDWrite(const void *ptr, sf_count_t count, void *data)
|
||||
{
|
||||
return PHYSFS_write(static_cast<PHYSFS_File *>(data), ptr, 1, count);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// * This file is part of the COLOBOT source code
|
||||
// * Copyright (C) 2014 Polish Portal of Colobot (PPC)
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <physfs.h>
|
||||
#include <sndfile.h>
|
||||
|
||||
|
||||
class CSNDFile
|
||||
{
|
||||
public:
|
||||
CSNDFile(const std::string &filename);
|
||||
virtual ~CSNDFile();
|
||||
|
||||
SF_INFO &GetFileInfo();
|
||||
bool IsOpen();
|
||||
std::string &GetLastError();
|
||||
sf_count_t Read(short int *ptr, sf_count_t items);
|
||||
|
||||
private:
|
||||
static sf_count_t SNDLength(void *data);
|
||||
static sf_count_t SNDSeek(sf_count_t offset, int whence, void *data);
|
||||
static sf_count_t SNDRead(void *ptr, sf_count_t count, void *data);
|
||||
static sf_count_t SNDWrite(const void *ptr, sf_count_t count, void *data);
|
||||
static sf_count_t SNDTell(void *data);
|
||||
|
||||
SF_INFO m_file_info;
|
||||
SNDFILE *m_snd_file;
|
||||
PHYSFS_File *m_file;
|
||||
std::string m_last_error;
|
||||
|
||||
SF_VIRTUAL_IO snd_callbacks = {
|
||||
SNDLength,
|
||||
SNDSeek,
|
||||
SNDRead,
|
||||
SNDWrite,
|
||||
SNDTell
|
||||
};
|
||||
};
|
|
@ -48,45 +48,44 @@ public:
|
|||
ALSound();
|
||||
~ALSound();
|
||||
|
||||
bool Create();
|
||||
bool Cache(Sound, const std::string &);
|
||||
bool CacheMusic(const std::string &);
|
||||
bool Create() override;
|
||||
bool Cache(Sound, const std::string &) override;
|
||||
bool CacheMusic(const std::string &) override;
|
||||
|
||||
bool GetEnable();
|
||||
bool GetEnable() override;
|
||||
|
||||
void SetAudioVolume(int volume);
|
||||
int GetAudioVolume();
|
||||
void SetMusicVolume(int volume);
|
||||
int GetMusicVolume();
|
||||
void SetAudioVolume(int volume) override;
|
||||
int GetAudioVolume() override;
|
||||
void SetMusicVolume(int volume) override;
|
||||
int GetMusicVolume() override;
|
||||
|
||||
void SetListener(const Math::Vector &eye, const Math::Vector &lookat);
|
||||
void FrameMove(float rTime);
|
||||
void SetListener(const Math::Vector &eye, const Math::Vector &lookat) override;
|
||||
void FrameMove(float rTime) override;
|
||||
|
||||
int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false);
|
||||
int Play(Sound sound, const Math::Vector &pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false);
|
||||
bool FlushEnvelope(int channel);
|
||||
bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
|
||||
bool Position(int channel, const Math::Vector &pos);
|
||||
bool Frequency(int channel, float frequency);
|
||||
bool Stop(int channel);
|
||||
bool StopAll();
|
||||
bool MuteAll(bool bMute);
|
||||
int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false) override;
|
||||
int Play(Sound sound, const Math::Vector &pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false) override;
|
||||
bool FlushEnvelope(int channel) override;
|
||||
bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper) override;
|
||||
bool Position(int channel, const Math::Vector &pos) override;
|
||||
bool Frequency(int channel, float frequency) override;
|
||||
bool Stop(int channel) override;
|
||||
bool StopAll() override;
|
||||
bool MuteAll(bool bMute) override;
|
||||
|
||||
bool PlayMusic(int rank, bool bRepeat, float fadeTime=2.0f);
|
||||
bool PlayMusic(const std::string &filename, bool bRepeat, float fadeTime=2.0f);
|
||||
bool RestartMusic();
|
||||
void SuspendMusic();
|
||||
void StopMusic(float fadeTime=2.0f);
|
||||
bool IsPlayingMusic();
|
||||
bool PlayPauseMusic(const std::string &filename, bool repeat);
|
||||
void StopPauseMusic();
|
||||
|
||||
bool CheckChannel(int &channel);
|
||||
bool PlayMusic(int rank, bool bRepeat, float fadeTime=2.0f) override;
|
||||
bool PlayMusic(const std::string &filename, bool bRepeat, float fadeTime=2.0f) override;
|
||||
bool RestartMusic() override;
|
||||
void SuspendMusic() override;
|
||||
void StopMusic(float fadeTime=2.0f) override;
|
||||
bool IsPlayingMusic() override;
|
||||
bool PlayPauseMusic(const std::string &filename, bool repeat) override;
|
||||
void StopPauseMusic() override;
|
||||
|
||||
private:
|
||||
void CleanUp();
|
||||
int GetPriority(Sound);
|
||||
bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
|
||||
bool CheckChannel(int &channel);
|
||||
|
||||
bool m_enabled;
|
||||
float m_audioVolume;
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
|
||||
#include "sound/oalsound/buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "common/resources/resourcemanager.h"
|
||||
|
||||
|
||||
Buffer::Buffer()
|
||||
{
|
||||
|
@ -42,19 +45,17 @@ bool Buffer::LoadFromFile(std::string filename, Sound sound)
|
|||
m_sound = sound;
|
||||
GetLogger()->Debug("Loading audio file: %s\n", filename.c_str());
|
||||
|
||||
SF_INFO fileInfo;
|
||||
memset(&fileInfo, 0, sizeof(SF_INFO));
|
||||
SNDFILE *file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
|
||||
std::unique_ptr<CSNDFile> file = std::unique_ptr<CSNDFile>(CResourceManager::GetSNDFileHandler(filename));
|
||||
|
||||
GetLogger()->Trace(" channels %d\n", fileInfo.channels);
|
||||
GetLogger()->Trace(" format %d\n", fileInfo.format);
|
||||
GetLogger()->Trace(" frames %d\n", fileInfo.frames);
|
||||
GetLogger()->Trace(" samplerate %d\n", fileInfo.samplerate);
|
||||
GetLogger()->Trace(" sections %d\n", fileInfo.sections);
|
||||
GetLogger()->Trace(" channels %d\n", file->GetFileInfo().channels);
|
||||
GetLogger()->Trace(" format %d\n", file->GetFileInfo().format);
|
||||
GetLogger()->Trace(" frames %d\n", file->GetFileInfo().frames);
|
||||
GetLogger()->Trace(" samplerate %d\n", file->GetFileInfo().samplerate);
|
||||
GetLogger()->Trace(" sections %d\n", file->GetFileInfo().sections);
|
||||
|
||||
if (!file)
|
||||
if (!file->IsOpen())
|
||||
{
|
||||
GetLogger()->Warn("Could not load file. Reason: %s\n", sf_strerror(file));
|
||||
GetLogger()->Warn("Could not load file. Reason: %s\n", file->GetLastError().c_str());
|
||||
m_loaded = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -64,23 +65,21 @@ bool Buffer::LoadFromFile(std::string filename, Sound sound)
|
|||
{
|
||||
GetLogger()->Warn("Could not create audio buffer\n");
|
||||
m_loaded = false;
|
||||
sf_close(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
// read chunks of 4096 samples
|
||||
std::vector<uint16_t> data;
|
||||
std::array<int16_t, 4096> buffer;
|
||||
data.reserve(fileInfo.frames);
|
||||
data.reserve(file->GetFileInfo().frames);
|
||||
size_t read = 0;
|
||||
while ((read = sf_read_short(file, buffer.data(), buffer.size())) != 0)
|
||||
while ((read = file->Read(buffer.data(), buffer.size())) != 0)
|
||||
{
|
||||
data.insert(data.end(), buffer.begin(), buffer.begin() + read);
|
||||
}
|
||||
sf_close(file);
|
||||
|
||||
alBufferData(m_buffer, fileInfo.channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, &data.front(), data.size() * sizeof(uint16_t), fileInfo.samplerate);
|
||||
m_duration = static_cast<float>(fileInfo.frames) / fileInfo.samplerate;
|
||||
alBufferData(m_buffer, file->GetFileInfo().channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, &data.front(), data.size() * sizeof(uint16_t), file->GetFileInfo().samplerate);
|
||||
m_duration = static_cast<float>(file->GetFileInfo().frames) / file->GetFileInfo().samplerate;
|
||||
m_loaded = true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ void CSoundInterface::CacheAll()
|
|||
for ( int i = 1; i < SOUND_MAX; i++ )
|
||||
{
|
||||
std::stringstream filename;
|
||||
filename << "sound" << std::setfill('0') << std::setw(3) << i << ".wav";
|
||||
filename << "sounds/sound" << std::setfill('0') << std::setw(3) << i << ".wav";
|
||||
if ( !Cache(static_cast<Sound>(i), filename.str()) )
|
||||
GetLogger()->Warn("Unable to load audio: %s\n", filename.str().c_str());
|
||||
}
|
||||
|
@ -54,10 +54,10 @@ void CSoundInterface::CacheAll()
|
|||
|
||||
void CSoundInterface::AddMusicFiles()
|
||||
{
|
||||
CacheMusic("Intro1.ogg");
|
||||
CacheMusic("Intro2.ogg");
|
||||
CacheMusic("music010.ogg");
|
||||
CacheMusic("music011.ogg");
|
||||
CacheMusic("music/Intro1.ogg");
|
||||
CacheMusic("music/Intro2.ogg");
|
||||
CacheMusic("music/music010.ogg");
|
||||
CacheMusic("music/music011.ogg");
|
||||
}
|
||||
|
||||
bool CSoundInterface::Cache(Sound bSound, const std::string &bFile)
|
||||
|
|
Loading…
Reference in New Issue