• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

Exclusive mode from web based players

Tom C

Major Contributor
Joined
Jun 16, 2019
Messages
1,504
Likes
1,371
Location
Wisconsin, USA
Hello,
The question:
Does anybody know how to run audio out of a web browser in exclusive mode, or know of some other work around for getting sample rates to change automatically to match a stream's native sample rate and bit depth?

The use setting:
I have a few outdated PC's and tablets around that I would like to use for audio only. Most of them won't run the latest OS's from Apple or Microsoft, and the one that does really strugles, as it is slow, laggy and a pain to use.
I'm subscribed to Qobuz, which I like for its sound quality, and also its versatility. That is, it can run on most any hardware platform, particularly if you use the web player. Then you just need whatever browser will run on the platform you're using at the time, which uses minimum system resources, and is usually not a problem if it is not the very latest version. But here's the rub: the web browsers I've tried (Safari, Edge and Firefox) all put out audio in shared mode, and I can't get them to use exclusive mode. That means the sample rates won't change automatically on the fly to match whatever is being played at the time. The sample rate can be manually selected in the OS sound controller, but you have to manually change it in the controller each time you select a stream with a different sample rate. It's especially a pain when using a playlist containing a wide variety of sample rates.
I know I can make life easy by just setting the shared mode to 44.1/16 or whatever, but I'm hoping not to compromise, since I'm paying for the service, the broadband connection, and capable output hardware. And it alows me to save by repurposing a computer deprecated only by software fiat that would otherwise become landfill.
 

phofman

Addicted to Fun and Learning
Joined
Apr 13, 2021
Messages
501
Likes
323
OP
Tom C

Tom C

Major Contributor
Joined
Jun 16, 2019
Messages
1,504
Likes
1,371
Location
Wisconsin, USA
Thank you for the reply. Doesn’t seem like it should be an insurmountable problem, but maybe there just aren’t enough people to whom it is important.
 

Zardozz

Member
Joined
Aug 4, 2023
Messages
16
Likes
7
Location
Pacific Ocean
I tried launching Chrome and Opera, both, with -exclusive-mode-audio in command line. And kept getting audio from other apps mixed in. FWIW.

It's somewhat disappointing since motherearthradio.de sends 24/192 streams, but what good is that if Windows is resampling with all its hocus pocus?
 

ChrisCables

Active Member
Audio Company
Joined
Nov 11, 2022
Messages
112
Likes
106
Location
NL
You can add their stream links to foobar2000 or similar and get bit-perfect audio playback that way.
It should be noted that you also need to enable bit-perfect passthrough via Windows or whatever OS you are using so that the stream/s bypass the OS mixer/driver and on the way to an external DAC.
You can verify this when implemented by altering the OS volume slider. It should make no difference to the volume if correctly set up.
 

staticV3

Master Contributor
Joined
Aug 29, 2019
Messages
7,855
Likes
12,547
You can verify this when implemented by altering the OS volume slider. It should make no difference to the volume if correctly set up.
Unless your DAC supports UAC2 Hardware Volume Control, in which case the OS volume slider will continue working even with bit-perfect audio playback enabled.
 

ChrisCables

Active Member
Audio Company
Joined
Nov 11, 2022
Messages
112
Likes
106
Location
NL
Unless your DAC supports UAC2 Hardware Volume Control, in which case the OS volume slider will continue working even with bit-perfect audio playback enabled.
You would still need to set and verify it via the OS/foobar.
 

staticV3

Master Contributor
Joined
Aug 29, 2019
Messages
7,855
Likes
12,547
You would still need to set and verify it via the OS/foobar.
Yes, foobar needs to be set to Wasapi(push) or ASIO output for bit-perfect playback.
However, whether or not the OS volume slider continues working is not a good way to verify bit-perfect audio playback, for the above reason.
 

ChrisCables

Active Member
Audio Company
Joined
Nov 11, 2022
Messages
112
Likes
106
Location
NL
Yes, foobar needs to be set to Wasapi(push) or ASIO output for bit-perfect playback.
However, whether or not the OS volume slider continues working is not a good way to verify bit-perfect audio playback, for the above reason.
Oh god, I'll never get this time back.
:facepalm:
 

