Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting Audio Unit to link on macos #58

Closed
baconpaul opened this issue Dec 8, 2018 · 32 comments
Closed

Getting Audio Unit to link on macos #58

baconpaul opened this issue Dec 8, 2018 · 32 comments

Comments

@baconpaul
Copy link
Collaborator

Hi!

So I just got the audio unit code to link on macOS. Don't have it packaged but have it linking. There are a few larger things I had to do to do this.

The code I have isn't really mergeable yet I don't think. (I did some radical things like remove the VST target in my premake for now for instance). And I have no idea if it works. But if you want to see what I did the whole thing is pushed on this fork (https://github.com/baconpaul/surge/tree/au-build) and you can just check that out by cloning my fork and hopping on to branch au-build.

There's a few bit things which were wrong in addition to the minor bits and bobs I already put in other issues (like the OBJC_PROTOTYPE and the missing header I did a PR for). The amounted to 2 enormous things

  • In order to build an AU V2 you need the AUPublic and PublicUtility code from the audio toolkit available. This is actually referenced in the premake5.lua (look https://github.com/kurasu/surge/blob/c6ad95dfa051649f5647b0064fe8b0548680c08a/premake5.lua#L460 at that line) but the source wasn't in lib. The source actually isn't all that easy to find but luckily other GitHub projects have it included so I did the following

  • So great now we have all the code we need to build an AUV2. But the other problem was that class names had changed since src/au too today. So go through and replace all the sub3_synth with SurgeSynthesizer and all the names_like_this with namesLikeThis, comment out one place I couldn't figure out in presets for a link error and put in a fix me, and

voila! A linking surge-au.

So anyway I'll keep picking on this some but if others are working I thought they may want to know how close I got and look at the code in my branch.

Hope this is helpful. Welcome all comments.

@baconpaul
Copy link
Collaborator Author

Oh and I meant to tag @esaruoho in this since he and I were chatting about it in last few days

@esaruoho
Copy link
Collaborator

esaruoho commented Dec 8, 2018

@baconpaul could you provide an image or a list of the files you grabbed from @getdunne's folder in AudioKit? Would help immensely. :) (see comment below)

@esaruoho
Copy link
Collaborator

esaruoho commented Dec 8, 2018

no, sorry, i was misguided.. you already have /libs/AUPublic there! thanks!

@esaruoho
Copy link
Collaborator

esaruoho commented Dec 8, 2018

i went and added vst3sdk as an includedirs in premake5.lua just to see if that would also assist :)

@esaruoho
Copy link
Collaborator

esaruoho commented Dec 8, 2018

I got this far:

linker command failed with exit code 1 (use -v to see invocation) clang

surge-au_xcodeproj_and_getting_audio_unit_to_link_on_macos_ _issue__58_ _kurasu_surge

but yeah, i've never seen it get this far! amazing work, @baconpaul !

@baconpaul
Copy link
Collaborator Author

Yeah I just changed two things which fix those errors. DO a fresh checkout.

This just worked for me, but it wouldn't have 10 minutes ago.

git clone git@github.com:baconpaul/surge.git
cd surge
git checkout au-build
git submodule update --init --recursive
./build-osx.sh 

@baconpaul
Copy link
Collaborator Author

Oh and if you expand that linker error it has a bunch of stuff about AUBase::foo missing I bet. That's fixed with the push I just did, including the C++ in the premake.lua.

And I think when you checkout you will need to use the https:// not git: to my git repo. Figure you know that tho!

Really appreciate knowing if it works for you.

@esaruoho
Copy link
Collaborator

esaruoho commented Dec 8, 2018

I have grabbed the new au-build, let's see! am running ./build-osx.sh

...and got a nice ** BUILD SUCCEEDED **!!!
__work_pb_surge_ _-bash_ _126x50

now, in surge/target/au/Release, I'm seeing

Surge.dylib		Surge.dylib.dSYM

and in surge/target/au/Debug am seeing

Surge-Debug.dylib.dSYM

Gonna boot up Xcode and see what that says (after clean and build). i wonder if this is supposed to kick up a Surge.component ?

@baconpaul
Copy link
Collaborator Author

Nope. We are now into the next part of the problem. If you look at how the vst is build it creates a dylib in Xcode then runs the package-vst.sh to copy things around. So we need to figure out how to actually make a .component from the dll. Choices are, I guess

1: Add a .component target to Xcode but then we get into the AU2/AU3 nastiness.
2: Look at some other AU2 component and figure out how to put the files in place by writing a fragile shell script
3: Bite the bullet and port the whole thing properly to AU3.

I think 1 is the hardest, and 3 is the best, so I was going to try 2. Chuckle.

@esaruoho
Copy link
Collaborator

esaruoho commented Dec 8, 2018

Weird thing is that package-au.sh is

#!/bin/bash


echo "This is now redundant"
exit 0

whereas the package-vst.sh and package-vst3.sh actually do take the vst dylib files and "do something" with them :)

