Code
;Raw Sound Creation Demo
;By: Joakim L. Christiansen
;Version: 1.1
EnableExplicit
; Structure WAVEFORMATEX ;may need to uncomment on Linux or Mac
; wFormatTag.w
; nChannels.w
; nSamplesPerSec.l
; nAvgBytesPerSec.l
; nBlockAlign.w
; wBitsPerSample.w
; cbSize.w
; EndStructure
Global format.WAVEFORMATEX
Procedure setWaveFormat(bitsPerSample=16,samplesPerSec=44100)
format\wFormatTag = #WAVE_FORMAT_PCM
format\nChannels = 1 ;mono
format\wBitsPerSample = bitsPerSample ;8/16
format\nSamplesPerSec = samplesPerSec ;8000 Hz, 11025 Hz, 22050 Hz, and 44100 Hz
format\nBlockAlign = (format\nChannels * format\wBitsPerSample) / 8 ;equal to the product of nChannels and wBitsPerSample divided by 8 (bits per byte).
format\nAvgBytesPerSec = format\nSamplesPerSec * format\nBlockAlign ;equal to the product of nSamplesPerSec and nBlockAlign
EndProcedure
Procedure.l createTone(*address,volume.d,duration,frequency.d) ;returns needed size if address=0
;creates a triangle wave
Protected sample.l, result
Protected pos, dir, waveY.d, maxValue, centerValue
Protected samplesPerHalfWave, waveIncrementValue.d, size
Protected samplesSinceHalfWave, waveTop.d
size = (format\nSamplesPerSec / 1000*duration) * format\wBitsPerSample / 8
If *address = 0 ;return size needed
ProcedureReturn size
EndIf
If format\wBitsPerSample = 8
maxValue = 255
ElseIf format\wBitsPerSample = 16
maxValue = 65535
EndIf
centerValue = (maxValue/2)
waveTop = volume/1000 * centerValue
samplesPerHalfWave = (format\nSamplesPerSec / frequency) / 2
waveIncrementValue = waveTop / samplesPerHalfWave
For pos=0 To size
If dir=0
waveY + waveIncrementValue
Else
waveY - waveIncrementValue
EndIf
samplesSinceHalfWave + 1
If samplesSinceHalfWave >= samplesPerHalfWave
dir = dir!1 ;switch it
samplesSinceHalfWave = 0
EndIf
If format\wBitsPerSample = 8
sample = centerValue + waveY
PokeA(*address+pos,sample)
ElseIf format\wBitsPerSample = 16
sample = waveY
PokeW(*address+pos,sample)
pos+1
EndIf
Next
EndProcedure
Procedure.l createToneEx(*address,volumeAtStart.d,volumeAtEnd.d,duration.d,frequencyAtStart.d,frequencyAtEnd.d=0,noiseAtStart.d=0,noiseAtEnd.d=0,backToStart=0) ;returns needed size if address=0
;creates a triangle wave with added effects
Protected sample.l, result, pos, dir, waveY.d, maxValue, centerValue
Protected samplesPerHalfWave.d, waveIncrementValue.d, size, samplesSinceHalfWave, waveTop.d
Protected frequency.d, frequencyIncrementValue.d, noise.d, noiseIncrementValue.d, lastNoise.d, halfSize, loop, loops
Protected waveYpos.d, volumeIncrementValue.d, volume.d
volume = volumeAtStart
frequency = frequencyAtStart
noise = noiseAtStart
size = (format\nSamplesPerSec / 1000*duration) * format\wBitsPerSample / 8
If *address = 0 ;return size needed
If backToStart
ProcedureReturn size * 2
Else
ProcedureReturn size
EndIf
EndIf
If format\wBitsPerSample = 8
maxValue = 255
ElseIf format\wBitsPerSample = 16
maxValue = 65535
EndIf
centerValue = (maxValue/2)
waveTop = centerValue
samplesPerHalfWave = (format\nSamplesPerSec / frequency) / 2
waveIncrementValue = waveTop / samplesPerHalfWave
volumeIncrementValue = (volumeAtEnd - volumeAtStart) / size * format\wBitsPerSample/8
frequencyIncrementValue = (frequencyAtEnd - frequencyAtStart) / size * format\wBitsPerSample/8
noiseIncrementValue = (noiseAtEnd - noiseAtStart) / size * format\wBitsPerSample/8
If backToStart: loops=1: EndIf
For loop=0 To loops
For pos=pos To size
If volumeAtEnd
volume + volumeIncrementValue
EndIf
If frequencyAtEnd
frequency + frequencyIncrementValue
samplesPerHalfWave = (format\nSamplesPerSec / frequency) / 2
waveIncrementValue = waveTop / samplesPerHalfWave
EndIf
If noiseAtEnd
noise + noiseIncrementValue
EndIf
If dir=0
waveYpos + waveIncrementValue
Else
waveYpos - waveIncrementValue
EndIf
samplesSinceHalfWave + 1
If samplesSinceHalfWave >= samplesPerHalfWave
If dir=0
waveYpos = waveTop
Else
waveYpos = -waveTop
EndIf
dir = dir!1 ;switch it
samplesSinceHalfWave = 0
EndIf
waveY = waveYpos
;waveY = waveY*16
;waveY + Random(90000)
If noiseAtStart
If lastNoise >= noise; Random(noise) = 0
Select 0
Case 0: waveYpos = Random(maxValue)-centerValue
Case 1: waveY = Random(maxValue)-centerValue
;Case 2: waveYpos = Random(maxValue) ; waveY + Random(90000)
EndSelect
lastNoise = 1
Else
lastNoise+1
EndIf
EndIf
;adjust volume
waveY = volume/1000 * waveY
If format\wBitsPerSample = 8
sample = centerValue + waveY
PokeA(*address+pos,sample)
ElseIf format\wBitsPerSample = 16
sample = waveY
PokeW(*address+pos,sample)
pos+1
EndIf
Next
If backToStart ;morph back
If volumeAtEnd
volume = volumeAtEnd
EndIf
If frequencyAtEnd
frequency = frequencyAtEnd
EndIf
If noiseAtEnd
noise = noiseAtEnd
EndIf
volumeIncrementValue = -volumeIncrementValue
frequencyIncrementValue = -frequencyIncrementValue
noiseIncrementValue = -noiseIncrementValue
size+size
EndIf
Next
EndProcedure
Procedure addWaveHeader(*address,dataSize,channels,samplesPerSec,blockAlign,bitsPerSample)
; RIFF Chunk
PokeL(*address+ 0, 'FFIR')
PokeL(*address+ 4, dataSize + 36)
PokeL(*address+ 8, 'EVAW')
; FORMAT Chunk
PokeL(*address+ 12, ' tmf')
PokeL(*address+ 16, $0010)
PokeW(*address+ 20, $01)
PokeW(*address+ 22, channels)
PokeL(*address+ 24, samplesPerSec)
PokeL(*address+ 28, samplesPerSec * channels * (bitsPerSample / 8) )
PokeW(*address+ 32, blockAlign)
PokeW(*address+ 34, bitsPerSample)
; DATA Chunk
PokeL(*address+ 36, 'atad')
PokeL(*address+ 40, dataSize)
EndProcedure
Procedure catchTone(volume,duration,frequency)
Protected *memory, id, size
size = createTone(0,volume,duration,frequency) ;get size
*memory = AllocateMemory(44+size)
createTone(*memory+44,volume,duration,frequency) ;write wave data to memory
addWaveHeader(*memory,size,format\nChannels,format\nSamplesPerSec,format\nBlockAlign,format\wBitsPerSample)
id = CatchSound(#PB_Any,*memory)
FreeMemory(*memory)
ProcedureReturn id
EndProcedure
Procedure catchToneEx(volumeAtStart,volumeAtEnd,duration,frequencyAtStart,frequencyAtEnd=0,noiseAtStart=0,noiseAtEnd=0,backToStart=0)
Protected *memory, id, size
size = createToneEx(0,volumeAtStart,volumeAtEnd,duration,frequencyAtStart,frequencyAtEnd,noiseAtStart,noiseAtEnd,backToStart) ;get size
*memory = AllocateMemory(44+size)
createToneEx(*memory+44,volumeAtStart,volumeAtEnd,duration,frequencyAtStart,frequencyAtEnd,noiseAtStart,noiseAtEnd,backToStart) ;write wave data to memory
addWaveHeader(*memory,size,format\nChannels,format\nSamplesPerSec,format\nBlockAlign,format\wBitsPerSample)
id = CatchSound(#PB_Any,*memory)
FreeMemory(*memory)
ProcedureReturn id
EndProcedure
InitSound()
setWaveFormat(16,44100)
Define snd_explosion, snd_laser, snd_shoot, snd_pacman, snd_flying
snd_explosion = catchToneEx(1000,100, 1000, 50,20, 20,100)
snd_laser = catchToneEx(1000,100, 300, 1500,200)
snd_shoot = catchToneEx(1000,1, 500, 200,10, 1,10)
snd_pacman = catchToneEx(500,0, 100, 400,200, 0,0, #True)
snd_flying = catchToneEx(500,0, 200, 10,0, 5,10, #True)
PlaySound(catchToneEx(1000,100, 2000, 200,40, 0,0)):Delay(2000)
PlaySound(catchToneEx(1000,100, 2000, 10,200, 100,1 )):Delay(2000)
PlaySound(snd_flying): Delay(400)
PlaySound(snd_flying): Delay(400)
PlaySound(snd_flying): Delay(400)
PlaySound(snd_flying): Delay(400)
PlaySound(snd_pacman): Delay(200)
PlaySound(snd_pacman): Delay(200)
PlaySound(snd_explosion): Delay(1000)
PlaySound(snd_laser): Delay(300)
PlaySound(snd_laser): Delay(300)
PlaySound(snd_shoot): Delay(1000)
PlaySound(catchToneEx(1000,100, 2000, 200,10, 1,100 )):Delay(2000)
;Have fun! ;-)