1use crate::decode::{AdpcmStream, Pcm8Stream};
2use crate::envelope::AdsrSpec;
3use crate::stream::SigmaDeltaBitStream;
4use crate::synth::{FmVoice, ToneParams, ToneVoice, Waveform, WavetableVoice};
5use crate::tier::EffectKind;
6
7#[derive(Debug, Clone, Copy)]
9pub enum VoiceSource<'a> {
10 Idle,
11 Tone(ToneVoice),
12 Wavetable(WavetableVoice<'a>),
13 Fm(FmVoice),
14 Pcm8(Pcm8Stream<'a>),
15 Adpcm(AdpcmStream<'a>),
16 SigmaDeltaBits(SigmaDeltaBitStream<'a>),
17}
18
19impl<'a> VoiceSource<'a> {
20 pub const fn idle() -> Self {
21 Self::Idle
22 }
23
24 pub fn stop(&mut self) {
25 *self = Self::Idle;
26 }
27
28 pub fn is_active(&self) -> bool {
29 match self {
30 Self::Idle => false,
31 Self::Tone(v) => v.is_active(),
32 Self::Wavetable(v) => v.is_active(),
33 Self::Fm(v) => v.is_active(),
34 Self::Pcm8(v) => !v.is_done(),
35 Self::Adpcm(v) => !v.is_done(),
36 Self::SigmaDeltaBits(v) => !v.is_done(),
37 }
38 }
39
40 pub fn carrier_hz(&self, sample_rate_hz: u32) -> Option<u32> {
42 match self {
43 Self::Tone(v) => {
44 let hz = v.carrier_hz(sample_rate_hz);
45 if hz == 0 { None } else { Some(hz) }
46 }
47 _ => None,
48 }
49 }
50
51 pub fn next_raw_sample(&mut self) -> Option<i8> {
52 match self {
53 Self::Idle => None,
54 Self::Tone(v) => v.next_sample(),
55 Self::Wavetable(v) => v.next_sample(),
56 Self::Fm(v) => v.next_sample(),
57 Self::Pcm8(v) => v.next_sample(),
58 Self::Adpcm(v) => v.next_sample(),
59 Self::SigmaDeltaBits(v) => v.next_sample(),
60 }
61 }
62
63 pub fn start_tone(
64 &mut self,
65 freq_hz: u32,
66 duration_ms: u16,
67 waveform: Waveform,
68 sample_rate_hz: u32,
69 ) {
70 let mut voice = ToneVoice::new();
71 voice.start(
72 ToneParams {
73 freq_hz,
74 duration_ms,
75 waveform,
76 adsr: AdsrSpec::click(),
77 },
78 sample_rate_hz,
79 );
80 *self = Self::Tone(voice);
81 }
82
83 pub fn start_wavetable(&mut self, table: &'a [u8], freq_hz: u32, sample_rate_hz: u32) {
84 let mut voice = WavetableVoice::new(table);
85 voice.start(freq_hz, sample_rate_hz);
86 *self = Self::Wavetable(voice);
87 }
88
89 pub fn start_fm(&mut self, carrier_hz: u32, mod_ratio_cent: u16, sample_rate_hz: u32) {
90 let mut voice = FmVoice::new();
91 voice.start(carrier_hz, mod_ratio_cent, 72, sample_rate_hz);
92 *self = Self::Fm(voice);
93 }
94
95 pub fn start_from_entry(
96 &mut self,
97 kind: EffectKind,
98 flags: u8,
99 param0: u16,
100 param1: u16,
101 payload: &'a [u8],
102 sample_rate_hz: u32,
103 ) -> bool {
104 match kind {
105 EffectKind::Tone => {
106 self.start_tone(param0 as u32, param1, Waveform::Sine, sample_rate_hz);
107 true
108 }
109 EffectKind::Wavetable => {
110 if payload.len() < 256 {
111 return false;
112 }
113 self.start_wavetable(payload, param0 as u32, sample_rate_hz);
114 true
115 }
116 EffectKind::Fm => {
117 self.start_fm(param0 as u32, param1, sample_rate_hz);
118 true
119 }
120 EffectKind::Pcm8 => {
121 *self = Self::Pcm8(Pcm8Stream::new(payload, flags));
122 true
123 }
124 EffectKind::Adpcm => {
125 if let Some(s) = AdpcmStream::new(payload, flags) {
126 *self = Self::Adpcm(s);
127 true
128 } else {
129 false
130 }
131 }
132 EffectKind::SigmaDeltaBits => {
133 *self = Self::SigmaDeltaBits(SigmaDeltaBitStream::new(payload, flags));
134 true
135 }
136 }
137 }
138}