CHANNEL MIXING

Started by hedgehog,

hedgehog

hi to all,
there's someone who knows how to mix some channels togheter and play (or write on a file) the result?
thanx Hh

Ingolf

#1
Get the data of all the channels using BASS_ChannelGetData into seperate buffers, and then add everything up to a master buffer. I have done this myself, but it is to complicated to post it here, as my functions use lots of other functions, that call other functions, etc.

If you want to play the data, do as above, but instead write it to a custom stream.

bigjim

Heres some code which was discussed in an earlier thread- translated from c++ if I remeber right.

Its a delphi unit consisting of a form(form1) and a button (button1)

unit mix2;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  type
  fakear = array[0..1] of smallint; //fake array to assign to callback buffer

var
  Form1: TForm1;
 handles : array[0..20] of dword; // array to hold the channel handles
// mixbuf : array of dword; // a dynamic array for the mixing buffer
 no_of_channels : integer; // the number of streams
 mixgain : float;
// buffa : ^fakear; // a pointer to the real buffer- but an array type


implementation

{$R *.DFM}

function Mixit(handle: HSTREAM; buffer: Pointer; length: DWORD; user: DWORD): DWORD; stdcall;
var
 buf: ^fakear;
 mixbuf: array of float;
 a,b,c: integer;
begin
 // allocate mixing buffer
 setlength(mixbuf,length div 2);
 ZeroMemory(mixbuf,(length div 2)*4);

 // mix the decoding channels
 buf:=buffer;
 for a:=0 to no_of_channels-1 do begin
   // may as well use "buffer" for temp storage :)
   b:=BASS_ChannelGetData(handles[a],buffer,length);
   for c:=0 to (b div 2)-1 do mixbuf[c]:= mixbuf[c]+buf[c];
 end;

 // put the final mix into "buffer"
 for a:=0 to (length div 2)-1 do begin
   b:= trunc(mixbuf[a] * mixgain);
   if b>32767 then b:=32767;
   if b<-32768 then b:=-32768;
   buf[a]:=b;
 end;

 mixbuf:=nil;
 Mixit:=length;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Bass_streamPlay(handles[2], FALSE, 0); // Play the custom stream
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Bass_Init(-1,44100,0, form1.handle); //init bass on default device
Bass_start; //start bass
handles[0] := Bass_StreamCreateFile(FALSE, pChar('one.mp3'), 0, 0, BASS_STREAM_DECODE); //load file 1
handles[1] := Bass_StreamCreateFile(FALSE, pChar('two.mp3'), 0, 0, BASS_STREAM_DECODE); //load file 2
no_of_channels := 2; // set the number of files loaded to 2
Bass_streamPlay(handles[0], FALSE, 0); // start the first file
Bass_streamPlay(handles[1], FALSE, 0); // start the second file
handles[2] := BASS_StreamCreate(44100, 0, @Mixit, 0); // Create a custom stream
mixgain := 1.0;
end;

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

end.


hedgehog

thanx a lot guys!!! i'll try as soon as possible this code!I want to try some effects on every channel too, kinda volume, bass & trebble, pan. Do you think this add-on will destroy my CPU? (all must be at real time, like real mixers!!!)
thanx Hh

CatHerder454

could someone tell me how to do this in VB?  ;D

thanks

hedgehog

this is a simple variation on your great decode function:
function Mixit(handle: HSTREAM; buffer: Pointer; length: DWORD; user: DWORD): DWORD; stdcall;
var
buf: ^fakear;
mixbuf: array of float;
a,b,c: integer;
x:float;
begin
// allocate mixing buffer
setlength(mixbuf,length div 2);
ZeroMemory(mixbuf,(length div 2)*4);

// mix the decoding channels
buf:=buffer;
for a:=0 to no_of_channels-1 do begin
  // may as well use "buffer" for temp storage :)
  b:=BASS_ChannelGetData(handles[a],buffer,length);

  for c:=0 to (b div 2)-1 do
  begin
  x:=buf[c];//new
  x:=x*mixgain[a];//new
  mixbuf[c]:= mixbuf[c]+x;
  end;
end;
by adding a mixgain to every channel (mixgain :array[0..20] of float;) you can set volume of every channel is mixed, now should be interest put an EQ to every single channel.. sholub be easy???  ???

VB translation is simple, take a look to VB examples given with bass...

Ingolf

I have made an equalizer by using the FFT algoritm, but it is not as easy as you think.

To make it easier for us, Microsoft has built-in an parametric equalizer into DirectX, which you can use in BASS (look in the help file, or this forum, for BASS_ChannelSetFX etc.)

Then by creating multiple param eq's, you have a multi-band equalizer, or whatever.