Linux

InTheWorks
Posts: 80
Joined: Sat May 28, 2022 11:59 pm

Re: Linux

Post by InTheWorks » Fri Dec 30, 2022 6:30 pm

NarcoticV wrote:
Fri Dec 30, 2022 1:32 pm
Just out of curiosity: do you have an idea of what kind of latency is needed for it to be unnoticeable for you?
This is tough to answer.

Aerodrums is a little different than other electronic drums because you don't hear the stick on the pad. How you 'feel' it is when you *think* you hit the snare vs when you hear it. There are no real audio cues to hear the latency.

With acoustic drums there's already latency built in due to the speed of sound and the distance between stuff; approx 3ms to travel 1m. You get that with the scan time on electronic drums. Were I designing as electronic drum system, I would make 10ms an upper bound and aim for 7ms or less. I have no idea what the latency is on my yamaha dtxm12, but I don't hear flams between the sticks hitting the pads and the audio coming out of the headphones.

Meanwhile, you can fake stereo audio by duplicating a mono channel and adding 10 to 20ms of latency to it. That's a difference between ears. So not exactly the same.

According to wikipedia:
https://en.wikipedia.org/wiki/Precedence_effect

The precedence effect occurs between 10 and 30ms. I know with speech, 30ms of latency in echo is noticeable, but not distracting. I've measured that. So I would say less than 20ms. But it's not something I've measured for drums.
NarcoticV wrote:
Fri Dec 30, 2022 1:32 pm
Are you aware of the wine alsa driver? This should expose your ALSA devices directly to Aerodrums. I found that if I run "winecfg" I cannot change the audio driver (which is by default set to winepulse). But after running "winetricks sound=alsa" (which I think only makes some registry edits), the driver is set to winealsa and it seems to work. Would be interesting for your latency comparison.
Yeah after my last post I tried alsa. Winetricks told me the prefix was 64bit by the way and there is a syswow64 directory. But Aerodrums installs itself in "Program Files (x86)" . Is that the reason 32-bit libusb0.dll is needed?

The latency was still bad with alsa. I had a look in /proc/asound/.../hw_params and the period size was set to 441 and the buffer size to 1764. That' a 10ms period and 40ms buffer size. And while that's bad it doesn't explain the ~100ms of total latency which means 60ms must exist somewhere between aerodrums and alsa.

I had a look at the source for both winepulse.drv and winealsa.drv. As I recall they both set a buffer size of 4x the period, but I didn't see where the period was defined. Anyway without recompiling the wine drivers (not user friendly), there's no way to reduce the latency there.

I think the only solution might be wineasio so I will look at that again. It only supports a jackd backend, but perhaps it's worth adding an alsa backend. As I recall from before, there were drop outs with jackd. Which is why I started looking at adding realtime flags to wine. Which then lead me to wine staging.

InTheWorks
Posts: 80
Joined: Sat May 28, 2022 11:59 pm

Re: Linux

Post by InTheWorks » Sat Dec 31, 2022 6:25 am

I think I found a workable solution using wineasio. It's ugly, but it's the only way to get decent latency and have the same usability as Aerodrums on windows. Latency is 18ms with 128 sample buffer. 64 sample buffer didn't work, but I didn't look into why.

I compiled wineasio from git which was important because there was some information there that I would have missed otherwise. You can probably install the debian package from kxstudio instead of compiling, but I didn't test it. The repositories can be added using the instructions here:

https://kx.studio/Repositories

at which point you should be able to "apt-get install wineasio". You will still need to follow the rest of these instruction, but you can skip building wineasio.

I built wineasio for 32-bit because libusb-wine is 32-bit. There's still a bit of a mystery there. So I had to install some extra packages (I already had libjack-jackd2-dev installed which is 64bit).

Code: Select all

$ sudo apt-get install libwine-dev libwine-dev:i386 libjack-jackd2-dev:i386

This ends up installing the following packages:
libwine-dev wine64-tools libc6-dev:i386 libcrypt-dev:i386
libwine-dev:i386 linux-libc-dev:i386
libjack-jackd2-dev:i386
The next step is to compile. Note that this is ubuntu specific. I don't know how the paths work out on other systems. You'll see that I had to adjust one of the include paths to point to a place that worked on my system.

Code: Select all

$ wget https://github.com/wineasio/wineasio/releases/download/v1.1.0/wineasio-1.1.0.tar.gz
$ tar xf wineasio-1.1.0.tar.gz
$ cp /path/to/build.patch wineasio-1.1.0/
$ cd wineasio-1.1.0/
$ patch -p0 << build.patch
$ make 32
$ sudo cp build32/wineasio.dll.so /usr/lib/i386-linux-gnu/wine/wineasio.dll.so
$ regsvr32 wineasio.dll
This is build.patch. I will include it in a tarball attached to this post. You'll need to remove the .txt extension that I had to add to upload it.

