From e74bd57c12f470257111c1c0530fb38f0fd34414 Mon Sep 17 00:00:00 2001
From: jaybinks <jaybinks@b956fd51-792f-4845-bead-9b4dfca2ff2c>
Date: Sat, 12 Jan 2008 12:31:43 +0000
Subject: bunch of smaller changes...

some changes to song loading...
Record global changed to singleton object
started implementing mic volume display in Settings-Record

hope this dosnt break anything.. :P

git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@789 b956fd51-792f-4845-bead-9b4dfca2ff2c
---
 Game/Code/Classes/UAudioInput_Bass.pas     |  23 +-
 Game/Code/Classes/UCommandLine.pas         |   5 +-
 Game/Code/Classes/UDataBase.pas            |   1 +
 Game/Code/Classes/UDraw.pas                |  28 ++-
 Game/Code/Classes/UFiles.pas               | 360 +++--------------------------
 Game/Code/Classes/UIni.pas                 |  10 +-
 Game/Code/Classes/ULog.pas                 |   6 +-
 Game/Code/Classes/UMain.pas                |  86 +++----
 Game/Code/Classes/UMusic.pas               |   1 +
 Game/Code/Classes/UPlatform.pas            |  74 ++----
 Game/Code/Classes/UPlatformLinux.pas       |   2 +-
 Game/Code/Classes/UPlatformMacOSX.pas      |  20 +-
 Game/Code/Classes/UPlatformWindows.pas     |  59 ++++-
 Game/Code/Classes/URecord.pas              |  81 +++++--
 Game/Code/Classes/USongs.pas               | 259 +++++++++------------
 Game/Code/Screens/UScreenEditConvert.pas   |   1 +
 Game/Code/Screens/UScreenEditHeader.pas    |   6 +-
 Game/Code/Screens/UScreenEditSub.pas       |  51 ++--
 Game/Code/Screens/UScreenMain.pas          |   7 +-
 Game/Code/Screens/UScreenOptionsRecord.pas | 132 ++++++++---
 Game/Code/Screens/UScreenOptionsSound.pas  |   9 +-
 Game/Code/Screens/UScreenScore.pas         |   6 +-
 Game/Code/Screens/UScreenSing.pas          |  91 ++++----
 Game/Code/Screens/UScreenSingModi.pas      |   4 +-
 Game/Code/Screens/UScreenSong.pas          |  18 +-
 Game/Code/Screens/UScreenStatMain.pas      |   7 +-
 Game/Code/Screens/UScreenTop5.pas          |  18 +-
 Game/Code/UltraStar.dpr                    |   1 +
 28 files changed, 599 insertions(+), 767 deletions(-)

diff --git a/Game/Code/Classes/UAudioInput_Bass.pas b/Game/Code/Classes/UAudioInput_Bass.pas
index 9807ffc3..75a5aee5 100644
--- a/Game/Code/Classes/UAudioInput_Bass.pas
+++ b/Game/Code/Classes/UAudioInput_Bass.pas
@@ -79,7 +79,7 @@ begin
   //Check for Soundcard with same Description
   For I := 0 to SC-1 do
   begin
-    if (Recording.SoundCard[I].Description = Desc) then
+    if (AudioInputProcessor.SoundCard[I].Description = Desc) then
     begin
       Result := True;
       Break;
@@ -88,7 +88,7 @@ begin
 end;
 
 begin
-  with Recording do
+  with AudioInputProcessor do
   begin
     // checks for recording devices and puts them into an array
     SetLength(SoundCard, 0);
@@ -170,21 +170,22 @@ var
   PlayerLeft, PlayerRight: integer;
   CaptureSoundLeft, CaptureSoundRight: TSound;
 begin
-  for S := 0 to High(Recording.Sound) do
-    Recording.Sound[S].BufferLong[0].Clear;
+  for S := 0 to High(AudioInputProcessor.Sound) do
+    AudioInputProcessor.Sound[S].BufferLong[0].Clear;
 
-  for SC := 0 to High(Ini.CardList) do begin
+  for SC := 0 to High(Ini.CardList) do
+  begin
     PlayerLeft  := Ini.CardList[SC].ChannelL-1;
     PlayerRight := Ini.CardList[SC].ChannelR-1;
     if PlayerLeft  >= PlayersPlay then PlayerLeft  := -1;
     if PlayerRight >= PlayersPlay then PlayerRight := -1;
     if (PlayerLeft > -1) or (PlayerRight > -1) then begin
       if (PlayerLeft > -1) then
-        CaptureSoundLeft := Recording.Sound[PlayerLeft]
+        CaptureSoundLeft := AudioInputProcessor.Sound[PlayerLeft]
       else
         CaptureSoundLeft := nil;
       if (PlayerRight > -1) then
-        CaptureSoundRight := Recording.Sound[PlayerRight]
+        CaptureSoundRight := AudioInputProcessor.Sound[PlayerRight]
       else
         CaptureSoundRight := nil;
 
@@ -224,14 +225,14 @@ end;
 function MicrophoneCallback(stream: HSTREAM; buffer: Pointer;
     len: Cardinal; Card: Cardinal): boolean; stdcall;
 begin
-  Recording.HandleMicrophoneData(buffer, len, Recording.SoundCard[Card]);
+  AudioInputProcessor.HandleMicrophoneData(buffer, len, AudioInputProcessor.SoundCard[Card]);
   Result := true;
 end;
 
 {*
  * Start input-capturing on Soundcard specified by Card.
  * Params:
- *   Card - soundcard index in Recording.SoundCard array
+ *   Card - soundcard index in AudioInputProcessor.SoundCard array
  *   CaptureSoundLeft  - sound(-buffer) used for left channel capture data
  *   CaptureSoundRight - sound(-buffer) used for right channel capture data
  *}
@@ -254,7 +255,7 @@ begin
   end
   else
   begin
-    bassSoundCard := TBassSoundCard(Recording.SoundCard[Card]);
+    bassSoundCard := TBassSoundCard(AudioInputProcessor.SoundCard[Card]);
     bassSoundCard.CaptureSoundLeft  := CaptureSoundLeft;
     bassSoundCard.CaptureSoundRight := CaptureSoundRight;
 
@@ -267,7 +268,7 @@ end;
 {*
  * Stop input-capturing on Soundcard specified by Card.
  * Params:
- *   Card - soundcard index in Recording.SoundCard array
+ *   Card - soundcard index in AudioInputProcessor.SoundCard array
  *}
 procedure TAudioInput_Bass.StopCard(Card: byte);
 begin
diff --git a/Game/Code/Classes/UCommandLine.pas b/Game/Code/Classes/UCommandLine.pas
index 86f822a4..55dfc6ce 100644
--- a/Game/Code/Classes/UCommandLine.pas
+++ b/Game/Code/Classes/UCommandLine.pas
@@ -61,7 +61,8 @@ const
 
 implementation
 
-uses SysUtils;
+uses SysUtils,
+     uPlatform;
 //      uINI   -- Nasty requirement... ( removed with permission of blindy )
 
 
@@ -99,7 +100,7 @@ begin
 
   writeln( '' );
 
-  halt;
+  platform.halt;
 end;
 
 //-------------
diff --git a/Game/Code/Classes/UDataBase.pas b/Game/Code/Classes/UDataBase.pas
index e99cb891..b5636d52 100644
--- a/Game/Code/Classes/UDataBase.pas
+++ b/Game/Code/Classes/UDataBase.pas
@@ -9,6 +9,7 @@ interface
 {$I switches.inc}
 
 uses USongs,
+     USong,
      SQLiteTable3;
 
 //--------------------
diff --git a/Game/Code/Classes/UDraw.pas b/Game/Code/Classes/UDraw.pas
index c399057b..662050dc 100644
--- a/Game/Code/Classes/UDraw.pas
+++ b/Game/Code/Classes/UDraw.pas
@@ -161,7 +161,7 @@ end;
 
 procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer);
 var
-  Pet:    integer;
+  Pet        : integer;
 begin;
 //  Log.LogStatus('Oscilloscope', 'SingDraw');
   glColor3f(Skin_OscR, Skin_OscG, Skin_OscB);
@@ -169,14 +169,19 @@ begin;
     glColor3f(1, 1, 1);  }
 
   glBegin(GL_LINE_STRIP);
-    glVertex2f(X, -Recording.Sound[NrSound].BufferArray[1] / $10000 * H + Y + H/2);
-    for Pet := 2 to Recording.Sound[NrSound].n div 1 do begin
-      glVertex2f(X + (Pet-1) * W / (Recording.Sound[NrSound].n - 1),
-      -Recording.Sound[NrSound].BufferArray[Pet] / $10000 * H + Y + H/2);
+
+    glVertex2f(X, -AudioInputProcessor.Sound[NrSound].BufferArray[1] / $10000 * H + Y + H/2);
+
+    for Pet := 2 to AudioInputProcessor.Sound[NrSound].n div 1 do
+    begin
+      glVertex2f( X + (Pet-1) * W / (AudioInputProcessor.Sound[NrSound].n - 1),
+                  -AudioInputProcessor.Sound[NrSound].BufferArray[Pet] / $10000 * H + Y + H/2 );
     end;
   glEnd;
 end;
 
+
+
 procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer);
 var
   Pet:    integer;
@@ -366,7 +371,7 @@ var
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-  if Player[NrGracza].IlNut > 0 then
+////  if Player[NrGracza].IlNut > 0 then
     begin
       TempR := W / (Czesci[0].Czesc[Czesci[0].Akt].Koniec - Czesci[0].Czesc[Czesci[0].Akt].StartNote);
         for N := 0 to Player[NrGracza].HighNut do
@@ -480,14 +485,7 @@ begin
 
   lTmpA := (Right-Left);
   lTmpB := (Czesci[NrCzesci].Czesc[Czesci[NrCzesci].Akt].Koniec - Czesci[NrCzesci].Czesc[Czesci[NrCzesci].Akt].StartNote);
-  
-  {$IFDEF LAZARUS}
-{*
-  writeln( 'UDRAW (Right-Left)    : ' + floattostr( lTmpA ) );
-  writeln( 'UDRAW                 : ' + floattostr( lTmpB ) );
-  writeln( '' );
-*}
-  {$ENDIF}
+
 
   if ( lTmpA > 0 ) AND
      ( lTmpB > 0 ) THEN
@@ -555,7 +553,7 @@ begin
         end; // if not FreeStyle
       end; // with
     end; // for
-  end; // with
+  end; // with                      1
 
   glDisable(GL_BLEND);
   glDisable(GL_TEXTURE_2D);
diff --git a/Game/Code/Classes/UFiles.pas b/Game/Code/Classes/UFiles.pas
index 69beefe9..d3e4729b 100644
--- a/Game/Code/Classes/UFiles.pas
+++ b/Game/Code/Classes/UFiles.pas
@@ -10,45 +10,33 @@ interface
 uses SysUtils,
      ULog,
      UMusic,
-     USongs;
+     USongs,
+     USong;
 
 //procedure   InitializePaths; //Function sets All Absolute Paths eg. for Songs
-function    ReadTXTHeader(var Song: TSong): boolean; //Reads Standard TXT Header
-function    AnalyseFile(var Song: TSong): boolean; //Analyse Song File and Read Header
-procedure   ClearSong(var Song: TSong); //Clears Song Header values
+//function    ReadTXTHeader(var Song: TSong): boolean; //Reads Standard TXT Header
+//function    AnalyseFile(var Song: TSong): boolean; //Analyse Song File and Read Header
+//procedure   ClearSong(var Song: TSong); //Clears Song Header values
 
 //Methodes Loading and Saving Songfiles
 procedure ResetSingTemp;
-procedure ParseNote(NrCzesci: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
-procedure NewSentence(NrCzesciP: integer; Param1, Param2: integer);
-function  LoadSong(Name: string): boolean;
+//procedure ParseNote(NrCzesci: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
+//procedure NewSentence(NrCzesciP: integer; Param1, Param2: integer);
+
+//function  LoadSong(Name: string): boolean;
 function  SaveSong(Song: TSong; Czesc: TCzesci; Name: string; Relative: boolean): boolean;
 
 
 
 var
-{*
-  //Absolute Paths
-  GamePath:         string;
-  SoundPath:        string;
-  SongPath:         string;
-  LogPath:          string;
-  ThemePath:        string;
-  ScreenshotsPath:  string;
-  CoversPath:       string;
-  LanguagesPath:    string;
-  PluginPath:       string;
-  PlayListPath:     string;
-*}
-
   SongFile: TextFile;   // all procedures in this unit operates on this file
   FileLineNo: integer;  //Line which is readed at Last, for error reporting
 
   // variables available for all procedures
-  Base:       array[0..1] of integer;
-  Rel:        array[0..1] of integer;
-  Mult:     integer = 1;
-  MultBPM:  integer = 4;
+  Base    : array[0..1] of integer;
+  Rel     : array[0..1] of integer;
+  Mult    : integer = 1;
+  MultBPM : integer = 4;
 
 implementation
 
@@ -57,7 +45,10 @@ uses TextGL,
 		 UPlatform,
      UMain;
 
+(*
 //--------------------
+<<<<<<< .mine
+=======
 // Clears Song Header values
 //--------------------
 procedure ClearSong(var Song: TSong);
@@ -367,7 +358,7 @@ Result := False;
   Log.LogError('An Error occured reading Line ' + inttostr(FileLineNo) + ' from SongHeader: ' + Song.FileName);
 end;}
 end;
-
+              *)
 //--------------------
 // Resets the temporary Sentence Arrays for each Player and some other Variables
 //--------------------
@@ -376,7 +367,6 @@ var
   Pet:  integer;
 begin
   SetLength(Czesci, Length(Player));
-  SetLength(AktSong.BPM, 0);
   for Pet := 0 to High(Player) do begin
     SetLength(Czesci[Pet].Czesc, 1);
     SetLength(Czesci[Pet].Czesc[0].Nuta, 0);
@@ -386,316 +376,18 @@ begin
     Player[pet].IlNut := 0;
     Player[pet].HighNut := -1;
   end;
