Eliminate the strict requirement of libsndfile

This commit is contained in:
Jean Pierre Cimalando 2020-10-07 16:42:25 +02:00
parent ff1d749ee7
commit d5aad58366
11 changed files with 196 additions and 110 deletions

View file

@ -29,6 +29,7 @@ option (SFIZZ_BENCHMARKS "Enable benchmarks build [default: OFF]" OFF)
option (SFIZZ_TESTS "Enable tests build [default: OFF]" OFF) option (SFIZZ_TESTS "Enable tests build [default: OFF]" OFF)
option (SFIZZ_DEVTOOLS "Enable developer tools build [default: OFF]" OFF) option (SFIZZ_DEVTOOLS "Enable developer tools build [default: OFF]" OFF)
option (SFIZZ_SHARED "Enable shared library build [default: ON]" ON) option (SFIZZ_SHARED "Enable shared library build [default: ON]" ON)
option (SFIZZ_USE_SNDFILE "Enable use of the sndfile library [default: ON]" ON)
option (SFIZZ_USE_VCPKG "Assume that sfizz is build using vcpkg [default: OFF]" OFF) option (SFIZZ_USE_VCPKG "Assume that sfizz is build using vcpkg [default: OFF]" OFF)
option (SFIZZ_STATIC_DEPENDENCIES "Link dependencies statically [default: OFF]" OFF) option (SFIZZ_STATIC_DEPENDENCIES "Link dependencies statically [default: OFF]" OFF)
option (SFIZZ_RELEASE_ASSERTS "Forced assertions in release builds [default: OFF]" OFF) option (SFIZZ_RELEASE_ASSERTS "Forced assertions in release builds [default: OFF]" OFF)

View file

@ -86,7 +86,7 @@ sfizz_add_benchmark(bm_flacfile BM_flacfile.cpp)
target_link_libraries(bm_flacfile PRIVATE sfizz-sndfile) target_link_libraries(bm_flacfile PRIVATE sfizz-sndfile)
sfizz_add_benchmark(bm_audioReaders BM_audioReaders.cpp ../src/sfizz/AudioReader.cpp) sfizz_add_benchmark(bm_audioReaders BM_audioReaders.cpp ../src/sfizz/AudioReader.cpp)
target_link_libraries(bm_audioReaders PRIVATE sfizz-sndfile) target_link_libraries(bm_audioReaders PRIVATE st_audiofile sfizz-sndfile)
sfizz_add_benchmark(bm_readChunk BM_readChunk.cpp) sfizz_add_benchmark(bm_readChunk BM_readChunk.cpp)
target_link_libraries(bm_readChunk PRIVATE sfizz-sndfile) target_link_libraries(bm_readChunk PRIVATE sfizz-sndfile)

View file