Code: Select all

--- Makefile.mk
+++ Makefile.mk
@@ -33,7 +33,7 @@
 RCEXTRA               =
 INCLUDE_PATH          = -I. -Irtaudio/include
 INCLUDE_PATH         += -I$(PREFIX)/include/wine
-INCLUDE_PATH         += -I$(PREFIX)/include/wine/windows
+INCLUDE_PATH         += -I$(PREFIX)/include/wine/wine/windows
 INCLUDE_PATH         += -I$(PREFIX)/include/wine-development
 INCLUDE_PATH         += -I$(PREFIX)/include/wine-development/wine/windows
 INCLUDE_PATH         += -I/opt/wine-stable/include
@@ -107,5 +107,5 @@
 	$(WINEBUILD) -m$(M) --dll --fake-module -E $(wineasio_dll_MODULE).spec $^ -o $@
 
 build$(M)/$(wineasio_dll_MODULE).so: $(wineasio_dll_OBJS)
-	$(WINECC) $^ $(wineasio_dll_LDFLAGS) $(LIBRARIES) \
+	$(WINECC) -m$(M) $^ $(wineasio_dll_LDFLAGS) $(LIBRARIES) \
 		$(wineasio_dll_DLLS:%=-l%) $(wineasio_dll_LIBRARIES:%=-l%) -o $@
Next you need to install jackd. I don't know if it was already installed or not since my system isn't fresh. The other piece is qjackctl:

Code: Select all

sudo apt-get install qjackctl
At this point you should be able to open qjackctl, start the jack server, and then start aerodrums. In aerodrums you should see the wineasio device and be able to select it. There may not be any sound yet. Some caveats:

1. the latency will be bad until we fix it
2. the volume may be low until we fix it
3. it's not clear to me what device qjackctl takes over by default
4. pulseaudio will not have any output through jack until we fix it

We can fix the latency by editing the registry. This was the important piece I learned from building from source. So run regedit and make these changes:

Code: Select all

HKEY_CURRENT_USER\Software\Wine\WineASIO\fixed buffer size set to 0
HKEY_CURRENT_USER\Software\Wine\WineASIO\preferred buffersize set to 128
You may not need to change the preferred buffer size. It appears that setting the fixed buffer size to 0 allows aerodrums to control the buffer size. You can see this in qjackctl by showing the Messages window.

The volume control of the jackd audio can be adjusted using alsamixer. Just be warned that the ubuntu volume control, at least on my machine, directly adjusts the same mixer setting via pulseaudio. What this means is if you normally have your system at 50% and after starting the jack server from qjackctl, anything played through jack will be at 50% volume. If you adjust the ubuntu volume control to 100% it won't affect anything (because pulseaudio is not routing through jack yet). However, when you stop the jack server, the pulseaudio volume will be at 100%, not 50%. There is a workaround for this using qjackctl scripts.

You can set the alsa device qjackctl uses. When you open qjackctl, click the Settings button. On the settings tab, pick the interface you want to use. You'll want to make sure it looks like the following:

driver = "alsa"
tick the box "Realtime"
set the device to the one you want
samplerate: 44100
frames/period: 128
periods/buffer: 2

To get jack to play nicely with pulseaudio:

First save the qjackctl scripts somewhere. I have mine in ~/bin/ where I keep other scripts. Make sure they are executable (chmod +x). On the Settings->Options tab in qjackctl, tick the following boxes and paste the following into the text fields.

Code: Select all

Exectute script after Startup:
/path/to/bin/qjackctl-start-post.sh

Execute script before Shutdown:
/path/to/bin/qjackctl-stop-pre.sh

Execute script after Shutdown:
/path/to/bin/qjackctl-stop-post.sh
When you start the jack server from qjackctl, pulse will route to jack and system sounds will come out through the jack device. The scripts also attempt to preserve the volume before and after the jack server has started. The scripts also make sure that pulsaudio can play through jackd without user intervention. This is assuming you want to use the same audio device for aerodrums and system audio (like youtube videos).

Note: You may want to experiment with the volume control on the alsa device. At least on my machine, using

Code: Select all

amixer -q -c "$ALSADEV" set Master 100%
100% is far too loud and makes for really low volumes (like 2% song volume) in the aerodrums interface. This is likely to be sound card and headphone dependent.

