hi,

I'm trying to do spectrum analysis with FMOD (using MASM)

my code :

invoke FSOUND_Init, 44100, 32, 0
invoke FSOUND_Stream_OpenFile, OFFSET songtitle, 1, 0
mov FMOD, eax
invoke FSOUND_Stream_Play, FSOUND_FREE, eax
invoke FSOUND_DSP_GetFFTUnit
invoke FSOUND_DSP_SetActive, eax, 1

invoke FSOUND_DSP_GetSpectrum
mov spec, eax

after getting the 32 nd float from spec array
spec[32*4] right ?

but my spec array is empty, what am i doing wrong ?

thanks
Posted on 2003-05-16 08:12:31 by andras
Hi andras,

Here's what I had on a project I played with (it works fine):



invoke FSOUND_Init,44100,32,0
invoke FSOUND_Sample_Load,FSOUND_FREE ,addr mp3fname,1,0
mov fhan,eax
invoke FSOUND_PlaySound,FSOUND_FREE,fhan
mov fchan,eax
invoke FSOUND_DSP_GetFFTUnit
mov dspUnit,eax
invoke FSOUND_DSP_SetActive,dspUnit,TRUE
invoke FSOUND_DSP_GetSpectrum
mov floatBuff,eax
invoke FSOUND_GetMixer
mov mixertype,eax
;7 = MMXP6 ppro+ MMX mixer
invoke FSOUND_DSP_GetBufferLength
mov floatBuffLength,eax
;this is samples not bytes. To convert to bytes multiply by 4 for mmx mixers


I'm sorry I don't really remember much about it (it was a pretty quick throw-together thing just to see if I could get it to do something...I noticed I was saving all my returns in variables to look at and I was doing a dump of the array after invoke FSOUND_DSP_GetSpectrum so they should be appearing there). But then again, I was using Sample_Load and PlaySound instead of the Stream stuff.

Maybe someone got more into it than I did and could help us both !!
Posted on 2003-05-16 10:55:20 by gscundiff
thanks gscundiff for your fast answer !

By the way, how did you declare your variable floatBuff (the pointer to the array of 512 floats)?

I did like that :

spec REAL4 ?


I've coded all this in C++ already and was working fine so the problem is in my ASM code.

Andras
Posted on 2003-05-16 12:00:56 by andras
Hi andras,

Try:

spec dd 0

FSOUND_DSP_GetSpectrum returns a pointer to an array of 512 floating point values between 0.0 and 1.0.
Posted on 2003-05-16 12:52:34 by gscundiff
I've tried already...
Posted on 2003-05-16 12:57:13 by andras
Hi andras,

Is your program small enough to post or send in a P.M.? I could probably take a better stab at it.
Posted on 2003-05-16 13:05:01 by gscundiff
Hi andras,

Had a chance to look through your PM'd listing and I removed the LOCAL variable "spec:REAL4" in the DrawGLScene proc and put "spec dd 0" in the .data section instead since "spec" needs to be a pointer to the REAL-data array.

Then I put the following two lines in WinMain (after the "invoke FSOUND_DSP_SetActive, eax, 1") just to see if the .wav would play:

invoke FSOUND_DSP_GetSpectrum
mov spec,eax

The .wav played fine and I looked at the data at the memory location pointed to by "spec" and it was there so I think that should point you in the right direction.

I also found that the MyCALLBACK proc never gets called so "markers" doesn't get incremented and stays at 0 so "specstart" never gets set to "1" to allow the original "invoke FSOUND_DSP_GetSpectrum" to execute.

Since this is your work in progress, I didn't go any farther to track down why the MyCALLBACK proc wasn't being called...

Hope it helps!
Posted on 2003-05-16 16:43:16 by gscundiff
Hi andras,

After a further look (and a little sleep) I realized I needed to use a .wav with cues/tags/markers in it, and when I did, the MyCALLBACK (and the rest) worked so markers does get incremented.

However, it didn't do much except show a small green square in the middle of the window when "specstart" was set to 1. What's it supposed to be doing there?
Posted on 2003-05-17 04:34:23 by gscundiff
Hi gscundiff,

Sorry i didn't answer you yesterday ( i had to go to sleep, night falls down before in France..)

