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)
Related
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.
new here, and new to mobile dev in general. This question is more about approach than anything. I have a simple app that I’m writing to learn various things, one of which is AVFoundation. I have the app working to the point where I record audio using AVAudioRecorder, play the recorded file back with AVAudioPlayer, and all is well. There are two things I’d like to achieve but I’m not quite sure how to go about them in the best way. I'm using Swift 3, xcode 8.3, iOS 10.3. Lots of 3s.
First: I want to only play back X number of seconds of the audio. To achieve this, my thought is to use scheduledTimer for X, which will trigger a stop() call when it elapses. Is that the best method to use?
Second: I want to measure the decibel level of input coming into the microphone while it’s recording. This is the one I truly have little insight on how to accomplish. I believe this can be obtained through the AVAudioRecorder.powerOutput value (?), but I’m unclear as to how I can monitor the value during playback and act on it.
Not really sure what code to include since it's pretty basic. I'm setting up the AVAudioSession in the AppDelegate, the AVAudioRecorder is setup to record in didFinishLoading, and the rest of the record, stop, play functionality is through buttons.
I'm trying to run an AVCaptureSession in a view controller, but within the same, I'm also calling a function from a library that uses AVAudioSession. I can't seem to get much info out of the debugger, other than it crashes exactly when I call this particular library's function. The library is libpd:
https://github.com/libpd
and it calls AVAudioSession as sharedInstance. I call libpd as:
[self.audioController configurePlaybackWithSampleRate:44100 numberChannels:2 inputEnabled:YES mixingEnabled:YES]
so mixing is enabled, but just in case, I've recompiled it so that when it inits, I do:
UInt32 doSetProperty = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doSetProperty), &doSetProperty);
but, no luck. Moving the calls to libpd to viewWillAppear within the view controller didn't work either. However, if I take the code that calls libpd out of my viewcontroller, and put it in the app delegate within didFinishLaunchingWithOptions, it then starts just fine, and the two sessions seem to co-exist without crashing.
Am I missing something about AVCaptureSession and mixing? How do I go about both sessions co-existing? I'm not using AVCapture to capture audio, only camera input, so shouldn't I be able to somehow have both going on?
Start the audio session (which can be set to support mixing) after you've started the camera session. I tried and you need to wait for the camera to be setup before you start the audio session (e.g. wait a couple of seconds)
Is it possible that the library assumes there's no other audio session active and calls AudioSessionInitialize?
Per the docs "You may activate and deactivate your audio session as needed (see AudioSessionSetActive), but should initialize it only once."
I'd guess that the authors of this library didn't include functionality for an ongoing audio session... but it would be easy enough to dive in there and comment out the initializing lines, as long as your app always hits that function call with a running audio session (otherwise just check with an if statement to see if you have an audio session, if you don't, initialize one, etc.)
For a project I need to handle audio in an iPhone app quite special and hope somebody may point me in the right direction.
Lets say you have a fixed set of up to thirty audio files of the same length (2-3 sec, non-compressed). While a que is playing from one audio file it should be able to update parameters that makes the playing continue from another audio file from the same timestamp the previous audiofile ended playing. If the different audio files is different versions of heavely filtered audio it should be possible to "slide" between them an get the impression that you applied the filter directly. The filtering is at the moment not possible to achive in realtime on an iPhone, therefore the prerendered files.
If A B and C is different audio files I like to be able to:
Play A without interruption:
Start AAAAAAAAAAAAA Stop
Or start play A and continue over in B and then C, initiated while playing
Start AAABBBBBBBBCC Stop
Ideally is should be possible to play two er more ques at the same time. Latency is not that important, but the skipping between files should ideally not produce clicks or delays.
I have looked into using Audio Queue Services (which look like hell to dive into) and sniffed on OpenAl. Could anyone give me a ruff overview and a general direction I can spend the next days burried into?
Try using the iOS Audio Unit API, particularly a mixer unit connected to RemoteIO for audio output.
I managed to do this by using FMOD Designer. FMOD (http://www.fmod.org/) is a sound design framework for game development, that supports iOS development. I made a multitrack-event in FMOD Designer with different layers for each sound clip. Add a parameter in the horizontal bar that lets you controll which sound clip to play in realtime. The trick is to let each soundclip continue over the whole bar and controll which sound that is beeing heard by using a volume effect (0-100%) like in the attached picture. In that way you are ensured that skipping between files follow the same timecode. I have tried this successfully with up to thirty layers, but experienced some double playing. This seemed to dissapear if I cut the number down to fifteen.
It should be possible to use iOS Audio Unit API if you are comfortable with this, but for those of us that like the most simple sollution FMOD is quite good :) Thanks to Ellen S for the sollution tip!
Screenshot of the multitrack-event in FMOD Designer:
https://plus.google.com/photos/106278910734599034045/albums/5723469198734595793?authkey=CNSIkbyYw8PM2wE
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.