WavForm of a sound in WAV format

Share your advanced PureBasic knowledge/code with the community.
User avatar
gally
User
User
Posts: 41
Joined: Thu May 28, 2009 9:07 pm
Location: France
Contact:

WavForm of a sound in WAV format

Post by gally »

hello,

Here is a small code to display the WavForm of a sound in WAV. I'm sorry if my english is bad because I used google translation to translate my post.

Code:

Code: Select all

; +======================================================+
; | ROUTINE DE CHARGEMENT DU FORMAT WAV (SPECTRE DU SON) |
; +------------------------------------------------------+
; | COPYRIGHT(C)2007-2012, ALL RIGHT RESERVED KOAKDESIGN |
; +--------------+---------------------------------------+
; | Program type | PUREBASIC 4.61                        |
; +--------------+---------------------------------------+
; | VER & REV    | 0.0.2                                 |
; +--------------+---------------------------------------+
; | Program name | main.pb                               |
; +======================================================+

; +======================================================+
; | Original Version: 0.0.2                              |
; +--------------+---------------------------------------+
; | Created by   | GallyHomeCorp                         |
; | Graphix by   | GallyHomeCorp                         |
; +--------------+---------------------------------------+
; | Comments:    |                                       |
; +--------------+                                       |
; |                                                      |
; |                                                      |
; |                                                      |
; +======================================================+

; +======================================================+
; | Système d'Exploitation                               |
; +--------------+---------------------------------------+
; | Window       | Oui                                   |
; | Linux        | Oui                                   |
; | MacOS        | Oui                                   |
; +======================================================+

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

EnableExplicit

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Declare.i OpenWAVFile(filename.s, x.l, y.l, w.l, h.l, z.l = 1)
Declare.i DrawWAVFile(x.l, y.l, w.l, h.l, z.l = 1, p.l = 0, play.l = 0)

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Structure WaveFileHeader
  chunkid.s{4}
  chunksize.l
  format.s{4}
  fmtchunkid.s{4}
  fmtchunksize.l
  audioformat.u
  numchannels.u
  samplerate.l
  byterate.l
  blockalign.u
  bitspersample.u
  datachunkid.s{4}
  datachunksize.l
EndStructure

Global sFileName.s
Global Dim tabWaveLenA.a(1)
Global Dim tabWaveLenB.w(1)
Global tabWaveFile.WaveFileHeader

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Procedure.i OpenWAVFile(filename.s, x.l, y.l, w.l, h.l, z.l = 1)
; ROUTINE DE CHARGEMENT DU HEADER DU WAV.
  Define i.l
  Define file.l
  Define flen.l
  Define dlen.l
  Define load.b = #False
  Define lImage.i
  Define lDataChunk.l
  Define datachunkid.s{4}
  
  file = ReadFile(#PB_Any, filename)
  If file <> 0
    sFileName = filename
    flen = Lof(file)
    ReadData(file, tabWaveFile, SizeOf(WaveFileHeader))
    If tabWaveFile\datachunkid <> "data"
      For i = 0 To 2048 Step 2
        FileSeek(file, (SizeOf(WaveFileHeader) - 6) + i)
        ReadData(file, @datachunkid, 4)
        If datachunkid = "data"
          lDataChunk = i + 2
          tabWaveFile\datachunkid   = "data"
          tabWaveFile\datachunksize = ReadLong(file)
          Break
        EndIf
      Next i
    EndIf
    ReDim tabWaveLenA(1)
    ReDim tabWaveLenB(1)
    If tabWaveFile\chunkid = "RIFF" And tabWaveFile\format = "WAVE" And tabWaveFile\fmtchunkid = "fmt " And tabWaveFile\datachunkid = "data" And tabWaveFile\DataChunkSize > 44 
      dlen = tabWaveFile\DataChunkSize / tabWaveFile\BlockAlign
      Select tabWaveFile\BitsPerSample
        Case 8
          Select tabWaveFile\NumChannels
            Case 1
              load = #True
              ReDim tabWaveLenA(dlen)
            Case 2
              load = #True
              ReDim tabWaveLenA(dlen * 2)
          EndSelect
          If load = #True
            FileSeek(file, SizeOf(WaveFileHeader) + lDataChunk)
            If ReadData(file, @tabWaveLenA(), tabWaveFile\DataChunkSize) = tabWaveFile\DataChunkSize
              lImage = DrawWAVFile(x, y, w, h, z)
            EndIf
          EndIf
        Case 16
          Select tabWaveFile\NumChannels
            Case 1
              load = #True
              ReDim tabWaveLenB(dlen)
            Case 2
              load = #True
              ReDim tabWaveLenB(dlen * 2)
          EndSelect
          If load = #True
            FileSeek(file, SizeOf(WaveFileHeader) + lDataChunk)
            If ReadData(file, @tabWaveLenB(), tabWaveFile\DataChunkSize) = tabWaveFile\DataChunkSize
              lImage = DrawWAVFile(x, y, w, h, z)
            EndIf
          EndIf
      EndSelect
    EndIf
    CloseFile(file)
  EndIf
  ProcedureReturn lImage

EndProcedure

Procedure.s GetWAVTime()
; ROUTINE DE RECUPERATION DU TEMPS DU WAV.
  ProcedureReturn FormatDate("%hh:%ii:%ss", Round((tabWaveFile\DataChunkSize / tabWaveFile\ByteRate) - 0.3, #PB_Round_Nearest))

EndProcedure

Procedure.l ParseWavTime(date.s, val.l)
; ROUTINE DE DECOUPAGE DU TEMPS DU WAV.
  If val < 1
    val = 1
  EndIf
  If val > 3
    val = 3
  EndIf
  ProcedureReturn Val(StringField(date, val, ":"))

EndProcedure

Procedure GetWavInformation()
; ROUTINE DE DECOUPAGE DU TEMPS DU WAV.
  Define stemp.s

  stemp = "ChunkID : " + tabWaveFile\chunkid + #CRLF$
  stemp +  "ChunkSize : " + Str(tabWaveFile\ChunkSize) + " Octets" + #CRLF$
  stemp +  "Format : " + tabWaveFile\Format + #CRLF$
  stemp +  "fmtChunkID : " + tabWaveFile\fmtChunkID + #CRLF$
  stemp +  "FmtChunkSize : " + Str(tabWaveFile\FmtChunkSize) + " Octets" + #CRLF$
  stemp +  "Format : " + Str(tabWaveFile\AudioFormat) + #CRLF$
  stemp +  "Channels : " + Str(tabWaveFile\NumChannels) + #CRLF$
  stemp +  "SampleRate : " + Str(tabWaveFile\SampleRate) + " Hz" + #CRLF$
  stemp +  "BitsRate : " + Str(tabWaveFile\ByteRate) + #CRLF$
  stemp +  "BlockAlign : " + Str(tabWaveFile\BlockAlign) + #CRLF$
  stemp +  "BitsPerSample : " + Str(tabWaveFile\BitsPerSample) + #CRLF$
  stemp +  "DataChunkID : " + tabWaveFile\DataChunkID + #CRLF$
  stemp +  "DataChunkSize : " + Str(tabWaveFile\DataChunkSize) + " Octets" + #CRLF$ + #CRLF$
  stemp +  "Temps Total : " + GetWAVTime()
  MessageRequester("PureWav", stemp, #PB_MessageRequester_Ok)
  
EndProcedure

Procedure.i DrawWAVFile(x.l, y.l, w.l, h.l, z.l = 1, p.l = 0, play.l = 0)
; ROUTINE DE TRACAGE DU SPECTRE DU WAV.
  Define i.l
  Define j.l
  Define dlen.l
  Define lpas.l
  Define ysav.l
  Define zsav.l
  Define lpos.l
  Define time.s = GetWAVTime()
  Define lsec.f = w / ((ParseWavTime(time, 1) * 3600) + (ParseWavTime(time, 2) * 60) + ParseWavTime(time, 3))
  Define lImage.i
  
  If z < 1
    z = 1
  EndIf
  If z > 16
    z = 16
  EndIf
  If tabWaveFile\chunkid <> "RIFF" Or tabWaveFile\format <> "WAVE" Or tabWaveFile\fmtchunkid <> "fmt "
    ProcedureReturn 0
  EndIf
  If tabWaveFile\DataChunkSize < 1
    ProcedureReturn 0
  EndIf
  lImage = CreateImage(#PB_Any, w, h)
  If lImage <> 0
    If StartDrawing(ImageOutput(lImage))
      Box(0, 0, w, h, $FFFFFF)
      dlen = tabWaveFile\DataChunkSize / tabWaveFile\BlockAlign
      Select tabWaveFile\NumChannels
        Case 1
          lpas = (dlen / w) / z
          lpos = ((dlen / lpas) - w)
          If p > lpos
            p = lpos
          EndIf
          Select tabWaveFile\BitsPerSample
            Case 8
              ysav = tabWaveLenA(0) - 128
              LineXY(0,(h / 6)     , w, (h / 6)    , $BBBBBB)
              LineXY(0, h - (h / 6), w, h - (h / 6), $BBBBBB)
              For i = 0 To w
                For j = 1 To lpas Step 1
                  j + (128 - (z * 4))
                  If ((i + p) * lpas) + j < dlen - 1
                    LineXY(i, (h / 2) - ysav, i, (h / 2) - (tabWaveLenA(((i + p) * lpas) + j) - 128) , $e8a200 + ((i * 255) / w))
                    ysav = (tabWaveLenA(((i + p) * lpas) + j) - 128)
                  EndIf
                Next j
                LineXY(i, (h / 2), i, (h / 2), $CC8E00 + ((i * 255) / w))
              Next i
            Case 16
              ysav = tabWaveLenB(0) / (h / 1.5)
              LineXY(0,(h / 6)     , w, (h / 6)    , $BBBBBB)
              LineXY(0, h - (h / 6), w, h - (h / 6), $BBBBBB)
              For i = 0 To w
                For j = 1 To lpas Step 1
                  j + (128 - (z * 4))
                  If ((i + p) * lpas) + j < dlen - 1
                    LineXY(i, (h / 2) - ysav, i, (h / 2) - (tabWaveLenB(((i + p) * lpas) + j) / (h / 1.5)), $e8a200 + ((i * 255) / w))
                    ysav = tabWaveLenB(((i + p) * lpas) + j) / (h / 1.5)
                  EndIf
                Next j
                LineXY(i, (h / 2), i, (h / 2), $CC8E00 + ((i * 255) / w))
              Next i
          EndSelect
        Case 2
          lpas = ((dlen / w) * 2) / z
          lpos = ((dlen / lpas) * 2) - w
          If p > lpos
            p = lpos
          EndIf
          Select tabWaveFile\BitsPerSample
            Case 8
              ysav = tabWaveLenA(1) - 128
              ysav = tabWaveLenA(0) - 128
              LineXY(0, (h / 12)          , w, (h / 12)           , $BBBBBB)
              LineXY(0, (h / 2) - (h / 12), w, (h / 2) - (h / 12) , $BBBBBB)
              LineXY(0, (h / 2) + (h / 12), w, (h / 2) + (h / 12) , $BBBBBB)
              LineXY(0, h - (h / 12)      , w, h - (h / 12)       , $BBBBBB)
              For i = 0 To w
                For j = 1 To lpas Step 1
                  j + (128 - (z * 4))
                  If ((i + p) * lpas) + j < (dlen * 2) - 1
                    LineXY(i, (h / 4) - ysav, i, (h / 4) - (tabWaveLenA(((i + p) * lpas) + j + 1) - 128) , $e8a200 + ((i * 255) / w))
                    ysav = (tabWaveLenA(((i + p) * lpas) + j + 1) - 128)
                    LineXY(i, h -(h / 4) - zsav, i, h - (h / 4) - (tabWaveLenA(((i + p) * lpas) + j) - 128) , $e8a200 + ((i * 255) / w))
                    zsav = (tabWaveLenA(((i + p) * lpas) + j) - 128)
                  EndIf
                Next j
                LineXY(i, (h / 4)     , i, (h / 4)    , $CC8E00 + ((i * 255) / w))
                LineXY(i, h - (h / 4) , i, h - (h / 4), $CC8E00 + ((i * 255) / w))
              Next i
              LineXY(0,(h / 2)     , w, (h / 2)    , $222222)
            Case 16
              ysav = tabWaveLenB(1) / (h / 0.9)
              zsav = tabWaveLenB(0) / (h / 0.9)
              LineXY(0, (h / 12)          , w, (h / 12)           , $BBBBBB)
              LineXY(0, (h / 2) - (h / 12), w, (h / 2) - (h / 12) , $BBBBBB)
              LineXY(0, (h / 2) + (h / 12), w, (h / 2) + (h / 12) , $BBBBBB)
              LineXY(0, h - (h / 12)      , w, h - (h / 12)       , $BBBBBB)
              For i = 0 To w
                For j = 1 To lpas Step 1
                  j + (128 - (z * 4))
                  If ((i + p) * lpas) + j < (dlen * 2) - 1
                    LineXY(i, (h / 4) - ysav, i, (h / 4) - (tabWaveLenB(((i + p) * lpas) + j + 1) / (h / 0.6)), $e8a200 + ((i * 255) / w))
                    ysav = tabWaveLenB(((i + p) * lpas) + j + 1) / (h / 0.6)
                    LineXY(i, h - (h / 4) - zsav, i, h - (h / 4) - (tabWaveLenB(((i + p) * lpas) + j) / (h / 0.6)), $e8a200 + ((i * 255)  / w))
                    zsav = tabWaveLenB(((i + p) * lpas) + j) / (h / 0.6)
                  EndIf
                Next j
                LineXY(i, (h / 4), i, (h / 4), $CC8E00 + ((i * 255) / w))
                LineXY(i, h - (h / 4), i, h - (h / 4), $CC8E00 + ((i * 255) / w))
              Next i
              LineXY(0, (h / 2), w, (h / 2)    , $222222)
          EndSelect
      EndSelect
      j = 0
      DrawingMode(#PB_2DDrawing_Transparent)
      If  Round((tabWaveFile\DataChunkSize / tabWaveFile\ByteRate) - 0.3, #PB_Round_Nearest) > 1
        For i = 1 To (w * z)
          j + 1
          i + (lsec * 30) * z
          If i - p => 0 And i - p <= w 
            LineXY(i - p, 0, i - p, h, $0000AA)
            DrawText((i - p) - 60 , h - 15, FormatDate("%hh:%ii:%ss", (j * 30)), $0000AA)
          EndIf
        Next i
      EndIf
      DrawText(w - 60 , 1, time, $000000)
      LineXY(((play + lsec) - lsec) * z, 0, ((play + lsec) - lsec) * z, h, $FF0000)
      StopDrawing()
      If z = 1
        SetGadgetState(1, 0)
      EndIf
      SetGadgetAttribute(1, #PB_ScrollBar_Maximum, lpos)
      ProcedureReturn lImage
    EndIf
  EndIf
    
  EndProcedure

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

If InitSound() = 0
EndIf

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Define i.l = 1
Define j.l = 0
Define hWnd.l
Define event.l
Define eveng.l
Define ImageWAV.i
Define time.l
Define timeout.l = 10

hWnd = OpenWindow(0, 0, 0, 800, 400, "PureWav", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
If hWnd <> 0
  ImageGadget(0, 0, 0, 800, 256, 0)
  ScrollBarGadget(1, 0, 257, 800, 18, 1, 1, 1000)
  ButtonGadget(2, 10, 300, 100, 32, "Fichier Wav")
  ButtonGadget(3, 120, 300, 100, 32, "Play")
  ButtonGadget(4, 230, 300, 100, 32, "Stop")
  ButtonGadget(5, 10, 340, 100, 32, "Zoom -")
  ButtonGadget(6, 120, 340, 100, 32, "Zoom +")
  
  Repeat
    event = WaitWindowEvent(1)
    eveng   = EventGadget()

    Select event
      Case #PB_Event_Gadget
        Select eveng
          Case 1
            j = GetGadgetState(1)
            If IsImage(ImageWAV) And ImageWAV <> 0
              FreeImage(ImageWAV)
            EndIf
            ImageWAV = DrawWAVFile(0, 0, 800, 256, i, j)
            If ImageWAV
              SetGadgetState(0, ImageID(ImageWAV))
            EndIf
          Case 2
            If IsImage(ImageWAV) And ImageWAV <> 0
              FreeImage(ImageWAV)
            EndIf
            ImageWAV = OpenWAVFile(OpenFileRequester("Ouvrir un archive Wav", "", "Musique Wav|*.wav", 0), 0, 0, 800, 256, i)            
            If ImageWAV
              SetGadgetState(0, ImageID(ImageWAV))
            EndIf
            GetWavInformation()
          Case 3
            If LoadSound(0, sFileName)
              PlaySound(0)
            EndIf
          Case 4
            If IsSound(0)
              StopSound(0)  
            EndIf
          Case 5
            i - 1
            If i < 2
              j = 0
            EndIf  
            If i < 1
              i = 1              
            EndIf
            If IsImage(ImageWAV) And ImageWAV <> 0
              FreeImage(ImageWAV)
            EndIf
            ImageWAV = DrawWAVFile(0, 0, 800, 256, i, j)
            If ImageWAV
              SetGadgetState(0, ImageID(ImageWAV))
            EndIf
          Case 6
            i + 1
            If i > 16
              i = 16
            EndIf
            If IsImage(ImageWAV) And ImageWAV <> 0
              FreeImage(ImageWAV)
            EndIf
            ImageWAV = DrawWAVFile(0, 0, 800, 256, i, j)
            If ImageWAV
              SetGadgetState(0, ImageID(ImageWAV))
            EndIf
      EndSelect
    EndSelect
  Until event = #PB_Event_CloseWindow
EndIf
Hoping this is useful

cordially,
GallyHC
Last edited by gally on Mon Oct 15, 2012 12:37 pm, edited 3 times in total.
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Spectrum of a sound in WAV format

Post by electrochrisso »

Hi gally, this looks interesting, but I cant see the waveform, I can only hear the sound, and if I zoom, I get a crash or dimension out of range error. :(
PureBasic! Purely the best 8)
dige
Addict
Addict
Posts: 1409
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Spectrum of a sound in WAV format

Post by dige »

Cool! thx for sharing!
"Daddy, I'll run faster, then it is not so far..."
User avatar
Lord
Addict
Addict
Posts: 907
Joined: Tue May 26, 2009 2:11 pm

Re: Spectrum of a sound in WAV format

Post by Lord »

Hello gally!

Nice piece of code, but it doesn't show the
spectrum of a file. It's showing the waveform.
Image
User avatar
gally
User
User
Posts: 41
Joined: Thu May 28, 2009 9:07 pm
Location: France
Contact:

Re: Spectrum of a sound in WAV format

Post by gally »

electrochrisso> hello

Can you give me the file that you have a problem? or just a snapshot of the header file from beginning until "data".

Sincerely,
GallyHC
User avatar
gally
User
User
Posts: 41
Joined: Thu May 28, 2009 9:07 pm
Location: France
Contact:

Re: WavForm of a sound in WAV format

Post by gally »

some correction...

GallyHC
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: WavForm of a sound in WAV format

Post by Kwai chang caine »

Cool !! works great here :D
Thanks to sharing 8)

Believe you, a day, you add a cursor for see the position of the read pointer ??
ImageThe happiness is a road...
Not a destination
User avatar
gally
User
User
Posts: 41
Joined: Thu May 28, 2009 9:07 pm
Location: France
Contact:

Re: WavForm of a sound in WAV format

Post by gally »

yes, see the cursor is in progress. But lib "Sound" does not get it?

GallyHC
chris319
Enthusiast
Enthusiast
Posts: 782
Joined: Mon Oct 24, 2005 1:05 pm

Re: WavForm of a sound in WAV format

Post by chris319 »

Something like this:

Code: Select all

    If InitSound() = 0
    EndIf
is useless unless you provide an alternative action in case the test fails, e.g.:

Code: Select all

If InitSound() = 0
MessageRequester(your message)
End
EndIf
User avatar
gally
User
User
Posts: 41
Joined: Thu May 28, 2009 9:07 pm
Location: France
Contact:

Re: WavForm of a sound in WAV format

Post by gally »

chris319 > Yes the source is just test. plus tard j'en ferais un gadget.

GallyHC
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: WavForm of a sound in WAV format

Post by electrochrisso »

gally wrote:electrochrisso> hello

Can you give me the file that you have a problem? or just a snapshot of the header file from beginning until "data".

Sincerely,
GallyHC
Gally, sorry for the late, been away, here is a link to one of the files, I think it has something to do with the way Reaper is rendering the wav, Audacity files seem to work ok.
http://www.psteam.webatu.com/temp/120%2 ... r%2001.wav
PureBasic! Purely the best 8)
User avatar
gally
User
User
Posts: 41
Joined: Thu May 28, 2009 9:07 pm
Location: France
Contact:

Re: WavForm of a sound in WAV format

Post by gally »

electrochrisso> code changed, thank you for the ascent of the problem.
Simo_na
Enthusiast
Enthusiast
Posts: 177
Joined: Sun Mar 03, 2013 9:01 am

Re: WavForm of a sound in WAV format

Post by Simo_na »

very nice

...waiting for progress cue :)
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: WavForm of a sound in WAV format

Post by eddy »

- display : cursor of playing sound position
- improved : imageGaget replaced by canvasGadget
- improved : realtime scrolling

Image

Code: Select all

; +======================================================+
; | ROUTINE DE CHARGEMENT DU FORMAT WAV (SPECTRE DU SON) |
; +------------------------------------------------------+
; | COPYRIGHT(C)2007-2012, ALL RIGHT RESERVED KOAKDESIGN |
; +--------------+---------------------------------------+
; | Program type | PUREBASIC 5.2b8                        |
; +--------------+---------------------------------------+
; | VER & REV    | 0.0.3                                 |
; +--------------+---------------------------------------+
; | Comments:    | unicode supported, realtime scroll    |
; +--------------+                                       |
; |                                                      |
; +======================================================+

; +======================================================+
; | Original Version: 0.0.2                              |
; +--------------+---------------------------------------+
; | Created by   | GallyHomeCorp                         |
; | Graphix by   | GallyHomeCorp                         |
; +--------------+---------------------------------------+
; | Comments:    |                                       |
; +--------------+                                       |
; |                                                      |
; +======================================================+

; +======================================================+
; | OS System
; +--------------+---------------------------------------+
; | Window       | Oui                                   |
; | Linux        | Oui                                   |
; | MacOS        | Oui                                   |
; +======================================================+

; ****************************************************************************
; ****************************************************************************

EnableExplicit

; ****************************************************************************
; ****************************************************************************

Declare.b OpenWAVFile(filename.s, x, y, w, h, z = 1)
Declare.b DrawWAVFile(x, y, w, h, z = 1, p = 0, play.b = #False)

; ****************************************************************************
; ****************************************************************************

Structure WaveFileHeader
   chunkid.a[4]
   chunksize.l
   format.a[4]
   fmtchunkid.a[4]
   fmtchunksize.l
   audioformat.u
   numchannels.u
   samplerate.l
   byterate.l
   blockalign.u
   bitspersample.u
   datachunkid.a[4]
   datachunksize.l
EndStructure

Global sFileName.s
Global Dim tabWaveLenA.a(1)
Global Dim tabWaveLenB.w(1)
Global tabWaveFile.WaveFileHeader

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Macro ReadWavString(structProperty)
   LSet(PeekS(@structProperty, 4, #PB_Ascii), 4, " ")
EndMacro
Macro WriteWavString(structProperty, value)
   PokeS(@structProperty, value, 4, #PB_Ascii)
EndMacro 

Procedure.b OpenWAVFile(filename.s, x, y, w, h, z = 1)
   ; ROUTINE DE CHARGEMENT DU HEADER DU WAV.
   Protected i
   Protected file
   Protected flen
   Protected dlen
   Protected load.b = #False
   Protected lDataChunk
   Protected datachunkid.s{4}
   
   file = ReadFile(#PB_Any, filename)
   If file <> 0
      sFileName = filename
      flen = Lof(file)
      ReadData(file, tabWaveFile, SizeOf(WaveFileHeader))
      If ReadWavString(tabWaveFile\datachunkid) <> "data"
         For i = 0 To 2048 Step 2
            FileSeek(file, (SizeOf(WaveFileHeader)- 6)+ i)
            ReadData(file, @datachunkid, 4)
            If datachunkid = "data"
               lDataChunk = i + 2
               WriteWavString(tabWaveFile\datachunkid, "data")
               tabWaveFile\datachunksize = ReadLong(file)
               Break
            EndIf
         Next i
      EndIf
      ReDim tabWaveLenA(1)
      ReDim tabWaveLenB(1)
      If ReadWavString(tabWaveFile\chunkid)= "RIFF" And
         ReadWavString(tabWaveFile\format)= "WAVE" And
         ReadWavString(tabWaveFile\fmtchunkid)= "fmt " And
         ReadWavString(tabWaveFile\datachunkid) = "data" And tabWaveFile\DataChunkSize > 44
         dlen = tabWaveFile\DataChunkSize / tabWaveFile\BlockAlign
         Select tabWaveFile\BitsPerSample
            Case 8
               Select tabWaveFile\NumChannels
                  Case 1
                     load = #True
                     ReDim tabWaveLenA(dlen)
                  Case 2
                     load = #True
                     ReDim tabWaveLenA(dlen * 2)
               EndSelect
               If load = #True
                  FileSeek(file, SizeOf(WaveFileHeader)+ lDataChunk)
                  If ReadData(file, @tabWaveLenA(), tabWaveFile\DataChunkSize)= tabWaveFile\DataChunkSize
                     DrawWAVFile(x, y, w, h, z)
                  EndIf
               EndIf
            Case 16
               Select tabWaveFile\NumChannels
                  Case 1
                     load = #True
                     ReDim tabWaveLenB(dlen)
                  Case 2
                     load = #True
                     ReDim tabWaveLenB(dlen * 2)
               EndSelect
               If load = #True
                  FileSeek(file, SizeOf(WaveFileHeader)+ lDataChunk)
                  If ReadData(file, @tabWaveLenB(), tabWaveFile\DataChunkSize)= tabWaveFile\DataChunkSize
                     DrawWAVFile(x, y, w, h, z)
                  EndIf
               EndIf
         EndSelect
      EndIf
      CloseFile(file)
   EndIf
   ProcedureReturn #True
   
EndProcedure

Procedure.s GetWAVTime()
   ; ROUTINE DE RECUPERATION DU TEMPS DU WAV.
   ProcedureReturn FormatDate("%hh:%ii:%ss", Round((tabWaveFile\DataChunkSize / tabWaveFile\ByteRate)- 0.3, #PB_Round_Nearest))
   
EndProcedure

Procedure.l ParseWavTime(date.s, val)
   ; ROUTINE DE DECOUPAGE DU TEMPS DU WAV.
   If val < 1
      val = 1
   EndIf
   If val > 3
      val = 3
   EndIf
   ProcedureReturn Val(StringField(date, val, ":"))
   
EndProcedure

Procedure GetWavInformation()
   ; ROUTINE DE DECOUPAGE DU TEMPS DU WAV.
   Protected stemp.s
   stemp = "ChunkID : " + tabWaveFile\chunkid +
           #CRLF$ + "ChunkSize : " + Str(tabWaveFile\ChunkSize)+ " Octets" +
           #CRLF$ + "Format : " + ReadWavString(tabWaveFile\Format) +
           #CRLF$ + "fmtChunkID : " + ReadWavString(tabWaveFile\fmtChunkID) +
           #CRLF$ + "FmtChunkSize : " + Str(tabWaveFile\FmtChunkSize)+ " Octets" +
           #CRLF$ + "Format : " + Str(tabWaveFile\AudioFormat)+
           #CRLF$ + "Channels : " + Str(tabWaveFile\NumChannels)+
           #CRLF$ + "SampleRate : " + Str(tabWaveFile\SampleRate)+ " Hz" +
           #CRLF$ + "BitsRate : " + Str(tabWaveFile\ByteRate)+
           #CRLF$ + "BlockAlign : " + Str(tabWaveFile\BlockAlign)+
           #CRLF$ + "BitsPerSample : " + Str(tabWaveFile\BitsPerSample)+
           #CRLF$ + "DataChunkID : " + ReadWavString(tabWaveFile\DataChunkID) +
           #CRLF$ + "DataChunkSize : " + Str(tabWaveFile\DataChunkSize)+ " Octets" +
           #CRLF$ + #CRLF$ + "Temps Total : " + GetWAVTime()
   MessageRequester("PureWav", stemp, #PB_MessageRequester_Ok)
   
EndProcedure

Procedure.b DrawWAVFile(x, y, w, h, z = 1, p = 0, play.b = #False)
   ; ROUTINE DE TRACAGE DU SPECTRE DU WAV.
   Protected i
   Protected j
   Protected dlen
   Protected lpas
   Protected ysav
   Protected zsav
   Protected lpos
   Protected time.s = GetWAVTime()
   Protected lsec.f = w /((ParseWavTime(time, 1)* 3600)+(ParseWavTime(time, 2)* 60)+ ParseWavTime(time, 3))
   
   If z < 1
      z = 1
   EndIf
   If z > 16
      z = 16
   EndIf
   If ReadWavString(tabWaveFile\chunkid)<> "RIFF" Or
      ReadWavString(tabWaveFile\format)<> "WAVE" Or
      ReadWavString(tabWaveFile\fmtchunkid) <> "fmt "
      ProcedureReturn #False
   EndIf
   If tabWaveFile\DataChunkSize < 1
      ProcedureReturn #False
   EndIf
   
   If StartDrawing(CanvasOutput(0))
      Box(0, 0, w, h, $FFFFFF)
      dlen = tabWaveFile\DataChunkSize / tabWaveFile\BlockAlign
      Select tabWaveFile\NumChannels
         Case 1
            lpas =(dlen / w)/ z
            lpos =((dlen / lpas)- w)
            If p > lpos
               p = lpos
            EndIf
            Select tabWaveFile\BitsPerSample
               Case 8
                  ysav = tabWaveLenA(0)- 128
                  LineXY(0, (h / 6), w, (h / 6), $BBBBBB)
                  LineXY(0, h -(h / 6), w, h -(h / 6), $BBBBBB)
                  For i = 0 To w
                     For j = 1 To lpas Step 1
                        j +(128 -(z * 4))
                        If ((i + p)* lpas)+ j < dlen - 1
                           LineXY(i, (h / 2)- ysav, i, (h / 2)-(tabWaveLenA(((i + p)* lpas)+ j)- 128), $e8a200 +((i * 255)/ w))
                           ysav =(tabWaveLenA(((i + p)* lpas)+ j)- 128)
                        EndIf
                     Next j
                     LineXY(i, (h / 2), i, (h / 2), $CC8E00 +((i * 255)/ w))
                  Next i
               Case 16
                  ysav = tabWaveLenB(0)/(h / 1.5)
                  LineXY(0, (h / 6), w, (h / 6), $BBBBBB)
                  LineXY(0, h -(h / 6), w, h -(h / 6), $BBBBBB)
                  For i = 0 To w
                     For j = 1 To lpas Step 1
                        j +(128 -(z * 4))
                        If ((i + p)* lpas)+ j < dlen - 1
                           LineXY(i, (h / 2)- ysav, i, (h / 2)-(tabWaveLenB(((i + p)* lpas)+ j)/(h / 1.5)), $e8a200 +((i * 255)/ w))
                           ysav = tabWaveLenB(((i + p)* lpas)+ j)/(h / 1.5)
                        EndIf
                     Next j
                     LineXY(i, (h / 2), i, (h / 2), $CC8E00 +((i * 255)/ w))
                  Next i
            EndSelect
         Case 2
            lpas =((dlen / w)* 2)/ z
            lpos =((dlen / lpas)* 2)- w
            If p > lpos
               p = lpos
            EndIf
            Select tabWaveFile\BitsPerSample
               Case 8
                  ysav = tabWaveLenA(1)- 128
                  ysav = tabWaveLenA(0)- 128
                  LineXY(0, (h / 12), w, (h / 12), $BBBBBB)
                  LineXY(0, (h / 2)-(h / 12), w, (h / 2)-(h / 12), $BBBBBB)
                  LineXY(0, (h / 2)+(h / 12), w, (h / 2)+(h / 12), $BBBBBB)
                  LineXY(0, h -(h / 12), w, h -(h / 12), $BBBBBB)
                  For i = 0 To w
                     For j = 1 To lpas Step 1
                        j +(128 -(z * 4))
                        If ((i + p)* lpas)+ j <(dlen * 2)- 1
                           LineXY(i, (h / 4)- ysav, i, (h / 4)-(tabWaveLenA(((i + p)* lpas)+ j + 1)- 128), $e8a200 +((i * 255)/ w))
                           ysav =(tabWaveLenA(((i + p)* lpas)+ j + 1)- 128)
                           LineXY(i, h -(h / 4)- zsav, i, h -(h / 4)-(tabWaveLenA(((i + p)* lpas)+ j)- 128), $e8a200 +((i * 255)/ w))
                           zsav =(tabWaveLenA(((i + p)* lpas)+ j)- 128)
                        EndIf
                     Next j
                     LineXY(i, (h / 4), i, (h / 4), $CC8E00 +((i * 255)/ w))
                     LineXY(i, h -(h / 4), i, h -(h / 4), $CC8E00 +((i * 255)/ w))
                  Next i
                  LineXY(0, (h / 2), w, (h / 2), $222222)
               Case 16
                  ysav = tabWaveLenB(1)/(h / 0.9)
                  zsav = tabWaveLenB(0)/(h / 0.9)
                  LineXY(0, (h / 12), w, (h / 12), $BBBBBB)
                  LineXY(0, (h / 2)-(h / 12), w, (h / 2)-(h / 12), $BBBBBB)
                  LineXY(0, (h / 2)+(h / 12), w, (h / 2)+(h / 12), $BBBBBB)
                  LineXY(0, h -(h / 12), w, h -(h / 12), $BBBBBB)
                  For i = 0 To w
                     For j = 1 To lpas Step 1
                        j +(128 -(z * 4))
                        If ((i + p)* lpas)+ j <(dlen * 2)- 1
                           LineXY(i, (h / 4)- ysav, i, (h / 4)-(tabWaveLenB(((i + p)* lpas)+ j + 1)/(h / 0.6)), $e8a200 +((i * 255)/ w))
                           ysav = tabWaveLenB(((i + p)* lpas)+ j + 1)/(h / 0.6)
                           LineXY(i, h -(h / 4)- zsav, i, h -(h / 4)-(tabWaveLenB(((i + p)* lpas)+ j)/(h / 0.6)), $e8a200 +((i * 255)/ w))
                           zsav = tabWaveLenB(((i + p)* lpas)+ j)/(h / 0.6)
                        EndIf
                     Next j
                     LineXY(i, (h / 4), i, (h / 4), $CC8E00 +((i * 255)/ w))
                     LineXY(i, h -(h / 4), i, h -(h / 4), $CC8E00 +((i * 255)/ w))
                  Next i
                  LineXY(0, (h / 2), w, (h / 2), $222222)
            EndSelect
      EndSelect
      If play
         i=GetSoundPosition(0)/lpas-p
         If i>=0 And i<w
            DrawingMode(#PB_2DDrawing_AlphaBlend)
            Box(i, 0, 5, h, RGBA(190, 91, 60, 204))
         EndIf
      EndIf
      j = 0
      DrawingMode(#PB_2DDrawing_Transparent)
      If Round((tabWaveFile\DataChunkSize / tabWaveFile\ByteRate)- 0.3, #PB_Round_Nearest)> 1
         For i = 1 To(w * z)
            j + 1
            i +(lsec * 30)* z
            If i - p => 0 And i - p <= w
               LineXY(i - p, 0, i - p, h, $0000AA)
               DrawText((i - p)- 60, h - 15, FormatDate("%hh:%ii:%ss", (j * 30)), $0000AA)
            EndIf
         Next i
      EndIf
      DrawText(w - 60, 1, time, $000000)
      LineXY(((play + lsec)- lsec)* z, 0, ((play + lsec)- lsec)* z, h, $FF0000)
      StopDrawing()
      If z = 1
         SetGadgetState(1, 0)
      EndIf
      SetGadgetAttribute(1, #PB_ScrollBar_Maximum, lpos)
      ProcedureReturn #True
   EndIf
   
   
EndProcedure

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

If Not InitSound()
   MessageRequester("Initialize the sound environment", "No sound supported!")
   End
EndIf

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Global zoom.l = 1
Global pos.l = 0
Global play.b = #False

Procedure ScrollWAVImage()
   pos = GetGadgetState(1)
   DrawWAVFile(0, 0, 800, 256, zoom, pos, play)
EndProcedure
Procedure ZoomWAVImage()
   Select EventGadget()
      Case 5
         zoom - 1
         If zoom < 2
            pos = 0
         EndIf
         If zoom < 1
            zoom = 1
         EndIf
      Case 6
         zoom + 1
         If zoom > 16
            zoom = 16
         EndIf
   EndSelect
   DrawWAVFile(0, 0, 800, 256, zoom, pos)
EndProcedure
Procedure LoadAndPlayWAVSound()
   Select EventGadget()
      Case 2
         OpenWAVFile(OpenFileRequester("Ouvrir un archive Wav", "", "Musique Wav|*.wav", 0), 0, 0, 800, 256, zoom)
         GetWavInformation()
      Case 3
         If LoadSound(0, sFileName)
            ;SetSoundFrequency(0,1000)
            PlaySound(0)
         EndIf
      Case 4
         If IsSound(0)
            StopSound(0)
         EndIf
   EndSelect
EndProcedure

If OpenWindow(0, 0, 0, 800, 400, "PureWav", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
   CanvasGadget(0, 0, 0, 800, 256, 0)
   ScrollBarGadget(1, 0, 257, 800, 18, 1, 1, 1000)
   ButtonGadget(2, 10, 300, 100, 32, "Fichier Wav")
   ButtonGadget(3, 120, 300, 100, 32, "Play")
   ButtonGadget(4, 230, 300, 100, 32, "Stop")
   ButtonGadget(5, 10, 340, 100, 32, "Zoom -")
   ButtonGadget(6, 120, 340, 100, 32, "Zoom +")
   BindGadgetEvent(1, @ScrollWAVImage())
   BindGadgetEvent(2, @LoadAndPlayWAVSound())
   BindGadgetEvent(3, @LoadAndPlayWAVSound())
   BindGadgetEvent(4, @LoadAndPlayWAVSound())
   BindGadgetEvent(5, @ZoomWAVImage())
   BindGadgetEvent(6, @ZoomWAVImage())
   Repeat      
      play=Bool(IsSound(0) And SoundStatus(0)=#PB_Sound_Playing)
      DrawWAVFile(0, 0, 800, 256, zoom, pos, play)      
   Until WaitWindowEvent(1)= #PB_Event_CloseWindow
EndIf
Last edited by eddy on Thu Aug 08, 2013 9:55 pm, edited 3 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: WavForm of a sound in WAV format

Post by kvitaliy »

Doesn't support Unicode :(
Post Reply