phofman

Addicted to Fun and Learning
Joined
Apr 13, 2021
Messages
501
Likes
323
Looking at chrome/chromium source code and logs of chrome with the exclusive command parameter, I do not think the exclusive mode can work as is coded in chrome. Unfortunately the source code does not log whether the device is open in shared vs. exclusive mode. Nevertheless, the only format chromium tries to set/use in its waveformatex struct is KSDATAFORMAT_SUBTYPE_IEEE_FLOAT https://github.com/chromium/chromiu...udio/win/audio_low_latency_output_win.cc#L148 . The logs confirm that. But very few devices support float format natively. As a result, it's logical that the logs show


[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] AMB::MakeAudioOutputStream({device_id={0.0.0.00000000}.{8d031027-8894-4ac9-ae8c-34e9ceed93c6}}, {params=[format: PCM_LOW_LATENCY, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 256, effects: 128, mic_positions: , hw_capabilities: min_frames_per_buffer: 0, max_frames_per_buffer: 0, bitstream_formats:0, require_encapsulation:0]})
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] WAOS::WASAPIAudioOutputStream({device_id={0.0.0.00000000}.{8d031027-8894-4ac9-ae8c-34e9ceed93c6}}, {params=[format: PCM_LOW_LATENCY, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 256, effects: 128, mic_positions: , hw_capabilities: min_frames_per_buffer: 0, max_frames_per_buffer: 0, bitstream_formats:0, require_encapsulation:0]}, {role=Console}) [this=0x351400094880]
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] WAOS::WASAPIAudioOutputStream => (audio engine format=[wFormatTag: WAVE_FORMAT_EXTENSIBLE (0xFFFE), nChannels: 2, nSamplesPerSec: 48000, nAvgBytesPerSec: 384000, nBlockAlign: 8, wBitsPerSample: 32, cbSize: 22 [+] wValidBitsPerSample: 32, dwChannelMask: FRONT_LEFT | FRONT_RIGHT (2), SubFormat: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT]) [this=0x351400094880]
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] WAOS::WASAPIAudioOutputStream => (packet size=[2048 bytes/256 audio frames/5.333 ms]) [this=0x351400094880]
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] AMB::MakeAudioOutputStream => (number of streams=1)
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] WAOS::Open([opened=false]) [this=0x351400094880]
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] WAOS::Open => (ERROR: CAU::IsFormatSupported failed) [this=0x351400094880]
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] WAOS::Close() [this=0x351400094880]
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] WAOS::Stop([started=false]) [this=0x351400094880]
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] AMB::MakeAudioOutputStream({device_id=}, {params=[format: PCM_LINEAR, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 2048, effects: 128, mic_positions: , hw_capabilities: min_frames_per_buffer: 0, max_frames_per_buffer: 0, bitstream_formats:0, require_encapsulation:0]})
[9728:852:1006/145023.535:VERBOSE1:media_stream_manager.cc(1416)] AMB::MakeAudioOutputStream => (number of streams=1)
[9728:852:1006/145023.583:VERBOSE1:media_stream_manager.cc(1416)] audio::OS::Ctor({audio_manager_name=Windows}, {device_id=default}, {params=[format: PCM_LOW_LATENCY, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 1024, effects: 128, mic_positions: ]}) [controller=0x3514000759A0]
[9728:852:1006/145023.583:VERBOSE1:media_stream_manager.cc(1416)] AOC::CreateStream([state=empty]) [this=0x3514000759A0]
[9728:852:1006/145023.583:VERBOSE1:media_stream_manager.cc(1416)] AOC::RecreateStream({reason = INITIAL_STREAM}, {params = [format: PCM_LOW_LATENCY, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 1024, effects: 128, mic_positions: ]}, [state = empty]) [this=0x3514000759A0]
[9728:852:1006/145023.583:VERBOSE1:media_stream_manager.cc(1416)] AOC::CreateStream => (state=created) [this=0x3514000759A0]
[9728:852:1006/145023.583:VERBOSE1:media_stream_manager.cc(1416)] audio::OS::CreateAudioPipe() [controller=0x3514000759A0]
[9728:852:1006/145023.584:VERBOSE1:media_stream_manager.cc(1416)] audio::OS:: Play() [controller=0x3514000759A0]
[9728:852:1006/145023.584:VERBOSE1:media_stream_manager.cc(1416)] AOC:: Play([state=created]) [this=0x3514000759A0]
[9728:852:1006/145023.584:VERBOSE1:media_stream_manager.cc(1416)] AOC::StartStream => (state=playing) [this=0x3514000759A0]


