- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将确定的 AVAudioPCMBuffer
(44.1khz、1ch、float32、未交错)转换为另一个 AVAudioPCMBuffer
(16khz、1ch、int16、未交错)使用AVAudioConverter
并使用AVAudioFile
编写。我的代码使用库 AudioKit
和水龙头 AKLazyTap
来在每个确定的时间获取缓冲区,基于此来源:
https://github.com/AudioKit/AudioKit/tree/master/AudioKit/Common/Taps/Lazy%20Tap
这是我的实现:
lazy var downAudioFormat: AVAudioFormat = {
let avAudioChannelLayout = AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_Mono)!
return AVAudioFormat(
commonFormat: .pcmFormatInt16,
sampleRate: 16000,
interleaved: false,
channelLayout: avAudioChannelLayout)
}()
//...
AKSettings.sampleRate = 44100
AKSettings.numberOfChannels = AVAudioChannelCount(1)
AKSettings.ioBufferDuration = 0.002
AKSettings.defaultToSpeaker = true
//...
let mic = AKMicrophone()
let originalAudioFormat: AVAudioFormat = mic.avAudioNode.outputFormat(forBus: 0) //41.100, 1ch, float32...
let inputFrameCapacity = AVAudioFrameCount(1024)
//I don't think this is correct, the audio is getting chopped...
//How to calculate it correctly?
let outputFrameCapacity = AVAudioFrameCount(512)
guard let inputBuffer = AVAudioPCMBuffer(
pcmFormat: originalAudioFormat,
frameCapacity: inputFrameCapacity) else {
fatalError()
}
// Your timer should fire equal to or faster than your buffer duration
bufferTimer = Timer.scheduledTimer(
withTimeInterval: AKSettings.ioBufferDuration/2,
repeats: true) { [weak self] _ in
guard let unwrappedSelf = self else {
return
}
unwrappedSelf.lazyTap?.fillNextBuffer(inputBuffer, timeStamp: nil)
// This is important, since we're polling for samples, sometimes
//it's empty, and sometimes it will be double what it was the last call.
if inputBuffer.frameLength == 0 {
return
}
//This converter is only create once, as the AVAudioFile. Ignore this code I call a function instead.
let converter = AVAudioConverter(from: originalAudioFormat, to: downAudioFormat)
converter.sampleRateConverterAlgorithm = AVSampleRateConverterAlgorithm_Normal
converter.sampleRateConverterQuality = .min
converter.bitRateStrategy = AVAudioBitRateStrategy_Constant
guard let outputBuffer = AVAudioPCMBuffer(
pcmFormat: converter.outputFormat,
frameCapacity: outputFrameCapacity) else {
print("Failed to create new buffer")
return
}
let inputBlock: AVAudioConverterInputBlock = { inNumPackets, outStatus in
outStatus.pointee = AVAudioConverterInputStatus.haveData
return inputBuffer
}
var error: NSError?
let status: AVAudioConverterOutputStatus = converter.convert(
to: outputBuffer,
error: &error,
withInputFrom: inputBlock)
switch status {
case .error:
if let unwrappedError: NSError = error {
print(unwrappedError)
}
return
default: break
}
//Only created once, instead of this code my code uses a function to verify if the AVAudioFile has been created, ignore it.
outputAVAudioFile = try AVAudioFile(
forWriting: unwrappedCacheFilePath,
settings: format.settings,
commonFormat: format.commonFormat,
interleaved: false)
do {
try outputAVAudioFile?.write(from: avAudioPCMBuffer)
} catch {
print(error)
}
}
(请注意 AVAudioConverter
和 AVAudioFile
正在重用,那里的初始化并不代表我代码的真正实现,只是为了简化和制作它更容易理解。)
将 outputBuffer: AVAudioPCMBuffer
上的 frameCapacity
设置为 512,音频将被截断。有没有办法为这个缓冲区发现正确的 frameCapacity
?
使用 Swift 4 和 AudioKit 4.1 编写。
非常感谢!
最佳答案
我设法解决了这个问题,在 inputNode
上安装了一个 Tap
,如下所示:
lazy var downAudioFormat: AVAudioFormat = {
let avAudioChannelLayout = AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_Mono)!
return AVAudioFormat(
commonFormat: .pcmFormatInt16,
sampleRate: SAMPLE_RATE,
interleaved: true,
channelLayout: avAudioChannelLayout)
}()
private func addBufferListener(_ avAudioNode: AVAudioNode) {
let originalAudioFormat: AVAudioFormat = avAudioNode.inputFormat(forBus: 0)
let downSampleRate: Double = downAudioFormat.sampleRate
let ratio: Float = Float(originalAudioFormat.sampleRate)/Float(downSampleRate)
let converter: AVAudioConverter = buildConverter(originalAudioFormat)
avAudioNode.installTap(
onBus: 0,
bufferSize: AVAudioFrameCount(downSampleRate * 2),
format: originalAudioFormat,
block: { (buffer: AVAudioPCMBuffer!, _ : AVAudioTime!) -> Void in
let capacity = UInt32(Float(buffer.frameCapacity)/ratio)
guard let outputBuffer = AVAudioPCMBuffer(
pcmFormat: self.downAudioFormat,
frameCapacity: capacity) else {
print("Failed to create new buffer")
return
}
let inputBlock: AVAudioConverterInputBlock = { inNumPackets, outStatus in
outStatus.pointee = AVAudioConverterInputStatus.haveData
return buffer
}
var error: NSError?
let status: AVAudioConverterOutputStatus = converter.convert(
to: outputBuffer,
error: &error,
withInputFrom: inputBlock)
switch status {
case .error:
if let unwrappedError: NSError = error {
print("Error \(unwrappedError)"))
}
return
default: break
}
self.delegate?.flushAudioBuffer(outputBuffer)
})
}
关于avaudioengine - 将 AVAudioPCMBuffer 转换为另一个 AVAudioPCMBuffer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48831411/
我正在尝试将确定的 AVAudioPCMBuffer(44.1khz、1ch、float32、未交错)转换为另一个 AVAudioPCMBuffer(16khz、1ch、int16、未交错)使用AVA
以下代码适用于我所有设备(iPhone、Apple Watch、模拟器)上持续时间较短的音频文件: let file = try! AVAudioFile(用于阅读:url!) let format
我正在使用 installTap(onBus:bufferSize:format) 使用 AVEngine 录制音频。这会生成我积累的 AVAudioPCMBuffers。当我完成录音时,我想将它们连
我已经实现了 installTap 方法,它为我提供了音频缓冲区浮点示例。我已经通过我的 C++ DSP 库过滤了它们。我想将此缓冲区“发送”到耳机/扬声器。我从示例中再次执行了 AVAudioPCM
我正在为 iOS 应用创建这个简单的录音机和编辑器界面: 音频被记录到用于创建波形的 float 组中。录制后,我将 float 数据复制到 AVAudioPCMBuffer 中,以便与 AVAudi
我对信号处理几乎一无所知,目前我正在尝试在 Swift 中实现一个函数,当 sound pressure level 增加时触发一个事件。 (例如,当人尖叫时)。 我正在使用这样的回调进入 AVAud
是否可以将缓冲区中的数据提取为数组?我已将音频文件保存到缓冲区中,现在想提取数据。代码是: import UIKit import AVFoundation //importing audio let
我正在从麦克风录制音频并将该音频流式传输到另一台设备。目前,即使用户没有说话,此音频也会通过流发送。但我注意到很多流媒体服务在检测到来自麦克风的噪音很小时实际上并没有发送你的麦克风输入。 所以我想问,
我正在尝试在 Swift 中以编程方式填充 AVAudioPCMBuffer 以构建节拍器。这是我尝试构建的第一个真正的应用程序,所以它也是我的第一个音频应用程序。现在我正在尝试使用不同的框架和方法来
我无法使用 AVAudioPCMBuffer 播放声音(尽管我可以使用 AVAudioFile 播放)。我收到了这个错误。 错误:AVAudioBuffer.mm:169: -[AVAudioPCMB
我目前正在尝试转换 AVAudioPCMBuffer 中的音频样本至NSData - 我已经查看了关于此的已接受答案SO Post还有这个code from GitHub但似乎有一些AVFAudio
与 iOS 10 一起,Apple 发布了一个识别语音的新框架。可以通过附加 AVAudioPCMBuffers 或为 m4a 提供 URL 将数据传递到此框架。目前,语音识别使用前者进行工作,但这只
我们正在开发一个记录和保留麦克风输入的应用程序。 AVAudioRecorder 的使用不是一个选项,因为需要实时音频处理。 AVAudioEngine 之所以被使用是因为它提供了对输入音频的低级访问
我有这个代码: func loadSoundfont(_ pitch : String) { let path: String = Bundle.main.path(forResource:
我一直在致力于一个项目,以创建一个显示麦克风功率级别的应用程序。我知道 AVAudioRecorder 类提供平均/峰值功率,但我希望只能记录某些频段的功率级别。我使用 AudioUnitEQ 类来设
我正在尝试从 PCMBuffer 播放音频。当我运行下面的代码时,由于某种原因,没有音频播放。我没有收到任何错误。 let engine = AVAudioEngine() let player =
我在 swift 中有一个数据对象,它是一个 Int16 对象数组。出于某种原因,使用“.pcmFormatInt16”对我的 AVAudioPCMBuffer 格式不起作用并且没有产生声音或内存错误
我正在尝试从 AVCaptureAudioDataOutputSampleBufferDelegate 的 captureOutput 返回的 CMSampleBuffer 中读取频率值。 我的想法是
我正在尝试获取 AVAudioPCMBuffer 的时间长度,但我似乎做不到。我尝试执行以下操作: func getLength(buffer: AVAudioPCMBuffer) -> TimeIn
我遇到了 AVAudioConverter 的问题.我正在尝试转换 AVAudioPCMBuffers至 AAC . 这是我用于转换的函数,取自“What's new in Core Audio” s
我是一名优秀的程序员,十分优秀!