PLAY - QB64Official/qb64 GitHub Wiki

PLAY is a statement that plays notes of sound through the sound card in QB64 using a command STRING.

Syntax

PLAY commandstring$

Parameter(s)

  • The commandstring can be any literal or variable STRING consisting of the following uppercase or lowercase commands:
    • On - Sets the current octave (from 0 to 6). Example: PLAY "O3"
    • < - Down one octave (cannot be below zero). Example: PLAY "<<" 'goes down two octaves.
    • > - Up one octave (cannot be above 6). Example: PLAY ">>" ' goes up two octaves.
    • A, B, C, D, E, F or G are the notes in the current octave. Can use the following suffixes:
      • + or # for a sharp note. Example: PLAY "C#"
      • - for a flat note. Example: PLAY "C-"
    • Nn - Plays a note n by number(n can be between 0 to 84 in the 7 octaves, where 0 is a rest). Example: PLAY "N42"
    • Ln - Sets length of a note (n can be 1 to 64 where 1 is a whole note and 4 is a quarter of a note etc.). Example: PLAY "L4"
      • MS - Each note plays 3/4 of length set by L (staccato)
      • MN - Each note plays 7/8 of length set by L (normal)
      • ML - Each note plays full length set by L (legato)
      • Pn - Pause in the duration of n quarternotes (n can be 1 to 64) corresponding to L, Example: PLAY "P32"
      • Tn - Tempo sets number of L4 quarter notes per minute (n can be 32 to 255 where 120 is the default). Example: PLAY "T180"
    • ** .** - period after a note plays 1½ times the note length determined by L * T.
    • .. - two periods plays 1-3/4 times the note length determined by L * T.
    • , - commas in QB64 stop play advancement to allow more than one note to be played simultaneously. Example: PLAY "C,E,G,"
    • Vn - Volume in QB64 only can be any volume from 0(none) to 100(full). The default level is 50 when n is not specified.
    • MF - Play music in the foreground (each note must be completed before another can start).
    • MB - Play music in the background while program code execution continues (QB64 has no note buffer limits).
    • X + VARPTR$(string-expression) - executes a command string variable. MUST be used with variables!.

Usage

  • MB will allow music to play while program code progresses. MF will wait for code to continue playing notes.
  • Command string values are not case sensitive and spacing is ignored. Use upper or lower case as desired. *NOTE: In QB64, PLAY may NOT delay program progress! Use _DELAY and END to allow music completion.

Example(s)

Plays a sound with the volume and note varying from 0 to 50. Maximum note can only be 84.

PLAY "mll64"
DO
    FOR x = 1 TO 50
        a$ = a$ + "v" + LTRIM$(STR$(x)) + "n" + LTRIM$(STR$(x))
    NEXT
    FOR x = 50 TO 1 STEP -1
        a$ = a$ + "v" + LTRIM$(STR$(x)) + "n" + LTRIM$(STR$(x))
    NEXT
    PLAY a$
    a$ = ""
LOOP UNTIL INKEY$ <> ""
PLAY "v10l1c,l4egl2o5c,o4l4eg" 

Plays "Frosty the snowman". The lyric printing is not delayed by PLAY in QB64.

