|
1 // MXAudioPlayerFadeOperation.m |
|
2 // |
|
3 // Created by Andrew Mackenzie-Ross on 30/11/10. |
|
4 // mackross.net. |
|
5 // |
|
6 |
|
7 #import "MXAudioPlayerFadeOperation.h" |
|
8 #import <AVFoundation/AVFoundation.h> |
|
9 |
|
10 #define SKVolumeChangesPerSecond 15 |
|
11 |
|
12 @interface MXAudioPlayerFadeOperation () |
|
13 @property (nonatomic, retain, readwrite) AVAudioPlayer *audioPlayer; |
|
14 - (void)beginFadeOperation; |
|
15 - (void)finishFadeOperation; |
|
16 @end |
|
17 |
|
18 @implementation MXAudioPlayerFadeOperation |
|
19 #pragma mark - |
|
20 #pragma mark Properties |
|
21 @synthesize audioPlayer = _audioPlayer; |
|
22 @synthesize fadeDuration = _fadeDuration; |
|
23 @synthesize finishVolume = _finishVolume; |
|
24 @synthesize playBeforeFade = _playBeforeFade; |
|
25 @synthesize pauseAfterFade = _pauseAfterFade; |
|
26 @synthesize stopAfterFade = _stopAfterFade; |
|
27 @synthesize delay = _delay; |
|
28 |
|
29 #pragma mark - |
|
30 #pragma mark Accessors |
|
31 - (AVAudioPlayer *)audioPlayer { |
|
32 AVAudioPlayer *result; |
|
33 @synchronized(self) { |
|
34 result = [_audioPlayer retain]; |
|
35 } |
|
36 return [result autorelease]; |
|
37 } |
|
38 |
|
39 - (void)setAudioPlayer:(AVAudioPlayer *)anAudioPlayer { |
|
40 @synchronized(self) { |
|
41 if (_audioPlayer != anAudioPlayer) { |
|
42 [_audioPlayer release]; |
|
43 _audioPlayer = [anAudioPlayer retain]; |
|
44 } |
|
45 } |
|
46 } |
|
47 |
|
48 #pragma mark - |
|
49 #pragma mark NSOperation |
|
50 -(id) initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume overDuration:(NSTimeInterval)duration withDelay:(NSTimeInterval)timeDelay { |
|
51 if (self = [super init]) { |
|
52 self.audioPlayer = player; |
|
53 [player prepareToPlay]; |
|
54 _fadeDuration = duration; |
|
55 _finishVolume = volume; |
|
56 _playBeforeFade = YES; |
|
57 _stopAfterFade = NO; |
|
58 _pauseAfterFade = (volume == 0.0) ? YES : NO; |
|
59 _delay = timeDelay; |
|
60 } |
|
61 return self; |
|
62 } |
|
63 |
|
64 - (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume overDuration:(NSTimeInterval)duration { |
|
65 return [self initFadeWithAudioPlayer:player toVolume:volume overDuration:duration withDelay:0.0]; |
|
66 } |
|
67 |
|
68 - (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume { |
|
69 return [self initFadeWithAudioPlayer:player toVolume:volume overDuration:1.0]; |
|
70 } |
|
71 |
|
72 - (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player { |
|
73 return [self initFadeWithAudioPlayer:player toVolume:0.0]; |
|
74 } |
|
75 |
|
76 - (id) init { |
|
77 ALog(@"Failed to init class (%@) with AVAudioPlayer instance, use initFadeWithAudioPlayer:",[self class]); |
|
78 return nil; |
|
79 } |
|
80 |
|
81 - (void)main { |
|
82 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
|
83 [NSThread sleepForTimeInterval:_delay]; |
|
84 if ([self.audioPlayer isKindOfClass:[AVAudioPlayer class]]) { |
|
85 [self beginFadeOperation]; |
|
86 } |
|
87 else { |
|
88 ALog(@"AudioPlayerFadeOperation began with invalid AVAudioPlayer"); |
|
89 } |
|
90 |
|
91 [pool release]; |
|
92 } |
|
93 |
|
94 - (void)beginFadeOperation { |
|
95 if (![self.audioPlayer isPlaying] && _playBeforeFade) [self.audioPlayer play]; |
|
96 |
|
97 if (_fadeDuration != 0.0) { |
|
98 |
|
99 NSTimeInterval sleepInterval = (1.0 / SKVolumeChangesPerSecond); |
|
100 NSTimeInterval startTime = [[NSDate date] timeIntervalSinceReferenceDate]; |
|
101 NSTimeInterval now = startTime; |
|
102 |
|
103 float startVolume = [self.audioPlayer volume]; |
|
104 |
|
105 while (now < (startTime + _fadeDuration)) { |
|
106 float ratioOfFadeCompleted = (now - startTime)/_fadeDuration; |
|
107 float volume = (_finishVolume * ratioOfFadeCompleted) + (startVolume * (1-ratioOfFadeCompleted)); |
|
108 [self.audioPlayer setVolume:volume]; |
|
109 [NSThread sleepForTimeInterval:sleepInterval]; |
|
110 now = [[NSDate date] timeIntervalSinceReferenceDate]; |
|
111 } |
|
112 |
|
113 [self.audioPlayer setVolume:_finishVolume]; |
|
114 [self finishFadeOperation]; |
|
115 } |
|
116 else { |
|
117 [self.audioPlayer setVolume:_finishVolume]; |
|
118 [self finishFadeOperation]; |
|
119 } |
|
120 } |
|
121 |
|
122 - (void)finishFadeOperation { |
|
123 if ([self.audioPlayer isPlaying] && _pauseAfterFade) [self.audioPlayer pause]; |
|
124 if ([self.audioPlayer isPlaying] && _stopAfterFade) [self.audioPlayer stop]; |
|
125 } |
|
126 |
|
127 - (void)dealloc { |
|
128 releaseAndNil(_audioPlayer); |
|
129 [super dealloc]; |
|
130 } |
|
131 |
|
132 @end |
|
133 |