Code archives/Audio/.wav samples value

This code has been declared by its author to be Public Domain code.

Download source code

.wav samples value by Flanker2016
Load a .wav audio file with :
sound = WaveLoad("music.wav")

Then you can access to any sample value with the function :
value = WaveSample(time)

Time is the time in millisecs from the beginning of the wav file. An optional channel parameter let you choose wich channel sample you want.

It only works with 16bits or 8bits stereo or mono PCM .wav files ! Blitz3D doesn't handle 24 and 32 bits audio, and doesn't work well with more than 2 channels.
Graphics 800,600,32,2
SetBuffer BackBuffer()

; variables
Global wavBank
Global wavChannels
Global wavFrequency
Global wavBytePerSec
Global wavBytePerBloc
Global wavBits
Global wavDataSize

Print "Loading .wav...":Flip
Global wavSound = WaveLoad("test16bits.wav") ; ONLY WORKS WITH MONO AND STEREO WAV 8 OR 16 BITS

PlaySound wavSound
wavStartTime = MilliSecs()

;------------------------------------------------------------------------------------;
While Not KeyHit(1)

	Cls
	
	; waveform
	wavCurrentTime = MilliSecs()-wavStartTime
	For channel = 0 To wavChannels-1
		For i = 0 To 800
			Plot i,75+channel*150+WaveSample(wavCurrentTime+i,channel)/500
		Next
	Next
	
	Flip 0

Wend
;------------------------------------------------------------------------------------;

FreeSound wavSound
FreeBank wavBank

End

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function WaveLoad(wavPath$)

	If FileType(wavPath) = 1
		wavBank = CreateBank(FileSize(wavPath))
		wavFile = OpenFile(wavPath)
		ReadBytes wavBank,wavFile,0,FileSize(wavPath)
		CloseFile wavFile
	Else
		Return 0
	EndIf

	If Chr(PeekByte(wavBank,0)) + Chr(PeekByte(wavBank,1)) + Chr(PeekByte(wavBank,2)) + Chr(PeekByte(wavBank,3)) = "RIFF"
	
		If PeekInt(wavBank,4)+8 = FileSize(wavPath) ; file size
		
			If Chr(PeekByte(wavBank,8)) + Chr(PeekByte(wavBank,9)) + Chr(PeekByte(wavBank,10)) + Chr(PeekByte(wavBank,11)) = "WAVE"
			
				If Chr(PeekByte(wavBank,12)) + Chr(PeekByte(wavBank,13)) + Chr(PeekByte(wavBank,14)) + Chr(PeekByte(wavBank,15)) = "fmt "
	
					If PeekInt(wavBank,16) = 16 ; bloc Size
					
						If PeekShort(wavBank,20) = 1 ; PCM
													
							If Chr(PeekByte(wavBank,36)) + Chr(PeekByte(wavBank,37)) + Chr(PeekByte(wavBank,38)) + Chr(PeekByte(wavBank,39)) = "data"
							
								wavChannels = PeekShort(wavBank,22)
								wavFrequency = PeekInt(wavBank,24)
								wavBytePerSec = PeekInt(wavBank,28)
								wavBytePerBloc = PeekShort(wavBank,32)
								wavBits = PeekShort(wavBank,34)
																
								wavDataSize = PeekInt(wavBank,40)
								
								If wavBits <= 16 And wavChannels <= 2							
									wavSound = LoadSound(wavPath)
									Return wavSound
								Else
									Return 0
								EndIf
								
							EndIf
							
						EndIf
					
					EndIf				
				
				EndIf
			
			EndIf
		
		EndIf
		
	EndIf

End Function

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function WaveSample(time,channel=0)
	
	offset = time*Float(wavBytePerSec)/1000/wavChannels/(wavBits/8)
	If offset > wavDataSize/wavChannels/(wavBits/8) Or offset < 0 Then Return 0
	
	Select wavBits
		Case 8
			sample = (PeekByte(wavBank,offset*wavChannels+channel)-128)*128
		Case 16
			sample = PeekShort(wavBank,offset*wavChannels*2+channel*2)
			If sample > 32768 Then sample = sample - 65535
	End Select

	Return sample

End Function

Comments

Charrua2016
very nice!, thank's for share, here an example of a filter:

for a smoothed oval, define a variable:

local alpha#=0.025 ;1=no smooth, 0.025 very!

and in the main loop, just after your oval insert

Oval 300-radius,300-radius,radius*2,radius*2,1
;just a smoothed one
smoothRadius# = Float(targetRadius) * alpha# + (smoothRadius# * ( 1.0 - alpha#))
Oval 500-smoothRadius,300-smoothRadius,smoothRadius*2,smoothRadius*2,1


note that i shift your oval to the left somewhat to place my oval somewhat to the right (to not overlap each other)

here a test1.wav for playing:
https://dl.dropboxusercontent.com/u/78894295/tmp1/test1.wav

and the exe, just in case:
https://dl.dropboxusercontent.com/u/78894295/tmp1/waveload.zip

modified source code:
https://dl.dropboxusercontent.com/u/78894295/tmp1/waveload.bb

Juan


Flanker2016
Thanks for the addition, I tried to do it at first but it didn't work very well.


Bobysait2016
Good one Flanker ^^

Just a small thing :
- A loaded file should not generate runtime errors, it should just return "0" if failed
I know it can relevant to generate errors, but to be consistent with blitz3d stuff, you might not want to introduice different behaviors who could lead to headackes to remember which function required to check the file exists before trying to load from the ones who returns a "0" to check.


Flanker2016
Yes you're right bobysait, it should return 0 instead of generating a runtime error. It's just there because before it was a function the code was in the main program and I forgot to remove that ^^

I will update the code when I'm back on my computer, so it can work with both mono and stereo and 8 or 16bits. It seems that wav files with more than 2 channels are not well supported with blitz3d, same with 32bits samples.


Flanker2016
Code updated so it works with 8 and 16 bits, stereo or mono PCM waves, and no need anymore for an array, it works directly from the bank so it's faster to load and takes less memory.

Blitz3D doesn't work with 24 and 32bits wav audio, and when there is more than 2 channels, it needs ChannelPitch to play the audio at the original speed.


Code Archives Forum