質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

0回答

1066閲覧

ipad同士でマイクから入力された音声で通話したい

nu-

総合スコア6

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/05/02 07:18

実現したいこと

作成しているアプリの機能の一部で、ipadのマイクから入力された音声で、リアルタイム通話をする
機能を作成しています。
マイクからの音声は、AVAudioEngineを使用しています。
音声データはData型に変換後、UDP通信を使用し送信しています。

現在、マイクから入力された音声をUDP通信で送信し受信するところまではできていると思うのですが、
受け取ったデータを再生する方法がわかりません。

試したこと

受信したData型をAVAudioPCMBufferに変換しAVAudioEngineで再生しようとしてみたのですが
下記のようなエラーがでてしまいアプリが落ちてしまいます。
また、この方法で試してはみたのですが、データを受信するたびにAngineを止めているため音声をうまく再生できた場合でも
音が途切れてしまうような気がします。

ソースコードの一部を貼らせていただきます。
長くなり申し訳ございませんが、
再生するための方法やアドバイスをいただけませんでしょうか。
###環境
言語:Swift4
Xcode:9.2
プログラムの実行は、シュミレータを使用しています。

エラーメッセージ

2018-05-02 15:07:35.508183+0900 AudioConnectTest[3614:125779] AUBase.cpp:832:DispatchSetProperty: ca_require: ValidFormat(inScope, inElement, newDesc) InvalidFormat 2018-05-02 15:07:35.508687+0900 AudioConnectTest[3614:125779] [avae] AVAEInternal.h:124:_AVAE_CheckSuccessAndNoNSError: [AUInterface.mm:512:SetFormat: ([[busArray objectAtIndexedSubscript:(NSUInteger)element] setFormat:format error:&nsErr])] returned false, error Error Domain=NSOSStatusErrorDomain Code=-10868 "(null)" 2018-05-02 15:07:35.512176+0900 AudioConnectTest[3614:125779] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: '[[busArray objectAtIndexedSubscript:(NSUInteger)element] setFormat:format error:&nsErr]: returned false, error Error Domain=NSOSStatusErrorDomain Code=-10868 "(null)"' *** First throw call stack: ( 0 CoreFoundation 0x000000010530312b __exceptionPreprocess + 171 1 libobjc.A.dylib 0x0000000103efef41 objc_exception_throw + 48 2 CoreFoundation 0x00000001053082f2 +[NSException raise:format:arguments:] + 98 3 AVFAudio 0x00000001142384fe _Z19AVAE_RaiseExceptionP8NSStringz + 158 4 AVFAudio 0x000000011429b596 _Z30_AVAE_CheckSuccessAndNoNSErrorPKciS0_S0_bP7NSError + 472 5 AVFAudio 0x000000011429b3b1 _ZN17AUInterfaceBaseV39SetFormatEbjP13AVAudioFormat + 147 6 AVFAudio 0x0000000114293913 _ZN21AVAudioPlayerNodeImpl15SetOutputFormatEmP13AVAudioFormat + 25 7 AVFAudio 0x000000011422d790 _ZN18AVAudioEngineGraph8_ConnectEP19AVAudioNodeImplBaseS1_jjP13AVAudioFormat + 1664 8 AVFAudio 0x0000000114297814 _ZN17AVAudioEngineImpl7ConnectEP11AVAudioNodeS1_mmP13AVAudioFormat + 194 9 AVFAudio 0x000000011429787b -[AVAudioEngine connect:to:format:] + 83 10 AudioConnectTest 0x000000010344012b _T016AudioConnectTest0A5UnittC13playSineWave3ySo16AVAudioPCMBufferC8audiobuf_tF + 1211 11 AudioConnectTest 0x000000010343d72a _T016AudioConnectTest0A5UnittC9udpSocketySo011GCDAsyncUdpF0C_10Foundation4DataV10didReceiveAI11fromAddressypSg17withFilterContexttF + 202 12 AudioConnectTest 0x000000010343d95f _T016AudioConnectTest0A5UnittC9udpSocketySo011GCDAsyncUdpF0C_10Foundation4DataV10didReceiveAI11fromAddressypSg17withFilterContexttFTo + 383 13 CocoaAsyncSocket 0x00000001037826cc __72-[GCDAsyncUdpSocket notifyDidReceiveData:fromAddress:withFilterContext:]_block_invoke + 76 14 libdispatch.dylib 0x000000010987e2f7 _dispatch_call_block_and_release + 12 15 libdispatch.dylib 0x000000010987f33d _dispatch_client_callout + 8 16 libdispatch.dylib 0x000000010988a5f9 _dispatch_main_queue_callback_4CF + 628 17 CoreFoundation 0x00000001052c5e39 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 18 CoreFoundation 0x000000010528a462 __CFRunLoopRun + 2402 19 CoreFoundation 0x0000000105289889 CFRunLoopRunSpecific + 409 20 GraphicsServices 0x000000010aec49c6 GSEventRunModal + 62 21 UIKit 0x00000001057815d6 UIApplicationMain + 159 22 AudioConnectTest 0x000000010344a647 main + 55 23 libdyld.dylib 0x00000001098fbd81 start + 1 24 ??? 0x0000000000000001 0x0 + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException

該当のソースコード

宣言部分

swift

1 var audioEngine : AVAudioEngine! 2 var audioFile : AVAudioFile! 3 var audioPlayer : AVAudioPlayerNode! 4 var outref: ExtAudioFileRef? 5 var audioFilePlayer: AVAudioPlayerNode! 6 var mixer : AVAudioMixerNode! 7 var filePath : String? = nil 8 var isPlay = false 9 var isRec = false 10 var captureSession = AVCaptureSession() 11 var audioData:AVCaptureAudioDataOutput! 12 13 var audioEngine1 : AVAudioEngine! 14 var audioFilePlayer1: AVAudioPlayerNode! 15 var mixer1 : AVAudioMixerNode! 16 17 let audioEngine2 = AVAudioEngine() 18 let player = AVAudioPlayerNode() 19 var sinFlg = false 20

音声データ受信と再生部分

swift

1//音声データ受信 2 func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?){ 3 let convertPcmData = toPCMBuffer(data: data as NSData)//受信したデータをPCMBufferに変換 4 audioPlay(audiobuf: convertPcmData)//再生 5 } 6 7//再生 8 func audioPlay(audiobuf:AVAudioPCMBuffer) { 9 let format2 = AVAudioFormat( 10 commonFormat: AVAudioCommonFormat.pcmFormatInt16, 11 sampleRate: 8000.0, 12 channels: 1, 13 interleaved: false) 14 15 if (audioEngine2.isRunning) {//2回目以降受信した場合は一度止めてから再生する。 16 audioEngine2.stop() 17 audioEngine2.reset() 18 } 19 if(!sinFlg){ 20 sinFlg = true 21 // オーディオエンジンにプレイヤーをアタッチ 22 audioEngine2.attach(player) 23 } 24 let mixer = audioEngine2.mainMixerNode 25 audioEngine2.connect(player, to: mixer, format: format2)//☆ここで上記のエラーが出てアプリが落ちてしまいます。 26 player.scheduleBuffer(audiobuf) { 27 print("Play completed") 28 } 29 do { 30 // エンジンを開始 31 try audioEngine2.start() 32 // 再生 33 player.play() 34 } catch let error { 35 print(error) 36 } 37 }

マイクからの音声データ取得部分

swift

1 func startRecord() { 2 3 let audioF = audioFilePlayer.outputFormat(forBus: 0) 4 let asdf = audioF.channelCount 5 let fasd = audioF.channelLayout 6 let wre = audioF.sampleRate 7 8 self.filePath = nil 9 10 self.isRec = true 11 try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord) 12 try! AVAudioSession.sharedInstance().setActive(true) 13 let format = AVAudioFormat( 14 commonFormat: AVAudioCommonFormat.pcmFormatInt16, 15 sampleRate: 44100.0, 16 channels: 1, 17 interleaved: true) 18 self.audioEngine.connect(self.audioEngine.inputNode, to: self.mixer, format: format) 19 20 //データ変換用フォーマット 21 let downFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16, 22 sampleRate: 8000.0, 23 channels: 1, 24 interleaved: true) 25 audioEngine.inputNode.installTap(onBus: 0, bufferSize: AVAudioFrameCount((format?.sampleRate)! * 0.1), format: format, block: { (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in 26 //音声データを取得してサンプリングレートを8000kHに変換 27 let converter = AVAudioConverter.init(from: format!, to: downFormat!) 28 let newbuffer = AVAudioPCMBuffer(pcmFormat: downFormat!, 29 frameCapacity: AVAudioFrameCount((downFormat?.sampleRate)! * 0.1)) 30 let inputBlock : AVAudioConverterInputBlock = { (inNumPackets, outStatus) -> AVAudioBuffer? in 31 outStatus.pointee = AVAudioConverterInputStatus.haveData 32 let audioBuffer : AVAudioBuffer = buffer 33 return audioBuffer 34 } 35 var error : NSError? 36 converter?.convert(to: newbuffer!, error: &error, withInputFrom: inputBlock) 37 _ = ExtAudioFileWrite(self.outref!, (newbuffer?.frameLength)!, (newbuffer?.audioBufferList)!) 38 39 let test = self.toNSData(PCMBuffer: newbuffer!)//PCMBufferからNSData型に変換 40 self.sendData(data: test as Data)//NSDataからData型に変換してUDP通信で送信 41 }) 42 43 try! self.audioEngine.start() 44 }

データ変換部分

swift

1 func toNSData(PCMBuffer: AVAudioPCMBuffer) -> NSData {//PCMBufferをDataに変換 2 let channelCount = 1 // given PCMBuffer channel count is 1 3 var channels = UnsafeBufferPointer(start: PCMBuffer.int16ChannelData, count: channelCount) 4 var ch0Data = NSData(bytes: channels[0], length:Int(PCMBuffer.frameCapacity * PCMBuffer.format.streamDescription.pointee.mBytesPerFrame)) 5 return ch0Data 6 } 7 func toPCMBuffer(data: NSData) -> AVAudioPCMBuffer {//データをPCMBufferに変換 8 let audioFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: 8000, channels: 1, interleaved: true) // given NSData audio format 9 var PCMBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat!, frameCapacity: UInt32(data.length) / (audioFormat?.streamDescription.pointee.mBytesPerFrame)!) 10 PCMBuffer?.frameLength = (PCMBuffer?.frameCapacity)! 11 let channels = UnsafeBufferPointer(start: PCMBuffer?.int16ChannelData, count: Int(PCMBuffer!.format.channelCount)) 12 data.getBytes(UnsafeMutableRawPointer(channels[0]) , length: data.length) 13 return PCMBuffer! 14 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問