As you've found out MyCallback proc gets called if there are markers in the .wav file.
So when specstart turns to TRUE i would like the green square to flicker with the bass ( or just do anything else)
For this i'm doing beat detection examining the avarage of the first 32 floats in spec array.

.IF (specstart)

invoke FSOUND_DSP_GetSpectrum
mov spec, eax

fldz
xor ecx,ecx

.while (cx<32)

fld REAL4 PTR spec
fadd
inc cx
.endw

invoke FpuDiv, 0, 32, 0, SRC1_FPU or SRC2_DIMM or DEST_FPU

fcom pertek ;if avarage spectrum < 0.7
fstsw ax
sahf
jna end_if

invoke glColor4f, F03, F07, F03, F03
invoke glBegin,GL_QUADS
invoke glVertex3f, Fm01,Fm01, F00
invoke glVertex3f, F01,Fm01, F00
invoke glVertex3f, F01, F01, F00
invoke glVertex3f, Fm01, F01, F00
invoke glEnd

end_if:

;here i'm just trying to see the value of the avarage spectrum; a sort of debugging
invoke FpuFLtoA, 0, 10, ADDR avsztring, SRC1_FPU or SRC2_DIMM
invoke glRasterPos2f, Fm01, F00
invoke glPrint, addr avsztring

fstp st(0)


.ENDIF

What i can't understand that when i've tried to replace the spec with a static float array and it worked...
Declaring spec the way you said
spec dd 0
did not bring the expected result.
So how did you get those float values out of the array ?

Many thnx, Andras
Posted on 2003-05-17 06:59:29 by andras
Hi andras,

Ah, sleep....

I replaced your routine (from "fldz" through "fstp st(0)") with the following crudely crafted code from my earlier FMOD experiment:



mov esi,spec ;floatBuff ; pointer to buffer holding FP values
lea edx,SpecVal ; 512 byte buffer to hold the 512 values
xor ebx,ebx
xor ecx,ecx
finit
ConvFP2I:
mov eax,[esi+ebx]
mov FPtemp,eax ; temp reg
fld FPtemp
fmul MaxRange ; MaxRange real4 118.0
fistp FPtemp
mov eax,FPtemp
mov [edx+ecx],ax
add ebx,4
inc ecx
cmp ecx,31 ; ecx = up to 511
jle ConvFP2I


; now the FP data is converted into integer values from 0-118

xor eax,eax
mov SVptr,eax
mov eax,SpecBaseX
mov SpecX,eax
DoSpec:
invoke MoveToEx,hDC,SpecX,SpecBaseY,NULL
invoke SelectObject,hDC,GrnPen
lea edx,SpecVal
mov ebx,SVptr
xor eax,eax
mov al,[edx+ebx]
mov ecx,SpecBaseY
sub ecx,eax
mov SY,ecx
invoke LineTo,hDC,SpecX,SY
invoke SelectObject,hDC,BlkPen
invoke LineTo,hDC,SpecX,SpecMaxY
inc SpecX
inc SVptr
mov eax,SVptr
cmp eax,31 ; eax = up to 511
jle DoSpec



You'll need these in your .data block:



MaxRange real4 118.0
FPtemp dd 0
SpecVal db 512 dup(0)
SpecBaseX equ 27
SpecBaseY equ 544
SpecMaxY equ 426
SpecX dd 0
SpecY dd 0
SVptr dd 0
SY dd 0
BlkPen dd 0
GrnPen dd 0


And add this to your WinMain below the FSOUND stuff:



invoke CreatePen,PS_SOLID,0,00000000h ; color value 00BBGGRRh
mov BlkPen,eax
invoke CreatePen,PS_SOLID,0,0000FF00h
mov GrnPen,eax


It converts and displays the spectrum in your window, so give it a look.

BTW, I took out the "spec dd 0" in .data and changed your original "LOCAL i:WORD , spec:REAL4" to "LOCAL i:WORD , spec:DWORD" and it works fine.
Posted on 2003-05-17 09:07:05 by gscundiff
yep, it works !

I'll examine your code, it must give the solution for my problem.

GREAT !!!


Andras
Posted on 2003-05-17 09:54:29 by andras