The original function was written by Ric 20 years ago.
https://forum.thegamecreators.com/thread/49008
I've ported it to AppGameKit, which has a different memblock header, and clarified some previous unknowns in the original code. You can change the sample rate, but altering the number of channels or bits per sample would require you to also update how the sound frames are written to the memblock. Not hard, I just didn't do it. The samples in the code are taken from my old DBC space invaders game which you can still download here:
https://zimnox.com/dbcc/index.php?page=games (surprisingly, it still runs ok on win10)
For instance, 16-bit mono requires writing 2-bytes per frame. (each loop in the function writes 1 frame)
16-bit stereo would write 4-bytes per frame; 2 for left channel and 2 for right channel.
Obviously 8-bit audio is then only 1 byte for mono and 2 bytes for stereo.
// Project: sound
// Created: 2025-03-28
SetErrorMode(2)
SetWindowTitle( "sound" )
SetWindowSize(640, 480, 0 )
SetSyncRate(0, 0)
explosion = createsound(1000,2000,3500,5,0.1,0.05,0,0,0,10)
ship_bullet = createsound(1500,100,4000,0.20,1.00,0.00,0,0.00,0,10.00)
alien_fall = createsound(2000,100,2000,-0.09,6.78,0.30,649,0.00,0,0.00)
block = createsound(500,41,4000,0.25,8.60,0.00,0,0.00,0,5.82)
alien_bullet = createsound(1200,30,2000,0.06,3.96,0.00,0,0.00,0,1.06)
title = createsound(1186,3000,4000,0.0,0.00,1.0,3,0.00,0,10.00)
beat1 = createsound(150,100,8000,0.0,0.0,0.0,0,0.0,0,10.00)
beat2 = createsound(120,100,8000,0.0,0.0,0.0,0,0.0,0,10.00)
ufo = createsound(500,2000,5000,0.00,0.00,0.02,2,0.00,0,10.00)
do
if getRawKeyPressed(49) then playSound(explosion)
if getRawKeyPressed(50) then playSound(ship_bullet)
if getRawKeyPressed(51) then playSound(alien_fall)
if getRawKeyPressed(52) then playSound(block)
if getRawKeyPressed(53) then playSound(alien_bullet)
if getRawKeyPressed(54) then playSound(title)
if getRawKeyPressed(55) then playSound(beat1)
if getRawKeyPressed(56) then playSound(beat2)
if getRawKeyPressed(57) then playSound(ufo)
Sync()
loop
/*
* Originally written by Ric in DarkBasic
* Ported to AGK by Phaelax
*
* length (ms)
*/
function createSound(fFrequency as float, length as float, fLoudness as float, fBend as float, fDecay as float, fVibratoSpeed as float, fVibratoDepth as float, fTremeloSpeed as float, fTremeloDepth as float, fAttack as float)
numChannels = 1 // 1=mono, 2=stereo (changing this requires further altering in the loop)
bitsPerSample = 16 // 8 or 16 (changing this requires further altering in the loop)
samplesPerSecond = 44100 // 44.1 kHz
numFrames = ((length / 1000) * samplesPerSecond) * (bitsPerSample / 8) * numChannels
iSamples as integer
fRiseInLoudness as float
fFallInLoudness as float
theta as float
phi as float
m = createMemblock(numFrames*(bitsPerSample/2)+12)
setmemblockInt(m, 0, numChannels) // number of channels
setmemblockInt(m, 2, bitsPerSample) // number of bits per sample
setmemblockInt(m, 4, samplesPerSecond) // samples per second
setmemblockInt(m, 8, numFrames) // number of frames in sound data
memPos = 12
fRiseInLoudness = fLoudness
for x = 1 to numFrames
outInteger = trunc(sin((x/122.5)*(fFrequency+fVibratoDepth*sin(theta)))*(fLoudness-fFallInLoudness-fRiseInLoudness+fTremeloDepth*sin(phi))) * 3.0
if outInteger < -32767 then outInteger = -32767 // is this the valid range?
if outInteger > 32767 then outInteger = 32767 //
inc theta, fVibratoSpeed
inc phi, fTremeloSpeed
dec fFrequency, fBend
if fFallInLoudness < fLoudness then inc fFallInLoudness, fDecay
if fRiseInLoudness > 0 then dec fRiseInLoudness, fAttack
setMemblockShort(m, memPos, outInteger)
inc memPos, 2
next x
snd = createSoundFromMemblock(m)
deleteMemblock(m)
endfunction snd