Added support for FLAC audio files

This commit is contained in:
Laurent Gomila 2014-10-02 20:24:00 +02:00 committed by Mario Liebisch
parent 6096d22091
commit 5e0e645f46
22 changed files with 8065 additions and 7 deletions

View file

@ -39,15 +39,19 @@ set(CODECS_SRC
${INCROOT}/SoundFileFactory.hpp
${INCROOT}/SoundFileFactory.inl
${INCROOT}/SoundFileReader.hpp
${SRCROOT}/SoundFileReaderFlac.hpp
${SRCROOT}/SoundFileReaderFlac.cpp
${SRCROOT}/SoundFileReaderOgg.hpp
${SRCROOT}/SoundFileReaderOgg.cpp
${SRCROOT}/SoundFileReaderWav.hpp
${SRCROOT}/SoundFileReaderWav.cpp
${INCROOT}/SoundFileWriter.hpp
${SRCROOT}/SoundFileWriterWav.hpp
${SRCROOT}/SoundFileWriterWav.cpp
${SRCROOT}/SoundFileWriterFlac.hpp
${SRCROOT}/SoundFileWriterFlac.cpp
${SRCROOT}/SoundFileWriterOgg.hpp
${SRCROOT}/SoundFileWriterOgg.cpp
${SRCROOT}/SoundFileWriterWav.hpp
${SRCROOT}/SoundFileWriterWav.cpp
)
source_group("codecs" FILES ${CODECS_SRC})
@ -64,19 +68,23 @@ endif()
if(NOT SFML_OS_ANDROID)
find_package(OpenAL REQUIRED)
find_package(Vorbis REQUIRED)
find_package(FLAC REQUIRED)
else()
find_host_package(OpenAL REQUIRED)
find_host_package(Vorbis REQUIRED)
find_host_package(FLAC REQUIRED)
endif()
include_directories(${OPENAL_INCLUDE_DIR})
include_directories(${VORBIS_INCLUDE_DIRS})
include_directories(${FLAC_INCLUDE_DIR})
add_definitions(-DOV_EXCLUDE_STATIC_CALLBACKS) # avoids warnings in vorbisfile.h
add_definitions(-DFLAC__NO_DLL)
# build the list of external libraries to link
if(SFML_OS_ANDROID)
list(APPEND AUDIO_EXT_LIBS android OpenSLES)
endif()
list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${VORBIS_LIBRARIES})
list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${VORBIS_LIBRARIES} ${FLAC_LIBRARY})
# define the sfml-audio target
sfml_add_library(sfml-audio

View file

@ -26,6 +26,8 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/SoundFileFactory.hpp>
#include <SFML/Audio/SoundFileReaderFlac.hpp>
#include <SFML/Audio/SoundFileWriterFlac.hpp>
#include <SFML/Audio/SoundFileReaderOgg.hpp>
#include <SFML/Audio/SoundFileWriterOgg.hpp>
#include <SFML/Audio/SoundFileReaderWav.hpp>
@ -42,6 +44,8 @@ namespace
static bool registered = false;
if (!registered)
{
sf::SoundFileFactory::registerReader<sf::priv::SoundFileReaderFlac>();
sf::SoundFileFactory::registerWriter<sf::priv::SoundFileWriterFlac>();
sf::SoundFileFactory::registerReader<sf::priv::SoundFileReaderOgg>();
sf::SoundFileFactory::registerWriter<sf::priv::SoundFileWriterOgg>();
sf::SoundFileFactory::registerReader<sf::priv::SoundFileReaderWav>();

View file

@ -0,0 +1,322 @@
////////////////////////////////////////////////////////////
//
// 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/SoundFileReaderFlac.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
namespace
{
FLAC__StreamDecoderReadStatus read(const FLAC__StreamDecoder*, FLAC__byte buffer[], std::size_t* bytes, void* clientData)
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
sf::Int64 count = data->stream->read(buffer, *bytes);
if (count > 0)
{
*bytes = static_cast<std::size_t>(count);
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
else if (count == 0)
{
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
else
{
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
}
FLAC__StreamDecoderSeekStatus seek(const FLAC__StreamDecoder*, FLAC__uint64 absoluteByteOffset, void* clientData)
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
sf::Int64 position = data->stream->seek(absoluteByteOffset);
if (position >= 0)
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
else
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
}
FLAC__StreamDecoderTellStatus tell(const FLAC__StreamDecoder*, FLAC__uint64* absoluteByteOffset, void* clientData)
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
sf::Int64 position = data->stream->tell();
if (position >= 0)
{
*absoluteByteOffset = position;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
else
{
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
}
}
FLAC__StreamDecoderLengthStatus length(const FLAC__StreamDecoder*, FLAC__uint64* streamLength, void* clientData)
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
sf::Int64 count = data->stream->getSize();
if (count >= 0)
{
*streamLength = count;
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
else
{
return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
}
}
FLAC__bool eof(const FLAC__StreamDecoder*, void* clientData)
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
return data->stream->tell() == data->stream->getSize();
}
FLAC__StreamDecoderWriteStatus write(const FLAC__StreamDecoder*, const FLAC__Frame* frame, const FLAC__int32* const buffer[], void* clientData)
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
// If there's no output buffer, it means that we are seeking
if (!data->buffer)
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
// Reserve memory if we're going to use the leftovers buffer
unsigned int frameSamples = frame->header.blocksize * frame->header.channels;
if (data->remaining < frameSamples)
data->leftovers.reserve(static_cast<std::size_t>(frameSamples - data->remaining));
// Decode the samples
for (unsigned i = 0; i < frame->header.blocksize; ++i)
{
for (unsigned int j = 0; j < frame->header.channels; ++j)
{
// Decode the current sample
sf::Int16 sample = 0;
switch (frame->header.bits_per_sample)
{
case 8:
sample = buffer[j][i] << 8;
break;
case 16:
sample = buffer[j][i];
break;
case 24:
sample = buffer[j][i] >> 8;
break;
case 32:
sample = buffer[j][i] >> 16;
break;
default:
assert(false);
break;
}
if (data->remaining > 0)
{
// There's room in the output buffer, copy the sample there
*data->buffer++ = sample;
data->remaining--;
}
else
{
// We have decoded all the requested samples, put the sample in a temporary buffer until next call
data->leftovers.push_back(sample);
}
}
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
void metadata(const FLAC__StreamDecoder*, const FLAC__StreamMetadata* meta, void* clientData)
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
if (meta->type == FLAC__METADATA_TYPE_STREAMINFO)
{
data->info.sampleCount = meta->data.stream_info.total_samples * meta->data.stream_info.channels;
data->info.sampleRate = meta->data.stream_info.sample_rate;
data->info.channelCount = meta->data.stream_info.channels;
}
}
void error(const FLAC__StreamDecoder*, FLAC__StreamDecoderErrorStatus status, void* clientData)
{
sf::priv::SoundFileReaderFlac::ClientData* data = static_cast<sf::priv::SoundFileReaderFlac::ClientData*>(clientData);
data->error = true;
}
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
bool SoundFileReaderFlac::check(InputStream& stream)
{
// Create a decoder
FLAC__StreamDecoder* decoder = FLAC__stream_decoder_new();
if (!decoder)
return false;
// Initialize the decoder with our callbacks
ClientData data;
data.stream = &stream;
data.error = false;
FLAC__stream_decoder_init_stream(decoder, &::read, &::seek, &::tell, &::length, &::eof, &::write, NULL, &::error, &data);
// Read the header
bool valid = FLAC__stream_decoder_process_until_end_of_metadata(decoder) != 0;
// Destroy the decoder
FLAC__stream_decoder_finish(decoder);
FLAC__stream_decoder_delete(decoder);
return valid && !data.error;
}
////////////////////////////////////////////////////////////
SoundFileReaderFlac::SoundFileReaderFlac() :
m_decoder(NULL)
{
}
////////////////////////////////////////////////////////////
SoundFileReaderFlac::~SoundFileReaderFlac()
{
close();
}
////////////////////////////////////////////////////////////
bool SoundFileReaderFlac::open(InputStream& stream, Info& info)
{
// Create the decoder
m_decoder = FLAC__stream_decoder_new();
if (!m_decoder)
{
err() << "Failed to open FLAC file (failed to allocate the decoder)" << std::endl;
return false;
}
// Initialize the decoder with our callbacks
m_clientData.stream = &stream;
FLAC__stream_decoder_init_stream(m_decoder, &::read, &::seek, &::tell, &::length, &::eof, &::write, &::metadata, &::error, &m_clientData);
// Read the header
if (!FLAC__stream_decoder_process_until_end_of_metadata(m_decoder))
{
close();
err() << "Failed to open FLAC file (failed to read metadata)" << std::endl;
return false;
}
// Retrieve the sound properties
info = m_clientData.info; // was filled in the "metadata" callback
return true;
}
////////////////////////////////////////////////////////////
void SoundFileReaderFlac::seek(Uint64 sampleOffset)
{
assert(m_decoder);
// Reset the callback data (the "write" callback will be called)
m_clientData.buffer = NULL;
m_clientData.remaining = 0;
m_clientData.leftovers.clear();
FLAC__stream_decoder_seek_absolute(m_decoder, sampleOffset);
}
////////////////////////////////////////////////////////////
Uint64 SoundFileReaderFlac::read(Int16* samples, Uint64 maxCount)
{
assert(m_decoder);
// If there are leftovers from previous call, use it first
Uint64 left = m_clientData.leftovers.size();
if (left > 0)
{
if (left > maxCount)
{
// There are more leftovers than needed
std::copy(m_clientData.leftovers.begin(), m_clientData.leftovers.end(), samples);
std::vector<Int16> leftovers(m_clientData.leftovers.begin() + maxCount, m_clientData.leftovers.end());
m_clientData.leftovers.swap(leftovers);
return maxCount;
}
else
{
// We can use all the leftovers and decode new frames
std::copy(m_clientData.leftovers.begin(), m_clientData.leftovers.end(), samples);
}
}
// Reset the data that will be used in the callback
m_clientData.buffer = samples + left;
m_clientData.remaining = maxCount - left;
m_clientData.leftovers.clear();
// Decode frames one by one until we reach the requested sample count, the end of file or an error
while (m_clientData.remaining > 0)
{
// Everything happens in the "write" callback
if (!FLAC__stream_decoder_process_single(m_decoder))
break;
}
return maxCount - m_clientData.remaining;
}
////////////////////////////////////////////////////////////
void SoundFileReaderFlac::close()
{
if (m_decoder)
{
FLAC__stream_decoder_finish(m_decoder);
FLAC__stream_decoder_delete(m_decoder);
m_decoder = NULL;
}
}
} // namespace priv
} // namespace sf

View file

@ -0,0 +1,140 @@
////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SOUNDFILEREADERFLAC_HPP
#define SFML_SOUNDFILEREADERFLAC_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/SoundFileReader.hpp>
#include <flac/stream_decoder.h>
#include <string>
#include <vector>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Implementation of sound file reader that handles FLAC files
///
////////////////////////////////////////////////////////////
class SoundFileReaderFlac : public SoundFileReader
{
public:
////////////////////////////////////////////////////////////
/// \brief Check if this reader can handle a file given by an input stream
///
/// \param stream Source stream to check
///
/// \return True if the file is supported by this reader
///
////////////////////////////////////////////////////////////
static bool check(InputStream& stream);
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
SoundFileReaderFlac();
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
~SoundFileReaderFlac();
////////////////////////////////////////////////////////////
/// \brief Open a sound file for reading
///
/// \param stream Stream to open
/// \param info Structure to fill with the attributes of the loaded sound
///
////////////////////////////////////////////////////////////
virtual bool open(sf::InputStream& stream, Info& info);
////////////////////////////////////////////////////////////
/// \brief Change the current read position to the given sample offset
///
/// If the given offset exceeds to total number of samples,
/// this function must jump to the end of the file.
///
/// \param sampleOffset Index of the sample to jump to, relative to the beginning
///
////////////////////////////////////////////////////////////
virtual void seek(Uint64 sampleOffset);
////////////////////////////////////////////////////////////
/// \brief Read audio samples from the open file
///
/// \param samples Pointer to the sample array to fill
/// \param maxCount Maximum number of samples to read
///
/// \return Number of samples actually read (may be less than \a maxCount)
///
////////////////////////////////////////////////////////////
virtual Uint64 read(Int16* samples, Uint64 maxCount);
public:
////////////////////////////////////////////////////////////
/// \brief Hold the state that is passed to the decoder callbacks
///
////////////////////////////////////////////////////////////
struct ClientData
{
InputStream* stream;
SoundFileReader::Info info;
Int16* buffer;
Uint64 remaining;
std::vector<Int16> leftovers;
bool error;
};
private:
////////////////////////////////////////////////////////////
/// \brief Close the open FLAC file
///
////////////////////////////////////////////////////////////
void close();
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
FLAC__StreamDecoder* m_decoder; ///< FLAC decoder
ClientData m_clientData; ///< Structure passed to the decoder callbacks
};
} // namespace priv
} // namespace sf
#endif // SFML_SOUNDFILEREADERFLAC_HPP

