1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use crate::datatype::Datatype;
use libsoxr_sys as soxr;
pub struct RuntimeSpec {
runtime_spec: soxr::soxr_runtime_spec_t,
}
impl RuntimeSpec {
pub fn new(num_threads: u32) -> RuntimeSpec {
RuntimeSpec {
runtime_spec: unsafe { soxr::soxr_runtime_spec(num_threads) },
}
}
pub fn soxr_spec(&self) -> &soxr::soxr_runtime_spec_t {
&self.runtime_spec
}
}
pub struct IOSpec {
io_spec: soxr::soxr_io_spec_t,
}
impl IOSpec {
pub fn new(input_type: Datatype, output_type: Datatype) -> IOSpec {
let itype = input_type.to_soxr_datatype();
let otype = output_type.to_soxr_datatype();
IOSpec {
io_spec: unsafe { soxr::soxr_io_spec(itype, otype) },
}
}
pub fn soxr_spec(&self) -> &soxr::soxr_io_spec_t {
&self.io_spec
}
}
bitflags! {
pub struct QualityFlags: std::os::raw::c_ulong {
const ROLLOFF_SMALL = soxr::SOXR_ROLLOFF_SMALL as std::os::raw::c_ulong;
const ROLLOFF_MEDIUM = soxr::SOXR_ROLLOFF_MEDIUM as std::os::raw::c_ulong;
const ROLLOFF_NONE = soxr::SOXR_ROLLOFF_NONE as std::os::raw::c_ulong;
const HI_PREC_CLOCK = soxr::SOXR_HI_PREC_CLOCK as std::os::raw::c_ulong;
const VR = soxr::SOXR_VR as std::os::raw::c_ulong;
}
}
pub enum QualityRecipe {
Quick,
Low,
Medium,
High,
VeryHigh,
}
impl QualityRecipe {
pub fn to_recipe(&self) -> u32 {
match self {
QualityRecipe::Quick => soxr::SOXR_QQ,
QualityRecipe::Low => soxr::SOXR_LQ,
QualityRecipe::Medium => soxr::SOXR_MQ,
QualityRecipe::High => soxr::SOXR_HQ,
QualityRecipe::VeryHigh => soxr::SOXR_VHQ,
}
}
}
#[derive(Debug)]
pub struct QualitySpec {
quality_spec: soxr::soxr_quality_spec_t,
}
impl QualitySpec {
pub fn new(quality: &QualityRecipe, flags: QualityFlags) -> QualitySpec {
QualitySpec {
quality_spec: unsafe {
soxr::soxr_quality_spec(
std::os::raw::c_ulong::from(quality.to_recipe()),
flags.bits as std::os::raw::c_ulong,
)
},
}
}
pub fn soxr_spec(&self) -> &soxr::soxr_quality_spec_t {
&self.quality_spec
}
}
#[test]
fn test_create_io_spec() {
let spec = IOSpec::new(Datatype::Float32I, Datatype::Int32I);
assert_eq!(
Datatype::Float32I.to_soxr_datatype() as isize,
spec.io_spec.itype as isize
);
assert_eq!(
Datatype::Int32I.to_soxr_datatype() as isize,
spec.io_spec.otype as isize
);
}
#[test]
fn test_create_runtime_spec() {
let spec = RuntimeSpec::new(16);
assert_eq!(16, spec.runtime_spec.num_threads);
}
#[test]
fn test_create_quality_spec() {
let spec = QualitySpec::new(
&QualityRecipe::High,
QualityFlags::ROLLOFF_SMALL | QualityFlags::ROLLOFF_MEDIUM,
);
let result = QualityFlags::from_bits_truncate(spec.soxr_spec().flags);
assert!(result.contains(QualityFlags::ROLLOFF_SMALL | QualityFlags::ROLLOFF_MEDIUM));
}