PLAY Command

discussion of beeb/electron applications, languages, utils and educational s/w
Post Reply
User avatar
dv8
Posts: 229
Joined: Mon Jun 22, 2009 9:07 pm
Contact:

PLAY Command

Post by dv8 » Fri Mar 15, 2019 12:43 pm

Presented here is an equivalent to the PLAY command found in some other dialects of BASIC. PLAY is a command that takes a sequence of musical notes and command characters and generates the appropriate sounds from them. Using PLAY is much easier than looking up numbers to pass to the SOUND command.

That said, PLAY is simply an alternative interface to the SOUND command (OSWORD 7) and as such is subject to the same restrictions. This command is not a substitute for a more advanced sequencer or 'tracker' style music player.

It's still a work-in-progress but I thought I'd share what I've done so far and see what the response is. For now the command needs to be loaded from disc. Future versions will also be implemented in a sideways ROM so it doesn't take up any user memory. EDIT: ROM version now included.

PLAY.ssd
(13.25 KiB) Downloaded 18 times
PLAY_ROM.zip
(2.15 KiB) Downloaded 5 times
PLAY_Instructions.pdf
(129.83 KiB) Downloaded 6 times
PLAY_Quick_Reference.pdf
(90.27 KiB) Downloaded 5 times

To try it out insert the attached disc then enter each of the following commands. The play string is case sensitive so be sure to enter the letters and symbols exactly as shown (or just copy & paste the lines one at a time into an emulator).

