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

fixed highpass and bandpass filters, moved filter and oscillator functions to their own files

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

+ 18 - 3
flizzer_tracker.c

@@ -183,7 +183,7 @@ int32_t flizzer_tracker_app(void* p)
 	// Бесконечный цикл обработки очереди событий
 	while(1) 
 	{
-		// Выбираем событие из очереди в переменную event (ждем бесконечно долго, если очередь пуста)
+		// Выбираем событие из очереди в переменную event (ждём бесконечно долго, если очередь пуста)
 		// и проверяем, что у нас получилось это сделать
 		furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk);
 
@@ -196,6 +196,21 @@ int32_t flizzer_tracker_app(void* p)
 				break;
 			}
 
+			if(event.input.key == InputKeyOk && event.input.type == InputTypeShort) 
+			{
+				tracker->playing = !(tracker->playing);
+
+				if(tracker->playing)
+				{
+					sound_engine_start();
+				}
+
+				else
+				{
+					sound_engine_stop();
+				}
+			}
+
 			if(event.input.key == InputKeyUp && event.input.type == InputTypeShort) 
 			{
 				if(tracker->selected_param > 0)
@@ -276,7 +291,7 @@ int32_t flizzer_tracker_app(void* p)
 						
 						tracker->sound_engine.channel[0].filter_cutoff = tracker->cutoff;
 
-						sound_engine_filter_set_coeff(&tracker->sound_engine.channel[0].filter, tracker->cutoff, tracker->resonance);
+						sound_engine_filter_set_coeff(&tracker->sound_engine.channel[0].filter, tracker->cutoff, tracker->resonance * 50);
 
 						break;
 					}
@@ -365,7 +380,7 @@ int32_t flizzer_tracker_app(void* p)
 						}
 						
 						tracker->sound_engine.channel[0].filter_cutoff = tracker->cutoff;
-						sound_engine_filter_set_coeff(&tracker->sound_engine.channel[0].filter, tracker->cutoff, tracker->resonance);
+						sound_engine_filter_set_coeff(&tracker->sound_engine.channel[0].filter, tracker->cutoff, tracker->resonance * 50);
 
 						break;
 					}

+ 3 - 0
flizzer_tracker.h

@@ -9,6 +9,7 @@
 
 #include "flizzer_tracker_hal.h"
 #include "sound_engine/freqs.h"
+#include "sound_engine/sound_engine_filter.h"
 
 typedef struct 
 {
@@ -29,4 +30,6 @@ typedef struct
 	uint16_t cutoff;
 	uint8_t resonance;
 	uint8_t filter_type;
+
+	bool playing;
 } FlizzerTrackerApp;

+ 1 - 1
flizzer_tracker_hal.c

@@ -53,7 +53,7 @@ void sound_engine_PWM_timer_init(bool external_audio_output) //external audio on
 
 	if(external_audio_output)
 	{
-		furi_hal_gpio_init_ex(&gpio_ext_pa6, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn14TIM16);
+		furi_hal_gpio_init_ex(&gpio_ext_pa6, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16);
 	}
 
 	else

+ 2 - 135
sound_engine/sound_engine.c

@@ -54,144 +54,11 @@ void sound_engine_set_channel_frequency(SoundEngine* sound_engine, SoundEngineCh
 	}
 }
 
