I want to waveform display in real-time input from the microphone. I have been implemented using the installTapOnBus:bufferSize:format:block:, This function is called three times in one second. I want to set this function to be called 20 times per second. Where can I set?
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError* error = nil;
if (audioSession.isInputAvailable) [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
if(error){
return;
}
[audioSession setActive:YES error:&error];
if(error){
retur;
}
self.engine = [[[AVAudioEngine alloc] init] autorelease];
AVAudioMixerNode* mixer = [self.engine mainMixerNode];
AVAudioInputNode* input = [self.engine inputNode];
[self.engine connect:input to:mixer format:[input inputFormatForBus:0]];
// tap ... 1 call in 16537Frames
// It does not change even if you change the bufferSize
[input installTapOnBus:0 bufferSize:4096 format:[input inputFormatForBus:0] block:^(AVAudioPCMBuffer* buffer, AVAudioTime* when) {
for (UInt32 i = 0; i < buffer.audioBufferList->mNumberBuffers; i++) {
Float32 *data = buffer.audioBufferList->mBuffers[i].mData;
UInt32 frames = buffer.audioBufferList->mBuffers[i].mDataByteSize / sizeof(Float32);
// create waveform
...
}
}];
[self.engine startAndReturnError:&error];
if (error) {
return;
}
they say, Apple Support replied no: (on sep 2014)
Yes, currently internally we have a fixed tap buffer size (0.375s), and the client specified buffer size for the tap is not taking effect.
but someone resizes buffer size and gets 40ms https://devforums.apple.com/thread/249510?tstart=0
Can not check it, neen in ObjC :(
UPD it works! just single line:
[input installTapOnBus:0 bufferSize:1024 format:[mixer outputFormatForBus:0] block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when) {
buffer.frameLength = 1024; //here
The AVAudioNode class reference states that the implementation may choose a buffer size other than the one that you supply, so as far as I know, we are stuck with the very large buffer size. This is unfortunate, because AVAudioEngine is otherwise an excellent Core Audio wrapper. Since I too need to use the input tap for something other than recording, I'm looking into The Amazing Audio Engine, as well as the Core Audio C API (see the iBook Learning Core Audio for excellent tutorials on it), as alternatives.
***Update: It turns out that you can access the AudioUnit of the AVAudioInputNode and install a render callback on it. Via AVAudioSession, you can set your audio session's desired buffer size (not guaranteed, but certainly better than node taps). Thus far, I've gotten buffer sizes as low as 64 samples using this approach. I'll post back here with code once I've had a chance to test this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With