Music Visualizer - FFT spectrum (webAudioPlugin)

Created a nice software using SpiderBasic ? Post you link here !
User avatar
eddy
Posts: 124
Joined: Thu Mar 27, 2014 8:34 am

Music Visualizer - FFT spectrum (webAudioPlugin)

Post by eddy »

- FFT analyzer
- web Audio Plugin is supported by following browsers (chrome, firefox, safari, ios) http://caniuse.com/audio-api

Image

Code: Select all

InitSound() 


Enumeration 
  #Window 
  #Button 
  #Canvas
EndEnumeration
#Button_Stop$="■ Stop Music"
#Button_Play$="► Play Music"
Global nbFrames
Global SoundAnalyzer
Global Dim SoundFreqDecibels.f(0)
Global Dim SoundFreqData.c(0)
Global Dim SoundTimeData.c(0)

Procedure.i CreateSoundAnalyzer(Array freqDecibels.f(1),Array freqData.c(1),Array timeData.c(1),FFTSIZE=512)
  Protected frequencyBinCount
  
  EnableJS
  ;// get the context.  NOTE To connect To existing nodes we need To work in the same context.
  var context = createjs.WebAudioPlugin.context;

  ;// create an analyser node
  analyserNode = context.createAnalyser();
  analyserNode.fftSize = v_FFTSIZE;  //The size of the FFT used for frequency-domain analysis. This must be a power of two
  analyserNode.smoothingTimeConstant = 0.85;  //A value from 0 -> 1 where 0 represents no time averaging with the last analysis frame
  analyserNode.connect(context.destination);  // connect to the context.destination, which outputs the audio

  ;// attach visualizer node To our existing dynamicsCompressorNode, which was connected To context.destination
  var dynamicsNode = createjs.WebAudioPlugin.dynamicsCompressorNode;
  dynamicsNode.disconnect();  // disconnect from destination
  dynamicsNode.connect(analyserNode);
  
  ;// resize data array
  v_frequencyBinCount=analyserNode.frequencyBinCount;  
  DisableJS  
  ReDim freqDecibels(frequencyBinCount-1)
  ReDim freqData(frequencyBinCount-1)
  ReDim timeData(frequencyBinCount-1)  
  !a_freqDecibels.array= new Float32Array(v_frequencyBinCount);
  !a_freqData.array= new Uint8Array(v_frequencyBinCount);
  !a_timeData.array= new Uint8Array(v_frequencyBinCount);

  ;// return analyzer object
  !return { analyserNode: analyserNode, dynamicsNode: dynamicsNode, freqDecibels: a_freqDecibels.array, freqData: a_freqData.array, timeData: a_timeData.array };  
EndProcedure 

Procedure UpdateSoundAnalyzerData(Analyzer)  
  !v_Analyzer.analyserNode.getFloatFrequencyData(v_Analyzer.freqDecibels);  // this gives us the dBs
  !v_Analyzer.analyserNode.getByteFrequencyData(v_Analyzer.freqData);  // this gives us the frequency
  !v_Analyzer.analyserNode.getByteTimeDomainData(v_Analyzer.timeData);  // this gives us the waveform  
EndProcedure 

Procedure PlayMusic()
  Static isMusicPlaying.b
  isMusicPlaying=~isMusicPlaying
  If isMusicPlaying
    SetGadgetText(#Button,#Button_Stop$)
    PlaySound(1)
  Else 
    SetGadgetText(#Button,#Button_Play$)
    StopSound(1)
  EndIf   
EndProcedure

Procedure Loading(Type, Filename$)  
  If Type=#PB_Loading_Sound
    Debug Filename$ + " loaded"
    DisableGadget(#Button, #False)
    SetGadgetText(#Button,"► Play Music")
  EndIf 
EndProcedure

Procedure LoadingError(Type, Filename$)
  If Type=#PB_Loading_Sound
    Debug Filename$ + ": loading error"
  EndIf   
EndProcedure

Procedure RenderCanvas()
  ;update audio data
  UpdateSoundAnalyzerData(SoundAnalyzer)
  
  ;draw audio graph
  StartDrawing(CanvasOutput(#Canvas))
  Box(0,0,GadgetWidth(#Canvas),GadgetHeight(#Canvas))  
  oldX=-1
  oldY=-1
  For i=0 To ArraySize(SoundFreqDecibels())
    Box(5+i*2,5,1,SoundFreqData(i),RGB(255,0,0))
    x=5+i*2
    y=280+SoundTimeData(i)
    If oldX>-1
      LineXY(oldX,oldY,x,y,RGB(255,166,66))
    EndIf     
    oldX=x
    oldY=y       
    Box(6+i*2,5,1,-SoundFreqDecibels(i),RGB(63, 191, 35))
  Next 
  StopDrawing()
EndProcedure

SoundAnalyzer=CreateSoundAnalyzer(SoundFreqDecibels(),SoundFreqData(),SoundTimeData())

OpenWindow(#Window, 0, 0, 0, 0, "Music Visualizer", #PB_Window_Background)

CanvasGadget(#Canvas,0,0,600, 600)
ButtonGadget(#Button, 605, 5, 190, 30, #Button_Play$)
DisableGadget(#Button, #True)
AddWindowTimer(#Window,100,1000/30)

BindGadgetEvent(#Button, @PlayMusic())
BindEvent(#PB_Event_Timer, @RenderCanvas())
BindEvent(#PB_Event_Loading, @Loading())
BindEvent(#PB_Event_LoadingError, @LoadingError())

;load your mp3 or Ogg music file
LoadSound(1,  "22 Gradius - Beat Bank.mp3")