thestk / rtaudio

A set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound, ASIO, and WASAPI) operating systems.
Other
1.49k stars 318 forks source link

24kHz output sample rate not supported #369

Closed KejPi closed 1 year ago

KejPi commented 2 years ago

Although RTAudio seems to support more sampling rates in general, it does not support 24kHz sample rate while on the same HW PortAudio does. This is an issue for DAB audio playback that requires support of 48kHz and 24kHz rates.

$ ./audioprobe.exe

RtAudio Version 6.0.0beta1

Compiled APIs:
0. WASAPI (wasapi)

API: WASAPI

Found 5 device(s) ...

Device Name = Headphones (Jabra Elite 85h Stereo)
Device Index = 0
Output Channels = 2
Input Channels = 0
Duplex Channels = 0
This is the default output device.
This is NOT the default input device.
Natively supported data formats:
  32-bit float
Supported sample rates = 4000 5512 8000 9600 11025 16000 22050 32000 44100 48000 88200 96000 176400 192000
Preferred sample rate = 44100
...
$ ./pa_devs.exe
PortAudio version: 0x00130700
Version text: 'PortAudio V19.7.0-devel, revision 147dd722548358763a8b649b3e4b41dfffbcfbb6'
Number of devices = 7
...
--------------------------------------- device #4
[ Default Output ]
Name                        = H
Host API                    = MME
Max inputs = 0, Max outputs = 2
Default low input latency   =   0.0900
Default low output latency  =   0.0900
Default high input latency  =   0.1800
Default high output latency =   0.1800
Default sample rate         = 44100.00
Supported standard sample rates
 for half-duplex 16 bit 2 channel output =
         8000.00,  9600.00, 11025.00, 12000.00,
        16000.00, 22050.00, 24000.00, 32000.00,
        44100.00, 48000.00, 88200.00, 96000.00,
        192000.00
...
garyscavone commented 2 years ago

All you probably need to do is add 24000 to the list of sample rates that are checked.

Cool-Coder174 commented 1 year ago

All you probably need to do is add 24000 to the list of sample rates that are checked.

Do you know which file the sample rates are checked? I can go in and take a crack at it.

garyscavone commented 1 year ago

Top of RtAudio.cpp

KejPi commented 1 year ago

I have tried to add 24000 to RtAudio.cpp in a3e9aa621e65a0744f125e9740d057a4d088e0e9 on MAC and it is even worse than on Win (it does not report support for 32k, 24k, 16k and others). The same is with 5.2.0:

$ ./pa_devs 
PortAudio version: 0x00130700
Version text: 'PortAudio V19.7.0-devel, revision 147dd722548358763a8b649b3e4b41dfffbcfbb6'
Number of devices = 2
--------------------------------------- device #0
[ Default Input ]
Name                        = Mikrofon MacBook Pro
Host API                    = Core Audio
Max inputs = 1, Max outputs = 0
Default low input latency   =   0.0529
Default low output latency  =   0.0100
Default high input latency  =   0.0622
Default high output latency =   0.1000
Default sample rate         = 48000.00
Supported standard sample rates
 for half-duplex 16 bit 1 channel input = 
     8000.00,  9600.00, 11025.00, 12000.00,
    16000.00, 22050.00, 24000.00, 32000.00,
    44100.00, 48000.00, 88200.00, 96000.00,
    192000.00
--------------------------------------- device #1
[ Default Output ]
Name                        = Reproduktory MacBook Pro
Host API                    = Core Audio
Max inputs = 0, Max outputs = 2
Default low input latency   =   0.0100
Default low output latency  =   0.0187
Default high input latency  =   0.1000
Default high output latency =   0.0280
Default sample rate         = 48000.00
Supported standard sample rates
 for half-duplex 16 bit 2 channel output = 
     8000.00,  9600.00, 11025.00, 12000.00,
    16000.00, 22050.00, 24000.00, 32000.00,
    44100.00, 48000.00, 88200.00, 96000.00,
    192000.00
----------------------------------------------
$ ./audioprobe 

RtAudio Version 6.0.0beta1

Compiled APIs:
0. CoreAudio (core)

API: CoreAudio

Found 2 device(s) ...

Device Name = Apple Inc.: Mikrofon MacBook Pro
Device Index = 0
Output Channels = 0
Input Channels = 1
Duplex Channels = 0
This is NOT the default output device.
This is the default input device.
Natively supported data formats:
  32-bit float
Supported sample rates = 44100 48000 88200 96000 
Preferred sample rate = 48000

Device Name = Apple Inc.: Reproduktory MacBook Pro
Device Index = 1
Output Channels = 2
Input Channels = 0
Duplex Channels = 0
This is the default output device.
This is NOT the default input device.
Natively supported data formats:
  32-bit float
Supported sample rates = 44100 48000 88200 96000 
Preferred sample rate = 48000
garyscavone commented 1 year ago

The sample rate querying code starts around line 1340 of RtAudio.cpp. You can check what it is getting from the system. I can see that there might be a problem with the else statement around line 1358 if nRanges > 1, since the later values will limit the set minimumRate and maximumRate values.

KejPi commented 1 year ago

Debug print (min - max):

nRanges = 4
0: 44100 - 44100
1: 48000 - 48000
2: 88200 - 88200
3: 96000 - 96000
nRanges = 4
0: 44100 - 44100
1: 48000 - 48000
2: 88200 - 88200
3: 96000 - 96000
garyscavone commented 1 year ago

In the probeDeviceOpen() function, it attempts to set whichever rate the user specifies, without attempting to query the supported rates. When I do that with something like 16000 for my built-in audio output, it fails with an indication that the rate is not supported. So, I am tending to believe the rate querying mechanism is correct. Is it possible that PortAudio is providing some sort of sample rate conversion? Or have you verified that you can actually use this device with PortAudio with a rate such as 16000?

KejPi commented 1 year ago

I have tried with 32kHz raw file that plays fine on Mac using PortAudio but it does not work with RtAudio:

./playraw 1 32000 audio.raw 
nRanges = 4
0: 44100 - 44100
1: 48000 - 48000
2: 88200 - 88200
3: 96000 - 96000
nRanges = 4
0: 44100 - 44100
1: 48000 - 48000
2: 88200 - 88200
3: 96000 - 96000

RtApiCore::probeDeviceOpen: system error (kAudioHardwareUnspecifiedError) setting sample rate for device (130).

RtApiCore::closeStream(): no open stream to close!

As far as I know there is no SRC in PortAudio but I may be wrong.

Cool-Coder174 commented 1 year ago

What does SRC stand for?

KejPi commented 1 year ago

SRC = Sample Rate Convertion

garyscavone commented 1 year ago

I did some investigating and PortAudio queries CoreAudio devices in the same way that RtAudio does. However, PortAudio has built-in sample rate conversion, so I believe that is why you are seeing a wider range of supported sample rates.

Cool-Coder174 commented 1 year ago

I can work on a function that converts the rate. I'll call More samples per second, so there's a higher the accuracy of the digitized sound. The Nyquist Theorem states that if you divide the sample rate by 2, the resulting number is the highest frequency that can be reproduced by the sample rate given. So, 48,000 samples / 2 = 24,000 Hz. Which should work.

KejPi commented 1 year ago

You would have to implement interpolation filter. That could be simple for 24kHz -> 48kHz conversion but for example 32kHz-> 48kHz conversion is more complicated (upsampling by 3 and then downsampling by 2). I think this issue can be closed because SRC implementation seems to be beyond the scope of the project.

Cool-Coder174 commented 1 year ago

I have a buddy who's an electrical engineer. I'll ask for his input, it should be some math functions we can plug and play. I'll send an update to see if it's gonna be more complicated than it seems.

KejPi commented 1 year ago

PortAudio FAQ explicitly states this (http://www.portaudio.com/faq.html):

How do I get audio at a sample rate that is not supported by PortAudio? PortAudio will use whatever sample rates are available on the host. PortAudio does not provide any additional sample rate conversion capability...

So it seems there is no SRC capability and still it works.

garyscavone commented 1 year ago

I'm closing this. I am not completely opposed to having someone add SRC to RtAudio but my feeling is that it would be better to use a library specifically designed for that.