forked from teamnwah/openmw-tes3coop
Use Ogre's resource group manager to handle sound files
This commit is contained in:
parent
80dbf82a74
commit
0261aac518
5 changed files with 125 additions and 122 deletions
|
@ -12,12 +12,83 @@ static void fail(const std::string &msg)
|
|||
namespace MWSound
|
||||
{
|
||||
|
||||
//
|
||||
// libSndFile io callbacks
|
||||
//
|
||||
sf_count_t MpgSnd_Decoder::ogresf_get_filelen(void *user_data)
|
||||
{
|
||||
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||
return stream->size();
|
||||
}
|
||||
|
||||
sf_count_t MpgSnd_Decoder::ogresf_seek(sf_count_t offset, int whence, void *user_data)
|
||||
{
|
||||
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||
|
||||
if(whence == SEEK_CUR)
|
||||
stream->seek(stream->tell()+offset);
|
||||
else if(whence == SEEK_SET)
|
||||
stream->seek(offset);
|
||||
else if(whence == SEEK_END)
|
||||
stream->seek(stream->size()+offset);
|
||||
else
|
||||
return -1;
|
||||
|
||||
return stream->tell();
|
||||
}
|
||||
|
||||
sf_count_t MpgSnd_Decoder::ogresf_read(void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||
return stream->read(ptr, count);
|
||||
}
|
||||
|
||||
sf_count_t MpgSnd_Decoder::ogresf_write(const void*, sf_count_t, void*)
|
||||
{ return -1; }
|
||||
|
||||
sf_count_t MpgSnd_Decoder::ogresf_tell(void *user_data)
|
||||
{
|
||||
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||
return stream->tell();
|
||||
}
|
||||
|
||||
//
|
||||
// libmpg13 io callbacks
|
||||
//
|
||||
ssize_t MpgSnd_Decoder::ogrempg_read(void *user_data, void *ptr, size_t count)
|
||||
{
|
||||
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||
return stream->read(ptr, count);
|
||||
}
|
||||
|
||||
off_t MpgSnd_Decoder::ogrempg_lseek(void *user_data, off_t offset, int whence)
|
||||
{
|
||||
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
|
||||
|
||||
if(whence == SEEK_CUR)
|
||||
stream->seek(stream->tell()+offset);
|
||||
else if(whence == SEEK_SET)
|
||||
stream->seek(offset);
|
||||
else if(whence == SEEK_END)
|
||||
stream->seek(stream->size()+offset);
|
||||
else
|
||||
return -1;
|
||||
|
||||
return stream->tell();
|
||||
}
|
||||
|
||||
|
||||
void MpgSnd_Decoder::open(const std::string &fname)
|
||||
{
|
||||
close();
|
||||
mDataStream = mResourceMgr.openResource(fname);
|
||||
|
||||
SF_INFO info;
|
||||
mSndFile = sf_open(fname.c_str(), SFM_READ, &info);
|
||||
SF_VIRTUAL_IO streamIO = {
|
||||
ogresf_get_filelen, ogresf_seek,
|
||||
ogresf_read, ogresf_write, ogresf_tell
|
||||
};
|
||||
mSndFile = sf_open_virtual(&streamIO, SFM_READ, &info, this);
|
||||
if(mSndFile)
|
||||
{
|
||||
if(info.channels == 1)
|
||||
|
@ -33,9 +104,11 @@ void MpgSnd_Decoder::open(const std::string &fname)
|
|||
mSampleRate = info.samplerate;
|
||||
return;
|
||||
}
|
||||
mDataStream->seek(0);
|
||||
|
||||
mMpgFile = mpg123_new(NULL, NULL);
|
||||
if(mMpgFile && mpg123_open(mMpgFile, fname.c_str()) == MPG123_OK)
|
||||
if(mMpgFile && mpg123_replace_reader_handle(mMpgFile, ogrempg_read, ogrempg_lseek, NULL) == MPG123_OK &&
|
||||
mpg123_open_handle(mMpgFile, this) == MPG123_OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -79,6 +152,8 @@ void MpgSnd_Decoder::close()
|
|||
mpg123_delete(mMpgFile);
|
||||
mMpgFile = NULL;
|
||||
}
|
||||
|
||||
mDataStream.setNull();
|
||||
}
|
||||
|
||||
void MpgSnd_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <OgreDataStream.h>
|
||||
|
||||
#include "mpg123.h"
|
||||
#include "sndfile.h"
|
||||
|
||||
|
@ -16,6 +18,15 @@ namespace MWSound
|
|||
SNDFILE *mSndFile;
|
||||
mpg123_handle *mMpgFile;
|
||||
|
||||
Ogre::DataStreamPtr mDataStream;
|
||||
static sf_count_t ogresf_get_filelen(void *user_data);
|
||||
static sf_count_t ogresf_seek(sf_count_t offset, int whence, void *user_data);
|
||||
static sf_count_t ogresf_read(void *ptr, sf_count_t count, void *user_data);
|
||||
static sf_count_t ogresf_write(const void*, sf_count_t, void*);
|
||||
static sf_count_t ogresf_tell(void *user_data);
|
||||
static ssize_t ogrempg_read(void*, void*, size_t);
|
||||
static off_t ogrempg_lseek(void*, off_t, int);
|
||||
|
||||
ChannelConfig mChanConfig;
|
||||
int mSampleRate;
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <OgreResourceGroupManager.h>
|
||||
|
||||
namespace MWSound
|
||||
{
|
||||
enum SampleType {
|
||||
|
@ -20,9 +22,10 @@ namespace MWSound
|
|||
size_t framesToBytes(size_t frames, ChannelConfig config, SampleType type);
|
||||
size_t bytesToFrames(size_t bytes, ChannelConfig config, SampleType type);
|
||||
|
||||
class Sound_Decoder
|
||||
struct Sound_Decoder
|
||||
{
|
||||
public:
|
||||
Ogre::ResourceGroupManager &mResourceMgr;
|
||||
|
||||
virtual void open(const std::string &fname) = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
|
@ -31,10 +34,9 @@ namespace MWSound
|
|||
virtual size_t read(char *buffer, size_t bytes) = 0;
|
||||
virtual void rewind() = 0;
|
||||
|
||||
Sound_Decoder() : mResourceMgr(Ogre::ResourceGroupManager::getSingleton())
|
||||
{ }
|
||||
virtual ~Sound_Decoder() { }
|
||||
|
||||
friend class OpenAL_Output;
|
||||
friend class SoundManager;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ namespace MWSound
|
|||
bool useSound, bool fsstrict, MWWorld::Environment& environment)
|
||||
: mFSStrict(fsstrict)
|
||||
, mEnvironment(environment)
|
||||
, mCurrentPlaylist(NULL)
|
||||
{
|
||||
if(!useSound)
|
||||
return;
|
||||
|
@ -59,24 +58,7 @@ namespace MWSound
|
|||
return;
|
||||
}
|
||||
|
||||
// The music library will accept these filetypes
|
||||
// If none is given then it will accept all filetypes
|
||||
std::vector<std::string> acceptableExtensions;
|
||||
acceptableExtensions.push_back(".mp3");
|
||||
acceptableExtensions.push_back(".wav");
|
||||
acceptableExtensions.push_back(".ogg");
|
||||
acceptableExtensions.push_back(".flac");
|
||||
|
||||
// Makes a list of all sound files, searches in reverse for priority reasons
|
||||
for(Files::PathContainer::const_reverse_iterator it = dataDirs.rbegin(); it != dataDirs.rend(); ++it)
|
||||
Files::FileLister(*it / std::string("Sound"), mSoundFiles, true);
|
||||
|
||||
// Makes a FileLibrary of all music files, searches in reverse for priority reasons
|
||||
for(Files::PathContainer::const_reverse_iterator it = dataDirs.rbegin(); it != dataDirs.rend(); ++it)
|
||||
mMusicLibrary.add(*it / std::string("Music"), true, mFSStrict, acceptableExtensions);
|
||||
|
||||
std::string anything = "anything"; // anything is better that a segfault
|
||||
mCurrentPlaylist = mMusicLibrary.section(anything, mFSStrict); // now points to an empty path
|
||||
mResourceMgr = Ogre::ResourceGroupManager::getSingletonPtr();
|
||||
}
|
||||
|
||||
SoundManager::~SoundManager()
|
||||
|
@ -120,7 +102,14 @@ namespace MWSound
|
|||
max = std::max(min, max);
|
||||
}
|
||||
|
||||
return Files::FileListLocator(mSoundFiles, snd->sound, mFSStrict, false);
|
||||
std::string fname = std::string("Sound\\")+snd->sound;
|
||||
if(!mResourceMgr->resourceExistsInAnyGroup(fname))
|
||||
{
|
||||
std::string::size_type pos = fname.rfind('.');
|
||||
if(pos != std::string::npos)
|
||||
fname = fname.substr(0, pos)+".mp3";
|
||||
}
|
||||
return fname;
|
||||
}
|
||||
|
||||
// Add a sound to the list and play it
|
||||
|
@ -163,53 +152,25 @@ namespace MWSound
|
|||
{
|
||||
if(mMusic)
|
||||
mMusic->stop();
|
||||
setPlaylist();
|
||||
}
|
||||
|
||||
void SoundManager::streamMusicFull(const std::string& filename)
|
||||
{
|
||||
if(mMusic)
|
||||
mMusic->stop();
|
||||
mMusic.reset(mOutput->streamSound(filename, 0.4f, 1.0f));
|
||||
mMusic.reset();
|
||||
}
|
||||
|
||||
void SoundManager::streamMusic(const std::string& filename)
|
||||
{
|
||||
std::string filePath = mMusicLibrary.locate(filename, mFSStrict, true).string();
|
||||
if(!filePath.empty())
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
streamMusicFull(filePath);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
std::cout << "Music Error: " << e.what() << "\n";
|
||||
}
|
||||
if(mMusic)
|
||||
mMusic->stop();
|
||||
mMusic.reset(mOutput->streamSound(filename, 0.4f, 1.0f));
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
std::cout << "Music Error: " << e.what() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::startRandomTitle()
|
||||
{
|
||||
if(mCurrentPlaylist && !mCurrentPlaylist->empty())
|
||||
{
|
||||
Files::PathContainer::const_iterator fileIter = mCurrentPlaylist->begin();
|
||||
srand( time(NULL) );
|
||||
int r = rand() % mCurrentPlaylist->size() + 1; //old random code
|
||||
|
||||
std::advance(fileIter, r - 1);
|
||||
std::string music = fileIter->string();
|
||||
//std::cout << "Playing " << music << "\n";
|
||||
|
||||
try
|
||||
{
|
||||
streamMusicFull(music);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cout << "Music Error: " << e.what() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundManager::isMusicPlaying()
|
||||
|
@ -217,52 +178,21 @@ namespace MWSound
|
|||
return mMusic && mMusic->isPlaying();
|
||||
}
|
||||
|
||||
bool SoundManager::setPlaylist(std::string playlist)
|
||||
{
|
||||
const Files::PathContainer* previousPlaylist;
|
||||
previousPlaylist = mCurrentPlaylist;
|
||||
if (playlist == "")
|
||||
{
|
||||
mCurrentPlaylist = mMusicLibrary.section(playlist, mFSStrict);
|
||||
}
|
||||
else if(mMusicLibrary.containsSection(playlist, mFSStrict))
|
||||
{
|
||||
mCurrentPlaylist = mMusicLibrary.section(playlist, mFSStrict);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Warning: playlist named " << playlist << " does not exist.\n";
|
||||
}
|
||||
return previousPlaylist == mCurrentPlaylist;
|
||||
}
|
||||
|
||||
void SoundManager::playPlaylist(std::string playlist)
|
||||
{
|
||||
if (playlist == "")
|
||||
{
|
||||
if(!isMusicPlaying())
|
||||
{
|
||||
startRandomTitle();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!setPlaylist(playlist))
|
||||
{
|
||||
startRandomTitle();
|
||||
}
|
||||
else if (!isMusicPlaying())
|
||||
{
|
||||
startRandomTitle();
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::say(MWWorld::Ptr ptr, const std::string& filename)
|
||||
{
|
||||
// The range values are not tested
|
||||
std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict, true);
|
||||
if(!filePath.empty())
|
||||
play3d(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false);
|
||||
std::string filePath = std::string("Sound\\")+filename;
|
||||
if(!mResourceMgr->resourceExistsInAnyGroup(filePath))
|
||||
{
|
||||
std::string::size_type pos = filePath.rfind('.');
|
||||
if(pos != std::string::npos)
|
||||
filePath = filePath.substr(0, pos)+".mp3";
|
||||
}
|
||||
play3d(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false);
|
||||
}
|
||||
|
||||
bool SoundManager::sayDone(MWWorld::Ptr ptr) const
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <OgreResourceGroupManager.h>
|
||||
|
||||
#include <components/files/filelibrary.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
@ -29,6 +31,8 @@ namespace MWSound
|
|||
|
||||
class SoundManager
|
||||
{
|
||||
Ogre::ResourceGroupManager *mResourceMgr;
|
||||
|
||||
// This is used for case insensitive and slash-type agnostic file
|
||||
// finding. It takes DOS paths (any case, \\ slashes or / slashes)
|
||||
// relative to the sound dir, and translates them into full paths
|
||||
|
@ -41,19 +45,6 @@ namespace MWSound
|
|||
|
||||
boost::shared_ptr<Sound> mMusic;
|
||||
|
||||
void streamMusicFull(const std::string& filename);
|
||||
///< Play a soundifle
|
||||
/// \param absolute filename
|
||||
|
||||
// A list of all sound files used to lookup paths
|
||||
Files::PathContainer mSoundFiles;
|
||||
|
||||
// A library of all Music file paths stored by the folder they are contained in
|
||||
Files::FileLibrary mMusicLibrary;
|
||||
|
||||
// Points to the current playlist of music files stored in the music library
|
||||
const Files::PathContainer* mCurrentPlaylist;
|
||||
|
||||
typedef boost::shared_ptr<Sound> SoundPtr;
|
||||
typedef std::map<std::string,SoundPtr> IDMap;
|
||||
typedef std::map<MWWorld::Ptr,IDMap> SoundMap;
|
||||
|
@ -92,12 +83,6 @@ namespace MWSound
|
|||
bool isMusicPlaying();
|
||||
///< Returns true if music is playing
|
||||
|
||||
bool setPlaylist(std::string playlist="");
|
||||
///< Set the playlist to an existing folder
|
||||
/// \param name of the folder that contains the playlist
|
||||
/// if none is set then it is set to an empty playlist
|
||||
/// \return Return true if the previous playlist was the same
|
||||
|
||||
void playPlaylist(std::string playlist="");
|
||||
///< Start playing music from the selected folder
|
||||
/// \param name of the folder that contains the playlist
|
||||
|
|
Loading…
Reference in a new issue