project_files/HedgewarsMobile/MXAudioPlayerFadeOperation.m
changeset 6656 6aeaba3ee584
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/HedgewarsMobile/MXAudioPlayerFadeOperation.m	Thu Feb 09 17:28:05 2012 +0100
@@ -0,0 +1,133 @@
+//  MXAudioPlayerFadeOperation.m
+//
+//  Created by Andrew Mackenzie-Ross on 30/11/10.
+//  mackross.net.
+//
+
+#import "MXAudioPlayerFadeOperation.h"
+#import <AVFoundation/AVFoundation.h>
+
+#define SKVolumeChangesPerSecond 15
+
+@interface MXAudioPlayerFadeOperation ()
+@property (nonatomic, retain, readwrite) AVAudioPlayer *audioPlayer; 
+- (void)beginFadeOperation;
+- (void)finishFadeOperation;
+@end
+
+@implementation MXAudioPlayerFadeOperation
+#pragma mark -
+#pragma mark Properties
+@synthesize audioPlayer = _audioPlayer;
+@synthesize fadeDuration = _fadeDuration;
+@synthesize finishVolume = _finishVolume;
+@synthesize playBeforeFade = _playBeforeFade;
+@synthesize pauseAfterFade = _pauseAfterFade;
+@synthesize stopAfterFade = _stopAfterFade;
+@synthesize delay = _delay;
+
+#pragma mark -
+#pragma mark Accessors
+- (AVAudioPlayer *)audioPlayer {
+  AVAudioPlayer *result;
+  @synchronized(self) {
+    result = [_audioPlayer retain];
+  }
+  return [result autorelease];
+}
+
+- (void)setAudioPlayer:(AVAudioPlayer *)anAudioPlayer {
+  @synchronized(self) {
+    if (_audioPlayer != anAudioPlayer) {
+      [_audioPlayer release];
+      _audioPlayer = [anAudioPlayer retain];
+    }
+  }
+}
+
+#pragma mark -
+#pragma mark NSOperation
+-(id) initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume overDuration:(NSTimeInterval)duration withDelay:(NSTimeInterval)timeDelay {
+  if (self = [super init]) {
+    self.audioPlayer = player;
+    [player prepareToPlay];
+    _fadeDuration = duration;
+    _finishVolume = volume;
+    _playBeforeFade = YES;
+    _stopAfterFade = NO;
+    _pauseAfterFade = (volume == 0.0) ? YES : NO;
+    _delay = timeDelay;
+  }
+  return self;
+}
+
+- (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume overDuration:(NSTimeInterval)duration {
+  return [self initFadeWithAudioPlayer:player toVolume:volume overDuration:duration withDelay:0.0];
+}
+
+- (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume {
+  return [self initFadeWithAudioPlayer:player toVolume:volume overDuration:1.0];
+}
+
+- (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player {
+  return [self initFadeWithAudioPlayer:player toVolume:0.0];
+}
+
+- (id) init {
+  ALog(@"Failed to init class (%@) with AVAudioPlayer instance, use initFadeWithAudioPlayer:",[self class]);
+  return nil;
+}
+
+- (void)main {
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  [NSThread sleepForTimeInterval:_delay];
+  if ([self.audioPlayer isKindOfClass:[AVAudioPlayer class]]) {
+    [self beginFadeOperation];
+  }
+  else {
+    ALog(@"AudioPlayerFadeOperation began with invalid AVAudioPlayer");
+  }
+  
+  [pool release];
+}
+
+- (void)beginFadeOperation {
+  if (![self.audioPlayer isPlaying] && _playBeforeFade) [self.audioPlayer play];
+  
+  if (_fadeDuration != 0.0) {
+    
+    NSTimeInterval sleepInterval = (1.0 / SKVolumeChangesPerSecond);
+    NSTimeInterval startTime = [[NSDate date] timeIntervalSinceReferenceDate];
+    NSTimeInterval now = startTime;
+    
+    float startVolume = [self.audioPlayer volume];
+    
+    while (now < (startTime + _fadeDuration)) {
+      float ratioOfFadeCompleted = (now - startTime)/_fadeDuration;
+      float volume = (_finishVolume * ratioOfFadeCompleted) + (startVolume * (1-ratioOfFadeCompleted));
+      [self.audioPlayer setVolume:volume];
+      [NSThread sleepForTimeInterval:sleepInterval];
+      now = [[NSDate date] timeIntervalSinceReferenceDate];
+    }
+    
+    [self.audioPlayer setVolume:_finishVolume];
+    [self finishFadeOperation];
+  }
+  else {
+    [self.audioPlayer setVolume:_finishVolume];
+    [self finishFadeOperation];
+  }
+}
+
+- (void)finishFadeOperation {
+  if ([self.audioPlayer isPlaying] && _pauseAfterFade) [self.audioPlayer pause];
+  if ([self.audioPlayer isPlaying] && _stopAfterFade) [self.audioPlayer stop];
+}
+
+- (void)dealloc {
+  releaseAndNil(_audioPlayer);
+  [super dealloc];
+}
+
+@end
+