降低iPod音量以播放应用程序声音(如本机SMS应用程序)

Jus*_*her 12 cocoa-touch avaudioplayer iphone-sdk-3.0 ios avaudiosession

我做了一个iPhone应用程序,在运动时使用.它会播放铃声,表示您(用户)应该从练习例程的一个步骤切换到下一个步骤.我设计了应用程序,以便您在使用应用程序时可以在iPod上听音乐,我希望音调可以在音乐上充分发声.我已经让这个工作......有点......

当音乐响亮时,很难听到音调.我理想的解决方案类似于iPod应用程序处理传入短信或电子邮件的方式.音乐音量降低,声音播放,音乐音量逐渐消失.

以下是我到目前为止尝试过的方法:

  1. 我以前常常AudioServicesPlaySystemSound播放声音.

    我初始化声音是这样的:

    CFBundleRef mainBundle = CFBundleGetMainBundle();
    soundFileURLRef = CFBundleCopyResourceURL(mainBundle, CFSTR ("bell"), CFSTR ("wav"), NULL);
    AudioServicesCreateSystemSoundID (soundFileURLRef, &soundFileID);
    
    Run Code Online (Sandbox Code Playgroud)

    我在适当的时候使用以下方式播放声音:

    AudioServicesPlaySystemSound (self.soundFileID);
    
    Run Code Online (Sandbox Code Playgroud)

    这播放声音很好,但是听到嘈杂的音乐太难了.试图2 ...

  2. 我试图降低iPod音量,播放声音,然后将音量恢复到之前的水平.

    如果当前步骤还剩1秒,则开始降低音量:

    if ([self.intervalSet currentStepTimeRemainingInSeconds] == 1) {
        self.volumeIncrement = originalVolume/5.0f;
        [NSTimer scheduledTimerWithTimeInterval:0.5f 
                                         target:self 
                                       selector:@selector(fadeVolumeOut:) 
                                       userInfo:[NSNumber numberWithInt:1]
                                        repeats:NO];
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这是fadeVolumeOut:方法:

    - (void) fadeVolumeOut:(NSTimer *)timer {
        if (!TARGET_IPHONE_SIMULATOR) {
            NSNumber *volumeStep = (NSNumber *)[timer userInfo];
            int vStep = [(NSNumber *)volumeStep intValue];
            float volume = [[MPMusicPlayerController iPodMusicPlayer] volume];
            volume = volume - self.volumeIncrement;
            if (volume < 0.0f) {
                volume = 0.0f;
            }
            [[MPMusicPlayerController iPodMusicPlayer] setVolume:volume];
            if (vStep < 5) {
                vStep = vStep + 1;
                [NSTimer scheduledTimerWithTimeInterval:0.1f 
                                                 target:self 
                                               selector:@selector(fadeVolumeOut:) 
                                               userInfo:[NSNumber numberWithInt:vStep]
                                                repeats:NO];
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    然后,当步骤结束时,播放警报声并将音量淡入:

     [NSTimer scheduledTimerWithTimeInterval:0.1f 
                                      target:self 
                                    selector:@selector(alertAndFadeVolumeIn) 
                                    userInfo:nil
                                     repeats:NO];
    
    Run Code Online (Sandbox Code Playgroud)

    这是alertAndFadeVolumeIn方法:

     - (void) alertAndFadeVolumeIn {
         [self alert];
         [NSTimer scheduledTimerWithTimeInterval:0.25f 
                                          target:self 
                                        selector:@selector(fadeVolumeIn:) 
                                        userInfo:[NSNumber numberWithInt:1]
                                         repeats:NO];
     }
    
    Run Code Online (Sandbox Code Playgroud)

    而且fadeVolumeIn:基本上与fadeVolumeOut:上面相反.

    这有效,音量消失,声音播放,音量逐渐消失.问题是音量降低了与iPod相同的音量,因此它不会让音乐更容易听到.

  3. 我切换到AVAudioSession播放声音,并设置会话,以便在应用程序使用时iPod音乐将继续播放.这是我正在初始化会话的方式:

     AVAudioSession *session = [AVAudioSession sharedInstance];
     [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    
     OSStatus propertySetError = 0;
     UInt32 allowMixing = true;
     propertySetError = AudioSessionSetProperty (
         kAudioSessionProperty_OverrideCategoryMixWithOthers,
         sizeof (allowMixing),
         &allowMixing
     );
    
     NSError *activationError = nil;
     [session setActive:YES error:&activationError];
    
     NSString *audioFile = [[NSBundle mainBundle] pathForResource:@"bell"
                                                           ofType:@"wav"];
     player = [[AVAudioPlayer alloc] initWithContentsOfURL:
         [NSURL fileURLWithPath:audioFile] error:NULL];
    
    Run Code Online (Sandbox Code Playgroud)

    为了播放声音,我[self.player play]在适当的时候打电话.同样,音量与iPod音量一起降低,音调也不容易听到.

  4. [[MPMusicPlayerController applicationMusicPlayer] setVolume:1.0f];在警报声响起之前,我试着把它放好.结果好坏参半.第一次按照我的预期,音量以满音量播放,但随后音量会低很多.此外,音乐不会平滑淡出.它似乎iPodMusicPlayerapplicationMusicPlayer共享相同的音量.这是使用的结果[AVAudioSession sharedInstance];吗?有没有另一种方法来初始化AVAudioSession

  5. 接下来,我尝试使用AVAudioSession"躲避":

     OSStatus propertySetError = 0;
     UInt32 allowDucking = true;
     propertySetError = AudioSessionSetProperty (
         kAudioSessionProperty_OtherMixableAudioShouldDuck,
         sizeof (allowDucking),
         &allowDucking
     );
    
    Run Code Online (Sandbox Code Playgroud)

    不幸的是,当音频会话被激活时,iPod音乐会"躲避",就像我一样装载viewController一样.

  6. 最后,我更改了我的代码,以便音频会话在步骤结束前一秒激活,声音在步骤结束时播放,一秒钟后,会话被停用.此时我已经删除了所有淡入淡出的代码.以下是相关的代码段:

    if ([self.intervalSet currentStepTimeRemainingInSeconds] == 1) {
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setActive:YES error:nil];
    }
    
    Run Code Online (Sandbox Code Playgroud)

    ...

    if (self.shouldRing) {
        [self.player play]; 
        [NSTimer scheduledTimerWithTimeInterval:1.0f 
                                         target:self 
                                       selector:@selector(stopSound)
                                       userInfo:nil
                                        repeats:NO];
    }
    
    Run Code Online (Sandbox Code Playgroud)

    ...

    - (void) stopSound {
        [self.player stop];
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setActive:NO error:nil];
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这让我陷入了困境.这在第一步结束后完美地起作用.iPod音量下降,声音大声播放,iPod音量在一秒后消失.然而,第二次步骤结束时,声音播放的声音稍微不那么大,第三次声音几乎听不到,第四次声音静音.然后,第五次,它再次大声播放,循环重复.

    最重要的是,激活和停用似乎是非常繁重的操作,它们导致计时器稍微断断续续.

有没有人试图做类似的事情?是否有一种首选的方法来播放iPod音乐的声音?

yoo*_*ood 11

AVAudioSession在应用程序,应用程序和设备级别处理" 音频行为 "的正确方法.我在iOS 4上使用了略微修改的#6,没有任何问题.背景音频淡出,我的声音播放,背景音频消失了.

  1. 初始化音频会话(删除错误处理代码):

    AVAudioSession* audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]
    [audioSession setActive:NO error:nil];
    
    Run Code Online (Sandbox Code Playgroud)
  2. 播放声音(AVAudioPlayer播放/ prepareToPlay将为您激活音频会话):

    AVAudioPlayer* audioPlayer = [[[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
    [audioPlayer play];
    
    Run Code Online (Sandbox Code Playgroud)
  3. 停止声音:

    [audioPlayer stop];
    [[AVAudioSession sharedInstance] setActive:NO withFlags:AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation error:nil];
    
    Run Code Online (Sandbox Code Playgroud)

    标志kAudioSessionSetActiveFlag_NotifyOthersOnDeactivation(iOS 4新增功能)告诉系统通知后台音频恢复播放.


mat*_*att 11

做你原来想做的事的正确方法是你的(5) - 使用躲避.这是交易.使用允许其他应用播放声音的音频会话类型(播放).在你即将播放声音之前不要打开闪避.当您即将播放声音时,请打开闪避!背景音乐会立即消失,因此可以听到您的声音.然后,当你的声音播放完毕后,关闭闪避现在(这是技巧)停用你的音频会话并再次激活它,使背景音乐立即恢复以前的响度:

UInt32 duck = 0;
AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(duck), &duck);
AudioSessionSetActive(false);
AudioSessionSetActive(true);
Run Code Online (Sandbox Code Playgroud)

编辑:在iOS 6中,您可以(并且应该)仅使用Objective-C API完成所有这些操作.所以,开始躲避其他音频:

[[AVAudioSession sharedInstance] 
    setCategory: AVAudioSessionCategoryAmbient
    withOptions: AVAudioSessionCategoryOptionDuckOthers
          error: nil];
Run Code Online (Sandbox Code Playgroud)

播放完声音后,关闭闪避:

[[AVAudioSession sharedInstance] setActive:NO withOptions:0 error:nil];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient
                                 withOptions: 0
                                       error: nil];
[[AVAudioSession sharedInstance] setActive:YES withOptions: 0 error:nil];
Run Code Online (Sandbox Code Playgroud)