mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-23 09:23:50 +00:00
Added support for libsndfile (sound input)
This commit is contained in:
parent
a69938364f
commit
ddfbcecfcd
6 changed files with 168 additions and 1 deletions
24
sound/filters/openal_sndfile.hpp
Normal file
24
sound/filters/openal_sndfile.hpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef MANGLE_SNDFILE_OPENAL_H
|
||||||
|
#define MANGLE_SNDFILE_OPENAL_H
|
||||||
|
|
||||||
|
#include "input_filter.hpp"
|
||||||
|
#include "../sources/libsndfile.hpp"
|
||||||
|
#include "../outputs/openal_out.hpp"
|
||||||
|
|
||||||
|
namespace Mangle {
|
||||||
|
namespace Sound {
|
||||||
|
|
||||||
|
/// A InputFilter that adds libsnd decoding to OpenAL. libsndfile
|
||||||
|
/// supports most formats except MP3.
|
||||||
|
class OpenAL_SndFile_Factory : public InputFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenAL_SndFile_Factory()
|
||||||
|
{
|
||||||
|
set(SoundFactoryPtr(new OpenAL_Factory),
|
||||||
|
SampleSourceLoaderPtr(new SndFileLoader));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
#endif
|
50
sound/sources/libsndfile.cpp
Normal file
50
sound/sources/libsndfile.cpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#include "libsndfile.hpp"
|
||||||
|
|
||||||
|
#include "../../tools/str_exception.hpp"
|
||||||
|
#include <sndfile.h>
|
||||||
|
|
||||||
|
using namespace Mangle::Stream;
|
||||||
|
|
||||||
|
static void fail(const std::string &msg)
|
||||||
|
{ throw str_exception("Mangle::libsndfile: " + msg); }
|
||||||
|
|
||||||
|
using namespace Mangle::Sound;
|
||||||
|
|
||||||
|
void SndFileSource::getInfo(int32_t *_rate, int32_t *_channels, int32_t *_bits)
|
||||||
|
{
|
||||||
|
*_rate = rate;
|
||||||
|
*_channels = channels;
|
||||||
|
*_bits = bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SndFileSource::readSamples(void *data, size_t length)
|
||||||
|
{
|
||||||
|
// Read frames. We count channels as part of the frame. Even though
|
||||||
|
// libsndfile does not, since it still requires the number of frames
|
||||||
|
// read to be a multiple of channels.
|
||||||
|
return channels*sf_read_short((SNDFILE*)handle, (short*)data, length*channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
SndFileSource::SndFileSource(const std::string &file)
|
||||||
|
{
|
||||||
|
SF_INFO info;
|
||||||
|
info.format = 0;
|
||||||
|
handle = sf_open(file.c_str(), SFM_READ, &info);
|
||||||
|
if(handle == NULL)
|
||||||
|
fail("Failed to open " + file);
|
||||||
|
|
||||||
|
// I THINK that using sf_read_short forces the library to convert to
|
||||||
|
// 16 bits no matter what, but the libsndfile docs aren't exactly
|
||||||
|
// very clear on this point.
|
||||||
|
channels = info.channels;
|
||||||
|
rate = info.samplerate;
|
||||||
|
bits = 16;
|
||||||
|
|
||||||
|
// 16 bits per sample times number of channels
|
||||||
|
setup(2*channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
SndFileSource::~SndFileSource()
|
||||||
|
{
|
||||||
|
sf_close((SNDFILE*)handle);
|
||||||
|
}
|
36
sound/sources/libsndfile.hpp
Normal file
36
sound/sources/libsndfile.hpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef MANGLE_SOUND_SNDFILE_SOURCE_H
|
||||||
|
#define MANGLE_SOUND_SNDFILE_SOURCE_H
|
||||||
|
|
||||||
|
#include "sample_reader.hpp"
|
||||||
|
|
||||||
|
namespace Mangle {
|
||||||
|
namespace Sound {
|
||||||
|
|
||||||
|
/// A sample source that decodes files using libsndfile. Supports most
|
||||||
|
/// formats except mp3.
|
||||||
|
class SndFileSource : public SampleReader
|
||||||
|
{
|
||||||
|
void *handle;
|
||||||
|
int channels, rate, bits;
|
||||||
|
|
||||||
|
size_t readSamples(void *data, size_t length);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Decode the given sound file
|
||||||
|
SndFileSource(const std::string &file);
|
||||||
|
|
||||||
|
/// Decode the given sound stream (not supported)
|
||||||
|
SndFileSource(Mangle::Stream::StreamPtr src) { assert(0); }
|
||||||
|
|
||||||
|
~SndFileSource();
|
||||||
|
|
||||||
|
void getInfo(int32_t *rate, int32_t *channels, int32_t *bits);
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "loadertemplate.hpp"
|
||||||
|
|
||||||
|
/// A factory that loads SndFileSources from file and stream
|
||||||
|
typedef SSL_Template<SndFileSource,false,true> SndFileLoader;
|
||||||
|
|
||||||
|
}} // Namespace
|
||||||
|
#endif
|
|
@ -1,6 +1,6 @@
|
||||||
GCC=g++ -I../ -Wall
|
GCC=g++ -I../ -Wall
|
||||||
|
|
||||||
all: audiere_source_test ffmpeg_source_test openal_output_test openal_audiere_test openal_ffmpeg_test openal_mpg123_test
|
all: audiere_source_test ffmpeg_source_test openal_output_test openal_audiere_test openal_ffmpeg_test openal_mpg123_test openal_sndfile_test
|
||||||
|
|
||||||
L_FFMPEG=$(shell pkg-config --libs libavcodec libavformat)
|
L_FFMPEG=$(shell pkg-config --libs libavcodec libavformat)
|
||||||
I_FFMPEG=-I/usr/include/libavcodec -I/usr/include/libavformat
|
I_FFMPEG=-I/usr/include/libavcodec -I/usr/include/libavformat
|
||||||
|
@ -16,6 +16,9 @@ openal_ffmpeg_test: openal_ffmpeg_test.cpp ../sources/ffmpeg_source.cpp ../outpu
|
||||||
openal_mpg123_test: openal_mpg123_test.cpp ../sources/mpg123_source.cpp ../outputs/openal_out.cpp
|
openal_mpg123_test: openal_mpg123_test.cpp ../sources/mpg123_source.cpp ../outputs/openal_out.cpp
|
||||||
$(GCC) $^ -o $@ -lmpg123 ${L_OPENAL}
|
$(GCC) $^ -o $@ -lmpg123 ${L_OPENAL}
|
||||||
|
|
||||||
|
openal_sndfile_test: openal_sndfile_test.cpp ../sources/libsndfile.cpp ../sources/sample_reader.cpp ../outputs/openal_out.cpp
|
||||||
|
$(GCC) $^ -o $@ -lsndfile ${L_OPENAL}
|
||||||
|
|
||||||
openal_output_test: openal_output_test.cpp ../outputs/openal_out.cpp
|
openal_output_test: openal_output_test.cpp ../outputs/openal_out.cpp
|
||||||
$(GCC) $^ -o $@ $(L_OPENAL)
|
$(GCC) $^ -o $@ $(L_OPENAL)
|
||||||
|
|
||||||
|
|
52
sound/tests/openal_sndfile_test.cpp
Normal file
52
sound/tests/openal_sndfile_test.cpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#include "../../stream/servers/file_stream.hpp"
|
||||||
|
#include "../filters/openal_sndfile.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Mangle::Stream;
|
||||||
|
using namespace Mangle::Sound;
|
||||||
|
|
||||||
|
OpenAL_SndFile_Factory mg;
|
||||||
|
|
||||||
|
void play(const char* name, bool stream=false)
|
||||||
|
{
|
||||||
|
// Only load streams if the backend supports it
|
||||||
|
if(stream && !mg.canLoadStream)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cout << "Playing " << name;
|
||||||
|
if(stream) cout << " (from stream)";
|
||||||
|
cout << "\n";
|
||||||
|
|
||||||
|
SoundPtr snd;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(stream)
|
||||||
|
snd = mg.load(StreamPtr(new FileStream(name)));
|
||||||
|
else
|
||||||
|
snd = mg.load(name);
|
||||||
|
|
||||||
|
snd->play();
|
||||||
|
|
||||||
|
while(snd->isPlaying())
|
||||||
|
{
|
||||||
|
usleep(10000);
|
||||||
|
if(mg.needsUpdate) mg.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(exception &e)
|
||||||
|
{
|
||||||
|
cout << " ERROR: " << e.what() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
play("cow.wav");
|
||||||
|
play("owl.ogg");
|
||||||
|
play("cow.wav", true);
|
||||||
|
return 0;
|
||||||
|
}
|
2
sound/tests/output/openal_sndfile_test.out
Normal file
2
sound/tests/output/openal_sndfile_test.out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Playing cow.wav
|
||||||
|
Playing owl.ogg
|
Loading…
Reference in a new issue