{* UltraStar Deluxe - Karaoke Game
*
* UltraStar Deluxe is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*}
unit UAudioPlaybackBase;
interface
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
{$I switches.inc}
uses
UMusic,
UTime,
UPath;
type
TAudioPlaybackBase = class(TInterfacedObject, IAudioPlayback)
protected
OutputDeviceList: TAudioOutputDeviceList;
MusicStream: TAudioPlaybackStream;
function CreatePlaybackStream(): TAudioPlaybackStream; virtual; abstract;
procedure ClearOutputDeviceList();
function GetLatency(): double; virtual; abstract;
// open sound or music stream (used by Open() and OpenSound())
function OpenStream(const Filename: IPath): TAudioPlaybackStream;
function OpenDecodeStream(const Filename: IPath): TAudioDecodeStream;
public
function GetName: string; virtual; abstract;
function Open(const Filename: IPath): boolean; // true if succeed
procedure Close;
procedure Play;
procedure Pause;
procedure Stop;
procedure FadeIn(Time: real; TargetVolume: single);
procedure Fade(Time: real; TargetVolume: single);
procedure SetSyncSource(SyncSource: TSyncSource);
procedure SetPosition(Time: real);
function GetPosition: real;
function InitializePlayback: boolean; virtual; abstract;
function FinalizePlayback: boolean; virtual;
//function SetOutputDevice(Device: TAudioOutputDevice): boolean;
function GetOutputDeviceList(): TAudioOutputDeviceList;
procedure SetAppVolume(Volume: single); virtual; abstract;
procedure SetVolume(Volume: single);
procedure SetLoop(Enabled: boolean);
procedure Rewind;
function Finished: boolean;
function Length: real;
// Sounds
function OpenSound(const Filename: IPath): TAudioPlaybackStream;
procedure PlaySound(Stream: TAudioPlaybackStream);
procedure StopSound(Stream: TAudioPlaybackStream);
// Equalizer
procedure GetFFTData(var Data: TFFTData);
// Interface for Visualizer
function GetPCMData(var Data: TPCMData): Cardinal;
function CreateVoiceStream(Channel: integer; FormatInfo: TAudioFormatInfo): TAudioVoiceStream; virtual; abstract;
end;
implementation
uses
ULog,
SysUtils;
{ TAudioPlaybackBase }
function TAudioPlaybackBase.FinalizePlayback: boolean;
begin
FreeAndNil(MusicStream);
ClearOutputDeviceList();
Result := true;
end;
function TAudioPlaybackBase.Open(const Filename: IPath): boolean;
begin
// free old MusicStream
MusicStream.Free;
MusicStream := OpenStream(Filename);
if not assigned(MusicStream) then
begin
Result := false;
Exit;
end;
//MusicStream.AddSoundEffect(TVoiceRemoval.Create());
Result := true;
end;
procedure TAudioPlaybackBase.Close;
begin
FreeAndNil(MusicStream);
end;
function TAudioPlaybackBase.OpenDecodeStream(const Filename: IPath): TAudioDecodeStream;
var
i: integer;
begin
for i := 0 to AudioDecoders.Count-1 do
begin
Result := IAudioDecoder(AudioDecoders[i]).Open(Filename);
if (assigned(Result)) then
begin
Log.LogInfo('Using decoder ' + IAudioDecoder(AudioDecoders[i]).GetName() +
' for "' + Filename.ToNative + '"', 'TAudioPlaybackBase.OpenDecodeStream');
Exit;
end;
end;
Result := nil;
end;
procedure OnClosePlaybackStream(Stream: TAudioProcessingStream);
var
PlaybackStream: TAudioPlaybackStream;
SourceStream: TAudioSourceStream;
begin
PlaybackStream := TAudioPlaybackStream(Stream);
SourceStream := PlaybackStream.GetSourceStream();
SourceStream.Free;
end;
function TAudioPlaybackBase.OpenStream(const Filename: IPath): TAudioPlaybackStream;
var
PlaybackStream: TAudioPlaybackStream;
DecodeStream: TAudioDecodeStream;
begin
Result := nil;
//Log.LogStatus('Loading Sound: "' + Filename + '"', 'TAudioPlayback_Bass.OpenStream');
DecodeStream := OpenDecodeStream(Filename);
if (not assigned(DecodeStream)) then
begin
Log.LogStatus('Could not open "' + Filename.ToNative + '"', 'TAudioPlayback_Bass.OpenStream');
Exit;
end;
// create a matching playback-stream for the decoder
PlaybackStream := CreatePlaybackStream();
if (not PlaybackStream.Open(DecodeStream)) then
begin
FreeAndNil(PlaybackStream);
FreeAndNil(DecodeStream);
Exit;
end;
PlaybackStream.AddOnCloseHandler(OnClosePlaybackStream);
Result := PlaybackStream;
end;
procedure TAudioPlaybackBase.Play;
begin
if assigned(MusicStream) then
MusicStream.Play();
end;
procedure TAudioPlaybackBase.Pause;
begin
if assigned(MusicStream) then
MusicStream.Pause();
end;
procedure TAudioPlaybackBase.Stop;
begin
if assigned(MusicStream) then
MusicStream.Stop();
end;
function TAudioPlaybackBase.Length: real;
begin
if assigned(MusicStream) then
Result := MusicStream.Length
else
Result := 0;
end;
function TAudioPlaybackBase.GetPosition: real;
begin
if assigned(MusicStream) then
Result := MusicStream.Position
else
Result := 0;
end;
procedure TAudioPlaybackBase.SetPosition(Time: real);
begin
if assigned(MusicStream) then
MusicStream.Position := Time;
end;
procedure TAudioPlaybackBase.SetSyncSource(SyncSource: TSyncSource);
begin
if assigned(MusicStream) then
MusicStream.SetSyncSource(SyncSource);
end;
procedure TAudioPlaybackBase.Rewind;
begin
SetPosition(0);
end;
function TAudioPlaybackBase.Finished: boolean;
begin
if assigned(MusicStream) then
Result := (MusicStream.Status = ssStopped)
else
Result := true;
end;
procedure TAudioPlaybackBase.SetVolume(Volume: single);
begin
if assigned(MusicStream) then
MusicStream.Volume := Volume;
end;
procedure TAudioPlaybackBase.FadeIn(Time: real; TargetVolume: single);
begin
if assigned(MusicStream) then
MusicStream.FadeIn(Time, TargetVolume);
end;
procedure TAudioPlaybackBase.Fade(Time: real; TargetVolume: single);
begin
if assigned(MusicStream) then
MusicStream.Fade(Time, TargetVolume);
end;
procedure TAudioPlaybackBase.SetLoop(Enabled: boolean);
begin
if assigned(MusicStream) then
MusicStream.Loop := Enabled;
end;
// Equalizer
procedure TAudioPlaybackBase.GetFFTData(var data: TFFTData);
begin
if assigned(MusicStream) then
MusicStream.GetFFTData(data);
end;
{*
* Copies interleaved PCM SInt16 stereo samples into data.
* Returns the number of frames
*}
function TAudioPlaybackBase.GetPCMData(var data: TPCMData): Cardinal;
begin
if assigned(MusicStream) then
Result := MusicStream.GetPCMData(data)
else
Result := 0;
end;
function TAudioPlaybackBase.OpenSound(const Filename: IPath): TAudioPlaybackStream;
begin
Result := OpenStream(Filename);
end;
procedure TAudioPlaybackBase.PlaySound(stream: TAudioPlaybackStream);
begin
if assigned(stream) then
stream.Play();
end;
procedure TAudioPlaybackBase.StopSound(stream: TAudioPlaybackStream);
begin
if assigned(stream) then
stream.Stop();
end;
procedure TAudioPlaybackBase.ClearOutputDeviceList();
var
DeviceIndex: integer;
begin
for DeviceIndex := 0 to High(OutputDeviceList) do
OutputDeviceList[DeviceIndex].Free();
SetLength(OutputDeviceList, 0);
end;
function TAudioPlaybackBase.GetOutputDeviceList(): TAudioOutputDeviceList;
begin
Result := OutputDeviceList;
end;
end.