apple/Video, Audio, DRM

AudioStreamBasicDescription 정리

lgvv 2025. 11. 24. 23:40

AudioStreamBasicDescription 정리

 

CoreAudioType에 속하는 AudioStreamBasicDescription를 정리. 

 

 

목차

  • AudioStreamBasicDescription
  • 패킷의 지속 시간(Duration) 계산
  • 구조체의 모든 필드를 0으로 초기화하는 코드
  • Core Audio에서 사용하는 용어 정의
  • AudioStreamBasicDescription의 Instance Property
    • mFormatIDmSampleRatemBitsPerChannel
    • mBytesPerPacket
    • mReserved
    • mFramesPerPacket
    • mChannelsPerFrame
    • mBytesPerFrame
    • mFormatFlags

 

 

AudioStreamBasicDescription

 

오디오 스트림을 위한 포맷 명세서.

 

오디오 데이터가 어떤 형식으로 구성되어 있는지를 정의하는 명세서

오디오 스트림의 구조를 기술하는 메타데이터의 성격

 

iOS 2.0+
iPadOS 2.0+
macOS 10.0+
tvOS 9.0+
visionOS 1.0+
watchOS 3.0+

 

 

 

 

Overview

 

오디오 스트림 기본 설명(Audio Stream Basic Description, ASBD)을 구성할 때 선형 PCM(Linear PCM) 포맷 또는 채널 크기가 동일한 CBR(Constant Bit Rate) 포맷을 지정할 수 있음.

만약 가변 비트레이트(VBR) 오디오거나 혹은 채널 크기가 서로 다른 CBR 오디오
각 패킷의 정보를 추가로 기술하기 위해 AudioStreamPacketDescription 구조체도 함께 사용해야 함.

 

만약 필드 값이 0이면, 해당 값이 알 수 없거나 혹은 format에 적용되지 않음을 의미

 

또한, 새로운 ASBD 구조체를 생성할 때는 모든 필드를 명시적으로 0으로 초기화하는 것을 권장

 

 

구조체의 모든 필드를 0으로 초기화하는 코드

 공식 문서에는 C 언어로 작성되어 있으나 Swift 문법 예제 추가

// MARK: - C Language
AudioStreamBasicDescription myAudioDataFormat = {0};

// MARK: - Swift Language

var myAudioDataFormat = AudioStreamBasicDescription()
myAudioDataFormat.mSampleRate = 0
myAudioDataFormat.mFormatID = 0
myAudioDataFormat.mFormatFlags = 0
myAudioDataFormat.mBytesPerPacket = 0
myAudioDataFormat.mFramesPerPacket = 0
myAudioDataFormat.mBytesPerFrame = 0
myAudioDataFormat.mChannelsPerFrame = 0
myAudioDataFormat.mBitsPerChannel = 0
myAudioDataFormat.mReserved = 0

 

 

패킷의 지속 시간(Duration) 계산

오디오 스트림에서 하나의 패킷이 재생되는 시간을 계산하려면 AudioStreamBasicDescription에 존재하는 2개의 필드를 활용

 

  • mSampleRate: 초당 샘플 수
  • mFramesPerPacket: 패킷 당 프레임 수

 

// MARK: - C Language
duration = (1 / mSampleRate) * mFramesPerPacket

// MARK: - Swift Language
let duration = (1.0 / sampleRate) * Double(framesPerPacket)

 

수식에 대한 설명

  • x = 1 / mSampleRate: 한 샘플의 재생 시간 
  • y = mFramesPerPacket: 패킷 내 프레임의 수

즉, x와 y를 곱하면 해당 패킷이 재생되는 총 시간을 구할 수 있음.

 

 

샘플코드

let sampleRate: Double = 44100  // 1초에 44100 샘플
let framesPerPacket: UInt32 = 1024

let duration = (1.0 / sampleRate) * Double(framesPerPacket)
print("패킷 지속 시간: \(duration) 초")

 

 

 

Core Audio에서 사용하는 용어 정의

