From f1b544cadd4170b156251a18166510c61e2d9dce Mon Sep 17 00:00:00 2001 From: Hunter Date: Mon, 4 Mar 2024 14:21:45 -0800 Subject: [PATCH] Sndfile min. 1.0.26, extension_table def in cpp, sndfile_backend remove conditions, TODO's added, split up map function --- 3rdparty/SConscript | 4 +- .../roc_sndio/sndfile_backend.cpp | 11 +-- .../roc_sndio/sndfile_extension_table.cpp | 16 ++++ .../roc_sndio/sndfile_extension_table.h | 13 +-- .../target_sndfile/roc_sndio/sndfile_sink.cpp | 84 ++++++++++--------- .../roc_sndio/sndfile_source.cpp | 13 ++- src/tests/roc_sndio/test_backend_sink.cpp | 2 +- src/tests/roc_sndio/test_backend_source.cpp | 2 +- 8 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.cpp diff --git a/3rdparty/SConscript b/3rdparty/SConscript index 2ce2cfe81..25c03f5ae 100644 --- a/3rdparty/SConscript +++ b/3rdparty/SConscript @@ -24,7 +24,7 @@ thirdparty_versions = { 'openfec': '1.4.2.7', 'openssl': '3.0.8', 'pulseaudio': '12.2', - 'sndfile': '1.0.25', + 'sndfile': '1.0.26', 'sox': '14.4.2', 'speexdsp': '1.2.0', @@ -252,7 +252,7 @@ elif 'sndfile' in system_dependencies: if not is_crosscompiling: if not conf.CheckLibWithHeaderExt( 'sndfile', 'sndfile.h', 'C'): - env.Die("libsndfile >= 1.0.25 not found (see 'config.log' for details)") + env.Die("libsndfile >= 1.0.26 not found (see 'config.log' for details)") else: if not conf.CheckLibWithHeaderExt('sndfile', 'sndfile.h', 'C', run=False): env.Die("libsndfile not found (see 'config.log' for details)") diff --git a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_backend.cpp b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_backend.cpp index 7b28177e1..5a1651ab8 100644 --- a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_backend.cpp +++ b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_backend.cpp @@ -40,13 +40,10 @@ void SndfileBackend::discover_drivers(core::Array& drive const char* driver = format_info.extension; - if ((strcmp(format_info.extension, "wav") == 0) - || (strcmp(format_info.extension, "mat") == 0)) { - for (size_t map_index = 0; map_index < ROC_ARRAY_SIZE(file_type_map); - map_index++) { - if (file_type_map[map_index].format_id == format_info.format) { - driver = file_type_map[map_index].driver_name; - } + for (size_t map_index = 0; map_index < ROC_ARRAY_SIZE(file_type_map); + map_index++) { + if (file_type_map[map_index].format_id == format_info.format) { + driver = file_type_map[map_index].driver_name; } } diff --git a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.cpp b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.cpp new file mode 100644 index 000000000..c95c9d213 --- /dev/null +++ b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sndfile_extension_table.h" +#include "sndfile.h" + +FileMap file_type_map[5] = { { SF_FORMAT_MAT4, "mat4", NULL }, + { SF_FORMAT_MAT5, "mat5", NULL }, + { SF_FORMAT_WAV, "wav", "wav" }, + { SF_FORMAT_NIST, "nist", NULL }, + { SF_FORMAT_WAVEX, "wavex", NULL } }; diff --git a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.h b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.h index f34030b7a..661d51a5c 100644 --- a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.h +++ b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.h @@ -7,14 +7,11 @@ */ //! @file roc_sndio/target_sndfile/roc_sndio/sndfile_extension_table.h -//! @brief TODO. +//! @brief Sndfile driver map. #ifndef ROC_SNDIO_SNDFILE_EXTENSION_TABLE_H_ #define ROC_SNDIO_SNDFILE_EXTENSION_TABLE_H_ -#pragma once -#include "sndfile.h" - //! Sndfile driver map. struct FileMap { //! SF_FORMAT ID corresponding to the enum value in sndfile.h @@ -24,10 +21,8 @@ struct FileMap { //! File extension associated with driver and SF_FORMAT if it exists. const char* file_extension; }; -static FileMap file_type_map[5] = { { SF_FORMAT_MAT4, "mat4", NULL }, - { SF_FORMAT_MAT5, "mat5", NULL }, - { SF_FORMAT_WAV, "wav", "wav" }, - { SF_FORMAT_NIST, "nist", NULL }, - { SF_FORMAT_WAVEX, "wavex", NULL } }; + +//! Declare the file_type_map as extern +extern FileMap file_type_map[5]; #endif // ROC_SNDIO_SNDFILE_EXTENSION_TABLE_H_ diff --git a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_sink.cpp b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_sink.cpp index 37aaa8fce..05dea2674 100644 --- a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_sink.cpp +++ b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_sink.cpp @@ -6,7 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#define FORMAT_COUNT 2 // Number of major formats that don't allow for 32 bits; #define BUFFER_SIZE 512 #include "roc_sndio/sndfile_sink.h" @@ -19,7 +18,25 @@ namespace roc { namespace sndio { namespace { -bool map_to_sndfile(const char** driver, const char* path, SF_INFO& sfinfo) { +bool map_to_sub_format(SF_INFO& file_info_, int format_enum) { + // Provides the minimum number of sub formats needed to support all possible major + // formats + int high_to_low_sub_formats[4] = { SF_FORMAT_PCM_24, SF_FORMAT_PCM_16, + SF_FORMAT_DPCM_16 }; + + for (size_t format_attempt = 0; + format_attempt < ROC_ARRAY_SIZE(high_to_low_sub_formats); format_attempt++) { + file_info_.format = format_enum | high_to_low_sub_formats[format_attempt]; + + if (sf_format_check(&file_info_)) { + return true; + } + } + + return false; +} + +bool map_to_sndfile(const char** driver, const char* path, SF_INFO& file_info_) { const char* file_extension; const char* dot = strrchr(path, '.'); @@ -91,38 +108,13 @@ bool map_to_sndfile(const char** driver, const char* path, SF_INFO& sfinfo) { roc_log(LogDebug, "detected file format type `%s'", *driver); - sfinfo.format = format_enum | sfinfo.format; + file_info_.format = format_enum | file_info_.format; - if (sf_format_check(&sfinfo)) { + if (sf_format_check(&file_info_)) { return true; + } else { + return map_to_sub_format(file_info_, format_enum); } - - int temp_format = 0; - - for (int format_attempt = 0; format_attempt < FORMAT_COUNT; format_attempt++) { - if (format_enum == SF_FORMAT_XI) { - sfinfo.channels = 1; - if (format_attempt == 0) { - temp_format = format_enum | SF_FORMAT_DPCM_16; - } else { - temp_format = format_enum | SF_FORMAT_DPCM_8; - } - } else { - if (format_attempt == 0) { - temp_format = format_enum | SF_FORMAT_PCM_24; - } else { - temp_format = format_enum | SF_FORMAT_PCM_16; - } - } - - sfinfo.format = temp_format; - - if (sf_format_check(&sfinfo)) { - return true; - } - } - - return false; } } // namespace @@ -142,24 +134,36 @@ SndfileSink::SndfileSink(core::IArena& arena, const Config& config) } frame_length_ = config.frame_length; - sample_spec_ = config.sample_spec; if (frame_length_ == 0) { roc_log(LogError, "sndfile sink: frame length is zero"); return; } - memset(&file_info_, 0, sizeof(file_info_)); - // file_info_.format = (int)config.sample_spec.pcm_format(); this needs to be - // converted to corresponding enum of sndfile somehow - file_info_.format = SF_FORMAT_PCM_32; - file_info_.channels = (int)config.sample_spec.num_channels(); - file_info_.samplerate = (int)config.sample_spec.sample_rate(); + sample_spec_ = config.sample_spec; + + if (sample_spec_.sample_format() == audio::SampleFormat_Invalid) { + sample_spec_.set_sample_format(audio::SampleFormat_Pcm); + sample_spec_.set_pcm_format(audio::PcmFormat_SInt32); + } + + if (sample_spec_.sample_rate() == 0) { + sample_spec_.set_sample_rate(41000); + } - if (file_info_.samplerate == 0) { - file_info_.samplerate = 48000; + if (!sample_spec_.channel_set().is_valid()) { + sample_spec_.channel_set().set_layout(audio::ChanLayout_Surround); + sample_spec_.channel_set().set_order(audio::ChanOrder_Smpte); + sample_spec_.channel_set().set_channel_range(0, 2, true); } + memset(&file_info_, 0, sizeof(file_info_)); + + // TODO(gh-696): map format from sample_space + file_info_.format = SF_FORMAT_PCM_32; + file_info_.channels = (int)sample_spec_.num_channels(); + file_info_.samplerate = (int)sample_spec_.sample_rate(); + valid_ = true; } diff --git a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_source.cpp b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_source.cpp index e7d793742..b8ffaf674 100644 --- a/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_source.cpp +++ b/src/internal_modules/roc_sndio/target_sndfile/roc_sndio/sndfile_source.cpp @@ -181,9 +181,9 @@ bool SndfileSource::read(audio::Frame& frame) { } audio::sample_t* frame_data = frame.raw_samples(); - size_t num_channels = (size_t)file_info_.channels; + // size_t num_channels = (size_t)file_info_.channels; sf_count_t frame_left = (sf_count_t)frame.num_raw_samples(); - size_t samples_per_ch = frame.num_raw_samples() / num_channels; + // size_t samples_per_ch = frame.num_raw_samples() / num_channels; sf_count_t n_samples = sf_read_float(file_, frame_data, frame_left); if (sf_error(file_) != 0) { @@ -191,14 +191,13 @@ bool SndfileSource::read(audio::Frame& frame) { roc_panic("sndfile source: sf_read_float() failed: %s", sf_strerror(file_)); } - if (n_samples < frame_left) { + if (n_samples == 0) { eof_ = true; } - if ((size_t)n_samples < samples_per_ch) { - memset(frame.raw_samples() + (size_t)n_samples * num_channels, 0, - (samples_per_ch - (size_t)n_samples) * num_channels - * sizeof(audio::sample_t)); + if (n_samples < frame_left && n_samples != 0) { + memset(frame.raw_samples() + (size_t)n_samples, 0, + (size_t)(frame_left - n_samples) * sizeof(audio::sample_t)); } return !eof_; diff --git a/src/tests/roc_sndio/test_backend_sink.cpp b/src/tests/roc_sndio/test_backend_sink.cpp index a0bafc589..0ce5867a1 100644 --- a/src/tests/roc_sndio/test_backend_sink.cpp +++ b/src/tests/roc_sndio/test_backend_sink.cpp @@ -53,7 +53,7 @@ TEST_GROUP(backend_sink) { } }; -TEST(backend_sink, noop) { +TEST(backend_sink, write_open) { for (size_t n_backend = 0; n_backend < BackendMap::instance().num_backends(); n_backend++) { IBackend& backend = BackendMap::instance().nth_backend(n_backend); diff --git a/src/tests/roc_sndio/test_backend_source.cpp b/src/tests/roc_sndio/test_backend_source.cpp index 6288b7278..61601f475 100644 --- a/src/tests/roc_sndio/test_backend_source.cpp +++ b/src/tests/roc_sndio/test_backend_source.cpp @@ -73,7 +73,7 @@ TEST_GROUP(backend_source) { } }; -TEST(backend_source, noop) { +TEST(backend_source, read_open) { for (size_t n_backend = 0; n_backend < BackendMap::instance().num_backends(); n_backend++) { core::TempFile file("test.wav");