简体   繁体   English

iPhone11 意外数量的音频样本

[英]iPhone11 unexpected number of Audio Samples

I have an app that captures audio and video using AVAssetWriter .我有一个使用AVAssetWriter捕获音频和视频的应用程序。 It runs a fast fourier transform (FFT) on the audio to create a visual spectrum of the captured audio in real time.它对音频运行快速傅立叶变换 (FFT),以实时创建捕获音频的可视频谱。

Up until the release of iPhone11, this all worked fine.直到 iPhone11 发布,这一切都运行良好。 Users with the iPhone 11, however, are reporting that audio is not being captured at all.但是,使用 iPhone 11 的用户报告说根本没有捕获音频。 I have managed to narrow down the issue - The number of samples returned in captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) is either 940 or 941 - On previous phone models, this is always 1024 samples.我设法缩小了问题的范围 - captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)中返回的样本数是 940 或 941 - 在以前的手机型号上,这始终是 1024 个样本。 I use CMSampleBufferGetNumSamples to get the number of samples.我使用CMSampleBufferGetNumSamples来获取样本数。 My FFT calculations rely on having the number of samples be a power of 2, so it drops all frames on the newer model iPhones.我的 FFT 计算依赖于样本数为 2 的幂,因此它会丢弃较新型号 iPhone 上的所有帧。

Can anybody shed light on why the new iPhone11 is returning an unusual number of samples?有人能解释一下为什么新 iPhone11 返回的样本数量异常吗? Here is how I have configured the AVAssetWriter :这是我配置AVAssetWriter

self.videoWriter = try AVAssetWriter(outputURL: self.outputURL, fileType: AVFileType.mp4)
var videoSettings: [String : Any]
if #available(iOS 11.0, *) {
    videoSettings = [
        AVVideoCodecKey  : AVVideoCodecType.h264,
        AVVideoWidthKey  : Constants.VIDEO_WIDTH,
        AVVideoHeightKey : Constants.VIDEO_HEIGHT,
    ]
} else {
    videoSettings = [
        AVVideoCodecKey  : AVVideoCodecH264,
        AVVideoWidthKey  : Constants.VIDEO_WIDTH,
        AVVideoHeightKey : Constants.VIDEO_HEIGHT,
    ]
}

//Video Input
videoWriterVideoInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: videoSettings)
videoWriterVideoInput?.expectsMediaDataInRealTime = true;
if (videoWriter?.canAdd(videoWriterVideoInput!))!
{
    videoWriter?.add(videoWriterVideoInput!)
}

//Audio Settings
let audioSettings : [String : Any] = [
    AVFormatIDKey : kAudioFormatMPEG4AAC,
    AVSampleRateKey : Constants.AUDIO_SAMPLE_RATE, //Float(44100.0)
    AVEncoderBitRateKey : Constants.AUDIO_BIT_RATE, //64000
    AVNumberOfChannelsKey: Constants.AUDIO_NUMBER_CHANNELS //1
]

//Audio Input
videoWriterAudioInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: audioSettings)
videoWriterAudioInput?.expectsMediaDataInRealTime = true;
if (videoWriter?.canAdd(videoWriterAudioInput!))!
{
    videoWriter?.add(videoWriterAudioInput!)
}


You can't assume a fixed sample rate.你不能假设一个固定的采样率。 Depending on the microphone and many other factors of a device, you can't always assume it will be the same.根据麦克风和设备的许多其他因素,您不能总是假设它是相同的。 This doesn't help with the FFT library I'm using (TempiFFT) - To get this to work you need to detect the sample rate ahead of time.这对我正在使用的 FFT 库(TempiFFT)没有帮助 - 要使其正常工作,您需要提前检测采样率。

Rather than:而不是:

let fft = TempiFFT(withSize: 1024, sampleRate: Constants.AUDIO_SAMPLE_RATE)

I need to first detect what the sample rate is when I start my AVCaptureSession, and then pass that detected value to the FFT library:我需要首先检测启动 AVCaptureSession 时的采样率,然后将检测到的值传递给 FFT 库:

//During initialization of AVCaptureSession
audioSampleRate = Float(AVAudioSession.sharedInstance().sampleRate)
...
//Run FFT calculations
let fft = TempiFFT(withSize: 1024, sampleRate: audioSampleRate)

Update更新

On some devices, you may not receive a full 1024 samples in your loop (on iPhone 11 I was getting 941) - if it doesn't have the right number of frames, you may get unexpected behavior from the FFT.在某些设备上,您可能无法在循环中收到完整的 1024 个样本(在 iPhone 11 上我得到了 941 个)——如果帧数不正确,您可能会从 FFT 中得到意外的行为。 I needed to create a circular buffer to store the samples upon return of each output til I had at least 1024 samples to perform the FFT.我需要创建一个循环缓冲区来存储每个输出返回时的样本,直到我至少有 1024 个样本来执行 FFT。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM