音频文件播放自己

时间:2015-12-29 11:43:53

标签: ios objective-c audio

我正在构建一个具有多个视图控制器的应用程序,我已经编写了一个音频文件,可以在应用程序启动时播放。这工作正常,当我点击按钮查看不同的屏幕时,音频文件仍然播放而不跳过它应该的节拍但我的问题出现时,当我点击按钮返回到主屏幕。当我点击返回主屏幕时,音频文件会自动播放,让我想起歌曲Row Row Your Boat。该应用程序正在重新读取该代码,该代码告诉自己播放音频文件,从而再次播放它。我的问题是,我无法弄清楚如何使它不这样做。我已经编写了应用程序,以便在单击开始游戏按钮时停止音频,这是我想要它做的但是直到那时。我只需要帮助让应用程序在返回主屏幕时不播放音频文件。音频文件被编码为无限播放,直到单击“开始”按钮。如果有人可以从我想说的那样做,那么请帮我正确编码这个东西。感谢任何能够使其正常工作的人。

这是我的代码:

-(void)viewDidLoad
{

    NSString *introMusic = [[NSBundle mainBundle]pathForResource:@"invadingForces" ofType:@"mp3"];
    audioPlayer0 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:introMusic] error:NULL];
    audioPlayer0.delegate = self;
    audioPlayer0.numberOfLoops = -1;
    [audioPlayer0 play];

}

2 个答案:

答案 0 :(得分:1)

问题是你在加载视图时在局部变量中启动声音,开始无限重复播放,然后忘掉它。然后关闭视图控制器,让现在忘记的音频播放器播放。下次调用视图控制器时,它的viewDidLoad方法会创建另一个音频播放器并启动播放,然后忘记该播放器。每次打开该视图控制器的新副本时,您将启动另一个声音播放器,为您的“行,行,划船”添加另一个声音。

天真的解决方案是将启动声音播放器的代码放在app委托中。将AVAudioPlayer设置为您的app delegate的属性。创建一个startPlaying方法和一个stopPlaying方法。在didFinishLaunchingWithOptions方法中,调用startPlaying。

更干净的应用程序设计不是将应用程序功能放在您的应用程序委托中,而是创建一个单例来管理声音播放。 (搜索“iOS单身设计模式”以了解更多信息。)在单身人士中创建appDidLaunch方法,并从appDidLaunch拨打didFinishLaunchingWithOptions以开始播放您的声音。这样,应用程序委托就不需要具有特定于应用程序的逻辑,而只需调用appDidLaunch并继续使用它。

编辑:

如果您想在app delegate中调用方法,并且您的app delegate声明为:

@interface AppDelegate : UIResponder <UIApplicationDelegate>

然后你会从另一个文件中调用它:

首先,导入app delegate的标题:

#import "AppDelegate.h"

调用你的app delegate的stopPlaying方法的实际代码:

//Get a pointer to the application object.
UIApplication *theApp = [UIApplication sharedApplication];

//ask the application object for a pointer to the app delegate, and cast it 
//to our custom "AppDelegate" class. If your app delegate uses a different 
//class name, use that name here instead of "AppDelegate"
AppDelegate *theAppDelegate = (AppDelegate *)theApp.delegate;
[theAppDelegate stopPlaying];

答案 1 :(得分:0)

以下是将 AVAudioPlayer 包装成单例的一些示例代码 -

<强> BWBackgroundMusic.h

@interface BWBackgroundMusic : NSObject

// singleton getter
+ (instancetype)sharedMusicPlayer;

/*  public interface required to control the AVAudioPlayer instance is as follows -

    start - plays from start - if playing stops and plays from start
    stop - stops and returns play-head to start regardless of state
    pause - stops and leaves play-head where it is - if already paused or stopped does nothing
    continue - continues playing from where the play-head was left - if playing does nothing

    replace audio track with new file - replaceBackgroundMusicWithFileOfName:
    set background player to nil - destroyBackgroundMusic

    NOTE:- change default track filename in .m #define */

// transport like methods
- (void)startBackgroundMusic;

- (void)stopBackgroundMusic;

- (void)pauseBackgroundMusic;

- (void)continueBackgroundMusic;

// audio source management
- (void)replaceBackgroundMusicWithFileOfName:(NSString*)audioFileName startPlaying:(BOOL)startPlaying;

- (void)destroyBackgroundMusic;

@end

<强> BWBackgroundMusic.m

#import "BWBackgroundMusic.h"
#import <AVFoundation/AVFoundation.h> // must link to project first

