Jump to content

Visualise Waveform


NBJ
 Share

Recommended Posts

Hi,

Over the past few years there have been some requests for a waveform visualization, I haven't found one so I thought I'd whip up a quick one with my limited skills.

I am sure some of you guys and gals can refine it and make it better - especially with GDI+ etc.

Just a quick and dirty example for people looking for somewhere to start.

Also a quick mod to the Seek function to allow seeking to ms.

post-20658-12507399335842_thumb.jpg

#Include <File.au3>
#Include <Array.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <Sound.au3>
#Include <GuiSlider.au3>



$file = 'C:\windows\Media\chimes.wav'
$file = 'C:\windows\Media\recycle.wav'
$file = @DesktopDir&'\WAVs\demo.wav'
$file = 'C:\windows\Media\notify.wav'
$file = 'C:\windows\Media\tada.wav'
$file = 'C:\windows\Media\Windows XP Logon Sound.wav'
$file = 'C:\windows\Media\Windows XP Start.wav'
$file = 'C:\windows\Media\Windows XP Shutdown.wav'


$x=1
$gui = GUICreate("WAV VIS", @DesktopWidth-40,@DesktopHeight-100)
GUISetState(@SW_SHOW)
$timer = TimerInit()

Global $Array
$fileopen = FileOpen ( $file, 16 )
$memory = FileRead($fileopen)
FileClose($fileopen)
$fileopen=""
$string = String($memory)
$memory =""
;ConsoleWrite($string)
Global $array[StringLen($string)]
$array = StringSplit($string,'',2)
$string = ""

$viewerWidth = (@DesktopWidth-40)-20
$viewerLeft = GUICtrlCreateGraphic(10,10,$viewerWidth, 256,$SS_SUNKEN )
$progress = GUICtrlCreateSlider(10,266,$viewerWidth,40,BitOr($GUI_SS_DEFAULT_SLIDER, $TBS_TOOLTIPS))
;$viewerRight = GUICtrlCreateGraphic(10,310,$viewerWidth, 256, $SS_SUNKEN )

$play = GUICtrlCreateButton("PLAY",10,320)
$pause = GUICtrlCreateButton("PAUSE",50,320)
$Time = GUICtrlCreateLabel("Time",200,320,300,50)

$zoom = $viewerWidth/(UBound($array))
$step = int(UBound($array)-88/$viewerWidth)
ConsoleWrite(@CR & TimerDiff($timer) & ' Zoom = ' & $zoom & ' Step = '&$step)
$sound = _SoundOpen ( $file  )
$soundLegnth = _SoundLength ( $sound , 2 )
GUICtrlSetLimit ( $progress,$soundLegnth , 0 )
_GUICtrlSlider_SetTicFreq($progress, 1000)


For $loop = 88 to UBound($array)-4 step 4; 44 is the offset where the data exists

    ;ConsoleWrite(@cr & $loop & '~')
    $left = ($array[$loop] &$array[$loop +1])
    $left = Dec($left)
    if $left >127 then $left -= 255
    if GUICtrlRead($time) <> int($loop/UBound($array)*100) then GUICtrlSetData($time,int($loop/UBound($array)*100))
    ;$right = ($array[$loop+2] &$array[$loop +3])
    ;$right = Dec($right)
    ;if $right >127 then $right -= 255
    
    ;GUICtrlSetGraphic($viewerLeft,$GUI_GR_MOVE,0,0)
    ;GUICtrlSetGraphic($viewerLeft,$GUI_GR_pixel,int(($loop-88)/4)/100, 127+$left)
    ;if $x<> (int(($loop-88)*$zoom)) then 
    ;           ConsoleWrite(@cr & '$x='&$x & ' ($loop-88)*$zoom='&($loop-88)*$zoom)
;
;   EndIf
            GUICtrlSetGraphic($viewerLeft,$GUI_GR_line,(($loop-88)*$zoom), 127+$left)

;GUICtrlSetGraphic($viewerLeft,$GUI_GR_line,(($loop-88)*$zoom), 127+$left)
        ;if ($x/60000) = int($x/60000) then ConsoleWrite(@cr & ($x/60000)&'=' & int($x/60000));GUICtrlSetGraphic($viewerLeft,$GUI_GR_RECT,(($loop-88)*$zoom), 0,1,256)
        ;GUICtrlSetGraphic($viewerLeft,$GUI_GR_REFRESH)
        ;GUICtrlSetGraphic($viewerRight,$GUI_GR_line,int(($loop-88)*$zoom), 127+$left)
        
        ;GUICtrlSetGraphic($viewerRight,$GUI_GR_pixel,int(($loop-88)*$zoom), 127+ $right)
;       GUICtrlSetGraphic($viewerRight,$GUI_GR_pixel,(($loop-88)*$zoom), 127+$left)
    
    ;GUICtrlSetGraphic($viewerLeft,$GUI_GR_pixel,int(($loop-88)*$zoom),0)
    ;GUICtrlSetGraphic($viewerLeft,$GUI_GR_pixel,int(($loop-88)*$zoom),127)
    ;GUICtrlSetGraphic($viewerLeft,$GUI_GR_pixel,int(($loop-88)*$zoom),255)
    
    ;ConsoleWrite(int(($loop-88)/4)/10& '(' & $left); left channel
    ;ConsoleWrite('-')
    ;ConsoleWrite($array[$loop+2] &$array[$loop +3] ); right channel
 ;GUICtrlSetState($viewerLeft,$gui_Show)
