Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Macとオーディオ再生 2024/11/02
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yusuke Ito
November 02, 2024
Programming
1.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Macとオーディオ再生 2024/11/02
macOS native Symposium #10 での発表資料です。
https://macos-native.github.io/backnumbers.html
Yusuke Ito
November 02, 2024
More Decks by Yusuke Ito
See All by Yusuke Ito
おうちHackを取り入れた リノベーション事例
yusukeito
0
1k
Server Side Swiftを しばらく運用してみた話
yusukeito
0
680
Swift からword2vecを 使ってみる
yusukeito
0
1.2k
Swift Outside the Box
yusukeito
1
2.9k
SwiftでgRPCとProtocolBuffersを使う
yusukeito
4
1.5k
Swift on Raspberry Pi でI2Cデバイスを使う
yusukeito
1
750
Isomorphic Swift
yusukeito
2
710
Swiftの値付きEnumをHackする
yusukeito
0
450
Swift プロトコル指向なCのラッパーを作る
yusukeito
3
1.3k
Other Decks in Programming
See All in Programming
Kotlinize Is Not Just Converting to Kotlin
chigichan24
1
210
Zero-Tap Sign-In対応、結局何をすればいいの?
mitohato14
0
1.3k
Materialが消えた日 〜真っ白なFlutterキャンバスにRenderObjectで絵を描く〜
umigishiaoi
0
140
sbt 2.0: takeoff
eed3si9n
0
190
AI-Powered Domain-Driven Design
ziobrando
0
370
선언형 햅틱 라이브러리 진동을 소개합니다
l2hyunwoo
1
260
私なりのハーネスエンジニアリング ~独自の言語処理系の開発を通して~
seosoft
0
170
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
5
680
自作Discord音声botをLambda MicroVMsに移行した話 / Migrating My Discord Voice Bot to Lambda MicroVMs
akihisaikeda
1
250
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
130
Spec-driven Development with AI
simas
PRO
0
2.2k
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
180
Featured
See All Featured
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.9k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
Faster Mobile Websites
deanohume
310
32k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
600
Navigating Weather and Climate Data
rabernat
0
580
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
2
380
Facilitating Awesome Meetings
lara
57
7.2k
The Limits of Empathy - UXLibs8
cassininazir
2
760
Technical Leadership for Architectural Decision Making
baasie
3
620
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
Building Adaptive Systems
keathley
44
3.3k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
320
Transcript
MacͱΦʔσΟΦ࠶ੜ 2024/11/02 Yusuke Ito Symposium #10 macOS
About me • Yusuke Ito • Web (TypeScript, React, Node.js)
macOS ωΠςΟϒΞϓϦ (Minutes) iOS ωΠςΟϒΞϓϦ (App Store Best of 2014) • ϝΠϯWeb͕ͩɺΦʔσΟΦػثͷ։ൃɾ +macOSΞϓϦ https://audio.current.directory/
None
Իσʔλͷجຊ
PCM (LPCM) Linear Pulse Code Modulation Ϗοτਂ=ৼ෯ (16, 24bit) αϯϓϦϯάप(1ඵ͋ͨΓͷׂ)
44.1kHz(CD) 48kHz, 96kHz (Ի੍ָ࡞) Իͷੜσʔλ 0 -32768 32767
LPCMͷσʔλྔ • 44.1kHz (CD) αϯϓϦϯάप • 16bit (CD) Ϗοτਂ •
3 (180ඵ) • 44100 (sample/sec) × 2 (byte, 16bit) × 2 (channel, L R) × 180 (secs) • = 31,752,000 (bytes) ≈ 30 MB (megabytes)
ίϯςφͱίʔσοΫ ίϯςφ: QuickTime (.mov) MPEG-4 (.m4a, .m4v) Ի AAC ө૾
H.264 ϝλσʔλ ΞʔςΟετ໊… ΞϧόϜ໊… ϝλσʔλ ίʔσοΫ: H.264 AAC Apple Lossless MP3, ATRAC (MD) JPEG PNG ϑΝΠϧͷ෦
ίʔσοΫͱσίʔυ Ի AAC σίʔυ LPCM Իੜσʔλ Τϯίʔυ ίʔσοΫ
Mixing & Playback ԻσʔλͷྲྀΕ Χʔωϧ ϛΩαʔ σόΠε 🔊 App A
App B γεςϜܯࠂԻ App C ഉଞϞʔυ OR (αϯϓϦϯάपม) 96kHz 48kHz 44.1kHz 96kHz LPCM LPCM
ΦʔσΟΦAPIΛ͏
Audio APIs on Mac • AVFoundation: ؆୯ʹ͑ΔΫϥε܈ • AVAudioPlayerͳͲ, ϑΝΠϧ(M4A…)ϨϕϧͷΓऔΓ
• Audio Toolbox: • σίʔυɾΤϯίʔυɾαϯϓϦϯάपม(SRC)ͳͲ • Իσʔλ(PCM)ϨϕϧͷΓऔΓ • Core Audio: ϋʔυΣΞͱͷ௨৴ • ϋʔυΣΞΛར༻͢Δ߹ Core Audio Hardware Audio Toolbox AVFoundation
Core Audio Λ͏ ࠷ϨΠϠʔͷAPI • ΦʔσΟΦσόΠεʹग़ྗ͞ΕΔσʔλΛࣗͰίϯτϩʔϧͰ͖Δ • ඞཁͳλΠϛϯάͰίʔϧόοΫ͕ݺΕΔͷͰԻσʔλ(PCMੜσʔλ)Λ ͢ •
σʔλͷ४උ͕࠶ੜʹؒʹ߹͏Α͏ʹ͢Δ • ΠϯλʔϑΣʔεCݴޠ • Audio Toolbox, Core Audio
ԻָPlayerΛ࡞Δ σʔλͷྲྀΕ αϯϓϦϯά पม (SRC) σίʔμʔ ϑΝΠϧ .m4a Apple Lossless
όοϑΝ Core Audio 🔊 औΓʹ͍͘ Audio Toolbox Core Audio LPCM LPCM LPCM Apple Lossless App C ഉଞϞʔυ
ഉଞϞʔυ • API: Hog Mode • ΧʔωϧϛΩαʔΛհ͞ͳ͍ • →αϯϓϦϯάपมͳͲ͕ߦΘΕͳ͍ •
→ଞͷΞϓϦέʔγϣϯͷԻग़ྗ͞Εͳ͍ • ΦʔσΟΦϋʔυΣΞʹΞΫηε • Ի(LPCM)σʔλΛૹͬͯ࠶ੜ
Swift & Concurrency
Swift & Realtime • ϦΞϧλΠϜॲཧͷอূ͞Ε͍ͯͳ͍(ͣ) • Swiftಛ༗ͷॲཧͷΦʔόʔϔου͕͋ΔՄೳੑ • ΫϦςΟΧϧͳͷ࠷ޙͷίʔϧόοΫՕॴͷΈ •
࣮ࡍSwiftͰͳ͠ • ͋ΓͳΒCͰॻ͘ • ͦΕҎ֎ͷՕॴઈରϦΞϧλΠϜͰͳͯ͘ͳ͠
Concurrency • (Իָ࠶ੜPlayerͰ) ฒߦॲཧͷඞཁੑബ͍ • ͨͩ͠… • ಉ͡ΦϒδΣΫτΛڞ༗͢Δ • όοϑΝʔ(ϝϞϦɾϑΝΠϧ),
ΦʔσΟΦσόΠε, σίʔμʔ • ಉ࣌ʹΞΫηε͠ͳ͍Έඞཁ
ಉظॲཧɾഉଞॲཧ • 1ͭͷϦιʔε(ΦϒδΣΫτ)ʹಉ࣌ʹΞΫηε͠ͳ͍Α͏ʹ͢Δ • ಉ࣌ΞΫηεͷྫ • ಡΈࠐΈதʹॻ͖ࠐΉ • εϨουAͰಡΈࠐΈதʹεϨουBͰಡΈࠐΉ
ഉଞॲཧ • ର͕ಉظؔͷ߹ • NIOLock - swift-nio (All Platforms) •
OSAllocatedUnfairLock (macOS 13~)
struct AudioSytemObject { let id: AudioObjectID = ... let lock
= NIOLock() func get(addr: T) throws -> [T.DataType] { try lock.withLock { let memory = ... let statusData = AudioObjectGetPropertyData(id, &propAddr, 0, nil, &propSize, memory) return (0..<count).map { memory[$0] } } } func set(values: [T.DataType], forAddr addr: T) throws { try lock.withLockVoid { ... let status = AudioObjectSetPropertyData(id, &propAddr, 0, nil, UInt32(propSize), memory) } } } कΓ͍ͨΦϒδΣΫτ
όοϑΝ (ϝϞϦ) εϨουB εϨουA ॻ͖ࠐΈ ಡΈࠐΈ
final class PlaybackBuffer { var buffer = Data() let lock
= NIOLock() func write(_ data: Data) { lock.withLockVoid { buffer.append(data) } } func read() -> Data? { return lock.withLock { if buffer.isEmpty { return nil } let buf = buffer buffer.removeAll() // clear data return buf } } }
Actor vs Lock • Actorͩͱisolated context (isolation boundary)Λ͑ΒΕͳ͍ • ݺͼग़͠ݩ͕CͷίʔϧόοΫ(ಉظ)ͷ߹ͳͲ
• nonisolated ʹ͢Δ? →ࣗલͷഉଞॲཧ͕ඞཁ • await ͢Δ? →ಉظઐ༻ίʔϧόοΫͳͷͰෆՄ func AudioIOProc(buffer: PlaybackBuffer, outOutputData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus { let data = buffer.read() memcpy(outOutputData, data, length) ...
ඇಉظؔͷഉଞॲཧ • ϑΝΠϧΛόοϑΝʔͱͯ࣋ͭ͠ • ಡΈࠐΈதॻ͖ࠐ·ͳ͍ (ಡΈࠐΈ͕ऴΘΔ·Ͱͭ) • ॻ͖ࠐΈதಡΈࠐ·ͳ͍ (ॻ͖ࠐΈ͕ऴΘΔ·Ͱͭ) •
ϩοΫ(ͦͷ··)͑ͳ͍ (σουϩοΫ͢Δ) actor FileCache { func write(_ data: Data) async func read() async -> Data? }
όοϑΝ (ϑΝΠϧ) εϨουB εϨουA ॻ͖ࠐΈ ಡΈࠐΈ
actor FileCache { let queue = DispatchQueue(label: "FileCacheQueue", qos: .utility)
let semaphore = DispatchSemaphore(value: 1) func write(_ data: Data) async { await withCheckedContinuation { continuation in queue.async { self.semaphore.wait() Task { await self.write_(data) continuation.resume() self.semaphore.signal() } } } } func read() async -> Data? { await withCheckedContinuation { continuation in queue.async { self.semaphore.wait() Task { let data = await self.read_() continuation.resume(returning: data) self.semaphore.signal() } } } } • ඇಉظؔ Serial Queue & Semaphore(or Mutex) • Actor͚ͩͰಉ࣌ಡΈॻ͖Λ͛ͳ͍߹͕͋Δ • อޢ͍ͨ͠Օॴ͕ඇಉظؔ
εϨουB εϨουA ϑΝΠϧ ҙεϨου ࣌ؒ ॻ͖ࠐΈத Semaphore 1 0 wait()
wait() DispatchQueue signal() Task ҙεϨου 1 ಡΈࠐΈ 0 signal() write() read() 1 Queue Block…
ࢀߟจݙ • Core Audio Overview (Apple) https://developer.apple.com/library/archive/documentation/MusicAudio/Conceptual/ CoreAudioOverview/WhatisCoreAudio/WhatisCoreAudio.html • Xcode
16 & Swift 6 ΩϟονΞοϓ: Swift Concurrencyͷجૅͱ࠷ॏཁϙΠϯτΛ૯෮श (QonceptInc) https://www.youtube.com/watch?v=jJgEtjx8KHY • ʲSwiftʳGrand Central Dispatch (GCD)ͱOperationQueue ·ͱΊ (@shiz) https://qiita.com/shiz/items/693241f41344a9df6d6f • Linuxͷsemaphoreͱmutexͷ࣮ (@watatuki) https://www.docswell.com/s/watatuki/Z7VNJG-2023-08-24-014308
None