mirror of
https://github.com/SFML/SFML.git
synced 2024-11-29 06:41:05 +08:00
Added Opus sound file support, added SoundFileReaderOpus and FindOpus cmake Module
This commit is contained in:
parent
37ac80dbe5
commit
15bb2ef28e
43
cmake/Modules/FindOpus.cmake
Normal file
43
cmake/Modules/FindOpus.cmake
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# This file was taken from Unvanquished,
|
||||||
|
# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
||||||
|
# It's licensed under the terms of the 3-clause OpenBSD license.
|
||||||
|
# Modifications Copyright 2014-2015 the openage authors.
|
||||||
|
# See copying.md for further legal info.
|
||||||
|
|
||||||
|
# - Find opus library
|
||||||
|
# Find the native Opus headers and libraries.
|
||||||
|
# This module defines
|
||||||
|
# OPUS_INCLUDE_DIRS - where to find opus/opus.h, opus/opusfile.h, etc
|
||||||
|
# OPUS_LIBRARIES - List of libraries when using libopus
|
||||||
|
# OPUS_FOUND - True if opus is found.
|
||||||
|
|
||||||
|
# find the opusfile header, defines our api.
|
||||||
|
find_path(OPUS_INCLUDE_DIR
|
||||||
|
NAMES opus/opusfile.h
|
||||||
|
DOC "Opus include directory"
|
||||||
|
)
|
||||||
|
mark_as_advanced(OPUS_INCLUDE_DIR)
|
||||||
|
|
||||||
|
# look for libopusfile, the highlevel container-aware api.
|
||||||
|
find_library(OPUSFILE_LIBRARY
|
||||||
|
NAMES opusfile
|
||||||
|
DOC "Path to OpusFile library"
|
||||||
|
)
|
||||||
|
mark_as_advanced(OPUSFILE_LIBRARY)
|
||||||
|
|
||||||
|
# find libopus, the core codec component.
|
||||||
|
find_library(OPUS_LIBRARY
|
||||||
|
NAMES opus
|
||||||
|
DOC "Path to Opus library"
|
||||||
|
)
|
||||||
|
mark_as_advanced(OPUS_LIBRARY)
|
||||||
|
|
||||||
|
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set OPUSFILE_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(Opus DEFAULT_MSG OPUSFILE_LIBRARY OPUS_LIBRARY OPUS_INCLUDE_DIR)
|
||||||
|
|
||||||
|
# export the variables
|
||||||
|
set(OPUS_LIBRARIES "${OPUSFILE_LIBRARY}" "${OPUS_LIBRARY}")
|
||||||
|
set(OPUS_INCLUDE_DIRS "${OPUS_INCLUDE_DIR}" "${OPUS_INCLUDE_DIR}/opus")
|
@ -48,6 +48,8 @@ set(CODECS_SRC
|
|||||||
${SRCROOT}/SoundFileReaderMp3.cpp
|
${SRCROOT}/SoundFileReaderMp3.cpp
|
||||||
${SRCROOT}/SoundFileReaderOgg.hpp
|
${SRCROOT}/SoundFileReaderOgg.hpp
|
||||||
${SRCROOT}/SoundFileReaderOgg.cpp
|
${SRCROOT}/SoundFileReaderOgg.cpp
|
||||||
|
${SRCROOT}/SoundFileReaderOpus.hpp
|
||||||
|
${SRCROOT}/SoundFileReaderOpus.cpp
|
||||||
${SRCROOT}/SoundFileReaderWav.hpp
|
${SRCROOT}/SoundFileReaderWav.hpp
|
||||||
${SRCROOT}/SoundFileReaderWav.cpp
|
${SRCROOT}/SoundFileReaderWav.cpp
|
||||||
${INCROOT}/SoundFileWriter.hpp
|
${INCROOT}/SoundFileWriter.hpp
|
||||||
@ -77,6 +79,7 @@ endif()
|
|||||||
# find external libraries
|
# find external libraries
|
||||||
find_package(Vorbis REQUIRED)
|
find_package(Vorbis REQUIRED)
|
||||||
find_package(FLAC REQUIRED)
|
find_package(FLAC REQUIRED)
|
||||||
|
find_package(Opus REQUIRED)
|
||||||
|
|
||||||
# define the sfml-audio target
|
# define the sfml-audio target
|
||||||
sfml_add_library(Audio
|
sfml_add_library(Audio
|
||||||
|
@ -29,9 +29,11 @@
|
|||||||
#include <SFML/Audio/SoundFileReaderFlac.hpp>
|
#include <SFML/Audio/SoundFileReaderFlac.hpp>
|
||||||
#include <SFML/Audio/SoundFileReaderMp3.hpp>
|
#include <SFML/Audio/SoundFileReaderMp3.hpp>
|
||||||
#include <SFML/Audio/SoundFileReaderOgg.hpp>
|
#include <SFML/Audio/SoundFileReaderOgg.hpp>
|
||||||
|
#include <SFML/Audio/SoundFileReaderOpus.hpp>
|
||||||
#include <SFML/Audio/SoundFileReaderWav.hpp>
|
#include <SFML/Audio/SoundFileReaderWav.hpp>
|
||||||
#include <SFML/Audio/SoundFileWriterFlac.hpp>
|
#include <SFML/Audio/SoundFileWriterFlac.hpp>
|
||||||
#include <SFML/Audio/SoundFileWriterOgg.hpp>
|
#include <SFML/Audio/SoundFileWriterOgg.hpp>
|
||||||
|
//#include <SFML/Audio/SoundFileWriterOpus.hpp>
|
||||||
#include <SFML/Audio/SoundFileWriterWav.hpp>
|
#include <SFML/Audio/SoundFileWriterWav.hpp>
|
||||||
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
@ -144,6 +146,7 @@ SoundFileFactory::ReaderFactoryMap& SoundFileFactory::getReaderFactoryMap()
|
|||||||
static ReaderFactoryMap result{{&priv::createReader<priv::SoundFileReaderFlac>, &priv::SoundFileReaderFlac::check},
|
static ReaderFactoryMap result{{&priv::createReader<priv::SoundFileReaderFlac>, &priv::SoundFileReaderFlac::check},
|
||||||
{&priv::createReader<priv::SoundFileReaderMp3>, &priv::SoundFileReaderMp3::check},
|
{&priv::createReader<priv::SoundFileReaderMp3>, &priv::SoundFileReaderMp3::check},
|
||||||
{&priv::createReader<priv::SoundFileReaderOgg>, &priv::SoundFileReaderOgg::check},
|
{&priv::createReader<priv::SoundFileReaderOgg>, &priv::SoundFileReaderOgg::check},
|
||||||
|
{&priv::createReader<priv::SoundFileReaderOpus>, &priv::SoundFileReaderOpus::check},
|
||||||
{&priv::createReader<priv::SoundFileReaderWav>, &priv::SoundFileReaderWav::check}};
|
{&priv::createReader<priv::SoundFileReaderWav>, &priv::SoundFileReaderWav::check}};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
189
src/SFML/Audio/SoundFileReaderOpus.cpp
Normal file
189
src/SFML/Audio/SoundFileReaderOpus.cpp
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2016 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.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Audio/SoundFileReaderOpus.hpp>
|
||||||
|
#include <SFML/System/MemoryInputStream.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cassert>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
int read(void* data, unsigned char* ptr, int bytes)
|
||||||
|
{
|
||||||
|
sf::InputStream* stream = static_cast<sf::InputStream*>(data);
|
||||||
|
return static_cast<int>(stream->read(ptr, bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
int seek(void* data, opus_int64 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 value expected from libopusfile: 0 - Success and -1 - Failure
|
||||||
|
return static_cast<int>(stream->seek(offset)) >= 0 ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
opus_int64 tell(void* data)
|
||||||
|
{
|
||||||
|
sf::InputStream* stream = static_cast<sf::InputStream*>(data);
|
||||||
|
return static_cast<opus_int64>(stream->tell());
|
||||||
|
}
|
||||||
|
|
||||||
|
static OpusFileCallbacks callbacks = {&read, &seek, &tell, NULL};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
namespace priv
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SoundFileReaderOpus::check(InputStream& stream)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
OggOpusFile* file = op_test_callbacks(&stream, &callbacks, NULL, 0, &error);
|
||||||
|
if (error == 0)
|
||||||
|
{
|
||||||
|
op_free(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundFileReaderOpus::SoundFileReaderOpus() :
|
||||||
|
m_opus (NULL),
|
||||||
|
m_channelCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundFileReaderOpus::~SoundFileReaderOpus()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SoundFileReaderOpus::open(InputStream& stream, Info& info)
|
||||||
|
{
|
||||||
|
// Open the Opus stream
|
||||||
|
int status = 0;
|
||||||
|
m_opus = op_open_callbacks(&stream, &callbacks, NULL, 0, &status);
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
err() << "Failed to open Opus file for reading" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the music attributes
|
||||||
|
const OpusHead* opusHead = op_head(m_opus, -1);
|
||||||
|
info.channelCount = opusHead->channel_count;
|
||||||
|
info.sampleRate = opusHead->input_sample_rate;
|
||||||
|
info.sampleCount = static_cast<std::size_t>(op_pcm_total(m_opus, -1) * opusHead->channel_count);
|
||||||
|
// We must keep the channel count for the seek function
|
||||||
|
m_channelCount = info.channelCount;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundFileReaderOpus::seek(Uint64 sampleOffset)
|
||||||
|
{
|
||||||
|
assert(m_opus != NULL);
|
||||||
|
|
||||||
|
op_pcm_seek(m_opus, sampleOffset / m_channelCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Uint64 SoundFileReaderOpus::read(Int16* samples, Uint64 maxCount)
|
||||||
|
{
|
||||||
|
assert(m_opus != NULL);
|
||||||
|
|
||||||
|
int samplesToRead;
|
||||||
|
// Try to read the requested number of samples, stop only on error or end of file
|
||||||
|
Uint64 count = 0;
|
||||||
|
while (maxCount > 0)
|
||||||
|
{
|
||||||
|
// since maxCount is uint64 we have to ensure that samplesToRead is <= INT_MAX (int overflow)
|
||||||
|
if (maxCount > INT_MAX)
|
||||||
|
{
|
||||||
|
samplesToRead = INT_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
samplesToRead = maxCount;
|
||||||
|
}
|
||||||
|
// op_read returns number of SAMPLES read PER CHANNEL
|
||||||
|
int samplesRead = op_read(m_opus, samples, samplesToRead, NULL) * m_channelCount;
|
||||||
|
if (samplesRead > 0)
|
||||||
|
{
|
||||||
|
maxCount -= samplesRead;
|
||||||
|
count += samplesRead;
|
||||||
|
samples += samplesRead;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// error or end of file
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SoundFileReaderOpus::close()
|
||||||
|
{
|
||||||
|
if (m_opus != NULL)
|
||||||
|
{
|
||||||
|
op_free(m_opus);
|
||||||
|
m_channelCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
|
} // namespace sf
|
124
src/SFML/Audio/SoundFileReaderOpus.hpp
Normal file
124
src/SFML/Audio/SoundFileReaderOpus.hpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2016 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_SOUNDFILEREADEROPUS_HPP
|
||||||
|
#define SFML_SOUNDFILEREADEROPUS_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Audio/SoundFileReader.hpp>
|
||||||
|
#include <opus/opusfile.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
namespace priv
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Implementation of sound file reader that handles Opus files
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SoundFileReaderOpus : 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
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SoundFileReaderOpus();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Destructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
~SoundFileReaderOpus();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \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 Opus file
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void close();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
OggOpusFile* m_opus; // opus file handle
|
||||||
|
unsigned int m_channelCount; // number of channels of the open sound file
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOUNDFILEREADEROPUS_HPP
|
Loading…
Reference in New Issue
Block a user