AVAudioRecorder actualTime dando valores incorrectos

Tengo una configuration como sigue, probando en un iPhone 5s con iOS 10.3, tanto dentro como fuera de la debugging.

  • Un AVAudioRecorder dispara el record(forDuration: 5.0)
  • A CADisplayLink observa los niveles de la grabadora (la grabadora se meteringEnabled ), sincroniza una animation y hace un seguimiento de recorder.currentTime (pero el problema puede reproducirse al mantener un seguimiento mínimo del time en el enlace de la pantalla)
  • Los informes de recorder.currentTime alcanzan valores> 5 (a menudo de 5.2 a 5.5). Los resultados son esencialmente consistentes con los valores de recorder.deviceTime y CFAbsoluteTimeGetCurrent
  • Inicializo un AVAudioPlayer y verifico que el recurso de sonido tenga una duración de exactamente 5.0 segundos.

Según mi comprensión, el time currentTime la grabadora se mide en segundos y se restablece a 0.0 cuando la grabadora. La grabación vuelve a ser falsa, lo que ocurre inmediatamente cuando la grabadora se detiene (esto es coherente con lo que veo en audioRecorderDidFinishRecording ) … observando con CADisplayLink ¿Debería producir valores actuales de Time estrictamente less de 5.0?

La pregunta es: ¿qué podría ir mal aquí? La grabadora se detiene como debería después de exactamente 5 segundos, pero internamente cree que se grabó durante más de 5 segundos? Estoy escuchando todas mis grabaciones y suenan bien.

No estoy seguro de si es relevante, pero mi AVAudioSession es del tipo AVAudioSessionCategoryPlayAndRecord , y mi configuration de audio es la siguiente (todas estas excepciones son necesarias para un análisis posterior):

 audioSettings = [ AVFormatIDKey: Int(kAudioFormatLinearPCM), AVSampleRateKey: 44100, AVNumberOfChannelsKey: 2, AVLinearPCMIsBigEndianKey: 0, AVLinearPCMIsFloatKey: 0, AVLinearPCMBitDepthKey: 16, AVLinearPCMIsNonInterleaved: 0 ] 

Ya intenté tocar el violín con todos estos y no vi ningún cambio en el comportamiento.

CADisplayLink se agrega desde el hilo principal a través de

 recorderDisplayLink?.add(to: RunLoop.current, forMode: RunLoopMode.commonModes) 

La única pregunta similar que puedo encontrar en el intercambio de stack es esta , pero la pregunta no está especificada y la respuesta no es útil (al less para mí).
Al principio pensé que tal vez el problema es sobrecargar la queue principal, de modo que de alguna manera el sentido del time del grabador se hinche (lo que creo que seguiría constituyendo un mal comportamiento), pero después de deshabilitar la animation (y también experimentar con un timer en lugar de un CADisplayLink), ¡el problema persiste! Tal vez todavía sea un problema de subprocesss, pero no veo por qué ese sería el caso. Y si necesito múltiples hilos, podría usar un poco de ayuda, tanto para comprenderlos como para implementarlos 🙂 Cualquier idea apreciada.

De todas las veces que he usado AVAudioRecorder , finalmente tuve que replacelo. AVAudioRecorder es una class de grabación de propósito general, por lo que una vez que sus requisitos se AVAudioRecorder un poco especializados, le decepcionará.

Sin embargo, hace la medición, que es lo que atrae a muchas personas. Entonces tal vez la situación se pueda salvar.

Posibilidades:

a. Si currentTime no es digno de confianza, entonces ¡no lo observe! Tienes tus files de 5 segundos, así que quizás encuentres otra forma de marcar ese paso del time en tu aplicación.

segundo. de la propiedad currentTime , el file de encabezado dice:

  only valid while recording 

¿Está probando currentTime solo durante la grabación? Si es así, ese podría ser el problema. En ese caso, podría usar la propiedad deviceCurrentTime , que siempre es válida, aunque deberá restar el deviceCurrentTime .

Si la situación no puede recuperarse, podría replace rápidamente AVAudioRecorder con AVAudioEngine y AVAudioFile , pero esa es una pregunta para otro día.