CLS : PRINT "Frosty the Snow Man" 
FOR X = 1 TO 2
  PRINT
  IF X = 1 THEN PRINT "Fros-ty the Snow man was a jolly happy soul,"
  IF X = 2 THEN PRINT "Fros-ty the Snow man knew the sun was hot that day"
  PLAY "t140o2p4g2e4.f8g4o3c2o2b8o3c8d4c4o2b4a8g2."   'MB removed to print song one line at a time
  IF X = 1 THEN PRINT "with a corn cob pipe and a button nose and two eyes made out of coal."
  IF X = 2 THEN PRINT "so he said Let's run and we'll have some fun now before I melt away."
  PLAY "o2b8o3c8d4c4o2b4a8a8g8o3c4o2e8e4g8a8g4f4e4f4g2."
  IF X = 1 THEN PRINT "Fros-ty the Snow Man is a fair-y tale, they say,"
  IF X = 2 THEN PRINT "Down to the vil-lage, with a broom-stick in his hand,"
  PLAY "g2e4.f8g4o3c2o2b8o3c8d4c4o2b4a8g2."
  IF X = 1 THEN PRINT "He was made of snow but the chil-dren knew how he come to life one day."
  IF X = 2 THEN PRINT "run-ning here and there all a-round the square, say-in' catch me if you can."
  PLAY "o2b8o3c8d4c4o2b4a8a8g8o3c4o2e8e4g8a8g4f4e4d4c2."
  IF X = 1 THEN PRINT "There must have been some magic in that old silk hat they found."
  IF X = 2 THEN PRINT "He led them down the streets of town right to the traffic cop."
  PLAY "c4a4a4o3c4c4o2b4a4g4e4f4a4g4f4e2."
  IF X = 1 THEN PRINT "For when they placed it on his head he be-gan to dance a round."
  IF X = 2 THEN PRINT "And he on-ly paused a moment when he heard him hol-ler Stop!"
  PLAY "e8e8d4d4g4g4b4b4o3d4d8o2b8o3d4c4o2b4a4g4p4"
  IF X = 1 THEN PRINT "Oh, Fros-ty the Snow Man was a-live as he could be,"
  IF X = 2 THEN PRINT "For, Fros-ty the Snow Man had to hur-ry on his way"
  PLAY "g2g2e4.f8g4o3c2o2b8o3c8d4c4o2b4a8g8g2."
  IF X = 1 THEN PRINT "and the chil-dren say he could laugh and play just the same as you and me."
  IF X = 2 THEN PRINT "but he waved good-bye say-in' Don't you cry, I'll be back a-gain some day."
  PLAY "o2b8o3c8d4c4o2b4a8a8g8o3c4o2e8e4g8a8g4f4e4d4c2.p4"
NEXT X
PRINT : PRINT "Thump-et-y thump thump, thump-et-y thump thump, look at Fros-ty go."
PLAY "t180g8g8g4g4g4a8g8g4g4g4a4g4e4g4d1"
PRINT "Thump-et-y thump thump, thump-et-y thump thump, ov-er the hills of snow."
PLAY "t180g8g8g4g4g4a8g8g4g4g4g8g8g4a4b4o3c2c4p1" 
END

Clicking on the grid enables various notes to be played simultaneously.

DIM SHARED grid(16, 16), grid2(16, 16), cur
CONST maxx = 512
CONST maxy = 512
SCREEN _NEWIMAGE(maxx, maxy, 32)
_TITLE "MusicGrid"
cleargrid
DO
    IF TIMER - t# > 1 / 8 THEN cur = (cur + 1) AND 15: t# = TIMER
    IF cur <> oldcur THEN
        figuregrid
        drawgrid
        playgrid
        oldcur = cur
    END IF
    domousestuff
    in$ = INKEY$
    IF in$ = "C" OR in$ = "c" THEN cleargrid
LOOP UNTIL in$ = CHR$(27)

SUB drawgrid
scale! = maxx / 16
scale2 = maxx \ 16 - 2
FOR y = 0 TO 15
    y1 = y * scale!
    FOR x = 0 TO 15
        x1 = x * scale!
        c& = _RGB32(grid2(x, y) * 64 + 64, 0, 0)
        LINE (x1, y1)-(x1 + scale2, y1 + scale2), c&, BF
    NEXT x
NEXT y
END SUB

SUB figuregrid
FOR y = 0 TO 15
    FOR x = 0 TO 15
        grid2(x, y) = grid(x, y)
    NEXT x
NEXT y
FOR y = 1 TO 14
    FOR x = 1 TO 14
        IF grid(x, y) = 1 AND cur = x THEN
            grid2(x, y) = 2
            IF grid(x - 1, y) = 0 THEN grid2(x - 1, y) = 1
            IF grid(x + 1, y) = 0 THEN grid2(x + 1, y) = 1
            IF grid(x, y - 1) = 0 THEN grid2(x, y - 1) = 1
            IF grid(x, y + 1) = 0 THEN grid2(x, y + 1) = 1
        END IF
    NEXT x
NEXT y
END SUB

