Skip to main content

gb/
apu.rs

1//! The four sound channels and the mixer.
2//!
3//! Each channel has a configuration type: [`Pulse`] for channels 1 and 2,
4//! [`Wave`] for channel 3, [`Noise`] for channel 4. Building one is a chain of
5//! const methods, and `play` writes it out and starts the channel.
6//!
7//! ```ignore
8//! const JUMP: Pulse = Pulse::new(12).note(Note::C, 5).length(8);
9//!
10//! JUMP.play_ch2();
11//! ```
12//!
13//! See <https://gbdev.io/pandocs/Audio.html>.
14//!
15//! # Power
16//!
17//! The boot ROM leaves the APU on at full volume. A program that only wants
18//! sound has nothing to set up. It does leave channels 3 and 4 reaching the
19//! left output alone, which [`set_panning`] settles.
20//!
21//! [`power_off`] draws less current and is worth having on a pause screen;
22//! [`power_on`] comes back from it.
23//!
24//! # Writing to `DIV`
25//!
26//! Envelopes, length timers and the channel 1 sweep are all counted off `DIV`,
27//! so [`timer::reset_divider`](crate::timer::reset_divider) steps them early.
28//! Resetting it while sound is playing is audible.
29
30#[cfg(feature = "cgb")]
31use crate::mmio::cgb::{PCM12, PCM34};
32use crate::mmio::{
33    AudioCtrl, Duty, Envelope, MasterVolume, NR10, NR11, NR12, NR13, NR14, NR21, NR22, NR23, NR24,
34    NR30, NR31, NR32, NR33, NR34, NR41, NR42, NR43, NR44, NR50, NR51, NR52, NoiseCtrl, NoiseFreq,
35    Panning, PeriodCtrl, PulseLengthDuty, Sweep, WAVE_RAM, WaveDac, WaveLevel, WaveOutput,
36};
37
38/// Power the APU on.
39///
40/// [`power_off`] took the master volume and the panning down with everything
41/// else, so [`set_master`] and [`set_panning`] have to follow this or nothing
42/// reaches the output.
43#[inline]
44pub fn power_on() {
45    NR52.write(AudioCtrl::new().with_audio_on(true));
46}
47
48/// Power the APU off.
49///
50/// Every audio register is cleared and stays read-only until [`power_on`]. Wave
51/// RAM survives. All four DACs go off together, so this clicks unless the
52/// channels were quiet already.
53#[inline]
54pub fn power_off() {
55    NR52.write(AudioCtrl::new());
56}
57
58/// Set the master volume.
59///
60/// The output moves as the volume does, so this clicks unless everything is
61/// already quiet. Fading a tune out with it is audible on top of the fade.
62#[inline]
63pub fn set_master(master: MasterVolume) {
64    NR50.write(master);
65}
66
67/// Set which channels reach which output.
68///
69/// Taking a channel whose DAC is on off an output, or putting it back, moves
70/// that output and clicks. Panning a channel that is playing is heard.
71#[inline]
72pub fn set_panning(panning: Panning) {
73    NR51.write(panning);
74}
75
76/// One of the twelve semitones.
77#[derive(Clone, Copy, Debug, PartialEq, Eq)]
78#[repr(u8)]
79pub enum Note {
80    C,
81    Cs,
82    D,
83    Ds,
84    E,
85    F,
86    Fs,
87    G,
88    Gs,
89    A,
90    As,
91    B,
92}
93
94/// The eighth octave in millihertz. Lower ones come from shifting this down,
95/// which keeps the division that follows precise.
96const OCTAVE_8: [u32; 12] = [
97    4_186_009, 4_434_922, 4_698_636, 4_978_032, 5_274_041, 5_587_652, 5_919_911, 6_271_927,
98    6_644_875, 7_040_000, 7_458_620, 7_902_133,
99];
100
101/// The period value that comes nearest `note` at `octave`, for a channel whose
102/// waveform repeats `clock` times a second at a period value of one.
103const fn period(note: Note, octave: u8, clock: u32) -> u16 {
104    let octave = if octave > 8 { 8 } else { octave };
105    let millihertz = OCTAVE_8[note as usize] >> (8 - octave);
106    let divider = (clock + millihertz / 2) / millihertz;
107    if divider >= 2048 {
108        0
109    } else {
110        (2048 - divider) as u16
111    }
112}
113
114/// Turn `ticks` of a length timer into the value the register takes, which
115/// counts up to `limit` from what is written.
116const fn length_from(ticks: u16, limit: u16) -> u8 {
117    let ticks = if ticks == 0 {
118        1
119    } else if ticks > limit {
120        limit
121    } else {
122        ticks
123    };
124    (limit - ticks) as u8
125}
126
127/// A pulse channel's settings.
128///
129/// Channels 1 and 2 differ only in that 1 has a frequency sweep, so one of
130/// these plays on either.
131#[derive(Clone, Copy, PartialEq, Eq)]
132pub struct Pulse {
133    length_duty: PulseLengthDuty,
134    envelope: Envelope,
135    period_low: u8,
136    period_ctrl: PeriodCtrl,
137}
138
139impl Pulse {
140    /// A 50% square wave at `volume`, out of 15, and the lowest period.
141    ///
142    /// A volume of 0 is not a quiet sound but a stopped channel: it turns the
143    /// DAC off, and a channel whose DAC is off will not start.
144    #[inline]
145    pub const fn new(volume: u8) -> Self {
146        Pulse {
147            length_duty: PulseLengthDuty::new().with_duty(Duty::Half),
148            envelope: Envelope::new().with_volume(if volume > 15 { 15 } else { volume }),
149            period_low: 0,
150            period_ctrl: PeriodCtrl::new().with_trigger(true),
151        }
152    }
153
154    /// Tune to `note` at `octave`.
155    ///
156    /// C2 through B5 comes out within about five cents. There is nothing below
157    /// C2 to reach and the pitch stops there; above B5 the period value runs
158    /// out of resolution and drifts, a quarter tone off by the eighth octave.
159    #[inline]
160    pub const fn note(self, note: Note, octave: u8) -> Self {
161        self.at_period(period(note, octave, 131_072_000))
162    }
163
164    /// Tune to a period value, which counts up rather than down: the larger it
165    /// is, the higher the pitch. At most `$7FF`.
166    #[inline]
167    pub const fn at_period(self, period: u16) -> Self {
168        let period = if period > 0x7FF { 0x7FF } else { period };
169        Pulse {
170            period_low: period as u8,
171            period_ctrl: self.period_ctrl.with_period_high((period >> 8) as u8 & 7),
172            ..self
173        }
174    }
175
176    /// Set the fraction of each cycle the wave spends high.
177    #[inline]
178    pub const fn duty(self, duty: Duty) -> Self {
179        Pulse {
180            length_duty: self.length_duty.with_duty(duty),
181            ..self
182        }
183    }
184
185    /// Step the volume every `pace` ticks of a 64 Hz count, up or down.
186    ///
187    /// A pace of 0 holds the volume where [`Pulse::new`] put it.
188    #[inline]
189    pub const fn envelope(self, pace: u8, increase: bool) -> Self {
190        Pulse {
191            envelope: self
192                .envelope
193                .with_pace(if pace > 7 { 7 } else { pace })
194                .with_increase(increase),
195            ..self
196        }
197    }
198
199    /// Stop the channel after `ticks` of a 256 Hz count, at most 64.
200    #[inline]
201    pub const fn length(self, ticks: u8) -> Self {
202        Pulse {
203            length_duty: self.length_duty.with_length(length_from(ticks as u16, 64)),
204            period_ctrl: self.period_ctrl.with_length_enable(true),
205            ..self
206        }
207    }
208
209    /// Play on channel 1, with `sweep` bending the pitch as it goes.
210    ///
211    /// The sweep is asked for because it belongs to the channel rather than to
212    /// these settings, and one left over from an earlier sound would bend this
213    /// one. [`Sweep::new`] leaves the pitch alone.
214    ///
215    /// The trigger decides whether a sweep runs at all, so a note started
216    /// without one cannot be given one part way through.
217    ///
218    /// A rising sweep is checked against the top as the note is triggered: a
219    /// step that would carry a high note past `$7FF` in one move cuts it before
220    /// anything is heard. The smaller the step number, the larger the move. A
221    /// falling sweep cannot reach the top and is never cut.
222    #[inline]
223    pub fn play_ch1(&self, sweep: Sweep) {
224        NR10.write(sweep);
225        NR11.write(self.length_duty);
226        NR12.write(self.envelope);
227        NR13.write(self.period_low);
228        NR14.write(self.period_ctrl);
229    }
230
231    /// Play on channel 2.
232    #[inline]
233    pub fn play_ch2(&self) {
234        NR21.write(self.length_duty);
235        NR22.write(self.envelope);
236        NR23.write(self.period_low);
237        NR24.write(self.period_ctrl);
238    }
239
240    /// Change the pitch on channel 1 without starting the note over.
241    ///
242    /// A running sweep holds its own copy of the pitch and writes that back at
243    /// its next step, so this reaches a channel playing without one.
244    #[inline]
245    pub fn retune_ch1(&self) {
246        NR13.write(self.period_low);
247        NR14.write(self.period_ctrl.with_trigger(false));
248    }
249
250    /// Change the pitch on channel 2 without starting the note over.
251    ///
252    /// The envelope and the waveform carry on from where they are, as a slide
253    /// or a vibrato needs. [`Pulse::play_ch2`] restarts both.
254    #[inline]
255    pub fn retune_ch2(&self) {
256        NR23.write(self.period_low);
257        NR24.write(self.period_ctrl.with_trigger(false));
258    }
259
260    /// Change the duty on channel 1 without starting the note over.
261    ///
262    /// The length timer shares the register and starts over with it.
263    #[inline]
264    pub fn set_duty_ch1(&self) {
265        NR11.write(self.length_duty);
266    }
267
268    /// Change the duty on channel 2 without starting the note over.
269    ///
270    /// The length timer shares the register and starts over with it.
271    #[inline]
272    pub fn set_duty_ch2(&self) {
273        NR21.write(self.length_duty);
274    }
275}
276
277/// Channel 3's settings, which play whatever [`load_wave`] last put in wave RAM.
278///
279/// There is no envelope here, and the volume is the four steps of [`WaveLevel`].
280#[derive(Clone, Copy, PartialEq, Eq)]
281pub struct Wave {
282    length: u8,
283    output: WaveOutput,
284    period_low: u8,
285    period_ctrl: PeriodCtrl,
286}
287
288impl Wave {
289    /// The wave at `level`, at the lowest period.
290    #[inline]
291    pub const fn new(level: WaveLevel) -> Self {
292        Wave {
293            length: 0,
294            output: WaveOutput::new().with_level(level),
295            period_low: 0,
296            period_ctrl: PeriodCtrl::new().with_trigger(true),
297        }
298    }
299
300    /// Tune to `note` at `octave`.
301    ///
302    /// This channel reads its waveform half as fast as a pulse channel, so its
303    /// range sits an octave below theirs: C1 through B4 within about five
304    /// cents, nothing lower to reach, and the same drift above.
305    #[inline]
306    pub const fn note(self, note: Note, octave: u8) -> Self {
307        self.at_period(period(note, octave, 65_536_000))
308    }
309
310    /// Tune to a period value, which counts up rather than down: the larger it
311    /// is, the higher the pitch. At most `$7FF`.
312    #[inline]
313    pub const fn at_period(self, period: u16) -> Self {
314        let period = if period > 0x7FF { 0x7FF } else { period };
315        Wave {
316            period_low: period as u8,
317            period_ctrl: self.period_ctrl.with_period_high((period >> 8) as u8 & 7),
318            ..self
319        }
320    }
321
322    /// Stop the channel after `ticks` of a 256 Hz count, at most 256.
323    #[inline]
324    pub const fn length(self, ticks: u16) -> Self {
325        Wave {
326            length: length_from(ticks, 256),
327            period_ctrl: self.period_ctrl.with_length_enable(true),
328            ..self
329        }
330    }
331
332    /// Play on channel 3.
333    ///
334    /// Triggering the channel while it is already playing can corrupt wave RAM
335    /// on an original Game Boy. [`stop`] first avoids that and costs a click.
336    #[inline]
337    pub fn play(&self) {
338        NR30.write(WaveDac::new().with_dac_on(true));
339        NR31.write(self.length);
340        NR32.write(self.output);
341        NR33.write(self.period_low);
342        NR34.write(self.period_ctrl);
343    }
344
345    /// Change the pitch without starting the waveform over.
346    #[inline]
347    pub fn retune(&self) {
348        NR33.write(self.period_low);
349        NR34.write(self.period_ctrl.with_trigger(false));
350    }
351
352    /// Change the output level without starting the waveform over.
353    ///
354    /// Channel 3 has no envelope, so use this to move its volume during a note.
355    #[inline]
356    pub fn set_level(&self) {
357        NR32.write(self.output);
358    }
359}
360
361/// Load the 32 four-bit samples channel 3 plays, high nibble of each byte first.
362///
363/// Channel 3 stops first, because wave RAM reached while it is playing does not
364/// answer for the address asked for. That means a click if it was playing, so
365/// this belongs in a quiet moment. Play a [`Wave`] to start it again.
366#[inline]
367pub fn load_wave(samples: &[u8; 16]) {
368    NR30.write(WaveDac::new());
369    let mut i = 0;
370    while i < 16 {
371        WAVE_RAM.index(i).write(samples[i]);
372        i += 1;
373    }
374}
375
376/// Channel 4's settings.
377///
378/// The pitch is a clock divider and shift rather than a note, since what comes
379/// out is noise and is chosen by ear.
380#[derive(Clone, Copy, PartialEq, Eq)]
381pub struct Noise {
382    length: u8,
383    envelope: Envelope,
384    freq: NoiseFreq,
385    ctrl: NoiseCtrl,
386}
387
388impl Noise {
389    /// Noise at `volume`, out of 15, clocked at `262144 / (divider << shift)`
390    /// hertz, where a divider of 0 counts as a half.
391    ///
392    /// A volume of 0 is not a quiet sound but a stopped channel: it turns the
393    /// DAC off, and a channel whose DAC is off will not start.
394    ///
395    /// A shift of 14 or 15 stops the clock, and neither is reachable here.
396    #[inline]
397    pub const fn new(volume: u8, divider: u8, shift: u8) -> Self {
398        Noise {
399            length: 0,
400            envelope: Envelope::new().with_volume(if volume > 15 { 15 } else { volume }),
401            freq: NoiseFreq::new()
402                .with_divider(if divider > 7 { 7 } else { divider })
403                .with_shift(if shift > 13 { 13 } else { shift }),
404            ctrl: NoiseCtrl::new().with_trigger(true),
405        }
406    }
407
408    /// Run the shift register seven bits wide, which repeats often enough to
409    /// carry a pitch.
410    #[inline]
411    pub const fn short_lfsr(self) -> Self {
412        Noise {
413            freq: self.freq.with_short_lfsr(true),
414            ..self
415        }
416    }
417
418    /// Step the volume every `pace` ticks of a 64 Hz count, up or down.
419    ///
420    /// A pace of 0 holds the volume where [`Noise::new`] put it.
421    #[inline]
422    pub const fn envelope(self, pace: u8, increase: bool) -> Self {
423        Noise {
424            envelope: self
425                .envelope
426                .with_pace(if pace > 7 { 7 } else { pace })
427                .with_increase(increase),
428            ..self
429        }
430    }
431
432    /// Stop the channel after `ticks` of a 256 Hz count, at most 64.
433    #[inline]
434    pub const fn length(self, ticks: u8) -> Self {
435        Noise {
436            length: length_from(ticks as u16, 64),
437            ctrl: self.ctrl.with_length_enable(true),
438            ..self
439        }
440    }
441
442    /// Play on channel 4.
443    #[inline]
444    pub fn play(&self) {
445        NR41.write(self.length);
446        NR42.write(self.envelope);
447        NR43.write(self.freq);
448        NR44.write(self.ctrl);
449    }
450}
451
452/// One of the four sound channels.
453#[derive(Clone, Copy, Debug, PartialEq, Eq)]
454pub enum Channel {
455    /// Pulse, with a frequency sweep.
456    One,
457    /// Pulse.
458    Two,
459    /// Wave.
460    Three,
461    /// Noise.
462    Four,
463}
464
465/// Take a channel down to nothing without stopping it.
466///
467/// The DAC stays on, which is the difference from [`stop`]: switching one off
468/// moves the output enough to click.
469///
470/// On channels 1 and 2 the pitch goes down with the volume, so playing again is
471/// how one of those comes back.
472#[inline]
473pub fn silence(ch: Channel) {
474    // A plain 0 would take the DAC down with it; volume 0 rising leaves it up.
475    // The channel then has to be triggered for the new volume to reach it.
476    const QUIET: Envelope = Envelope::new().with_increase(true);
477    const RETRIGGER: PeriodCtrl = PeriodCtrl::new().with_trigger(true);
478    match ch {
479        Channel::One => {
480            NR12.write(QUIET);
481            NR14.write(RETRIGGER);
482        }
483        Channel::Two => {
484            NR22.write(QUIET);
485            NR24.write(RETRIGGER);
486        }
487        // Channel 3 has an output level instead of an envelope, and it takes
488        // effect where it is written.
489        Channel::Three => NR32.write(WaveOutput::new().with_level(WaveLevel::Mute)),
490        Channel::Four => {
491            NR42.write(QUIET);
492            NR44.write(NoiseCtrl::new().with_trigger(true));
493        }
494    }
495}
496
497/// Stop a channel by turning its DAC off.
498///
499/// Clicks. Between notes, prefer [`silence`].
500#[inline]
501pub fn stop(ch: Channel) {
502    match ch {
503        Channel::One => NR12.write(Envelope::new()),
504        Channel::Two => NR22.write(Envelope::new()),
505        Channel::Three => NR30.write(WaveDac::new()),
506        Channel::Four => NR42.write(Envelope::new()),
507    }
508}
509
510/// Whether a channel is still running.
511///
512/// A channel stops when a length timer set by [`Pulse::length`] and its
513/// counterparts expires, when its DAC goes off, or, on channel 1, when the
514/// sweep carries the pitch past the top.
515#[inline]
516pub fn playing(ch: Channel) -> bool {
517    let status = NR52.read();
518    match ch {
519        Channel::One => status.ch1_on(),
520        Channel::Two => status.ch2_on(),
521        Channel::Three => status.ch3_on(),
522        Channel::Four => status.ch4_on(),
523    }
524}
525
526/// What a channel is putting out, from 0 to 15.
527///
528/// This is the digital value on its way to the DAC, so it moves with the
529/// envelope and the waveform rather than with the volume the mixer applies. A
530/// program drawing its own sound reads it here.
531#[cfg(feature = "cgb")]
532#[cfg_attr(docsrs, doc(cfg(feature = "cgb")))]
533#[inline]
534pub fn output(ch: Channel) -> u8 {
535    match ch {
536        Channel::One => PCM12.read().low(),
537        Channel::Two => PCM12.read().high(),
538        Channel::Three => PCM34.read().low(),
539        Channel::Four => PCM34.read().high(),
540    }
541}