2015-11-25 55 views
6

私は2つのクラス、MicrophoneHandler、およびAudioPlayerを持っています。私は、承認された答えhereを使用して、マイクデータをタップするAVCaptureSessionを使用して管理し、かつ、この機能を使用してNSDataCMSampleBufferを変換した:AVAudioEngineでAVAudioPCMBufferからオーディオを再生

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への変換と変換の間に何かが一致しないと想像することができます。何か案は?前もって感謝します。

答えて

1

NSData形式

はなぜAVAudioPlayerすべての方法を使用してスキップ? NSDataが確実に必要な場合は、そのデータをいつでも下のsoundURLから読み込むことができます。

​​

それが最適なメモリとリソース管理のためにとにかくファイルに直接録音することは理にかなっています。この例では、ディスクバッファのようなものです。あなたの記録からこの方法を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からダウンロードします。

+0

ソケットで送信するには、NSData raw形式が必要です。私たちはオーディオをストリーミングしています。 –

+0

ファイルを 'NSData'に出力します。ファイルを単なるバッファと考えることはできますか?それはディスクバッファであることがありますが、それはまだ単なるバッファですか? – SwiftArchitect

+0

ソケットを介してNSDataのパケットを送信するたびにバッファをクリアするにはどうすればよいですか? @SwiftArchitect –

関連する問題