Redesigned the audio encoding/decoding classes to get rid of libsndfile
This commit is contained in:
parent
34692d5a39
commit
f0608eaed8
68 changed files with 4523 additions and 2241 deletions
|
@ -21,8 +21,10 @@ set(SRC
|
|||
${INCROOT}/SoundBuffer.hpp
|
||||
${SRCROOT}/SoundBufferRecorder.cpp
|
||||
${INCROOT}/SoundBufferRecorder.hpp
|
||||
${SRCROOT}/SoundFile.cpp
|
||||
${SRCROOT}/SoundFile.hpp
|
||||
${SRCROOT}/InputSoundFile.cpp
|
||||
${INCROOT}/InputSoundFile.hpp
|
||||
${SRCROOT}/OutputSoundFile.cpp
|
||||
${INCROOT}/OutputSoundFile.hpp
|
||||
${SRCROOT}/SoundRecorder.cpp
|
||||
${INCROOT}/SoundRecorder.hpp
|
||||
${SRCROOT}/SoundSource.cpp
|
||||
|
@ -32,36 +34,52 @@ set(SRC
|
|||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
set(CODECS_SRC
|
||||
${SRCROOT}/SoundFileFactory.cpp
|
||||
${INCROOT}/SoundFileFactory.hpp
|
||||
${INCROOT}/SoundFileFactory.inl
|
||||
${INCROOT}/SoundFileReader.hpp
|
||||
${SRCROOT}/SoundFileReaderOgg.hpp
|
||||
${SRCROOT}/SoundFileReaderOgg.cpp
|
||||
${SRCROOT}/SoundFileReaderWav.hpp
|
||||
${SRCROOT}/SoundFileReaderWav.cpp
|
||||
${INCROOT}/SoundFileWriter.hpp
|
||||
${SRCROOT}/SoundFileWriterWav.hpp
|
||||
${SRCROOT}/SoundFileWriterWav.cpp
|
||||
${SRCROOT}/SoundFileWriterOgg.hpp
|
||||
${SRCROOT}/SoundFileWriterOgg.cpp
|
||||
)
|
||||
source_group("codecs" FILES ${CODECS_SRC})
|
||||
|
||||
# let CMake know about our additional audio libraries paths (on Windows and OSX)
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows")
|
||||
elseif(SFML_OS_MACOSX)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/android")
|
||||
endif()
|
||||
|
||||
# find external libraries
|
||||
if(NOT SFML_OS_ANDROID)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(Sndfile REQUIRED)
|
||||
find_package(Vorbis REQUIRED)
|
||||
else()
|
||||
find_host_package(OpenAL REQUIRED)
|
||||
find_host_package(Sndfile REQUIRED)
|
||||
find_host_package(Vorbis REQUIRED)
|
||||
endif()
|
||||
include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
||||
include_directories(${OPENAL_INCLUDE_DIR})
|
||||
include_directories(${VORBIS_INCLUDE_DIRS})
|
||||
add_definitions(-DOV_EXCLUDE_STATIC_CALLBACKS) # avoids warnings in vorbisfile.h
|
||||
|
||||
# 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} ${SNDFILE_LIBRARY})
|
||||
list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${VORBIS_LIBRARIES})
|
||||
|
||||
# define the sfml-audio target
|
||||
sfml_add_library(sfml-audio
|
||||
SOURCES ${SRC}
|
||||
SOURCES ${SRC} ${CODECS_SRC}
|
||||
DEPENDS sfml-system
|
||||
EXTERNAL_LIBS ${AUDIO_EXT_LIBS})
|
||||
|
|
257
src/SFML/Audio/InputSoundFile.cpp
Normal file
257
src/SFML/Audio/InputSoundFile.cpp
Normal file
|
@ -0,0 +1,257 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/InputSoundFile.hpp>
|
||||
#include <SFML/Audio/SoundFileReader.hpp>
|
||||
#include <SFML/Audio/SoundFileFactory.hpp>
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/FileInputStream.hpp>
|
||||
#include <SFML/System/MemoryInputStream.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
InputSoundFile::InputSoundFile() :
|
||||
m_reader (NULL),
|
||||
m_stream (NULL),
|
||||
m_streamOwned (false),
|
||||
m_sampleCount (0),
|
||||
m_channelCount(0),
|
||||
m_sampleRate (0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
InputSoundFile::~InputSoundFile()
|
||||
{
|
||||
// Close the file in case it was open
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool InputSoundFile::openFromFile(const std::string& filename)
|
||||
{
|
||||
// If the file is already open, first close it
|
||||
close();
|
||||
|
||||
// Find a suitable reader for the file type
|
||||
m_reader = SoundFileFactory::createReaderFromFilename(filename);
|
||||
if (!m_reader)
|
||||
{
|
||||
err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wrap the file into a stream
|
||||
FileInputStream* file = new FileInputStream;
|
||||
m_stream = file;
|
||||
m_streamOwned = true;
|
||||
|
||||
// Open it
|
||||
if (!file->open(filename))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pass the stream to the reader
|
||||
SoundFileReader::Info info;
|
||||
if (!m_reader->open(*file, info))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the attributes of the open sound file
|
||||
m_sampleCount = info.sampleCount;
|
||||
m_channelCount = info.channelCount;
|
||||
m_sampleRate = info.sampleRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool InputSoundFile::openFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
// If the file is already open, first close it
|
||||
close();
|
||||
|
||||
// Find a suitable reader for the file type
|
||||
m_reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes);
|
||||
if (!m_reader)
|
||||
{
|
||||
err() << "Failed to open sound file from memory (format not supported)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wrap the memory file into a stream
|
||||
MemoryInputStream* memory = new MemoryInputStream;
|
||||
m_stream = memory;
|
||||
m_streamOwned = true;
|
||||
|
||||
// Open it
|
||||
memory->open(data, sizeInBytes);
|
||||
|
||||
// Pass the stream to the reader
|
||||
SoundFileReader::Info info;
|
||||
if (!m_reader->open(*memory, info))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the attributes of the open sound file
|
||||
m_sampleCount = info.sampleCount;
|
||||
m_channelCount = info.channelCount;
|
||||
m_sampleRate = info.sampleRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool InputSoundFile::openFromStream(InputStream& stream)
|
||||
{
|
||||
// If the file is already open, first close it
|
||||
close();
|
||||
|
||||
// Find a suitable reader for the file type
|
||||
m_reader = SoundFileFactory::createReaderFromStream(stream);
|
||||
if (!m_reader)
|
||||
{
|
||||
err() << "Failed to open sound file from stream (format not supported)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// store the stream
|
||||
m_stream = &stream;
|
||||
m_streamOwned = false;
|
||||
|
||||
// Don't forget to reset the stream to its beginning before re-opening it
|
||||
if (stream.seek(0) != 0)
|
||||
{
|
||||
err() << "Failed to open sound file from stream (cannot restart stream)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pass the stream to the reader
|
||||
SoundFileReader::Info info;
|
||||
if (!m_reader->open(stream, info))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the attributes of the open sound file
|
||||
m_sampleCount = info.sampleCount;
|
||||
m_channelCount = info.channelCount;
|
||||
m_sampleRate = info.sampleRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint64 InputSoundFile::getSampleCount() const
|
||||
{
|
||||
return m_sampleCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int InputSoundFile::getChannelCount() const
|
||||
{
|
||||
return m_channelCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int InputSoundFile::getSampleRate() const
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time InputSoundFile::getDuration() const
|
||||
{
|
||||
return seconds(static_cast<float>(m_sampleCount) / m_channelCount / m_sampleRate);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void InputSoundFile::seek(Uint64 sampleOffset)
|
||||
{
|
||||
if (m_reader)
|
||||
m_reader->seek(sampleOffset);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void InputSoundFile::seek(Time timeOffset)
|
||||
{
|
||||
seek(static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint64 InputSoundFile::read(Int16* samples, Uint64 maxCount)
|
||||
{
|
||||
if (m_reader && samples && maxCount)
|
||||
return m_reader->read(samples, maxCount);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void InputSoundFile::close()
|
||||
{
|
||||
// Destroy the reader
|
||||
delete m_reader;
|
||||
m_reader = NULL;
|
||||
|
||||
// Destroy the stream if we own it
|
||||
if (m_streamOwned)
|
||||
{
|
||||
delete m_stream;
|
||||
m_stream = NULL;
|
||||
m_streamOwned = false;
|
||||
}
|
||||
|
||||
// Reset the sound file attributes
|
||||
m_sampleCount = 0;
|
||||
m_channelCount = 0;
|
||||
m_sampleRate = 0;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -27,7 +27,6 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/Music.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/Audio/SoundFile.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <fstream>
|
||||
|
@ -37,7 +36,7 @@ namespace sf
|
|||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Music::Music() :
|
||||
m_file (new priv::SoundFile),
|
||||
m_file (),
|
||||
m_duration()
|
||||
{
|
||||
|
||||
|
@ -49,8 +48,6 @@ Music::~Music()
|
|||
{
|
||||
// We must stop before destroying the file
|
||||
stop();
|
||||
|
||||
delete m_file;
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,7 +58,7 @@ bool Music::openFromFile(const std::string& filename)
|
|||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(filename))
|
||||
if (!m_file.openFromFile(filename))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
|
@ -78,7 +75,7 @@ bool Music::openFromMemory(const void* data, std::size_t sizeInBytes)
|
|||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(data, sizeInBytes))
|
||||
if (!m_file.openFromMemory(data, sizeInBytes))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
|
@ -95,7 +92,7 @@ bool Music::openFromStream(InputStream& stream)
|
|||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(stream))
|
||||
if (!m_file.openFromStream(stream))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
|
@ -119,7 +116,7 @@ bool Music::onGetData(SoundStream::Chunk& data)
|
|||
|
||||
// Fill the chunk parameters
|
||||
data.samples = &m_samples[0];
|
||||
data.sampleCount = m_file->read(&m_samples[0], m_samples.size());
|
||||
data.sampleCount = static_cast<std::size_t>(m_file.read(&m_samples[0], m_samples.size()));
|
||||
|
||||
// Check if we have reached the end of the audio file
|
||||
return data.sampleCount == m_samples.size();
|
||||
|
@ -131,7 +128,7 @@ void Music::onSeek(Time timeOffset)
|
|||
{
|
||||
Lock lock(m_mutex);
|
||||
|
||||
m_file->seek(timeOffset);
|
||||
m_file.seek(timeOffset);
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,13 +136,13 @@ void Music::onSeek(Time timeOffset)
|
|||
void Music::initialize()
|
||||
{
|
||||
// Compute the music duration
|
||||
m_duration = seconds(static_cast<float>(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount());
|
||||
m_duration = m_file.getDuration();
|
||||
|
||||
// Resize the internal buffer so that it can contain 1 second of audio samples
|
||||
m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount());
|
||||
m_samples.resize(m_file.getSampleRate() * m_file.getChannelCount());
|
||||
|
||||
// Initialize the stream
|
||||
SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate());
|
||||
SoundStream::initialize(m_file.getChannelCount(), m_file.getSampleRate());
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
92
src/SFML/Audio/OutputSoundFile.cpp
Normal file
92
src/SFML/Audio/OutputSoundFile.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/OutputSoundFile.hpp>
|
||||
#include <SFML/Audio/SoundFileWriter.hpp>
|
||||
#include <SFML/Audio/SoundFileFactory.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
OutputSoundFile::OutputSoundFile() :
|
||||
m_writer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
OutputSoundFile::~OutputSoundFile()
|
||||
{
|
||||
// Close the file in case it was open
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool OutputSoundFile::openFromFile(const std::string& filename, unsigned int sampleRate, unsigned int channelCount)
|
||||
{
|
||||
// If the file is already open, first close it
|
||||
close();
|
||||
|
||||
// Find a suitable writer for the file type
|
||||
m_writer = SoundFileFactory::createWriterFromFilename(filename);
|
||||
if (!m_writer)
|
||||
{
|
||||
err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pass the stream to the reader
|
||||
if (!m_writer->open(filename, sampleRate, channelCount))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void OutputSoundFile::write(const Int16* samples, Uint64 count)
|
||||
{
|
||||
if (m_writer && samples && count)
|
||||
m_writer->write(samples, count);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void OutputSoundFile::close()
|
||||
{
|
||||
// Destroy the reader
|
||||
delete m_writer;
|
||||
m_writer = NULL;
|
||||
}
|
||||
|
||||
} // namespace sf
|
|
@ -26,7 +26,8 @@
|
|||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundBuffer.hpp>
|
||||
#include <SFML/Audio/SoundFile.hpp>
|
||||
#include <SFML/Audio/InputSoundFile.hpp>
|
||||
#include <SFML/Audio/OutputSoundFile.hpp>
|
||||
#include <SFML/Audio/Sound.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
|
@ -77,8 +78,8 @@ SoundBuffer::~SoundBuffer()
|
|||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromFile(const std::string& filename)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(filename))
|
||||
InputSoundFile file;
|
||||
if (file.openFromFile(filename))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
|
@ -88,8 +89,8 @@ bool SoundBuffer::loadFromFile(const std::string& filename)
|
|||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(data, sizeInBytes))
|
||||
InputSoundFile file;
|
||||
if (file.openFromMemory(data, sizeInBytes))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
|
@ -99,8 +100,8 @@ bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
|||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromStream(InputStream& stream)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(stream))
|
||||
InputSoundFile file;
|
||||
if (file.openFromStream(stream))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
|
@ -108,7 +109,7 @@ bool SoundBuffer::loadFromStream(InputStream& stream)
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate)
|
||||
bool SoundBuffer::loadFromSamples(const Int16* samples, Uint64 sampleCount, unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
if (samples && sampleCount && channelCount && sampleRate)
|
||||
{
|
||||
|
@ -137,8 +138,8 @@ bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount,
|
|||
bool SoundBuffer::saveToFile(const std::string& filename) const
|
||||
{
|
||||
// Create the sound file in write mode
|
||||
priv::SoundFile file;
|
||||
if (file.openWrite(filename, getChannelCount(), getSampleRate()))
|
||||
OutputSoundFile file;
|
||||
if (file.openFromFile(filename, getSampleRate(), getChannelCount()))
|
||||
{
|
||||
// Write the samples to the opened file
|
||||
file.write(&m_samples[0], m_samples.size());
|
||||
|
@ -160,7 +161,7 @@ const Int16* SoundBuffer::getSamples() const
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t SoundBuffer::getSampleCount() const
|
||||
Uint64 SoundBuffer::getSampleCount() const
|
||||
{
|
||||
return m_samples.size();
|
||||
}
|
||||
|
@ -208,15 +209,15 @@ SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::initialize(priv::SoundFile& file)
|
||||
bool SoundBuffer::initialize(InputSoundFile& file)
|
||||
{
|
||||
// Retrieve the sound parameters
|
||||
std::size_t sampleCount = file.getSampleCount();
|
||||
Uint64 sampleCount = file.getSampleCount();
|
||||
unsigned int channelCount = file.getChannelCount();
|
||||
unsigned int sampleRate = file.getSampleRate();
|
||||
|
||||
// Read the samples from the provided file
|
||||
m_samples.resize(sampleCount);
|
||||
m_samples.resize(static_cast<std::size_t>(sampleCount));
|
||||
if (file.read(&m_samples[0], sampleCount) == sampleCount)
|
||||
{
|
||||
// Update the internal buffer with the new samples
|
||||
|
|
|
@ -1,231 +0,0 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// 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_SOUNDFILE_HPP
|
||||
#define SFML_SOUNDFILE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <sndfile.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class InputStream;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Provide read and write access to sound files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SoundFile : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFile();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~SoundFile();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the total number of audio samples in the file
|
||||
///
|
||||
/// \return Number of samples
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t getSampleCount() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the number of channels used by the sound
|
||||
///
|
||||
/// \return Number of channels (1 = mono, 2 = stereo)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int getChannelCount() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the sample rate of the sound
|
||||
///
|
||||
/// \return Sample rate, in samples per second
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int getSampleRate() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file for reading
|
||||
///
|
||||
/// \param filename Path of the sound file to load
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file in memory for reading
|
||||
///
|
||||
/// \param data Pointer to the file data in memory
|
||||
/// \param sizeInBytes Size of the data to load, in bytes
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(const void* data, std::size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file from a custom stream for reading
|
||||
///
|
||||
/// \param stream Source stream to read from
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(InputStream& stream);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief a the sound file for writing
|
||||
///
|
||||
/// \param filename Path of the sound file to write
|
||||
/// \param channelCount Number of channels in the sound
|
||||
/// \param sampleRate Sample rate of the sound
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read audio samples from the loaded sound
|
||||
///
|
||||
/// \param data Pointer to the sample array to fill
|
||||
/// \param sampleCount Number of samples to read
|
||||
///
|
||||
/// \return Number of samples actually read (may be less than \a sampleCount)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t read(Int16* data, std::size_t sampleCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Write audio samples to the file
|
||||
///
|
||||
/// \param data Pointer to the sample array to write
|
||||
/// \param sampleCount Number of samples to write
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void write(const Int16* data, std::size_t sampleCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Change the current read position in the file
|
||||
///
|
||||
/// \param timeOffset New playing position, from the beginning of the file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void seek(Time timeOffset);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Initialize the internal state of the sound file
|
||||
///
|
||||
/// This function is called by all the openRead functions.
|
||||
///
|
||||
/// \param fileInfo Information about the loaded sound file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void initialize(SF_INFO fileInfo);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the internal format of an audio file according to
|
||||
/// its filename extension
|
||||
///
|
||||
/// \param filename Filename to check
|
||||
///
|
||||
/// \return Internal format matching the filename (-1 if no match)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int getFormatFromFilename(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Data and callbacks for opening from memory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct Memory
|
||||
{
|
||||
const char* begin;
|
||||
const char* current;
|
||||
sf_count_t size;
|
||||
|
||||
static sf_count_t getLength(void* user);
|
||||
static sf_count_t read(void* ptr, sf_count_t count, void* user);
|
||||
static sf_count_t seek(sf_count_t offset, int whence, void* user);
|
||||
static sf_count_t tell(void* user);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Data and callbacks for opening from stream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct Stream
|
||||
{
|
||||
InputStream* source;
|
||||
Int64 size;
|
||||
|
||||
static sf_count_t getLength(void* user);
|
||||
static sf_count_t read(void* ptr, sf_count_t count, void* user);
|
||||
static sf_count_t seek(sf_count_t offset, int whence, void* user);
|
||||
static sf_count_t tell(void* user);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
SNDFILE* m_file; ///< File descriptor
|
||||
Memory m_memory; ///< Memory reading info
|
||||
Stream m_stream; ///< Stream reading info
|
||||
std::size_t m_sampleCount; ///< Total number of samples in the file
|
||||
unsigned int m_channelCount; ///< Number of channels used by the sound
|
||||
unsigned int m_sampleRate; ///< Number of samples per second
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
void* m_resourceStream; ///< Asset file streamer (if loaded from file)
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOUNDFILE_HPP
|
142
src/SFML/Audio/SoundFileFactory.cpp
Normal file
142
src/SFML/Audio/SoundFileFactory.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/SoundFileFactory.hpp>
|
||||
#include <SFML/Audio/SoundFileReaderOgg.hpp>
|
||||
#include <SFML/Audio/SoundFileWriterOgg.hpp>
|
||||
#include <SFML/Audio/SoundFileReaderWav.hpp>
|
||||
#include <SFML/Audio/SoundFileWriterWav.hpp>
|
||||
#include <SFML/System/FileInputStream.hpp>
|
||||
#include <SFML/System/MemoryInputStream.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// register all the built-in readers and writers if not already done
|
||||
void ensureDefaultReadersWritersRegistered()
|
||||
{
|
||||
static bool registered = false;
|
||||
if (!registered)
|
||||
{
|
||||
sf::SoundFileFactory::registerReader<sf::priv::SoundFileReaderOgg>();
|
||||
sf::SoundFileFactory::registerWriter<sf::priv::SoundFileWriterOgg>();
|
||||
sf::SoundFileFactory::registerReader<sf::priv::SoundFileReaderWav>();
|
||||
sf::SoundFileFactory::registerWriter<sf::priv::SoundFileWriterWav>();
|
||||
registered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
SoundFileFactory::ReaderFactoryArray SoundFileFactory::s_readers;
|
||||
SoundFileFactory::WriterFactoryArray SoundFileFactory::s_writers;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileReader* SoundFileFactory::createReaderFromFilename(const std::string& filename)
|
||||
{
|
||||
// Register the built-in readers/writers on first call
|
||||
ensureDefaultReadersWritersRegistered();
|
||||
|
||||
// Wrap the input file into a file stream
|
||||
FileInputStream stream;
|
||||
if (!stream.open(filename))
|
||||
return NULL;
|
||||
|
||||
// Test the filename in all the registered factories
|
||||
for (ReaderFactoryArray::const_iterator it = s_readers.begin(); it != s_readers.end(); ++it)
|
||||
{
|
||||
stream.seek(0);
|
||||
if (it->check(stream))
|
||||
return it->create();
|
||||
}
|
||||
|
||||
// No suitable reader found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileReader* SoundFileFactory::createReaderFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
// Register the built-in readers/writers on first call
|
||||
ensureDefaultReadersWritersRegistered();
|
||||
|
||||
// Wrap the memory file into a file stream
|
||||
MemoryInputStream stream;
|
||||
stream.open(data, sizeInBytes);
|
||||
|
||||
// Test the filename in all the registered factories
|
||||
for (ReaderFactoryArray::const_iterator it = s_readers.begin(); it != s_readers.end(); ++it)
|
||||
{
|
||||
stream.seek(0);
|
||||
if (it->check(stream))
|
||||
return it->create();
|
||||
}
|
||||
|
||||
// No suitable reader found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileReader* SoundFileFactory::createReaderFromStream(InputStream& stream)
|
||||
{
|
||||
// Register the built-in readers/writers on first call
|
||||
ensureDefaultReadersWritersRegistered();
|
||||
|
||||
// Test the filename in all the registered factories
|
||||
for (ReaderFactoryArray::const_iterator it = s_readers.begin(); it != s_readers.end(); ++it)
|
||||
{
|
||||
if (it->check(stream))
|
||||
return it->create();
|
||||
}
|
||||
|
||||
// No suitable reader found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileWriter* SoundFileFactory::createWriterFromFilename(const std::string& filename)
|
||||
{
|
||||
// Register the built-in readers/writers on first call
|
||||
ensureDefaultReadersWritersRegistered();
|
||||
|
||||
// Test the filename in all the registered factories
|
||||
for (WriterFactoryArray::const_iterator it = s_writers.begin(); it != s_writers.end(); ++it)
|
||||
{
|
||||
if (it->check(filename))
|
||||
return it->create();
|
||||
}
|
||||
|
||||
// No suitable writer found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace sf
|
179
src/SFML/Audio/SoundFileReaderOgg.cpp
Normal file
179
src/SFML/Audio/SoundFileReaderOgg.cpp
Normal file
|
@ -0,0 +1,179 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/SoundFileReaderOgg.hpp>
|
||||
#include <SFML/System/MemoryInputStream.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
size_t read(void* ptr, size_t size, size_t nmemb, void* data)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(data);
|
||||
return static_cast<std::size_t>(stream->read(ptr, size * nmemb));
|
||||
}
|
||||
|
||||
int seek(void* data, ogg_int64_t offset, int whence)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(data);
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset += stream->tell();
|
||||
break;
|
||||
case SEEK_END:
|
||||
offset = stream->getSize() - offset;
|
||||
}
|
||||
return static_cast<int>(stream->seek(offset));
|
||||
}
|
||||
|
||||
long tell(void* data)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(data);
|
||||
return static_cast<long>(stream->tell());
|
||||
}
|
||||
|
||||
static ov_callbacks callbacks = {&read, &seek, NULL, &tell};
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileReaderOgg::check(InputStream& stream)
|
||||
{
|
||||
OggVorbis_File file;
|
||||
if (ov_test_callbacks(&stream, &file, NULL, 0, callbacks) == 0)
|
||||
{
|
||||
ov_clear(&file);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileReaderOgg::SoundFileReaderOgg() :
|
||||
m_vorbis (),
|
||||
m_channelCount(0)
|
||||
{
|
||||
m_vorbis.datasource = NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileReaderOgg::~SoundFileReaderOgg()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileReaderOgg::open(InputStream& stream, Info& info)
|
||||
{
|
||||
// Open the Vorbis stream
|
||||
int status = ov_open_callbacks(&stream, &m_vorbis, NULL, 0, callbacks);
|
||||
if (status < 0)
|
||||
{
|
||||
err() << "Failed to open Vorbis file for reading" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the music attributes
|
||||
vorbis_info* vorbisInfo = ov_info(&m_vorbis, -1);
|
||||
info.channelCount = vorbisInfo->channels;
|
||||
info.sampleRate = vorbisInfo->rate;
|
||||
info.sampleCount = static_cast<std::size_t>(ov_pcm_total(&m_vorbis, -1) * vorbisInfo->channels);
|
||||
|
||||
// We must keep the channel count for the seek function
|
||||
m_channelCount = info.channelCount;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFileReaderOgg::seek(Uint64 sampleOffset)
|
||||
{
|
||||
assert(m_vorbis.datasource);
|
||||
|
||||
ov_pcm_seek(&m_vorbis, sampleOffset / m_channelCount);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint64 SoundFileReaderOgg::read(Int16* samples, Uint64 maxCount)
|
||||
{
|
||||
assert(m_vorbis.datasource);
|
||||
|
||||
// Try to read the requested number of samples, stop only on error or end of file
|
||||
Uint64 count = 0;
|
||||
while (count < maxCount)
|
||||
{
|
||||
int bytesToRead = static_cast<int>(maxCount - count) * sizeof(Int16);
|
||||
long bytesRead = ov_read(&m_vorbis, reinterpret_cast<char*>(samples), bytesToRead, 0, 2, 1, NULL);
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
long samplesRead = bytesRead / sizeof(Int16);
|
||||
count += samplesRead;
|
||||
samples += samplesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
// error or end of file
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFileReaderOgg::close()
|
||||
{
|
||||
if (m_vorbis.datasource)
|
||||
{
|
||||
ov_clear(&m_vorbis);
|
||||
m_vorbis.datasource = NULL;
|
||||
m_channelCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
124
src/SFML/Audio/SoundFileReaderOgg.hpp
Normal file
124
src/SFML/Audio/SoundFileReaderOgg.hpp
Normal file
|
@ -0,0 +1,124 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_SOUNDFILEREADEROGG_HPP
|
||||
#define SFML_SOUNDFILEREADEROGG_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundFileReader.hpp>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Implementation of sound file reader that handles ogg/vorbis files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SoundFileReaderOgg : 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileReaderOgg();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~SoundFileReaderOgg();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file for reading
|
||||
///
|
||||
/// \param stream Source stream to read from
|
||||
/// \param info Structure to fill with the properties of the loaded sound
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool open(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);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close the open Vorbis file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void close();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
OggVorbis_File m_vorbis; // ogg/vorbis file handle
|
||||
unsigned int m_channelCount; // number of channels of the open sound file
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOUNDFILEREADEROGG_HPP
|
266
src/SFML/Audio/SoundFileReaderWav.cpp
Normal file
266
src/SFML/Audio/SoundFileReaderWav.cpp
Normal file
|
@ -0,0 +1,266 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/SoundFileReaderWav.hpp>
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// The following functions read integers as little endian and
|
||||
// return them in the host byte order
|
||||
|
||||
bool decode(sf::InputStream& stream, sf::Uint8& value)
|
||||
{
|
||||
return stream.read(&value, sizeof(value)) == sizeof(value);
|
||||
}
|
||||
|
||||
bool decode(sf::InputStream& stream, sf::Int16& value)
|
||||
{
|
||||
unsigned char bytes[sizeof(value)];
|
||||
if (stream.read(bytes, sizeof(bytes)) != sizeof(bytes))
|
||||
return false;
|
||||
|
||||
value = bytes[0] | (bytes[1] << 8);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool decode(sf::InputStream& stream, sf::Uint16& value)
|
||||
{
|
||||
unsigned char bytes[sizeof(value)];
|
||||
if (stream.read(bytes, sizeof(bytes)) != sizeof(bytes))
|
||||
return false;
|
||||
|
||||
value = bytes[0] | (bytes[1] << 8);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool decode(sf::InputStream& stream, sf::Uint32& value)
|
||||
{
|
||||
unsigned char bytes[sizeof(value)];
|
||||
if (stream.read(bytes, sizeof(bytes)) != sizeof(bytes))
|
||||
return false;
|
||||
|
||||
value = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const sf::Uint64 mainChunkSize = 12;
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileReaderWav::check(InputStream& stream)
|
||||
{
|
||||
char header[mainChunkSize];
|
||||
if (stream.read(header, sizeof(header)) < sizeof(header))
|
||||
return false;
|
||||
|
||||
return (header[0] == 'R') && (header[1] == 'I') && (header[2] == 'F') && (header[3] == 'F')
|
||||
&& (header[8] == 'W') && (header[9] == 'A') && (header[10] == 'V') && (header[11] == 'E');
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileReaderWav::SoundFileReaderWav() :
|
||||
m_stream (NULL),
|
||||
m_bytesPerSample(0),
|
||||
m_dataStart (0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileReaderWav::open(InputStream& stream, Info& info)
|
||||
{
|
||||
m_stream = &stream;
|
||||
|
||||
if (!parseHeader(info))
|
||||
{
|
||||
err() << "Failed to open WAV sound file (invalid or unsupported file)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFileReaderWav::seek(Uint64 sampleOffset)
|
||||
{
|
||||
assert(m_stream);
|
||||
|
||||
m_stream->seek(m_dataStart + sampleOffset * m_bytesPerSample);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint64 SoundFileReaderWav::read(Int16* samples, Uint64 maxCount)
|
||||
{
|
||||
assert(m_stream);
|
||||
|
||||
Uint64 count = 0;
|
||||
while (count < maxCount)
|
||||
{
|
||||
switch (m_bytesPerSample)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
Uint8 sample = 0;
|
||||
if (decode(*m_stream, sample))
|
||||
*samples++ = (static_cast<Int16>(sample) - 128) << 8;
|
||||
else
|
||||
return count;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
Int16 sample = 0;
|
||||
if (decode(*m_stream, sample))
|
||||
*samples++ = sample;
|
||||
else
|
||||
return count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileReaderWav::parseHeader(Info& info)
|
||||
{
|
||||
assert(m_stream);
|
||||
|
||||
// If we are here, it means that the first part of the header
|
||||
// (the format) has already been checked
|
||||
char mainChunk[mainChunkSize];
|
||||
if (m_stream->read(mainChunk, sizeof(mainChunk)) != sizeof(mainChunk))
|
||||
return false;
|
||||
|
||||
// Parse all the sub-chunks
|
||||
bool dataChunkFound = false;
|
||||
while (!dataChunkFound)
|
||||
{
|
||||
// Parse the sub-chunk id and size
|
||||
char subChunkId[4];
|
||||
if (m_stream->read(subChunkId, sizeof(subChunkId)) != sizeof(subChunkId))
|
||||
return false;
|
||||
Uint32 subChunkSize = 0;
|
||||
if (!decode(*m_stream, subChunkSize))
|
||||
return false;
|
||||
|
||||
// Check which chunk it is
|
||||
if ((subChunkId[0] == 'f') && (subChunkId[1] == 'm') && (subChunkId[2] == 't') && (subChunkId[3] == ' '))
|
||||
{
|
||||
// "fmt" chunk
|
||||
|
||||
// Audio format
|
||||
Uint16 format = 0;
|
||||
if (!decode(*m_stream, format))
|
||||
return false;
|
||||
if (format != 1) // PCM
|
||||
return false;
|
||||
|
||||
// Channel count
|
||||
Uint16 channelCount = 0;
|
||||
if (!decode(*m_stream, channelCount))
|
||||
return false;
|
||||
info.channelCount = channelCount;
|
||||
|
||||
// Sample rate
|
||||
Uint32 sampleRate = 0;
|
||||
if (!decode(*m_stream, sampleRate))
|
||||
return false;
|
||||
info.sampleRate = sampleRate;
|
||||
|
||||
// Byte rate
|
||||
Uint32 byteRate = 0;
|
||||
if (!decode(*m_stream, byteRate))
|
||||
return false;
|
||||
|
||||
// Block align
|
||||
Uint16 blockAlign = 0;
|
||||
if (!decode(*m_stream, blockAlign))
|
||||
return false;
|
||||
|
||||
// Bits per sample
|
||||
Uint16 bitsPerSample = 0;
|
||||
if (!decode(*m_stream, bitsPerSample))
|
||||
return false;
|
||||
m_bytesPerSample = bitsPerSample / 8;
|
||||
|
||||
// Skip potential extra information (should not exist for PCM)
|
||||
if (subChunkSize > 16)
|
||||
{
|
||||
char buffer[1024];
|
||||
if (m_stream->read(buffer, subChunkSize - 16) != subChunkSize - 16)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ((subChunkId[0] == 'd') && (subChunkId[1] == 'a') && (subChunkId[2] == 't') && (subChunkId[3] == 'a'))
|
||||
{
|
||||
// "data" chunk
|
||||
|
||||
// Compute the total number of samples
|
||||
info.sampleCount = subChunkSize / info.channelCount / m_bytesPerSample;
|
||||
|
||||
// Store the starting position of samples in the file
|
||||
m_dataStart = m_stream->tell();
|
||||
|
||||
dataChunkFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unknown chunk, skip it
|
||||
char buffer[1024];
|
||||
if (m_stream->read(buffer, subChunkSize) != subChunkSize)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
121
src/SFML/Audio/SoundFileReaderWav.hpp
Normal file
121
src/SFML/Audio/SoundFileReaderWav.hpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_SOUNDFILEREADERWAV_HPP
|
||||
#define SFML_SOUNDFILEREADERWAV_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundFileReader.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Implementation of sound file reader that handles wav files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SoundFileReaderWav : 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileReaderWav();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \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);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read the header of the open file
|
||||
///
|
||||
/// \param info Attributes of the sound file
|
||||
///
|
||||
/// \return True on success, false on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool parseHeader(Info& info);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
InputStream* m_stream; ///< Source stream to read from
|
||||
unsigned int m_bytesPerSample; ///< Size of a sample, in bytes
|
||||
Uint64 m_dataStart; ///< Starting position of the audio data in the open file
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOUNDFILEREADERWAV_HPP
|
206
src/SFML/Audio/SoundFileWriterOgg.cpp
Normal file
206
src/SFML/Audio/SoundFileWriterOgg.cpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/SoundFileWriterOgg.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileWriterOgg::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 == "ogg";
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileWriterOgg::SoundFileWriterOgg() :
|
||||
m_channelCount(0),
|
||||
m_file (),
|
||||
m_ogg (),
|
||||
m_vorbis (),
|
||||
m_state ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileWriterOgg::~SoundFileWriterOgg()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileWriterOgg::open(const std::string& filename, unsigned int sampleRate, unsigned int channelCount)
|
||||
{
|
||||
// Save the channel count
|
||||
m_channelCount = channelCount;
|
||||
|
||||
// Initialize the ogg/vorbis stream
|
||||
ogg_stream_init(&m_ogg, std::rand());
|
||||
vorbis_info_init(&m_vorbis);
|
||||
|
||||
// Setup the encoder: VBR, automatic bitrate management
|
||||
// Quality is in range [-1 .. 1], 0.4 gives ~128 kbps for a 44 KHz stereo sound
|
||||
int status = vorbis_encode_init_vbr(&m_vorbis, channelCount, sampleRate, 0.4f);
|
||||
if (status < 0)
|
||||
{
|
||||
err() << "Failed to write ogg/vorbis file \"" << filename << "\" (unsupported bitrate)" << std::endl;
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
vorbis_analysis_init(&m_state, &m_vorbis);
|
||||
|
||||
// Open the file after the vorbis setup is ok
|
||||
m_file.open(filename.c_str(), std::ios::binary);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to write ogg/vorbis file \"" << filename << "\" (cannot open file)" << std::endl;
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate header metadata (leave it empty)
|
||||
vorbis_comment comment;
|
||||
vorbis_comment_init(&comment);
|
||||
|
||||
// Generate the header packets
|
||||
ogg_packet header, headerComm, headerCode;
|
||||
status = vorbis_analysis_headerout(&m_state, &comment, &header, &headerComm, &headerCode);
|
||||
vorbis_comment_clear(&comment);
|
||||
if (status < 0)
|
||||
{
|
||||
err() << "Failed to write ogg/vorbis file \"" << filename << "\" (cannot generate the headers)" << std::endl;
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the header packets to the ogg stream
|
||||
ogg_stream_packetin(&m_ogg, &header);
|
||||
ogg_stream_packetin(&m_ogg, &headerComm);
|
||||
ogg_stream_packetin(&m_ogg, &headerCode);
|
||||
|
||||
// This ensures the actual audio data will start on a new page, as per spec
|
||||
ogg_page page;
|
||||
while (ogg_stream_flush(&m_ogg, &page) > 0)
|
||||
{
|
||||
m_file.write(reinterpret_cast<const char*>(page.header), page.header_len);
|
||||
m_file.write(reinterpret_cast<const char*>(page.body), page.body_len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFileWriterOgg::write(const Int16* samples, Uint64 count)
|
||||
{
|
||||
// Prepare a buffer to hold our samples
|
||||
int frameCount = static_cast<int>(count / m_channelCount);
|
||||
float** buffer = vorbis_analysis_buffer(&m_state, frameCount);
|
||||
assert(buffer);
|
||||
|
||||
// Write the samples to the buffer, converted to float
|
||||
for (int i = 0; i < frameCount; ++i)
|
||||
for (unsigned int j = 0; j < m_channelCount; ++j)
|
||||
buffer[j][i] = *samples++ / 32767.0f;
|
||||
|
||||
// Tell the library how many samples we've written
|
||||
vorbis_analysis_wrote(&m_state, frameCount);
|
||||
|
||||
// Flush any produced block
|
||||
flushBlocks();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFileWriterOgg::flushBlocks()
|
||||
{
|
||||
// Let the library divide uncompressed data into blocks, and process them
|
||||
vorbis_block block;
|
||||
vorbis_block_init(&m_state, &block);
|
||||
while (vorbis_analysis_blockout(&m_state, &block) == 1)
|
||||
{
|
||||
// Let the automatic bitrate management do its job
|
||||
vorbis_analysis(&block, NULL);
|
||||
vorbis_bitrate_addblock(&block);
|
||||
|
||||
// Get new packets from the bitrate management engine
|
||||
ogg_packet packet;
|
||||
while (vorbis_bitrate_flushpacket(&m_state, &packet))
|
||||
{
|
||||
// Write the packet to the ogg stream
|
||||
ogg_stream_packetin(&m_ogg, &packet);
|
||||
|
||||
// If the stream produced new pages, write them to the output file
|
||||
ogg_page page;
|
||||
while (ogg_stream_flush(&m_ogg, &page) > 0)
|
||||
{
|
||||
m_file.write(reinterpret_cast<const char*>(page.header), page.header_len);
|
||||
m_file.write(reinterpret_cast<const char*>(page.body), page.body_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the allocated block
|
||||
vorbis_block_clear(&block);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFileWriterOgg::close()
|
||||
{
|
||||
if (m_file.is_open())
|
||||
{
|
||||
// Submit an empty packet to mark the end of stream
|
||||
vorbis_analysis_wrote(&m_state, 0);
|
||||
flushBlocks();
|
||||
|
||||
// Close the file
|
||||
m_file.close();
|
||||
}
|
||||
|
||||
// Clear all the ogg/vorbis structures
|
||||
ogg_stream_clear(&m_ogg);
|
||||
vorbis_dsp_clear(&m_state);
|
||||
vorbis_info_clear(&m_vorbis);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
122
src/SFML/Audio/SoundFileWriterOgg.hpp
Normal file
122
src/SFML/Audio/SoundFileWriterOgg.hpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_SOUNDFILEWRITEROGG_HPP
|
||||
#define SFML_SOUNDFILEWRITEROGG_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundFileWriter.hpp>
|
||||
#include <vorbis/vorbisenc.h>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Implementation of sound file writer that handles ogg files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SoundFileWriterOgg : 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileWriterOgg();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~SoundFileWriterOgg();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \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 Flush blocks produced by the ogg stream, if any
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void flushBlocks();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close the file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void close();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int m_channelCount; // channel count of the sound being written
|
||||
std::ofstream m_file; // output file
|
||||
ogg_stream_state m_ogg; // ogg stream
|
||||
vorbis_info m_vorbis; // vorbis handle
|
||||
vorbis_dsp_state m_state; // current encoding state
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOUNDFILEWRITEROGG_HPP
|
207
src/SFML/Audio/SoundFileWriterWav.cpp
Normal file
207
src/SFML/Audio/SoundFileWriterWav.cpp
Normal file
|
@ -0,0 +1,207 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/SoundFileWriterWav.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// The following functions takes integers in host byte order
|
||||
// and writes them to a stream as little endian
|
||||
|
||||
void encode(std::ostream& stream, sf::Int16 value)
|
||||
{
|
||||
unsigned char bytes[] =
|
||||
{
|
||||
static_cast<unsigned char>(value & 0xFF),
|
||||
static_cast<unsigned char>(value >> 8)
|
||||
};
|
||||
stream.write(reinterpret_cast<const char*>(bytes), sizeof(bytes));
|
||||
}
|
||||
|
||||
void encode(std::ostream& stream, sf::Uint16 value)
|
||||
{
|
||||
unsigned char bytes[] =
|
||||
{
|
||||
static_cast<unsigned char>(value & 0xFF),
|
||||
static_cast<unsigned char>(value >> 8)
|
||||
};
|
||||
stream.write(reinterpret_cast<const char*>(bytes), sizeof(bytes));
|
||||
}
|
||||
|
||||
void encode(std::ostream& stream, sf::Uint32 value)
|
||||
{
|
||||
unsigned char bytes[] =
|
||||
{
|
||||
static_cast<unsigned char>(value & 0x000000FF),
|
||||
static_cast<unsigned char>((value & 0x0000FF00) >> 8),
|
||||
static_cast<unsigned char>((value & 0x00FF0000) >> 16),
|
||||
static_cast<unsigned char>((value & 0xFF000000) >> 24),
|
||||
};
|
||||
stream.write(reinterpret_cast<const char*>(bytes), sizeof(bytes));
|
||||
}
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileWriterWav::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 == "wav";
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileWriterWav::SoundFileWriterWav() :
|
||||
m_file (),
|
||||
m_sampleCount (0),
|
||||
m_channelCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileWriterWav::~SoundFileWriterWav()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileWriterWav::open(const std::string& filename, unsigned int sampleRate, unsigned int channelCount)
|
||||
{
|
||||
// Open the file
|
||||
m_file.open(filename.c_str(), std::ios::binary);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to open WAV sound file \"" << filename << "\" for writing" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the header
|
||||
if (!writeHeader(sampleRate, channelCount))
|
||||
{
|
||||
err() << "Failed to write header of WAV sound file \"" << filename << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the channel count
|
||||
m_channelCount = channelCount;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFileWriterWav::write(const Int16* samples, Uint64 count)
|
||||
{
|
||||
assert(m_file.good());
|
||||
|
||||
m_sampleCount += count;
|
||||
|
||||
while (count--)
|
||||
encode(m_file, *samples++);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFileWriterWav::writeHeader(unsigned int sampleRate, unsigned int channelCount)
|
||||
{
|
||||
assert(m_file.good());
|
||||
|
||||
// Write the main chunk ID
|
||||
char mainChunkId[4] = {'R', 'I', 'F', 'F'};
|
||||
m_file.write(mainChunkId, sizeof(mainChunkId));
|
||||
|
||||
// Write the main chunk header
|
||||
Uint32 mainChunkSize = 0; // placeholder, will be written later
|
||||
encode(m_file, mainChunkSize);
|
||||
char mainChunkFormat[4] = {'W', 'A', 'V', 'E'};
|
||||
m_file.write(mainChunkFormat, sizeof(mainChunkFormat));
|
||||
|
||||
// Write the sub-chunk 1 ("format") id and size
|
||||
char fmtChunkId[4] = {'f', 'm', 't', ' '};
|
||||
m_file.write(fmtChunkId, sizeof(fmtChunkId));
|
||||
Uint32 fmtChunkSize = 16;
|
||||
encode(m_file, fmtChunkSize);
|
||||
|
||||
// Write the format (PCM)
|
||||
Uint16 format = 1;
|
||||
encode(m_file, format);
|
||||
|
||||
// Write the sound attributes
|
||||
encode(m_file, static_cast<Uint16>(channelCount));
|
||||
encode(m_file, static_cast<Uint32>(sampleRate));
|
||||
Uint32 byteRate = sampleRate * channelCount * 2;
|
||||
encode(m_file, byteRate);
|
||||
Uint16 blockAlign = channelCount * 2;
|
||||
encode(m_file, blockAlign);
|
||||
Uint16 bitsPerSample = 16;
|
||||
encode(m_file, bitsPerSample);
|
||||
|
||||
// Write the sub-chunk 2 ("data") id and size
|
||||
char dataChunkId[4] = {'d', 'a', 't', 'a'};
|
||||
m_file.write(dataChunkId, sizeof(dataChunkId));
|
||||
Uint32 dataChunkSize = 0; // placeholder, will be written later
|
||||
encode(m_file, dataChunkSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFileWriterWav::close()
|
||||
{
|
||||
// If the file is open, finalize the header and close it
|
||||
if (m_file.is_open())
|
||||
{
|
||||
m_file.flush();
|
||||
|
||||
// Update the main chunk size and data sub-chunk size
|
||||
Uint32 dataChunkSize = static_cast<Uint32>(m_sampleCount * m_channelCount * 2);
|
||||
Uint32 mainChunkSize = dataChunkSize + 36;
|
||||
m_file.seekp(4);
|
||||
encode(m_file, mainChunkSize);
|
||||
m_file.seekp(40);
|
||||
encode(m_file, dataChunkSize);
|
||||
|
||||
m_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
125
src/SFML/Audio/SoundFileWriterWav.hpp
Normal file
125
src/SFML/Audio/SoundFileWriterWav.hpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_SOUNDFILEWRITERWAV_HPP
|
||||
#define SFML_SOUNDFILEWRITERWAV_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundFileWriter.hpp>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Implementation of sound file writer that handles wav files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SoundFileWriterWav : 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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFileWriterWav();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~SoundFileWriterWav();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \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 Write the header of the open file
|
||||
///
|
||||
/// \param sampleRate Sample rate of the sound
|
||||
/// \param channelCount Number of channels of the sound
|
||||
///
|
||||
/// \return True on success, false on error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool writeHeader(unsigned int sampleRate, unsigned int channelCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close the file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void close();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ofstream m_file; ///< File stream to write to
|
||||
Uint64 m_sampleCount; ///< Total number of samples written to the file
|
||||
unsigned int m_channelCount; ///< Number of channels of the sound
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOUNDFILEWRITERWAV_HPP
|
|
@ -35,6 +35,10 @@ set(SRC
|
|||
${INCROOT}/Vector2.inl
|
||||
${INCROOT}/Vector3.hpp
|
||||
${INCROOT}/Vector3.inl
|
||||
${SRCROOT}/FileInputStream.cpp
|
||||
${INCROOT}/FileInputStream.hpp
|
||||
${SRCROOT}/MemoryInputStream.cpp
|
||||
${INCROOT}/MemoryInputStream.hpp
|
||||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
|
|
76
src/SFML/System/FileInputStream.cpp
Normal file
76
src/SFML/System/FileInputStream.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/System/FileInputStream.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool FileInputStream::open(const std::string& filename)
|
||||
{
|
||||
m_file.open(filename.c_str(), std::ios::binary);
|
||||
return m_file.good();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 FileInputStream::read(void* data, Int64 size)
|
||||
{
|
||||
m_file.read(static_cast<char*>(data), size);
|
||||
return m_file.gcount();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 FileInputStream::seek(Int64 position)
|
||||
{
|
||||
if (m_file.eof())
|
||||
m_file.clear();
|
||||
m_file.seekg(position);
|
||||
return tell();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 FileInputStream::tell()
|
||||
{
|
||||
return m_file.tellg();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 FileInputStream::getSize()
|
||||
{
|
||||
std::ifstream::pos_type pos = m_file.tellg();
|
||||
m_file.seekg(0, std::ios::end);
|
||||
std::ifstream::pos_type size = m_file.tellg();
|
||||
m_file.seekg(pos);
|
||||
return size;
|
||||
}
|
||||
|
||||
} // namespace sf
|
101
src/SFML/System/MemoryInputStream.cpp
Normal file
101
src/SFML/System/MemoryInputStream.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/System/MemoryInputStream.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
MemoryInputStream::MemoryInputStream() :
|
||||
m_data (NULL),
|
||||
m_size (0),
|
||||
m_offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MemoryInputStream::open(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
m_data = static_cast<const char*>(data);
|
||||
m_size = sizeInBytes;
|
||||
m_offset = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 MemoryInputStream::read(void* data, Int64 size)
|
||||
{
|
||||
if (!m_data)
|
||||
return -1;
|
||||
|
||||
Int64 endPosition = m_offset + size;
|
||||
Int64 count = endPosition <= m_size ? size : m_size - m_offset;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
std::memcpy(data, m_data + m_offset, static_cast<std::size_t>(count));
|
||||
m_offset += count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 MemoryInputStream::seek(Int64 position)
|
||||
{
|
||||
if (!m_data)
|
||||
return -1;
|
||||
|
||||
m_offset = position < m_size ? position : m_size;
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 MemoryInputStream::tell()
|
||||
{
|
||||
if (!m_data)
|
||||
return -1;
|
||||
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 MemoryInputStream::getSize()
|
||||
{
|
||||
if (!m_data)
|
||||
return -1;
|
||||
|
||||
return m_size;
|
||||
}
|
||||
|
||||
} // namespace sf
|
Loading…
Add table
Add a link
Reference in a new issue