-static inline uint16_t sound_engine_pulse(uint32_t acc, uint32_t pw) //0-FFF pulse width range
-{
-	return (((acc >> (((uint32_t)ACC_BITS - 17))) >= ((pw == 0xfff ? pw + 1 : pw) << 4) ? (WAVE_AMP - 1) : 0));
-}
-
-
-static inline uint16_t sound_engine_saw(uint32_t acc) 
-{
-	return (acc >> (ACC_BITS - OUTPUT_BITS - 1)) & (WAVE_AMP - 1);
-}
-
-
-static inline uint16_t sound_engine_triangle(uint32_t acc)
-{
-	return ((((acc & (ACC_LENGTH / 2)) ? ~acc : acc) >> (ACC_BITS - OUTPUT_BITS - 2)) & (WAVE_AMP * 2 - 1));
-}
-
-static inline uint16_t sound_engine_sine(uint32_t acc, SoundEngine* sound_engine) 
-{
-	return (sound_engine->sine_lut[(acc >> (ACC_BITS - SINE_LUT_BITDEPTH))] << (OUTPUT_BITS - SINE_LUT_BITDEPTH));
-}
-
-inline static void shift_lfsr(uint32_t* v, uint32_t tap_0, uint32_t tap_1)
-{
-	typedef uint32_t T;
-	const T zero = (T)(0);
-	const T lsb = zero + (T)(1);
-	const T feedback = (
-		(lsb << (tap_0)) ^
-		(lsb << (tap_1))
-	);
-
-	*v = (*v >> 1) ^ ((zero - (*v & lsb)) & feedback);
-}
-
-uint16_t sound_engine_osc(SoundEngine* sound_engine, SoundEngineChannel* channel, uint32_t prev_acc)
-{
-	switch(channel->waveform)
-	{
-		case SE_WAVEFORM_NOISE:
-		{
-			if((prev_acc & (ACC_LENGTH / 32)) != (channel->accumulator & (ACC_LENGTH / 32)))
-			{
-				shift_lfsr(&channel->lfsr, 22, 17);
-				channel->lfsr &= (1 << (22 + 1)) - 1;
-			}
-
-			return (channel->lfsr) & (WAVE_AMP - 1);
-
-			break;
-		}
-
-		case SE_WAVEFORM_PULSE:
-		{
-			return sound_engine_pulse(channel->accumulator, channel->pw);
-			break;
-		}
-
-		case SE_WAVEFORM_TRIANGLE:
-		{
-			return sound_engine_triangle(channel->accumulator);
-			break;
-		}
-		
-		case SE_WAVEFORM_SAW:
-		{
-			return sound_engine_saw(channel->accumulator);
-			break;
-		}
-
-		case SE_WAVEFORM_NOISE_METAL:
-		{
-			if((prev_acc & (ACC_LENGTH / 32)) != (channel->accumulator & (ACC_LENGTH / 32)))
-			{
-				shift_lfsr(&channel->lfsr, 14, 8);
-				channel->lfsr &= (1 << (14 + 1)) - 1;
-			}
-
-			return (channel->lfsr) & (WAVE_AMP - 1);
-
-			break;
-		}
-
-		case SE_WAVEFORM_SINE:
-		{
-			return sound_engine_sine(channel->accumulator, sound_engine);
-			break;
-		}
-	}
-
-	return 0;
-}
-
-void sound_engine_filter_set_coeff(SoundEngineFilter *flt, uint32_t frequency, uint16_t resonance)
-{
-	flt->q = 2048 - frequency;
-	flt->p = frequency + ((int32_t)(0.8f * 2048.0f) * frequency / 2048 * flt->q) / 2048;
-	flt->f = flt->p + flt->p - 2048;
-	flt->q = resonance;
-}
-
-void sound_engine_filter_cycle(SoundEngineFilter* flt, int32_t input)
-{
-	input -= flt->q * flt->b4 / 2048; //feedback
-	int32_t t1 = flt->b1;  
-	flt->b1 = (input + flt->b0) * flt->p / 2048 - flt->b1 * flt->f / 2048;
-	int32_t t2 = flt->b2;  
-	flt->b2 = (flt->b1 + t1) * flt->p / 2048 - flt->b2 * flt->f / 2048;
-	t1 = flt->b3;
-	flt->b3 = (flt->b2 + t2) * flt->p / 2048 - flt->b3 * flt->f / 2048;
-	flt->b4 = (flt->b3 + t1) * flt->p / 2048 - flt->b4 * flt->f / 2048;
-	
-	//flt->b4 = my_min(32767, my_max(-32768, flt->b4));    //clipping
-	
-	flt->b0 = input;
-}
-
-int32_t sound_engine_output_lowpass(SoundEngineFilter* flt)
-{
-	return flt->b4;
-}
-
-int32_t sound_engine_output_highpass(SoundEngineFilter* flt)
-{
-	return flt->b0 - flt->b4;
-}
-
-
-int32_t sound_engine_output_bandpass(SoundEngineFilter* flt)
-{
-	return 3 * (flt->b3 - flt->b4);
-}
-
 void sound_engine_fill_buffer(SoundEngine* sound_engine, uint16_t* audio_buffer, uint32_t audio_buffer_size)
 {
 	for(uint32_t i = 0; i < audio_buffer_size; ++i)
 	{
-		int32_t output = 0;
+		int32_t output = WAVE_AMP / 2 / 64;
 
 		for(uint32_t chan = 0; chan < NUM_CHANNELS; ++chan)
 		{
@@ -234,7 +101,7 @@ void sound_engine_fill_buffer(SoundEngine* sound_engine, uint16_t* audio_buffer,
 					}
 				}
 
-				output += ((channel_output + WAVE_AMP / 2) >> (6 + 2)); //2 more bits so all channels fit
+				output += ((channel_output) / (64 * 4)); //2 more bits so all channels fit
 			}
 		}
 

