mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-25 03:29:58 -07:00
202 lines
6.2 KiB
C
202 lines
6.2 KiB
C
#include "util.h"
|
|
#include "macros.h"
|
|
|
|
void reset_buffer(SoundEngine* sound_engine) {
|
|
for(uint16_t i = 0; i < sound_engine->audio_buffer_size; i++) {
|
|
sound_engine->audio_buffer[i] = 512;
|
|
}
|
|
}
|
|
|
|
void stop_song(FlizzerTrackerApp* tracker) {
|
|
tracker->tracker_engine.playing = false;
|
|
tracker->editing = tracker->was_editing;
|
|
|
|
for(int i = 0; i < SONG_MAX_CHANNELS; i++) {
|
|
tracker->sound_engine.channel[i].adsr.volume = 0;
|
|
tracker->tracker_engine.channel[i].channel_flags &= ~(TEC_PROGRAM_RUNNING);
|
|
}
|
|
|
|
stop();
|
|
|
|
reset_buffer(&tracker->sound_engine);
|
|
}
|
|
|
|
void play_song(FlizzerTrackerApp* tracker, bool from_cursor) {
|
|
uint16_t temppos = tracker->tracker_engine.pattern_position;
|
|
|
|
stop_song(tracker);
|
|
|
|
sound_engine_dma_init(
|
|
(uint32_t)tracker->sound_engine.audio_buffer, tracker->sound_engine.audio_buffer_size);
|
|
|
|
tracker->tracker_engine.playing = true;
|
|
|
|
tracker->was_editing = tracker->editing;
|
|
tracker->editing = false;
|
|
|
|
if(!(from_cursor)) {
|
|
tracker->tracker_engine.pattern_position = 0;
|
|
temppos = 0;
|
|
}
|
|
|
|
tracker_engine_timer_init(tracker->song.rate);
|
|
|
|
/*sound_engine_init_hardware(tracker->sound_engine.sample_rate,
|
|
tracker->sound_engine.external_audio_output,
|
|
tracker->sound_engine.audio_buffer,
|
|
tracker->sound_engine.audio_buffer_size);
|
|
tracker_engine_init_hardware(tracker->song.rate);*/
|
|
|
|
tracker->tracker_engine.current_tick = 0;
|
|
tracker_engine_set_song(&tracker->tracker_engine, &tracker->song);
|
|
|
|
for(uint8_t i = 0; i < SONG_MAX_CHANNELS; i++) {
|
|
bool was_disabled = tracker->tracker_engine.channel[i].channel_flags & TEC_DISABLED;
|
|
|
|
memset(&tracker->sound_engine.channel[i], 0, sizeof(SoundEngineChannel));
|
|
memset(&tracker->tracker_engine.channel[i], 0, sizeof(TrackerEngineChannel));
|
|
|
|
if(was_disabled) {
|
|
tracker->tracker_engine.channel[i].channel_flags |= TEC_DISABLED;
|
|
}
|
|
}
|
|
|
|
tracker->tracker_engine.pattern_position = temppos;
|
|
|
|
play();
|
|
}
|
|
|
|
bool is_pattern_empty(TrackerSong* song, uint8_t pattern) {
|
|
TrackerSongPattern song_pattern = song->pattern[pattern];
|
|
|
|
for(int i = 0; i < song->pattern_length; i++) {
|
|
TrackerSongPatternStep* step = &song_pattern.step[i];
|
|
|
|
if(tracker_engine_get_note(step) != MUS_NOTE_NONE ||
|
|
tracker_engine_get_instrument(step) != MUS_NOTE_INSTRUMENT_NONE ||
|
|
tracker_engine_get_volume(step) != MUS_NOTE_VOLUME_NONE ||
|
|
tracker_engine_get_command(step) != 0) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool check_and_allocate_pattern(TrackerSong* song, uint8_t pattern) {
|
|
if(pattern < song->num_patterns) // we can set this pattern since it already exists
|
|
{
|
|
return true;
|
|
}
|
|
|
|
else {
|
|
if(song->pattern[pattern - 1].step == NULL)
|
|
return false; // if we hop through several patterns (e.g. editing upper digit)
|
|
|
|
if(!(is_pattern_empty(
|
|
song, pattern - 1))) // don't let the user flood the song with empty patterns
|
|
{
|
|
song->pattern[pattern].step =
|
|
malloc(sizeof(TrackerSongPatternStep) * song->pattern_length);
|
|
set_empty_pattern(&song->pattern[pattern], song->pattern_length);
|
|
song->num_patterns++;
|
|
return true;
|
|
}
|
|
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void resize_pattern(TrackerSongPattern* pattern, uint16_t old_length, uint16_t new_length) {
|
|
TrackerSongPattern temp;
|
|
temp.step = malloc((new_length) * sizeof(TrackerSongPatternStep));
|
|
|
|
set_empty_pattern(&temp, new_length);
|
|
memcpy(
|
|
temp.step, pattern->step, my_min(old_length, new_length) * sizeof(TrackerSongPatternStep));
|
|
|
|
free(pattern->step);
|
|
pattern->step = temp.step;
|
|
}
|
|
|
|
void change_pattern_length(TrackerSong* song, uint16_t new_length) {
|
|
for(int i = 0; i < MAX_PATTERNS; i++) {
|
|
if(song->pattern[i].step) {
|
|
resize_pattern(&song->pattern[i], song->pattern_length, new_length);
|
|
}
|
|
}
|
|
|
|
song->pattern_length = new_length;
|
|
}
|
|
|
|
bool is_default_instrument(Instrument* inst) {
|
|
Instrument* ref = malloc(sizeof(Instrument));
|
|
set_default_instrument(ref);
|
|
bool is_default = memcmp(ref, inst, sizeof(Instrument)) != 0 ? false : true;
|
|
free(ref);
|
|
return is_default;
|
|
}
|
|
|
|
bool check_and_allocate_instrument(TrackerSong* song, uint8_t inst) {
|
|
if(inst < song->num_instruments) // we can go to this instrument since it already exists
|
|
{
|
|
return true;
|
|
}
|
|
|
|
else {
|
|
if(inst >= MAX_INSTRUMENTS) return false;
|
|
|
|
if(!(is_default_instrument(
|
|
song->instrument
|
|
[inst - 1]))) // don't let the user flood the song with default instrument
|
|
{
|
|
song->instrument[inst] = malloc(sizeof(Instrument));
|
|
set_default_instrument(song->instrument[inst]);
|
|
song->num_instruments++;
|
|
return true;
|
|
}
|
|
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void set_default_song(FlizzerTrackerApp* tracker) {
|
|
tracker->tracker_engine.master_volume = 0x80;
|
|
|
|
tracker->song.speed = 6;
|
|
tracker->song.rate = tracker->tracker_engine.rate;
|
|
tracker->song.num_instruments = 1;
|
|
tracker->song.num_patterns = 5;
|
|
tracker->song.num_sequence_steps = 1;
|
|
tracker->song.pattern_length = 64;
|
|
|
|
tracker->song.sequence.sequence_step[0].pattern_indices[0] = 1;
|
|
tracker->song.sequence.sequence_step[0].pattern_indices[1] = 2;
|
|
tracker->song.sequence.sequence_step[0].pattern_indices[2] = 3;
|
|
tracker->song.sequence.sequence_step[0].pattern_indices[3] = 4;
|
|
|
|
for(int i = 0; i < 5; i++) {
|
|
tracker->song.pattern[i].step = malloc(64 * sizeof(TrackerSongPatternStep));
|
|
memset(tracker->song.pattern[i].step, 0, 64 * sizeof(TrackerSongPatternStep));
|
|
}
|
|
|
|
for(int i = 0; i < 64; ++i) {
|
|
for(int j = 0; j < 5; j++) {
|
|
set_note(&tracker->song.pattern[j].step[i], MUS_NOTE_NONE);
|
|
|
|
set_instrument(&tracker->song.pattern[j].step[i], MUS_NOTE_INSTRUMENT_NONE);
|
|
|
|
set_volume(&tracker->song.pattern[j].step[i], MUS_NOTE_VOLUME_NONE);
|
|
}
|
|
}
|
|
|
|
tracker->song.instrument[0] = malloc(sizeof(Instrument));
|
|
|
|
set_default_instrument(tracker->song.instrument[0]);
|
|
|
|
tracker->tracker_engine.playing = false;
|
|
} |