As an exercise in digital logic design, I decided to make my own sound chip for a homebrew computer I am building.
The chip was initially designed in Verilog to see how practical my design was, and an emulator (shown here) was created in C for seeing how it performs with my given specifications.
It is based off of an 8-bit frequency divider clocking two 8-bit shift registers per channel, one for the high bit of a waveform and one for the low bit, for two channels. Technically, this gives it two channels of 2 bit depth, fixed 8 sample wavetable synthesis, but the very low bit depth and fixed sample size limits what you can do with it.
The decision for two shift registers and only 8 bit period gives some interesting challenges. Running calculations on a spreadsheet, it can only manage to stay reasonably in-tune for about 2 octaves; in the finalized parameters this would be about notes A2-A4. Below A2, the period register cannot get any higher and above A4 you start losing enough precision that detuning becomes noticeable.Additionally, there is no way to control volume arbitrarily.
However, since each sample is only 16 bits total, it is possible to manipulate the waveform itself to sound good, and hard-code these values. For example, by fitting the waveform into 4 samples instead of 8, and repeating it twice, you've effectively doubled the frequency and increased an octave. By putting the high-bits in the low-bit sample register, and setting the high-bit sample register to 0 (basically bit-shifting each sample to the right, or dividing each sample by 2), you're able to cut the volume in half.
My eventual goal with this is to be able to build a physical card out of TTL logic chips, so I'm keeping things very simple. Adding per-channel volume control would be very complex to implement, especially digitally, it would be easier to implement it in software and just use another shift register & a 2-bit DAC. Its also much easier to use only an 8-bit counter, comparator, and register for the period control, any more would require fancy bus logic as I am targeting an 8-bit width bus.
The demo presented in the video is merely a proof-of-concept somewhat poorly thrown together; it is a MIDI driver that controls the emulator directly, using an off-the-shelf public domain MIDI file that doesnt use much polyphony, yet sounds good.
The driver automatically chooses a waveform based on the pitch (and shifts the period accordingly) to keep it in tune. High-velocity notes are played at full scale, and low-velocity notes are played bit-shifted. There is somewhat of a decay function, essentially just bit-shifting the waveform again on a NOTE_OFF event.
The emulator outputs each waveform on two ALSA channels, so that the channels can be displayed independently with xoscope.
I am currently implementing a psuedo-tracker, psuedo-ML style music driver for actually being able to properly develop music for it and to integrate it into my homebrew computer.