Optimize MIXXX for usage on PI2

Hello Folks,

This is my first post at the forum, but i use it passively for a months already, to fix my day-to-day MIXXX problems :slight_smile:

i got a new project i am working on. I want to build a open source musicplayer like a regular CDJ with the help of a Raspberry PI2. I know a few people who really would like to get a cheap DJ-Musicplayer with a nice display and the ability to play music from USB-sticks without paying 1000€ for a device which just plays mp3.
There are a few cheap players around 100-200€, but they are ugly ( :wink: ), don’t have a nice display and are not open source. The price of the whole thing should be below 100€. ( without case ) If the performance of the whole thing is good at the end, i was thinking to build it as a allinone-soluten for multiple decks.

As i really like MIXXX and i use it for my own DJing purposes, i want to use it as the SW-base for this project.
The hardwareside will involve a display(with touch), some buttons, faders, encoders and a decent jogwheel. Just the same stuff found on a CDJ. I plan to use a small generalpurpose microcontroller to provide the Input. That should be no problem.

The problem arises from the output to the display and limited performance of a PI2. I already bought a small 3,5" display, build a primitive skin which shows just the necessary waveform + metadata and tested the performance on the PI2.

Testsetup:

  • MIXXX 1.12 compiled on PI (armhf)
  • PI2 overclocked to 1000Mhz
  • Waveformsetting is “Filtered” without GL
  • external Soundcard
    Test results:
  • Waveform-framerate is fluctuating between 3-22fps
  • Sound is quite good. No artifacts.

Things to do at the SW-Side:

  1. get constant waveform-framerate around 25fps
  2. Change library-gui for USB-stick-only use.

My questions are:

  1. Where should i start trying to optimize the code to get a better framerate?
  2. Which parts could be disabled to get a better performance? (But i think i will need all threads: mixxx.org/wiki/doku.php/threads)
  3. Why are there still lots of cpu-resources unused (screenshot) although i got that bad framerate ?

If someone is interested in the project and want to help me, just give me a hint :slight_smile:

Cheers

Julian

Have you tried testing the various waveform options? Some work dramatically better on different machines.

Interesting Project.

The waveform drawing has bug room for optimizations. Any help is appreciated.

One issue is that we draw the entire waveform every frame without reusing a single pixel.
But changing this requires a mayor refactoring :-/

As a short term solution, it may work reasonable if you port the waveforms to openGL ES, which seams to be supported on the RaspberryPi.
There are some pending bugs:
bugs.launchpad.net/mixxx/+bug/1401283
bugs.launchpad.net/mixxx/+bug/1316402

I think it is hard to track the waveform draw pace by watching a CPU monitor.
Waveform drawing is done in a single thread among all other GUI stuff (and DB access). There are many wait conditions where the CPU is waiting instead of drawing, which leads to a jerking waveform.
Original I have tried to move Waveform drawing to a separate thead. This should be possible from the Qt docks, but I failed.
Currently we have a thread, that only managed that the right picture is drawed at the right time:
github.com/mixxxdj/mixxx/blob/m … thread.cpp

I tried to get my fingers on implementing a OpenGLES2.0 compatible Waveform. I used the hints from github.com/mixxxdj/mixxx/pull/706 to implement them using VBOs and GLES compatible commands only.

i compiled everything on my x86 Ubuntu machine without the regular GL linker flags. Instead i linked it with the GLES2.0 librarys by adding the flags to the GLES feature in /mixxx/build/features.py.
The waveforms work quite fine on the x86 machine.

Then i tried to move all the code to the PI2 and linked it to the libs on the PI2.
I also added the VideoCore specific commands to add GPU-acceleration for GLES: elinux.org/Raspberry_Pi_VideoCore_APIs#Quirks

I am able to compile everything but when i want to start mixxx, i am running into a Segfault. :frowning:
The last to debugmsg i can see are:

Debug [Main]: Created QGLWidget. Context Valid: true Sharing: true Debug [Main]: WaveformWidgetFactory::setWaveformWidget - waveform widget added in factory, index 0 Segmentation fault

If i run gdb backtrace i get:

Program received signal SIGSEGV, Segmentation fault. 0x76e44144 in ?? () from /usr/lib/arm-linux-gnueabihf/libQtOpenGL.so.4

So it must be Qt-related somehow. I tried to replicate that error on my x86 but without success.

So i got four questions:

  1. Anyone got a idea what could cause that error? I was wondering if the existing code (GUI,QGlWidget,etc. ) could have a problem with GLES?
  2. I cannot debug really good at the Pi to find the exact command which causes the Segfault. How could i get closer to the error? I already tried to put lots of qdebug()-msg in the code to get closer but without success…
  3. Should i post this message to the dev-maillist?
  4. Does it make sense to provide the code already?

