aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/base/UThemes.pas91
-rw-r--r--src/menu/UMenuEqualizer.pas285
-rw-r--r--src/screens/UScreenSong.pas120
3 files changed, 337 insertions, 159 deletions
diff --git a/src/base/UThemes.pas b/src/base/UThemes.pas
index 2319107a..6097e3ee 100644
--- a/src/base/UThemes.pas
+++ b/src/base/UThemes.pas
@@ -145,6 +145,23 @@ type
SkipX: integer;
end;
+ TThemeEqualizer = record
+ Visible: Boolean;
+ Direction: Boolean;
+ Alpha: real;
+ X: Integer;
+ Y: Integer;
+ Z: Real;
+ W: Integer;
+ H: Integer;
+ Space: Integer;
+ Bands: Integer;
+ Length: Integer;
+ ColR, ColG, ColB: Real;
+ Reflection: boolean;
+ Reflectionspacing: Real;
+ end;
+
PThemeBasic = ^TThemeBasic;
TThemeBasic = class
Background: TThemeBackground;
@@ -208,20 +225,7 @@ type
end;
//Equalizer Mod
- Equalizer: record
- Visible: Boolean;
- Direction: Boolean;
- Alpha: real;
- X: Integer;
- Y: Integer;
- Z: Real;
- W: Integer;
- H: Integer;
- Space: Integer;
- Bands: Integer;
- Length: Integer;
- ColR, ColG, ColB: Real;
- end;
+ Equalizer: TThemeEqualizer;
//Party and Non Party specific Statics and Texts
@@ -708,6 +712,7 @@ type
procedure ThemeLoadButtonCollection(var Collection: TThemeButtonCollection; Name: string);
procedure ThemeLoadButtonCollections(var Collections: AThemeButtonCollection; Name: string);
procedure ThemeLoadSelectSlide(var ThemeSelectS: TThemeSelectSlide; Name: string);
+ procedure ThemeLoadEqualizer(var ThemeEqualizer: TThemeEqualizer; Name: string);
procedure ThemeSave(FileName: string);
procedure ThemeSaveBasic(Theme: TThemeBasic; Name: string);
@@ -939,32 +944,7 @@ begin
Song.Cover.Reflections := (ThemeIni.ReadInteger('SongCover', 'Reflections', 0) = 1);
//Load Cover Pos and Size from Theme Mod End
- //Load Equalizer Pos and Size from Theme Mod
- Song.Equalizer.Visible := (ThemeIni.ReadInteger('SongEqualizer', 'Visible', 0) = 1);
- Song.Equalizer.Direction := (ThemeIni.ReadInteger('SongEqualizer', 'Direction', 0) = 1);
- Song.Equalizer.Alpha := ThemeIni.ReadInteger('SongEqualizer', 'Alpha', 1);
- Song.Equalizer.Space := ThemeIni.ReadInteger('SongEqualizer', 'Space', 1);
- Song.Equalizer.X := ThemeIni.ReadInteger('SongEqualizer', 'X', 0);
- Song.Equalizer.Y := ThemeIni.ReadInteger('SongEqualizer', 'Y', 0);
- Song.Equalizer.Z := ThemeIni.ReadInteger('SongEqualizer', 'Z', 1);
- Song.Equalizer.W := ThemeIni.ReadInteger('SongEqualizer', 'PieceW', 8);
- Song.Equalizer.H := ThemeIni.ReadInteger('SongEqualizer', 'PieceH', 8);
- Song.Equalizer.Bands := ThemeIni.ReadInteger('SongEqualizer', 'Bands', 5);
- Song.Equalizer.Length := ThemeIni.ReadInteger('SongEqualizer', 'Length', 12);
-
- //Color
- I := ColorExists(ThemeIni.ReadString('SongEqualizer', 'Color', 'Black'));
- if I >= 0 then begin
- Song.Equalizer.ColR := Color[I].RGB.R;
- Song.Equalizer.ColG := Color[I].RGB.G;
- Song.Equalizer.ColB := Color[I].RGB.B;
- end
- else begin
- Song.Equalizer.ColR := 0;
- Song.Equalizer.ColG := 0;
- Song.Equalizer.ColB := 0;
- end;
- //Load Equalizer Pos and Size from Theme Mod End
+ ThemeLoadEqualizer(Song.Equalizer, 'SongEqualizer');
//Party and Non Party specific Statics and Texts
ThemeLoadStatics (Song.StaticParty, 'SongStaticParty');
@@ -1717,6 +1697,37 @@ begin
ThemeSelectS.STDInt := ThemeIni.ReadFloat(Name, 'STDInt', 1);
end;
+procedure TTheme.ThemeLoadEqualizer(var ThemeEqualizer: TThemeEqualizer; Name: string);
+var I: Integer;
+begin
+ ThemeEqualizer.Visible := (ThemeIni.ReadInteger(Name, 'Visible', 0) = 1);
+ ThemeEqualizer.Direction := (ThemeIni.ReadInteger(Name, 'Direction', 0) = 1);
+ ThemeEqualizer.Alpha := ThemeIni.ReadInteger(Name, 'Alpha', 1);
+ ThemeEqualizer.Space := ThemeIni.ReadInteger(Name, 'Space', 1);
+ ThemeEqualizer.X := ThemeIni.ReadInteger(Name, 'X', 0);
+ ThemeEqualizer.Y := ThemeIni.ReadInteger(Name, 'Y', 0);
+ ThemeEqualizer.Z := ThemeIni.ReadInteger(Name, 'Z', 1);
+ ThemeEqualizer.W := ThemeIni.ReadInteger(Name, 'PieceW', 8);
+ ThemeEqualizer.H := ThemeIni.ReadInteger(Name, 'PieceH', 8);
+ ThemeEqualizer.Bands := ThemeIni.ReadInteger(Name, 'Bands', 5);
+ ThemeEqualizer.Length := ThemeIni.ReadInteger(Name, 'Length', 12);
+ ThemeEqualizer.Reflection := (ThemeIni.ReadInteger(Name, 'Reflection', 0) = 1);
+ ThemeEqualizer.ReflectionSpacing := ThemeIni.ReadFloat(Name, 'ReflectionSpacing', 15);
+
+ //Color
+ I := ColorExists(ThemeIni.ReadString(Name, 'Color', 'Black'));
+ if I >= 0 then begin
+ ThemeEqualizer.ColR := Color[I].RGB.R;
+ ThemeEqualizer.ColG := Color[I].RGB.G;
+ ThemeEqualizer.ColB := Color[I].RGB.B;
+ end
+ else begin
+ ThemeEqualizer.ColR := 0;
+ ThemeEqualizer.ColG := 0;
+ ThemeEqualizer.ColB := 0;
+ end;
+end;
+
procedure TTheme.LoadColors;
var
SL: TStringList;
diff --git a/src/menu/UMenuEqualizer.pas b/src/menu/UMenuEqualizer.pas
new file mode 100644
index 00000000..8cff606d
--- /dev/null
+++ b/src/menu/UMenuEqualizer.pas
@@ -0,0 +1,285 @@
+unit UMenuEqualizer;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses UMusic, UThemes;
+
+type
+ //----------------
+ //Tms_Equalizer
+ //Class displaying an equalizer (Songscreen)
+ //----------------
+ Tms_Equalizer = class(TObject)
+ private
+ FFTData: TFFTData; // moved here to avoid stack overflows
+ BandData: array of Byte;
+ RefreshTime: Cardinal;
+
+ Source: IAudioPlayback;
+
+ Procedure Analyse;
+ public
+ X: Integer;
+ Y: Integer;
+ Z: Real;
+
+ W: Integer;
+ H: Integer;
+ Space: Integer;
+
+ Visible: Boolean;
+ Alpha: real;
+ Color: TRGB;
+
+ Direction: Boolean;
+
+ BandLength: Integer;
+
+ Reflection: boolean;
+ Reflectionspacing: Real;
+
+
+ constructor Create(Source: IAudioPlayback; mySkin: TThemeEqualizer);
+
+ procedure Draw;
+
+ Procedure SetBands(Value: Byte);
+ Function GetBands: Byte;
+ Property Bands: Byte read GetBands write SetBands;
+ procedure SetSource(newSource: IAudioPlayback);
+ end;
+
+implementation
+uses math, SDL, gl, glext;
+
+
+constructor Tms_Equalizer.Create(Source: IAudioPlayback; mySkin: TThemeEqualizer);
+var I: Integer;
+begin
+ If (Source <> nil) then
+ begin
+ X := mySkin.X;
+ Y := mySkin.Y;
+ W := mySkin.W;
+ H := mySkin.H;
+ Z := mySkin.Z;
+
+ Space := mySkin.Space;
+
+ Visible := mySkin.Visible;
+ Alpha := mySkin.Alpha;
+ Color.R := mySkin.ColR;
+ Color.G := mySkin.ColG;
+ Color.B := mySkin.ColB;
+
+ Direction := mySkin.Direction;
+ Bands := mySkin.Bands;
+ BandLength := mySkin.Length;
+
+ Reflection := mySkin.Reflection;
+ Reflectionspacing := mySkin.Reflectionspacing;
+
+ Self.Source := Source;
+
+
+ //Check if Visible
+ If (Bands <= 0) OR
+ (BandLength <= 0) OR
+ (W <= 0) OR
+ (H <= 0) OR
+ (Alpha <= 0) then
+ Visible := False;
+
+ //ClearArray
+ For I := low(BandData) to high(BandData) do
+ BandData[I] := 3;
+ end
+ else
+ Visible := False;
+end;
+
+//--------
+// evaluate FFT-Data
+//--------
+Procedure Tms_Equalizer.Analyse;
+ var
+ I: Integer;
+ ChansPerBand: byte; // channels per band
+ MaxChannel: Integer;
+ Pos: Real;
+ CurBand: Integer;
+begin
+ Source.GetFFTData(FFTData);
+
+ Pos := 0;
+ // use only the first approx. 92 of 256 FFT-channels (approx. up to 8kHz
+ ChansPerBand := ceil(92 / Bands); // How much channels are used for one Band
+ MaxChannel := ChansPerBand * Bands - 1;
+
+ // Change Lengths
+ for i := 0 to MaxChannel do
+ begin
+ // Gain higher freq. data so that the bars are visible
+ if i > 35 then
+ FFTData[i] := FFTData[i] * 8
+ else if i > 11 then
+ FFTData[i] := FFTData[i] * 4.5
+ else
+ FFTData[i] := FFTData[i] * 1.1;
+
+ // clamp data
+ if (FFTData[i] > 1) then
+ FFTData[i] := 1;
+
+ // Get max. pos
+ if (FFTData[i] * BandLength > Pos) then
+ Pos := FFTData[i] * BandLength;
+
+ // Check if this is the last channel in the band
+ if ((i+1) mod ChansPerBand = 0) then
+ begin
+ CurBand := i div ChansPerBand;
+
+ // Smooth delay if new equalizer is lower than the old one
+ if ((BandData[CurBand] > Pos) and (BandData[CurBand] > 1)) then
+ BandData[CurBand] := BandData[CurBand] - 1
+ else
+ BandData[CurBand] := Round(Pos);
+
+ Pos := 0;
+ end;
+ end;
+end;
+
+//--------
+// Draw SpectrumAnalyser, Call Analyse
+//--------
+procedure Tms_Equalizer.Draw;
+ var
+ CurTime: Cardinal;
+ PosX, PosY: Real;
+ I, J: Integer;
+ Diff: Real;
+
+ Function GetAlpha(H: Single): Single;
+ begin
+ Result := (Alpha * 0.3) *(1 - H/(Bands * (W + Space)));
+ end;
+begin
+ If (Visible) AND not (AudioPlayback.Finished) then
+ begin
+ //Call Analyse if necessary
+ CurTime := SDL_GetTicks();
+ If (CurTime > RefreshTime) then
+ begin
+ Analyse;
+
+ RefreshTime := CurTime + 44;
+ end;
+
+ //Draw Equalizer Bands
+ // Setup OpenGL
+ glColorRGB(Color, Alpha);
+ glDisable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+
+ // Set position of the first equalizer bar
+ PosY := Y;
+ PosX := X;
+
+ // Draw bars for each band
+ for I := 0 to High(BandData) do
+ begin
+ // Reset to lower or left position depending on the drawing-direction
+ if Direction then // Vertical bars
+ // FIXME: Is Y the upper or lower coordinate?
+ PosY := Y //+ (H + Space) * BandLength
+ else // Horizontal bars
+ PosX := X;
+
+ // Draw the bar as a stack of blocks
+ for J := 1 to BandData[I] do
+ begin
+ // Draw block
+ glBegin(GL_QUADS);
+ glVertex3f(PosX, PosY, Z);
+ glVertex3f(PosX, PosY+H, Z);
+ glVertex3f(PosX+W, PosY+H, Z);
+ glVertex3f(PosX+W, PosY, Z);
+ glEnd;
+
+ If (Reflection) AND (J < BandLength div 2) then
+ begin
+ Diff := (Y-PosY) + H;
+
+ //Draw Reflection
+ If Direction then
+ begin
+ glBegin(GL_QUADS);
+ glColorRGB(Color, GetAlpha(Diff));
+ glVertex3f(PosX, Diff + Y + ReflectionSpacing, Z);
+ glVertex3f(PosX, Diff + Y+H + ReflectionSpacing, Z);
+ glVertex3f(PosX+W, Diff + Y+H + ReflectionSpacing, Z);
+ glVertex3f(PosX+W, Diff + Y + ReflectionSpacing, Z);
+ glColorRGB(Color, GetAlpha(Diff + H));
+ glEnd;
+ end
+ else
+ begin
+ glBegin(GL_QUADS);
+ glColorRGB(Color, GetAlpha(Diff));
+ glVertex3f(PosX, Diff + Y + (H + Space)*Bands + ReflectionSpacing, Z);
+ glVertex3f(PosX, Diff + Y+H + (H + Space)*Bands + ReflectionSpacing, Z);
+ glVertex3f(PosX+W, Diff + Y+H + (H + Space)*Bands + ReflectionSpacing, Z);
+ glVertex3f(PosX+W, Diff + Y + (H + Space)*Bands + ReflectionSpacing, Z);
+ glColorRGB(Color, GetAlpha(Diff + H));
+ glEnd;
+ end;
+
+ glColorRGB(Color, Alpha);
+ end;
+
+
+ // Calc position of the bar's next block
+ if Direction then // Vertical bars
+ PosY := PosY - H - Space
+ else // Horizontal bars
+ PosX := PosX + W + Space;
+ end;
+
+ // Calc position of the next bar
+ if Direction then // Vertical bars
+ PosX := PosX + W + Space
+ else // Horizontal bars
+ PosY := PosY + H + Space;
+ end;
+
+
+ end;
+end;
+
+Procedure Tms_Equalizer.SetBands(Value: Byte);
+begin
+ SetLength(BandData, Value);
+end;
+
+Function Tms_Equalizer.GetBands: Byte;
+begin
+ Result := Length(BandData);
+end;
+
+Procedure Tms_Equalizer.SetSource(newSource: IAudioPlayback);
+begin
+ If (newSource <> nil) then
+ Source := newSource;
+end;
+
+
+
+end. \ No newline at end of file
diff --git a/src/screens/UScreenSong.pas b/src/screens/UScreenSong.pas
index 1b5e4c41..f632afe0 100644
--- a/src/screens/UScreenSong.pas
+++ b/src/screens/UScreenSong.pas
@@ -110,7 +110,6 @@ type
procedure ShowCatTLCustom(Caption: String);// Show Custom Text in Top left
procedure HideCatTL;// Show Cat in Tob left
procedure Refresh; //Refresh Song Sorting
- procedure DrawEqualizer;
procedure ChangeMusic;
//Party Mode
procedure SelectRandomSong;
@@ -776,13 +775,8 @@ begin
// Randomize Patch
Randomize;
- {//Equalizer
- SetLength(EqualizerBands, Theme.Song.Equalizer.Bands);
- //ClearArray
- For I := low(EqualizerBands) to high(EqualizerBands) do
- EqualizerBands[I] := 3; }
- Equalizer := Tms_Equalizer.Create(AudioPlayback);
+ Equalizer := Tms_Equalizer.Create(AudioPlayback, Theme.Song.Equalizer);
if (Length(CatSongs.Song) > 0) then
Interaction := 0;
@@ -1495,8 +1489,6 @@ begin
for I := 0 to Length(Text) - 1 do
Text[I].Draw;
-
- //Draw Equalizer
Equalizer.Draw;
DrawExtensions;
@@ -1656,116 +1648,6 @@ begin
FixSelected2;
end;
-procedure TScreenSong.DrawEqualizer;
-{var
- I, J: Integer;
- ChansPerBand: byte; // channels per band
- MaxChannel: Integer;
- CurBand: Integer; // current band
- CurTime: Cardinal;
- PosX, PosY: Integer;
- Pos: Real; }
-begin
- { // Nothing to do if no music is played or an equalizer bar consists of no block
- if (AudioPlayback.Finished or (Theme.Song.Equalizer.Length <= 0)) then
- Exit;
-
- CurTime := SDL_GetTicks();
-
- // Evaluate FFT-data every 44 ms
- if (CurTime >= EqualizerTime) then
- begin
- EqualizerTime := CurTime + 44;
- AudioPlayback.GetFFTData(EqualizerData);
-
- Pos := 0;
- // use only the first approx. 92 of 256 FFT-channels (approx. up to 8kHz
- ChansPerBand := ceil(92 / Theme.Song.Equalizer.Bands); // How much channels are used for one Band
- MaxChannel := ChansPerBand * Theme.Song.Equalizer.Bands - 1;
-
- // Change Lengths
- for i := 0 to MaxChannel do
- begin
- // Gain higher freq. data so that the bars are visible
- if i > 35 then
- EqualizerData[i] := EqualizerData[i] * 8
- else if i > 11 then
- EqualizerData[i] := EqualizerData[i] * 4.5
- else
- EqualizerData[i] := EqualizerData[i] * 1.1;
-
- // clamp data
- if (EqualizerData[i] > 1) then
- EqualizerData[i] := 1;
-
- // Get max. pos
- if (EqualizerData[i] * Theme.Song.Equalizer.Length > Pos) then
- Pos := EqualizerData[i] * Theme.Song.Equalizer.Length;
-
- // Check if this is the last channel in the band
- if ((i+1) mod ChansPerBand = 0) then
- begin
- CurBand := i div ChansPerBand;
-
- // Smooth delay if new equalizer is lower than the old one
- if ((EqualizerBands[CurBand] > Pos) and (EqualizerBands[CurBand] > 1)) then
- EqualizerBands[CurBand] := EqualizerBands[CurBand] - 1
- else
- EqualizerBands[CurBand] := Round(Pos);
-
- Pos := 0;
- end;
- end;
-
- end;
-
- // Draw equalizer bands
-
- // Setup OpenGL
- glColor4f(Theme.Song.Equalizer.ColR, Theme.Song.Equalizer.ColG, Theme.Song.Equalizer.ColB, Theme.Song.Equalizer.Alpha);
- glDisable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
-
- // Set position of the first equalizer bar
- PosY := Theme.Song.Equalizer.Y;
- PosX := Theme.Song.Equalizer.X;
-
- // Draw bars for each band
- for I := 0 to High(EqualizerBands) do
- begin
- // Reset to lower or left position depending on the drawing-direction
- if Theme.Song.Equalizer.Direction then // Vertical bars
- // FIXME: Is Theme.Song.Equalizer.Y the upper or lower coordinate?
- PosY := Theme.Song.Equalizer.Y //+ (Theme.Song.Equalizer.H + Theme.Song.Equalizer.Space) * Theme.Song.Equalizer.Length
- else // Horizontal bars
- PosX := Theme.Song.Equalizer.X;
-
- // Draw the bar as a stack of blocks
- for J := 1 to EqualizerBands[I] do
- begin
- // Draw block
- glBegin(GL_QUADS);
- glVertex3f(PosX, PosY, Theme.Song.Equalizer.Z);
- glVertex3f(PosX, PosY+Theme.Song.Equalizer.H, Theme.Song.Equalizer.Z);
- glVertex3f(PosX+Theme.Song.Equalizer.W, PosY+Theme.Song.Equalizer.H, Theme.Song.Equalizer.Z);
- glVertex3f(PosX+Theme.Song.Equalizer.W, PosY, Theme.Song.Equalizer.Z);
- glEnd;
-
- // Calc position of the bar's next block
- if Theme.Song.Equalizer.Direction then // Vertical bars
- PosY := PosY - Theme.Song.Equalizer.H - Theme.Song.Equalizer.Space
- else // Horizontal bars
- PosX := PosX + Theme.Song.Equalizer.W + Theme.Song.Equalizer.Space;
- end;
-
- // Calc position of the next bar
- if Theme.Song.Equalizer.Direction then // Vertical bars
- PosX := PosX + Theme.Song.Equalizer.W + Theme.Song.Equalizer.Space
- else // Horizontal bars
- PosY := PosY + Theme.Song.Equalizer.H + Theme.Song.Equalizer.Space;
- end; }
-end;
-
procedure TScreenSong.SelectRandomSong;
var
I, I2: Integer;