v5: Has CallbackInstrument been removed along with other PolyphonicNodes? - audiokit

I noticed in the Migration Guide that polyphonic nodes have been removed. Does this also apply to CallbackInstrument? Is it still the case?
The oscillator banks such as AKOscillatorBank have all been removed. They were coded in a way that we have since outgrown. The only polyphonic node left is Synth but we intend on bringing back polyphonic instruments in a well-coded way as soon as possible.
I'm trying to build a Sequencer which uses CallbackInstrument to drive UI updates. I've not been able to get the callback to work so far. I'm not sure if the problem is with my code or CallbackInstrument hasn't been fully implemented in v5 yet.

Related

Using AVAudioSequencer to send MIDI to third-party AUv3 instruments

I'm having trouble controlling third-party AUv3 instruments with MIDI using AVAudioSequencer (iOS 12.1.4, Swift 4.2, Xcode 10.1) and would appreciate your help.
What I'm doing currently:
Get all AUs of type kAudioUnitType_MusicDevice.
Instantiate one and connect it to the AVAudioEngine.
Create some notes, and put them on a MusicTrack.
Hand the track data over to an AVAudioSequencer connected to the engine.
Set the destinationAudioUnit of the track to my selected Audio Unit.
So far, so good, but...
When I play the sequence using AVAudioSequencer it plays fine the first time, using the selected Audio Unit. On the second time I get either silence, or a sine wave sound (and I wonder who is making that). I'm thinking the Audio Unit should not be going out of scope in between playbacks of the sequence, but I do stop the engine and restart it again for the new round. (But it should even be possible to swap AUs while the engine is running, so I think this is OK.)
Are there some steps that I'm missing? I would love to include code, but it is really hard to condense it down to its essence from a wall of text. But if you want to ask for specifics, I can answer. Or if you can point me to a working example that shows how to reliably send MIDI to AUv3 using AVAudioSequencer, that would be great.
Is AVAudioSequencer even supposed to work with other Audio Units than Apple's? Or should I start looking for other ways to send MIDI over to AUv3?
I should add that I can consistently send MIDI to the AUv3 using the InstrumentPlayer method from Apple's AUv3Host sample, but that involves a concurrent thread, and results in all sorts of UI sync and timing problems.
EDIT: I added an example project to GitHub:
https://github.com/jerekapyaho/so54753738
It seems that it's now working in iPadOS 13.7, but I don't think I'm doing anything that different than earlier, except this loads a MIDI file from the bundle, instead of generating it from data on the fly.
If someone still has iOS 12, it would be interesting to know if it's broken there, but working on iOS 13.x (x = ?)
In case you are using AVAudioUnitSampler as an audio unit instrument, the sine tone happens when you stop and start the audio engine without reloading the preset. Whenever you start the engine you need to load any instruments back into the sampler (e.g. a SoundFont), otherwise you may hear the sine. This is an issue with the Apple AUSampler, not with 3rd party instruments.
Btw you can test it under iOS 12 using the simulator.

Stop AKMicrophone without stopping AudioKit

I have an app in which I only want to be recording from one particular screen. On every other screen I would like to not be recording mostly so that audio can still play while the app is in the background without the red recording bar being there.
The only way I've been able to do this is to stop AudioKit (AudioKit.stop()) but I'm pretty sure the starting and stopping of AudioKit is causing some very random hard to track down crashes. I have also tried calling stop on the Microphone, and setting input enabled to false but this has not worked either.
I know there is a similar question AudioKit: Can I disable an AKMicrophone without calling AudioKit.stop()?
but the answer doesn't address this.
Is there anyway to stop receiving input from the microphone without stopping the engine?
It depends a bit on your goal with disconnecting the microphone. If you just want to stop processing input and change the AVAudioSession category so that the red bar goes away you could set AKSettings.audioInputEnabled = false but then you'll need to get AVAudioSession's category updated. Currently as far as I can tell there isn't a good way to do this without stopping/starting AudioKit although changing the category without restarting the engine should be possible. One hack that seems to work on first blush is to assign AudioKit.output = AudioKit.output to trigger the didSet side-effect that will update the category via updateSessionCategoryAndOptions().
You could always bypass AudioKit and try to set the shared AVAudioSession's category directly as well. I'm looking into creating a PR for AudioKit to expose updateSessionCategoryAndOptions() but in the meantime you could always make this function public in your own branch and run build_frameworks.sh. Anyway, not great solutions but this is a valid use-case AudioKit should support better in the future!
As a general rule for using Audio Kit you should be employing a proper gain staging pattern. I don't know if you have any experiences with any DAW's (protools, logic, cubase etc) but you should view AudioKit as a DAW... in code.
AudioKit.start()
is your master output and I honestly see no reason to ever stop it during your application. Instead you should mute the master output of audiokit to 'kill the sound'
As for your question, AKMicrophone does have both a start and a stop property, you should just be able to call stop!
let mic = AKMicrophone
mic.start(AKMicrophone)
mic.stop(AKMicrophone)

AudioKit sequencer clock

