I updated my old Snowman screen saver to test the experimental (and $UNSTABLE) MIDI playback feature of QB64PE. This is a simple looping animation that plays 17 different Christmas songs continuously. It's just something nice to have on the screen whenever you need a snowy atmosphere.
It sure is nice to have MIDI playback in QB64PE, the only negative is that it takes a rather long time to open a MIDI file. Loading these 17 MIDI files takes a couple minutes on my PC. I found that MIDI feature is most stable when opening MIDI files at the beginning and leaving them open throughout the program. Opening/Closing them over and over in the program caused hangups, so I ended up just loading them all at startup and doing a _SNDSTOP when changing to a start new song.
I'll post the code here for the curious, but you will need to download the archive to run it. You will need QB64PE v3.2 or higher to use the $MIDISOUNDFONT metacommand. I haven't tested this in Linux yet, but I guess it will work if the Linux version also supports the new MIDI metacommand.
- Dav
snowman-v103.zip (Size: 710.24 KB / Downloads: 88)
It sure is nice to have MIDI playback in QB64PE, the only negative is that it takes a rather long time to open a MIDI file. Loading these 17 MIDI files takes a couple minutes on my PC. I found that MIDI feature is most stable when opening MIDI files at the beginning and leaving them open throughout the program. Opening/Closing them over and over in the program caused hangups, so I ended up just loading them all at startup and doing a _SNDSTOP when changing to a start new song.
I'll post the code here for the curious, but you will need to download the archive to run it. You will need QB64PE v3.2 or higher to use the $MIDISOUNDFONT metacommand. I haven't tested this in Linux yet, but I guess it will work if the Linux version also supports the new MIDI metacommand.
- Dav
snowman-v103.zip (Size: 710.24 KB / Downloads: 88)
Code: (Select All)
'==========
'SNOWMAN.BAS v1.03
'===========
'Play Snowman animation while playing 17 Christmas songs.
'Coded by Dav for QB64PE, DEC/2022
'ALL MEDIA SOURCES FOUND IN PUBLIC DOMAIN
'
'=======================================================================
'NOTE: THIS PROGRAM REQUIRES QB64-PE v3.2 OR HIGHER TO RUN & USE MIDI
'=======================================================================
'
'CONTROLS:
' WHILE PLAYING, USE LEFT & RIGHT ARROWS TO SKIP SONGS.
' ANY OTHER KEY QUITS THE SAVER
'
'The screen saver will start playing a random song. You an skip up/down
'to different songs using the left/right arrow keys. Pressing any other
'key will quit the program.
'
'NOTE: It takes a minute or two to load all the MIDI files on startup.
'Please be patient while they load, and enjoythe Christmas screen saver.
'
'=======================================================================
$UNSTABLE:MIDI
PRINT "=============================="
PRINT "SNOWMAN SCREENSAVER FOR QB64PE"
PRINT "(please wait while files load)"
PRINT "=============================="
PRINT
PRINT "Init MIDI soundfont...";
$MIDISOUNDFONT:DEFAULT
PRINT "OK!"
'=== Check the animation file
PRINT "Checking animation file...";
file$ = "snowman.dat"
OPEN file$ FOR BINARY AS #1
IF LOF(1) = 0 THEN
PRINT "SNOWMAN.DAT NOT FOUND!"
CLOSE 1: KILL file$
END
END IF
IF LOF(1) <> 800528 THEN
PRINT "INVALID SNOWMAN.DAT!"
CLOSE 1
END
END IF
PRINT "OK!"
'=== Build the MIDI song list..
trackmax = 17 '17 midi files
DIM song$(1 TO trackmax), songhand&(1 TO trackmax)
'name each one
song$(1) = "frosty.mid"
song$(2) = "hark.mid"
song$(3) = "away.mid"
song$(4) = "angels.mid"
song$(5) = "carol.mid"
song$(6) = "joy.mid"
song$(7) = "deck.mid"
song$(8) = "wethree.mid"
song$(9) = "holynite.mid"
song$(10) = "godrest.mid"
song$(11) = "itcame.mid"
song$(12) = "ohcome.mid"
song$(13) = "noel.mid"
song$(14) = "silent.mid"
song$(15) = "town.mid"
song$(16) = "jingle.mid"
song$(17) = "wewish.mid"
FOR s = 1 TO trackmax
PRINT "Loading MIDI file"; s; "of"; trackmax; ": "; song$(s); "...";
songhand&(s) = _SNDOPEN(song$(s), "stream")
IF songhand&(s) = 0 THEN
PRINT "Error opening file: "; song$(s)
END
END IF
PRINT "OK!"
NEXT
'=== start playing a random track
RANDOMIZE TIMER
track = INT(RND * trackmax) + 1
_SNDPLAY songhand&(track)
SCREEN 13: _FULLSCREEN _SQUAREPIXELS , _SMOOTH
DO
SEEK 1, 129
FOR f% = 1 TO 15
FF& = SEEK(1): FRM$ = INPUT$(16, 1)
FrameSize& = CVL(MID$(FRM$, 1, 4))
chunks% = CVI(MID$(FRM$, 7, 2))
d$ = INKEY$
IF d$ <> "" THEN
SELECT CASE d$
CASE CHR$(0) + CHR$(77)
_SNDSTOP songhand&(track)
track = track + 1
IF track > trackmax THEN track = 1
_SNDPLAY songhand&(track)
CASE CHR$(0) + CHR$(75)
_SNDSTOP songhand&(track)
track = track - 1
IF track < 1 THEN track = trackmax
_SNDPLAY songhand&(track)
CASE ELSE: EXIT DO
END SELECT
END IF
FOR C% = 1 TO chunks%
Fpos& = SEEK(1)
CD$ = INPUT$(6, 1)
ChunkSize& = CVL(MID$(CD$, 1, 4))
ChunkType% = CVI(MID$(CD$, 5, 2))
Fpos& = Fpos& + ChunkSize&
SELECT CASE ChunkType%
CASE 11
Clr% = 0
paks% = ASC(INPUT$(2, 1))
FOR d% = 1 TO paks%
skip% = ASC(INPUT$(1, 1))
change% = ASC(INPUT$(1, 1))
IF change% = 0 THEN change% = 256
Clr% = Clr% + skip%
FOR s% = 1 TO change%
OUT &H3C8, Clr%
OUT &H3C9, ASC(INPUT$(1, 1))
OUT &H3C9, ASC(INPUT$(1, 1))
OUT &H3C9, ASC(INPUT$(1, 1))
Clr% = Clr% + 1
NEXT
NEXT
CASE 12
skip% = CVI(INPUT$(2, 1))
change% = CVI(INPUT$(2, 1))
FOR y% = skip% TO change% + (skip% - 1)
ppos& = SEEK(1)
C$ = INPUT$(500, 1): m% = 1
paks% = ASC(MID$(C$, m%, 1)): m% = m% + 1: x% = 0
FOR d% = 1 TO paks%
s% = ASC(MID$(C$, m%, 1))
p% = ASC(MID$(C$, m% + 1, 1))
m% = m% + 2: x% = x% + s%
IF p% > 127 THEN
p% = (256 - p%)
LINE (x%, y%)-STEP(p% - 1, 0), ASC(MID$(C$, m%, 1))
x% = x% + p%: m% = m% + 1
ELSE
Row$ = MID$(C$, m%, p%)
m% = m% + p%
FOR g% = 0 TO p% - 1
PSET (x% + g%, y%), ASC(MID$(Row$, g% + 1, 1))
NEXT
x% = x% + p%
END IF
NEXT
SEEK #1, ppos& + m% - 1: C$ = ""
NEXT
CASE 16
x% = 0
FOR y% = 0 TO 199
Row$ = INPUT$(320, 1): p% = 320
FOR g% = 0 TO p% - 1
PSET (x% + g%, y%), ASC(MID$(Row$, g% + 1, 1))
NEXT
NEXT
CASE ELSE: CLOSE 1: EXIT DO
END SELECT
SEEK #1, Fpos&
NEXT
SEEK 1, FF& + FrameSize&
_DISPLAY
_LIMIT 12
NEXT
IF NOT _SNDPLAYING(songhand&(track)) THEN
_SNDSTOP songhand&(track)
track = track + 1
IF track > trackmax THEN track = 1
_SNDPLAY songhand&(track)
END IF
LOOP
_SNDSTOP songhand&(track)
_SNDCLOSE songhand&(track)
CLOSE 1
SYSTEM