112 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <META NAME=VIEWPORT CONTENT=initial-scale=1>
 | |
| <CENTER>
 | |
| <P><A HREF=http://nycki.net/qrplay>qrplay v3b</A><br>by nycki and SArpnt</P>
 | |
| <TEXTAREA ID=F 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="
 | |
| F.A?.close();
 | |
| F.A=A=new AudioContext;
 | |
| // kill some time for the audio context to start
 | |
| S='@qx@'+F.value;
 | |
| // stack
 | |
| B=[];
 | |
| // stack variables
 | |
| K=O=T=Z=L=0;
 | |
| U=137;
 | |
| V=40;
 | |
| // samples
 | |
| C=[
 | |
| 	'+g',
 | |
| 	'-b+c#deff#g',
 | |
| 	'g++ddb--g++ddb',
 | |
| 	,
 | |
| 	'+ea-g--b++g++c#',
 | |
| 	'a#ga#g-a#+g-b+g',
 | |
| 	'-a++c#-aae+e--a',
 | |
| 	'-ffed#ddc#',
 | |
| 	'dddddd#e',
 | |
| 	'--ba#bb-a+a#-b'
 | |
| ].map(c=>`{@++m${c}}x`);
 | |
| 
 | |
| // main loop
 | |
| M=_=>{
 | |
| 	[a,b,c,d]=S;
 | |
| 	// next index into S
 | |
| 	s=1;
 | |
| 	// opcode
 | |
| 	z='\n;+-@.3cdefgabx012456789jtsiqhwmuv{}'.indexOf(a);
 | |
| 
 | |
| 	// no match
 | |
| 	z<0?0:
 | |
| 	// comment
 | |
| 	z<2?K=z:K?0:
 | |
| 	// octave
 | |
| 	z<4?O+=a+1|0:
 | |
| 	// reset octave and length
 | |
| 	z<5?(O=0,L=1):
 | |
| 	// dots and triplets
 | |
| 	z<7?L*=3/(z<6?2:9):
 | |
| 	// note or rest
 | |
| 	z<15?(
 | |
| 		z-=7,
 | |
| 		o=new OscillatorNode(A,{
 | |
| 			type:'square',
 | |
| 			detune:100*(z*2-(z>2)-(b=='!')+(b=='#')+12*O-9)
 | |
| 		}),
 | |
| 		g=new GainNode(A,{gain:z<7&&.5**(14-V/5)}),
 | |
| 		o.connect(g),
 | |
| 		g.connect(A.destination),
 | |
| 		o.start(T),
 | |
| 		o.stop(T+=7.5*L/U)
 | |
| 	):
 | |
| 	// store sample
 | |
| 	z<24&&b=='['?(
 | |
| 		m=0,
 | |
| 		d=B.findIndex.call(S,c=>
 | |
| 			c=='['?!++m:
 | |
| 			c==']'?!--m:
 | |
| 			0
 | |
| 		),
 | |
| 		C[a]=S.slice(s,d),
 | |
| 		s=d+1
 | |
| 	):
 | |
| 	// play sample
 | |
| 	z<24?S=C[a]+S.slice(s--):
 | |
| 	// set note length
 | |
| 	z<31?L=2**(z-25):
 | |
| 	// set note length (microtone)
 | |
| 	z<32?L=U/2**11:
 | |
| 	// change tempo in bpm
 | |
| 	z<33?(U=b+c+d,s+=3):
 | |
| 	// change volume
 | |
| 	z<34?(V=b+c,s+=2):
 | |
| 	// play simultaneously
 | |
| 	z<35?B[Z++]={L,O,T,U,V}:
 | |
| 	{L,O,T,U,V}=B[--Z];
 | |
| 	
 | |
| 	// loop
 | |
| 	(S=S.slice(s))&&setTimeout(M)
 | |
| };M()
 | |
| ">#play</BUTTON> <BUTTON ONCLICK=F.A.close()>#stop
 |