[haiku] HDA audio driver - more testing, possible patch?
- From: "Cyan" <cyanh256@xxxxxxxxxxxx>
- To: haiku@xxxxxxxxxxxxx
- Date: Mon, 11 May 2009 06:59:32 +0100 BST
Hi guys,
Sorry it's taken so long to get around to doing this; the last tests
I did were during the winter. However I've recently had the chance
to give the HDA drivers another thrashing, so I thought I'd report
back on what I found.
First up, thanks to everyone who's put in the effort on this driver
so far -- by and large, for audio output things are working really
very well!
The rest of this might sound pretty critical; that isn't my intent
at all, but I have run into some quite strange issues in some areas
which will require a lengthy explanation to describe accurately.
===============
Test conditions
===============
Chipset: Intel P965 with ICH8R southbridge.
HDA codec chip: Realtek ALC882
Audio recording software: Haiku sound recorder, also a few other
applications for double-checking results.
Test platform: BeOS R5 with the multi-audio-addon, Haiku media kit
mixer, and HDA drivers. The multi-audio-addon was quite an old
version (let me know if this is a problem), but I used a very recent
version of the media kit mixer and HDA driver -- downloaded 3rd May
2009.
IMPORTANT NOTE: The HDA hardware on this system has never been tested
under any other operating system. Therefore there's a remote
possibility there could be undiscovered hardware faults.
=======================================================
Audio output performance - sample rate, possible patch?
=======================================================
The default sample rate of the driver is 192kHz. Because the media
kit mixer currently only supports "drop-sample" resampling, this
results in very poor audio quality when playing back most audio files
(which have a sample rate of 44.1kHz).
This is to be expected under these conditions and isn't a fault in
the software. However, in order to provide acceptable sound quality,
I modified the driver to allow the sample rate to be varied for
testing.
I used two methods to change the sample rate, both of which gave
identical results -- one is to comment out the "unwanted" higher
sample rates around lines 241-251 in hda_codec.cpp. The other method
was to insert the lines:
data->input_rates = B_SR_44100;
data->output_rates = B_SR_44100;
after line 108 in hda_multi_audio.cpp. Both are nasty temporary
hacks, but until the media kit mixer offers some way for the user
to pick a sample rate in the GUI, I can't really see any other way
of doing it?
(Side note: Changing data->input_rates seemed to have absolutely
no effect on anything. Changing data->output_rates affected both
input and output rates simultaneously. Is this a bug?
Also it's worth mentioning that the ADCs on this codec chip can
only operate at 96kHz maximum, so mismatched input and output rates
are a necessity if the DAC is to run at the full 192kHz.)
In any case, after the adjustment was made, a new problem surfaced --
there was an audible discontinuity at the end of every audio buffer.
This problem only occurred at 44.1kHz -- it did not occur at 48kHz,
96kHz or 192kHz.
The problem seems to be related to the "offset" calculation, around
line 550 in hda_controller.cpp. Specifically "offset" ends up being
an "odd" length (not a whole frame) at 44.1kHz because of the
division by 48000.
I implemented a work-around as follows -- I've no idea if this is
correct, but it seems to fix the problem at 44.1kHz, and didn't
interfere with the other rates:
// Stream interrupts seem to arrive too early on most HDA
// so we adjust buffer descriptors to take this into account
uint32 offset;
if( format & FORMAT_44_1_BASE_RATE ) {
offset = (stream->sample_size * stream->num_channels) * stream-
>rate / 44100;
} else {
offset = (stream->sample_size * stream->num_channels) * stream-
>rate / 48000;
}
With all sample rates now working correctly, I did several hours of
listening tests with a variety of source material. The sample rate
of the driver was adjusted to match the source material in all cases
to avoid resampling.
I must say, I'm very impressed by the audio quality! There's a huge
improvement in clarity and transient detail over the SB Live,
possibly due to the elimination of resampling (the SB Live resamples
everything to 48kHz).
No clicks, crackles, discontinuities or any other artifacts were
encountered at all during testing -- just exceptionally clean audio.
System stability, as reported previously, was flawless. No media kit
mishaps or KDLs.
Audio output appears simultaneously at all analogue output jacks
at full line level -- so no more attenuation problems.
The bulk of the listening tests were performed with the "rear out"
jack, because it provides a slightly improved analogue audio path
(the elimination of two electrolytic capacitors), but the other
jacks, including the "front out" jack still provide excellent audio
performance.
If there's one complaint I have about sound quality, it would be
that there seems to be a very slight lack of weight at the bottom-end
compared to the SB Live. However this might be an illusion caused by
the dramatic increase in treble detail. I did wonder if some kind of
high-pass filter was engaged, but after doing some A/B testing, I'm
pretty sure the effect is way too small to be a deliberate filter at
work, maybe even non-existent.
===========
Buffer size
===========
One thing I noticed was that everything was very unresponsive --
there was a disconcerting lag time between clicking play in
MediaPlayer and the music starting, etc.
I hacked this by modifying the values in the
default_buffer_length_for_rate() function in hda_multi_audio.cpp.
For the time being I'm using a size of 512 frames for sample rates
8kHz to 48kHz, 1024 frames up to 96kHz, and 2048 frames beyond that.
By comparison to other platforms, this is still quite a high latency
figure -- 12ms per buffer -- but it's fast enough for casual use.
Considering this is supposed to be a "Media OS", of sorts, would it
be okay to change the current values (2048 frames at 44.1k: a latency
of 46ms per buffer!) at least down to 512 frames?
I think it should be okay even on slower hardware -- I used
512-frame buffers for years on my old 233MHz K6 system; it's still
quite a large buffer compared to the 32-frame buffers I've been
using more recently.
======
S/PDIF
======
This motherboard doesn't have a S/PDIF input socket, but it does
have a S/PDIF output socket (both Toslink-optical and coaxial).
The codec chip has pins for both input and output (but the pitch is
too fine to easily solder to the input unfortunately).
I hooked the S/PDIF coaxial output up to another digital audio
device (PCM), but I didn't manage to get a signal. Also, the Toslink
output remained dark (no red LED glowing). I tested at 44.1kHz,
48kHz, 96kHz and 192kHz -- no change.
Although I haven't checked with a scope yet, it's looking like
there's no signal coming out of the S/PDIF ports. Also, I didn't see
any mention of S/PDIF in the HDA mixer, even although the codec chip
is supposed to support the feature.
I don't really need S/PDIF yet, but it made me wonder -- is this
normal? If S/PDIF isn't actually implemented yet, no problem.
===============
Analogue inputs
===============
This is where I had most of the trouble during testing --
I couldn't really get a satisfactory signal recorded under any
conditions.
There are a lot of variables, and at least two separate problems
which seem to be affecting me, so unfortunately this is going to be
pretty long. I hope it's not too unreadable!
Software used was the Haiku sound recorder (for its 24-bit support),
but I did quick tests with several other 24-bit-supporting
applications, all with identical results.
===================================
Input gain, clipping, and DC offset
===================================
I think the left and right input channels may be flipped. Increasing
the left fader in the input mixer causes the right meter in the
recording application to increase and vice-versa. Also it looks like
applying a signal to the left input causes a signal to appear on
the right channel of the recording (suggesting it's the channels
which are flipped, not the mixer faders), but I can't say for 100%
certain -- my wiring might be to blame.
The outputs, however, are definitely correct.
The left channel (right physical input) is very much hotter than the
right channel. This seems to occur with both the rear-panel
"line input" jack, and the CD header on the motherboard. I couldn't
test the microphone inputs with the equipment on-hand.
This channel also has a rather high negative DC offset (~25% full
scale), but that might just be due to excessive gain.
When the right channel (left physical input) is clipped, due to
overdriving the input or increasing the codec mixer fader too far,
normal "flat-topped" clipping occurs which sounds like ordinary
distortion.
However when the left channel clips (right physical input -- the one
with the offset and high-gain problem), a completely different
behaviour is seen. Instead of "flat-topping", the signal wraps
around to the opposite polarity, exactly like integer overflow.
Increase the gain further, and it wraps around further -- eventually
ending up with solid noise.
This problem is specifically isolated to the left channel --
no matter how hard I drive the right channel, I can't get it to
behave in the same way.
===========================
Inputs, mux and noise floor
===========================
There are three stereo input faders in the "input" section of the
HDA mixer (presumably corresponding to the three stereo ADCs in
the codec chip?), all of which are labeled "Line".
Only the first stereo fader and its mute control have any effect --
the last two stereo faders and mute controls don't appear to have
any effect on the recording at all.
Judging by the very high noise floor of the recordings, it appears
that all analogue inputs may be routed to the ADC simultaneously.
I injected a signal into the CD header on the motherboard and a
different signal via the rear-panel "line in" jack, and both were
mixed together and recorded (again, only the first stereo mixer fader
had any effect).
I couldn't test the microphone inputs, but as microphone inputs are
usually pretty noisy, I wouldn't be surprised if those were
contributing to some of the noise here.
The "stereo mix" itself (output from the soundcard) does not appear
to be routed to the ADC -- not a problem; just an observation.
If this all-input behaviour is normal, would it be difficult to
supply checkboxes in the mixer to mute individual physical inputs?
Looking at the datasheet, it seems that the codec chip apparently has
some kind of muting/mux system before the ADCs for this purpose.
=================
Recording quality
=================
After adjusting the levels to obtain a recording of reasonable
level, the recording quality did not seem to be very good. Apart
from the previously-mentioned noise floor, there was a distinct
loss of high frequency detail. Recording sample rate was 48kHz
(discussed later), so there shouldn't have been any noticeable loss.
Maybe this is related to the unusual gain settings required to
obtain an acceptable recording? Or perhaps it has something to do
with sample rates and ADC anti-aliasing filters?
I tested a friend's machine, which has identical audio hardware,
and runs Windows. The gain on the line input was very high, but
it was the same on both channels, and did not seem to exhibit
"wrapping" behaviour. Moreover, the recording was almost
indistinguishable from the original, so the codec chip itself
should at least be capable of this level of performance (assuming
the one in my machine isn't broken -- see the earlier warning).
There weren't any buffer-related problems with recording though --
as long as it was kept below clipping, the audio was click- and
crackle-free.
=================
Input sample rate
=================
This one is very strange! As mentioned earlier, changing
input_rates in the driver had no effect on anything, while
output_rates affected both input and output together.
By default (unmodified driver), the output is at 192kHz, and the
input is also at 192kHz. This is very interesting, because the ADC
isn't even capable of this rate!
Making a recording under these conditions and playing it back
results in a 4x speed increase. In other words, the recording is
actually happening at 48kHz, but 192kHz is being reported to
recording applications.
Lowering the output sample rate to 96kHz has no effect on the actual
recording rate (it still happens at 48kHz), but because the reported
rate is now lower, the speedup is only 2x.
Lowering the output sample rate to 48kHz, unfortunately, does not
restore natural speed -- instead, no audio buffers arrive from
the recording side, rendering recording impossible.
Selecting 44.1kHz also has the same effect.
========================================
Attempts to change the input sample rate
========================================
Ideally both the output and input should be running at 44.1kHz
to allow the use of industry-standard sample rates when recording
and playing back.
Because of this, I set about trying to pin down exactly why
recording stops when 48kHz or 44.1kHz are selected for output,
and why the recording always takes place at 48kHz.
I can't say I've had much luck trying to answer this one, although
I'm still experimenting. However I did find the following:
In hda_controller.cpp, there's an array of sample rates, kRates[],
used to convert numerical sample rates into hardware register
rates, etc. The "hardware rate" seems to consist of three
parameters -- base rate (44100 or 48000), multiplier, and divider.
Whenever "multiplier" is set to "2", recording works (albeit at
48kHz). I think it must also work when set to "4", because recording
works with 192kHz output selected, but my notes are a bit sketchy
here.
However, when "multiplier" is set to "1", recording stops working;
no buffers arrive.
I managed to get recording and playback operating at 48kHz by
selecting a rate with the following settings:
Base = 48000
Multiplier = 2
Divider = 2
Because "multiplier" is 2, recording works (at 48kHz as usual), and
because "divider" is 2, the overall output rate is lowered back
to 48kHz.
I tried to get this to work for 44.1kHz (base=44100, multiplier=2,
divider=2), but unfortunately that didn't work. No recording buffers
arrived, and moreover, the output sound quality was completely ruined
(surprising, because it seemed okay at 48kHz using the same trick).
Overall I'm pretty confused about these results! It looks like
there's three main issues with the recording sample rate:
1) Reported input rate follows the output rate, regardless of the
actual rate. (hence the cause of the speedup)
Could this be an external problem, such as the multi-audio-addon
or the R5 media kit?
2) Recording doesn't work when multiplier is "1", and the trick of
selecting "2" with a divider of "2" won't work if the base is
44100Hz.
3) The ADC is always clocked at 48kHz regardless of the selected
sample rate, or the base, multiplier or divider settings.
The codec chip datasheet says that the ADC can be clocked at
44.1kHz, 48kHz, or 96kHz, but the ADC clock rate does not appear
to be changed by the driver.
Any pointers about how to fix any of these issues would be very,
very much appreciated!
I can do some more tests if anyone's got any suggestions, and/or
provide some example recordings. Would serial debug output in this
case be of any use?
Thanks!
Other related posts: