rustedbytes_bytepusher/
audio.rs1use crate::memory::Memory;
2use crate::vm::{AUDIO_BUFFER_SIZE, AUDIO_SAMPLES_PER_SECOND};
3
4use rodio::{Sink, cpal::Sample, source::Source};
5use std::cell::RefCell;
6use std::rc::Rc;
7use std::time::Duration;
8
9#[derive(Clone)]
11pub struct AudioConfig {
12 pub sample_rate: u32,
13 pub channels: u16,
14}
15
16impl Default for AudioConfig {
17 fn default() -> Self {
18 Self {
19 sample_rate: AUDIO_SAMPLES_PER_SECOND, channels: 1,
21 }
22 }
23}
24
25pub struct AudioHandler {
26 config: AudioConfig,
27 memory_register_addr: usize,
28 memory: Rc<RefCell<Memory>>,
29 sink: Rc<RefCell<Sink>>,
30}
31
32impl AudioHandler {
33 pub fn new(
34 memory_register_addr: usize,
35 memory: Rc<RefCell<Memory>>,
36 sink: Rc<RefCell<Sink>>,
37 ) -> Self {
38 Self {
39 config: AudioConfig::default(),
40 memory,
41 memory_register_addr,
42 sink,
43 }
44 }
45
46 pub fn append_samples(&self) {
48 let buffer = self.get_sample_buffer();
49 if buffer.iter().any(|&sample| sample != 0) {
50 let source = SampleBufferSource::new(buffer, self.config.clone());
51 self.sink.borrow_mut().append(source);
52 }
53 }
54
55 pub fn get_sample_buffer(&self) -> [u8; AUDIO_BUFFER_SIZE] {
56 let mem = self.memory.borrow();
57 let audio_addr = (mem.read_16_bits(self.memory_register_addr) as usize) << 8;
58 let sample_buffer = &mem[audio_addr..audio_addr + AUDIO_BUFFER_SIZE];
59 let mut arr = [0u8; AUDIO_BUFFER_SIZE];
60 arr.copy_from_slice(sample_buffer);
61 arr
62 }
63}
64
65pub struct SampleBufferSource<const N: usize> {
67 buffer: [u8; N],
68 index: usize,
69 config: AudioConfig,
70}
71
72impl<const N: usize> SampleBufferSource<N> {
73 pub fn new(buffer: [u8; N], config: AudioConfig) -> Self {
74 Self {
75 buffer,
76 index: 0,
77 config,
78 }
79 }
80
81 fn convert_sample(sample: u8) -> i16 {
83 (sample as i8).to_sample::<i16>()
84 }
85}
86
87impl<const N: usize> Source for SampleBufferSource<N> {
88 fn current_frame_len(&self) -> Option<usize> {
89 let remaining = self.buffer.len().saturating_sub(self.index);
90 if remaining == 0 {
91 None
92 } else {
93 Some(remaining)
94 }
95 }
96
97 fn channels(&self) -> u16 {
98 self.config.channels
99 }
100
101 fn sample_rate(&self) -> u32 {
102 self.config.sample_rate
103 }
104
105 fn total_duration(&self) -> Option<Duration> {
106 let samples = self.buffer.len() as u64;
107 let duration_nanos = (samples * 1_000_000_000) / (self.config.sample_rate as u64);
108 Some(Duration::from_nanos(duration_nanos))
109 }
110}
111
112impl<const N: usize> Iterator for SampleBufferSource<N> {
113 type Item = i16;
114
115 fn next(&mut self) -> Option<Self::Item> {
116 self.buffer.get(self.index).map(|&sample| {
117 self.index += 1;
118 Self::convert_sample(sample)
119 })
120 }
121}