TamaTac & SfxEngine + Sprite tools (#24)
This commit is contained in:
@@ -0,0 +1,601 @@
|
||||
/**
|
||||
* @file SfxDefinitions.h
|
||||
* @brief 52 curated SFX definitions for SfxEngine.
|
||||
*
|
||||
* Implements SfxEngine::loadSound() — mapping SfxId values to note sequences.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SfxEngine.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
// Safety macro to prevent buffer overflow
|
||||
#define ADD_SFX_NOTE(seq, idx, ...) do { \
|
||||
if ((idx) < MAX_SFX_NOTES) { \
|
||||
SfxSequenceNote n = __VA_ARGS__; \
|
||||
(seq)[(idx)++] = n; \
|
||||
} else { \
|
||||
ESP_LOGE("SfxDef", "SFX note overflow at index %d", (idx)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
inline void SfxEngine::loadSound(SfxId sound) {
|
||||
sequenceIndex_ = 0;
|
||||
sequenceDelaySamples_ = 0;
|
||||
sequenceLength_ = 0;
|
||||
|
||||
// Stop all voices
|
||||
for (int i = 0; i < NUM_VOICES; i++) {
|
||||
voices_[i].active = false;
|
||||
voices_[i].envStage = EnvelopeStage::Off;
|
||||
}
|
||||
|
||||
switch (sound) {
|
||||
|
||||
// ── UI Sounds ────────────────────────────────────────────────────────
|
||||
|
||||
case SfxId::Click:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 80, 30, 0, SfxWaveType::Square, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Confirm:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 80, 0, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 120, 70, SfxWaveType::Square, 0.4f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Cancel:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 80, 0, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 120, 70, SfxWaveType::Square, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Error:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 150, 0, SfxWaveType::Sawtooth, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 51, 150, 0, SfxWaveType::Sawtooth, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::MenuOpen:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 40, 0, SfxWaveType::Pulse25, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 60, 30, SfxWaveType::Pulse25, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::MenuClose:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 40, 0, SfxWaveType::Pulse25, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 60, 30, SfxWaveType::Pulse25, 0.2f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Toggle:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 50, 0, SfxWaveType::Pulse12, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Slider:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 15, 0, SfxWaveType::Pulse25, 0.2f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Tab:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 67, 50, 0, SfxWaveType::Square, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 70, 40, SfxWaveType::Square, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
// ── TamaTac Pet Sounds ───────────────────────────────────────────────
|
||||
|
||||
case SfxId::Feed:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 80, 0, SfxWaveType::Pulse25, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 76, 80, 80, SfxWaveType::Pulse25, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 100, 80, SfxWaveType::Pulse25, 0.4f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Play:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 70, 0, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 60, 280, 0, SfxWaveType::Triangle, 0.2f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 76, 70, 70, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 70, 70, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 100, 70, SfxWaveType::Square, 0.35f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Medicine:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 200, 0, SfxWaveType::Triangle, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 79, 200, 50, SfxWaveType::Sine, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Sleep:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 200, 0, SfxWaveType::Triangle, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 76, 200, 180, SfxWaveType::Triangle, 0.3f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 300, 180, SfxWaveType::Triangle, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Clean:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 50, 0, SfxWaveType::Pulse12, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 50, 40, SfxWaveType::Pulse12, 0.3f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 80, 40, SfxWaveType::Pulse12, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Evolve:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 150, 0, SfxWaveType::Square, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 48, 600, 0, SfxWaveType::Triangle, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 64, 150, 130, SfxWaveType::Square, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 67, 150, 130, SfxWaveType::Square, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 400, 130, SfxWaveType::Square, 0.5f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Sick:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 100, 0, SfxWaveType::Square, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 100, 150, SfxWaveType::Square, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 100, 150, SfxWaveType::Square, 0.4f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Death:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 67, 250, 0, SfxWaveType::Triangle, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 64, 250, 220, SfxWaveType::Triangle, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 250, 220, SfxWaveType::Triangle, 0.3f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 55, 350, 220, SfxWaveType::Triangle, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 500, 300, SfxWaveType::Triangle, 0.2f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
// ── Game Sounds ──────────────────────────────────────────────────────
|
||||
|
||||
case SfxId::Coin:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 83, 60, 0, SfxWaveType::Square, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 88, 150, 50, SfxWaveType::Square, 0.35f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Powerup:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 80, 0, SfxWaveType::Pulse25, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 64, 80, 60, SfxWaveType::Pulse25, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 67, 80, 60, SfxWaveType::Pulse25, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 80, 60, SfxWaveType::Pulse25, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 76, 80, 60, SfxWaveType::Pulse25, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 80, 60, SfxWaveType::Pulse25, 0.45f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 200, 60, SfxWaveType::Pulse25, 0.5f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Jump:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 30, 0, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 65, 30, 25, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 70, 30, 25, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 75, 30, 25, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 80, 40, 25, SfxWaveType::Square, 0.3f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 50, 30, SfxWaveType::Square, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Land:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 36, 80, 0, SfxWaveType::Triangle, 0.5f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 40, 60, 0, SfxWaveType::Noise, 0.15f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Laser:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 96, 25, 0, SfxWaveType::Pulse25, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 90, 25, 20, SfxWaveType::Pulse25, 0.38f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 25, 20, SfxWaveType::Pulse25, 0.36f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 78, 30, 20, SfxWaveType::Pulse25, 0.34f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 40, 25, SfxWaveType::Pulse25, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Explosion:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 50, 0, SfxWaveType::Noise, 0.5f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 30, 300, 0, SfxWaveType::Triangle, 0.45f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 36, 150, 40, SfxWaveType::Noise, 0.45f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 30, 200, 100, SfxWaveType::Noise, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 24, 250, 150, SfxWaveType::Noise, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Hurt:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 80, 0, SfxWaveType::Sawtooth, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 120, 60, SfxWaveType::Sawtooth, 0.35f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Warp:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 40, 0, SfxWaveType::Sine, 0.3f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 36, 350, 0, SfxWaveType::Noise, 0.12f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 55, 40, 35, SfxWaveType::Sine, 0.32f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 62, 40, 35, SfxWaveType::Sine, 0.34f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 69, 40, 35, SfxWaveType::Sine, 0.36f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 76, 40, 35, SfxWaveType::Sine, 0.38f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 83, 50, 35, SfxWaveType::Sine, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 90, 60, 40, SfxWaveType::Sine, 0.3f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 96, 80, 50, SfxWaveType::Sine, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Pickup:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 60, 0, SfxWaveType::Pulse12, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 88, 60, 50, SfxWaveType::Pulse12, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 91, 100, 50, SfxWaveType::Pulse12, 0.35f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::OneUp:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 100, 0, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 76, 100, 80, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 100, 80, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 250, 80, SfxWaveType::Square, 0.45f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 60, 450, 0, SfxWaveType::Triangle, 0.2f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::BrickHit:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 76, 20, 0, SfxWaveType::Pulse25, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
// ── Notifications ────────────────────────────────────────────────────
|
||||
|
||||
case SfxId::Alert:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 80, 0, SfxWaveType::Square, 0.45f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 80, 120, SfxWaveType::Square, 0.45f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 80, 120, SfxWaveType::Square, 0.45f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Notify:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 100, 0, SfxWaveType::Sine, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 150, 90, SfxWaveType::Sine, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 67, 250, 0, SfxWaveType::Triangle, 0.15f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Success:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 100, 0, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 100, 80, SfxWaveType::Square, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 200, 80, SfxWaveType::Square, 0.45f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 60, 400, 0, SfxWaveType::Triangle, 0.2f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
// ── Drum Kit ─────────────────────────────────────────────────────────
|
||||
|
||||
case SfxId::Kick:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 15, 0, SfxWaveType::Triangle, 0.6f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 36, 60, 10, SfxWaveType::Triangle, 0.55f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Snare:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 50, 0, SfxWaveType::Noise, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 48, 30, 0, SfxWaveType::Triangle, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::HiHat:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 80, 15, 0, SfxWaveType::Noise, 0.2f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Crash:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 250, 0, SfxWaveType::Noise, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
// ── Synth Percussion ─────────────────────────────────────────────────
|
||||
|
||||
case SfxId::SynthKick:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 55, 10, 0, SfxWaveType::Sine, 0.6f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 36, 120, 8, SfxWaveType::Sine, 0.55f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::SynthSnare:
|
||||
// MetalNoise -> Noise substitution
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 80, 0, SfxWaveType::Noise, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 55, 40, 0, SfxWaveType::Triangle, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::SynthHat:
|
||||
// MetalNoise -> Noise substitution
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 30, 0, SfxWaveType::Noise, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::SynthTom:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 15, 0, SfxWaveType::Triangle, 0.5f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 100, 12, SfxWaveType::Triangle, 0.45f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::SynthRim:
|
||||
// MetalNoise -> Noise substitution
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 25, 0, SfxWaveType::Noise, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 84, 15, 0, SfxWaveType::Pulse12, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
// ── Extra Effects ────────────────────────────────────────────────────
|
||||
|
||||
case SfxId::Zap:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 96, 15, 0, SfxWaveType::Square, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 15, 10, SfxWaveType::Square, 0.30f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 15, 10, SfxWaveType::Square, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 20, 10, SfxWaveType::Square, 0.20f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Blip:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 90, 20, 0, SfxWaveType::Square, 0.3f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Chirp:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 20, 0, SfxWaveType::Pulse25, 0.3f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 30, 15, SfxWaveType::Pulse25, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Whoosh:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 30, 0, SfxWaveType::Noise, 0.15f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 30, 25, SfxWaveType::Noise, 0.20f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 30, 25, SfxWaveType::Noise, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 40, 25, SfxWaveType::Noise, 0.20f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::Ding:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 300, 0, SfxWaveType::Sine, 0.4f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 91, 200, 0, SfxWaveType::Sine, 0.2f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::RisingWhoosh:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 36, 30, 0, SfxWaveType::Noise, 0.15f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 30, 25, SfxWaveType::Noise, 0.20f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 30, 25, SfxWaveType::Noise, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 40, 25, SfxWaveType::Noise, 0.30f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 50, 30, SfxWaveType::Noise, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::FallingWhoosh:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 30, 0, SfxWaveType::Noise, 0.30f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 30, 25, SfxWaveType::Noise, 0.25f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 30, 25, SfxWaveType::Noise, 0.20f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 40, 25, SfxWaveType::Noise, 0.15f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 36, 50, 30, SfxWaveType::Noise, 0.10f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::GlitchHit:
|
||||
// MetalNoise -> Noise substitution
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 48, 20, 0, SfxWaveType::Noise, 0.45f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 36, 80, 0, SfxWaveType::Sawtooth, 0.40f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 96, 15, 15, SfxWaveType::Pulse12, 0.30f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 40, 10, SfxWaveType::Noise, 0.25f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::DigitalBurst:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 25, 0, SfxWaveType::Pulse12, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 25, 20, SfxWaveType::Pulse12, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 96, 25, 20, SfxWaveType::Pulse12, 0.35f});
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 108, 30, 20, SfxWaveType::Pulse12, 0.30f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::RetroBell:
|
||||
// HarmonicSquare -> Square substitution
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 200, 0, SfxWaveType::Square, 0.15f});
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 91, 180, 0, SfxWaveType::Pulse25, 0.10f});
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
// ── Jingles ──────────────────────────────────────────────────────────
|
||||
|
||||
// Rising arpeggio (C4-E4-G4-C5-E5-G5-C6) with sustained bass (C3)
|
||||
case SfxId::LevelUp:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 100, 0, SfxWaveType::Square, 0.28f}); // C4
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 48, 800, 0, SfxWaveType::Triangle, 0.16f}); // C3 bass pad
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 64, 100, 80, SfxWaveType::Square, 0.28f}); // E4
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 67, 100, 80, SfxWaveType::Square, 0.28f}); // G4
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 150, 80, SfxWaveType::Square, 0.32f}); // C5
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 76, 100, 130, SfxWaveType::Square, 0.32f}); // E5
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 79, 100, 80, SfxWaveType::Square, 0.32f}); // G5
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 84, 300, 80, SfxWaveType::Square, 0.40f}); // C6 (hold)
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
// Descending chromatic line (C5-B4-A4-G4-F4-E4-C4) with bass drone
|
||||
case SfxId::GameOver:
|
||||
{
|
||||
int i = 0;
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 72, 200, 0, SfxWaveType::Square, 0.30f}); // C5
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 60, 800, 0, SfxWaveType::Triangle, 0.15f}); // C4 bass drone
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 71, 200, 180, SfxWaveType::Square, 0.28f}); // B4
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 69, 200, 180, SfxWaveType::Square, 0.27f}); // A4
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 67, 200, 180, SfxWaveType::Square, 0.25f}); // G4
|
||||
ADD_SFX_NOTE(sequence_, i, {1, 55, 600, 0, SfxWaveType::Triangle, 0.15f}); // G3 bass shift
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 65, 250, 180, SfxWaveType::Square, 0.24f}); // F4
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 64, 400, 230, SfxWaveType::Square, 0.22f}); // E4
|
||||
ADD_SFX_NOTE(sequence_, i, {0, 60, 600, 380, SfxWaveType::Square, 0.18f}); // C4 (hold)
|
||||
sequenceLength_ = i;
|
||||
}
|
||||
break;
|
||||
|
||||
case SfxId::None:
|
||||
default:
|
||||
sequenceLength_ = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Start sequence
|
||||
if (sequenceLength_ > 0) {
|
||||
sequenceDelaySamples_ = (sequence_[0].delayMs * SAMPLE_RATE) / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
#undef ADD_SFX_NOTE
|
||||
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
* @file SfxEngine.h
|
||||
* @brief Lightweight SFX-only audio engine for ESP32/Tactility apps (~1.5KB RAM)
|
||||
*
|
||||
* A stripped-down version of SoundEngine focused on sound effects only.
|
||||
* No background music, no advanced synthesis (FM, filters, pluck, delay).
|
||||
*
|
||||
* Features:
|
||||
* - 4 simultaneous voices (polyphony)
|
||||
* - Waveforms: Square, Pulse (25%/12.5%/75%), Triangle, Sawtooth, Sine, Noise, RetroNoise
|
||||
* - ADSR envelope + special types (Punch, Flare, Swell, Twang, Decay)
|
||||
* - Effects: Vibrato, Pitch Sweep
|
||||
* - 52 curated predefined sound effects
|
||||
* - Queue-based triggering (thread-safe)
|
||||
* - Persistent audio task
|
||||
*
|
||||
* Usage:
|
||||
* SfxEngine* engine = new SfxEngine();
|
||||
* engine->start();
|
||||
* engine->play(SfxId::Coin);
|
||||
* engine->playNote(0, 72, 200);
|
||||
* engine->stop();
|
||||
* delete engine;
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <tactility/device.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
//==============================================================================
|
||||
// Configuration
|
||||
//==============================================================================
|
||||
|
||||
#ifndef SFX_ENGINE_NUM_VOICES
|
||||
#define SFX_ENGINE_NUM_VOICES 4
|
||||
#endif
|
||||
|
||||
#ifndef SFX_ENGINE_SAMPLE_RATE
|
||||
#define SFX_ENGINE_SAMPLE_RATE 16000
|
||||
#endif
|
||||
|
||||
#ifndef SFX_ENGINE_BUFFER_SAMPLES
|
||||
#define SFX_ENGINE_BUFFER_SAMPLES 256
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// Types
|
||||
//==============================================================================
|
||||
|
||||
enum class SfxWaveType : uint8_t {
|
||||
Square, // 50% duty cycle
|
||||
Pulse25, // 25% duty cycle (NES-style)
|
||||
Pulse12, // 12.5% duty cycle
|
||||
Pulse75, // 75% duty cycle (bright, hollow)
|
||||
Triangle,
|
||||
Sawtooth,
|
||||
Sine,
|
||||
Noise, // White noise (random)
|
||||
RetroNoise // NES-style LFSR noise
|
||||
};
|
||||
|
||||
enum class SfxId : uint8_t {
|
||||
None = 0,
|
||||
|
||||
// UI Sounds (9)
|
||||
Click, Confirm, Cancel, Error,
|
||||
MenuOpen, MenuClose, Toggle, Slider, Tab,
|
||||
|
||||
// TamaTac Pet Sounds (8)
|
||||
Feed, Play, Medicine, Sleep, Clean, Evolve, Sick, Death,
|
||||
|
||||
// Game Sounds (11)
|
||||
Coin, Powerup, Jump, Land, Laser, Explosion,
|
||||
Hurt, Warp, Pickup, OneUp, BrickHit,
|
||||
|
||||
// Notifications (3)
|
||||
Alert, Notify, Success,
|
||||
|
||||
// Drum Kit (4)
|
||||
Kick, Snare, HiHat, Crash,
|
||||
|
||||
// Synth Percussion (5)
|
||||
SynthKick, SynthSnare, SynthHat, SynthTom, SynthRim,
|
||||
|
||||
// Extra Effects (10)
|
||||
Zap, Blip, Chirp, Whoosh, Ding,
|
||||
RisingWhoosh, FallingWhoosh, GlitchHit, DigitalBurst, RetroBell,
|
||||
|
||||
// Jingles (2)
|
||||
LevelUp, GameOver
|
||||
};
|
||||
|
||||
enum class SfxEnvelopeType : uint8_t {
|
||||
ADSR, // Standard attack-decay-sustain-release
|
||||
Punch, // Constant volume with boost at start
|
||||
Flare, // Exponential rise then decay
|
||||
Swell, // Linear fade-in
|
||||
Twang, // Extremely fast decay
|
||||
Decay // Linear decay to zero
|
||||
};
|
||||
|
||||
// Compact note for SFX sequences
|
||||
struct SfxSequenceNote {
|
||||
uint8_t voice;
|
||||
uint8_t pitch;
|
||||
uint16_t durationMs;
|
||||
uint16_t delayMs;
|
||||
SfxWaveType wave;
|
||||
float volume;
|
||||
// Optional ADSR override (all zero = use defaults)
|
||||
uint16_t attackMs = 0;
|
||||
uint16_t decayMs = 0;
|
||||
float sustain = 0.0f;
|
||||
uint16_t releaseMs = 0;
|
||||
SfxEnvelopeType envType = SfxEnvelopeType::ADSR;
|
||||
|
||||
constexpr SfxSequenceNote()
|
||||
: voice(0), pitch(0), durationMs(0), delayMs(0),
|
||||
wave(SfxWaveType::Square), volume(0.0f) {}
|
||||
|
||||
constexpr SfxSequenceNote(uint8_t v, uint8_t p, uint16_t dur, uint16_t del,
|
||||
SfxWaveType w, float vol,
|
||||
uint16_t att = 0, uint16_t dec = 0, float sus = 0.0f,
|
||||
uint16_t rel = 0, SfxEnvelopeType et = SfxEnvelopeType::ADSR)
|
||||
: voice(v), pitch(p), durationMs(dur), delayMs(del), wave(w), volume(vol),
|
||||
attackMs(att), decayMs(dec), sustain(sus), releaseMs(rel), envType(et) {}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// SfxEngine Class
|
||||
//==============================================================================
|
||||
|
||||
class SfxEngine {
|
||||
public:
|
||||
SfxEngine() = default;
|
||||
~SfxEngine() { stop(); }
|
||||
|
||||
SfxEngine(const SfxEngine&) = delete;
|
||||
SfxEngine& operator=(const SfxEngine&) = delete;
|
||||
SfxEngine(SfxEngine&&) = delete;
|
||||
SfxEngine& operator=(SfxEngine&&) = delete;
|
||||
|
||||
// Lifecycle
|
||||
bool start();
|
||||
void stop();
|
||||
bool isRunning() const { return running_; }
|
||||
|
||||
// SFX API
|
||||
void play(SfxId sound);
|
||||
void stopAllSounds();
|
||||
|
||||
// Manual note API
|
||||
void playNote(uint8_t voice, uint8_t midiNote, uint16_t durationMs,
|
||||
SfxWaveType wave = SfxWaveType::Square, float volume = 0.5f);
|
||||
void stopVoice(uint8_t voice);
|
||||
|
||||
// Settings
|
||||
void setEnabled(bool enabled) { enabled_ = enabled; }
|
||||
bool isEnabled() const { return enabled_; }
|
||||
void setVolume(float vol) { masterVolume_ = (vol < 0) ? 0 : (vol > 1.0f) ? 1.0f : vol; }
|
||||
float getVolume() const { return masterVolume_; }
|
||||
|
||||
// Volume presets (consistent with SoundEngine naming)
|
||||
enum class VolumePreset { Quiet, Normal, Loud };
|
||||
void applyVolumePreset(VolumePreset preset);
|
||||
|
||||
// Polyphonic gate (consistent with SoundEngine)
|
||||
void setPolyphonicGateEnabled(bool enabled) { polyphonicGateEnabled_ = enabled; }
|
||||
bool isPolyphonicGateEnabled() const { return polyphonicGateEnabled_; }
|
||||
void setSoftGateThreshold(float threshold) {
|
||||
softGateThreshold_ = (threshold < 0.5f) ? 0.5f : (threshold > 1.0f) ? 1.0f : threshold;
|
||||
}
|
||||
float getSoftGateThreshold() const { return softGateThreshold_; }
|
||||
|
||||
// Auto-normalization (consistent with SoundEngine)
|
||||
void setAutoNormalization(bool enabled) { autoNormalize_ = enabled; }
|
||||
bool isAutoNormalizationEnabled() const { return autoNormalize_; }
|
||||
void setTargetRms(float rms) {
|
||||
targetRms_ = (rms < 0.1f) ? 0.1f : (rms > 0.8f) ? 0.8f : rms;
|
||||
}
|
||||
float getTargetRms() const { return targetRms_; }
|
||||
void setRmsSmoothing(float smoothing) {
|
||||
rmsSmoothing_ = (smoothing < 0.9f) ? 0.9f : (smoothing > 0.99999f) ? 0.99999f : smoothing;
|
||||
}
|
||||
float getRmsSmoothing() const { return rmsSmoothing_; }
|
||||
|
||||
static constexpr int NUM_VOICES = SFX_ENGINE_NUM_VOICES;
|
||||
static constexpr int SAMPLE_RATE = SFX_ENGINE_SAMPLE_RATE;
|
||||
|
||||
private:
|
||||
static constexpr const char* TAG = "SfxEngine";
|
||||
static constexpr int BUFFER_SAMPLES = SFX_ENGINE_BUFFER_SAMPLES;
|
||||
static constexpr int MAX_SFX_NOTES = 64;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Voice State
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
enum class EnvelopeStage { Off, Attack, Decay, Sustain, Release };
|
||||
|
||||
struct Voice {
|
||||
// Oscillator
|
||||
SfxWaveType wave = SfxWaveType::Square;
|
||||
float phase = 0.0f;
|
||||
float baseFreq = 0.0f;
|
||||
float currentFreq = 0.0f;
|
||||
|
||||
// Timing
|
||||
int samplePos = 0;
|
||||
int totalSamples = 0;
|
||||
|
||||
// Envelope
|
||||
SfxEnvelopeType envType = SfxEnvelopeType::ADSR;
|
||||
EnvelopeStage envStage = EnvelopeStage::Off;
|
||||
float envLevel = 0.0f;
|
||||
int envSamplePos = 0;
|
||||
int attackSamples = 0;
|
||||
int decaySamples = 0;
|
||||
float sustainLevel = 0.7f;
|
||||
int releaseSamples = 0;
|
||||
|
||||
// Volume
|
||||
float volume = 0.5f;
|
||||
|
||||
// Pitch effects
|
||||
float vibratoDepth = 0.0f;
|
||||
float vibratoRate = 0.0f;
|
||||
float vibratoPhase = 0.0f;
|
||||
float pitchSweep = 0.0f;
|
||||
|
||||
bool active = false;
|
||||
};
|
||||
|
||||
Voice voices_[NUM_VOICES] = {};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// SFX Sequence
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
SfxSequenceNote sequence_[MAX_SFX_NOTES] = {};
|
||||
int sequenceLength_ = 0;
|
||||
int sequenceIndex_ = 0;
|
||||
int sequenceDelaySamples_ = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Queue Messages
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
enum class MsgType : uint8_t {
|
||||
PlaySound, PlayNote, StopVoice, StopAll
|
||||
};
|
||||
|
||||
struct PlayNoteMsg {
|
||||
uint8_t voice;
|
||||
uint8_t midiNote;
|
||||
uint16_t durationMs;
|
||||
SfxWaveType wave;
|
||||
float volume;
|
||||
};
|
||||
|
||||
struct QueueMsg {
|
||||
MsgType type;
|
||||
union {
|
||||
SfxId sfxId;
|
||||
PlayNoteMsg note;
|
||||
uint8_t voiceIndex;
|
||||
};
|
||||
|
||||
QueueMsg() : type(MsgType::StopAll), sfxId(SfxId::None) {}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// State
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Device* i2sDevice_ = nullptr;
|
||||
TaskHandle_t task_ = nullptr;
|
||||
SemaphoreHandle_t stopSemaphore_ = nullptr; // Signaled when audio task exits
|
||||
QueueHandle_t msgQueue_ = nullptr;
|
||||
|
||||
volatile bool running_ = false;
|
||||
volatile bool enabled_ = true;
|
||||
volatile float masterVolume_ = 0.5f;
|
||||
|
||||
// Polyphonic gate
|
||||
volatile bool polyphonicGateEnabled_ = true;
|
||||
volatile float softGateThreshold_ = 0.95f;
|
||||
|
||||
// Auto-normalization
|
||||
volatile bool autoNormalize_ = true;
|
||||
volatile float targetRms_ = 0.35f;
|
||||
volatile float rmsSmoothing_ = 0.999f;
|
||||
|
||||
// Noise generator state (per-instance, audio task only)
|
||||
uint16_t lfsr_ = 0xACE1;
|
||||
uint16_t retroLfsr_ = 0xACE1;
|
||||
|
||||
// Auto-normalization working state (audio task only)
|
||||
float currentRms_ = 0.0f;
|
||||
int rmsCalcCounter_ = 0;
|
||||
float cachedNormGain_ = 1.0f;
|
||||
|
||||
// Audio buffer (member to avoid stack pressure in audio task)
|
||||
int16_t audioBuffer_[BUFFER_SAMPLES * 2] = {};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Audio Generation
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static float midiToFreq(uint8_t midi);
|
||||
float generateNoise();
|
||||
float generateRetroNoise();
|
||||
float oscillator(SfxWaveType wave, float phase);
|
||||
void updateEnvelope(Voice& v);
|
||||
float generateVoiceSample(Voice& v);
|
||||
void fillStereoBuffer(int16_t* buf, int samples);
|
||||
float applyPolyphonicGate(float mix, int activeVoices);
|
||||
float applyAutoNormalization(float mix);
|
||||
float applyBrickWallLimiter(float sample);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Sound Loading
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void loadSound(SfxId sound);
|
||||
void triggerNote(Voice& v, uint8_t midiNote, uint16_t durationMs,
|
||||
SfxWaveType wave, float volume, SfxEnvelopeType envType,
|
||||
uint16_t attackMs = 0, uint16_t decayMs = 0,
|
||||
float sustain = 0.0f, uint16_t releaseMs = 0);
|
||||
void processSequence();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Task
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static void audioTaskFunc(void* param);
|
||||
};
|
||||
Reference in New Issue
Block a user