--
-- Copyright (c) 2012 Kevin Wellwood
-- All rights reserved.
--
-- This source code is distributed under the Modified BSD License. For terms and
-- conditions, see license.txt.
--
private with Allegro.Digital_Samples;
private with Almp3;
private with Resources;
private package Audio_Players.Cache is
-- Represents a sound effect/music loaded from a file that can be played
-- once or in a loop. This is a specific instance of a played sound that
-- can be started and stopped. It is backed by an audio resource that
-- contains the audio data.
type Sound is abstract new Limited_Object with private;
type A_Sound is access all Sound'Class;
-- Returns the name of the file that the Sound was loaded from.
function Get_Filename( this : not null access Sound'Class ) return String;
pragma Postcondition( Get_Filename'Result'Length > 0 );
-- Returns True if the sound finished playing or it has been stopped.
function Is_Done( this : not null access Sound'Class ) return Boolean;
-- Starts playing the sound. If 'looping' is True, the sound will
-- automatically loop when it finishes and will repeat until explicitly
-- stopped.
procedure Play( this : access Sound; looping : Boolean ) is abstract;
-- Polls the Sound object to maintain the stream of audio it must send to
-- the audio hardware. This should be called approximately every 100ms.
procedure Poll( this : access Sound ) is abstract;
-- Stops playing the sound if it is playing.
procedure Stop( this : access Sound ) is abstract;
----------------------------------------------------------------------------
-- Loads a sound to be played. Sound objects are backed by cached
-- Audio_Resource data so they can be played instantly without waiting to
-- load or decode anything. An exception is raised on error.
function Load_Sound( filename : String ) return A_Sound;
pragma Precondition( filename'Length > 0 );
pragma Postcondition( Load_Sound'Result /= null );
-- Discards a sound instance when it is no longer being played. It's
-- Audio_Resource's reference count will decrease.
procedure Unload_Sound( snd : in out A_Sound );
private
use Allegro.Digital_Samples;
use Almp3;
use Resources;
-- An Audio_Resources is a reference counted object that encapsulates the
-- processed audio data necessary to play a sound. All Audio_Resources are
-- cached in a thread-safe protected object.
type Audio_Resource is abstract new Limited_Object with
record
refs : Natural := 0; -- number of Sound objects referencing this
resource : A_Resource_File := null;
end record;
type A_Audio_Resource is access all Audio_Resource'Class;
-- Loads a Resource_File from 'filename'. The subclass's constructor should
-- process the data as necessary. This should be called first by a subclass
-- constructor.
procedure Construct( this : access Audio_Resource; filename : String );
-- Creates and returns a new instance of the sound backed by this audio
-- resource. The instance counts as a reference this so it must be deleted
-- before the resource. An exception is raised on error. This base procedure
-- does nothing and must be overridden by each subclass of Audio_Resource.
function Create_Sound( this : access Audio_Resource ) return A_Sound;
pragma Postcondition( Create_Sound'Result = null );
procedure Delete( this : in out Audio_Resource );
----------------------------------------------------------------------------
-- Represents an MP3 audio file.
type Mp3_Resource is new Audio_Resource with null record;
type A_Mp3_Resource is access all Mp3_Resource'Class;
-- Raises an exception on error.
function Create_Sound( this : access Mp3_Resource ) return A_Sound;
pragma Postcondition( Create_Sound'Result /= null );
----------------------------------------------------------------------------
-- Represents an Allegro sample file (.wav or .voc)
type Sample_Resource is new Audio_Resource with
record
sample : A_Sample := null;
end record;
type A_Sample_Resource is access all Sample_Resource'Class;
-- Raises an exception on error.
procedure Construct( this : access Sample_Resource; filename : String );
-- Raises an exception on error.
function Create_Sound( this : access Sample_Resource ) return A_Sound;
pragma Postcondition( Create_Sound'Result /= null );
procedure Delete( this : in out Sample_Resource );
--==========================================================================
type Sound is abstract new Limited_Object with
record
resource : A_Audio_Resource := null;
done : Boolean := False;
end record;
-- 'resource' is the audio data backing this sound. This constructor should
-- be called first by an Audio_Resource subclass constructor.
procedure Construct( this : access Sound; resource : not null A_Audio_Resource );
procedure Delete( this : in out A_Sound );
pragma Postcondition( this = null );
----------------------------------------------------------------------------
type Mp3_Sound is new Sound with
record
mp3 : A_mp3 := null;
end record;
type A_Mp3_Sound is access all Mp3_Sound'Class;
-- Raises an exception on error.
procedure Construct( this : access Mp3_Sound; resource : not null A_Mp3_Resource );
procedure Delete( this : in out Mp3_Sound );
procedure Play( this : access Mp3_Sound; looping : Boolean );
procedure Poll( this : access Mp3_Sound );
procedure Stop( this : access Mp3_Sound );
----------------------------------------------------------------------------
type Sample_Sound is new Sound with
record
voice : Integer := -1;
end record;
type A_Sample_Sound is access all Sample_Sound'Class;
procedure Play( this : access Sample_Sound; looping : Boolean );
procedure Poll( this : access Sample_Sound );
procedure Stop( this : access Sample_Sound );
end Audio_Players.Cache;