How to cross yourself between AVAudioPlayers

I want to use AVAudioPlayer and drag and drop more than two mp3 files.

I have 5 mp3 files and 5 "myScrollView" pages with the UIScrollView class and pagingEnabled = YES.

When the user moves the page, I want to play each song for each page with the sound fading out for the previous mp3 file and disappearing for the next mp3.

Help solve this problem.

+3
iphone avaudioplayer fade volume
Sep 15 '12 at 8:35
source share
2 answers

This is not a cross fading operation. But it can fade in / out at a time with a new stream using NSOperation, and fade-in / out effects can be added to the stream in any order.

I found the Linear fade Object MXAudioPlayerFadeOperation created by Andrew Mackenzie-Ross 11/30/10. mackross.net .

MXAudioPlayerFadeOperation.h

#import <Foundation/Foundation.h> @class AVAudioPlayer; @interface MXAudioPlayerFadeOperation : NSOperation { AVAudioPlayer *_audioPlayer; NSTimeInterval _fadeDuration; NSTimeInterval _delay; float _finishVolume; BOOL _pauseAfterFade; BOOL _stopAfterFade; BOOL _playBeforeFade; } // The AVAudioPlayer that the volume fade will be applied to. // Retained until the fade is completed. // Must be set with init method. @property (nonatomic, strong, readonly) AVAudioPlayer *audioPlayer; // The duration of the volume fade. // Default value is 1.0 @property (nonatomic, assign) NSTimeInterval fadeDuration; // The delay before the volume fade begins. // Default value is 0.0 @property (nonatomic, assign) NSTimeInterval delay; // The volume that will be faded to. // Default value is 0.0 @property (nonatomic, assign) float finishVolume; // If YES, audio player will be sent a pause message when the fade has completed. // Default value is NO, however, if finishVolume is 0.0, default is YES @property (nonatomic, assign) BOOL pauseAfterFade; // If YES, when the fade has completed the audio player will be sent a stop message. // Default value is NO. @property (nonatomic, assign) BOOL stopAfterFade; // If YES, audio player will be sent a play message after the delay. // Default value is YES. @property (nonatomic, assign) BOOL playBeforeFade; // Init Methods - (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume overDuration:(NSTimeInterval)duration withDelay:(NSTimeInterval)timeDelay; - (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume overDuration:(NSTimeInterval)duration; - (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player toVolume:(float)volume; - (id)initFadeWithAudioPlayer:(AVAudioPlayer*)player; @end 

MXAudioPlayerFadeOperation.m

 #import "MXAudioPlayerFadeOperation.h" #import <AVFoundation/AVFoundation.h> #define SKVolumeChangesPerSecond 15 @interface MXAudioPlayerFadeOperation () - (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; } return result; } - (void)setAudioPlayer:(AVAudioPlayer *)anAudioPlayer { @synchronized(self) { if (_audioPlayer != anAudioPlayer) { _audioPlayer = nil; _audioPlayer = anAudioPlayer; } } } #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 { NSLog(@"Failed to init class (%@) with AVAudioPlayer instance, use initFadeWithAudioPlayer:",[self class]); return nil; } - (void)main { @autoreleasepool { [NSThread sleepForTimeInterval:_delay]; if ([self.audioPlayer isKindOfClass:[AVAudioPlayer class]]) { [self beginFadeOperation]; } else { NSLog(@"AudioPlayerFadeOperation began with invalid AVAudioPlayer"); } } } - (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]; } @end 

With a sample for using AudioManagerController

AudioManagerController.h

 /* * Hedgewars-iOS, a Hedgewars port for iOS devices * Copyright (c) 2009-2011 Vittorio Giovara <vittorio.giovara@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * File created on 23/09/2011. */ #import <Foundation/Foundation.h> @interface AudioManagerController : NSObject { } +(void) playBackgroundMusic; +(void) pauseBackgroundMusic; +(void) stopBackgroundMusic; +(void) fadeInBackgroundMusic; +(void) fadeOutBackgroundMusic; +(void) playClickSound; +(void) playBackSound; +(void) playSelectSound; +(void) releaseCache; @end 