-  //Reset Path and Filename Values to Prevent Errors in Editor
-  AktSong.Path := '';
-  AktSong.FileName := '';
-end;
-
-//--------------------
-// Parses Note Infos and save them to Array
-//--------------------
-procedure ParseNote(NrCzesci: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
-var
-  Space:  boolean;
-begin
-  case Ini.Solmization of
-    1:  // european
-      begin
-        case (NoteP mod 12) of
-          0..1:  LyricS := ' do ';
-          2..3:  LyricS := ' re ';
-          4:  LyricS := ' mi ';
-          5..6:  LyricS := ' fa ';
-          7..8:  LyricS := ' sol ';
-          9..10:  LyricS := ' la ';
-          11:  LyricS := ' si ';
-        end;
-      end;
-    2:  // japanese
-      begin
-        case (NoteP mod 12) of
-          0..1:  LyricS := ' do ';
-          2..3:  LyricS := ' re ';
-          4:  LyricS := ' mi ';
-          5..6:  LyricS := ' fa ';
-          7..8:  LyricS := ' so ';
-          9..10:  LyricS := ' la ';
-          11:  LyricS := ' shi ';
-        end;
-      end;
-    3:  // american
-      begin
-        case (NoteP mod 12) of
-          0..1:  LyricS := ' do ';
-          2..3:  LyricS := ' re ';
-          4:  LyricS := ' mi ';
-          5..6:  LyricS := ' fa ';
-          7..8:  LyricS := ' sol ';
-          9..10:  LyricS := ' la ';
-          11:  LyricS := ' ti ';
-        end;
-      end;
-  end; // case
-
-  with Czesci[NrCzesci].Czesc[Czesci[NrCzesci].High] do begin
-    SetLength(Nuta, Length(Nuta) + 1);
-    IlNut := IlNut + 1;
-    HighNut := HighNut + 1;
-    Muzyka.IlNut := Muzyka.IlNut + 1;
-
-    Nuta[HighNut].Start := StartP;
-    if IlNut = 1 then begin
-      StartNote := Nuta[HighNut].Start;
-      if Czesci[NrCzesci].Ilosc = 1 then
-        Start := -100;
-//        Start := Nuta[HighNut].Start;
-    end;
-
-    Nuta[HighNut].Dlugosc := DurationP;
-    Muzyka.DlugoscNut := Muzyka.DlugoscNut + Nuta[HighNut].Dlugosc;
-
-    // back to the normal system with normal, golden and now freestyle notes
-    case TypeP of
-      'F':  Nuta[HighNut].Wartosc := 0;
-      ':':  Nuta[HighNut].Wartosc := 1;
-      '*':  Nuta[HighNut].Wartosc := 2;
-    end;
-
-    Czesci[NrCzesci].Wartosc := Czesci[NrCzesci].Wartosc + Nuta[HighNut].Dlugosc * Nuta[HighNut].Wartosc;
 
-    Nuta[HighNut].Ton := NoteP;
-    if Nuta[HighNut].Ton < Base[NrCzesci] then Base[NrCzesci] := Nuta[HighNut].Ton;
-    Nuta[HighNut].TonGamy := Nuta[HighNut].TonGamy mod 12;
-
-    Nuta[HighNut].Tekst := Copy(LyricS, 2, 100);
-    Lyric := Lyric + Nuta[HighNut].Tekst;
-
-    if TypeP = 'F' then
-      Nuta[HighNut].FreeStyle := true;
-
-    Koniec := Nuta[HighNut].Start + Nuta[HighNut].Dlugosc;
-  end; // with
-end;
-
-//--------------------
-// Called when a new Sentence is found in the TXT File
-//--------------------
-procedure NewSentence(NrCzesciP: integer; Param1, Param2: integer);
-var
-I: Integer;
-begin
-
-  // stara czesc //Alter Satz //Update Old Part
-  Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].BaseNote := Base[NrCzesciP];
-  Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].LyricWidth := glTextWidth(PChar(Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].Lyric));
-
-  //Total Notes Patch
-  Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].TotalNotes := 0;
-  for I := low(Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].Nuta) to high(Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].Nuta) do
+  //Reset Path and Filename Values to Prevent Errors in Editor
+  if assigned( CurrentSong ) then
   begin
-    Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].TotalNotes := Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].TotalNotes + Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].Nuta[I].Dlugosc * Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].Nuta[I].Wartosc;
+    SetLength(CurrentSong.BPM, 0);
+    CurrentSong.Path := '';
+    CurrentSong.FileName := '';
   end;
-  //Total Notes Patch End
-
-
-  // nowa czesc //Neuer Satz //Update New Part
-  SetLength(Czesci[NrCzesciP].Czesc, Czesci[NrCzesciP].Ilosc + 1);
-  Czesci[NrCzesciP].High := Czesci[NrCzesciP].High + 1;
-  Czesci[NrCzesciP].Ilosc := Czesci[NrCzesciP].Ilosc + 1;
-  Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].HighNut := -1;
-
-  if not AktSong.Relative then
-    Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].Start := Param1;
-
-  if AktSong.Relative then begin
-    Czesci[NrCzesciP].Czesc[Czesci[NrCzesciP].High].Start := Param1;
-    Rel[NrCzesciP] := Rel[NrCzesciP] + Param2;
-  end;
-
-  Base[NrCzesciP] := 100; // high number
+  
+//  CurrentSong := nil;
 end;
 
-//--------------------
-// Load a Song
-//--------------------
-function LoadSong(Name: string): boolean;
-var
-  TempC:    char;
-  Tekst:    string;
-  CP:       integer; // Current Player (0 or 1)
-  Pet:      integer;
-  Both:     boolean;
-  Param1:   integer;
-  Param2:   integer;
-  Param3:   integer;
-  ParamS:   string;
-  I: Integer;
-begin
-  Result := false;
-
-  if not FileExists(Name) then begin
-    Log.LogError('File not found: "' + Name + '"', 'WczytajCzesci');
-    exit;
-  end;
-
-  try
-  MultBPM := 4; // 4 - mnoznik dla czasu nut
-  Mult := 1; // 4 - dokladnosc pomiaru nut
-  Base[0] := 100; // high number
-//  Base[1] := 100; // high number
-  Czesci[0].Wartosc := 0;
-//  Czesci[1].Wartosc := 0; // here was the error in 0.3.2
-  AktSong.Relative := false;
-
-  Rel[0] := 0;
-//  Rel[1] := 0;
-  CP := 0;
-  Both := false;
-  if Length(Player) = 2 then Both := true;
-
-  FileMode := fmOpenRead;
-  AssignFile(SongFile, Name);
-  Reset(SongFile);
-
-  //Clear old Song Header
-  ClearSong(AktSong);
-
-  if (AktSong.Path = '') then
-    AktSong.Path := ExtractFilePath(Name);
-
-  if (AktSong.FileName = '') then
-    AktSong.Filename := ExtractFileName(Name);
-  //Read Header
-  Result := ReadTxTHeader(AktSong);
-  if not Result then
-  begin
-    CloseFile(SongFile);
-    Log.LogError('Error Loading SongHeader, abort Song Loading');
-    Exit;
-  end;
-
-  Result := False;
-
-  Reset(SongFile);
-  FileLineNo := 0;
-  //Search for Note Begining
-  repeat
-    ReadLn(SongFile, Tekst);
-    Inc(FileLineNo);
-    
-    if (EoF(SongFile)) then
-    begin //Song File Corrupted - No Notes
-      CloseFile(SongFile);
-      Log.LogError('Could not load txt File, no Notes found: ' + Name);
-      Result := False;
-      Exit;
-    end;
-    Read(SongFile, TempC);
-  until ((TempC = ':') or (TempC = 'F') or (TempC = '*'));
-
-  SetLength(Czesci, 2);
-  for Pet := 0 to High(Czesci) do begin
-    SetLength(Czesci[Pet].Czesc, 1);
-    Czesci[Pet].High := 0;
-    Czesci[Pet].Ilosc := 1;
-    Czesci[Pet].Akt := 0;
-    Czesci[Pet].Resolution := AktSong.Resolution;
-    Czesci[Pet].NotesGAP := AktSong.NotesGAP;
-    Czesci[Pet].Czesc[0].IlNut := 0;
-    Czesci[Pet].Czesc[0].HighNut := -1;
-  end;
-
-//  TempC := ':';
-//  TempC := Tekst[1]; // read from backup variable, don't use default ':' value
-
-  while (TempC <> 'E') AND (not EOF(SongFile)) do begin
-    if (TempC = ':') or (TempC = '*') or (TempC = 'F') then begin
-      // wczytuje nute
-      Read(SongFile, Param1);
-      Read(SongFile, Param2);
-      Read(SongFile, Param3);
-      Read(SongFile, ParamS);
-
-      // dodaje nute
-      if not Both then
-        // P1
-        ParseNote(0, TempC, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamS)
-      else begin
-        // P1 + P2
-        ParseNote(0, TempC, (Param1+Rel[0]) * Mult, Param2 * Mult, Param3, ParamS);
-        ParseNote(1, TempC, (Param1+Rel[1]) * Mult, Param2 * Mult, Param3, ParamS);
-      end;
-    end; // if
-    if TempC = '-' then begin
-      // reads sentence
-      Read(SongFile, Param1);
-      if AktSong.Relative then Read(SongFile, Param2); // read one more data for relative system
-
-      // new sentence
-      if not Both then
-        // P1
-        NewSentence(0, (Param1 + Rel[0]) * Mult, Param2)
-      else begin
-        // P1 + P2
-        NewSentence(0, (Param1 + Rel[0]) * Mult, Param2);
-        NewSentence(1, (Param1 + Rel[1]) * Mult, Param2);
-      end;
-
-    end; // if
-
-    if TempC = 'B' then begin
-      SetLength(AktSong.BPM, Length(AktSong.BPM) + 1);
-      Read(SongFile, AktSong.BPM[High(AktSong.BPM)].StartBeat);
-      AktSong.BPM[High(AktSong.BPM)].StartBeat := AktSong.BPM[High(AktSong.BPM)].StartBeat + Rel[0];
-
-      Read(SongFile, Tekst);
-      AktSong.BPM[High(AktSong.BPM)].BPM := StrToFloat(Tekst);
-      AktSong.BPM[High(AktSong.BPM)].BPM := AktSong.BPM[High(AktSong.BPM)].BPM * Mult * MultBPM;
-    end;
-
-
-    if not Both then begin
-      Czesci[CP].Czesc[Czesci[CP].High].BaseNote := Base[CP];
-      Czesci[CP].Czesc[Czesci[CP].High].LyricWidth := glTextWidth(PChar(Czesci[CP].Czesc[Czesci[CP].High].Lyric));
-      //Total Notes Patch
-      Czesci[CP].Czesc[Czesci[CP].High].TotalNotes := 0;
-      for I := low(Czesci[CP].Czesc[Czesci[CP].High].Nuta) to high(Czesci[CP].Czesc[Czesci[CP].High].Nuta) do
-      begin
-       Czesci[CP].Czesc[Czesci[CP].High].TotalNotes := Czesci[CP].Czesc[Czesci[CP].High].TotalNotes + Czesci[CP].Czesc[Czesci[CP].High].Nuta[I].Dlugosc * Czesci[CP].Czesc[Czesci[CP].High].Nuta[I].Wartosc;
-      end;
-      //Total Notes Patch End
-    end else begin
-      for Pet := 0 to High(Czesci) do begin
-        Czesci[Pet].Czesc[Czesci[Pet].High].BaseNote := Base[Pet];
-        Czesci[Pet].Czesc[Czesci[Pet].High].LyricWidth := glTextWidth(PChar(Czesci[Pet].Czesc[Czesci[Pet].High].Lyric));
-        //Total Notes Patch
-        Czesci[Pet].Czesc[Czesci[Pet].High].TotalNotes := 0;
-        for I := low(Czesci[Pet].Czesc[Czesci[Pet].High].Nuta) to high(Czesci[Pet].Czesc[Czesci[Pet].High].Nuta) do
-        begin
-          Czesci[Pet].Czesc[Czesci[Pet].High].TotalNotes := Czesci[Pet].Czesc[Czesci[Pet].High].TotalNotes + Czesci[Pet].Czesc[Czesci[Pet].High].Nuta[I].Dlugosc * Czesci[Pet].Czesc[Czesci[Pet].High].Nuta[I].Wartosc;
-        end;
-        //Total Notes Patch End
-      end;
-    end;
-
-    Read(SongFile, TempC);
-    Inc(FileLineNo);
-  end; // while}
-
-  CloseFile(SongFile);
-  except
-    try
-      CloseFile(SongFile);
-    except
-
-    end;
-
-    Log.LogError('Error Loading File: "' + Name + '" in Line ' + inttostr(FileLineNo));
-    exit;
-  end;
-
-  Result := true;
-end;
 
 //--------------------
 // Saves a Song
@@ -738,8 +430,8 @@ begin
   WriteLn(SongFile, '#GAP:' + FloatToStr(Song.GAP));
 
   RelativeSubTime := 0;
-  for B := 1 to High(AktSong.BPM) do
-    WriteLn(SongFile, 'B ' + FloatToStr(AktSong.BPM[B].StartBeat) + ' ' + FloatToStr(AktSong.BPM[B].BPM/4));
+  for B := 1 to High(CurrentSong.BPM) do
+    WriteLn(SongFile, 'B ' + FloatToStr(CurrentSong.BPM[B].StartBeat) + ' ' + FloatToStr(CurrentSong.BPM[B].BPM/4));
 
   for C := 0 to Czesc.High do begin
     for N := 0 to Czesc.Czesc[C].HighNut do begin
diff --git a/Game/Code/Classes/UIni.pas b/Game/Code/Classes/UIni.pas
index e4f5e823..599bb8fa 100644
--- a/Game/Code/Classes/UIni.pas
+++ b/Game/Code/Classes/UIni.pas
@@ -463,9 +463,9 @@ begin
     //{
     B := False;
     //Look for Soundcard
-    for I2 := 0 to High(Recording.SoundCard) do
+    for I2 := 0 to High(AudioInputProcessor.SoundCard) do
     begin
-      if (S = Trim(Recording.SoundCard[I2].Description)) then
+      if (S = Trim(AudioInputProcessor.SoundCard[I2].Description)) then
       begin
       B := True;
       Break;
@@ -485,12 +485,12 @@ begin
   end;
 
   // Record - append detected soundcards
-  for I := 0 to High(Recording.SoundCard) do
+  for I := 0 to High(AudioInputProcessor.SoundCard) do
   begin
     B := False;
     For I2 := 0 to High(CardList) do
     begin //Search for Card in List
-      if (CardList[I2].Name = Trim(Recording.SoundCard[I].Description)) then
+      if (CardList[I2].Name = Trim(AudioInputProcessor.SoundCard[I].Description)) then
       begin
         B := True;
         Break;
@@ -502,7 +502,7 @@ begin
     begin
       I3 := Length(CardList);
       SetLength(CardList, I3+1);
-      CardList[I3].Name := Trim(Recording.SoundCard[I].Description);
+      CardList[I3].Name := Trim(AudioInputProcessor.SoundCard[I].Description);
       CardList[I3].Input := 0;
       CardList[I3].ChannelL := 0;
       CardList[I3].ChannelR := 0;
diff --git a/Game/Code/Classes/ULog.pas b/Game/Code/Classes/ULog.pas
index fc567d54..49b02c00 100644
--- a/Game/Code/Classes/ULog.pas
+++ b/Game/Code/Classes/ULog.pas
@@ -212,9 +212,9 @@ begin
 
   FS := TFileStream.Create(FileName, fmCreate);
 
