diff mbox

On non-rewindability of resamplers

Message ID CAN8cciaAazGX4HZet+UgbWGN4iOk9hknCjYTtdwD+k+ptqakOw@mail.gmail.com (mailing list archive)
State Changes Requested
Delegated to: Takashi Iwai
Headers show

Commit Message

Raymond Yau May 24, 2014, 5:10 a.m. UTC
>
>>
>> The appl_ptr  can be placed in any position in the ring buffer for the
>> application to write data but the sound card fetch data from this ring
>> buffer sequentially, however snd_pcm_write() assume the maximum distance
>> between appl_ptr and hwptr is only one buffer
>>
>>
https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/hda/hda_intel.c?id=2ae66c26550cd94b0e2606a9275eb0ab7070ad0e
>>
>> Do you mean hwptr does not decrease by one period when you use arbitrary
>> period sizes for hda-Intel  ?
>
>
> I cannot comment on this commit. But "snd_hda_intel.align_buffer_size=1"
indeed existed on my kernel command line (for no good reason now - so
removed), and I don't use a strange period size.

3.6.2 Buffer Descriptor List

There must be at least two entries in the list, with a maximum of 256
entries.

3.6.3 Buffer Descriptor List Entry

the buffers described by BDLE must start on 128 bytes boundary

refer to azx_setup_periods, if one period  represent one BDLE ,  the
buffers described by two periods must start on 128 bytes boundary

with default prealloc_max = 64,  pulseaudio are forced to use maximum
buffer size / period size which are also 128 bytes aligned

 when you specifiy prealloc_max = 4096,  one second 48000Hz is also aligned
to 128 bytes boundary but one second 44100 Hz is not

>
>
> Still, the bug (negative reported rewindable amount) also exists without
align_buffer_size=1.
>
>
>>
>> e.g.  48 samples (192 bytes) when using 1ms period time and  stereo
>> instead of 4 channels
>
>
> Not tested.

The implementation dependent FIFO Size  affect the number of the bytes that
could be fetched by the controller at one time.

3.3.40 Offset 90: {IOB}SDnFIFOS – Input/Output/Bidirectional Stream
Descriptor n FIFO Size

FIFO Size (FIFOS): Indicates the maximum number of bytes that could be
fetched by the controller at one time. This is the maximum number of bytes
that may have been DMA?d into memory but not yet transmitted on the link,
and is also the maximum possible value that the LPIB count will increase by
at one time.

>
>
>
>>
>> you program seen hang when using pulse plugin
>
>
> I am not interested in any more rewind-related bug reports for the pulse
plugin. This particular bug will be fixed, together with many others, by
always returning 0 from the .rewindable callback for ioplug if mmap_rw is
false.

why do you assume rewind is supported if mmap_rw is true ? any example

>
>
>>
>>  >
>>  >
>>  > How do I test this? Could you please post some userspace test code or
>> a kernel patch, together with the instructions?
>>  >
>>
>> Attach the patch to dump the values of the audio function group
capability
>
>
> There was no attachment.
>
>
>> There are three cases
>>
>> 1) delay in analog output > delay in digital output  e.g, idt codecs
>> 2) delay in analog output < delay in digital output e.g. adi codecs
>> 3) no delay in audio widgets ,  digital output and analog output have no
>> delay difference when output delay in audio  function group is non zero ?
>
>
> Yes, that's logical.
>
>
>>
>> It is unlikely for ordinary user to measure the delay without using
>> oscilloscope since the Analog speaker and digital receiver also have
delay
>
>
> Correct. Also, while delay in analog speakers can be often rightfully
assumed to be 0 samples, this is not the case for digital receivers. In
other words, the delay on the digital path is in fact unknown.

If  13 samples delay in analog output is due to the five bands equalizer in
IDT codecs, the headphone should not has same delay since equalizer in not
present in the headphone path, may need to implement multi-channel capture
to find out any delay between headphone and line out

Comments

Alexander Patrakov May 24, 2014, 7:31 a.m. UTC | #1
24.05.2014 11:10, Raymond Yau wrote:
>  >
>  >>
>  >> The appl_ptr  can be placed in any position in the ring buffer for the
>  >> application to write data but the sound card fetch data from this ring
>  >> buffer sequentially, however snd_pcm_write() assume the maximum distance
>  >> between appl_ptr and hwptr is only one buffer
>  >>
>  >>
> https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/hda/hda_intel.c?id=2ae66c26550cd94b0e2606a9275eb0ab7070ad0e
>  >>
>  >> Do you mean hwptr does not decrease by one period when you use arbitrary
>  >> period sizes for hda-Intel  ?
>  >
>  >
>  > I cannot comment on this commit. But
> "snd_hda_intel.align_buffer_size=1" indeed existed on my kernel command
> line (for no good reason now - so removed), and I don't use a strange
> period size.
>
> 3.6.2 Buffer Descriptor List
>
> There must be at least two entries in the list, with a maximum of 256
> entries.
>
> 3.6.3 Buffer Descriptor List Entry
>
> the buffers described by BDLE must start on 128 bytes boundary
>
> refer to azx_setup_periods, if one period  represent one BDLE ,  the
> buffers described by two periods must start on 128 bytes boundary
>
> with default prealloc_max = 64,  pulseaudio are forced to use maximum
> buffer size / period size which are also 128 bytes aligned
>
>   when you specifiy prealloc_max = 4096,  one second 48000Hz is also
> aligned to 128 bytes boundary but one second 44100 Hz is not