View file

@ -37,7 +37,7 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Implementation of sound file reader that handles ogg/vorbis files
/// \brief Implementation of sound file reader that handles OGG/Vorbis files
///
////////////////////////////////////////////////////////////
class SoundFileReaderOgg : public SoundFileReader

View file

@ -0,0 +1,133 @@
////////////////////////////////////////////////////////////
//
// 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/SoundFileWriterFlac.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
#include <cctype>
#include <cassert>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
bool SoundFileWriterFlac::check(const std::string& filename)
{
std::string extension = filename.substr(filename.find_last_of(".") + 1);
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
return extension == "flac";
}
////////////////////////////////////////////////////////////
SoundFileWriterFlac::SoundFileWriterFlac() :
m_encoder (NULL),
m_channelCount(0),
m_samples32 ()
{
}
////////////////////////////////////////////////////////////
SoundFileWriterFlac::~SoundFileWriterFlac()
{
close();
}
////////////////////////////////////////////////////////////
bool SoundFileWriterFlac::open(const std::string& filename, unsigned int sampleRate, unsigned int channelCount)
{
// Create the encoder
m_encoder = FLAC__stream_encoder_new();
if (!m_encoder)
{
err() << "Failed to write flac file \"" << filename << "\" (failed to allocate encoder)" << std::endl;
return false;
}
// Setup the encoder
FLAC__stream_encoder_set_channels(m_encoder, channelCount);
FLAC__stream_encoder_set_bits_per_sample(m_encoder, 16);
FLAC__stream_encoder_set_sample_rate(m_encoder, sampleRate);
// Initialize the output stream
if (FLAC__stream_encoder_init_file(m_encoder, filename.c_str(), NULL, NULL) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
{
err() << "Failed to write flac file \"" << filename << "\" (failed to open the file)" << std::endl;
close();
return false;
}
// Store the channel count
m_channelCount = channelCount;
return true;
}
////////////////////////////////////////////////////////////
void SoundFileWriterFlac::write(const Int16* samples, Uint64 count)
{
while (count > 0)
{
// Make sure that we don't process too many samples at once
unsigned int frames = std::min(static_cast<unsigned int>(count / m_channelCount), 10000u);
// Convert the samples to 32-bits
m_samples32.assign(samples, samples + frames * m_channelCount);
// Write them to the FLAC stream
FLAC__stream_encoder_process_interleaved(m_encoder, &m_samples32[0], frames);
// Next chunk
count -= m_samples32.size();
samples += m_samples32.size();
}
}
////////////////////////////////////////////////////////////
void SoundFileWriterFlac::close()
{
if (m_encoder)
{
// Close the output stream
FLAC__stream_encoder_finish(m_encoder);
// Destroy the encoder
FLAC__stream_encoder_delete(m_encoder);
m_encoder = NULL;
}
}
} // namespace priv
} // namespace sf

