- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有两个类,MicrophoneHandler
和 AudioPlayer
。我已经设法使用 AVCaptureSession
使用已批准的答案来窃听麦克风数据 here ,并使用此函数将 CMSampleBuffer
转换为 NSData
:
func sendDataToDelegate(buffer: CMSampleBuffer!)
{
let block = CMSampleBufferGetDataBuffer(buffer)
var length = 0
var data: UnsafeMutablePointer<Int8> = nil
var status = CMBlockBufferGetDataPointer(block!, 0, nil, &length, &data) // TODO: check for errors
let result = NSData(bytesNoCopy: data, length: length, freeWhenDone: false)
self.delegate.handleBuffer(result)
}
我现在想通过将上面生成的 NSData
转换为 AVAudioPCMBuffer
并使用 AVAudioEngine
播放它来通过扬声器播放音频。我的AudioPlayer
类如下:
var engine: AVAudioEngine!
var playerNode: AVAudioPlayerNode!
var mixer: AVAudioMixerNode!
override init()
{
super.init()
self.setup()
self.start()
}
func handleBuffer(data: NSData)
{
let newBuffer = self.toPCMBuffer(data)
print(newBuffer)
self.playerNode.scheduleBuffer(newBuffer, completionHandler: nil)
}
func setup()
{
self.engine = AVAudioEngine()
self.playerNode = AVAudioPlayerNode()
self.engine.attachNode(self.playerNode)
self.mixer = engine.mainMixerNode
engine.connect(self.playerNode, to: self.mixer, format: self.mixer.outputFormatForBus(0))
}
func start()
{
do {
try self.engine.start()
}
catch {
print("error couldn't start engine")
}
self.playerNode.play()
}
func toPCMBuffer(data: NSData) -> AVAudioPCMBuffer
{
let audioFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.PCMFormatFloat32, sampleRate: 8000, channels: 2, interleaved: false) // given NSData audio format
let PCMBuffer = AVAudioPCMBuffer(PCMFormat: audioFormat, frameCapacity: UInt32(data.length) / audioFormat.streamDescription.memory.mBytesPerFrame)
PCMBuffer.frameLength = PCMBuffer.frameCapacity
let channels = UnsafeBufferPointer(start: PCMBuffer.floatChannelData, count: Int(PCMBuffer.format.channelCount))
data.getBytes(UnsafeMutablePointer<Void>(channels[0]) , length: data.length)
return PCMBuffer
}
当在上面的第一个代码片段中调用 self.delegate.handleBuffer(result)
时,缓冲区到达 handleBuffer:buffer
函数。
我能够print(newBuffer)
,并查看转换后缓冲区的内存位置,但扬声器没有任何声音。我只能想象与 NSData
之间的转换不一致。有任何想法吗?提前致谢。
最佳答案
NSData
格式为什么不一路使用AVAudioPlayer
呢?如果您确实需要 NSData
,您始终可以从下面的 soundURL
加载此类数据。在这个例子中,磁盘缓冲区是这样的:
let soundURL = documentDirectory.URLByAppendingPathComponent("sound.m4a")
无论如何,为了优化内存和资源管理,直接记录到文件中是有意义的。您可以通过这种方式从记录中获取 NSData
:
let data = NSFileManager.defaultManager().contentsAtPath(soundURL.path())
下面的代码就是你所需要的:
记录
if !audioRecorder.recording {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
audioRecorder.record()
} catch {}
}
播放
if (!audioRecorder.recording){
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: audioRecorder.url)
audioPlayer.play()
} catch {}
}
设置
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
try audioRecorder = AVAudioRecorder(URL: self.directoryURL()!,
settings: recordSettings)
audioRecorder.prepareToRecord()
} catch {}
设置
let recordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)),
AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)),
AVNumberOfChannelsKey : NSNumber(int: 1),
AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue))]
下载 Xcode 项目:
你可以找到这个例子here .从 Swift Recipes 下载完整的项目,它可以在模拟器和设备上录制和播放。 .
关于ios - 使用 AVAudioEngine 从 AVAudioPCMBuffer 播放音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33906649/
我正在尝试将确定的 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
我是一名优秀的程序员,十分优秀!