This code is supposed to generate a 64 sample loop. Carrier volume is not calculated, because it can be handled in hardware by the DSP.
Code: Select all
fm_synth: //this uses bass.exe as the assembler
lda #$82
sta {brr_buffer}
sta {brr_buffer}+9
sta {brr_buffer}+18 //BRR samples need a header byte every 9th byte
inc
sta {brr_buffer}+27 //first 3 BRR blocks have a header byte of $82 (range = 8, filter = 0, loop flag set)
ldx #$00 //last block has a header byte of $83 (same as above, but with end flag set)
str {#_of_blocks}=#$04 //4 blocks of 16 samples = 64 samples
-;
inx
str {countdown}=#$08 //8 pairs of samples per block
-;
clc
adc {modulator_phase}={modulator_frequency} //add modulator frequency to phase
ldy {modulator_phase}
lda sine_table,y //use modulator phase to index an 8-bit sine wave
ldy {modulator_amplitude} //with a range from 0 to 255
mul //multiply the sine wave (A) with amplitude (Y) to get the modulation height (Y)
clc //I believe SPC700 uses unsigned multiply. I'll fix it if I'm wrong
adc {carrier_phase}={carrier_frequency} //add carrier frequency to carrier phase
tya
clc
adc {carrier_phase} //take the carrier phase and add the current modulation height
tay
lda waveform,y //use that to get the final 4-bit sample
sta {temp}
clc
adc {modulator_phase}={modulator_frequency} //do it all again for another sample
ldy {modulator_phase}
lda sine_table,y
ldy {modulator_amplitude}
mul
clc
adc {modulator_phase}={modulator_frequency}
tya
clc
adc {carrier_phase}
tay
lda {temp}
xcn //this time, grab the previous sample, and swap nibbles
ora waveform,y //OR it with the new sample, to have 2 samples in 1 byte
sta {brr_buffer},x //save the result
inx
dec {countdown}
bne -
dec {#_of_blocks}
bne --
rts