Skip to content

Commit

Permalink
Merge pull request #151 from noisedsn/main
Browse files Browse the repository at this point in the history
Global sound settings and sound menu added (conflict resolved)
  • Loading branch information
frostmorn authored Dec 25, 2024
2 parents 124a287 + 4fac29a commit 3b957ac
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 15 deletions.
1 change: 1 addition & 0 deletions firmware/doom/src/i_i2ssound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ void queueSound(const uint8_t* data, uint32_t length, uint32_t sample_rate, uint
// Number of samples to add unmixed beyond buffered samples
int unmixedLength = length - mixedLength;

vol = vol * lilka::audio.getVolume() / 100;
uint32_t pos = mixerBufferStart;
for (int i = 0; i < mixedLength; i++) {
uint16_t rawSample =
Expand Down
20 changes: 11 additions & 9 deletions firmware/keira/src/apps/launcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "liltracker/liltracker.h"
#include "ble_gamepad/app.h"
#include "pastebin/pastebinApp.h"
#include "settings/sound.h"

#include "icons/demos.h"
#include "icons/sdcard.h"
Expand Down Expand Up @@ -109,9 +110,7 @@ void LauncherApp::run() {
int16_t index = menu.getCursor();
if (index == 0) {
appsMenu("Додатки", app_items);
}

else if (index == 1) {
} else if (index == 1) {
AppManager::getInstance()->runApp(new FileManagerApp(&SD, "/"));
} else if (index == 2) {
AppManager::getInstance()->runApp(new FileManagerApp(&SPIFFS, "/"));
Expand Down Expand Up @@ -153,6 +152,7 @@ void LauncherApp::settingsMenu() {
String titles[] = {
"WiFi-адаптер",
"Мережі WiFi",
"Звук",
"Про систему",
"Інфо про пристрій",
"Таблиця розділів",
Expand Down Expand Up @@ -196,8 +196,10 @@ void LauncherApp::settingsMenu() {
}
AppManager::getInstance()->runApp(new WiFiConfigApp());
} else if (index == 2) {
alert("Keira OS", "by Андерсон & friends");
AppManager::getInstance()->runApp(new SoundConfigApp());
} else if (index == 3) {
alert("Keira OS", "by Андерсон & friends");
} else if (index == 4) {
char buf[256];
sprintf(
buf,
Expand All @@ -215,7 +217,7 @@ void LauncherApp::settingsMenu() {
networkService->getIpAddr().c_str()
);
alert("Інфо про пристрій", buf);
} else if (index == 4) {
} else if (index == 5) {
String labels[16];
int labelCount = lilka::sys.get_partition_labels(labels);
labels[labelCount++] = "<< Назад";
Expand All @@ -240,7 +242,7 @@ void LauncherApp::settingsMenu() {
"Розмір: 0x" + String(lilka::sys.get_partition_size(labels[partitionIndex].c_str()), HEX)
);
}
} else if (index == 5) {
} else if (index == 6) {
lilka::Alert confirm(
"Форматування",
"УВАГА: Це очистить ВСІ дані з SD-карти!\n"
Expand Down Expand Up @@ -283,13 +285,13 @@ void LauncherApp::settingsMenu() {
"Систему буде перезавантажено."
);
esp_restart();
} else if (index == 6) {
} else if (index == 7) {
lilka::board.enablePowerSavingMode();
esp_light_sleep_start();
} else if (index == 7) {
} else if (index == 8) {
lilka::board.enablePowerSavingMode();
esp_deep_sleep_start();
} else if (index == 8) {
} else if (index == 9) {
esp_restart();
}
}
Expand Down
3 changes: 3 additions & 0 deletions firmware/keira/src/apps/liltracker/liltracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ void LilTrackerApp::run() {

char str[64];

// Set initial volume
sequencer.setMasterVolume(0.25f * lilka::audio.getVolume() / 100);

while (1) {
seq_state_t seqState = sequencer.getSeqState();

Expand Down
6 changes: 5 additions & 1 deletion firmware/keira/src/apps/modplayer/modplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ void ModPlayerApp::playTask() {
AudioFileSourcePROGMEM* modBufferSource = new AudioFileSourcePROGMEM(modFileData, modSource->getSize());
std::unique_ptr<AudioFileSource> modBufferSourcePtr(modBufferSource);

// Set initial volume
float initialGain = (1.0f * lilka::audio.getVolume() / 100);

// Create MOD player
AudioGeneratorMOD* mod = new AudioGeneratorMOD();
std::unique_ptr<AudioGeneratorMOD> modPtr(mod);
Expand All @@ -188,7 +191,8 @@ void ModPlayerApp::playTask() {
xSemaphoreTake(playerMutex, portMAX_DELAY);
playerTaskData.isPaused = false;
playerTaskData.isFinished = false;
playerTaskData.gain = 1.0f;
playerTaskData.gain = initialGain;
out->SetGain(initialGain);
xSemaphoreGive(playerMutex);

while (1) {
Expand Down
2 changes: 2 additions & 0 deletions firmware/keira/src/apps/nes/osd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ void do_audio_frame() {
}

size_t i2s_bytes_write;
// adjust volume
lilka::audio.adjustVolume(audio_frame, 4 * n, 16);
i2s_write(esp_i2s::I2S_NUM_0, static_cast<int16_t*>(audio_frame), 4 * n, &i2s_bytes_write, portMAX_DELAY);
left -= i2s_bytes_write / 4;
}
Expand Down
66 changes: 66 additions & 0 deletions firmware/keira/src/apps/settings/sound.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "sound.h"

SoundConfigApp::SoundConfigApp() : App("SoundConfig") {
}

void SoundConfigApp::run() {
int volumeLevel = lilka::audio.getVolume();
bool startupSound = lilka::audio.getStartupSoundEnabled();
bool startupBuzzer = lilka::buzzer.getStartupBuzzerEnabled();

lilka::Menu menu("Звук");
menu.addActivationButton(lilka::Button::B);
menu.addItem("Гучність:", 0, 0U, (String)volumeLevel);
menu.addItem("Звук вітання:", 0, 0U, (startupSound) ? "ON" : "OFF");
menu.addItem("Вітання бузером:", 0, 0U, (startupBuzzer) ? "ON" : "OFF");
menu.addItem("<< Зберегти");

while (true) {
while (!menu.isFinished()) {
menu.update();
menu.draw(canvas);
queueDraw();
}

if (menu.getButton() == lilka::Button::B) {
break;
}
int16_t index = menu.getCursor();
if (index == 0) {
if (volumeLevel < 100) {
volumeLevel += 10;
} else {
volumeLevel = 0;
}

lilka::MenuItem volumeItem;
menu.getItem(0, &volumeItem);
volumeItem.postfix = volumeLevel;
menu.setItem(0, volumeItem.title, volumeItem.icon, volumeItem.color, volumeItem.postfix);
} else if (index == 1) {
startupSound = !startupSound;

lilka::MenuItem startupItem;
menu.getItem(1, &startupItem);
startupItem.postfix = (startupSound) ? "ON" : "OFF";
menu.setItem(1, startupItem.title, startupItem.icon, startupItem.color, startupItem.postfix);
} else if (index == 2) {
startupBuzzer = !startupBuzzer;

lilka::MenuItem buzzerItem;
menu.getItem(2, &buzzerItem);
buzzerItem.postfix = (startupBuzzer) ? "ON" : "OFF";
menu.setItem(2, buzzerItem.title, buzzerItem.icon, buzzerItem.color, buzzerItem.postfix);
} else if (index == 3) {
break;
}
}

lilka::serial_log(
"Saving sound settings: volume %d, startup %d, buzzer %d", volumeLevel, startupSound, startupBuzzer
);

lilka::audio.setVolume(volumeLevel);
lilka::audio.setStartupSoundEnabled(startupSound);
lilka::buzzer.setStartupBuzzerEnabled(startupBuzzer);
}
10 changes: 10 additions & 0 deletions firmware/keira/src/apps/settings/sound.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <lilka.h>
#include "app.h"

class SoundConfigApp : public App {
public:
SoundConfigApp();

private:
void run() override;
};
74 changes: 70 additions & 4 deletions sdk/lib/lilka/src/lilka/audio.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "audio.h"
#include "config.h"
#include "ping.h"
#include "Preferences.h"

namespace lilka {

Expand All @@ -16,9 +17,15 @@ void Audio::begin() {

initPins();

Preferences prefs;
prefs.begin("sound", true);
volumeLevel = prefs.getUInt("volumeLevel", 100);
startupSound = prefs.getBool("startupSound", true);
prefs.end();

I2S.setAllPins(LILKA_I2S_BCLK, LILKA_I2S_LRCK, LILKA_I2S_DOUT, LILKA_I2S_DOUT, -1);

xTaskCreatePinnedToCore(ping_task, "ping_task", 4096, NULL, 1, NULL, 0);
if (startupSound) xTaskCreatePinnedToCore(ping_task, "ping_task", 4096, NULL, 1, NULL, 0);
#endif
}

Expand All @@ -34,23 +41,82 @@ void Audio::initPins() {
}
}

void Audio::adjustVolume(void* buffer, size_t size, int bitsPerSample) {
int gain = (volumeLevel * 1024.0) / 100.0;
int samples = size / (bitsPerSample / 8);

if (bitsPerSample == 8) {
uint8_t* smp = static_cast<uint8_t*>(buffer);

for (int i = 0; i < samples; i++) {
*smp = (*smp * gain) >> 10;
smp++;
}
} else if (bitsPerSample == 16) {
int16_t* smp = static_cast<int16_t*>(buffer);

for (int i = 0; i < samples; i++) {
*smp = (*smp * gain) >> 10;
smp++;
}
} else if (bitsPerSample == 32) {
int32_t* smp = static_cast<int32_t*>(buffer);

for (int i = 0; i < samples; i++) {
*smp = (*smp * gain) >> 10;
smp++;
}
}
}

int Audio::getVolume() {
return volumeLevel;
}

void Audio::setVolume(int level) {
volumeLevel = level;
saveSettings();
}

bool Audio::getStartupSoundEnabled() {
return startupSound;
}

void Audio::setStartupSoundEnabled(bool enable) {
startupSound = enable;
saveSettings();
}

void Audio::saveSettings() {
Preferences prefs;
prefs.begin("sound", false);
prefs.putUInt("volumeLevel", lilka::audio.volumeLevel);
prefs.putBool("startupSound", startupSound);
prefs.end();
}

void ping_task(void* arg) {
#if LILKA_VERSION == 1
serial_err("This part of code should never be called. Audio not supported for this version of lilka");
#elif LILKA_VERSION == 2
# ifndef LILKA_NO_AUDIO_HELLO

// Signed 16-bit PCM
const int16_t* ping = reinterpret_cast<const int16_t*>(ping_raw);

vTaskDelay(400 / portTICK_PERIOD_MS);

int16_t buf;
I2S.begin(I2S_PHILIPS_MODE, 22050, 16);
for (int i = 0; i < ping_raw_size / 2; i++) {
// TODO: Should use i2s_write & DMA
I2S.write(ping[i] >> 2);
I2S.write(ping[i] >> 2);
memcpy(&buf, &ping[i], 2);
lilka::audio.adjustVolume(&buf, 2, 16);

I2S.write(buf >> 2);
I2S.write(buf >> 2);
}
I2S.end();

# endif

vTaskDelete(NULL);
Expand Down
17 changes: 17 additions & 0 deletions sdk/lib/lilka/src/lilka/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ class Audio {
/// Налаштувує піни для I2S.
/// Цей метод варто викликати перед викликом `i2s_driver_install()`.
void initPins();
/// Регулює гучність до рівня, збереженого в налаштуваннях
/// Цей метод бажано викликати перед `i2s_write`.
void adjustVolume(void* buffer, size_t size, int bitsPerSample);
/// Повертає рівень гучності
int getVolume();
/// Встановлює рівень гучності
void setVolume(int level);
/// Перевіряє чи увімкнено звук вітання
bool getStartupSoundEnabled();
/// Вмикає чи вимикає звук вітання
void setStartupSoundEnabled(bool enable);

private:
/// Глобальна гучність
uint32_t volumeLevel = 100;
bool startupSound = true;
void saveSettings();
};

extern Audio audio;
Expand Down
25 changes: 24 additions & 1 deletion sdk/lib/lilka/src/lilka/buzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "buzzer.h"
#include "config.h"
#include "serial.h"
#include "Preferences.h"

namespace lilka {

Expand All @@ -20,11 +21,17 @@ void Buzzer::begin() {
serial_err("Buzzer is not supported on this board");
return;
#else

Preferences prefs;
prefs.begin("sound", true);
startupBuzzer = prefs.getBool("startupBuzzer", true);
prefs.end();

_stop();
pinMode(LILKA_BUZZER, OUTPUT);
# ifndef LILKA_NO_BUZZER_HELLO
const Tone helloTune[] = {{NOTE_C3, 8}, {NOTE_C4, 8}, {NOTE_C5, 8}, {NOTE_C7, 4}, {0, 8}, {NOTE_C6, 4}};
playMelody(helloTune, sizeof(helloTune) / sizeof(Tone), 160);
if (startupBuzzer) playMelody(helloTune, sizeof(helloTune) / sizeof(Tone), 160);
# endif
#endif
}
Expand Down Expand Up @@ -254,6 +261,22 @@ void Buzzer::playDoom() {
); // TODO - Should be 160... But note durations seem to be off
}

bool Buzzer::getStartupBuzzerEnabled() {
return startupBuzzer;
}

void Buzzer::setStartupBuzzerEnabled(bool enable) {
startupBuzzer = enable;
saveSettings();
}

void Buzzer::saveSettings() {
Preferences prefs;
prefs.begin("sound", false);
prefs.putBool("startupBuzzer", startupBuzzer);
prefs.end();
}

Buzzer buzzer;

} // namespace lilka
Loading

0 comments on commit 3b957ac

Please sign in to comment.