I am not sure I can continue this line of discussion usefully, because I 
don't understand the purpose. If this is an attempt to understand the 
granularity of hw_ptr (which would indeed be useful), then I cannot 
help. If this is a report of a possible non-rewind-related bug in 
PulseAudio, please start a new thread.

>
>  >
>  >
>  > Still, the bug (negative reported rewindable amount) also exists
> without align_buffer_size=1.
>  >
>  >
>  >>
>  >> e.g.  48 samples (192 bytes) when using 1ms period time and  stereo
>  >> instead of 4 channels
>  >
>  >
>  > Not tested.
>
> The implementation dependent FIFO Size  affect the number of the bytes
> that could be fetched by the controller at one time.
>
> 3.3.40 Offset 90: {IOB}SDnFIFOS – Input/Output/Bidirectional Stream
> Descriptor n FIFO Size
>
> FIFO Size (FIFOS): Indicates the maximum number of bytes that could be
> fetched by the controller at one time. This is the maximum number of
> bytes that may have been DMA?d into memory but not yet transmitted on
> the link, and is also the maximum possible value that the LPIB count
> will increase by at one time.

OK, this looks very relevant. Is this the same value as would be 
returned by snd_pcm_hw_params_get_fifo_size()? If not, why, and how do I 
view this value?

>
>  >
>  >
>  >
>  >>
>  >> you program seen hang when using pulse plugin
>  >
>  >
>  > I am not interested in any more rewind-related bug reports for the
> pulse plugin. This particular bug will be fixed, together with many
> others, by always returning 0 from the .rewindable callback for ioplug
> if mmap_rw is false.
>
> why do you assume rewind is supported if mmap_rw is true ? any example

The example is jack plugin (in fact, the only plugin known to me that 
sets mmap_rw to true). It does support rewinds, as I have already 
explained and tested. It works because the periodic transfer of samples 
to JACK is done in a separate realtime thread. Application writes 
samples into a circular mmap-style buffer, ioplug uses the generic 
mmap-style functions for rewinding that buffer, and the thread reads 
from it, just as a real sound card would do. So an application can 
safely rewind any samples that it has written to that buffer but that 
the thread hasn't yet copied to JACK.

Of course it is possible to write a buggy ioplug-based plugin that 
doesn't really support rewinds even though it sets mmap_rw to true (e.g. 
by implementing the transfer callback - the real problem here, if my 
understanding is correct, is that it has no access to the application 
pointer). But in reality I don't know any such plugin.

Still, you are right, and a better idea would be to say: an ioplug-based 
plugin can be assumed to support rewinds if and only if it sets mmap_rw 
to true and does not provide a transfer callback. I say so because such 
architecture forces the plugin to use a low-latency thread to do the 
actual transfers and also avoids the need to care about the application 
pointer altogether. In other words, such plugin implements an 
architecture similar to one of a real DMA-based sound card.

>
>  >
>  >
>  >>
>  >>  >
>  >>  >
>  >>  > How do I test this? Could you please post some userspace test code or
>  >> a kernel patch, together with the instructions?
>  >>  >
>  >>
>  >> Attach the patch to dump the values of the audio function group
> capability
>  >
>  >
>  > There was no attachment.
>  >
>  >
>  >> There are three cases
>  >>
>  >> 1) delay in analog output > delay in digital output  e.g, idt codecs
>  >> 2) delay in analog output < delay in digital output e.g. adi codecs
>  >> 3) no delay in audio widgets ,  digital output and analog output have no
>  >> delay difference when output delay in audio  function group is non
> zero ?
>  >
>  >
>  > Yes, that's logical.
>  >
>  >
>  >>
>  >> It is unlikely for ordinary user to measure the delay without using
>  >> oscilloscope since the Analog speaker and digital receiver also have
> delay
>  >
>  >
>  > Correct. Also, while delay in analog speakers can be often rightfully
> assumed to be 0 samples, this is not the case for digital receivers. In
> other words, the delay on the digital path is in fact unknown.
>
> If  13 samples delay in analog output is due to the five bands equalizer
> in IDT codecs, the headphone should not has same delay since equalizer
> in not present in the headphone path, may need to implement
> multi-channel capture to find out any delay between headphone and line out
>

