Procházet zdrojové kódy

instrument program minimum functionality

LTVA1 před 3 roky
rodič
revize
baa663f9b3

+ 1 - 1
README.md

@@ -1,4 +1,4 @@
 # flizzer_tracker
  A Flipper Zero chiptune tracker.
 
-CURRENT STATE: proof of concept+++. Works only on custom build of the firmware (tiny font not supported yet); effects are not implemented, as well as a lot of other things (song loop points, instrument klystrack-like program (you can edit it but it does not work), etc.). After brief testing looks like it saves and loads modules properly tho.
+CURRENT STATE: barely usable. Works only on custom build of the firmware (tiny font not supported yet); only a few effects are implemented. After brief testing looks like it saves and loads modules properly tho.

+ 10 - 0
input/instrument.c

@@ -406,6 +406,16 @@ void edit_instrument_param(FlizzerTrackerApp *tracker, uint8_t selected_param, i
             flipbit(inst->flags, TE_PROG_NO_RESTART);
             break;
         }
+
+        case INST_PROGRAMEPERIOD:
+        {
+            if ((int16_t)inst->program_period + (int16_t)delta >= 0 && (int16_t)inst->program_period + (int16_t)delta <= 0xff)
+            {
+                inst->program_period += delta;
+            }
+
+            break;
+        }
     }
 }
 

+ 5 - 0
input_event.c

@@ -216,6 +216,11 @@ void cycle_focus(FlizzerTrackerApp *tracker)
             if (tracker->focus > EDIT_PROGRAM)
             {
                 tracker->focus = EDIT_INSTRUMENT;
+
+                if (tracker->current_digit > 1)
+                {
+                    tracker->current_digit = 1;
+                }
             }
 
             break;

+ 112 - 7
tracker_engine/tracker_engine.c

@@ -153,13 +153,14 @@ void tracker_engine_trigger_instrument_internal(TrackerEngine *tracker_engine, u
 
     te_channel->channel_flags = TEC_PLAYING | (te_channel->channel_flags & TEC_DISABLED);
 
+    te_channel->program_period = pinst->program_period;
+
     if (!(pinst->flags & TE_PROG_NO_RESTART) && pinst->program_period > 0)
     {
         te_channel->channel_flags |= TEC_PROGRAM_RUNNING;
 
         te_channel->program_counter = 0;
-        te_channel->program_loop = 0;
-        te_channel->program_period = pinst->program_period;
+        te_channel->program_loop = 1;
         te_channel->program_tick = 0;
     }
 
@@ -275,6 +276,105 @@ void tracker_engine_execute_track_command(TrackerEngine *tracker_engine, uint8_t
     }
 }
 
