ios SystemSound 不会响应音量按钮

Posted

技术标签:

【中文标题】ios SystemSound 不会响应音量按钮【英文标题】:ios SystemSound will not respond to volume buttons 【发布时间】:2013-06-20 11:48:15 【问题描述】:

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

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

- (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(即使通过像 Finch 或 CocosDenshion 这样的第三方声音库)

有什么想法吗?

【问题讨论】:

【参考方案1】:

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

您可以为您经常使用的每个声音文件保留AVAudioPlayer 的实例,只需调用play 方法即可。使用prepareToPlay 预加载缓冲区。

【讨论】:

感谢您的建议,但我之前在 AVAudioPlayer 上做了一些测试,但它有一些滞后问题。猜猜我唯一的选择是使用 OpenAL 库吗?无法让 SystemSound 响应音量按钮? @am_,您是否预加载了文件、保留了我在(更新的)答案中提到的 AVAudioPlayer 实例,并使用了prepareToPlay?它立即为我工作。我什至将它用于 UI 声音。 SystemSound 用于“警报”。无论如何,OpenAL 只会使用 Core Audio (AVAudioPlayer)。 嗯,我想我可以在应用程序启动后立即使用 prepareToPlay 加载我的所有 wav 文件(我有大约 60 个 wav 文件)。在 finch 主页上提到 AVAudioPlayer 的播放方法有滞后。但明天我会试试看它是如何工作的!会告诉你的!【参考方案2】:

感谢 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;

【讨论】:

以上是关于ios SystemSound 不会响应音量按钮的主要内容,如果未能解决你的问题,请参考以下文章

iPhone iOS7 系统声音(铃声和警报)音量控制

iPhone - 无法使用硬按钮调节音量

ios应用程序在后台使用SwiftUI时如何播放SystemSound

检测 iPhone 音量按钮保持? (iOS 8)

检测音量按钮的长按和短按 - iOS

聆听音量按钮按下的正确方式(iOS 15)