Skip to content

Commit

Permalink
Passes all unit tests, moved test_pump/test_helpers, moved extension …
Browse files Browse the repository at this point in the history
…detector to sndfile_sink
  • Loading branch information
Hrick87 committed Dec 10, 2023
1 parent 87a6679 commit abe16df
Show file tree
Hide file tree
Showing 8 changed files with 606 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,54 +11,6 @@
namespace roc {
namespace sndio {

namespace{

const char* drivers[] = {
"aiff",
"au",
"avr",
"caf",
"htk",
"iff",
"mat",
"mpc",
"paf",
"pvf",
"snd",
"raw",
"rf64",
"sd2",
"sds",
"sf",
"voc",
"w64",
"wav",
"wve",
"xi",
};

const char * detect_file_extension(const char* path){
const char *dot = strrchr(path, '.');
if(!dot || dot == path){
return NULL;
}
roc_log(LogInfo, "detected file format type `%s'", dot + 1);
return dot + 1;
}

bool check_file_extension_support(const char* file_extension){
for(size_t sndfile_extension = 0; sndfile_extension < ROC_ARRAY_SIZE(drivers); sndfile_extension++){
if(strcmp(drivers[sndfile_extension], file_extension) == 0){

return true;
}
}

return false;
}

}

SndfileBackend::SndfileBackend() : first_created_(false) {

roc_log(LogDebug, "sndfile backend: initializing");
Expand Down Expand Up @@ -104,17 +56,6 @@ IDevice * SndfileBackend::open_device(DeviceType device_type,
return NULL;
}

if(!driver && path){
if(!(driver = detect_file_extension(path))){
roc_panic("sndfile backend: file format could not be detected");
}
}

//possibly redundant?
if(!check_file_extension_support(driver)){
roc_panic("sndfile backend: file format is not supported");
}

first_created_ = true;

switch (device_type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace roc {
namespace sndio {
namespace {

struct {
struct FileMap{
const char * format_cstring;
int format_enum;
} file_type_map[]={
Expand Down Expand Up @@ -46,7 +46,32 @@ namespace {
{"xi", SF_FORMAT_XI},
};

int map_to_sndfile(SF_INFO sfinfo, const char* driver, int &bits){
bool detect_file_extension(const char **driver, const char* path){
const char *dot = strrchr(path, '.');

if(!dot || dot == path){
return false;
}

const char *file_extension = dot + 1;
bool found_extension = false;

for(size_t sndfile_extension = 0; sndfile_extension < ROC_ARRAY_SIZE(file_type_map); sndfile_extension++){
if(strcmp(file_type_map[sndfile_extension].format_cstring, file_extension) == 0){
found_extension = true;
}
}

if(!found_extension){
return false;
}

roc_log(LogInfo, "detected file format type `%s'", file_extension);
*driver = file_extension;
return true;
}

bool map_to_sndfile(SF_INFO &sfinfo, const char* driver, int &bits){
int format = 0;
for(size_t format_struct_index = 0; format_struct_index < sizeof(file_type_map) / sizeof(file_type_map[0]); format_struct_index++){
if(strcmp(file_type_map[format_struct_index].format_cstring, driver) == 0){
Expand All @@ -56,15 +81,15 @@ namespace {
}

if(format == 0){
roc_panic("sndfile sink: Cannot map driver name to sndfile format");
return false;
}

sfinfo.format = format | sfinfo.format;

if(sf_format_check(&sfinfo))
{
bits = 32;
return sfinfo.format;
return true;
}

int temp_format = 0;
Expand Down Expand Up @@ -96,11 +121,11 @@ namespace {
sfinfo.format = temp_format;

if(sf_format_check(&sfinfo)){
return sfinfo.format;
return true;
}
}

roc_panic("sndfile sink: Cannot find valid subtype format for major format type");
return false;
}

}
Expand Down Expand Up @@ -298,11 +323,22 @@ bool SndfileSink::open_(const char* driver, const char* path) {

unsigned long out_rate = (unsigned long)sf_info_out_.samplerate;

if(!driver){
if(!detect_file_extension(&driver, path)){
roc_log(LogDebug, "sndfile sink: Driver extension could not be detected");
return false;
}
}

int bits = 0;
sf_info_out_.format = map_to_sndfile(sf_info_out_, driver, bits);
if(!map_to_sndfile(sf_info_out_, driver, bits)){
roc_log(LogDebug, "sndfile sink: Cannot find valid subtype format for major format type");
return false;
}

if(!sf_format_check(&sf_info_out_)){
roc_panic("sndfile sink: sf_format_check detected invalid format parameters");
roc_log(LogDebug, "sndfile sink: can't open: driver=%s path=%s", driver, path);
return false;
}

sndfile_output_ = sf_open(path, SFM_WRITE, &sf_info_out_);
Expand Down
80 changes: 80 additions & 0 deletions src/tests/roc_sndio/target_sndfile/test_sndfile_sink.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2015 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 <CppUTest/TestHarness.h>

#include "roc_core/heap_arena.h"
#include "roc_core/temp_file.h"
#include "roc_sndio/sndfile_sink.h"

namespace roc {
namespace sndio {

namespace {

enum { FrameSize = 500, SampleRate = 44100, ChMask = 0x3 };

core::HeapArena arena;

} // namespace

TEST_GROUP(sndfile_sink) {
Config sink_config;

void setup() {
sink_config.sample_spec = audio::SampleSpec(
SampleRate, audio::ChanLayout_Surround, audio::ChanOrder_Smpte, ChMask);

sink_config.frame_length = FrameSize * core::Second
/ core::nanoseconds_t(sink_config.sample_spec.sample_rate()
* sink_config.sample_spec.num_channels());
}
};

TEST(sndfile_sink, noop) {
SndfileSink sndfile_sink(arena, sink_config);
}

TEST(sndfile_sink, error) {

SndfileSink sndfile_sink(arena, sink_config);

CHECK(!sndfile_sink.open(NULL, "/bad/file"));
}

TEST(sndfile_sink, has_clock) {

SndfileSink sndfile_sink(arena, sink_config);

core::TempFile file("test.wav");
CHECK(sndfile_sink.open(NULL, file.path()));
CHECK(!sndfile_sink.has_clock());
}

TEST(sndfile_sink, sample_rate_auto) {

sink_config.sample_spec.set_sample_rate(0);
SndfileSink sndfile_sink(arena, sink_config);

core::TempFile file("test.wav");
CHECK(sndfile_sink.open(NULL, file.path()));
CHECK(sndfile_sink.sample_spec().sample_rate() != 0);
}

TEST(sndfile_sink, sample_rate_force) {

sink_config.sample_spec.set_sample_rate(SampleRate);
SndfileSink sndfile_sink(arena, sink_config);

core::TempFile file("test.wav");
CHECK(sndfile_sink.open(NULL, file.path()));
CHECK(sndfile_sink.sample_spec().sample_rate() == SampleRate);
}

} // namespace sndio
} // namespace roc
Loading

0 comments on commit abe16df

Please sign in to comment.