View file

@ -0,0 +1,114 @@
////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////
#ifndef SFML_SOUNDFILEWRITERFLAC_HPP
#define SFML_SOUNDFILEWRITERFLAC_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/SoundFileWriter.hpp>
#include <flac/stream_encoder.h>
#include <vector>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Implementation of sound file writer that handles FLAC files
///
////////////////////////////////////////////////////////////
class SoundFileWriterFlac : public SoundFileWriter
{
public:
////////////////////////////////////////////////////////////
/// \brief Check if this writer can handle a file on disk
///
/// \param filename Path of the sound file to check
///
/// \return True if the file can be written by this writer
///
////////////////////////////////////////////////////////////
static bool check(const std::string& filename);
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
SoundFileWriterFlac();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SoundFileWriterFlac();
////////////////////////////////////////////////////////////
/// \brief Open a sound file for writing
///
/// \param filename Path of the file to open
/// \param sampleRate Sample rate of the sound
/// \param channelCount Number of channels of the sound
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
virtual bool open(const std::string& filename, unsigned int sampleRate, unsigned int channelCount);
////////////////////////////////////////////////////////////
/// \brief Write audio samples to the open file
///
/// \param samples Pointer to the sample array to write
/// \param count Number of samples to write
///
////////////////////////////////////////////////////////////
virtual void write(const Int16* samples, Uint64 count);
private:
////////////////////////////////////////////////////////////
/// \brief Close the file
///
////////////////////////////////////////////////////////////
void close();
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
FLAC__StreamEncoder* m_encoder; ///< FLAC stream encoder
unsigned int m_channelCount; ///< Number of channels
std::vector<Int32> m_samples32; ///< Conversion buffer
};
} // namespace priv
} // namespace sf
#endif // SFML_SOUNDFILEWRITERFLAC_HPP

View file

@ -38,7 +38,7 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Implementation of sound file writer that handles ogg files
/// \brief Implementation of sound file writer that handles OGG/Vorbis files
///
////////////////////////////////////////////////////////////
class SoundFileWriterOgg : public SoundFileWriter