CoreAudioでよく使われるAudioStreamBasicDescription
これはC言語の構造体で使いづらいです。
macOS10.10, iOS8以降ではAVAudioFormatと相互変換できますので、これを経由するとコーディングが簡単になります。
まずは実例を見ていきます。
よく使われる.wavファイルのフォーマットを作ってみます。
let fmt = AVAudioFormat(commonFormat:.pcmFormatInt16, sampleRate:44100, channels:2, interleaved:true) print("\(fmt)") // <AVAudioFormat 0x100b06650: 2 ch, 44100 Hz, Int16, inter> let asbd:AudioStreamBasicDescription = fmt.streamDescription.pointee // AudioStreamBasicDescription(mSampleRate: 44100.0, mFormatID: 1819304813, mFormatFlags: 12, mBytesPerPacket: 4, mFramesPerPacket: 1, mBytesPerFrame: 4, mChannelsPerFrame: 2, mBitsPerChannel: 16, mReserved: 0) print("\(asbd)")
1819304813(=0x6c70636d)というのは kAudioFormatLinearPCM = 'lpcm'の10進値で、線形PCM形式であることを示しています。
フォーマットフラグの12は
12=8(=kAudioFormatFlagIsPacked)+4(kAudioFormatFlagIsSignedInteger)
を意味します。
例をもう一つ見て見ましょう。
import AVFoundation let fmt = AVAudioFormat(standardFormatWithSampleRate:44100, channels:2) //<AVAudioFormat 0x100a00bb0: 2 ch, 44100 Hz, Float32, non-inter> let asbd:AudioStreamBasicDescription = fmt.streamDescription.pointee print("\(asbd)") //AudioStreamBasicDescription( mSampleRate: 44100.0, mFormatID: 1819304813, mFormatFlags: 41, mBytesPerPacket: 4, //mFramesPerPacket: 1, mBytesPerFrame: 4, mChannelsPerFrame: 2, mBitsPerChannel: 32, mReserved: 0)
標準フォーマットとはfloat32のnon-interleavedの事だとわかります。
non-interleaveとはステレオの場合に、
LRの音データをLLL..., RRR...
のように別領域に割り当てることを指します。
interleaveの場合LRLR...のように交互に割り当てます。
フォーマットフラグの41は
41=32(kAudioFormatFlagsIsNonInterleaved)+8(kAudioFormatFlagsIsPacked)+1(kAudioFormatFlagIsFloat)
を意味します。
クラス構造を見てきます。
open class AVAudioFormat : NSObject, NSSecureCoding { public init(streamDescription asbd: UnsafePointer<AudioStreamBasicDescription>) public init(streamDescription asbd: UnsafePointer<AudioStreamBasicDescription>, channelLayout layout: AVAudioChannelLayout?) public init(standardFormatWithSampleRate sampleRate: Double, channels: AVAudioChannelCount) public init(standardFormatWithSampleRate sampleRate: Double, channelLayout layout: AVAudioChannelLayout) public init(commonFormat format: AVAudioCommonFormat, sampleRate: Double, channels: AVAudioChannelCount, interleaved: Bool) public init(commonFormat format: AVAudioCommonFormat, sampleRate: Double, interleaved: Bool, channelLayout layout: AVAudioChannelLayout) public init(settings: [String : Any]) public init(cmAudioFormatDescription formatDescription: CMAudioFormatDescription) open func isEqual(_ object: Any) -> Bool open var isStandard: Bool { get } open var commonFormat: AVAudioCommonFormat { get } open var channelCount: AVAudioChannelCount { get } open var sampleRate: Double { get } open var isInterleaved: Bool { get } open var streamDescription: UnsafePointer<AudioStreamBasicDescription> { get } open var channelLayout: AVAudioChannelLayout? { get } open var magicCookie: Data? open var settings: [String : Any] { get } open var formatDescription: CMAudioFormatDescription { get } } // モノラルなら1,ステレオなら2の値です public typealias AVAudioChannelCount = UInt32 // よく使うのはpcmFormatFloat32とpcmFormatInt16でしょう public enum AVAudioCommonFormat : UInt { case otherFormat case pcmFormatFloat32 case pcmFormatFloat64 case pcmFormatInt16 case pcmFormatInt32 }
formatDescriptionプロパティとsettingsプロパティに何が入っているのかも見てみましょう。
let fmt = AVAudioFormat(commonFormat:.pcmFormatInt16, sampleRate:44100, channels:2, interleaved:true) print("\(fmt.formatDescription)") print("\(fmt.settings)") <CMAudioFormatDescription 0x100a075a0 [0x7fffd7221d80]> { mediaType:'soun' mediaSubType:'lpcm' mediaSpecific: { ASBD: { mSampleRate: 44100.000000 mFormatID: 'lpcm' mFormatFlags: 0xc mBytesPerPacket: 4 mFramesPerPacket: 1 mBytesPerFrame: 4 mChannelsPerFrame: 2 mBitsPerChannel: 16 } cookie: {(null)} ACL: {(null)} FormatList Array: {(null)} } extensions: {(null)} } ["AVLinearPCMIsFloatKey": 0, "AVLinearPCMIsNonInterleaved": 0, "AVNumberOfChannelsKey": 2, "AVSampleRateKey": 44100, "AVLinearPCMBitDepthKey": 16, "AVLinearPCMIsBigEndianKey": 0, "AVFormatIDKey": 1819304813]
settingsには文字列キーのDictionaryが入っているようです。