katana-dev / docs

Main compilation of documentation
Creative Commons Attribution Share Alike 4.0 International
100 stars 11 forks source link

Thoughts on rapid patch change in this new universe #1

Open snhirsch opened 7 years ago

snhirsch commented 7 years ago

Since the Katana sysex map is much richer than expected, restoring a remotely managed preset presents additional challenges. My experimentation indicates that writing in the entire MIDI address range leaves a significant audible gap and is not going to play nicely with live performance. So, why not take the approach of comparing current state with target state on the controller and sending only the differential? The algorithm would have to be aware of locations that require writes to start on specific boundaries, but it would seem straightforward to implement. Thoughts?

Beanow commented 7 years ago

So far I have not done any testing with "best sounding" patch uploads explicitly in mind. But indeed several optimizations spring to mind that I think are worth testing.

This probably depends on how far you want to go down the optimization rabbit hole. You could use an audio interface to send a loop or a saw wave to your input, record your rec out. Measuring the audio gap. While having your hands free to send commands and change the program.

When it comes to patch changes though, my very first thought would be to try out an alternative mode, where CH1-4 are uploaded at the same time, so you can use 6 CC messages for Bank Up/Down, switch to CH1-4 using the Katanas memory alone during a song, using the banks between songs. (Again you can apply difference algorithms between the CH1-4 patches to skip sections if they are the same)

See how much of this audio gap is actually caused by SysEx protocol overhead and how much is the DSP module needing time to reconfiguring itself.

Identifying all the addresses that are linked and which can be skipped without affecting the patch.

Test if uploading deep parameters for disabled effects is audible. And if not reorder their blocks to be written last.

The difference algorithm like you mentioned. Although in a live situation that means the bridge software would need to keep a local copy of the state in advance, otherwise the extra queries would translate into latency. Wouldn't sound as bad, but still bad for live performances if switching takes an extra 100ms.

Beanow commented 7 years ago

One that I can certainly recommend is to read the FX1 (Mod) and FX2 (FX) type, and only write deep parameters for the relevant effect.

These are the [xx xx 01 41] and [xx xx 03 4D] values. That should save roughly 2x 200 bytes. And the left out values are only relevant if you want to open BTS and change the type of effect and preserve the old values you had for the different effect.

snhirsch commented 7 years ago

That's what my bridge code is currently doing. It checks to see exactly what's assigned to button colors and saves/restores the minimum to cover these.

skconrad commented 7 years ago

Great work!

Just leaving a comment to let folks know Ive finally joined Github.

so "skconrad" = elantric @ VGuitarForums

Here are the known applicable URLs

TGP Thread: BOSS KATANA 刀 amplifiers (where the users are) https://www.thegearpage.net/board/index.php?posts/23891522/

Beanow commented 7 years ago

Welcome @skconrad. Since it's off topic for this issue, let's resume in #2.

gumtown commented 7 years ago

For fast patch change, you will need to determine the speeds and change gaps (audio dropout). Sending random parameter differences can make the total data slower, as one byte here and one byte there can make the total package quite large mostly with sysx headers and addresses just to send one byte at a time. The whole patch file contains a lot of redundant data, including blocks of text data, initially designed in the GT-100 patch as "Quick effects" titles for each effect. I think a patch of relevant data can be rendered down quite small for live performance, the Katana is not going to care about patch name, or GT-100 only related data (preamp B, NS2, accel, pedalFX, Chorus, Comp, channel settings, and assigns).

If speed is not a requirement and gapless audio preferred, then toggling Katana channels 1 and 2, and writing the next patch to the alternate channel might work. with the current patch in KAT channel 2, the next patch change, the patch data can be written to KAT Channel 1, and then a program change (P.C.) message issued for the Katana to handle the data exchange to the next patch.

Beanow commented 7 years ago

Perhaps you might be able to do this with a single channel. Because on recall of a CH I believe the patch is mirrored to the 60 00 region.

Even for the relevant bytes there are different upload strategies that come to mind. For example a patch like this: Boost > Amp > Delay (Off) > Reverb (Off)

You might have configured the delay and reverb to be used with your stompbox later. Kill the boost for clean sound. Delay + reverb.

