Author Topic: Persistent EQ Settings  (Read 20582 times)

nobody

  • Guest
Persistent EQ Settings
« on: 10 Aug '03 - 07:45 »
I have followed the code in this post
http://un4seen.com/YaBB.cgi?board=bass&action=display&num=1040075762 to create a 10 band EQ and I was wondering if there was a way to make it so the settings would carry over from song to song until I did something like uncheck a checkbox and if I wanted to reapply the settings all I would have to do is check the box again.

Thx

nobody

  • Guest
Re: Persistent EQ Settings
« Reply #1 on: 11 Aug '03 - 01:28 »
anyone ???

Creadig

  • Posts: 71
Re: Persistent EQ Settings
« Reply #2 on: 11 Aug '03 - 02:17 »
you could save the eq. settings into a file. Then restore the settings when you need and apply the changes to the file you are playing.

Good luck.

nobody

  • Guest
Re: Persistent EQ Settings
« Reply #3 on: 11 Aug '03 - 04:23 »
I just tried moving the upeq procedure from being fired when a slider is moved to a timer which is set for 20ms and it works ok but I was wondering if there were any negatives to using this method seeing how the same code fires off 50 times a second. I know it will use more memory this way but other then that is there anything wrong with this method ?

Ian @ un4seen

  • Administrator
  • Posts: 26083
