Skip to content

Commit ac866fa

Browse files
committed
0.5 Add auto split mode
1 parent 16d8f42 commit ac866fa

24 files changed

+407
-104
lines changed

.github/workflows/build.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ jobs:
3939
- os: macos-latest
4040
TARGET: macos
4141
CMD_BUILD: >
42-
pyinstaller -F microtonal-seaboard.spec &&
42+
pyinstaller microtonal-seaboard.spec &&
4343
cd dist/ &&
4444
zip -r9 microtonal-seaboard-macos.zip ../mappings microtonal-seaboard
4545
OUT_FILE_NAME: microtonal-seaboard-macos.zip
4646
ASSET_MIME: application/zip
4747
- os: windows-latest
4848
TARGET: windows
4949
CMD_BUILD: >
50-
pyinstaller -F microtonal-seaboard.spec &&
50+
pyinstaller microtonal-seaboard.spec &&
5151
cd dist/ &&
5252
tar -a -c -f microtonal-seaboard-windows.zip ../mappings microtonal-seaboard.exe
5353
OUT_FILE_NAME: microtonal-seaboard-windows.zip

README.md

+14-37
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ notes across different MIDI channels to achieve a larger range using
147147
multiple VST instances or using a VST's internal multi-channel mapping
148148
ability.
149149

