20 May '13 - 13:50 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1]
  Reply  |  Print  
Author Topic: Multi-band Compressor/Limiter  (Read 738 times)
JesseW
Posts: 6


« on: 11 Sep '12 - 19:29 »
Reply with quoteQuote

Hello,

I've been thinking on writing a multi-band compressor/limiter using BASS. But I need some idea's on how you can filter the incoming signal (recorded from Line In or from a HTTP stream) to multiple bands.

One idea I have is to have a decoding mixer channel with input from various sources. Copy that channel to separate bands and then do the filtering and compression and mix it back together. But I don't know on how to do this the right way on copying the channel to multiple ones.

Does anybody have an idea or suggestion on how to do this?

JesseW
Logged
ken
Posts: 630


« Reply #1 on: 12 Sep '12 - 08:02 »
Reply with quoteQuote

To simplify it you split up the signal in 3 or more "bands" by crossover filter, then process each band separately, at last mix the bands together.



Here is a more complex way to do it (BreakAway processor sounds very good)



I like to see something what you come up with.

Logged
JesseW
Posts: 6


« Reply #2 on: 12 Sep '12 - 21:25 »
Reply with quoteQuote

Well, I've been working on it this evening with succes.

The BassMix splitter streams are really something I didn't look into, but it was the thing I just needed to split a mixer into separate bands.

I'm using the DcDSP components for the compression and dynamic amplifying. As these components return information about gain reduction for the GUI.

The code I have at the moment:
unit Main;

interface

...

var
  MainForm: TMainForm;
  SINChannel : hrecord;
  SMixer : DWORD;
  AGCBass : DWORD;
  AGCHigh : DWORD;
  Band1 : DWORD;
  Band2 : DWORD;
  Band3 : DWORD;
  Band4 : DWORD;
  Band5 : DWORD;
  Band6 : DWORD;
  OMixer : DWORD;
  MBMixer : DWORD;

  AGCLowHandle : hDSP;
  AGCHighHandle : hDSP;
  Band1Handle : hDSP;
  Band2Handle : hDSP;
  Band3Handle : hDSP;
  Band4Handle : hDSP;
  Band5Handle : hDSP;
  Band6Handle : hDSP;
  FLimiterHandle : hDSP;

implementation

{$R *.dfm}

procedure AGCLowProc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.AGCBP1.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.AGC1.Process(Buffer, Length, 44100, 16, 2, False);
end;

procedure AGCHighProc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.AGCBP2.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.AGC2.Process(Buffer, Length, 44100, 16, 2, False);
end;



procedure Band1Proc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.DCBandPass1.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.DCCompressor1.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.MBLim1.Process(Buffer, Length, 44100, 16, 2, False);
end;

procedure Band2Proc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.DCBandPass2.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.DCCompressor2.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.MBLim2.Process(Buffer, Length, 44100, 16, 2, False);
end;

procedure Band3Proc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.DCBandPass3.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.DCCompressor3.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.MBLim3.Process(Buffer, Length, 44100, 16, 2, False);
end;

procedure Band4Proc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.DCBandPass4.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.DCCompressor4.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.MBLim4.Process(Buffer, Length, 44100, 16, 2, False);
end;

procedure Band5Proc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.DCBandPass5.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.DCCompressor5.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.MBLim5.Process(Buffer, Length, 44100, 16, 2, False);
end;

procedure Band6Proc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.DCBandPass6.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.DCCompressor6.Process(Buffer, Length, 44100, 16, 2, False);
  MainForm.MBLim6.Process(Buffer, Length, 44100, 16, 2, False);
end;

procedure FLimiterProc(Handle : HDSP; channel: DWORD; buffer: Pointer; length: DWORD; user: DWORD); stdcall;
var
  BufTemp : Pointer;
  LenTemp : Dword;
begin
  MainForm.FLimiter12.Process(Buffer, Length, 44100, 16, 2, False);
end;


procedure TMainForm.FormCreate(Sender: TObject);
var
  TempChan : DWORD;
