Я пытаюсь сделать точный таймер для анализа ввода. Я бы хотел измерить 1% -ное отклонение в сигналах ~ 200 мс. Я понимаю, что с помощью AudioUnit вы сможете получить < 1ms. Я попытался реализации кода из Stefan Popp's example После обновления несколько вещей, чтобы заставить его работать на Xcode 6.3, у меня есть пример работает, однако:Точный таймер с использованием AudioUnit
В то время как я в конечном счете хочу, чтобы записывать звук, я думал, должен быть каким-то образом получить уведомление, например NSTimer, поэтому я попробовал AudioUnitAddRenderNotify, но он делает именно то, что он говорит, что нужно - то есть привязан к рендерингу, а не только произвольному таймеру. Есть ли способ вызвать обратный вызов, не требующий записи или воспроизведения?
Когда я просматриваю mSampleTime, я обнаружил, что интервал между срезами соответствует inNumberFrames - 512 - который работает до 11.6ms. Я вижу такой же интервал как для записи, так и для воспроизведения. Мне нужно больше разрешения, чем это.
Я пытался играть с kAudioSessionProperty_PreferredHardwareIOBufferDuration, но все примеры, которые я мог бы найти использовать устаревшие AudioSessions, поэтому я попытался преобразовать в AudioUnits:
Float32 preferredBufferSize = .001; // in seconds
status = AudioUnitSetProperty(audioUnit, kAudioSessionProperty_PreferredHardwareIOBufferDuration, kAudioUnitScope_Output, kOutputBus, &preferredBufferSize, sizeof(preferredBufferSize));
Но я получаю OSStatus -10879, kAudioUnitErr_InvalidProperty.
Затем я попытался kAudioUnitProperty_MaximumFramesPerSlice со значениями 128 и 256, но inNumberFrames всегда 512.
UInt32 maxFrames = 128;
status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFrames, sizeof(maxFrames));
[EDIT] Я пытаюсь сравнить сроки вклада (выбор пользователя миди или микрофона) когда это должно быть. В частности, инструмент играет до или после бит/метроном и на сколько? Это для музыкантов, а не для игры, поэтому ожидается точность.
[EDIT] Ответы кажутся повторно активными для событий. Т.е. они позволяют мне точно видеть, когда что-то произошло, однако я не вижу, как я точно делаю . Моя вина за неясность. Мое приложение также должно быть метрономом - синхронизировать воспроизведение щелчка по ритму и мгновенно мигать в такт - тогда я могу проанализировать действие пользователя, чтобы сравнить время. Но если я не смогу точно сыграть в ритме, все остальное развалится. Может быть, я должен записывать аудио - даже если я этого не хочу - просто чтобы получить inTimeStamp из обратного вызова?
[EDIT] В настоящее время мой метроном:
- (void) setupAudio
{
AVAudioPlayer *audioPlayer;
NSString *path = [NSString stringWithFormat:@"%@/click.mp3", [[NSBundle mainBundle] resourcePath]];
NSURL *soundUrl = [NSURL fileURLWithPath:path];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
[audioPlayer prepareToPlay];
CADisplayLink *syncTimer;
syncTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(syncFired:)];
syncTimer.frameInterval = 30;
[syncTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
-(void)syncFired:(CADisplayLink *)displayLink
{
[audioPlayer play];
}
Как вы играете на своем аудио в этот момент? это миди? Или вы буферизируете звук вручную? На выбор есть много API. Если вы будете делать приложение для караоке-стиля, то вам определенно нужно будет изучить основной звук внутри и снаружи, и это займет некоторое время. Если вы делаете что-то более простое, например, обнаруживаете, насколько близко к клику пользователь, вы можете использовать комбинацию основного звука и [MusicPlayer] (https://developer.apple.com/library/prerelease/ios /documentation/AudioToolbox/Reference/MusicPlayerServices_Reference/index.html) API – dave234