summaryrefslogtreecommitdiff
path: root/src/SFML/Audio/SoundFile.cpp
diff options
context:
space:
mode:
authorJames Cowgill <james410@cowgill.org.uk>2014-12-09 20:21:40 +0000
committerJames Cowgill <james410@cowgill.org.uk>2014-12-09 20:21:40 +0000
commitfa21c65d0c764705cfc377bf0d0de08fac26874e (patch)
treedbc9e87bbd8684d15e79fc0c8b7a8985389c3b35 /src/SFML/Audio/SoundFile.cpp
parentdd835931261c340acd5f0409341d13fa2670423e (diff)
Imported Upstream version 2.2.0+dfsg
Diffstat (limited to 'src/SFML/Audio/SoundFile.cpp')
-rw-r--r--src/SFML/Audio/SoundFile.cpp876
1 files changed, 451 insertions, 425 deletions
diff --git a/src/SFML/Audio/SoundFile.cpp b/src/SFML/Audio/SoundFile.cpp
index 91db819..7ca5f82 100644
--- a/src/SFML/Audio/SoundFile.cpp
+++ b/src/SFML/Audio/SoundFile.cpp
@@ -1,425 +1,451 @@
-////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// This software is provided 'as-is', without any express or implied warranty.
-// In no event will the authors be held liable for any damages arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/Audio/SoundFile.hpp>
-#include <SFML/System/InputStream.hpp>
-#include <SFML/System/Err.hpp>
-#include <cstring>
-#include <cctype>
-
-
-namespace
-{
- // Convert a string to lower case
- std::string toLower(std::string str)
- {
- for (std::string::iterator i = str.begin(); i != str.end(); ++i)
- *i = static_cast<char>(std::tolower(*i));
- return str;
- }
-}
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-SoundFile::SoundFile() :
-m_file (NULL),
-m_sampleCount (0),
-m_channelCount(0),
-m_sampleRate (0)
-{
-
-}
-
-
-////////////////////////////////////////////////////////////
-SoundFile::~SoundFile()
-{
- if (m_file)
- sf_close(m_file);
-}
-
-
-////////////////////////////////////////////////////////////
-std::size_t SoundFile::getSampleCount() const
-{
- return m_sampleCount;
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundFile::getChannelCount() const
-{
- return m_channelCount;
-}
-
-
-////////////////////////////////////////////////////////////
-unsigned int SoundFile::getSampleRate() const
-{
- return m_sampleRate;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundFile::openRead(const std::string& filename)
-{
- // If the file is already opened, first close it
- if (m_file)
- sf_close(m_file);
-
- // Open the sound file
- SF_INFO fileInfo;
- fileInfo.format = 0;
- m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
- if (!m_file)
- {
- err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
- return false;
- }
-
- // Initialize the internal state from the loaded information
- initialize(fileInfo);
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
-{
- // If the file is already opened, first close it
- if (m_file)
- sf_close(m_file);
-
- // Prepare the memory I/O structure
- SF_VIRTUAL_IO io;
- io.get_filelen = &Memory::getLength;
- io.read = &Memory::read;
- io.seek = &Memory::seek;
- io.tell = &Memory::tell;
-
- // Initialize the memory data
- m_memory.begin = static_cast<const char*>(data);
- m_memory.current = m_memory.begin;
- m_memory.size = sizeInBytes;
-
- // Open the sound file
- SF_INFO fileInfo;
- fileInfo.format = 0;
- m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory);
- if (!m_file)
- {
- err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl;
- return false;
- }
-
- // Initialize the internal state from the loaded information
- initialize(fileInfo);
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundFile::openRead(InputStream& stream)
-{
- // If the file is already opened, first close it
- if (m_file)
- sf_close(m_file);
-
- // Prepare the memory I/O structure
- SF_VIRTUAL_IO io;
- io.get_filelen = &Stream::getLength;
- io.read = &Stream::read;
- io.seek = &Stream::seek;
- io.tell = &Stream::tell;
-
- // Initialize the stream data
- m_stream.source = &stream;
- m_stream.size = stream.getSize();
-
- // Make sure that the stream's reading position is at the beginning
- stream.seek(0);
-
- // Open the sound file
- SF_INFO fileInfo;
- fileInfo.format = 0;
- m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
- if (!m_file)
- {
- err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
- return false;
- }
-
- // Initialize the internal state from the loaded information
- initialize(fileInfo);
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate)
-{
- // If the file is already opened, first close it
- if (m_file)
- sf_close(m_file);
-
- // Find the right format according to the file extension
- int format = getFormatFromFilename(filename);
- if (format == -1)
- {
- // Error : unrecognized extension
- err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
- return false;
- }
-
- // Fill the sound infos with parameters
- SF_INFO fileInfos;
- fileInfos.channels = channelCount;
- fileInfos.samplerate = sampleRate;
- fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
-
- // Open the sound file for writing
- m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
- if (!m_file)
- {
- err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
- return false;
- }
-
- // Set the sound parameters
- m_channelCount = channelCount;
- m_sampleRate = sampleRate;
- m_sampleCount = 0;
-
- return true;
-}
-
-
-////////////////////////////////////////////////////////////
-std::size_t SoundFile::read(Int16* data, std::size_t sampleCount)
-{
- if (m_file && data && sampleCount)
- return static_cast<std::size_t>(sf_read_short(m_file, data, sampleCount));
- else
- return 0;
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundFile::write(const Int16* data, std::size_t sampleCount)
-{
- if (m_file && data && sampleCount)
- {
- // Write small chunks instead of everything at once,
- // to avoid a stack overflow in libsndfile (happens only with OGG format)
- while (sampleCount > 0)
- {
- std::size_t count = sampleCount > 10000 ? 10000 : sampleCount;
- sf_write_short(m_file, data, count);
- data += count;
- sampleCount -= count;
- }
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundFile::seek(Time timeOffset)
-{
- if (m_file)
- {
- sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset.asSeconds() * m_sampleRate);
- sf_seek(m_file, frameOffset, SEEK_SET);
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void SoundFile::initialize(SF_INFO fileInfo)
-{
- // Save the sound properties
- m_channelCount = fileInfo.channels;
- m_sampleRate = fileInfo.samplerate;
- m_sampleCount = static_cast<std::size_t>(fileInfo.frames) * fileInfo.channels;
-
- // Enable scaling for Vorbis files (float samples)
- // @todo enable when it's faster (it currently has to iterate over the *whole* music)
- //if (fileInfo.format & SF_FORMAT_VORBIS)
- // sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
-}
-
-
-////////////////////////////////////////////////////////////
-int SoundFile::getFormatFromFilename(const std::string& filename)
-{
- // Extract the extension
- std::string ext = "wav";
- std::string::size_type pos = filename.find_last_of(".");
- if (pos != std::string::npos)
- ext = filename.substr(pos + 1);
-
- // Match every supported extension with its format constant
- if (toLower(ext) == "wav" ) return SF_FORMAT_WAV;
- if (toLower(ext) == "aif" ) return SF_FORMAT_AIFF;
- if (toLower(ext) == "aiff" ) return SF_FORMAT_AIFF;
- if (toLower(ext) == "au" ) return SF_FORMAT_AU;
- if (toLower(ext) == "raw" ) return SF_FORMAT_RAW;
- if (toLower(ext) == "paf" ) return SF_FORMAT_PAF;
- if (toLower(ext) == "svx" ) return SF_FORMAT_SVX;
- if (toLower(ext) == "nist" ) return SF_FORMAT_NIST;
- if (toLower(ext) == "voc" ) return SF_FORMAT_VOC;
- if (toLower(ext) == "sf" ) return SF_FORMAT_IRCAM;
- if (toLower(ext) == "w64" ) return SF_FORMAT_W64;
- if (toLower(ext) == "mat4" ) return SF_FORMAT_MAT4;
- if (toLower(ext) == "mat5" ) return SF_FORMAT_MAT5;
- if (toLower(ext) == "pvf" ) return SF_FORMAT_PVF;
- if (toLower(ext) == "xi" ) return SF_FORMAT_XI;
- if (toLower(ext) == "htk" ) return SF_FORMAT_HTK;
- if (toLower(ext) == "sds" ) return SF_FORMAT_SDS;
- if (toLower(ext) == "avr" ) return SF_FORMAT_AVR;
- if (toLower(ext) == "sd2" ) return SF_FORMAT_SD2;
- if (toLower(ext) == "flac" ) return SF_FORMAT_FLAC;
- if (toLower(ext) == "caf" ) return SF_FORMAT_CAF;
- if (toLower(ext) == "wve" ) return SF_FORMAT_WVE;
- if (toLower(ext) == "ogg" ) return SF_FORMAT_OGG;
- if (toLower(ext) == "mpc2k") return SF_FORMAT_MPC2K;
- if (toLower(ext) == "rf64" ) return SF_FORMAT_RF64;
-
- return -1;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Memory::getLength(void* user)
-{
- Memory* memory = static_cast<Memory*>(user);
- return memory->size;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
-{
- Memory* memory = static_cast<Memory*>(user);
-
- sf_count_t position = tell(user);
- if (position + count >= memory->size)
- count = memory->size - position;
-
- std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
- memory->current += count;
- return count;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
-{
- Memory* memory = static_cast<Memory*>(user);
- sf_count_t position = 0;
- switch (whence)
- {
- case SEEK_SET : position = offset; break;
- case SEEK_CUR : position = memory->current - memory->begin + offset; break;
- case SEEK_END : position = memory->size - offset; break;
- default : position = 0; break;
- }
-
- if (position >= memory->size)
- position = memory->size - 1;
- else if (position < 0)
- position = 0;
-
- memory->current = memory->begin + position;
- return position;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Memory::tell(void* user)
-{
- Memory* memory = static_cast<Memory*>(user);
- return memory->current - memory->begin;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Stream::getLength(void* userData)
-{
- Stream* stream = static_cast<Stream*>(userData);
- return stream->size;
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
-{
- Stream* stream = static_cast<Stream*>(userData);
- Int64 position = stream->source->tell();
- if (position != -1)
- {
- if (count > stream->size - position)
- count = stream->size - position;
- return stream->source->read(reinterpret_cast<char*>(ptr), count);
- }
- else
- {
- return -1;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
-{
- Stream* stream = static_cast<Stream*>(userData);
- switch (whence)
- {
- case SEEK_SET : return stream->source->seek(offset);
- case SEEK_CUR : return stream->source->seek(stream->source->tell() + offset);
- case SEEK_END : return stream->source->seek(stream->size - offset);
- default : return stream->source->seek(0);
- }
-}
-
-
-////////////////////////////////////////////////////////////
-sf_count_t SoundFile::Stream::tell(void* userData)
-{
- Stream* stream = static_cast<Stream*>(userData);
- return stream->source->tell();
-}
-
-} // namespace priv
-
-} // namespace sf
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Audio/SoundFile.hpp>
+#ifdef SFML_SYSTEM_ANDROID
+ #include <SFML/System/Android/ResourceStream.hpp>
+#endif
+#include <SFML/System/InputStream.hpp>
+#include <SFML/System/Err.hpp>
+#include <cstring>
+#include <cctype>
+
+
+namespace
+{
+ // Convert a string to lower case
+ std::string toLower(std::string str)
+ {
+ for (std::string::iterator i = str.begin(); i != str.end(); ++i)
+ *i = static_cast<char>(std::tolower(*i));
+ return str;
+ }
+}
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+SoundFile::SoundFile() :
+m_file (NULL),
+m_sampleCount (0),
+m_channelCount(0),
+m_sampleRate (0)
+{
+ #ifdef SFML_SYSTEM_ANDROID
+
+ m_resourceStream = NULL;
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+SoundFile::~SoundFile()
+{
+ if (m_file)
+ sf_close(m_file);
+
+ #ifdef SFML_SYSTEM_ANDROID
+
+ if (m_resourceStream)
+ delete (priv::ResourceStream*)m_resourceStream;
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+std::size_t SoundFile::getSampleCount() const
+{
+ return m_sampleCount;
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundFile::getChannelCount() const
+{
+ return m_channelCount;
+}
+
+
+////////////////////////////////////////////////////////////
+unsigned int SoundFile::getSampleRate() const
+{
+ return m_sampleRate;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundFile::openRead(const std::string& filename)
+{
+ #ifndef SFML_SYSTEM_ANDROID
+
+ // If the file is already opened, first close it
+ if (m_file)
+ sf_close(m_file);
+
+ // Open the sound file
+ SF_INFO fileInfo;
+ fileInfo.format = 0;
+ m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
+ if (!m_file)
+ {
+ err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
+ return false;
+ }
+
+ // Initialize the internal state from the loaded information
+ initialize(fileInfo);
+
+ return true;
+
+ #else
+
+ if (m_resourceStream)
+ delete (priv::ResourceStream*)m_resourceStream;
+
+ m_resourceStream = new priv::ResourceStream(filename);
+ return openRead(*(priv::ResourceStream*)m_resourceStream);
+
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
+{
+ // If the file is already opened, first close it
+ if (m_file)
+ sf_close(m_file);
+
+ // Prepare the memory I/O structure
+ SF_VIRTUAL_IO io;
+ io.get_filelen = &Memory::getLength;
+ io.read = &Memory::read;
+ io.seek = &Memory::seek;
+ io.tell = &Memory::tell;
+
+ // Initialize the memory data
+ m_memory.begin = static_cast<const char*>(data);
+ m_memory.current = m_memory.begin;
+ m_memory.size = sizeInBytes;
+
+ // Open the sound file
+ SF_INFO fileInfo;
+ fileInfo.format = 0;
+ m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory);
+ if (!m_file)
+ {
+ err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl;
+ return false;
+ }
+
+ // Initialize the internal state from the loaded information
+ initialize(fileInfo);
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundFile::openRead(InputStream& stream)
+{
+ // If the file is already opened, first close it
+ if (m_file)
+ sf_close(m_file);
+
+ // Prepare the memory I/O structure
+ SF_VIRTUAL_IO io;
+ io.get_filelen = &Stream::getLength;
+ io.read = &Stream::read;
+ io.seek = &Stream::seek;
+ io.tell = &Stream::tell;
+
+ // Initialize the stream data
+ m_stream.source = &stream;
+ m_stream.size = stream.getSize();
+
+ // Make sure that the stream's reading position is at the beginning
+ stream.seek(0);
+
+ // Open the sound file
+ SF_INFO fileInfo;
+ fileInfo.format = 0;
+ m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
+ if (!m_file)
+ {
+ err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
+ return false;
+ }
+
+ // Initialize the internal state from the loaded information
+ initialize(fileInfo);
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate)
+{
+ // If the file is already opened, first close it
+ if (m_file)
+ sf_close(m_file);
+
+ // Find the right format according to the file extension
+ int format = getFormatFromFilename(filename);
+ if (format == -1)
+ {
+ // Error: unrecognized extension
+ err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
+ return false;
+ }
+
+ // Fill the sound infos with parameters
+ SF_INFO fileInfos;
+ fileInfos.channels = channelCount;
+ fileInfos.samplerate = sampleRate;
+ fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
+
+ // Open the sound file for writing
+ m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
+ if (!m_file)
+ {
+ err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
+ return false;
+ }
+
+ // Set the sound parameters
+ m_channelCount = channelCount;
+ m_sampleRate = sampleRate;
+ m_sampleCount = 0;
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+std::size_t SoundFile::read(Int16* data, std::size_t sampleCount)
+{
+ if (m_file && data && sampleCount)
+ return static_cast<std::size_t>(sf_read_short(m_file, data, sampleCount));
+ else
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundFile::write(const Int16* data, std::size_t sampleCount)
+{
+ if (m_file && data && sampleCount)
+ {
+ // Write small chunks instead of everything at once,
+ // to avoid a stack overflow in libsndfile (happens only with OGG format)
+ while (sampleCount > 0)
+ {
+ std::size_t count = sampleCount > 10000 ? 10000 : sampleCount;
+ sf_write_short(m_file, data, count);
+ data += count;
+ sampleCount -= count;
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundFile::seek(Time timeOffset)
+{
+ if (m_file)
+ {
+ sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset.asSeconds() * m_sampleRate);
+ sf_seek(m_file, frameOffset, SEEK_SET);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void SoundFile::initialize(SF_INFO fileInfo)
+{
+ // Save the sound properties
+ m_channelCount = fileInfo.channels;
+ m_sampleRate = fileInfo.samplerate;
+ m_sampleCount = static_cast<std::size_t>(fileInfo.frames) * fileInfo.channels;
+
+ // Enable scaling for Vorbis files (float samples)
+ // @todo enable when it's faster (it currently has to iterate over the *whole* music)
+ //if (fileInfo.format & SF_FORMAT_VORBIS)
+ // sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
+}
+
+
+////////////////////////////////////////////////////////////
+int SoundFile::getFormatFromFilename(const std::string& filename)
+{
+ // Extract the extension
+ std::string ext = "wav";
+ std::string::size_type pos = filename.find_last_of(".");
+ if (pos != std::string::npos)
+ ext = toLower(filename.substr(pos + 1));
+
+ // Match every supported extension with its format constant
+ if (ext == "wav" ) return SF_FORMAT_WAV;
+ if (ext == "aif" ) return SF_FORMAT_AIFF;
+ if (ext == "aiff" ) return SF_FORMAT_AIFF;
+ if (ext == "au" ) return SF_FORMAT_AU;
+ if (ext == "raw" ) return SF_FORMAT_RAW;
+ if (ext == "paf" ) return SF_FORMAT_PAF;
+ if (ext == "svx" ) return SF_FORMAT_SVX;
+ if (ext == "nist" ) return SF_FORMAT_NIST;
+ if (ext == "voc" ) return SF_FORMAT_VOC;
+ if (ext == "sf" ) return SF_FORMAT_IRCAM;
+ if (ext == "w64" ) return SF_FORMAT_W64;
+ if (ext == "mat4" ) return SF_FORMAT_MAT4;
+ if (ext == "mat5" ) return SF_FORMAT_MAT5;
+ if (ext == "pvf" ) return SF_FORMAT_PVF;
+ if (ext == "xi" ) return SF_FORMAT_XI;
+ if (ext == "htk" ) return SF_FORMAT_HTK;
+ if (ext == "sds" ) return SF_FORMAT_SDS;
+ if (ext == "avr" ) return SF_FORMAT_AVR;
+ if (ext == "sd2" ) return SF_FORMAT_SD2;
+ if (ext == "flac" ) return SF_FORMAT_FLAC;
+ if (ext == "caf" ) return SF_FORMAT_CAF;
+ if (ext == "wve" ) return SF_FORMAT_WVE;
+ if (ext == "ogg" ) return SF_FORMAT_OGG;
+ if (ext == "mpc2k") return SF_FORMAT_MPC2K;
+ if (ext == "rf64" ) return SF_FORMAT_RF64;
+
+ return -1;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Memory::getLength(void* user)
+{
+ Memory* memory = static_cast<Memory*>(user);
+ return memory->size;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
+{
+ Memory* memory = static_cast<Memory*>(user);
+
+ sf_count_t position = tell(user);
+ if (position + count >= memory->size)
+ count = memory->size - position;
+
+ std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
+ memory->current += count;
+ return count;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
+{
+ Memory* memory = static_cast<Memory*>(user);
+ sf_count_t position = 0;
+ switch (whence)
+ {
+ case SEEK_SET: position = offset; break;
+ case SEEK_CUR: position = memory->current - memory->begin + offset; break;
+ case SEEK_END: position = memory->size - offset; break;
+ default: position = 0; break;
+ }
+
+ if (position >= memory->size)
+ position = memory->size - 1;
+ else if (position < 0)
+ position = 0;
+
+ memory->current = memory->begin + position;
+ return position;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Memory::tell(void* user)
+{
+ Memory* memory = static_cast<Memory*>(user);
+ return memory->current - memory->begin;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Stream::getLength(void* userData)
+{
+ Stream* stream = static_cast<Stream*>(userData);
+ return stream->size;
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
+{
+ Stream* stream = static_cast<Stream*>(userData);
+ Int64 position = stream->source->tell();
+ if (position != -1)
+ {
+ if (count > stream->size - position)
+ count = stream->size - position;
+ return stream->source->read(reinterpret_cast<char*>(ptr), count);
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
+{
+ Stream* stream = static_cast<Stream*>(userData);
+ switch (whence)
+ {
+ case SEEK_SET: return stream->source->seek(offset);
+ case SEEK_CUR: return stream->source->seek(stream->source->tell() + offset);
+ case SEEK_END: return stream->source->seek(stream->size - offset);
+ default: return stream->source->seek(0);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+sf_count_t SoundFile::Stream::tell(void* userData)
+{
+ Stream* stream = static_cast<Stream*>(userData);
+ return stream->source->tell();
+}
+
+} // namespace priv
+
+} // namespace sf