Chrome tries to open the wasapi PCM_LOW_LATENCY stream with float format, using WASAPI, the driver refuses that format in https://github.com/chromium/chromiu...win/audio_low_latency_output_win.cc#L225-L231 , and chrome tries to open the output stream using WaveOut API (not WASAPI) https://github.com/chromium/chromiu...2a9/media/audio/win/audio_manager_win.cc#L237 -> https://github.com/chromium/chromium/blob/main/media/audio/win/waveout_output_win.h#L35

On the other hand, this is standard non-exclusive chrome log (no exclusive command-line parameter):

[9852:8380:1006/154438.487:VERBOSE1:media_stream_manager.cc(1416)] AMB::MakeAudioOutputStream({device_id={0.0.0.00000000}.{8d031027-8894-4ac9-ae8c-34e9ceed93c6}}, {params=[format: PCM_LOW_LATENCY, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 480, effects: 128, mic_positions: , hw_capabilities: min_frames_per_buffer: 128, max_frames_per_buffer: 480, bitstream_formats:0, require_encapsulation:0]})
[9852:8380:1006/154438.487:VERBOSE1:media_stream_manager.cc(1416)] WAOS::WASAPIAudioOutputStream({device_id={0.0.0.00000000}.{8d031027-8894-4ac9-ae8c-34e9ceed93c6}}, {params=[format: PCM_LOW_LATENCY, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 480, effects: 128, mic_positions: , hw_capabilities: min_frames_per_buffer: 128, max_frames_per_buffer: 480, bitstream_formats:0, require_encapsulation:0]}, {role=Console}) [this=0x79A000094880]
[9852:8380:1006/154438.487:VERBOSE1:media_stream_manager.cc(1416)] WAOS::WASAPIAudioOutputStream => (audio engine format=[wFormatTag: WAVE_FORMAT_EXTENSIBLE (0xFFFE), nChannels: 2, nSamplesPerSec: 48000, nAvgBytesPerSec: 384000, nBlockAlign: 8, wBitsPerSample: 32, cbSize: 22 [+] wValidBitsPerSample: 32, dwChannelMask: FRONT_LEFT | FRONT_RIGHT (2), SubFormat: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT]) [this=0x79A000094880]
[9852:8380:1006/154438.487:VERBOSE1:media_stream_manager.cc(1416)] WAOS::WASAPIAudioOutputStream => (packet size=[3840 bytes/480 audio frames/10.000 ms]) [this=0x79A000094880]
[9852:8380:1006/154438.487:VERBOSE1:media_stream_manager.cc(1416)] AMB::MakeAudioOutputStream => (number of streams=1)
[9852:8380:1006/154438.487:VERBOSE1:media_stream_manager.cc(1416)] WAOS::Open([opened=false]) [this=0x79A000094880]
[9852:8380:1006/154438.510:VERBOSE1:media_stream_manager.cc(1416)] WAOS::Open => (preferred_frames_per_buffer=[480 audio frames]) [this=0x79A000094880]
[9852:8380:1006/154438.514:VERBOSE1:media_stream_manager.cc(1416)] audio::OS::Ctor({audio_manager_name=Windows}, {device_id=default}, {params=[format: PCM_LOW_LATENCY, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 960, effects: 128, mic_positions: ]}) [controller=0x79A0000761A0]
[9852:8380:1006/154438.514:VERBOSE1:media_stream_manager.cc(1416)] AOC::CreateStream([state=empty]) [this=0x79A0000761A0]
[9852:8380:1006/154438.514:VERBOSE1:media_stream_manager.cc(1416)] AOC::RecreateStream({reason = INITIAL_STREAM}, {params = [format: PCM_LOW_LATENCY, channel_layout: 3, channels: 2, sample_rate: 48000, frames_per_buffer: 960, effects: 128, mic_positions: ]}, [state = empty]) [this=0x79A0000761A0]
[9852:8380:1006/154438.514:VERBOSE1:media_stream_manager.cc(1416)] AOC::CreateStream => (state=created) [this=0x79A0000761A0]
[9852:8380:1006/154438.514:VERBOSE1:media_stream_manager.cc(1416)] audio::OS::CreateAudioPipe() [controller=0x79A0000761A0]
[9852:8380:1006/154438.514:VERBOSE1:media_stream_manager.cc(1416)] WAOS::SetVolume({volume=1.00}) [this=0x79A000094880]
[9852:8380:1006/154438.514:VERBOSE1:media_stream_manager.cc(1416)] WAOS::Start([opened=true, started=false]) [this=0x79A000094880]
[9852:8380:1006/154438.516:VERBOSE1:media_stream_manager.cc(1416)] audio::OS:: Play() [controller=0x79A0000761A0]
[9852:8380:1006/154438.516:VERBOSE1:media_stream_manager.cc(1416)] AOC:: Play([state=created]) [this=0x79A0000761A0]
[9852:8380:1006/154438.516:VERBOSE1:media_stream_manager.cc(1416)] AOC::StartStream => (state=playing) [this=0x79A0000761A0]