SUB domousestuff
DO WHILE _MOUSEINPUT
    IF _MOUSEBUTTON(1) THEN
        x = _MOUSEX \ (maxx \ 16)
        y = _MOUSEY \ (maxy \ 16)
        grid(x, y) = 1 - grid(x, y)
    END IF
LOOP
END SUB

SUB playgrid
n$ = "L16 "
'scale$ = "O1CO1DO1EO1FO1GO1AO1BO2CO2DO2EO2FO2GO2AO2BO3CO3D"
scale$ = "o1fo1go1ao2co2do2fo2go2ao3co3do3fo3go3ao4co4do4fo"
FOR y = 15 TO 0 STEP -1
    IF grid(cur, y) = 1 THEN
        note$ = MID$(scale$, 1 + (15 - y) * 3, 3)
        n$ = n$ + note$ + ","   'comma plays 2 or more column notes simultaneously
    END IF
NEXT y
n$ = LEFT$(n$, LEN(n$) - 1)
PLAY n$
END SUB

SUB cleargrid
FOR y = 0 TO 15
    FOR x = 0 TO 15
        grid(x, y) = 0
    NEXT x
NEXT y
END SUB 

Play strings starting with MB allow program code to run while music plays in background.

' 2012, 2013 mennonite
' license: creative commons cc0 1.0 universal
' (public domain) http://creativecommons.org/publicdomain/zero/1.0/

SCREEN 12 ' the following works in other screen modes, too
RANDOMIZE TIMER

PLAY "mb l4cf.l8el4fag.l8fl4gl8agl4f.l8fl4a>cl2dl4dl4c.<l8al4afg.l8fl4gl8agl4f.l8dl4dcl2f>l4dc.<l8al4afg.l8fl4g>dc.<l8al4a>cl2dl4dc.<l8al4afg.l8fl4gl8agl4f.l8dl4dcl1f"

DIM ccs(1 TO 9, 1 TO 2)
ccs(1, 1) = 415: ccs(1, 2) = 289
ccs(2, 1) = 185: ccs(2, 2) = 128
ccs(3, 1) = 108: ccs(3, 2) = 75
ccs(4, 1) = 70: ccs(4, 2) = 48
ccs(5, 1) = 48: ccs(5, 2) = 32
ccs(6, 1) = 32: ccs(6, 2) = 20
ccs(7, 1) = 20: ccs(7, 2) = 12
ccs(8, 1) = 10: ccs(8, 2) = 6
ccs(9, 1) = 2: ccs(9, 2) = 2

FOR extra = 1 TO 23
  FOR p = 1 TO 9
    gcolor INT(RND * 9 + 14 - 9)
    _DELAY .04
    CLS
    gscale p
    row = ccs(p, 1)
    cl = ccs(p, 2)
    glocate row, cl
    gprint "000000000000000000000000000000000000000000000000000000000000000000000"
    glocate row + 1, cl
    gprint "0x00x0xxxx0xxxx0xxxx0x0x000x00x0xxxx0x000x000x0x0xxxx0xxxx0xxxx000x00"
    glocate row + 2, cl
    gprint "0x00x0x00x0x00x0x00x0x0x000xx0x0x0000x000x000x0x0x0000x00x0x00x000x00"
    glocate row + 3, cl
    gprint "0xxxx0xxxx0xxxx0xxxx0x0x000x0xx0xxx00x0x0x000x0x0xxx00xxxx0xxxx000x00"
    glocate row + 4, cl
    gprint "0x00x0x00x0x0000x00000x0000x00x0x0000x0x0x0000x00x0000x00x0x0x0000000"
    glocate row + 5, cl
    gprint "0x00x0x00x0x0000x00000x0000x00x0xxxx0xx0xx0000x00xxxx0x00x0x00x000x00"
    glocate row + 6, cl
    gprint "000000000000000000000000000000000000000000000000000000000000000000000"
  NEXT p
  SLEEP 1
  IF INKEY$ = CHR$(27) THEN EXIT FOR
NEXT extra

END

SUB gscale (s):
SHARED gscalep
gscalep = INT(s)
END SUB

SUB gcolor (c):
SHARED gcolorp
gcolorp = c
END SUB