@esaruoho
Copy link
Collaborator

esaruoho commented Dec 8, 2018

@baconpaul well, amazing work! i guess there might be plenty of different build scripts out there to package them out, but .. i suppose the key is in finding a non-brittle one :)

@baconpaul
Copy link
Collaborator Author

baconpaul commented Dec 8, 2018

I was taking a look at dexed just now which does this (dexed is an oss implementation of something very close to the DX-7: https://github.com/asb2m10/dexed) but it uses Juce. I suppose we could also use Juce.

But the contents of an AU2 component look like this

paul:~/Library/Audio/Plug-Ins/Components$ find Dexed.component -print
Dexed.component
Dexed.component/Contents
Dexed.component/Contents/MacOS
Dexed.component/Contents/MacOS/Dexed
Dexed.component/Contents/Resources
Dexed.component/Contents/Resources/Dexed.rsrc
Dexed.component/Contents/Resources/RecentFilesMenuTemplate.nib
Dexed.component/Contents/Info.plist
Dexed.component/Contents/PkgInfo

And yeah I know about package-au.sh. I added those 2 lines since it was both empty and non-executable 30 minutes ago :)

@baconpaul
Copy link
Collaborator Author

Oh duh the place to look is the same AudioKit place where I found the AUPublic files.

https://github.com/AudioKit/AudioKit/tree/master/Developer/AKSampler/Mac%20AUv2%20Plugin

I bet that .xcodeproj has the goods inside it....

@baconpaul
Copy link
Collaborator Author

screen shot 2018-12-08 at 5 21 20 pm

So I think you sort of need to work down this list of differences and create a correct info.plist file. Not impossible but I have no idea how to put that into the premake5.lua. And anyway its' dinner time here so I'm done for the day. I'm going to declare partial victory and go do something else for a bit!

@esaruoho
Copy link
Collaborator

esaruoho commented Dec 8, 2018

this ain't a partial victory, this is a victory and a half!! great job @baconpaul
thanks for keeping at it so very patiently!

@baconpaul
Copy link
Collaborator Author

Thanks! Yeah lots of progress today. Fun stuff.

But I’ll declare victory when it works in logic with mpe working properly, and we can make a pr to put it back on the main branch. Still some work to do...

@baconpaul
Copy link
Collaborator Author

So in resources/osx-au there is both an Info.plist and a PkgInfo already in the source tree. I wonder if just copying those around in the script could do it for us... that seems to be what the vst.sh does.

I'll see if I can get some time to look at that route rather than looking at the premake partial implementation of Xcode features which I think could be a bit of a pain.

@baconpaul
Copy link
Collaborator Author

In the "things which don't work breadcrumps" camp, I tried copying package-vst to package-au, changed the vst file names to au, modified Info.plist to have the right case for the Surge executable, and made a .component. But that component wouldn't even load in auval so that's clearly not right.

Also the Info.plist generated by latest Juce is way bigger than the Info.plist in resources/osx-au so that's probably way out of date too.

@baconpaul
Copy link
Collaborator Author

OK and a bit more looking. Seems the dylib we have linked isn't ejecting an AUFactory method. Here's two components I have that work in my system. These Factory entry points are explicitly referenced in the Info.plist for both.

paul:~/Library/Audio/Plug-Ins/Components$ nm -gU s\(M\)exoscope.component/Contents/MacOS/s\(M\)exoscope 
000000000004de80 T __ZN4juce20repostCurrentNSEventEv
00000000001d4ec0 D __ZTINSt3__113basic_ostreamIcNS_11char_traitsIcEEEE
00000000001d4ea8 D __ZTINSt3__115basic_streambufIcNS_11char_traitsIcEEEE
00000000001d4ef0 D __ZTINSt3__19basic_iosIcNS_11char_traitsIcEEEE
000000000017c3b0 S __ZTSNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE
000000000017c370 S __ZTSNSt3__115basic_streambufIcNS_11char_traitsIcEEEE
000000000017c3e0 S __ZTSNSt3__19basic_iosIcNS_11char_traitsIcEEEE
00000000000014d0 T _sMexoscopeAUEntry
000000000000f5d0 T _sMexoscopeAUFactory
paul:~/Library/Audio/Plug-Ins/Components$ nm -gU Dexed.component/Contents/MacOS/Dexed  
000000000002d820 T _DexedAUEntry
000000000002d82a T _DexedAUFactory
000000000012309a T _VSTPluginMain
0000000000123172 T _main_macho

