###2016.09.05
- オディオのAVFrameのlinesizeやnb_samplesについてAVAudioPCMBufferの設定値をもっと精密にやり直しました。
let audioContext: UnsafeMutablePointer<AVCodecContext>
// プレイするサウンドの基本設定
let audioFormat: AVAudioFormat(
commonFormat: .pcmFormatFloat32,
sampleRate: Double(audioContext.pointee.sample_rate),
channels: 2, // サウンドシステムのoutputチャンネルを超えたらクラッシューが発生されます。
interleaved: false)
let audioEngine = AVAudioEngine()
let audioPlayer = AVAudioPlayerNode()
// オディオエンジンにプレイヤーを付けます。
engine.attach(audioPlayer)
// オディオエンジンの基本出力ノードにプレイヤーを連結します。
engine.connect(audioPlayer, to: engine.mainMixerNode, format: audioFormat)
engine.prepare()
try! engine.start()
audioPlayer.play()
...
// ディコードされたAVFrameをAVAudioPCMBufferに格納します。
let frame: AVFrame
// frameCapacityはframeに配置されているfloatデータの個数を計算し渡します。
let pcmBuffer = AVAudioPCMBuffer(
pcmFormat: audioFormat,
frameCapacity: AVAudioFrameCount(frame.linesize.0 / MemoryLayout<Float>.size))
// frameLengthは実際のaudioのfloatデータの個数を渡します。
// バーファーの長さとsamplesの個数は同じ場合も違う場合もあります。
pcmBuffer.frameLength = frame.nb_samples // AVAudioFileを利用する場合は自動に設定されるところですが、その以外は直接やります。
// ファファーに設定したformatでかくチャンネルのデータのメモリが配置されます。
// 普通はステレオで2個になります。
let channels = buffer.floatChannelData!
let leftOutputChannel: UnsafeMutablePointer<UnsafeMutablePointer<Float>> = channels[0]
let rightOutputChannel: UnsafeMutablePointer<UnsafeMutablePointer<Float>> = channels[1]
// frameのデータタイプは常にUInt8なのでFloatに変えます。
let leftAudioBuffer: UnsafeMutablePointer<Float> = frame.data.0!.withMemoryRebound(to: Float.self, capacity: Int(pcmBuffer.frameLength)){$0}
let rightAudioBuffer: UnsafeMutablePointer<Float> = frame.data.1!.withMemoryRebound(to: Float.self, capacity: Int(pcmBuffer.frameLength)){$0}
// leftAudioBufferの内容をAccelerateの関数を利用し複写します。
cblas_scopy(Int32(pcmBuffer.frameLength), leftAudioBuffer, 1, channels[0], 1)
cblas_scopy(Int32(pcmBuffer.frameLength), rightAudioBuffer, 1, channels[1], 1)
// オディオのデータが2チャンネル以上を持つ場合、ここでは5.1chのオディオだと仮定します。
// 出力のチャンネルは二つなので余るデータはAccelerateの関数を使って既存のデータに加えます。
let lbuf1 = frame.data.2!.withMemoryRebound(to: Float.self, capacity: Int(buffer.frameLength)){$0}
let rbuf1 = frame.data.3!.withMemoryRebound(to: Float.self, capacity: Int(buffer.frameLength)){$0}
let lbuf2 = frame.data.4!.withMemoryRebound(to: Float.self, capacity: Int(buffer.frameLength)){$0}
let rbuf2 = frame.data.5!.withMemoryRebound(to: Float.self, capacity: Int(buffer.frameLength)){$0}
vDSP_vadd(channels[0], 1, lbuf1, 1, channels[0], 1, vDSP_Length(buffer.frameLength))
vDSP_vadd(channels[1], 1, rbuf1, 1, channels[1], 1, vDSP_Length(buffer.frameLength))
vDSP_vadd(channels[0], 1, lbuf2, 1, channels[0], 1, vDSP_Length(buffer.frameLength))
vDSP_vadd(channels[1], 1, rbuf2, 1, channels[1], 1, vDSP_Length(buffer.frameLength))
//最後に作ったオディオのbufferをAVAudioPlayerNodeに入れます。
audioPlayer.scheduleBuffer(pcmBuffer, completionHandler: nil)
で、サウンドの再生が可能になります。