Voice Rework -- Events, Track Queues (#806)
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.
This commit is contained in:
69
src/input/container/mod.rs
Normal file
69
src/input/container/mod.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user