I want to write my own DSP (Digital Signal Processing) - Unit for FMOD.
right only numbers > 0 ... but can you play a sine without numbers < 0?  
Code: Select all
Declare MAKELONG(low, high)
Declare HIWORD(Value) 
Declare LOWORD(Value) 
Declare Unload()
Declare Stop()
Declare.l Lowpass(ptOriginalbuffer.l, ptNewbuffer.l, Length.l, Param.l)
Declare FFT() 
Global Volume.l
Global Quit.l
Global Play.l
Global Stream_ID.l
Global LowPassID.l
Global FFTFrequenz.l
Global Wert.l
Volume = 25
Wert = 2000
Quit = #False
Play = #False
Pause.l = #False
FFT_ID.l = #Null
Stream_ID = #Null
LowPassID = #Null
FFTUnit_ID.l = #Null
LowpassUnit_ID.l = #Null
Temp.s = ""
FFTFrequenz = 30
Soundfile.s = ""
Structure fftarray 
  Value.f[512] 
EndStructure
If OpenWindow(1,0,0,520,350,#PB_Window_SystemMenu|#PB_Window_ScreenCentered, "FMOD FFT-Spectrum Visualization") <> #False
  
  If FSOUND_SetBufferSize(125) <> #False
    If FSOUND_Init(44100, 32, 0) <> #False
      If CreateMenu(1, WindowID(1)) <> #False And CreateGadgetList(WindowID(1)) <> #False
        MenuItem(1, "Open") 
        MenuItem(2, "Play") 
        MenuItem(3, "Stop")    
        MenuItem(4, "Pause")
        OpenSubMenu("Spectrum Analyzer")
        OpenSubMenu("Frequenz") 
        MenuItem(5, "10 Hz")
        MenuItem(6, "30 Hz")
        MenuItem(7, "50 Hz")
        MenuItem(8, "70 Hz")
        MenuItem(9, "90 Hz")
        CloseSubMenu()
        CloseSubMenu()
        
        SetMenuItemState(1, 6, #True)
        
        CreateImage(1, 513, 201)
        
        TrackBarGadget(1, 4, 215, 513, 20, 0, 255)
        TrackBarGadget(2, 4, 245, 513, 20, 0, 5000)
        TrackBarGadget(3, 4, 275, 513, 20, 1, 2000)
        SetGadgetState(1, Volume) 
        SetGadgetState(3, 2000)
        
        FFT_ID = CreateThread(@FFT(), #Null)
        
        If FFT_ID <> 0
          
          Repeat 
            Event = WaitWindowEvent() 
            
            Select Event  
              Case #PB_EventMenu 
                
                Select EventMenuID() 
                  Case 1 ;(Open) 
                    
                    Stop()
                    
                    Temp = OpenFileRequester("", "c:\music\club\", "Music (*.mp3, *.wav, *.mp2, *.ogg, *.raw)|*.mp3;*.wav;*.mp2;*.ogg;*.raw|*.*|*.*", #Null, #Null)
                    
                    If Temp <> ""
                      Soundfile = Temp 
                    EndIf 
                    
                  Case 2 ;(Play) 
                    
                    Stream_ID = FSOUND_Stream_OpenFile(Soundfile, 0, 0) ;open the soundfile 
                    
                    If Stream_ID <> 0
                      
                      FFTUnit_ID = FSOUND_DSP_GetFFTUnit()
                      FSOUND_DSP_SetActive(FFTUnit_ID, #True) ;activate the FastFourierTransformation-DSP-Unit  
                      
                      LowpassUnit_ID = FSOUND_DSP_Create(@Lowpass(), FSOUND_DSP_GetPriority(FFTUnit_ID) - 1, #Null)
                      FSOUND_DSP_SetActive(LowpassUnit_ID, #True)
                      
                      FSOUND_Stream_Play(1, Stream_ID) ;play the stream on channel 1
                      Play = #True
                      
                      ;Lautstärke setzen 
                      FSOUND_SetVolume(1, GetGadgetState(1))
                    EndIf 
                    
                  Case 3 ;(Stop)  
                    Stop()
                    
                  Case 4 ;(Pause)
                    If Pause <> #True
                      FSOUND_Stream_Stop(Stream_ID) ;stop playing the stream 
                      Play = #False
                      Pause = #True
                      
                      FSOUND_DSP_SetActive(FFTUnit_ID, #False)
                      FSOUND_DSP_SetActive(LowpassUnit_ID, #False)
                      FSOUND_DSP_Free(LowpassUnit_ID) 
                    Else 
                      If Stream_ID <> 0
                        
                        Pause = #False
                        
                        FFTUnit_ID = FSOUND_DSP_GetFFTUnit()
                        FSOUND_DSP_SetActive(FFTUnit_ID, #True) ;activate the FastFourierTransformation-DSP-Unit  
                        
                        LowpassUnit_ID = FSOUND_DSP_Create(@Lowpass(), FSOUND_DSP_GetPriority(FFTUnit_ID) - 1, #Null)
                        FSOUND_DSP_SetActive(LowpassUnit_ID, #True)
                        
                        FSOUND_Stream_Play(1, Stream_ID) ;play the stream on channel 1
                        Play = #True
                        
                        ;Lautstärke setzen 
                        FSOUND_SetVolume(1, GetGadgetState(1))
                        
                        ;Position setzen
                        FSOUND_Stream_SetPosition(Stream_ID, Int((FSOUND_Stream_GetLength(Stream_ID) / 5000) * GetGadgetState(2)))
                        
                      EndIf 
                    EndIf 
                    
                  Case 5
                    FFTFrequenz = 10
                    SetMenuItemState(1, 5 ,#True)
                    SetMenuItemState(1, 6 ,#False)
                    SetMenuItemState(1, 7 ,#False)
                    SetMenuItemState(1, 8 ,#False)
                    SetMenuItemState(1, 9 ,#False)
                    
                  Case 6
                    FFTFrequenz = 30
                    SetMenuItemState(1, 5 ,#False)
                    SetMenuItemState(1, 6 ,#True)
                    SetMenuItemState(1, 7 ,#False)
                    SetMenuItemState(1, 8 ,#False)
                    SetMenuItemState(1, 9 ,#False)
                    
                  Case 7
                    FFTFrequenz = 50
                    SetMenuItemState(1, 5 ,#False)
                    SetMenuItemState(1, 6 ,#False)
                    SetMenuItemState(1, 7 ,#True)
                    SetMenuItemState(1, 8 ,#False)
                    SetMenuItemState(1, 9 ,#False)
                    
                  Case 8 
                    FFTFrequenz = 70
                    SetMenuItemState(1, 5 ,#False)
                    SetMenuItemState(1, 6 ,#False)
                    SetMenuItemState(1, 7 ,#False)
                    SetMenuItemState(1, 8 ,#True)
                    SetMenuItemState(1, 9 ,#False)
                    
                  Case 9
                    FFTFrequenz = 90
                    SetMenuItemState(1, 5 ,#False)
                    SetMenuItemState(1, 6 ,#False)
                    SetMenuItemState(1, 7 ,#False)
                    SetMenuItemState(1, 8 ,#False)
                    SetMenuItemState(1, 9 ,#True)
                    
                EndSelect 
                
              Case #PB_Event_Gadget
                Select EventGadgetID()
                  Case 1
                    If Play <> #False
                      ;Lautstärke setzen 
                      FSOUND_SetVolume(1, GetGadgetState(1))
                    EndIf
                    
                  Case 2
                    If Play <> #False
                      ;Position ändern 
                      FSOUND_Stream_SetPosition(Stream_ID, Int((FSOUND_Stream_GetLength(Stream_ID) / 5000) * GetGadgetState(2)))
                    EndIf
                    
                  Case 3
                    Wert = GetGadgetState(3)
                    
                EndSelect
                
              Case #PB_Event_CloseWindow
                Unload()
                
              Case #WM_QUIT
                Unload()
                
            EndSelect   
          Until Quit <> #False
        EndIf
      EndIf
    EndIf
  EndIf
EndIf 
End
Procedure FFT() 
  
  Protected TimeStart.l
  Protected Time.l
  Protected hfft.fftarray
  Protected x.l
  Protected y.l
  Protected Value.f
  Protected Color.l 
  Protected Periodendauer.l
  
  Repeat 
    
    If Play <> #False And FSOUND_DSP_GetActive(FSOUND_DSP_GetFFTUnit()) <> 0
      
      TimeStart = GetTickCount_() 
      
      Periodendauer = Int((1 / FFTFrequenz) * 1000) 
      CopyMemory(FSOUND_DSP_GetSpectrum(), hfft, 4*512) 
      
      UseImage(1) 
      StartDrawing(ImageOutput()) 
      
      For i = 0 To 511 Step 4
        Value = 199 - Pow(0.0000001, hfft\Value[i]) * 199 
        
        ;Jeder der 512 Frequenzen kann sich von 0 bis 200 erstrecken
        ;Jeder "Block" ist 5 Pixel hoch, deshalb in 5er Schritten
        For y = 0 To 200 Step 5
          
          ;Die Farbe für jeden 5er Schritt berechnen
          ;Formel by Froggerprogger
          Color = (255 - y) * $000100 + y * $000001
          
          ;Wenn der aktuelle "Block" aktiv ist
          If Value > y 
            
            ;Den Block mit der dynamischen Farbe füllen  
            Box(i + 1, 200 - y, 3, 6, Color)
            
          ;ist der "Block" leer, ...
          ElseIf actfftvalue < y
            
            ;... muss er mit grauer Farbe gefüllt werden
            Box(i + 1, 205 - y, 3, y - 200, RGB($B0,$CF,$F4))
            y = 200
            
          EndIf 
          
        ;Next block
        Next y
        
      ;Next Frequenz
      Next i
      
      StopDrawing()
      
      UseWindow(1)
      StartDrawing(WindowOutput())
      DrawImage(UseImage(1), 4, 10)
      StopDrawing()
      
      ;Positionen berechnen 
      SetGadgetState(2, Int((FSOUND_Stream_GetPosition(Stream_ID) / FSOUND_Stream_GetLength(Stream_ID)) * 5000))
      
      If FSOUND_Stream_GetPosition(Stream_ID) = FSOUND_Stream_GetLength(Stream_ID)
        
        FSOUND_Stream_Stop(Stream_ID) ;stop playing the stream 
        Play = 0
        
        FSOUND_DSP_Free(LowpassUnit_ID)
        FSOUND_DSP_Free(FFTUnit_ID)
        
        SetGadgetState(2, 1)
      EndIf
      
      Time = Int(Periodendauer - (GetTickCount_() - TimeStart))
      If Time > 0 And Time < Periodendauer
        Delay(Time)
      EndIf 
      
    Else
      
      ;Wenn keine Musik aktiv ist
      
      UseImage(1) 
      StartDrawing(ImageOutput()) 
      Box(0, 0, 512, 200)
      
      For i = 0 To 511 Step 4 
        Box(i + 1, 0, 3, 201, RGB($B0,$CF,$F4))
      Next i
      
      StopDrawing()
      
      UseWindow(1)
      StartDrawing(WindowOutput())
      DrawImage(UseImage(1), 4, 10)
      StopDrawing()
      
      Delay(50)
      
    EndIf 
  Until Quit = #True 
EndProcedure 
Procedure.l Lowpass(ptOriginalbuffer.l, ptNewbuffer.l, Length.l, Param.l)
  
  Protected ptNewbuffer
  Protected ptOriginalbuffer
  Protected Length
  Protected Param
  
  Protected Counter.l
  Protected Left.l
  Protected Right.l 
  
  Dim Daten.l(Length)
  CopyMemory(ptNewbuffer, @Daten(), 4 * Length) 
  
  For Counter = 0 To Length - 1 
    Debug Daten(Counter) 
  Next Counter 
  
  ProcedureReturn @Daten()
  
EndProcedure
Procedure Stop()
  
  Shared Stream_ID, Volume, Play, FFTUnit_ID, LowpassUnit_ID 
  
  ;Fadeout
  For i = Volume To 0 Step -1 ;a small fast fade-out to prevent a clipping-sound 
    FSOUND_SetVolume(1, i)
    Delay(5)
  Next 
  
  FSOUND_Stream_Stop(Stream_ID) ;stop playing the stream 
  Play = #False
  
  FSOUND_DSP_SetActive(FFTUnit_ID, #False)
  FSOUND_DSP_SetActive(LowpassUnit_ID, #False)
  FSOUND_DSP_Free(LowpassUnit_ID)  
  
  SetGadgetState(2, 1)
EndProcedure
Procedure Unload()
  Quit = #True 
  WaitThread(FFT_ID) 
  
  FSOUND_Stream_Stop(Stream_ID) ;stop playing the stream 
  FSOUND_DSP_SetActive(FFTUnit_ID, #False) ;set the FFT-DSP-Unit inactive 
  FSOUND_DSP_SetActive(LowpassUnit_ID, #False)
  FSOUND_DSP_Free(LowpassUnit_ID)
  FSOUND_Close() ;shut down FSOUND  
EndProcedure
Procedure LOWORD(Value) 
  ProcedureReturn Value & $FFFF 
EndProcedure 
Procedure HIWORD(Value) 
  ProcedureReturn (Value >> 16) & $FFFF 
EndProcedure 
Procedure MAKELONG(low, high)
  ProcedureReturn low | (high<<16) 
EndProcedure
thing, the lowpass callback are in english...
The first TrackBarGadget are the volume and the 2. are the position
at the song. The 3. for some testing ... and later for the cutoff frequency