User Tools

Site Tools


tutorial:audio

Audio

Introduction

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

Or download them in one zip file from here

You can download the source for this tutorial here.

Create the audio engine

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;

Selecting the audio device

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)');

Loading audio samples

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;

Playing audio samples

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;

Loading audio streams

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]));

Changing volume

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;

Back to tutorial index

tutorial/audio.txt · Last modified: 2013/08/17 12:29 by amnoxx