Added a second modulation amplifier, so the oscillators and filter can have different levels. Tuned these amplifiers according to oscillators and filter range.

Added function setting for modulation range (same as pitchbend range), each can be independently set.
Completed readme with pitchbend and modulation range functions.
Added keys / knob used for function to readme.
Corrected midi in and out top setting values for channels (was 17 instead of 16).
master
Pierre-Loup Martin 4 years ago
parent 801ed52e1c
commit 8f3496b4bb
  1. 29
      README.MD
  2. 60
      minimoog_teensy/audio_setup.h
  3. 6
      minimoog_teensy/function settings.txt
  4. 39
      minimoog_teensy/minimoog_teensy.ino

@ -77,9 +77,12 @@ Portamento can be from 0 to ten seconds, and switch on and off.
There is +- 2 octave transpose available to compensate the only 2 1/2 octave from the keyboard.
### Function settings
There are "hidden" settings available through a function switch. When turn on, the keyboard can be used to change the behavior of some things. Each of this setting is saved when powered off.
There are "hidden" settings available through a function switch. When turn on, the keyboard can be used to change the behavior of some things. Each of this setting is saved when power is turned off.
The first octave of the keyboard is used to select the setting to be changed, then keys from the second C used to set the new value.
#### Keyboard priority mode
_Function + C_
This defines the way the keyboard behave. There are four mode available :
1. lower note priority : a note will be played only if it's lower than the one already playing.
1. first note priority : a note will be played only if no note is already playing.
@ -88,9 +91,13 @@ This defines the way the keyboard behave. There are four mode available :
In any case, ten notes are tracked, so when several key are pressed releasing a key will play another, according to their position or the order they was pressed.
#### Note retrigger
_Function + D_
This defines how a new note is played. If some keys are already pressed when a new note is played, it can retrigger the envelopes, or let them to their state. This can be turned on or off.
#### Keyboard detune
_Function + E_
The original minimoog has a resistor ladder keyboard, which implies small variations in tonality regarding a perfect pitch. This setting reproduce this by applying detune to each note and letting you choice :
1. off : perfect pitch for each key
1. soft : lightly detuned, +-10% of a semitone
@ -100,13 +107,31 @@ The original minimoog has a resistor ladder keyboard, which implies small variat
The detune table stores a fix detune coefficient for each of all 128 MIDI notes.
#### Bitcrush
_Function + F_
Output resolution can be changed. The default is 16 bits, but any bitsize between 4 and 16 can be choose.
The bitcrushing is applied at the end of the audio stream, just before the i2s / USB output.
#### Filter mode
The filter band knob slide continuously from low pass to high pass. It can be choosen wether :
_Function + G_
The filter band knob slides continuously from low pass to high pass. It can be choosen wether :
* it slides from low pass to band pass for the lower half (high pass cut), and from band pass to high pass in the upper half (low pass cut), or
* it slides continuously from low pass to high pass, thus resulting in a band stop filter when knob is centered. (well, kind of : having a true band stop filter would mean to mix two different filters with frequency offsets. Here they overlap.)
#### MIDI channel setting
_Function + A_ for MIDI in
_Function + B_ for MIDI out
The MIDI channel the synth listens and emit on when connected _via_ USB can be changed. Any channel from 1 to 16.
#### Pitchbend range
_Function + pitchbend wheel move_
The amount the pitch wheel bends a note above or bellow the note being played can be changed semitone by semitone.
#### Modulation range
_Function + modulation wheel move_
As well as the pitch bend range can be changed, so does the modulation range. Pressing any key will set this interval according to second C, for the modulation applied to oscillators. Modulation applied to filter can be changed as well, by pressing second C before to set the new interval.

