Files
HaishinKit.swift/HaishinKit/Sources/Codec/ADTSHeader.swift
2025-07-13 12:43:53 +09:00

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
}
}
}