Create Audio from an audio file with Audio variableName{ U"filePath" };
File paths use relative paths from the folder where the executable is located (the App folder during development) or absolute paths
For example, U"example/test.mp3" refers to the test.mp3 file in the example/ folder of the folder where the executable is located (App folder)
Siv3D supports loading the following audio formats:
Some audio formats have different support depending on the OS
Format
Extension
Windows
macOS
Linux
Web
WAVE
.wav
✅
✅
✅
✅
MP3
.mp3
✅
✅
✅
✅*
AAC
.m4a
✅
✅
✅
✅*
OggVorbis
.ogg
✅
✅
✅
✅
Opus
.opus
✅
✅
✅
✅
MIDI
.mid
✅
✅
✅
✅
WMA
.wma
✅
FLAC
.flac
✅
✅
AIFF
.aif, .aiff, .aifc
✅
(*) Requires build option settings and use of special functions.
To play audio, call Audio's .play()
Calling .play() on audio that is already playing does nothing
To play the same audio overlapping, use .playOneShot() from 41.6
#include<Siv3D.hpp>voidMain(){// Load audio file and create AudioconstAudioaudio{U"example/test.mp3"};// Play audioaudio.play();while(System::Update()){}}
Audio cannot be played if the audio object doesn't exist
Code like Audio{ U"example/test.mp3" }.play(); using temporary objects cannot play audio
WAVE, MP3, OggVorbis, and FLAC format audio files support streaming playback
Streaming playback doesn't load the entire file content at first, but loads only a portion to start audio playback while progressively loading the remaining parts
Using streaming playback significantly reduces file loading time during audio creation and memory usage during playback
To enable streaming playback, pass Audio::Stream to the Audio constructor to request streaming playback
If the requested file doesn't support streaming playback, normal loading is performed
You can check if streaming playback is enabled with .isStreaming()
#include<Siv3D.hpp>voidMain(){// Load audio file and create Audio (request streaming playback)constAudioaudio{Audio::Stream,U"example/test.mp3"};// Returns true if streaming playback is enabledPrint<<audio.isStreaming();// Play audioaudio.play();while(System::Update()){}}
Audio with streaming playback enabled has the following limitations, but they don't cause problems for normal audio playback:
In loop playback, the loop end position cannot be set to anything other than the audio end
Cannot access audio waveform data with .getSamples()
Empty audio is a 0.5-second sound that makes a "whoosh" sound, and can be treated the same as valid audio, with no errors when played
Audio file loading failures also result in empty audio
To check if audio is empty, use if (audio.isEmpty()), if (audio), or if (not audio)
#include<Siv3D.hpp>voidMain(){// Without providing initial data, it becomes empty audioAudioaudioA;if(notaudioA){Print<<U"audioA is empty";}// If audio file loading fails, it becomes empty audioAudioaudioB{U"aaa/bbb.wav"};if(notaudioB){Print<<U"audioB is empty";}while(System::Update()){if(SimpleGUI::Button(U"Play A",Vec2{200,20})){audioA.playOneShot();}if(SimpleGUI::Button(U"Play B",Vec2{200,60})){audioB.playOneShot();}}}
There are member functions for audio playback and stop operations:
Audio paused with .pause() resumes playback from the paused position
On the other hand, audio stopped with .stop() returns the playback position to the beginning
Code
Description
.play()
Play audio
.pause()
Pause audio
.stop()
Stop audio and return playback position to the beginning
.isPlaying()
Returns whether audio is playing
.isPaused()
Returns whether audio is paused
.playOneShot()
Play audio (overlapping playback)
.pauseAllShots()
Pause all overlapping audio
.resumeAllShots()
Resume all paused overlapping audio
.stopAllShots()
Stop all overlapping audio
#include<Siv3D.hpp>voidMain(){constAudioaudio{Audio::Stream,U"example/test.mp3"};while(System::Update()){ClearPrint();// Whether playingPrint<<U"isPlaying: "<<audio.isPlaying();// Whether pausedPrint<<U"isPaused: "<<audio.isPaused();if(SimpleGUI::Button(U"Play",Vec2{200,20})){// Play/resumeaudio.play();}if(SimpleGUI::Button(U"Pause",Vec2{200,60})){// Pauseaudio.pause();}if(SimpleGUI::Button(U"Stop",Vec2{200,100})){// Stop and return playback position to the beginningaudio.stop();}}}
To change audio volume, use .setVolume(volume) to set a value from 0.0 to 1.0
The default volume is 1.0
You can get the set volume with .getVolume()
.setVolume(volume) does not apply to audio played with .playOneShot()
#include<Siv3D.hpp>voidMain(){constAudioaudio{Audio::Stream,U"example/test.mp3"};audio.play();doublevolume=1.0;while(System::Update()){ClearPrint();// Get current volumePrint<<audio.getVolume();if(SimpleGUI::Slider(U"volume: {:.2f}"_fmt(volume),volume,Vec2{200,20},160,140)){// Set volumeaudio.setVolume(volume);}}}
41.10 Volume Control Considering Human Characteristics¶
The human ear perceives sound loudness logarithmically rather than linearly relative to volume
While 0.0 → 0.5 causes a large change in perceived loudness, 0.5 → 1.0 doesn't feel like the sound gets much louder
When implementing volume sliders, you can make volume changes closer to human perception by doing the following:
#include<Siv3D.hpp>doubleLinearToLog(doublevalue){if(value==0.0){return0.0;}constdoubleminDb=-40.0;// Adjust as neededconstdoubledb=(minDb*(1.0-value));returnMath::Pow(10.0,(db/20.0));}voidMain(){constAudioaudio{Audio::Stream,U"example/test.mp3"};audio.play();size_tindex=0;doublevolume=1.0;while(System::Update()){if(SimpleGUI::RadioButtons(index,{U"Linear",U"Log"},Vec2{200,40},160,20)){if(index==0){audio.setVolume(volume);}else{audio.setVolume(LinearToLog(volume));}}if(index==0){if(SimpleGUI::Slider(U"volume: {:.4f}"_fmt(volume),volume,Vec2{400,40},160,140)){audio.setVolume(volume);}}else{if(SimpleGUI::Slider(U"volume: {:.4f}"_fmt(LinearToLog(volume)),volume,Vec2{400,40},160,140)){audio.setVolume(LinearToLog(volume));}}}}
Passing time as an argument to .play(), .pause(), .stop() causes the volume to fade in/out over that time
Pause and stop are delayed until fade out is complete
Code
Description
.play(duration)
Start playing from volume 0 and change volume to 1 over the specified time
.pause(duration)
Change volume from current volume to 0 over the specified time and pause
.stop(duration)
Change volume from current volume to 0 over the specified time, stop and return playback position to the beginning
#include<Siv3D.hpp>voidMain(){constAudioaudio{Audio::Stream,U"example/test.mp3"};while(System::Update()){ClearPrint();// Whether playingPrint<<U"isPlaying: "<<audio.isPlaying();// Whether pausedPrint<<U"isPaused: "<<audio.isPaused();// Current volumePrint<<audio.getVolume();if(SimpleGUI::Button(U"Play",Vec2{200,20})){// Play/resume over 2 secondsaudio.play(2s);}if(SimpleGUI::Button(U"Pause",Vec2{200,60})){// Pause over 2 secondsaudio.pause(2s);}if(SimpleGUI::Button(U"Stop",Vec2{200,100})){// Stop over 2 seconds and return playback position to the beginningaudio.stop(2s);}}}
Using .fadeVolume(volume, duration) gradually changes the volume to volume over the specified time duration
#include<Siv3D.hpp>voidMain(){constAudioaudio{Audio::Stream,U"example/test.mp3"};audio.play();while(System::Update()){ClearPrint();// Current volumePrint<<audio.getVolume();if(SimpleGUI::Button(U"1.0",Vec2{200,20})){// Change volume to 1.0 over 2 secondsaudio.fadeVolume(1.0,2s);}if(SimpleGUI::Button(U"0.5",Vec2{200,60})){// Change volume to 0.5 over 1 secondaudio.fadeVolume(0.5,1s);}if(SimpleGUI::Button(U"0.1",Vec2{200,100})){// Change volume to 0.1 over 1.5 secondsaudio.fadeVolume(0.1,1.5s);}}}
To change playback speed, use .setSpeed(speed) or .fadeSpeed(speed, duration) to set the playback speed multiplier
The default playback speed is 1.0
Increasing playback speed makes the sound higher, and decreasing it makes it lower
To avoid pitch changes when changing speed, use 41.20 pitch shift
You can get the current playback speed with .getSpeed()
#include<Siv3D.hpp>voidMain(){constAudioaudio{Audio::Stream,U"example/test.mp3"};audio.play();while(System::Update()){ClearPrint();// Current speedPrint<<audio.getSpeed();if(SimpleGUI::Button(U"1.2",Vec2{200,20})){// Change speed to 1.2 over 2 secondsaudio.fadeSpeed(1.2,2s);}if(SimpleGUI::Button(U"1.0",Vec2{200,60})){// Change speed to 1.0 over 1 secondaudio.fadeSpeed(1.0,1s);}if(SimpleGUI::Button(U"0.8",Vec2{200,100})){// Change speed to 0.8 over 1.5 secondsaudio.fadeSpeed(0.8,1.5s);}}}
To change left-right volume balance (pan), use .setPan(pan) or .fadePan(pan, duration) to set pan in the range -1.0 to 1.0
-1.0 is far left, 1.0 is far right, and the default is center 0.0
You can get the current pan with .getPan()
#include<Siv3D.hpp>voidMain(){constAudioaudio{Audio::Stream,U"example/test.mp3"};audio.play();while(System::Update()){ClearPrint();// Current panPrint<<audio.getPan();if(SimpleGUI::Button(U"0.9",Vec2{200,20})){// Change pan to 0.9 over 2 secondsaudio.fadePan(0.9,2s);}if(SimpleGUI::Button(U"0.0",Vec2{200,60})){// Change pan to 0.0 over 1 secondaudio.fadePan(0.0,1s);}if(SimpleGUI::Button(U"-0.9",Vec2{200,100})){// Change pan to -0.9 over 1.5 secondsaudio.fadePan(-0.9,1.5s);}}}
There are member functions to get audio playback time and playback position:
Code
Description
.lengthSec()
Returns total audio playback time (seconds)
.lengthSample()
Returns total audio playback sample count
.posSec()
Returns current playback position (seconds)
.posSample()
Returns current playback position (sample count)
These values can be used for timing effects with music and rhythm game timing
#include<Siv3D.hpp>voidMain(){constAudioaudio{Audio::Stream,U"example/test.mp3"};audio.play();while(System::Update()){ClearPrint();// Total song lengthPrint<<U"all: {:.1f} sec ({} samples)"_fmt(audio.lengthSec(),audio.samples());// Current playback positionPrint<<U"play: {:.1f} sec ({} samples)"_fmt(audio.posSec(),audio.posSample());}}
You can classify audio played in applications into groups like "BGM", "environmental sounds", "character voices", etc., and control volume and filters for each group
Each group is called a mixing bus
All audio is processed through one of four groups: MixBus0 to MixBus3
Default is set to MixBus0
Audio that passes through the mixing bus goes through global audio for playback
You can also control volume and filters for global audio
The final output volume is calculated as follows:
Volume set in Audio × Mixing bus volume × Global audio volume
Set pitch shift to the index-th filter of mixing bus mixbus
pitchShift is specified in semitone units
0.0 represents no pitch change
12.0 represents raising by one octave
-12.0 represents lowering by one octave
#include<Siv3D.hpp>voidMain(){// Load audio file and create AudioconstAudioaudio{U"example/test.mp3"};// Play audioaudio.play();// Amount of pitch shiftdoublepitchShift=0.0;while(System::Update()){if(SimpleGUI::Slider(U"pitchShift: {:.2f}"_fmt(pitchShift),pitchShift,-12.0,12.0,Vec2{40,40},160,300)){// Set pitch shift to the 0th filter of MixBus0GlobalAudio::BusSetPitchShiftFilter(MixBus0,0,pitchShift);}}}
From non-streaming audio, you can access the entire audio waveform data with .getSamples(channel)
channel represents 0 for left channel and 1 for right channel, returning a pointer const float* to the beginning of each channel's waveform
#include<Siv3D.hpp>voidMain(){constAudioaudio{U"example/test.mp3"};audio.play();constfloat*pSamples=audio.getSamples(0);LineStringlines(800);while(System::Update()){constint64posSample=audio.posSample();// Get 800 samples of waveform from current playback positionfor(int64i=posSample;i<(posSample+800);++i){if(i<audio.samples()){lines[i-posSample].set((i-posSample),(300+pSamples[i]*200));}else{lines[i-posSample].set((i-posSample),300);}}// Draw waveformlines.draw(2);}}
You can get recent 256 samples of waveform data that passed through mixing buses as Array<float>
You can get composite waveforms of all audio played through mixing buses regardless of streaming
Code
Source
GlobalAudio::GetSamples()
Global audio
GlobalAudio::BusGetSamples(mixbus)
Mixing bus
#include<Siv3D.hpp>voidMain(){constAudioaudio1{U"example/test.mp3"};constAudioaudio2{GMInstrument::Trumpet,PianoKey::E4,0.5s};audio1.play();LineStringlines(256);Array<float>samples;while(System::Update()){if(KeySpace.down()){audio2.playOneShot();}// Get recent 256 samples of waveform that passed through global audioGlobalAudio::GetSamples(samples);for(size_ti=0;i<samples.size();++i){lines[i].set((i*800.0/256.0),(300+samples[i]*200));}// Draw waveformlines.draw(2);}}