+ 4 - 84
sound_engine/sound_engine.h

@@ -1,90 +1,10 @@
 #pragma once
 
-#include <stdio.h>
-#include <stdbool.h>
-
-#define NUM_CHANNELS 4
-
-#define RANDOM_SEED 0xf31782ce
-
-#define ACC_BITS 23
-#define ACC_LENGTH (1 << (ACC_BITS - 1))
-
-#define OUTPUT_BITS 16
-#define WAVE_AMP (1 << OUTPUT_BITS)
-
-#define SINE_LUT_SIZE 256
-#define SINE_LUT_BITDEPTH 8
-
-typedef enum
-{
-	SE_WAVEFORM_NONE = 0,
-	SE_WAVEFORM_NOISE = 1,
-	SE_WAVEFORM_PULSE = 2,
-	SE_WAVEFORM_TRIANGLE = 4,
-	SE_WAVEFORM_SAW = 8,
-	SE_WAVEFORM_NOISE_METAL = 16,
-	SE_WAVEFORM_SINE = 32,
-} SoudEngineWaveformType;
-
-typedef enum
-{
-	SE_ENABLE_FILTER = 1,
-	SE_ENABLE_GATE = 2,
-	SE_ENABLE_RING_MOD = 4,
-	SE_ENABLE_HARD_SYNC = 8,
-	SE_ENABLE_KEYDOWN_SYNC = 16, //sync oscillators on keydown
-} SoundEngineFlags;
-
-typedef enum
-{
-	FIL_OUTPUT_LOWPASS = 1,
-	FIL_OUTPUT_HIGHPASS = 2,
-	FIL_OUTPUT_BANDPASS = 3,
-} SoundEngineFilterModes;
-
-typedef struct
-{
-	uint8_t a, d, s, r, volume;
-	uint32_t envelope, envelope_speed;
-} SoundEngineADSR;
-
-typedef struct
-{
-	int32_t f, q, p;
-	int32_t b0, b1, b2, b3, b4; //filter coefficients
-} SoundEngineFilter;
-
-typedef struct
-{
-	uint32_t accumulator;
-	uint32_t frequency;
-	uint8_t waveform;
-	uint16_t pw;
-	uint32_t lfsr;
-	SoundEngineADSR adsr;
-
-	uint16_t flags;
-
-	uint8_t filter_mode;
-	uint16_t filter_cutoff;
-	uint16_t filter_resonace;
-
-	SoundEngineFilter filter;
-} SoundEngineChannel;
-
-typedef struct
-{
-	SoundEngineChannel channel[NUM_CHANNELS];
-	uint32_t sample_rate;
-	uint16_t* audio_buffer;
-	uint32_t audio_buffer_size;
-	bool external_audio_output;
-	uint8_t sine_lut[SINE_LUT_SIZE];
-} SoundEngine;
+#include "sound_engine_osc.h"
+#include "sound_engine_filter.h"
+#include "sound_engine_defs.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);
 void sound_engine_set_channel_frequency(SoundEngine* sound_engine, SoundEngineChannel* channel, uint32_t frequency);
-void sound_engine_fill_buffer(SoundEngine* sound_engine, uint16_t* audio_buffer, uint32_t audio_buffer_size);
-void sound_engine_filter_set_coeff(SoundEngineFilter *flt, uint32_t frequency, uint16_t resonance);
+void sound_engine_fill_buffer(SoundEngine* sound_engine, uint16_t* audio_buffer, uint32_t audio_buffer_size);

+ 85 - 0
sound_engine/sound_engine_defs.h

