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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

iOS

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

Swift

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

Q&A

解決済

2回答

4303閲覧

【iOS】sampleBufferをAACへ正しくエンコードできない。

t_suzuki_

総合スコア7

Objective-C

Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

iOS

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

Swift

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

0グッド

0クリップ

投稿2016/06/29 09:34

編集2016/07/06 10:04

###前提・実現したいこと

xcode7.3にて、iphoneから録音した音声をリアルタイムに送信したい。
録音はAVCaptureSessionで行い、captureOutputにて得られるsampleBuffer(llcm)をformat:AAC,16000Khzにエンコード。

エンコードは以下のライブラリを使用。
エンコードライブラリ

###発生している問題・エラーメッセージ・疑問点
AAC decode failed

7/6 正常に動いたものにコード書き換え
encodeは上記ライブラリ使用
16000KHzのためAACEncoderのfreqIdx = 8

captureClass var audioConnection:AVCaptureConnection? var sessions = AVCaptureSession() var aacEncoder: AACEncoder = AACEncoder() func setupMicrophone() { let audio_output = AVCaptureAudioDataOutput() let audioSession:AVAudioSession = AVAudioSession.sharedInstance() try! audioSession.setCategory(AVAudioSessionCategoryRecord) try! audioSession.setPreferredSampleRate(16000.0) try! audioSession.setPreferredIOBufferDuration(1024.0/16000.0) try! audioSession.setActive(true) self.sessions.beginConfiguration() self.sessions = AVCaptureSession() self.sessions.automaticallyConfiguresApplicationAudioSession = false self.sessions.commitConfiguration() sessions.sessionPreset = AVCaptureSessionPresetLow let mic = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeAudio) var mic_input: AVCaptureDeviceInput! audio_output.setSampleBufferDelegate(self, queue: dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) do { mic_input = try AVCaptureDeviceInput(device: mic) } catch { return } sessions.addInput(mic_input) sessions.addOutput(audio_output) audioConnection = audio_output.connectionWithMediaType(AVMediaTypeAudio) } func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) { if connection == audioConnection { aacEncoder.encodeSampleBuffer(sampleBuffer) { (data:NSData!, error:NSError!) in if data != nil{ 送信処理(data) NSLog("complete data.length %d", data.length) } } }

###考えられる原因
・nsDataへの変換に問題がある?

###試したこと
・adtsヘッダのfreqIdxを変更。
・ACCaptureのsampleRate,IOBufferDurationを変更。

・音楽ファイル.aacをnsDataとして読み込み、adtsヘッダをつけて送信したところ正しく再生された。

当方、xcodeを触り始めて間もない初心者ですが、どなたかご教授願いします。

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

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

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

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

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

pebble8888

2016/07/01 00:56

ライブラリの利用部分のソースも含めた全体のソースを提示して貰えたら回答できるかも知れません。
t_suzuki_

2016/07/01 02:18

一部追加しました。AACEncoderは上記リンクのものをそのまま使用しています。
guest

回答2

0

こんにちわ。
AVCaptureOutputでのCMSampleBufferからAACへのエンコード処理も書いています。ご参考までにどうぞ。
https://github.com/shogo4405/lf.swift/blob/master/Sources/Codec/AACEncoder.swift

上記コードのNSLog(サイズ0)ではmDataByteSize:4096だが
(サイズ1)ではmDataByteSize:4になる。

AudioConverterFillComplexBufferの後では圧縮した後の実際の値なので減ること自体は問題ありません。

audioSessionのSampleRateを16000にすると

ダウンサンプル(入力44.1khz→出力16khz)考慮していない可能性があるので、入力ソース自体を16khzに設定して(入力16khz→入力16khz)で期待した動作する可能性があります。

let sampleRate:Double = 16_000
do {
try AVAudioSession.sharedInstance().setPreferredSampleRate(sampleRate)
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
try AVAudioSession.sharedInstance().setMode(AVAudioSessionModeVideoChat)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
}

投稿2016/07/03 12:19

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

t_suzuki_

2016/07/05 08:04

回答ありがとうございます。 貼って頂いたAACEncoderを利用し、sampleOutputのsampleBufferをprintすると mediaType:'soun' mediaSubType:'AAC ' となることを確認できました。 ただしこれをNSdataにして送っても、送信先でAAC decode failedとなってしまいます。 これはAACのCMSampleBufferを正しくNSDataにできていないためなのでしょうか? 申し訳ないのですが、該当部分のソースを追記したので教えていただけると幸いです。
退会済みユーザー

退会済みユーザー

2016/07/06 04:54

NSData化はうまくいっているように見えます。 AAC decodeライブラリーなどを提示していただければデバッグできると思いますので差し支えなければ教えてください。
t_suzuki_

2016/07/06 09:58

すいません、Encoderの使い方が悪かっただけで、AAC decodeライブラリーの方は問題なく正常に再生できました。 回答ありがとうございました。
guest

0

ベストアンサー

エンコードライブラリに問題がある気がしますが、
どこが問題なのかは分かりません。

AACへのエンコード処理は、Appleの公式SampleCodeを参考にご自身で実装される方がよいかも知れません。
エンコード処理部分のコード量はそれほど多くありません。

https://developer.apple.com/library/ios/samplecode/iPhoneACFileConvertTest/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010581-Intro-DontLinkElementID_2

[追記]
よく見るとaacEncoderがローカル変数になっていますね。
クラスのメンバ変数にしないとまともに動作しないと思います。
ライブラリに問題はなさそうです。

投稿2016/07/01 00:36

編集2016/07/02 12:37
pebble8888

総合スコア390

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

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

t_suzuki_

2016/07/01 09:50 編集

回答ありがとうございます! このライブラリは使用せず、公式のコードを参考に実装してみようと思います。 【追記】 貼って頂いたリンクを見てみたのですが、既存のファイルからエンコード処理,再生をしているようなのですが、既存のファイルではなくAVCaptureOutputのsamplebufferからリアルタイムにエンコードはできるのでしょうか? 知識がなく申し訳ないです。
pebble8888

2016/07/01 11:31 編集

AVCaptureOutputは使ったことがないので分かりませんが、sample bufferも音声データだと思いますので、リアルタイムにエンコードできると思います。SampleCodeは入力と出力がたまたまファイルなだけです。が、AAC出力をストリームにするには知識が必要なので難しいかもですね。
t_suzuki_

2016/07/05 08:18

回答ありがとうございます。 AAC出力をストリームにするのは難しいのですね。 もっと勉強してから自分で実装できればと思います。
pebble8888

2016/07/05 11:50

回答本文に追記しましたが、aacEncoderがローカル変数になっていたのでそれでは動きません。 aacEncoderをクラスのメンバ変数に直してみてください。 ちなみにそれを行ったサンプルをこちらに上げてあります。 データを検証する方法がないですが、有効そうなデータが生成されているように見えます。 https://github.com/pebble8888/AACEncoderSample
t_suzuki_

2016/07/06 09:56

回答の追記ありがとうございます。サンプル参照させて頂きました。 そちらを参考に修正を行ったところ、正しくエンコード、再生できました! ありがとうございました。 aacEncoderをクラスのメンバ変数に修正することでうまくいったようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問