Sound FX Woes

Blitz3D Forums/Blitz3D Beginners Area/Sound FX Woes

Some strange problems I have observed.

Some .wav sounds loop automatically when I play them.
Some do not.
Some sounds play hundreds of times per second.

I find that loading the background music is best done outside the game loop.

Does anyone have solutions to these problems or know where to look for the answers?

PS: If at all possible, please do not answer to comlicatedly as I have trouble understanding some of the more complex stuff. If this is not possible, I understand.

Thanks in advance!

code examples ?

Code example would be good yeah. When you have .wav loops that do not loop, you should assign a channel upon playing the sound, look for the channel commands in the manual, then check to see if the channel is still playing.

TBH though, you don't have the greatest control over sounds in blitz basic.

Ok, I'll get some examples. It may take a day, though.

I find that loading the background music is best done outside the game loop.


Maybe that's your problem. You don't load anything at the game loop - you load it once, and just play/emit the sounds during the game loop; after it's finished you free them, and that's it.

The music is the only thing I emit from outside the game loop. If I use it inside, it just repeats numerous times per second. I would do the same thing with the sounds but If... Then statements do not work too well out side the game loop.
I'm guessing that channels might solve this problem but I don't know how to use them too well.

Ok. I guess it didn't take a whole day.

Here is an example of a sound that repeats numerous times per second:
Global thrust=LoadSound("Escaping The Atmosphere.wav")

Graphics3D 1024,764
SetBuffer BackBuffer()

While Not KeyDown(1)

