0

I have a rather different question. So I'm using Matlab on a Linux Gentoo machine. I got a few Asus Xonar STX soundcards, and I'm trying to use them as sensitive audio frequency analyzer using the PlayRec non blocking audio IO package.

Now I know that Matlab will say if you try to use the audiorecorder function, and specify 24 bits in linux, it will tell you that 24bit is only supported in Windows. However the ALSA literature does not imply that this is a limitation of the operating system or of ALSA itself, and as a matter of fact Alsa seems to allow you to specify a 24 bit PCM device. And PlayRec uses PortAudio, which then uses Alsa on Linux systems.

Now this is all well and good, and Playrec doesn't seem to have a means of specifying the bit depth, just the sample rate. I have run many tests and know what the transfer function of my soundcard is (floating point return value to input Voltage conversion ratio), and I know my peak voltage is 3V, and my noise is around 100uV. This gives me 20*log10(3/100e-6) = 91dB. Which is closer to what I expect to see from 16 bits and not from 24.

My real question is this: Is there some way of verifying that I am in fact getting 24 bits in my captured signal?

And if I am not, is there some inherent limitation of ALSA or Matlab which is restricting me to only 16-bit data from sound capture devices, even when using 3rd party program to gather that data.

dynamphorous
  • 739
  • 1
  • 9
  • 20

2 Answers2

1

If you observe the data that playrec is putting out through playrec('getRec', ...), you'll see that it always is single-precision floating point (tested on Windows, MATLAB R2013b, most current Playrec). (you can verify it yourself after recording a single page with Playrec and looking in the workspace window of the IDE or by running whos('<variable_name_of_page>') at the command line.

If you look at Line 50 of pa_dll_playrec.h, you'll see that single-precision is chosen by definition:

/* Format to be used for samples with PortAudio = 32bit */
typedef float SAMPLE;

Unfortunately, this does not completely answer the question of exact sample precision, because the PortAudio lib converts samples from the APIs varying in format into the defined one. So if you want to know, what precision you're actually getting, I'd suggest a very pragmatic solution: looking at the mantissa of the 32-bit floating sample values. A simple fprintf('%+.32f\n', data) should suffice to find out how many decimal places are actually used.


Edit: I just realized I got it wrong. But here's the trick: Record audio off of an empty channel of your audio device. Plot the recorded data and zoom into the noise floor. If you're just getting plain zeros, the device is probably not activated properly (or has a too good signal/noise ratio). Try an external interface and/or turn up the gain a little bit). Depending on the actual bit resolution of the recorded data, you'll see quantization steps in the samples. Depending on the bit-depth originally used by the quantizer, those steps are bigger or smaller. Below you'll see the comparison between 16-bit (left) and 24-bit (right) of to seperately recorded blocks, from the same audio device, only that I used PortAudio's WASAPI API (on Windows, obviously) on the left and ASIO on the right:

Comparison of sample quantization of 16-bit (left) and 24-bit (right) audio

The difference is quite obvious: at these very low levels, 16-bit only allows three values, while 24-bit has much finer stepping. So this should be a sufficient answer to your question on how to determine the real bitdepth and if your signal is recorded at 24-bit. If there are sample steps smaller than 2^-15, the odds are pretty good.

Looking in to this topic made me realize that it very much depends on the API of the currently chosen recording device, which bit-depth the quantization actually happens at. ASIO seems to always use 24-bit, while for example WASAPI falls back to 16-bit.

Jan W
  • 143
  • 1
  • 10
  • But just because you know how many bits in the FP number are being used does not really help you that much right? Unless you had a means of manipulating one LSB on the A/D. Then you could see how that affected the floating point value with respect to full scale and determine the bits of precision. As long as its a black box doing the A/D (in integer values)->single precision floating point without knowing the transfer function, there is no way to determine what bit resolution you are getting from the soundcard A/D. – dynamphorous Mar 31 '14 at 18:50
  • @dynamphorous You are right. I updated my answer above. – Jan W Apr 01 '14 at 12:09
  • I'll grant you that this is one possible way. But I've never seen a soundcard that does not have a noise floor substantially above the LSB of the quantizer. So I guess I could look for the smallest possible set of steps across my white spectrum and try to assume that is my minimum quantized step. But it still feels kludgy to me. I will mark this as the answer, as I can tell you did put a considerable amount of thought into it, and it is a reasonable answer if the Johnson noise is below your LSB of your quantizer! – dynamphorous Apr 01 '14 at 16:26
0

If you can store that signal as a wav file, run a file command on the wav from the command line in linux. Something like:
file x.wav will give you sampling rate and bits that the file was encoded at. The output is usually something like: 16 bit, 16000Hz etc.

Sriram
  • 10,298
  • 21
  • 83
  • 136
  • Well I like how you are thinking, the only problem is that by the time its read into Matlab, the signal becomes 2 channels of single precision floating point numbers. So writing it to a wav file, using wavwrite, or some other function seems like it will then simply convert the file to the bit depth and sampling rate you specify it at, rather than retain the characteristics it had when it first came out of the A/D. That is why I tied doing my own S/N computation, since the Xonar STX SHOULD have 118dB of dynamic range (which they prove in the manual with audio precision), and I'm getting 91dB. – dynamphorous Jun 03 '11 at 15:31