surge-synthesizer / stochas

The Stochas Sequencer
https://stochas.org
GNU General Public License v3.0
404 stars 35 forks source link

Building on Raspberry Pi #74

Closed tyberion closed 3 years ago

tyberion commented 3 years ago

I am trying to build Stochas on the Raspberry Pi 4b and everything seems to be going well, the build succeeds without errors, however there are a few things that don't work.

Does anyone know what might be wrong?

rudeog commented 3 years ago

You are definitely entering into bleeding edge territory here, and are probably the first person to try this. All I can suggest (for the vst3) is to see if there is another JUCE based plugin that you can build and have it scan by reaper.

baconpaul commented 3 years ago

Surge 19 builds and scans reaper on 64 bit pi. I think j the head of code will too

I have never tried stochas! I should when I fire up my pi next

tyberion commented 3 years ago

I have succesfully compiled Surge, but that runs as an lv2 I will try compiling it as a vst as well. Is there any way of getting more debug information while running Stochas to see what might be wrong?

tyberion commented 3 years ago

Surge indeed successfully compiles as a vst3 and runs flawlessly on Reaper...

baconpaul commented 3 years ago

Yeah the surge lv2 is full of bugs which no one ever fixed - the vst3 is way better

as to stochas hmm I would start by seeing if it validates in the Streinberg validator or loads in the juce audiopluginhost - I wonder if the midi in out topology is tripping it up

rudeog commented 3 years ago

Yeah, I think Paul is right. Stochas has some non-standard settings wrt to how it's configured. You could try playing with some of those settings in the cmakefile. specifially is syth, is midi effect, needs midi in/out

tyberion commented 3 years ago

I tried several things this afternoon unfortunately to no avail, Stochas still behaves like described above... The things I tried:

rhall4242 commented 3 years ago

The reason the plugin won't load in Reaper is because the subdirectory name under 'Contents' in the VST3 directory is 'arm64' not 'aarch64'. Change it and it will load. But it still won't work right, that's a bigger mystery...

rudeog commented 3 years ago

Well at least you made some progress!

baconpaul commented 3 years ago

oh we should check at head of code with surge to see what architecture it chooses there. (Surge 1.9 hard codes it; Surge at head uses juce)

Why not compile the steinberg validator from the VST3 SDK and try and load the plugin? You can attach a debugger to that and see where it fails. That's what I would try next (I don't have a pi with me right now).

rhall4242 commented 3 years ago

Let me be a bit more specific and share some observations (it was late last night when I wrote the previous comment). First of all, I am running on 64-bit Raspberry Ubuntu 21.04 Desktop, although I also tried building on 32-bit Raspian and had the same incorrect behavior in Standalone and VST3. What I meant to say about the (64-bit) plugin is that the directory should be 'aarch64-linux', not 'arm64-linux'. Now, as for other observations:

1) I have built both Release and Debug versions using g++ and/or clang++, all behave the same. When compiling using clang++ I get numerous warnings in many source files about comparisons of -1 to (signed) char always being true or false depending on == or !=. I suspect this is probably due to something typedefed to char which maybe should be unsigned char.

2) The root of the operational problem seems to be that for some reason, all of the grids seem to be continually refilled with the magic value '157'. This is clearly visible in the velocity and shift grids (screenshot attached), and probably in the others as well, just not visible due to the display method of those screens. If you clear the pattern or layer, the values return almost instantly. The reason that it keeps sending MIDI note offs seems to be because the velocity is '157' which being greater than 127 seems to mae it send a note off (velocity 0) message. If you drag on one of the velocity cells and make it below 127 and keep it long enough for that cell to be triggered, a note on gets sent, but 157 gets put back almost immediately.

