macOS Audio Player

From Free Pascal wiki
Revision as of 10:11, 28 December 2019 by Trev (talk | contribs) (→‎See also: Added Multimedia Programming link)
Jump to navigationJump to search
macOSlogo.png

This article applies to macOS only.

See also: Multiplatform Programming Guide

Overview

The Apple AVFoundation framework combines four major technology areas that together encompass a wide range of tasks for capturing, processing, synthesising, controlling, importing and exporting audiovisual media on Apple platforms. It is available from macOS 10.7 (Lion). The framework provides essential services for working with time-based audiovisual media.

  • To play sound files, you can use AVAudioPlayer.
  • To record audio, you can use AVAudioRecorder.

AVAudioPlayer

The AVAudioPlayer class lets you play sound in any audio format available in macOS from a file or memory. The properties of this class are used for managing information about a sound such as the playback point within the sound’s timeline and for accessing playback options such as volume and looping.

The supported audio formats are:

  • AAC (MPEG-4 Advanced Audio Coding);
  • ALAC (Apple Lossless);
  • AMR (Adaptive Multi-rate);
  • HE-AAC (MPEG-4 High Efficiency AAC);
  • iLBC (internet Low Bit Rate Codec);
  • Linear PCM (uncompressed, linear pulse code modulation);
  • MP3 (MPEG-1 audio layer 3); and
  • µ-law and a-law.

Using an audio player you can:

  • Play sounds of any duration (unlike System Sound Services that has a 30 second limit);
  • Play sounds from files or memory buffers;
  • Play sounds when your application is in the background;
  • Loop sounds (including indefinitely);
  • Play multiple sounds simultaneously, one sound per audio player, with precise synchronisation;
  • Control relative playback level, stereo positioning, and playback rate for each sound you are playing;
  • Seek to a particular point in a sound file, which supports such application features as fast forward and rewind; and
  • Obtain data you can use for playback-level metering.

Example Code

Light bulb  Note: Not every method in the AVAudioPlayer class has been implemented in the code below. Those methods needed for play audio from a file, pause playback, resume playback, stop playback, set volume and set looping, plus a few others, have been implemented. Check the Apple documentation for the rest. The implemented methods are described in detail in the code below.
//
// Note: Free Pascal v3.3.1 (trunk), revision r42640, was used 27-Dec-2019
//

unit unit1;

{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$linkframework AVFoundation}

interface

uses                          
...
  MacOSAll,
  CocoaAll,
  LCLType,
...

type

  { TForm1 }

  AVAudioPlayer = objcclass external(NSObject)
  public
    {Plays a sound asynchronously. Calling this method implicitly calls the
     prepareToPlay() method if the audio player is not already prepared to play.}
    function play: Boolean; message 'play';

    {A value of 0.0 indicates silence; a value of 1.0 (the default) indicates
     full volume for the audio player instance. Use this property to control an
     audio player’s volume relative to other audio output.}
    function volume: Single; message 'volume';
    procedure setVolume(newValue: Single); message 'setVolume:';

    {A value of 0, which is the default, means to play the sound once.
     Set a positive integer value to specify the number of times to return
     to the start and play again. For example, specifying a value of 1
     results in a total of two plays of the sound. Set any negative
     integer value to loop the sound indefinitely until you call the
     stop() method.}
    function  numbreOfLoops: Integer; message 'numberOfLoops';
    procedure setNumberOfLoops(newValue: Integer); message 'setNumberOfLoops:';

    {A Boolean value that indicates whether the audio player is playing (true)
     or not (false).}
    function isPlaying: Boolean; message 'isPlaying';

    {Calling this method preloads buffers and acquires the audio hardware
     needed for playback, which minimises the lag between calling the play()
     method and the start of sound output.}
    function prepareToPlay: Boolean; message 'prepareToPlay';

    {Pauses playback; sound remains ready to resume playback from where
    it left off. It does not release the audio hardware that was acquired
    on calling play() or prepareToPlay().}
    procedure pause; message 'pause';

    {The stop method does not reset the value of the currentTime property to 0.
     If you call stop during playback and then call play(), playback resumes
     at the point where it left off. Callikng this method undoes the setup
     performed on calling the play() or prepareToPlay() methods.}
    procedure stop; message 'stop';

    {The total duration, in seconds, of the sound associated with the audio
    player.}
    function duration: Double; message 'duration';
  end;
     
  TForm1 = class(TForm)

  ...
  
  private

  public

  end; 

var
  Form1: TForm1;
  MyAudioPlayer : AVAudioPlayer = Nil;

implementation 

...

// Convert NSStrings function 
function NSStringToString(ns: NSString): String;
var
  pathStr: shortstring;
begin
  CFStringGetPascalString(CFStringRef(ns),@pathStr,255,CFStringGetSystemEncoding());
  Result := pathStr;
end;


// Play audio procedure
procedure PlayAudio(audioFileName : NSString; numberOfLoops: Integer);
var
  path: NSString;
  url : NSURL;
  err : NSError;
begin
  // Path to your application bundle's resource directory
  // with the mp3 filename appended
  path := NSBundle.mainBundle.resourcePath.stringByAppendingPathComponent(audioFileName);
  url  := NSURL.fileURLWithPath(path);

  MyAudioPlayer := AVAudioPlayer.alloc.initWithContentsOfURL_error(url, @err);

  if Assigned(MyAudioPlayer) then
    begin
      MyAudioPlayer.setNumberOfLoops(numberOfLoops);
      MyAudioPlayer.play
    end
  else
    // Use the Applications > Utilities > Console application to find error messages
    NSLog(NSStr('Error in procedure PlaySound(): %@'), err);
end;

...

// Play audio file located in your application bundle Resources directory
// This particular demo file can be found on your Mac at: 
// /Applications/iPhoto.app/Contents/Resources/Music/Minuet in G.mp3
// and should be copied to your application bundle Resources directory.
procedure TForm1.MenuItem23Click(Sender: TObject);
begin
  PlayAudio(NSStr('Minuet in G.mp3'), 0);
end;


// Pause audio
procedure TForm1.MenuItem24Click(Sender: TObject);
begin
  MyAudioPlayer.pause;
end;

// Resume audio
procedure TForm1.MenuItem25Click(Sender: TObject);
begin
  // Note: This will restart the audio where it left off after a pause or stop
  // Do not create yet another audio player by calling PlayAudio() again :-)
  MyAudioPlayer.play;
end;

// Stop audio
procedure TForm1.MenuItem26Click(Sender: TObject);
begin
  MyAudioPlayer.stop;
end;

...

finalization

If (Assigned (MyAudioPlayer)) then
  begin
    MyAudioPlayer.Release;
    MyAudioPlayer := Nil;
  end;

end.

See also

External links