对于传输指定帧数的阻塞读取或写入操作,请将 timeoutNanos 设置为大于零。 对于非阻塞调用,请将 timeoutNanos 设置为零。 在这种情况下,结果将是传输的实际帧数。
读取输入值时,您应验证是否已读取正确数量的帧。 如果并非如此,则缓冲区可能包含未知的数据,从而引起音频干扰。 您可以在缓冲区中填入零,以产生静音效果:
您可以先准备好流的缓冲区,再通过将数据写入或静音写入其中来启动流。 此操作必须在 timeoutNanos 设置为零的情况下,通过非阻塞调用来完成。
流断开连接后,其状态为“Disconnected”,任何尝试执行 write() 或其他函数的操作都会返回AAUDIO_ERROR_DISCONNECTED。 流断开连接后,您只能将其关闭。
回调应检查流的状态,如以下示例所示。 您不应从回调中关闭或重新打开流,而应使用另一个线程。 请注意,如果打开新的流,其特征可能与原始流不同(例如,framesPerBurst):
您可以通过调整内部缓冲区,以及使用特殊的高优先级线程,优化音频应用的性能。
AAudio 会将数据传入其维护的内部缓冲区,并从中传出数据(每个音频设备各有一个内部缓冲区)。
注:请勿将 AAudio 的内部缓冲区与 AAudio 流读写函数的缓冲区参数混淆。
应用不必使用缓冲区的全部容量。 您可以设置 AAudio 填充缓冲区的大小上限。 缓冲区大小不得超过其容量,而且通常较小。 您可以通过控制缓冲区大小,确定填充缓冲区所需的脉冲串数,从而控制延迟时间。 您可使用AAudioStreamBuilder_setBufferSizeInFrames()和AAudioStreamBuilder_getBufferSizeInFrames()方法来处理缓冲区大小。
应用播放音频时,会将数据写入缓冲区并阻止运行,直至写入完成。 AAudio 以离散的脉冲串从缓冲区中读取数据。 每个脉冲串都包含多个音频帧,而且通常小于所读取的缓冲区大小。 脉冲串的大小及速率由系统控制,而这些属性通常由音频设备的电路指定。 虽然您无法更改脉冲串的大小或速率,但可根据内部缓冲区所含的脉冲串数量来设置内部缓冲区大小。 通常,当 AAudioStream 的缓冲区大小是所报告脉冲串大小的倍数时,延迟时间最短。
优化缓冲区大小的一种方法是从较大的缓冲区开始,逐渐将其减小直至开始出现缓冲区不足现象,再稍稍将其调大。 此外,您也可以从较小的缓冲区大小开始,如果出现缓冲区不足现象,则增大缓冲区大小,直至输出再次流畅为止。
这个过程推进速度很快,很可能在用户开始播放第一个音频前就已完成。 您可以先以静音执行初始缓冲区大小调整,确保用户不会听到任何音频干扰声。 随着时间推移,系统性能可能会有所变化(例如,用户可能会关闭飞行模式)。 因为缓冲区调整所产生的开销非常小,应用可以在对流读写数据的同时,连续不断地调整缓冲区。
对于输入流来说,使用这种方法优化缓冲区大小并无益处。 输入流以尽可能快的速度运行,以尝试将缓存数据量保持在最低限度,然后在应用被抢占时填补缓冲区。
如果您的应用从原始线程中读写音频数据,则可能会被抢占或遇到定时抖动, 进而可能引起音频干扰。 使用较大的缓冲区有助于避免此类干扰,但是如果缓冲区较大,音频延迟时间也会更长。 对于要求短延迟时间的应用,音频流可以使用一个异步回调函数,将数据传输到您的应用并从中传输数据。 AAudio 会在优先级较高的线程中执行该回调,这有助于改善性能。
在最简单的情况下,流会定期执行该回调函数,以获取用于下一个脉冲串的数据。
该回调函数不应对调用它的流执行读写操作。 如果该回调属于某个输入流,那么您的代码应处理在 audioData 缓冲区(指定为第三个参数)中提供的数据。 如果该回调属于某个输出流,那么您的代码应将数据放入该缓冲区。