As you might have noticed, its my first time i work on a big open-source project, so please dont blame me for my stupid questions :slight_smile:

Cheers
Julian

Yes and yes. Are you using git? It would be a good idea to post to the mailing list with a link to your fork of Mixxx on GitHub. More people who may know how to help would see this on the mailing list.

Yea! As i cleaned up the code and fed it into a fresh fork of the master branch, it strangely just work now on my Pi2 :smiley:
I dont have a big speed up on the PI2, but it works now “stable” with the OpenGLES Waveform around 6-7FPS (via X forwarding with SSH).

If you want to try it for yourself:

- git clone https://github.com/julled/mixxx.git
- If you want to compile it on PI2, you need to uncomment the corresponding section in /mixxx/build/features.py.
- scons opengles=1
  (add -jx to scons to speed up compilation via parallel compilation on x cores of the multicore-cpu) 
  (add machine=armhf for compilation on arm) 
- Choose "Filtered (GLSL)" in Preferences->Waveform

If you change the lib paths to the corresponding paths on your own ARM platform, it might compile and work.
I am still not sure if it is real GLES only, as Qt also uses GL somehow, but i am not that much into Qt to say how it uses GL or GLES.
Maybe someone got some ideas about that?

The other part of the story is, that i still need a big speedup to get higher fps…
As i was working on the code, i realized that the whole GUI part is still to complicated for me with all the Qtcode.
Thus i think i am also not able to put the drawing into a seperate thread.

Can you test the performance by plugging a monitor into your Pi rather than going through the network?

yes i know, but i am kind of limited to network only right over here…
But i dont think the bottleneck is the ethernet. I think the problem with low fps is there:

If there is also a DB access, this could lead to slow fps as there is only a SD-Card in the PI.
I think the best solution would be to put the Waveform into a seperate thread.+

Whats your opinion guys (+girls)?

Do you have a USB hard drive? You could try putting Mixxx’s settings directory (which includes its database) on there by using the --setingsPath command line option. A USB flash drive could be faster than a microSD card too.

Okey, i will try that later.

Okey i think i found the source of the GPU problem at the PI: raspberrypi.org/forums/view … 2&p=290309
It seems that mixxx uses softwarerendering, even if you write some GLES code for it. The package “libgl1-mesa-dri” installs the library "/usr/lib/arm-linux-gnueabihf/dri/swrast_dri.so ", which is basicly a softwarerasterizer for OpenGL. Thus mixxx uses softwarerendering via libGL even if i dont link it with it (strange?but maybe its somehow linked via qt?).
If i remove the driver, it fails to show anything in the waveformwindow:

libGL error: failed to open drm device: No such file or directory libGL error: failed to load driver: i965 libGL: OpenDriver: trying /usr/lib/arm-linux-gnueabihf/dri/tls/swrast_dri.so libGL: OpenDriver: trying /usr/lib/arm-linux-gnueabihf/dri/swrast_dri.so libGL: dlopen /usr/lib/arm-linux-gnueabihf/dri/swrast_dri.so failed (/usr/lib/arm-linux-gnueabihf/dri/swrast_dri.so: cannot open shared object file: No such file or directory) libGL: OpenDriver: trying ${ORIGIN}/dri/tls/swrast_dri.so libGL: OpenDriver: trying ${ORIGIN}/dri/swrast_dri.so libGL: dlopen ${ORIGIN}/dri/swrast_dri.so failed (${ORIGIN}/dri/swrast_dri.so: cannot open shared object file: No such file or directory) libGL: OpenDriver: trying /usr/lib/dri/tls/swrast_dri.so libGL: OpenDriver: trying /usr/lib/dri/swrast_dri.so libGL: dlopen /usr/lib/dri/swrast_dri.so failed (/usr/lib/dri/swrast_dri.so: cannot open shared object file: No such file or directory) libGL error: unable to load driver: swrast_dri.so libGL error: failed to load driver: swrast Warning [Main]: X Error: BadValue (integer parameter out of range for operation) 2 Extension: 154 (Uknown extension) Minor opcode: 3 (Unknown request) Resource id: 0x0 Warning [Main]: X Error: GLXBadContext 169 Extension: 154 (Uknown extension) Minor opcode: 5 (Unknown request) Resource id: 0x7e00012 Warning [Main]: X Error: 0 0 Extension: 154 (Uknown extension) Minor opcode: 26 (Unknown request) Resource id: 0x0 Warning [Main]: QGLTempContext: Unable to create GL context.

Any ideas to force hardware rendering?

Wow I just stumbled upon this post while researching another project. I actually had this same idea a few months ago but I do not have any experience in graphics programming so I could not write the waveforms for GLES. In my personal experience I noticed a few things while trying to make a better port for the Raspberry Pi.

