Targets:

PET
VIC-20
C64
Plus/4 (unfinished, but intended)

All targets can be both PAL and NTSC.


Evening out capabilities between the targets:

- 3 virtual channels, mixed into 1-3 hardware channels;
- The lowest note is 55 Hz (A-1), defined by lowest note on VIC-20 (PET and Plus/4 will use IRQs to go below 245 Hz and 110 Hz);
- Two of the virtual channels are shifted by an octave as with the VIC-20 sound chip, three octaves per channel, four octave range overall;
- The drum channel octave is the same as the first tone channel, as the drums need to have low frequencies;
- Waveshaping is supported for the PET, translated to viznut's waveforms for the VIC-20, duty cycle, or volumes for other targets.





Music data format:

	byte speed * 16, normally (3..6)*16
	byte pattern len (normally 4..32)
	word instruments data offset
	word pattern data offset
	word order list start point
	word order list loop point

	all offsets are relative to the music data start

Instrument data follows:

	an empty instrument
	7 instruments for ch1
	7 instruments for ch2
	7 instruments for ch3
	
	an instrument is a pair of words that pointing out to the volume and arp/pitch envelope
	the pointers are relative to the instrument data start
	
Envelope data follows:

	a variable number of bytes per an envelope
	one byte is a signed 8-bit value, other than the special ones:
		127 toggle arp/pitch effect for the arp/pitch envelopes
		129 loop start
		128 envelope end
	
Order list data follows:

	three bytes per an order position, which are the pattern numbers (up to 254 patterns)
	ends with 255, which loops the list to the order loop point
	
Patterns list follows:

	16-bit pointers to the pattern data of each pattern
	the pointers are relative to the pattern list start
	
Pattern data follows:
	
	N bytes per a pattern, usually 8-16
	a byte has format %iiinnnnn, where i is an instrument number 1..7, nnnnn is a note 0..31
	the special values are 0 to just skip the position, 1 to a note off, 2..31 to repeat a previous byte 2..31 times
	

	
	
Player common logic:

	init:
	
		read speed and pattern len
		load order_ptr with pointer to beginning of the order list
		reset all variables, including pattern_row_counter, to 0
	

	update:
	
		check tempo_acc
		
		if it is equal or greater than music_speed, do order/pattern/row read
			
			subtract music_speed from tempo_acc
			
			check pattern_row_counter
		
			call order_update if 0
			
			
				order_update:
				
					read byte of order
					if 255, go loop, re-read byte
					
					read three bytes of pattern numbers, advance pointer by 3
					
					calculate the new pattern pointers
					
					set pattern_row_counter to pattern_len
					
			for each channel
			
				if skip counter > 0
			
				decrement skip counter
				
				if it is not zero, skip to next channel
				
				
				read pattern byte, which is %iiinnnnn
				advance pattern pointer
				
				if it is 0 to 30 (no active note)
			
				set skip counter to this value
				skip to next channel
				
				otherwise
				
					remember byte as channel_base_note (complete with instrument bits)
					
					extract the instrument bits, that's instrument number
					add 0,7, or 14 to instrument number depending on the channel number
					
					restart channel envelopes:
					
						calculate address in the instrument table (instrument number * 4 + table start)
						read two word pointers
						store each word pointer to ENV_PTR and ENV_LOOP of the volume and arp/pitch envelopes
						set ENV_MODE of arp/pitch envelope to zero
						
					set channel_detune to zero
					

			decrement pattern_row_counter
			
			
		add 16 or 14 to tempo_acc (PAL/NTSC, this is tempo compensation)
			
			
		envelope_advance, needs to be done each update regardless of tempo:
		(done after channel readouts to get the envelopes updated with the new values)
		
			for each envelope (there is two envelopes per channel, six total)
			
				read byte from pointer
				increase pointer
				
				if it is 128, set pointer to ENV_LOOP
				if it is 129, remember pointer to ENV_LOOP
				if it is 130, toggle ENV_MODE byte
				(planned) if it is 131, read another byte and set ENV_REPEAT, don't go reread after this
				
					 read another byte if it was one of the above
					  
				store byte to ENV_OUT
				store pointer
			
			
		mix envelope and note outputs to the actual values, needs to be done each update regardless of tempo:

			if base_note is less than 31
			
				skip to next channel
				
			if base_note is 31 (note off)
			
				set channel wave to 0 (mute), skip to next channel
								
			otherwise
			
				set channel wave to the volume envelope output
				
				read arp/pitch envelope mode
				
				if zero, this is arp mode
				
					read channel base note
					and #1f
					add arp/pitch envelope output
					add 12, if this is second channel
					remember as out note
					
				if not zero, this is pitch mode
				
					read channel base note
					and #1f
					remember as out note	

					read arp/pitch envelope output
					multiply by 8 (depends on platform)
					remember as channel detune
		
		
		go platform dependent logic

			
			
Player platform dependent logic for the PET:

	read ch3_wave
	if not zero, use third channel to output
	read ch2 wave
	if not zero, use second channel to output
	use first channel to output otherwise
	
		read chN_wave
		update sound wave 
		
			replace the current one only when it is different to avoid unwanted clicks
			should be checked against a RAM copy that does not get shifted while the sound is playing
	
		read a 16-bit divider from table using chN_out_note as offset
		extend chN_detune sign to 16 bit
		add to the divider
			
		update the divider