路由 iPhone 音频声音

发布于 2024-09-18 14:35:20 字数 400 浏览 8 评论 0原文

我有一个可以同时收听和播放声音的应用程序。默认情况下,声音通过耳机输出。因此,我使用以下代码将其路由到扬声器:

UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);

这工作正常。但现在,我想在连接耳机或外部扬声器时通过耳机传送声音。我将如何实现这一目标?

理想情况下,应用程序启动时所有其他声音(即音乐等)都应静音。

谢谢!

I have an app which does listen and play sound at the same time. By default, the sound output goes through the earphone. So I use the following code to route it through the speaker:

UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);

This works fine. But now, I'd like to route the sound through the headphones when headphones or external speakers are attached. How would I achieve that?

Also ideally all other sound (i.e. music etc.) should mute when the app launches.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

老旧海报 2024-09-25 14:35:20

为此,您必须在设置音频会话时添加属性侦听器:

AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audioSessionPropertyListener, nil);

因此

void audioSessionPropertyListener(void* inClientData, AudioSessionPropertyID inID,
                                          UInt32 inDataSize, const void* inData) {
          UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;

          if (!isHeadsetPluggedIn()) 
            AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
        }

BOOL isHeadsetPluggedIn() {
  UInt32 routeSize = sizeof (CFStringRef);
  CFStringRef route;

  OSStatus error = AudioSessionGetProperty (kAudioSessionProperty_AudioRoute,
                                            &routeSize,
                                            &route
                                            );



     if (!error && (route != NULL) && ([(NSString*)route rangeOfString:@"Head"].location != NSNotFound)) {
        NSLog(@"HeadsetPluggedIn");
        return YES;
      }
      NSLog(@"Headset_NOT_PluggedIn");
      return NO;
    }

,当插入或拔出耳机时,您会收到通知并更改音频输出方向。

To do this you have to add property listener when you setup audio session:

AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audioSessionPropertyListener, nil);

Where

void audioSessionPropertyListener(void* inClientData, AudioSessionPropertyID inID,
                                          UInt32 inDataSize, const void* inData) {
          UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;

          if (!isHeadsetPluggedIn()) 
            AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
        }

BOOL isHeadsetPluggedIn() {
  UInt32 routeSize = sizeof (CFStringRef);
  CFStringRef route;

  OSStatus error = AudioSessionGetProperty (kAudioSessionProperty_AudioRoute,
                                            &routeSize,
                                            &route
                                            );



     if (!error && (route != NULL) && ([(NSString*)route rangeOfString:@"Head"].location != NSNotFound)) {
        NSLog(@"HeadsetPluggedIn");
        return YES;
      }
      NSLog(@"Headset_NOT_PluggedIn");
      return NO;
    }

So when headphones are plugged in or out you get a notification and change audio output direction.

一抹苦笑 2024-09-25 14:35:20

这是一种快速而肮脏的方法,似乎对我有用:

void sessionPropertyListener(void * inClientData,
                             AudioSessionPropertyID inID,
                             UInt32 inDataSize,
                             常量无效 * inData){

  if (inID == kAudioSessionProperty_AudioRouteChange)
  {
    CFStringRef 新路由;
    UInt32 大小 = sizeof(CFStringRef);
    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &newRoute);
    如果(新路线)
    {
      CFShow(新路线);
      if (CFStringCompare(newRoute, CFSTR("ReceiverAndMicrophone"),
                          (UInt32)NULL) == kCFCompareEqualTo)//如果是接收器,则通过扬声器播放
      {
        UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
        AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
                                 sizeof(audioRouteOverride),
                                 &audioRouteOverride);
      }
      否则 if (CFStringCompare(newRoute, CFSTR("HeadsetInOut"),
                               (UInt32)NULL) == kCFCompareEqualTo)//耳机
      {
        UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None;
        AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
                                 sizeof(audioRouteOverride),
                                 &audioRouteOverride);
      }
    }
  }
}

This is a quick and dirty way and seems to work for me:

