v3e based on SArpnt's golf3
All checks were successful
/ build (push) Successful in 3m2s

This commit is contained in:
Nycki 2025-07-13 00:52:22 -07:00
parent 9e556f4ccb
commit c1bd32fba4
3 changed files with 200 additions and 0 deletions

109
static/qrplay/golf3.html Normal file
View file

@ -0,0 +1,109 @@
<!--
new parser, not zzt compatible, but conversion is easy
commands, must be uppercase
ABCDEFG play note
* sharp (modifier for note letter)
: flat (modifier for note letter)
X rest
JTSIQHW set note duration (J:sixtyfourth, Thirtysecond, Sixteenth, eIghth, Quarter, Half, Whole)
. increase note duration by 50% (persistent)
3 divide note duration by 3 (persistent)
+ octave up (persistent)
- octave down (persistent)
R reset note duration, octave, volume
Vxx set volume
Uxxx set bpm
$x.../ set sample
012456789: play sample
to convert:
make all letters uppercase
replace other simple commands with their new counterparts
#* !: @R
organize all Z channels in order
turn each channel into a sample that immediately plays (like $0.../0)
at the top of the file, define samples for drums 12456789
in each channel sample, define drum 0 inside, at the top
source variables
A: Audio context
C: Command Character from V
D: character after C (or other temporary Data)
F: function that plays notes, also stores samples
G: Gain node
H: textarea Html element
I: Index into V
J: `indexOf`
L: note Length
M: Music text
N: semitone Note offset for octave changes
O: Oscillator
Q: numeric command id
S: Sample function
T: note Time
U: Bpm
Z: channel
-->
<!--
DATA:TEXT/HTML,<META NAME=VIEWPORT CONTENT=INITIAL-SCALE=1><CENTER><H1><A HREF=HTTP://NYCKI.NET/QRPLAY>QRPLAY 3S</A></H1><TEXTAREA ID=H STYLE=WIDTH:MIN(40EM,99%);HEIGHT:9LH>U023%0A$0%0A$4D*/$5E/$6C*/%0A$7-B+4F*-JBT+4F*/%0A$8C*5GJC*T5G/%0A$9T7XX.XT7XX.XT4F*/%0A+9QX%0AT8XX.XT8XX.XT5G%0A9QX-%0ATA+6E-JAT+6E- F*6AJF*T6A 6A%0A/%0A$1-%0A$4JB+F*BF*/%0A$5JC*G+C*-GTC*+C*/%0A$6-4SXTB+B-4SX/%0AI6.X JED*E-B+%0AI5X5X%0A6.X JD*EF*G%0ATA-A+JATE .F*T-F*+F*-F*%0A/%0AW0X10X10X</TEXTAREA><P><BUTTON ONCLICK='H.A=A=new AudioContext,F=(M=``,T=0,L,N,I=0,S=D=>D?S(D+(M[++I]==C)-(M[I]==`/`)):I)=>{for(;C=M[I++];D=M[I],Q>7?(Q-=9)?Q>9?L/=+C||2/3:Q>7?(D=D+M[++I,I++]|0)?Q>8?U=D+M[I++]:G=new GainNode(A,{gain:2**(D/5-11)}):0:L=~Q?1<<Q:N=4:F[D]=M.slice(++I,S(1)):~Q?(O=new OscillatorNode(A,{type:`square`,detune:100*(Q*2-(Q>3)+(D==`*`)-(D==`:`)-N-7)}),Q&&O.connect(G,G.connect(A.destination)),O.start(T),O.stop(T+=L/U*15/8)):C-3|C>`_`?F(F[C],T,L,N):N-=C+12|0)Q=`XCDEFGABR$JTSIQHWVU3.`.indexOf(C)},F(`RU137V30`+H.value)'>PLAY</BUTTON> <BUTTON ONCLICK=H.A.close()>STOP
-->
<META NAME=VIEWPORT CONTENT=INITIAL-SCALE=1>
<CENTER>
<H1><A HREF=HTTP://NYCKI.NET/QRPLAY>QRPLAY 3S</A></H1>
<TEXTAREA ID=H STYLE=WIDTH:MIN(40EM,99%);HEIGHT:9LH>U023
$0
$4D*/$5E/$6C*/
$7-B+4F*-JBT+4F*/
$8C*5GJC*T5G/
$9T7XX.XT7XX.XT4F*/
+9QX
T8XX.XT8XX.XT5G
9QX-
TA+6E-JAT+6E- F*6AJF*T6A 6A
/
$1-
$4JB+F*BF*/
$5JC*G+C*-GTC*+C*/
$6-4SXTB+B-4SX/
I6.X JED*E-B+
I5X5X
6.X JD*EF*G
TA-A+JATE .F*T-F*+F*-F*
/
W0X10X10X</TEXTAREA>
<P><BUTTON ONCLICK='
H.A=A=new AudioContext,
F=(M=``,T=0,L,N,I=0,S=D=>D?S(D+(M[++I]==C)-(M[I]==`/`)):I)=>{for(
;
C=M[I++];
D=M[I],
Q>7?
(Q-=9)?
Q>9?L/=+C||2/3: /* DECREASE Q! and multiply note duration (3.) */
Q>7?
(D=D+M[++I,I++]|0)? /* get two digits */
Q>8?U=D+M[I++]: /* set bpm (U) */
G=new GainNode(A,{gain:2**(D/5-11)}): /* set Volume */
0:
L=
~Q?1<<Q: /* set note duration (JTSIQHW) */
N=4: /* Reset */
F[D]=M.slice(++I,S(1)): /* set sample ($x.../) */
~Q?( /* play note or rest (XCDEFGAB) */
O=new OscillatorNode(A,{
type:`square`,
detune:100*(Q*2-(Q>3)+(D==`*`)-(D==`:`)-N-7) /* pitch with sharp/flat (*:) */
}),
Q&&O.connect(G,G.connect(A.destination)),
O.start(T),
O.stop(T+=L/U*15/8)
):
C-3|C>`_`? /* numbers, whitespace, lowercase letters, some symbols */
F(F[C],T,L,N): /* play sample */
N-=C+12|0 /* change octave or nop */
)Q=`XCDEFGABR$JTSIQHWVU3.`.indexOf(C)},
F(`RU137V30`+H.value)
'>PLAY</BUTTON> <BUTTON ONCLICK=H.A.close()>STOP

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

