mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 17:26:38 +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 | ||||
| 
 | ||||
| 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) | ||||
| 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 | ||||
| 	$(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 | ||||
| 	$(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