For me an easier way would be to go to the nearest electronic components 
shop and buy three 3.5mm jacks and some wires to do a non-standard 
interconnection. You only need to capture two channels anyway: one from 
headphones and one from line output.
Raymond Yau May 30, 2014, 12:59 a.m. UTC | #2
>>  >>
>>  >> The appl_ptr  can be placed in any position in the ring buffer for
the
>>  >> application to write data but the sound card fetch data from this
ring
>>  >> buffer sequentially, however snd_pcm_write() assume the maximum
distance
>>  >> between appl_ptr and hwptr is only one buffer
>>  >>
>>  >>
>>
https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/hda/hda_intel.c?id=2ae66c26550cd94b0e2606a9275eb0ab7070ad0e
>>  >>
>>  >> Do you mean hwptr does not decrease by one period when you use
arbitrary
>>  >> period sizes for hda-Intel  ?
>>  >
>>  >
>>  > I cannot comment on this commit. But
>> "snd_hda_intel.align_buffer_size=1" indeed existed on my kernel command
>> line (for no good reason now - so removed), and I don't use a strange
>> period size.
Loaded sound module options
!!--------------------------

!!Module: snd_hda_intel
align_buffer_size : -1
bdl_pos_adj :
32,32,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1

Why only one entry for align_buffer_size if it is specific to hda
controller when the computer have two hda controllers ?

https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/1324426

https://launchpadlibrarian.net/176540072/Symptom_PulseAudioLog.txt

May 29 06:57:49 Lihkin pulseaudio[1874]: [alsa-sink-92HD81B1X5 Analog]
alsa-sink.c: ALSA woke us up to write new data to the device, but there was
actually nothing to write!

Most likely this is a bug in the ALSA driver 'snd_hda_intel'. Please report
this issue to the ALSA developers.
We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail()
returned 0 or another value < min_avail.

snd_pcm_avail() returned a value that is exceptionally large: 181132 bytes
(1026 ms).
Most likely this is a bug in the ALSA driver 'snd_hda_intel'. Please report
this issue to the ALSA developers.

Seem pulseaudio can use strange period size

May 29 11:36:52 Lihkin pulseaudio[1306]: [alsa-sink-HDMI 0] alsa-util.c:
Its setup is:
  stream       : PLAYBACK
   access       : MMAP_INTERLEAVED
   format       : S16_LE
   subformat    : STD
   channels     : 2
   rate         : 44100
   exact rate   : 44100 (44100/1)
   msbits       : 16
   buffer_size  : 3520
   period_size  : 352
   period_time  : 7981
   tstamp_mode  : ENABLE
   period_step  : 1
   avail_min    : 352
   period_event : 1
   start_threshold  : -1
   stop_threshold   : 7926335344172072960
   silence_threshold: 0
   silence_size : 0
   boundary     : 7926335344172072960
   appl_ptr     : 2916662
   hw_ptr       : 2958425

start_threshold  : -1

This mean the playback will automatically start if pulseaudio write any
audio data instead of start after write  pre buffer

Try aplay with  any arbitrary period size/period time and xrun_debug ,
check whether hw_ptr is updated on every period update in the system log

aplay  -v --period-size=352 --buffer-size=3520   -Dhw:0,0 stereo.wav

http://www.alsa-project.org/main/index.php/XRUN_Debug

/proc/asound/card#/pcm0p/xrun_debug

Replace '#' with your card number (usually 0). This proc file can enable
various debugging tools. The CONFIG_SND_PCM_XRUN_DEBUG,
CONFIG_SND_VERBOSE_PROCFS, CONFIG_SND_DEBUG options must be enabled in your
kernel (if xrun_debug proc file is present - this feature is enabled).

# Enable basic debugging, do jiffies check and dump position on each period
and hardware pointer update calls
# Usefull when the lowlevel (specific) hardware driver is somehow broken
echo 29 > /proc/asound/card0/pcm0p/xrun_debug
diff mbox

Patch

diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index ce5a6da..65c1da9 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -482,6 +482,14 @@  static void print_power_state(struct snd_info_buffer *buffer,
 	snd_iprintf(buffer, "\n");
 }
 
+static void print_afg_caps(struct snd_info_buffer *buffer,
+				struct hda_codec *codec, hda_nid_t nid)
+{
+	int afg_cap = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_FG_CAP); 
+	snd_iprintf(buffer, "0x%08x OutputDelay=0x%02x InputDelay=0x%02x BeepGen=%x\n", 
+		afg_cap, afg_cap & 0xf, (afg_cap >> 8) & 0xf, (afg_cap >> 16) & 1);
+}
+
 static void print_unsol_cap(struct snd_info_buffer *buffer,
 			      struct hda_codec *codec, hda_nid_t nid)
 {
@@ -682,6 +690,8 @@  static void print_codec_info(struct snd_info_entry *entry,
 	print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT);
 	snd_iprintf(buffer, "State of AFG node 0x%02x:\n", codec->afg);
 	print_power_state(buffer, codec, codec->afg);
+	snd_iprintf(buffer, "AFG caps: ");
+	print_afg_caps(buffer, codec, codec->afg);
 
 	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
 	if (! nid || nodes < 0) {