$x=int (($loop-88)*$zoom)
$array[$loop] =''
$array[$loop+1]=''
Next
$array=''
GUICtrlSetState($viewerLeft,$gui_Hide)
GUICtrlSetState($viewerLeft,$gui_Show)
;GUICtrlSetState($viewerRight,$gui_Hide)
;GUICtrlSetState($viewerRight,$gui_Show)
ConsoleWrite(@CR & TimerDiff($timer) & ' ------------- Drawn' )





$sound = _SoundOpen ( $file  )
$soundLegnth = _SoundLength ( $sound , 2 )
GUICtrlSetLimit ( $progress,$soundLegnth , 0 )
_GUICtrlSlider_SetTicFreq($progress, 1000)
_SoundPlay ( $sound)

While 1
    if _SoundStatus($sound)= "playing" then GUICtrlSetData($progress,_SoundPos ( $sound , 2  ))
    ;if int(GUICtrlRead($time)/100) <> int(GUICtrlRead($progress)/100) then GUICtrlSetData($time,GUICtrlRead($progress))

    $msg = GUIGetMsg(1)
    If $msg[0] > 0 Then ConsoleWrite(@CR & "$msg[0] =  " & $msg[0])
    Switch $msg[0]
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $progress
            Slider()
        Case $play
            _SoundPlay ( $sound)
        Case $pause
            _SoundPause ( $sound)
    EndSwitch
WEnd

Func ms2hms($ms) ; converts ms to an array, $array[0]=hrs $array[1]=min $array[2]=sec $array[3]=ms
    Local $array[4]
    $ms_per_HR = (1000 * 60 *60)
    $ms_per_min = (1000 * 60)
    $ms_per_sec = (1000)
    
    $array[0]= int ( $ms/ ($ms_per_HR))
    $array[1]= int (($ms - ($array[0]*$ms_per_HR))/$ms_per_min)
    $array[2]= int (($ms - ($array[0]*$ms_per_HR) - ($array[1]*$ms_per_min))/$ms_per_sec)
    $array[3]= int (($ms - ($array[0]*$ms_per_HR) - ($array[1]*$ms_per_min) - $array[2]*$ms_per_sec))
    
    ConsoleWrite(@cr & $ms & 'ms = ' & $array[0] &' hrs '& $array[1] &' mins '& $array[2] &' sec '& $array[3] &' ms ' )
    Return $array
EndFunc


Func Slider()
        $SeekTime = ms2hms(GUICtrlRead($progress))
            if GUICtrlRead($timer) <> GUICtrlRead($progress) then GUICtrlSetData($timer,GUICtrlRead($progress))
        _SoundPause($sound)
        SoundSeekNJ( $sound, $SeekTime[0], $SeekTime[1], $SeekTime[2],$SeekTime[3] )
        _SoundPlay($sound)

EndFunc
    
    
Func SoundSeekNJ(ByRef $aSndID, $iHour, $iMin, $iSec, $MS_1)
    ;Declare variables
    Local $iMs = 0, $iRet, $vTemp
    If Not IsArray($aSndID) Then
        If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias
        $vTemp = FileGetShortName($aSndID)
        Dim $aSndID[1] = [$vTemp]
    EndIf
    If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias
    
    ;prepare mci to receive time in milliseconds
    __mciSendString("set " & $aSndID[0] & " time format miliseconds")
    ;modify the $iHour, $iMin and $iSec parameters to be in milliseconds
    ;and add to $iMs
    $iMs += $MS_1
    $iMs += $iSec * 1000
    $iMs += $iMin * 60 * 1000
    $iMs += $iHour * 60 * 60 * 1000
    If $aSndID[1] <> 0 Then
        $aSndID[2] = Round($iMs * $aSndID[1]) - $iMs
        $iMs = Round($iMs * $aSndID[1])
    EndIf
    ; seek sound to time ($iMs)
    $iRet = __mciSendString("seek " & $aSndID[0] & " to " & $iMs)
    If _SoundPos($aSndID, 2) < 0 Then $aSndID[2] = 0
    ;return
    If $iRet = 0 Then
        Return 1
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>_SoundSeek

Cheers

Neil

Edited by NBJ
Link to comment
Share on other sites

Nice. Thanks for sharing. Do you think this waveform visualization you have could be modified to work as a wave audio diff/comparison of waveforms?

I suppose it could - there is an ArrayDiff() function on the forum what could be used to compare 2 different wav forms Edited by NBJ
Link to comment
Share on other sites

Very nice!

It reminds me a bit of CyberZeroCool's Audio Spectrascope. If you want more advanced graphics you may want to try GDI+ (in the helpfile) or SDL (in my signature).

Link to comment
Share on other sites

Hi!

Looks nice. If you want to look at a different implementation in GDI+ you can check the audio visualization program in my sig. It also cotains a waveform viz >_<

@Monocess-Thanks I'll check them out, I cant believe I missed them! cheers

@AdmiralAlex - Yes - I'll have a look though those also.

Still need to get my head around the different wav formats and figure out how to convert mp3 etc to wav, then store image so it doesn't have to redraw etcetc.....

Thanks to both of you

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...