Просмотр исходного кода

ADSR (tested), ringmod and hardsync (untested), initial data structure for tracker engine and song, test timer interrupt for tracker engine (works!)

LTVA1 3 лет назад
Родитель
Сommit
ef7a0e3b4a

+ 28 - 20
flizzer_tracker.c

@@ -85,38 +85,42 @@ static void draw_callback(Canvas* canvas, void* ctx)
 
 	char buffer[30] = {0};
 
-	snprintf(buffer, 20, "FREQUENCY: %ld Hz", tracker->frequency);
+	snprintf(buffer, 20, "FREQUENCY:%ld Hz", tracker->frequency);
 	
 	canvas_draw_str(canvas, 0, 6, buffer);
 
-	snprintf(buffer, 20, "WAVEFORM: %s", wave_names[tracker->current_waveform_index]);
+	snprintf(buffer, 20, "WAVEFORM:%s", wave_names[tracker->current_waveform_index]);
 	
 	canvas_draw_str(canvas, 0, 12, buffer);
 
-	snprintf(buffer, 20, "PULSE WIDTH: $%03X", tracker->pw);
+	snprintf(buffer, 20, "PULSE WIDTH:$%03X", tracker->pw);
 	
 	canvas_draw_str(canvas, 0, 18, buffer);
 
-	snprintf(buffer, 20, "FILTER: %s", (tracker->flags & SE_ENABLE_FILTER) ? "ENABLED" : "DISABLED");
+	snprintf(buffer, 20, "FILTER:%s", (tracker->flags & SE_ENABLE_FILTER) ? "ENABLED" : "DISABLED");
 
 	canvas_draw_str(canvas, 0, 24, buffer);
 
-	snprintf(buffer, 20, "CUTOFF: %d", tracker->cutoff);
+	snprintf(buffer, 20, "CUTOFF:%d", tracker->cutoff);
 	
 	canvas_draw_str(canvas, 0, 30, buffer);
 
-	snprintf(buffer, 20, "RESONANCE: %d", tracker->resonance);
+	snprintf(buffer, 20, "RESONANCE:%d", tracker->resonance);
 	
 	canvas_draw_str(canvas, 0, 36, buffer);
 
-	snprintf(buffer, 20, "TYPE: %s", filter_names[tracker->filter_type]);
+	snprintf(buffer, 20, "TYPE:%s", filter_names[tracker->filter_type]);
 	
 	canvas_draw_str(canvas, 0, 42, buffer);
 
+	snprintf(buffer, 20, "TR.ENG.CALLS: %d", tracker->tracker_engine.absolute_position);
+	
+	canvas_draw_str(canvas, 0, 48, buffer);
+
 	canvas_draw_str(canvas, 70, tracker->selected_param * 6 + 6, "<");
 
     uint32_t bytes = memmgr_get_free_heap();
-	snprintf(buffer, 20, "BYTES FREE: %ld", bytes);
+	snprintf(buffer, 20, "BYTES FREE:%ld", bytes);
 
 	canvas_draw_str(canvas, 0, 64, buffer);
 }
@@ -151,7 +155,7 @@ int32_t flizzer_tracker_app(void* p)
 	// Очередь событий на 8 элементов размера FlizzerTrackerEvent
 	FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(FlizzerTrackerEvent));
 
-	FlizzerTrackerApp* tracker = malloc(sizeof(FlizzerTrackerApp));
+	FlizzerTrackerApp* tracker = init_tracker(44100, 50, true, 1024);
 
 	// Создаем новый view port
 	ViewPort* view_port = view_port_alloc();
@@ -169,8 +173,6 @@ int32_t flizzer_tracker_app(void* p)
 	tracker->notification = furi_record_open(RECORD_NOTIFICATION);
 	notification_message(tracker->notification, &sequence_display_backlight_enforce_on);
 
-	init_tracker(tracker, 44100, true, 1024);
-
 	tracker->sound_engine.channel[0].waveform = SE_WAVEFORM_NOISE;
 
 	tracker->frequency = 440;
@@ -178,7 +180,17 @@ int32_t flizzer_tracker_app(void* p)
 
 	sound_engine_set_channel_frequency(&tracker->sound_engine, &tracker->sound_engine.channel[0], 440 * 1024);
 