SUB gbackcolor (c):
SHARED gbackcolorp
gbackcolorp = c
END SUB

SUB glocate (row, column):
SHARED gposxp
SHARED gposyp
gposyp = row
gposxp = column
END SUB

SUB gprint (p$):
SHARED gscalep
SHARED gposxp, gposyp
SHARED gcolorp, gbackcolorp
' # means "use the foreground color here."
' . means "use the background color here."
' _ means "transparent - don't draw this block at all" (you can layer!)
' 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f means "do color attribute 0 to 15."
' any letter after f: "use the foreground color here."
IF gscalep < 1 THEN gscalep = 1
pcolorp = gcolorp
FOR p = 1 TO LEN(p$):
  SELECT CASE LCASE$(MID$(p$, p, 1))
    CASE "#", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
      pcolorp = gcolorp
    CASE "."
      pcolorp = gbackcolorp
    CASE "_"
      pcolorp = -1
    CASE "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"
      pcolorp = INSTR("0123456789abcdef", LCASE$(MID$(p$, p, 1))) - 1
  END SELECT
  IF NOT pcolorp = -1 THEN
    IF gscalep > 1 THEN
      LINE ((gposxp - 1) * gscalep, (gposyp - 1) * gscalep)-STEP(gscalep - 1, gscalep - 1), pcolorp, BF
    ELSE:
      PSET (gposxp, gposyp), pcolorp
    END IF
  END IF
  glocate gposyp, gposxp + 1
NEXT p
gposxp = 1
glocate gposyp + 1, 1 'gposyp = gposyp + 1
END SUB 

This example uses PRINT to good effect as string spacing is ignored by PLAY:

WIDTH 59, 28
PRINT <nowiki>
x$ = x$ + "   o3    l4         t         0120c    ml<f1   ,a      1,  "
x$ = x$ + "   >c    1,        mnf        .e  8f   am  l<   e1    ,g   "
x$ = x$ + "   1,    >c       1, mn       g.   f8  ga   8g   8m  l<    "
x$ = x$ + "   f2.,a2.,      >c   2.      ,m  nf   .f  8a     ml<f     "
x$ = x$ + "   ,a,>c,mn     >cd2.,<f2     .,d2     .,<b        -2      "
x$ = x$ + "   .m    lb    -,>d,f,mn>d    ml       <c          1,      "
x$ = x$ + "   <a    1,   f1         ,m   n>       >c          .<      "
x$ = x$ + "   a8    af  ml           c1  ,<       e1          ,g      "
x$ = x$ + "                                                           "
x$ = x$ + "      1,m      n>  g.f8ga8g8m  l<                   f1     "
x$ = x$ + "      ,d1,     <b  -1           ,m                 n>      "
x$ = x$ + "      >f .d    8d  c<            f2               .,       "
x$ = x$ + "      a2  .,   c2  .,>f2.         ml      <      b-        "
x$ = x$ + "      ,>   d,  f,  mn>dml          <c    1,<    a1         "
x$ = x$ + "      ,f    1, mn  >>               c.  <a 8a  fm          "
x$ = x$ + "      lc     2.,<  e2                .,g2   .,mn           "
x$ = x$ + "      >g      .f8  gml<b-,>d,         f,     mn            "
x$ = x$ + "                                                           "
x$ = x$ + ">d      ml  <<f2.,a2.,         >         c2.,m       n>  c."
x$ = x$ + " <a    8a   ml                <e,        g,  >c      ,m  n>"
x$ = x$ + "  cm  l<    <b               -2 .,       >d   2.     ,f  2."
x$ = x$ + "   ,mn>     d2.ml<          <b   -,      >d  ,f      ,m  n>"
x$ = x$ + "    dm      l<<f1,         a1,>c1,mn     >c.<a       8a  fm"
x$ = x$ + "    lc      1,            <e1,g1,mn>g    .f  8g      a8  g8"
x$ = x$ + "    ml      <<           b-         1,   >d   1,           "
x$ = x$ + "    f1      ,mn>f.d8dc  l1           ml  f,    c,    <a  ,f"</nowiki>
PRINT x$;
PLAY x 

See Also

⚠️ **GitHub.com Fallback** ⚠️