In this tutorial we will add audio support using the BASS audio provider.
Start by downloading these three sounds and put them in the output folder
Name | Type | Url |
---|---|---|
Bomb.mp3 | Sample | http://www.freesound.org/people/Zangrutz/sounds/155235/ |
Missile.wav | Sample | http://www.freesound.org/people/Benboncan/sounds/167563/ |
Music.wav | Stream | http://www.freesound.org/people/ERH/sounds/30192/ |
Or download them in one zip file from here
You can download the source for this tutorial here.
Start by adding the phxAudio unit to the uses list. We also need to include a provider, in this case we use the Bass provider. There is a OpenAL provider included aswell but it is not completed as of 2013-08-08
uses ... // Audio classes phxAudio, // Audio device using the bass provider phxAudio_Bass;
Next we have to add the audio engine variable and the other content that is needed.
TGame = class(TPHXApplication) private Device: TPHXDevice; Timer : TPHXTimer; Canvas: TPHXCanvas; Fonts : TPHXFontList; Input : TPHXInput; Audio : TPHXAudioEngine; public procedure Init; override; procedure Update; override; procedure Render; override; procedure Shutdown; override; end;
Now we have to create a instance of the engine as well as initialize it. Calling the Initialize function of the audio engine initializes the audio using the default sound device that is selected in the os.
procedure TGame.Init; begin ... // Create the audio engine using the included BASS provider Audio:= TPHXAudioEngine.Create; // Initialize the audio engine using the default audio device Audio.Initialize; end;
To select the audio output device we first have to determine the name or index of the device to use. The Devices property of the audio engine contains all supported devices and are initialized when the audio engine is creates.
for Index:=0 to Audio.Devices.Count-1 do begin Fonts[0].TextOut(400, 4 + Fonts[0].Height * Index, Format('%d: %s', [Index, Audio.Devices[Index].Name])); end;
To select the audio engine with a specific device we have to call the Initialize function with the device index or name.
// Initialize the audio engine using a audio device by index Audio.Initialize(2); // Initialize the audio engine using a audio device by name Audio.Initialize('SPDIF Out (Creative SB X-Fi)');
Samples are loaded into memory and is used for effects that needs to be played without any delays.
procedure TGame.Init; begin ... // Load the bomb sample Audio.LoadSample('Bomb.mp3', 'Bomb'); // Load the missile sample Audio.LoadSample('Missile.wav', 'Missile'); end;
To play a loaded audio sample we can use the Play method of the audio engine.
procedure TGame.Update; begin ... // Update the audio engine Audio.Update; // Play the bomb sample with the left mouse button if isButton1 in Input.States then begin Audio.Play('Bomb'); Input.States:= Input.States - [isButton1]; end; // Play the missile sample the right mouse button if isButton2 in Input.States then begin Audio.Play('Missile'); Input.States:= Input.States - [isButton2]; end; end;
It is also possible to play the sample with a specific volume
// Play the missile sample at 50% volume with the right mouse button if isButton3 in Input.States then begin Audio.Play('Missile', 0.5); // Remove the state Input.States:= Input.States - [isButton3]; end;
Audio streams are used to play music that are to large to upload into memory before playing, there might be some delay when starting playing them due to the disk access.
To load a music stream we call the LoadSample function of the audio engine with the filename and optional name of the audio file.
procedure TGame.Init; begin ... // Streams are streamed from disk and are used for music Music:= Audio.LoadStream('string-1-loop.wav', 'Music'); // We want to loop the music Music.Looped:= True; // Set the volume of the music from 0.0 (silent) to 1.0 (full) Music.Volume:= 0.5; // Play the music Music.Play; end;
This function returns a TPHXAudioStream instance where it is possible to set if the stream should be looped and read the duration and position of the sample.
Fonts[0].TextOut(4, 4 + Fonts[0].Height * 0, Format('Music volume: %d %%', [ Round(Music.Volume*100)])); Fonts[0].TextOut(4, 4 + Fonts[0].Height * 1, Format('Music position: %.1f s', [Music.Position])); Fonts[0].TextOut(4, 4 + Fonts[0].Height * 2, Format('Music duration: %.1f s', [Music.Duration]));
To change the master volume of the audio we can write to the Volume property of the audio engine.
procedure TGame.KeyPressed(Key: TPHXVirtualKey; Shift: TPHXShiftStates); begin inherited; // Change the master volume to 50% when pressing 1 on the keyboard if Key = VK_1 then begin Audio.Volume:= 0.5; end; // Change the master volume to 100% when pressing 2 on the keyboard if Key = VK_2 then begin Audio.Volume:= 1.0; end; end;
To change the volume of the music we have to modify the Volume property of the audio stream.
// Raise the volume of the music if isUp in Input.States then begin Music.Volume:= Music.Volume + 0.2 * Timer.FrameTime; if Music.Volume > 1 then Music.Volume:= 1; end; // Lower the volume of the music if isDown in Input.States then begin Music.Volume:= Music.Volume - 0.2 * Timer.FrameTime; if Music.Volume < 0 then Music.Volume:= 0; end;
To change the volume of a sample we have to modify the Volume property of the audio sample. This changes the volume of all channels playing this sample
// Change the volume of all playing instances the missile sample if Key = VK_3 then begin Audio.Samples[1].Volume:= 0.1; end;