You need a dedicated sound card. I have not tried a USB sound card (I have heard good things about them) but the Cirrus Logic audio card actually works really well and I can usually get somewhat of a mix going, it signficantly helps the latency. The latency on the raspberry pi is slow even going through HDMI it lags, I beleive this really has something to do with how ALSA gets prioritzed and how it allocates memory. I think it could be possible to run sound through HDMI but with limited usage.

You can look into trying to compile Mixxx using QT 5 (but then you would need to complie QT5) I never got QT5 to compile proerly, I have heard that it uses GLES and it works with the VC4.

I will complie the version by bambam on my Raspberry Pi 2 with the Cirrus Logic card as the output.

Ok I had to recompile the Kernel for the Cirrus Logic board and Raspbian Jessie. After that I compiled the master branch of Mixxx and used the opengles=1 flag. The results were much better than expected.

The only issue that I am noticing is that the pitch and BPM are very low (off by about 20-30 percent). This could be just a bug in this alpha release of Mixxx that I don’t know about.

I tried to run Mixxx in its own X window without starting X11 first. I ususall do this by

startx /path/to/mixx 

I am having a hard time passing --resourcePath res/ after that , maybe I typed it in wrong?

I’ll post a video later of it running, I’m sure there are a few people interested in Mixxx running on a platform like the Raspberry Pi. If anyone has any other ideas I would like to hear them.

EDIT: Pitch is off by about 40 - 50 percent.

EDIT 2: Here is a link to the video. https://vimeo.com/144671146

EDIT 3: I might have compiled Mixxx 2.1? I guess that is the version coming from master?

You may want to try (Without tailing slash):
–resorcePath res

Yes 2.1 is the version we use for master.

If the tracks are played too slow, this can be an symptom of buffer under-runs. However, your latency usage meter looks good.
Does the underflow counter increase in hardware preferences?

Generally, the shell syntax to pass commands as an argument to another command uses – to separate the commands. So, to pass an argument to mixxx when running mixxx with startx, try startx -- mixxx --resourcePath res

Otherwise, --resourcePath res will be passed as an argument to startx rather than mixxx.

Does this work well with the RGB waveforms?

The current development branch closely follows 1.12. We frequently merge the fixes from 1.12 back into master. I’m using it exclusively without any issues and would consider it even more robust and optimized than 1.12 for all file related functionality, i.e. audio decoding and parsing of metadata.

Unfortunately I don’t have any idea or explanation about what causes the timing issues that you describe :confused:

Try changing the pitch locking library. You can choose between Soundtouch and Rubberband in the preferences.

Ok I got it to run under just one window by iteself without runnning the entire desktop. I did notice a small differenece in response time but it might just be a placebo effect.

RGB waveforms work just as good as the filtered ones.

I also tried changing the pitch locking library as Be suggested, Soundtouch seemed to work the best, Rubberband was lagging to keep up with pitch changes.

It is worth pointing out that changing back to Rubberband did not yelid the pitch issues that I had before, theses seemed to go away completely. I am not sure why I had them in the first place. If you look at my video I posted the pitch had to be brought up about to 30 percent because set at 0% sounded very slow (slower than what the orginal track would sound like).

I am not noticing any buffer underruns as I normally would with the build in HDMI audio.

I am curious as to how I would complie the source to run a profiler on Mixxx. I would think this would be the next step in trying to sqeeze some more performance from the ARM CPU. I’ll be honest and say that I have never used Gprof, and it might be beyond my scope of knowdege. I am always willing to learn something new.

Cheers.

EDIT: I don’t know why I didnt try it before but 4 deck Mixing (although a little laggy) actually works too. Audio Latency is pinned in the red.

EDIT 2: This is with no overclock and no changes to memory.

Strange. That is definitely a bug. Please open a new bug report on Launchpad.

Rubberband is unfortunately rather slow. I can’t use on my old Asus EeePC either.

Run scons with the option “profiling=1”.

Nice. If the audio buffer meter is always in the red, increase the buffer size in the hardware preferences. This will increase latency.

I’ve been working on a somewhat similar project, but from the opposite direction. I built the midi controller side first and am now moving onto the dj software side. Some of the things I’m looking to do a bit different are i want to strip down mixxx to a single turntable, with pitch and bpm control, key lock, jogwheel, very small input joystick fpr track navigation, start/stop button, plus one or two more buttons for later assignments running on an RPI2. Sound card will be direct GPIO to DAC using the I2S bus, bypassing USB all together. midi input will still be over USB. Here’s something I was just reading in regards to running SoundTouch on an embedded multicore processor that I think will be of a lot of use to the current issues you guys are having with the pitch/bpm http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices/
here also are some pics of the prototype controller I’ve built :
http://imgur.com/a/noCmH/all