VCI-400 mapping spinback bug fixes, other ideas

I’m wondering if I am the only person having this problem.

The VCI-400 mapping has a “feature” where “if you release the Vinyl button while scratching it stays in vinyl mode for spinback”. Which is nice, but the problem is that now it’s stuck. Once it is stuck, whenever I turn on Vinyl mode, playback instantly stops for that deck, and it stays in scratch mode. No amount of touching or other button gymnastics will get it to un-touch the jog wheel, other than turning off vinyl mode. It stays stuck when I load a new track.

I may hack it and post a fix, or simply remove the feature depending on how messy the code is. A feature that breaks a deck in the middle of a set is a feature that I can live without. :wink:

(The mapping otherwise works great. Manual beatmatching is as natural and effortless as any software I have tried, and much easier than with Traktor. The wheels are super responsive with very fine resolution, and the latency is unnaturally low with raw ALSA processing. Makes it hard to go back to other software TBH.)

Some other stuff I’m considering

I was wondering where to hack in a “split cue toggle”, and maybe a “headphone pfl/main mix control”. Both of which can be helpful when the delay to the mains is off. I also see there is a “headphone delay” control so that might also be useful. There are some unused loop recorder controls in the middle…one of which is a handy micro slider that might be perfect for this. Of course they probably should control one of the looper decks :slight_smile: but I don’t really use loopers so…

Would also like to see beatjump–extremely handy feature in a live set when I haven’t had time to set cue points. It probably make sense to (optionally?) replace one of the sets of main pad controls, but 8 pads for beatjump? Honestly if I just had the option of either 4 or 8 beats forward or backward, or a rotary encoder that skips beats per tick… would it make more sense to steal the “master FX mix” rotary encoder for simple beatjump functionality, and lose the third FX parameter knob? I dunno, maybe I can live without beatjump entirely…

EDIT: thread renamed because bug fixes. Enjoy!

I tweaked the “spinback” code, and it works nicely now. It’s pretty spiff I think. :slight_smile: If you, like me, like to put just a tiny bit of tension on the wheels, this should make them work right with this mapping when spin-back-ing.

It is simplified a bit so that it was easier to guarantee that it never gets stuck (unless a timer tick gets lost!), and also I tried to make it match speeds better with playing decks as it spins down. I like it anyway. :slight_smile:

This also removes the “hold VINYL button to spinback” function, because it is/was no longer necessary: the decks are always in spinback mode! i think this legacy function interacting with the wheels was most of the problem.

I also slightly increased the jog-pitch sensitivity (OK I admit 4x is not “slightly” but man I felt like I was wheelchair racing or something trying to match beats), and because this is a personal preference, I made that configurable at the top of the file, along with the spinback poll frequency.

Hope these help. My contributions here are licensed under the WTFPL (yes that’s a real license) which is to say, help yourself.

Share and enjoy!

EDIT: I attached the wrong files, so I have deleted them. See the next post for bug fixes and the right files. What a night.

I realized that I had a bug --joyDivider did not adjust the right sensitivity parameter. And then I decided that I could make spindown settle into the regular playback better. So I did. It works well on this system anyway. Would welcome any feedback.

If you edit the script to set spindownPollMs = 30 and put just a little tension on the wheel so it doesn’t spin freely, it’s quite scratch-friendly.

Share and enjoy.
VCI-400-BHVN.midi.xml (84.1 KB)
VCI-400-BHVN-scripts.js (39.5 KB)

When a controller turns off scratch mode (scratchDisable), you have the choice to either smooth or immediately jump to the current play speed. I noticed that if I use “smooth”, and the scratch is being pushed forward when you scratchDisable, the pitch will wobble frantically around the playback speed for a bit before settling in. I mean, yes real turntables might do this a little, but it’s pretty radical. Maybe the lead/lag parameters of the smoothing function could use some tuning? This seems like a bug in Mixxx. Possibly related to the sudden change in “jog speed”.

The official VCI-400 mapping does a trick where it maintains the jog wheel motion when scratching, and this is supposed to smooth the transition to normal playback, but I have experimented and this does not appear to make a difference with MIXXX 2.0.0.

I have worked around the problem by disabling the smoothing effect on scratchDisable if the current scratch rate is approximately normal playback speed, which also makes transitioning from scratch intros into playback more predictable. This seems to work, and is largely inaudible (with rubber band enabled), but the whole thing seems hackish to me.

Maybe the internal smoothing function could be improved so that its internal state is aware that you’ve just disabled scratching and takes into account its rate at that moment?