qjackctl-start-post.sh

Code: Select all

#!/bin/sh

#Get the script's directory not the running directory
DIR="$( cd "$( dirname "$0" )" && pwd )"

# The default sink name is the sink currently in use.
SINK=$(pacmd stat | grep "Default sink name:" | cut -d : -f 2 | cut -d ' ' -f 2)

# Get the volume of the currently used sink.
VOL=$(pulsemixer --get-volume | cut -d ' ' -f 1)

# parse SINK to turn alsa_output.pci-0000_00_1f.3.analog-stereo
# into pci and 0000:00:1f.3
# This way we can construct /sys/bus/pci/devices/0000\:00\:1f.3/sound/card0/id
# which holds the name of the card we can use in amixer.
TMP=$(echo $SINK | cut -d '.' -f 2,3)
BUS=$(echo $TMP | cut -d '-' -f 1)
TMP2=$(echo $TMP | cut -d '-' -f 2)
DEV=$(echo $TMP2 | sed 's/_/:/g')

# I don't know if this is always true. It should be for alsa devices.
ALSADEV=$(cat /sys/bus/$BUS/devices/$DEV/sound/card0/id)

# Save these variables to file.  We'll need them from other scripts.
echo "$SINK" > $DIR/pulseaudio-sink
echo "$VOL" > $DIR/pulseaudio-vol
echo "$ALSADEV" > $DIR/pulseaudio-alsadev

# set the jack sink as the currently used sink
pacmd set-default-sink jack_out
sleep 1
# After setting the sink, set the jack sink volume to be the old
# volume.  Since we will make the device volume maximum, we should
# get the same volume before and after the switch.
pulsemixer --set-volume "$VOL"

# the device volume is probably where pulseaudio left it.  We need to
# make sure it is maximum so that aerodrums has full control of the
# available volume.
amixer -q -c "$ALSADEV" set Master 100%
qjackctl-stop-pre.sh

Code: Select all

#!/bin/sh

ALSADEV=$(cat /home/algo/bin/pulseaudio-alsadev)

# we have to do this prior to stopping the jack server or when pulseaudio
# detect that jack has stopped, it switches.  Maybe.
# This guarantees that the volume should be muted before anything changes
# on the pulseaudio side.  And prevents having the volume at max unintentionally.
amixer -q -c $ALSADEV set Master 0
qjackctl-stop-post.sh

Code: Select all

#!/bin/sh

SINK=$(cat /home/algo/bin/pulseaudio-sink)
VOL=$(cat /home/algo/bin/pulseaudio-vol)

pacmd set-default-sink $SINK 
# don't try to set the volume too quickly or the
# sink change won't have happened yet.
sleep 1
pulsemixer --set-volume $VOL
Using these scripts, you can control the volume from within aerodrums using the drumstick interface.

If you are not using ubuntu 20.04 you may need to modify these instructions. I think Ubuntu 20.04 has the pulseaudio-jack module already installed and /etc/pulse/default.pa is set up to load it. The name of the jack sink may not be the same so the scripts I provided will need to be changed. The master volume on your device may not be called "Master". Little things like that.

This rigamarole is difficult, but I don't know how to make it any easier.
Attachments
wineasio.tar.gz.txt
(1.5 KiB) Downloaded 589 times
Last edited by InTheWorks on Sun Jan 01, 2023 8:07 pm, edited 1 time in total.

InTheWorks
Posts: 80
Joined: Sat May 28, 2022 11:59 pm

Re: Linux

Post by InTheWorks » Sun Jan 01, 2023 10:00 am

elloh wrote:
Fri Jul 15, 2022 8:55 pm
(I installed aerodrums using wine64).
Going back to this post, I decided to install aerodrums in a 64bit prefix:

Code: Select all

WINEPREFIX=~/.wine64 wine64 ~/Downloads/aerodrums-setup-v1-1-2.exe
But aerodrums wants to install itself to "C:\Program Files (x86)\Aerodrums" which, as I understand it, is for 32-bit programs.

The default wine prefix is setup as Windows 7, so I configured one for Windows 10 before installing aerodrums and it still wans to install to "C:\Program Files (x86)\Aerodrums".

Based on this, I don't see how 64-bit Aerodrums is being installed. Does this explains why 32-bit libusb and wineasio are needed?

InTheWorks
Posts: 80
Joined: Sat May 28, 2022 11:59 pm

Re: Linux

Post by InTheWorks » Sun Jan 01, 2023 10:24 am

One last observation.

Code: Select all

