1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use serde::{Deserialize, Serialize};
/// MOS6581 SID Voice
///
/// Synchronize & ring modulation:
/// - voice0: from voice2
/// - voice1: from voice0
/// - voice2: from voice1
#[derive(Default, Serialize, Deserialize, Copy, Clone, Debug)]
pub struct SidVoice {
/// frequency Voice
pub freq: u16,
/// pulse wave duty cycle
pub pw: u16,
pub ctrl_noise: bool, // 7
pub ctrl_pulse: bool, // 6
pub ctrl_sawtooth: bool, // 5
pub ctrl_triangle: bool, // 4
pub ctrl_test: bool, // 3
/// ring modulation (2->0, 0->1, 1->2)
pub ctrl_rm: bool, // 2
/// synchronize with (2->0, 0->1, 1->2)
pub ctrl_sync: bool, // 1
pub ctrl_gate: bool, // 0
/// attack (0..15), decay (0..15)
pub ad: u8,
/// sustain (0..15), release (0..15)
pub sr: u8,
}
impl SidVoice {
pub fn update_from_ctrl_register(&mut self, ctrl: u8) {
// 7 noise
if ctrl & 0b1000_0000 != 0 {
self.ctrl_noise = true;
}
// 6 pulse
if ctrl & 0b0100_0000 != 0 {
self.ctrl_pulse = true;
}
// 5 sawtooth
if ctrl & 0b0010_0000 != 0 {
self.ctrl_sawtooth = true;
}
// 4 triangle
if ctrl & 0b0001_0000 != 0 {
self.ctrl_triangle = true;
}
// 3 test
if ctrl & 0b0000_1000 != 0 {
self.ctrl_test = true;
}
// 2 ring modulation with voice X
if ctrl & 0b0000_0100 != 0 {
self.ctrl_rm = true;
}
// 1 synchronize with voice X
if ctrl & 0b0000_0010 != 0 {
self.ctrl_sync = true;
}
// 0 gate
if ctrl & 0b0000_0001 != 0 {
self.ctrl_gate = true;
}
}
pub fn generate_ctrl_register(&self) -> u8 {
let mut ctrl = 0;
// 7 noise
if self.ctrl_noise {
ctrl |= 0b1000_0000;
}
// 6 pulse
if self.ctrl_pulse {
ctrl |= 0b0100_0000;
}
// 5 sawtooth
if self.ctrl_sawtooth {
ctrl |= 0b0010_0000;
}
// 4 triangle
if self.ctrl_triangle {
ctrl |= 0b0001_0000;
}
// 3 test
if self.ctrl_test {
ctrl |= 0b0000_1000;
}
// 2 ring modulation with voice X
if self.ctrl_rm {
ctrl |= 0b0000_0100;
}
// 1 synchronize with voice X
if self.ctrl_sync {
ctrl |= 0b0000_0010;
}
// 0 gate
if self.ctrl_gate {
ctrl |= 0b0000_0001;
}
ctrl
}
}
/// MOS6581 SID Instrument
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InstrSid {
pub voice: [SidVoice; 3],
pub fc: u16, // Filter cutoff frequency (0..2047) - Used by (Low, Band, High)Pass
pub filter_resonance: u8, // u4 (0..15) - Amount of feedback a filter receives from itself
pub filter_gate: [bool; 4], // 0 for voice0, ..., 3 for external input
pub low_pass: bool,
pub band_pass: bool,
pub high_pass: bool,
pub mute_voice3: bool,
pub main_volume: u8, // u4 (0..15)
}
impl Default for InstrSid {
fn default() -> Self {
Self {
voice: [SidVoice::default(); 3],
fc: 0,
filter_resonance: 0,
filter_gate: [false; 4],
low_pass: false,
band_pass: false,
high_pass: false,
mute_voice3: false,
main_volume: 15,
}
}
}