【问题标题】:Delphi BASS library - change audio output device during runtimeDelphi BASS 库 - 在运行时更改音频输出设备
【发布时间】:2018-05-02 03:03:27
【问题描述】:

我在 Delphi 有一个 mp3 播放器。 当播放器正在运行并且我将音频输出设备更改为从线路输出(扬声器)到蓝牙时,播放器仍将声音“发送”到线路输出设备。 当我的蓝牙耳机连接并启动播放器时,一切都很好,播放器将声音“发送”到蓝牙设备。但是当我断开蓝牙扬声器/耳机时,播放器不会播放任何歌曲,它只是跳过每首歌曲,因为它们不会“可播放”。

有没有办法管理这个? 其他所有播放器,VLC、Winamp、Windows Media Player,都能够“即时”处理输出设备的变化。

对于我使用 Delphi XE 的播放器,但我认为这与问题本身无关。 当时我使用 BASS 库 2.4.11

提前感谢您的回答! 页面

【问题讨论】:

  • 暂停播放,设置设备,开始播放(可以通过枚举设备信息找到新选择的默认设备)。
  • @Victoria 如果您能向我展示一个用于枚举和设置输出设备的示例,我们将不胜感激。 :-) 非常感谢!

标签: delphi bluetooth mp3 bass bass.dll


【解决方案1】:

是的,有办法。

AIMP 播放器完全使用 Delphi 使用 BASS 库编写。

如果您停止播放,请更改首选项中的音频输出并开始播放 - 它会将音乐发送到新选择的声音设备。

【讨论】:

  • @Victoria “播放器不播放任何歌曲,它只是跳过每一首歌” - 你可能会尝试猜测这家伙的意思,甚至为他开发播放器,但到目前为止他还没有要求它,没有提供他的代码,没有报告具体的错误和位置 - 没有常识和 SE 规则所要求的。 (PS:还有SetChannelDevice功能,另外一个可以做虚拟通道解耦输入解包和输出sink管理,你可以给他开发一个例子)
  • 感谢两位的回答! @Arioch'我没有“呈现”代码,因为没有错误。播放器跳过文件的原因是输出设备不可用。所以,如果我能实现一个“设备输出改变功能”,那么一切都会好起来的。是的,从你的回答中我可以看出,这是可能的。 :-) 我从来没有改变过输出设备。现在我明白了,我需要一个例程来扫描和设置输出设备。 MPage
  • @XingFuZhuanYun 没有错误也没关系。您说您的代码没有按预期工作:显示您的代码,以便人们能够告诉您它是否有问题或替代方案。
  • @Dave Nottage 我没有说可能代码无法按预期工作。从 Victoria 和 Arioch 的回答中,我可以读到我需要一个程序来枚举输出设备并将设备设置为活动输出设备。目前,我没有这样的功能/程序。 “其他任何东西”都很好用。
  • @XingFuZhuanYun 您的问题是:“但是当我断开蓝牙扬声器/耳机时,播放器不播放任何歌曲,它只是跳过每首歌曲,因为它们不会“可播放”,即代码没有按照您的意愿执行。这可能是因为您的代码中有问题,包括您可能遗漏的某些内容。无法判断,因为您没有发布任何代码
【解决方案2】:

所以,在阅读了一些手册并进行了一些测试之后,这就是我现在的“MediaPause”例程中的内容:

// Reset counter
i := 1;

// Reset device list
lstADevices.Clear;

while BASS_GetDeviceInfo(i, ADeviceInfo) do
begin
  lstADevices.Add(ADeviceInfo.name);
  inc(i);

end;

intDevice := -1;

for i := 0 to lstADevices.Count - 1 do
begin
  if lstADevices[i] = 'Bluetooth A2DP Stereo Audio (Bose AE2w 01.02.00( Stereo ))' then
  begin
    intDevice := i + 1; // + 1 is important, because the list starts with 0! (for BASS 0 means 'no device')
    BASS_GetDeviceInfo(intDevice, ADeviceInfo);
    intFlag := ADeviceInfo.flags;

    if intFlag = 67108868 then
    begin
      for j := 0 to lstADevices.Count - 1 do
      begin
        if lstADevices[j] = 'Speakers (Realtek High Definition Audio)' then
        begin
          intDevice := j + 1; // The list starts at 0
          break;

        end;

      end;

    end;

    break;

  end;

end;

BASS_Init(intDevice, 44100, 0, Application.Handle, nil);
blnBASS := BASS_ChannelSetDevice(AudioStream, intDevice);

if not blnBASS then
  intBASSErrorCode := BASS_ErrorGetCode;

BASS_ChannelPlay(AudioStream, False);

程序启动时,未连接蓝牙耳机时,不会枚举进入设备列表。所以我必须在任何必要的时候枚举设备。我想在“滴答计数器”中实现它以显示时间(以秒为单位的滴答声),但由于以下行为,我还没有这样做。 我可以在蓝牙耳机和扬声器之间切换(BASS_ChannelSetDevice)一次。当我想/必须再次切换时,无论出于何种原因,我都会收到错误代码 4,这意味着 BASS_ERROR_BUFLOST(样本缓冲区丢失)。 我试图根据缓冲区大小找到任何东西,但找不到任何东西。

我检查了蓝牙设备的标志值 67108868,因为我找不到任何其他方法来检查设备是否可用。 如果蓝牙设备在运行时连接过一次,即使之后断开连接,它也会一直被枚举。它也有“启用”状态,所以我只发现了标志值的差异。 将上面的代码打包到显示器的刻度计数器中,我可以设法将设备从扬声器自动更改为耳机,这对我来说是“完美”的方式,但由于“缓冲区丢失”错误的问题,我将它从滴答计数器例程中删除。

就像 Victoria 和 Arioch '前面提到的,我在更换设备之前暂停了播放器。如前所述,它一次有效,下一次我遇到“缓冲区丢失”错误。这意味着,没有产生错误,但输出没有改变。

由于我不确定“我的方式”在任何意义上是否正确,是否有“更安全”的方式来更换设备?

MPage

【讨论】:

  • 我可以根据缓冲区找到一些东西并将这一行包含在我的代码中:BASS_SetConfig(BASS_CONFIG_BUFFER, 5000);但是,和以前一样,我只能更换一次设备。然后我又遇到了“缓冲区丢失”的情况。
猜你喜欢
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多