Tenori-On : Project Introduction and Goals
The Yamaha Tenori-on, designed in collaboration between the performance artist Toshio Iwai and Yamaha, is a wonderful piece of hardware.
However, Yamaha seem to have given up supporting the hardware version in preference to the (iOS only 😞 ) TNR-i and TNR-e. For the hardware (TNR-w, TNR-o), the v2.10 firmware was released back in 2011 and nothing has happened since.
The software (firmware) running on it has some issues. It isn’t well optimised (I mainly blame the Toshiba TLCS-900 compiler for that) which is an issue when under load. Also, to use the device fully as part of a live setup, requires some extensions/modifications to play nice, if it is going to be used as a midi controller. Fortunately, it is possible to safely update the “application” software, without touching the boot code that actually loads/saves the application software, so it is possible to perform test updates without bricking the device (it is always possible to go back to the stock application software).
NB : Updating the boot software may brick your TNR! Don’t do it!
This project is therefore an attempt to patch the software (starting with v2.1 as a base) to improve/modify the functionality. A major rewrite is not really possible : although there is lots of information about the CPU, quite a lot of the action occurs in the SWL-01 chip, on which I can find no information, so the “API” to the SWL-01 in the code has to remain. As a result this is really just patching the code.
This page acts to track the goals, provide some context, and try to say what I’m doing.
The mods are divided into:
- Minor : Where a small change could have a big effect
- Major : Where significant rewrites are needed
Summary
Title | Class | Status |
---|---|---|
Quiet Mode | Minor | Complete : Midi quiet |
Block change | Minor | Complete : Block Change |
Code optimisation | Minor | Ongoing |
Assignable Midi channels | Major | Complete : Per layer midi channel |
Per-layer scales | Major | Complete : Per layer scales |
Wider range | Major | Complete : Splits |
Arpeggiator | Major | Partial : Arp-4 |
Controller output | Major | Complete : Control Change |
Sequencer | Major | Partial; several subgoals compete, i.e. ScoreX and Block change meta controller |
Velocity control | Major | Partial : Splits |
Sound length control | Minor | Partial : Splits |
Randomizer | Major | Partial; Probablistic splits |
Recorder | Major | Partial : Recorder |
Usable Clock | Minor | Not started |
Save Layer | Minor | Not started |
Minor : Quiet mode
Problem : Sysex messages are sent whenever keys are pressed.
In normal mode, pressing a key emits sysex codes. This is unnecessary traffic (and buffer handling in the TNR), and in the worst case, seems to confuse other bits of kit.
Solution : Include a menu setting for not sending SysEx codes when in normal mode, but leave remote mode alone, since that is how one TNR controls another.
Status : Completed in A009. See Midi quiet
Minor : Block change in normal mode
Problem : TNR only responds to block change requests in remote mode.
It would be good to be able to change the block playing from a different midi controller, while in normal mode. In my case, to allow a foot controller to change the block number, so that swaps between verses and chorus can be done with the feet rather than with the hands. This is of course possible in remote mode, by sending sysex messages (providing that you have a foot controller that can send arbitrary sysex messages, which the Behringer FCB1010 can’t but the Roland FC-300 can). Unforunately, in remote mode, no note on/note off messages are produced by the TNR, defeating the point of its use as a controller.
Solution : F3 “Song Select” can be used to change the block, whether in remote mode or not. The song select command can also be set to a CC message.
Status : Completed in A010. See Block change
Minor : Code optimisation
Problem : TNR code is not well optimised.
As far as I can tell from the assembler, the code produced by the TLCS-900 compiler is very poorly optimised. This can range from the trivial (there are several occasions where unnecessary jumps and stack pushes are done, probably coming from variable type casting) to the complex (e.g. searching an instrument array every time a note is played). The compiler also looks like it eschewed some TLCS-900/H1 commands (e.g. EX) in favour of long winded work-arounds). The tenori-on is not a high power machine, so the more that can be done to optimise the code, the better.
Solution : Remove redundant code. Optimise where possible.
Status : Ongoing. Code optimisation is done where it looks like it will save significant cycles.
Major : Assignable Midi channels
Problem : Layers do not have assignable midi channels.
Layer 1 is Midi channel 1, Layer 2 is Midi channel 2, etc. If both layer 1 & 2 were set to the same midi channel, very interesting effects could be generated.
Solution : In fact, in the code, there is an array interpreted as midi-channel-per-layer. However I haven’t yet sorted out how to provide an easy user interface, nor how to save/load the data from a layer or song. Layers can certainly only output on one channel (adding output on multiple channels is too difficult). An approach where the tenori-on main grid can be used to do the map - e.g. the Y axis is the layer, and the X-axis is the channel (like the volume sliders) would be good.
Status : Completed in A008. See Per layer midi channel
Major : Assignable scales
Problem : Layers do not have assignable scales.
All layers work on the same scale (Dorian, Ionian, Chromatic, etc.). This is limiting
Solution : Per layer scales are implemented in A006 and improved in A021. A few extra preset scales have been added (Harmonic Minor, Melodic Minor, Bebop Dominant, 6-note Blues, 9-note Blues, Whole Tone), and - in addition to the existing “User” scale - a further 16 user definable scales have been added, allowing each layer to have a unique scale. These are all saved/loaded as settings, similar to the existing “User” scale. Using “Master scale” works like “Master loop point” - at the moment it is set (via OK), all scales of all layers will be overwritten to this one.
Complete : Partial implementation completed in A006, completed in A021 See Per layer scales
Major : Wider Playable range
Problem : If using a chromatic scale, the range is limited to just over an octave. This is quite limiting.
Solution 1 : In score mode, at least, one could imaging using the rotary dial to scroll up and down, so that the enterable range is larger. (e.g. +1/-1 scale extent). Since this is lots more notes in the scale, this would require the scale definitions to be extended to cover more than 16 notes.
Solution 2 : A split approach where some of the notes are used to indicate +1 oct, 0 oct, -1 oct etc. This is the approach that has been implemented.
Status : Completed in A015. See Splits
Major : Arpeggiator
Problem : I want an arpeggiator.
In particular, to allow singificant rythmic infill without “using up” so much of a blocks time allocation.
Solution : The approach here is to define a new type of instrument, one that doesn’t produce audible notes, but that does set the scale for a different layer. Here the midi-mapping would indicate which layers scale was intended, rather than actually producing any MIDI messages. This would allow one layer to contain chords, with a very slow loop speed, and another layer to contain an arpeggio pattern. Assignable scales is a precursor to this mod.
Status : A partial implementation - a 4 note version - is in A021. See Arp-4 Meta Controller
Major : Controller output
Problem : Only note on/note off messages can be produced
Solution : The approach is to “tag” any layer as being a controller layer, rather than a note layer. Standard TNR instrument selection approaches - [L1], menu - then change the CC type.
Status : Considered completed in A016, although would be good to be able to customize the range of CC values being output. See Control Change
Major : Sequencer
Problem : The TNR can not chain blocks together
Solution 1 : A new layer mode - a 256 step score - has been implemented as a sub-goal of this. See ScoreX . This has been enhanced in A017 with a block-change meta-controller “instrument” ( See Block change meta controller ) to permit true block change programming.
Solution 2 : Extending the solution above with additional mute/don’t mute/fade in/fade out layer instructions would allow whole song programming.
Status : Ongoing
Major : Direct Velocity control
Problem : The TNR just produces notes with the same velocity
Interestingly, the underlying SWL-01 will produce audio with variable volume/velocity - as can be seen when sending note-on from somewhere else - and the TNR SW stores velocity, it’s just that you can’t input velocity via the UI.
Solution 1 : Possibly use the variable brightness to allow 3-state velocity (full, 2⁄3, 1⁄3, off) via multiple presses.
Solution 2 : Alternatively, the Controller Output mod above could also have a “velocity” controller, to update the internal velocity, although this might be tricky to coordinate. One layer running the notes in draw mode with another layer running the velocity in bounce mode could produce some nice effects
Solution 3 : Another approach is to have a “split screen” where the bottom N (say 13) rows are notes, and the top 3 are the velocity. This would force the velocity of all playing notes within that step. This has been implemented.
Solution 4 : Adding a per-layer velocity baseline value, like sound length and octave etc.
Status : Ongoing. Solution 2 has been implemented here Velocity controller. Solution 3 has been implemented here : Splits
Major : Variable sound length
Problem : Each layer has a set sound length.
There isn’t a way to have variable sound lengths within a layer. There isn’t any underlying reason why; when a new note comes up, tne TNR pushes it, and a timer count, into a “notes on” buffer, and then simply down-counts throught the buffer to see when to send the note-off. So long as the note length is known at the time the note-on appears, then there could be a way of having variable note lengths. An approach whereby the notes duration is a “bar” on the grid - i.e. play the note until there is no LED lit - is not easy to implement, and only really valid in Score mode.
Solution 1 : Possibly use the variable brightness to allow 3-state note lenths (full, 2⁄3, 1⁄3, off) via multiple presses.
Solution 2 : Alternatively, the Controller Output mod above could also have a “note length” controller, to update the note length, although this might be tricky to coordinate.
Solution 3 : A similar “split screen” to the Direct Velocity control above. This has been implemented.
Status : Ongoing. Solution 3 has been implemented here : Splits
Major : Randomizer
Problem : “Random” mode isn’t random
It would be nice to have a truly random note loop generator, like several modular synths, where the probability of each note in the scale occuring is settable.
Solution : This would be a new layer type, probably a bit visually similar to Bounce, where the height of each note corresponded to how likely that note was to fire.
Status : Ongoing. A partial implementation has been included via probability/chance splits : Splits
Major : Recorder
Problem : The TNR can’t record incoming midi
It would be nice if the TNR could record incoming midi onto a score. There are lots of issues here.
a) The way the code currently works is that the note duration is fixed, and known in advance, so there is no easy way of responding to Note-Off events. Nevertheless, Note-On events could be translated into grid notes, similar to remote mode.
b) As a result, turning notes off can only be done fro the TNR itself, by deselecting LEDs. (Asking the user to reset notes with more note-on events seems wrong, and asking for 0-velocity note on’s rather than note-offs seems awkward too)
c) The translation task from incoming pitch to grid position is difficult. What should happen when the incoming note is “off screen” because of being too high or low? Or not in the current scale? Simplest would be to restrict recording to layers with chromatic scale, and within the octave that is displayed.
d) Is this relevant for any other layers other than score?
Solution : Release A018 (see Recorder ) includes a working version of this. Recording into Score-256 is not yet possible, nor is recording of CC messages. Neverthess, and with reference to the points above, (a,b) Only Note on is recorded, (c) only notes in the current scale and octave range are recorded, (d) all layer types have been implemented. Draw in particular is useful as an “unquantized” recorder.
Status : In Progress
Minor : Usable Clock
Problem : Honestly, you can see the clock from space, and with all the flashing going on, planes keep trying to land in my street.
It would be nice if there was a less bright, and less distracting clock.
Solution : An analogue clock face, or one that didn’t keep clearing with the clear animation. Or smaller characters? (at least dimmer ones).
Status : Open
Minor : True save layer
Problem : There is no way to save and load all the blocks from just the current layer. “Layer” menu settings apply to all blocks in this layer. However “Layer” save items just refer to the current block of the current layer. This makes score-256 a bit tricky to use.
Solution 1 : Modify “layer” save/load to mean what it says, and rename the existing “layer” file menu setting something like “block+layer”.
Solution 2 : This is only really a problem for multi-block layers. Make save “layer” work as saving all blocks, when the layer type is multi-block (like score-256)
Status : Open