fix audio playback of 8Khz samples, further cut down on clones/copies
This commit is contained in:
+5
-7
@@ -156,18 +156,16 @@ impl AudioSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn process(&mut self, scope: &ProcessScope) -> Result<(), AudioError> {
|
fn process(&mut self, scope: &ProcessScope) -> Result<(), AudioError> {
|
||||||
let mut next_outbuf = match self.sample_src.try_recv() {
|
if let Ok(buf) = self.sample_src.try_recv() {
|
||||||
Ok(buf) => buf,
|
self.output_buf.extend(buf);
|
||||||
Err(tokio::sync::mpsc::error::TryRecvError::Empty) => return Ok(()),
|
}
|
||||||
Err(err) => return Err(err.into())
|
|
||||||
};
|
|
||||||
self.output_buf.append(&mut next_outbuf);
|
|
||||||
|
|
||||||
if self.port.connected_count()? > 0 && !self.output_buf.is_empty() {
|
if self.port.connected_count()? > 0 && !self.output_buf.is_empty() {
|
||||||
let outbuf = self.port.as_mut_slice(scope);
|
let outbuf = self.port.as_mut_slice(scope);
|
||||||
let mut next_segment: Vec<f32> = self.output_buf.drain(0..(outbuf.len()).min(self.output_buf.len())).collect();
|
let mut next_segment: Vec<f32> = self.output_buf.drain(..(outbuf.len()).min(self.output_buf.len())).collect();
|
||||||
let underrun = outbuf.len() - next_segment.len();
|
let underrun = outbuf.len() - next_segment.len();
|
||||||
if underrun > 0 {
|
if underrun > 0 {
|
||||||
|
log::warn!("Audio stream underrun: {} samples", underrun);
|
||||||
next_segment.extend(std::iter::repeat_n(0., underrun));
|
next_segment.extend(std::iter::repeat_n(0., underrun));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-6
@@ -41,13 +41,23 @@ pub async fn start_sfx(audio_sink: AudioOutStream) -> SfxControl {
|
|||||||
.probe(&hint, mss, fmt_opts, meta_opts)
|
.probe(&hint, mss, fmt_opts, meta_opts)
|
||||||
.expect("Unsupported audio format");
|
.expect("Unsupported audio format");
|
||||||
let track = format.default_track(TrackType::Audio).expect("No audio track");
|
let track = format.default_track(TrackType::Audio).expect("No audio track");
|
||||||
|
let track_id = track.id;
|
||||||
let dec_opts = Default::default();
|
let dec_opts = Default::default();
|
||||||
let mut decoder = symphonia::default::get_codecs()
|
let mut decoder = symphonia::default::get_codecs()
|
||||||
.make_audio_decoder(
|
.make_audio_decoder(
|
||||||
track.codec_params.as_ref().expect("codec params missing").audio().unwrap(),
|
track.codec_params.as_ref().expect("codec params missing").audio().unwrap(),
|
||||||
&dec_opts
|
&dec_opts
|
||||||
).expect("Unsupported audio codec");
|
).expect("Unsupported audio codec");
|
||||||
|
|
||||||
|
let sample_rate = decoder.codec_params().sample_rate.unwrap();
|
||||||
|
let channel_num = decoder.codec_params().channels.as_ref().unwrap().count();
|
||||||
|
log::debug!("Resampling {} -> {}", sample_rate, audio_sink.sample_rate);
|
||||||
|
// Our resampler works on a mono input
|
||||||
|
let mut bitrate_resample = resampler::ResamplerFir::new_from_hz(channel_num, sample_rate, audio_sink.sample_rate, Default::default(), Default::default());
|
||||||
|
|
||||||
log::debug!("Starting stream");
|
log::debug!("Starting stream");
|
||||||
|
let mut audio_out_buf = vec![];
|
||||||
|
let mut channel_bufs: Vec<f32> = vec![];
|
||||||
loop {
|
loop {
|
||||||
let packet = match format.next_packet() {
|
let packet = match format.next_packet() {
|
||||||
Ok(Some(packet)) => packet,
|
Ok(Some(packet)) => packet,
|
||||||
@@ -55,19 +65,40 @@ pub async fn start_sfx(audio_sink: AudioOutStream) -> SfxControl {
|
|||||||
Err(err) => panic!()
|
Err(err) => panic!()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if packet.track_id != track_id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
match decoder.decode_ref(&packet.as_packet_ref()) {
|
match decoder.decode_ref(&packet.as_packet_ref()) {
|
||||||
Ok(samples) => {
|
Ok(samples) => {
|
||||||
let mut channel_bufs: Vec<f32> = vec![];
|
channel_bufs.resize(samples.samples_interleaved(), 0.);
|
||||||
samples.copy_to_vec_interleaved(&mut channel_bufs);
|
samples.copy_to_slice_interleaved(&mut channel_bufs);
|
||||||
let audio_out_buf: Vec<f32> = channel_bufs.windows(samples.byte_len_per_plane()).map(|channels| {
|
|
||||||
|
let mut resampled = [0.; 2048];
|
||||||
|
let (_, write_count) = bitrate_resample.resample(&channel_bufs, &mut resampled).unwrap();
|
||||||
|
|
||||||
|
// First we convert the audio feed from stereo down to mono by simple average
|
||||||
|
// TODO: This should be something smarter, like a saturating add..?
|
||||||
|
let mono_stream = resampled[..write_count].chunks(channel_num).map(|channels| {
|
||||||
let total_volume = channels.iter().cloned().reduce(|a, b| a + b).unwrap_or_default();
|
let total_volume = channels.iter().cloned().reduce(|a, b| a + b).unwrap_or_default();
|
||||||
total_volume / (channels.len() as f32)
|
total_volume / (channel_num as f32)
|
||||||
}).collect();
|
});
|
||||||
audio_sink.sink.send(audio_out_buf).await.unwrap();
|
|
||||||
|
// Then we write out the resampled audio to our staging buffer
|
||||||
|
audio_out_buf.extend(mono_stream);
|
||||||
|
|
||||||
|
// Once we have 1024 samples (jack default, I guess), we send it to the audio output
|
||||||
|
if audio_out_buf.len() >= 1024 {
|
||||||
|
audio_sink.sink.send(audio_out_buf).await.unwrap();
|
||||||
|
audio_out_buf = vec![];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Err(err) => panic!()
|
Err(err) => panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !audio_out_buf.is_empty() {
|
||||||
|
audio_sink.sink.send(audio_out_buf).await.unwrap();
|
||||||
|
}
|
||||||
log::debug!("Playback complete");
|
log::debug!("Playback complete");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user