so when I fixed up the Info.plist to add something which looked like a factory function it referenced one that wasn't exported.

From looking through a few plugins, though, it seems we don't even really need to put the factory function in the Info.plist if the name matches "AUFactory".

So more digging into what that src/au code is actually doing!

@baconpaul
Copy link
Collaborator Author

Aha! The AUDIO_COMPONENT_ENTRY macro in aulayer.cpp wasn't quite right and didn't match the info.plist. With that all fixed, I can now make a VST component which logic loads and crashes on!

screen shot 2018-12-08 at 8 06 13 pm

So that's good enough for me to commit and push (again to baconpaul/au-build) the three changes I had to make to get that far.

Close. Really close.

@baconpaul
Copy link
Collaborator Author

OK so some stuff starting to come through!

auvaltool -vt aumu VmbA

    AU Validation Tool
    Version: 1.6.1a1 
    Copyright 2003-2013, Apple Inc. All Rights Reserved.
    Specify -h (-help) for command options

--------------------------------------------------
VALIDATING AUDIO UNIT: 'aumu' - 'Srge' - 'VmbA'
--------------------------------------------------
Manufacturer String: VmbA
AudioUnit Name: Surge
Component Version: 1.0.0 (0x10000)

* * PASS
--------------------------------------------------
TESTING OPEN TIMES:
COLD:
Time to open AudioUnit:         8.419 ms
WARM:
Time to open AudioUnit:         0.009  ms
Segmentation fault: 11

@baconpaul
Copy link
Collaborator Author

baconpaul commented Dec 9, 2018

Huh getting a core file and a stack trace is a bit of work. Here's how to do it if you want to.

  • cp /usr/bin/auvaltool .
    • you have to do this since mojave won't allow you to attach a debugger to stuff owned by root thanks to SIP
  • ulimit -c unlimited
  • touch /cores/foo
  • rm /cores/foo
    • if those don't work, then you need to set permissions on /cores properly
  • ./auvaltool -vt aumu VmbA
    • this should dump a nice big /cores/core.(pid) file
  • lldb ./auvaltool -c /cores/core.(pid)
  • bt all

and you'll get your stack trace. From the trace below, it's clear that we have found, opened, and entered the linked .dylib and are crashing in filesystem somewhere in SurgeStorage after constructing SurgeSyntehsizer. So now we know where to look tomorrow I guess!

(lldb) bt all
* thread #1, stop reason = signal SIGSTOP
  * frame #0: 0x00007fff7d8ed14b libsystem_pthread.dylib`pthread_mutex_lock
    frame #1: 0x00007fff7d76d9c1 libsystem_c.dylib`closedir + 25
    frame #2: 0x00000001048523de Surge`std::experimental::filesystem::is_directory(p=<unavailable>) at filesystem.cpp:92 [opt]
    frame #3: 0x000000010486f029 Surge`SurgeStorage::refresh_wtlist(this=0x0000000104bd1230) at SurgeStorage.cpp:256 [opt]
    frame #4: 0x000000010486dfda Surge`SurgeStorage::SurgeStorage(this=0x0000000104bd1230) at SurgeStorage.cpp:173 [opt]
    frame #5: 0x0000000104874415 Surge`SurgeSynthesizer::SurgeSynthesizer(this=0x0000000104bd1000, parent=0x00007fe3f3018240) at SurgeSynthesizer.cpp:25 [opt]
    frame #6: 0x000000010485dada Surge`aulayer::Initialize() [inlined] aulayer::InitializePlugin(this=0x00007fe3f3018240) at aulayer.cpp:112 [opt]
    frame #7: 0x000000010485dac2 Surge`aulayer::Initialize(this=0x00007fe3f3018240) at aulayer.cpp:130 [opt]
    frame #8: 0x00000001048370a6 Surge`AUBase::DoInitialize(this=0x00007fe3f3018240) at AUBase.cpp:206 [opt]
    frame #9: 0x0000000104844b6b Surge`AUMethodInitialize(self=<unavailable>) at AUPlugInDispatch.cpp:25 [opt]
    frame #10: 0x00000001035f016e auvaltool`___lldb_unnamed_symbol13$$auvaltool + 90
    frame #11: 0x00000001035ef971 auvaltool`___lldb_unnamed_symbol8$$auvaltool + 697
    frame #12: 0x00000001035fcfbd auvaltool`___lldb_unnamed_symbol115$$auvaltool + 417
    frame #13: 0x00000001035ee6af auvaltool`___lldb_unnamed_symbol3$$auvaltool + 2285
    frame #14: 0x00000001035edced auvaltool`___lldb_unnamed_symbol2$$auvaltool + 384
    frame #15: 0x00007fff7d6fd08d libdyld.dylib`start + 1
    frame #16: 0x00007fff7d6fd08d libdyld.dylib`start + 1
  thread #2, stop reason = signal SIGSTOP
    frame #0: 0x00007fff7d8375be libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x00007fff7d8ee661 libsystem_pthread.dylib`_pthread_wqthread + 446
    frame #2: 0x00007fff7d8ee435 libsystem_pthread.dylib`start_wqthread + 13
  thread #3, stop reason = signal SIGSTOP
    frame #0: 0x00007fff7d8ee428 libsystem_pthread.dylib`start_wqthread

