Snowman screen saver playing 17 MIDI Christmas songs
#1
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


.zip   snowman-v103.zip (Size: 710.24 KB / Downloads: 49)

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

Find my programs here in Dav's QB64 Corner
Reply


Messages In This Thread
Snowman screen saver playing 17 MIDI Christmas songs - by Dav - 12-17-2022, 12:23 PM



Users browsing this thread: 6 Guest(s)