aboutsummaryrefslogtreecommitdiffstats
path: root/Game
diff options
context:
space:
mode:
authorjaybinks <jaybinks@b956fd51-792f-4845-bead-9b4dfca2ff2c>2007-10-27 06:31:04 +0000
committerjaybinks <jaybinks@b956fd51-792f-4845-bead-9b4dfca2ff2c>2007-10-27 06:31:04 +0000
commit8cca9e3e6f591c35d35d132a9d3f93ffc7cdfee8 (patch)
tree985dac320ed9d8456a682c952c1b0ab0f502859b /Game
parent64f2c9b369185575d397dccbbcacc7f818874952 (diff)
downloadusdx-8cca9e3e6f591c35d35d132a9d3f93ffc7cdfee8.tar.gz
usdx-8cca9e3e6f591c35d35d132a9d3f93ffc7cdfee8.tar.xz
usdx-8cca9e3e6f591c35d35d132a9d3f93ffc7cdfee8.zip
made some major progress with ffmpeg audio playback !!!
YAY !!! still a little choppy, so I suspect incorrect buffer sizes or something like that. also made some mods to support Unicode song file iteration on windows, this is no worse than what we had before, but is not complete.. oh this code only supports win 2000 and up .. no Win 98... git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@533 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to 'Game')
-rw-r--r--Game/Code/Classes/UAudio_FFMpeg.pas153
-rw-r--r--Game/Code/Classes/UCommon.pas88
-rw-r--r--Game/Code/Classes/UFiles.pas20
-rw-r--r--Game/Code/Classes/USongs.pas65
-rw-r--r--Game/Code/Classes/UVideo.pas85
-rw-r--r--Game/Code/Screens/UScreenSong.pas8
-rw-r--r--Game/Code/UltraStar.dpr13
7 files changed, 311 insertions, 121 deletions
diff --git a/Game/Code/Classes/UAudio_FFMpeg.pas b/Game/Code/Classes/UAudio_FFMpeg.pas
index 548fb343..35822a3b 100644
--- a/Game/Code/Classes/UAudio_FFMpeg.pas
+++ b/Game/Code/Classes/UAudio_FFMpeg.pas
@@ -7,6 +7,8 @@ This unit is primarily based upon -
and tutorial03.c
+ http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
+
*******************************************************************************)
interface
@@ -25,10 +27,10 @@ uses Classes,
{$IFNDEF FPC}
Forms,
{$ENDIF}
+ SDL, // Used for Audio output Interface
avcodec, // FFMpeg Audio file decoding
avformat,
avutil,
- SDL, // Used for Audio output Interface
ULog,
UMusic;
@@ -47,19 +49,28 @@ type
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;
+ function audio_decode_frame(aCodecCtx : TAVCodecContext; aAudio_buf : PUInt8; buf_size: integer): integer;
var
singleton_MusicFFMpeg : IAudioPlayback = nil;
+var
+ audioq : TPacketQueue;
+ quit : integer = 0;
+// faudio_buf : array[ 0 .. 0 ] of byte; //pUInt8{$ifndef fpc};{$else} = nil;{$endif}
+// audio_buf : array[ 0 .. AVCODEC_MAX_AUDIO_FRAME_SIZE ] of byte; //pUInt8{$ifndef fpc};{$else} = nil;{$endif}
+
+type
+ Taudiobuff = array[ 0 .. AVCODEC_MAX_AUDIO_FRAME_SIZE ] of byte;
+ PAudioBuff = ^Taudiobuff;
implementation
uses
{$IFDEF FPC}
lclintf,
- {$ENDIF}
libc,
+ {$ENDIF}
// URecord,
UIni,
UMain,
@@ -82,9 +93,6 @@ type
const
ModeStr: array[TMPModes] of string = ('Not ready', 'Stopped', 'Playing', 'Recording', 'Seeking', 'Paused', 'Open');
-var
- audioq : TPacketQueue;
- quit : integer = 0;
type
@@ -154,7 +162,7 @@ end;
constructor TAudio_ffMpeg.create();
begin
- writeln( 'UVideo_FFMpeg - av_register_all' );
+// writeln( 'UVideo_FFMpeg - av_register_all' );
av_register_all;
end;
@@ -170,20 +178,20 @@ begin
i := 0;
while ( i < aFormatCtx.nb_streams ) do
begin
- writeln( ' aFormatCtx.streams[i] : ' + inttostr( i ) );
+// writeln( ' aFormatCtx.streams[i] : ' + inttostr( i ) );
st := aFormatCtx.streams[i];
if(st.codec.codec_type = CODEC_TYPE_VIDEO ) AND
(aFirstVideoStream < 0) THEN
begin
- writeln( 'Found Video Stream' );
+// writeln( 'Found Video Stream' );
aFirstVideoStream := i;
end;
if ( st.codec.codec_type = CODEC_TYPE_AUDIO ) AND
( aFirstAudioStream < 0) THEN
begin
- writeln( 'Found Audio Stream' );
+// writeln( 'Found Audio Stream' );
aFirstAudioStream := i;
end;
@@ -206,8 +214,8 @@ var
S: integer;
begin
- LoadSoundFromFile(BassStart, SoundPath + 'foo fighters - best of you.mp3');
-
+// LoadSoundFromFile(BassStart, SoundPath + 'Green Day - American Idiot.mp3');
+
(*
LoadSoundFromFile(BassStart, SoundPath + 'Common start.mp3');
LoadSoundFromFile(BassBack, SoundPath + 'Common back.mp3');
@@ -438,12 +446,13 @@ end;
procedure TAudio_ffMpeg.StopCard(Card: byte);
begin
+
// TODO : jb_linux replace with something other than bass
// BASS_RecordSetDevice(Card);
// BASS_RecordFree;
end;
-function audio_decode_frame(aCodecCtx : TAVCodecContext; audio_buf : PUInt8; buf_size: integer): integer;
+function audio_decode_frame(aCodecCtx : TAVCodecContext; aAudio_buf : PUInt8; buf_size: integer): integer;
var
pkt : TAVPacket;
audio_pkt_data : pchar;//PUInt8 = nil;
@@ -451,26 +460,44 @@ var
len1 ,
data_size : integer;
begin
-// result := 1;
-// exit;
+ {$ifdef win32}
+ FillChar(pkt, sizeof(pkt), #0);
+ {$else}
+ memset(@pkt, 0, sizeof(pkt)); // todo : jb memset
+ {$endif}
+
+ audio_pkt_data := nil;
+ audio_pkt_size := 0;
while true do
begin
while ( audio_pkt_size > 0 ) do
begin
- writeln( 'got audio packet' );
+// 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.
+
+ len1 := -1;
+
+ if aAudio_buf <> nil then
+ begin
+// writeln( 'pre avcodec_decode_audio' );
+ {$ifdef fpc}
+ len1 := avcodec_decode_audio(@aCodecCtx, PWord( aAudio_buf ), data_size, audio_pkt_data, audio_pkt_size); // Todo.. should be avcodec_decode_audio2 but this wont link on my ubuntu box.
+ {$else}
+ len1 := avcodec_decode_audio(@aCodecCtx, Pointer( aAudio_buf ), data_size, audio_pkt_data, audio_pkt_size); // Todo.. should be avcodec_decode_audio2 but this wont link on my ubuntu box.
+ {$endif}
+// writeln( 'post avcodec_decode_audio' );
+
+ end;
// writeln('avcodec_decode_audio');
if(len1 < 0) then
begin
//* if error, skip frame */
- audio_pkt_size := 0;
+// writeln( 'Skip audio frame' );
+ audio_pkt_size := 0;
break;
end;
@@ -506,7 +533,7 @@ begin
audio_pkt_data := pchar( pkt.data );
audio_pkt_size := pkt.size;
- writeln( 'Audio Packet Size - ' + inttostr(audio_pkt_size) );
+// writeln( 'Audio Packet Size - ' + inttostr(audio_pkt_size) );
end;
end;
@@ -517,52 +544,69 @@ var
audio_size ,
len1 : integer;
aCodecCtx : TAVCodecContext;
- audio_buf : pUInt8 = nil;
+
+ lSrc : pointer;
+
+ // this is used to emulate ...... static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
+ lAudio_buf_data : Taudiobuff; // This created the memory we need
+ laudio_buf : PAudioBuff; // this makes it easy to work with.. since its the pointer to that memeory everywhere
begin
- aCodecCtx := pAVCodecContext(userdata)^;
- audio_buf := UInt8( (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) div 2); // todo : JB
- audio_size := -1;
+ laudio_buf := @lAudio_buf_data ;
-// writeln('----------- audio callback' );
+ aCodecCtx := pAVCodecContext(userdata)^;
+ audio_size := -1;
+ audio_buf_index := 0;
+ audio_buf_size := 0;
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));
+ audio_size := audio_decode_frame(aCodecCtx, pUInt8( laudio_buf ), sizeof(laudio_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
+
+ {$ifdef win32}
+ FillChar(laudio_buf, audio_buf_size, #0);
+ {$else}
+ memset(laudio_buf, 0, audio_buf_size); // todo : jb memset
+ {$endif}
end
else
begin
audio_buf_size := audio_size;
end;
-// audio_buf_index := 0; // Todo : jb - SegFault ?
+ audio_buf_index := 0; // Todo : jb - SegFault ?
end;
len1 := audio_buf_size - audio_buf_index;
if (len1 > len) then
len1 := len;
-
- memcpy(stream, PUInt8( audio_buf ) + audio_buf_index , len1);
- len := len - len1;
- stream := stream + len1;
+
+ {$ifdef win32}
+ lSrc := PUInt8( integer( laudio_buf ) + audio_buf_index );
+ CopyMemory(stream, lSrc , len1);
+ {$else}
+ memcpy(stream, PUInt8( laudio_buf ) + audio_buf_index , len1);
+ {$endif}
+
+ 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;
- pFormatCtx: PAVFormatContext;
+ L : Integer;
+ pFormatCtx : PAVFormatContext;
lVidStreamID ,
lAudStreamID : Integer;
aCodecCtx : pAVCodecContext;
@@ -578,7 +622,7 @@ begin
if FileExists(Name) then
begin
- writeln('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
@@ -593,11 +637,11 @@ begin
if not find_stream_ids( pFormatCtx, lVidStreamID, lAudStreamID ) then
exit;
- writeln( 'done searching for stream ids' );
+// writeln( 'done searching for stream ids' );
if lAudStreamID > -1 then
begin
- writeln( 'Audio Stream ID is : '+ inttostr( lAudStreamID ) );
+// writeln( 'Audio Stream ID is : '+ inttostr( lAudStreamID ) );
lAudioStream := pFormatCtx.streams[lAudStreamID];
aCodecCtx := lAudioStream.codec;
@@ -617,9 +661,9 @@ begin
writeln('SDL_OpenAudio: '+SDL_GetError());
exit
end;
-
- writeln( 'SDL opened audio device' );
-
+
+// writeln( 'SDL opened audio device' );
+
aCodec := avcodec_find_decoder(aCodecCtx.codec_id);
if (aCodec = nil) then
begin
@@ -629,27 +673,28 @@ begin
avcodec_open(aCodecCtx, aCodec);
- writeln( 'Opened the codec' );
+// writeln( 'Opened the codec' );
packet_queue_init( audioq );
SDL_PauseAudio(0);
- writeln( 'SDL_PauseAudio' );
+// writeln( 'SDL_PauseAudio' );
i := 0;
- while (av_read_frame(pFormatCtx, packet)>=0) do
+ while (av_read_frame(pFormatCtx, packet) >= 0) do
begin
- writeln( 'ffmpeg - av_read_frame' );
+// writeln( 'ffmpeg - av_read_frame' );
if (packet.stream_index = lAudStreamID ) then
begin
+// writeln( 'packet_queue_put' );
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);
@@ -665,12 +710,14 @@ begin
*)
end;
-
+
+// halt(0);
+
// Close the codec
- avcodec_close(aCodecCtx);
+// avcodec_close(aCodecCtx);
// Close the video file
- av_close_input_file(pFormatCtx);
+// av_close_input_file(pFormatCtx);
(*
try
@@ -698,7 +745,11 @@ end;
procedure packet_queue_init(var aPacketQueue : TPacketQueue );
begin
- memset(@aPacketQueue, 0, sizeof(TPacketQueue));
+ {$ifdef win32}
+ FillChar(aPacketQueue, sizeof(TPacketQueue), #0);
+ {$else}
+ memset(@aPacketQueue, 0, sizeof(TPacketQueue));
+ {$endif}
aPacketQueue.mutex := SDL_CreateMutex();
aPacketQueue.cond := SDL_CreateCond();
@@ -710,7 +761,7 @@ var
begin
result := -1;
- writeln( 'TAudio_ffMpeg.packet_queue_put' );
+// writeln( 'TAudio_ffMpeg.packet_queue_put' );
if av_dup_packet(@AVPacket) < 0 then
exit;
diff --git a/Game/Code/Classes/UCommon.pas b/Game/Code/Classes/UCommon.pas
index af9ae82d..44ec6bb3 100644
--- a/Game/Code/Classes/UCommon.pas
+++ b/Game/Code/Classes/UCommon.pas
@@ -58,6 +58,26 @@ function AdaptFilePaths( const aPath : widestring ): widestring;
procedure ZeroMemory( Destination: Pointer; Length: DWORD );
{$ENDIF}
+{$IFDEF Win32}
+
+type
+ TSearchRecW = record
+ Time: Integer;
+ Size: Integer;
+ Attr: Integer;
+ Name: WideString;
+ ExcludeAttr: Integer;
+ FindHandle: THandle;
+ FindData: TWin32FindDataW;
+ end;
+
+ function FindFirstW(const Path: WideString; Attr: Integer; var F: TSearchRecW): Integer;
+ function FindNextW(var F: TSearchRecW): Integer;
+ procedure FindCloseW(var F: TSearchRecW);
+ function FindMatchingFileW(var F: TSearchRecW): Integer;
+ function DirectoryExistsW(const Directory: widestring): Boolean;
+{$endif}
+
implementation
function StringReplaceW(text : WideString; search, rep: WideChar):WideString;
@@ -190,7 +210,75 @@ begin
end;
{$ENDIF}
+
+
+
{$ENDIF}
+{$ifdef win32}
+function FindFirstW(const Path: widestring; Attr: Integer; var F: TSearchRecW): Integer;
+const
+ faSpecial = faHidden or faSysFile or faVolumeID or faDirectory;
+begin
+ F.ExcludeAttr := not Attr and faSpecial;
+ F.FindHandle := FindFirstFileW(PWideChar(Path), F.FindData);
+ if F.FindHandle <> INVALID_HANDLE_VALUE then
+ begin
+ Result := FindMatchingFileW(F);
+ if Result <> 0 then FindCloseW(F);
+ end else
+ Result := GetLastError;
+end;
+
+function FindNextW(var F: TSearchRecW): Integer;
+begin
+ if FindNextFileW(F.FindHandle, F.FindData) then
+ Result := FindMatchingFileW(F)
+ else
+ Result := GetLastError;
+end;
+
+procedure FindCloseW(var F: TSearchRecW);
+begin
+ if F.FindHandle <> INVALID_HANDLE_VALUE then
+ begin
+ Windows.FindClose(F.FindHandle);
+ F.FindHandle := INVALID_HANDLE_VALUE;
+ end;
+end;
+
+function FindMatchingFileW(var F: TSearchRecW): Integer;
+var
+ LocalFileTime: TFileTime;
+begin
+ with F do
+ begin
+ while FindData.dwFileAttributes and ExcludeAttr <> 0 do
+ if not FindNextFileW(FindHandle, FindData) then
+ begin
+ Result := GetLastError;
+ Exit;
+ end;
+ FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
+ FileTimeToDosDateTime(LocalFileTime, LongRec(Time).Hi, LongRec(Time).Lo);
+ Size := FindData.nFileSizeLow;
+ Attr := FindData.dwFileAttributes;
+ Name := FindData.cFileName;
+ end;
+ Result := 0;
+end;
+
+function DirectoryExistsW(const Directory: widestring): Boolean;
+var
+ Code: Integer;
+begin
+ Code := GetFileAttributesW(PWideChar(Directory));
+ Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
+end;
+{$endif}
+
+
+
+
end.
diff --git a/Game/Code/Classes/UFiles.pas b/Game/Code/Classes/UFiles.pas
index 7e23b42f..717d20e2 100644
--- a/Game/Code/Classes/UFiles.pas
+++ b/Game/Code/Classes/UFiles.pas
@@ -333,16 +333,22 @@ Result := False;
//Open File and set File Pointer to the beginning
AssignFile(SongFile, Song.Path + Song.FileName);
- Reset(SongFile);
+// if assinged( SongFile ) then
+ begin
+ try
+ Reset(SongFile);
- //Clear old Song Header
- ClearSong(Song);
+ //Clear old Song Header
+ ClearSong(Song);
- //Read Header
- Result := ReadTxTHeader(Song);
+ //Read Header
+ Result := ReadTxTHeader(Song);
- //And Close File
- CloseFile(SongFile);
+ //And Close File
+ finally
+ CloseFile(SongFile);
+ end;
+ end;
{except
CloseFile(SongFile);
diff --git a/Game/Code/Classes/USongs.pas b/Game/Code/Classes/USongs.pas
index 99474961..e3c54ac4 100644
--- a/Game/Code/Classes/USongs.pas
+++ b/Game/Code/Classes/USongs.pas
@@ -13,6 +13,7 @@ uses SysUtils,
{$endif}
ULog,
UTexture,
+ UCommon,
UCatCovers;
type
@@ -23,33 +24,33 @@ type
end;
TScore = record
- Name: string;
+ Name: widestring;
Score: integer;
Length: string;
end;
TSong = record
- Path: string;
- Folder: string; // for sorting by folder
- FileName: string;
+ Path: widestring;
+ Folder: widestring; // for sorting by folder
+ FileName: widestring;
// sorting methods
- Category: array of string; // I think I won't need this
- Genre: string;
- Edition: string;
- Language: string; // 0.5.0: new
+ Category: array of widestring; // I think I won't need this
+ Genre: widestring;
+ Edition: widestring;
+ Language: widestring; // 0.5.0: new
- Title: string;
- Artist: string;
+ Title: widestring;
+ Artist: widestring;
- Text: string;
- Creator: string;
+ Text: widestring;
+ Creator: widestring;
- Cover: string;
+ Cover: widestring;
CoverTex: TTexture;
- Mp3: string;
- Background: string;
- Video: string;
+ Mp3: widestring;
+ Background: widestring;
+ Video: widestring;
VideoGAP: real;
VideoLoaded: boolean; // 0.5.0: true if the video has been loaded
NotesGAP: integer;
@@ -79,7 +80,7 @@ type
procedure LoadSongList; // load all songs
procedure BrowseDir(Dir: widestring); // should return number of songs in the future
procedure Sort(Order: integer);
- function FindSongFile(Dir, Mask: string): string;
+ function FindSongFile(Dir, Mask: widestring): widestring;
end;
TCatSongs = class
@@ -133,7 +134,7 @@ end;
procedure TSongs.BrowseDir(Dir: widestring);
var
- SR: TSearchRec; // for parsing Songs Directory
+ SR: TSearchRecW; // for parsing Songs Directory
SLen: integer;
{$ifndef win32}
@@ -144,16 +145,16 @@ var
{$endif}
begin
{$ifdef win32}
- if FindFirst(Dir + '*', faDirectory, SR) = 0 then // JB_Unicode - windows
+ if FindFirstW(Dir + '*', faDirectory, SR) = 0 then // JB_Unicode - windows
begin
repeat
if (SR.Name <> '.') and (SR.Name <> '..') then
begin
BrowseDir(Dir + Sr.Name + PathDelim);
end
- until FindNext(SR) <> 0;
+ until FindNextw(SR) <> 0;
end; // if
- FindClose(SR);
+ FindClosew(SR);
{$else}
// Itterate the Songs Directory... ( With unicode capable functions for linux )
TheDir := opendir( Dir ); // JB_Unicode - linux
@@ -178,7 +179,7 @@ begin
// Log.LogStatus('Parsing directory: ' + Dir + SR.Name, 'LoadSongList');
- if FindFirst(Dir + '*.txt', 0, SR) = 0 then
+ if FindFirstW(Dir + '*.txt', 0, SR) = 0 then
begin
repeat
SLen := BrowsePos;
@@ -204,9 +205,9 @@ begin
SetLength(Song, Length(Song) + 50);
end;
- until FindNext(SR) <> 0;
+ until FindNextW(SR) <> 0;
end; // if FindFirst
- FindClose(SR);
+ FindCloseW(SR);
end;
procedure TSongs.Sort(Order: integer);
@@ -309,7 +310,7 @@ begin
end; // case
end;
-function TSongs.FindSongFile(Dir, Mask: string): string;
+function TSongs.FindSongFile(Dir, Mask: widestring): widestring;
var
SR: TSearchRec; // for parsing song directory
begin
@@ -463,10 +464,12 @@ case Ini.Sorting of
CatSongs.Song[CatLen].Visible := true;
end
- else if (Ini.Sorting = sTitle) and (Length(Songs.Song[S].Title)>=1) and (Letter <> UpCase(Songs.Song[S].Title[1])) then begin
+ else if (Ini.Sorting = sTitle) and
+ (Length(Songs.Song[S].Title)>=1) and
+ (Letter <> UpperCase(Songs.Song[S].Title)[1]) then begin
// add a letter Category Button
Inc(Order);
- Letter := UpCase(Songs.Song[S].Title[1]);
+ Letter := Uppercase(Songs.Song[S].Title)[1];
CatLen := Length(CatSongs.Song);
SetLength(CatSongs.Song, CatLen+1);
CatSongs.Song[CatLen].Artist := '[' + Letter + ']';
@@ -491,10 +494,10 @@ case Ini.Sorting of
CatSongs.Song[CatLen].Visible := true;
end
- else if (Ini.Sorting = sArtist) and (Length(Songs.Song[S].Artist)>=1) and (Letter <> UpCase(Songs.Song[S].Artist[1])) then begin
+ else if (Ini.Sorting = sArtist) and (Length(Songs.Song[S].Artist)>=1) and (Letter <> UpperCase(Songs.Song[S].Artist)[1]) then begin
// add a letter Category Button
Inc(Order);
- Letter := UpCase(Songs.Song[S].Artist[1]);
+ Letter := UpperCase(Songs.Song[S].Artist)[1];
CatLen := Length(CatSongs.Song);
SetLength(CatSongs.Song, CatLen+1);
CatSongs.Song[CatLen].Artist := '[' + Letter + ']';
@@ -545,7 +548,7 @@ case Ini.Sorting of
end
else if (Ini.Sorting = sTitle2) AND (Length(Songs.Song[S].Title)>=1) then begin
- if (ord(Songs.Song[S].Title[1]) > 47) and (ord(Songs.Song[S].Title[1]) < 58) then Letter2 := '#' else Letter2 := UpCase(Songs.Song[S].Title[1]);
+ if (ord(Songs.Song[S].Title[1]) > 47) and (ord(Songs.Song[S].Title[1]) < 58) then Letter2 := '#' else Letter2 := UpperCase(Songs.Song[S].Title)[1];
if (Letter <> Letter2) then begin
// add a letter Category Button
Inc(Order);
@@ -575,7 +578,7 @@ case Ini.Sorting of
end
else if (Ini.Sorting = sArtist2) AND (Length(Songs.Song[S].Artist)>=1) then begin
- if (ord(Songs.Song[S].Artist[1]) > 47) and (ord(Songs.Song[S].Artist[1]) < 58) then Letter2 := '#' else Letter2 := UpCase(Songs.Song[S].Artist[1]);
+ if (ord(Songs.Song[S].Artist[1]) > 47) and (ord(Songs.Song[S].Artist[1]) < 58) then Letter2 := '#' else Letter2 := UpperCase(Songs.Song[S].Artist)[1];
if (Letter <> Letter2) then begin
// add a letter Category Button
Inc(Order);
diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas
index 4c27867d..154cd04c 100644
--- a/Game/Code/Classes/UVideo.pas
+++ b/Game/Code/Classes/UVideo.pas
@@ -10,9 +10,11 @@ unit UVideo;
# #
############################################################################## }
-{$define DebugDisplay} // uncomment if u want to see the debug stuff
+//{$define DebugDisplay} // uncomment if u want to see the debug stuff
//{$define DebugFrames}
//{$define Info}
+
+//{$define FFMpegAudio}
{}
@@ -45,6 +47,9 @@ uses SDL,
dialogs,
{$endif}
{$ENDIF}
+ {$ifdef FFMpegAudio}
+ UAudio_FFMpeg,
+ {$endif}
UIni,
UMusic;
@@ -108,7 +113,9 @@ type
end;
-
+ const
+ SDL_AUDIO_BUFFER_SIZE = 1024;
+
{$ifdef DebugDisplay}
//{$ifNdef win32}
@@ -262,19 +269,23 @@ begin
FrameFinished:=0;
// read packets until we have a finished frame (or there are no more packets)
-// while (FrameFinished=0) and (av_read_frame(VideoFormatContext, @AVPacket)>=0) do
- while (FrameFinished=0) and (av_read_frame(VideoFormatContext, AVPacket)>=0) do // JB-ffmpeg
+ while ( FrameFinished = 0 ) and
+ ( av_read_frame(VideoFormatContext, AVPacket) >= 0 ) do // JB-ffmpeg
begin
// if we got a packet from the video stream, then decode it
if (AVPacket.stream_index=VideoStreamIndex) then
-// errnum:=avcodec_decode_video(VideoCodecContext, AVFrame, @frameFinished , AVPacket.data, AVPacket.size);
+ begin
errnum := avcodec_decode_video(VideoCodecContext, AVFrame, frameFinished , AVPacket.data, AVPacket.size); // JB-ffmpeg
-
-
- // release internal packet structure created by av_read_frame
-// av_free_packet(PAVPacket(@AVPacket));
+ {$ifdef FFMpegAudio}
+ end
+ else
+ if (AVPacket.stream_index = AudioStreamIndex ) then
+ begin
+ UAudio_FFMpeg.packet_queue_put(UAudio_FFMpeg.audioq, AVPacket);
+ {$endif}
+ end;
try
if AVPacket.data <> nil then
@@ -427,6 +438,10 @@ var
errnum, i, x,y: Integer;
lStreamsCount : Integer;
+ wanted_spec ,
+ spec : TSDL_AudioSpec;
+ aCodec : pAVCodec;
+
begin
fVideoOpened := False;
fVideoPaused := False;
@@ -471,27 +486,47 @@ begin
end;
aCodecCtx := VideoFormatContext.streams[ AudioStreamIndex ].codec;
+ {$ifdef FFMpegAudio}
+ // This is the audio ffmpeg audio support Jay is working on.
if aCodecCtx <> nil then
begin
+ 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 := UAudio_FFMpeg.audio_callback;
+ wanted_spec.userdata := aCodecCtx;
-// WantedAudioCodecContext.freq := aCodecCtx^.sample_rate;
-// WantedAudioCodecContext.format := AUDIO_S16SYS;
-// WantedAudioCodecContext.channels := aCodecCtx^.channels;
-(* WantedAudioCodecContext.silence := 0;
- WantedAudioCodecContext.samples := 1024;//SDL_AUDIO_BUFFER_SIZE;
-// WantedAudioCodecContext.callback := audio_callback;
- WantedAudioCodecContext.userdata := aCodecCtx;
-*)
+
+ 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' );
+
end;
-(*
- if(SDL_OpenAudio(WantedAudioCodecContext, AudioCodecContext) < 0) then
- begin
- writeln( 'Could not do SDL_OpenAudio' );
- exit;
- end;
-*)
-
+ {$endif}
+
if(VideoStreamIndex >= 0) then
begin
VideoCodecContext:=VideoFormatContext^.streams[VideoStreamIndex]^.codec;
diff --git a/Game/Code/Screens/UScreenSong.pas b/Game/Code/Screens/UScreenSong.pas
index ea1dd8a5..4d146283 100644
--- a/Game/Code/Screens/UScreenSong.pas
+++ b/Game/Code/Screens/UScreenSong.pas
@@ -261,7 +261,9 @@ begin
begin
For I := 1 to high(CatSongs.Song) do
begin
- if (CatSongs.Song[(I + Interaction) mod I2].Visible) AND (Length(CatSongs.Song[(I + Interaction) mod I2].Title)>0) AND (UpCase(CatSongs.Song[(I + Interaction) mod I2].Title[1]) = Letter) then
+ if (CatSongs.Song[(I + Interaction) mod I2].Visible) AND
+ (Length(CatSongs.Song[(I + Interaction) mod I2].Title)>0) AND
+ (widechar(UpperCase(CatSongs.Song[(I + Interaction) mod I2].Title)[1]) = widechar(Letter)) then
begin
SkipTo(CatSongs.VisibleIndex((I + Interaction) mod I2));
@@ -280,7 +282,9 @@ begin
begin
For I := 1 to high(CatSongs.Song) do
begin
- if (CatSongs.Song[(I + Interaction) mod I2].Visible) AND (Length(CatSongs.Song[(I + Interaction) mod I2].Artist)>0) AND (UpCase(CatSongs.Song[(I + Interaction) mod I2].Artist[1]) = Letter) then
+ if (CatSongs.Song[(I + Interaction) mod I2].Visible) AND
+ (Length(CatSongs.Song[(I + Interaction) mod I2].Artist)>0) AND
+ (widechar(uppercase(CatSongs.Song[(I + Interaction) mod I2].Artist)[1]) = widechar(Letter)) then
begin
SkipTo(CatSongs.VisibleIndex((I + Interaction) mod I2));
diff --git a/Game/Code/UltraStar.dpr b/Game/Code/UltraStar.dpr
index 1e418a49..0b7e8449 100644
--- a/Game/Code/UltraStar.dpr
+++ b/Game/Code/UltraStar.dpr
@@ -59,8 +59,6 @@ uses
UCommon in 'Classes\UCommon.pas',
UGraphic in 'Classes\UGraphic.pas',
UTexture in 'Classes\UTexture.pas',
- UMusic in 'Classes\UMusic.pas',
- UAudio_Bass in 'Classes\UAudio_Bass.pas',
ULanguage in 'Classes\ULanguage.pas',
UMain in 'Classes\UMain.pas',
UDraw in 'Classes\UDraw.pas',
@@ -100,10 +98,14 @@ uses
UParty in 'Classes\UParty.pas', // to - do : rewrite Party Manager as Module, reomplent ability to offer party Mody by Plugin
//------------------------------
- //Includes - Video Support
+ //Includes - Media support classes....
+ // Make sure UMedia always first, then UMedia_dummy
//------------------------------
- UMedia_dummy in 'Classes\UMedia_dummy.pas',
- UVideo in 'Classes\UVideo.pas',
+ UMusic in 'Classes\UMusic.pas',
+ UMedia_dummy in 'Classes\UMedia_dummy.pas',
+ UVideo in 'Classes\UVideo.pas',
+// UAudio_FFMpeg in 'Classes\UAudio_FFMpeg.pas', // this is NEARLY to a working point :P
+ UAudio_Bass in 'Classes\UAudio_Bass.pas',
//------------------------------
//Includes - Screens
@@ -330,6 +332,7 @@ begin
Log.BenchmarkEnd(1);
Log.LogBenchmark('Initializing Sound', 1);
+// exit;
// Graphics
Log.BenchmarkStart(1);