@ -28,7 +28,8 @@ AudioMixer4 osc3ControlMixer; //xy=855,156
AudioMixer4 modMixer; //xy=867,405
AudioSynthWaveformDc dcOsc2Tune; //xy=1027,112
AudioSynthWaveformDc dcOsc3Tune; //xy=1028,178
AudioAmplifier ampModWheel; //xy=1081,405
AudioAmplifier ampModWheelOsc; //xy=1077,385
AudioAmplifier ampModWheelFilter; //xy=1084.5666809082031,420.566650390625
AudioMixer4 osc3TuneMixer; //xy=1211,174
AudioMixer4 osc2TuneMixer; //xy=1212,110
AudioSynthWaveformDc dcPulse; //xy=1228,22
@ -73,32 +74,33 @@ AudioConnection patchCord21(modMix2, 0, modMixer, 1);
AudioConnection patchCord22(modMix1, 0, modMixer, 0);
AudioConnection patchCord23(dcOsc3, 0, osc3ControlMixer, 1);
AudioConnection patchCord24(osc3ControlMixer, 0, osc3TuneMixer, 0);
AudioConnection patchCord25(modMixer, ampModWheel);
AudioConnection patchCord26(dcOsc2Tune, 0, osc2TuneMixer, 1);
AudioConnection patchCord27(dcOsc3Tune, 0, osc3TuneMixer, 1);
AudioConnection patchCord28(ampModWheel, 0, filterMixer, 0);
AudioConnection patchCord29(ampModWheel, 0, mainTuneMixer, 3);
AudioConnection patchCord30(osc3TuneMixer, 0, osc3Waveform, 0);
AudioConnection patchCord31(osc2TuneMixer, 0, osc2Waveform, 0);
AudioConnection patchCord32(dcPulse, 0, osc1Waveform, 1);
AudioConnection patchCord33(dcPulse, 0, osc2Waveform, 1);
AudioConnection patchCord34(dcPulse, 0, osc3Waveform, 1);
AudioConnection patchCord35(osc1Waveform, 0, oscMixer, 0);
AudioConnection patchCord36(osc2Waveform, 0, oscMixer, 1);
AudioConnection patchCord37(osc3Waveform, 0, oscMixer, 2);
AudioConnection patchCord38(osc3Waveform, ampOsc3Mod);
AudioConnection patchCord39(oscMixer, 0, globalMixer, 0);
AudioConnection patchCord40(globalMixer, ampPreFilter);
AudioConnection patchCord41(ampPreFilter, 0, vcf, 0);
AudioConnection patchCord42(ampPreFilter, printPreFilter);
AudioConnection patchCord43(filterMixer, 0, vcf, 1);
AudioConnection patchCord44(vcf, 0, bandMixer, 0);
AudioConnection patchCord45(vcf, 1, bandMixer, 1);
AudioConnection patchCord46(vcf, 2, bandMixer, 2);
AudioConnection patchCord47(bandMixer, mainEnvelope);
AudioConnection patchCord48(bandMixer, 0, globalMixer, 1);
AudioConnection patchCord49(mainEnvelope, bitCrushOutput);
AudioConnection patchCord50(bitCrushOutput, masterVolume);
AudioConnection patchCord51(masterVolume, 0, i2s, 0);
AudioConnection patchCord52(masterVolume, 0, i2s, 1);
AudioConnection patchCord25(modMixer, ampModWheelOsc);
AudioConnection patchCord26(modMixer, ampModWheelFilter);
AudioConnection patchCord27(dcOsc2Tune, 0, osc2TuneMixer, 1);
AudioConnection patchCord28(dcOsc3Tune, 0, osc3TuneMixer, 1);
AudioConnection patchCord29(ampModWheelOsc, 0, mainTuneMixer, 3);
AudioConnection patchCord30(ampModWheelFilter, 0, filterMixer, 0);
AudioConnection patchCord31(osc3TuneMixer, 0, osc3Waveform, 0);
AudioConnection patchCord32(osc2TuneMixer, 0, osc2Waveform, 0);
AudioConnection patchCord33(dcPulse, 0, osc1Waveform, 1);
AudioConnection patchCord34(dcPulse, 0, osc2Waveform, 1);
AudioConnection patchCord35(dcPulse, 0, osc3Waveform, 1);
AudioConnection patchCord36(osc1Waveform, 0, oscMixer, 0);
AudioConnection patchCord37(osc2Waveform, 0, oscMixer, 1);
AudioConnection patchCord38(osc3Waveform, 0, oscMixer, 2);
AudioConnection patchCord39(osc3Waveform, ampOsc3Mod);
AudioConnection patchCord40(oscMixer, 0, globalMixer, 0);
AudioConnection patchCord41(globalMixer, ampPreFilter);
AudioConnection patchCord42(ampPreFilter, 0, vcf, 0);
AudioConnection patchCord43(ampPreFilter, printPreFilter);
AudioConnection patchCord44(filterMixer, 0, vcf, 1);
AudioConnection patchCord45(vcf, 0, bandMixer, 0);
AudioConnection patchCord46(vcf, 1, bandMixer, 1);
AudioConnection patchCord47(vcf, 2, bandMixer, 2);
AudioConnection patchCord48(bandMixer, mainEnvelope);
AudioConnection patchCord49(bandMixer, 0, globalMixer, 1);
AudioConnection patchCord50(mainEnvelope, bitCrushOutput);
AudioConnection patchCord51(bitCrushOutput, masterVolume);
AudioConnection patchCord52(masterVolume, 0, i2s, 0);
AudioConnection patchCord53(masterVolume, 0, i2s, 1);
// GUItool: end automatically generated code

@ -36,3 +36,9 @@ filter mode
The upper half mixes band pass with high pass. Low pass cut.
Band stop The low and high pass are mixed continuously, band pass cut, resulting in a band stop
on middle position.
pitchbend range
Any interval regarding the note beeing played can be choosen for the pitchbend.
modulation range
The modulation range can be changed independently for the oscillators and for the filter.

@ -113,6 +113,8 @@ const uint16_t EE_TRIGGER_ADD = 4;
const uint16_t EE_DETUNE_ADD = 5;
const uint16_t EE_FILTER_MODE = 6;
const uint16_t EE_PITCH_BEND_RANGE = 7;
const uint16_t EE_MOD_WHEEL_OSC_RANGE = 8;
const uint16_t EE_MOD_WHEEL_FILTER_RANGE = 9;
const uint16_t EE_DETUNE_TABLE_ADD = 20;
// variables
@ -141,6 +143,8 @@ float egDecay = 0;
int16_t filterBandValue = 0;
uint8_t pitchBendRange = 3;
uint8_t modWheelOscRange = 3;
uint8_t modWheelFilterRange = 12;
// Waveforms
uint8_t waveforms[6] = {WAVEFORM_SINE, WAVEFORM_TRIANGLE, WAVEFORM_SAWTOOTH,
@ -168,6 +172,8 @@ enum function_t{
FUNCTION_MIDI_IN_CHANNEL,
FUNCTION_MIDI_OUT_CHANNEL,
FUNCTION_PITCH_BEND_RANGE,
FUNCTION_MOD_WHEEL_OSC_RANGE,
FUNCTION_MOD_WHEEL_FILTER_RANGE,
};
function_t currentFunction = FUNCTION_KEYBOARD_MODE;
@ -249,7 +255,8 @@ void setup() {
EEPROM.get(EE_TRIGGER_ADD, noteRetrigger);
EEPROM.get(EE_DETUNE_ADD, detune);
EEPROM.get(EE_FILTER_MODE, filterMode);
EEPROM.get(EE_PITCH_BEND_RANGE, pitchBendRange);
EEPROM.get(EE_MOD_WHEEL_OSC_RANGE, modWheelOscRange);
EEPROM.get(EE_MOD_WHEEL_FILTER_RANGE, modWheelFilterRange);
uint16_t address = EE_DETUNE_TABLE_ADD;
for(uint16_t i = 0; i < 128; ++i){
@ -281,7 +288,8 @@ void setup() {
// amp
ampPitchBend.gain(pitchBendRange * HALFTONE_TO_DC * 2);
ampModWheel.gain(0.0);
ampModWheelOsc.gain(0.0);
ampModWheelFilter.gain(0.0);
ampPreFilter.gain(0.55);
ampModEg.gain(0.1);
ampOsc3Mod.gain(1);
@ -828,8 +836,9 @@ void handleControlChange(uint8_t channel, uint8_t command, uint8_t value){
break;
case CC_MOD_WHEEL_LSB:
// CC_33
// ampModWheel.gain(((float)longValue - 1 - MOD_WHEEL_MIN) / 12 / MOD_WHEEL_COURSE);
ampModWheel.gain(((float)longValue) / 12 / 16384);
// ampModWheelOsc.gain(((float)longValue - 1 - MOD_WHEEL_MIN) / 12 / MOD_WHEEL_COURSE);
ampModWheelOsc.gain(((float)(longValue * modWheelOscRange)) / MAX_OCTAVE / 12 / 16384);
ampModWheelFilter.gain(((float)(longValue * modWheelFilterRange)) / FILTER_MAX_OCTAVE / 12 / 16384);
// Mod wheel goes from 360 to 666.
/*
Serial.print("mod wheel : ");
@ -1247,14 +1256,14 @@ void handleKeyboardFunction(uint8_t key, bool active){
break;
case FUNCTION_MIDI_IN_CHANNEL:
// change (usb) midi in channel
if(key > 16)return;
if(key > 15)return;
midiInChannel = key + 1;
//MIDI.begin(midiInChannel);
EEPROM.put(EE_MIDI_IN_CH_ADD, midiInChannel);
break;
case FUNCTION_MIDI_OUT_CHANNEL:
// change (usb) midi out channel
if(key > 16)return;
if(key > 15)return;
midiOutChannel = key + 1;
//MIDI.begin(midiInChannel);
EEPROM.put(EE_MIDI_OUT_CH_ADD, midiOutChannel);
@ -1266,6 +1275,21 @@ void handleKeyboardFunction(uint8_t key, bool active){
ampPitchBend.gain(pitchBendRange * HALFTONE_TO_DC * 2);
EEPROM.put(EE_PITCH_BEND_RANGE, pitchBendRange);
break;
case FUNCTION_MOD_WHEEL_OSC_RANGE:
// Change mod wheel range for osc
if(key == 0){
currentFunction = FUNCTION_MOD_WHEEL_FILTER_RANGE;
break;
}
modWheelOscRange = key;
EEPROM.put(EE_MOD_WHEEL_OSC_RANGE, modWheelOscRange);
break;
case FUNCTION_MOD_WHEEL_FILTER_RANGE:
// Change mod wheel range for osc
if(key == 0) break;
modWheelFilterRange = key;
EEPROM.put(EE_MOD_WHEEL_FILTER_RANGE, modWheelFilterRange);
break;
default:
break;
}
@ -1278,6 +1302,9 @@ void handlePitchBendFunction(){
void handleCCFunction(uint8_t command, uint8_t value){
switch(command){
case CC_MOD_WHEEL:
currentFunction = FUNCTION_MOD_WHEEL_OSC_RANGE;
break;
case CC_FUNCTION:
// CC_113
if(value < 64){

Loading…
Cancel
Save