@@ -0,0 +1,85 @@
+#pragma once
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#define NUM_CHANNELS 4
+
+#define RANDOM_SEED 0xf31782ce
+
+#define ACC_BITS 23
+#define ACC_LENGTH (1 << (ACC_BITS - 1))
+
+#define OUTPUT_BITS 16
+#define WAVE_AMP (1 << OUTPUT_BITS)
+
+#define SINE_LUT_SIZE 256
+#define SINE_LUT_BITDEPTH 8
+
+typedef enum
+{
+	SE_WAVEFORM_NONE = 0,
+	SE_WAVEFORM_NOISE = 1,
+	SE_WAVEFORM_PULSE = 2,
+	SE_WAVEFORM_TRIANGLE = 4,
+	SE_WAVEFORM_SAW = 8,
+	SE_WAVEFORM_NOISE_METAL = 16,
+	SE_WAVEFORM_SINE = 32,
+} SoudEngineWaveformType;
+
+typedef enum
+{
+	SE_ENABLE_FILTER = 1,
+	SE_ENABLE_GATE = 2,
+	SE_ENABLE_RING_MOD = 4,
+	SE_ENABLE_HARD_SYNC = 8,
+	SE_ENABLE_KEYDOWN_SYNC = 16, //sync oscillators on keydown
+} SoundEngineFlags;
+
+typedef enum
+{
+	FIL_OUTPUT_LOWPASS = 1,
+	FIL_OUTPUT_HIGHPASS = 2,
+	FIL_OUTPUT_BANDPASS = 3,
+} SoundEngineFilterModes;
+
+typedef struct
+{
+	uint8_t a, d, s, r, volume;
+	uint32_t envelope;
+	int32_t envelope_speed;
+} SoundEngineADSR;
+
+typedef struct
+{
+	int32_t f, q, p;
+	int32_t b0, b1, b2, b3, b4; //filter coefficients
+} SoundEngineFilter;
+
+typedef struct
+{
+	uint32_t accumulator;
+	uint32_t frequency;
+	uint8_t waveform;
+	uint16_t pw;
+	uint32_t lfsr;
+	SoundEngineADSR adsr;
+
+	uint16_t flags;
+
+	uint8_t filter_mode;
+	uint16_t filter_cutoff;
+	uint16_t filter_resonace;
+
+	SoundEngineFilter filter;
+} SoundEngineChannel;
+
+typedef struct
+{
+	SoundEngineChannel channel[NUM_CHANNELS];
+	uint32_t sample_rate;
+	uint16_t* audio_buffer;
+	uint32_t audio_buffer_size;
+	bool external_audio_output;
+	uint8_t sine_lut[SINE_LUT_SIZE];
+} SoundEngine;

+ 38 - 0
sound_engine/sound_engine_filter.c

@@ -0,0 +1,38 @@
+#include "sound_engine_filter.h"
+
+void sound_engine_filter_set_coeff(SoundEngineFilter* flt, uint32_t frequency, uint16_t resonance)
+{
+	flt->q = 2048 - frequency;
+	flt->p = frequency + ((int32_t)(0.8f * 2048.0f) * frequency / 2048 * flt->q) / 2048;
+	flt->f = flt->p + flt->p - 2048;
+	flt->q = resonance;
+}
+
+void sound_engine_filter_cycle(SoundEngineFilter* flt, int32_t input)
+{
+	input -= flt->q * flt->b4 / 2048; //feedback
+	int32_t t1 = flt->b1;  
+	flt->b1 = (input + flt->b0) * flt->p / 2048 - flt->b1 * flt->f / 2048;
+	int32_t t2 = flt->b2;  
+	flt->b2 = (flt->b1 + t1) * flt->p / 2048 - flt->b2 * flt->f / 2048;
+	t1 = flt->b3;
+	flt->b3 = (flt->b2 + t2) * flt->p / 2048 - flt->b3 * flt->f / 2048;
+	flt->b4 = (flt->b3 + t1) * flt->p / 2048 - flt->b4 * flt->f / 2048;
+	
+	flt->b0 = input;
+}
+
+int32_t sound_engine_output_lowpass(SoundEngineFilter* flt)
+{
+	return flt->b4;
+}
+
+int32_t sound_engine_output_highpass(SoundEngineFilter* flt)
+{
+	return flt->b0 - flt->b4;
+}
+
+int32_t sound_engine_output_bandpass(SoundEngineFilter* flt)
+{
+	return 3 * (flt->b3 - flt->b4);
+}

+ 9 - 0
sound_engine/sound_engine_filter.h