I plan to build a sequencer using audioKit.
I would like to generate midiNotes on the fly according to user interactions, so I'd like to be able to record and play midi but not only (I'd like to record some time stamped objects as well).
I guess I have to set a recursive loop with a delay somewhere, but I don't know what is the best way to have a stable clock that I could control remotely (stop or suspend, change tempo...).
Is there some components already implemented in audioKit to achieve this?
Or should I use some system components (Grand central Dispatch or NSTimer...)
Any suggestion is welcome,
Thanks :-)
I got an answer from Aurelius Prochazka (AudioKit Developper)
"AKOperations can't trigger arbitrary code."
I found a solution using "dispatch_after" in swift that seems to do the trick.
(stable even in playground with a clock set to 1 ms per tick)
But after digging the web and according to Aurelius, using CADisplayLink seems to be more appropriate to have a stable clock.
There's an example in AudioKit playgrounds of a triggering clock (AKPlaygroundLoop.swift in AudioKit.playground/Sources folder)

Midi Timing Issues with Delphi ASIO VST and MiniHost

I'm coming from a background of using MSC* MidiSequencer for a Delphi XE2 project and have been playing with DelphiASIOVST this weekend on the off chance the MIDI may be stable enough to use as my core MIDI engine while also allowing me to support VST plug ins. I pulled the D16 trunk off the SVN and compiled effortlessly after a few path tweaks.
I understand a great deal of what I'm seeing but I'm wondering if others have experienced issues with MIDI file playback in the the MiniHost example application. Specifically with a one track melodic performance it sounds like notes are getting skipped and/or playing back a bit later over other notes that are playing as they should. Basically it's just hit or miss if a note is even played at all.
I have numerous pro sequencers on my machine and the MIDI files are fine there. they also support VST with little to no problems. I also know the MIDI lowest level file format and know the file structure is sound.
Can the TMidiFile play direct to the standard MIDI synth in the computer? I'm trying to rule out VST issues by getting a direct pipeline to the built in synth. Barring that, anyone seen these issues or know of some more/better examples of MIDI file to VST using the component set?
I use FL studios with my Midi and odds are is you need to turn down your buffer quality so that there is little to no delay.
It's probably by default set to about mid-high range which means you will almost for sure have 1 - 1.5 second delay
Don't turn it down too low otherwise you'll get trash can sound where everything sounds hollow and robotic, but keep smashing the keys while you're adju8sting the setting
Is the wordclock functioning properly? Do you have the ability of driving off another midi clock-source, just to test with?
Though you said: "I have numerous pro sequencers on my machine and the MIDI files are fine there", you could also try http://www.reaper.fm (works on Linux/BSD, Mac and Win) DAW and import the midi directly into that, then set your default midi device as that which you wish to test with.
Check the Midi Overflow settings.
Ensure each of your Midi Devices has a unique ID.
Get a midi throughput app like Midi-ox http://www.midiox.com/ To see realtime messages and data. and see where things are going.
Midi workflow checking is required for setting as per our requirements.
Set all devices with unique ids that have been specified in your midi overflow.
Midi throughput application is required to see the messages that are realtime and data that are also realtime.
User has to see the things where they are going to what purpose.
Hope this will help u...

iOS: Sample code for simultaneous record and playback

I'm designing a simple proof of concept for multitrack recorder.
Obvious starting point is to play from file A.caf to headphones while simultaneously recording microphone input into file B.caf
This question -- Record and play audio Simultaneously -- points out that there are three levels at which I can work:
AVFoundation API (AVAudioPlayer + AVAudioRecorder)
Audio Queue API
Audio Unit API (RemoteIO)
What is the best level to work at? Obviously the generic answer is to work at the highest level that gets the job done, which would be AVFoundation.
But I'm taking this job on from someone who gave up due to latency issues (he was getting a 0.3sec delay between the files), so maybe I need to work at a lower level to avoid these issues?
Furthermore, what source code is available to springboard from? I have been looking at SpeakHere sample ( http://developer.apple.com/library/ios/#samplecode/SpeakHere/Introduction/Intro.html ). if I can't find something simpler I will use this.
But can anyone suggest something simpler/else? I would rather not work with C++ code if I can avoid it.
Is anyone aware of some public code that uses AVFoundation to do this?
EDIT: AVFoundation example here: http://www.iphoneam.com/blog/index.php?title=using-the-iphone-to-record-audio-a-guide&more=1&c=1&tb=1&pb=1
EDIT(2): Much nicer looking one here: http://www.switchonthecode.com/tutorials/create-a-basic-iphone-audio-player-with-av-foundation-framework
EDIT(3): How do I record audio on iPhone with AVAudioRecorder?
To avoid latency issues, you will have to work at a lower level than AVFoundation alright. Check out this sample code from Apple - Auriotouch. It uses Remote I/O.
As suggested by Viraj, here is the answer.
Yes, you can achieve very good results using AVFoundation. Firstly you need to pay attention to the fact that for both the player and the recorder, activating them is a two step process.
First you prime it.
Then you play it.
So, prime everything. Then play everything.
This will get your latency down to about 70ms. I tested by recording a metronome tick, then playing it back through the speakers while holding the iPhone up to the speakers and simultaneously recording.
The second recording had a clear echo, which I found to be ~70ms. I could have analysed the signal in Audacity to get an exact offset.
So in order to line everything up I just performSelector:x withObject: y afterDelay: 70.0/1000.0
There may be hidden snags, for example the delay may differ from device to device. it may even differ depending on device activity. It is even possible the thread could get interrupted/rescheduled in between starting the player and starting the recorder.
But it works, and is a lot tidier than messing around with audio queues / units.
I had this problem and I solved it in my project simply by changing the PreferredHardwareIOBufferDuration parameter of the AudioSession. I think I have just 6ms latency now, that is good enough for my app.
Check this answer that has a good explanation.

Resources