aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Game/Code/Classes/UAudio_FFMpeg.pas690
-rw-r--r--Game/Code/UltraStar.lpr14
2 files changed, 487 insertions, 217 deletions
diff --git a/Game/Code/Classes/UAudio_FFMpeg.pas b/Game/Code/Classes/UAudio_FFMpeg.pas
index 959d904a..548fb343 100644
--- a/Game/Code/Classes/UAudio_FFMpeg.pas
+++ b/Game/Code/Classes/UAudio_FFMpeg.pas
@@ -1,5 +1,14 @@
unit UAudio_FFMpeg;
+(*******************************************************************************
+
+This unit is primarily based upon -
+ http://www.dranger.com/ffmpeg/ffmpegtutorial_all.html
+
+ and tutorial03.c
+
+*******************************************************************************)
+
interface
{$IFDEF FPC}
@@ -16,37 +25,76 @@ uses Classes,
{$IFNDEF FPC}
Forms,
{$ENDIF}
+ avcodec, // FFMpeg Audio file decoding
+ avformat,
+ avutil,
+ SDL, // Used for Audio output Interface
ULog,
UMusic;
+type
+ TPacketQueue = record
+ first_pkt ,
+ last_pkt : pAVPacketList;
+ nb_packets : integer;
+ size : integer;
+ mutex : pSDL_mutex;
+ cond : pSDL_cond;
+ end;
+ pPacketQueue = ^TPacketQueue;
+
+ function packet_queue_put(var aPacketQueue : TPacketQueue; var AVPacket : TAVPacket): integer;
+ function packet_queue_get(var aPacketQueue : TPacketQueue; var AVPacket : TAVPacket; block : integer ): integer;
+ procedure packet_queue_init( var aPacketQueue : TPacketQueue );
+ procedure audio_callback( userdata: Pointer; stream: PUInt8; len: Integer ); cdecl;
+ function audio_decode_frame(aCodecCtx : TAVCodecContext; audio_buf : PUInt8; buf_size: integer): integer;
+
+var
+ singleton_MusicFFMpeg : IAudioPlayback = nil;
+
+
implementation
uses
{$IFDEF FPC}
lclintf,
{$ENDIF}
- URecord,
+ libc,
+// URecord,
UIni,
UMain,
UThemes;
+//var
+// singleton_MusicFFMpeg : IAudioPlayback = nil;
+
+
const
RecordSystem = 1;
+ SDL_AUDIO_BUFFER_SIZE = 1024;
+
type
- TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking,
- mpPaused, mpOpen);
+ TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, mpPaused, mpOpen);
+
+
const
ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open');
+var
+ audioq : TPacketQueue;
+ quit : integer = 0;
+
+
type
TAudio_ffMpeg = class( TInterfacedObject, IAudioPlayback )
private
- BassStart: hStream; // Wait, I've replaced this with BASS
- BassBack: hStream; // It has almost all features we need
+
+ BassStart: hStream;
+ BassBack: hStream;
BassSwoosh: hStream;
- BassChange: hStream; // Almost? It aleady has them all :)
+ BassChange: hStream;
BassOption: hStream;
BassClick: hStream;
BassDrum: hStream;
@@ -60,11 +108,12 @@ type
Loop: boolean;
fHWND: THandle;
+ function find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean;
public
- Bass: hStream;
+// Bass: hStream;
+ constructor create();
function GetName: String;
procedure InitializePlayback;
- procedure InitializeRecord;
procedure SetVolume(Volume: integer);
procedure SetMusicVolume(Volume: integer);
procedure SetLoop(Enabled: boolean);
@@ -77,7 +126,7 @@ type
procedure Close;
function Finished: boolean;
function Length: real;
- function Position: real;
+ function getPosition: real;
procedure PlayStart;
procedure PlayBack;
procedure PlaySwoosh;
@@ -89,9 +138,9 @@ type
procedure PlayClap;
procedure PlayShuffle;
procedure StopShuffle;
- procedure CaptureStart;
- procedure CaptureStop;
- procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte);
+// procedure CaptureStart;
+// procedure CaptureStop;
+// procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte);
procedure StopCard(Card: byte);
function LoadSoundFromFile(var hStream: hStream; Name: string): boolean;
@@ -103,141 +152,83 @@ type
procedure PlayCustomSound(const Index: Cardinal );
end;
-var
- singleton_MusicFFMpeg : IAudioPlayback;
-
-function TAudio_ffMpeg.GetName: String;
+constructor TAudio_ffMpeg.create();
begin
- result := 'FFMpeg';
+ writeln( 'UVideo_FFMpeg - av_register_all' );
+ av_register_all;
end;
-procedure TAudio_ffMpeg.InitializePlayback;
+function TAudio_ffMpeg.find_stream_ids( const aFormatCtx : PAVFormatContext; Out aFirstVideoStream, aFirstAudioStream : integer ): boolean;
var
- Pet: integer;
- S: integer;
+ i : integer;
+ st : pAVStream;
begin
- Log.BenchmarkStart(4);
- Log.LogStatus('Initializing Playback Subsystem', 'Music Initialize');
-
- Loaded := false;
- Loop := false;
+ // Find the first video stream
+ aFirstAudioStream := -1;
+ aFirstVideoStream := -1;
- {$ifdef win32}
- // TODO : JB_Linux ... is this needed ? :)
- fHWND := AllocateHWND( nil); // TODO : JB_lazarus - can we do something different here ?? lazarus didnt like this function
- {$ENDIF}
-
- // TODO : jb_linux replace with something other than bass
- if not BASS_Init(1, 44100, 0, fHWND, nil) then
+ i := 0;
+ while ( i < aFormatCtx.nb_streams ) do
begin
- {$IFNDEF FPC}
- // TODO : JB_linux find a way to do this nice..
- Application.MessageBox ('Could not initialize BASS', 'Error');
- {$ENDIF}
- Exit;
- end;
+ writeln( ' aFormatCtx.streams[i] : ' + inttostr( i ) );
+ st := aFormatCtx.streams[i];
- Log.BenchmarkEnd(4); Log.LogBenchmark('--> Bass Init', 4);
+ if(st.codec.codec_type = CODEC_TYPE_VIDEO ) AND
+ (aFirstVideoStream < 0) THEN
+ begin
+ writeln( 'Found Video Stream' );
+ aFirstVideoStream := i;
+ end;
- // config playing buffer
-// BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
-// BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
+ if ( st.codec.codec_type = CODEC_TYPE_AUDIO ) AND
+ ( aFirstAudioStream < 0) THEN
+ begin
+ writeln( 'Found Audio Stream' );
+ aFirstAudioStream := i;
+ end;
- Log.LogStatus('Loading Sounds', 'Music Initialize');
+ inc( i );
+ end; // while
- Log.BenchmarkStart(4);
- LoadSoundFromFile(BassStart, SoundPath + 'Common Start.mp3');
- LoadSoundFromFile(BassBack, SoundPath + 'Common Back.mp3');
- LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3');
- LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3');
- LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3');
- LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3');
-
-// LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3');
-// LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3');
-// LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3');
+ result := (aFirstAudioStream > -1) OR
+ (aFirstVideoStream > -1) ; // Didn't find any streams stream
+end;
-// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3');
- Log.BenchmarkEnd(4);
- Log.LogBenchmark('--> Loading Sounds', 4);
+function TAudio_ffMpeg.GetName: String;
+begin
+ result := 'FFMpeg';
end;
-procedure TAudio_ffMpeg.InitializeRecord;
+procedure TAudio_ffMpeg.InitializePlayback;
var
- S: integer;
- device: integer;
- descr: string;
- input: integer;
- input2: integer;
- flags: integer;
- mic: array[0..15] of integer;
- SC: integer; // soundcard
- SCI: integer; // soundcard input
-begin
- if RecordSystem = 1 then begin
- SetLength(Sound, 6 {max players});//Ini.Players+1);
- for S := 0 to High(Sound) do begin //Ini.Players do begin
- Sound[S] := TSound.Create;
- Sound[S].Num := S;
- Sound[S].BufferNew := TMemoryStream.Create;
- SetLength(Sound[S].BufferLong, 1);
- Sound[S].BufferLong[0] := TMemoryStream.Create;
- Sound[S].n := 4*1024;
- end;
-
-
- // check for recording devices;
- {device := 0;
- descr := BASS_RecordGetDeviceDescription(device);
-
- SetLength(SoundCard, 0);
- while (descr <> '') do begin
- SC := High(SoundCard) + 1;
- SetLength(SoundCard, SC+1);
-
- Log.LogAnalyze('Device #'+IntToStr(device)+': '+ descr);
- SoundCard[SC].Description := Descr;
-
- // check for recording inputs
- mic[device] := -1; // default to no change
- input := 0;
- BASS_RecordInit(device);
- Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input));
- flags := BASS_RecordGetInput(input);
-
- SetLength(SoundCard[SC].Input, 0);
- while (flags <> -1) do begin
- SCI := High(SoundCard[SC].Input) + 1;
- SetLength(SoundCard[SC].Input, SCI+1);
+// Pet: integer;
+ S: integer;
+begin
- Log.LogAnalyze('Input #' + IntToStr(Input) + ': ' + BASS_RecordGetInputName(input));
- SoundCard[SC].Input[SCI].Name := BASS_RecordGetInputName(Input);
+ LoadSoundFromFile(BassStart, SoundPath + 'foo fighters - best of you.mp3');
- if (flags and BASS_INPUT_TYPE_MASK) = BASS_INPUT_TYPE_MIC then begin
- mic[device] := input; // auto set microphone
- end;
- Inc(Input);
- flags := BASS_RecordGetInput(input);
- end;
+(*
+ LoadSoundFromFile(BassStart, SoundPath + 'Common start.mp3');
+ LoadSoundFromFile(BassBack, SoundPath + 'Common back.mp3');
+ LoadSoundFromFile(BassSwoosh, SoundPath + 'menu swoosh.mp3');
+ LoadSoundFromFile(BassChange, SoundPath + 'select music change music 50.mp3');
+ LoadSoundFromFile(BassOption, SoundPath + 'option change col.mp3');
+ LoadSoundFromFile(BassClick, SoundPath + 'rimshot022b.mp3');
- if mic[device] <> -1 then begin
- Log.LogAnalyze('Found the mic at input ' + IntToStr(Mic[device]))
- end else begin
- Log.LogAnalyze('Mic not found');
- mic[device] := 0; // setting to the first one (for kxproject)
- end;
- SoundCard[SC].InputSeleceted := Mic[Device];
+ LoadSoundFromFile(BassDrum, SoundPath + 'bassdrumhard076b.mp3');
+ LoadSoundFromFile(BassHihat, SoundPath + 'hihatclosed068b.mp3');
+ LoadSoundFromFile(BassClap, SoundPath + 'claps050b.mp3');
+*)
+// LoadSoundFromFile(BassShuffle, SoundPath + 'Shuffle.mp3');
- BASS_RecordFree;
+// Log.BenchmarkEnd(4);
+// Log.LogBenchmark('--> Loading Sounds', 4);
- inc(Device);
- descr := BASS_RecordGetDeviceDescription(Device);
- end; // while}
- end; // if
end;
+
procedure TAudio_ffMpeg.SetVolume(Volume: integer);
begin
//Old Sets Wave Volume
@@ -246,9 +237,11 @@ begin
// TODO : jb_linux replace with something other than bass
+(*
BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume);
BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume);
BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume);
+*)
end;
procedure TAudio_ffMpeg.SetMusicVolume(Volume: Integer);
@@ -263,7 +256,7 @@ begin
//Set Volume
// TODO : jb_linux replace with something other than bass
- BASS_ChannelSetAttributes (Bass, -1, Volume, -101);
+// BASS_ChannelSetAttributes (Bass, -1, Volume, -101);
end;
procedure TAudio_ffMpeg.SetLoop(Enabled: boolean);
@@ -277,11 +270,11 @@ begin
if FileExists(Name) then
begin
// TODO : jb_linux replace with something other than bass
- Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0);
+// Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0);
Loaded := true;
//Set Max Volume
- SetMusicVolume (100);
+// SetMusicVolume (100);
end;
Result := Loaded;
@@ -289,7 +282,8 @@ end;
procedure TAudio_ffMpeg.Rewind;
begin
- if Loaded then begin
+ if Loaded then
+ begin
end;
end;
@@ -298,12 +292,13 @@ var
bytes: integer;
begin
// TODO : jb_linux replace with something other than bass
- bytes := BASS_ChannelSeconds2Bytes(Bass, Time);
- BASS_ChannelSetPosition(Bass, bytes);
+// bytes := BASS_ChannelSeconds2Bytes(Bass, Time);
+// BASS_ChannelSetPosition(Bass, bytes);
end;
procedure TAudio_ffMpeg.Play;
begin
+(*
// TODO : jb_linux replace with something other than bass
if Loaded then
begin
@@ -312,26 +307,27 @@ begin
BASS_ChannelPlay(Bass, False); // for setting position before playing
end;
+*)
end;
procedure TAudio_ffMpeg.Pause; //Pause Mod
begin
+(*
// TODO : jb_linux replace with something other than bass
if Loaded then begin
BASS_ChannelPause(Bass); // Pauses Song
end;
+*)
end;
procedure TAudio_ffMpeg.Stop;
begin
- // TODO : jb_linux replace with something other than bass
- Bass_ChannelStop(Bass);
+// Bass_ChannelStop(Bass);
end;
procedure TAudio_ffMpeg.Close;
begin
- // TODO : jb_linux replace with something other than bass
- Bass_StreamFree(Bass);
+// Bass_StreamFree(Bass);
end;
function TAudio_ffMpeg.Length: real;
@@ -339,183 +335,344 @@ var
bytes: integer;
begin
Result := 60;
-
+(*
// TODO : jb_linux replace with something other than bass
bytes := BASS_ChannelGetLength(Bass);
Result := BASS_ChannelBytes2Seconds(Bass, bytes);
+*)
end;
-function TAudio_ffMpeg.Position: real;
+function TAudio_ffMpeg.getPosition: real;
var
bytes: integer;
begin
Result := 0;
+(*
// TODO : jb_linux replace with something other than bass
bytes := BASS_ChannelGetPosition(BASS);
Result := BASS_ChannelBytes2Seconds(BASS, bytes);
+*)
end;
function TAudio_ffMpeg.Finished: boolean;
begin
Result := false;
+(*
// TODO : jb_linux replace with something other than bass
if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then
begin
Result := true;
end;
+*)
end;
procedure TAudio_ffMpeg.PlayStart;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassStart, True);
+// BASS_ChannelPlay(BassStart, True);
end;
procedure TAudio_ffMpeg.PlayBack;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassBack, True);// then
+// BASS_ChannelPlay(BassBack, True);// then
end;
procedure TAudio_ffMpeg.PlaySwoosh;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassSwoosh, True);
+// BASS_ChannelPlay(BassSwoosh, True);
+
+
end;
procedure TAudio_ffMpeg.PlayChange;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassChange, True);
+// BASS_ChannelPlay(BassChange, True);
end;
procedure TAudio_ffMpeg.PlayOption;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassOption, True);
+// BASS_ChannelPlay(BassOption, True);
end;
procedure TAudio_ffMpeg.PlayClick;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassClick, True);
+// BASS_ChannelPlay(BassClick, True);
end;
procedure TAudio_ffMpeg.PlayDrum;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassDrum, True);
+// BASS_ChannelPlay(BassDrum, True);
end;
procedure TAudio_ffMpeg.PlayHihat;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassHihat, True);
+// BASS_ChannelPlay(BassHihat, True);
end;
procedure TAudio_ffMpeg.PlayClap;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassClap, True);
+// BASS_ChannelPlay(BassClap, True);
end;
procedure TAudio_ffMpeg.PlayShuffle;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelPlay(BassShuffle, True);
+// BASS_ChannelPlay(BassShuffle, True);
end;
procedure TAudio_ffMpeg.StopShuffle;
begin
// TODO : jb_linux replace with something other than bass
- BASS_ChannelStop(BassShuffle);
+// BASS_ChannelStop(BassShuffle);
end;
-procedure TAudio_ffMpeg.CaptureStart;
-var
- S: integer;
- SC: integer;
- P1: integer;
- P2: integer;
-begin
- for S := 0 to High(Sound) do
- Sound[S].BufferLong[0].Clear;
-
- for SC := 0 to High(Ini.CardList) do begin
- P1 := Ini.CardList[SC].ChannelL;
- P2 := Ini.CardList[SC].ChannelR;
- if P1 > PlayersPlay then P1 := 0;
- if P2 > PlayersPlay then P2 := 0;
- if (P1 > 0) or (P2 > 0) then
- CaptureCard(SC, P1, P2);
- end;
+procedure TAudio_ffMpeg.StopCard(Card: byte);
+begin
+ // TODO : jb_linux replace with something other than bass
+// BASS_RecordSetDevice(Card);
+// BASS_RecordFree;
end;
-procedure TAudio_ffMpeg.CaptureStop;
+function audio_decode_frame(aCodecCtx : TAVCodecContext; audio_buf : PUInt8; buf_size: integer): integer;
var
- SC: integer;
- P1: integer;
- P2: integer;
+ pkt : TAVPacket;
+ audio_pkt_data : pchar;//PUInt8 = nil;
+ audio_pkt_size : integer;
+ len1 ,
+ data_size : integer;
begin
+// result := 1;
+// exit;
+
+ while true do
+ begin
+
+ while ( audio_pkt_size > 0 ) do
+ begin
+ writeln( 'got audio packet' );
+ data_size := buf_size;
+
+// len1 := avcodec_decode_audio2(aCodecCtx, (int16_t )audio_buf, &data_size, audio_pkt_data, audio_pkt_size);
+ len1 := avcodec_decode_audio(@aCodecCtx, PWord( audio_buf ), data_size, audio_pkt_data, audio_pkt_size); // Todo.. should be avcodec_decode_audio2 but this wont link on my ubuntu box.
+
+// writeln('avcodec_decode_audio');
+
+ if(len1 < 0) then
+ begin
+ //* if error, skip frame */
+ audio_pkt_size := 0;
+ break;
+ end;
+
+ audio_pkt_data := audio_pkt_data + len1;
+ audio_pkt_size := audio_pkt_size + len1;
+
+ if (data_size <= 0) then
+ begin
+ //* No data yet, get more frames */
+ continue;
+ end;
+
+ //* We have data, return it and come back for more later */
+ result := data_size;
+ exit;
+ end;
+
+ if ( pkt.data <> nil ) then
+ av_free_packet( pkt );
+
+ if ( quit <> 0 ) then
+ begin
+ result := -1;
+ exit;
+ end;
+
+ if (packet_queue_get(audioq, pkt, 1) < 0) then
+ begin
+ result := -1;
+ exit;
+ end;
- for SC := 0 to High(Ini.CardList) do begin
- P1 := Ini.CardList[SC].ChannelL;
- P2 := Ini.CardList[SC].ChannelR;
- if P1 > PlayersPlay then P1 := 0;
- if P2 > PlayersPlay then P2 := 0;
- if (P1 > 0) or (P2 > 0) then StopCard(SC);
- end;
+ audio_pkt_data := pchar( pkt.data );
+ audio_pkt_size := pkt.size;
+ writeln( 'Audio Packet Size - ' + inttostr(audio_pkt_size) );
+ end;
end;
-//procedure TAudio_ffMpeg.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte);
-procedure TAudio_ffMpeg.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte);
+procedure audio_callback( userdata: Pointer; stream: PUInt8; len: Integer );
var
- Error: integer;
- ErrorMsg: string;
+ audio_buf_index : cardinal; // static unsigned int audio_buf_index = 0;
+ audio_buf_size : cardinal; // static unsigned int audio_buf_size = 0;
+ audio_size ,
+ len1 : integer;
+ aCodecCtx : TAVCodecContext;
+ audio_buf : pUInt8 = nil;
begin
- if not BASS_RecordInit(RecordI) then
- begin
- Error := BASS_ErrorGetCode;
+ aCodecCtx := pAVCodecContext(userdata)^;
+ audio_buf := UInt8( (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) div 2); // todo : JB
+ audio_size := -1;
- ErrorMsg := IntToStr(Error);
- if Error = BASS_ERROR_DX then ErrorMsg := 'No DX5';
- if Error = BASS_ERROR_ALREADY then ErrorMsg := 'The device has already been initialized';
- if Error = BASS_ERROR_DEVICE then ErrorMsg := 'The device number specified is invalid';
- if Error = BASS_ERROR_DRIVER then ErrorMsg := 'There is no available device driver';
+// writeln('----------- audio callback' );
- {Log.LogAnalyze('Error initializing record [' + IntToStr(RecordI) + ', '
- + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: '
- + ErrorMsg);}
- Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', '
- + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: '
- + ErrorMsg);
- Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg);
+ while (len > 0) do
+ begin
+ if(audio_buf_index >= audio_buf_size) then
+ begin
+ // We have already sent all our data; get more */
+ audio_size := audio_decode_frame(aCodecCtx, audio_buf, sizeof(audio_buf));
+
+ if(audio_size < 0) then
+ begin
+ // If error, output silence */
+ audio_buf_size := 1024; // arbitrary?
+ memset(audio_buf, 0, audio_buf_size); // todo : jb memset
+ end
+ else
+ begin
+ audio_buf_size := audio_size;
+ end;
+// audio_buf_index := 0; // Todo : jb - SegFault ?
+ end;
+
+ len1 := audio_buf_size - audio_buf_index;
- end
- else
- begin
- Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256);
- end;
-end;
+ if (len1 > len) then
+ len1 := len;
+
+ memcpy(stream, PUInt8( audio_buf ) + audio_buf_index , len1);
-procedure TAudio_ffMpeg.StopCard(Card: byte);
-begin
- // TODO : jb_linux replace with something other than bass
- BASS_RecordSetDevice(Card);
- BASS_RecordFree;
+ len := len - len1;
+ stream := stream + len1;
+ audio_buf_index := audio_buf_index + len1;
+ end;
end;
function TAudio_ffMpeg.LoadSoundFromFile(var hStream: hStream; Name: string): boolean;
var
L: Integer;
-begin
+ pFormatCtx: PAVFormatContext;
+ lVidStreamID ,
+ lAudStreamID : Integer;
+ aCodecCtx : pAVCodecContext;
+ wanted_spec ,
+ spec : TSDL_AudioSpec;
+ lAudioStream : pAVStream;
+ aCodec : pAVCodec;
+ i : integer;
+ packet : TAVPacket;
+ event : TSDL_Event;
+begin
+ result := false;
+
if FileExists(Name) then
begin
- Log.LogStatus('Loading Sound: "' + Name + '"', 'LoadSoundFromFile');
+ writeln('Loading Sound: "' + Name + '"', 'LoadSoundFromFile');
+
+ // Open video file
+ if (av_open_input_file(pFormatCtx, pchar(Name), nil, 0, nil) > 0) then
+ exit;
+
+ // Retrieve stream information
+ if (av_find_stream_info(pFormatCtx)<0) then
+ exit;
+
+ dump_format(pFormatCtx, 0, pchar(Name), 0);
+
+ if not find_stream_ids( pFormatCtx, lVidStreamID, lAudStreamID ) then
+ exit;
+
+ writeln( 'done searching for stream ids' );
+
+ if lAudStreamID > -1 then
+ begin
+ writeln( 'Audio Stream ID is : '+ inttostr( lAudStreamID ) );
+
+ lAudioStream := pFormatCtx.streams[lAudStreamID];
+ aCodecCtx := lAudioStream.codec;
+
+ // Set audio settings from codec info
+ wanted_spec.freq := aCodecCtx.sample_rate;
+ wanted_spec.format := AUDIO_S16SYS;
+ wanted_spec.channels := aCodecCtx.channels;
+ wanted_spec.silence := 0;
+ wanted_spec.samples := SDL_AUDIO_BUFFER_SIZE;
+ wanted_spec.callback := audio_callback;
+ wanted_spec.userdata := aCodecCtx;
+ end;
+
+ if (SDL_OpenAudio(@wanted_spec, @spec) < 0) then
+ begin
+ writeln('SDL_OpenAudio: '+SDL_GetError());
+ exit
+ end;
+
+ writeln( 'SDL opened audio device' );
+
+ aCodec := avcodec_find_decoder(aCodecCtx.codec_id);
+ if (aCodec = nil) then
+ begin
+ writeln('Unsupported codec!');
+ exit;
+ end;
+
+ avcodec_open(aCodecCtx, aCodec);
+
+ writeln( 'Opened the codec' );
+
+ packet_queue_init( audioq );
+ SDL_PauseAudio(0);
+
+ writeln( 'SDL_PauseAudio' );
+
+ i := 0;
+ while (av_read_frame(pFormatCtx, packet)>=0) do
+ begin
+ writeln( 'ffmpeg - av_read_frame' );
+
+ if (packet.stream_index = lAudStreamID ) then
+ begin
+ packet_queue_put(audioq, packet);
+ end
+ else
+ begin
+ av_free_packet(packet);
+ end;
+
+
+ // Free the packet that was allocated by av_read_frame
+ SDL_PollEvent(@event);
+
+(*
+ if event.type_ = SDL_QUIT the
+ begin
+ quit := 1;
+ SDL_Quit();
+ end
+ else
+ break;
+*)
+
+ end;
+
+ // Close the codec
+ avcodec_close(aCodecCtx);
+
+ // Close the video file
+ av_close_input_file(pFormatCtx);
+
+(*
try
// TODO : jb_linux replace with something other than bass
hStream := BASS_StreamCreateFile(False, pchar(Name), 0, 0, 0);
@@ -528,21 +685,124 @@ begin
except
Log.LogError('Failed to open using BASS', 'LoadSoundFromFile');
end;
+*)
+
end
else
begin
- Log.LogError('Sound not found: "' + Name + '"', 'LoadSoundFromFile');
+ writeln('Sound not found: "' + Name + '"', 'LoadSoundFromFile');
+ exit;
+ end;
+
+end;
+
+procedure packet_queue_init(var aPacketQueue : TPacketQueue );
+begin
+ memset(@aPacketQueue, 0, sizeof(TPacketQueue));
+
+ aPacketQueue.mutex := SDL_CreateMutex();
+ aPacketQueue.cond := SDL_CreateCond();
+end;
+
+function packet_queue_put(var aPacketQueue : TPacketQueue; var AVPacket : TAVPacket): integer;
+var
+ pkt1 : pAVPacketList;
+begin
+ result := -1;
+
+ writeln( 'TAudio_ffMpeg.packet_queue_put' );
+
+ if av_dup_packet(@AVPacket) < 0 then
exit;
+
+ pkt1 := av_malloc(sizeof(TAVPacketList));
+ if (pkt1 = nil) then
+ exit;
+
+ pkt1.pkt := AVPacket;
+ pkt1.next := nil;
+
+
+ SDL_LockMutex( aPacketQueue.mutex );
+ try
+
+ if (aPacketQueue.last_pkt = nil) then
+ aPacketQueue.first_pkt := pkt1
+ else
+ aPacketQueue.last_pkt.next := pkt1;
+
+ aPacketQueue.last_pkt := pkt1;
+ inc( aPacketQueue.nb_packets );
+
+ aPacketQueue.size := aPacketQueue.size + pkt1.pkt.size;
+ SDL_CondSignal(aPacketQueue.cond);
+
+ finally
+ SDL_UnlockMutex( aPacketQueue.mutex );
end;
+
+ result := 0;
end;
+function packet_queue_get(var aPacketQueue : TPacketQueue; var AVPacket : TAVPacket; block : integer ): integer;
+var
+ pkt1 : pAVPacketList;
+begin
+ result := -1;
+// writeln( 'packet_queue_get' );
+
+ SDL_LockMutex(aPacketQueue.mutex);
+ try
+ while true do
+ begin
+
+ if (quit <> 0) then
+ exit;
+
+ pkt1 := aPacketQueue.first_pkt;
+
+ if ( pkt1 <> nil ) then
+ begin
+ aPacketQueue.first_pkt := pkt1.next;
+
+ if (aPacketQueue.first_pkt = nil ) then
+ aPacketQueue.last_pkt := nil;
+
+ dec(aPacketQueue.nb_packets);
+
+ aPacketQueue.size := aPacketQueue.size - pkt1.pkt.size;
+
+ AVPacket := pkt1.pkt;
+
+ av_free(pkt1);
+
+ result := 1;
+ break;
+ end
+ else
+ if (block = 0) then
+ begin
+ result := 0;
+ break;
+ end
+ else
+ begin
+ SDL_CondWait(aPacketQueue.cond, aPacketQueue.mutex);
+ end;
+ end;
+ finally
+ SDL_UnlockMutex(aPacketQueue.mutex);
+ end;
+end;
+
+
//Equalizer
function TAudio_ffMpeg.GetFFTData: TFFTData;
var
Data: TFFTData;
begin
//Get Channel Data Mono and 256 Values
- BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512);
+// BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512);
end;
function TAudio_ffMpeg.LoadCustomSound(const Filename: String): Cardinal;
@@ -551,6 +811,7 @@ var
I: Integer;
F: String;
begin
+(*
//Search for Sound in already loaded Sounds
F := UpperCase(SoundPath + FileName);
For I := 0 to High(CustomSounds) do
@@ -566,12 +827,13 @@ begin
Result := High(CustomSounds)
else
Result := 0;
+*)
end;
procedure TAudio_ffMpeg.PlayCustomSound(const Index: Cardinal );
begin
- if Index <= High(CustomSounds) then
- BASS_ChannelPlay(CustomSounds[Index].Handle, True);
+// if Index <= High(CustomSounds) then
+// BASS_ChannelPlay(CustomSounds[Index].Handle, True);
end;
@@ -625,8 +887,8 @@ initialization
writeln( 'UAudio_Bass - Register Playback' );
AudioManager.add( IAudioPlayback( singleton_MusicFFMpeg ) );
-finalization
- AudioManager.Remove( IAudioPlayback( singleton_MusicFFMpeg ) );
-
+finalization
+ AudioManager.Remove( IAudioPlayback( singleton_MusicFFMpeg ) );
+
end.
diff --git a/Game/Code/UltraStar.lpr b/Game/Code/UltraStar.lpr
index 31115dde..1026c04b 100644
--- a/Game/Code/UltraStar.lpr
+++ b/Game/Code/UltraStar.lpr
@@ -123,15 +123,15 @@ uses
UMusic in 'Classes\UMusic.pas',
+
UMedia_dummy in 'Classes\UMedia_dummy.pas',
-// UAudio_FFMpeg in 'Classes\UAudio_FFMpeg.pas',
UVideo in 'Classes\UVideo.pas',
-
+// UAudio_FFMpeg in 'Classes\UAudio_FFMpeg.pas',
{$ifdef win32}
UAudio_bass in 'Classes\UAudio_bass.pas',
{$endif}
-// UAudio_fmod in 'Classes\UAudio_fmod.pas', // Not ready yet
+// UAudio_fmod in 'Classes\UAudio_fmod.pas', // this has not yet been developed.. :(
UParty in 'Classes\UParty.pas',
UPlaylist in 'Classes\UPlaylist.pas',
@@ -417,6 +417,14 @@ exit;
Log.LogStatus('Initialize Sound', 'Initialization'); InitializeSound();
Log.BenchmarkEnd(1);
Log.LogBenchmark('Initializing Sound', 1);
+
+
+(*
+ // This is jays debugging for FFMpeg audio output..
+ singleton_MusicFFMpeg.PlaySwoosh();
+ writeln( 'did you hear the sound ?? ' );
+ halt(0);
+*)
// Graphics
Log.BenchmarkStart(1);