Get the sample rate of the default playback audio device

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
myQwil
Prole
Posts: 13
Joined: Mon Nov 23, 2020 7:19 pm

Get the sample rate of the default playback audio device

Post by myQwil »

I'm currently working on some real-time audio generation and I want the sample rate to be whatever the playback device's sample rate happens to be, so as to prevent resampling from occurring. I want to avoid hard-coding the sample rate to an arbitrary amount like 44100 or 48000. Is there a way to retrieve this value?
breuning
Prole
Posts: 3
Joined: Mon Nov 23, 2020 2:52 pm

Re: Get the sample rate of the default playback audio device

Post by breuning »

Depends on the OS, I think you can find audio device sample rate in the Windows Registry

For me (Win10 x64) it is:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render
The subfolders are named after all the audio device GUID, the active one will have a DeviceState 0x0000001 word

In HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render\{DEVICEGUID}\Properties
You'll find the values "{f19f064d-082c-4e27-bc73-6882a1bb8e4c},0" and "{e4870e26-3cc5-4cd2-ba46-ca0a9a70ed04},0", which according to my search control the sampling rate. They contain binary data and I have no idea what to make of that.

I also found this: https://stackoverflow.com/questions/262 ... o-playback
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Get the sample rate of the default playback audio device

Post by zorg »

There might be a cleaner (and OS-independent) solution;

Unfortunately i have not found an online function list that OpenALSoft implements (which löve uses), so i can't give exact examples at the moment, but if there's a method to query the currently used device's sampling rate, then you can use the LuaJIT FFI (which löve has) to declare that method, and call it from lua.

Code example missing due to above reason. https://github.com/kcat/openal-soft/wik ... troduction
Edit: Maybe something like this, untested:

Code: Select all

local ffi = require 'ffi'
local liblove = (ffi.os == "Windows") and ffi.load('love') or ffi.C
rffi.cdef[[
typedef struct ALCcontext ALCcontext;
typedef struct ALCdevice ALCdevice;
typedef int ALCenum;
typedef int ALCsizei;
typedef int ALCint;
typedef void ALCvoid;

void alcGetIntegerv(
    ALCdevice* device,
    ALCenum param,
    ALCsizei size,
    ALCint* data
);
ALCcontext* alcGetCurrentContext(ALCvoid);
ALCdevice* alcGetContextsDevice(ALCcontext *context);
]]

srate = ffi.new('ALCint',1)
local ALC_FREQUENCY = 0x1007
local context = liblove.alcGetCurrentContext()
local device = liblove.alcGetContextsDevice(context)
liblove.alcGetIntegerv(device, ALC_FREQUENCY, srate)
print(tostring(srate[1]))

Do note though, that resampling shouldn't cause too many issues in most cases anyway, although i do recall some people who did say otherwise. :3
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
myQwil
Prole
Posts: 13
Joined: Mon Nov 23, 2020 7:19 pm

Re: Get the sample rate of the default playback audio device

Post by myQwil »

That works, thank you :)
I needed to make a slight change to get it working:

Code: Select all

	buf = Buffer(4)
	local ALC_FREQUENCY = 0x1007
	local context = liblove.alcGetCurrentContext()
	local device = liblove.alcGetContextsDevice(context)
	liblove.alcGetIntegerv(device, ALC_FREQUENCY, 1, buf:ptr())
	print(buf:at(0))
Buffer is a custom class that's part of the C library I'm currently working on. It's basically just a thin wrapper around a std::vector that I was using as a fallback for test case scenarios. Just for the sake of reference, it looks like this:

Code: Select all

	
class Buffer {
	vector<unsigned char> data;
public:
	Buffer   (size_t n)   { data.reserve(n);        }
	~Buffer  ()           { data.shrink_to_fit();   }
	void *ptr(size_t i=0) { return &data[i];        }
	int   at (size_t i=0) { return *(int*)&data[i]; }
};
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Get the sample rate of the default playback audio device

Post by zorg »

I see, glad that it worked. :3

Technically, here, alcGetIntegerv just puts an integer containing the device's sampling rate into the memory area pointed to by the last parameter, so you can store it in any var, if you have a pointer to its memory location; me typedef-ing and using ALCInt was just for simplicity's sake. (And it should work with that type as well, i probably just wrote it wrong)

I'll touch up my snippet tomorrow, since i'll probably consider using this as well, in my stuff.

Just out of curiosity, what kind of thing are you making that uses real-time audio synthesis? a game, or a composing app, or...?
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
myQwil
Prole
Posts: 13
Joined: Mon Nov 23, 2020 7:19 pm

Re: Get the sample rate of the default playback audio device

Post by myQwil »

LuaPd https://github.com/myQwil/luapd
It's a spiritual successor to love-pd-audio https://github.com/ghoulsblade/love-pd-audio
That project was updated 7 or 8 years ago so it's been in need of an update.

So far I've only worked on it in a Linux environment. At some point I hope to build it for Windows and Mac as well.
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Get the sample rate of the default playback audio device

Post by zorg »

Neat, i might include it in my composing sw whenever both gets to that state. :3
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
myQwil
Prole
Posts: 13
Joined: Mon Nov 23, 2020 7:19 pm

Re: Get the sample rate of the default playback audio device

Post by myQwil »

I got it to work without the Buffer class.
ffi.new needs to be written as "ALCint[1]"
Also, the library that Windows users need to load is "OpenAL32"
Here's the full solution.

samplerate.lua:

Code: Select all

local ffi = require('ffi')
local openal = (ffi.os == 'Windows') and ffi.load('OpenAL32') or ffi.C
ffi.cdef[[
typedef struct ALCcontext ALCcontext;
typedef struct ALCdevice  ALCdevice;
typedef int    ALCenum;
typedef int    ALCsizei;
typedef int    ALCint;
typedef void   ALCvoid;

void alcGetIntegerv(
	 ALCdevice *device
	,ALCenum    param
	,ALCsizei   size
	,ALCint    *data
);

ALCcontext *alcGetCurrentContext(ALCvoid);
ALCdevice  *alcGetContextsDevice(ALCcontext *context);
]]

local srate = ffi.new('ALCint[1]')
local ALC_FREQUENCY = 0x1007
local context = openal.alcGetCurrentContext()
local device  = openal.alcGetContextsDevice(context)
openal.alcGetIntegerv(device, ALC_FREQUENCY, 1, srate)

return srate[0]
Implement with:

Code: Select all

samplerate = require('samplerate')
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 231 guests