ios におけるサウンド処理2015

42
iOSにおけるサウンド処理 2015

Upload: cocominap

Post on 12-Apr-2017

1.587 views

Category:

Engineering


1 download

TRANSCRIPT

Page 1: iOS におけるサウンド処理2015

iOSにおけるサウンド処理2015

Page 2: iOS におけるサウンド処理2015

• me.name = “Tamiya Tokihiko”

• me.company = “Classmethod, Inc.”

• company.blog = “Developers.IO”

自己紹介(プロパティ)

Page 3: iOS におけるサウンド処理2015

概要• AVAudioEngine

• iOS 8 から加わったクラス

• Audio Unit Extension

• iOS 9 で追加されたExtension Point

• Audio Unit をアプリ間で共有できる

• AVAudioSessionModeSpokenAudio

• 声コンテンツが他アプリの音声の妨げにならない仕組み

Page 4: iOS におけるサウンド処理2015

AVAudioEngine

Page 5: iOS におけるサウンド処理2015

このままだと不便

© Apple

Page 6: iOS におけるサウンド処理2015

© Apple

Page 7: iOS におけるサウンド処理2015

AVFoudation が拡充

© Apple

Page 8: iOS におけるサウンド処理2015

© Apple

Page 9: iOS におけるサウンド処理2015

AVAudioEngine

AVAudioPlayerNode

AVAudioUnit Delay

AVAudioMixerNode

AVAudio OutputNodeAVAudioFile

Page 10: iOS におけるサウンド処理2015

@property (nonatomic, strong) AVAudioEngine *engine;

@property (nonatomic, strong) AVAudioPlayerNode *audioPlayerNode;

@property (nonatomic, strong) AVAudioFile *audioFile;

@property (nonatomic, strong) AVAudioUnitDelay *audioUnitDelay;

プロパティ

Page 11: iOS におけるサウンド処理2015

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

self.audioPlayerNode = [AVAudioPlayerNode new];

[self.engine attachNode:self.audioPlayerNode];

AVAudioPlayerNode

AVAudioEngine

AVAudioPlayerNode

Page 13: iOS におけるサウンド処理2015

self.audioUnitDelay = [AVAudioUnitDelay new];

self.audioUnitDelay.wetDryMix = 50;

[self.engine attachNode:self.audioUnitDelay];

AVAudioEngine

AVAudioPlayerNode

AVAudioUnit Delay

AVAudioUnitDelay

Page 14: iOS におけるサウンド処理2015

AVAudioMixerNode *mixerNode = [self.engine mainMixerNode];

AVAudioEngine

AVAudioPlayerNode

AVAudioUnit Delay

AVAudioMixerNode

AVAudioMixerNode を生成

Page 15: iOS におけるサウンド処理2015

[self.engine connect:self.audioPlayerNode to:self.audioUnitDelay format:self.audioFile.processingFormat];

AVAudioEngine

AVAudioPlayerNode

AVAudioUnit Delay

AVAudioMixerNode

ノード同士をつなぐ

Page 16: iOS におけるサウンド処理2015

[self.engine connect:self.audioUnitDelay to:mixerNode format:self.audioFile.processingFormat];

AVAudioEngine

AVAudioPlayerNode

AVAudioUnit Delay

AVAudioMixerNode

ノード同士をつなぐ

Page 17: iOS におけるサウンド処理2015

NSError *error;

[self.engine startAndReturnError:&error];

AVAudioEngine

AVAudioPlayerNode

AVAudioUnit Delay

AVAudioMixerNode

Page 18: iOS におけるサウンド処理2015

AVAudioPlayerNodeで 音を再生

AVAudioEngine

AVAudioPlayerNode

AVAudioUnit Delay

AVAudioMixerNode

[self.audioPlayerNode scheduleFile:self.audioFile atTime:nil completionHandler:^() {}];

AVAudio OutputNodeAVAudioFile

Page 19: iOS におけるサウンド処理2015

/*! @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

/*! @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

demo

Page 22: iOS におけるサウンド処理2015

AudioUnitExtension

Page 23: iOS におけるサウンド処理2015

© Apple

Page 24: iOS におけるサウンド処理2015

AVAudioPlayerNode

AVAudioUnit Delay

AVAudioMixerNode

AVAudio OutputNodeAVAudioFile

Page 25: iOS におけるサウンド処理2015

@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

self.audioPlayerNode = [AVAudioPlayerNode new];

self.engine = [AVAudioEngine new];

self.effect = [AVAudioUnit new];

[self.engine attachNode:self.audioPlayerNode];

Page 27: iOS におけるサウンド処理2015

[self.engine connect:self.audioPlayerNode to:self.engine.mainMixerNode format:self.file.processingFormat];

ノード同士をつなぐ

Page 28: iOS におけるサウンド処理2015

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

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

[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

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

AVAudioUnitComponent *auComponent  = self.items[indexPath.row - 1];

auComponent.name;

auComponent.manufacturerName;

AVAudioUnitComponent の名前・製造元

Page 33: iOS におけるサウンド処理2015

auComponent = self.items[indexPath.row - 1];

[self selectEffectWithComponentDescription:auComponent.audioComponentDescription];

Page 34: iOS におけるサウンド処理2015

[self.audioUnit requestViewControllerWithCompletionHandler:^(AUViewController * _Nullable viewController) {}];

独自の View を持っている場合 取得

Page 35: iOS におけるサウンド処理2015

demo

Page 36: iOS におけるサウンド処理2015

AVAudioSessionMode SpokenAudio

Page 37: iOS におけるサウンド処理2015

声のコンテンツでありがちな問題

Page 38: iOS におけるサウンド処理2015

聞き逃した!

Podcast に切替え

巻き戻し早送り 再生

Page 39: iOS におけるサウンド処理2015

AVAudioSessionCategoryOptionInterrupt SpokenAudioAndMixWithOthers

Page 40: iOS におけるサウンド処理2015

AVAudioSessionModeSpokenAudio

Page 41: iOS におけるサウンド処理2015

一時停止 ちょっと巻き戻し

Page 42: iOS におけるサウンド処理2015

概要• AVAudioEngine

• iOS 8 から加わったクラス

• Audio Unit Extension

• iOS 9 で追加されたExtension Point

• Audio Unit をアプリ間で共有できる

• AVAudioSessionModeSpokenAudio

• 声コンテンツが他アプリの音声の妨げにならない仕組み