繁体   English   中英

iPhone11 意外数量的音频样本

[英]iPhone11 unexpected number of Audio Samples

我有一个使用AVAssetWriter捕获音频和视频的应用程序。 它对音频运行快速傅立叶变换 (FFT),以实时创建捕获音频的可视频谱。

直到 iPhone11 发布,这一切都运行良好。 但是,使用 iPhone 11 的用户报告说根本没有捕获音频。 我设法缩小了问题的范围 - captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)中返回的样本数是 940 或 941 - 在以前的手机型号上,这始终是 1024 个样本。 我使用CMSampleBufferGetNumSamples来获取样本数。 我的 FFT 计算依赖于样本数为 2 的幂,因此它会丢弃较新型号 iPhone 上的所有帧。

有人能解释一下为什么新 iPhone11 返回的样本数量异常吗? 这是我配置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!)
}


你不能假设一个固定的采样率。 根据麦克风和设备的许多其他因素,您不能总是假设它是相同的。 这对我正在使用的 FFT 库(TempiFFT)没有帮助 - 要使其正常工作,您需要提前检测采样率。

而不是:

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

我需要首先检测启动 AVCaptureSession 时的采样率,然后将检测到的值传递给 FFT 库:

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

更新

在某些设备上,您可能无法在循环中收到完整的 1024 个样本(在 iPhone 11 上我得到了 941 个)——如果帧数不正确,您可能会从 FFT 中得到意外的行为。 我需要创建一个循环缓冲区来存储每个输出返回时的样本,直到我至少有 1024 个样本来执行 FFT。

暂无
暂无

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

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