Waves again

Just starting out? Need help? Post your questions and find answers here.
Megaborsti
User
User
Posts: 35
Joined: Sat Aug 16, 2003 4:52 pm
Location: Germany

Waves again

Post by Megaborsti »

Hi,
I asked about wave-files not long ago and wrote the following test-program, but the created file cannot be played with the mediaplayer.
Why not? Can anyone help me?

Code: Select all

  CreateFile(0,"wavtest.wav")
 
  WriteString("RIFF")
  WriteLong(932)
  WriteString("WAVEfmt ")
  WriteLong(16)
  WriteWord(1)
  WriteWord(2)
  WriteLong(22050)
  WriteLong(44100)
  WriteWord(4)
  WriteWord(16)
  WriteString("data")
  WriteLong(880)
  
  For a = 0 To 10
    WriteLong(0)
  Next
  For a = 0 To 100
    WriteLong(65536)
    WriteLong(-65536)
  Next
  For a = 0 To 10
    WriteLong(0)
  Next 
I become better!!! :)
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Post by GPI »

Maybe this help:
I translatet a programm from Delphi (i think):

It create a wave in the memory and play it.

Code: Select all

Procedure CreateSound(nr,Frequency,Duration,SampleRate); 
  SoundValue.b
  w.f; // omega ( 2 * pi * frequency) 
 
  wave_FormatEx.wave_
  wave_FormatEx\wFormatTag=#WAVE_FORMAT_PCM; 
  wave_FormatEx\nChannels =$0001;mono 
  wave_FormatEx\nSamplesPerSec = SampleRate; 
  wave_FormatEx\wBitsPerSample = $0008; 
  wave_FormatEx\nBlockAlign = (wave_FormatEx\nChannels * wave_FormatEx\wBitsPerSample) /8
  wave_FormatEx\nAvgBytesPerSec = wave_FormatEx\nSamplesPerSec * wave_FormatEx\nBlockAlign; 
  wave_FormatEx\cbSize = 0; 
  
  DataCount = (Duration * SampleRate)/1000; // sound data 
  RiffCount = 4+4 +4+ SizeOf(wave_)+4 +4+ DataCount
  
  start=GlobalAlloc_(#GMEM_FIXED|#GMEM_ZEROINIT,RiffCount+100)
  MS=start
  
  PokeS(MS,"RIFF"):MS+4   ;'RIFF' 
  PokeL(MS,RiffCount):MS+4 ;file Data size 
  PokeS(MS,"wave"):MS+4   ;'wave_' 
  PokeS(MS,"fmt "):MS+4    ;'fmt ' 
  TempInt = SizeOf(wave_); 
  PokeL(MS,TempInt):MS+4   ;Twave_Format data size
  
  PokeW(MS,wave_FormatEx\wFormatTag):MS+2; wave_FormatEx record
  PokeW(MS,wave_FormatEx\nChannels):MS+2
  PokeL(MS,wave_FormatEx\nSamplesPerSec):MS+4
  PokeL(MS,wave_FormatEx\nAvgBytesPerSec):MS+4
  PokeW(MS,wave_FormatEx\nBlockAlign):MS+2
  PokeW(MS,wave_FormatEx\wBitsPerSample):MS+2
  PokeW(MS,wave_FormatEx\cbSize):MS+2
  
  PokeS(MS,"data"):MS+4   ;'data' 
  PokeL(MS,DataCount):MS+4 ;sound data size 
  
  ; {Calculate And write out the tone signal}  // now the Data values 
  
  w = 2 * 3.1415 * Frequency;  omega 
  For i = 0 To DataCount - 1
   SoundValue = 127 + 127 * Sin(i * w / SampleRate);
   PokeB(MS,SoundValue):MS+1; 
  Next
  CatchSound(Nr,start)
  GlobalFree_(start)
EndProcedure
and it is now part of the jaPBe-IncludePack1
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

Post by Froggerprogger »

Here one more.
Simply creates a WAV-file with a sinustone.

Code: Select all

;-  04.09.03 by Froggerprogger
;-  04.09.03 by Froggerprogger
;- 
;-  Tip: You can replace the byte-text-output with the following:
;-
;-  WriteLong($46464952) = "RIFF"
;-  WriteLong($45564157) = "WAVE"
;-  WriteLong($20746D66) = "fmt "
;-
;-  You can even use WriteString("RIFF") and WriteString("WAVEfmt "), because PB doesn't write a 
;-  terminating 0 - but I don't like this way, perhaps it's too easy ;-)
;-
;- For further information on the WAV-format look at: http://www.sonicspot.com/guide/wavefiles.html 

#pi = 3.141593                      ; pi
#fq = 220                           ; frequenz in Hz for sinustone
#samplerate = 44100                 ; samplerate
#bitrate = 16                       ; Bits per sample, #bitrate Mod 8 must be 0 !
#channels = 2                       ; number of channels
#secs = 4                           ; time for the sinustone in seconds
#soundfilename.s = "wavtest.wav"    ; filename fr the soundfile

avBytesPerSec.l = #channels*#bitrate/8*#samplerate  ; calculate the average bytes per second

CreateFile(0, #soundfilename) 
  WriteByte(Asc("R"))               ; here you can use WriteLong($46464952) instead - see the tip on top
  WriteByte(Asc("I"))
  WriteByte(Asc("F"))
  WriteByte(Asc("F"))
  WriteLong(36+avBytesPerSec*#secs) ; normally filesize - 8 Bytes, here a bit tricky, fmt-chunk + data-chunk

  WriteByte(Asc("W"))
  WriteByte(Asc("A"))
  WriteByte(Asc("V"))
  WriteByte(Asc("E"))
  
  WriteByte(Asc("f"))
  WriteByte(Asc("m"))
  WriteByte(Asc("t"))
  WriteByte(Asc(" "))
  WriteLong(16)                     ; chunk data size

  WriteWord(1)                      ; compression code 
  WriteWord(#channels)              ; number of channels
  WriteLong(#samplerate)            ; samplerate
  WriteLong(avBytesPerSec)          ; average bytes per second, here 2(channels)*2(block align)*44100(samplerate)
  WriteWord(#bitrate/8*#channels)   ; Block Align ('bytes per sample')
  WriteWord(#bitrate)               ; Bits per sample
  WriteByte(Asc("d"))
  WriteByte(Asc("a"))
  WriteByte(Asc("t"))
  WriteByte(Asc("a"))
  WriteLong(avBytesPerSec*#secs)    ; data chunk size in byes

  Global  actsamplevalue.w         ; for signed RAW data
  
  For acttime = 1 To #samplerate * #secs
    For actchannel = 1 To #channels
        actsamplevalue = 32767 * Sin(2 * #pi * #fq * acttime / #samplerate)
        WriteWord(actsamplevalue)
    Next
  Next
CloseFile(0)
%1>>1+1*1/1-1!1|1&1<<$1=1
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

may i ask how wav files are formated so i can understand this more
~Dreglor
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

@Froggerprogger:

Instead of writing Asc("W"), you can simply write 'W' .
The compiler then inserts the ASCII value for that character in that place.
so do it like:

WriteByte('W')

And this works even with more characters, so instead of doing:

WriteLong($46464952) ; = "RIFF"

You can actually do:

WriteLong('FFIR')

Note, that this must be reversed here, due to the little-endian thingy.

Timo
quidquid Latine dictum sit altum videtur
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

Post by Froggerprogger »

@freak
Thanks for this! I haven't known, but the 'xxx' is a very cool compiler-feature !

@Dreglor
For example here you'll find information on the possible wav-chunks. The data-chunk is the one storing the uncompressed RAW-data.
http://www.sonicspot.com/guide/wavefiles.html
%1>>1+1*1/1-1!1|1&1<<$1=1
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2071
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Post by Andre »

@freak
Thanks for this! I haven't known, but the 'xxx' is a very cool compiler-feature !
Freak, would you write a little extension for the manual about this feature, please ?
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Post by GPI »

Andre wrote:
@freak
Thanks for this! I haven't known, but the 'xxx' is a very cool compiler-feature !
Freak, would you write a little extension for the manual about this feature, please ?
debug 'A'
debug 'a'
debug 'HA'
debug 'HALL'

'xxxx' is the same like
string.s="xxxx"
debug peekl(@string)
'xx'
string.s="xx"
debug peekw(@string)
'x'
string.s="x"
debug peekb(@string)
debug asc(string)

GPI
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

Post by Froggerprogger »

But (of course) be careful with the order of the letters:

Code: Select all

;'HALL' is the same like PeekL("LLAH")
Debug 'HALL' 
string.s="LLAH" 
Debug PeekL(@string) 

;'HAL' is the same like PeekL("LAH")
Debug 'HAL' 
string.s="LAH" 
Debug PeekL(@string) 

;'HA' is the same like PeekL("AH")
Debug 'HA'
string.s="AH" 
Debug PeekL(@string) 
Debug PeekW(@string) 

;'H' is (of course) the same like PeekL("H")
Debug 'H'
string.s="H" 
Debug PeekL(@string)
Debug PeekW(@string)
Debug PeekB(@string) 
Debug Asc(string) 
%1>>1+1*1/1-1!1|1&1<<$1=1
Post Reply