For a faster change though you might order this to be:

  1. Send CH1 Boost+Amp in single bulk write (since they happen to be close).
  2. Send OFF to FX1, FX2, Delay, Reverb. (4x single byte writes).
  3. Recall CH1 (initial tone sounds correctly now)
  4. Send remaining deep effect params to temp 60 00. (stompboxes are ready now)
  5. Send remaining deep effect params to CH1. (recalling would be correct now)
  6. Write anything else. Name, further FX1/2 parameters, etc.

Is that actually faster though? Maybe not, because delay and reverb can be written in a single bulk write.

snhirsch commented 7 years ago

Am I correct that the maximum single-message length is 255 bytes? Unless I miscounted that seems to be how the amp quantizes returned data.

I'm going to make a quick hack to my bridge code that snapshots all preamp, boost, mod, delay, efx, reverb and chain setup ranges from 60 00 rather than trying to be clever. I can think of many schemes for optimizing write operations, but over the years I've learned that complexity often invites more problems than it solves. I want to see if this causes objectionable gaps.

With such expanded coverage of the 60 00 block, is it even necessary to save/restore the 00 00 04 xx block? That particular range tends to act like controller assigns and may be redundant in the case where we fully manage 60 00.

Beanow commented 7 years ago

I suspect that due to the 60 00 12 .. range being added to patches, the 00 00 04 .. section is fully redundant. Furthermore, the 00 00 04 .. part is only implemented once, so it has to be capable of being replicated from a patch.

Message size is 255 including everything, from F7 to F0 yes, that should give you 241 bytes you can write per message.

snhirsch commented 7 years ago

Thanks, Robin. Your observation about the single 00 00 04 .. section is right on point. I think when we start deciphering the controller assigns we'll find that the 00 00 04 .. addresses are treated as "external" controllers that are linked in various manners to the 60 00 .. region. If you think about what's possible with controller assigns, e.g. having the first 1/2 of the range make one device active as it adjusts it and the second 1/2 doing the same for a different device, this may be exactly how they deal with the boost/mod and delay/fx knobs. Have you dug into that at all?

snhirsch commented 7 years ago

This is looking promising. In Python, I can read the range from 60 00 01 40 - 60 00 06 1A in about 80 ms. I do need to pickup a couple of much smaller blocks below and above those limits and will have to evaluate whether its quicker to do this piecewise or in a single shot.

snhirsch commented 7 years ago

Question: What does the 'Volume' block in Gumtown's Fx editor map to in the GT-100 spec? Is it 'FOOT VOLUME: LEVEL' at xx xx 0x06 0x33 ?

Beanow commented 7 years ago

Only 1 out of 4 values actually works there, the others are fixed. https://github.com/katana-dev/docs/blob/master/tables/patch-capabilities.md#sysex-patch-blocks perhaps it changes GA-FC behavior?

snhirsch commented 7 years ago

So the answer appears to be "yes" to my question? That's great news. I was jumping through hoops to manage volume such that toe-down on the Midi controller never moved panel volume (04 xx block) above it's setting at capture time. The real answer is to tie the pedal to 0x60 0x00 0x06 0x33. If I need to limit the range, I can do that in the FCB1010 configuration. Cool. Should have this working in another hour or so.

gumtown commented 7 years ago

For reading in a patch, I think reading the entire contents in one shot would take less time than piece meal parts. This is the request command I use for one whole patch F0 41 00 00 00 00 33 11 60 00 00 00 00 00 13 00 0D F7

Edit Note: the data request size 00 00 13 00 is used as at the time the patch size was uncertain, and using this value will request everything the Katana can give up to 60 00 12 7F (which I think ends at 60 00 12 17).

Depending on how you intend to internally arrange the patch data (in FxFloorBoard it is arranged in 128 byte blocks with new sysx headers added), writing back to the Katana is done in the 128 byte unit + syx header & footer. It may be easier to send a complete patch back all in one go.

The system data only needs to be read once, I have been working on this last night, organising a data structure, as there are some parameters in the 00 00 04 xx area (S/R and USB) and one in the 00 02 00 xx area (midi RX channel). So I have made the data request as follows F041000000003311000000000002000E70F7 which retrieves all from 00 00 00 00 to 00 02 00 0E including the first 15 parameters in the 00 02 00 xx address area, which might be useful related to midi channels and other useful stuff in the GT-100 which could be worth probing. The system data returned will be 617 bytes in size, in 2 Katana format 255 byte blocks + what ever size is left.

The Foot Volume in the editor (as with all the parameters) is based on the GT-100/001 spec.

