Skip to content

Commit

Permalink
Make MIDI CC mapping configurable
Browse files Browse the repository at this point in the history
The MIDI CC mapping can be configured with the file midi-cc.txt on the
SD card now. The file format should be self explanatory. A default
config file is the config/ directory.

Issue #12
  • Loading branch information
rsta2 committed Apr 2, 2021
1 parent e889ce5 commit c39c980
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 24 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Furthermore you need the Raspberry Pi firmware. You can get it as follows:

You have to copy the three files *bootcode.bin*, *start.elf* and *fixup.dat* from the *circle/boot/* subdirectory to the FAT partition on the SD card. The Raspberry Pi 4 requires different firmware files. Please read the file *circle/boot/README* for details!

Finally you have to copy the configuration files *cmdline.txt*, *patchN.txt* (example patches) and *velocity-???.txt* (keyboard velocity curve) from the *config/* subdirectory to the SD card. The appropriate velocity curve file has to be renamed to *velocity.txt* to be used. You can optionally create a subdirectory */patches* and copy the example patches there, if you do not want to have them in the root directory of your SD card.
Finally you have to copy the configuration files *cmdline.txt*, *patchN.txt* (example patches), *velocity-???.txt* (keyboard velocity curve) and *midi-cc.txt* (MIDI CC mapping) from the *config/* subdirectory to the SD card. The appropriate velocity curve file has to be renamed to *velocity.txt* to be used. You can optionally create a subdirectory */patches* and copy the example patches there, if you do not want to have them in the root directory of your SD card.

Put the SD card into the card reader of your Raspberry Pi.

Expand Down Expand Up @@ -129,7 +129,7 @@ One patch of MiniSynth Pi has the following parameters:
| Section | Module | Parameter | Unit | Range | Default | Description | MIDI CC |
| ---------- | -------- | --------- | ---- | --------- | ------- | -------------------- | ------- |
| OSCILLATOR | VCO | Wave | | | Square | Waveform (*) | |
| OSCILLATOR | VCO (2) | Detune | % | 0-200 | 100 | Semitone -/+ | |
| OSCILLATOR | VCO (2) | Detune | % | 0-200 | 100 | Semitone -/+ | 94 (**) |
| OSCILLATOR | LFO | Wave | | | Sine | Waveform (*) | |
| OSCILLATOR | LFO | Rate | Hz | 1-35 | 20 | Modulation frequency | |
| OSCILLATOR | LFO | Volume | % | 0-100 | 0 | Modulation volume | |
Expand All @@ -151,10 +151,12 @@ One patch of MiniSynth Pi has the following parameters:
| AMPLIFIER | ENVELOPE | Sustain | % | 0-100 | 100 | Sustain level | |
| AMPLIFIER | ENVELOPE | Release | ms | 0-5000 | 100 | Release delay | |
| EFFECTS | REVERB | Decay | % | 0-50 | 20 | Rate of decay | |
| EFFECTS | REVERB | Volume | % | 0-30 | 0 | Wet/dry ratio | |
| EFFECTS | REVERB | Volume | % | 0-30 | 0 | Wet/dry ratio | 91 |

(*) Waveform can be: Sine, Square, Sawtooth, Triangle, Pulse 12.5%, Pulse 25% or Noise (Noise not for LFO)

(\*\*) The MIDI CC mapping can be modified in the file *midi-cc.txt*. This is the default mapping.

MiniSynth Pi provides two VCOs, one runs at the pitch frequency, the other at pitch frequency detuned by a configurable value (max. one semitone - or +, default 100% = Detune off).