-  for BL := 0 to High(Recording.Sound[SoundNr].BufferLong) do begin
-    Recording.Sound[SoundNr].BufferLong[BL].Seek(0, soBeginning);
-    FS.CopyFrom(Recording.Sound[SoundNr].BufferLong[BL], Recording.Sound[SoundNr].BufferLong[BL].Size);
+  for BL := 0 to High(AudioInputProcessor.Sound[SoundNr].BufferLong) do begin
+    AudioInputProcessor.Sound[SoundNr].BufferLong[BL].Seek(0, soBeginning);
+    FS.CopyFrom(AudioInputProcessor.Sound[SoundNr].BufferLong[BL], AudioInputProcessor.Sound[SoundNr].BufferLong[BL].Size);
   end;
 
   FS.Free;
diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas
index e2e0eaa0..901d7370 100644
--- a/Game/Code/Classes/UMain.pas
+++ b/Game/Code/Classes/UMain.pas
@@ -20,6 +20,7 @@ uses
     ULog,
     ULyrics,
     UScreenSing,
+    USong,
     OpenGL12,
     {$IFDEF UseSerialPort}
     zlportio {you can disable it and all PortWriteB calls},
@@ -107,6 +108,8 @@ var
   Player:       array of TPlayer;
   PlayersPlay:  integer;
 
+  CurrentSong : TSong;
+
 procedure InitializePaths;
 
 Procedure Main;
@@ -130,7 +133,7 @@ uses USongs,
      math,
      UCommandLine, ULanguage, SDL_ttf,
      USkins, UCovers, UCatCovers, UDataBase, UPlaylist, UDLLManager,
-	 UParty, UCore, UGraphicClasses, UPluginDefs, UPlatform;
+  	 UParty, UCore, UGraphicClasses, UPluginDefs, UPlatform;
 
 const
   Version = 'UltraStar Deluxe V 1.10 Alpha Build';
@@ -192,12 +195,14 @@ begin
     Log.BenchmarkEnd(1);
     Log.LogBenchmark('Loading Skin List', 1);
 
+(*
     // Sound Card List
     Log.BenchmarkStart(1);
     Log.LogStatus('Loading Soundcard list', 'Initialization');
     Recording := TRecord.Create;
     Log.BenchmarkEnd(1);
     Log.LogBenchmark('Loading Soundcard list', 1);
+*)
 
     // Sound (+ fills Sound Card List)
     Log.BenchmarkStart(1);
@@ -508,23 +513,23 @@ procedure GetMidBeatSub(BPMNum: integer; var Time: real; var CurBeat: real);
 var
   NewTime:  real;
 begin
-  if High(AktSong.BPM) = BPMNum then begin
+  if High(CurrentSong.BPM) = BPMNum then begin
     // last BPM
-    CurBeat := AktSong.BPM[BPMNum].StartBeat + GetBeats(AktSong.BPM[BPMNum].BPM, Time);
+    CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
     Time := 0;
   end else begin
     // not last BPM
     // count how much time is it for start of the new BPM and store it in NewTime
-    NewTime := GetTimeForBeats(AktSong.BPM[BPMNum].BPM, AktSong.BPM[BPMNum+1].StartBeat - AktSong.BPM[BPMNum].StartBeat);
+    NewTime := GetTimeForBeats(CurrentSong.BPM[BPMNum].BPM, CurrentSong.BPM[BPMNum+1].StartBeat - CurrentSong.BPM[BPMNum].StartBeat);
 
     // compare it to remaining time
     if (Time - NewTime) > 0 then begin
       // there is still remaining time
-      CurBeat := AktSong.BPM[BPMNum].StartBeat;
+      CurBeat := CurrentSong.BPM[BPMNum].StartBeat;
       Time := Time - NewTime;
     end else begin
       // there is no remaining time
-      CurBeat := AktSong.BPM[BPMNum].StartBeat + GetBeats(AktSong.BPM[BPMNum].BPM, Time);
+      CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
       Time := 0;
     end; // if
   end; // if
@@ -539,18 +544,18 @@ var
 //  TempTime: real;
 begin
   Result := 0;
-  if Length(AktSong.BPM) = 1 then Result := Time * AktSong.BPM[0].BPM / 60;
+  if Length(CurrentSong.BPM) = 1 then Result := Time * CurrentSong.BPM[0].BPM / 60;
 
   (* 2 BPMs *)
-{  if Length(AktSong.BPM) > 1 then begin
+{  if Length(CurrentSong.BPM) > 1 then begin
     (* new system *)
     CurBeat := 0;
-    TopBeat := GetBeats(AktSong.BPM[0].BPM, Time);
-    if TopBeat > AktSong.BPM[1].StartBeat then begin
+    TopBeat := GetBeats(CurrentSong.BPM[0].BPM, Time);
+    if TopBeat > CurrentSong.BPM[1].StartBeat then begin
       // analyze second BPM
-      Time := Time - GetTimeForBeats(AktSong.BPM[0].BPM, AktSong.BPM[1].StartBeat - CurBeat);
-      CurBeat := AktSong.BPM[1].StartBeat;
-      TopBeat := GetBeats(AktSong.BPM[1].BPM, Time);
+      Time := Time - GetTimeForBeats(CurrentSong.BPM[0].BPM, CurrentSong.BPM[1].StartBeat - CurBeat);
+      CurBeat := CurrentSong.BPM[1].StartBeat;
+      TopBeat := GetBeats(CurrentSong.BPM[1].BPM, Time);
       Result := CurBeat + TopBeat;
 
     end else begin
@@ -560,7 +565,7 @@ begin
   end; // if}
 
   (* more BPMs *)
-  if Length(AktSong.BPM) > 1 then begin
+  if Length(CurrentSong.BPM) > 1 then begin
 
     CurBeat := 0;
     CurBPM := 0;
@@ -578,21 +583,21 @@ var
   CurBPM:   integer;
 begin
   Result := 0;
-  if Length(AktSong.BPM) = 1 then Result := AktSong.GAP / 1000 + Beat * 60 / AktSong.BPM[0].BPM;
+  if Length(CurrentSong.BPM) = 1 then Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM;
 
   (* more BPMs *)
-  if Length(AktSong.BPM) > 1 then begin
-    Result := AktSong.GAP / 1000;
+  if Length(CurrentSong.BPM) > 1 then begin
+    Result := CurrentSong.GAP / 1000;
     CurBPM := 0;
-    while (CurBPM <= High(AktSong.BPM)) and (Beat > AktSong.BPM[CurBPM].StartBeat) do begin
-      if (CurBPM < High(AktSong.BPM)) and (Beat >= AktSong.BPM[CurBPM+1].StartBeat) then begin
+    while (CurBPM <= High(CurrentSong.BPM)) and (Beat > CurrentSong.BPM[CurBPM].StartBeat) do begin
+      if (CurBPM < High(CurrentSong.BPM)) and (Beat >= CurrentSong.BPM[CurBPM+1].StartBeat) then begin
         // full range
-        Result := Result + (60 / AktSong.BPM[CurBPM].BPM) * (AktSong.BPM[CurBPM+1].StartBeat - AktSong.BPM[CurBPM].StartBeat);
+        Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) * (CurrentSong.BPM[CurBPM+1].StartBeat - CurrentSong.BPM[CurBPM].StartBeat);
       end;
 
-      if (CurBPM = High(AktSong.BPM)) or (Beat < AktSong.BPM[CurBPM+1].StartBeat) then begin
+      if (CurBPM = High(CurrentSong.BPM)) or (Beat < CurrentSong.BPM[CurBPM+1].StartBeat) then begin
         // in the middle
-        Result := Result + (60 / AktSong.BPM[CurBPM].BPM) * (Beat - AktSong.BPM[CurBPM].StartBeat);
+        Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) * (Beat - CurrentSong.BPM[CurBPM].StartBeat);
       end;
       Inc(CurBPM);
     end;
@@ -615,7 +620,7 @@ begin
   Czas.Teraz := Czas.Teraz + TimeSkip;
 
   Czas.OldBeat := Czas.AktBeat;
