Skip to content

Commit

Permalink
Added discover drivers to sndfile_backend
Browse files Browse the repository at this point in the history
  • Loading branch information
Hrick87 committed Nov 29, 2023
1 parent 2cfea4f commit 739b4bc
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 145 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,107 +11,11 @@
namespace roc {
namespace sndio {

namespace {

// sorted in order of priority
const char* default_drivers[] = {
"waveaudio", // windows
"coreaudio", // macos
"alsa", // linux
"sndio", // openbsd
"oss", // unix
};

const char* driver_renames[][2] = {
{ "waveaudio", "wave" },
{ "coreaudio", "core" },
};

const char* hidden_drivers[] = {
// this format doesn't specify the encoding explicitly
// use its explicit variants like f32, s32, etc
"raw",
// deprecated aliases
"f4",
"f8",
"s1",
"s2",
"s3",
"s4",
"u1",
"u2",
"u3",
"u4",
"sb",
"sw",
"sl",
"ub",
"uw",
// pseudo-formats
"sndfile",
"null",
// unsupported device drivers
"ao",
"ossdsp",
"pulseaudio",
};

const char* map_to_sndfile_driver(const char* driver) {
if (!driver) {
return NULL;
}
for (size_t n = 0; n < ROC_ARRAY_SIZE(driver_renames); n++) {
if (strcmp(driver_renames[n][1], driver) == 0) {
return driver_renames[n][0];
}
}
return driver;
};

bool is_driver_hidden(const char* driver) {
// replicate the behavior of display_supported_formats() from sndfile.c
if (strchr(driver, '/')) {
return true;
}
for (size_t n = 0; n < ROC_ARRAY_SIZE(hidden_drivers); n++) {
if (strcmp(hidden_drivers[n], driver) == 0) {
return true;
}
}
return false;
}

const char* map_from_sndfile_driver(const char* driver) {
if (!driver) {
return NULL;
}
for (size_t n = 0; n < ROC_ARRAY_SIZE(driver_renames); n++) {
if (strcmp(driver_renames[n][0], driver) == 0) {
return driver_renames[n][1];
}
}
return driver;
}

bool is_default_driver(const char* driver) {
for (size_t n = 0; n < ROC_ARRAY_SIZE(default_drivers); n++) {
if (strcmp(driver, default_drivers[n]) == 0) {
return true;
}
}

return false;
}

}


SndfileBackend::SndfileBackend() : first_created_(false) {
roc_log(LogDebug, "sndfile backend: initializing");
}

void SndfileBackend::set_frame_size(core::nanoseconds_t frame_length, const audio::SampleSpec& sample_spec){
//size_t size = sample_spec.ns_2_samples_overall(frame_length);

if (first_created_) {
roc_panic(
Expand All @@ -120,6 +24,29 @@ void SndfileBackend::set_frame_size(core::nanoseconds_t frame_length, const audi
}
}

void SndfileBackend::discover_drivers(core::Array<DriverInfo, MaxDrivers>& driver_list){

SNDFILE * sndfile;
int total_number_of_drivers;
sf_command(sndfile, SFC_GET_FORMAT_MAJOR_COUNT, &total_number_of_drivers, sizeof(int));

SF_FORMAT_INFO format_info;

for (size_t n = 0; n < total_number_of_drivers; n++) {
format_info.format = n;
sf_command (sndfile, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ;

const char* driver = format_info.extension;
if (!driver_list.push_back(DriverInfo(driver, DriverType_File,
DriverFlag_IsDefault
| DriverFlag_SupportsSource
| DriverFlag_SupportsSink,
this))) {
roc_panic("sndfile backend: can't add driver");
}
}
}

IDevice * SndfileBackend::open_device(DeviceType device_type,
DriverType driver_type,
const char* driver,
Expand All @@ -128,14 +55,6 @@ IDevice * SndfileBackend::open_device(DeviceType device_type,
core::IArena& arena){
first_created_ = true;

driver = map_to_sndfile_driver(driver);

if (driver && is_driver_hidden(driver)) {
roc_log(LogDebug, "sndfile backend: driver is not supported: driver=%s path=%s",
driver, path);
return NULL;
}

switch (device_type) {
case DeviceType_Sink: {
core::ScopedPtr<SndfileSink> sink(new (arena) SndfileSink(arena, config), arena);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class SndfileBackend : public IBackend, core::NonCopyable<> {
void set_frame_size(core::nanoseconds_t frame_length,
const audio::SampleSpec& sample_spec);

//! Append supported drivers to the list.
virtual void discover_drivers(core::Array<DriverInfo, MaxDrivers>& driver_list);

//! Create and open a sink or source.
virtual IDevice* open_device(DeviceType device_type,
DriverType driver_type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ SndfileSink::SndfileSink(core::IArena& arena, const Config& config)
return;
}

memset(&sf_info_out_, 0, sizeof(sf_info_out_));
sf_info_out_->samplerate = (int)config.sample_spec.sample_rate();
sf_info_out_->channels = (int)config.sample_spec.num_channels();
sf_info_out_->format = SF_FORMAT_PCM_32;
sf_info_out_ = {0};

valid_ = true;
}
Expand Down Expand Up @@ -105,13 +102,13 @@ audio::SampleSpec SndfileSink::sample_spec() const {
roc_panic("sndfile sink: sample_rate(): non-open output file or device");
}

if (sf_info_out_->channels == 1) {
return audio::SampleSpec(size_t(sf_info_out_->samplerate), audio::ChanLayout_Surround,
if (sf_info_out_.channels == 1) {
return audio::SampleSpec(size_t(sf_info_out_.samplerate), audio::ChanLayout_Surround,
audio::ChanOrder_Smpte, audio::ChanMask_Surround_Mono);
}

if (sf_info_out_->channels == 2) {
return audio::SampleSpec(size_t(sf_info_out_->samplerate), audio::ChanLayout_Surround,
if (sf_info_out_.channels == 2) {
return audio::SampleSpec(size_t(sf_info_out_.samplerate), audio::ChanLayout_Surround,
audio::ChanOrder_Smpte, audio::ChanMask_Surround_Stereo);
}

Expand Down Expand Up @@ -190,44 +187,31 @@ bool SndfileSink::setup_buffer_() {
}

bool SndfileSink::open_(const char* driver, const char* path) {
sndfile_output_ = sf_open(path, SFM_WRITE, sf_info_out_);

if(!sf_format_check (&sf_info_out_))
{
roc_panic("sndfile sink: Invalid encoding");
}

sndfile_output_ = sf_open(path, SFM_WRITE, &sf_info_out_);
if (!sndfile_output_) {
roc_log(LogDebug, "sndfile sink: can't open: driver=%s path=%s", driver, path);
return false;
}

unsigned long in_rate = (unsigned long)sf_info_out_->samplerate;
unsigned long out_rate = (unsigned long)sf_info_out_->samplerate;

if (in_rate != 0 && in_rate != out_rate) {
roc_log(LogError,
"sndfile sink:"
" can't open output file or device with the required sample rate:"
" required_by_output=%lu requested_by_user=%lu",
out_rate, in_rate);
return false;
}
sample_spec_.set_sample_rate((unsigned long)sf_info_out_.samplerate);

sample_spec_.set_sample_rate((unsigned long)sf_info_out_->samplerate);

/*
roc_log(LogInfo,
"sndfile sink:"
" opened: bits=%lu out_rate=%lu in_rate=%lu ch=%lu is_file=%d",
(unsigned long)sndfile_output_->encoding.bits_per_sample, out_rate, in_rate,
(unsigned long)sndfile_output_->signal.channels, (int)is_file_);
*/

roc_log(LogInfo,
"sndfile sink:"
" out_rate=%lu in_rate=%lu ch=%lu is_file=%d",
out_rate, in_rate,
(unsigned long)sf_info_out_->channels, (int)is_file_);
" opened: samplerate=%lu ch=%lu is_file=%d",
(unsigned long)sf_info_out_.samplerate,
(unsigned long)sf_info_out_.channels, (int)is_file_);

return true;
}

void SndfileSink::write_(const int32_t * samples, size_t n_samples) {

if (n_samples > 0) {
if (sf_writef_int(sndfile_output_, samples, (sf_count_t)n_samples) != (sf_count_t)n_samples) {
roc_log(LogError, "sndfile sink: failed to write output buffer");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class SndfileSink : public ISink, public core::NonCopyable<> {
void close_();

SNDFILE * sndfile_output_;
SF_INFO * sf_info_out_;
SF_INFO sf_info_out_;

core::Array<int32_t> buffer_;
size_t buffer_size_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,6 @@ SndfileSource::SndfileSource(core::IArena& arena, const Config& config)
}

sf_info_in_ = {0};
/*
sf_info_in_.samplerate = (int)sample_spec_.sample_rate();
sf_info_in_.channels = (int)sample_spec_.num_channels();
sf_info_in_.frames = frame_length_;
*/

valid_ = true;
}
Expand Down Expand Up @@ -251,7 +246,7 @@ bool SndfileSource::read(audio::Frame& frame) {
n_samples = buffer_size_;
}

n_samples = (size_t)sf_readf_int(sndfile_input_, buffer_data, (sf_count_t)n_samples); //cannot return less than 0 so casting is safe
n_samples = (size_t)sf_readf_int(sndfile_input_, buffer_data, (sf_count_t)n_samples); //Does not return less than 0 so casting is safe

if (n_samples == 0) {
roc_log(LogDebug, "sndfile source: got eof from sndfile");
Expand All @@ -260,7 +255,7 @@ bool SndfileSource::read(audio::Frame& frame) {
}

for (size_t n = 0; n < n_samples; n++) {
frame_data[n] = buffer_data[n];
frame_data[n] = (float)buffer_data[n];
}

frame_data += n_samples;
Expand Down

0 comments on commit 739b4bc

Please sign in to comment.