pub mod decoder;
pub mod encoder;
use crate::{FrameRate, Timecode, TimecodeError, TimecodeReader, TimecodeWriter};
#[derive(Debug, Clone)]
pub struct LtcReaderConfig {
pub sample_rate: u32,
pub frame_rate: FrameRate,
pub min_amplitude: f32,
pub max_speed: f32,
}
impl Default for LtcReaderConfig {
fn default() -> Self {
LtcReaderConfig {
sample_rate: 48000,
frame_rate: FrameRate::Fps25,
min_amplitude: 0.1,
max_speed: 2.0,
}
}
}
pub struct LtcReader {
decoder: decoder::LtcDecoder,
frame_rate: FrameRate,
}
impl LtcReader {
pub fn new(config: LtcReaderConfig) -> Self {
LtcReader {
decoder: decoder::LtcDecoder::new(
config.sample_rate,
config.frame_rate,
config.min_amplitude,
),
frame_rate: config.frame_rate,
}
}
pub fn process_samples(&mut self, samples: &[f32]) -> Result<Option<Timecode>, TimecodeError> {
self.decoder.process_samples(samples)
}
pub fn reset(&mut self) {
self.decoder.reset();
}
pub fn sync_confidence(&self) -> f32 {
self.decoder.sync_confidence()
}
}
impl TimecodeReader for LtcReader {
fn read_timecode(&mut self) -> Result<Option<Timecode>, TimecodeError> {
Ok(self.decoder.last_decoded_timecode())
}
fn frame_rate(&self) -> FrameRate {
self.frame_rate
}
fn is_synchronized(&self) -> bool {
self.decoder.is_synchronized()
}
}
#[derive(Debug, Clone)]
pub struct LtcWriterConfig {
pub sample_rate: u32,
pub frame_rate: FrameRate,
pub amplitude: f32,
}
impl Default for LtcWriterConfig {
fn default() -> Self {
LtcWriterConfig {
sample_rate: 48000,
frame_rate: FrameRate::Fps25,
amplitude: 0.5,
}
}
}
pub struct LtcWriter {
encoder: encoder::LtcEncoder,
frame_rate: FrameRate,
}
impl LtcWriter {
pub fn new(config: LtcWriterConfig) -> Self {
LtcWriter {
encoder: encoder::LtcEncoder::new(
config.sample_rate,
config.frame_rate,
config.amplitude,
),
frame_rate: config.frame_rate,
}
}
pub fn encode_frame(&mut self, timecode: &Timecode) -> Result<Vec<f32>, TimecodeError> {
self.encoder.encode_frame(timecode)
}
pub fn reset(&mut self) {
self.encoder.reset();
}
}
impl TimecodeWriter for LtcWriter {
fn write_timecode(&mut self, timecode: &Timecode) -> Result<(), TimecodeError> {
let _samples = self.encode_frame(timecode)?;
Ok(())
}
fn frame_rate(&self) -> FrameRate {
self.frame_rate
}
fn flush(&mut self) -> Result<(), TimecodeError> {
Ok(())
}
}
pub(crate) mod constants {
pub const SYNC_WORD: u16 = 0x3FFD;
pub const BITS_PER_FRAME: usize = 80;
pub const DATA_BITS: usize = 64;
pub const SYNC_BITS: usize = 16;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ltc_reader_creation() {
let config = LtcReaderConfig::default();
let _reader = LtcReader::new(config);
}
#[test]
fn test_ltc_writer_creation() {
let config = LtcWriterConfig::default();
let _writer = LtcWriter::new(config);
}
#[test]
fn test_sync_word() {
assert_eq!(constants::SYNC_WORD, 0x3FFD);
assert_eq!(constants::BITS_PER_FRAME, 80);
}
}