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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use std::fs::File;
use std::path::Path;
use symphonia::core::audio::Signal;
use symphonia::core::audio::{AudioBuffer as SymphoniaAudioBuffer, AudioBufferRef};
use symphonia::core::formats::FormatOptions;
use symphonia::core::io::MediaSourceStream;
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::{Hint, ProbeResult};
use symphonia::default::get_probe;
use thiserror::Error;
use augmented_audio_metrics as metrics;
#[derive(Error, Debug)]
pub enum AudioFileError {
#[error("Failed to decode input file")]
DecodeError(#[from] symphonia::core::errors::Error),
#[error("Failed to read input file")]
FileReadError(#[from] std::io::Error),
#[error("Failed to open read stream")]
OpenStreamError,
}
pub fn default_read_audio_file(input_audio_path: &str) -> Result<ProbeResult, AudioFileError> {
log::info!(
"Trying to open and probe audio file at {}",
input_audio_path
);
let mut hint = Hint::new();
let media_source = {
let audio_input_path = Path::new(input_audio_path);
let _ = try_set_audio_file_hint(&mut hint, audio_input_path);
File::open(audio_input_path)?
};
let audio_file = MediaSourceStream::new(Box::new(media_source), Default::default());
let format_opts: FormatOptions = Default::default();
let metadata_opts: MetadataOptions = Default::default();
let audio_file = get_probe().format(&hint, audio_file, &format_opts, &metadata_opts)?;
Ok(audio_file)
}
fn try_set_audio_file_hint(hint: &mut Hint, audio_input_path: &Path) -> Option<()> {
let extension = audio_input_path.extension()?;
let extension_str = extension.to_str()?;
hint.with_extension(extension_str);
Some(())
}
pub fn read_file_contents(
audio_file: &mut ProbeResult,
) -> Result<SymphoniaAudioBuffer<f32>, AudioFileError> {
let audio_file_stream = audio_file
.format
.default_track()
.ok_or(AudioFileError::OpenStreamError)?;
let mut decoder = symphonia::default::get_codecs()
.make(&audio_file_stream.codec_params, &Default::default())?;
let audio_file_stream_id = audio_file_stream.id;
let mut audio_buffer: Vec<SymphoniaAudioBuffer<f32>> = Vec::new();
metrics::time("AudioFileProcessor - Reading file packages", || loop {
match audio_file.format.next_packet().ok() {
None => break,
Some(packet) => {
if packet.track_id() != audio_file_stream_id {
break;
}
let decoded = decoder.decode(&packet).ok();
match decoded {
Some(AudioBufferRef::F32(packet_buffer)) => {
audio_buffer.push(packet_buffer.into_owned());
}
_ => break,
}
}
}
});
Ok(metrics::time(
"AudioFileProcessor - Concatenating packets",
|| concat_buffers(audio_buffer),
))
}
pub fn convert_audio_file_sample_rate(
audio_file_contents: &SymphoniaAudioBuffer<f32>,
output_rate: f32,
channel_number: usize,
) -> Vec<f32> {
let audio_file_channel = audio_file_contents.chan(channel_number);
let input_rate = audio_file_contents.spec().rate as f32;
let audio_file_duration = audio_file_channel.len() as f32 / input_rate;
let output_size = (audio_file_duration * output_rate).ceil() as usize;
let mut channel = Vec::new();
channel.resize(output_size, 0.0);
let audio_file_channel = audio_file_contents.chan(channel_number);
log::info!(
"Converting sample_rate channel={} input_rate={} output_rate={}",
channel_number,
input_rate,
output_rate
);
augmented_convert_sample_rate::convert_sample_rate(
input_rate,
audio_file_channel,
output_rate,
channel.as_mut_slice(),
);
channel
}
fn concat_buffers(buffers: Vec<SymphoniaAudioBuffer<f32>>) -> SymphoniaAudioBuffer<f32> {
let duration = buffers
.iter()
.map(|buffer| buffer.chan(0).len() as u64)
.sum();
let mut output = SymphoniaAudioBuffer::new(duration, *buffers[0].spec());
let _ = output.fill(|_, _| Ok(()));
let mut output_cursor = 0;
for buffer in buffers {
let mut channel_size = 0;
for channel_num in 0..2 {
let mut cursor = output_cursor;
let output_channel = output.chan_mut(channel_num);
let channel = buffer.chan(channel_num);
channel_size = channel.len();
for sample in channel {
output_channel[cursor] = *sample;
cursor += 1;
}
}
output_cursor += channel_size;
}
output
}