Another sound question

BlitzMax Forums/BlitzMax Beginners Area/Another sound question

Hi gang,

You have no idea how frustrating this is for a casual programmer like myself. Why doesn't Blitz have better sound commands?

What I'm trying to do is just play simple sounds, maybe two or three notes at a time. I'm not interested in loading WAV files or OGG or anything like that, I want the computer just to beep and boop on que.

Here's my code so far:

Global duration:Int=0
Global note:Int=0

Graphics 640,480,0
Playnote(0,100)
WaitKey
End

Function PlayNote(note,duration)
Local sample1:TAudioSample=CreateAudioSample( 16,13675,SF_MONO8 )
For Local k=0 Until 32
sample1.samples[k]=Sin(k*360/32)*127.5+127.5+note
Next
Local sound1:TSound=LoadSound( sample1,True )

timer=CreateTimer(20)
channel=AllocChannel()

PlaySound sound1,channel

For i=1 To duration; WaitTimer timer; Next
StopChannel channel
End Function


Basically, it works...but it sounds awful. How do I get a pure note, middle C? From there I can step backwards and forwards thru the musical scale.

Here's a formula that I found on the web: amplitude * SIN( 360 * time / period ). That's great, but I'm an idiot on some topics and implementing this is bumping up against my dummy regions.

P.S. Ultimately I'd like to create a function that works like the old Atari SOUND command (SOUND voice, pitch, distortion, loudness)

The A below middle C has a frequency of 440Hz, you can extrapolate from there.

Okay, I saw that somewhere else too. Thanks for the quick reply.

I guess what I'm asking for at the moment is help with the formula, to make it a pure note.

sample1.samples[k]=Sin(k*360/32)*127.5+127.5+note was lifted from the Blitzwiki, I have no idea how to change it to sound better. I've experimented for a bit, I've changed the pitch etc but it still sounds bad.

Try for k=0 to 31 - going up to 32 will introduce a small discontinuity in your sine wave. Don't add note on as a constant - you need it as a frequency multiplier inside the bracket. Use decimals in all your numbers, eg 360.0/32.0.

Hi Nomen,

I changed K so that it's limit is 31; that got rid of a clipping sound I was hearing at the beginning.

"Note" is just a variable name, I can change it to anything.

It's sounding a bit better now, I figured out that by changing the second value in this line:

Local sample1:TAudioSample=CreateAudioSample( 16,13675,SF_MONO8 )

to something other than 13675, that changes the pitch. Now I just have to figure out what middle C is. It sure isn't 256Hz or 264Hz, 'cause those numbers don't work in this situation.

Here's something for you to be getting on with lotonah...
Strict 

Graphics 640,480,0

Local Note = 64

Repeat
	Cls
	DrawText "Use Spacebar to play sound, Up/Down to change note, Escape to quit",10,5
	DrawText "Note = "+Note,10,25
	If KeyHit(KEY_UP) Then Note:+1
	If KeyHit(KEY_DOWN) Then Note:-1
	If KeyHit(KEY_SPACE) Then PlayNote(Note,1000)
	Flip
Until KeyDown(KEY_ESCAPE)
End

Function PlayNote(note#,duration)	' NOTE: duration is in milliseconds

	' create a channel that will be reused each time this function is called
	Global channel:TChannel = AllocChannel()

	' calculate frequency for required note
	Local period#    = (10.0*12.0*16.0*4.0) - (NOTE*16.0*4.0) 
	Local frequency# = (8363.0*2^((6.0*12.0*16.0*4.0 - Period) / (12.0*16.0*4.0)))
	SetChannelRate(channel,frequency/44100)

	' calculate how many bytes are needed to play for the duration time
	Local length = (frequency/1000) * duration

	' create the waveform
	Local sample1:TAudioSample = CreateAudioSample( length,44100,SF_MONO8 )
	Local k ; For k=0 Until length
		sample1.samples[k]=(Sin(k*2)*127.0)+128
	Next
	Local sound1:TSound=LoadSound( sample1 )

	' play it
	PlaySound sound1,channel

End Function