dagargo / overwitch

JACK client for Overbridge devices

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Syntakt support

szszoke opened this issue · comments

I have one of them on it's way. I will do some testing once it is here.

I was thinking exactly about this.

I'll release both Overwitch and Elektroid once you add the device and check it out.

Thanks for taking care of this!

No worries! I don't have a confirmation on the delivery date yet but hopefully it well be here early next week.

commented

oh great!

I have a tracking number and I'm hoping that I get my delivery this week.

It arrived. The outputs seem to work (including monitoring the two physical inputs). MIDI In and Out needs to be tested. There is something with the OB main inputs. Audio that is routed in via them sounds high pitched.

#define OB_MAX_TRACKS 20

...

static const struct ow_device_desc SYNTAKT_DESC = {
  .pid = STAKT_PID,
  .name = "Syntakt",
  .inputs = 2,
  .outputs = 20,
  .input_track_names = {
     "Main L Input", "Main R Input"},
  .output_track_names =
    {"Main L", "Main R", "Track 1", "Track 2", "Track 3", "Track 4",
     "Track 5", "Track 6", "Track 7", "Track 8", "Track 9", "Track 10",
     "Track 11", "Track 12", "FX Track L", "FX Track R", "Delay/Reverb L",
    "Delay/Reverb R", "Input L", "Input R"},
  .output_track_scales =
    {OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32,
     OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32,
     OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32,
     OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32,
     OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32, OW_CONV_SCALE_32}
};

Congrats on your new acquisition. That was fast!

20 outputs... It's quite a lot.

I have a hypothesis. If the pitch is increased by a X ratio, it is because Overwitch sends less tracks than expected exactly in the same ratio. If pitch frequency is twice, it is because there should be twice the outputs. Could you try with 4 output tracks?

Perhaps, the analog drums or the FX track are audio destinations too.

I tried with 4 tracks as well but then I get audio overflows. I think there are 4 tracks. On Windows I can route to Main L/R and Pre FX L/R.

Then there are definitely 4 tracks.

The issue is probably in the code. I'll take a look later.

Or perhaps the Overbridge packages are different.

Is there anything interesting in the console output with 4 tracks enabled? If so, post them here, please. Or are the overflows just audible?

When I said Overbridge packages I meant the structure of the Overbridge frames and the layout of the different tracks in them.

I am logging some extra variables:

resampler.c:319:error_print ("j2o: Audio ring buffer overflow. %ld %ld %ld Discarding data...\n", gen_frames, bytes, wsj2o);

This output repeats:

ERROR:resampler.c:319:(ow_resampler_write_audio): j2o: Audio ring buffer overflow. 1024 16384 12991 Discarding data...
ERROR:resampler.c:319:(ow_resampler_write_audio): j2o: Audio ring buffer overflow. 1024 16384 15167 Discarding data...
ERROR:resampler.c:319:(ow_resampler_write_audio): j2o: Audio ring buffer overflow. 1024 16384 14655 Discarding data...
ERROR:resampler.c:319:(ow_resampler_write_audio): j2o: Audio ring buffer overflow. 1024 16384 11199 Discarding data...
ERROR:resampler.c:319:(ow_resampler_write_audio): j2o: Audio ring buffer overflow. 1024 16384 13375 Discarding data...
ERROR:resampler.c:319:(ow_resampler_write_audio): j2o: Audio ring buffer overflow. 1024 16384 15551 Discarding data...

It also makes the Syntakt partially lock up and not react to the play button until a reboot. If I don't connect anything to the inputs then this issue doesn't come up.

Another hypothesis. What if there are 4 tracks of 16 bits values instead of 32 bits?

Was the sound with 2 tracks clean and high pitched or had some distortion in it? If distortion was present, I suspect some digital audio might get into the analog FX.

Could you check if there is audio leaked in the FX track when using 2 tracks?

With two tracks the sound is high pitched and no distortion is present. With four tracks the sound is high pitched and distorted.

With only two tracks, the high pitched sound can be heard from both the Main L/R outputs and the FX Track L/R outputs.

Not sure if it's the right way to do it but nothing changes if I set p2o_frame_size like this:

engine->p2o_frame_size = 2 * engine->device_desc->inputs

The underlying hypothesis is that they keep the same structure at a USB level as in the case with 2 inputs but they transmit 4 inputs.

This is the block description made by Stefan Rehm in dtdump and included in Overwitch.

overwitch/src/engine.h

Lines 25 to 69 in fb8206d

/*
Protocol details known so far
-----------------------------
For USB configuration and transfer setup, please read the code :)
All values are big-endian (MSB first)!
Sample rate is 48kHz
Data format TO Digitakt (USB interrupt transfer, EP 0x03)
----------------------------------------------------------------
Raw data of the transfer consists of 24 blocks, each block holding
- a fixed header
- a sample counter (uint16 BE), increased by 7 per block (because
each block contains 7 samples)
- 7 samples (int32 BE) * 2 channels (interleaved)
(total 168 samples, 2112 Bytes). Structure of a single block:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| fixed header: 0x07FF | sample counter (uint16_t) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ unknown +
...
+ (28 Bytes) +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sample 1, Master Out 1, int32_t |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sample 1, Master Out 2, int32_t |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sample 2, Master Out 1, int32_t |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sample 2, Master Out 2, int32_t |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ samples 3 .. 7 +
...
+ (5*8 Bytes = 40 Bytes) +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

As it can be seen, samples are 32 bits. My guessing is that in this case these are 16 bits.

There are 3 possible scenarios here:

  1. 2 samples for the same input are set in those 32 bits words.
  2. 2 samples for the two inputs are set in those 32 bits words (stereo).

Considering that the audio was high pitched and distorted I consider that our best candidate is the first option as we were providing the higher bits as the sample and the lower as just noise and both the audio and the Main and FX tracks would be the same (if mono).

This is the patch for the first scenario. We set 2 32 bits words for every 4 samples from JACK.

$ git diff
diff --git a/src/engine.c b/src/engine.c
index 18dc6c1..6355006 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -269,11 +269,19 @@ set_blocks:
       s = blk->data;
       for (int j = 0; j < OB_FRAMES_PER_BLOCK; j++)
        {
-         for (int k = 0; k < engine->device_desc->inputs; k++)
+         for (int k = 0; k < 4; k += 4)
            {
-             hv = htobe32 ((int32_t) (*f * INT_MAX));
-             *s = hv;
+             int32_t hv1 = htobe16 ((int16_t) (*f * SHRT_MAX)) << 16;
              f++;
+             int32_t hv2 = htobe16 ((int16_t) (*f * SHRT_MAX)) << 16;
+             f++;
+             hv1 |= 0xffff & htobe16 ((int16_t) (*f * SHRT_MAX));
+             f++;
+             hv2 |= 0xffff & htobe16 ((int16_t) (*f * SHRT_MAX));
+             f++;
+             *s = hv1;
+             s++;
+             *s = hv2;
              s++;
            }
        }

This is the patch for the second scenario, which is easier to implement. For ever track pair, we set 1 32 bits word.

$ git diff
diff --git a/src/engine.c b/src/engine.c
index 18dc6c1..0cc0305 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -269,9 +269,11 @@ set_blocks:
       s = blk->data;
       for (int j = 0; j < OB_FRAMES_PER_BLOCK; j++)
        {
-         for (int k = 0; k < engine->device_desc->inputs; k++)
+         for (int k = 0; k < 4; k += 2)
            {
-             hv = htobe32 ((int32_t) (*f * INT_MAX));
+             hv = htobe16 ((int16_t) (*f * SHRT_MAX)) << 16;
+             f++;
+             hv |= 0xffff & htobe16 ((int16_t) (*f * SHRT_MAX));
              *s = hv;
              f++;
              s++;

Keeping my fingers crossed.

I tried both but it did not make a difference. There is one more variable. Pipewire. I will try to rig up a machine with Jack and see if I'm still getting the buffer overflow.

I forgot to mention that both the above tweaks will only work with Syntakt as a 2 inputs device. With 4 inputs it will behave erratically.

Anyway, let's focus on JACK for now.

Then I did the test wrong. I will test again with just two input devices.

I get a constant static sound with the first patch on Main L and high pitch with some distortion if I apply the second patch.

I performed all the tests with Jack2 and the results are more or less the same. The only difference is that if I apply the second patch then I get static on Main R which I do not get with Pipewire.

Just to be sure, have you tried without any patch with 4 inputs?

I tested the following:

  • 2 inputs, no patch
  • 4 inputs, no patch
  • 2 inputs, patch 1
  • 2 inputs, patch 2
  • 4 inputs, patch 1
  • 4 inputs, patch 2

I tested first with Pipewire, then I uninstalled the Jack implementation of Pipewire, installed Jack2 and tested again.

What's the value of STAKT_PID?

#define STAKT_PID 0x001e

Makes you wonder if some Elektron box is missing from overwitch.c or there is something in the works based on the skipped PID

#define DKEYS_PID 0x001c
#define STAKT_PID 0x001e

Makes you wonder if some Elektron box is missing from overwitch.c or there is something in the works based on the skipped PID

Yeah, they've skipped some numbers here and there.

I've added support for the Syntakt following the official description found in the Overbridge 2.1 manual, page 40.

It definitely has 8 inputs as the 4 analog drum tracks have an audio input (same as in Analog Rytm).

Looks like it has "only" 16 outputs: main (stereo), Analog FX out (stereo) and the 12 individual tracks. You reported 20 tracks and perhaps there are a couple more being the analog Syntakt inputs. But I'm not sure about the Digital FX output pair. This will never mess with the USB system as the only thing will happen is that packages will not inject audio into those phantom tracks.

Could you try this? Probably the USB packages length, which are calculated on the number of tracks, were messing with the audio.

I redid my testing with 20 individual output tracks and Jack.

There is Main Left and Right. There are the 12 tracks. There are the physical Input L and R tracks. Then there are two more for Reverb/Delay and two more for the FX out.

Main Left and Right outputs the main mix.
The 12 individual track outputs play the 12 individual tracks on the Syntakt if I press their trigger button.
The two physical input tracks play the signal that I inject via the physical input jacks.
The two Reverb/Delay tracks don't play anything unless I increase the Reverb or Delay send on a track and trigger it. If I do that then they just play the wet signal.
The two FX out tracks don't play anything unless I enable the insert for a track via the Routing page and trigger it.

This reflects how the Overbridge standalone app lists the outputs.

I will pull master and try your changes now.

I get a segmentation fault with the latest master:

(gdb) exec-file overwitch-cli
(gdb) run -n 0
Starting program: /home/eon/Downloads/overwitch/src/overwitch-cli -n 0
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[New Thread 0x7ffff71ac640 (LWP 16094)]
[Thread 0x7ffff71ac640 (LWP 16094) exited]
[New Thread 0x7ffff71ac640 (LWP 16095)]
[New Thread 0x7ffff684f640 (LWP 16096)]
[New Thread 0x7ffff604e640 (LWP 16097)]
[New Thread 0x7ffff5e0f640 (LWP 16098)]
Cannot lock down 107341340 byte memory area (Cannot allocate memory)
ERROR:jclient.c:484:(jclient_run): Error while registering JACK port

Thread 4 "overwitch-cli" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff684f640 (LWP 16096)]
0x00007ffff7f42b68 in jack_ringbuffer_free () from /usr/lib/libjack.so.0

The segmentation fault is caused by Analog FX L Input and Analog FX L appearing twice.

Regardless, I am getting a ton of errors like this one 👇 with 8 inputs and 16 outputs:

ERROR:engine.c:292:(cb_xfr_in): o2p: Error on USB audio transfer: Other error

The manual is not very precise about the device outputs as both Digitone and Digitakt do not include either the main or the physical inputs.

It makes sense that it has 20 outputs. All in all, it was working for you before.

Could you try again with the same outputs you provided? I've just pushed b97e812.

I am still getting the same libusb before. Did you mean to leave .outputs at 16?

I am still getting the same libusb before. Did you mean to leave .outputs at 16?

Oops! I didn't mean it, sorry. Fixed in bfd891d.

I will try to record the high pitched audio tomorrow and upload it here.

I'm thinking that if we can turn it into the "original" then may we can find out what is wrong with the inputs.

Other than that I can't think of anything but to inject a pure sine wave into the inputs and capture the USB packets.

Would they be the same between the ritterent devices?

I'm thinking that if we can turn it into the "original" then may we can find out what is wrong with the inputs.

That's a very good idea. Perhaps it's just an endianness issue.

Would they be the same between the ritterent devices?

The protocol and the packages are exactly the same. Only the amount of tracks per USB package is what makes them different.

Let's leave it here for today but I have one last question. Has your Syntakt became unresponsive with the last code? If not, then we're on the right track.

I guess the audio tracks from the Syntakt to the CP are working well.

It only ever locked up when it was paying back and I connected something to the input tracks in Jack/Pipewire and I have not tried that today.

I will test it tomorrow.

I tested and it still locks up when I connect something to the input tracks that plays a sound. (But not if no sound is coming)

I tested with a pure sine wave note from the Digitone which sounded distorted and beyond recognition.

If you have new code revisions to test, I can do that but I will probably put debugging on hold and play the thing a bit.

At least the outputs are working so people can record.

Sure, enjoy your Syntakt and we can continue next week.

I'll take a look at the code as the issue is most probably there.

Thanks!

I've added a couple of tests to the check if the audio is properly copied between JACK and the resampler and between the engine and the USB stack and everything looks right.

Just in case, are you still having issues with this?

Hi, I just got a Syntakt and I'm trying to use Overwitch on Ubuntu. I'm not familiar with autotools but I followed the installation instructions step by step and (after some complaints and a couple of cautionary reboots) the three binaries seem to be properly installed.

I'm getting mixed results so far.

This part looks good:

overwitch-cli -vv -l
DEBUG:overwitch.c:227:(ow_get_devices): Found Syntakt (bus 001, address 014, ID 1935:001e)
0: Syntakt (ID 1935:001e) at bus 001, address 014
  Inputs:
    Main L Input
    Main R Input
    Analog FX L Input
    Analog FX R Input
    Track 9 Input
    Track 10 Input
    Track 11 Input
    Track 12 Input
  Outputs:
    Main L
    Main R
    Track 1
    Track 2
    Track 3
    Track 4
    Track 5
    Track 6
    Track 7
    Track 8
    Track 9
    Track 10
    Track 11
    Track 12
    Analog FX L
    Analog FX R
    Delay/Reverb L
    Delay/Reverb R
    Input L
    Input R

But that's it, from here I hit the same wall:

$ overwitch-cli -vv -n 0
DEBUG:overwitch.c:227:(ow_get_devices): Found Syntakt (bus 001, address 014, ID 1935:001e)
ERROR:engine.c:704:(ow_engine_init_from_bus_address): Error while opening device: LIBUSB_SUCCESS / LIBUSB_TRANSFER_COMPLETED
ERROR:jclient.c:394:(jclient_init): Overwitch error: can't find a matching device

The same error appears with -d Syntakt. Same when clicking on the "reload" button on Overwitch.

overwitch-dump -l -v gives the same correct output as above. However...

$ overwitch-dump -n 0
ERROR:engine.c:704:(ow_engine_init_from_bus_address): Error while opening device: LIBUSB_SUCCESS / LIBUSB_TRANSFER_COMPLETED
ERROR:main-dump.c:324:(run_dump): can't find a matching device

@quimgil, your issue was reported in #33 and I have just improved the error message because it was totally misleading. Take a look there for more details.

Thank you! Issue resolved, and now I can get Syntakt's audio on Bitwig via USB.

Syntakt is identified as "Syntakt@001,014"

When adding mono inputs, the DAW lets me choose from the 20 outputs listed above, with those exact names. I could test the 12 Tracks (side question, Syntakt's tracks are mono, right?).

When adding stereo inputs, these options are available:

Analog FX
Delay/Reverb
Input
Main
Track 1
Track 11
Track 2
Track 4
Track 6
Track 8

I still need to learn more about Syntakt to understand the difference between Main and Input, and to do anything with FX & Delay/Reverb. And I don't get the logic of the tracks offered (I guess I can just ignore tracks for stereo input?)

Anyway, progress! Thank you very much for your work on this very useful piece of software.

I don't know whether you are interested in overwitch-dump feedback yet, but just in case it helps:

$ overwitch-dump -v -d Syntakt
DEBUG:overwitch.c:227:(ow_get_devices): Found Syntakt (bus 001, address 014, ID 1935:001e)
Segmentation fault (core dumped)

Syntakt's tracks are mono, right?

You're correct. Syntakt is a 20 mono outputs and 10 mono inputs Overwitch device. There are no stereo tracks, although two tracks with the same name but the L and R at the end could be considered as a stereo track.

I still need to learn more about Syntakt to understand the difference between Main and Input

This is particularly confusing.

  • Main L and Main R are the internal device mixer stereo output pair.
  • Main L Input and Main R Input are virtual input tracks that go directly into the main output. You can see them as a a pair of inputs that are mixed together with the main output.
  • The outputs labeled as Input L Input R are the hardware inputs in your Syntakt.

When adding stereo inputs, these options are available:
Analog FX
Delay/Reverb
Input
Main
Track 1
Track 11
Track 2
Track 4
Track 6
Track 8

Just to be clear, these are the 8 audio channels that go from Bitwig to your Syntakt. It looks weird as there should be 8 input tracks in your Syntakt named

  • Main L Input
  • Main R Input
  • Analog FX L Input
  • Analog FX R Input
  • Track 9 Input
  • Track 10 Input
  • Track 11 Input
  • Track 12 Input

Neither the names nor the amount match. Could you double check this o post a Bitwig capture or something?

This evening I turned on my PC, opened the Syntakt project in the DAW and... all the tracks I had configured were useless because this time Syntakt is on Address 13, this morning was in 14. Can this be prevented?

Just to be clear, these are the 8 audio channels that go from Bitwig to your Syntakt.

No, what I listed above were still inputs from Syntakt to Bitwig. In Bitwig you can add mono inputs or stereo inputs. What I wanted to say in my previous comment is that the list of mono inputs corresponds to overwitch-cli -vv -l (good) but the list of stereo inputs is the one I posted above (with the weird list of tracks). The numbers fit (6 pairs of "stereo" tracks = 12 tracks) what is weird is the track numbers shown and, well, even the notion of listing stereo tracks when they are just different mono tracks puts in pairs.

I haven't got yet to sending audio from Bitwig to Syntakt. And at least right now I'm not even sure I'd need this. My main interest is to get the separate tracks on Bitwig for audio manipulation and mixing there.

I just tested which Syntakt track appeared where, in case it is useful. In the left you have the label visible in Bitwig when selecting Stereo inputs. In the right you have the pair of Syntakt tracks:

Track 1 - Track 1 & Track 10
Track 2 - T2 & T3
Track 4 - T4 & T5
Track 6 - T6 & T7
Track 8 - T8 & T9
Track 11 - T11 & T12

At least now it's clear why these "stereo" tracks have these labels. But as said, they are rather pointless. I wonder who tells Bitwig about the existence of these "stereo" tracks. Is it Overwitch via JACK or something that JACK alone comes up with?

This evening I turned on my PC, opened the Syntakt project in the DAW and... all the tracks I had configured were useless because this time Syntakt is on Address 13, this morning was in 14. Can this be prevented?

I'm sorry. I didn't think about this. I will remove this antifeature tomorrow. The reason for this was to avoid the same issue when more than one machine of the same type is used.

I wonder who tells Bitwig about the existance of these "stereo" tracks. Is it Overwitch via JACK or something that JACK alone comes up with?

No idea. I don't use Bitwig but from the POV of JACK, which is the audio server, there are only mono tracks in this case so I think is Bitwig trying to pair them alphabetically.

It is very easy to solve if we name the tracks adding an extra space for the single digits ones.

I think is Bitwig trying to pair them alphabetically.

Yes, that makes sense.

Is there anything else I can do to help testing?

I think is Bitwig trying to pair them alphabetically.

Yes, that makes sense.

Is there anything else I can do to help testing?

Can you test what happens if you send in some audio to the Overwitch input ports?

@quimgil, I've hopefully fixed the alphabetical ordering and removed the bus and address from the device name.

Let me know if this actually works for you.

@szszoke

Can you test what happens if you send in some audio to the Overwitch input ports?

I can select from these outputs:

    Main L Input
    Main R Input
    Analog FX L Input
    Analog FX R Input
    Track 9 Input
    Track 10 Input
    Track 11 Input
    Track 12 Input

However, when I select any, this error message appears in the terminal multiple times:

ERROR:resampler.c:319:(ow_resampler_write_audio): j2o: Audio ring buffer overflow. Discarding data...

With the headset plugged in the Syntakt's headset plug, when I press a key on a Bitwigh synth, all I can hear is a buzz with a bit of pitch and significant lag. I guess that's the audio going through a lot of destruction?

(Note that at this point I don't even know what to do with incoming audio on the Syntakt i.e. if it is assigned to a track -- still learning the very basics.)

@dagargo Thank you! I got the 14 address this time, and I'll check tomorrow again (I need some sleep now). :)

Not sure what is happening with the audio that goes from JACK to Syntakt but I believe that the issue is that the Syntakt is reading at a slower byte rate than JACK is writing. I guess it's happening because the Syntakt expects N tracks but we are providing M, where M > N but the Syntakt is just buffering these, which causes the audio artifacts, BTW.

We can ensure than the track amount is right by changing this.

overwitch/src/engine.c

Lines 467 to 469 in 1556112

engine->usb.data_out_blk_len =
sizeof (struct ow_engine_usb_blk) +
sizeof (int32_t) * OB_FRAMES_PER_BLOCK * engine->device_desc->inputs;

The idea is to replace the engine->device_desc->inputs expression with a 6, 4 or 2 constant. The audio might be corrupted but the buffer will not be completely filled up. Whatever amount does not cause overflows it's the right one.

The manual is clear regarding this stating that there are 8 input tracks but...

It would be nice if you could try this.

For anyone reading this, no more new features will get into the version 1.0 but it's still open for fixes.

BTW, any update on the Overbridge device inputs?

I don't know whether you are interested in overwitch-dump feedback yet

Of course I'm interested. In fact, I've fixed a few issues in overwitch-dump including your issue. Looks like it's working nice now.

So I managed to get my hands on a Syntakt. Outputs seem alright for me so far, haven't tested inputs so I could do that for you. Thing is I've been using Pipewire and inputs passing through Overwitch for any of my devices kinda comes out extremely distorted (though I'm not sure if its a Pipewire thing or its because I haven't really done much to optimise my system for recording audio).

Didn't really report this before considering this project was still centred around JACK and I wasn't sure about the support for Pipewire.

Thing is I've been using Pipewire and inputs passing through Overwitch for any of my devices kinda comes out extremely distorted

Are you saying that you tried to send signals to a Digitone or Digitakt and they were distorted the same way as the Syntakt?

Yeah it ain't hot, usually around 300-400ms. Tested with A4, Heat, Digitone and now this.
2022-05-25_190033

Could it be possible that the issue happens only from JACK to Overbridge when using PipeWire?

If this was the case, could you try that with JACK instead? Is this huge latency happening with other clients?

Could it be possible that the issue happens only from JACK to Overbridge when using PipeWire?

If this was the case, could you try that with JACK instead? Is this huge latency happening with other clients?

During my testing I did try with JACK and I got the same distorted sound.

I never tried injecting signals into the inputs of other devices. I just assumed that they work.

In my case, the audio going from JACK to the Digitakt is clear and the measured latency of the buffer is below 2 ms.

Edit (typo): The latency is below 2 milliseconds, not seconds.

Both Main and FX outs are the same, just distorted. Mind you I haven't used JACK before nor do I know how to set it up properly but
2022-05-25_213126

Syntakt -> System -> Heat

Could you try with a lower number of blocks? Use 4 and medium quality.

What CPU ar you using? Is hypertheading or SMT active?

Will give it a try tomorrow and report back. CPU is AMD 3900x though haven't checked if SMT was on or not

I tested again with my Digitone now and there is no distortion when a signal is patched into the inputs.

I updated my Syntakt with the 1.01 OS update but that didn't change the anything.

Thanks for testing this again.

I'm pretty sure there is something in the protocol that makes it different in devices with more than 2 inputs.

There is a frame counter that goes in every Overbridge which doesn't look quite right to me.

I'm gonna do some research on this.

Is there something that I can do on my end?

How do you normally debug these things?

Wireshark and capturing USB traffic?

2022-05-26_222319
Routed Syntakt into Digitone but I hear nothing, though happy to see Digitone having such a low latency with JACK, wish it was like this with Pipewire.

2022-05-26_222356
... Digitone into Syntakt however was not too hot

2022-05-26_222912
Also tried Syntakt into Heat again with the settings you suggested and its still a bit high

Oh forgot to check SMT but considering that I was able to have something good with Digitone I don't think that was gonna be it. It was on when I tested.

The issue is most probably in the JACK to Overbridge code for devices with more than 2 inputs. Digitakt and Digitone work quite well.

For now, let's try one device at a time and JACK.

@serratedserenade, latency should be around 2 ms for you en every scenario and max latency should be around this value too.

@serratedserenade, latency should be around 2 ms for you en every scenario and max latency should be around this value too.

I think something messed up a bit for it to jump there cause I did remember it was lower.

Also however since it was a bit of time that I whipped out the Digitone with Overwitch I was able to achieve low latency with Pipewire, not sure what has changed since the last attempt but neat to know. Maybe I don't have to keep swapping between that and jack2 anymore.

Is there anything else you need me to do with the syntakt?

Is there something that I can do on my end?
How do you normally debug these things?
Wireshark and capturing USB traffic?

Wireshark on a borrowed Windows machine is what I normally use.

We need no more than 2 seconds of the USB traffic because we just need a few packages to check if the packages are the same. In order to record it you'll need a machine with Elektron Overbridge installed and Overbridge Control Panel running with a single Overbridge device connected.

@szszoke, could you try recording a few seconds in Wireshark of the Syntakt?

@serratedserenade, could you do this for the AnalogHeat too?

Thanks to both of you for helping me with this.

I'm dual-booting Windows so this won't be a problem.

Just to double check: I should have a signal sent to the Syntakt while I'm recording the USB traffic - correct?

Just to double check: I should have a signal sent to the Syntakt while I'm recording the USB traffic - correct?

Yes. I do nothing but turning the Overbridge Control Panel on.

Do you use some sort of filter?

I tried with usb.idProduct == 0x001e but I only get a single GET DESCRIPTOR message with USBPcap2 and nothing with USBPcap3.

I looked at the bus and device IDs in that single message and then based on those I created this filter:

usb.bus_id == 2 && usb.device_address == 5

I am now getting a lot of USB_INTERRUPT messages. Is that what you're looking for?

I had Overbridge Control Panel running and I let the capture run for a few seconds. Here is the file from Wireshark: syntakt_pcap.zip

I am now getting a lot of USB_INTERRUPT messages. Is that what you're looking for?

Yeah! It is! I'm taking a look at it now.

Sadly, everything looks as expected and I can confirm that the block structure is the same. Now, I expect it to be the same on the AnalogHeat.

But, what's the problem? I'm out of ideas. 😞

In the meantime, do you mind recording the same traffic but in Linux with Overwitch? Perhaps we saw something different.

I think I did it right in Linux with Overwitch, never really used Wireshark before. Did it with the Main and Analog inputs

syntakt_pcaps.zip

Thanks, @serratedserenade.

Everything looks nice, so the problem must be elsewhere.

Could you try running this from the command line to see if something happens? Let's go with the default amount of blocks and the lowest quality. There will be some errors and I'm interested in the first ones that will appear.

$ overwitch-cli -q 4 -vv
DEBUG:overwitch.c:195:(ow_get_devices): Found Digitakt (bus 001, address 005, ID 1935:000c)
DEBUG:engine.c:494:(ow_engine_init_mem): USB in block size: 368 B
DEBUG:engine.c:495:(ow_engine_init_mem): USB out block size: 88 B
DEBUG:engine.c:1201:(ow_engine_load_overbridge_name): USB control in data (32 B): Digitakt
DEBUG:engine.c:1221:(ow_engine_load_overbridge_name): USB control in data (16 B): 0064       1.30B
DEBUG:jclient.c:112:(jclient_set_sample_rate_cb): JACK sample rate: 48000
DEBUG:resampler.c:155:(ow_resampler_reset_dll): Resetting the DLL...
DEBUG:dll.c:114:(ow_dll_primary_reset): Target delay: 7.0 ms (336 frames)
DEBUG:jclient.c:489:(jclient_run): Using RT priority 5...
DEBUG:engine.c:1035:(ow_engine_activate): Starting p2o MIDI thread...
DEBUG:engine.c:1049:(ow_engine_activate): Starting audio and o2p MIDI thread...
DEBUG:jclient.c:112:(jclient_set_sample_rate_cb): JACK sample rate: 48000
DEBUG:jclient.c:102:(jclient_set_buffer_size_cb): JACK buffer size: 64
DEBUG:resampler.c:155:(ow_resampler_reset_dll): Resetting the DLL...
DEBUG:dll.c:114:(ow_dll_primary_reset): Target delay: 9.0 ms (432 frames)
DEBUG:jclient.c:102:(jclient_set_buffer_size_cb): JACK buffer size: 64
DEBUG:resampler.c:340:(ow_resampler_compute_ratios): Booting Overbridge side...
DEBUG:resampler.c:351:(ow_resampler_compute_ratios): Starting up resampler...
Digitakt@001,005: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 1.000002, avg. 0.999813
DEBUG:resampler.c:399:(ow_resampler_compute_ratios): Tunning resampler...
Digitakt@001,005: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999913, avg. 0.999934
Digitakt@001,005: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999891, avg. 0.999899
Digitakt@001,005: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999882, avg. 0.999884
Digitakt@001,005: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999876, avg. 0.999877
DEBUG:resampler.c:410:(ow_resampler_compute_ratios): Running resampler...
DEBUG:resampler.c:233:(resampler_o2p_reader): o2p: Emptying buffer and running...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 8064). Replicating last sample...
Digitakt@001,005: o2p latency:  0.5 ms, max.  1.4 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999890, avg. 0.999886
^CDigitakt@001,005: o2p latency:  0.8 ms, max.  1.6 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999889, avg. 0.999886
DEBUG:jclient.c:597:(jclient_run): Exiting...

Thanks.

A couple of observations.

  • You're not using the last master as I changed some debug lines to make it easier to detect the important errors. Also you use a non valid quality as seen in the first output line.
Resampling quality value must be in [0..4]. Using value 2...
  • You're having this error which might be part of the problem.
�[31mERROR:jclient.c:369:(set_rt_priority): Could not set real time priority

Addressing this depends on your OS so I can not help you much with this. When installing or reconfiguring JACK with sudo dpkg-reconfigure jackd2 I'm asked if I want to run JACK with RT priority but probably this isn't useful for you.

Take a look at the tunning section in the README.md and let me know if you've applied any of the suggestions.

So I:

  • use the performance governor
  • disabled SMT
  • restarted to use the RT kernel and set up all the RT stuff
  • pulled the latest version from master

Still the same result (badly distorted audio as before with the 300ms~ latency), though I can't get the logs for o2p to come up detailing latency when trying to output to a file (since it starts spamming the error hard).
cli_output.txt

I think we're really close.

In your output, there is something weird with this.

DEBUG:engine.c:1141:(ow_engine_set_p2o_audio_enabled): Setting p2o audio to 1...

This is telling the engine to start transferring actual audio to the devices via USB, otherwise the USB packets are filled up with zeroes. (I did this to save the resampling computations in case no audio is sent to the devices.)

When a connection to the device input ports is detected, the buffer is cleaned up and only from then on the audio sent by JACK is being copied to the device.

Under this scenario, the audio buffer is cleaned up before it needs to be. So, this might be the issue.

So, could you try this simple patch?

$ git diff
diff --git a/src/engine.c b/src/engine.c
index c068ed6..a760400 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -226,10 +226,15 @@ set_usb_output_data_blks (struct ow_engine *engine)
        {
          if (p2o_enabled && rsp2o >= engine->p2o_transfer_size)
            {
-             debug_print (2, "p2o: Emptying buffer and running...\n");
-             bytes = ow_bytes_to_frame_bytes (rsp2o, engine->p2o_frame_size);
-             engine->context->read (engine->context->p2o_audio, NULL, bytes);
-             engine->reading_at_p2o_end = 1;
+             if (ow_engine_get_status (engine) == OW_ENGINE_STATUS_RUN)
+               {
+                 debug_print (2, "p2o: Emptying buffer and running...\n");
+                 bytes =
+                   ow_bytes_to_frame_bytes (rsp2o, engine->p2o_frame_size);
+                 engine->context->read (engine->context->p2o_audio, NULL,
+                                        bytes);
+                 engine->reading_at_p2o_end = 1;
+               }
            }
          goto set_blocks;
        }

This will only empty the buffer and change the reading flag if the engine has reached the RUN status.

Try this, please, with 4 and 24 blocks and let me know your results.

Nothing has changed with the patch, logs and all.

Also on p2o audio to 1, I notice that only happens when I manually route something into its input, so I have been routing something into it before overwitch was ready.

Snippet of log when I wait till its ready before I make the connection in Carla

...
DEBUG:resampler.c:399:(ow_resampler_compute_ratios): Tunning resampler...
Syntakt@007,012: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 1.000006, avg. 1.000031
Syntakt@007,012: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999991, avg. 0.999999
Syntakt@007,012: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999981, avg. 0.999975
DEBUG:engine.c:1146:(ow_engine_set_p2o_audio_enabled): Setting p2o audio to 1...
Syntakt@007,012: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency:  0.0 ms, max.  0.0 ms, o2p ratio: 0.999980, avg. 0.999985
Syntakt@007,012: o2p latency: -1.0 ms, max. -1.0 ms; p2o latency:  0.0 ms, max.  0.0 ms, o2p ratio: 0.999984, avg. 0.999984
DEBUG:resampler.c:410:(ow_resampler_compute_ratios): Running resampler...
DEBUG:engine.c:231:(set_usb_output_data_blks): p2o: Emptying buffer and running...
DEBUG:resampler.c:233:(resampler_o2p_reader): o2p: Emptying buffer and running...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
DEBUG:resampler.c:216:(resampler_o2p_reader): o2p: Audio ring buffer underflow (0 < 13440). Replicating last sample...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
...

Another snippet when I let it on for some time, the moment I connect something to the input:

Syntakt@007,012: o2p latency:  3.7 ms, max.  6.6 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999986, avg. 0.999988
Syntakt@007,012: o2p latency:  5.7 ms, max.  6.6 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999990, avg. 0.999989
Syntakt@007,012: o2p latency:  4.2 ms, max.  6.6 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999987, avg. 0.999988
Syntakt@007,012: o2p latency:  6.2 ms, max.  6.6 ms; p2o latency: -1.0 ms, max. -1.0 ms, o2p ratio: 0.999987, avg. 0.999987
DEBUG:engine.c:1146:(ow_engine_set_p2o_audio_enabled): Setting p2o audio to 1...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
DEBUG:engine.c:231:(set_usb_output_data_blks): p2o: Emptying buffer and running...
Syntakt@007,012: o2p latency:  4.6 ms, max.  6.6 ms; p2o latency: 339.5 ms, max. 341.2 ms, o2p ratio: 0.999987, avg. 0.999987
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
ERROR:resampler.c:313:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...

I can't see where the issue is. 😞

I've added a few more debug messages, Perhaps, it'd shed some light.

I just need one single run but lets do it like this.

  1. Start overwitch with overwitch-cli -b 4 -q 4 -vv.
  2. Connect something to the inputs.
  3. Wait until the audio is actually being passed thru.
  4. Disconnect whatever was connected in step 2.
  5. Wait a second.
  6. Connect something to the inputs again.
  7. Wait a second.
  8. Disconnect whatever was connected in step 7.

TIA.

I think I followed it right
cli_output.txt

Been capturing the logs with overwitch-cli -b 4 -q 4 -vv 2>&1 | tee cli_output.txt by the way

I think you didn't git-pull the repo so the new messages didn't get in the log.

Could you try again? Sorry, if I wasn't clear enough about the new commits.

Yeah I just realised I messed up haha, sorry about that
cli_output.txt

This is on the latest master now. What message are you expecting to see?

EDIT: I see it now

I've just pushed a commit just in case the resampler is doing some bad thing internally when ratio is 0, which is my fault anyway. This could be the issue.

If it is, what's the libsamplerate version you are using?

I used libsamplerate 0.2.2 throughout my testing. I didn't have a chance to test your latest changes for today though.

The error is not resolved but the log looks different. There are a lot of MIDI events logged with 0 frames.

cli_output-2.txt

Thank you both for all the time and effort putting into this. 🙏
Sadly we're not there yet.

There are a lot of MIDI events logged with 0 frames.

These are incoming MIDI clock messages. You probably connected something to the Syntakt MIDI input in Carla.

These are incoming MIDI clock messages. You probably connected something to the Syntakt MIDI input in Carla.

That is my MIDI clock.

What happens if you apply this patch?

$ git diff
diff --git a/src/engine.c b/src/engine.c
index a5b9210..fa4d539 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -231,6 +231,14 @@ set_usb_output_data_blks (struct ow_engine *engine)
              debug_print (2, "p2o: Emptying buffer (%zu B) and running...\n",
                           bytes);
              engine->context->read (engine->context->p2o_audio, NULL, bytes);
+
+             rsp2o =
+               engine->context->read_space (engine->context->p2o_audio);
+             bytes = ow_bytes_to_frame_bytes (rsp2o, engine->p2o_frame_size);
+             debug_print (2,
+                          "p2o: Used space after emptying the buffer: %zu\n",
+                          bytes);
+
              engine->reading_at_p2o_end = 1;
            }
          goto set_blocks;

This is what I see.

DEBUG:resampler.c:411:(ow_resampler_compute_ratios): Running resampler...
DEBUG:engine.c:231:(set_usb_output_data_blks): p2o: Emptying buffer (512 B) and running...
DEBUG:engine.c:237:(set_usb_output_data_blks): p2o: Used space after emptying the buffer: 0

The buffer is correctly emptied before the resampler is writing data to the p2o (primary to Overbridge—or secondary) buffer. So, probably there is something wrong with the first writings or the ratio is miscalculated.

Could you try this patch so we can confirm that the error is there? I promise no more patches or anything in a few days.

$ git diff
diff --git a/src/resampler.c b/src/resampler.c
index 8ff4282..c3903f8 100644
--- a/src/resampler.c
+++ b/src/resampler.c
@@ -304,6 +304,9 @@ ow_resampler_write_audio (struct ow_resampler *resampler)
 
   if (bytes <= wsp2o)
     {
+      debug_print (2,
+                  "p2o: Writing to audio buffer (%zu B) with ratio %f...\n",
+                  bytes, resampler->p2o_ratio);
       resampler->engine->context->write (resampler->engine->context->
                                         p2o_audio,
                                         (void *) resampler->p2o_buf_out,

I'm looking for something different than this. The value should be around the JACK buffer frames/buffer (buffer size) times the number of samples/frame (8 in the case of the Syntakt) times 4 bytes/sample.

DEBUG:engine.c:231:(set_usb_output_data_blks): p2o: Emptying buffer (512 B) and running...
DEBUG:resampler.c:306:(ow_resampler_write_audio): o2p: Writing to audio buffer (512 B) with ratio 1.000115...
DEBUG:resampler.c:306:(ow_resampler_write_audio): o2p: Writing to audio buffer (512 B) with ratio 1.000115...
DEBUG:resampler.c:306:(ow_resampler_write_audio): o2p: Writing to audio buffer (512 B) with ratio 1.000115...

Haha, I don't mind doing these.
cli_output.txt

Will be the last one for the night.
Is the ratio meant to change over time?

Is the ratio meant to change over time?

After some time, the ratio becomes estable but during a few moments it's varies quite a lot. In fact this is the whole thing around Overwitch (and also Overbridge) audio transmission.
Although the main audio interface had a 48 kHz sample rate, it would never be 100 % the same as in the devices. The resampler behind Overwitch tries to equal the amount of samples per unit of time getting from the device and and ones getting into JACK.
The process is complex but basically starts at the theoretical ratio and recalculates it continuously in order to adjust the resampler so, in your case, you'll see some writings with 4128 instead of 4096. (This difference is actually only one sample, which is 8 tracks times 4 bytes/track.)

These are some selected lines from grep 2o cli_output.txt.

DEBUG:engine.c:1154:(ow_engine_set_p2o_audio_enabled): Setting p2o audio to 1...
DEBUG:resampler.c:307:(ow_resampler_write_audio): p2o: Writing to audio buffer (4096 B) with ratio 1.000194...
[...]
DEBUG:resampler.c:307:(ow_resampler_write_audio): p2o: Writing to audio buffer (4096 B) with ratio 1.000194...
DEBUG:engine.c:231:(set_usb_output_data_blks): p2o: Emptying buffer (16384 B) and running...
DEBUG:resampler.c:307:(ow_resampler_write_audio): p2o: Writing to audio buffer (4128 B) with ratio 1.000194...
DEBUG:resampler.c:307:(ow_resampler_write_audio): p2o: Writing to audio buffer (4096 B) with ratio 1.000194...
[..]
DEBUG:resampler.c:307:(ow_resampler_write_audio): p2o: Writing to audio buffer (4096 B) with ratio 1.000194...
ERROR:resampler.c:317:(ow_resampler_write_audio): p2o: Audio ring buffer overflow. Discarding data...
DEBUG:engine.c:231:(set_usb_output_data_blks): p2o: Emptying buffer (520480 B) and running...
[...]

Clearly, the issue is that the USB side is not awaken in time to copy the data from JACK into the USB blocks. This is why the audio is not only very delayed but also distorted, because great part of the incoming data is dismissed as it can't be written into the buffer.

Do you have any guess what could be causing this?

It can't be a driver issue because there is no driver - right?

It's Overwitch talking directly to the Syntakt.

Do you have any guess what could be causing this?

No idea. It's something in the code but I can't see it. 😞

It can't be a driver issue because there is no driver - right?
t's Overwitch talking directly to the Syntakt.

Exactly. It's just a JACK client that on the other end sends and receives USB packages in userspace for audio and MIDI.

I've done some tests and the activation of the J2O audio might be the issue. I'll remove it and let you know if you need to do other tests. Sadly, I won't be be able to take a look until Friday.