148 lines
		
	
	
		
			No EOL
		
	
	
		
			5 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			No EOL
		
	
	
		
			5 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <meta name="twitter:image" content="http://nycki.net/qrplay/qrplay-v3e-WiL-the-forest-chase.png">
 | |
| <meta property="og:image" content="http://nycki.net/qrplay/qrplay-v3e-WiL-the-forest-chase.png">
 | |
| 
 | |
| <!--
 | |
| nycki's modified version of SArpnt's player (see /golf3.html)
 | |
| compatible with ZZM files or with a reduced instruction set for QR Alphanumeric efficiency.
 | |
| 
 | |
| commands, case-insensitive
 | |
|     ABCDEFG play note
 | |
| 	* or # sharp
 | |
| 	: or ! flat
 | |
| 	X rest
 | |
| 	P go one note length to the Past
 | |
| 	JTSIQHW set note length to sixtyfourth, Thirtytwoth, Sixteenth, eIghth, Quarter, Half, Whole. (persistent)
 | |
| 	. increase note length by 50% (persistent)
 | |
| 	3 divide note length by 3 (persistent)
 | |
| 	+ octave up (persistent)
 | |
| 	- octave down (persistent)
 | |
| 	R or \n reset note length and octave
 | |
| 	Vxx set volume
 | |
| 	Uxxx set bpm
 | |
| 	$x.../ set sample
 | |
| 	01245679 play sample
 | |
| 
 | |
| ZZM mode
 | |
| 	comments begin with ; and metadata begins with $ (inside a comment)
 | |
| 	for instance:
 | |
| 	; $SONG TITLE 1 The Forest Chase
 | |
| 
 | |
| QR Alphanumeric Mode
 | |
| 	0-9A-Z $%*+-./:
 | |
| 	no lowercase, no newline, limited punctuation.
 | |
| 	to convert, use R for reset, * for sharp, : for flat, /.../ for comment.
 | |
| 
 | |
| Chords
 | |
|     to play multiple notes at once, use P after each note to back up and play another one in parallel. to play multiple channels at once, convert each channel to a sample and use P after playing each sample.
 | |
| 
 | |
| variable reference
 | |
| 	A: Audio context
 | |
| 	C: Command Character
 | |
| 	D: character after C, or other Data
 | |
| 	F: main Function, also object that holds samples
 | |
| 	G: Gain node
 | |
| 	H: textarea Html element
 | |
| 	I: Index into M
 | |
| 	J: lookahead (for sharps and flats)
 | |
| 	L: note Length
 | |
| 	M: Music text
 | |
| 	N: semitone Note offset (for octave changes)
 | |
| 	O: Oscillator node
 | |
| 	P: current time step
 | |
| 	Q: numeric command id
 | |
| 	S: find Sample
 | |
| 	T: note Time
 | |
| 	U: bpm
 | |
| 	W: realtime When the song starts
 | |
| -->
 | |
| 
 | |
| <!--
 | |
| data:TEXT/HTML,<META%20NAME=VIEWPORT%20CONTENT=initial-scale=1><CENTER><P><A%20HREF=http://nycki.net/qrplay>qrplay%20v3e</A><br>by%20nycki%20and%20SArpnt</P><TEXTAREA%20ID=H%20STYLE=WIDTH:MIN(40EM,99%);HEIGHT:9LH>; $TITLE WiL Best :: Atrocity%0A; $SONG TITLE 1 The Forest Chase%0AS-A+EBAEAGEA+C-BGAE+C-GRS-DA+DEGF*DAGEDF*DCEF*RS-A+EBAEAGEA+C-BGAE+C-GRS-DA+DEGF*DAGEDF*DEGARS--G+G+BAGDBF*BGDF*GAB+CRSCG+CE-G+E-G+CD-G+CC-G+CD-GRS-F+CF+C-AFCFGCFACEFERS-EB+EFG*AB+CD*EFG*AB+FE%0A</TEXTAREA><P><BUTTON%20onclick="H.A?.close();H.A=A=new%20AudioContext;W=Date.now();U=137;F=(M='',T=0,L,N,I=0,K=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,P=L/U*15/8,Q>25?K=!K:Q>23?(K=Q-24)||(L=N=4):K?0:Q>22?T-=P:Q>20?N-=C+12: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%20GainNode(A,{gain:2**(D/5-11)}):0:L=~Q?1<<Q:(K=0,N=4):F[D]=M.slice(++I,S(1)):~Q?(O=new%20OscillatorNode(A,{type:%20'square',detune:100*(Q*2-(Q>3)-J('!:')+J('%23*')-N-7)}),Q&&O.connect(G),G.connect(A.destination),O.start(T),O.stop(T+=P)):C>'@'||1+C>1?(E=>setTimeout(_=>F(...E),1e3*E[1]-Date.now()+W-5e3,))([F[C],T+=P,L,N]):0)Q='XCDEFGABR$JTSIQHWVU3.-+P\n;/'.indexOf(C)},F('RV35'+H.value.toUpperCase())">%23play</BUTTON>%20<BUTTON%20onclick=H.A.close()>%23stop
 | |
| -->
 | |
| 
 | |
| 
 | |
| <!-- snip -->
 | |
| <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 WiL Best :: Atrocity
 | |
| ; $SONG TITLE 1 The Forest Chase
 | |
| S-A+EBAEAGEA+C-BGAE+C-GRS-DA+DEGF*DAGEDF*DCEF*RS-A+EBAEAGEA+C-BGAE+C-GRS-DA+DEGF*DAGEDF*DEGARS--G+G+BAGDBF*BGDF*GAB+CRSCG+CE-G+E-G+CD-G+CC-G+CD-GRS-F+CF+C-AFCFGCFACEFERS-EB+EFG*AB+CD*EFG*AB+FE
 | |
| </TEXTAREA><P>
 | |
| <BUTTON onclick="
 | |
| H.A?.close();
 | |
| H.A=A=new AudioContext;
 | |
| W=Date.now();
 | |
| U=137;
 | |
| F=(
 | |
| 	M='',
 | |
| 	T=0,
 | |
| 	L,
 | |
| 	N,
 | |
| 	I=0,
 | |
| 	K=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,
 | |
| 	P=L/U*15/8,
 | |
| 	// skip comments and reset on newline
 | |
| 	Q>25?K=!K:
 | |
| 	Q>23?(K=Q-24)||(L=N=4):
 | |
| 	K?0:
 | |
| 	// backspace
 | |
| 	Q>22?T-=P:
 | |
| 	// change octave
 | |
| 	Q>20?N-=C+12:
 | |
| 	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+=P)
 | |
| 	):
 | |
| 	// any unused non-whitespace letter or number
 | |
| 	C>'@'||1+C>1?(E=>setTimeout(
 | |
| 		// play a sample async
 | |
| 		_=>F(...E),
 | |
| 		// don't async too far ahead or you'll lag us out
 | |
| 		1e3*E[1]-Date.now()+W-5e3,
 | |
| 	))([F[C],T+=P,L,N]):
 | |
| 	// do nothing
 | |
| 	0
 | |
| 	)Q='XCDEFGABR$JTSIQHWVU3.-+P\n;/'.indexOf(C)},
 | |
| 	F('RV35'+H.value.toUpperCase())
 | |
| ">#play</BUTTON> <BUTTON onclick=H.A.close()>#stop
 | |
| 
 | |
| <!-- snip -->
 | |
| </BUTTON></P>
 | |
| <img src="qrplay-v3e-WiL-the-forest-chase.png">
 | |
| </center> |