;Run gauge
If fin=0 Then
     Color 255,255,255
     Rect 90,155,run#,20,1
     
     If MouseDown(2) And KeyDown(200=True Then
          run#=run# -.8
          thrustchn=PlaySound(thrust)
         Else
          run#=run# +.3
     EndIf
EndIf

RenderWorld
Flip

Wend

End

My guess is that this is because of the MouseDOWN command. Though, I can't get the result I want with the gauge with a MouseDown command.

Here is an example of a sound that repeats automatically:
Global die=LoadSound("Screams Male 03.wav")

Graphics3D 1024,764
SetBuffer BackBuffer()

While Not KeyDown(1)

targethealth(ammo.bullet,foe.target)

RenderWorld
Flip

Wend

End

Function targethealth(ammo.bullet,foe.target)
     If CountCollisions(ammo\shape)>0
          entity=EntityCollided(ammo\shape,type_target)
          If entity>0
               foe.target=Object.target(EntityName(entity))
               foe\health=foe\health-1
               If foe<>Null And foe\health=0
                    HideEntity foe\shape
                    HideEntity ammo\shape
                    dascore#=dascore#+1
                    foesleft=foesleft-1
                    PlaySound(die) 
               EndIf
          EndIf
     EndIf
End Function


Behold my barbaric coding!
If you have any channel advice for this, it would help, I'm sure.

PS: Sorry if I am being a pest asking all these questions. But I do appriciate the help.

In the first example the sound keeps restarting as long as the mouse button is depressed try this

If Not ChannelPlaying(thrustchn)
	thrustchn=PlaySound(thrust)
End if


In the second example you are not deleting the type so it never equals null and the condition If foe<>Null And foe\health=0 is always true

Hmm... Ok, I'll give it a go.
Thanks!

Unfortunately, your first suggestion didn't work and I couldn't figure out how to apply the second.

this didn't work, i don't know how you didn't get an error with your initial code anyway as it was lacking the closing parenthesis on KeyDown(200 lol

If MouseDown(2) And KeyDown(200)=True
  	run#=run# -.8
  	If Not ChannelPlaying(thrustchn)
	      thrustchn=PlaySound(thrust)
	End if
 Else
  	run#=run# +.3
EndIf


in the second example you never delete the type so the condition remains true and the sound will continue to be played forever ie foe will NEVER be null

The KeyDown(200 was actually a typo.
I'll try the new code example.

When I tried to delete the type, it pointed to "foe\health=foe\health-1" and said entity does not exist.
A code example for this would be quite helpful, as I am new to types.

Aha! The Thrust code worked! It started to loop automatically so I put in a StopChannel command. Thanks!

Still need help with the types though.

Ace Killjoy, have you seen my website (programming tutorial) with its explanation of Types. I don't know how much of it you might find useful but it might be worth taking a look.

Also, checking out how Types are used in some of the code examples on my website might help as well.

Link is in my signature...

Wow, that's handy.
I may have to reffer to that later.
I'm still not sure how to solve my problem.
I'll try messing around with the conditions.

EDIT: I'm going to need more help on this one. I can't figure out how to Null it after the sound plays.

delete foe.target
you should also free any entities accoiated with the type before you delete it

So, just to clarify, I delete foe.target after the PlaySound command and free the entities in between the Wend and End?
I'll try fiddling about with it though.

EDIT: I'm going to need the know pretty much exactly what to do because I can't seem to figure it out on my own.

Hi, the problem with looping sounds is the SMPT chuck inside of the samples, look in BlitzBassStudio. In STUFF you will find a wav.bb to fix this samples. With this code you can also create "perfekt" autoloops.

bye

Edit :SMPL not SMPT

I'm sorry. I haven't been coding for more than a few years.
What is an SMPT chuck and BlitzBassStudio?

see my signature. BlitzBassStudio is an audio engine from un4seen with includes and decls for blitzbasic. But for wav.bb you dont need to use bass.

bye

wav files can contain a marker which tells DirectX to automatically loop the sound.
If you have such a wav file, you will have to load and save in a wav editor to remove the marker.

For intentional looping have you tried LoopSound()?

That is not true.

directsound only supports the officiel Microsoft Chunks (RIFF FMT DATA).

Blitzbasic dont use directsound but fmod 3.x. This engine supports the SMPL chuck and only open an output stream to directsound...nothing more.

to remove the SMPL you can also only use an editor who ignore that. As i now AUDACITY also ignore SMPL.

bye

;Abrexxes 2007
;With this you can read, write a wav header and make sample loops for blitzbasic.
;You dont need Loopsound () but make perfect loops. ;)
;You dont need this global, but you can use it to see the data size of your wav file for max value

Global s_datalenght%

Graphics 640,480,0,2
SetBuffer BackBuffer ()

;LoadLoopSound("test.wav",0,0) ; no loop
LoadLoopSound("test.wav",1,s_datalenght) ; maximum loop
;LoadLoopSound("test.wav",800,8000) ; what you want but not more then datalenght

musik = LoadSound ("s_temp.wav")
DeleteFile "s_temp.wav"


While Not KeyHit (1)
Cls
If KeyHit (57) Then
PlaySound (musik)
EndIf
Text 10,10,"Press space to play"
Text 10,20, "Datasize = "+s_datalenght
Flip
Wend
End



Function LoadLoopSound(s_file$,s_start%,s_end%)

;**********************************
;**** Read Source Wav File *****
;**********************************
s_source = ReadFile (s_file)

; read RIFF header (1179011410) to see if it is a wav file
s_check = ReadInt (s_source)
      If s_check = 1179011410 Then ; RIFF found
            s_check = ReadInt (s_source)
            s_sourcesize = (s_check + 8) ; size of sourcefile
            s_check = ReadInt (s_source) ; read "wave"
      EndIf   
If Not s_check = 1163280727 Then Return 0 ; no wave..go away with that :)
                     
; search and read   FMT chunk for sample infos      
s_position = 12
s_goal = 0
Repeat
      SeekFile s_source, s_position
            s_check = ReadInt (s_source)
                  If s_check = 544501094 Then ; FMT found
                        s_goal = 1 ; now lets read and store all the infos
                              s_fmtsize = ReadInt (s_source) ;<fmt length>  size of this chunk, normal = 16 byte from here
                              s_format = ReadShort (s_source)   ;<format tag>    sample format, normal = 1 (hex) for PCM
                              s_channels = ReadShort (s_source) ;<channels>  1 = mono, 2 = stereo
                              s_rate = ReadInt (s_source) ;<sample rate>    (hz)
                              s_bytes = ReadInt (s_source) ;<bytes/second>    Sample-Rate * Block-Align
                              s_block = ReadShort (s_source) ;<block align>    Channels * bits/sample / 8
                              s_bit = ReadShort (s_source) ;<bits/sample>    8, 16 or 24
                  EndIf
            s_position = s_position +1 ;FMT not found, next step
