ios におけるサウンド処理2015
TRANSCRIPT
![Page 1: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/1.jpg)
iOSにおけるサウンド処理2015
![Page 2: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/2.jpg)
• me.name = “Tamiya Tokihiko”
• me.company = “Classmethod, Inc.”
• company.blog = “Developers.IO”
自己紹介(プロパティ)
![Page 3: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/3.jpg)
概要• AVAudioEngine
• iOS 8 から加わったクラス
• Audio Unit Extension
• iOS 9 で追加されたExtension Point
• Audio Unit をアプリ間で共有できる
• AVAudioSessionModeSpokenAudio
• 声コンテンツが他アプリの音声の妨げにならない仕組み
![Page 4: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/4.jpg)
AVAudioEngine
![Page 5: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/5.jpg)
このままだと不便
© Apple
![Page 6: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/6.jpg)
© Apple
![Page 7: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/7.jpg)
AVFoudation が拡充
© Apple
![Page 8: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/8.jpg)
© Apple
![Page 9: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/9.jpg)
AVAudioEngine
AVAudioPlayerNode
AVAudioUnit Delay
AVAudioMixerNode
AVAudio OutputNodeAVAudioFile
![Page 10: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/10.jpg)
@property (nonatomic, strong) AVAudioEngine *engine;
@property (nonatomic, strong) AVAudioPlayerNode *audioPlayerNode;
@property (nonatomic, strong) AVAudioFile *audioFile;
@property (nonatomic, strong) AVAudioUnitDelay *audioUnitDelay;
プロパティ
![Page 11: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/11.jpg)
self.engine = [AVAudioEngine new]; NSString *path = [[NSBundle mainBundle] pathForResource:@"loop.m4a" ofType:nil];
self.audioFile = [[AVAudioFile alloc] initForReading:[NSURL fileURLWithPath:path] error:nil];
AVAudioEngine と AVAudioFile
AVAudioEngine
![Page 12: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/12.jpg)
self.audioPlayerNode = [AVAudioPlayerNode new];
[self.engine attachNode:self.audioPlayerNode];
AVAudioPlayerNode
AVAudioEngine
AVAudioPlayerNode
![Page 13: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/13.jpg)
self.audioUnitDelay = [AVAudioUnitDelay new];
self.audioUnitDelay.wetDryMix = 50;
[self.engine attachNode:self.audioUnitDelay];
AVAudioEngine
AVAudioPlayerNode
AVAudioUnit Delay
AVAudioUnitDelay
![Page 14: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/14.jpg)
AVAudioMixerNode *mixerNode = [self.engine mainMixerNode];
AVAudioEngine
AVAudioPlayerNode
AVAudioUnit Delay
AVAudioMixerNode
AVAudioMixerNode を生成
![Page 15: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/15.jpg)
[self.engine connect:self.audioPlayerNode to:self.audioUnitDelay format:self.audioFile.processingFormat];
AVAudioEngine
AVAudioPlayerNode
AVAudioUnit Delay
AVAudioMixerNode
ノード同士をつなぐ
![Page 16: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/16.jpg)
[self.engine connect:self.audioUnitDelay to:mixerNode format:self.audioFile.processingFormat];
AVAudioEngine
AVAudioPlayerNode
AVAudioUnit Delay
AVAudioMixerNode
ノード同士をつなぐ
![Page 17: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/17.jpg)
NSError *error;
[self.engine startAndReturnError:&error];
AVAudioEngine
AVAudioPlayerNode
AVAudioUnit Delay
AVAudioMixerNode
![Page 18: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/18.jpg)
AVAudioPlayerNodeで 音を再生
AVAudioEngine
AVAudioPlayerNode
AVAudioUnit Delay
AVAudioMixerNode
[self.audioPlayerNode scheduleFile:self.audioFile atTime:nil completionHandler:^() {}];
AVAudio OutputNodeAVAudioFile
![Page 19: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/19.jpg)
/*! @property delayTime Time taken by the delayed input signal to reach the output @abstract Range: 0 -> 2 Default: 1 Unit: Seconds */ @property (nonatomic) NSTimeInterval delayTime;
/*! @property feedback @abstract Amount of the output signal fed back into the delay line Range: -100 -> 100 Default: 50 Unit: Percent */ @property (nonatomic) float feedback;
AVAudioUnitDelay.h
![Page 20: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/20.jpg)
/*! @property lowPassCutoff @abstract Cutoff frequency above which high frequency content is rolled off Range: 10 -> (samplerate/2) Default: 15000 Unit: Hertz */ @property (nonatomic) float lowPassCutoff;
/*! @property wetDryMix @abstract Blend of the wet and dry signals Range: 0 (all dry) -> 100 (all wet) Default: 100 Unit: Percent */ @property (nonatomic) float wetDryMix;
AVAudioUnitDelay.h
![Page 21: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/21.jpg)
demo
![Page 22: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/22.jpg)
AudioUnitExtension
![Page 23: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/23.jpg)
© Apple
![Page 24: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/24.jpg)
AVAudioPlayerNode
AVAudioUnit Delay
AVAudioMixerNode
AVAudio OutputNodeAVAudioFile
![Page 25: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/25.jpg)
@property (nonatomic) AVAudioEngine *engine;
@property (nonatomic) AVAudioPlayerNode *audioPlayerNode;
@property (nonatomic) AVAudioFile *file;
@property (nonatomic) AUAudioUnit *audioUnit;
@property (nonatomic) AVAudioUnit *effect;
@property (nonatomic) NSArray *items;
プロパティ
![Page 26: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/26.jpg)
self.audioPlayerNode = [AVAudioPlayerNode new];
self.engine = [AVAudioEngine new];
self.effect = [AVAudioUnit new];
[self.engine attachNode:self.audioPlayerNode];
![Page 27: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/27.jpg)
[self.engine connect:self.audioPlayerNode to:self.engine.mainMixerNode format:self.file.processingFormat];
ノード同士をつなぐ
![Page 28: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/28.jpg)
AVAudioUnitComponent が入った配列を取得
AudioComponentDescription anyEffectDescription;
anyEffectDescription.componentType = kAudioUnitType_Effect;
anyEffectDescription.componentSubType = 0; anyEffectDescription.componentManufacturer = 0; anyEffectDescription.componentFlags = 0; anyEffectDescription.componentFlagsMask = 0; self.items = [[AVAudioUnitComponentManager sharedAudioUnitComponentManager] componentsMatchingDescription:anyEffectDescription];
![Page 29: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/29.jpg)
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.engine startAndReturnError:nil]; [self scheduleLoop]; [self.audioPlayerNode play]; }
- (void)scheduleLoop { [self.audioPlayerNode scheduleFile:self.file atTime:nil completionHandler:^{ [self scheduleLoop]; }]; }
AVAudioPlayerNode 再生
![Page 30: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/30.jpg)
[self.audioPlayerNode pause]; [self.engine disconnectNodeInput:self.effect]; [self.engine disconnectNodeInput:self.engine.mainMixerNode]; [self.engine connect:self.audioPlayerNode to:self.engine.mainMixerNode format:self.file.processingFormat]; self.effect = nil; self.audioUnit = nil;
ノードをつなぎ直す
![Page 31: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/31.jpg)
self.effect = audioUnit;
(略)
[self.engine connect:self.audioPlayerNode to:self.effect format:self.file.processingFormat];
[self.engine connect:self.effect to:self.engine.mainMixerNode format:self.file.processingFormat];
特定のエフェクトを実現する AVAudioUnit を取得
[AVAudioUnit instantiateWithComponentDescription:componentDescription options:kAudioComponentInstantiation_LoadOutOfProcess completionHandler:^(__kindof AVAudioUnit * _Nullable audioUnit, NSError * _Nullable error) {}];
AVAudioUnit を使いノードをつなぐ
![Page 32: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/32.jpg)
AVAudioUnitComponent *auComponent = self.items[indexPath.row - 1];
auComponent.name;
auComponent.manufacturerName;
AVAudioUnitComponent の名前・製造元
![Page 33: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/33.jpg)
auComponent = self.items[indexPath.row - 1];
[self selectEffectWithComponentDescription:auComponent.audioComponentDescription];
![Page 34: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/34.jpg)
[self.audioUnit requestViewControllerWithCompletionHandler:^(AUViewController * _Nullable viewController) {}];
独自の View を持っている場合 取得
![Page 35: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/35.jpg)
demo
![Page 36: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/36.jpg)
AVAudioSessionMode SpokenAudio
![Page 37: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/37.jpg)
声のコンテンツでありがちな問題
![Page 38: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/38.jpg)
聞き逃した!
Podcast に切替え
巻き戻し早送り 再生
![Page 39: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/39.jpg)
AVAudioSessionCategoryOptionInterrupt SpokenAudioAndMixWithOthers
![Page 40: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/40.jpg)
AVAudioSessionModeSpokenAudio
![Page 41: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/41.jpg)
一時停止 ちょっと巻き戻し
![Page 42: iOS におけるサウンド処理2015](https://reader030.vdocuments.pub/reader030/viewer/2022033014/58ee24251a28abb7608b4651/html5/thumbnails/42.jpg)
概要• AVAudioEngine
• iOS 8 から加わったクラス
• Audio Unit Extension
• iOS 9 で追加されたExtension Point
• Audio Unit をアプリ間で共有できる
• AVAudioSessionModeSpokenAudio
• 声コンテンツが他アプリの音声の妨げにならない仕組み