MiniSynth Pi allows to use a specific keyboard velocity curve, which fits best to your keyboard and your playing style. It has to be provided in the file *velocity.txt* on the SD card. The default velocity curve is linear. Have a look into the example files in the *config/* subdirectory. If you want to use one of these files, it has to be renamed to *velocity.txt* on the SD card. It should be easy to modify one example file to adjust the velocity curve to your own needs.
Expand Down
27 changes: 27 additions & 0 deletions config/midi-cc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# MIDI CC Mapping
#
LFOVCOWaveform=
LFOVCOFrequency=
VCOWaveform=
VCOModulationVolume=
VCODetune=94
LFOVCFWaveform=
LFOVCFFrequency=
VCFCutoffFrequency=74
VCFResonance=71
EGVCFAttack=
EGVCFDecay=
EGVCFSustain=
EGVCFRelease=
VCFModulationVolume=
LFOVCAWaveform=
LFOVCAFrequency=
EGVCAAttack=
EGVCADecay=
EGVCASustain=
EGVCARelease=
VCAModulationVolume=
ReverbDecay=
ReverbVolume=91
SynthVolume=7
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CIRCLEHOME ?= ../circle
OBJS = main.o kernel.o minisynth.o mididevice.o \
midikeyboard.o pckeyboard.o serialmididevice.o voicemanager.o \
voice.o oscillator.o mixer.o filter.o amplifier.o envelopegenerator.o \
reverbmodule.o synthconfig.o patch.o parameter.o velocitycurve.o \
reverbmodule.o synthconfig.o patch.o parameter.o velocitycurve.o midiccmap.o \
mainwindow.o guiparameter.o guistringproperty.o

LIBS = $(CIRCLEHOME)/addon/lvgl/liblvgl.a \
Expand Down
67 changes: 67 additions & 0 deletions src/midiccmap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// midiccmap.h
//
// MiniSynth Pi - A virtual analogue synthesizer for Raspberry Pi
// Copyright (C) 2021 R. Stange <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include "midiccmap.h"
#include "config.h"
#include <assert.h>

CMIDICCMap::CMIDICCMap (FATFS *pFileSystem)
: m_Properties (DRIVE "/midi-cc.txt", pFileSystem)
{
for (unsigned i = MIDICC_MIN; i <= MIDICC_MAX; i++)
{
m_Map[i] = SynthParameterUnknown;
}
}

CMIDICCMap::~CMIDICCMap (void)
{
}

boolean CMIDICCMap::Load (void)
{
boolean bResult = m_Properties.Load ();
if (!bResult)
{
m_Properties.RemoveAll ();
}

for (unsigned i = 0; i < SynthParameterUnknown; i++)
{
unsigned nMIDICC =
m_Properties.GetNumber (CPatch::GetParameterName ((TSynthParameter) i), 0);

if (MIDICC_MIN <= nMIDICC && nMIDICC <= MIDICC_MAX)
{
m_Map[nMIDICC] = (TSynthParameter) i;
}
}

return bResult;
}

TSynthParameter CMIDICCMap::Map (u8 ucMIDICC) const
{
if (MIDICC_MIN <= ucMIDICC && ucMIDICC <= MIDICC_MAX)
{
return m_Map[ucMIDICC];
}

return SynthParameterUnknown;
}
49 changes: 49 additions & 0 deletions src/midiccmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// midiccmap.h
//
// Maps MIDI CC numbers to TSynthParameter
//
// MiniSynth Pi - A virtual analogue synthesizer for Raspberry Pi
// Copyright (C) 2021 R. Stange <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef _midiccmap_h
#define _midiccmap_h

#include <fatfs/ff.h>
#include <circle/types.h>
#include <Properties/propertiesfatfsfile.h>
#include "patch.h"

#define MIDICC_MIN 1
#define MIDICC_MAX 127

class CMIDICCMap
{
public:
CMIDICCMap (FATFS *pFileSystem);
~CMIDICCMap (void);

boolean Load (void);

TSynthParameter Map (u8 ucMIDICC) const;

private:
CPropertiesFatFsFile m_Properties;

TSynthParameter m_Map[MIDICC_MAX+1];
};

#endif
14 changes: 4 additions & 10 deletions src/minisynth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// minisynth.cpp
//
// MiniSynth Pi - A virtual analogue synthesizer for Raspberry Pi
// Copyright (C) 2017-2020 R. Stange <[email protected]>
// Copyright (C) 2017-2021 R. Stange <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -133,19 +133,13 @@ boolean CMiniSynthesizer::ConfigUpdated (void)

void CMiniSynthesizer::ControlChange (u8 ucFunction, u8 ucValue)
{
TSynthParameter Parameter;

switch (ucFunction)
assert (m_pConfig != 0);
TSynthParameter Parameter = m_pConfig->MapMIDICC (ucFunction);
if (Parameter >= SynthParameterUnknown)
{
case 7: Parameter = SynthVolume; break;
case 71: Parameter = VCFResonance; break;
case 74: Parameter = VCFCutoffFrequency; break;

default:
return;
}

assert (m_pConfig != 0);
CPatch *pPatch = m_pConfig->GetActivePatch ();
assert (pPatch != 0);

Expand Down
19 changes: 14 additions & 5 deletions src/patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// patch.cpp
//
// MiniSynth Pi - A virtual analogue synthesizer for Raspberry Pi
// Copyright (C) 2017-2020 R. Stange <[email protected]>
// Copyright (C) 2017-2021 R. Stange <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand All @@ -21,7 +21,7 @@
#include "oscillator.h"
#include <assert.h>

static struct
static const struct
{
const char *pName;
TParameterType Type;
Expand Down Expand Up @@ -74,7 +74,7 @@ ParameterList[] = // must match TSynthParameter
{"SynthVolume", ParameterPercent, 0, 100, 10, 50, "Volume"}
};

static struct
static const struct
{
const char *pName;
unsigned nMaxLength;
Expand Down Expand Up @@ -188,9 +188,12 @@ void CPatch::SetParameter (TSynthParameter Parameter, unsigned nValue)
void CPatch::SetMIDIParameter (TSynthParameter Parameter, u8 ucValue)
{
assert (Parameter < SynthParameterUnknown);
assert (ParameterList[Parameter].Type == ParameterPercent);

unsigned nValue = (ucValue*100 + 63) / 127;
unsigned nValue = ucValue;
nValue *= ParameterList[Parameter].nMaximum - ParameterList[Parameter].nMinimum;
nValue = (nValue + 63) / 127;
nValue += ParameterList[Parameter].nMinimum;

nValue = (nValue + ParameterList[Parameter].nStep/2)
/ ParameterList[Parameter].nStep
* ParameterList[Parameter].nStep;
Expand Down Expand Up @@ -262,3 +265,9 @@ const char *CPatch::GetPropertyHelp (TPatchProperty Property)
assert (Property < PatchPropertyUnknown);
return PropertyList[Property].pHelp;
}

const char *CPatch::GetParameterName (TSynthParameter Parameter)
{
assert (Parameter < SynthParameterUnknown);
return ParameterList[Parameter].pName;
}
4 changes: 3 additions & 1 deletion src/patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Container for patch settings, loadable from properties file
//
// MiniSynth Pi - A virtual analogue synthesizer for Raspberry Pi
// Copyright (C) 2017-2020 R. Stange <[email protected]>
// Copyright (C) 2017-2021 R. Stange <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -108,6 +108,8 @@ class CPatch
static boolean GetPropertyUppercase (TPatchProperty Property);
static const char *GetPropertyHelp (TPatchProperty Property);

static const char *GetParameterName (TSynthParameter Parameter);

private:
CPropertiesFatFsFile m_Properties;

Expand Down
16 changes: 13 additions & 3 deletions src/synthconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// synthconfig.cpp
//
// MiniSynth Pi - A virtual analogue synthesizer for Raspberry Pi
// Copyright (C) 2017-2020 R. Stange <[email protected]>
// Copyright (C) 2017-2021 R. Stange <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand All @@ -25,7 +25,8 @@
CSynthConfig::CSynthConfig (FATFS *pFileSystem)
: m_pFileSystem (pFileSystem),
m_nActivePatch (0),
m_VelocityCurve (pFileSystem)
m_VelocityCurve (pFileSystem),
m_MIDICCMap (pFileSystem)
{
for (unsigned i = 0; i < PATCHES; i++)
{
Expand Down Expand Up @@ -62,7 +63,11 @@ boolean CSynthConfig::Load (void)
assert (m_pPatch[i] != 0);
}

return m_VelocityCurve.Load ();
boolean bOK = m_VelocityCurve.Load ();

bOK = m_MIDICCMap.Load () && bOK;

return bOK;
}

unsigned CSynthConfig::GetActivePatchNumber (void) const
Expand Down Expand Up @@ -94,3 +99,8 @@ u8 CSynthConfig::MapVelocity (u8 ucVelocity) const
{
return m_VelocityCurve.MapVelocity (ucVelocity);
}

TSynthParameter CSynthConfig::MapMIDICC (u8 ucMIDICC) const
{
return m_MIDICCMap.Map (ucMIDICC);
}
5 changes: 4 additions & 1 deletion src/synthconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Container for global configuration and all patches
//
// MiniSynth Pi - A virtual analogue synthesizer for Raspberry Pi
// Copyright (C) 2017-2020 R. Stange <[email protected]>
// Copyright (C) 2017-2021 R. Stange <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand All @@ -25,6 +25,7 @@
#include <fatfs/ff.h>
#include "patch.h"
#include "velocitycurve.h"
#include "midiccmap.h"
#include "config.h"

class CSynthConfig
Expand All @@ -47,6 +48,7 @@ class CSynthConfig
CPatch *GetPatch (unsigned nPatch);

u8 MapVelocity (u8 ucVelocity) const;
TSynthParameter MapMIDICC (u8 ucMIDICC) const;

private:
FATFS *m_pFileSystem;
Expand All @@ -55,6 +57,7 @@ class CSynthConfig
unsigned m_nActivePatch;

CVelocityCurve m_VelocityCurve;
CMIDICCMap m_MIDICCMap;
};

#endif

0 comments on commit c39c980

Please sign in to comment.