@baconpaul
Copy link
Collaborator Author

Huh wow filesystem actually had an error in is_directory! It did a closedir(dp) without checking if dp was null. Added a guard and pushed to au-build. Now my crash is somewhere else (it's in the xml parser).

Neat. There's now a clean workflow to build test stack trace and debug. I added a small script called install-local-au.sh which packages and installs the AU for you so you can run auval and see. I also added output with build time so you know what you are running.

@baconpaul
Copy link
Collaborator Author

Hey the SurgePatch also was under-conservative with null checks so I fixed those also.

Now I'm getting a crash far later on. We get through a large amount of validation before we segfault. Seems we are now faulting on CFGetTypeID with a bit of a mangled stack, so I'm going to call it a night.

But hey we have a built audio unit linked from the code which actually enters the code under auvalidation so I think we can call this a partial victory plus!

@baconpaul
Copy link
Collaborator Author

GOT IT!!

I found the last bug making us segfault and I can now link and pass auvalidation with the Surge on baconpaul/au-build.

That let me load it into logic, instantiate it on a track, send midi to it, and have it make a horrible popping noise which seems like it may have been bad for my speakers! Use a limiter, folks!

The Cocoa UI is not loading properly so it is using the default parameter UI in logic. auval also says that it has no cocoa UI so that should be easy to fix.

And in the "pictures or it didn't happen" meme camp, here's a screenshot.

And now, I'm calling it a night. That was a fun day of hacking!!

screen shot 2018-12-08 at 9 21 35 pm

@baconpaul
Copy link
Collaborator Author

Ha OK and the reason there is no UI is because aulayer has only implemented a carbon ui, not a cocoa one, and no way carbon runs on a modern mac. So some actual work to do there. Look at the #if MAC_COCOA in aulayer.cpp if you feel like some cocoa C++ hacking. I may get to that this week. Will see.

@baconpaul
Copy link
Collaborator Author

And hey if you pull to head this morning you will find a few more updates which mean it actually plays sounds and you can adjust at least one parameter and hear a change. I updated the README and all the scripts, and got the code in a state where we could contemplate a (big) pull request but there's a couple of other things I want to do before I go that route.

I think a pull request with "makes some sound, no UI" is a reasonable point though and will spend a bit of time this morning working towards that.

@baconpaul
Copy link
Collaborator Author

Hey and if yo pull now, in addition to building and working, it will load all the presets and wavetables if you run the ./installer-local-au.sh script to stage them in the right place. (How to do this as a proper install is for the future).

I can now pick from 1000 odd presets and make them sound in logic 10.4 with a 64 bit AU! Wahey!

@Jorgeelalto
Copy link

Can't wait to get my hands dirty with the Win/Linux version, amazing work guys! We also had problems with GUIs in the Linux realm I think so for me it's very interesting to follow this thread :)

@baconpaul
Copy link
Collaborator Author

Cool! Not sure how much of this will be in common with Linux or Windows. It seems almost all in mac /cocoa/au land. But happy to toss in any ideas!

Since au-build is in the PR, I am now working on au-build-ui with the UI stuff if you want to keep following at home. But nothing works there at all!

@esaruoho
Copy link
Collaborator

@baconpaul did you see that #59 was merged in? :) so awesome!

@baconpaul
Copy link
Collaborator Author

Yep; great this was merged. Move the UI action to a new issue #61 and am closing this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants