detect driver sample rate

btone's icon

Hi,

I'm trying to build a Max patch that can automatically detect the audio driver's sample rate set in Audio MIDI settings in Mac OSX. You'll see in this example patch that if you look at the default audio status in Audio MIDI settings (Built-in Output on my machine) that changing the sampling rate in Max changes it in Audio MIDI.

But how do I go the other way - change it in Audio MIDI and detect that in Max? I assume there must be some way to do it with [adstatus] but I haven't been able to find anything so far.

Thanks!

adstatus_test.maxpat
Max Patch
btone's icon

Another Max user told me he thought it couldn't be done, but I just confirmed that Bidule (a much lower-end graphical audio programming system) has this functionality. Surely Max can do this somehow? Anyone have any ideas?

Edgar Choueiri's icon

I just posted a posting on this forum with the subject "Adaptive Sampling Rate" with this same exact question. I am wondering if you have found an answer since you posted your question in Sept of 2015.
Indeed, Plogue Bidule, which I use extensively, has this capability but I cannot find a way to do it in Max. If I find a way, I will sure let you know. Please do the same if you get a hint in the right direction.
Thanks.

Roman Thilenius's icon

couldnt you retrigger adstatus or dspstatus every 15 seconds to get the recent changes? and then re-set this setting via max? (which of course would interrupt the chain once more)

Edgar Choueiri's icon

While adstatus and dsptatus can be used to set the the SR on the audio device, they do not reflect SR changes made on the actual audio device (hardware) or in Audio Midi Setup. I am looking for a way to query the actual SR on the device (or equivalently, the SR set in Audio Midi Setup).

Roman Thilenius's icon

ah right, you would have to re-select the driver from max _first. and this cant be done somehow in a subpatcher which is silenced.

regarding changes diretly at the device, it owuld think that this needed to be implementated into the CA driver.

Edgar Choueiri's icon

Thanks for the reply. I am not sure I understand what you mean by "max_first" or the "CA driver".

I found out that the SR info I need can easily be obtained through the CoreAudio API, it's a simple call to AudioDeviceGetProperty for the kAudioDevicePropertyStreamFormat property, but I have no idea if this could be done from Max.

Source Audio's icon

read /Library/Preferences/Audio/com.apple.audio.DeviceSettings.plist
into text or coll, dump out, route sample rate and read the value ...

Roman Thilenius's icon

but he would have to watch that file for changes all the time. so either a max external which can talk (or actually listen) to coreaudio, or something else in the OS which does the same.

beside the fact that you cant do anything c++ in max, AudioDeviceGetProperty is probably not what is making bidule aware of a change to the SR when the SR is changed directly at the physical device. get property and set property sound like somewhere else, i think the "nominal sampling rate" stuff is what would be required.

if bidule is the only app which can do this with your device maybe ask them?

Source Audio's icon

I don't actually understand why would someone change audio sampling rate on the fly, while max is running.
What sense would that make ?

Edgar Choueiri's icon

First, to answer Source Audio's last question: I am developing a standalone (max-based) application that processes stereo audio for 3D rendering over two loudspeakers. The application is intended for audiophiles (who typically have a collection of HD music at various sampling rates from 44.1 to 192 kHz) and audiophiles expect any audio processing to be done at the native sampling rate. Therefore the standalone application must switch its sampling rate to match the sampling rate of the audio device (which automatically switches with the sampling rate of the source). I understand that this not a common thing in most audio applications, but adaptive sampling rate is a standard expectation for DACs and digital audio processing in "high-end audio". (A delay of 1-4 seconds for SR switching is tolerated and most high-end audio digital streaming sources have a setting to accommodate such a delay.)

Thank you for your suggestion to parse the DeviceSettings.plist. Indeed this has to be done on a frequent basis (once every second or two) and I will evaluate how feasible this potential solution is.

Another promising solution is having the audio device send its SR regularly to Max through OSC. Luckily the device I am using does support OSC but unfortunately the SR setting is one of the few things that it does send via OSC. I am talking to the manufacturer to see if this can be added.

In the meantime, I continue to look for more elegant solutions that can work with all devices. As I said in a previous posting, the best and cleanest way to do it is via calls to the Core Audio API. It was indeed the developer of Plogue Bidule, Sebastian Beaulieu, who told me that Bidule does it by calls to AudioDeviceGetProperty.

Source Audio's icon

So if I understand that properly, some external Audio Hardware Player is sending audio to max,
which processes it in real time and sends it back to same device, is that correct?
It probably works without adc / dac conversion, all in digital domain.
What device is it exactly ?

Edgar Choueiri's icon

That is correct. The device is RME's Babyface Pro.

Source Audio's icon

RME babyface is just and only audio interface, not a player, and by no means "that" Hi End audiophile device... these "audiophile" guys invest much more in a single chinch cable than what rme interface would cost.
Anyway, babyface is not a player and so it can just input and output audio.
What Audio Player is playing the audio files ?
Why not let Max play Audio Files, detect the Sample Rate before Playback starts and set the SR on Babyface ?
That would definitely be within "normal" quality audio playback,
and audiophile which accepts that audio passest through Max should see no reason not to accept Max to also play fies.

Edgar Choueiri's icon

The Babyface Pro is used for its stereo Mic preamp (which is used for the included binaural mics needed to do the required calibration). It is also used to handle the digital audio i/o. Although it has excellent DAC/ADC, almost all of our customers (who are computer audiophiles) prefer to use their high-end audio DACs. The Babyface Pro simply routes the digital audio from the processing application to the outboard high-end DAC.
As to the file source, the application does have a file player (which already accommodates the solution you suggested, i.e. it can switch the processing SR to that of the file being played internally) but it is a rudimentary file player compared to what our customers use (Roon, Audirvana, Pure Music, etc..). For instance it does not handle metadata and we have no intention in making the app a file player for audiophiles. Hence, our customers use their own sources (audio file players or even CD players), which are configured (in various ways) to send digital audio to the BabyFace Pro, which in turn routes it to the app for processing, then routes the processed audio to the outboard high-end DAC.

At present, the processing is done at a fixed SR and I am looking into making the SR adapt to that of the source.

Source Audio's icon

So You will need to switch the SR on external DAC as well, right?
Well how about call to system profiler?
I don't know how fast does it reflect hardware changes (same would apply to audio.DeviceSettings.plist)
Here is a patch that requests audio hardware properties via shell.
It is then only a matter to route infos for device of interest.
You can find shell object here > https://cycling74.com/tools/bernstein-shell/
Before You hit the "system_profiler SPAudioDataType" have a look at output
for my built in and little motu devices...

Max Patch
Copy patch and select New From Clipboard in Max.

Sample Rate is being reported on Mountin Lion and up.
But one thing is sure, one would have to frequently ask for changes,
there is no way I know of that would make Max autodetect SR and adapt.

Roman Thilenius's icon

or what about logging out and in again.

the only thing whats sure is that a C++ CA API cannot be added to the max runtime with tesa tape or pattex.

Edgar Choueiri's icon

Thank you Source Audio. I put together the attached Max patch that issues the shell call "system_profiler SPAudioDataType" at a set frequency (e.g. every 2 seconds) and extracts the SR of the Default Output Device by parsing the output.

That should do it until I find a more elegant solution.

Detect_Device_SR.maxpat
Max Patch

Source Audio's icon

You are welcome.
As You say this is not elegant solution, because it does not react fast to SR changes on device.
In reality, even if Babyface would send current SR via OSC to Max, Max would actually send it
back to Babyface , so maybe some kind of backloop could become a problem.
One thing is interesting - if one would set the highest available sampling rate
available on a device when max starts, and later change SR on the device, Max will simply
work for In -> Out audio, only any dsp synthesis like for example cycle~frequency would suffer from SR change...
By the way You could optimise the patch a bit to react faster, also maybe one could start requesting, SR only wenn Audio Playback level drops to zero, but then call for SR change
much faster, every 100 ms or so.
Here is little bit changed patch :

Max Patch
Copy patch and select New From Clipboard in Max.


If You can spare a bit of time, coud You please provide a bit more info on,
the way that SR gets changed by Audio Playback.
Which device, or software is doing it, and at which point ( wenn Playback starts
or wenn different Hardware gets connected or engaded...)

Edgar Choueiri's icon

Thanks again for a good idea. Luckily, it turns out that when the SR is changed on the device, the audio streaming in Max stops (even though audio status/processing remains on) so instead of sending frequent shell calls, all one needs to do is detect when the streaming stops. This cannot be done with signals whose source is digital (since that signal is zero when there is no audio playback even if the streaming has not been interrupted by the SR change) but can easily be done with a signal whose origin is analog, which most conveniently is the signal from the mic(s) channel(s) since there is always noise on the preamp/ADC channel(s). In the case of the BabyFace Pro, these are simply input channels 1 and 2, and in the case of the Mac with no external device, they are the channels associated with the built-in mic.

Therefore, I have evolved the patch (see attached patch) to do such a detection and issue the SPAudioDataType shell call only when audio streaming interruption is detected. Nicely, the "; dsp sr $1" message, not only sets the SR in Max but also restarts the streaming, so by removing, the change object that you had placed before it, the reset SR operation will always restart the streaming and, if the SR has changed on the device, resets the SR in Max to match it.

Perhaps you know a better way to detect the halt in audio streaming (any ideas would be appreciated). Given that the audio stream freezes (it does not just go to zero value) the only way (so far) I could do the detection is by taking recurrent (100 ms) snapshots of the signal and doing a delayed comparison using the pipe object.

It all works nicely now and the SR detection/switch happens in less than 1.5 seconds, which is perfectly fine for my application as many high-end DACs take even longer to switch (as I said before the delay can be set in many high-end audio streaming/file players to wait for the DAC to switch).

I will describe how typical playback switches SR on the device in a separate post.

Max Patch
Copy patch and select New From Clipboard in Max.

Source Audio's icon

Now that is good news, You have something which works,
refinements can be done later if needed.
As I am on the road at the time, I can't do any testing,
and what interests me in the first place is how fast info about SR change on the device gets reflected in system profiler.
Audio Stream Interrupt detection is just fine the way You did it, it coud
be done by other objects as well, but I don't see any reason to change it.

Edgar Choueiri's icon

As to "how fast info about SR change on the device gets reflected in system profiler", the change is reflected quite quickly - quicker than it takes to get the relevant data from the shell command so there is no need to delay sending the shell command once the streaming halt is detected (as is shown in my latest patch).

Matthieu Tibi's icon

Hello,

Is this patch supposed to work now ?
With Mac OS 10.13.6 ?

It doesn't seems to...

EDIT- I hadn't read the total explanation (the needed analogic input)
Sorry my bad...
I'll try again and I'll tell you !

Matthieu Tibi's icon

Well I tried with an analog input and it doesn't seems to work...
Did you try on a recent Mac OS ?
Thanks you very much !

EDIT- Or maybe this trick doesn't work with my sound card (Metric Halo 2882)...
But it seems to generate a silence too when I change the Sample Rate...

Matthieu Tibi's icon

- UPDATE -

Ok it works !
I took the 1st version your patch (the version with the 2sec triggering) and I changed the triggering with the silence method of the last version.
The combination of the two patches works.

Thank you very much !