@ -79,30 +79,40 @@ function(sfizz_enable_fast_math NAME)
endif() endif()
endfunction() endfunction()
# The sndfile library
add_library(sfizz-sndfile INTERFACE)
# The jsl utility library for C++ # The jsl utility library for C++
add_library(sfizz-jsl INTERFACE) add_library(sfizz-jsl INTERFACE)
target_include_directories(sfizz-jsl INTERFACE "external/jsl/include") target_include_directories(sfizz-jsl INTERFACE "external/jsl/include")
if (SFIZZ_USE_VCPKG OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC") # The sndfile library
find_package(SndFile CONFIG REQUIRED) if (SFIZZ_USE_SNDFILE OR SFIZZ_TESTS OR SFIZZ_BENCHMARKS OR SFIZZ_RENDER)
find_path(SNDFILE_INCLUDE_DIR sndfile.hh) add_library(sfizz-sndfile INTERFACE)
target_include_directories(sfizz-sndfile INTERFACE "${SNDFILE_INCLUDE_DIR}") if (SFIZZ_USE_VCPKG OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
target_link_libraries(sfizz-sndfile INTERFACE SndFile::sndfile) find_package(SndFile CONFIG REQUIRED)
else() find_path(SNDFILE_INCLUDE_DIR "sndfile.hh")
find_package(PkgConfig REQUIRED) target_include_directories(sfizz-sndfile INTERFACE "${SNDFILE_INCLUDE_DIR}")
pkg_check_modules(SNDFILE "sndfile" REQUIRED) target_link_libraries(sfizz-sndfile INTERFACE SndFile::sndfile)
target_include_directories(sfizz-sndfile INTERFACE ${SNDFILE_INCLUDE_DIRS})
if (SFIZZ_STATIC_DEPENDENCIES)
target_link_libraries(sfizz-sndfile INTERFACE ${SNDFILE_STATIC_LIBRARIES})
else() else()
target_link_libraries(sfizz-sndfile INTERFACE ${SNDFILE_LIBRARIES}) find_package(PkgConfig REQUIRED)
pkg_check_modules(SNDFILE "sndfile" REQUIRED)
target_include_directories(sfizz-sndfile INTERFACE ${SNDFILE_INCLUDE_DIRS})
if (SFIZZ_STATIC_DEPENDENCIES)
target_link_libraries(sfizz-sndfile INTERFACE ${SNDFILE_STATIC_LIBRARIES})
else()
target_link_libraries(sfizz-sndfile INTERFACE ${SNDFILE_LIBRARIES})
endif()
link_directories(${SNDFILE_LIBRARY_DIRS})
endif() endif()
link_directories(${SNDFILE_LIBRARY_DIRS})
endif() endif()
# The st_audiofile library
if (SFIZZ_USE_SNDFILE)
set(ST_AUDIO_FILE_USE_SNDFILE ON CACHE BOOL "" FORCE)
set(ST_AUDIO_FILE_EXTERNAL_SNDFILE "sfizz-sndfile" CACHE STRING "" FORCE)
else()
set(ST_AUDIO_FILE_USE_SNDFILE OFF CACHE BOOL "" FORCE)
set(ST_AUDIO_FILE_EXTERNAL_SNDFILE "" CACHE STRING "" FORCE)
endif()
add_subdirectory("external/st_audiofile" EXCLUDE_FROM_ALL)
# If we build with Clang, optionally use libc++. Enabled by default on Apple OS. # If we build with Clang, optionally use libc++. Enabled by default on Apple OS.
cmake_dependent_option(USE_LIBCPP "Use libc++ with clang" "${APPLE}" cmake_dependent_option(USE_LIBCPP "Use libc++ with clang" "${APPLE}"
@ -154,6 +164,7 @@ Build VST plug-in: ${SFIZZ_VST}
Build AU plug-in: ${SFIZZ_AU} Build AU plug-in: ${SFIZZ_AU}
Build benchmarks: ${SFIZZ_BENCHMARKS} Build benchmarks: ${SFIZZ_BENCHMARKS}
Build tests: ${SFIZZ_TESTS} Build tests: ${SFIZZ_TESTS}
Use sndfile: ${SFIZZ_USE_SNDFILE}
Use vcpkg: ${SFIZZ_USE_VCPKG} Use vcpkg: ${SFIZZ_USE_VCPKG}
Statically link dependencies: ${SFIZZ_STATIC_DEPENDENCIES} Statically link dependencies: ${SFIZZ_STATIC_DEPENDENCIES}
Link libatomic: ${SFIZZ_LINK_LIBATOMIC} Link libatomic: ${SFIZZ_LINK_LIBATOMIC}

View file

@ -218,7 +218,7 @@ target_sources(sfizz_static PRIVATE
target_include_directories (sfizz_static PUBLIC .) target_include_directories (sfizz_static PUBLIC .)
target_include_directories (sfizz_static PUBLIC external) target_include_directories (sfizz_static PUBLIC external)
target_link_libraries (sfizz_static PUBLIC absl::strings absl::span) target_link_libraries (sfizz_static PUBLIC absl::strings absl::span)
target_link_libraries (sfizz_static PRIVATE sfizz_parser absl::flat_hash_map Threads::Threads sfizz-sndfile sfizz-pugixml sfizz-spline sfizz-tunings sfizz-kissfft sfizz-cpuid sfizz-jsl sfizz-atomic) target_link_libraries (sfizz_static PRIVATE sfizz_parser absl::flat_hash_map Threads::Threads st_audiofile sfizz-pugixml sfizz-spline sfizz-tunings sfizz-kissfft sfizz-cpuid sfizz-jsl sfizz-atomic)
set_target_properties (sfizz_static PROPERTIES OUTPUT_NAME sfizz PUBLIC_HEADER "sfizz.h;sfizz.hpp") set_target_properties (sfizz_static PROPERTIES OUTPUT_NAME sfizz PUBLIC_HEADER "sfizz.h;sfizz.hpp")
if (WIN32) if (WIN32)
target_compile_definitions (sfizz_static PRIVATE _USE_MATH_DEFINES) target_compile_definitions (sfizz_static PRIVATE _USE_MATH_DEFINES)
@ -245,7 +245,7 @@ if (SFIZZ_SHARED)
${SFIZZ_HEADERS} ${SFIZZ_SOURCES} ${FAUST_FILES} sfizz/sfizz_wrapper.cpp sfizz/sfizz.cpp) ${SFIZZ_HEADERS} ${SFIZZ_SOURCES} ${FAUST_FILES} sfizz/sfizz_wrapper.cpp sfizz/sfizz.cpp)
target_include_directories (sfizz_shared PRIVATE .) target_include_directories (sfizz_shared PRIVATE .)
target_include_directories (sfizz_shared PRIVATE external) target_include_directories (sfizz_shared PRIVATE external)
target_link_libraries (sfizz_shared PRIVATE absl::strings absl::span sfizz_parser absl::flat_hash_map Threads::Threads sfizz-sndfile sfizz-pugixml sfizz-spline sfizz-tunings sfizz-kissfft sfizz-cpuid sfizz-jsl sfizz-atomic) target_link_libraries (sfizz_shared PRIVATE absl::strings absl::span sfizz_parser absl::flat_hash_map Threads::Threads st_audiofile sfizz-pugixml sfizz-spline sfizz-tunings sfizz-kissfft sfizz-cpuid sfizz-jsl sfizz-atomic)
if (WIN32) if (WIN32)
target_compile_definitions (sfizz_shared PRIVATE _USE_MATH_DEFINES) target_compile_definitions (sfizz_shared PRIVATE _USE_MATH_DEFINES)
endif() endif()

View file

@ -5,51 +5,60 @@
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "AudioReader.h" #include "AudioReader.h"
#include <sndfile.hh> #include "FileMetadata.h"
#include <st_audiofile.hpp>
#if defined(ST_AUDIO_FILE_USE_SNDFILE)
#include <sndfile.h>
#endif
#include <algorithm> #include <algorithm>
namespace sfz { namespace sfz {
class BasicSndfileReader : public AudioReader { class BasicSndfileReader : public AudioReader {
public: public:
explicit BasicSndfileReader(SndfileHandle handle) : handle_(handle) {} explicit BasicSndfileReader(ST_AudioFile handle) : handle_(std::move(handle)) {}
virtual ~BasicSndfileReader() {} virtual ~BasicSndfileReader() {}
int format() const override; int format() const override;
int64_t frames() const override; int64_t frames() const override;
unsigned channels() const override; unsigned channels() const override;
unsigned sampleRate() const override; unsigned sampleRate() const override;
bool getInstrument(SF_INSTRUMENT* instrument) override; bool getInstrument(InstrumentInfo* instrument) override;
protected: protected:
SndfileHandle handle_; ST_AudioFile handle_;
}; };
int BasicSndfileReader::format() const int BasicSndfileReader::format() const
{ {
return handle_.format(); return handle_.get_type();
} }
int64_t BasicSndfileReader::frames() const int64_t BasicSndfileReader::frames() const
{ {
return handle_.frames(); return handle_.get_frame_count();
} }
unsigned BasicSndfileReader::channels() const unsigned BasicSndfileReader::channels() const
{ {
return handle_.channels(); return handle_.get_channels();
} }
unsigned BasicSndfileReader::sampleRate() const unsigned BasicSndfileReader::sampleRate() const
{ {
return handle_.samplerate(); return handle_.get_sample_rate();
} }
bool BasicSndfileReader::getInstrument(SF_INSTRUMENT* instrument) bool BasicSndfileReader::getInstrument(InstrumentInfo* instrument)
{ {
if (handle_.command(SFC_GET_INSTRUMENT, instrument, sizeof(SF_INSTRUMENT)) == SF_FALSE) #if defined(ST_AUDIO_FILE_USE_SNDFILE)
return false; SNDFILE* sndfile = reinterpret_cast<SNDFILE*>(handle_.get_sndfile_handle());
return true; if (sf_command(sndfile, SFC_GET_INSTRUMENT, &instrument, sizeof(instrument)) == SF_TRUE)
return true;
#else
(void)instrument;
#endif
return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -59,13 +68,13 @@ bool BasicSndfileReader::getInstrument(SF_INSTRUMENT* instrument)
*/ */
class ForwardReader : public BasicSndfileReader { class ForwardReader : public BasicSndfileReader {
public: public:
explicit ForwardReader(SndfileHandle handle); explicit ForwardReader(ST_AudioFile handle);
AudioReaderType type() const override; AudioReaderType type() const override;
size_t readNextBlock(float* buffer, size_t frames) override; size_t readNextBlock(float* buffer, size_t frames) override;
}; };
ForwardReader::ForwardReader(SndfileHandle handle) ForwardReader::ForwardReader(ST_AudioFile handle)
: BasicSndfileReader(handle) : BasicSndfileReader(std::move(handle))
{ {
} }
@ -76,7 +85,7 @@ AudioReaderType ForwardReader::type() const
size_t ForwardReader::readNextBlock(float* buffer, size_t frames) size_t ForwardReader::readNextBlock(float* buffer, size_t frames)
{ {
sf_count_t readFrames = handle_.readf(buffer, frames); uint64_t readFrames = handle_.read_f32(buffer, frames);
if (frames <= 0) if (frames <= 0)
return 0; return 0;
@ -93,7 +102,7 @@ struct AudioFrame {
/** /**
* @brief Reorder a sequence of frames in reverse * @brief Reorder a sequence of frames in reverse
*/ */
static void reverse_frames(float* data, sf_count_t frames, unsigned channels) static void reverse_frames(float* data, size_t frames, unsigned channels)
{ {
switch (channels) { switch (channels) {
@ -108,8 +117,8 @@ static void reverse_frames(float* data, sf_count_t frames, unsigned channels)
SPECIALIZE_FOR(2); SPECIALIZE_FOR(2);
default: default:
for (sf_count_t i = 0; i < frames / 2; ++i) { for (size_t i = 0; i < frames / 2; ++i) {
sf_count_t j = frames - 1 - i; size_t j = frames - 1 - i;
float* frame1 = &data[i * channels]; float* frame1 = &data[i * channels];
float* frame2 = &data[j * channels]; float* frame2 = &data[j * channels];
for (unsigned c = 0; c < channels; ++c) for (unsigned c = 0; c < channels; ++c)
@ -128,18 +137,18 @@ static void reverse_frames(float* data, sf_count_t frames, unsigned channels)
*/ */
class ReverseReader : public BasicSndfileReader { class ReverseReader : public BasicSndfileReader {
public: public:
explicit ReverseReader(SndfileHandle handle); explicit ReverseReader(ST_AudioFile handle);
AudioReaderType type() const override; AudioReaderType type() const override;
size_t readNextBlock(float* buffer, size_t frames) override; size_t readNextBlock(float* buffer, size_t frames) override;
private: private:
sf_count_t position_ {}; uint64_t position_ {};
}; };
ReverseReader::ReverseReader(SndfileHandle handle) ReverseReader::ReverseReader(ST_AudioFile handle)
: BasicSndfileReader(handle) : BasicSndfileReader(std::move(handle))
{ {
position_ = handle.seek(0, SEEK_END); position_ = handle_.get_frame_count();
} }
AudioReaderType ReverseReader::type() const AudioReaderType ReverseReader::type() const
@ -149,16 +158,16 @@ AudioReaderType ReverseReader::type() const
size_t ReverseReader::readNextBlock(float* buffer, size_t frames) size_t ReverseReader::readNextBlock(float* buffer, size_t frames)
{ {
sf_count_t position = position_; uint64_t position = position_;
const unsigned channels = handle_.channels(); const unsigned channels = handle_.get_channels();
const sf_count_t readFrames = std::min<sf_count_t>(frames, position); const uint64_t readFrames = std::min<uint64_t>(frames, position);
if (readFrames <= 0) if (readFrames <= 0)
return false; return false;
position -= readFrames; position -= readFrames;
if (handle_.seek(position, SEEK_SET) != position || if (!handle_.seek(position) ||
handle_.readf(buffer, readFrames) != readFrames) handle_.read_f32(buffer, readFrames) != readFrames)
return false; return false;
position_ = position; position_ = position;
@ -173,7 +182,7 @@ size_t ReverseReader::readNextBlock(float* buffer, size_t frames)
*/ */
class NoSeekReverseReader : public BasicSndfileReader { class NoSeekReverseReader : public BasicSndfileReader {
public: public:
explicit NoSeekReverseReader(SndfileHandle handle); explicit NoSeekReverseReader(ST_AudioFile handle);
AudioReaderType type() const override; AudioReaderType type() const override;
size_t readNextBlock(float* buffer, size_t frames) override; size_t readNextBlock(float* buffer, size_t frames) override;
@ -182,11 +191,11 @@ private:
private: private:
std::unique_ptr<float[]> fileBuffer_; std::unique_ptr<float[]> fileBuffer_;
sf_count_t fileFramesLeft_ { 0 }; uint64_t fileFramesLeft_ { 0 };
}; };
NoSeekReverseReader::NoSeekReverseReader(SndfileHandle handle) NoSeekReverseReader::NoSeekReverseReader(ST_AudioFile handle)
: BasicSndfileReader(handle) : BasicSndfileReader(std::move(handle))
{ {
} }
@ -203,9 +212,9 @@ size_t NoSeekReverseReader::readNextBlock(float* buffer, size_t frames)
fileBuffer = fileBuffer_.get(); fileBuffer = fileBuffer_.get();
} }
const unsigned channels = handle_.channels(); const unsigned channels = handle_.get_channels();
const sf_count_t fileFramesLeft = fileFramesLeft_; const uint64_t fileFramesLeft = fileFramesLeft_;
sf_count_t readFrames = std::min<sf_count_t>(frames, fileFramesLeft); uint64_t readFrames = std::min<uint64_t>(frames, fileFramesLeft);
if (readFrames <= 0) if (readFrames <= 0)
return 0; return 0;
@ -220,15 +229,16 @@ size_t NoSeekReverseReader::readNextBlock(float* buffer, size_t frames)
void NoSeekReverseReader::readWholeFile() void NoSeekReverseReader::readWholeFile()
{ {
const sf_count_t frames = handle_.frames(); const uint64_t frames = handle_.get_frame_count();
const unsigned channels = handle_.channels(); const unsigned channels = handle_.get_channels();
float* fileBuffer = new float[channels * frames]; float* fileBuffer = new float[channels * frames];
fileBuffer_.reset(fileBuffer); fileBuffer_.reset(fileBuffer);
fileFramesLeft_ = handle_.readf(fileBuffer, frames); fileFramesLeft_ = handle_.read_f32(fileBuffer, frames);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if defined(ST_AUDIO_FILE_USE_SNDFILE)
const std::error_category& sndfile_category() const std::error_category& sndfile_category()
{ {
class sndfile_category : public std::error_category { class sndfile_category : public std::error_category {
@ -248,6 +258,26 @@ const std::error_category& sndfile_category()
static const sndfile_category cat; static const sndfile_category cat;
return cat; return cat;
} }
#endif
const std::error_category& undetailed_category()
{
class undetailed_category : public std::error_category {
public:
const char* name() const noexcept override
{
return "undetailed";
}
std::string message(int condition) const override
{
return (condition == 0) ? "success" : "failure";
}
};
static const undetailed_category cat;
return cat;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -260,7 +290,7 @@ public:
unsigned channels() const override { return 1; } unsigned channels() const override { return 1; }
unsigned sampleRate() const override { return 44100; } unsigned sampleRate() const override { return 44100; }
size_t readNextBlock(float*, size_t) override { return 0; } size_t readNextBlock(float*, size_t) override { return 0; }
bool getInstrument(SF_INSTRUMENT* ) override { return false; } bool getInstrument(InstrumentInfo* ) override { return false; }
private: private:
AudioReaderType type_ {}; AudioReaderType type_ {};
@ -268,6 +298,7 @@ private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if defined(ST_AUDIO_FILE_USE_SNDFILE)
static bool formatHasFastSeeking(int format) static bool formatHasFastSeeking(int format)
{ {
bool fast; bool fast;
@ -300,8 +331,9 @@ static bool formatHasFastSeeking(int format)
return fast; return fast;
} }
#endif
static AudioReaderPtr createAudioReaderWithHandle(SndfileHandle handle, bool reverse, std::error_code* ec) static AudioReaderPtr createAudioReaderWithHandle(ST_AudioFile handle, bool reverse, std::error_code* ec)
{ {
AudioReaderPtr reader; AudioReaderPtr reader;
@ -310,30 +342,38 @@ static AudioReaderPtr createAudioReaderWithHandle(SndfileHandle handle, bool rev
if (!handle) { if (!handle) {
if (ec) if (ec)
*ec = std::error_code(handle.error(), sndfile_category()); *ec = std::error_code(1, undetailed_category());
reader.reset(new DummyAudioReader(reverse ? AudioReaderType::Reverse : AudioReaderType::Forward)); reader.reset(new DummyAudioReader(reverse ? AudioReaderType::Reverse : AudioReaderType::Forward));
} }
else if (!reverse) else if (!reverse)
reader.reset(new ForwardReader(handle)); reader.reset(new ForwardReader(std::move(handle)));
else if (formatHasFastSeeking(handle.format())) else {
reader.reset(new ReverseReader(handle)); #if defined(ST_AUDIO_FILE_USE_SNDFILE)
else bool hasFastSeeking = formatHasFastSeeking(handle.get_sndfile_format());
reader.reset(new NoSeekReverseReader(handle)); #else
bool hasFastSeeking = true;
#endif
if (hasFastSeeking)
reader.reset(new ReverseReader(std::move(handle)));
else
reader.reset(new NoSeekReverseReader(std::move(handle)));
}
return reader; return reader;
} }
AudioReaderPtr createAudioReader(const fs::path& path, bool reverse, std::error_code* ec) AudioReaderPtr createAudioReader(const fs::path& path, bool reverse, std::error_code* ec)
{ {
ST_AudioFile handle;
#if defined(_WIN32) #if defined(_WIN32)
SndfileHandle handle(path.wstring().c_str()); handle.open_file_w(path.wstring().c_str());
#else #else
SndfileHandle handle(path.c_str()); handle.open_file(path.c_str());
#endif #endif
return createAudioReaderWithHandle(handle, reverse, ec); return createAudioReaderWithHandle(std::move(handle), reverse, ec);
} }
static AudioReaderPtr createExplicitAudioReaderWithHandle(SndfileHandle handle, AudioReaderType type, std::error_code* ec) static AudioReaderPtr createExplicitAudioReaderWithHandle(ST_AudioFile handle, AudioReaderType type, std::error_code* ec)
{ {
AudioReaderPtr reader; AudioReaderPtr reader;
@ -342,19 +382,19 @@ static AudioReaderPtr createExplicitAudioReaderWithHandle(SndfileHandle handle,
if (!handle) { if (!handle) {
if (ec) if (ec)
*ec = std::error_code(handle.error(), sndfile_category()); *ec = std::error_code(1, undetailed_category());
reader.reset(new DummyAudioReader(type)); reader.reset(new DummyAudioReader(type));
} }
else { else {
switch (type) { switch (type) {
case AudioReaderType::Forward: case AudioReaderType::Forward:
reader.reset(new ForwardReader(handle)); reader.reset(new ForwardReader(std::move(handle)));
break; break;
case AudioReaderType::Reverse: case AudioReaderType::Reverse:
reader.reset(new ReverseReader(handle)); reader.reset(new ReverseReader(std::move(handle)));
break; break;
case AudioReaderType::NoSeekReverse: case AudioReaderType::NoSeekReverse:
reader.reset(new NoSeekReverseReader(handle)); reader.reset(new NoSeekReverseReader(std::move(handle)));
break; break;
} }
} }
@ -364,12 +404,13 @@ static AudioReaderPtr createExplicitAudioReaderWithHandle(SndfileHandle handle,
AudioReaderPtr createExplicitAudioReader(const fs::path& path, AudioReaderType type, std::error_code* ec) AudioReaderPtr createExplicitAudioReader(const fs::path& path, AudioReaderType type, std::error_code* ec)
{ {
ST_AudioFile handle;
#if defined(_WIN32) #if defined(_WIN32)
SndfileHandle handle(path.wstring().c_str()); handle.open_file_w(path.wstring().c_str());
#else #else
SndfileHandle handle(path.c_str()); handle.open_file(path.c_str());
#endif #endif
return createExplicitAudioReaderWithHandle(handle, type, ec); return createExplicitAudioReaderWithHandle(std::move(handle), type, ec);
} }
} // namespace sfz } // namespace sfz

View file

@ -7,16 +7,13 @@
#pragma once #pragma once
#include "absl/types/span.h" #include "absl/types/span.h"
#include "ghc/fs_std.hpp" #include "ghc/fs_std.hpp"
#include <st_audiofile.h>
#include <system_error> #include <system_error>
#include <memory> #include <memory>
#include <cstdio> #include <cstdio>
#if defined(_WIN32)
#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
#include <windows.h>
#endif
#include <sndfile.h>
namespace sfz { namespace sfz {
struct InstrumentInfo;
/** /**
* @brief Designation of a particular kind of audio reader * @brief Designation of a particular kind of audio reader
@ -42,7 +39,7 @@ public:
virtual unsigned channels() const = 0; virtual unsigned channels() const = 0;
virtual unsigned sampleRate() const = 0; virtual unsigned sampleRate() const = 0;
virtual size_t readNextBlock(float* buffer, size_t frames) = 0; virtual size_t readNextBlock(float* buffer, size_t frames) = 0;
virtual bool getInstrument(SF_INSTRUMENT* instrument) = 0; virtual bool getInstrument(InstrumentInfo* instrument) = 0;
}; };
typedef std::unique_ptr<AudioReader> AudioReaderPtr; typedef std::unique_ptr<AudioReader> AudioReaderPtr;

View file

@ -242,7 +242,7 @@ size_t FileMetadataReader::Impl::readRiffData(size_t index, void* buffer, size_t
return fread(buffer, 1, count, stream); return fread(buffer, 1, count, stream);
} }
bool FileMetadataReader::extractRiffInstrument(SF_INSTRUMENT& ins) bool FileMetadataReader::extractRiffInstrument(InstrumentInfo& ins)
{ {
const RiffChunkInfo* riff = riffChunkById(RiffChunkId{'s', 'm', 'p', 'l'}); const RiffChunkInfo* riff = riffChunkById(RiffChunkId{'s', 'm', 'p', 'l'});
if (!riff) if (!riff)
@ -278,16 +278,16 @@ bool FileMetadataReader::extractRiffInstrument(SF_INSTRUMENT& ins)
switch (extractU32(loopOffset + 0x04)) { switch (extractU32(loopOffset + 0x04)) {
default: default:
ins.loops[i].mode = SF_LOOP_NONE; ins.loops[i].mode = LoopNone;
break; break;
case 0: case 0:
ins.loops[i].mode = SF_LOOP_FORWARD; ins.loops[i].mode = LoopForward;
break; break;
case 1: case 1:
ins.loops[i].mode = SF_LOOP_ALTERNATING; ins.loops[i].mode = LoopAlternating;
break; break;
case 2: case 2:
ins.loops[i].mode = SF_LOOP_BACKWARD; ins.loops[i].mode = LoopBackward;
break; break;
} }

View file

@ -5,15 +5,13 @@
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once #pragma once
#if defined(ST_AUDIO_FILE_USE_SNDFILE)
#include <sndfile.h>
#endif
#include "ghc/fs_std.hpp" #include "ghc/fs_std.hpp"
#include <array> #include <array>
#include <memory> #include <memory>
#include <cstdio> #include <cstdio>
#if defined(_WIN32)
#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
#include <windows.h>
#endif
#include <sndfile.h>
namespace sfz { namespace sfz {
@ -26,6 +24,44 @@ struct RiffChunkInfo {
uint32_t length; uint32_t length;
}; };
#if !defined(ST_AUDIO_FILE_USE_SNDFILE)
/**
@brief Loop mode, like SF_LOOP_*
*/
enum LoopMode {
LoopNone,
LoopForward,
LoopBackward,
LoopAlternating,
};
/**
@brief Instrument information, like SF_INSTRUMENT
*/
struct InstrumentInfo {
int gain;
int8_t basenote, detune;
int8_t velocity_lo, velocity_hi;
int8_t key_lo, key_hi;
int loop_count;
struct {
int mode;
uint32_t start;
uint32_t end;
uint32_t count;
} loops[16];
};
#else
enum LoopMode {
LoopNone = SF_LOOP_NONE,
LoopForward = SF_LOOP_FORWARD,
LoopBackward = SF_LOOP_BACKWARD,
LoopAlternating = SF_LOOP_ALTERNATING,
};
struct InstrumentInfo : SF_INSTRUMENT {};
#endif
struct WavetableInfo { struct WavetableInfo {
/** /**
@brief Size of each successive table in the file @brief Size of each successive table in the file
@ -79,7 +115,7 @@ public:
/** /**
* @brief Extract the RIFF 'smpl' data and convert it to sndfile instrument * @brief Extract the RIFF 'smpl' data and convert it to sndfile instrument
*/ */
bool extractRiffInstrument(SF_INSTRUMENT& ins); bool extractRiffInstrument(InstrumentInfo& ins);
/** /**
* @brief Extract the wavetable information from various relevant RIFF chunks * @brief Extract the wavetable information from various relevant RIFF chunks

View file

@ -39,7 +39,6 @@
#include <memory> #include <memory>
#include <thread> #include <thread>
#include <system_error> #include <system_error>
#include <sndfile.hh>
#if defined(_WIN32) #if defined(_WIN32)
#include <windows.h> #include <windows.h>
#else #else
@ -235,7 +234,7 @@ absl::optional<sfz::FileInformation> sfz::FilePool::getFileInformation(const Fil
returnedValue.sampleRate = static_cast<double>(reader->sampleRate()); returnedValue.sampleRate = static_cast<double>(reader->sampleRate());
returnedValue.numChannels = reader->channels(); returnedValue.numChannels = reader->channels();
SF_INSTRUMENT instrumentInfo {}; InstrumentInfo instrumentInfo {};
bool haveInstrumentInfo = reader->getInstrument(&instrumentInfo); bool haveInstrumentInfo = reader->getInstrument(&instrumentInfo);
FileMetadataReader mdReader; FileMetadataReader mdReader;

View file

@ -88,10 +88,10 @@ if(JACK_FOUND AND TARGET Qt5::Widgets)
endif() endif()
add_executable(eq_apply EQ.cpp) add_executable(eq_apply EQ.cpp)
target_link_libraries(eq_apply PRIVATE sfizz::sfizz) target_link_libraries(eq_apply PRIVATE sfizz::sfizz sfizz-sndfile)
add_executable(filter_apply Filter.cpp) add_executable(filter_apply Filter.cpp)
target_link_libraries(filter_apply PRIVATE sfizz::sfizz) target_link_libraries(filter_apply PRIVATE sfizz::sfizz sfizz-sndfile)
add_executable(sfizz_plot_curve PlotCurve.cpp) add_executable(sfizz_plot_curve PlotCurve.cpp)
target_link_libraries(sfizz_plot_curve PRIVATE sfizz::sfizz) target_link_libraries(sfizz_plot_curve PRIVATE sfizz::sfizz)
@ -100,10 +100,10 @@ add_executable(sfizz_plot_wavetables PlotWavetables.cpp)
target_link_libraries(sfizz_plot_wavetables PRIVATE sfizz::sfizz) target_link_libraries(sfizz_plot_wavetables PRIVATE sfizz::sfizz)
add_executable(sfizz_plot_lfo PlotLFO.cpp) add_executable(sfizz_plot_lfo PlotLFO.cpp)
target_link_libraries(sfizz_plot_lfo PRIVATE sfizz::sfizz) target_link_libraries(sfizz_plot_lfo PRIVATE sfizz::sfizz sfizz-sndfile)
add_executable(sfizz_file_instrument FileInstrument.cpp) add_executable(sfizz_file_instrument FileInstrument.cpp)
target_link_libraries(sfizz_file_instrument PRIVATE sfizz::sfizz) target_link_libraries(sfizz_file_instrument PRIVATE sfizz::sfizz sfizz-sndfile)
add_executable(sfizz_file_wavetable FileWavetable.cpp) add_executable(sfizz_file_wavetable FileWavetable.cpp)
target_link_libraries(sfizz_file_wavetable PRIVATE sfizz::sfizz) target_link_libraries(sfizz_file_wavetable PRIVATE sfizz::sfizz)

View file

@ -12,20 +12,21 @@
static const char* modeString(int mode, const char* valueFallback = nullptr) static const char* modeString(int mode, const char* valueFallback = nullptr)
{ {
switch (mode) { switch (mode) {
case SF_LOOP_NONE: case sfz::LoopNone:
return "none"; return "none";
case SF_LOOP_FORWARD: case sfz::LoopForward:
return "forward"; return "forward";
case SF_LOOP_BACKWARD: case sfz::LoopBackward:
return "backward"; return "backward";
case SF_LOOP_ALTERNATING: case sfz::LoopAlternating:
return "alternating"; return "alternating";
default: default:
return valueFallback; return valueFallback;
} }
} }
static void printInstrument(const SF_INSTRUMENT& ins) template <class Instrument>
static void printInstrument(const Instrument& ins)
{ {
printf("Gain: %d\n", ins.gain); printf("Gain: %d\n", ins.gain);
printf("Base note: %d\n", ins.basenote); printf("Base note: %d\n", ins.basenote);
@ -34,7 +35,7 @@ static void printInstrument(const SF_INSTRUMENT& ins)
printf("Key: %d:%d\n", ins.key_lo, ins.key_hi); printf("Key: %d:%d\n", ins.key_lo, ins.key_hi);
printf("Loop count: %d\n", ins.loop_count); printf("Loop count: %d\n", ins.loop_count);
for (int i = 0; i < ins.loop_count; ++i) { for (unsigned i = 0, n = ins.loop_count; i < n; ++i) {
printf("\nLoop %d:\n", i + 1); printf("\nLoop %d:\n", i + 1);
printf("\tMode: %s\n", modeString(ins.loops[i].mode, "(unknown)")); printf("\tMode: %s\n", modeString(ins.loops[i].mode, "(unknown)"));
printf("\tStart: %u\n", ins.loops[i].start); printf("\tStart: %u\n", ins.loops[i].start);
@ -83,18 +84,18 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
SF_INSTRUMENT ins {};
if (method == kMethodRiff) { if (method == kMethodRiff) {
sfz::FileMetadataReader reader; sfz::FileMetadataReader reader;
if (!reader.open(path)) { if (!reader.open(path)) {
fprintf(stderr, "Cannot open file\n"); fprintf(stderr, "Cannot open file\n");
return 1; return 1;
} }
sfz::InstrumentInfo ins {};
if (!reader.extractRiffInstrument(ins)) { if (!reader.extractRiffInstrument(ins)) {
fprintf(stderr, "Cannot get instrument\n"); fprintf(stderr, "Cannot get instrument\n");
return 1; return 1;
} }
printInstrument(ins);
} }
else { else {
SndfileHandle sndFile(path); SndfileHandle sndFile(path);
@ -102,13 +103,13 @@ int main(int argc, char *argv[])
fprintf(stderr, "Cannot open file\n"); fprintf(stderr, "Cannot open file\n");
return 1; return 1;
} }
SF_INSTRUMENT ins {};
if (sndFile.command(SFC_GET_INSTRUMENT, &ins, sizeof(ins)) != 1) { if (sndFile.command(SFC_GET_INSTRUMENT, &ins, sizeof(ins)) != 1) {
fprintf(stderr, "Cannot get instrument\n"); fprintf(stderr, "Cannot get instrument\n");
return 1; return 1;
} }
printInstrument(ins);
} }
printInstrument(ins);
return 0; return 0;
} }