#define DEFAULT_BACKGROUND_AUDIO_FILENAME @"invadingForces.mp3"

@interface BWBackgroundMusic ()

@property (strong, nonatomic) AVAudioPlayer *backgroundMusicPlayer;

@end

@implementation BWBackgroundMusic

#pragma mark Singleton getter
+ (instancetype)sharedMusicPlayer {

    static BWBackgroundMusic *musicPlayer = nil;
    static dispatch_once_t onceToken;

    dispatch_once (&onceToken, ^{
        musicPlayer = [[self alloc] init];
    });

    //NSLog(@"sample rate of file is %f",[musicPlayer currentSampleRate]);

    return musicPlayer;
}

#pragma mark Initialiser
- (id)init {
    //NSLog(@"sharedMusicPlayer from BWBackgroundMusic.h init called...");
    if (self = [super init]) {
        // self setup _backgroundMusicPlayer here...
        // configure the audio player
        NSURL *musicURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], DEFAULT_BACKGROUND_AUDIO_FILENAME]];
        NSError *error;
        if (_backgroundMusicPlayer == nil) {
            _backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicURL error:&error];
        }
        if (_backgroundMusicPlayer == nil) {
            NSLog(@"%@",[error description]);
        } else {
            [self makePlaybackInfinite];
            [_backgroundMusicPlayer play];
        }
    }
    return self;
}

#pragma mark Selfish methods
- (void)makePlaybackInfinite {
    // access backing ivar directly because this is also called from init method
    if (_backgroundMusicPlayer) {
        _backgroundMusicPlayer.numberOfLoops = -1;
    }
}

- (CGFloat)currentSampleRate {
    NSDictionary *settingsDict = [self.backgroundMusicPlayer settings];
    NSNumber *sampleRate = [settingsDict valueForKey:AVSampleRateKey];
    return [sampleRate floatValue];
}

#pragma mark Transport like methods
- (void)startBackgroundMusic {
    // plays from start - if playing stops and plays from start
    if (self.backgroundMusicPlayer.isPlaying) {
        [self.backgroundMusicPlayer stop];
        self.backgroundMusicPlayer.currentTime = 0;
        [self.backgroundMusicPlayer prepareToPlay];// this is not required as play calls this implicitly if not already prepared
        [self.backgroundMusicPlayer play];
    }
    else {
        self.backgroundMusicPlayer.currentTime = 0;
        [self.backgroundMusicPlayer prepareToPlay];
        [self.backgroundMusicPlayer play];
    }
}

- (void)stopBackgroundMusic {
    // stops and returns play-head to start regardless of state and prepares to play
    if (self.backgroundMusicPlayer.isPlaying) {
        [self.backgroundMusicPlayer stop];
        self.backgroundMusicPlayer.currentTime = 0;
        [self.backgroundMusicPlayer prepareToPlay];
    }
    else {
        self.backgroundMusicPlayer.currentTime = 0;
        [self.backgroundMusicPlayer prepareToPlay];
    }
}

- (void)pauseBackgroundMusic {
    // stops and leaves play-head where it is - if already paused or stopped does nothing
    if (self.backgroundMusicPlayer.isPlaying) {
        [self.backgroundMusicPlayer pause];
    }
}

- (void)continueBackgroundMusic {
    // continues playing from where the play-head was left - if playing does nothing
    if (!self.backgroundMusicPlayer.isPlaying) {
        [self.backgroundMusicPlayer play];
    }
}

#pragma mark Content management
- (void)replaceBackgroundMusicWithFileOfName:(NSString*)audioFileName startPlaying:(BOOL)startPlaying {
    // construct filepath
    NSString *filePath = [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], audioFileName];
    // make a url from the filepath
    NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
    // construct player and prepare
    NSError *error;
    self.backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileUrl error:&error];
    [self.backgroundMusicPlayer prepareToPlay];
    [self makePlaybackInfinite];
    // if startplaying then play
    if (startPlaying) {
        [self.backgroundMusicPlayer play];
    }
}

- (void)destroyBackgroundMusic {
    // stop playing if playing
    [self stopBackgroundMusic];
    // destroy by setting background player to nil
    self.backgroundMusicPlayer = nil;
}

@end

使用简单地调用[BWBackgroundMusic sharedMusicPlayer];这将实例化单例(如果尚未实例化),自动启动播放器,默认情况下将无限循环。

此外,您可以从任何导入BWBackgroundMusic.h

的类控制它

例如暂停播放器使用

[[BWBackgroundMusic sharedMusicPlayer] pauseBackgroundMusic];