mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-25 03:29:58 -07:00
536 lines
13 KiB
C
536 lines
13 KiB
C
#include "instrument.h"
|
|
#include "songinfo.h"
|
|
|
|
void edit_instrument_param(FlizzerTrackerApp* tracker, uint8_t selected_param, int8_t delta) {
|
|
if(!(tracker->current_digit)) {
|
|
delta *= 16;
|
|
}
|
|
|
|
Instrument* inst = tracker->song.instrument[tracker->current_instrument];
|
|
|
|
switch(selected_param) {
|
|
case INST_CURRENTINSTRUMENT: {
|
|
int16_t inst = tracker->current_instrument;
|
|
|
|
int8_t inst_delta = delta > 0 ? 1 : -1;
|
|
|
|
inst += inst_delta;
|
|
|
|
clamp(inst, 0, 0, tracker->song.num_instruments);
|
|
|
|
if(check_and_allocate_instrument(&tracker->song, (uint8_t)inst)) {
|
|
tracker->current_instrument = inst;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_INSTRUMENTNAME: {
|
|
text_input_set_header_text(tracker->text_input, "Instrument name:");
|
|
text_input_set_result_callback(
|
|
tracker->text_input,
|
|
return_from_keyboard_callback,
|
|
tracker,
|
|
(char*)&inst->name,
|
|
MUS_INST_NAME_LEN + 1,
|
|
false);
|
|
|
|
view_dispatcher_switch_to_view(tracker->view_dispatcher, VIEW_KEYBOARD);
|
|
break;
|
|
}
|
|
|
|
case INST_CURRENT_NOTE: {
|
|
int8_t note_delta = 0;
|
|
|
|
if(delta < 0) {
|
|
if(tracker->current_digit) {
|
|
note_delta = -12;
|
|
}
|
|
|
|
else {
|
|
note_delta = -1;
|
|
}
|
|
}
|
|
|
|
if(delta > 0) {
|
|
if(tracker->current_digit) {
|
|
note_delta = 12;
|
|
}
|
|
|
|
else {
|
|
note_delta = 1;
|
|
}
|
|
}
|
|
|
|
clamp(inst->base_note, note_delta, 0, MAX_NOTE);
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_FINETUNE: {
|
|
int8_t fine_delta = 0;
|
|
|
|
if(delta < 0) {
|
|
if(tracker->current_digit) {
|
|
fine_delta = -1;
|
|
}
|
|
|
|
else {
|
|
fine_delta = -10;
|
|
}
|
|
}
|
|
|
|
if(delta > 0) {
|
|
if(tracker->current_digit) {
|
|
fine_delta = 1;
|
|
}
|
|
|
|
else {
|
|
fine_delta = 10;
|
|
}
|
|
}
|
|
|
|
inst->finetune += fine_delta;
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_SLIDESPEED: {
|
|
if((int16_t)inst->slide_speed + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->slide_speed + (int16_t)delta <= 0xff) {
|
|
inst->slide_speed += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_SETPW: {
|
|
flipbit(inst->flags, TE_SET_PW);
|
|
break;
|
|
}
|
|
|
|
case INST_PW: {
|
|
if((int16_t)inst->pw + (int16_t)delta >= 0 && (int16_t)inst->pw + (int16_t)delta <= 0xff) {
|
|
inst->pw += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_SETCUTOFF: {
|
|
flipbit(inst->flags, TE_SET_CUTOFF);
|
|
break;
|
|
}
|
|
|
|
case INST_WAVE_NOISE: {
|
|
flipbit(inst->waveform, SE_WAVEFORM_NOISE);
|
|
break;
|
|
}
|
|
|
|
case INST_WAVE_PULSE: {
|
|
flipbit(inst->waveform, SE_WAVEFORM_PULSE);
|
|
break;
|
|
}
|
|
|
|
case INST_WAVE_TRIANGLE: {
|
|
flipbit(inst->waveform, SE_WAVEFORM_TRIANGLE);
|
|
break;
|
|
}
|
|
|
|
case INST_WAVE_SAWTOOTH: {
|
|
flipbit(inst->waveform, SE_WAVEFORM_SAW);
|
|
break;
|
|
}
|
|
|
|
case INST_WAVE_NOISE_METAL: {
|
|
flipbit(inst->waveform, SE_WAVEFORM_NOISE_METAL);
|
|
break;
|
|
}
|
|
|
|
case INST_WAVE_SINE: {
|
|
flipbit(inst->waveform, SE_WAVEFORM_SINE);
|
|
break;
|
|
}
|
|
|
|
case INST_ATTACK: {
|
|
if((int16_t)inst->adsr.a + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->adsr.a + (int16_t)delta <= 0xff) {
|
|
inst->adsr.a += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_DECAY: {
|
|
if((int16_t)inst->adsr.d + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->adsr.d + (int16_t)delta <= 0xff) {
|
|
inst->adsr.d += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_SUSTAIN: {
|
|
if((int16_t)inst->adsr.s + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->adsr.s + (int16_t)delta <= 0xff) {
|
|
inst->adsr.s += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_RELEASE: {
|
|
if((int16_t)inst->adsr.r + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->adsr.r + (int16_t)delta <= 0xff) {
|
|
inst->adsr.r += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_VOLUME: {
|
|
if((int16_t)inst->adsr.volume + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->adsr.volume + (int16_t)delta <= 0xff) {
|
|
inst->adsr.volume += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_ENABLEFILTER: {
|
|
flipbit(inst->sound_engine_flags, SE_ENABLE_FILTER);
|
|
break;
|
|
}
|
|
|
|
case INST_FILTERCUTOFF: {
|
|
if((int16_t)inst->filter_cutoff + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->filter_cutoff + (int16_t)delta <= 0xff) {
|
|
inst->filter_cutoff += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_FILTERRESONANCE: {
|
|
if((int16_t)inst->filter_resonance + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->filter_resonance + (int16_t)delta <= 0xff) {
|
|
inst->filter_resonance += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_FILTERTYPE: {
|
|
int8_t flt_delta = (delta > 0 ? 1 : -1);
|
|
|
|
if((int16_t)inst->filter_type + (int16_t)flt_delta >= 0 &&
|
|
(int16_t)inst->filter_type + (int16_t)flt_delta < FIL_MODES) {
|
|
inst->filter_type += flt_delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_ENABLERINGMOD: {
|
|
flipbit(inst->sound_engine_flags, SE_ENABLE_RING_MOD);
|
|
break;
|
|
}
|
|
|
|
case INST_RINGMODSRC: {
|
|
if((int16_t)inst->ring_mod + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->ring_mod + (int16_t)delta < SONG_MAX_CHANNELS) {
|
|
inst->ring_mod += delta;
|
|
}
|
|
|
|
if((int16_t)inst->ring_mod + (int16_t)delta < 0) {
|
|
inst->ring_mod = 0xff; // 0xff = self
|
|
}
|
|
|
|
if((int16_t)inst->ring_mod == 0xff && (int16_t)delta > 0) {
|
|
inst->ring_mod = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_ENABLEHARDSYNC: {
|
|
flipbit(inst->sound_engine_flags, SE_ENABLE_HARD_SYNC);
|
|
break;
|
|
}
|
|
|
|
case INST_HARDSYNCSRC: {
|
|
if((int16_t)inst->hard_sync + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->hard_sync + (int16_t)delta < SONG_MAX_CHANNELS) {
|
|
inst->hard_sync += delta;
|
|
}
|
|
|
|
if((int16_t)inst->hard_sync + (int16_t)delta < 0) {
|
|
inst->hard_sync = 0xff; // 0xff = self
|
|
}
|
|
|
|
if((int16_t)inst->hard_sync == 0xff && (int16_t)delta > 0) {
|
|
inst->hard_sync = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_RETRIGGERONSLIDE: {
|
|
flipbit(inst->flags, TE_RETRIGGER_ON_SLIDE);
|
|
break;
|
|
}
|
|
|
|
case INST_ENABLEKEYSYNC: {
|
|
flipbit(inst->sound_engine_flags, SE_ENABLE_KEYDOWN_SYNC);
|
|
break;
|
|
}
|
|
|
|
case INST_ENABLEVIBRATO: {
|
|
flipbit(inst->flags, TE_ENABLE_VIBRATO);
|
|
break;
|
|
}
|
|
|
|
case INST_VIBRATOSPEED: {
|
|
if((int16_t)inst->vibrato_speed + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->vibrato_speed + (int16_t)delta <= 0xff) {
|
|
inst->vibrato_speed += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_VIBRATODEPTH: {
|
|
if((int16_t)inst->vibrato_depth + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->vibrato_depth + (int16_t)delta <= 0xff) {
|
|
inst->vibrato_depth += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_VIBRATODELAY: {
|
|
if((int16_t)inst->vibrato_delay + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->vibrato_delay + (int16_t)delta <= 0xff) {
|
|
inst->vibrato_delay += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_ENABLEPWM: {
|
|
flipbit(inst->flags, TE_ENABLE_PWM);
|
|
break;
|
|
}
|
|
|
|
case INST_PWMSPEED: {
|
|
if((int16_t)inst->pwm_speed + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->pwm_speed + (int16_t)delta <= 0xff) {
|
|
inst->pwm_speed += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_PWMDEPTH: {
|
|
if((int16_t)inst->pwm_depth + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->pwm_depth + (int16_t)delta <= 0xff) {
|
|
inst->pwm_depth += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_PWMDELAY: {
|
|
if((int16_t)inst->pwm_delay + (int16_t)delta >= 0 &&
|
|
(int16_t)inst->pwm_delay + (int16_t)delta <= 0xff) {
|
|
inst->pwm_delay += delta;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_PROGRESTART: {
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void instrument_edit_event(FlizzerTrackerApp* tracker, FlizzerTrackerEvent* event) {
|
|
if(event->input.key == InputKeyOk && event->input.type == InputTypeShort &&
|
|
!tracker->tracker_engine.playing) {
|
|
tracker->editing = !(tracker->editing);
|
|
return;
|
|
}
|
|
|
|
if(event->input.key == InputKeyOk && event->input.type == InputTypeLong && !tracker->editing) {
|
|
reset_buffer(&tracker->sound_engine);
|
|
tracker_engine_set_song(&tracker->tracker_engine, NULL);
|
|
|
|
for(int i = 1; i < SONG_MAX_CHANNELS; i++) {
|
|
tracker->tracker_engine.channel[i].channel_flags &= TEC_PLAYING;
|
|
tracker->tracker_engine.sound_engine->channel[i].frequency = 0;
|
|
tracker->tracker_engine.sound_engine->channel[i].waveform = 0;
|
|
}
|
|
|
|
Instrument* inst = tracker->song.instrument[tracker->current_instrument];
|
|
tracker_engine_trigger_instrument_internal(
|
|
&tracker->tracker_engine, 0, inst, (MIDDLE_C << 8));
|
|
tracker->tracker_engine.playing = true;
|
|
play();
|
|
return;
|
|
}
|
|
|
|
if(event->input.key == InputKeyOk && event->input.type == InputTypeRelease &&
|
|
!tracker->editing) {
|
|
SoundEngineChannel* se_channel = &tracker->sound_engine.channel[0];
|
|
sound_engine_enable_gate(&tracker->sound_engine, se_channel, false);
|
|
return;
|
|
}
|
|
|
|
if(event->input.key == InputKeyRight && event->input.type == InputTypeShort) {
|
|
switch(tracker->selected_param) {
|
|
default: {
|
|
tracker->current_digit++;
|
|
|
|
if(tracker->current_digit > 1) {
|
|
tracker->selected_param++;
|
|
|
|
tracker->current_digit = 0;
|
|
|
|
if(tracker->selected_param > INST_PARAMS - 1) {
|
|
tracker->selected_param = 0;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_CURRENTINSTRUMENT:
|
|
case INST_INSTRUMENTNAME:
|
|
case INST_SETPW:
|
|
case INST_SETCUTOFF:
|
|
case INST_WAVE_NOISE:
|
|
case INST_WAVE_PULSE:
|
|
case INST_WAVE_TRIANGLE:
|
|
case INST_WAVE_SAWTOOTH:
|
|
case INST_WAVE_NOISE_METAL:
|
|
case INST_WAVE_SINE:
|
|
case INST_ENABLEFILTER:
|
|
case INST_FILTERTYPE:
|
|
case INST_ENABLERINGMOD:
|
|
case INST_RINGMODSRC:
|
|
case INST_ENABLEHARDSYNC:
|
|
case INST_HARDSYNCSRC:
|
|
case INST_RETRIGGERONSLIDE:
|
|
case INST_ENABLEKEYSYNC:
|
|
case INST_ENABLEVIBRATO:
|
|
case INST_ENABLEPWM:
|
|
case INST_PROGRESTART: {
|
|
tracker->selected_param++;
|
|
|
|
tracker->current_digit = 1;
|
|
|
|
if(tracker->selected_param > INST_PARAMS - 1) {
|
|
tracker->selected_param = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(event->input.key == InputKeyLeft && event->input.type == InputTypeShort) {
|
|
switch(tracker->selected_param) {
|
|
default: {
|
|
tracker->current_digit--;
|
|
|
|
if(tracker->current_digit > 1) // unsigned int overflow
|
|
{
|
|
tracker->selected_param--;
|
|
|
|
tracker->current_digit = 1;
|
|
|
|
if(tracker->selected_param > INST_PARAMS - 1) // unsigned int overflow
|
|
{
|
|
tracker->selected_param = INST_PARAMS - 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case INST_CURRENTINSTRUMENT:
|
|
case INST_INSTRUMENTNAME:
|
|
case INST_SETPW:
|
|
case INST_SETCUTOFF:
|
|
case INST_WAVE_NOISE:
|
|
case INST_WAVE_PULSE:
|
|
case INST_WAVE_TRIANGLE:
|
|
case INST_WAVE_SAWTOOTH:
|
|
case INST_WAVE_NOISE_METAL:
|
|
case INST_WAVE_SINE:
|
|
case INST_ENABLEFILTER:
|
|
case INST_FILTERTYPE:
|
|
case INST_ENABLERINGMOD:
|
|
case INST_RINGMODSRC:
|
|
case INST_ENABLEHARDSYNC:
|
|
case INST_HARDSYNCSRC:
|
|
case INST_RETRIGGERONSLIDE:
|
|
case INST_ENABLEKEYSYNC:
|
|
case INST_ENABLEVIBRATO:
|
|
case INST_ENABLEPWM:
|
|
case INST_PROGRESTART: {
|
|
tracker->selected_param--;
|
|
|
|
tracker->current_digit = 1;
|
|
|
|
if(tracker->selected_param > INST_PARAMS - 1) // unsigned int overflow
|
|
{
|
|
tracker->selected_param = INST_PARAMS - 1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if(event->input.key == InputKeyDown && event->input.type == InputTypeShort) {
|
|
if(tracker->editing) {
|
|
edit_instrument_param(tracker, tracker->selected_param, -1);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if(event->input.key == InputKeyUp && event->input.type == InputTypeShort) {
|
|
if(tracker->editing) {
|
|
edit_instrument_param(tracker, tracker->selected_param, 1);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if(tracker->selected_param > INST_VIBRATODELAY) {
|
|
tracker->inst_editor_shift = 6;
|
|
}
|
|
|
|
if(tracker->selected_param > INST_PWMDELAY) {
|
|
tracker->inst_editor_shift = 12;
|
|
}
|
|
|
|
if(tracker->selected_param < INST_CURRENT_NOTE) {
|
|
tracker->inst_editor_shift = 0;
|
|
}
|
|
} |