*PLAY C D E F G A B ^C
*PLAY S R4:CEGE: R4:CFAF: R4:DFAF: R4:DGBG:
*PLAY O1 I [CEGA$BAGE] [M1M1] T0M2 T2M2 T0M2 T5M1 T3M1 T0M1
*PLAY r2 [ QCCGGAA HG QFFEEDD HC ] M1 R2:QGGFFEE HD: M1
*PLAY @32 r1 [QC IC QD IDEGE Q.C] M1 QC IC QD ID Q.E QC I_ M1 IA__ QD IF Q.E QC I_
*PLAY O3 T-4 r1 iEE qE iEE qE iEG i.C sD hE iFF.F sF iFEE sEE iGGFD hC
*PLAY R2:I~B#CDE#FD Q#F IF#C QF IEC QE I~B#CDE#FD#FBA#FD#F QA_ T+7:
*PLAY @32 r1 [Q#F#FGAAG#FEDDE#F] M1 .#F IE HE M1 .E ID HD QEE#FDE I#FG Q#FDE I#FG Q#FEDE~A#F M1 .E ID HD
*PLAY @32 Q $B" ^C" $A" ~$A" H $E"
*PLAY H CM Q Dm _" H Fv5 Q Em _
*PLAY @48 =,0 I. ~C,,_'_Cm ~$E,,_'_Cm ~D,,_'_Do ~F,,_,I_SD,I._Do
*PLAY =K O1 r3 Q Gv5 $Bv5 Q.^Cv5 Q Gv5 $Bv5 r0 I ^$Dv5 Q.^Cv5 I_ r3 Q Gv5 $Bv5 Q.^Cv5 Q $Bv5 H Gv5
*PLAY =K I GM__ ^CvM__ FM__ FM_ GM_ Q.GM I ^CvM__ FM_ Q FvM I CM_ Q.Csus2

The PLAY command can also be used to create sound effects. Try these:

*PLAY O4 R3( L1 R4(C^C) ____ R5(C^C) H._ )
*PLAY U0 =V1 =,2 R9:^C'<G'<: t-2 R9:^C'>G'>:
*PLAY L1 O4 =V1 R5:F_: R15:F_>:
*PLAY L1 V0 R15:P4;8:
*PLAY L1 R25:CG^C T+1:
*PLAY V0 L140 P7 V1 L1 U0 P0 R128:P-2:
*PLAY f1 R55:P+126;1:_

The following examples repeat forever. Press Escape to stop them:

*PLAY f1 R:P+107;1:
*PLAY f1 L1 =P1 R:R50:+;:=P+1:
*PLAY L1 R:P+69,:
*PLAY V0 L* P3 V1 L1 U0 P0 R: R21:P+12: R21:P-12: :

Finally, CHAIN "DEMO" to hear a familiar tune.

The PLAY command loads into the host processor at &2100 so it may overwrite any BASIC program in memory (unless you are using a second processor). There is an alternative way of loading PLAY that relocates it to the start of host processor user memory:

*RPLAY play string

If you load it this way you will probably also want to increase the value of PAGE (there is no need to do this if you are using a second processor):

PAGE=PAGE+&800
NEW

To prevent the command having to be reloaded from disc each time it is run PLAY can install a handler to allow the *LINE command to pass play strings to it:

*RPLAY *
PAGE=PAGE+&800
NEW
*LINE play string

(again PAGE does not need to be increased if you are using a second processor)

The *LINE handler is installed for you if you boot the disc with Shift+Break.
Last edited by dv8 on Wed Apr 03, 2019 2:35 pm, edited 2 times in total.

User avatar
BigEd
Posts: 2565
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: PLAY Command

Post by BigEd » Sat Mar 16, 2019 10:04 am

I like this, a lot! Haven't had a chance to have a go yet.

User avatar
jgharston
Posts: 3597
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: PLAY Command

Post by jgharston » Sat Mar 16, 2019 8:11 pm

Looks interesting, reminds me of a DEFPROC_PLAY() routine I wrote years (eek! decades!) ago. One thing I notice is PROC_PLAY() used suffixed not modifiers, so eg C C# D D# E F F# G G# A A# B. I think I also used note+octave, so eg CC+1C+2 would be a chord of three Cs across three octaves. I vaguely remember basing it on the Spectrum 128 PLAY command.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
dv8
Posts: 229
Joined: Mon Jun 22, 2009 9:07 pm
Contact:

Re: PLAY Command

Post by dv8 » Wed Mar 20, 2019 11:52 am

Updated to version 1.01. Download links in opening post.

Made a couple of small improvements and added a preliminary ROM version.

jgharston wrote:
Sat Mar 16, 2019 8:11 pm
One thing I notice is PROC_PLAY() used suffixed not modifiers, so eg C C# D D# E F F# G G# A A# B. I think I also used note+octave, so eg CC+1C+2 would be a chord of three Cs across three octaves. I vaguely remember basing it on the Spectrum 128 PLAY command.
This one was inspired by the Commodore 128 PLAY command. I chose to use prefixes partly because in music notation accidentals are placed before the note they apply to, but mostly to make parsing easier. In particular I wanted to reduce the need for look-ahead to a minimum.

User avatar
dv8
Posts: 229
Joined: Mon Jun 22, 2009 9:07 pm
Contact:

Re: PLAY Command

Post by dv8 » Wed Apr 03, 2019 2:55 pm

Updated to version 1.02

New disc, ROM and documentation links in first post.

Changes:
  • Added double note length (d) and halve note length (l) commands
  • Added =K option to select whether chord notes are synchronized
  • Added new chord types 8 {0,12,12} and pow8 {0,12,24}
  • ROM version only: ? command now also prints current values of all settings

User avatar
lurkio
Posts: 2147
Joined: Tue Apr 09, 2013 11:30 pm
Location: Doomawangara
Contact:

Re: PLAY Command

Post by lurkio » Thu Apr 04, 2019 1:08 pm

Finally got a chance to, er, play with this. Very impressive -- though I'm not the best judge because I don't really understand music let alone how to encode it for the Beeb! But still I say, in all my ignorance, very impressive!

Is there any way the prog could be modified so that a *PLAY or *LINE command could be run "in the background", interrupt-driven, while a (non-musical) BASIC program runs in the foreground? I'm thinking of something like an intro screen that displays the title and artwork for a game and waits for keyboard input while a tune plays in the background, for example...

:?:
Last edited by lurkio on Thu Apr 04, 2019 1:12 pm, edited 1 time in total.

User avatar
dv8
Posts: 229
Joined: Mon Jun 22, 2009 9:07 pm
Contact:

Re: PLAY Command

Post by dv8 » Thu Apr 04, 2019 2:56 pm

As it stands there's no way the PLAY command could run under interrupt, the way some of the options work would need to change. It would have to be a separate version of the program, not terribly difficult but not trivial either.

In the very early pre-release versions there was an option to detect a key press and immediately stop playing and return control back to the user. This was put in for exactly the purpose you describe. Unfortunately it had to be dropped to make room for other commands.

PLAY will, however, still respond to an Escape event and stop immediately. So, with the aid of *FX220 to re-assign the Escape key you can kind of achieve what you want like this:

Code: Select all

10 ON ERROR GOTO 50
20 *FX220,32
30 PRINT "Press SPACE to stop the tune"
40 *PLAY =! R:T0 R2:I~B#CDE#FD Q#F IF#C QF IEC QE I~B#CDE#FD#FBA#FD#F QA_ T+7::
50 *FX220,27
60 ON ERROR OFF
70 PRINT "Continuing with rest of program"

User avatar
lurkio
Posts: 2147
Joined: Tue Apr 09, 2013 11:30 pm
Location: Doomawangara
Contact:

Re: PLAY Command

Post by lurkio » Thu Apr 04, 2019 7:21 pm

dv8 wrote:
Thu Apr 04, 2019 2:56 pm
...you can kind of achieve what you want like this:

Code: Select all

10 ON ERROR GOTO 50
20 *FX220,32
30 PRINT "Press SPACE to stop the tune"
40 *PLAY =! R:T0 R2:I~B#CDE#FD Q#F IF#C QF IEC QE I~B#CDE#FD#FBA#FD#F QA_ T+7::
50 *FX220,27
60 ON ERROR OFF
70 PRINT "Continuing with rest of program"
Your code doesn't seem to play any sounds at all..? It's just silent.

But the *PLAY command on its own does work if you copy and paste it separately, as a standalone line by itself (not as part of a BASIC prog).

:?:

User avatar
dv8
Posts: 229
Joined: Mon Jun 22, 2009 9:07 pm
Contact:

Re: PLAY Command

Post by dv8 » Thu Apr 04, 2019 7:43 pm

If you are booting the disc it will install the *LINE handler and raise PAGE to &2100. Since "PLAY" loads at &2100, running a *PLAY command in this state will overwrite the BASIC program.

Either run the example program above without booting the disc or change *PLAY to *LINE in line 40.

The boot environment is meant as a quick way to experiment with the *PLAY and *LINE commands. For use in real programs it's best to use the relocator *RPLAY and increase PAGE by &800. Have a look at the "DEMO" program on the disc to see how this can be done in practice.
Last edited by dv8 on Thu Apr 04, 2019 9:34 pm, edited 1 time in total.

Post Reply