diff options
-rw-r--r-- | CMake/macros.cmake | 6 | ||||
-rw-r--r-- | CMakeLists.txt | 22 | ||||
-rw-r--r-- | intern/audaspace/CMakeLists.txt | 8 | ||||
-rw-r--r-- | intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp | 49 | ||||
-rw-r--r-- | intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h | 9 | ||||
-rw-r--r-- | intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp | 9 | ||||
-rw-r--r-- | intern/audaspace/ffmpeg/AUD_FFMPEGReader.h | 10 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_C-API.cpp | 14 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_FileFactory.cpp | 95 | ||||
-rw-r--r-- | intern/audaspace/intern/AUD_FileFactory.h | 71 | ||||
-rw-r--r-- | intern/audaspace/sndfile/AUD_SndFileFactory.cpp | 67 | ||||
-rw-r--r-- | intern/audaspace/sndfile/AUD_SndFileFactory.h | 71 | ||||
-rw-r--r-- | intern/audaspace/sndfile/AUD_SndFileReader.cpp | 233 | ||||
-rw-r--r-- | intern/audaspace/sndfile/AUD_SndFileReader.h | 131 |
14 files changed, 735 insertions, 60 deletions
diff --git a/CMake/macros.cmake b/CMake/macros.cmake index 9ba33dfb158..6a337505c00 100644 --- a/CMake/macros.cmake +++ b/CMake/macros.cmake @@ -70,6 +70,9 @@ MACRO(SETUP_LIBDIRS) IF(WITH_JACK) LINK_DIRECTORIES(${JACK_LIBPATH}) ENDIF(WITH_JACK) + IF(WITH_SNDFILE) + LINK_DIRECTORIES(${SNDFILE_LIBPATH}) + ENDIF(WITH_SNDFILE) IF(WITH_FFTW3) LINK_DIRECTORIES(${FFTW3_LIBPATH}) ENDIF(WITH_FFTW3) @@ -118,6 +121,9 @@ MACRO(SETUP_LIBLINKS IF(WITH_JACK) TARGET_LINK_LIBRARIES(${target} ${JACK_LIB}) ENDIF(WITH_JACK) + IF(WITH_SNDFILE) + TARGET_LINK_LIBRARIES(${target} ${SNDFILE_LIB}) + ENDIF(WITH_SNDFILE) IF(WITH_SDL) TARGET_LINK_LIBRARIES(${target} ${SDL_LIBRARY}) ENDIF(WITH_SDL) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9db25115099..749284def28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OPTION(WITH_WEBPLUGIN "Enable Web Plugin (Unix only)" OFF) OPTION(WITH_FFTW3 "Enable FFTW3 support" OFF) OPTION(WITH_JACK "Enable Jack Support (http://www.jackaudio.org)" OFF) +OPTION(WITH_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" OFF) OPTION(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation" OFF) OPTION(WITH_INSTALL "Install accompanying scripts and language files needed to run blender" ON) @@ -109,6 +110,13 @@ IF(UNIX AND NOT APPLE) SET(JACK_LIBPATH ${JACK}/lib) ENDIF(WITH_JACK) + IF(WITH_SNDFILE) + SET(SNDFILE /usr) + SET(SNDFILE_INC ${SNDFILE}/include) + SET(SNDFILE_LIB sndfile) + SET(SNDFILE_LIBPATH ${SNDFILE}/lib) + ENDIF(WITH_SNDFILE) + FIND_LIBRARY(INTL_LIBRARY NAMES intl PATHS @@ -247,6 +255,13 @@ IF(WIN32) SET(JACK_LIBPATH ${JACK}/lib) ENDIF(WITH_JACK) + IF(WITH_SNDFILE) + SET(SNDFILE ${LIBDIR}/sndfile) + SET(SNDFILE_INC ${SNDFILE}/include) + SET(SNDFILE_LIB sndfile) + SET(SNDFILE_LIBPATH ${SNDFILE}/lib) + ENDIF(WITH_SNDFILE) + IF(CMAKE_CL_64) SET(PNG_LIBRARIES libpng) ELSE(CMAKE_CL_64) @@ -392,6 +407,13 @@ IF(APPLE) SET(JACK_LIBPATH ${JACK}/lib) ENDIF(WITH_JACK) + IF(WITH_SNDFILE) + SET(SNDFILE /usr) + SET(SNDFILE_INC ${SNDFILE}/include) + SET(SNDFILE_LIB sndfile) + SET(SNDFILE_LIBPATH ${SNDFILE}/lib) + ENDIF(WITH_SNDFILE) + SET(PYTHON_VERSION 3.1) IF(PYTHON_VERSION MATCHES 3.1) diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index 940a4b2bedc..1b48de3190b 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -53,6 +53,12 @@ IF(WITH_JACK) ADD_DEFINITIONS(-DWITH_JACK) ENDIF(WITH_JACK) -SET(SRC ${SRC} ${FFMPEGSRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC}) +IF(WITH_SNDFILE) + SET(INC ${INC} sndfile ${SNDFILE_INC}) + FILE(GLOB SNDFILESRC sndfile/*.cpp) + ADD_DEFINITIONS(-DWITH_SNDFILE) +ENDIF(WITH_SNDFILE) + +SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC}) BLENDERLIB(bf_audaspace "${SRC}" "${INC}") diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp index 5f9006b0ec0..f67c819ff10 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp @@ -25,31 +25,24 @@ #include "AUD_FFMPEGFactory.h" #include "AUD_FFMPEGReader.h" -#include "AUD_Space.h" - -extern "C" { -#include <libavformat/avformat.h> -} +#include "AUD_Buffer.h" AUD_FFMPEGFactory::AUD_FFMPEGFactory(const char* filename) { - if(filename != 0) + if(filename != NULL) { m_filename = new char[strlen(filename)+1]; AUD_NEW("string") strcpy(m_filename, filename); } else - m_filename = 0; - m_buffer = 0; - m_size = 0; + m_filename = NULL; } AUD_FFMPEGFactory::AUD_FFMPEGFactory(unsigned char* buffer, int size) { - m_filename = 0; - m_buffer = (unsigned char*)av_malloc(size); AUD_NEW("buffer") - m_size = size; - memcpy(m_buffer, buffer, size); + m_filename = NULL; + m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size)); + memcpy(m_buffer.get()->getBuffer(), buffer, size); } AUD_FFMPEGFactory::~AUD_FFMPEGFactory() @@ -58,31 +51,15 @@ AUD_FFMPEGFactory::~AUD_FFMPEGFactory() { delete[] m_filename; AUD_DELETE("string") } - if(m_buffer) - { - av_free(m_buffer); AUD_DELETE("buffer") - } } AUD_IReader* AUD_FFMPEGFactory::createReader() { - try - { - AUD_IReader* reader; - if(m_filename) - reader = new AUD_FFMPEGReader(m_filename); - else - reader = new AUD_FFMPEGReader(m_buffer, m_size); - AUD_NEW("reader") - return reader; - } - catch(AUD_Exception e) - { - // return 0 if ffmpeg cannot read the file - if(e.error == AUD_ERROR_FFMPEG) - return 0; - // but throw an exception if the file doesn't exist - else - throw; - } + AUD_IReader* reader; + if(m_filename) + reader = new AUD_FFMPEGReader(m_filename); + else + reader = new AUD_FFMPEGReader(m_buffer); + AUD_NEW("reader") + return reader; } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h index 0a9fcc22c8b..22560303a73 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h @@ -27,6 +27,8 @@ #define AUD_FFMPEGFACTORY #include "AUD_IFactory.h" +#include "AUD_Reference.h" +class AUD_Buffer; /** * This factory reads a sound file via ffmpeg. @@ -44,12 +46,7 @@ private: /** * The buffer to read from. */ - unsigned char* m_buffer; - - /** - * The size of the buffer. - */ - int m_size; + AUD_Reference<AUD_Buffer> m_buffer; public: /** diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index b79375c2dc5..de0e47300f8 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -158,21 +158,22 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename) AUD_NEW("buffer") } -AUD_FFMPEGReader::AUD_FFMPEGReader(unsigned char* buffer, int size) +AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) { m_position = 0; m_pkgbuf_left = 0; m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext)); AUD_NEW("byteiocontext") + m_membuffer = buffer; - if(init_put_byte(m_byteiocontext, buffer, size, 0, + if(init_put_byte(m_byteiocontext, buffer.get()->getBuffer(), buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0) AUD_THROW(AUD_ERROR_FILE); AVProbeData probe_data; probe_data.filename = ""; - probe_data.buf = buffer; - probe_data.buf_size = size; + probe_data.buf = buffer.get()->getBuffer(); + probe_data.buf_size = buffer.get()->getSize(); AVInputFormat* fmt = av_probe_input_format(&probe_data, 1); // open stream diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h index 645f5f356f0..6e303934f36 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h @@ -27,7 +27,9 @@ #define AUD_FFMPEGREADER #include "AUD_IReader.h" +#include "AUD_Reference.h" class AUD_Buffer; + struct AVCodecContext; extern "C" { #include <libavformat/avformat.h> @@ -90,6 +92,11 @@ private: int m_stream; /** + * The memory file to read from, only saved to keep the buffer alive. + */ + AUD_Reference<AUD_Buffer> m_membuffer; + + /** * Decodes a packet into the given buffer. * \param packet The AVPacket to decode. * \param buffer The target buffer. @@ -109,11 +116,10 @@ public: /** * Creates a new reader. * \param buffer The buffer to read from. - * \param size The size of the buffer. * \exception AUD_Exception Thrown if the buffer specified cannot be read * with ffmpeg. */ - AUD_FFMPEGReader(unsigned char* buffer, int size); + AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer); /** * Destroys the reader and closes the file. diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index d2c8e94c949..9481e2139e8 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -25,6 +25,7 @@ #include "AUD_NULLDevice.h" #include "AUD_I3DDevice.h" +#include "AUD_FileFactory.h" #include "AUD_StreamBufferFactory.h" #include "AUD_DelayFactory.h" #include "AUD_LimiterFactory.h" @@ -48,7 +49,6 @@ #endif #ifdef WITH_FFMPEG -#include "AUD_FFMPEGFactory.h" extern "C" { #include <libavformat/avformat.h> } @@ -187,21 +187,13 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) AUD_Sound* AUD_load(const char* filename) { assert(filename); -#ifdef WITH_FFMPEG - return new AUD_FFMPEGFactory(filename); -#else - return NULL; -#endif + return new AUD_FileFactory(filename); } AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size) { assert(buffer); -#ifdef WITH_FFMPEG - return new AUD_FFMPEGFactory(buffer, size); -#else - return NULL; -#endif + return new AUD_FileFactory(buffer, size); } AUD_Sound* AUD_bufferSound(AUD_Sound* sound) diff --git a/intern/audaspace/intern/AUD_FileFactory.cpp b/intern/audaspace/intern/AUD_FileFactory.cpp new file mode 100644 index 00000000000..a1f81f49061 --- /dev/null +++ b/intern/audaspace/intern/AUD_FileFactory.cpp @@ -0,0 +1,95 @@ +/* + * $Id: AUD_FFMPEGFactory.cpp 22328 2009-08-09 23:23:19Z gsrb3d $ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_FileFactory.h" +#include "AUD_Buffer.h" + +#include <cstring> + +#ifdef WITH_FFMPEG +#include "AUD_FFMPEGReader.h" +#endif +#ifdef WITH_SNDFILE +#include "AUD_SndFileReader.h" +#endif + +AUD_FileFactory::AUD_FileFactory(const char* filename) +{ + if(filename != NULL) + { + m_filename = new char[strlen(filename)+1]; AUD_NEW("string") + strcpy(m_filename, filename); + } + else + m_filename = NULL; +} + +AUD_FileFactory::AUD_FileFactory(unsigned char* buffer, int size) +{ + m_filename = NULL; + m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size)); + memcpy(m_buffer.get()->getBuffer(), buffer, size); +} + +AUD_FileFactory::~AUD_FileFactory() +{ + if(m_filename) + { + delete[] m_filename; AUD_DELETE("string") + } +} + +AUD_IReader* AUD_FileFactory::createReader() +{ + AUD_IReader* reader = 0; + +#ifdef WITH_SNDFILE + try + { + if(m_filename) + reader = new AUD_SndFileReader(m_filename); + else + reader = new AUD_SndFileReader(m_buffer); + AUD_NEW("reader") + return reader; + } + catch(AUD_Exception e) {} +#endif + +#ifdef WITH_FFMPEG + try + { + if(m_filename) + reader = new AUD_FFMPEGReader(m_filename); + else + reader = new AUD_FFMPEGReader(m_buffer); + AUD_NEW("reader") + return reader; + } + catch(AUD_Exception e) {} +#endif + + return reader; +} diff --git a/intern/audaspace/intern/AUD_FileFactory.h b/intern/audaspace/intern/AUD_FileFactory.h new file mode 100644 index 00000000000..8badb4429df --- /dev/null +++ b/intern/audaspace/intern/AUD_FileFactory.h @@ -0,0 +1,71 @@ +/* + * $Id: AUD_FFMPEGFactory.h 22328 2009-08-09 23:23:19Z gsrb3d $ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_FILEFACTORY +#define AUD_FILEFACTORY + +#include "AUD_IFactory.h" +#include "AUD_Reference.h" +class AUD_Buffer; + +/** + * This factory tries to read a sound file via all available file readers. + */ +class AUD_FileFactory : public AUD_IFactory +{ +private: + /** + * The filename of the sound source file. + */ + char* m_filename; + + /** + * The buffer to read from. + */ + AUD_Reference<AUD_Buffer> m_buffer; + +public: + /** + * Creates a new factory. + * \param filename The sound file path. + */ + AUD_FileFactory(const char* filename); + + /** + * Creates a new factory. + * \param buffer The buffer to read from. + * \param size The size of the buffer. + */ + AUD_FileFactory(unsigned char* buffer, int size); + + /** + * Destroys the factory. + */ + ~AUD_FileFactory(); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_FILEFACTORY diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp new file mode 100644 index 00000000000..d3c5ea8a273 --- /dev/null +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp @@ -0,0 +1,67 @@ +/* + * $Id: AUD_FFMPEGFactory.cpp 22328 2009-08-09 23:23:19Z gsrb3d $ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_SndFileFactory.h" +#include "AUD_SndFileReader.h" +#include "AUD_Buffer.h" + +#include <cstring> + +AUD_SndFileFactory::AUD_SndFileFactory(const char* filename) +{ + if(filename != NULL) + { + m_filename = new char[strlen(filename)+1]; AUD_NEW("string") + strcpy(m_filename, filename); + } + else + m_filename = NULL; +} + +AUD_SndFileFactory::AUD_SndFileFactory(unsigned char* buffer, int size) +{ + m_filename = NULL; + m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size)); + memcpy(m_buffer.get()->getBuffer(), buffer, size); +} + +AUD_SndFileFactory::~AUD_SndFileFactory() +{ + if(m_filename) + { + delete[] m_filename; AUD_DELETE("string") + } +} + +AUD_IReader* AUD_SndFileFactory::createReader() +{ + AUD_IReader* reader; + if(m_filename) + reader = new AUD_SndFileReader(m_filename); + else + reader = new AUD_SndFileReader(m_buffer); + AUD_NEW("reader") + return reader; +} diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.h b/intern/audaspace/sndfile/AUD_SndFileFactory.h new file mode 100644 index 00000000000..6e265a63abe --- /dev/null +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.h @@ -0,0 +1,71 @@ +/* + * $Id: AUD_FFMPEGFactory.h 22328 2009-08-09 23:23:19Z gsrb3d $ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_SNDFILEFACTORY +#define AUD_SNDFILEFACTORY + +#include "AUD_IFactory.h" +#include "AUD_Reference.h" +class AUD_Buffer; + +/** + * This factory reads a sound file via libsndfile. + */ +class AUD_SndFileFactory : public AUD_IFactory +{ +private: + /** + * The filename of the sound source file. + */ + char* m_filename; + + /** + * The buffer to read from. + */ + AUD_Reference<AUD_Buffer> m_buffer; + +public: + /** + * Creates a new factory. + * \param filename The sound file path. + */ + AUD_SndFileFactory(const char* filename); + + /** + * Creates a new factory. + * \param buffer The buffer to read from. + * \param size The size of the buffer. + */ + AUD_SndFileFactory(unsigned char* buffer, int size); + + /** + * Destroys the factory. + */ + ~AUD_SndFileFactory(); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_SNDFILEFACTORY diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.cpp b/intern/audaspace/sndfile/AUD_SndFileReader.cpp new file mode 100644 index 00000000000..8daef573d37 --- /dev/null +++ b/intern/audaspace/sndfile/AUD_SndFileReader.cpp @@ -0,0 +1,233 @@ +/* + * $Id: AUD_FFMPEGReader.cpp 22328 2009-08-09 23:23:19Z gsrb3d $ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_SndFileReader.h" +#include "AUD_Buffer.h" + +#include <cstring> + +// This function transforms a SampleFormat to our own sample format +static inline AUD_SampleFormat SNDFILE_TO_AUD(int fmt) +{ + switch(fmt & SF_FORMAT_SUBMASK) + { + // only read s16, s32 and double as they are + case SF_FORMAT_PCM_16: + return AUD_FORMAT_S16; + case SF_FORMAT_PCM_32: + return AUD_FORMAT_S32; + case SF_FORMAT_DOUBLE: + return AUD_FORMAT_FLOAT64; + // read all other formats as floats + default: + return AUD_FORMAT_FLOAT32; + } +} + +sf_count_t AUD_SndFileReader::vio_get_filelen(void *user_data) +{ + AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; + return reader->m_membuffer.get()->getSize(); +} + +sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, void *user_data) +{ + AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; + + switch(whence) + { + case SEEK_SET: + reader->m_memoffset = offset; + break; + case SEEK_CUR: + reader->m_memoffset = reader->m_memoffset + offset; + break; + case SEEK_END: + reader->m_memoffset = reader->m_membuffer.get()->getSize() + offset; + break; + } + + return reader->m_memoffset; +} + +sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count, void *user_data) +{ + AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; + + if(reader->m_memoffset + count > reader->m_membuffer.get()->getSize()) + count = reader->m_membuffer.get()->getSize() - reader->m_memoffset; + + memcpy(ptr, reader->m_membuffer.get()->getBuffer() + reader->m_memoffset, count); + reader->m_memoffset += count; + + return count; +} + +sf_count_t AUD_SndFileReader::vio_tell(void *user_data) +{ + AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; + + return reader->m_memoffset; +} + +AUD_SndFileReader::AUD_SndFileReader(const char* filename) +{ + SF_INFO sfinfo; + + sfinfo.format = 0; + m_sndfile = sf_open(filename, SFM_READ, &sfinfo); + + if(!m_sndfile) + AUD_THROW(AUD_ERROR_FILE); + + m_specs.channels = (AUD_Channels) sfinfo.channels; + m_specs.format = SNDFILE_TO_AUD(sfinfo.format); + m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; + m_length = sfinfo.frames; + m_seekable = sfinfo.seekable; + m_position = 0; + + switch(m_specs.format) + { + case AUD_FORMAT_S16: + m_read = (sf_read_f) sf_readf_short; + break; + case AUD_FORMAT_S32: + m_read = (sf_read_f) sf_readf_int; + break; + case AUD_FORMAT_FLOAT64: + m_read = (sf_read_f) sf_readf_double; + break; + default: + m_read = (sf_read_f) sf_readf_float; + } + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") +} + +AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer) +{ + m_membuffer = buffer; + m_memoffset = 0; + + m_vio.get_filelen = vio_get_filelen; + m_vio.read = vio_read; + m_vio.seek = vio_seek; + m_vio.tell = vio_tell; + m_vio.write = NULL; + + SF_INFO sfinfo; + + sfinfo.format = 0; + m_sndfile = sf_open_virtual(&m_vio, SFM_READ, &sfinfo, this); + + if(!m_sndfile) + AUD_THROW(AUD_ERROR_FILE); + + m_specs.channels = (AUD_Channels) sfinfo.channels; + m_specs.format = SNDFILE_TO_AUD(sfinfo.format); + m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; + m_length = sfinfo.frames; + m_seekable = sfinfo.seekable; + m_position = 0; + + switch(m_specs.format) + { + case AUD_FORMAT_S16: + m_read = (sf_read_f) sf_readf_short; + break; + case AUD_FORMAT_S32: + m_read = (sf_read_f) sf_readf_int; + break; + case AUD_FORMAT_FLOAT64: + m_read = (sf_read_f) sf_readf_double; + break; + default: + m_read = (sf_read_f) sf_readf_float; + } + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") +} + +AUD_SndFileReader::~AUD_SndFileReader() +{ + sf_close(m_sndfile); + + delete m_buffer; AUD_DELETE("buffer") +} + +bool AUD_SndFileReader::isSeekable() +{ + return m_seekable; +} + +void AUD_SndFileReader::seek(int position) +{ + if(m_seekable) + { + position = sf_seek(m_sndfile, position, SEEK_SET); + m_position = position; + } +} + +int AUD_SndFileReader::getLength() +{ + return m_length; +} + +int AUD_SndFileReader::getPosition() +{ + return m_position; +} + +AUD_Specs AUD_SndFileReader::getSpecs() +{ + return m_specs; +} + +AUD_ReaderType AUD_SndFileReader::getType() +{ + return AUD_TYPE_STREAM; +} + +bool AUD_SndFileReader::notify(AUD_Message &message) +{ + return false; +} + +void AUD_SndFileReader::read(int & length, sample_t* & buffer) +{ + int sample_size = AUD_SAMPLE_SIZE(m_specs); + + // resize output buffer if necessary + if(m_buffer->getSize() < length*sample_size) + m_buffer->resize(length*sample_size); + + buffer = m_buffer->getBuffer(); + + length = m_read(m_sndfile, buffer, length); + + m_position += length; +} diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.h b/intern/audaspace/sndfile/AUD_SndFileReader.h new file mode 100644 index 00000000000..f55c36b47e8 --- /dev/null +++ b/intern/audaspace/sndfile/AUD_SndFileReader.h @@ -0,0 +1,131 @@ +/* + * $Id: AUD_FFMPEGReader.h 22328 2009-08-09 23:23:19Z gsrb3d $ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_SNDFILEREADER +#define AUD_SNDFILEREADER + +#include "AUD_IReader.h" +#include "AUD_Reference.h" +class AUD_Buffer; + +#include <sndfile.h> + +typedef sf_count_t (*sf_read_f)(SNDFILE *sndfile, void *ptr, sf_count_t frames); + +/** + * This class reads a sound file via libsndfile. + */ +class AUD_SndFileReader : public AUD_IReader +{ +private: + /** + * The current position in samples. + */ + int m_position; + + /** + * The sample count in the file. + */ + int m_length; + + /** + * Whether the file is seekable. + */ + bool m_seekable; + + /** + * The specification of the audio data. + */ + AUD_Specs m_specs; + + /** + * The playback buffer. + */ + AUD_Buffer* m_buffer; + + /** + * The sndfile. + */ + SNDFILE* m_sndfile; + + /** + * The reading function. + */ + sf_read_f m_read; + + /** + * The virtual IO structure for memory file reading. + */ + SF_VIRTUAL_IO m_vio; + + /** + * The pointer to the memory file. + */ + AUD_Reference<AUD_Buffer> m_membuffer; + + /** + * The current reading pointer of the memory file. + */ + int m_memoffset; + + // Functions for libsndfile virtual IO functionality + static sf_count_t vio_get_filelen(void *user_data); + static sf_count_t vio_seek(sf_count_t offset, int whence, void *user_data); + static sf_count_t vio_read(void *ptr, sf_count_t count, void *user_data); + static sf_count_t vio_tell(void *user_data); + +public: + /** + * Creates a new reader. + * \param filename The path to the file to be read. + * \exception AUD_Exception Thrown if the file specified does not exist or + * cannot be read with libsndfile. + */ + AUD_SndFileReader(const char* filename); + + /** + * Creates a new reader. + * \param buffer The buffer to read from. + * \exception AUD_Exception Thrown if the buffer specified cannot be read + * with libsndfile. + */ + AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer); + + /** + * Destroys the reader and closes the file. + */ + virtual ~AUD_SndFileReader(); + + virtual bool isSeekable(); + virtual void seek(int position); + virtual int getLength(); + virtual int getPosition(); + virtual AUD_Specs getSpecs(); + virtual AUD_ReaderType getType(); + virtual bool notify(AUD_Message &message); + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_SNDFILEREADER |