mv ~/.wine64/drive_c/windows/system32 ~/.wine64/drive_c/windows/system32.bak
WINEPREFIX=~/.wine64 wine64 ~/Downloads/aerodrums-setup-v1-1-2.exe
results in an error

Code: Select all

00b:err:wineboot:process_run_key Error running cmd L"C:\\windows\\system32\\winemenubuilder.exe -a -r" (2).
So the aerodrums installer appears to be 32-bit. Maybe Sipaliwini could chime in with how the installer determines a 32-bit vs 64-bit install.

InTheWorks
Posts: 80
Joined: Sat May 28, 2022 11:59 pm

Re: Linux

Post by InTheWorks » Sun Jan 01, 2023 7:59 pm

InTheWorks wrote:
Sat Dec 31, 2022 6:25 am
1. the buffer setting in aerodrums will never do anything

We can fix the latency by editing the registry. This was the important piece I learned from building from source. So run regedit and make these changes:

Code: Select all

HKEY_CURRENT_USER\Software\Wine\WineASIO\fixed buffer size set to 0
HKEY_CURRENT_USER\Software\Wine\WineASIO\preferred buffersize set to 128
Even though you change the fixed buffer size registry key to 0, that doesn't allow aerodrums to change the buffer size like it should. Instead you will always get the preferred buffer size. This should match what you have set in qjackctl. You'll have to make it match if 128 doesn't work for you.
[/code]
I noticed that this is not true. I will edit the original post, but when fixed buffer size is set to 0, the buffer size slider does work in aerodrums.

I'll also add that you may not want to set the Alsa volume control to 100%. It requires some very low percentages in the Aerodrums volume control. At least that's the experience on my machine.

InTheWorks
Posts: 80
Joined: Sat May 28, 2022 11:59 pm

Re: Linux

Post by InTheWorks » Sun Feb 26, 2023 11:37 pm

I just discovered something about my setup that may explain why my dock doesn't perform as well as my laptop headset jack.

In order to play from aerodrums, we generally need 44k1 sample rate. My dock doesn't support 44k1 and it's also using a funky format S24_3LE. Actually that's probably the same as my Scarlett 2i2. The problem is that my dock *only* supports those 2 combinations.

Code: Select all

$ alsa-capabilities -s
 2) USB Audio Class Digital alsa audio output interface `hw:0,1'
 - device name       = Dock                                                        
 - interface name    = USB Audio                                                   
 - usb audio class   = (n/a)                                                       
 - character device  = /dev/snd/pcmC0D1p                                           
 - samplerates (Hz)  = S24_3LE:48000                                               
 - monitor file      = /proc/asound/card0/pcm1p/sub0/hw_params                     
 - stream file       = /proc/asound/card0/stream1

 3) Analog alsa audio output interface `hw:1,0'
 - device name       = PCH                                                         
 - interface name    = ALC3204 Analog                                              
 - usb audio class   = (n/a)                                                       
 - character device  = /dev/snd/pcmC1D0p                                           
 - samplerates (Hz)  = S16_LE:44100,48000,88200,96000,176400,192000,352800,384000  
                       S32_LE:44100,48000,88200,96000,176400,192000,352800,384000  
 - monitor file      = /proc/asound/card1/pcm0p/sub0/hw_params                     
 - stream file       = (n/a)
Device number 3 above is my laptop headset jack and it can support 44k1 with S32_LE. From what I see in qjackctl, this is the format aerodrums uses:

Code: Select all

Sun Feb 26 14:16:02 2023: New client 'aerodrums' with PID 178595
Sun Feb 26 14:16:02 2023: Client 'aerodrums' with PID 178595 is out
Sun Feb 26 14:16:02 2023: New client 'aerodrums' with PID 178595
Sun Feb 26 14:16:03 2023: configuring for 44100Hz, period = 128 frames (2.9 ms), buffer = 2 periods
Sun Feb 26 14:16:03 2023: ALSA: final selected sample format for capture: 32bit integer little-endian
Sun Feb 26 14:16:03 2023: ALSA: use 2 periods for capture
Sun Feb 26 14:16:03 2023: ALSA: final selected sample format for playback: 32bit integer little-endian
Sun Feb 26 14:16:03 2023: ALSA: use 2 periods for playback
That may explain why I couldn't get good performance with my dock as it requires resampling and format conversion. Just wanted to add this information to this thread in case it helps anyone.

If aerorums could support different formats and sample rates, then this wouldn't be a problem. I seem to recall an experimental 48kHz build, but I don't see an option anywhere in the software and nothing obvious in aerodrums.cfg for 48kHz settings.

Post Reply