91
static/qrplay/v3e.html Normal file
View file

@ -0,0 +1,91 @@
<META NAME=VIEWPORT CONTENT=initial-scale=1>
<CENTER>
<P><A HREF=http://nycki.net/qrplay>qrplay v3e</A><br>by nycki and SArpnt</P>
<TEXTAREA ID=H STYLE=WIDTH:MIN(40EM,99%);HEIGHT:9LH>; @title nupa's theme
; @authors nycki bsp
; single channel version
1[@0000]
2[
0[c-c+]1 1
0[e-c+]1 0[g-c+]1
0[c-b!+]1 1
0[e-b!+]1 0[g-b!+]1
0[d-a+]1 0[c-a+]1
]
2
0[d-a+]1 0[c-a+]1
0[d#-a!+]1 0[d-a!+]1
1 1
2
0[d#-a!+]1 0[d-g+]1
0[c--c++]1 1
1 1
</TEXTAREA><P>
<BUTTON onclick="
H.A=A=new AudioContext;
W=Date.now();
F=(
M='',
T=0,
L,
N,
I=0,
S=D=>D?S(D+(M[++I]==C)-(M[I]=='/')):I
)=>{;for(;
C=M[I++];
D=M[I],
J=E=>E.indexOf(D)>=0,
Q>7?
// DECREMENT Q, and then...
(Q-=9)?
// triplet or dotted rhythm, C is 3 or .
Q>9?L/=+C||2/3:
Q>7?
// extended command. read two digits, then...
(D=D+M[++I,I++]|0)?
// set bpm (U)
Q>8?U=D+M[I++]:
// set volume (V)
G=new GainNode(A,{gain:2**(D/5-11)}):
0:
// else, set length to...
L=
// fixed length (JTSIQHW)
~Q?1<<Q:
// reset L=N=4
(K=0,N=4):
// save sample ($x.../)
F[D]=M.slice(++I,S(1)):
~Q?(
// play note or rest
O=new OscillatorNode(A,{
type: 'square',
// !: are flat, #* are sharp
detune:100*(Q*2-(Q>3)-J('!:')+J('#*')-N-7)
}),
Q&&O.connect(G),
G.connect(A.destination),
O.start(T),
O.stop(T+=L/U*15/8)
):
// any unused letter or number
C-3|C>'@'?setTimeout(
// play a sample in parallel
_=>F(D,T,L,N),
// ...but don't read infinitely far ahead
1e3*T-Date.now()+W-5e3,
D=F[C]
):
// change octave, or noop
N-=C+12|0
)Q='XCDEFGABR$JTSIQHWVU3.'.indexOf(C)},
F('RU137V40'+H.value.toUpperCase())
">#play</BUTTON> <BUTTON onclick=H.A.close()>#stop
<!-- snip -->
</BUTTON></P>
<img src="qrplay-v3d-nupas-theme.png">
</center>