AudioEngine¶
Core class for the NES-like audio subsystem.
Description¶
AudioEngine manages the audio channels (Pulse, Triangle, Noise), mixes their output, and provides the audio stream to the backend. It implements a NES-like audio system with 4 fixed channels: 2 Pulse channels, 1 Triangle channel, and 1 Noise channel.
The engine is event-driven: you trigger sound effects via playEvent(), and the engine automatically manages channel allocation and playback.
Namespace¶
Inheritance¶
- Base class: None (standalone class)
- Used by:
Engine(manages audio engine instance)
Constructors¶
AudioEngine(const AudioConfig& config)¶
Constructs the AudioEngine with the given configuration.
Parameters: - config (const AudioConfig&): Configuration struct containing the backend and parameters (sample rate, etc.)
Example:
#include "audio/AudioEngine.h"
#include "audio/AudioConfig.h"
pixelroot32::audio::AudioConfig audioConfig;
audioConfig.backend = &audioBackend; // Platform-specific backend
audioConfig.sampleRate = 22050; // 22.05 kHz for retro feel
pixelroot32::audio::AudioEngine audioEngine(audioConfig);
audioEngine.init();
Public Methods¶
void init()¶
Initializes the audio subsystem and the backend.
Returns: - void
Notes: - Must be called after construction and before use - Initializes the platform-specific audio backend - Safe to call multiple times (idempotent) - Typically called automatically by Engine::init()
Example:
void update(unsigned long deltaTime)¶
Updates the audio state based on game time.
Parameters: - deltaTime (unsigned long): Time elapsed since last frame in milliseconds
Returns: - void
Notes: - Should be called from the main game loop (typically via Engine::update()) - Updates channel lifetimes and durations - Automatically stops channels when their duration expires - Must be called every frame for proper audio timing
Example:
void update(unsigned long deltaTime) override {
// Update audio (called automatically by Engine)
engine.getAudioEngine().update(deltaTime);
// Your game logic...
}
void generateSamples(int16_t* stream, int length)¶
Fills the provided buffer with mixed audio samples.
Parameters: - stream (int16_t*): Pointer to the buffer to fill - length (int): Number of samples to generate
Returns: - void
Notes: - This method is typically called by the AudioBackend from an audio callback or task - Not usually called directly by game code - Generates 16-bit signed integer PCM samples - Mixes all active channels into a mono stream
Advanced Usage:
// Typically not called directly, but if implementing custom backend:
int16_t buffer[512];
audioEngine.generateSamples(buffer, 512);
void playEvent(const AudioEvent& event)¶
Triggers a one-shot sound effect.
Parameters: - event (const AudioEvent&): The audio event to play
Returns: - void
Notes: - Automatically finds an available channel of the correct type - If no channel is available, the event may be dropped (no error) - Events are fire-and-forget (no need to track playback) - Use for sound effects, not background music
Example:
// Play a jump sound
pixelroot32::audio::AudioEvent jumpSound{};
jumpSound.type = pixelroot32::audio::WaveType::PULSE;
jumpSound.frequency = 800.0f;
jumpSound.duration = 0.1f;
jumpSound.volume = 0.7f;
jumpSound.duty = 0.5f;
auto& audio = engine.getAudioEngine();
audio.playEvent(jumpSound);
// Play an explosion sound
pixelroot32::audio::AudioEvent explosion{};
explosion.type = pixelroot32::audio::WaveType::NOISE;
explosion.frequency = 1000.0f;
explosion.duration = 0.3f;
explosion.volume = 0.9f;
audio.playEvent(explosion);
void setMasterVolume(float volume)¶
Sets the master volume for all audio output.
Parameters: - volume (float): Volume level (0.0 = silent, 1.0 = full volume)
Returns: - void
Notes: - Affects all channels and events - Clamped to [0.0, 1.0] range - Use for volume control menus or mute functionality
Example:
auto& audio = engine.getAudioEngine();
audio.setMasterVolume(0.5f); // 50% volume
audio.setMasterVolume(0.0f); // Mute
audio.setMasterVolume(1.0f); // Full volume
float getMasterVolume() const¶
Gets the current master volume.
Returns: - float: Current master volume (0.0 to 1.0)
Example:
Audio Channels¶
The engine manages 4 fixed channels:
- Channel 0: Pulse wave
- Channel 1: Pulse wave
- Channel 2: Triangle wave
- Channel 3: Noise wave
Notes: - Channels are automatically allocated when playing events - If all channels of a type are busy, new events may be dropped - Background music typically uses one channel (via MusicPlayer)
Usage Example¶
#include "audio/AudioEngine.h"
#include "audio/AudioConfig.h"
class MyScene : public pixelroot32::core::Scene {
private:
void playJumpSound() {
auto& audio = engine.getAudioEngine();
pixelroot32::audio::AudioEvent sound{};
sound.type = pixelroot32::audio::WaveType::PULSE;
sound.frequency = 800.0f;
sound.duration = 0.1f;
sound.volume = 0.7f;
sound.duty = 0.5f;
audio.playEvent(sound);
}
void playHitSound() {
auto& audio = engine.getAudioEngine();
pixelroot32::audio::AudioEvent sound{};
sound.type = pixelroot32::audio::WaveType::NOISE;
sound.frequency = 500.0f;
sound.duration = 0.05f;
sound.volume = 0.5f;
audio.playEvent(sound);
}
void update(unsigned long deltaTime) override {
Scene::update(deltaTime);
// Audio is updated automatically by Engine
// Just play events when needed
if (playerJumped) {
playJumpSound();
playerJumped = false;
}
}
};
Performance Considerations¶
- Channel limit: Only 4 channels total; plan sound effects accordingly
- Event dropping: If all channels are busy, new events are silently dropped
- Update frequency:
update()must be called every frame for proper timing - Sample generation:
generateSamples()is called by backend at audio rate (not game rate)
ESP32 Considerations¶
- Sample rate: Lower sample rates (11025 Hz) use less CPU and memory
- Backend choice: DAC backend is simpler but lower quality than I2S
- Buffer size: Larger buffers reduce underruns but increase latency
- Channel management: Limit simultaneous sounds to avoid channel conflicts
See Also¶
- AudioConfig - Audio configuration
- AudioTypes - Audio data structures
- MusicPlayer - Background music playback
- Manual - Audio
- API Overview