Core Audio에서 용어를 아래와 같은 의미로 정의하여서 사용

  • 오디오 스트림(Audio Stream)
    • 소리를 표현하는 연속적인 데이터 시퀀스를 의미
    • 에시) 노래 한 곡의 데이터가 오디오 스트림
  • 채널(Channel)
    • 모노 오디오의 독립적인 트랙을 의미
      • 모노 스트림 : 1개 채널
      • 스테레오 스트림 : 2개 채널
  • 샘플(Sample)
    • 오디오 스트림 내 단일 채널의 단일 수치 값을 의미.
  • 프레임(Frame)
    • 시간적으로 일치하는 샘플들의 집합
    • 예시) Linear PCM 스테레오 오디오 파일은 프레임당 2개의 샘플을 가짐
    • 왼쪽 채널 1샘플 + 오른쪽 채널 1샘플 = 1 프레임
  • 패킷(Packet)
    • 연속된 1개 이상의 프레임 집합을 의미
    • 패킷은 특정 오디오 데이터 포맷에서 시간을 측정할 수 있는 가장 작은 단위
    • Linear PCM에서는 패킷이 1 프레임을 담음.
    • 압축 포맷에서는 일반적으로 여러 프레임 담음.
    • 일부 포맷에서는 패킷당 프레임 수가 가변적일 수 있음.
  • 샘플 레이트(Sample Rate)
    • 비압축 오디오: 초당 프레임 수(frames per second)
    • 압축 오디오: 압축을 해제했을 때의 동등한 초당 프레임 수

 

 

AudioStreamBasicDescription의 Instance Property

해당 객체에 존재하는 인스턴스 프로퍼티 정리

 

 

mFormatID

    • 스트림의 일반 오디오 데이터 형식을 지정하는 식별자
    • 지원되는 오디오 형식을 나타내는 식별자
      • 간단하게 코덱에 대한 정보
var mFormatID: AudioFormatID

 

 


mFormatFlags

  • 형식별 세부 정보를 지정하기 위한 포맷 전용 플래그
  • 플래그가 없음을 나타내려면 0으로 설정
var mFormatFlags: AudioFormatFlags

 

 


mSampleRate

  • 압축 포맷의 경우 압축을 해제한 데이터 기준 초당 프레임 수를 나타냄
  • mSampleRate 필드는 0이 될 수 없음.
    • 단, AudioStreamBasicDescription 구조체에서 지원되는 포맷 리스트를 나열할 때는 예외 (kAudioStreamAnyRate로 표현)
    • kAudioStreamAnyRate은 오디오 스트림이 어떤 샘플 레이트라도 사용할 수 있음을 나타내는 값
var mFormatFlags: AudioFormatFlags

 

단, AudioStreamBasicDescription 구조체에서 지원되는 포맷 리스트를 나열할 때는 예외라는 의미는

 

녹음할 때, 샘플 레이트, 채널 수 등을 정확하게 넣어주어야 하나, OS나 라이브러리가 단순히 어떤 포맷들을 지원하는지 목록으로 나열해줄 때는 샘플레이트가 정확히 무엇인지는 중요하지 않기 때문에 mSampleRate = kAudioStreamAnyRate와 같은 특수값으로 표현.

 

 

 

 

mBitsPerChannel

  • 오디오 샘플 하나를 표현하는 비트 수
  • 압축 포맷의 경우에는 패킷 내 샘플 비트 수를 정확하게 알 수 없어서 mBitsPerChannel 값을 0으로 설정
  • 비압축 오디오에서는 샘플당 비트 수를 직접 계산하고압축 오디오에서는 의미 없는 값이므로 0으로 초기화
var mBitsPerChannel: UInt32

 


linear PCM에서 kAudioFormatFlagsCanonical를 사용하는 경우 비트수를 계산하는 방법

// MARK: - C Language
mBitsPerChannel = 8 * sizeof(AudioSampleType);

// MARK: - Swift Language
let mBitsPerChannel = 8 * MemoryLayout<AudioSampleType>.size // warning: 'AudioSampleType' is deprecated: The concept of canonical formats is deprecated

 

 

Xcode 26에서는 아래와 같은 경고가 발생.

 

warning: 'AudioSampleType' is deprecated: The concept of canonical formats is deprecated

 

Core Audio 프레임워크에서 AudioSampleType 타입이 더 이상 권장되지 않으며, 예전 “canonical format” 개념 자체가 deprecated 되었음을 의미.

 

모든 오디오 샘플은 명시적으로 포맷을 지정해야 하고 오래된 기본형 AudioSampleType을 사용하지 말라고 경고를 띄워줌.

 

아래 샘플 코드처럼 Core Audio에서 AudioSampleType에 의존하기 보단, ASBD 등 명시적으로 포맷을 전환하는 것이 안전.

 

