Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Soul from Scratch: Designing a More Portable Organ

Soul from Scratch: Designing a More Portable Organ

Your Hammond B-3 sounds like nothing on Earth, but at 450 lbs your friends are sick of helping you carry it. They demand that you make it lighter, or they'll stop showing up to your gigs.

I will present the technical design of the Hammond B-3 and its frequent collaborator the Leslie rotating speaker cabinet, then model their audio components digitally. I'll show how to implement each of these components on a microcontroller. With a 20,000x savings in weight, you won't need friends!

This organ synthesizer includes full MIDI control of notes, drawbar settings, and effects. Recreate it inexpensively at home or apply its principles in other contexts.

The journey follows successes and failures of my initial design and optimizations that allow the simulation to run on a very low powered device. There's something for creative programmers, music fans, makers, and optimizers. My intent is to give enough groundwork that you can walk away and write your own synthesizer.

Avatar for Peter Teichman

Peter Teichman

September 28, 2018

Other Decks in Programming

Transcript

  1. ❤

  2. “If you wish to make ‘Green Onions’ from scratch, you

    must first invent the universe” CARL SAGAN
  3. MIDI Messages Note on 1001 CCCC 0NNNNNNN 0VVVVVVV Note off

    1000 CCCC 0NNNNNNN 0VVVVVVV Control change 1011 CCCC 0NNNNNNN 0VVVVVVV byte 1 byte 2 byte 3 4 bit channel 7 bit note 7 bit velocity
  4. TODO DISTORTION TREMOLO / VIBRATO 2 ROTATING SPEAKERS STEREO OUTPUT

    SINE OSCILLATOR VIBRATO / CHORUS PERCUSSION SWELL
  5. 91 tonewheel oscillators upper manual lower manual upper drawbars lower

    drawbars vibrato / chorus swell pedal percussion switches
  6. 91 tonewheel oscillators upper manual lower manual upper drawbars lower

    drawbars vibrato / chorus swell pedal percussion switches 53
  7. 91 tonewheel oscillators upper manual lower manual upper drawbars lower

    drawbars vibrato / chorus swell pedal percussion switches 54
  8. 91 tonewheel oscillators upper manual lower manual upper drawbars lower

    drawbars vibrato / chorus swell pedal percussion switches 56
  9. 91 tonewheel oscillators upper manual lower manual upper drawbars lower

    drawbars vibrato / chorus swell pedal percussion switches 57
  10. 91 tonewheel oscillators upper manual lower manual upper drawbars lower

    drawbars vibrato / chorus swell pedal percussion switches 58
  11. Tonewheels void transmit( audio_block_t *block, unsigned char index = 0);

    typedef struct audio_block_struct { int16_t data[128]; /* other stuff deleted */ } audio_block_t;
  12. Direct Digital Synthesis uint32_t counter = 0; while (1) {

    counter += 1; } while (1) { counter += 2; }
  13. sine lookup table: 16 bit signed values, 256 elements int16_t

    sine[256] uint32_t counter 32 24 16 8 oscillator { uint32_t counter; uint32_t increment; } int16_t next() { counter += increment; index = counter >> 24; return sine[index]; } Direct Digital Synthesis
  14. sine lookup table: 16 bit signed values, 256 elements int16_t

    sine[256] uint32_t counter 32 24 16 8 oscillator { uint32_t counter; uint32_t increment; } int16_t next() { counter += increment; index = counter >> 24; return sine[index]; } Direct Digital Synthesis
  15. sine lookup table: 16 bit signed values, 256 elements int16_t

    sine[256] uint32_t counter 32 24 16 8 oscillator { uint32_t counter; uint32_t increment; } int16_t next() { counter += increment; index = counter >> 24; return sine[index]; } incr = 00000001 00000000 00000000 00000000 Direct Digital Synthesis
  16. sine lookup table: 16 bit signed values, 256 elements int16_t

    sine[256] uint32_t counter 32 24 16 8 oscillator { uint32_t counter; uint32_t increment; } int16_t next() { counter += increment; index = counter >> 24; return sine[index]; } Direct Digital Synthesis sine lookup table: 16 bit signed values, 256 elements int16_t sine[256] uint32_t counter 32 24 16 8 oscillator { uint32_t counter; uint32_t increment; } int16_t next() { counter += increment; index = counter >> 24; return sine[index]; }
  17. increment < 2^24? increment > 2^24? incr = 00000001 00000000

    00000000 00000000 frequency < 172Hz frequency > 172Hz uint32_t counter = 0; while (1) { counter += 1; } while (1) { counter += 2; } Setting Frequency
  18. Setting Frequency incr = 232 44100 * freq increment <

    2^24? increment > 2^24? incr = 00000001 00000000 00000000 00000000 frequency < 172Hz frequency > 172Hz
  19. Setting Frequency uint32_t counter 32 24 16 8 32 24

    16 8 table index interpolation scale value = interpolate(v1, v2, scale); v1 v2
  20. Setting Volume oscillator { uint32_t accumulator; uint32_t increment; uint16_t volume;

    } int16_t next() { accumulator += increment; index = accumulator >> 24; scale = (accumulator >> 8) & 0xFFFF; sample = interpolate(sine[index], sine[index+1], scale); return (sample * volume) >> 16; } top 8 bits next 16 bits apply volume
  21. Setting Volume int16 sample; int16 volume; int16 result = (sample

    * volume) >> 16; (N bits) * (M bits) = N+M bits (N bits) + (M bits) = (max(N, M) + 1) bits
  22. writer reader read offset from writer t writer reader read

    offset from writer t Vibrato / Chorus
  23. Vibrato / Chorus int16_t triangle[256]; oscillator { uint32_t accumulator; uint32_t

    increment; uint16_t depth; } oscillator position frequency (7Hz) vibrato depth
  24. Percussion 91 original oscillators upper manual lower manual upper drawbars

    lower drawbars percussion switches 91 percussion oscillators percussion envelope to vibrato / chorus
  25. Don Leslie "I was amazed at all the publicity Hammond

    created for me by their continuous bad-mouthing of my product. This word-of-mouth advertising was so good that from the start until the company was sold to CBS in 1965, no advertising was ever needed and my problem has always been keeping up production to match sales."
  26. Treble horn amfm { int16 ringbuf[] uint32 accumulator uint32 increment

    uint16 read_shift[256] uint16 volume[256] } sawtooth oscillator frequency control vibrato tremelo
  27. audio from organ amplifier (growl) crossover filter treble horn (vibrato

    + tremolo) bass speaker (tremolo) audio to output high freqs low freqs Leslie Block Diagram Leslie 122 block diagram
  28. audio from organ amplifier (growl) crossover filter treble horn (vibrato

    + tremolo) bass speaker (tremolo) audio to L output high freqs low freqs Leslie Stereo Block Diagram crossover filter treble horn (vibrato + tremolo) bass speaker (tremolo) audio to R output high freqs low freqs phase shifted 90° Leslie stereo block diagram Stereo