Yet to be explored are the system area controls for S/R loop, and it seems the panel knobs are mapped here, these seem to add an extra layer of control, where some control two parameters in the patch data area, and the manipulating the patch data directly (bypassing the panel knobs) allows for these extra control features, like extra effects with mod and booster controlled independently.

I have nearly gotten as far a I can get without actually clapping eyes on a Katana, I hope to get one soon. But the biggest problem so far is sending a patch from the editor to the Katana, which seems to mute the patch volume. I need to find which parameter this is affecting.

snhirsch commented 7 years ago

I'm having good success writing back 255 byte chunks (241 bytes of data) at one shot. I have the S/R loop documented in the katana-bridge project:

[Send/Return]

Loop Active (Off, On)
00 00 04 00 --> 00, 01

Note1: Loop-active commands effective only when a 1/4" plug is
inserted in Return jack. Inserting the jack forces loop to
the active state.

Note2: CC# 19 performs the same function.

Routing Scheme (Series, Parallel)
00 00 04 01 --> 00, 01

Send Level (0..Unity..200)
00 00 04 02 --> 00 .. 32 .. 64

Return Level (0..Unity..200)
00 00 04 03 --> 00 .. 32 .. 64`

Not sure what you mean by panel knobs being mapped there. The panel knobs are in the same area, but a few bytes higher up (I have this documented as well). As a result of my experiments today I'm coming to the conclusion that it's best not to include the panel knobs when restoring a patch. Or, if you do, make sure that comes prior to restoring the patch area.

Just noticed your comment about muting. I am not seeing that when restoring large portions of the patch data area. It must be something not included in my logic.

snhirsch commented 7 years ago

Here are the ranges I'm saving/restoring in case it will help narrow down what is causing the mute action. Sorry about the decimal radix, but Python's JSON reader is strict and will not permit hex literals:

[
    {
        "name": "range1",
        "baseAddr": [96, 0, 0, 48],
        "lastAddr": [96, 0, 0, 111]
    },
    {
        "name": "range2",
        "baseAddr": [96, 0, 1, 64],
        "lastAddr": [96, 0, 6, 51]
    },
    {
        "name": "range3",
        "baseAddr": [96, 0, 6, 85],
        "lastAddr": [96, 0, 6, 102]
    },
    {
        "name": "range4",
        "baseAddr": [96, 0, 7, 24],
        "lastAddr": [96, 0, 7, 51]
    },
    {
        "name": "range5",
        "baseAddr": [96, 0, 16, 16],
        "lastAddr": [96, 0, 16, 35]
    }
]
snhirsch commented 7 years ago

I'm pleased to report that ignoring the 0x0, 0x0, 0x04, xx region works quite nicely. Patch data restore is essentially instantaneous with a minimal amount of glitching. I'm going to try muting the output during patch change to see if I can clean it up a bit more.

Tying the MIDI volume controller to the internal pedal volume is definitely the right approach.

Beanow commented 7 years ago

:tada: yaay

What kind of speed are we talking about? You added the 50ms delay before volume restore yourself. That 50ms plus a bit? Or more like half a second? Does BTS mode affect the speed?

Also it seems you're writing as fast as you can write. Good to see the buffer kicking in and holding a full patch. When I did the memory scanning script I needed to give it about 40-50ms of time to respond to each query. So on the order of 20-50ms I would expect a single message to be processed. But if you're doing the whole patch in 50ms, perhaps this delay is mostly in the MIDI transport and does not occur for the Katana's buffer?

snhirsch commented 7 years ago

I'm no longer using the 50ms delay in my code. Reading the patch data takes about 80ms. (starting from the call that issues the read command) and restoration just about the same. If any sound is being produced at the time there's a short "hiccup" as the new parameters take effect. I haven't formally measured the interruption, but it's quite short.

Ran into a bit of frustration switching between FxFloorboard and the Beaglebone computer. If I disconnect from the laptop with the amp in edit mode the current tone setting is reloaded from preset memory on USB handshake with the BB, wiping out any unsaved changes made in the floorboard session. After being burned a few times, I learned to explicitly exit floorboard before switching cables. I'm guessing this is deliberate on Roland's part to provide known state after losing and regaining USB connectivity.

Beanow commented 7 years ago

As a heads up, I'm making some progress with the groundwork for a shared library. See https://github.com/katana-dev/lib-katana/issues/1

The fast patch change learnings would be excellent to implement there as well. Since Floorboard, Patch Loader and the Android Editor would all have the same concerns to some degree.