var asbd = AudioStreamBasicDescription()
asbd.mSampleRate = 44100
asbd.mFormatID = kAudioFormatLinearPCM
asbd.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked
asbd.mBitsPerChannel = 32
asbd.mChannelsPerFrame = 2
asbd.mBytesPerFrame = asbd.mChannelsPerFrame * (asbd.mBitsPerChannel / 8)
asbd.mFramesPerPacket = 1
asbd.mBytesPerPacket = asbd.mBytesPerFrame * asbd.mFramesPerPacket

 

 

mBytesPerFrame

  • 오디오 버퍼에서 한 프레임의 시작 지점부터 다음 프레임 시작 지점까지의 바이트 수
  • 압축 포맷의 경우  필드는 0으로 설정
var mBytesPerFrame: UInt32

 

 

 

n개의 채널을 가지는 인터리브드(interleaved) 데이터의 오디오 버퍼에서, 각 샘플이 AudioSampleType일 경우

// MARK: - C Language
mBytesPerFrame = n * sizeof(AudioSampleType)

// MARK: - Swift Language

// 인터리브드 데이터 (n개의 채널)
let nChannels = n // 채널 수
let bytesPerFrame = nChannels * MemoryLayout<AudioSampleType>.size

 

 

비인터리브드(noninterleaved, 모노포닉) 데이터의 오디오 버퍼에서, 각 샘플이 AudioSampleType일 경우

// MARK: - C Language
mBytesPerFrame = sizeof(AudioSampleType)

// MARK: - Swift Language

// 비인터리브드 데이터 (모노포닉)
let monoBytesPerFrame = MemoryLayout<AudioSampleType>.size

 

 

 

 

mChannelsPerFrame

  • 각 오디오 프레임에 포함된 채널 수
  • 이 값은 0이 될 수 없음
    • 오디오에서 채널이 0개라는 것은 의미가 없음.
    • 0채널이면 소리가 없는 것과 같아서, 프레임 단위 계산이나 버퍼 처리도 불가능
    • 따라서 Core Audio에서는 항상 1 이상이어야 함.
      • 1 → 모노
      • 2 → 스테레오
      • 5, 6, 7, 8 → 서라운드 채널 등
var mChannelsPerFrame: UInt32

 

 

 


mBytesPerPacket

  • 오디오 데이터 패킷의 바이트 수
  • 가변 패킷 크기(variable packet size)를 나타내려면 이 필드를 0으로 설정
  • 가변 패킷 크기를 사용하는 포맷의 경우, 각 패킷의 크기는 AudioStreamPacketDescription 구조체를 사용하여 지정

 

AudioStreamPacketDescription

  • 패킷 크기가 일정하지 않거나 패킷 사이에 불필요한 데이터가 있는 버퍼의 패킷 구조를 위한 구조체
  • mStartOffset
    • 버퍼의 시작 지점부터 해당 패킷의 시작 지점까지의 바이트 수입니다.
  • mVariableFramesInPacket
    • 패킷 내 데이터의 샘플 프레임 수
    • 만약 패킷당 프레임 수가 일정한 포맷에서는 이 필드를 0으로 설정
  • mDataByteSize
    • 패킷의 바이트 
var mBytesPerPacket: UInt32

 

 

 

 

mFramesPerPacket

  • 오디오 데이터 패킷에 포함된 프레임 수
  • 비압축 오디오의 경우 이 값은 1
  • 가변 비트레이트(VBR) 형식에서는 이 값이 1024(AAC)처럼 더 큰 고정된 숫자.
  • Ogg Vorbis처럼 패킷마다 프레임 수가 달라지는 형식이라면, 이 필드를 0으로 설정.

 

var mFramesPerPacket: UInt32

 

 

 

mReserved

  • 구조체를 8바이트 단위로 정렬하기 위해 추가하는 패딩 바이트 수
  • 이 값은 0으로 설정
var mReserved: UInt32

 

 

 

 

(참고)
https://developer.apple.com/documentation/CoreAudioTypes/AudioStreamBasicDescription

 

AudioStreamBasicDescription | Apple Developer Documentation

A format specification for an audio stream.

developer.apple.com

 

'apple > Video, Audio, DRM' 카테고리의 다른 글

AVAudioEngine, AVAudioNode 정리  (0) 2025.11.26
AVAudioFormat 정리  (0) 2025.11.24
AVAudioPCMBuffer 정리  (0) 2025.11.24
Adaptive Bit Streaming  (0) 2025.10.23
[HLS] Creating a Multivariant Playlist  (0) 2024.12.05