mirror of
https://github.com/HaishinKit/HaishinKit.swift.git
synced 2026-05-07 20:12:28 +00:00
92 lines
3.1 KiB
Swift
92 lines
3.1 KiB
Swift
import CoreMedia
|
|
import Foundation
|
|
|
|
package struct ADTSHeader: Equatable {
|
|
static let size: Int = 7
|
|
static let sizeWithCrc = 9
|
|
static let sync: UInt8 = 0xFF
|
|
|
|
var sync = Self.sync
|
|
var id: UInt8 = 0
|
|
var layer: UInt8 = 0
|
|
var protectionAbsent = false
|
|
var profile: UInt8 = 0
|
|
var sampleFrequencyIndex: UInt8 = 0
|
|
var channelConfiguration: UInt8 = 0
|
|
var originalOrCopy = false
|
|
var home = false
|
|
var copyrightIdBit = false
|
|
var copyrightIdStart = false
|
|
package var aacFrameLength: UInt16 = 0
|
|
var bufferFullness: UInt16 = 0
|
|
var aacFrames: UInt8 = 0
|
|
|
|
package init() {
|
|
}
|
|
|
|
package init(data: Data) {
|
|
self.data = data
|
|
}
|
|
|
|
package func makeFormatDescription() -> CMFormatDescription? {
|
|
guard
|
|
let type = AudioSpecificConfig.AudioObjectType(rawValue: profile + 1),
|
|
let frequency = AudioSpecificConfig.SamplingFrequency(rawValue: sampleFrequencyIndex),
|
|
let channel = AudioSpecificConfig.ChannelConfiguration(rawValue: channelConfiguration) else {
|
|
return nil
|
|
}
|
|
var formatDescription: CMAudioFormatDescription?
|
|
var audioStreamBasicDescription = AudioStreamBasicDescription(
|
|
mSampleRate: frequency.sampleRate,
|
|
mFormatID: kAudioFormatMPEG4AAC,
|
|
mFormatFlags: UInt32(type.rawValue),
|
|
mBytesPerPacket: 0,
|
|
mFramesPerPacket: 1024,
|
|
mBytesPerFrame: 0,
|
|
mChannelsPerFrame: UInt32(channel.rawValue),
|
|
mBitsPerChannel: 0,
|
|
mReserved: 0
|
|
)
|
|
guard CMAudioFormatDescriptionCreate(
|
|
allocator: kCFAllocatorDefault,
|
|
asbd: &audioStreamBasicDescription,
|
|
layoutSize: 0,
|
|
layout: nil,
|
|
magicCookieSize: 0,
|
|
magicCookie: nil,
|
|
extensions: nil,
|
|
formatDescriptionOut: &formatDescription
|
|
) == noErr else {
|
|
return nil
|
|
}
|
|
return formatDescription
|
|
}
|
|
}
|
|
|
|
extension ADTSHeader: DataConvertible {
|
|
package var data: Data {
|
|
get {
|
|
Data()
|
|
}
|
|
set {
|
|
guard ADTSHeader.size <= newValue.count else {
|
|
return
|
|
}
|
|
sync = newValue[0]
|
|
id = (newValue[1] & 0b00001111) >> 3
|
|
layer = (newValue[1] >> 2) & 0b00000011
|
|
protectionAbsent = (newValue[1] & 0b00000001) == 1
|
|
profile = newValue[2] >> 6 & 0b11
|
|
sampleFrequencyIndex = (newValue[2] >> 2) & 0b00001111
|
|
channelConfiguration = ((newValue[2] & 0b1) << 2) | newValue[3] >> 6
|
|
originalOrCopy = (newValue[3] & 0b00100000) == 0b00100000
|
|
home = (newValue[3] & 0b00010000) == 0b00010000
|
|
copyrightIdBit = (newValue[3] & 0b00001000) == 0b00001000
|
|
copyrightIdStart = (newValue[3] & 0b00000100) == 0b00000100
|
|
aacFrameLength = UInt16(newValue[3] & 0b00000011) << 11 | UInt16(newValue[4]) << 3 | UInt16(newValue[5] >> 5)
|
|
bufferFullness = UInt16(newValue[5]) >> 2 | UInt16(newValue[6] >> 2)
|
|
aacFrames = newValue[6] & 0b00000011
|
|
}
|
|
}
|
|
}
|