begin
  BASS_Init(-1, 44100, 0, Application.Handle, 0);

  //Set Bandpasses correct!
  AGCBP1.CutoffLow[0] := 40;
  AGCBP1.CutoffHigh[0] := 300;

  AGCBP2.CutoffLow[0] := 300;
  AGCBP2.CutoffHigh[0] := 15000;

  DCBandPass1.CutoffLow[0] := 40;
  DCBandPass1.CutoffHigh[0] := 270;

  DCBandPass2.CutoffLow[0] := 270;
  DCBandPass2.CutoffHigh[0] := 3500;

  DCBandPass3.CutoffLow[0] := 3500;
  DCBandPass3.CutoffHigh[0] := 6000;

  DCBandPass4.CutoffLow[0] := 6000;
  DCBandPass4.CutoffHigh[0] := 9000;

  DCBandPass5.CutoffLow[0] := 9000;
  DCBandPass5.CutoffHigh[0] := 12500;

  DCBandPass6.CutoffLow[0] := 12500;
  DCBandPass6.CutoffHigh[0] := 15000;


  //Make Source mixer
  SMixer := BASS_Mixer_StreamCreate(44100, 2, BASS_MIXER_NONSTOP or BASS_Stream_Decode);
  //BASS_ChannelPlay(SMixer, True);

  //Just start recording from the default record device
  BASS_RecordInit(-1);
  SINChannel := BASS_RecordStart(192000, 2, BASS_Stream_Decode, nil, 0);
  //Add source to the Source Mixer
  BASS_Mixer_StreamAddChannel(Main.SMixer, SINChannel, 0);

  //Split bands to AGC
  AGCBass := BASS_Split_StreamCreate(SMixer, BASS_STREAM_DECODE, nil);
  AGCHigh := BASS_Split_StreamCreate(SMixer, BASS_STREAM_DECODE, nil);

  //Set AGC DSP's on the two bands
  AGCLowHandle := BASS_ChannelSetDSP(AGCBass, @AGCLowProc, 0, 1);
  AGCHighHandle := BASS_ChannelSetDSP(AGCHigh, @AGCHighProc, 0, 1);

  //MB Mixer
  MBMixer := BASS_Mixer_StreamCreate(44100, 2, BASS_Mixer_Nonstop or BASS_Stream_Decode);
  BASS_Mixer_StreamAddChannel(Main.MBMixer, AGCBass, 0);
  BASS_Mixer_StreamAddChannel(Main.MBMixer, AGCHigh, 0);


  //Make the bands for the multiband compressor/limiter
  Band1 := BASS_Split_StreamCreate(MBMixer, BASS_STREAM_DECODE, nil);
  Band2 := BASS_Split_StreamCreate(MBMixer, BASS_STREAM_DECODE, nil);
  Band3 := BASS_Split_StreamCreate(MBMixer, BASS_STREAM_DECODE, nil);
  Band4 := BASS_Split_StreamCreate(MBMixer, BASS_STREAM_DECODE, nil);
  Band5 := BASS_Split_StreamCreate(MBMixer, BASS_STREAM_DECODE, nil);
  Band6 := BASS_Split_StreamCreate(MBMixer, BASS_STREAM_DECODE, nil);


  //Set DSP on the bands
  Band1Handle := BASS_ChannelSetDSP(Band1, @Band1Proc, 0, 1);
  Band2Handle := BASS_ChannelSetDSP(Band2, @Band2Proc, 0, 1);
  Band3Handle := BASS_ChannelSetDSP(Band3, @Band3Proc, 0, 1);
  Band4Handle := BASS_ChannelSetDSP(Band4, @Band4Proc, 0, 1);
  Band5Handle := BASS_ChannelSetDSP(Band5, @Band5Proc, 0, 1);
  Band6Handle := BASS_ChannelSetDSP(Band6, @Band6Proc, 0, 1);

  //Make the output mixer
  OMixer := BASS_Mixer_StreamCreate(44100, 2, BASS_Mixer_Nonstop);

  //Add the bands to the output mixer
  BASS_Mixer_StreamAddChannel(Main.OMixer, Band1, 0);
  BASS_Mixer_StreamAddChannel(Main.OMixer, Band2, 0);
  BASS_Mixer_StreamAddChannel(Main.OMixer, Band3, 0);
  BASS_Mixer_StreamAddChannel(Main.OMixer, Band4, 0);
  BASS_Mixer_StreamAddChannel(Main.OMixer, Band5, 0);
  BASS_Mixer_StreamAddChannel(Main.OMixer, Band6, 0);

  BASS_ChannelPlay(OMixer, True);
end;
Logged
dennis_margelys
Posts: 66


« Reply #3 on: 14 Nov '12 - 22:40 »
Reply with quoteQuote

hi!!

i see you use an AGC and you use a dsp to implement it can you please tell me where to find an example of dsp for it.... i also need to develop an AGC ... i've looked into musicdsp.org but no luck finding an AGC DSP...

thanks...
Logged
Chris
Posts: 1504


« Reply #4 on: 15 Nov '12 - 10:48 »
Reply with quoteQuote

AGC ? The AGC from Jobbys bass_fx will working excellent and fine!
Logged
dennis_margelys
Posts: 66


« Reply #5 on: 15 Nov '12 - 12:19 »
Reply with quoteQuote

do you mean the damp example??? if so we don't understand how can it be an AGC because every time we try to adjust the loudness of an audio file it doesn't keep the level i set to it... ie if i set fgain to 1 it keep increasing this value (gain) if i set it to 0 it does nothing... so we don't get it... and we don't understand the ftarget and fquiet parameter there....i repeat if damp example is consider as an AGC....
Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines