Author Topic: display the entire wave ?  (Read 6778 times)

Uwe

  • Posts: 10
display the entire wave ?
« on: 4 Jun '03 - 00:21 »
hi, me again... so soon ;)


i've searched the Threads in here and sure... i got some
verry good tips. But now i'm helpless. I don't understand the routines that i found here for displaying waveforms so i hope i may ask again ;)
I have a  TPaintbox, width 1000px, height 200(maybe)px.
What i want is to display the entire waveform of the
file(mp3).

Is there any Delphi solution out there ?





« Last Edit: 4 Jun '03 - 00:36 by Uwe »

bigjim

  • Posts: 232
Re: display the entire wave ?
« Reply #1 on: 4 Jun '03 - 07:39 »
Hi- I've written you a little delphi example to get you started- you can build quite substantially on it to allow zooming, etc.

I would consider using the bitblt commands with image boxes instead of paintboxes and using threads instead of timers as they are faster.

But here you go- you should be able to get the basic idea of how to do it ;)
http://www.ingenious.demon.co.uk/wave.zip
« Last Edit: 4 Jun '03 - 07:39 by bigjim »

Sebastian_Mares

  • Guest
Re: display the entire wave ?
« Reply #2 on: 4 Jun '03 - 09:06 »
Would it be possible for you to write a Visual Basic sample? I am looking for something like that, too, but without any success. :-/

bigjim

  • Posts: 232
Re: display the entire wave ?
« Reply #3 on: 4 Jun '03 - 09:13 »
Right- very simple example in vb for displaying a whole file. :)

http://www.ingenious.demon.co.uk/wavevb.zip
« Last Edit: 4 Jun '03 - 10:26 by bigjim »

Uwe

  • Posts: 10
Re: display the entire wave ?
« Reply #4 on: 4 Jun '03 - 13:24 »
big thx to bigjim ;)


Hmm,i think im tooo stupid. I don't know much about Waveforms a.s.o but ok, here's what i figured out...

Code: [Select]

Bass_ChannelGetData(file1h, @buff, 100000); // Get data- lower the number to zoom in horizontally
/////////////
   minL := 0; // Set variables
   maxL := 0;
   minR := 0;
   maxR := 0;
   j := -1;
   for i := 0 to 50000 do // Half of the buffer size
   begin
     j := j + 1;
     if buff[j] > maxL then maxL := buff[j]; // Find left channel min & max
     if buff[j] < minL then minL := buff[j];
     j := j + 1;
     if buff[j] > maxR then maxR := buff[j]; // Find right channel min & max
     if buff[j] < minR then minR := buff[j];
   end;


if i understand, this piece of code give me ONE! value of the Waveform.
So where is the sentence to get 100000 values
with ChannelGetData ? (xcuse my maybe stupid questions ;) )
How can i get the "WaveData" at position(x) in the File?

Maybe someone knows a source where i can find a introduction
on "ChannelGetData" and what i can do with the values ;)

bigjim

  • Posts: 232
Re: display the entire wave ?
« Reply #5 on: 4 Jun '03 - 14:02 »
You can find quite alot of information in the bass help file ;)

But sorry I should have clarified my methods a bit clearer.

* A wave from a song when you see it in a program such as goldwave has a positive value(above the centre line) and a negative value (below the line)

* So normally each positive value will have a corresponding negative value. If you plot each of these consecutivley you will see the wave fully zoomed in.

Quote

if i understand, this piece of code give me ONE! value of the Waveform.
So where is the sentence to get 100000 values


* From what i gather you want to zoom out to fit the song on a screen so you need to take a sort of average. Except you do NOT take an average as such as this does NOT work.

* You simply get the largest value and lowest value from every n samples. I picked 100000 samples cause it allowed the song I was using to fit on the screen.

* Basically the more samples you look at in turn the more zoomed out your wave will be. And the less samples you ask for the more zoomed in your wave will ulimately be.

**** This is beacuse as you take samples with Bass_ChannelGetData the position you at in the file moves on.

Quote

on "ChannelGetData" and what i can do with the values


** Bass_ChannelGetData gives you access to the raw data of the file and allows you to do basically whatever you want with. ie visualizations, bpm detection, etc

finally

Quote

How can i get the "WaveData" at position(x) in the File?


You can see what data is currently plotted by using Bass_ChannelBytes2Seconds(file_handle, Bass_ChannelGetPosition(file_handle))

and you can seek as normal if you want to plot from a poision in the file with Bass_ChannelSetPosition(xxxxxx)

Hope this helps.

Uwe

  • Posts: 10
Re: display the entire wave ?
« Reply #6 on: 4 Jun '03 - 23:07 »
o.k.   im going MAD ;)

after studying the Forums, your sample and so on i've tried
a little to get handy with the ChannelGetData, but ...
in fact: i think i'm too stupid...
so here's my Code :

Code: [Select]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Controls, Forms,BASS, ExtCtrls, StdCtrls,;