-  Czas.MidBeat := GetMidBeat(Czas.Teraz - (AktSong.Gap{ + 90 I've forgotten for what it is}) / 1000); // new system with variable BPM in function
+  Czas.MidBeat := GetMidBeat(Czas.Teraz - (CurrentSong.Gap{ + 90 I've forgotten for what it is}) / 1000); // new system with variable BPM in function
   Czas.AktBeat := Floor(Czas.MidBeat);
 
 //  Czas.OldHalf := Czas.AktHalf;
@@ -623,11 +628,11 @@ begin
 //  Czas.AktHalf := Floor(Czas.MidHalf);
 
   Czas.OldBeatC := Czas.AktBeatC;
-  Czas.MidBeatC := GetMidBeat(Czas.Teraz - (AktSong.Gap) / 1000);
+  Czas.MidBeatC := GetMidBeat(Czas.Teraz - (CurrentSong.Gap) / 1000);
   Czas.AktBeatC := Floor(Czas.MidBeatC);
 
   Czas.OldBeatD := Czas.AktBeatD;
-  Czas.MidBeatD := -0.5+GetMidBeat(Czas.Teraz - (AktSong.Gap + 120 + 20) / 1000); // MidBeat with addition GAP
+  Czas.MidBeatD := -0.5+GetMidBeat(Czas.Teraz - (CurrentSong.Gap + 120 + 20) / 1000); // MidBeat with addition GAP
   Czas.AktBeatD := Floor(Czas.MidBeatD);
   Czas.FracBeatD := Frac(Czas.MidBeatD);
 
@@ -822,7 +827,7 @@ begin
 //  beep;
 
   // On linux we get an AV @ NEWNOTE,  line 600 of Classes/UMain.pas
-  if not assigned( Recording.Sound ) then  // TODO : JB_Linux ... why is this now not assigned... it was fine a few hours ago..
+  if not assigned( AudioInputProcessor.Sound ) then  // TODO : JB_Linux ... why is this now not assigned... it was fine a few hours ago..
     exit;
 
   // analizuje dla obu graczy ten sam sygnal (Sound.OneSrcForBoth)
@@ -831,7 +836,7 @@ begin
   begin
 
     // analyze buffer
-    Recording.Sound[CP].AnalizujBufor;
+    AudioInputProcessor.Sound[CP].AnalyzeBuffer;
 
     // adds some noise
 //    Czas.Ton := Czas.Ton + Round(Random(3)) - 1;
@@ -866,7 +871,7 @@ begin
 //    Czas.Ton := 27;
 
     // gdy moze, to dodaje nute
-    if (Recording.Sound[CP].SzczytJest) and (Mozna) then begin
+    if (AudioInputProcessor.Sound[CP].SzczytJest) and (Mozna) then begin
       // operowanie na ostatniej nucie
       for Pet := 0 to Czesci[0].Czesc[S].HighNut do
         if (Czesci[0].Czesc[S].Nuta[Pet].Start <= Czas.OldBeatD+1)
@@ -875,10 +880,11 @@ begin
           // to robi, tylko dla pary nut (oryginalnej i gracza)
 
           // przesuwanie tonu w odpowiednia game
-          while (Recording.Sound[CP].Ton - Czesci[0].Czesc[S].Nuta[Pet].Ton > 6) do
-            Recording.Sound[CP].Ton := Recording.Sound[CP].Ton - 12;
-          while (Recording.Sound[CP].Ton - Czesci[0].Czesc[S].Nuta[Pet].Ton < -6) do
-            Recording.Sound[CP].Ton := Recording.Sound[CP].Ton + 12;
+          while (AudioInputProcessor.Sound[CP].Ton - Czesci[0].Czesc[S].Nuta[Pet].Ton > 6) do
+            AudioInputProcessor.Sound[CP].Ton := AudioInputProcessor.Sound[CP].Ton - 12;
+
+          while (AudioInputProcessor.Sound[CP].Ton - Czesci[0].Czesc[S].Nuta[Pet].Ton < -6) do
+            AudioInputProcessor.Sound[CP].Ton := AudioInputProcessor.Sound[CP].Ton + 12;
 
           // Half size Notes Patch
           NoteHit := false;
@@ -887,8 +893,9 @@ begin
           //if Ini.Difficulty = 1 then Range := 1;
           //if Ini.Difficulty = 2 then Range := 0;
           Range := 2 - Ini.Difficulty;
-          if abs(Czesci[0].Czesc[S].Nuta[Pet].Ton - Recording.Sound[CP].Ton) <= Range then begin
-            Recording.Sound[CP].Ton := Czesci[0].Czesc[S].Nuta[Pet].Ton;
+
+          if abs(Czesci[0].Czesc[S].Nuta[Pet].Ton - AudioInputProcessor.Sound[CP].Ton) <= Range then begin
+            AudioInputProcessor.Sound[CP].Ton := Czesci[0].Czesc[S].Nuta[Pet].Ton;
 
 
             // Half size Notes Patch
@@ -929,7 +936,7 @@ begin
       Nowa := true;
       // jezeli ostatnia ma ten sam ton
       if (Player[CP].IlNut > 0 )
-        and (Player[CP].Nuta[Player[CP].HighNut].Ton = Recording.Sound[CP].Ton)
+        and (Player[CP].Nuta[Player[CP].HighNut].Ton = AudioInputProcessor.Sound[CP].Ton)
         and (Player[CP].Nuta[Player[CP].HighNut].Start + Player[CP].Nuta[Player[CP].HighNut].Dlugosc = Czas.AktBeatD)
         then Nowa := false;
       // jezeli jest jakas nowa nuta na sprawdzanym beacie
@@ -943,10 +950,10 @@ begin
         Player[CP].IlNut := Player[CP].IlNut + 1;
         Player[CP].HighNut := Player[CP].HighNut + 1;
         SetLength(Player[CP].Nuta, Player[CP].IlNut);
-        Player[CP].Nuta[Player[CP].HighNut].Start := Czas.AktBeatD;
+        Player[CP].Nuta[Player[CP].HighNut].Start   := Czas.AktBeatD;
         Player[CP].Nuta[Player[CP].HighNut].Dlugosc := 1;
-        Player[CP].Nuta[Player[CP].HighNut].Ton := Recording.Sound[CP].Ton; // Ton || TonDokl
-        Player[CP].Nuta[Player[CP].HighNut].Detekt := Czas.MidBeat;
+        Player[CP].Nuta[Player[CP].HighNut].Ton     := AudioInputProcessor.Sound[CP].Ton; // Ton || TonDokl
+        Player[CP].Nuta[Player[CP].HighNut].Detekt  := Czas.MidBeat;
 
 
         // Half Note Patch
@@ -977,7 +984,8 @@ begin
 
 //On Sentence End -> For LineBonus + SingBar
 if (sDet >= low(Czesci[0].Czesc)) AND (sDet <= high(Czesci[0].Czesc)) then
-if ((Czesci[0].Czesc[SDet].Nuta[Czesci[0].Czesc[SDet].HighNut].Start + Czesci[0].Czesc[SDet].Nuta[Czesci[0].Czesc[SDet].HighNut].Dlugosc - 1) = Czas.AktBeatD) then
+if assigned( Sender ) AND
+   ((Czesci[0].Czesc[SDet].Nuta[Czesci[0].Czesc[SDet].HighNut].Start + Czesci[0].Czesc[SDet].Nuta[Czesci[0].Czesc[SDet].HighNut].Dlugosc - 1) = Czas.AktBeatD) then
   Sender.onSentenceEnd(sDet);
 
 end;
diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas
index bf366130..a7f1918f 100644
--- a/Game/Code/Classes/UMusic.pas
+++ b/Game/Code/Classes/UMusic.pas
@@ -413,6 +413,7 @@ end;
 initialization
 begin
   singleton_AudioManager := TInterfaceList.Create();
+  
 end;
 
 finalization
diff --git a/Game/Code/Classes/UPlatform.pas b/Game/Code/Classes/UPlatform.pas
index 19a960e7..bfb03d54 100644
--- a/Game/Code/Classes/UPlatform.pas
+++ b/Game/Code/Classes/UPlatform.pas
@@ -16,7 +16,6 @@ interface
 uses Classes;
 
 type
-  
   TDirectoryEntry = Record
                       Name        : WideString;
                       IsDirectory : Boolean;
@@ -27,33 +26,16 @@ type
 	
   IPlatform = Interface
   ['{63A5EBC3-3F4D-4F23-8DFB-B5165FCA23DF}']
-    Function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray;
-    function TerminateIfAlreadyRunning(var WndTitle : String) : Boolean;
-	
-    function GetLogPath        : WideString;
-    function GetGameSharedPath : WideString;
-    function GetGameUserPath   : WideString;
-  end;
- 
-  TPlatform = class( TInterfacedOBject, IPlatform )
-
-	  // DirectoryFindFiles returns all files matching the filter. Do not use '*' in the filter.
-	  // If you set ReturnAllSubDirs = true all directories will be returned, if yout set it to false
-	  // directories are completely ignored.
-    function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; virtual; abstract;
-    
-    function TerminateIfAlreadyRunning(var WndTitle : String) : Boolean; virtual;
-
-//    function GetGamePath       : WideString; virtual;
-    function GetLogPath        : WideString; virtual;
-    function GetGameSharedPath : WideString; virtual;
-    function GetGameUserPath   : WideString; virtual;
-
+    Function  DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray;
+    function  TerminateIfAlreadyRunning(var WndTitle : String) : Boolean;
+    function  FindSongFile(Dir, Mask: widestring): widestring;
+    procedure halt;
+    function  GetLogPath        : WideString;
+    function  GetGameSharedPath : WideString;
+    function  GetGameUserPath   : WideString;
   end;
 
-
-var
-  Platform : IPlatform;
+  function Platform : IPlatform;
 
 implementation
 
@@ -69,48 +51,30 @@ uses
   UPlatformMacOSX;
   {$ENDIF}
 
-{ TPlatform }
 
-(*
-function TPlatform.GetGamePath: WideString;
-begin
-  // Windows and Linux use this:
-  Result := ExtractFilePath(ParamStr(0));
-end;
-*)
-function TPlatform.GetLogPath        : WideString;
-begin
-  result := ExtractFilePath(ParamStr(0));
-end;
-
-function TPlatform.GetGameSharedPath : WideString;
-begin
-  result := ExtractFilePath(ParamStr(0));
-end;
+// I have modified it to use the Platform_singleton in this location ( in the implementaiton )
+// so that this variable can NOT be overwritten from anywhere else in the application.
+// the accessor function platform, emulates all previous calls to work the same way.  
+var
+  Platform_singleton : IPlatform;
 
-function TPlatform.GetGameUserPath   : WideString;
+function Platform : IPlatform;
 begin
-  result := ExtractFilePath(ParamStr(0));
+  result := Platform_singleton;
 end;
 
-function TPlatform.TerminateIfAlreadyRunning(var WndTitle : String) : Boolean;
-begin
-  // Linux and Mac don't check for running apps at the moment
-  Result := false;
-end;
 
 initialization
-
   {$IFDEF MSWINDOWS}
-    Platform := TPlatformWindows.Create;
+    Platform_singleton := TPlatformWindows.Create;
   {$ENDIF}
   {$IFDEF LINUX}
-    Platform := TPlatformLinux.Create;
+    Platform_singleton := TPlatformLinux.Create;
   {$ENDIF}
   {$IFDEF DARWIN}
-    Platform := TPlatformMacOSX.Create;
+    Platform_singleton := TPlatformMacOSX.Create;
   {$ENDIF}
 
 finalization
-    Platform := nil;
+    Platform_singleton := nil;
 end.
diff --git a/Game/Code/Classes/UPlatformLinux.pas b/Game/Code/Classes/UPlatformLinux.pas
index 0098baee..cde737b6 100644
--- a/Game/Code/Classes/UPlatformLinux.pas
+++ b/Game/Code/Classes/UPlatformLinux.pas
@@ -12,7 +12,7 @@ uses Classes, UPlatform;
 
 type
 
-  TPlatformLinux = class(TPlatform)
+  TPlatformLinux = class(TInterfacedObject, IPlatform)
     function get_homedir(): string;
   public
     Function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; override;
diff --git a/Game/Code/Classes/UPlatformMacOSX.pas b/Game/Code/Classes/UPlatformMacOSX.pas
index a418919c..97c32fe3 100644
--- a/Game/Code/Classes/UPlatformMacOSX.pas
+++ b/Game/Code/Classes/UPlatformMacOSX.pas
@@ -12,13 +12,20 @@ uses Classes, UPlatform;
 
 type
 
-  TPlatformMacOSX = class(TPlatform)
+  TPlatformMacOSX = class( TInterfacedObject, IPlatform)
   private
   public
+<<<<<<< .mine
+    Function  DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; override;
+    function  GetGamePath: WideString; override;
+    function  TerminateIfAlreadyRunning(var WndTitle : String) : Boolean;
+    procedure halt();
+=======
     function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; override;
     function GetLogPath        : WideString; override;
     function GetGameSharedPath : WideString; override;
     function GetGameUserPath   : WideString; override;
+>>>>>>> .r788
   end;
 
 implementation
@@ -100,4 +107,15 @@ begin
 	FPCloseDir(TheDir);
 end;
 
+function TPlatformMacOSX.TerminateIfAlreadyRunning(var WndTitle : String) : Boolean;
+begin
+  result := false;
+end;
+
+
+procedure TPlatformMacOSX.halt;
+begin
+  halt;
+end;
+
 end.
diff --git a/Game/Code/Classes/UPlatformWindows.pas b/Game/Code/Classes/UPlatformWindows.pas
index 93e72e7a..d4ba757a 100644
--- a/Game/Code/Classes/UPlatformWindows.pas
+++ b/Game/Code/Classes/UPlatformWindows.pas
@@ -8,19 +8,30 @@ interface
 
 {$I switches.inc}
 
-uses Classes, UPlatform;
+uses Classes,
+     UPlatform;
 
 type
 
-  TPlatformWindows = class(TPlatform)
+  TPlatformWindows = class( TInterfacedObject, IPlatform)
   public
-    Function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; override;
-    function TerminateIfAlreadyRunning(var WndTitle : String) : Boolean; override;
+    Function  DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray;
+    function  TerminateIfAlreadyRunning(var WndTitle : String) : Boolean;
+    function  GetGamePath: WideString;
+    function  FindSongFile(Dir, Mask: widestring): widestring;
+
+    procedure halt;
+
+    function GetLogPath        : WideString;
+    function GetGameSharedPath : WideString;
+    function GetGameUserPath   : WideString;
   end;
 
 implementation
 
-uses SysUtils, Windows;
+uses SysUtils,
+     Windows,
+     Forms;  
 
 type
 
@@ -175,4 +186,42 @@ begin
   FindCloseW(SR);
 end;
 
+function TPlatformWindows.GetGamePath: WideString;
+begin
+  // Windows and Linux use this:
+  Result := ExtractFilePath(ParamStr(0));
+end;
+
+procedure TPlatformWindows.halt;
+begin
+  application.terminate;
+end;
+
+function TPlatformWindows.GetLogPath        : WideString;
+begin
+  result := ExtractFilePath(ParamStr(0));
+end;
+
+function TPlatformWindows.GetGameSharedPath : WideString;
+begin
+  result := ExtractFilePath(ParamStr(0));
+end;
+
+function TPlatformWindows.GetGameUserPath   : WideString;
+begin
+  result := ExtractFilePath(ParamStr(0));
+end;
+
+
function TPlatformWindows.FindSongFile(Dir, Mask: widestring): widestring;
+
var
+
  SR:     TSearchRec;   // for parsing song directory
+begin
+  Result := '';
+  if SysUtils.FindFirst(Dir + Mask, faDirectory, SR) = 0 then begin
+    Result := SR.Name;
+  end; // if
+  SysUtils.FindClose(SR);
+end;
+
+
 end.
diff --git a/Game/Code/Classes/URecord.pas b/Game/Code/Classes/URecord.pas
index dee1a687..ab351f6e 100644
--- a/Game/Code/Classes/URecord.pas
+++ b/Game/Code/Classes/URecord.pas
@@ -14,7 +14,9 @@ uses Classes,
      UCommon,
      UMusic,
      UIni;
-     
+
+//  http://www.poltran.com
+
 type
   TSound = class
     BufferNew:    TMemoryStream; // buffer for newest sample
@@ -26,7 +28,7 @@ type
 
     // pitch detection
     SzczytJest:   boolean;       // czy jest szczyt
-    Szczyt:       integer;    // pozycja szczytu na osi poziomej
+    pivot :       integer;    // Position of summit (top) on horizontal pivot 
     TonDokl:      real;       // ton aktualnego szczytu
     Ton:          integer;    // ton bez ulamka
     TonGamy:      integer;    // ton w gamie. wartosci: 0-11
@@ -34,8 +36,8 @@ type
 
     // procedures
     procedure ProcessNewBuffer;
-    procedure AnalizujBufor;    // use to analyze sound from buffers to get new pitch
-    procedure AnalizujByAutocorrelation;    // we call it to analyze sound by checking Autocorrelation
+    procedure AnalyzeBuffer;    // use to analyze sound from buffers to get new pitch
+    procedure AnalyzeByAutocorrelation;    // we call it to analyze sound by checking Autocorrelation
     function  AnalyzeAutocorrelationFreq(Freq: real): real;   // use this to check one frequency by Autocorrelation
   end;
 
@@ -54,31 +56,46 @@ type
     CaptureSoundRight: TSound; // sound(-buffer) used for right channel capture data
   end;
 
-  TRecord = class
+  TAudioInputProcessor = class
     Sound:      array of TSound;
     SoundCard:  array of TGenericSoundCard;
+
     constructor Create;
-    
+
     // handle microphone input
     procedure HandleMicrophoneData(Buffer: Pointer; Length: Cardinal;
-        InputDevice: TGenericSoundCard);
+                                   InputDevice: TGenericSoundCard);
+
+    function volume( aChannel : byte ): byte;
   end;
 
   smallintarray = array [0..maxInt shr 1-1] of smallInt;
   psmallintarray = ^smallintarray;
 
-var
-  Poz:        integer;
-  Recording:  TRecord;
+  function AudioInputProcessor(): TAudioInputProcessor;
 
 implementation
 
 uses UMain;
 
+var
+  singleton_AudioInputProcessor : TAudioInputProcessor = nil;
+
+
 // FIXME: Race-Conditions between Callback-thread and main-thread
 //        on BufferArray (maybe BufferNew also).
 //        Use SDL-mutexes to solve this problem.
 
+
+function AudioInputProcessor(): TAudioInputProcessor;
+begin
+  if singleton_AudioInputProcessor = nil then
+    singleton_AudioInputProcessor := TAudioInputProcessor.create();
+
+  result := singleton_AudioInputProcessor;
+ 
+end;
+
 procedure TSound.ProcessNewBuffer;
 var
   S:    integer;
@@ -108,12 +125,12 @@ begin
   end;
 end;
 
-procedure TSound.AnalizujBufor;
+procedure TSound.AnalyzeBuffer;
 begin
-  AnalizujByAutocorrelation;
+  AnalyzeByAutocorrelation;
 end;
 
-procedure TSound.AnalizujByAutocorrelation;
+procedure TSound.AnalyzeByAutocorrelation;
 var
   T:        integer;  // tone
   F:        real; // freq
@@ -143,7 +160,7 @@ begin
   // analyze all 12 halftones
   for T := 0 to 35 do // to 11, then 23, now 35 (for Whitney and my high voice)
   begin
-    F := 130.81*Power(1.05946309436, T)/2; // let's analyze below 130.81
+    F := 130.81 * Power(1.05946309436, T)/2; // let's analyze below 130.81
     Wages[T] := AnalyzeAutocorrelationFreq(F);
 
     if Wages[T] > MaxW then
@@ -164,8 +181,8 @@ begin
   if MaxV >= Threshold then
   begin // found acceptable volume // 0.1
     SzczytJest := true;
-    TonGamy := MaxT mod 12;
-    Ton := MaxT mod 12;
+    TonGamy    := MaxT mod 12;
+    Ton        := MaxT mod 12;
   end;
 
 end;
@@ -206,8 +223,7 @@ end;
  *   Length - number of bytes in Buffer
  *   Input - Soundcard-Input used for capture
  *}
-procedure TRecord.HandleMicrophoneData(Buffer: Pointer; Length: Cardinal;
-    InputDevice: TGenericSoundCard);
+procedure TAudioInputProcessor.HandleMicrophoneData(Buffer: Pointer; Length: Cardinal; InputDevice: TGenericSoundCard);
 var
   L:    integer;
   S:    integer;
@@ -231,8 +247,14 @@ begin
   for S := 0 to L-1 do
   begin
     I := PSI^[S] * Boost;
-    if I > 32767 then I := 32767; // 0.5.0: limit
-    if I < -32768 then I := -32768; // 0.5.0: limit
+
+    // TODO :  JB -  This will clip the audio... cant we reduce the "Boot" if the data clips ??
+    if I > 32767 then
+      I := 32767; // 0.5.0: limit
+
+    if I < -32768 then
+      I := -32768; // 0.5.0: limit
+
     PSI^[S] := I;
   end;
 
@@ -266,12 +288,13 @@ begin
   end;
 end;
 
-constructor TRecord.Create;
+constructor TAudioInputProcessor.Create;
 var
   S:        integer;
 begin
   SetLength(Sound, 6 {max players});//Ini.Players+1);
-  for S := 0 to High(Sound) do begin //Ini.Players do begin
+  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;
@@ -281,6 +304,20 @@ begin
   end;
 end;
 
+function TAudioInputProcessor.volume( aChannel : byte ): byte;
+var
+  lCount  : Integer;
+  lMaxVol : double;
+begin;
+  lMaxVol :=  AudioInputProcessor.Sound[aChannel].BufferArray[1];
+  for lCount := 2 to AudioInputProcessor.Sound[aChannel].n div 1 do
+  begin
+    if AudioInputProcessor.Sound[aChannel].BufferArray[lCount] > lMaxVol then
+      lMaxVol := AudioInputProcessor.Sound[aChannel].BufferArray[lCount];
+  end;
+
+  result := trunc( ( 255 / 32767 ) * trunc( lMaxVol ) );
+end;
 
 end.
 
diff --git a/Game/Code/Classes/USongs.pas b/Game/Code/Classes/USongs.pas
index a4709b43..c5acec9c 100644
--- a/Game/Code/Classes/USongs.pas
+++ b/Game/Code/Classes/USongs.pas
@@ -40,6 +40,7 @@ uses
 	 {$IFDEF USE_PSEUDO_THREAD}
 	 PseudoThread,
 	 {$ENDIF}
+   USong,
      UCatCovers;
 
 type
@@ -55,48 +56,6 @@ type
     Length:     string;
   end;
 
-  TSong = record
-    Path:       widestring;
-    Folder:     widestring; // for sorting by folder
-    FileName:   widestring;
-
-    // sorting methods
-    Category:   array of widestring; // I think I won't need this
-    Genre:      widestring;
-    Edition:    widestring;
-    Language:   widestring; // 0.5.0: new
-
-    Title:      widestring;
-    Artist:     widestring;
-
-    Text:       widestring;
-    Creator:    widestring;
-
-    Cover:      widestring;
-    CoverTex:   TTexture;
-    Mp3:        widestring;
-    Background: widestring;
-    Video:      widestring;
-    VideoGAP:   real;
-    VideoLoaded: boolean; // 0.5.0: true if the video has been loaded
-    NotesGAP:   integer;
-    Start:      real; // in seconds
-    Finish:     integer; // in miliseconds
-    Relative:   boolean;
-    Resolution: integer;
-    BPM:        array of TBPM;
-    GAP:        real; // in miliseconds
-
-    Score:      array[0..2] of array of TScore;
-
-    // these are used when sorting is enabled
-    Visible:    boolean; // false if hidden, true if visible
-    Main:       boolean; // false for songs, true for category buttons
-    OrderNum:   integer; // has a number of category for category buttons and songs
-    OrderTyp:   integer; // type of sorting for this button (0=name)
-    CatNumber:  integer; // Count of Songs in Category for Cats and Number of Song in Category for Songs
-  end;
-	
 	
 	{$IFDEF USE_PSEUDO_THREAD}
 	TSongs = class( TPseudoThread )
@@ -104,7 +63,6 @@ type
   TSongs = class( TThread )
 	{$ENDIF}
   private
-    BrowsePos : Integer; //Actual Pos in Song Array. eddie: Must be int, because it could be decremented to -1.
     fNotify   ,
     fWatch    : longint;
     fParseSongDirectory : boolean;
@@ -117,9 +75,13 @@ type
   protected
     procedure Execute; override;
   public
-    Song      : array of TSong; // array of songs
+//    Song      : array of TSong; // array of songs
+    SongList  : TList; // array of songs
     Selected  : integer;        // selected song index
     constructor create();
+    destructor  destroy();
+
+
     procedure LoadSongList;     // load all songs
     procedure BrowseDir(Dir: widestring); // should return number of songs in the future
     procedure Sort(Order: integer);
@@ -127,6 +89,7 @@ type
     property  Processing : boolean read fProcessing;
   end;
 
+
   TCatSongs = class
     Song:       array of TSong; // array of categories with songs
     Selected:   integer; // selected song index
@@ -150,7 +113,6 @@ type
 var
   Songs:      TSongs; // all songs
   CatSongs:   TCatSongs; // categorized songs
-  AktSong:    TSong; // one song *unknown use)
 
 const
      IN_ACCESS		    = $00000001;	//* File was accessed */
@@ -187,6 +149,8 @@ begin
   inherited create( false );
   self.freeonterminate := true;
 
+  SongList := TList.create();
+
   {$ifdef Delphi}
     fDirWatch := TDirectoryWatch.create(nil);
     fDirWatch.OnChange     := DoDirChanged;
@@ -218,12 +182,18 @@ begin
   writeln( 'Calling syscall_nr_inotify_init : '+ inttostr(fWatch)  );
 *)
   {$endif}
-  
-{$IFNDEF USE_PSEUDO_THREAD}  
-	Setlength(Song, 0);
+
+{$IFNDEF USE_PSEUDO_THREAD}
+//	Setlength(Song, 0);
+  SongList.clear;
 {$ENDIF}
 end;
 
+destructor TSongs.destroy();
+begin
+  freeandnil( SongList );
+end;
+
 procedure TSongs.DoDirChanged(Sender: TObject);
 begin
   LoadSongList();
@@ -237,7 +207,7 @@ begin
   int_LoadSongList();
 {$ELSE}
   fParseSongDirectory := true;
-  
+
   while not self.terminated do
   begin
 
@@ -256,21 +226,15 @@ procedure TSongs.int_LoadSongList;
 begin
   try
     fProcessing := true;
-    Setlength(Song, 0);
 
+    SongList.clear;
     Log.LogError('SongList', 'Searching For Songs');
 
-    Setlength(Song, 50);
-
-    BrowsePos := 0;
     // browse directories
     BrowseDir(SongPath);
-    
+
     if UserSongPath <> SongPath then
       BrowseDir(UserSongPath);
-      
-    //Set Correct SongArray Length
-    SetLength(Song, BrowsePos);
 
     if assigned( CatSongs ) then
       CatSongs.Refresh;
@@ -287,7 +251,6 @@ begin
       ScreenSong.OnShow; // refresh ScreenSong
     end;
 
-
   finally
     Log.LogError('SongList', 'Search Complete');
     
@@ -305,12 +268,13 @@ end;
 
 procedure TSongs.BrowseDir(Dir: widestring);
 var
-  SLen:   integer;
-  i : Integer;
+  i     : Integer;
   Files : TDirectoryEntryArray;
+  lSong : TSong;
 begin
 
 	  Files := Platform.DirectoryFindFiles( Dir, '.txt', true);
+    
 		for i := 0 to Length(Files)-1 do
 		begin
 		  if Files[i].IsDirectory then
@@ -319,37 +283,21 @@ begin
 			end
 			else
 			begin
-				SLen := BrowsePos;
+        lSong := TSong.create( Dir + Files[i].Name );
 
-				Song[SLen].Path     := Dir;
-//				Song[SLen].Folder   := Copy(Dir, Length(SongPath)+1, 10000);
-				Song[SLen].Folder   := Copy(Dir, Length(Dir)+1, 10000);
-				Song[SLen].Folder   := Copy(Song[SLen].Folder, 1, Pos( PathDelim , Song[SLen].Folder)-1);
-				Song[SLen].FileName := Files[i].Name;
-
-				if (AnalyseFile(Song[SLen]) = false) then
+        if NOT lSong.Analyse then
 				begin
 					Log.LogError('AnalyseFile failed for "' + Files[i].Name + '".');
-					Dec(BrowsePos);
+          freeandnil( lSong );
 				end
 				else
 				begin
-					if Song[SLen].Cover = '' then
-						Song[SLen].Cover := FindSongFile(Dir, '*[CO].jpg');
+          SongList.add( lSong );
 				end;
 
-				//Change Length Only every 50 Entrys
-				Inc(BrowsePos);
-
-				if (BrowsePos mod 50 = 0) AND (BrowsePos <> 0) then
-				begin
-						SetLength(Song, Length(Song) + 50);
-				end;
 			end;
 		end;
 		SetLength( Files, 0);
-
-//  Log.LogStatus('Parsing directory: ' + Dir + SR.Name, 'LoadSongList');
 end;
 
 procedure TSongs.Sort(Order: integer);
@@ -361,91 +309,99 @@ begin
   case Order of
     sEdition: // by edition
       begin
-        for S2 := 0 to Length(Song)-1 do
-          for S := 1 to Length(Song)-1 do
-            if CompareText(Song[S].Edition, Song[S-1].Edition) < 0 then begin
+        for S2 := 0 to SongList.Count -1 do
+          for S := 1 to SongList.Count-1 do
+            if CompareText(TSong( SongList[S] ).Edition, TSong( SongList[S-1] ).Edition) < 0 then
+            begin
               // zamiana miejscami
-              TempSong := Song[S-1];
-              Song[S-1] := Song[S];
-              Song[S] := TempSong;
+              TempSong      := SongList[S-1];
+              SongList[S-1] := SongList[S];
+              SongList[S]   := TempSong;
             end;
       end;
     sGenre: // by genre
       begin
-        for S2 := 0 to Length(Song)-1 do
-          for S := 1 to Length(Song)-1 do
-            if CompareText(Song[S].Genre, Song[S-1].Genre) < 0 then begin
+        for S2 := 0 to SongList.Count-1 do
+          for S := 1 to SongList.Count-1 do
+            if CompareText(TSong( SongList[S] ).Genre, TSong( SongList[S-1] ).Genre) < 0 then
+            begin
               // zamiana miejscami
-              TempSong := Song[S-1];
-              Song[S-1] := Song[S];
-              Song[S] := TempSong;
+              TempSong      := SongList[S-1];
+              SongList[S-1] := SongList[S];
+              SongList[S]   := TempSong;
             end;
       end;
     sTitle: // by title
       begin
-        for S2 := 0 to Length(Song)-1 do
-          for S := 1 to Length(Song)-1 do
-            if CompareText(Song[S].Title, Song[S-1].Title) < 0 then begin
+        for S2 := 0 to SongList.Count-1 do
+          for S := 1 to SongList.Count-1 do
+            if CompareText(TSong( SongList[S] ).Title, TSong( SongList[S-1] ).Title) < 0 then
+            begin
               // zamiana miejscami
-              TempSong := Song[S-1];
-              Song[S-1] := Song[S];
-              Song[S] := TempSong;
+              TempSong      := SongList[S-1];
+              SongList[S-1] := SongList[S];
+              SongList[S]   := TempSong;
             end;
 
       end;
     sArtist: // by artist
       begin
-        for S2 := 0 to Length(Song)-1 do
-          for S := 1 to Length(Song)-1 do
-            if CompareText(Song[S].Artist, Song[S-1].Artist) < 0 then begin
+        for S2 := 0 to SongList.Count-1 do
+          for S := 1 to SongList.Count-1 do
+            if CompareText(TSong( SongList[S] ).Artist, TSong( SongList[S-1] ).Artist) < 0 then
+            begin
               // zamiana miejscami
-              TempSong := Song[S-1];
-              Song[S-1] := Song[S];
-              Song[S] := TempSong;
+              TempSong      := SongList[S-1];
+              SongList[S-1] := SongList[S];
+              SongList[S]   := TempSong;
             end;
       end;
     sFolder: // by folder
       begin
-        for S2 := 0 to Length(Song)-1 do
-          for S := 1 to Length(Song)-1 do
-            if CompareText(Song[S].Folder, Song[S-1].Folder) < 0 then begin
+        for S2 := 0 to SongList.Count-1 do
+          for S := 1 to SongList.Count-1 do
+            if CompareText(TSong( SongList[S] ).Folder, TSong( SongList[S-1] ).Folder) < 0 then
+            begin
               // zamiana miejscami
-              TempSong := Song[S-1];
-              Song[S-1] := Song[S];
-              Song[S] := TempSong;
+              TempSong      := SongList[S-1];
+              SongList[S-1] := SongList[S];
+              SongList[S]   := TempSong;
             end;
       end;
     sTitle2: // by title2
       begin
-        for S2 := 0 to Length(Song)-1 do
-          for S := 1 to Length(Song)-1 do
-            if CompareText(Song[S].Title, Song[S-1].Title) < 0 then begin
+        for S2 := 0 to SongList.Count-1 do
+          for S := 1 to SongList.Count-1 do
+            if CompareText(TSong( SongList[S] ).Title, TSong( SongList[S-1] ).Title) < 0 then
+            begin
               // zamiana miejscami
-              TempSong := Song[S-1];
-              Song[S-1] := Song[S];
-              Song[S] := TempSong;
+              TempSong      := SongList[S-1];
+              SongList[S-1] := SongList[S];
+              SongList[S]   := TempSong;
             end;
 
       end;
     sArtist2: // by artist2
       begin
-        for S2 := 0 to Length(Song)-1 do
-          for S := 1 to Length(Song)-1 do
-            if CompareText(Song[S].Artist, Song[S-1].Artist) < 0 then begin
+        for S2 := 0 to SongList.Count-1 do
+          for S := 1 to SongList.Count-1 do
+            if CompareText(TSong( SongList[S] ).Artist, TSong( SongList[S-1] ).Artist) < 0 then
+            begin
               // zamiana miejscami
-              TempSong := Song[S-1];
-              Song[S-1] := Song[S];
-              Song[S] := TempSong;
+              TempSong      := SongList[S-1];
+              SongList[S-1] := SongList[S];
+              SongList[S]   := TempSong;
             end;
       end;
     sLanguage: // by Language
       begin
-        for S2 := 0 to Length(Song)-1 do
-          for S := 1 to Length(Song)-1 do
-            if CompareText(Song[S].Language, Song[S-1].Language) < 0 then begin
-              TempSong := Song[S-1];
-              Song[S-1] := Song[S];
-              Song[S] := TempSong;
+        for S2 := 0 to SongList.Count-1 do
+          for S := 1 to SongList.Count-1 do
+            if CompareText(TSong( SongList[S] ).Language, TSong( SongList[S-1] ).Language) < 0 then
+            begin
+              TempSong      := SongList[S-1];
+              SongList[S-1] := SongList[S];
+              SongList[S]   := TempSong;
             end;
       end;
 
@@ -509,12 +465,13 @@ case Ini.Sorting of
   //Songs leeren
   SetLength (Song, 0);
 
-  for S := Low(Songs.Song) to High(Songs.Song) do begin
+  for S := 0 to Songs.SongList.Count-1 do
+  begin
     if (Ini.Tabs = 1) then
-    if (Ini.Sorting = sEdition) and (CompareText(SS, Songs.Song[S].Edition) <> 0) then begin
+    if (Ini.Sorting = sEdition) and (CompareText(SS, TSong( Songs.SongList[S] ).Edition) <> 0) then begin
       // add Category Button
       Inc(Order);
-      SS := Songs.Song[S].Edition;
+      SS := TSong( Songs.SongList[S] ).Edition;
       CatLen := Length(CatSongs.Song);
       SetLength(CatSongs.Song, CatLen+1);
       CatSongs.Song[CatLen].Artist := '[' + SS + ']';
@@ -554,10 +511,10 @@ case Ini.Sorting of
       CatSongs.Song[CatLen].Visible := true;
     end
 
-    else if (Ini.Sorting = sGenre) and (CompareText(SS, Songs.Song[S].Genre) <> 0) then begin
+    else if (Ini.Sorting = sGenre) and (CompareText(SS, TSong( Songs.SongList[S] ).Genre) <> 0) then begin
       // add Genre Button
       Inc(Order);
-      SS := Songs.Song[S].Genre;
+      SS := TSong( Songs.SongList[S] ).Genre;
       CatLen := Length(CatSongs.Song);
       SetLength(CatSongs.Song, CatLen+1);
       CatSongs.Song[CatLen].Artist := SS;
@@ -580,10 +537,10 @@ case Ini.Sorting of
       CatSongs.Song[CatLen].Visible := true;
     end
 
-    else if (Ini.Sorting = sLanguage) and (CompareText(SS, Songs.Song[S].Language) <> 0) then begin
+    else if (Ini.Sorting = sLanguage) and (CompareText(SS, TSong( Songs.SongList[S] ).Language) <> 0) then begin
       // add Language Button
       Inc(Order);
-      SS := Songs.Song[S].Language;
+      SS := TSong( Songs.SongList[S] ).Language;
       CatLen := Length(CatSongs.Song);
       SetLength(CatSongs.Song, CatLen+1);
       CatSongs.Song[CatLen].Artist := SS;
@@ -607,11 +564,11 @@ case Ini.Sorting of
     end
 
     else if (Ini.Sorting = sTitle) and
-            (Length(Songs.Song[S].Title)>=1) and
-            (Letter <> UpperCase(Songs.Song[S].Title)[1]) then begin
+            (Length(TSong( Songs.SongList[S] ).Title)>=1) and
+            (Letter <> UpperCase(TSong( Songs.SongList[S] ).Title)[1]) then begin
       // add a letter Category Button
       Inc(Order);
-      Letter := Uppercase(Songs.Song[S].Title)[1];
+      Letter := Uppercase(TSong( Songs.SongList[S] ).Title)[1];
       CatLen := Length(CatSongs.Song);
       SetLength(CatSongs.Song, CatLen+1);
       CatSongs.Song[CatLen].Artist := '[' + Letter + ']';
@@ -636,10 +593,11 @@ case Ini.Sorting of
       CatSongs.Song[CatLen].Visible := true;
     end
 
-    else if (Ini.Sorting = sArtist) and (Length(Songs.Song[S].Artist)>=1) and (Letter <> UpperCase(Songs.Song[S].Artist)[1]) then begin
+    else if (Ini.Sorting = sArtist) and (Length(TSong( Songs.SongList[S] ).Artist)>=1) and
+            (Letter <> UpperCase(TSong( Songs.SongList[S] ).Artist)[1]) then begin
       // add a letter Category Button
       Inc(Order);
-      Letter := UpperCase(Songs.Song[S].Artist)[1];
+      Letter := UpperCase(TSong( Songs.SongList[S] ).Artist)[1];
       CatLen := Length(CatSongs.Song);
       SetLength(CatSongs.Song, CatLen+1);
       CatSongs.Song[CatLen].Artist := '[' + Letter + ']';
@@ -663,10 +621,10 @@ case Ini.Sorting of
       CatSongs.Song[CatLen].Visible := true;
     end
 
-    else if (Ini.Sorting = sFolder) and (CompareText(SS, Songs.Song[S].Folder) <> 0) then begin
+    else if (Ini.Sorting = sFolder) and (CompareText(SS, TSong( Songs.SongList[S] ).Folder) <> 0) then begin
       // 0.5.0: add folder tab
       Inc(Order);
-      SS := Songs.Song[S].Folder;
+      SS := TSong( Songs.SongList[S] ).Folder;
       CatLen := Length(CatSongs.Song);
       SetLength(CatSongs.Song, CatLen+1);
       CatSongs.Song[CatLen].Artist := SS;
@@ -689,8 +647,8 @@ case Ini.Sorting of
       CatSongs.Song[CatLen].Visible := true;
     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 := UpperCase(Songs.Song[S].Title)[1];
+    else if (Ini.Sorting = sTitle2) AND (Length(TSong( Songs.SongList[S] ).Title)>=1) then begin
+      if (ord(TSong( Songs.SongList[S] ).Title[1]) > 47) and (ord(TSong( Songs.SongList[S] ).Title[1]) < 58) then Letter2 := '#' else Letter2 := UpperCase(TSong( Songs.SongList[S] ).Title)[1];
       if (Letter <> Letter2) then begin
         // add a letter Category Button
         Inc(Order);
@@ -719,8 +677,8 @@ case Ini.Sorting of
       end;
     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 := UpperCase(Songs.Song[S].Artist)[1];
+    else if (Ini.Sorting = sArtist2) AND (Length(TSong( Songs.SongList[S] ).Artist)>=1) then begin
+     if (ord(TSong( Songs.SongList[S] ).Artist[1]) > 47) and (ord(TSong( Songs.SongList[S] ).Artist[1]) < 58) then Letter2 := '#' else Letter2 := UpperCase(TSong( Songs.SongList[S] ).Artist)[1];
        if (Letter <> Letter2) then begin
         // add a letter Category Button
         Inc(Order);
@@ -755,7 +713,7 @@ case Ini.Sorting of
 
     Inc (CatNumber); //Increase Number in Cat
 
-    CatSongs.Song[CatLen] := Songs.Song[S];
+    CatSongs.Song[CatLen] := TSong( Songs.SongList[S] );
     CatSongs.Song[CatLen].OrderNum := Order; // assigns category
     CatSongs.Song[CatLen].CatNumber := CatNumber;
 
@@ -923,4 +881,11 @@ begin
   end;
 end;
 
+
+
+// -----------------------------------------------------------------------------
+
+
+
+
 end.
diff --git a/Game/Code/Screens/UScreenEditConvert.pas b/Game/Code/Screens/UScreenEditConvert.pas
index e370ad67..a523afd2 100644
--- a/Game/Code/Screens/UScreenEditConvert.pas
+++ b/Game/Code/Screens/UScreenEditConvert.pas
@@ -16,6 +16,7 @@ uses UMenu,
      {$ENDIF}
      ULog,
      USongs,
+     USong,
      UMusic,
      UThemes;
 
diff --git a/Game/Code/Screens/UScreenEditHeader.pas b/Game/Code/Screens/UScreenEditHeader.pas
index 7c8b2d56..60466a27 100644
--- a/Game/Code/Screens/UScreenEditHeader.pas
+++ b/Game/Code/Screens/UScreenEditHeader.pas
@@ -4,7 +4,11 @@ interface
 
 {$I switches.inc}
 
-uses UMenu, SDL, USongs, UThemes;
+uses UMenu,
+     SDL,
+     USongs,
+     USong,
+     UThemes;
 
 type
   TScreenEditHeader = class(TMenu)
diff --git a/Game/Code/Screens/UScreenEditSub.pas b/Game/Code/Screens/UScreenEditSub.pas
index 725dd4e9..57d6777e 100644
--- a/Game/Code/Screens/UScreenEditSub.pas
+++ b/Game/Code/Screens/UScreenEditSub.pas
@@ -15,6 +15,7 @@ uses
     UFiles,
     UTime,
     USongs,
+    USong,
     UIni,
     ULog,
     UTexture,
@@ -143,40 +144,40 @@ begin
         begin
           // Increase BPM
           if SDL_ModState = 0 then
-            AktSong.BPM[0].BPM := Round((AktSong.BPM[0].BPM * 5) + 1) / 5; // (1/20)
+            CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 5) + 1) / 5; // (1/20)
           if SDL_ModState = KMOD_LSHIFT then
-            AktSong.BPM[0].BPM := AktSong.BPM[0].BPM + 4; // (1/1)
+            CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM + 4; // (1/1)
           if SDL_ModState = KMOD_LCTRL then
-            AktSong.BPM[0].BPM := Round((AktSong.BPM[0].BPM * 25) + 1) / 25; // (1/100)
+            CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 25) + 1) / 25; // (1/100)
         end;
 
       SDLK_MINUS:
         begin
           // Decrease BPM
           if SDL_ModState = 0 then
