Ver Fonte

documented effects

SG há 3 anos atrás
pai
commit
e3541dc49f
1 ficheiros alterados com 60 adições e 7 exclusões
  1. 60 7
      zero_tracker.c

+ 60 - 7
zero_tracker.c

@@ -79,14 +79,47 @@ typedef uint16_t NoteRecord;
 #define NOTE_OFF 63
 #define NOTE_OFF 63
 
 
 typedef enum {
 typedef enum {
+    // 0xy, x - first semitones offset, y - second semitones offset. 0 - no offset .. 7 - +7 semitones...
+    // Play the arpeggio chord with three notes. The first note is the base note, the second and third are offset by x and y.
+    // Each note plays one tick.
     EffectArpeggio = 0x00,
     EffectArpeggio = 0x00,
+
+    // 1xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest.
+    // Slide the note pitch up by xx Hz every tick.
     EffectSlideUp = 0x01,
     EffectSlideUp = 0x01,
+
+    // 2xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest.
+    // Slide the note pitch down by xx Hz every tick.
     EffectSlideDown = 0x02,
     EffectSlideDown = 0x02,
+
+    // 3xx, xx - effect speed, 0 - no effect, 1 - slowest, 0x3F - fastest.
+    // Slide the already playing note pitch towards another one by xx Hz every tick.
+    // The note value is saved until the note is playing, so you don't have to repeat the note value to continue sliding.
     EffectSlideToNote = 0x03,
     EffectSlideToNote = 0x03,
+
+    // 4xy, x - vibrato speed (0..7), y - vibrato depth (0..7).
+    // Vibrato effect. The pitch of the note increases by x Hz each tick to a positive vibrato depth, then decreases to a negative depth.
+    // Value 1 of depth means 1/7 of a semitone (about 14.28 ct), so value 7 means full semitone.
+    // Note will play without vibrato on the first tick at the beginning of the effect.
+    // Vibrato speed and depth are saved until the note is playing, and will be updated only if they are not zero, so you doesn't have to repeat them every tick.
     EffectVibrato = 0x04,
     EffectVibrato = 0x04,
 
 
+    // Bxx, xx - pattern number
+    // Jump to the pattern number xx at first tick of current row.
+    // So if you want to jump to the pattern after note 4, you should put this effect on the 5th note.
+    EffectJumpToPattern = 0x0B,
+
+    // Cxx, xx - pwm value
+    // Set the PWM value to xx.
     EffectPWM = 0x0C,
     EffectPWM = 0x0C,
 
 
+    // Bxx, xx - row number
+    // Jump to the row xx in next pattern at first tick of current row.
+    // So if you want to jump to the pattern after note 4, you should put this effect on the 5th note.
+    EffectBreakPattern = 0x0D,
+
+    // Fxx, xx - song speed, 0 - 1 tick per note, 1 - 2 ticks per note, 0x3F - 64 ticks per note.
+    // Set the speed of the song in terms of ticks per note.
     EffectSetSpeed = 0x0F,
     EffectSetSpeed = 0x0F,
 } Effect;
 } Effect;
 
 
@@ -386,6 +419,32 @@ void tracker_interrupt_body() {
 
 
     // load frequency from note at tick 0
     // load frequency from note at tick 0
     if(song_state.tick == 0) {
     if(song_state.tick == 0) {
+        // handle "on first tick" effects
+        if(effect == EffectBreakPattern) {
+            // TODO: advance to next pattern
+            song_state.row = data;
+
+            // reload note and effect
+            note = record_get_note(row.notes[song_state.row]);
+            effect = record_get_effect(row.notes[song_state.row]);
+            data = record_get_effect_data(row.notes[song_state.row]);
+        }
+
+        if(effect == EffectJumpToPattern) {
+            // TODO: advance to pattern[data]
+
+            // reload note and effect
+            note = record_get_note(row.notes[song_state.row]);
+            effect = record_get_effect(row.notes[song_state.row]);
+            data = record_get_effect_data(row.notes[song_state.row]);
+        }
+
+        // no "else", cos previous effects reloads the effect value
+        if(effect == EffectSetSpeed) {
+            song_state.tick_limit = data;
+        }
+
+        // handle note effects
         if(note == NOTE_OFF) {
         if(note == NOTE_OFF) {
             ch_state.play = false;
             ch_state.play = false;
         } else if((note > NOTE_NONE) && (note < NOTE_OFF)) {
         } else if((note > NOTE_NONE) && (note < NOTE_OFF)) {
@@ -407,11 +466,6 @@ void tracker_interrupt_body() {
                 ch_state.frequency_target = FREQUENCY_UNSET;
                 ch_state.frequency_target = FREQUENCY_UNSET;
             }
             }
         }
         }
-
-        // handle "on first tick" effects
-        if(effect == EffectSetSpeed) {
-            song_state.tick_limit = data;
-        }
     }
     }
 
 
     if(ch_state.play) {
     if(ch_state.play) {
@@ -491,8 +545,7 @@ void tracker_interrupt_body() {
 
 
         // next note
         // next note
         song_state.row = (song_state.row + 1) % PATTERN_SIZE;
         song_state.row = (song_state.row + 1) % PATTERN_SIZE;
-
-        // handle "on last tick" effects
+        //TODO: advance to next pattern
     }
     }
 }
 }