type
 TForm1 = class(TForm)
   Timer1: TTimer;
   Label1: TLabel;
   Label2: TLabel;
   Label3: TLabel;
   Label4: TLabel;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
 private
   { Private-Deklarationen }
 public
   { Public-Deklarationen }
 end;

var
 Form1: TForm1;
 P1:DWORD;
 decodeb:array[0..4410] of smallint;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
// BASS init
BASS_Init(-1,44100,0,Handle);
BASS_Start();
// Create MP3-Stream
P1:=BASS_StreamCreateFile(FALSE,pchar('c:\test.mp3'),0,0,BASS_SAMPLE_FLOAT);
// ...and start...
BASS_Streamplay(p1,false,0);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
// Freeing Memory
BASS_StreamFree(P1);
BASS_Stop();
BASS_Free();
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var             i:Integer;
   Maxval,Minval:smallint;
begin
MaxVal:=0;
MinVal:=0;
// Getting Sample Data
BASS_ChannelGetData(P1,@decodeb,4410);
for i := 0 to 2205 do
begin
if decodeb[i*2] > maxval then maxval := decodeb[i*2];
if decodeb[i*2] < minval then minval := decodeb[i*2];
end;
// Just to check what happens...
Label1.Caption:=inttostr(maxval);
Label2.Caption:=inttostr(minval);
Label3.Caption:=inttostr(BASS_ChannelGetPosition(P1));
end;

end.


The Stream starts playing, but only the "Position"-Label (Label3) works.
Label1 and Label2 should display the current min/max Values
of the sample but they do not...
Can someone tell me why ? */mesmilestobigjim*

(i know, it's not a DECODE-Stream because i want to
"hear what i do" ;) )


bigjim

  • Posts: 232
Re: display the entire wave ?
« Reply #7 on: 4 Jun '03 - 23:23 »
Can you elaborate why you are using BASS_SAMPLE_FLOAT as this is not any good with my method- if it works the way I think it does.

[i*2] will not work either as the sample buffer is interleaved:

ie:

BUFFER POS |0 1 2 3 4 5 6 7 8 9
SAMPLE     |1 1 2 2 3 3 4 4 5 5
CHANNEL    |L R L R L R L R L R

If you want to hear what you do its best to use two streams (one decoding, one playing)-

if you can tell me WHAT you want to do or email me a diagram if your first lang isnt english I can guide you through it.

I've written code for realtime display like "traktor" and pre-render like "goldwave" and actaully most of the diritives by now. ;)

If you need help try my msn messenger with un: ag_ingenious
« Last Edit: 4 Jun '03 - 23:33 by bigjim »

Uwe

  • Posts: 10
Re: display the entire wave ?
« Reply #8 on: 5 Jun '03 - 04:57 »
YES!
Thats what 1 get now:
Klick button, select file, display waveform...
based mostly on bigjim's nice example (thx again ;) )
Code: [Select]

while BASS_ChannelGetPosition(P1)<BASS_StreamGetlength(P1) do
begin
BASS_ChannelGetData(P1,@decodeb,2956);
maxval:=0;
Minval:=0;
for i := 0 to 2956 div 2 do
 begin
 if decodeb[i*2] > maxval then maxval := decodeb[i*2];
 if decodeb[i*2] < minval then minval := decodeb[i*2];
 if decodeb[i] > maxval then maxval := decodeb[i];
 if decodeb[i] < minval then minval := decodeb[i];
 end;
new(WaveData);
WaveData.min:=minval;
WaveData.max:=maxval;
Waveform.Add(WaveData);
end;


I store the wavedata in a Tlist for further operations.
But there's one thing:
This is SLOOOOOW...
It take about 6 seconds to scan a 3.30 MP3-File and
1min 30seconds for a 1hour MP3-File.
ok, i could increase the ChannelGetData Value but
this would change my "resolution" ;)

Any Ideas ?

Sebastian_Mares

  • Guest
Re: display the entire wave ?
« Reply #9 on: 5 Jun '03 - 08:21 »
Quote

Right- very simple example in vb for displaying a whole file. :)

http://www.ingenious.demon.co.uk/wavevb.zip


Thank you very much!

Ingolf

  • Posts: 81
Re: display the entire wave ?
« Reply #10 on: 5 Jun '03 - 11:39 »
is this correct?

Code: [Select]
BASS_ChannelGetData(P1,@decodeb,4410);

I think ChannelGetData needs the length of the buffer in bytes, is it not?

So, if the buffer is [0..4410] of smallint, then you would have 4411 samples * stereo * bits, would be 4411 * 2 * 2, if using 16 bits stereo.

Code: [Select]
BASS_ChannelGetData(P1,@decodeb,17644);

Tell me if i'm blabbing.

Creadig

  • Posts: 71
Re: display the entire wave ?
« Reply #11 on: 10 Jun '03 - 04:52 »
BigJim. The link of vb sample for display the entire wave from an mp3 as broken. Please can u send me this sample or check the link???