@@ -0,0 +1,9 @@
+#pragma once
+
+#include "sound_engine_defs.h"
+
+void sound_engine_filter_set_coeff(SoundEngineFilter* flt, uint32_t frequency, uint16_t resonance);
+void sound_engine_filter_cycle(SoundEngineFilter* flt, int32_t input);
+int32_t sound_engine_output_lowpass(SoundEngineFilter* flt);
+int32_t sound_engine_output_highpass(SoundEngineFilter* flt);
+int32_t sound_engine_output_bandpass(SoundEngineFilter* flt);

+ 93 - 0
sound_engine/sound_engine_osc.c

@@ -0,0 +1,93 @@
+#include "sound_engine_osc.h"
+
+static inline uint16_t sound_engine_pulse(uint32_t acc, uint32_t pw) //0-FFF pulse width range
+{
+	return (((acc >> (((uint32_t)ACC_BITS - 17))) >= ((pw == 0xfff ? pw + 1 : pw) << 4) ? (WAVE_AMP - 1) : 0));
+}
+
+static inline uint16_t sound_engine_saw(uint32_t acc) 
+{
+	return (acc >> (ACC_BITS - OUTPUT_BITS - 1)) & (WAVE_AMP - 1);
+}
+
+
+static inline uint16_t sound_engine_triangle(uint32_t acc)
+{
+	return ((((acc & (ACC_LENGTH / 2)) ? ~acc : acc) >> (ACC_BITS - OUTPUT_BITS - 2)) & (WAVE_AMP * 2 - 1));
+}
+
+static inline uint16_t sound_engine_sine(uint32_t acc, SoundEngine* sound_engine) 
+{
+	return (sound_engine->sine_lut[(acc >> (ACC_BITS - SINE_LUT_BITDEPTH))] << (OUTPUT_BITS - SINE_LUT_BITDEPTH));
+}
+
+inline static void shift_lfsr(uint32_t* v, uint32_t tap_0, uint32_t tap_1)
+{
+	typedef uint32_t T;
+	const T zero = (T)(0);
+	const T lsb = zero + (T)(1);
+	const T feedback = (
+		(lsb << (tap_0)) ^
+		(lsb << (tap_1))
+	);
+
+	*v = (*v >> 1) ^ ((zero - (*v & lsb)) & feedback);
+}
+
+uint16_t sound_engine_osc(SoundEngine* sound_engine, SoundEngineChannel* channel, uint32_t prev_acc)
+{
+	switch(channel->waveform)
+	{
+		case SE_WAVEFORM_NOISE:
+		{
+			if((prev_acc & (ACC_LENGTH / 32)) != (channel->accumulator & (ACC_LENGTH / 32)))
+			{
+				shift_lfsr(&channel->lfsr, 22, 17);
+				channel->lfsr &= (1 << (22 + 1)) - 1;
+			}
+
+			return (channel->lfsr) & (WAVE_AMP - 1);
+
+			break;
+		}
+
+		case SE_WAVEFORM_PULSE:
+		{
+			return sound_engine_pulse(channel->accumulator, channel->pw);
+			break;
+		}
+
+		case SE_WAVEFORM_TRIANGLE:
+		{
+			return sound_engine_triangle(channel->accumulator);
+			break;
+		}
+		
+		case SE_WAVEFORM_SAW:
+		{
+			return sound_engine_saw(channel->accumulator);
+			break;
+		}
+
+		case SE_WAVEFORM_NOISE_METAL:
+		{
+			if((prev_acc & (ACC_LENGTH / 32)) != (channel->accumulator & (ACC_LENGTH / 32)))
+			{
+				shift_lfsr(&channel->lfsr, 14, 8);
+				channel->lfsr &= (1 << (14 + 1)) - 1;
+			}
+
+			return (channel->lfsr) & (WAVE_AMP - 1);
+
+			break;
+		}
+
+		case SE_WAVEFORM_SINE:
+		{
+			return sound_engine_sine(channel->accumulator, sound_engine);
+			break;
+		}
+	}
+
+	return 0;
+}

+ 5 - 0
sound_engine/sound_engine_osc.h

@@ -0,0 +1,5 @@
+#pragma once
+
+#include "sound_engine_defs.h"
+
+uint16_t sound_engine_osc(SoundEngine* sound_engine, SoundEngineChannel* channel, uint32_t prev_acc);