-            AktSong.BPM[0].BPM := Round((AktSong.BPM[0].BPM * 5) - 1) / 5;
+            CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 5) - 1) / 5;
           if SDL_ModState = KMOD_LSHIFT then
-            AktSong.BPM[0].BPM := AktSong.BPM[0].BPM - 4;
+            CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM - 4;
           if SDL_ModState = KMOD_LCTRL then
-            AktSong.BPM[0].BPM := Round((AktSong.BPM[0].BPM * 25) - 1) / 25;
+            CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 25) - 1) / 25;
         end;
 
       SDLK_0:
         begin
           // Increase GAP
           if SDL_ModState = 0 then
-            AktSong.GAP := AktSong.GAP + 10;
+            CurrentSong.GAP := CurrentSong.GAP + 10;
           if SDL_ModState = KMOD_LSHIFT then
-            AktSong.GAP := AktSong.GAP + 1000;
+            CurrentSong.GAP := CurrentSong.GAP + 1000;
         end;
 
       SDLK_9:
         begin
           // Decrease GAP
           if SDL_ModState = 0 then
-            AktSong.GAP := AktSong.GAP - 10;
+            CurrentSong.GAP := CurrentSong.GAP - 10;
           if SDL_ModState = KMOD_LSHIFT then
-            AktSong.GAP := AktSong.GAP - 1000;
+            CurrentSong.GAP := CurrentSong.GAP - 1000;
         end;
 
       SDLK_KP_PLUS:
@@ -222,13 +223,13 @@ begin
         begin
           // Save Song
           if SDL_ModState = KMOD_LSHIFT then
-            SaveSong(AktSong, Czesci[0], Path + FileName, true)
+            SaveSong(CurrentSong, Czesci[0], Path + FileName, true)
           else
-            SaveSong(AktSong, Czesci[0], Path + FileName, false);
+            SaveSong(CurrentSong, Czesci[0], Path + FileName, false);
 
           {if SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL + KMOD_LALT then
             // Save Song
-            SaveSongDebug(AktSong, Czesci[0], 'C:\song.asm', false);}
+            SaveSongDebug(CurrentSong, Czesci[0], 'C:\song.asm', false);}
 
         end;
 
@@ -656,7 +657,7 @@ var
   C:    integer;
   N:    integer;
 begin                    
-  AktSong.BPM[0].BPM := AktSong.BPM[0].BPM / 2;
+  CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM / 2;
   for C := 0 to Czesci[0].High do begin
     Czesci[0].Czesc[C].Start :=     Czesci[0].Czesc[C].Start div 2;
     Czesci[0].Czesc[C].StartNote := Czesci[0].Czesc[C].StartNote div 2;
@@ -673,7 +674,7 @@ var
   C:    integer;
   N:    integer;
 begin
-  AktSong.BPM[0].BPM := AktSong.BPM[0].BPM * 2;
+  CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM * 2;
   for C := 0 to Czesci[0].High do begin
     Czesci[0].Czesc[C].Start :=     Czesci[0].Czesc[C].Start * 2;
     Czesci[0].Czesc[C].StartNote := Czesci[0].Czesc[C].StartNote * 2;
@@ -1160,7 +1161,7 @@ begin
 
   try
     ResetSingTemp;
-    Error := not LoadSong(Path + FileName);
+//    Error := not LoadSong(Path + FileName);  // todo - JB come back to this
   except
     Error := True;
   end;
@@ -1179,15 +1180,15 @@ begin
       MidiOut.ProductName := 'Microsoft GS Wavetable SW Synth'; // for my kxproject without midi table
     MidiOut.Open;
   {$ENDIF}
-    Text[TextTitle].Text :=   AktSong.Title;
-    Text[TextArtist].Text :=  AktSong.Artist;
-    Text[TextMp3].Text :=     AktSong.Mp3;
+    Text[TextTitle].Text :=   CurrentSong.Title;
+    Text[TextArtist].Text :=  CurrentSong.Artist;
+    Text[TextMp3].Text :=     CurrentSong.Mp3;
 
     Czesci[0].Akt := 0;
     AktNuta := 0;
     Czesci[0].Czesc[0].Nuta[0].Color := 1;
 
-    AudioPlayback.Open(Path + AktSong.Mp3);
+    AudioPlayback.Open(Path + CurrentSong.Mp3);
     //Set Down Music Volume for Better hearability of Midi Sounds
     //Music.SetVolume(40);
     
@@ -1238,7 +1239,7 @@ begin
     {$ENDIF}
 
     // click
-    AktBeat := Floor(GetMidBeat(MidiPos - AktSong.GAP / 1000));
+    AktBeat := Floor(GetMidBeat(MidiPos - CurrentSong.GAP / 1000));
     Text[TextDebug].Text := IntToStr(AktBeat);
 
     if AktBeat <> LastClick then begin
@@ -1269,8 +1270,8 @@ begin
 
     // click
     if (Click) and (PlaySentence) then begin
-//      AktBeat := Floor(AktSong.BPM[0].BPM * (Music.Position - AktSong.GAP / 1000) / 60);
-      AktBeat := Floor(GetMidBeat(AudioPlayback.Position - AktSong.GAP / 1000));
+//      AktBeat := Floor(CurrentSong.BPM[0].BPM * (Music.Position - CurrentSong.GAP / 1000) / 60);
+      AktBeat := Floor(GetMidBeat(AudioPlayback.Position - CurrentSong.GAP / 1000));
       Text[TextDebug].Text := IntToStr(AktBeat);
       if AktBeat <> LastClick then begin
         for Pet := 0 to Czesci[0].Czesc[Czesci[0].Akt].HighNut do
@@ -1288,8 +1289,8 @@ begin
   Text[TextNote].Text := IntToStr(AktNuta + 1) + ' / ' + IntToStr(Czesci[0].Czesc[Czesci[0].Akt].IlNut);
 
   // Song info
-  Text[TextBPM].Text := FloatToStr(AktSong.BPM[0].BPM / 4);
-  Text[TextGAP].Text := FloatToStr(AktSong.GAP);
+  Text[TextBPM].Text := FloatToStr(CurrentSong.BPM[0].BPM / 4);
+  Text[TextGAP].Text := FloatToStr(CurrentSong.GAP);
 
   //Error reading Variables when no Song is loaded
   if not Error then
diff --git a/Game/Code/Screens/UScreenMain.pas b/Game/Code/Screens/UScreenMain.pas
index 5f7a0461..a4dc5f0d 100644
--- a/Game/Code/Screens/UScreenMain.pas
+++ b/Game/Code/Screens/UScreenMain.pas
@@ -124,7 +124,7 @@ begin
           //Solo
           if (Interaction = 0) then
           begin
-            if (Length(Songs.Song) >= 1) then
+            if (Songs.SongList.Count >= 1) then
             begin
               AudioPlayback.PlayStart;
               if (Ini.Players >= 0) and (Ini.Players <= 3) then PlayersPlay := Ini.Players + 1;