Thanks for working on this. Could you update the mapping for the new effects UI in Mixxx 2.1? There is a new JS library that will make it quite easy to map the effects.

If you have ideas for ways to improve how Mixxx handles jog wheels, contributions are welcome! Scratching is handled here.

Summary for non techies: the attached file does not glitch when you spin a wheel and keep on spinning (like balancing a plate) through the file. Also, Del = split cue toggle.

I think some of the problem is that the code was calling scratchEnable() when scratch was already enabled, and this was causing additional glitching. I also think there are performance issues with constantly deleting and recreating the timer. I tweaked the code this morning to avoid these things, and it works very nicely for me. ((Also mapped autoDJ and split cue toggle just because they were there.)

Probably should replace all the separate deck timers with one global repeating timer, and leave it on. I suspect there’s more time spent turning the timer on and off than actually handling the ticks, and it’s during the jog moves, when we’re already busy already handling hundreds of jog messages, etc. Anyway, might rewrite it later but the attached changes seem to be adequate.

It might be convenient if Mixxx handled the free-spinning jog grab/throw/catch/release action internally, but I’m not sure that’s a universal behavior. If I recall correctly, Traktor’s spinback behavior is BORING. :slight_smile:

Re the new effects UI, I’m not using Mixxx 2.1 because it’s not released yet, and I’m a bit too lazy/busy to put together an overlay for it at the moment, so it’s largely a moot point. The controller abstractions are…um… I’ll check them in more depth when 2.1 is released, or when I get caught up on my other projects. It would help if some of the effects were things I’d consider using, but I figure once 2.1 is out that will happen pretty quickly.

I really hate that it wastes a rotary encoder on the FX dry/wet blend. Wouldn’t that just make a lovely beatjump control? No, I would want to move the pitch control there, and make the current pitch knob into beatjump.
VCI-400-BHVN-scripts.js (40 KB)
VCI-400-BHVN.midi.xml (85.1 KB)

Hi tekHedd,

My script for VCI100mkII may help you.
The implementation uses one loop timer for delay instead of a series of one-shot timers. The essence is,

VCI102.scratchTimer = [0, 0, 0, 0];

VCI102.wheelTouch = function(ch, midino, value, status, group) {
    var deck = ch + 1;
    if (value) {
        if (VCI102.scratchTimer[ch]) {
            VCI102.scratchTimer[ch] = 0;
        } else {
            engine.scratchEnable(deck, 2400, 100 / 3, 1 / 8, 1 / 256);
    } else {
        VCI102.scratchTimer[ch] = engine.beginTimer(20, function() {
            var vel = Math.abs(engine.getValue(group, "scratch2"));
            if (vel < 1 && (vel < 1 / 64 || engine.getValue(group, "play"))) {
                if (VCI102.scratchTimer[ch]) {
                    VCI102.scratchTimer[ch] = 0;

And I think the resolution of the wheel is not 4096 but 2400 pulses/rotation, same as VCI100mkII, not officially announced though.

Thanks, that’s more or less what I had in mind. :slight_smile: But it does seem to work well as it is… and performance is well within acceptable parameters… and I have to try so hard to stop twiddling with something that simply ain’t broke… Must… Stop… Tweaking…

That sounds right, but I don’t remember where I saw it before. Maybe someone in the FB group can confirm? Then again, they do feel really good with the 4096 setting and default alpha/beta. Then again on the third hand (!), the vestax wheels usually feel good. Nothing else to do but give it a try, right? And then tweak all the hand-tweaked parameters in the spinback code. Hah.

I suppose I could measure it. (if I could get “print” to work, that is–debugging scripts without even print style debugging is a real PITA) It would also make a lot of sense for them to use the same encoders across products…but on the other hand those specifications always increase even when we’re well past the point of being able to feel the difference. :slight_smile:

Yup, 2400 ticks-per-revolution REALLY makes it better.

I collapsed all the timers into a single timer, and it does seem to use less cpu when scratching and cueing. But of course more cpu all the rest of the time. The tradeoffs for dependable behavior, I think.

I get a “can’t delete timer” message on exit. Maybe I’m not expected to clean up in shutdown()?

(XML mapping file has not changed, included simply to avoid confusion when downloading.)
VCI-400-BHVN.midi.xml (85.1 KB)
VCI-400-BHVN-scripts.js (40 KB)

Mixxx stops script timers on shutdown. There is no need for the script to handle that.

Thanks, good to have that confirmed.

This mapping is the one I had made for my own use. I post it here because the official mapping is not updated especially around FX. But ideas and codings are so different that I don’t intend this to be the update but alternative. Feel free to use it as is, modify it or use it partially to update official’s.

  1. FX select (FX chain select when unfocused)
  2. FX on/off (slot1-3, insert to headphone)
  3. FX parameter control (FX meta control when unfocused)
  4. FX super knob (dry/wet mix when unfocused; focus next slot/unfocus if pushed)
  5. Pitch (reset key if pushed)
  6. Waveform zoom (set beatgrid if pushed)
  7. Pad (upper: 1/8, 1/4, 1/2, 1 beats; lower: 2, 4, 8, 16 beats)
  8. Pad mode (loop, rolling loop, jump backward, jump forward)
  9. SAMPLER cue and play (upper: sampler1-2; lower: sampler3-4)
  10. SAMPLER volume
  11. Rate
  12. Jog
  13. Cue (depend on transport pad mode)
  14. Play (depend on transport pad mode)
  15. Hotcue (depend on transport pad mode)
  16. Master gain
  17. Channel gain
  18. Equalizer
  19. Sync
  20. Load
  21. Filter
  22. FX insert
  23. Channel volume
  24. Crossfader
  25. Library control (move (scroll on shift) up/down, next pane (activate selected on shift) if pushed)
  26. Crossfader curve
  27. Transport pad mode (Mode1: hotcue1-4, cue, play of channel 1; Mode2: cue, play, cue and play of channel 3, cue and play, cue, play of channel 1; Mode3: hotcue1-4, cue, play of channel 3)

Numbers are of owner’s manual. … arent_id=8

Edited: 2019-9-30 (The file is deleted. See the recent post of this topic.)

The old mapping should be a replaced with a mapping the uses the new effects and looping interfaces in 2.1. Could you open a pull request for this new mapping targeted at the 2.1 branch? We could release it with Mixxx 2.1.1 or 2.1.2.

Before a pull I have modified a bit this mapping to make usable for Serato model of VCI-400 (I own a plain model without labels of pads). I want to hear from the users which is better, pulling as update or alternative.

  1. Pad mode (jump backward, loop, looproll, jump forward)

  2. Track pad mode
    Mode1: hotcue1-4 (clear it on shift), cue, play
    Mode2: reverseroll, cue, play of channel 3; reverseroll, cue, play of channel 1
    Mode3: hotcue5-8 (clear it on shift), cue, play

Differences of main pads are left as before, and I have no plan to modify this mapping around these.

Edited: 2019-9-30 (The file is deleted. See the recent post of this topic.)

Add assignments of master and headphone fx insert, and change library control.

  1. FX insert (master, headphone)
  2. FX enable (slot1-3, toggle (move on shift) focus)
  3. FX metaknob1-3 (parameter1-3 (4-6 on shift) if focused)
  4. FX mix (toggle it if pushed, superknob (select effect if focused) on shift)
  5. Library control (select item (pane on shift), activate it if pushed)

Edited: 2019-8-16 (enable softTakeover on FX metaknob1-3), 2019-8-19 (improve the softTakeover), 2019-9-1 (no change in functionality), 2019-9-23 (improve the softTakeover more), 2019-9-30 (no change in functionality), 2020-1-21 (The file is deleted. See the recent post of this topic.)

oh cool! I’ll try this out and see how it works.

One thing we need to do for VCI 400 is make the effects work with the new Mixxx effect control objects. Did you do that here?

Don’t know if it will help, but you can freely steal from the rewritten VCI-400 mapping I released in the other thread, which was rewrittend for Mixxx 2.2.x and has support for the new objects etc. All of the code is licensed very permissively, in the hopes that it will be used to improve the official mapping. [deleted! Nope, that’s not the right gitlab repo] It is written with low level JS prototype style for performance, but maybe it will be of some use for copy/paste?

Oddly, the announcement thread does not turn up when I search for VCI-400: Vestax VCI-400 Mapping v1.0 [BHVN Official]

Regarding OP of this thread, I no longer use code derived from the official mapping–we can now use the built-in spinback code and I felt the legacy codebase to have a lot of abstraction that really is not necessary for this controller.

Anyway, glad to see there are still VCI-400 users out there!

cool I’ll check it out and let you know if I have any comments. I’m the official maintainer of the vci400 mapping in mixxx so it’s good to see it get some love

(I replied in the other thread)

FYI have migrated my internal HG repo to gitlab at