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
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
980
Server Side Swiftを しばらく運用してみた話
yusukeito
0
670
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
700
Swiftの値付きEnumをHackする
yusukeito
0
440
Swift プロトコル指向なCのラッパーを作る
yusukeito
3
1.3k
Other Decks in Programming
See All in Programming
ALB ログから Trace を気合で繋げる技術
fohte
7
880
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
160
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
430
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
770
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
300
コンパウンドプロダクト開発のためのローカルプロセスマネージャー再発明 #layerxgo
izumin5210
0
660
新卒PdEのリアル
ryu1013
1
480
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
150
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
280
What We Talk About When We Talk About XP
m_seki
2
460
Deep dive into the select statement (GopherCon UK)
jespino
0
170
不幸な GC
chencmd
0
900
Featured
See All Featured
Joys of Absence: A Defence of Solitary Play
codingconduct
1
500
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
500
Designing for humans not robots
tammielis
254
26k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
65k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Building an army of robots
kneath
306
46k
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