150-
Pianoteq 6+ natively supports multi-channel midi inputs to obtain a larger range.
151-
[Follow these steps instead for Pianoteq](#microtuning-on-pianoteq).
150+
Pianoteq 6+ natively supports multi-channel midi inputs to obtain a larger range for big EDOs.
151+
[**Follow these simpler instructions instead for pianoteq.**](#microtuning-on-pianoteq).
152152

153153
Otherwise, to get more range out of microtunable synths,
154154
you can open multiple instances of them and set them at different
@@ -194,48 +194,25 @@ Pianoteq offers [multi-channel keyboard mappings](https://forum.modartt.com/view
194194
which bypasses the need for opening multiple instances of pianoteq in order to get the
195195
full range.
196196

197-
There is little official documentation on this feature, so here's how it works:
198-
- Under Pianoteq's microtuning screen, there's a button on the top right
199-
to change the keyboard mapping. Click on it and you will see an option
200-
titled 'Extended layout for up to 16*128 notes'
197+
To make use of this in the seaboard mapper:
198+
199+
1. enter `autosplit` in the console to turn auto split mode on
200+
201+
2. Under Pianoteq's microtuning screen, there's a button on the top right
202+
to change the **keyboard mapping**. Click on it and you will see an option
203+
titled '**Extended layout for up to 16*128 notes**'. Open the drop down and select **MIDI channel 5**
201204

202205
![img.png](imgs/extended-layout-pianoteq.png)
203206

204-
- If you toggle the 'Multi-channel MIDI layout' option and activate it,
205-
it will cause the notes received on each subsequent MIDI channel
207+
- This will cause the notes received on each subsequent MIDI channel
206208
to sound one octave higher than the previous MIDI channel.
207-
- The Main MIDI Channel setting determines the MIDI channel that will not
208-
be transposed at all.
209-
- E.g. if MIDI channel 4 is selected as the main channel,
210-
channel 3 will be transposed one octave below, channel 5 will be transposed
211-
an octave up, etc...
212-
- Note that if the scala tuning file imported denotes a non-octave tuning
209+
- The checked midi channel (5) denotes the MIDI channel that will not have any octave/equave transposition at all.
210+
- E.g. if MIDI channel 5 is selected as the main channel,
211+
Notes played on channel 4 will sound one octave below what's played, notes played on channel 6 will sound one octave up, etc...
212+
- Note that if the scala tuning file imported on Pianoteq denotes a non-octave tuning
213213
(e.g. Bohlen-pierce/Wendy Carlos's alpha/beta), then Pianoteq will
214214
transpose according to the tuning system's [period](https://en.xen.wiki/w/Periods_and_generators).
215215

216-
217-
Here's how to obtain the full 8 octave range on the piano in
218-
the default 31 edo mapping using Pianoteq and the seaboard mapper:
219-
220-
1. Turn on Multi=channel MIDI layout mode
221-
(Microtuning > Keyboard Mapping > Extended layout for up to... >
222-
Multi-channel MIDI layout)
223-
2. Set Main MIDI channel to channel 4. This opens up 3 more octaves below.
224-
3. Enter the `split` command in the seaboard mapping program
225-
4. Input the following (see above section for
226-
explanation):
227-
1. `C2 C3 C4 C5 C6 C7`
228-
2. `93`
229-
3. `62`
230-
4. `31`
231-
5. `0`
232-
6. `-31`
233-
7. `-62`
234-
8. `-93`
235-
5. Enter the [`save` command](#save) so you don't have to do this every time.
236-
237-
Now you can play all the way down to A0 and up to C8 and beyond!
238-
239216
## Other Settings/Commands
240217

241218
### Save

__pycache__/configs.cpython-39.pyc

1.89 KB
Binary file not shown.

__pycache__/convert.cpython-39.pyc

3.63 KB
Binary file not shown.

__pycache__/handler.cpython-39.pyc

5.61 KB
Binary file not shown.

__pycache__/keytracker.cpython-39.pyc

4.97 KB
Binary file not shown.

__pycache__/main.cpython-39.pyc

6.24 KB
Binary file not shown.

__pycache__/mapping.cpython-39.pyc

3.75 KB
Binary file not shown.

__pycache__/split.cpython-39.pyc

1.51 KB
Binary file not shown.

build.bat

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
py -m pip install --upgrade pip
22
py -m pip install --user virtualenv
3-
py -m venv venv
4-
.\venv\Scripts\activate
3+
py -m venv .venv
4+
.\.venv\Scripts\activate
55
pip install --upgrade setuptools
66
pip install -r requirements.txt
7-
pyinstaller -F microtonal-seaboard.spec &&^
7+
pyinstaller microtonal-seaboard.spec &&^
88
cd dist/ &&^
99
tar -a -c -f microtonal-seaboard-windows.zip ../mappings microtonal-seaboard.exe
1010
deactivate

build.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
python3 -m pip install --user --upgrade pip
22
python3 -m pip install --user virtualenv
3-
python3 -m venv venv
4-
source venv/bin/activate
3+
python3 -m venv .venv
4+
source .venv/bin/activate
55
python3 -m pip install -r requirements.txt
66
pyinstaller -F ./microtonal-seaboard.spec &&\
77
cd dist/ &&\

configs.py

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
from enum import Enum
3+
from typing import Optional
34

45
import dill
56

@@ -16,10 +17,20 @@ class SlideMode(Enum):
1617

1718

1819
class CONFIGS:
20+
'''
21+
Static Singleton class for storing global configuration data.
22+
'''
1923
MPE_MODE = True
2024
SLIDE_MODE = SlideMode.RELATIVE
2125
SLIDE_FIXED_N = 64
2226
SPLITS = SplitData()
27+
AUTO_SPLIT: Optional[SplitData] = None
28+
'''
29+
If true, MIDI mode will output each octave in its own channel, and SPLITS will be ignored.
30+
The interval between C4 and C5 in the mapping will be used to determine octave offset in edosteps.
31+
This is useful for Pianoteq which allows multi-channel mode where channel N+1 is pitched
32+
one octave higher than channel N. (useful for very large edos)
33+
'''
2334
PITCH_BEND_RANGE = 24
2435
MAPPING: Mapping = None
2536
TOGGLE_SUSTAIN = False
@@ -42,6 +53,7 @@ def read_configs() -> bool:
4253
CONFIGS.SLIDE_MODE = c['SLIDE_MODE']
4354
CONFIGS.SLIDE_FIXED_N = c['SLIDE_FIXED_N']
4455
CONFIGS.SPLITS = c['SPLITS']
56+
CONFIGS.AUTO_SPLIT = c['AUTO_SPLIT']
4557
CONFIGS.PITCH_BEND_RANGE = c['PITCH_BEND_RANGE']
4658
CONFIGS.MAPPING = c['MAPPING']
4759
CONFIGS.TOGGLE_SUSTAIN = c['TOGGLE_SUSTAIN']
@@ -62,6 +74,7 @@ def save_configs():
6274
'SLIDE_MODE': CONFIGS.SLIDE_MODE,
6375
'SLIDE_FIXED_N': CONFIGS.SLIDE_FIXED_N,
6476
'SPLITS': CONFIGS.SPLITS,
77+
'AUTO_SPLIT': CONFIGS.AUTO_SPLIT,
6578
'PITCH_BEND_RANGE': CONFIGS.PITCH_BEND_RANGE,
6679
'MAPPING': CONFIGS.MAPPING,
6780
'TOGGLE_SUSTAIN': CONFIGS.TOGGLE_SUSTAIN

convert.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from typing import Tuple
2+
3+
14
__NOTENAMES = {
25
0: 'C',
36
1: 'C#',
@@ -84,7 +87,7 @@ def raw_pitch_msg_to_pitch_bend(ls7, ms7):
8487
return 2**7 * ms7 + ls7
8588

8689

87-
def pitch_bend_to_raw_pitch_msg(pb) -> (int, int):
90+
def pitch_bend_to_raw_pitch_msg(pb) -> Tuple[int, int]:
8891
"""
8992
:param pb: pitch bend amount (will be bounded to 0-16383 if it exceeds range)
9093
:return: (lsb, msb)

handler.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ def tune_and_send_note(note, vel, cc74):
4747
# otherwise strobe 2 complete disregards it
4848
self.send_pitch_bend(channel, pitchbend)
4949
else:
50-
send_ch, send_note_offset = CONFIGS.SPLITS.get_split_range(note)
50+
if CONFIGS.AUTO_SPLIT is not None:
51+
send_ch, send_note_offset = CONFIGS.AUTO_SPLIT.get_split_range(note)
52+
else:
53+
send_ch, send_note_offset = CONFIGS.SPLITS.get_split_range(note)
54+
5155
send_note = edosteps_from_a4 + MIDI_NOTE_A4 + send_note_offset
5256

5357
if 0 > send_note > 127:

main.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def intable(s):
138138

139139

140140
if __name__ == '__main__':
141-
print('microtonal seaboard retuner v0.4.5d')
141+
print('microtonal seaboard retuner v0.5')
142142

143143
has_read_configs = configs.read_configs()
144144

@@ -179,10 +179,11 @@ def intable(s):
179179
abs: emulate absolute slide mode
180180
bip: (default) emulate bipolar mode
181181
split set split points (for midi mode)
182+
autosplit toggle auto-split for Pianoteq (for midi mode)
182183
map select new .sbmap file
183184
pb change pitch bend amount
184185
sus toggles sustain pedal polarity
185-
save saves all current settings
186+
save saves all current settings (not automatic)
186187
exit exit the program""")
187188

188189
while True:
@@ -239,6 +240,12 @@ def intable(s):
239240
pass
240241
elif s == 'split':
241242
select_splits()
243+
elif s == 'autosplit':
244+
if CONFIGS.AUTO_SPLIT is not None:
245+
CONFIGS.AUTO_SPLIT = None
246+
else:
247+
CONFIGS.AUTO_SPLIT = SplitData(CONFIGS.MAPPING)
248+
print(f'Auto Split: {"on" if CONFIGS.AUTO_SPLIT is not None else "off"}')
242249
elif s == 'map':
243250
select_mapping()
244251
elif s == 'pb':

mapping.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ def __init__(self, sbm_file_path):
3434
"""
3535

3636
self.load_mapping(sbm_file_path)
37+
38+
39+
# Add heuristic for how many edosteps per octave (assumes octaves are mapped all the same on the seaboard)
40+
# Calculate step offset difference between lowest split of C4 to C5 to get EDO
41+
self.edo = self.__keys[convert.notename_to_midinum('c5')][0][2] - self.__keys[convert.notename_to_midinum('c4')][0][2]
42+
'''
43+
A heuristic guess on how many steps correspond to an octave. Used for auto splitting in MIDI mode.
44+
'''
3745

3846
def load_mapping(self, sbm_file_path):
3947
self.__keys = {}
@@ -70,7 +78,7 @@ def load_mapping(self, sbm_file_path):
7078

7179
previous_cc74 = 0
7280

73-
split_points = []
81+
vert_split_points = []
7482
last_split_point = 0
7583
for cc74, cents, steps in segments:
7684
try:
@@ -96,13 +104,13 @@ def load_mapping(self, sbm_file_path):
96104
except Exception:
97105
raise MapParsingError(f'line {linecount}: invalid steps value: {steps}')
98106

99-
split_points.append((cc74, cents, steps))
107+
vert_split_points.append((cc74, cents, steps))
100108
last_split_point = cc74
101109

102110
if last_split_point != 128:
103111
raise MapParsingError(f'line {linecount}: last cc74 split point of a key must be 128')
104112

105-
self.__keys[midinote] = split_points
113+
self.__keys[midinote] = vert_split_points
106114

107115
print('Mapping loaded!')
108116

Binary file not shown.

0 commit comments

Comments
 (0)