Here the WAOS::Open call succeeds (WASAPI shared goes through the MS audio subsystem which supports many sample formats, of course float being among them), and playback goes through WASAPI.

Conclusion - IMO unless a device supports float format natively, chrome cannot use it in exclusive mode. IME when working on wasapi-exclusive connector for Roomeqwizard (REW) https://github.com/pavhofman/csjsound-wasapi the by far most difficult part of wasapi excl API is finding the exact format supported by the driver/device. My code must iterate through lots of variants https://github.com/pavhofman/csjsound-wasapi/blob/main/src/formats.rs#L106 . So does wasapi excl code for CamillaDSP https://github.com/HEnquist/wasapi-rs/blob/master/src/api.rs#L455 . So does Portaudio (used e.g. in FlexASIO or Audacity) https://github.com/PortAudio/portau...rc/hostapi/wasapi/pa_win_wasapi.c#L3016-L3028 https://github.com/PortAudio/portau...3322/src/hostapi/wasapi/pa_win_wasapi.c#L2876

Chrome/chromium does none of that. The chances of guessing the device format right at first try are quite low, especially with the float format. There is a reason the exclusive feature is marked experimental...
 

palm

Member
Joined
Mar 4, 2023
Messages
74
Likes
62
It‘s difficult to control what happens exactly in the chain and this is annoying. On the other hand, for years the only available format was 44.1/16 and you would just have to trust that any sampling rate conversion before the transfer to CD was done according to the state of the art. That’s obviously not an excuse for crappy sound processing between the streaming service and what is sent to the DAC, but I try nevertheless to put things in perspective and appreciate being able to listen to a vast lossless catalogue on flawless DACs of today.
 

Moderate Dionysianism

Active Member
Joined
Aug 27, 2020
Messages
287
Likes
472

Moderate Dionysianism

Active Member
Joined
Aug 27, 2020
Messages
287
Likes
472
how is it supoused to work anyways? You can't chose the audio device directly in the browser and you can't chose exclusive devices in Windows Mixer
Beats me, we probably should ask that Peter dude, who included it in his huge list, prefaced with:
There are lots of command lines which can be used with the Google Chrome browser.

I assume he wasn't just sitting there coming up with random commands...
 

phofman

Addicted to Fun and Learning
Joined
Apr 13, 2021
Messages
501
Likes
323
how is it supoused to work anyways? You can't chose the audio device directly in the browser and you can't chose exclusive devices in Windows Mixer
IIUC the source code the device is default device. That means set a device default in windows audio subsystem and chrome will try to open it in exclusive mode.
 
Top Bottom