-	sound_engine_start();
+	tracker->sound_engine.channel[0].adsr.a = 0x10;
+	tracker->sound_engine.channel[0].adsr.d = 0x10;
+	tracker->sound_engine.channel[0].adsr.s = 0xff;
+	tracker->sound_engine.channel[0].adsr.volume = 0x80;
+	tracker->sound_engine.channel[0].adsr.envelope_state = ATTACK;
+
+	SoundEngine* eng = &(tracker->sound_engine);
+
+	tracker->sound_engine.channel[0].adsr.envelope_speed = envspd(eng, tracker->sound_engine.channel[0].adsr.a);
+
+	play();
 
 	// Бесконечный цикл обработки очереди событий
 	while(1) 
@@ -202,12 +214,12 @@ int32_t flizzer_tracker_app(void* p)
 
 				if(tracker->playing)
 				{
-					sound_engine_start();
+					play();
 				}
 
 				else
 				{
-					sound_engine_stop();
+					stop();
 				}
 			}
 
@@ -272,8 +284,6 @@ int32_t flizzer_tracker_app(void* p)
 					case PARAM_ENABLE_FILTER:
 					{
 						tracker->flags ^= SE_ENABLE_FILTER;
-
-						tracker->sound_engine.channel[0].filter_mode = FIL_OUTPUT_LOWPASS;
 						
 						tracker->sound_engine.channel[0].flags = tracker->flags;
 
@@ -364,8 +374,6 @@ int32_t flizzer_tracker_app(void* p)
 					case PARAM_ENABLE_FILTER:
 					{
 						tracker->flags ^= SE_ENABLE_FILTER;
-
-						tracker->sound_engine.channel[0].filter_mode = FIL_OUTPUT_LOWPASS;
 						
 						tracker->sound_engine.channel[0].flags = tracker->flags;
 
@@ -411,7 +419,7 @@ int32_t flizzer_tracker_app(void* p)
 		}
 	}
 
-	deinit_tracker(tracker);
+	stop();
 
 	notification_message(tracker->notification, &sequence_display_backlight_enforce_auto);
 	furi_record_close(RECORD_NOTIFICATION);
@@ -424,7 +432,7 @@ int32_t flizzer_tracker_app(void* p)
 	view_port_free(view_port);
 	furi_record_close(RECORD_GUI);
 
-	free(tracker);
+	deinit_tracker(tracker);
 
 	return 0;
 }

+ 5 - 0
flizzer_tracker.h

@@ -10,6 +10,8 @@
 #include "flizzer_tracker_hal.h"
 #include "sound_engine/freqs.h"
 #include "sound_engine/sound_engine_filter.h"
+#include "sound_engine/sound_engine_defs.h"
+#include "tracker_engine/tracker_engine_defs.h"
 
 typedef struct 
 {
@@ -19,6 +21,9 @@ typedef struct
 	NotificationApp* notification;
 
 	SoundEngine sound_engine;
+	TrackerEngine tracker_engine;
+
+	TrackerSong song;
 
 	uint32_t frequency;
 	uint8_t current_waveform_index;

+ 58 - 10
flizzer_tracker_hal.c

@@ -1,16 +1,6 @@
 #include "flizzer_tracker_hal.h"
 #include "flizzer_tracker.h"
 
-#define SPEAKER_PWM_TIMER TIM16
-#define SAMPLE_RATE_TIMER TIM2
-#define TRACKER_ENGINE_TIMER TIM1
-
-#define SPEAKER_PWM_TIMER_CHANNEL LL_TIM_CHANNEL_CH1
-
-#define TIMER_BASE_CLOCK 64000000 /* CPU frequency, 64 MHz */
-
-#define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1
-
 void sound_engine_dma_isr(void* ctx)
 {
 	SoundEngine* sound_engine = (SoundEngine*)ctx;
@@ -36,6 +26,18 @@ void sound_engine_dma_isr(void* ctx)
 	}
 }
 
