This implements a proof-of-concept for an improved audio frontend. The largest change is the introduction of events and event handling: both by time elapsed and by track events, such as ending or looping. Following on from this, the library now includes a basic, event-driven track queue system (which people seem to ask for unusually often). A new sample, `examples/13_voice_events`, demonstrates both the `TrackQueue` system and some basic events via the `~queue` and `~play_fade` commands. Locks are removed from around the control of `Audio` objects, which should allow the backend to be moved to a more granular futures-based backend solution in a cleaner way.
70 lines
1.7 KiB
Rust
70 lines
1.7 KiB
Rust
mod frame;
|
|
|
|
pub use frame::*;
|
|
|
|
use super::CodecType;
|
|
use byteorder::{LittleEndian, ReadBytesExt};
|
|
use std::{
|
|
fmt::Debug,
|
|
io::{Read, Result as IoResult},
|
|
mem,
|
|
};
|
|
|
|
/// Marker and state for decoding framed input files.
|
|
#[non_exhaustive]
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum Container {
|
|
/// Raw, unframed input.
|
|
Raw,
|
|
/// Framed input, beginning with a JSON header.
|
|
///
|
|
/// Frames have the form `{ len: i16, payload: [u8; len]}`.
|
|
Dca {
|
|
/// Byte index of the first frame after the JSON header.
|
|
first_frame: usize,
|
|
},
|
|
}
|
|
|
|
impl Container {
|
|
/// Tries to read the header of the next frame from an input stream.
|
|
pub fn next_frame_length(
|
|
&mut self,
|
|
mut reader: impl Read,
|
|
input: CodecType,
|
|
) -> IoResult<Frame> {
|
|
use Container::*;
|
|
|
|
match self {
|
|
Raw => Ok(Frame {
|
|
header_len: 0,
|
|
frame_len: input.sample_len(),
|
|
}),
|
|
Dca { .. } => reader.read_i16::<LittleEndian>().map(|frame_len| Frame {
|
|
header_len: mem::size_of::<i16>(),
|
|
frame_len: frame_len.max(0) as usize,
|
|
}),
|
|
}
|
|
}
|
|
|
|
/// Tries to seek on an input directly using sample length, if the input
|
|
/// is unframed.
|
|
pub fn try_seek_trivial(&self, input: CodecType) -> Option<usize> {
|
|
use Container::*;
|
|
|
|
match self {
|
|
Raw => Some(input.sample_len()),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
/// Returns the byte index of the first frame containing audio payload data.
|
|
pub fn input_start(&self) -> usize {
|
|
use Container::*;
|
|
|
|
match self {
|
|
Raw => 0,
|
|
Dca { first_frame } => *first_frame,
|
|
}
|
|
}
|
|
}
|