Ich habe zwei Klassen, MicrophoneHandler
und AudioPlayer
. Ich habe es geschafft AVCaptureSession
zu verwenden Mikrofondaten mit der genehmigten Antwort here tippen, und und konvertiert die CMSampleBuffer
-NSData
mit dieser Funktion:Wiedergabe von AVAudioPCMBuffer mit AVAudioEngine
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)
}
Ich möchte nun den Ton über den Lautsprecher spielen, indem sie die NSData
Umwandlung erzeugt oben zu AVAudioPCMBuffer
und spielen Sie es mit AVAudioEngine
. Meine AudioPlayer
Klasse ist wie folgt:
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
}
Der Puffer erreicht die handleBuffer:buffer
Funktion, wenn self.delegate.handleBuffer(result)
oben im ersten Schnipsel genannt wird.
Ich kann print(newBuffer)
, und sehen Sie die Speicherplätze der konvertierten Puffer, aber nichts kommt aus den Lautsprechern. Ich kann mir nur vorstellen, dass zwischen den Konvertierungen zu und von NSData
etwas nicht konsistent ist. Irgendwelche Ideen? Danke im Voraus.
Wir benötigen das NSData-Rohformat, um es über einen Socket zu übertragen. Wir streamen Audio. –
Datei zu 'NSData' kommt aus der Box. Kannst du dir die Datei nur als Puffer vorstellen? Es ist zufällig ein Plattenpuffer, aber es ist immer noch nur ein Puffer? – SwiftArchitect
Wie löschen wir den Puffer jedes Mal, wenn wir ein Paket mit NSData über den Socket senden? @SwiftArchitect –