This week, I ported the LFO and envelope code (including the delay feature for envelope 2, a sweet little pseudorandom number generator for the LFO, and all the original bodges to make the amplitude attack sound better), mapped the control surface properly to the synth controls, and translated the original OSCar patches from the old layout into the new one.
The patch data translation was achieved using a Python script I wrote, because that’s what Python is for. While it was changing the order, range, and zero-value points for the parameters, it also decoded them into something more readable:
2 : CELLO
--------------------------------
Osc1Wave: Pulse
Osc2Wave: =Osc1
Osc2Oct: +0
Osc2Semi: +0
Osc2Detune: +8
Octave: +0
Transpose: +0
BendAmt: 0x1d
PulseWidth: +35
OscBalance: -2
NoiseBalance: -64
GlideType: Normal/Fix
GlideRate: 0x00
FiltType: LowPass
FiltFreq: 0x9c
FiltQ: 0x21
FiltSeparation: 0x4b
FiltDrive: 0x71
LFOWave: Triangle
LFORate: 0x60
IntroDelay: 0x40
EAAttack: 0x4e
EADecay: 0x00
EASustain: 0x7f
EARelease: 0x2f
EFAttack: 0x54
EFDecay: 0x00
EFSustain: 0x7f
EFRelease: 0x34
VoiceMode: Normal
TriggerType: Single
ExtAndSync: 0
ArpFlags: Up-Down-Rpt hands-on
GateTime: 0x30
WheelToPitch: 0x0c
WheelToFilt: 0x00
LFOToPitch: +9
LFOToFilt: +5
EnvToFilt: -12
Pulse is an interesting choice of basic waveform for cello: Helmholtz told us to start with a sawtooth, but it’s not that different in the frequency domain.
Once I’ve finished tinkering with the memory layout, I have to come up with a way for the new OSCar to accept a patch dump from the old one, and vice versa. It’s complicated by the all-or-nothing nature of OSCar’s Sysex format, and the fact that I don’t want to have to write converters in both directions in firmware. There’s probably going to have to be a Paul Whittington Music patch librarian at some point: thank goodness (well, thank Jules) for JUCE.
Three new LEDs on the control panel show LFO and envelope levels, and they do their job nicely enough now, but two things are preventing me from filming another demo. The first is that the Jewish calendar has a festival at this time of year. I’m visiting my mother for Pesach, and didn’t want to schlep a full-sized synth on the train with me. The second is I didn’t quite finish the modulation maths, which is surprisingly sprawling, taking in the data from all these modulators, testing for all kinds of mode-based exceptions, and mixing via a lot of arithmetic and mod wheel signals to the filter and amplitude control voltages.

This will be the last progress-o-gram, for a few reasons:
- Little remains to be ported of OSCar’s code that actually affects the way it sounds or operates. From now on, a short list will serve better.
- This has always been a loose abstraction, which is another way of signalling that it has passed the stage where it was serving a useful purpose and is now telling lies. It’s a question of taste to decide when a routine deserves to turn green. xpot.mac, for example, converts 8-bit control values to the 16-bit numbers that the synth engine uses internally. It includes functions to rescale, exponentiate, and reverse the direction of some controls. While this stuff is all converted and tested, a few of the parameters that use this pipeline aren’t wired in yet. That’s one reason why it’s not marked as done. The other is that the code has changed context and location. Whereas the original codebase had to deal with a control surface, it’s needed to become more abstract so it can handle MIDI data too. At risk of labouring the point, kwave.mac is green but the keyboard waveforms aren’t usable yet. (Clerical error.) On the other hand, the two routines left in orange, that compute the control voltages for filters and amplifiers and live-edit the wave tables to modulate the pulse width respectively, are sufficiently understood to make a start on conversion even if the source code isn’t yet documented to my usual fussy standard.
- As it’s the precise character, quirks, and workflow of the original we want to emulate, and not its technical limitations, most of the rest of the work is going to be coupled less closely to the original OSCar. That 1-kilobyte lump of MIDI code is very much a case in point. The abstraction will only hold worse from now on.
Since we’re leaving the progress-o-gram behind, here’s my to-do list, organised into the only two categories that currently matter. It’s still looking good for a publicly-playable demo by Superbooth on May 7th. We’ll be doing this with the current iteration of prototype, complete with little green wires, as it’ll save me a day of administering and building a new PCB.
Before Superbooth:
- Making the modulation engine work the 7 internal control voltages properly (of which two are currently complete and the rest are bodged with falsework code). At this point, OSCar will suddenly sound like OSCar;
- Adding the two LFO settings that aren’t actually LFO settings: keyboard control voltage and envelope;
- ‘Hold’ mode, which seems to work quite differently to the same feature on Mininova and Mantis;
- Adding the pulse waveform modes and the special LFOs that control them according to their own weird rules;
- Adding all pitch control logic, including glide, tuning, transpose, and the pitch bend wheel;
- Lighting up the panel octave LEDs;
- Temporary patch recall so that we can audition the original factory presets;
- If I can be bothered, designing and 3D printing a temporary top panel just to make the prototype look more like an OSCar.
After Superbooth:
- The user wavetable editor;
- External tempo sync;
- Advanced triggering options that the original ‘TRIGGERING’ knob supported;
- Full preset management: loading, saving, and MIDI dumps;
- Fixing the architectural mess that Chris left with the wavetable oscillators (on which, more in good time) so that, without changing the sound, we’ll be able to accommodate a wider range than the original 60 semitones.
- The arpeggiator;
- The sequencer;
- Mysterious and exciting new features, which I know better than to promise in any detail.

Leave a Reply