From 4563cc85fcd1ef3176d56e652c17ac4679bba8c3 Mon Sep 17 00:00:00 2001 From: Andrew Dunai Date: Wed, 17 Apr 2024 21:06:43 +0300 Subject: [PATCH] keira: liltracker: pack structs, cleanup code, fix UI fonts keira: modplayer: normalize visualizer for nicer display when volume is low keira: replace double-precision funcs with faster float variants --- firmware/keira/src/apps/liltracker/config.h | 2 + firmware/keira/src/apps/liltracker/effects.h | 4 +- .../keira/src/apps/liltracker/liltracker.cpp | 7 +- firmware/keira/src/apps/liltracker/mixer.cpp | 208 ------------------ firmware/keira/src/apps/liltracker/mixer.h | 60 ----- firmware/keira/src/apps/liltracker/note.cpp | 2 +- firmware/keira/src/apps/liltracker/note.h | 171 +------------- .../keira/src/apps/liltracker/pattern.cpp | 2 +- firmware/keira/src/apps/liltracker/pattern.h | 4 +- firmware/keira/src/apps/liltracker/synth.h | 1 - firmware/keira/src/apps/liltracker/track.h | 2 +- firmware/keira/src/apps/liltracker/wav_sink.h | 7 +- firmware/keira/src/apps/lua/lualilka_math.cpp | 2 +- .../keira/src/apps/modplayer/modplayer.cpp | 2 +- 14 files changed, 24 insertions(+), 450 deletions(-) delete mode 100644 firmware/keira/src/apps/liltracker/mixer.cpp delete mode 100644 firmware/keira/src/apps/liltracker/mixer.h diff --git a/firmware/keira/src/apps/liltracker/config.h b/firmware/keira/src/apps/liltracker/config.h index 4027df85..55dbad8c 100644 --- a/firmware/keira/src/apps/liltracker/config.h +++ b/firmware/keira/src/apps/liltracker/config.h @@ -4,3 +4,5 @@ #define DEFAULT_BPM 400 #define CHANNEL_SIZE 32 #define MAX_VOLUME 128 + +#define PACKED __attribute__((packed)) diff --git a/firmware/keira/src/apps/liltracker/effects.h b/firmware/keira/src/apps/liltracker/effects.h index 0e4e6f2d..224849c1 100644 --- a/firmware/keira/src/apps/liltracker/effects.h +++ b/firmware/keira/src/apps/liltracker/effects.h @@ -2,6 +2,8 @@ #include +#include "config.h" + typedef enum : uint8_t { EFFECT_TYPE_NONE, EFFECT_TYPE_ARPEGGIO, // NES: 00xy @@ -30,7 +32,7 @@ const char effect_signs[EFFECT_TYPE_COUNT] = { typedef struct { effect_type_t type; uint8_t param; -} effect_t; +} PACKED effect_t; typedef void (*effect_fn_t)( const float time, const float relTime, float* frequency, float* amplitude, float* phase, uint8_t param diff --git a/firmware/keira/src/apps/liltracker/liltracker.cpp b/firmware/keira/src/apps/liltracker/liltracker.cpp index 927eecde..82c0bbf4 100644 --- a/firmware/keira/src/apps/liltracker/liltracker.cpp +++ b/firmware/keira/src/apps/liltracker/liltracker.cpp @@ -114,7 +114,7 @@ void LilTrackerApp::run() { int visualizerMode = VISUALIZER_MODE_PER_CHANNEL; - event_t copiedEvent = {N_C0, WAVEFORM_CONT, MAX_VOLUME, EVENT_TYPE_CONT, {EFFECT_TYPE_NONE, 0}}; + event_t copiedEvent = {NOTE_ZERO, WAVEFORM_CONT, MAX_VOLUME, EVENT_TYPE_CONT, {EFFECT_TYPE_NONE, 0}}; char str[64]; @@ -381,7 +381,6 @@ void LilTrackerApp::run() { int8_t fontShiftY = 0; if (event.waveform == WAVEFORM_CONT) { sprintf(str, "."); - canvas->setFont(FONT); } else { sprintf(str, "%d", event.waveform - 1); canvas->setFont(FONT_ICONS); @@ -398,7 +397,7 @@ void LilTrackerApp::run() { eventFocused && currentSegment == SEGMENT_WAVEFORM, event.waveform == WAVEFORM_CONT ? lilka::colors::Battleship_gray : lilka::colors::Cyan ); - canvas->setFont(FONT); + canvas->setFont(SCORE_FONT); xOffset += 9; // Volume if (event.volume == 0) { @@ -610,7 +609,7 @@ void LilTrackerApp::run() { } } if (!found) { - event.note = N_C0; + event.note = NOTE_ZERO; } } if (state.up.justPressed) { diff --git a/firmware/keira/src/apps/liltracker/mixer.cpp b/firmware/keira/src/apps/liltracker/mixer.cpp deleted file mode 100644 index 273692b4..00000000 --- a/firmware/keira/src/apps/liltracker/mixer.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// #include -// #include -// #include -// // #include "WiFi.h" -// #include "mixer.h" -// #include "config.h" -// #include "utils/acquire.h" -// -// Mixer::Mixer() : -// xMutex(xSemaphoreCreateMutex()), -// xQueue(xQueueCreate(CHANNEL_COUNT * MIXER_COMMAND_COUNT, sizeof(mixer_command_t))), -// masterVolume(0.25) { -// constexpr uint8_t pinCount = 3; -// uint8_t pins[pinCount] = {LILKA_I2S_BCLK, LILKA_I2S_LRCK, LILKA_I2S_DOUT}; -// uint8_t funcs[pinCount] = {I2S0O_BCK_OUT_IDX, I2S0O_WS_OUT_IDX, I2S0O_SD_OUT_IDX}; -// for (int i = 0; i < pinCount; i++) { -// gpio_pad_select_gpio(pins[i]); -// gpio_set_direction((gpio_num_t)pins[i], GPIO_MODE_OUTPUT); -// gpio_matrix_out(pins[i], funcs[i], false, false); -// } -// -// esp_i2s::i2s_config_t cfg = { -// .mode = (esp_i2s::i2s_mode_t)(esp_i2s::I2S_MODE_MASTER | esp_i2s::I2S_MODE_TX), -// .sample_rate = SAMPLE_RATE, -// .bits_per_sample = esp_i2s::I2S_BITS_PER_SAMPLE_16BIT, -// .channel_format = esp_i2s::I2S_CHANNEL_FMT_ONLY_LEFT, -// .communication_format = -// (esp_i2s::i2s_comm_format_t)(esp_i2s::I2S_COMM_FORMAT_STAND_I2S | esp_i2s::I2S_COMM_FORMAT_STAND_MSB), -// .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, -// .dma_buf_count = 4, -// .dma_buf_len = MIXER_BUFFER_SIZE, -// .use_apll = false, -// .tx_desc_auto_clear = true, -// }; -// if (esp_i2s::i2s_driver_install(esp_i2s::I2S_NUM_0, &cfg, 0, NULL) != ESP_OK) { -// lilka::serial_err("Failed to install I2S driver"); -// return; -// } -// if (esp_i2s::i2s_zero_dma_buffer(esp_i2s::I2S_NUM_0) != ESP_OK) { -// lilka::serial_err("Failed to zero I2S DMA buffer"); -// return; -// } -// -// // Free up the core 0 for the mixer task -// // WiFi.mode(WIFI_OFF); -// // esp_wifi_stop(); -// // esp_wifi_deinit(); -// // esp_bt_controller_disable(); -// // esp_bt_controller_deinit(); -// -// xTaskCreatePinnedToCore( -// [](void* pvParameters) { -// static_cast(pvParameters)->mixerTask(); -// vTaskDelete(NULL); -// }, -// "mixerTask", -// 8192, -// this, -// 1, -// nullptr, -// 0 -// ); -// -// xSemaphoreGive(xMutex); -// } -// -// Mixer::~Mixer() { -// vQueueDelete(xQueue); -// vSemaphoreDelete(xMutex); -// } -// -// void Mixer::sendCommand(const mixer_command_t command) { -// xQueueSend(xQueue, &command, portMAX_DELAY); -// } -// -// void Mixer::start(uint8_t channelIndex, waveform_t waveform, float frequency, float volume, effect_t effect) { -// mixer_command_t cmd; -// cmd.channelIndex = channelIndex; -// cmd.type = MIXER_COMMAND_SET_WAVEFORM; -// cmd.waveform = waveform; -// sendCommand(cmd); -// cmd.type = MIXER_COMMAND_SET_FREQUENCY; -// cmd.frequency = frequency; -// sendCommand(cmd); -// cmd.type = MIXER_COMMAND_SET_VOLUME; -// cmd.volume = volume; -// sendCommand(cmd); -// cmd.type = MIXER_COMMAND_SET_EFFECT; -// cmd.effect = effect; -// sendCommand(cmd); -// } -// -// void Mixer::stop() { -// // start(NULL, 0); -// for (uint8_t channelIndex = 0; channelIndex < CHANNEL_COUNT; channelIndex++) { -// mixer_command_t request = {channelIndex, MIXER_COMMAND_SET_OFF}; -// xQueueSend(xQueue, &request, portMAX_DELAY); -// } -// } -// -// void Mixer::reset() { -// for (uint8_t channelIndex = 0; channelIndex < CHANNEL_COUNT; channelIndex++) { -// mixer_command_t cmd; -// cmd.channelIndex = channelIndex; -// cmd.type = MIXER_COMMAND_SET_WAVEFORM; -// cmd.waveform = WAVEFORM_SQUARE; -// sendCommand(cmd); -// cmd.type = MIXER_COMMAND_SET_FREQUENCY; -// cmd.frequency = 0.0f; -// sendCommand(cmd); -// cmd.type = MIXER_COMMAND_SET_VOLUME; -// cmd.volume = 1.0f; -// sendCommand(cmd); -// cmd.type = MIXER_COMMAND_SET_EFFECT; -// cmd.effect = {EFFECT_TYPE_NONE, 0}; -// sendCommand(cmd); -// } -// } -// -// void Mixer::mixerTask() { -// int16_t audioBuffer[MIXER_BUFFER_SIZE]; -// int16_t channel0AudioBuffer[MIXER_BUFFER_SIZE]; -// int16_t channel1AudioBuffer[MIXER_BUFFER_SIZE]; -// int16_t channel2AudioBuffer[MIXER_BUFFER_SIZE]; -// int16_t* channelAudioBuffers[CHANNEL_COUNT] = {channel0AudioBuffer, channel1AudioBuffer, channel2AudioBuffer}; -// -// while (1) { // TODO: make this stoppable -// // TODO: Handle envelopes, effects and stuff in this loop -// // Check if queue has a new pattern and event index to play -// // start_request_t request; -// mixer_command_t command; -// while (xQueueReceive(xQueue, &command, 0) == pdTRUE) { -// // channelStates[request.channelIndex] = {request.waveform, request.frequency, request.volume, request.effect}; -// if (command.type == MIXER_COMMAND_SET_WAVEFORM) { -// synth.setWaveform(command.channelIndex, command.waveform); -// } else if (command.type == MIXER_COMMAND_SET_FREQUENCY) { -// synth.setFrequency(command.channelIndex, command.frequency); -// } else if (command.type == MIXER_COMMAND_SET_VOLUME) { -// synth.setVolume(command.channelIndex, command.volume); -// } else if (command.type == MIXER_COMMAND_SET_EFFECT) { -// synth.setEffect(command.channelIndex, command.effect); -// } else if (command.type == MIXER_COMMAND_SET_OFF) { -// synth.setOff(command.channelIndex); -// } -// } -// // Mix the channels -// float _masterVolume; -// { -// Acquire lock(xMutex); -// _masterVolume = masterVolume; -// } -// int64_t mixStart = millis(); -// synth.render(audioBuffer, channelAudioBuffers, MIXER_BUFFER_SIZE, _masterVolume); -// int64_t mixEnd = millis(); -// // Check if time spent mixing is more than the duration of the buffer -// // Duration of the buffer in microseconds: 1 / SAMPLE_RATE * 1000 * MIXER_BUFFER_SIZE -// // For 256-sample buffer at 8 kHz, it is 32000 microseconds -// if (mixEnd - mixStart > MIXER_BUFFER_DURATION_MS) { -// lilka::serial_err( -// "Mixer buffer underrun! Spent %lld ms mixing, had %d ms", mixEnd - mixStart, MIXER_BUFFER_DURATION_MS -// ); -// } else { -// // lilka::serial_log("Mixer buffer mix took %lld ms", mixEnd - mixStart); -// } -// -// size_t bytesWritten = 0; -// esp_i2s::i2s_write(esp_i2s::I2S_NUM_0, audioBuffer, MIXER_BUFFER_SIZE * 2, &bytesWritten, portMAX_DELAY); -// { -// Acquire lock(xMutex); -// memcpy(audioBufferCopy, audioBuffer, sizeof(int16_t) * MIXER_BUFFER_SIZE); -// for (uint8_t channelIndex = 0; channelIndex < CHANNEL_COUNT; channelIndex++) { -// memcpy( -// channelAudioBuffersCopy[channelIndex], -// channelAudioBuffers[channelIndex], -// sizeof(int16_t) * MIXER_BUFFER_SIZE -// ); -// } -// } -// synth.advanceTime(bytesWritten / 2); -// // taskYIELD(); -// vTaskDelay(1); // Needed to wait for UI to be able to acquire the mutex... Probably can go back to taskYIELD now -// } -// -// // TODO: Make this part reachable & deinit I2S -// i2s_driver_uninstall(esp_i2s::I2S_NUM_0); -// } -// -// int16_t Mixer::readBuffer(int16_t* targetBuffer) { -// Acquire lock(xMutex); -// memcpy(targetBuffer, audioBufferCopy, sizeof(int16_t) * MIXER_BUFFER_SIZE); -// return MIXER_BUFFER_SIZE; -// } -// -// int16_t Mixer::readBuffer(int16_t* targetBuffer, uint8_t channelIndex) { -// Acquire lock(xMutex); -// memcpy(targetBuffer, channelAudioBuffersCopy[channelIndex], sizeof(int16_t) * MIXER_BUFFER_SIZE); -// return MIXER_BUFFER_SIZE; -// } -// -// void Mixer::setMasterVolume(float volume) { -// Acquire lock(xMutex); -// masterVolume = fmaxf(0.0f, fminf(1.0f, volume)); -// } -// -// float Mixer::getMasterVolume() { -// Acquire lock(xMutex); -// return masterVolume; -// } diff --git a/firmware/keira/src/apps/liltracker/mixer.h b/firmware/keira/src/apps/liltracker/mixer.h deleted file mode 100644 index 46409ba3..00000000 --- a/firmware/keira/src/apps/liltracker/mixer.h +++ /dev/null @@ -1,60 +0,0 @@ -// #pragma once -// -// #include "FreeRTOS.h" -// #include -// #include -// #include "config.h" -// #include "waveforms.h" -// #include "effects.h" -// #include "synth.h" -// -// #define MIXER_BUFFER_SIZE 512 -// #define SAMPLE_RATE 44100 -// #define MIXER_BUFFER_DURATION_MS (MIXER_BUFFER_SIZE * 1000 / SAMPLE_RATE) -// #define SECONDS_PER_SAMPLE (1.0f / SAMPLE_RATE) -// -// typedef enum : uint8_t { -// MIXER_COMMAND_SET_WAVEFORM, -// MIXER_COMMAND_SET_FREQUENCY, -// MIXER_COMMAND_SET_VOLUME, -// MIXER_COMMAND_SET_EFFECT, -// MIXER_COMMAND_SET_OFF, -// MIXER_COMMAND_COUNT, -// } mixer_command_type_t; -// -// typedef struct { -// uint8_t channelIndex; -// mixer_command_type_t type; -// union { -// waveform_t waveform; -// float frequency; -// float volume; -// effect_t effect; -// }; -// } mixer_command_t; -// -// class Mixer { -// public: -// Mixer(); -// ~Mixer(); -// void sendCommand(const mixer_command_t command); -// void start( -// uint8_t channelIndex, waveform_t waveforms, float frequency, float volume, -// effect_t effect = {EFFECT_TYPE_NONE, 0} -// ); -// void stop(); -// void reset(); -// int16_t readBuffer(int16_t* targetBuffer); -// int16_t readBuffer(int16_t* targetBuffer, uint8_t channelIndex); -// void setMasterVolume(float volume); -// float getMasterVolume(); -// -// private: -// SemaphoreHandle_t xMutex; -// QueueHandle_t xQueue; -// void mixerTask(); -// int16_t audioBufferCopy[MIXER_BUFFER_SIZE]; -// int16_t channelAudioBuffersCopy[CHANNEL_COUNT][MIXER_BUFFER_SIZE]; -// float masterVolume; -// Synth synth; -// }; diff --git a/firmware/keira/src/apps/liltracker/note.cpp b/firmware/keira/src/apps/liltracker/note.cpp index ea1586fb..fc6dda89 100644 --- a/firmware/keira/src/apps/liltracker/note.cpp +++ b/firmware/keira/src/apps/liltracker/note.cpp @@ -19,7 +19,7 @@ const char* note_names[] = {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#" void noteinfo_t::fromFrequency(float frequency) { // 16.35 Hz is the lowest note, which is C0 (returned as octave 0, index 0) - int absIndex = round(log2(frequency / A4_FREQUENCY) * NOTES_PER_OCTAVE) + 57; + int absIndex = roundf(log2f(frequency / A4_FREQUENCY) * NOTES_PER_OCTAVE) + 57; if (absIndex < 0) { absIndex = 0; diff --git a/firmware/keira/src/apps/liltracker/note.h b/firmware/keira/src/apps/liltracker/note.h index 43c0edf5..42956347 100644 --- a/firmware/keira/src/apps/liltracker/note.h +++ b/firmware/keira/src/apps/liltracker/note.h @@ -1,20 +1,17 @@ #pragma once -// #include #include +#include "config.h" + typedef struct noteinfo_t { uint8_t index; // [0;11] - uint8_t octave; + uint8_t octave; // [0;9] char* toStr(); void add(int16_t semitoneCount); void fromFrequency(float frequency); float toFrequency(); -} noteinfo_t; - -// inline float modulate_frequency(int16_t frequency, int16_t semitoneCount) { -// return frequency * powf(2.0f, semitoneCount / 12.0f); -// } +} PACKED noteinfo_t; // Lookup table for powers of 2 in range [-10;10] with a step of 1/12 extern float pow2table[12 * 10 * 2 + 1]; @@ -27,165 +24,7 @@ inline float modulate_frequency(float frequency, float semitoneCount) { index = 12 * 10 * 2; } return frequency * pow2table[index]; - // int index = semitoneCount + 12; - // if (index < 0) { - // index = 0; - // } else if (index > 24) { - // index = 24; - // } - // - // return frequency * pow2table[index][0] / pow2table[index][1]; } -#define N_C0 \ +#define NOTE_ZERO \ { 0, 0 } - -#define N_C1 \ - { 0, 1 } -#define N_CS1 \ - { 1, 1 } -#define N_D1 \ - { 2, 1 } -#define N_DS1 \ - { 3, 1 } -#define N_E1 \ - { 4, 1 } -#define N_F1 \ - { 5, 1 } -#define N_FS1 \ - { 6, 1 } -#define N_G1 \ - { 7, 1 } -#define N_GS1 \ - { 8, 1 } -#define N_A1 \ - { 9, 1 } -#define N_AS1 \ - { 10, 1 } -#define N_B1 \ - { 11, 1 } - -#define N_C2 \ - { 0, 2 } -#define N_CS2 \ - { 1, 2 } -#define N_D2 \ - { 2, 2 } -#define N_DS2 \ - { 3, 2 } -#define N_E2 \ - { 4, 2 } -#define N_F2 \ - { 5, 2 } -#define N_FS2 \ - { 6, 2 } -#define N_G2 \ - { 7, 2 } -#define N_GS2 \ - { 8, 2 } -#define N_A2 \ - { 9, 2 } -#define N_AS2 \ - { 10, 2 } -#define N_B2 \ - { 11, 2 } - -#define N_C3 \ - { 0, 3 } -#define N_CS3 \ - { 1, 3 } -#define N_D3 \ - { 2, 3 } -#define N_DS3 \ - { 3, 3 } -#define N_E3 \ - { 4, 3 } -#define N_F3 \ - { 5, 3 } -#define N_FS3 \ - { 6, 3 } -#define N_G3 \ - { 7, 3 } -#define N_GS3 \ - { 8, 3 } -#define N_A3 \ - { 9, 3 } -#define N_AS3 \ - { 10, 3 } -#define N_B3 \ - { 11, 3 } - -#define N_C4 \ - { 0, 4 } -#define N_CS4 \ - { 1, 4 } -#define N_D4 \ - { 2, 4 } -#define N_DS4 \ - { 3, 4 } -#define N_E4 \ - { 4, 4 } -#define N_F4 \ - { 5, 4 } -#define N_FS4 \ - { 6, 4 } -#define N_G4 \ - { 7, 4 } -#define N_GS4 \ - { 8, 4 } -#define N_A4 \ - { 9, 4 } -#define N_AS4 \ - { 10, 4 } -#define N_B4 \ - { 11, 4 } - -#define N_C5 \ - { 0, 5 } -#define N_CS5 \ - { 1, 5 } -#define N_D5 \ - { 2, 5 } -#define N_DS5 \ - { 3, 5 } -#define N_E5 \ - { 4, 5 } -#define N_F5 \ - { 5, 5 } -#define N_FS5 \ - { 6, 5 } -#define N_G5 \ - { 7, 5 } -#define N_GS5 \ - { 8, 5 } -#define N_A5 \ - { 9, 5 } -#define N_AS5 \ - { 10, 5 } -#define N_B5 \ - { 11, 5 } - -#define N_C6 \ - { 0, 6 } -#define N_CS6 \ - { 1, 6 } -#define N_D6 \ - { 2, 6 } -#define N_DS6 \ - { 3, 6 } -#define N_E6 \ - { 4, 6 } -#define N_F6 \ - { 5, 6 } -#define N_FS6 \ - { 6, 6 } -#define N_G6 \ - { 7, 6 } -#define N_GS6 \ - { 8, 6 } -#define N_A6 \ - { 9, 6 } -#define N_AS6 \ - { 10, 6 } -#define N_B6 \ - { 11, 6 } diff --git a/firmware/keira/src/apps/liltracker/pattern.cpp b/firmware/keira/src/apps/liltracker/pattern.cpp index 874dfc6b..20628bbb 100644 --- a/firmware/keira/src/apps/liltracker/pattern.cpp +++ b/firmware/keira/src/apps/liltracker/pattern.cpp @@ -23,7 +23,7 @@ Pattern::Pattern() : xMutex(xSemaphoreCreateMutex()) { channels[channelIndex].volume = 1.0f; for (int16_t eventIndex = 0; eventIndex < CHANNEL_SIZE; eventIndex++) { event_t event = { - N_C0, + NOTE_ZERO, eventIndex == 0 ? defaultWaveforms[channelIndex] : WAVEFORM_CONT, MAX_VOLUME, EVENT_TYPE_CONT, diff --git a/firmware/keira/src/apps/liltracker/pattern.h b/firmware/keira/src/apps/liltracker/pattern.h index 17f04639..11538209 100644 --- a/firmware/keira/src/apps/liltracker/pattern.h +++ b/firmware/keira/src/apps/liltracker/pattern.h @@ -21,12 +21,12 @@ typedef struct { uint8_t volume; event_type_t type; effect_t effect; -} event_t; +} PACKED event_t; typedef struct { uint8_t volume; event_t events[CHANNEL_SIZE]; -} channel_t; +} PACKED channel_t; class Pattern { public: diff --git a/firmware/keira/src/apps/liltracker/synth.h b/firmware/keira/src/apps/liltracker/synth.h index 6d5a7191..19e02f20 100644 --- a/firmware/keira/src/apps/liltracker/synth.h +++ b/firmware/keira/src/apps/liltracker/synth.h @@ -20,7 +20,6 @@ typedef struct { // some effects are cancelled by others, some are reset by OFF, etc... /AD effect_t effect; float effectStartTime; - // float time; // TODO } channel_state_t; class Synth { diff --git a/firmware/keira/src/apps/liltracker/track.h b/firmware/keira/src/apps/liltracker/track.h index 2999a1f8..3f6654d9 100644 --- a/firmware/keira/src/apps/liltracker/track.h +++ b/firmware/keira/src/apps/liltracker/track.h @@ -8,7 +8,7 @@ // Each page tells which patterns to play. typedef struct page_t { int16_t patternIndices[CHANNEL_COUNT] = {0, 0, 0}; -} page_t; +} PACKED page_t; // Track is the top-level container for a song. // It contains patterns and pages. diff --git a/firmware/keira/src/apps/liltracker/wav_sink.h b/firmware/keira/src/apps/liltracker/wav_sink.h index 4e9976f9..bed03e27 100644 --- a/firmware/keira/src/apps/liltracker/wav_sink.h +++ b/firmware/keira/src/apps/liltracker/wav_sink.h @@ -1,12 +1,13 @@ #include #include "sink.h" +#include "config.h" typedef struct { char chunkID[4]; // "RIFF" unsigned int chunkSize; // size of the entire file minus 8 bytes char format[4]; // "WAVE" -} riff_header_t; +} PACKED riff_header_t; typedef struct { char subchunk1ID[4]; // "fmt " @@ -17,12 +18,12 @@ typedef struct { unsigned int byteRate; // = SampleRate * NumChannels * BitsPerSample/8 unsigned short blockAlign; // = NumChannels * BitsPerSample/8 unsigned short bitsPerSample; // 16 for PCM -} fmt_subchunk_t; +} PACKED fmt_subchunk_t; typedef struct { char subchunk2ID[4]; // "data" unsigned int subchunk2Size; // num samples * num channels * bits per sample/8 -} data_subchunk_t; +} PACKED data_subchunk_t; class WAVSink : public Sink { public: diff --git a/firmware/keira/src/apps/lua/lualilka_math.cpp b/firmware/keira/src/apps/lua/lualilka_math.cpp index 66939605..55a20012 100644 --- a/firmware/keira/src/apps/lua/lualilka_math.cpp +++ b/firmware/keira/src/apps/lua/lualilka_math.cpp @@ -250,7 +250,7 @@ int lualilka_math_round(lua_State* L) { } float value = luaL_checknumber(L, 1); - lua_pushinteger(L, round(value)); + lua_pushinteger(L, roundf(value)); return 1; } diff --git a/firmware/keira/src/apps/modplayer/modplayer.cpp b/firmware/keira/src/apps/modplayer/modplayer.cpp index 78f98d68..76e4787f 100644 --- a/firmware/keira/src/apps/modplayer/modplayer.cpp +++ b/firmware/keira/src/apps/modplayer/modplayer.cpp @@ -96,7 +96,7 @@ void ModPlayerApp::mainWindow() { for (int i = 0; i < ANALYZER_BUFFER_SIZE; i += 4) { int x = i * width / ANALYZER_BUFFER_SIZE; int index = (i + head) % ANALYZER_BUFFER_SIZE; - float amplitude = static_cast(analyzerBuffer[index]) / 32768 * gain; + float amplitude = static_cast(analyzerBuffer[index]) / 32768 * fminf(gain, 1.0f); int y = yCenter + static_cast(amplitude * height / 2); if (i > 0) { int16_t hue = (time / HUE_SPEED_DIV + i / HUE_SCALE) % 360;