Re: Persistent EQ Settings
« Reply #4 on: 11 Aug '03 - 12:29 »
The best thing would be to simply declare an array of float/single, to store the gain for each EQ band. When an EQ slider is moved, you change the stored setting (as well as the playing channel's setting). When you create a new channel you set the gain of all the bands from those stored settings.

nobody

  • Guest
Re: Persistent EQ Settings
« Reply #5 on: 12 Aug '03 - 07:15 »
Have some sample code (delphi) that you would care to share which will accomplish this task.

bigjim

  • Posts: 232
Re: Persistent EQ Settings
« Reply #6 on: 12 Aug '03 - 12:47 »
Hi nobody:-

I think this is what you are needing to do:

Code: [Select]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Bass,
 ComCtrls, StdCtrls;

type
 TForm1 = class(TForm)
   TrackBar1: TTrackBar;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure upeq(bar_to_upt : integer; bar_val : single);
   procedure TrackBar1Change(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 streamh : DWORD; // Stream handle
 eq_handles : array[0..9] of BASS_FXPARAMEQ; // array of actual eq objects
 eq_ch_handles : array[0..9] of DWORD; // eq channel handles
 eq_settings : array[0..9, 0..2] of single; // inter song eq settings

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
 i : integer;
begin
Bass_Init(-1, 44100, 0, Form1.handle); //Init bass on default device
Bass_Start; // Start Bass
streamh := Bass_StreamCreateFile(FALSE, pChar('one.mp3'), 0, 0, 0); // Load a mp3
Bass_StreamPlay(streamh, FALSE, 0); // Play the mp3
for i := 0 to 9 do eq_ch_handles[i] := BASS_ChannelSetFX(streamh, BASS_FX_PARAMEQ); // Get handles for all bands
for i := 0 to 9 do // Set virtual bandwidth and gains
begin
 eq_settings[i, 1] := 5; //bandwidth for all bands = 5
 eq_settings[i, 2] := 0; // initial gain on all bands is 0
end;
 eq_settings[0, 0] := 100; // Some center freqs i made up
 eq_settings[1, 0] := 400;
 eq_settings[2, 0] := 800;
 eq_settings[3, 0] := 1600;
 eq_settings[4, 0] := 2400;
 eq_settings[5, 0] := 3200;
 eq_settings[6, 0] := 4000;
 eq_settings[7, 0] := 5000;
 eq_settings[8, 0] := 6000;
 eq_settings[9, 0] := 8000;

for i := 0 to 9 do // 0-9 = 10 bands
begin
 eq_handles[i].fCenter := eq_settings[i, 0]; // Copy over eq settings to actual eq objects
 eq_handles[i].fBandwidth := eq_settings[i, 1]; // Same Again
 eq_handles[i].fGain := eq_settings[i, 2]; // Same Again
 BASS_FXSetParameters(eq_ch_handles[i], @eq_handles[i]); // Actually set the parameters
end;

end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Bass_Free; // Free Bass
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
upeq(2, -trackbar1.position); // Update the eq band 2 with the position
end;

procedure TForm1.upeq(bar_to_upt : integer; bar_val : single);
begin
eq_settings[bar_to_upt, 0] := bar_val;  // Write gain to settings array for later use, etc
eq_handles[bar_to_upt].fGain := eq_settings[bar_to_upt, 0]; //Write eq object property settings from eq_settings array
BASS_FXSetParameters(eq_ch_handles[bar_to_upt], @eq_handles[bar_to_upt]); //Actually set the parameters
end;
end.


Iv only put one trackbar in cause i couldnt be bothered to make 10- but just add upeq(trackbar number, -trackbar value) under each trackbar you have.

All settings which would normally be lost when changin a song are held in the array eq_settings now and can be reaplyed to the song again if desired/ or overwritten if say a checkbox is ticked ;D

Hope this helps.
« Last Edit: 12 Aug '03 - 12:49 by bigjim »

nobody

  • Guest
Re: Persistent EQ Settings
« Reply #7 on: 12 Aug '03 - 19:02 »
Thanks for the code BigJim but unless I am missing somthing this code does the same thing your original code did in that you still have to move one of the trackbars to apply the settings on a new song.

Here is my version of your code and the only changes I made were that the loading/playing of the song now takes place on a button instead of when the form is created and I set different bandwidth and frequency settings but everyting else I believe is the same as in your code.

What I meant by prsistent is that that I "do not" have to change the sliders everytime I want the effect to be applied to a new song so lets say for example I moved all the sliders up to their max value before I even loaded the first song...what should happen is when I press the button the effect is applied without having to change the sliders again and if I get tired of that song and stop it and load a new song those settings again should automatically be applied to the new song without doing any moving of the sliders but as it is now that is not how it works.

From what I can see the code needs to be changes so that the upeq stuff gets fired when changing trackbar values AND when you are loading a song and that is why I was using a timer because is always firing off except when I uncheck my checkbox that is but the only problem with my method is that it takes up more cpu which I was trying to avoid.

Anyway I will step down from my soapbox now and hope you can makes sense out of my dribble and thx again for the code.

Code: [Select]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, bass, TFlatButtonUnit, TFlatCheckBoxUnit, SkinCtrls;

type
 TForm1 = class(TForm)
   s1: TspSkinTrackBar;
   s2: TspSkinTrackBar;
   s3: TspSkinTrackBar;
   s4: TspSkinTrackBar;
   s5: TspSkinTrackBar;
   s6: TspSkinTrackBar;
   s7: TspSkinTrackBar;
   s8: TspSkinTrackBar;
   s9: TspSkinTrackBar;
   s10: TspSkinTrackBar;
   enable_eq_cb: TFlatCheckBox;
   load_song_btn: TFlatButton;
   procedure FormCreate(Sender: TObject);
   procedure load_song_btnClick(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure upeq(bar_to_upt : integer; bar_val : single);
   procedure s1Change(Sender: TObject);

 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 streamh : hstream;
 eq_handles : array[0..9] of BASS_FXPARAMEQ; // array of actual eq objects
 eq_ch_handles : array[0..9] of DWORD; // eq channel handles
 eq_settings : array[0..9, 0..2] of single; // inter song eq settings

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
Bass_Init(-1, 44100, 0, Form1.handle); //Init bass on default device
Bass_Start; // Start Bass
end;

procedure TForm1.load_song_btnClick(Sender: TObject);
var
i : integer;
begin
Bass_StreamFree(streamh); // free any song if playing
Bass_Stop(); // Stop Bass
Bass_Start; // Start Bass
song := Bass_StreamCreateFile(FALSE, pChar('one.mp3'), 0, 0, 0); // Load a mp3
Bass_StreamPlay(streamh, FALSE, 0); // Play the mp3

for i := 0 to 9 do eq_ch_handles[i] := BASS_ChannelSetFX(streamh, BASS_FX_PARAMEQ); // Get handles for all bands
for i := 0 to 9 do // Set virtual bandwidth and gains
begin
eq_settings[i, 1] := 7; //bandwidth for all bands = 7
eq_settings[i, 2] := 0; // initial gain on all bands is 0
end;
eq_settings[0, 0] := 80; // Some center freqs i made up
eq_settings[1, 0] := 170;
eq_settings[2, 0] := 310;
eq_settings[3, 0] := 600;
eq_settings[4, 0] := 1000;
eq_settings[5, 0] := 3000;
eq_settings[6, 0] := 6000;
eq_settings[7, 0] := 10000;
eq_settings[8, 0] := 12000;
eq_settings[9, 0] := 14000;

for i := 0 to 9 do // 0-9 = 10 bands
begin
eq_handles[i].fCenter := eq_settings[i, 0]; // Copy over eq settings to actual eq objects
eq_handles[i].fBandwidth := eq_settings[i, 1]; // Same Again
eq_handles[i].fGain := eq_settings[i, 2]; // Same Again
BASS_FXSetParameters(eq_ch_handles[i], @eq_handles[i]); // Actually set the parameters
end;

end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Bass_Stop();
Bass_Free();
end;

procedure TForm1.upeq(bar_to_upt : integer; bar_val : single);
begin
eq_settings[bar_to_upt, 0] := bar_val;  // Write gain to settings array for later use, etc
eq_handles[bar_to_upt].fGain := eq_settings[bar_to_upt, 0]; //Write eq object property settings from eq_settings array
BASS_FXSetParameters(eq_ch_handles[bar_to_upt], @eq_handles[bar_to_upt]); //Actually set the parameters
end;

procedure TForm1.s1Change(Sender: TObject);
begin
upeq(1, + s1.value); // Update eq band 1 with the slider value;
upeq(2, + s2.Value);
upeq(3, + s3.Value);
upeq(4, + s4.Value);
upeq(5, + s5.Value);
upeq(6, + s6.Value);
upeq(7, + s7.Value);
upeq(8, + s8.Value);
upeq(9, + s9.Value);
upeq(10, + s10.Value);
end;

end.


BTW why is it in your code (and other ppls code I see) they use  (something - trackbar.position) which works for horizonal trackbars but has the opposite effect you would normally see when using vertical trackbars which is the case for eq trackbars ???

nobody

  • Guest
Re: Persistent EQ Settings
« Reply #8 on: 12 Aug '03 - 19:20 »
I did manage to get your code to work when using the play button that I was using by adding the upeq... stuff to the buttons OnClick event but this is not going to help when doing something like cycling through the playlist (ie playing one song after another without any user intervention) because something like that is going to need a timer so I guess I am stuck with using the timer anyway ... well thx again for the code.

Irrational86

  • Posts: 960
Re: Persistent EQ Settings
« Reply #9 on: 12 Aug '03 - 20:46 »
nobody...one thing, you have posted a lot, so i guess it should be only fair to register now...

As to your code, this is all you need...
Code: [Select]
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, bass, TFlatButtonUnit, TFlatCheckBoxUnit, SkinCtrls;

type
TForm1 = class(TForm)
  s1: TspSkinTrackBar;
  s2: TspSkinTrackBar;
  s3: TspSkinTrackBar;
  s4: TspSkinTrackBar;
  s5: TspSkinTrackBar;
  s6: TspSkinTrackBar;
  s7: TspSkinTrackBar;
  s8: TspSkinTrackBar;
  s9: TspSkinTrackBar;
  s10: TspSkinTrackBar;
  enable_eq_cb: TFlatCheckBox;
  load_song_btn: TFlatButton;
  procedure FormCreate(Sender: TObject);
  procedure load_song_btnClick(Sender: TObject);
  procedure FormDestroy(Sender: TObject);
  procedure upeq(bar_to_upt : integer; bar_val : single);
  procedure s1Change(Sender: TObject);

private
  { Private declarations }
public
  { Public declarations }
end;

var
Form1: TForm1;
streamh : hstream;
eq_handles : array[0..9] of BASS_FXPARAMEQ; // array of actual eq objects
eq_ch_handles : array[0..9] of DWORD; // eq channel handles
eq_settings : array[0..9, 0..2] of single; // inter song eq settings

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
Bass_Init(-1, 44100, 0, Form1.handle); //Init bass on default device
Bass_Start; // Start Bass
for i := 0 to 9 do // Set virtual bandwidth and gains
begin
eq_settings[i, 1] := 7; //bandwidth for all bands = 7
eq_settings[i, 2] := 0; // initial gain on all bands is 0
end;
eq_settings[0, 0] := 80; // Some center freqs i made up
eq_settings[1, 0] := 170;
eq_settings[2, 0] := 310;
eq_settings[3, 0] := 600;
eq_settings[4, 0] := 1000;
eq_settings[5, 0] := 3000;
eq_settings[6, 0] := 6000;
eq_settings[7, 0] := 10000;
eq_settings[8, 0] := 12000;
eq_settings[9, 0] := 14000;
end;

procedure TForm1.load_song_btnClick(Sender: TObject);
var
i : integer;
begin
Bass_StreamFree(streamh); // free any song if playing
Bass_Stop(); // Stop Bass
Bass_Start; // Start Bass
song := Bass_StreamCreateFile(FALSE, pChar('one.mp3'), 0, 0, 0); // Load a mp3
Bass_StreamPlay(streamh, FALSE, 0); // Play the mp3

for i := 0 to 9 do eq_ch_handles[i] := BASS_ChannelSetFX(streamh, BASS_FX_PARAMEQ); // Get handles for all bands
s1Change(nil);
for i := 0 to 9 do // 0-9 = 10 bands
begin
eq_handles[i].fCenter := eq_settings[i, 0]; // Copy over eq settings to actual eq objects
eq_handles[i].fBandwidth := eq_settings[i, 1]; // Same Again
eq_handles[i].fGain := eq_settings[i, 2]; // Same Again
BASS_FXSetParameters(eq_ch_handles[i], @eq_handles[i]); // Actually set the parameters
end;

end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Bass_Stop();
Bass_Free();
end;

procedure TForm1.upeq(bar_to_upt : integer; bar_val : single);
begin
eq_settings[bar_to_upt, 0] := bar_val;  // Write gain to settings array for later use, etc
eq_handles[bar_to_upt].fGain := eq_settings[bar_to_upt, 0]; //Write eq object property settings from eq_settings array
BASS_FXSetParameters(eq_ch_handles[bar_to_upt], @eq_handles[bar_to_upt]); //Actually set the parameters
end;

procedure TForm1.s1Change(Sender: TObject);
begin
upeq(1, + s1.value); // Update eq band 1 with the slider value;
upeq(2, + s2.Value);
upeq(3, + s3.Value);
upeq(4, + s4.Value);
upeq(5, + s5.Value);
upeq(6, + s6.Value);
upeq(7, + s7.Value);
upeq(8, + s8.Value);
upeq(9, + s9.Value);
upeq(10, + s10.Value);
end;

end.

This is your code modified, try this one..it will work..

nobody

  • Guest
Re: Persistent EQ Settings
« Reply #10 on: 12 Aug '03 - 21:29 »
XMinioNX

Thanks for the code but as I said I was able to modify the code BigJim posted so that it would work when using the trackbars as well as when the play button is pressed.

However, none of the methods discussed so far will work on something like a continous play feature where it plays one song and automatically plays the next song in the list when the first one is over without any user intervention.

This kind of thing will require a Timer to check when the first song is over and then start the next one and so it's the only way I know that will work for "ALL" senerios (OnButtonClick, OnSliderChange, OnAutomaticPlay...)

As far as registering goes I am not sure what benefit it would be.

bigjim

  • Posts: 232
Re: Persistent EQ Settings
« Reply #11 on: 13 Aug '03 - 04:59 »
Hey nobody:

I dont think you are understanding this quite right :(

I was just showing the use of an extra array (eq_settings) just to show the use independantly from song changes.

You would apply these to each song you loaded.

You see in this piece of my code for example:

Code: [Select]

eq_settings[bar_to_upt, 0] := bar_val;  // Write gain to settings array for later use, etc
eq_handles[bar_to_upt].fGain := eq_settings[bar_to_upt, 0]; //Write eq object property settings


I could have put

Code: [Select]

eq_handles[bar_to_upt].fGain := bar_val


However i chose to make evident that its being saved to a totally independant array.

Whenever you load a song- use a loop to apply these settings to your new song...

OK ILL POST CODE TOMORROW WHEN IM MORE AWAKE...
THERES NO NEED FOR TIMERS AND WHAT NOT... JUST A FEW CAREFULLY PLACED PROCEDURES 8)

Ian @ un4seen

  • Administrator
  • Posts: 26083
Re: Persistent EQ Settings
« Reply #12 on: 13 Aug '03 - 14:48 »
If you're using an array of BASS_FXPARAMEQ structures anyway, there's no need for the array of float/singles - that's just duplicating the same info :)

Initialize the array at startup, and when you create a new stream, simply apply the array to the EQ bands...
Code: [Select]
procedure TForm1.FormCreate(Sender: TObject);
var
i : integer;
begin
Bass_Init(-1, 44100, 0, Form1.handle); //Init bass on default device
Bass_Start; // Start Bass

for i := 0 to 9 do // 0-9 = 10 bands
begin
eq_handles[i].fBandwidth := 7; //bandwidth for all bands = 7
eq_handles[i].fGain := 0; // initial gain on all bands is 0
end;
eq_handles[0].fBandwidth := 80; // Some center freqs i made up
eq_handles[1].fBandwidth := 170;
eq_handles[2].fBandwidth := 310;
eq_handles[3].fBandwidth := 600;
eq_handles[4].fBandwidth := 1000;
eq_handles[5].fBandwidth := 3000;
eq_handles[6].fBandwidth := 6000;
eq_handles[7].fBandwidth := 10000;
eq_handles[8].fBandwidth := 12000;
eq_handles[9].fBandwidth := 14000;
end;

procedure TForm1.load_song_btnClick(Sender: TObject);
var
i : integer;
begin
Bass_StreamFree(streamh); // free any song if playing
streamh := Bass_StreamCreateFile(FALSE, pChar('one.mp3'), 0, 0, 0); // Load a mp3

for i := 0 to 9 do // 0-9 = 10 bands
begin
eq_ch_handles[i] := BASS_ChannelSetFX(streamh, BASS_FX_PARAMEQ); // Create the band
BASS_FXSetParameters(eq_ch_handles[i], @eq_handles[i]); // Actually set the parameters
end;

Bass_StreamPlay(streamh, FALSE, 0); // Play the mp3
end;


For clarity, I'd also change the variable names a bit - "eq_handles" isn't storing handles (I'd call it "eq_params"), and then "eq_ch_handles" could be "eq_handles" :)

bigjim

  • Posts: 232
Re: Persistent EQ Settings
« Reply #13 on: 13 Aug '03 - 21:24 »
Yep your right Ian:-

I was pretty pushed for time when i wrote that.

I think i used the extra array because i wasnt sure if changing songs had any effect on the BASS_FXPARAMEQ structures. ???

However when i think about it- it dosnt ::)

Well anyway ill leave this for the minute cause im having a fight with an asp website im writing for someone


nobody

  • Guest
Re: Persistent EQ Settings
« Reply #14 on: 14 Aug '03 - 01:03 »
I am a php coder by trade and I will build ur website if you will build my player :P

bigjim

  • Posts: 232
Re: Persistent EQ Settings
« Reply #15 on: 15 Aug '03 - 01:29 »
Thanx for the very generous offer nobody - i also am native php, but im just about finished- touch wood.

I am happy to help with anything within your project- but unfortuantly i am too busy at the mo to write the full code.

AGGGGHHHHH if only i had the time i would be onto winamp 12 by now :(