SaXAudio is a Simple audio library using XAudio
It provides an easy-to-use C++ interface for loading, playing, and manipulating audio with advanced features like real-time effects and audio routing.
- Audio Bank System: Efficiently manage multiple audio assets with automatic memory handling
- Ogg Vorbis Support: Decode and play Ogg Vorbis audio files with asynchronous loading
- Multiple Voice Playback: Create multiple simultaneous audio voices from the same or different audio sources
- Real-time Parameter Control: Adjust volume, speed, and panning during playback with smooth fading
- Advanced Looping: Set custom loop points with sample-accurate precision
- Audio Effects: Built-in reverb, EQ, and echo effects for voices and buses
- Audio Routing: Use buses to group and process multiple voices together
- Flexible Playback Control: Start, stop, pause, and resume with fade transitions
- Seek Support: Jump to specific positions in audio (by sample or time)
- Pause Stack System: Handle multiple pause/resume operations gracefully
- Voice Protection: Protect specific voices from global pause/resume operations
- Callback System: Get notified when voices finish playing
- Position Tracking: Monitor playback position in real-time
- Fade Transitions: Smooth parameter changes and playback control
- Resource Management: Automatic cleanup and memory management
#include "SaXAudio.h"
// Initialize XAudio2 and create master voice
BOOL success = SaXAudio::Create();
if (!success) {
// Handle initialization failure
return false;
}// Option 1: Load directly from file (easiest)
INT32 bankID = SaXAudio::BankLoadOggFile("audio.ogg");
if (bankID == 0) {
// Handle loading failure
}
// Option 2: Load from memory buffer
BYTE* audioBuffer = /* your audio data */;
UINT32 bufferSize = /* size of your audio data */;
INT32 bankID = SaXAudio::BankAddOgg(audioBuffer, bufferSize);// Create a bus for audio routing (optional)
INT32 busID = SaXAudio::CreateBus();
// Create a voice for playback
INT32 voiceID = SaXAudio::CreateVoice(bankID, busID, true); // starts paused
if (voiceID == 0) {
// Handle voice creation failure
}
// Configure voice settings
SaXAudio::SetVolume(voiceID, 0.8f); // 80% volume
SaXAudio::SetPanning(voiceID, -0.5f); // Pan left
SaXAudio::SetLooping(voiceID, true); // Enable looping// Start playing the voice
BOOL playing = SaXAudio::Start(voiceID);
if (!playing) {
// Handle playback failure
}
// Or start at a specific time
SaXAudio::StartAtTime(voiceID, 10.5f); // Start at 10.5 secondsNote: Voices are automatically destroyed when they finish playing (unless looping). Use the SetOnFinishedCallback() to get notified when this happens.
// Adjust parameters during playback with smooth transitions
SaXAudio::SetSpeed(voiceID, 0.5f, 2.0f); // Slow to half speed over 2 seconds
SaXAudio::SetVolume(voiceID, 0.3f, 1.0f); // Fade to 30% volume over 1 second
// Control playback
SaXAudio::Pause(voiceID, 0.5f); // Pause with 0.5s fade
SaXAudio::Resume(voiceID, 0.5f); // Resume with 0.5s fade
SaXAudio::Stop(voiceID, 1.0f); // Stop with 1s fade (destroys voice)// Remove audio from bank when no longer needed
SaXAudio::BankRemove(bankID);
// Or use auto-removal (removes when all voices finish)
SaXAudio::BankAutoRemove(bankID);
// Shutdown audio system
SaXAudio::Release();For quick testing, you can use the one-liner function:
#include "SaXAudio.h"
int main() {
// Play a file with one function call (handles initialization too)
INT32 voiceID = SaXAudio::PlayOggFile("sound.ogg");
if (voiceID != 0) {
// Optionally control the voice
SaXAudio::SetVolume(voiceID, 0.5f);
std::cout << "Playing... Press Enter to stop." << std::endl;
std::cin.get();
SaXAudio::Stop(voiceID);
}
SaXAudio::Release();
return 0;
}#include <iostream>
#include "SaXAudio.h"
// Callback function for when voices finish playing
void OnVoiceFinished(INT32 voiceID) {
std::cout << "Voice " << voiceID << " finished playing" << std::endl;
}
int main() {
// Initialize audio system
if (!SaXAudio::Create()) {
std::cerr << "Failed to initialize SaXAudio" << std::endl;
return 1;
}
// Set up finished callback
SaXAudio::SetOnFinishedCallback(OnVoiceFinished);
// Load audio file - now much easier!
INT32 bankID = SaXAudio::BankLoadOggFile("sound.ogg");
if (bankID == 0) {
std::cerr << "Failed to load audio file" << std::endl;
SaXAudio::Release();
return 1;
}
// Create bus and voice
INT32 busID = SaXAudio::CreateBus();
INT32 voiceID = SaXAudio::CreateVoice(bankID, busID);
if (voiceID == 0) {
std::cerr << "Failed to create voice" << std::endl;
SaXAudio::BankRemove(bankID);
SaXAudio::Release();
return 1;
}
// Configure and start playback
SaXAudio::SetVolume(voiceID, 0.7f);
SaXAudio::SetLooping(voiceID, true);
if (!SaXAudio::Start(voiceID)) {
std::cerr << "Failed to start playback" << std::endl;
} else {
std::cout << "Playing audio... Press Enter to stop." << std::endl;
std::cin.get();
// Fade out and stop
SaXAudio::Stop(voiceID, 1.0f);
}
// Cleanup
SaXAudio::BankRemove(bankID);
SaXAudio::Release();
return 0;
}Create()- Initialize XAudio2 and create master voiceRelease()- Clean up all resourcesStartEngine()/StopEngine()- Start/stop the audio engine
PlayOggFile(filePath, busID)- One-call file loading and playback
PauseAll(fade, busID)- Pause all voices (or specific bus)ResumeAll(fade, busID)- Resume all voices (or specific bus)StopAll(fade, busID)- Stop all voices (or specific bus)Protect(voiceID)- Protect voice from global operations
BankAddOgg(buffer, length, callback)- Add Ogg Vorbis data from memoryBankLoadOggFile(filePath)- Load Ogg file directly into bankBankRemove(bankID)- Remove audio data from bankBankAutoRemove(bankID)- Auto-remove bank when all voices finish
CreateVoice(bankID, busID, paused)- Create new voiceVoiceExist(voiceID)- Check if voice exists
CreateBus()- Create audio bus for grouping voicesRemoveBus(busID)- Remove bus (stops all voices on it)
Start(voiceID)- Start voice playbackStartAtSample(voiceID, sample)- Start/seek to specific sampleStartAtTime(voiceID, time)- Start/seek to specific timeStop(voiceID, fade)- Stop voice with fadePause(voiceID, fade)- Pause voice with fade (stacks)Resume(voiceID, fade)- Resume voice with fade (unstacks)GetPauseStack(voiceID)- Get current pause stack count
SetMasterVolume(volume, fade)- Set global master volumeSetVolume(voiceID, volume, fade, isBus)- Set voice/bus volume [0.0-1.0]SetSpeed(voiceID, speed, fade)- Set playback speed (affects pitch)SetPanning(voiceID, panning, fade)- Set stereo panning [-1.0-1.0]SetLooping(voiceID, looping)- Enable/disable loopingSetLoopPoints(voiceID, start, end)- Set custom loop boundaries
GetMasterVolume()- Get global master volumeGetVolume(voiceID)- Get voice volume [0.0-1.0]GetSpeed(voiceID)- Get playback speed multiplierGetPanning(voiceID)- Get stereo panning [-1.0-1.0]GetLooping(voiceID)- Get looping stateGetLoopStart(voiceID)/GetLoopEnd(voiceID)- Get loop boundaries
SetReverb(voiceID, params, fade, isBus)- Apply reverb effectRemoveReverb(voiceID, fade, isBus)- Remove reverb effectSetEq(voiceID, params, fade, isBus)- Apply EQ effectRemoveEq(voiceID, fade, isBus)- Remove EQ effectSetEcho(voiceID, params, fade, isBus)- Apply echo effectRemoveEcho(voiceID, fade, isBus)- Remove echo effect
GetPositionSample(voiceID)- Get current playback position in samplesGetPositionTime(voiceID)- Get current playback position in secondsGetTotalSample(voiceID)- Get total audio length in samplesGetTotalTime(voiceID)- Get total audio duration in secondsGetSampleRate(voiceID)- Get audio sample rate in HzGetChannelCount(voiceID)- Get number of audio channels
GetVoiceCount()- Get number of currently active voicesGetBankCount()- Get number of loaded audio banks
SetOnFinishedCallback(callback)- Set callback for when voices finish playing
- Windows 10 or later
- XAudio2 (included with Windows)
- Visual Studio 2019 or later (for building)
- XAudio2 - Microsoft's audio API
- stb_vorbis - Ogg Vorbis decoder
MIT License - see LICENSE file for details.
Contributions are welcome! Please feel free to submit issues and pull requests.