At first glance, all of these issues seem to point to some data type which ends up being different size and/or signed/unsigned when compiled for arm (I'm now only working with 64 bit, but the same things seem to happen with 32 bit). Like Intel processors, Arm is little-endian, so it's not likely that. But it may be that it's working by {coincidence, good luck} on the Intel processors.

Anyway, I hope this may give some clues as to the problem. It may be as simple as modifying a typedef or two in header files to keep all processors happy. Hope this helps...

Screenshot from 2021-05-31 11-14-07

rudeog commented 3 years ago

So it sounds like something is setting each and every cell to invalid values. It also sounds like it's not some initial state, but rather something that is continually updating and setting these cells (as you said that if you set one of the cells differently it will go back to the invalid value). I am trying to think what we have running that might be responsible for doing this continually. As you said, there is probably some assumption that is being made about Intel which behaves differently on arm.

The file SequenceData.h is where the actual memory layout is described (see SequenceLayer). If you see anything in here that looks suspect (eg alignment, or other) with regard to arm, let us know.

rhall4242 commented 3 years ago

Yes, the identical bad behavior occurs in VST3 or Standalone, Release or Debug, g++ or clang++, 32 bit Raspian (32-bit compiler) or 64 bit Ubuntu (64 bit compiler). And the value is ALWAYS 157 in every cell, which leads me to believe its not just a wild pointer pointing to some random place in memory. And yes, even when the transport is not running, if I drag down a velocity value, it goes up and down with the mouse, but as soon as I release the mouse button it instantly snaps back to 157. Another thing is that in the probability page, you can drag through low, med, high, but as soon as you release the mouse the cell appears blanking. When you run the transport notes get the little black tick mark in any place randomly, suggesting that all cells have something (157?) in them, just not low, med, high. If you drag the right side of a cell rightwards, you do see the extension bar, and it remains on the screen. As for alignment problem, I have no idea if that is really what it is, it is just something I've encountered in the past when there a strange values when you are porting code. I thought it might suggest something to someone familiar with the code. The problem could be in libraries, not the source code. However, on the 32 bit Raspian I got the libraries from the Raspian apt-get repository and on the 64 bit Ubuntu from the Ubuntu repository. I will take a look at SequenceData.h. I was hoping not to have to get into it this deeply. I am trying to get some of the same things I have working on my Intel laptop working on Raspberry. This is not one I expected to have trouble with. Surge, by the way, works perfectly, although it uses a bit more CPU than on Intel, especially when idling. Other Juce applications work fine, including one I wrote, but again idling CPU is higher than on Intel, especially when connecting to Jack vs PulseAudio.

rhall4242 commented 3 years ago

As for SequenceData.h, I see a lot of places where 'char' is used to hold non-character (i.e small integer) values. I'm not sure that it is 100% safe in this day and age to assume that char will always be a 7-bit value with a sign bit. There also seems to be some values that are signed and others which are unsigned. 157 is not a possible value for traditional signed char. It is -99 in twos-complement format. Remember I pointed out about all the clang warnings about comparisons to -1 always being true or false. I definitely think this is at the root of the problem, although I'm not exactly sure how. It also occurred to me that it could be treating char as unicode or something, but I think something in the handling of signed/unsigned is more likely.

baconpaul commented 3 years ago

-99 is MOUSE_STARTVAL_INVALID which is used as a sentinel often in the StepPanel code. That seems to be the only spot.

The C++ spec says super clearly that char is an 8 bit storage (as is unsigned char and signed char)

but i wonder if it is a sign thing. If you change src/StepPanel.h variable mTempValue from "char" to "signed char" does the problem resolve? Or from char to int8_t?

Again still don't have a PI up and running, and i don't know the stochas code all that well, but seems like this would match what you are saying happens.

baconpaul commented 3 years ago

Oh huh also TIL that whether char is signed or unsigned is indeed implementation specific. The only thing required is that it is 1 byte. So changing mTempValue from char to signed char may indeed solve the problem (or even better, int8_t)

And hey voila:

char is signed on Intel and unsigned on ARM (the Pi)`

https://www.raspberrypi.org/forums/viewtopic.php?t=233557

So I guess: I would try changing char to int8_t everywhere until it works then fire in a PR!

rhall4242 commented 3 years ago

I had been thinking along the same lines. I wonder if there is a compiler flag which changes the default signed/unsigned behavior? Even so, using int8_t or byte would be clearer as to the intention. I've always avoided using char for anything but actual characters. I'll try int8_t and see what happens...l

baconpaul commented 3 years ago

I think it is hard to do with a compiler flag but def worth a google. A few decades of midi programming and bad c++’specs have led folks to use char but the specific type is better indeed and nowadays int8_t or uint8_t is the best choice

tyberion commented 3 years ago

I tried changing the char to int8_t and that seems to have fixed the problem.

baconpaul commented 3 years ago

Ok great! So I guess we should look for other structure values - want to send in a pull request?

and great! Thank you!! This is probably also a problem on m1 so great to know

rudeog commented 3 years ago

Yes, thank you very much Maarten!

tyberion commented 3 years ago

I have created a pull request for this issue which should solve it.

rhall4242 commented 3 years ago

(Whew!) I had already started doing it myself when I saw you had already done it, so decided to keep going forward, and just got it working myself. But I will go ahead and use your source when it is in the repository. There were a LOT of changes, and many cases where char actually was referring to chars so you had to be very careful about what was changed. If I were starting from scratch to write a MIDI program, I would probably go one step further and do something like:

typedef int8_t midi_note_t; typedef int8_t midi_vel_t;

etc. This is what I (we) have typically done in my professional experience interfacing to industrial tools when referring to values which represent an external entity such as protocol element or device data type.

rudeog commented 3 years ago

Yeah the typedef would have been the better way to go if starting from scratch.

tyberion commented 3 years ago

So after some experimentation it turns out there was a lot more chars that needen to be changed to int8_t for Stochas to work properly on the raspberry pi and I have created a pull request for those changes, it is however a lot more work to check if everything was done correctly...

rudeog commented 3 years ago

Wow this looks like it was a lot of work! Thanks!