09-07-2024, 05:55 PM
Quote:Instead of playing with _SNDRAW like this, Is it possible to feed the data to a _SNDNEW memory instead so I could have the song with a handle for using it with _SNDPLAY controls?It is! That's exactly the reason why we added _SNDNEW. Mixing two sounds into the buffer is just a matter of summing the samples of the sounds (assuming they are signed and of the same format).
Here is a crude example of _SNDNEW. GenerateSineWave() simply inserts the samples into the buffer created by _SNDNEW using ProcSoundInsertSampleFrame(). It also mixes a tiny bit of noise into the sine waveform.
Code: (Select All)
OPTION _EXPLICIT
'-------------------------------------------------------------------------------
TYPE ProcSoundType
handle AS LONG
buffer AS _MEM
cursor AS _UNSIGNED _OFFSET
END TYPE
'-------------------------------------------------------------------------------
' Since the sound buffer size cannot be changed after it is created, we'll need to know the exact frames we need in advance
CONST FRAMES = 65536
DIM ps(1 TO 7) AS ProcSoundType, i AS LONG
FOR i = 1 TO 7
ProcSoundCreate ps(i), FRAMES
NEXT i
GenerateSineWave ps(1), 262!
GenerateSineWave ps(2), 294!
GenerateSineWave ps(3), 330!
GenerateSineWave ps(4), 349!
GenerateSineWave ps(5), 392!
GenerateSineWave ps(6), 440!
GenerateSineWave ps(7), 494!
PRINT "Press 1 - 7"
DIM k AS LONG
DO
k = _KEYHIT
SELECT CASE k
CASE 49
_SNDPLAYCOPY ProcSoundGetHandle(ps(1))
CASE 50
_SNDPLAYCOPY ProcSoundGetHandle(ps(2))
CASE 51
_SNDPLAYCOPY ProcSoundGetHandle(ps(3))
CASE 52
_SNDPLAYCOPY ProcSoundGetHandle(ps(4))
CASE 53
_SNDPLAYCOPY ProcSoundGetHandle(ps(5))
CASE 54
_SNDPLAYCOPY ProcSoundGetHandle(ps(6))
CASE 55
_SNDPLAYCOPY ProcSoundGetHandle(ps(7))
END SELECT
_LIMIT 60
LOOP UNTIL k = 27
FOR i = 1 TO 7
ProcSoundDelete ps(i)
NEXT i
END
SUB GenerateSineWave (ps AS ProcSoundType, frequency AS SINGLE)
DIM angleDelta AS SINGLE: angleDelta = _PI(2!) * frequency / _SNDRATE
DIM angle AS SINGLE
ProcSoundSeek ps, 0
DO UNTIL ProcSoundIsFull(ps)
ProcSoundInsertSampleFrame ps, SIN(angle) + ((RND - RND) * 0.05!)
angle = angle + angleDelta
LOOP
END SUB
'-------------------------------------------------------------------------------
SUB ProcSoundDelete (ps AS ProcSoundType)
IF ps.handle THEN
_SNDCLOSE ps.handle
ps.handle = 0
ps.cursor = 0
END IF
END SUB
SUB ProcSoundCreate (ps AS ProcSoundType, sampleFrames AS _UNSIGNED LONG)
ProcSoundDelete ps
ps.handle = _SNDNEW(sampleFrames, 1, 32) ' hardcoded to create mono 32-bit FP buffer
ps.cursor = 0
ps.buffer = _MEMSOUND(ps.handle)
END SUB
FUNCTION ProcSoundGetHandle& (ps AS ProcSoundType)
ProcSoundGetHandle = ps.handle
END FUNCTION
FUNCTION ProcSoundIsFull%% (ps AS ProcSoundType)
ProcSoundIsFull = ps.cursor >= ps.buffer.SIZE
END FUNCTION
FUNCTION ProcSoundGetFrames~%& (ps AS ProcSoundType)
ProcSoundGetFrames = ps.buffer.SIZE \ ps.buffer.ELEMENTSIZE
END FUNCTION
SUB ProcSoundSeek (ps AS ProcSoundType, frame AS _UNSIGNED _OFFSET)
ps.cursor = frame * ps.buffer.ELEMENTSIZE
END SUB
FUNCTION ProcSoundGetPosition~%& (ps AS ProcSoundType)
ProcSoundGetPosition = ps.cursor \ ps.buffer.ELEMENTSIZE
END FUNCTION
SUB ProcSoundInsertSampleFrame (ps AS ProcSoundType, sample AS SINGLE)
_MEMPUT ps.buffer, ps.buffer.OFFSET + ps.cursor, sample AS SINGLE
ps.cursor = ps.cursor + ps.buffer.ELEMENTSIZE ' ELEMENTSIZE here is 4 since sizeof(single) = 4
END SUB
'-------------------------------------------------------------------------------