If s_goal = 1 Then Exit   ; ok    
Until Eof (s_source) = 1
If s_goal = 0 Then Return 0 ; no FMT found, Error

; search and read DATA chunk
s_position =12
s_goal = 0
Repeat
      SeekFile s_source, s_position
            s_check = ReadInt (s_source)
            If s_check = 1635017060 Then ; DATA found
                  s_goal = 1
                  s_datalenght = ReadInt (s_source) ;<length> of data block
                  sbank_cache = CreateBank (s_datalenght) ; now we store the sample data
                        For i = 0 To (s_datalenght-1)
                              s_value = ReadByte (s_source)
                              PokeByte sbank_cache,i,s_value
                        Next
            EndIf
      s_position = s_position +1 ; DATA not found, next step
If s_goal = 1 Then Exit ; ok
Until Eof (s_source) = 1
If s_goal = 0 Then Return 0 ; no DATA found, Error

CloseFile s_source ; we have what we need, all other chunks we can ignore

;**********************************
;**** Write temp Wav File *****
;**********************************

s_temp = WriteFile ("s_temp.wav") ; create a temp

;write RIFF header
WriteInt s_temp, 1179011410 ; RIFF
WriteInt s_temp, s_sourcesize-8 ;size of header
WriteInt s_temp, 1163280727 ; WAVE

;write FMT chunk
WriteInt s_temp, 544501094 ; FMT
WriteInt s_temp, s_fmtsize ;<fmt length>
WriteShort s_temp, s_format ;<format tag>
WriteShort s_temp, s_channels ;<channels>
WriteInt s_temp, s_rate ;<sample rate>
WriteInt s_temp, s_bytes ;<bytes/second>
WriteShort s_temp, s_block ;<block align>
WriteShort s_temp, s_bit ;<bits/sample>
                  
;write SMPL chunk
WriteInt s_temp, 1819307379 ;SMPL
WriteInt s_temp, 60 ;36 + 1 sample loop section (24)
WriteInt s_temp, 0 ; Manufacturer , we dont need    
WriteInt s_temp, 0   ; ProductID , we dont need
WriteInt s_temp, 0   ;Sample Period    ,not supported by blitzbasic
WriteInt s_temp, 0   ;MIDI Unity Note    ,not supported by blitzbasic
WriteInt s_temp, 0   ;MIDI Pitch Fraction    ,not supported by blitzbasic
WriteInt s_temp, 0   ;SMPTE Format    ,not supported by blitzbasic
WriteInt s_temp, 0   ;SMPTE Offset    ,not supported by blitzbasic
WriteInt s_temp, 0 ;Num Sample Loops    ,not supported by blitzbasic
WriteInt s_temp, 0   ;Sampler Data    ,not supported by blitzbasic

WriteInt s_temp, 0 ;Cue Point ,not supported by blitzbasic
WriteInt s_temp, 0 ;Type    ,not supported by blitzbasic
WriteInt s_temp, s_start ;   Start loop
WriteInt s_temp, s_end ;End loop
WriteInt s_temp, 0 ;Fraction ,not supported by blitzbasic
WriteInt s_temp, 0 ;Play Count ,not supported by blitzbasic

;write DATA chunk & data
WriteInt s_temp, 1635017060 ; DATA
WriteInt s_temp, s_datalenght ;<length>
WriteBytes (sbank_cache,s_temp,0,s_datalenght) ;sample data from bank
FreeBank sbank_cache ; we no need this longer

CloseFile s_temp

End Function 
;~IDEal Editor Parameters:
;~C#Blitz3D


I was thinking...
Do you think I could fix this problem with a timer?

"That is not true. directsound only supports the officiel Microsoft Chunks (RIFF FMT DATA). Blitzbasic dont use directsound but fmod 3.x."

Then this currently looping wav file in B3D must just be my imagination then, eh?

(I use Audio Cleaning Lab to save/load the wav file and problem goes away.)