Posts: 176
Threads: 36
Joined: May 2022
Reputation:
16
02-19-2023, 04:25 PM
(This post was last modified: 02-19-2023, 08:08 PM by Petr.)
Hello. I found a MemSound bug (see attached test program) that makes Phoenix 3.5.0 MemSound unable to be used properly and causing my programs to crash, unlike QB64 2.02. The attached program exactly shows the occurrence of the error.
Code: (Select All) $NoPrefix
s = SndOpen("0.mp3")
Dim As MEM l, r
l = MemSound(s, 1)
r = MemSound(s, 2)
Print "MemSound bug"
Print
Print "Value returned for left audio channel:"; l.SIZE
Print "Value returned for right audio channel:"; r.SIZE
chan& = SndLen(s) * 2 * SndRate
If l.SIZE = r.SIZE And r.SIZE = chan& Then Print "All ok!": End
Print "the size of the ONE audio track channel, that is expected:"; chan&
Print "Value returned with SndOpen:"; s;
If s > 0 Then Print "[correct audio file]" Else Print "[unsupported audio file]"
Print
Print "press key for try play this file"
Sleep
SndPlay s
If SndPlaying(s) Then Print "Both channels playing, bug is not in SndOpen." Else Print "Bug is in SndOpen"
'wroted in Phoenix IDE 3.5.0
Posts: 131
Threads: 7
Joined: May 2022
Reputation:
20
02-19-2023, 04:53 PM
(This post was last modified: 02-19-2023, 05:14 PM by a740g.)
(02-19-2023, 04:25 PM)Petr Wrote: Hello. I found a MemSound bug (see attached test program) that makes Phoenix 3.5.0 MemSound unable to be used properly and causing my programs to crash, unlike QB64 2.02. The attached program exactly shows the occurrence of the error.
Code: (Select All) $NoPrefix
s = SndOpen("0.mp3")
Dim As MEM l, r
l = MemSound(s, 1)
r = MemSound(s, 2)
Print "MemSound bug"
Print
Print "Value returned for left audio channel:"; l.SIZE
Print "Value returned for right audio channel:"; r.SIZE
chan& = SndLen(s) * 2 * SndRate
If l.SIZE = r.SIZE And r.SIZE = chan& Then Print "All ok!": End
Print "the size of the ONE audio track channel, that is expected:"; chan&
Print "Value returned with SndOpen:"; s;
If s > 0 Then Print "[correct audio file]" Else Print "[unsupported audio file]"
Print
Print "press key for try play this file"
Sleep
SndPlay s
If SndPlaying(s) Then Print "Both channels playing, bug is not in SndOpen." Else Print "Bug is in SndOpen"
'wroted in Phoenix IDE 3.5.0
This is working for me @Petr.
However, there has been a slight change in the behavior of _MemSound since we moved to the miniaudio backend. The wiki link has all the details and new examples. But to put this briefly, line "r.SIZE" will always return 0 since miniaudio internally uses interleaved audio for multi-channel sounds. Hence, the "All ok!" text will never print.
Posts: 176
Threads: 36
Joined: May 2022
Reputation:
16
Ok then write me how to get the audio data for the right channel. Also try to play the acquired music data for the left channel. It caused the program to crash. Don't tell me you've made changes to MemSound that would cause incompatibility. I couldn't find any such change on Wiki.
then try this:
Code: (Select All) $NoPrefix
s = SndOpen("0.mp3")
Dim As MEM l, r
Dim done As Long, m As Integer
l = MemSound(s, 1)
Do Until done = l.SIZE
MemGet l, l.OFFSET + done, m
done = done + 2
SndRaw m / 32768
Loop
It's entirely possible that I've missed something, so I'll ask you for a valid link to a real working use of memsound. Thank you.
In the attached screenshot, look at the numeric values returned. Even if you got it right, I absolutely do not understand the difference between the correctly calculated expected data size and what it returns for the left channel. And try playing the audio for the left channel.
Posts: 176
Threads: 36
Joined: May 2022
Reputation:
16
Good. I kicked it now. Phoenix seems to have a much better level of oversampling. So I want to confirm only one thing, but it is essential. Are the samples in the MEM array organized in order Left, Right, Left, Right...? So MemSound with a parameter of 1 will return the entire sound array for both channels?
I also found out, and I'm thrilled and thank you very much, that SndRaw is now fixed in Phoenix and actually plays in stereo! Here is a test program that opened my eyes.
Code: (Select All) $NoPrefix
Dim s As Long
s = SndOpen("0.mp3")
Dim As MEM l, r
Dim done As Long
Dim m2 As Single '4 byte long, so 32bit sound!
Dim m As Single
l = MemSound(s, 1)
If l.ELEMENTSIZE <> 8 Then Print "This program play just 32 bit songs.": End
Do Until done = l.SIZE - 8
MemGet l, l.OFFSET + done, m
MemGet l, l.OFFSET + done + 4, m2
done = done + 8
SndRaw m, m2
Loop
'wroted in Phoenix 3.5.0
I will change the name of the thread.
Posts: 131
Threads: 7
Joined: May 2022
Reputation:
20
02-19-2023, 06:51 PM
(This post was last modified: 02-20-2023, 12:26 AM by a740g.)
Code: (Select All) OPTION _EXPLICIT
PRINT "Loading...";
DIM Song AS LONG
Song = _SNDOPEN("STARDUST.MOD") ' Replace file name with your sound file
IF Song < 1 THEN
PRINT "Failed to load sound!"
END
END IF
PRINT "Done!"
DIM Channels AS _UNSIGNED _BYTE
Channels = SndChannels(Song)
IF Channels > 0 THEN
PRINT "The sound has"; Channels; "channels."
ELSE
PRINT "An error occurred."
END
END IF
DIM AS LONG i, rawSnd
rawSnd = _SNDOPENRAW
IF rawSnd < 1 THEN
PRINT "Failed to open sound pipe!"
END
END IF
FOR i = 0 TO Channels - 1
PRINT "Queueing channel"; i; "...";
PlaySoundChannel Song, i, rawSnd
PRINT "Done!"
PRINT "Waiting for playback to finish...";
DO WHILE _SNDRAWLEN(rawSnd) > 0 'Finish any left over queued sound!
SLEEP 1
LOOP
PRINT "Done!"
NEXT
_SNDCLOSE rawSnd
_SNDCLOSE Song 'closing the sound releases the mem blocks
END
' Here chan starts from 0
' So, chan 0 is the first channel, 1 the next one and so on
' rs is the raw sound handle
SUB PlaySoundChannel (handle AS LONG, chan AS _UNSIGNED _BYTE, rs AS LONG)
DIM AS _UNSIGNED _INTEGER64 i, sz, es, ofs
DIM SampleData AS _MEM
DIM channels AS _UNSIGNED _BYTE
DIM samp AS SINGLE
channels = SndChannels(handle)
SampleData = _MEMSOUND(handle, 0)
IF SampleData.SIZE = 0 THEN
EXIT SUB
END IF
$IF 64BIT THEN
sz = _CV(_UNSIGNED _INTEGER64, _MK$(_OFFSET, SampleData.SIZE)) ' sz is the total size of the sound in bytes
es = _CV(_UNSIGNED _INTEGER64, _MK$(_OFFSET, SampleData.ELEMENTSIZE))
$ELSE
sz = _CV(_Unsigned long, _MK$(_Offset, SampleData.SIZE)) ' sz is the total size of the sound in bytes
es = _CV(_Unsigned long, _MK$(_Offset, SampleData.ELEMENTSIZE))
$END IF
ofs = es \ channels
FOR i = 0 TO sz - es STEP es
IF SampleData.TYPE = 260 THEN ' 32-bit floating point
samp = _MEMGET(SampleData, SampleData.OFFSET + i + (chan * ofs), SINGLE)
ELSEIF SampleData.TYPE = 132 THEN ' 32-bit integer
samp = _MEMGET(SampleData, SampleData.OFFSET + i + (chan * ofs), LONG) / 2147483648
ELSEIF SampleData.TYPE = 130 THEN ' 16-bit integer
samp = _MEMGET(SampleData, SampleData.OFFSET + i + (chan * ofs), INTEGER) / 32768
ELSEIF SampleData.TYPE = 1153 THEN ' 8-bit unsigned integer
samp = (_MEMGET(SampleData, SampleData.OFFSET + i + (chan * ofs), _UNSIGNED _BYTE) - 128) / 128
END IF
IF chan MOD 2 = 0 THEN
_SNDRAW samp, 0, rs
ELSE
_SNDRAW 0, samp, rs
END IF
NEXT
END SUB
' This function returns the number of sound channels for a valid sound "handle"
' Note that we are assuming that the sound can have at most 2 channels
' In reality miniaudio can handle sounds with more than 2 channels
' 2 = stereo, 1 = mono, 0 = error
FUNCTION SndChannels~%% (handle AS LONG)
DIM SampleData AS _MEM
' Check if the sound is valid
SampleData = _MEMSOUND(handle, 0)
IF SampleData.SIZE = 0 THEN
EXIT FUNCTION
END IF
' Check the data type and then decide if the sound is stereo or mono
IF SampleData.TYPE = 260 THEN ' 32-bit floating point
IF SampleData.ELEMENTSIZE = 4 THEN
SndChannels = 1
ELSEIF SampleData.ELEMENTSIZE = 8 THEN
SndChannels = 2
END IF
ELSEIF SampleData.TYPE = 132 THEN ' 32-bit integer
IF SampleData.ELEMENTSIZE = 4 THEN
SndChannels = 1
ELSEIF SampleData.ELEMENTSIZE = 8 THEN
SndChannels = 2
END IF
ELSEIF SampleData.TYPE = 130 THEN ' 16-bit integer
IF SampleData.ELEMENTSIZE = 2 THEN
SndChannels = 1
ELSEIF SampleData.ELEMENTSIZE = 4 THEN
SndChannels = 2
END IF
ELSEIF SampleData.TYPE = 1153 THEN ' 8-bit unsigned integer
IF SampleData.ELEMENTSIZE = 1 THEN
SndChannels = 1
ELSEIF SampleData.ELEMENTSIZE = 2 THEN
SndChannels = 2
END IF
END IF
END FUNCTION
Here you go @Petr. Hope this will help.
Posts: 176
Threads: 36
Joined: May 2022
Reputation:
16
I tried it and it ended up with an error.
Posts: 131
Threads: 7
Joined: May 2022
Reputation:
20
02-19-2023, 07:08 PM
(This post was last modified: 02-19-2023, 07:13 PM by a740g.)
Quote:Good. I kicked it now. Phoenix seems to have a much better level of oversampling. So I want to confirm only one thing, but it is essential. Are the samples in the MEM array organized in order Left, Right, Left, Right...? So MemSound with a parameter of 1 will return the entire sound array for both channels?
Yes. They are interleaved. LRLR... for stereo sounds.
Quote:I also found out, and I'm thrilled and thank you very much, that SndRaw is now fixed in Phoenix and actually plays in stereo! Here is a test program that opened my eyes.
Yes. That bug was really annoying. But it is fixed now. I discovered it while writing my MOD re-player using _SNDRAW and then I discovered your posts about it in the old forums.
You've been away from the scene for a while. Nice to see you are back.
Posts: 131
Threads: 7
Joined: May 2022
Reputation:
20
02-19-2023, 07:12 PM
(This post was last modified: 02-19-2023, 07:17 PM by a740g.)
You are using the 32-bit version of QB64-PE. Sorry, I did not pay much attention to what it would do when compiled with the 32-bit version of QB64-PE.
The code should run correctly if you compile with the 64-bit version of QB64-PE though.
Update: I fixed my code above for 32-bit QB64-PE. It should work correctly now.
Posts: 176
Threads: 36
Joined: May 2022
Reputation:
16
It works now. I will study it. Thank you.
Posts: 131
Threads: 7
Joined: May 2022
Reputation:
20
02-20-2023, 12:22 AM
(This post was last modified: 02-20-2023, 12:22 AM by a740g.)
(02-19-2023, 07:06 PM)Petr Wrote: I tried it and it ended up with an error.
(02-19-2023, 07:43 PM)Petr Wrote: It works now. I will study it. Thank you.
@Petr there was a bug. More like a typo inside the PlaySoundChannel FOR loop that I corrected. The updated code is in the same post.
|