1. -- 
  2. -- Copyright (c) 2012 Kevin Wellwood 
  3. -- All rights reserved. 
  4. -- 
  5. -- This source code is distributed under the Modified BSD License. For terms and 
  6. -- conditions, see license.txt. 
  7. -- 
  8.  
  9. private with Allegro.Digital_Samples; 
  10. private with Almp3; 
  11. private with Resources; 
  12.  
  13. private package Audio_Players.Cache is 
  14.  
  15.     -- Represents a sound effect/music loaded from a file that can be played 
  16.     -- once or in a loop. This is a specific instance of a played sound that 
  17.     -- can be started and stopped. It is backed by an audio resource that 
  18.     -- contains the audio data. 
  19.     type Sound is abstract new Limited_Object with private; 
  20.     type A_Sound is access all Sound'Class; 
  21.  
  22.     -- Returns the name of the file that the Sound was loaded from. 
  23.     function Get_Filename( this : not null access Sound'Class ) return String; 
  24.     pragma Postcondition( Get_Filename'Result'Length > 0 ); 
  25.  
  26.     -- Returns True if the sound finished playing or it has been stopped. 
  27.     function Is_Done( this : not null access Sound'Class ) return Boolean; 
  28.  
  29.     -- Starts playing the sound. If 'looping' is True, the sound will 
  30.     -- automatically loop when it finishes and will repeat until explicitly 
  31.     -- stopped. 
  32.     procedure Play( this : access Sound; looping : Boolean ) is abstract; 
  33.  
  34.     -- Polls the Sound object to maintain the stream of audio it must send to 
  35.     -- the audio hardware. This should be called approximately every 100ms. 
  36.     procedure Poll( this : access Sound ) is abstract; 
  37.  
  38.     -- Stops playing the sound if it is playing. 
  39.     procedure Stop( this : access Sound ) is abstract; 
  40.  
  41.     ---------------------------------------------------------------------------- 
  42.  
  43.     -- Loads a sound to be played. Sound objects are backed by cached 
  44.     -- Audio_Resource data so they can be played instantly without waiting to 
  45.     -- load or decode anything. An exception is raised on error. 
  46.     function Load_Sound( filename : String ) return A_Sound; 
  47.     pragma Precondition( filename'Length > 0 ); 
  48.     pragma Postcondition( Load_Sound'Result /= null ); 
  49.  
  50.     -- Discards a sound instance when it is no longer being played. It's 
  51.     -- Audio_Resource's reference count will decrease. 
  52.     procedure Unload_Sound( snd : in out A_Sound ); 
  53.  
  54. private 
  55.  
  56.     use Allegro.Digital_Samples; 
  57.     use Almp3; 
  58.     use Resources; 
  59.  
  60.     -- An Audio_Resources is a reference counted object that encapsulates the 
  61.     -- processed audio data necessary to play a sound. All Audio_Resources are 
  62.     -- cached in a thread-safe protected object. 
  63.     type Audio_Resource is abstract new Limited_Object with 
  64.         record 
  65.             refs     : Natural := 0;  -- number of Sound objects referencing this 
  66.             resource : A_Resource_File := null; 
  67.         end record; 
  68.     type A_Audio_Resource is access all Audio_Resource'Class; 
  69.  
  70.     -- Loads a Resource_File from 'filename'. The subclass's constructor should 
  71.     -- process the data as necessary. This should be called first by a subclass 
  72.     -- constructor. 
  73.     procedure Construct( this : access Audio_Resource; filename : String ); 
  74.  
  75.     -- Creates and returns a new instance of the sound backed by this audio 
  76.     -- resource. The instance counts as a reference this so it must be deleted 
  77.     -- before the resource. An exception is raised on error. This base procedure 
  78.     -- does nothing and must be overridden by each subclass of Audio_Resource. 
  79.     function Create_Sound( this : access Audio_Resource ) return A_Sound; 
  80.     pragma Postcondition( Create_Sound'Result = null ); 
  81.  
  82.     procedure Delete( this : in out Audio_Resource ); 
  83.  
  84.     ---------------------------------------------------------------------------- 
  85.  
  86.     -- Represents an MP3 audio file. 
  87.     type Mp3_Resource is new Audio_Resource with null record; 
  88.     type A_Mp3_Resource is access all Mp3_Resource'Class; 
  89.  
  90.     -- Raises an exception on error. 
  91.     function Create_Sound( this : access Mp3_Resource ) return A_Sound; 
  92.     pragma Postcondition( Create_Sound'Result /= null ); 
  93.  
  94.     ---------------------------------------------------------------------------- 
  95.  
  96.     -- Represents an Allegro sample file (.wav or .voc) 
  97.     type Sample_Resource is new Audio_Resource with 
  98.         record 
  99.             sample : A_Sample := null; 
  100.         end record; 
  101.     type A_Sample_Resource is access all Sample_Resource'Class; 
  102.  
  103.     -- Raises an exception on error. 
  104.     procedure Construct( this : access Sample_Resource; filename : String ); 
  105.  
  106.     -- Raises an exception on error. 
  107.     function Create_Sound( this : access Sample_Resource ) return A_Sound; 
  108.     pragma Postcondition( Create_Sound'Result /= null ); 
  109.  
  110.     procedure Delete( this : in out Sample_Resource ); 
  111.  
  112.     --========================================================================== 
  113.  
  114.     type Sound is abstract new Limited_Object with 
  115.         record 
  116.             resource : A_Audio_Resource := null; 
  117.             done     : Boolean := False; 
  118.         end record; 
  119.  
  120.     -- 'resource' is the audio data backing this sound. This constructor should 
  121.     -- be called first by an Audio_Resource subclass constructor. 
  122.     procedure Construct( this : access Sound; resource : not null A_Audio_Resource ); 
  123.  
  124.     procedure Delete( this : in out A_Sound ); 
  125.     pragma Postcondition( this = null ); 
  126.  
  127.     ---------------------------------------------------------------------------- 
  128.  
  129.     type Mp3_Sound is new Sound with 
  130.         record 
  131.             mp3 : A_mp3 := null; 
  132.         end record; 
  133.     type A_Mp3_Sound is access all Mp3_Sound'Class; 
  134.  
  135.     -- Raises an exception on error. 
  136.     procedure Construct( this : access Mp3_Sound; resource : not null A_Mp3_Resource ); 
  137.  
  138.     procedure Delete( this : in out Mp3_Sound ); 
  139.  
  140.     procedure Play( this : access Mp3_Sound; looping : Boolean ); 
  141.  
  142.     procedure Poll( this : access Mp3_Sound ); 
  143.  
  144.     procedure Stop( this : access Mp3_Sound ); 
  145.  
  146.     ---------------------------------------------------------------------------- 
  147.  
  148.     type Sample_Sound is new Sound with 
  149.         record 
  150.             voice : Integer := -1; 
  151.         end record; 
  152.     type A_Sample_Sound is access all Sample_Sound'Class; 
  153.  
  154.     procedure Play( this : access Sample_Sound; looping : Boolean ); 
  155.  
  156.     procedure Poll( this : access Sample_Sound ); 
  157.  
  158.     procedure Stop( this : access Sample_Sound ); 
  159.  
  160. end Audio_Players.Cache;