QB64 Phoenix Edition
Extension of playable audio formats in QB64 (32 bit) - Printable Version

+- QB64 Phoenix Edition (https://staging.qb64phoenix.com)
+-- Forum: QB64 Rising (https://staging.qb64phoenix.com/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://staging.qb64phoenix.com/forumdisplay.php?fid=3)
+---- Forum: Programs (https://staging.qb64phoenix.com/forumdisplay.php?fid=7)
+---- Thread: Extension of playable audio formats in QB64 (32 bit) (/showthread.php?tid=410)



Extension of playable audio formats in QB64 (32 bit) - Petr - 05-14-2022

Hi, I finally found some time and went through the disks. Here is a DLL for playing MIDI files and below it is LibXMP from RhoSigma, which allows you to play MOD, XM, S3M and other audio formats. At the end is also support for IMF music files.

All of these programs must be compiled in a 32-bit IDE because the used dynamic libraries are 32-bit.


MIDI playing:

Code: (Select All)
'program works only in 32bit IDE because DLL library is 32bit. Tested in QB64 v. 1.2 (revision 20180202/85)

DECLARE DYNAMIC LIBRARY "playmidi32"
    FUNCTION PlayMIDI& (filename AS STRING)
END DECLARE

DO WHILE _KEYHIT <> 27
    PRINT "Press spacebar for stop music or Esc for end"
    status = PlayMIDI("Super Mario 64 - Medley.mid")

    DO WHILE i$ <> CHR$(32) OR i$ = CHR$(27)
        i$ = INKEY$
        IF i$ = CHR$(27) THEN SYSTEM
    LOOP
    stat2 = PlayMIDI("")
    PRINT "STOPED. Press other key (no spacebar or Esc) for playing from begin again."
    SLEEP
    i$ = ""
LOOP

For midi playing is need library Playmidi32.dll


MOD/XM/S3M and other playing:

Code: (Select All)
'Author: RhoSigma

'***********************************
'*** Use the QB64 32-bit version ***
'*** the DLL is for 32 bits only ***
'***********************************

'--- declare the required (only) DLL routines, there are much more ---
DECLARE DYNAMIC LIBRARY "./libxmp"
    FUNCTION xmp_create_context%& ()
    SUB xmp_free_context (BYVAL xmp_context%&)
    FUNCTION xmp_load_module& (BYVAL xmp_context%&, path$)
    SUB xmp_release_module (BYVAL xmp_context%&)
    FUNCTION xmp_start_player& (BYVAL xmp_context%&, BYVAL rate&, BYVAL format&)
    FUNCTION xmp_play_buffer& (BYVAL xmp_context%&, BYVAL buffer%&, BYVAL size&, BYVAL loops&)
    SUB xmp_end_player (BYVAL xmp_context%&)
END DECLARE

'--- init player ---
ctx%& = xmp_create_context%&

xErr& = xmp_load_module&(ctx%&, "s.xm" + CHR$(0)) 'load music MOD/XM/S3M file (amiga MOD file format)
xErr& = xmp_start_player&(ctx%&, _SNDRATE, 0)

'--- get storage for sound data ---
DIM buf AS _MEM
bsz& = _SNDRATE * 5 * 2 * 2 'space for 5 seconds 16-bit stereo sound
buf = _MEMNEW(bsz&)

'--- init scroll text ---
txt$ = "The 'External Module Player (XMP)' library (http://xmp.sourceforge.net/) " +_
       "integrated into the QB64 parts system could greatly improve the sound " +_
       "abilities of QB64 by easily adding dozens of well known and even some " +_
       "obscure music tracker formats from various platforms ontop of the already " +_
       "existing sound functions. Hence it could bring back a couple of those " +_
       "formats, which got lost with the transition from SDL to OpenGL. --- --- "

'--- main loop ---
PRINT "Press any key to stop replay, or wait until end ..."
st! = TIMER


DO
    _LIMIT 7
    IF _SNDRAWLEN < .5 THEN GOSUB RefillSoundBuffer
    'do your stuff here (non-blocking, ie. no INPUT etc.)
    LOCATE 10, 10
    PRINT LEFT$(txt$, 60)
    txt$ = MID$(txt$, 2) + LEFT$(txt$, 1)
    '-----
    LOCATE 14, 24
    PRINT USING "Buffered sound: ##.##### seconds"; _SNDRAWLEN
    '-----
    ct! = TIMER
    min$ = RIGHT$("00" + LTRIM$(STR$(INT((ct! - st!) / 60))), 2)
    sec$ = RIGHT$("00" + LTRIM$(STR$(INT((ct! - st!) - (VAL(min$) * 60)))), 2)
    LOCATE 16, 24
    PRINT USING "  Elapsed time:  &:& (mm:ss)"; min$; sec$
LOOP UNTIL xErr& 'WHILE NOT xErr& AND _KEYHIT = 0
_SNDRAWDONE

'--- free storage ---
_MEMFREE buf

'--- free player ---
xmp_end_player ctx%&
xmp_release_module ctx%&
xmp_free_context ctx%&

'--- wait until _SNDRAW is done ---
LOCATE 1, 1: COLOR 28
PRINT "Replay stopped or reached end, emptying sound buffer ...": COLOR 12
DO
    _LIMIT 7
    LOCATE 10, 10
    PRINT LEFT$(txt$, 60)
    txt$ = MID$(txt$, 2) + LEFT$(txt$, 1)
    remain# = _SNDRAWLEN
    '-----
    LOCATE 14, 24
    PRINT USING "Buffered sound: ##.##### seconds"; remain#
    '-----
    ct! = TIMER
    min$ = RIGHT$("00" + LTRIM$(STR$(INT((ct! - st!) / 60))), 2)
    sec$ = RIGHT$("00" + LTRIM$(STR$(INT((ct! - st!) - (VAL(min$) * 60)))), 2)
    LOCATE 16, 24
    PRINT USING "  Elapsed time:  &:& (mm:ss)"; min$; sec$
LOOP UNTIL remain# = 0

'--- guess what ---
END

'--- get next portion of sound and send to _SNDRAW ---
RefillSoundBuffer:
'To avoid sound garbage at the end, we first clear the
'buffer, just in case the final portion doesn't fill the
'entire buffer anymore.
_MEMFILL buf, buf.OFFSET, bsz&, 0 AS _BYTE
'-----
xErr& = xmp_play_buffer&(ctx%&, buf.OFFSET, bsz&, 1)
'PRINT bsz&, xErr&

FOR i& = 0 TO (bsz&) - 2 STEP 4
    leftSample& = _MEMGET(buf, buf.OFFSET + i&, INTEGER)
    rigtSample& = _MEMGET(buf, buf.OFFSET + i& + 2, INTEGER)
    _SNDRAW leftSample& / 32768#, rigtSample& / 32768#
NEXT i&

RETURN
For this is need library LibXMP.dll

Last is IMF sound support:
Code: (Select All)
'must be compiled in 32bit IDE
DECLARE DYNAMIC LIBRARY "./imfLib"
    SUB InitIMFPlayer
    SUB StartIMFMusic (BYVAL pointer AS _OFFSET, BYVAL size AS _OFFSET)
    SUB ShutdownIMFPlayer ()
    SUB SetIMFEndedEvent (hwnd, UWM_MUSICENDED)
    '//           where hwnd is the window to get your user defined
    '//           message UWM_MUSICENDED (i.e. #define UWM_MUSICENDED (WM_APP + 1)).
    '//           There you should restart the song by just calling
    '//           StartIMFMusic with the same pointer again, or load
    '//           another song and start this.
END DECLARE




file$ = "test.imf"
T = 0
ff = FREEFILE
OPEN file$ FOR BINARY AS ff
size = LOF(ff) - T

REDIM NewSound AS _MEM
NewSound = _MEMNEW(size)
s$ = SPACE$(size)
REM SEEK ff, T
GET #ff, , s$
_MEMPUT NewSound, NewSound.OFFSET, s$
s$ = ""
CLOSE #ff

InitIMFPlayer
StartIMFMusic NewSound.OFFSET, NewSound.SIZE
SetIMFEndedEvent _WINDOWHANDLE, 5
DO
    LOCATE 1
    PRINT "Press any key to end. For listening set your audio to stereo and disable some dolby software!"

LOOP UNTIL _KEYHIT = 32

ShutdownIMFPlayer
_MEMFREE NewSound
END


For this is need IMFLib.dll, placed in IMF Play.zip

All need libraries, source codes and music files in attachment.
Zip files contians just BAS files, music files and DLL. None EXE files.


RE: Extension of playable audio formats in QB64 (32 bit) - RhoSigma - 05-14-2022

Hi Petr, nice to see you in this new place again Smile

FYI - Here's the latest and now complete version of the LibXMP wrapper/player, guess you know it already from the old forum. It has a new home here too now: https://staging.qb64phoenix.com/showthread.php?tid=29


RE: Extension of playable audio formats in QB64 (32 bit) - Petr - 05-15-2022

(05-14-2022, 10:36 PM)RhoSigma Wrote: Hi Petr, nice to see you in this new place again Smile

FYI - Here's the latest and now complete version of the LibXMP wrapper/player, guess you know it already from the old forum. It has a new home here too now: https://staging.qb64phoenix.com/showthread.php?tid=29

Hi, nice to see you too Smile. Thanks for the alert and for the new version.


RE: Extension of playable audio formats in QB64 (32 bit) - a740g - 05-25-2022

Hi Petr & RhoSigma,

I am late to the QB64 party. But I am glad that I found it.
And lately I have been bitten by the QB64 bug. What can I say... QB was and always will be my first love.

I am planning to write a fully native QB64 MOD player library. What started as a fun little weekend project turned out to be quite interesting and now, I am thinking of adding multiple formats (S3M, XM etc.). My day job prevents me working on this fulltime. But I hope one day I'll be able to finish what I started. Anyway, the library now plays MOD files only (> 4 channel MODs are supported too). So, give it a spin. There are some subtle bugs that I will fix once I get some time. Most of my QEPE GitHub issue reports are a direct result of me working on this library.
GitHub link: https://github.com/a740g/QB64-MOD-Player

I am also planning to implement a QB64 native MIDI player library using Win32 WinMM MIDI streaming API or FluidSynth (not able to decide and I am at war with myself Smile.

From what I understand, QB64 was able to play these natively with the SDL version and ever since we left SDL behind, support for these formats was dropped.
If there are any plans to reintroduce support for MODs and MIDI format in QB64 in the future, then please do let me know and I'll not burn my midnight oil. Smile