02-24-2023, 07:22 PM
Hello. I wrote a function that you just push a music file, set the echo length and volume (in the range from 0 to 1) and the program will generate a new sound straight away. I used _SndNew for this.
Code: (Select All)
Snd& = _SndOpen("SongEight.mod")
For Echo = 1 To 3
Print "Creating Echo level: "; Echo
_Delay .1
news& = MakeEcho&(Snd&, Echo / 10, .85)
_Delay .1
_SndClose Snd&
Snd& = _SndCopy(news&)
Next
_SndPlay news&
Print "Program create new sound handle ("; news&; " )"
Print " This new handle is not full compatible:"
Print "_SndLen return: "; _SndLen(news&)
Sleep 2
Print "_SndGetPos return: "; _SndGetPos(news&)
Sleep 4
Print "Trying use _SndSetPos to begin this track..."
_SndSetPos news&, 0
Function MakeEcho& (InputSound As Long, SoundDelay As Single, EchoVolume As Single)
If SoundDelay < 0 Then Print "Error: EchoDelay must be higher than zero.": Exit Function
'EchoVolume in range 0 to 1!
Dim SourceSound As _MEM
SourceSound = _MemSound(InputSound&, 0)
Select Case GetBites(SourceSound)
Case 1, 2: Multiply = 4
Case 3: Multiply = 2
Case 4: Multiply = 1
End Select
Select Case SourceSound.TYPE
Case 260 ' 32-bit floating point
If SourceSound.ELEMENTSIZE = 4 Then
SndChannels = 1
ElseIf SourceSound.ELEMENTSIZE = 8 Then
SndChannels = 2
End If
Case 132 ' 32-bit integer
If SourceSound.ELEMENTSIZE = 4 Then
SndChannels = 1
ElseIf SourceSound.ELEMENTSIZE = 8 Then
SndChannels = 2
End If
Case 130: ' 16-bit integer
If SourceSound.ELEMENTSIZE = 2 Then
SndChannels = 1
ElseIf SourceSound.ELEMENTSIZE = 4 Then
SndChannels = 2
End If
Case 1153: ' 8-bit unsigned integer
If SourceSound.ELEMENTSIZE = 1 Then
SndChannels = 1
ElseIf SourceSound.ELEMENTSIZE = 2 Then
SndChannels = 2
End If
End Select
Dim As Long i, BB
Dim As Double sampL, sampL2, sampR, sampR2
BB& = Multiply * _SndRate * SoundDelay * SndChannels
Dim TrackTime As _Float
TrackTime = ConvertOffset(SourceSound.SIZE) \ _SndRate \ ConvertOffset(SourceSound.ELEMENTSIZE) + _Ceil(SoundDelay)
Print "New track time: "; TrackTime; "[sec]"
MakeEch& = _SndNew((TrackTime + SoundDelay) * _SndRate, SndChannels, Multiply * 8)
' Print MakeEch&, SndChannels, Multiply, _SndLen(InputSound)
Dim ME As _MEM
ME = _MemSound(MakeEch&, 0)
Do Until i >= SourceSound.SIZE - SourceSound.ELEMENTSIZE
Select Case SndChannels
Case 1
Select Case SourceSound.TYPE
Case 260: sampL = _MemGet(SourceSound, SourceSound.OFFSET + i, Single) ' 32-bit floating point
Case 132: sampL = _MemGet(SourceSound, SourceSound.OFFSET + i, Long) / 2147483648 ' 32-bit integer
Case 130: sampL = _MemGet(SourceSound, SourceSound.OFFSET + i, Integer) / 32768 ' 16-bit integer
Case 1153: sampL = (_MemGet(SourceSound, SourceSound.OFFSET + i, _Unsigned _Byte) - 128) / 128 ' 8-bit unsigned integer
End Select
Case 2
Select Case SourceSound.TYPE
Case 260: sampL = _MemGet(SourceSound, SourceSound.OFFSET + i, Single): sampR = _MemGet(SourceSound, SourceSound.OFFSET + i + SourceSound.ELEMENTSIZE \ 2, Single) ' 32-bit floating point
Case 132: sampL = _MemGet(SourceSound, SourceSound.OFFSET + i, Long) / 2147483648: sampR = _MemGet(SourceSound, SourceSound.OFFSET + i + SourceSound.ELEMENTSIZE \ 2, Long) / 2147483648 ' 32-bit integer
Case 130: sampL = _MemGet(SourceSound, SourceSound.OFFSET + i, Integer) / 32768: sampR = _MemGet(SourceSound, SourceSound.OFFSET + i + SourceSound.ELEMENTSIZE \ 2, Integer) / 32768 ' 16-bit integer
Case 1153: sampL = (_MemGet(SourceSound, SourceSound.OFFSET + i, _Unsigned _Byte) - 128) / 128: sampR = (_MemGet(SourceSound, SourceSound.OFFSET + i + SourceSound.ELEMENTSIZE \ 2, _Unsigned _Byte) - 128) / 128 ' 8-bit unsigned integer
End Select
End Select
If i& > BB& Then
Select Case SndChannels
Case 1
Select Case SourceSound.TYPE
Case 260: sampL2 = _MemGet(SourceSound, SourceSound.OFFSET + i - BB&, Single) ' 32-bit floating point
Case 132: sampL2 = _MemGet(SourceSound, SourceSound.OFFSET + i - BB&, Long) / 2147483648 ' 32-bit integer
Case 130: sampL2 = _MemGet(SourceSound, SourceSound.OFFSET + i - BB&, Integer) / 32768 ' 16-bit integer
Case 1153: sampL2 = (_MemGet(SourceSound, SourceSound.OFFSET + i - BB&, _Unsigned _Byte) - 128) / 128 ' 8-bit unsigned integer
End Select
Case 2
Select Case SourceSound.TYPE
Case 260: sampL2 = _MemGet(SourceSound, SourceSound.OFFSET + i - BB&, Single): sampR2 = _MemGet(SourceSound, SourceSound.OFFSET + i + SourceSound.ELEMENTSIZE \ 2 - BB&, Single) ' 32-bit floating point
Case 132: sampL2 = _MemGet(SourceSound, SourceSound.OFFSET + i - BB&, Long) / 2147483648: sampR2 = _MemGet(SourceSound, SourceSound.OFFSET + i + SourceSound.ELEMENTSIZE \ 2 - BB&, Long) / 2147483648 ' 32-bit integer
Case 130: sampL2 = _MemGet(SourceSound, SourceSound.OFFSET + i - BB&, Integer) / 32768: sampR2 = _MemGet(SourceSound, SourceSound.OFFSET + i + SourceSound.ELEMENTSIZE \ 2 - BB&, Integer) / 32768 ' 16-bit integer
Case 1153: sampL2 = (_MemGet(SourceSound, SourceSound.OFFSET + i - BB&, _Unsigned _Byte) - 128) / 128: sampR2 = (_MemGet(SourceSound, SourceSound.OFFSET + i + SourceSound.ELEMENTSIZE \ 2 - BB&, _Unsigned _Byte) - 128) / 128 ' 8-bit unsigned integer
End Select
End Select
End If
sampL2 = sampL2 * EchoVolume
sampR2 = sampR2 * EchoVolume
LeftOut = (sampL * (1 - EchoVolume)) + sampL2
RightOut = (sampR * (1 - EchoVolume)) + sampR2
Select Case SndChannels
Case 1
Select Case ME.TYPE
Case 260: _MemPut ME, ME.OFFSET + i, LeftOut As SINGLE ' 32-bit floating point
Case 132: _MemPut ME, ME.OFFSET + i, LeftOut * 2147483648 As LONG ' 32-bit integer
Case 130: _MemPut ME, ME.OFFSET + i, LeftOut * 32768 As INTEGER ' 16-bit integer
Case 1153: _MemPut ME, ME.OFFSET + i, 128 - (LeftOut * 128) As _UNSIGNED _BYTE ' 8-bit unsigned integer
End Select
Case 2
Select Case ME.TYPE
Case 260: _MemPut ME, ME.OFFSET + i, LeftOut As SINGLE: _MemPut ME, ME.OFFSET + i + ME.ELEMENTSIZE \ 2, RightOut As SINGLE ' 32-bit floating point
Case 132: _MemPut ME, ME.OFFSET + i, LeftOut * 2147483648 As LONG: _MemPut ME, ME.OFFSET + i + ME.ELEMENTSIZE \ 2, RightOut * 2147483648 As LONG ' 32-bit integer
Case 130: _MemPut ME, ME.OFFSET + i, LeftOut * 32768 As INTEGER: _MemPut ME, ME.OFFSET + i + ME.ELEMENTSIZE \ 2, RightOut * 32768 As INTEGER ' 16-bit integer
Case 1153: _MemPut ME, ME.OFFSET + i, 128 - (LeftOut * 128) As _UNSIGNED _BYTE: _MemPut ME, ME.OFFSET + i + ME.ELEMENTSIZE \ 2, 128 - (128 * RightOut) As _UNSIGNED _BYTE ' 8-bit unsigned integer
End Select
End Select
i = i + Multiply * 2
Loop
MakeEcho& = _SndCopy(MakeEch&)
_SndClose MakeEch&
If ME.SIZE Then _MemFree ME
If SourceSound.SIZE Then _MemFree SourceSound
End Function
Function GetBites (handle As _MEM)
Select Case handle.TYPE
Case 260: GetBites = 1 ' 32-bit floating point SINGLE
Case 132: GetBites = 2 ' 32-bit integer LONG
Case 130: GetBites = 3 ' 16-bit integer INTEGER
Case 1153: GetBites = 4 ' 8-bit unsigned integer
End Select
End Function
Sub PlaySound (handle As Long, rs As Long)
Dim SampleData As _MEM
Dim channels As _Unsigned _Byte
Dim sampL As Single, sampR As Single
Dim i As _Offset
channels = SndChannels(handle)
SampleData = _MemSound(handle, 0)
If SampleData.SIZE = 0 Then
Print "PlaySound: Sample data array is empty."
Exit Sub
End If
Do Until i = SampleData.SIZE - SampleData.ELEMENTSIZE
Select Case channels
Case 1
Select Case SampleData.TYPE
Case 260: sampL = _MemGet(SampleData, SampleData.OFFSET + i, Single) ' 32-bit floating point
Case 132: sampL = _MemGet(SampleData, SampleData.OFFSET + i, Long) / 2147483648 ' 32-bit integer
Case 130: sampL = _MemGet(SampleData, SampleData.OFFSET + i, Integer) / 32768 ' 16-bit integer
Case 1153: sampL = (_MemGet(SampleData, SampleData.OFFSET + i, _Unsigned _Byte) - 128) / 128 ' 8-bit unsigned integer
End Select
Case 2
Select Case SampleData.TYPE
Case 260: sampL = _MemGet(SampleData, SampleData.OFFSET + i, Single): sampR = _MemGet(SampleData, SampleData.OFFSET + i + SampleData.ELEMENTSIZE \ 2, Single) ' 32-bit floating point
Case 132: sampL = _MemGet(SampleData, SampleData.OFFSET + i, Long) / 2147483648: sampR = _MemGet(SampleData, SampleData.OFFSET + i + SampleData.ELEMENTSIZE \ 2, Long) / 2147483648 ' 32-bit integer
Case 130: sampL = _MemGet(SampleData, SampleData.OFFSET + i, Integer) / 32768: sampR = _MemGet(SampleData, SampleData.OFFSET + i + SampleData.ELEMENTSIZE \ 2, Integer) / 32768 ' 16-bit integer
Case 1153: sampL = (_MemGet(SampleData, SampleData.OFFSET + i, _Unsigned _Byte) - 128) / 128: sampR = (_MemGet(SampleData, SampleData.OFFSET + i + SampleData.ELEMENTSIZE \ 2, _Unsigned _Byte) - 128) / 128 ' 8-bit unsigned integer
End Select
End Select
If channels Mod 2 = 0 Then
_SndRaw sampL, sampR, rs 'stereo
Else
_SndRaw sampL, sampL, rs 'mono = left channel in both speakers
End If
i = i + SampleData.ELEMENTSIZE
Loop
_MemFree SampleData
End Sub
Function ConvertOffset&& (value As _Offset)
$Checking:Off
Dim m As _MEM 'Define a memblock
m = _Mem(value) 'Point it to use value
$If 64BIT Then
'On 64 bit OSes, an OFFSET is 8 bytes in size. We can put it directly into an Integer64
_MEMGET m, m.OFFSET, ConvertOffset&& 'Get the contents of the memblock and put the values there directly into ConvertOffset&&
$Else
'However, on 32 bit OSes, an OFFSET is only 4 bytes. We need to put it into a LONG variable first
_MemGet m, m.OFFSET, temp& 'Like this
ConvertOffset&& = temp& 'And then assign that long value to ConvertOffset&&
$End If
_MemFree m 'Free the memblock
$Checking:On
End Function