@@ -138,8 +138,9 @@ begin
           end;
 
           //Multi
-          if Interaction = 1 then begin
-            if (Length(Songs.Song) >= 1) then
+          if Interaction = 1 then
+          begin
+            if (Songs.SongList.Count >= 1) then
             begin
               if (Length(DLLMan.Plugins)>=1) then
               begin
diff --git a/Game/Code/Screens/UScreenOptionsRecord.pas b/Game/Code/Screens/UScreenOptionsRecord.pas
index 80259802..42776717 100644
--- a/Game/Code/Screens/UScreenOptionsRecord.pas
+++ b/Game/Code/Screens/UScreenOptionsRecord.pas
@@ -15,14 +15,21 @@ type
       SelectSlideChannelR:    integer;
     public
       constructor Create; override;
-      function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
-      procedure onShow; override;
-      procedure UpdateCard;
+      function    Draw: boolean; override;
+      function    ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
+      procedure   onShow; override;
+      procedure   onHide; override;
+      procedure   UpdateCard;
   end;
 
 implementation
 
-uses SysUtils, UGraphic, URecord, ULog;
+uses SysUtils,
+     UGraphic,
+     URecord,
+     UDraw,
+     UMain,
+     ULog;
 
 function TScreenOptionsRecord.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean;
 begin
@@ -43,7 +50,7 @@ begin
         end;
       SDLK_RETURN:
         begin
-          if SelInteraction = 4 then begin
+          if SelInteraction = 5 then begin
             Ini.Save;
             AudioPlayback.PlayBack;
             FadeTo(@ScreenOptions);
@@ -55,19 +62,21 @@ begin
         InteractPrev;
       SDLK_RIGHT:
         begin
-          if (SelInteraction >= 0) and (SelInteraction <= 3) then begin
+          if (SelInteraction >= 0) and (SelInteraction <= 4) then begin
             AudioPlayback.PlayOption;
             InteractInc;
           end;
-          if SelInteraction = 0 then UpdateCard;
+//          if SelInteraction = 0 then UpdateCard;
+          UpdateCard;
         end;
       SDLK_LEFT:
         begin
-          if (SelInteraction >= 0) and (SelInteraction <= 3) then begin
+          if (SelInteraction >= 0) and (SelInteraction <= 4) then begin
             AudioPlayback.PlayOption;
             InteractDec;
           end;
-          if SelInteraction = 0 then UpdateCard;
+          UpdateCard;          
+//          if SelInteraction = 0 then UpdateCard;
         end;
     end;
   end;
@@ -80,22 +89,27 @@ var
   SCI:    integer;
 begin
   inherited Create;
-  
+
   LoadFromTheme(Theme.OptionsRecord);
 
-  SetLength(ICard, Length(Recording.SoundCard));
-  for SC := 0 to High(Recording.SoundCard) do
-    ICard[SC] := Recording.SoundCard[SC].Description;
+  SetLength(ICard, Length(AudioInputProcessor.SoundCard));
+  for SC := 0 to High(AudioInputProcessor.SoundCard) do
+    ICard[SC] := AudioInputProcessor.SoundCard[SC].Description;
+
+  if (Length(AudioInputProcessor.SoundCard) > 0) then
+  begin
+    SetLength(IInput, Length(AudioInputProcessor.SoundCard[Ini.Card].Input));
+    for SCI := 0 to High(AudioInputProcessor.SoundCard[Ini.Card].Input) do
+      IInput[SCI] := AudioInputProcessor.SoundCard[Ini.Card].Input[SCI].Name;
 
-  if (Length(Recording.SoundCard) > 0) then begin
-    SetLength(IInput, Length(Recording.SoundCard[Ini.Card].Input));
-    for SCI := 0 to High(Recording.SoundCard[Ini.Card].Input) do
-      IInput[SCI] := Recording.SoundCard[Ini.Card].Input[SCI].Name;
 
     AddSelectSlide(Theme.OptionsRecord.SelectSlideCard, Ini.Card, ICard);
+
     SelectSlideInput    := AddSelectSlide(Theme.OptionsRecord.SelectSlideInput, Ini.CardList[0].Input, IInput);
     SelectSlideChannelL := AddSelectSlide(Theme.OptionsRecord.SelectSlideChannelL, Ini.CardList[0].ChannelL, IChannel);
     SelectSlideChannelR := AddSelectSlide(Theme.OptionsRecord.SelectSlideChannelR, Ini.CardList[0].ChannelR, IChannel);
+
+    AddSelect(Theme.OptionsSound.SelectMicBoost, Ini.MicBoost, IMicBoost);
   end;
 
   AddButton(Theme.OptionsRecord.ButtonExit);
@@ -108,6 +122,16 @@ end;
 procedure TScreenOptionsRecord.onShow;
 begin
   Interaction := 0;
+  writeln( 'AudioInput.CaptureStart') ;
+
+  PlayersPlay := 2;  //  TODO : This needs fixing
+  AudioInput.CaptureStart;
+
+end;
+
+procedure TScreenOptionsRecord.onHide;
+begin
+  AudioInput.CaptureStop;
 end;
 
 procedure TScreenOptionsRecord.UpdateCard;
@@ -115,18 +139,74 @@ var
   SC:     integer;
   SCI:    integer;
 begin
-  SC := Ini.Card;
-//  if SC = 1 then beep;
+  writeln( 'Update Card') ;
+  AudioInput.CaptureStop;
+  try
+    SC := Ini.Card;
+  //  if SC = 1 then beep;
+
+    SetLength(IInput, Length(AudioInputProcessor.SoundCard[SC].Input));
+    for SCI := 0 to High(AudioInputProcessor.SoundCard[SC].Input) do begin
+      IInput[SCI] := AudioInputProcessor.SoundCard[SC].Input[SCI].Name;
+  //    Log.LogError(IInput[SCI]);
+    end;
 
-  SetLength(IInput, Length(Recording.SoundCard[SC].Input));
-  for SCI := 0 to High(Recording.SoundCard[SC].Input) do begin
-    IInput[SCI] := Recording.SoundCard[SC].Input[SCI].Name;
-//    Log.LogError(IInput[SCI]);
+
+    UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideInput, SelectSlideInput, IInput, Ini.CardList[SC].Input);
+    UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelL, SelectSlideChannelL, IChannel, Ini.CardList[SC].ChannelL);
+    UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelR, SelectSlideChannelR, IChannel, Ini.CardList[SC].ChannelR);
+
+  finally
+    AudioInput.CaptureStart;
   end;
+end;
 
-  UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideInput, SelectSlideInput, IInput, Ini.CardList[SC].Input);
-  UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelL, SelectSlideChannelL, IChannel, Ini.CardList[SC].ChannelL);
-  UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelR, SelectSlideChannelR, IChannel, Ini.CardList[SC].ChannelR);
+function TScreenOptionsRecord.Draw: boolean;
+begin
+  DrawBG;
+  DrawFG;
+
+    // TODO : this needs to be positioned correctly
+    if PlayersPlay = 1 then
+      SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+
+    if PlayersPlay = 2 then begin
+      SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+      SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
+    end;
+
+    if PlayersPlay = 4 then begin
+      if ScreenAct = 1 then begin
+        SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
+        SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
+      end;
+      if ScreenAct = 2 then begin
+        SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2);
+        SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3);
+      end;
+    end;
+
+    if PlayersPlay = 3 then begin
+      SingDrawOscilloscope(75 + 10*ScreenX, 95, 100, 20, 0);
+      SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
+      SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
+    end;
+
+    if PlayersPlay = 6 then begin
+      if ScreenAct = 1 then begin
+        SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0);
+        SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
+        SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
+      end;
+      if ScreenAct = 2 then begin
+        SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3);
+        SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4);
+        SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5);
+      end;
+    end;
+
+  Result := True;
 end;
 
+
 end.
diff --git a/Game/Code/Screens/UScreenOptionsSound.pas b/Game/Code/Screens/UScreenOptionsSound.pas
index 867a10b6..64a0413f 100644
--- a/Game/Code/Screens/UScreenOptionsSound.pas
+++ b/Game/Code/Screens/UScreenOptionsSound.pas
@@ -51,14 +51,14 @@ begin
         InteractPrev;
       SDLK_RIGHT:
         begin
-          if (SelInteraction >= 0) and (SelInteraction <= 5) then begin
+          if (SelInteraction >= 0) and (SelInteraction <= 6) then begin
             AudioPlayback.PlayOption;
             InteractInc;
           end;
         end;
       SDLK_LEFT:
         begin
-          if (SelInteraction >= 0) and (SelInteraction <= 5) then begin
+          if (SelInteraction >= 0) and (SelInteraction <= 6) then begin
             AudioPlayback.PlayOption;
             InteractDec;
           end;
@@ -75,15 +75,14 @@ begin
 
   LoadFromTheme(Theme.OptionsSound);
 
-  AddSelect(Theme.OptionsSound.SelectMicBoost, Ini.MicBoost, IMicBoost);
+  AddSelect(Theme.OptionsSound.SelectMicBoost, Ini.MicBoost, IMicBoost);  // TODO - This need moving to ScreenOptionsRecord
   AddSelect(Theme.OptionsSound.SelectClickAssist, Ini.ClickAssist, IClickAssist);
   AddSelect(Theme.OptionsSound.SelectBeatClick, Ini.BeatClick, IBeatClick);
   AddSelect(Theme.OptionsSound.SelectThreshold, Ini.Threshold, IThreshold);
 
   //Song Preview
   AddSelectSlide(Theme.OptionsSound.SelectSlidePreviewVolume, Ini.PreviewVolume, IPreviewVolume);
-  AddSelectSlide
-  (Theme.OptionsSound.SelectSlidePreviewFading, Ini.PreviewFading, IPreviewFading);
+  AddSelectSlide(Theme.OptionsSound.SelectSlidePreviewFading, Ini.PreviewFading, IPreviewFading);
 
   AddButton(Theme.OptionsSound.ButtonExit);
   if (Length(Button[0].Text)=0) then
diff --git a/Game/Code/Screens/UScreenScore.pas b/Game/Code/Screens/UScreenScore.pas
index 84fd4e15..c53844f5 100644
--- a/Game/Code/Screens/UScreenScore.pas
+++ b/Game/Code/Screens/UScreenScore.pas
@@ -304,9 +304,9 @@ begin
   // Singstar
   Fadeout := false;
 
-  Text[TextArtist].Text      := AktSong.Artist;
-  Text[TextTitle].Text       := AktSong.Title;
-  Text[TextArtistTitle].Text := AktSong.Artist + ' - ' + AktSong.Title;
+  Text[TextArtist].Text      := CurrentSong.Artist;
+  Text[TextTitle].Text       := CurrentSong.Title;
+  Text[TextArtistTitle].Text := CurrentSong.Artist + ' - ' + CurrentSong.Title;
 
   // set visibility
   case PlayersPlay of
diff --git a/Game/Code/Screens/UScreenSing.pas b/Game/Code/Screens/UScreenSing.pas
index 5a9ecae7..adfc4d2c 100644
--- a/Game/Code/Screens/UScreenSing.pas
+++ b/Game/Code/Screens/UScreenSing.pas
@@ -101,22 +101,29 @@ type
       fCurrentVideoPlaybackEngine : IVideoPlayback;
 
       constructor Create; override;
-      procedure onShow; override;
-      procedure onShowFinish; override;
-      function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
-      function Draw: boolean; override;
-      procedure Finish; virtual;
-      procedure UpdateLCD;
-      procedure Pause; //Pause Mod(Toggles Pause)
-
-      //OnSentenceEnd for LineBonus + Singbar
-      procedure onSentenceEnd(S: Cardinal);
-      //OnSentenceChange (for Golden Notes)
-      procedure onSentenceChange(S: Cardinal);
+      procedure   onShow; override;
+      procedure   onShowFinish; override;
+
+      function    ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
+      function    Draw: boolean; override;
+
+      procedure   Finish; virtual;
+      procedure   UpdateLCD;
+      procedure   Pause; //Pause Mod(Toggles Pause)
+
+      procedure   onSentenceEnd(S: Cardinal);     //OnSentenceEnd for LineBonus + Singbar
+      procedure   onSentenceChange(S: Cardinal);  //OnSentenceChange (for Golden Notes)
   end;
 
 implementation
-uses UGraphic, UDraw, UMain, Classes, URecord, ULanguage, math;
+
+uses UGraphic,
+     UDraw,
+     UMain,
+     Classes,
+     URecord,
+     ULanguage,
+     math;
 
 // Method for input parsing. If False is returned, GetNextWindow
 // should be checked to know the next window to load;
@@ -204,7 +211,7 @@ begin
       AudioPlayback.Pause;
 
       // pause Video
-      if (AktSong.Video <> '') and FileExists(AktSong.Path + AktSong.Video) then
+      if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then
         fCurrentVideoPlaybackEngine.Pause;
 
     end
@@ -218,7 +225,7 @@ begin
       AudioPlayback.Play;
 
       // Video
-      if (AktSong.Video <> '') and FileExists(AktSong.Path + AktSong.Video) then
+      if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then
         fCurrentVideoPlaybackEngine.Pause;
 
       Paused := false;
@@ -425,12 +432,13 @@ begin
   {Static[StaticP3RScoreBG].Visible      := V3R;
   Text[TextP3RScore].Visible            := V3R; }
 
-  // load notes
   ResetSingTemp;
 //  Log.LogWarning(CatSongs.Song[CatSongs.Selected].Path + CatSongs.Song[CatSongs.Selected].FileName, '!!!');
-  AktSong := CatSongs.Song[CatSongs.Selected];
+  CurrentSong := CatSongs.Song[CatSongs.Selected];
+
   try
-    if not LoadSong(CatSongs.Song[CatSongs.Selected].Path + CatSongs.Song[CatSongs.Selected].FileName) then
+    if not CurrentSong.LoadSong then
+//    if not LoadSong(CatSongs.Song[CatSongs.Selected].Path + CatSongs.Song[CatSongs.Selected].FileName) then
     begin
       //Error Loading Song -> Go back to Song Screen and Show some Error Message
       FadeTo(@ScreenSong);
@@ -449,26 +457,26 @@ begin
     ScreenPopupError.ShowPopup (Language.Translate('ERROR_CORRUPT_SONG'));
     Exit;
   end;
-  AktSong.Path := CatSongs.Song[CatSongs.Selected].Path;
-//  AktSong.GAP := AktSong.GAP + 40 {4096 = 100ms for buffer} + 20 {microphone} + 60000 / AktSong.BPM[0].BPM / 2; // temporary until UMain will be fixed
+  CurrentSong.Path := CatSongs.Song[CatSongs.Selected].Path;
+//  CurrentSong.GAP := CurrentSong.GAP + 40 {4096 = 100ms for buffer} + 20 {microphone} + 60000 / CurrentSong.BPM[0].BPM / 2; // temporary until UMain will be fixed
 
   // set movie