+void tracker_engine_timer_isr(void* ctx)
+{
+	if(LL_TIM_IsActiveFlag_UPDATE(TIM1)) 
+	{
+		LL_TIM_ClearFlag_UPDATE(TIM1);
+	}
+
+	TrackerEngine* tracker_engine = (TrackerEngine*)ctx;
+
+	tracker_engine_advance_tick(tracker_engine);
+}
+
 void sound_engine_PWM_timer_init(bool external_audio_output) //external audio on pin PA6
 {
 	LL_TIM_InitTypeDef TIM_InitStruct = {0};
@@ -78,6 +80,28 @@ void sound_engine_timer_init(uint32_t sample_rate) //external audio on pin PA6
 	LL_TIM_OC_Init(SAMPLE_RATE_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
 }
 
+void tracker_engine_timer_init(uint8_t rate) //0-255 hz
+{
+	LL_TIM_InitTypeDef TIM_InitStruct = {0};
+	LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
+
+	TIM_InitStruct.Prescaler = 976 - 1; //so with highest autoreload you get 1 Hz
+	TIM_InitStruct.Autoreload = (TIMER_BASE_CLOCK / 976) / rate; //to support various rates
+	TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
+	LL_TIM_Init(TRACKER_ENGINE_TIMER, &TIM_InitStruct);
+
+	TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
+	TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
+	LL_TIM_OC_Init(TRACKER_ENGINE_TIMER, SPEAKER_PWM_TIMER_CHANNEL, &TIM_OC_InitStruct);
+
+	LL_TIM_EnableIT_UPDATE(TRACKER_ENGINE_TIMER);
+}
+
+void tracker_engine_init_hardware(uint8_t rate)
+{
+	tracker_engine_timer_init(rate);
+}
+
 void sound_engine_dma_init(uint32_t address, uint32_t size)
 {
 	uint32_t dma_dst = (uint32_t) & (SPEAKER_PWM_TIMER->CCR1);
@@ -136,4 +160,28 @@ void sound_engine_stop()
 	LL_TIM_DisableCounter(SPEAKER_PWM_TIMER);
 
 	sound_engine_dma_stop();
+}
+
+void tracker_engine_start()
+{
+	LL_TIM_EnableAllOutputs(TRACKER_ENGINE_TIMER);
+	LL_TIM_EnableCounter(TRACKER_ENGINE_TIMER);
+}
+
+void tracker_engine_stop()
+{
+	LL_TIM_DisableAllOutputs(TRACKER_ENGINE_TIMER);
+	LL_TIM_DisableCounter(TRACKER_ENGINE_TIMER);
+}
+
+void play()
+{
+	tracker_engine_start();
+	sound_engine_start();
+}
+
+void stop()
+{
+	sound_engine_stop();
+	tracker_engine_stop();
 }

+ 18 - 6
flizzer_tracker_hal.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "sound_engine/sound_engine.h"
+#include "tracker_engine/tracker_engine.h"
 
 #include <stm32wbxx_ll_tim.h>
 #include <stm32wbxx_ll_dma.h>
@@ -10,12 +11,23 @@
 #include <furi_hal_gpio.h>
 #include <furi_hal_resources.h>
 
+#define SPEAKER_PWM_TIMER TIM16
+#define SAMPLE_RATE_TIMER TIM2
+#define TRACKER_ENGINE_TIMER TIM1
+
+#define SPEAKER_PWM_TIMER_CHANNEL LL_TIM_CHANNEL_CH1
+
+#define TIMER_BASE_CLOCK 64000000 /* CPU frequency, 64 MHz */
+
+#define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1
+
 void sound_engine_dma_isr(void* ctx);
-void sound_engine_PWM_timer_init(bool external_audio_output);
-void sound_engine_timer_init(uint32_t sample_rate);
-void sound_engine_dma_init(uint32_t address, uint32_t size);
+void tracker_engine_timer_isr(void* ctx);
 void sound_engine_init_hardware(uint32_t sample_rate, bool external_audio_output, uint16_t* audio_buffer, uint32_t audio_buffer_size);
-void sound_engine_dma_start();
-void sound_engine_dma_stop();
+void tracker_engine_init_hardware(uint8_t rate);
 void sound_engine_start();
-void sound_engine_stop();
+void sound_engine_stop();
+void stop();
+void play();
+void tracker_engine_stop();
+void tracker_engine_start();

+ 15 - 4
init_deinit.c

@@ -1,17 +1,28 @@
 #include "init_deinit.h"
 
-void init_tracker(FlizzerTrackerApp* tracker, uint32_t sample_rate, bool external_audio_output, uint32_t audio_buffer_size)
+FlizzerTrackerApp* init_tracker(uint32_t sample_rate, uint8_t rate, bool external_audio_output, uint32_t audio_buffer_size)
 {
+	FlizzerTrackerApp* tracker = malloc(sizeof(FlizzerTrackerApp));
+	memset(tracker, 0, sizeof(FlizzerTrackerApp));
+
 	sound_engine_init(&tracker->sound_engine, sample_rate, external_audio_output, audio_buffer_size);
+	tracker_engine_init(&tracker->tracker_engine, rate, &tracker->sound_engine);
+
+	tracker->tracker_engine.song = &tracker->song;
+
+	return tracker;
 }
 
 void deinit_tracker(FlizzerTrackerApp* tracker)
 {
 	sound_engine_deinit(&tracker->sound_engine);
+	tracker_engine_deinit(&tracker->tracker_engine);
 
 	FURI_CRITICAL_ENTER();
-	LL_TIM_DeInit(TIM1);
-	LL_TIM_DeInit(TIM2);
-	LL_TIM_DeInit(TIM16);
+	LL_TIM_DeInit(TRACKER_ENGINE_TIMER);
+	LL_TIM_DeInit(SAMPLE_RATE_TIMER);
+	LL_TIM_DeInit(SPEAKER_PWM_TIMER);
 	FURI_CRITICAL_EXIT();
+
+	free(tracker);
 }

+ 1 - 1
init_deinit.h

@@ -3,5 +3,5 @@
 #include "flizzer_tracker_hal.h"
 #include "flizzer_tracker.h"
 
-void init_tracker(FlizzerTrackerApp* tracker, uint32_t sample_rate, bool external_audio_output, uint32_t audio_buffer_size);
+FlizzerTrackerApp* init_tracker(uint32_t sample_rate, uint8_t rate, bool external_audio_output, uint32_t audio_buffer_size);
 void deinit_tracker(FlizzerTrackerApp* tracker);

+ 31 - 9
sound_engine/sound_engine.c

@@ -1,5 +1,4 @@
 #include "sound_engine.h"
-#include "../flizzer_tracker.h"
 #include "../flizzer_tracker_hal.h"
 
 #include <furi_hal.h>
@@ -9,6 +8,7 @@
 void sound_engine_init(SoundEngine* sound_engine, uint32_t sample_rate, bool external_audio_output, uint32_t audio_buffer_size)
 {
 	sound_engine->audio_buffer = malloc(audio_buffer_size * sizeof(sound_engine->audio_buffer[0]));
+	memset(sound_engine->audio_buffer, 0, sizeof(SoundEngine));
 	sound_engine->audio_buffer_size = audio_buffer_size;
 	sound_engine->sample_rate = sample_rate;
 	sound_engine->external_audio_output = external_audio_output;
@@ -56,6 +56,9 @@ void sound_engine_set_channel_frequency(SoundEngine* sound_engine, SoundEngineCh
 
 void sound_engine_fill_buffer(SoundEngine* sound_engine, uint16_t* audio_buffer, uint32_t audio_buffer_size)
 {
+	int32_t channel_output[NUM_CHANNELS];
+	int32_t channel_output_final[NUM_CHANNELS];
+
 	for(uint32_t i = 0; i < audio_buffer_size; ++i)
 	{
 		int32_t output = WAVE_AMP / 2 / 64;
@@ -64,44 +67,63 @@ void sound_engine_fill_buffer(SoundEngine* sound_engine, uint16_t* audio_buffer,
 		{
 			SoundEngineChannel* channel = &sound_engine->channel[chan];
 
-			int32_t channel_output = 0;
-
 			if(channel->frequency > 0)
 			{
 				uint32_t prev_acc = channel->accumulator;
 
 				channel->accumulator += channel->frequency;
+
+				channel->sync_bit |= (channel->accumulator & ACC_LENGTH);
+
 				channel->accumulator &= ACC_LENGTH - 1;
 
-				channel_output += sound_engine_osc(sound_engine, channel, prev_acc) - WAVE_AMP / 2;
+				if(channel->flags & SE_ENABLE_HARD_SYNC)
+				{
+					uint8_t hard_sync_src = channel->hard_sync == 0xff ? i : channel->hard_sync;
+					
+					if(sound_engine->channel[hard_sync_src].sync_bit)
+					{
+						channel->accumulator = 0;
+					}
+				}
+
+				channel_output[chan] = sound_engine_osc(sound_engine, channel, prev_acc) - WAVE_AMP / 2;
+
+				if(channel->flags & SE_ENABLE_RING_MOD)
+				{
+					uint8_t ring_mod_src = channel->ring_mod == 0xff ? i : channel->ring_mod;
+					channel_output[chan] = channel_output[chan] * channel_output[ring_mod_src] / WAVE_AMP;
+				}
 
+				channel_output_final[chan] = sound_engine_cycle_and_output_adsr(channel_output[chan], sound_engine, &channel->adsr, &channel->flags);
+				
 				if(channel->flags & SE_ENABLE_FILTER)
 				{
-					sound_engine_filter_cycle(&channel->filter, channel_output);
+					sound_engine_filter_cycle(&channel->filter, channel_output[i]);
 
 					switch(channel->filter_mode)
 					{
 						case FIL_OUTPUT_LOWPASS:
 						{
-							channel_output = sound_engine_output_lowpass(&channel->filter);
+							channel_output_final[chan] = sound_engine_output_lowpass(&channel->filter);
 							break;
 						}
 
 						case FIL_OUTPUT_HIGHPASS:
 						{
-							channel_output = sound_engine_output_highpass(&channel->filter);
+							channel_output_final[chan] = sound_engine_output_highpass(&channel->filter);
 							break;
 						}
 
 						case FIL_OUTPUT_BANDPASS:
 						{
-							channel_output = sound_engine_output_bandpass(&channel->filter);
+							channel_output_final[chan] = sound_engine_output_bandpass(&channel->filter);
 							break;
 						}
 					}
 				}
 
-				output += ((channel_output) / (64 * 4)); //2 more bits so all channels fit
+				output += ((channel_output_final[chan]) / (64 * 4)); //2 more bits so all channels fit
 			}
 		}
 

+ 1 - 0
sound_engine/sound_engine.h

@@ -3,6 +3,7 @@
 #include "sound_engine_osc.h"
 #include "sound_engine_filter.h"
 #include "sound_engine_defs.h"
+#include "sound_engine_adsr.h"
 
 void sound_engine_init(SoundEngine* sound_engine, uint32_t sample_rate, bool external_audio_output, uint32_t audio_buffer_size);
 void sound_engine_deinit(SoundEngine* sound_engine);

+ 65 - 0
sound_engine/sound_engine_adsr.c

@@ -0,0 +1,65 @@
+#include "sound_engine_adsr.h"
+
+int32_t sound_engine_cycle_and_output_adsr(int32_t input, SoundEngine* eng, SoundEngineADSR* adsr, uint16_t* flags)
+{
+	switch(adsr->envelope_state)
+	{
+		case ATTACK:
+		{
+			adsr->envelope += adsr->envelope_speed;
+			
+			if (adsr->envelope >= MAX_ADSR) 
+			{
+				adsr->envelope_state = DECAY;
+				adsr->envelope = MAX_ADSR;
+
+				adsr->envelope_speed = envspd(eng, adsr->d);
+			}
+
+			break;
+		}
+
+		case DECAY:
+		{
+			if (adsr->envelope > ((uint32_t)adsr->s << 17) + adsr->envelope_speed)
+			{
+				adsr->envelope -= adsr->envelope_speed;
+			}
+			
+			else
+			{
+				adsr->envelope = (uint32_t)adsr->s << 17;
+				adsr->envelope_state = (adsr->s == 0) ? RELEASE : SUSTAIN;
+				
+				adsr->envelope_speed = envspd(eng, adsr->r);
+			}
+
+			break;
+		}
+
+		case SUSTAIN:
+		case DONE:
+		{
+			break;
+		}
+
+		case RELEASE:
+		{
+			if (adsr->envelope > adsr->envelope_speed)
+			{
+				adsr->envelope -= adsr->envelope_speed;
+			}
+			
+			else 
+			{
+				adsr->envelope_state = DONE;
+				*flags &= ~SE_ENABLE_GATE;
+				adsr->envelope = 0;
+			}
+
+			break;
+		}
+	}
+
+	return (int32_t)((int64_t)input * adsr->envelope / MAX_ADSR * (int64_t)adsr->volume / MAX_ADSR_VOLUME);
+}

+ 5 - 0
sound_engine/sound_engine_adsr.h

@@ -0,0 +1,5 @@
+#pragma once
+
+#include "sound_engine_defs.h"
+
+int32_t sound_engine_cycle_and_output_adsr(int32_t input, SoundEngine* eng, SoundEngineADSR* adsr, uint16_t* flags);

+ 19 - 3
sound_engine/sound_engine_defs.h

@@ -16,6 +16,11 @@
 #define SINE_LUT_SIZE 256
 #define SINE_LUT_BITDEPTH 8
 
+#define MAX_ADSR (0xff << 17)
+#define MAX_ADSR_VOLUME 0x80
+#define BASE_FREQ 22050
+#define envspd(eng, slope) ((slope) != 0 ? (((uint64_t)MAX_ADSR / ((slope) * (slope) * 256)) * BASE_FREQ / eng->sample_rate) : ((uint64_t)MAX_ADSR * BASE_FREQ / eng->sample_rate))
+
 typedef enum
 {
 	SE_WAVEFORM_NONE = 0,
@@ -43,11 +48,19 @@ typedef enum
 	FIL_OUTPUT_BANDPASS = 3,
 } SoundEngineFilterModes;
 
+typedef enum
+{
+	ATTACK = 1,
+	DECAY = 2,
+	SUSTAIN = 3,
+	RELEASE = 4,
+	DONE = 5,
+} SoundEngineEnvelopeStates;
+
 typedef struct
 {
-	uint8_t a, d, s, r, volume;
-	uint32_t envelope;
-	int32_t envelope_speed;
+	uint8_t a, d, s, r, volume, envelope_state;
+	uint32_t envelope, envelope_speed;
 } SoundEngineADSR;
 
 typedef struct
@@ -67,6 +80,9 @@ typedef struct
 
 	uint16_t flags;
 
+	uint8_t ring_mod, hard_sync; //0xff = self
+	uint8_t sync_bit;
+
 	uint8_t filter_mode;
 	uint16_t filter_cutoff;
 	uint16_t filter_resonace;

+ 25 - 0
tracker_engine/tracker_engine.c

@@ -0,0 +1,25 @@
+#include "tracker_engine.h"
+
+#include "../flizzer_tracker_hal.h"
+
+#include <furi_hal.h>
+
+void tracker_engine_init(TrackerEngine* tracker_engine, uint8_t rate, SoundEngine* sound_engine)
+{
+	furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTim1UpTim16, 14, tracker_engine_timer_isr, (void*)tracker_engine);
+	tracker_engine_init_hardware(rate);
+
+	tracker_engine->sound_engine = sound_engine;
+}
+
+void tracker_engine_deinit(TrackerEngine* tracker_engine)
+{
+	UNUSED(tracker_engine);
+	furi_hal_interrupt_set_isr_ex(FuriHalInterruptIdTim1UpTim16, 13, NULL, NULL);
+	tracker_engine_stop();
+}
+
+void tracker_engine_advance_tick(TrackerEngine* tracker_engine)
+{
+	tracker_engine->absolute_position++;
+}

+ 7 - 0
tracker_engine/tracker_engine.h

@@ -0,0 +1,7 @@
+#pragma once
+
+#include "tracker_engine_defs.h"
+
+void tracker_engine_init(TrackerEngine* tracker_engine, uint8_t rate, SoundEngine* sound_engine);
+void tracker_engine_deinit(TrackerEngine* tracker_engine);
+void tracker_engine_advance_tick(TrackerEngine* tracker_engine);

+ 145 - 0
tracker_engine/tracker_engine_defs.h

@@ -0,0 +1,145 @@
+#pragma once
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "../sound_engine/sound_engine_defs.h"
+
+#define INST_PROG_LEN 16
+#define MUS_SONG_NAME_LEN 17
+#define MUS_INST_NAME_LEN (MUS_SONG_NAME_LEN - 3)
+
+#define SONG_MAX_CHANNELS NUM_CHANNELS
+#define MAX_INSTRUMENTS 31
+#define MAX_PATTERN_LENGTH 256
+#define MAX_SEQUENCE_LENGTH 256
+
+#define MUS_NOTE_NONE 127
+#define MUS_NOTE_RELEASE 126
+
+#define MUS_NOTE_INSTRUMENT_NONE 31
+#define MUS_NOTE_VOLUME_NONE 31
+
+#define SONG_FILE_SIG "FLZ!SONG"
+
+#define TRACKER_ENGINE_VERSION 1
+
+typedef enum
+{
+	TE_ENABLE_VIBRATO = 1,
+	TE_ENABLE_PWM = 2,
+	TE_PROG_NO_RESTART = 4,
+	TE_SET_CUTOFF = 8,
+	TE_SET_PW = 16,
+	TE_KEY_SYNC = 32, //sync oscillators on keydown
+	TE_RETRIGGER_ON_SLIDE = 64, //call trigger instrument function even if slide command is there
+} TrackerEngineFlags;
+
+typedef enum
+{
+	TEC_PLAYING = 1,
+	TEC_PROGRAM_RUNNING = 2,
+	TEC_DISABLED = 4,
+} TrackerEngineChannelFlags;
+
+typedef struct
+{
+	uint8_t a, d, s, r, volume;
+} InstrumentAdsr;
+
+typedef struct
+{
+	char name[MUS_INST_NAME_LEN];
+
+	uint16_t flags;
+	uint16_t sound_engine_flags;
+
+	InstrumentAdsr adsr;
+
+	uint8_t ring_mod, hard_sync; //0xff = self
+
+	uint8_t pw, cutoff; //store only one byte since we don't have the luxury of virtually unlimited memory!
+
+	uint16_t program[INST_PROG_LEN]; //MSB is unite bit (indicates this and mext command must be executed at once)
+	uint8_t program_period;
+
+	uint8_t vibrato_speed, vibrato_depth, vibrato_delay;
+	uint8_t pwm_speed, pwm_depth, pwm_delay;
+
+	uint8_t filter_cutoff, filter_resonance, filter_type;
+
+	int8_t finetune;
+} Instrument;
+
+typedef struct
+{
+	Instrument* inst;
+
+	uint16_t flags;
+
+	uint8_t channel_flags;
+
+	uint16_t note, target_note, last_note;
+	uint8_t volume;
+
+	uint8_t program_counter, program_tick, program_loop, prog_period;
+
+	uint16_t filter_cutoff;
+	uint8_t filter_resonance, filter_type;
+
+	uint8_t vibrato_speed, vibrato_depth, vibrato_delay;
+	uint8_t pwm_speed, pwm_depth, pwm_delay;
+
+	uint16_t vibrato_position, pwm_position;
+
+	uint8_t extarp1, extarp2;
+
+	uint16_t pw;
+} TrackerEngineChannel;
+
+typedef struct
+{
+	uint8_t note; //MSB is used for instrument number MSB
+	uint8_t inst_vol; //high nibble + MSB from note = instrument, low nibble = 4 volume LSBs
+	uint16_t command; //MSB used as volume MSB
+} TrackerSongPatternStep;
+
+typedef struct
+{
+	TrackerSongPatternStep* step;
+} TrackerSongPattern;
+
+typedef struct
+{
+	uint8_t pattern_indices[SONG_MAX_CHANNELS];
+} TrackerSongSequenceStep;
+
+typedef struct
+{
+	TrackerSongSequenceStep* sequence[MAX_SEQUENCE_LENGTH];
+} TrackerSongSequence;
+
+typedef struct
+{
+	Instrument* instrument;
+	TrackerSongPattern* pattern;
+	TrackerSongSequence* sequence;
+
+	uint8_t num_patterns, num_sequence_steps, num_instruments;
+
+	char song_name[MUS_SONG_NAME_LEN];
+	uint8_t speed, rate;
+} TrackerSong;
+
+typedef struct
+{
+	TrackerEngineChannel channel[SONG_MAX_CHANNELS];
+
+	TrackerSong* song;
+	SoundEngine* sound_engine;
+
+	uint8_t pattern_position, sequence_position, current_tick, song_speed;
+	uint16_t absolute_position; //sequence_position * sequence_length + pattern_position
+
+	uint8_t speed, rate;
+} TrackerEngine;