+void tracker_engine_execute_program_tick(TrackerEngine *tracker_engine, uint8_t chan, uint8_t advance)
+{
+    TrackerEngineChannel *te_channel = &tracker_engine->channel[chan];
+    uint8_t tick = te_channel->program_tick;
+    uint8_t visited[INST_PROG_LEN] = {0};
+
+do_it_again:;
+
+    const uint16_t inst = te_channel->instrument->program[tick];
+
+    if ((inst & 0x7fff) == TE_PROGRAM_END)
+    {
+        te_channel->channel_flags &= ~(TEC_PROGRAM_RUNNING);
+        return;
+    }
+
+    uint8_t dont_reloop = 0;
+
+    if ((inst & 0x7fff) != TE_PROGRAM_NOP)
+    {
+        switch (inst & 0x7f00)
+        {
+            case TE_PROGRAM_JUMP:
+            {
+                if (!visited[tick])
+                {
+                    visited[tick] = 1;
+                    tick = inst & (INST_PROG_LEN - 1);
+                }
+
+                else
+                    return;
+
+                break;
+            }
+
+            case TE_PROGRAM_LOOP_BEGIN:
+                break;
+
+            case TE_PROGRAM_LOOP_END:
+            {
+                if (te_channel->program_loop == (inst & 0xff))
+                {
+                    if (advance)
+                        te_channel->program_loop = 1;
+                }
+
+                else
+                {
+                    if (advance)
+                        ++te_channel->program_loop;
+
+                    uint8_t l = 0;
+
+                    while ((te_channel->instrument->program[tick] & 0x7f00) != TE_PROGRAM_LOOP_BEGIN && tick > 0)
+                    {
+                        --tick;
+                        if (!(te_channel->instrument->program[tick] & 0x8000))
+                            ++l;
+                    }
+
+                    --tick;
+
+                    dont_reloop = l <= 1;
+                }
+
+                break;
+            }
+
+            default:
+            {
+                do_command(inst, tracker_engine, chan);
+                break;
+            }
+        }
+    }
+
+    if ((inst & 0x7fff) == TE_PROGRAM_NOP || (inst & 0x7f00) != TE_PROGRAM_JUMP)
+    {
+        ++tick;
+        if (tick >= INST_PROG_LEN)
+        {
+            tick = 0;
+        }
+    }
+
+    // skip to next on msb
+
+    if (((inst & 0x8000) || ((inst & 0x7f00) == TE_PROGRAM_LOOP_BEGIN) || ((inst & 0x7f00) == TE_PROGRAM_JUMP)) && (inst & 0x7fff) != TE_PROGRAM_NOP && !dont_reloop)
+    {
+        goto do_it_again;
+    }
+
+    if (advance)
+    {
+        te_channel->program_tick = tick;
+    }
+}
+
 void tracker_engine_advance_channel(TrackerEngine *tracker_engine, uint8_t chan)
 {
     SoundEngineChannel *se_channel = &tracker_engine->sound_engine->channel[chan];
@@ -302,7 +402,12 @@ void tracker_engine_advance_channel(TrackerEngine *tracker_engine, uint8_t chan)
 
         if (te_channel->channel_flags & TEC_PROGRAM_RUNNING)
         {
-            // TODO: add instrument program execution
+            uint8_t u = (te_channel->program_counter + 1) >= te_channel->program_period;
+            tracker_engine_execute_program_tick(tracker_engine, chan, u);
+            ++te_channel->program_counter;
+
+            if (u)
+                te_channel->program_counter = 0;
         }
 
         int16_t vib = 0;
@@ -423,8 +528,8 @@ void tracker_engine_advance_tick(TrackerEngine *tracker_engine)
                         te_channel->instrument = pinst;
                     }
                 }
-                
-                if(note == MUS_NOTE_CUT)
+
+                if (note == MUS_NOTE_CUT)
                 {
                     sound_engine_enable_gate(tracker_engine->sound_engine, se_channel, 0);
                     se_channel->adsr.volume = 0;
@@ -438,11 +543,11 @@ void tracker_engine_advance_tick(TrackerEngine *tracker_engine)
 
                 else if (pinst && note != MUS_NOTE_RELEASE && note != MUS_NOTE_CUT && note != MUS_NOTE_NONE)
                 {
-                    //te_channel->slide_speed = 0;
+                    // te_channel->slide_speed = 0;
 
                     uint8_t prev_adsr_volume = se_channel->adsr.volume;
 
-                    if((opcode & 0x7f00) == TE_EFFECT_SLIDE)
+                    if ((opcode & 0x7f00) == TE_EFFECT_SLIDE)
                     {
                         te_channel->target_note = ((note + pinst->base_note - MIDDLE_C) << 8) + pinst->finetune;
                         te_channel->slide_speed = (opcode & 0xff);

+ 1 - 1
tracker_engine/tracker_engine_defs.h

@@ -1,8 +1,8 @@
 #pragma once
 
 #include <stdbool.h>
-#include <stdio.h>
 #include <stdint.h>
+#include <stdio.h>
 
 #include "../sound_engine/sound_engine_defs.h"
 

+ 14 - 0
view/instrument_editor.c

@@ -328,6 +328,20 @@ void draw_instrument_program_view(Canvas *canvas, FlizzerTrackerApp *tracker)
         }
     }
 
+    // draw arrow pointing at current program step
+
+    for (uint8_t i = 0; i < SONG_MAX_CHANNELS; i++)
+    {
+        if (tracker->tracker_engine.channel[i].instrument == inst && (tracker->tracker_engine.channel[i].channel_flags & TEC_PROGRAM_RUNNING) && (tracker->tracker_engine.sound_engine->channel[i].flags & SE_ENABLE_GATE))
+        {
+            if (tracker->tracker_engine.channel[i].program_tick >= tracker->program_position && tracker->tracker_engine.channel[i].program_tick < tracker->program_position + 8)
+            {
+                canvas_draw_str(canvas, 85, 6 * tracker->tracker_engine.channel[i].program_tick - tracker->program_position * 6 + 6, ">");
+                break;
+            }
+        }
+    }
+
     if (tracker->focus == EDIT_PROGRAM)
     {
         uint16_t opcode = (inst->program[tracker->current_program_step] & 0x7fff);