1

我在我的应用程序中使用了 SystemSound 来播放简单的音效。除此之外,我通过 MPMoviePlayerController 播放音乐视频 - 现在,当我将音量调高/调低时,视频中的音乐会按预期响应(调高/调低音量)。

但是播放的系统声音不响应音量。当用户点击应用程序中的某些区域时,我会播放系统声音。这是我的代码片段:

- (void)handleTap:(UITapGestureRecognizer *)recognizer {
   SystemSoundID completeSound = nil;

   //yellow folder in xcode doesnt need subdirectory param
   //blue folder (true folder) will need to use subdirectory:@"dirname"
   NSURL *sound_path  = [[NSBundle mainBundle] URLForResource: target_sound_filename withExtension: @"wav"];

   AudioServicesCreateSystemSoundID((__bridge CFURLRef)sound_path, &completeSound);
   AudioServicesPlaySystemSound(completeSound);
}

PS。我仔细检查了我的“设置->声音->铃声和警报->使用按钮更改”是否设置为开启(正如我在其他一些 SO 答案中看到的那样,关闭此选项会导致系统声音无法响应音量按钮)

此外,使用 systemsound 的原因是它在播放多个声音时(如在游戏中)提供了最准确和响应最灵敏的结果。

如果可能,我宁愿不使用 OpenAL(即使通过FinchCocosDenshion等第三方声音库)

有任何想法吗?

4

2 回答 2

2

使用AVAudioPlayer类播放由用户音量设置控制的声音(非系统声音)。

AVAudioPlayer您可以保留您经常使用的每个声音文件的实例并简单地调用该play方法。用于prepareToPlay预加载缓冲区。

于 2013-06-20T12:26:32.810 回答
1

感谢 Marcus 建议我可以为每个声音文件保留 AVAudioPlayer 实例并使用 prepareToPlay 预加载声音。这可能是为了帮助其他寻求相同解决方案的人,所以这就是我的做法(如果有人有改进建议,请随时发表评论)

//top of viewcontroller.m
@property (nonatomic, strong) NSMutableDictionary *audioPlayers;
@synthesize audioPlayers = _audioPlayers;

//on viewDidLoad
self.audioPlayers = [NSMutableDictionary new];

//creating the instances and adding them to the nsmutabledictonary in order to retain them
//soundFile is just a NSString containing the name of the wav file
NSString *soundFile = [[NSBundle mainBundle] pathForResource:s ofType:@"wav"];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:soundFile] error:nil];
//audioPlayer.numberOfLoops = -1;
[audioPlayer prepareToPlay];

//add to dictonary with filename (omit extension) as key
[self.audioPlayers setObject:audioPlayer forKey:s];

//then i use the following to play the sound later on (i have it on a tap event)
//get pointer reference to the correct AVAudioPlayer instance for this sound, and play it
AVAudioPlayer *foo = [self.audioPlayers objectForKey:target_sound_filename];
[foo play];

//also im not sure how ARC will treat the strong property, im setting it to nil in dealloc atm.
-(void)dealloc {
    self.audioPlayers = nil;
}
于 2013-06-24T23:31:31.163 回答