void sessionPropertyListener(void *                  inClientData,
                             AudioSessionPropertyID  inID,
                             UInt32                  inDataSize,
                             const void *            inData){

  if (inID == kAudioSessionProperty_AudioRouteChange)
  {
    CFStringRef newRoute;
    UInt32 size = sizeof(CFStringRef);
    AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &size, &newRoute);
    if (newRoute)
    {
      CFShow(newRoute);
      if (CFStringCompare(newRoute, CFSTR("ReceiverAndMicrophone"),
                          (UInt32)NULL) == kCFCompareEqualTo)//if receiver, play through speakers
      {
        UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
        AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
                                 sizeof(audioRouteOverride),
                                 &audioRouteOverride);
      }
      else if (CFStringCompare(newRoute, CFSTR("HeadsetInOut"),
                               (UInt32)NULL) == kCFCompareEqualTo)//headset
      {
        UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_None;
        AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
                                 sizeof(audioRouteOverride),
                                 &audioRouteOverride);
      }
    }
  }
}
时光沙漏 2024-09-25 14:35:20

自 iOS 7 以来,AudioSessionSetProperty 已被弃用,我们应该使用 AVFoundation AVAudioSession。由于所需的操作是允许用户操作覆盖通过扬声器的路由,因此您可能会考虑 AVAudioSessionPortOverrideSpeaker 和 AVAudioSessionCategoryOptionDefaultToSpeaker 之间的区别。

根据技术公告 Q&A QA1754:“使用 AVAudioSessionCategoryOptionDefaultToSpeaker 时,将尊重用户手势。例如,插入耳机将导致路由更改为耳机麦克风/耳机,拔下耳机将导致路由更改为内置- 在麦克风/扬声器中”。

请注意,技术公告解释说 AVAudioSessionPortOverrideSpeaker 更适合与扬声器按钮一起使用,这不是原始帖子所要求的。

https://developer.apple.com/library/ios/qa/ qa1754/_index.html

在调用播放器之前,会调用我自己的实现,如下所示:

NSError *error;
AVAudioSession* audioSession   = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:&error];
// handle any error
// initiate the player or recorder
[_player play];

此外,这个问题与另一篇不同但相关的帖子中解决的问题类似。

根据此处提到的同一技术公告“考虑使用 overrideOutputAudioPort:就您可能使用的内容来实现扬声器按钮而言,您希望能够在扬声器 (AVAudioSessionPortOverrideSpeaker) 和正常输出路由 (AVAudioSessionPortOverrideNone) 之间切换。 ”

如果您正在寻找实现扬声器覆盖 overrideOutputPort 类别,请参阅该文章:
如何在不使用 AudioSessionSetProperty 的情况下将音频路由到扬声器?< /a>

With AudioSessionSetProperty deprecated since iOS 7 we should be using AVFoundation AVAudioSession. Since the desired action is to allow a user action to override the route through the speaker you might consider the difference between AVAudioSessionPortOverrideSpeaker and AVAudioSessionCategoryOptionDefaultToSpeaker.

According to Technical bulletin Q&A QA1754: "When using AVAudioSessionCategoryOptionDefaultToSpeaker, user gestures will be honored. For example, plugging in a headset will cause the route to change to headset mic/headphones and unplugging the headset will cause the route to change to built-in mic/speaker".

Note that the technical bulletin explains that AVAudioSessionPortOverrideSpeaker would be more appropriate for use with a speakerphone button for example, which is not what the original post was asking for.

https://developer.apple.com/library/ios/qa/qa1754/_index.html

My own implementation is called before I invoke the player as follows:

NSError *error;
AVAudioSession* audioSession   = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:&error];
// handle any error
// initiate the player or recorder
[_player play];

Also this question is similar to one addressed in a different but related post.

According to the same technical bulletin referred to here "Think of using overrideOutputAudioPort: in terms of what you might use to implement a Speakerphone button where you want to be able to toggle between the speaker (AVAudioSessionPortOverrideSpeaker) and the normal output route (AVAudioSessionPortOverrideNone)."

Refer to that post if you are looking for implementing the speaker override overrideOutputPort category:
How Do I Route Audio to Speaker without using AudioSessionSetProperty?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文