]> git.seodisparate.com - LD53/commitdiff
Rewrite music module (needs tweaks)
authorStephen Seo <seo.disparate@gmail.com>
Sun, 30 Apr 2023 06:08:06 +0000 (15:08 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sun, 30 Apr 2023 06:08:06 +0000 (15:08 +0900)
Music now slows down on miss or slowdown. Support for music speed-up is
in, but sounds not good when used, so it's currently disabled.

src/music.rs
src/world.rs

index 52b4d1d1bc6c02e9572fa7cf9e0dfb1439cca326..b213ece9ceb6feb2a14e8a701ff1d7d023f3c20a 100644 (file)
 use crate::wasm4::*;
 
-const C4: u32 = 262;
-const D4: u32 = 293;
-const E4: u32 = 330;
-const F4: u32 = 349;
-const G4: u32 = 392;
-const A4: u32 = 440;
-const B4: u32 = 494;
-const C5: u32 = 523;
-const D5: u32 = 587;
-const E5: u32 = 659;
-const F5: u32 = 698;
-const G5: u32 = 784;
-const A5: u32 = 880;
-const B5: u32 = 988;
-const C6: u32 = 1047;
+const FRAMES_PER_SIXTEENTH: f32 = 6.0f32;
+
+const SLOWDOWN_RATE: f32 = 0.001f32;
+const SLOWDOWN_REVERT_RATE: f32 = 0.002f32;
+const SLOWDOWN_MIN: f32 = 0.6f32;
+
+const SPEEDUP_RATE: f32 = 1.00f32;
+const SPEEDUP_REVERT_RATE: f32 = 0.1f32;
+const SPEEDUP_MAX: f32 = 1.6f32;
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum Pitch {
+    C0,
+    D0,
+    E0,
+    F0,
+    G0,
+    A0,
+    B0,
+    C1,
+    D1,
+    E1,
+    F1,
+    G1,
+    A1,
+    B1,
+    C2,
+    D2,
+    E2,
+    F2,
+    G2,
+    A2,
+    B2,
+    C3,
+    D3,
+    E3,
+    F3,
+    G3,
+    A3,
+    B3,
+    C4,
+    D4,
+    E4,
+    F4,
+    G4,
+    A4,
+    B4,
+    C5,
+    D5,
+    E5,
+    F5,
+    G5,
+    A5,
+    B5,
+    C6,
+    D6,
+    E6,
+    F6,
+    G6,
+    A6,
+    B6,
+    C7,
+    D7,
+    E7,
+    F7,
+    G7,
+    A7,
+    B7,
+    C8,
+    D8,
+    E8,
+    F8,
+    G8,
+    A8,
+    B8,
+}
+
+impl Into<f32> for Pitch {
+    fn into(self) -> f32 {
+        match self {
+            Pitch::C0 => 16.35,
+            Pitch::D0 => 17.32,
+            Pitch::E0 => 20.6,
+            Pitch::F0 => 21.83,
+            Pitch::G0 => 24.5,
+            Pitch::A0 => 27.5,
+            Pitch::B0 => 30.87,
+            Pitch::C1 => 32.70,
+            Pitch::D1 => 36.71,
+            Pitch::E1 => 41.2,
+            Pitch::F1 => 43.65,
+            Pitch::G1 => 49.0,
+            Pitch::A1 => 55.0,
+            Pitch::B1 => 61.74,
+            Pitch::C2 => 65.41,
+            Pitch::D2 => 73.42,
+            Pitch::E2 => 82.41,
+            Pitch::F2 => 87.31,
+            Pitch::G2 => 98.0,
+            Pitch::A2 => 110.0,
+            Pitch::B2 => 123.47,
+            Pitch::C3 => 130.81,
+            Pitch::D3 => 146.83,
+            Pitch::E3 => 164.81,
+            Pitch::F3 => 174.61,
+            Pitch::G3 => 196.0,
+            Pitch::A3 => 220.0,
+            Pitch::B3 => 246.94,
+            Pitch::C4 => 261.63,
+            Pitch::D4 => 293.66,
+            Pitch::E4 => 329.63,
+            Pitch::F4 => 349.23,
+            Pitch::G4 => 392.0,
+            Pitch::A4 => 440.0,
+            Pitch::B4 => 493.88,
+            Pitch::C5 => 523.25,
+            Pitch::D5 => 587.33,
+            Pitch::E5 => 659.25,
+            Pitch::F5 => 698.46,
+            Pitch::G5 => 783.99,
+            Pitch::A5 => 880.0,
+            Pitch::B5 => 987.77,
+            Pitch::C6 => 1046.5,
+            Pitch::D6 => 1174.66,
+            Pitch::E6 => 1318.51,
+            Pitch::F6 => 1396.91,
+            Pitch::G6 => 1567.98,
+            Pitch::A6 => 1760.00,
+            Pitch::B6 => 1975.53,
+            Pitch::C7 => 2093.0,
+            Pitch::D7 => 2349.32,
+            Pitch::E7 => 2637.02,
+            Pitch::F7 => 2793.83,
+            Pitch::G7 => 3135.96,
+            Pitch::A7 => 3520.00,
+            Pitch::B7 => 3951.07,
+            Pitch::C8 => 4186.01,
+            Pitch::D8 => 4698.63,
+            Pitch::E8 => 5274.04,
+            Pitch::F8 => 5587.65,
+            Pitch::G8 => 6271.93,
+            Pitch::A8 => 7040.0,
+            Pitch::B8 => 7902.13,
+        }
+    }
+}
+
+impl Pitch {
+    pub fn to_u32(self) -> u32 {
+        (Into::<f32>::into(self) + 0.5f32) as u32
+    }
+
+    pub fn to_u32_mult(self, mult: f32) -> u32 {
+        (Into::<f32>::into(self) * mult + 0.5f32) as u32
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum Duration {
+    SIXTEENTH,
+    EIGHTH,
+    QUARTER,
+    HALF,
+    FULL,
+}
+
+impl Into<f32> for Duration {
+    fn into(self) -> f32 {
+        match self {
+            Duration::SIXTEENTH => 1f32,
+            Duration::EIGHTH => 2f32,
+            Duration::QUARTER => 4f32,
+            Duration::HALF => 8f32,
+            Duration::FULL => 16f32,
+        }
+    }
+}
+
+const PULSE1_NOTES: [(Pitch, Duration, u8); 63] = [
+    // m1
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::E4, Duration::EIGHTH, 40),
+    (Pitch::D4, Duration::EIGHTH, 40),
+    (Pitch::F4, Duration::EIGHTH, 40),
+    (Pitch::E4, Duration::EIGHTH, 40),
+    (Pitch::C6, Duration::EIGHTH, 40),
+    (Pitch::B5, Duration::EIGHTH, 40),
+    (Pitch::G5, Duration::EIGHTH, 40),
+    // m2
+    (Pitch::D5, Duration::EIGHTH, 40),
+    (Pitch::G5, Duration::EIGHTH, 40),
+    (Pitch::A5, Duration::EIGHTH, 40),
+    (Pitch::A4, Duration::EIGHTH, 40),
+    (Pitch::G5, Duration::EIGHTH, 40),
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::G4, Duration::QUARTER, 40),
+    // m3
+    (Pitch::A4, Duration::EIGHTH, 40),
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::F4, Duration::EIGHTH, 40),
+    (Pitch::E4, Duration::EIGHTH, 40),
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::F4, Duration::EIGHTH, 40),
+    (Pitch::E4, Duration::EIGHTH, 40),
+    (Pitch::D4, Duration::EIGHTH, 40),
+    // m4
+    (Pitch::C4, Duration::EIGHTH, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+    (Pitch::D5, Duration::EIGHTH, 40),
+    (Pitch::G5, Duration::EIGHTH, 40),
+    (Pitch::C4, Duration::EIGHTH, 40),
+    (Pitch::G5, Duration::EIGHTH, 40),
+    (Pitch::C6, Duration::EIGHTH, 40),
+    (Pitch::G5, Duration::EIGHTH, 40),
+    // m5
+    (Pitch::A4, Duration::EIGHTH, 40),
+    (Pitch::B4, Duration::EIGHTH, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+    (Pitch::E5, Duration::EIGHTH, 40),
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::A4, Duration::EIGHTH, 40),
+    (Pitch::B4, Duration::EIGHTH, 40),
+    (Pitch::D5, Duration::EIGHTH, 40),
+    // m6
+    (Pitch::C5, Duration::EIGHTH, 40),
+    (Pitch::B4, Duration::EIGHTH, 40),
+    (Pitch::A4, Duration::EIGHTH, 40),
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::B5, Duration::EIGHTH, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+    (Pitch::G5, Duration::EIGHTH, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+    // m7
+    (Pitch::A5, Duration::EIGHTH, 40),
+    (Pitch::G5, Duration::EIGHTH, 40),
+    (Pitch::F5, Duration::EIGHTH, 40),
+    (Pitch::E5, Duration::EIGHTH, 40),
+    (Pitch::D5, Duration::EIGHTH, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+    (Pitch::B4, Duration::EIGHTH, 40),
+    (Pitch::A4, Duration::EIGHTH, 40),
+    // m8
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::F4, Duration::EIGHTH, 40),
+    (Pitch::E4, Duration::EIGHTH, 40),
+    (Pitch::D4, Duration::EIGHTH, 40),
+    (Pitch::C4, Duration::EIGHTH, 40),
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+    (Pitch::C4, Duration::EIGHTH, 40),
+];
+
+const TRI_NOTES: [(Pitch, Duration, u8); 37] = [
+    // m1
+    (Pitch::E4, Duration::QUARTER, 40),
+    (Pitch::G4, Duration::QUARTER, 40),
+    (Pitch::C4, Duration::QUARTER, 40),
+    (Pitch::G4, Duration::QUARTER, 40),
+    // m2
+    (Pitch::F5, Duration::QUARTER, 40),
+    (Pitch::A4, Duration::QUARTER, 40),
+    (Pitch::A4, Duration::QUARTER, 40),
+    (Pitch::G5, Duration::QUARTER, 40),
+    // m3
+    (Pitch::F5, Duration::QUARTER, 40),
+    (Pitch::G5, Duration::QUARTER, 40),
+    (Pitch::C5, Duration::QUARTER, 40),
+    (Pitch::G5, Duration::QUARTER, 40),
+    // m4
+    (Pitch::B4, Duration::QUARTER, 40),
+    (Pitch::G5, Duration::QUARTER, 40),
+    (Pitch::C4, Duration::EIGHTH, 40),
+    (Pitch::G4, Duration::EIGHTH, 40),
+    (Pitch::C4, Duration::QUARTER, 40),
+    // m5
+    (Pitch::A4, Duration::QUARTER, 40),
+    (Pitch::A4, Duration::QUARTER, 40),
+    (Pitch::B4, Duration::EIGHTH, 40),
+    (Pitch::A4, Duration::EIGHTH, 40),
+    (Pitch::B4, Duration::EIGHTH, 40),
+    (Pitch::E5, Duration::EIGHTH, 40),
+    // m6
+    (Pitch::C5, Duration::QUARTER, 40),
+    (Pitch::E5, Duration::QUARTER, 40),
+    (Pitch::D5, Duration::QUARTER, 40),
+    (Pitch::C5, Duration::QUARTER, 40),
+    // m7
+    (Pitch::A5, Duration::QUARTER, 40),
+    (Pitch::E5, Duration::QUARTER, 40),
+    (Pitch::A5, Duration::QUARTER, 40),
+    (Pitch::E5, Duration::QUARTER, 40),
+    // m8
+    (Pitch::G5, Duration::QUARTER, 40),
+    (Pitch::D5, Duration::QUARTER, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+    (Pitch::B4, Duration::EIGHTH, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+    (Pitch::C5, Duration::EIGHTH, 40),
+];
 
 pub struct Music {
     started: bool,
-    frame: u32,
+    pulse1_time: f32,
+    pulse1_idx: usize,
+    tri_time: f32,
+    tri_idx: usize,
+    factor: f32,
+    factor_slowing: Option<bool>,
+    factor_speeding: Option<bool>,
 }
 
 impl Music {
     pub fn new() -> Self {
         Self {
             started: false,
-            frame: 0,
+            pulse1_time: 0f32,
+            pulse1_idx: 0,
+            tri_time: 0f32,
+            tri_idx: 0,
+            factor: 1f32,
+            factor_slowing: None,
+            factor_speeding: None,
         }
     }
 
+    pub fn speed_up(&mut self) {
+        self.factor_slowing = None;
+        //self.factor_speeding = Some(true);
+        self.factor_speeding = None;
+        self.factor = 1f32;
+    }
+
+    pub fn slow_down(&mut self) {
+        self.factor_slowing = Some(true);
+        self.factor_speeding = None;
+        self.factor = 1f32;
+    }
+
+    fn get_factor(&self) -> f32 {
+        self.factor
+    }
+
     pub fn start(&mut self) {
         self.started = true;
     }
@@ -38,94 +351,80 @@ impl Music {
             return;
         }
 
-        // m1
-        if self.frame == 0 {
-            tone(G4, 10 << 8, 40, TONE_PULSE1);
-            tone(E4, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 10 {
-            tone(E4, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 20 {
-            tone(D4, 10 << 8, 40, TONE_PULSE1);
-            tone(G4, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 30 {
-            tone(F4, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 40 {
-            tone(E4, 10 << 8, 40, TONE_PULSE1);
-            tone(C4, 30 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 50 {
-            tone(C6, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 60 {
-            tone(B5, 10 << 8, 40, TONE_PULSE1);
-            tone(G4, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 70 {
-            tone(G5, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 80 {
-            tone(D5, 10 << 8, 40, TONE_PULSE1);
-            tone(F5, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 90 {
-            tone(G5, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 100 {
-            tone(A5, 10 << 8, 40, TONE_PULSE1);
-            tone(A4, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 110 {
-            tone(A4, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 120 {
-            tone(G5, 10 << 8, 40, TONE_PULSE1);
-            tone(A4, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 130 {
-            tone(G4, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 140 {
-            tone(G4, 20 << 8, 40, TONE_PULSE1);
-            tone(G5, 20 << 8, 40, TONE_TRIANGLE);
+        if let Some(not_reverting) = &mut self.factor_slowing {
+            if *not_reverting {
+                self.factor -= SLOWDOWN_RATE;
+                if self.factor <= SLOWDOWN_MIN {
+                    *not_reverting = false;
+                    self.factor = SLOWDOWN_MIN;
+                }
+            } else {
+                self.factor += SLOWDOWN_REVERT_RATE;
+                if self.factor >= 1f32 {
+                    self.factor = 1f32;
+                    self.factor_slowing.take();
+                }
+            }
+        } else if let Some(not_reverting) = &mut self.factor_speeding {
+            if *not_reverting {
+                self.factor += SPEEDUP_RATE;
+                if self.factor >= SPEEDUP_MAX {
+                    *not_reverting = false;
+                    self.factor = SPEEDUP_MAX;
+                }
+            } else {
+                self.factor -= SPEEDUP_REVERT_RATE;
+                if self.factor <= 1f32 {
+                    self.factor = 1f32;
+                    self.factor_speeding.take();
+                }
+            }
         }
-        // m3
-        else if self.frame == 160 {
-            tone(A4, 10 << 8, 40, TONE_PULSE1);
-            tone(F5, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 170 {
-            tone(G4, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 180 {
-            tone(F4, 10 << 8, 40, TONE_PULSE1);
-            tone(G5, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 190 {
-            tone(E4, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 200 {
-            tone(G4, 10 << 8, 40, TONE_PULSE1);
-            tone(C5, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 210 {
-            tone(F4, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 220 {
-            tone(E4, 10 << 8, 40, TONE_PULSE1);
-            tone(G5, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 230 {
-            tone(D4, 10 << 8, 40, TONE_PULSE1);
+
+        if self.pulse1_idx < PULSE1_NOTES.len() {
+            if self.pulse1_time <= 0f32 {
+                let frames =
+                    Into::<f32>::into(PULSE1_NOTES[self.pulse1_idx].1) * FRAMES_PER_SIXTEENTH;
+                //                    / self.get_factor();
+                crate::tone(
+                    PULSE1_NOTES[self.pulse1_idx]
+                        .0
+                        .to_u32_mult(self.get_factor()),
+                    ((frames + 0.5f32) as u32) << 8,
+                    PULSE1_NOTES[self.pulse1_idx].2 as u32,
+                    TONE_PULSE1,
+                );
+                self.pulse1_time += frames;
+                self.pulse1_idx += 1;
+            }
         }
-        // m4
-        else if self.frame == 240 {
-            tone(C4, 10 << 8, 40, TONE_PULSE1);
-            tone(B4, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 250 {
-            tone(C5, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 260 {
-            tone(D5, 10 << 8, 40, TONE_PULSE1);
-            tone(G5, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 270 {
-            tone(G5, 10 << 8, 40, TONE_PULSE1);
-        } else if self.frame == 280 {
-            tone(C4, 10 << 8, 40, TONE_PULSE1);
-            tone(C4, 10 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 290 {
-            tone(G5, 10 << 8, 40, TONE_PULSE1);
-            tone(G4, 10 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 300 {
-            tone(C6, 10 << 8, 40, TONE_PULSE1);
-            tone(C4, 20 << 8, 40, TONE_TRIANGLE);
-        } else if self.frame == 310 {
-            tone(G5, 10 << 8, 40, TONE_PULSE1);
+        self.pulse1_time -= self.get_factor();
+        //self.pulse1_time -= 1f32;
+
+        if self.tri_idx < TRI_NOTES.len() {
+            if self.tri_time <= 0f32 {
+                let frames = Into::<f32>::into(TRI_NOTES[self.tri_idx].1) * FRAMES_PER_SIXTEENTH;
+                //                    / self.get_factor();
+                crate::tone(
+                    TRI_NOTES[self.tri_idx].0.to_u32_mult(self.get_factor()),
+                    ((frames + 0.5f32) as u32) << 8,
+                    TRI_NOTES[self.tri_idx].2 as u32,
+                    TONE_TRIANGLE,
+                );
+                self.tri_time += frames;
+                self.tri_idx += 1;
+            }
         }
-        self.frame += 1;
-        if self.frame == 320 {
-            self.frame = 0;
+        self.tri_time -= self.get_factor();
+        //self.tri_time -= 1f32;
+
+        if self.pulse1_idx >= PULSE1_NOTES.len()
+            && self.tri_idx >= TRI_NOTES.len()
+            && self.pulse1_time <= 0f32
+            && self.tri_time <= 0f32
+        {
+            self.pulse1_idx = 0;
+            self.tri_idx = 0;
         }
     }
 }
index 182c41cdb0e9a1e169604a870c67191155f73306..a767f5adef2ca9cc220eda0d03acc4fbb95a2da1 100644 (file)
@@ -133,6 +133,7 @@ impl World {
                         self.rate_multiplier = 1f32;
                     }
                     self.status_text = Some(("Miss!\nSlow down!", 80));
+                    self.music.slow_down();
                 }
                 self.building.take();
                 self.is_in_range = false;
@@ -155,11 +156,13 @@ impl World {
                         self.score += 1;
                         self.rate_multiplier += MULTIPLIER_INC_RATE;
                         self.status_text = Some(("Nice delivery!\nSpeed up!", 80));
+                        self.music.speed_up();
                     }
                     Building::SpeedUp => {
                         self.rate_multiplier += SPEEDUP_INC;
                         self.status_text = Some(("Speed up!", 80));
                         self.building.take();
+                        self.music.speed_up();
                     }
                     Building::SlowDown => {
                         self.rate_multiplier /= SLOWDOWN_DIV;
@@ -168,6 +171,7 @@ impl World {
                         }
                         self.status_text = Some(("Slow down!", 80));
                         self.building.take();
+                        self.music.slow_down();
                     }
                 }
                 self.music.start();