AudioManagerController.m

 /* * Hedgewars-iOS, a Hedgewars port for iOS devices * Copyright (c) 2009-2011 Vittorio Giovara <vittorio.giovara@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * File created on 23/09/2011. */ #import "AudioManagerController.h" #import "AVFoundation/AVAudioPlayer.h" #import <AudioToolbox/AudioToolbox.h> #import "MXAudioPlayerFadeOperation.h" static AVAudioPlayer *backgroundMusic = nil; static SystemSoundID clickSound = -1; static SystemSoundID backSound = -1; static SystemSoundID selSound = -1; static NSOperationQueue *audioFaderQueue = nil; static MXAudioPlayerFadeOperation *fadeIn = nil; static MXAudioPlayerFadeOperation *fadeOut = nil; @implementation AudioManagerController #pragma mark - #pragma mark background music control +(void) loadBackgroundMusic { NSString *musicString = [[NSBundle mainBundle] pathForResource:@"hwclassic" ofType:@"mp3"]; backgroundMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicString] error:nil]; backgroundMusic.delegate = nil; backgroundMusic.volume = 0; backgroundMusic.numberOfLoops = -1; [backgroundMusic prepareToPlay]; } +(void) playBackgroundMusic { if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"music"] boolValue] == NO) return; if (backgroundMusic == nil) [AudioManagerController loadBackgroundMusic]; backgroundMusic.volume = 0.45f; [backgroundMusic play]; } +(void) pauseBackgroundMusic { [backgroundMusic pause]; } +(void) stopBackgroundMusic { [backgroundMusic stop]; } +(void) fadeOutBackgroundMusic { if (audioFaderQueue == nil) audioFaderQueue = [[NSOperationQueue alloc] init]; if (backgroundMusic == nil) [AudioManagerController loadBackgroundMusic]; if (fadeOut == nil) fadeOut = [[MXAudioPlayerFadeOperation alloc] initFadeWithAudioPlayer:backgroundMusic toVolume:0.0 overDuration:3.0]; [audioFaderQueue addOperation:fadeOut]; } +(void) fadeInBackgroundMusic { if (audioFaderQueue == nil) audioFaderQueue = [[NSOperationQueue alloc] init]; if (backgroundMusic == nil) [AudioManagerController loadBackgroundMusic]; if (fadeIn == nil) fadeIn = [[MXAudioPlayerFadeOperation alloc] initFadeWithAudioPlayer:backgroundMusic toVolume:0.45 overDuration:2.0]; [audioFaderQueue addOperation:fadeIn]; } #pragma mark - #pragma mark sound effects control +(SystemSoundID) loadSound:(NSString *)snd { // get the filename of the sound file: NSString *path = [NSString stringWithFormat:@"%@/%@",[[NSBundle mainBundle] resourcePath],snd]; // declare a system sound id and get a URL for the sound file SystemSoundID soundID; NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO]; // use audio sevices to create and play the sound AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID); return soundID; } +(void) playClickSound { if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"sound"] boolValue] == NO) return; if (clickSound == -1) clickSound = [AudioManagerController loadSound:@"clickSound.wav"]; AudioServicesPlaySystemSound(clickSound); } +(void) playBackSound { if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"sound"] boolValue] == NO) return; if (backSound == -1) backSound = [AudioManagerController loadSound:@"backSound.wav"]; AudioServicesPlaySystemSound(backSound); } +(void) playSelectSound { if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"sound"] boolValue] == NO) return; if (selSound == -1) selSound = [AudioManagerController loadSound:@"selSound.wav"]; AudioServicesPlaySystemSound(selSound); } #pragma mark - #pragma mark memory management +(void) releaseCache { [backgroundMusic stop]; [backgroundMusic release], backgroundMusic = nil; [fadeOut release], fadeOut = nil; [fadeIn release], fadeIn = nil; [audioFaderQueue release], audioFaderQueue = nil; AudioServicesDisposeSystemSoundID(clickSound), clickSound = -1; AudioServicesDisposeSystemSoundID(backSound), backSound = -1; AudioServicesDisposeSystemSoundID(selSound), selSound = -1; MSG_MEMCLEAN(); } @end 

ref .: hedgewars

+3
02 Oct '12 at 17:05
source share

This is a really old thread, but I was just looking for a solution to the cross fading problem and found it. I solved it like this:

 -(void)crossFadePlayerOne:(AVAudioPlayer *)player1 andPlayerTwo:(AVAudioPlayer *)player2 withCompletion:(void(^)())completion{ if([player1 volume] > 0){ [player1 setVolume:[player1 volume] - 0.05]; [player2 setVolume:[player2 volume] + 0.05]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC),dispatch_get_main_queue(),^{ [self crossFadePlayerOne:player1 andPlayerTwo:player2 withCompletion:completion]; }); }else{ if(completion){ completion(); } } } 
+2
Mar 22 '15 at 18:45
source share



All Articles