-  if (AktSong.Video <> '') and FileExists(AktSong.Path + AktSong.Video) then
+  if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then
   begin
     // todo: VideoGap and Start time verwursten
-    fCurrentVideoPlaybackEngine.Open( AktSong.Path + AktSong.Video );
+    fCurrentVideoPlaybackEngine.Open( CurrentSong.Path + CurrentSong.Video );
 
-    fCurrentVideoPlaybackEngine.position := AktSong.VideoGAP + AktSong.Start;
+    fCurrentVideoPlaybackEngine.position := CurrentSong.VideoGAP + CurrentSong.Start;
     
-    AktSong.VideoLoaded := true;
+    CurrentSong.VideoLoaded := true;
   end;
 
   // set background
-  if (AktSong.Background <> '')  and (AktSong.VideoLoaded = false) then
+  if (CurrentSong.Background <> '')  and (CurrentSong.VideoLoaded = false) then
     try
-      Tex_Background := Texture.LoadTexture(AktSong.Path + AktSong.Background);
+      Tex_Background := Texture.LoadTexture(CurrentSong.Path + CurrentSong.Background);
     except
-      log.LogError('Background could not be loaded: ' + AktSong.Path + AktSong.Background);
+      log.LogError('Background could not be loaded: ' + CurrentSong.Path + CurrentSong.Background);
       Tex_Background.TexNum := -1;
     end
   else
@@ -478,20 +486,20 @@ begin
 
   // play music (I)
   AudioInput.CaptureStart;
-  AudioPlayback.Position := AktSong.Start;
+  AudioPlayback.Position := CurrentSong.Start;
 //  Music.Play;
 
   // prepare timer (I)
 //  CountSkipTimeSet;
-  Czas.Teraz := AktSong.Start;
+  Czas.Teraz := CurrentSong.Start;
   Czas.Razem := AudioPlayback.Length;
-  if (AktSong.Finish > 0) then Czas.Razem := AktSong.Finish / 1000;
+  if (CurrentSong.Finish > 0) then Czas.Razem := CurrentSong.Finish / 1000;
   Czas.OldBeat := -1;
   for P := 0 to High(Player) do
     ClearScores(P);
 
   // main text
-  Lyrics.Clear (AktSong.BPM[0].BPM, AktSong.Resolution);
+  Lyrics.Clear (CurrentSong.BPM[0].BPM, CurrentSong.Resolution);
 
   // set custom options
   case Ini.LyricsFont of
@@ -870,7 +878,7 @@ procedure TScreenSing.onShowFinish;
 begin
   // play movie (II)
 
-  if AktSong.VideoLoaded then
+  if CurrentSong.VideoLoaded then
   begin
     try
       writeln( 'VideoPlayback.FFmpegGetFrame' );
@@ -884,11 +892,11 @@ begin
      on E : Exception do
      begin
        //If an Error occurs Reading Video: prevent Video from being Drawn again and Close Video
-       AktSong.VideoLoaded := False;
+       CurrentSong.VideoLoaded := False;
        Log.LogError('Error drawing Video, Video has been disabled for this Song/Session.');
        Log.LogError('Error Message : '+ E.message );
        Log.LogError('      In      : '+ E.ClassName +' (TScreenSing.onShowFinish)' );
-       Log.LogError('Corrupted File: ' + AktSong.Video);
+       Log.LogError('Corrupted File: ' + CurrentSong.Video);
        try
 //         CloseSmpeg;
          fCurrentVideoPlaybackEngine.Close;
@@ -1141,7 +1149,8 @@ begin
   SingDrawBackground;
   // update and draw movie
   
-  if ShowFinish and ( AktSong.VideoLoaded or fShowVisualization ) then
+  if ShowFinish and
+     ( CurrentSong.VideoLoaded or fShowVisualization ) then
 //  if ShowFinish then
   begin
 //    try
@@ -1161,12 +1170,12 @@ begin
       begin
 
         //If an Error occurs drawing: prevent Video from being Drawn again and Close Video
-        AktSong.VideoLoaded := False;
+        CurrentSong.VideoLoaded := False;
         log.LogError('Error drawing Video, Video has been disabled for this Song/Session.');
         Log.LogError('Error Message : '+ E.message );
         Log.LogError('      In      : '+ E.ClassName +' (TScreenSing.Draw)' );
 
-        Log.LogError('Corrupted File: ' + AktSong.Video);
+        Log.LogError('Corrupted File: ' + CurrentSong.Video);
         try
 //        CloseSmpeg;
           fCurrentVideoPlaybackEngine.Close;
@@ -1183,9 +1192,9 @@ begin
   DrawFG;
 
   // check for music finish
-//  Log.LogError('Check for music finish: ' + BoolToStr(Music.Finished) + ' ' + FloatToStr(Czas.Teraz*1000) + ' ' + IntToStr(AktSong.Finish));
+//  Log.LogError('Check for music finish: ' + BoolToStr(Music.Finished) + ' ' + FloatToStr(Czas.Teraz*1000) + ' ' + IntToStr(CurrentSong.Finish));
   if ShowFinish then begin
-  if (not AudioPlayback.Finished) and ((AktSong.Finish = 0) or (Czas.Teraz*1000 <= AktSong.Finish)) then begin
+  if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or (Czas.Teraz*1000 <= CurrentSong.Finish)) then begin
   //Pause Mod:
     if not Paused then
     Sing(Self);       // analyze song
@@ -1251,11 +1260,11 @@ begin
     Log.LogBenchmark('Creating files', 0);
   end;
 
-  if AktSong.VideoLoaded then
+  if CurrentSong.VideoLoaded then
   begin
 //    CloseSmpeg;
     fCurrentVideoPlaybackEngine.Close;
-    AktSong.VideoLoaded := false; // to prevent drawing closed video
+    CurrentSong.VideoLoaded := false; // to prevent drawing closed video
   end;
 
   SetFontItalic (False);
diff --git a/Game/Code/Screens/UScreenSingModi.pas b/Game/Code/Screens/UScreenSingModi.pas
index 5d87ffdd..7d2eba07 100644
--- a/Game/Code/Screens/UScreenSingModi.pas
+++ b/Game/Code/Screens/UScreenSingModi.pas
@@ -520,7 +520,7 @@ end;
   // comment by blindy: wo zum henker wird denn in diesem screen ein video abgespielt?
   // update and draw movie
   // <mog> wie wo wadd? also in der selben funktion in der uscreensing kommt des video in der zeile 995, oder was wollteste wissen? :X
-{  if ShowFinish and AktSong.VideoLoaded AND DllMan.Selected.LoadVideo then begin
+{  if ShowFinish and CurrentSong.VideoLoaded AND DllMan.Selected.LoadVideo then begin
     UpdateSmpeg; // this only draws
   end;}
 
@@ -530,7 +530,7 @@ end;
   if ShowFinish then begin
     if DllMan.Selected.LoadSong then
     begin
-      if (not AudioPlayback.Finished) and ((AktSong.Finish = 0) or (Czas.Teraz*1000 <= AktSong.Finish)) then begin
+      if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or (Czas.Teraz*1000 <= CurrentSong.Finish)) then begin
         //Pause Mod:
         if not Paused then
           Sing(Self);       // analyze song
diff --git a/Game/Code/Screens/UScreenSong.pas b/Game/Code/Screens/UScreenSong.pas
index 4f90e2ca..4b42288a 100644
--- a/Game/Code/Screens/UScreenSong.pas
+++ b/Game/Code/Screens/UScreenSong.pas
@@ -383,7 +383,7 @@ begin
         end;
       SDLK_RETURN:
         begin
-          if Length(Songs.Song) > 0 then
+          if Songs.SongList.Count > 0 then
           begin
             {$IFDEF UseSerialPort}
               // PortWriteB($378, 0);
@@ -438,7 +438,7 @@ begin
 
       SDLK_M: //Show SongMenu
         begin
-          if (Length(Songs.Song) > 0) then begin
+          if (Songs.SongList.Count > 0) then begin
             if (Mode = 0) then begin
               if not CatSongs.Song[Interaction].Main then begin // clicked on Song
                 if CatSongs.CatNumShow = -3 then
@@ -457,14 +457,14 @@ begin
 
       SDLK_P: //Show Playlist Menu
         begin
-          if (Length(Songs.Song) > 0) AND (Mode = 0) then begin
+          if (Songs.SongList.Count > 0) AND (Mode = 0) then begin
               ScreenSongMenu.MenuShow(SM_Playlist_Load);
           end;
         end;
 
       SDLK_J: //Show Jumpto Menu
         begin
-          if (Length(Songs.Song) > 0) AND (Mode = 0) then
+          if (Songs.SongList.Count > 0) AND (Mode = 0) then
           begin
             ScreenSongJumpto.Visible := True;
           end;
@@ -553,7 +553,7 @@ begin
 
       SDLK_RIGHT:
         begin
-          if (Length(Songs.Song) > 0) AND (Mode = 0) then
+          if (Songs.SongList.Count > 0) AND (Mode = 0) then
           begin
             AudioPlayback.PlayChange;
             SelectNext;
@@ -568,7 +568,7 @@ begin
 
       SDLK_LEFT:
         begin
-          if (Length(Songs.Song) > 0)AND (Mode = 0)  then begin
+          if (Songs.SongList.Count > 0)AND (Mode = 0)  then begin
             AudioPlayback.PlayChange;
             SelectPrev;
             ChangeMusic;
@@ -585,7 +585,7 @@ begin
 
       SDLK_R:
         begin
-          if (Length(Songs.Song) > 0) AND (Mode = 0) then begin
+          if (Songs.SongList.Count > 0) AND (Mode = 0) then begin
 
             if (SDL_ModState = KMOD_LSHIFT) AND (Ini.Tabs_at_startup = 1) then //Random Category
             begin
@@ -1819,7 +1819,7 @@ begin
     EqualizerTime := A;
     Data := AudioPlayback.GetFFTData;
 
-    B:=0;
+    B   := 0;
     Pos := 0;
     Res := ceil(92/Theme.Song.Equalizer.Bands);//How much channels are used for one Band
 
@@ -2121,7 +2121,7 @@ end;
 
 procedure TScreenSong.OpenEditor;
 begin
-  if (Length(Songs.Song) > 0) and (not CatSongs.Song[Interaction].Main) AND (Mode = 0) then
+  if (Songs.SongList.Count > 0) and (not CatSongs.Song[Interaction].Main) AND (Mode = 0) then
   begin
     AudioPlayback.Stop;
     AudioPlayback.PlayStart;
diff --git a/Game/Code/Screens/UScreenStatMain.pas b/Game/Code/Screens/UScreenStatMain.pas
index 7e5c7d91..f7257201 100644
--- a/Game/Code/Screens/UScreenStatMain.pas
+++ b/Game/Code/Screens/UScreenStatMain.pas
@@ -37,6 +37,7 @@ implementation
 uses UGraphic,
      UDataBase,
      USongs,
+     USong,
      ULanguage,
      UCommon,
      {$IFDEF win32}
@@ -133,8 +134,8 @@ begin
 
   //Set Songs with Vid
   SongswithVid := 0;
-  For I := 0 to high(Songs.Song) do
-    if (Songs.Song[I].Video <> '') then
+  For I := 0 to Songs.SongList.Count -1 do
+    if (TSong(Songs.SongList[I]).Video <> '') then
       Inc(SongswithVid);
 end;
 
@@ -233,7 +234,7 @@ begin
     %2:d Count of UnSung Songs
     %3:d Count of Songs with Video (A3)
     %4:s Name of the most popular Song}
-  A1 := Length(Songs.Song);
+  A1 := Songs.SongList.Count;
   A2 := Database.GetTotalEntrys(2);
 
   A3 := SongswithVid;
diff --git a/Game/Code/Screens/UScreenTop5.pas b/Game/Code/Screens/UScreenTop5.pas
index bf19fed2..207f6ee6 100644
--- a/Game/Code/Screens/UScreenTop5.pas
+++ b/Game/Code/Screens/UScreenTop5.pas
@@ -92,29 +92,29 @@ var
 begin
   Fadeout := false;
 
-  //ReadScore(AktSong);
+  //ReadScore(CurrentSong);
 
   PMax := Ini.Players;
   if Ini.Players = 4 then Ini.Players := 5;
   for I := 0 to PMax do
-    DataBase.AddScore(AktSong, Ini.Difficulty, Ini.Name[I], Round(Player[I].ScoreTotalI));
+    DataBase.AddScore(CurrentSong, Ini.Difficulty, Ini.Name[I], Round(Player[I].ScoreTotalI));
 
-  DataBase.WriteScore(AktSong);
-  DataBase.ReadScore(AktSong);
+  DataBase.WriteScore(CurrentSong);
+  DataBase.ReadScore(CurrentSong);
 
-  Text[TextArtistTitle].Text := AktSong.Artist + ' - ' + AktSong.Title;
+  Text[TextArtistTitle].Text := CurrentSong.Artist + ' - ' + CurrentSong.Title;
 
-  for I := 1 to Length(AktSong.Score[Ini.Difficulty]) do begin
+  for I := 1 to Length(CurrentSong.Score[Ini.Difficulty]) do begin
     Static[StaticNumber[I]].Visible := true;
     Text[TextNumber[I]].Visible := true;
     Text[TextName[I]].Visible := true;
     Text[TextScore[I]].Visible := true;
 
-    Text[TextName[I]].Text := AktSong.Score[Ini.Difficulty, I-1].Name;
-    Text[TextScore[I]].Text := IntToStr(AktSong.Score[Ini.Difficulty, I-1].Score);
+    Text[TextName[I]].Text := CurrentSong.Score[Ini.Difficulty, I-1].Name;
+    Text[TextScore[I]].Text := IntToStr(CurrentSong.Score[Ini.Difficulty, I-1].Score);
   end;
 
-  for I := Length(AktSong.Score[Ini.Difficulty])+1 to 5 do begin
+  for I := Length(CurrentSong.Score[Ini.Difficulty])+1 to 5 do begin
     Static[StaticNumber[I]].Visible := false;
     Text[TextNumber[I]].Visible := false;
     Text[TextName[I]].Visible := false;
diff --git a/Game/Code/UltraStar.dpr b/Game/Code/UltraStar.dpr
index 236d0b1e..ca639d1e 100644
--- a/Game/Code/UltraStar.dpr
+++ b/Game/Code/UltraStar.dpr
@@ -87,6 +87,7 @@ uses
   URecord           in 'Classes\URecord.pas',
   UTime             in 'Classes\UTime.pas',
   TextGL            in 'Classes\TextGL.pas',
+  USong             in 'Classes\USong.pas',
   USongs            in 'Classes\USongs.pas',
   UIni              in 'Classes\UIni.pas',
   ULyrics           in 'Classes\ULyrics.pas',
-- 
cgit v1.2.3