Я пытаюсь сделать точный таймер для анализа ввода. Я хотел бы иметь возможность измерять отклонение 1% в сигналах ~ 200 мс. Насколько я понимаю, использование AudioUnit позволит получить ‹1 мс. Я попытался реализовать код из примера Стефана Поппа. работайте над xcode 6.3, однако у меня работает пример:
Хотя я в конечном итоге хочу захватить звук, я подумал, что должен быть какой-то способ получить уведомление, например NSTimer, поэтому я попробовал AudioUnitAddRenderNotify, но он делает именно то, что должен, — т.е. он привязан к рендерингу, а не просто произвольный таймер. Есть ли способ вызвать обратный вызов без необходимости записи или воспроизведения?
Когда я изучаю mSampleTime, я обнаруживаю, что интервал между срезами соответствует inNumberFrames — 512 — что составляет 11,6 мс. Я вижу одинаковый интервал как для записи, так и для воспроизведения. Мне нужно большее разрешение, чем это.
Я попытался поиграть с 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] Я пытаюсь сравнить синхронизацию ввода (выбор пользователем MIDI или микрофона) с тем, когда это должно быть. В частности, играет ли инструмент до или после такта/метронома и насколько сильно? Это для музыкантов, а не для игр, поэтому точность требуется.
[EDIT] Ответы кажутся реактивными на события. т.е. они позволяют мне точно видеть, когда что-то произошло, однако я не вижу, как я делаю что-то точно. Моя вина, что не ясно. Мое приложение также должно быть метрономом — синхронизировать воспроизведение клика в такт и мигать точкой в такт — тогда я могу проанализировать действия пользователя, чтобы сравнить время. Но если я не смогу точно сыграть бит, все остальное развалится. Может быть, я должен записывать звук — даже если я этого не хочу — просто для того, чтобы получить отметку времени из обратного вызова?
[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];
}