SG 3 лет назад
Родитель
Сommit
ed5368a979
1 измененных файлов с 163 добавлено и 10 удалено
  1. 163 10
      zero_tracker.c

+ 163 - 10
zero_tracker.c

@@ -78,6 +78,12 @@ typedef uint16_t NoteRecord;
 #define NOTE_B6 60
 #define NOTE_B6 60
 #define NOTE_KILL 63
 #define NOTE_KILL 63
 
 
+#define EFFECT_ARPEGGIO 0
+
+#define EFFECT_DATA_NONE 0
+
+#define EFFECT_DATA_2(x, y) ((x) | ((y) << 3))
+
 uint8_t record_get_note(NoteRecord note) {
 uint8_t record_get_note(NoteRecord note) {
     return note & 0x3F;
     return note & 0x3F;
 }
 }
@@ -117,6 +123,10 @@ float note_to_freq(uint8_t note) {
     return notes_oct[note_in_oct] * (1 << octave);
     return notes_oct[note_in_oct] * (1 << octave);
 }
 }
 
 
+float frequency_offset(float frequency, uint8_t semitones) {
+    return frequency * (1.0f + ((1.0f / 12.0f) * semitones));
+}
+
 #define PATTERN_SIZE 64
 #define PATTERN_SIZE 64
 
 
 typedef struct {
 typedef struct {
@@ -128,7 +138,7 @@ typedef struct {
     NoteRow* rows;
     NoteRow* rows;
 } NotePattern;
 } NotePattern;
 
 
-NoteRow row = {
+NoteRow _row = {
     .notes =
     .notes =
         {
         {
             //
             //
@@ -214,23 +224,140 @@ NoteRow row = {
         },
         },
 };
 };
 
 
-uint8_t counter = 0;
-uint8_t counter_limit = 2;
+NoteRow row = {
+    .notes =
+        {
+            //
+            RECORD_MAKE(NOTE_A4, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            //
+            RECORD_MAKE(NOTE_KILL, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(NOTE_A4, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            //
+            RECORD_MAKE(NOTE_KILL, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(NOTE_A4, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            //
+            RECORD_MAKE(NOTE_KILL, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(NOTE_A4, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            RECORD_MAKE(0, EFFECT_ARPEGGIO, EFFECT_DATA_2(3, 7)),
+            //
+            RECORD_MAKE(NOTE_KILL, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            //
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+            RECORD_MAKE(0, 0, 0),
+        },
+};
 
 
+uint8_t tick_counter = 0;
+uint8_t tick_limit = 2;
 uint8_t row_counter = 0;
 uint8_t row_counter = 0;
 
 
+float note_frequency = 0;
+bool note_play = false;
+
 void tracker_interrupt_body() {
 void tracker_interrupt_body() {
-    if(counter == 0) {
-        uint8_t note = record_get_note(row.notes[row_counter]);
+    uint8_t note = record_get_note(row.notes[row_counter]);
+    uint8_t effect = record_get_effect(row.notes[row_counter]);
+    uint8_t data = record_get_effect_data(row.notes[row_counter]);
+
+    // load frequency from note at tick 0
+    if(tick_counter == 0) {
         if(note == NOTE_KILL) {
         if(note == NOTE_KILL) {
-            tracker_speaker_stop();
-        } else if(note > 0 && note < NOTE_KILL) {
-            float freq = note_to_freq(note);
-            tracker_speaker_play(freq, 0.5f);
+            note_play = false;
+        } else if((note > 0) && (note < NOTE_KILL)) {
+            note_play = true;
+            note_frequency = note_to_freq(note);
+        }
+    }
+
+    if(note_play) {
+        float frequency = note_frequency;
+
+        // apply arpeggio effect
+        if(effect == EFFECT_ARPEGGIO && data != EFFECT_DATA_NONE) {
+            if((tick_counter % 3) == 1) {
+                uint8_t note_offset = data & 0b000111;
+                frequency = frequency_offset(frequency, note_offset);
+            } else if((tick_counter % 3) == 2) {
+                uint8_t note_offset = (data >> 3) & 0b000111;
+                frequency = frequency_offset(frequency, note_offset);
+            }
         }
         }
+
+        tracker_speaker_play(frequency, 0.5f);
+    } else {
+        tracker_speaker_stop();
+    }
+
+    tick_counter++;
+    if(tick_counter >= tick_limit) {
+        tick_counter = 0;
+
+        // next note
         row_counter = (row_counter + 1) % PATTERN_SIZE;
         row_counter = (row_counter + 1) % PATTERN_SIZE;
     }
     }
-    counter = (counter + 1) % counter_limit;
 }
 }
 
 
 void tracker_interrupt_cb() {
 void tracker_interrupt_cb() {
@@ -239,12 +366,38 @@ void tracker_interrupt_cb() {
     tracker_debug_set(false);
     tracker_debug_set(false);
 }
 }
 
 
+void log_record(NoteRecord record) {
+    uint8_t note = record_get_note(record);
+    uint8_t effect = record_get_effect(record);
+    uint8_t data = record_get_effect_data(record);
+
+    printf("Note: %u, Effect: %u, Data: %u", note, effect, data);
+
+    if(effect == EFFECT_ARPEGGIO) {
+        uint8_t note_offset = data & 0b000111;
+        uint8_t note_offset2 = (data >> 3) & 0b000111;
+        printf(" (Arpeggio: %u, %u)", note_offset, note_offset2);
+
+        float frequency = note_to_freq(note);
+        float new_frequency = frequency_offset(frequency, note_offset);
+        float new_frequency2 = frequency_offset(frequency, note_offset2);
+        printf(
+            " (Freq: %f, %f, %f)",
+            (double)frequency,
+            (double)new_frequency,
+            (double)new_frequency2);
+    }
+
+    printf("\r\n");
+}
+
 int32_t zero_tracker_app(void* p) {
 int32_t zero_tracker_app(void* p) {
     UNUSED(p);
     UNUSED(p);
 
 
     tracker_debug_init();
     tracker_debug_init();
     tracker_speaker_init();
     tracker_speaker_init();
     tracker_interrupt_init(60.0f, tracker_interrupt_cb, NULL);
     tracker_interrupt_init(60.0f, tracker_interrupt_cb, NULL);
+    // log_record(row.notes[0]);
 
 
     while(1) {
     while(1) {
         furi_delay_ms(1000);
         furi_delay_ms(1000);