Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
524 views
in Technique[技术] by (71.8m points)

driver - A period of PCM data from ALSA is duplicated

Our hardware saves 1024 frames of 16 bit stereo. I wrote an ALSA driver for it. PCM data is captured using arecord and saved to a wav file.

arecord -Dhw:0,0 -t wav -f S16_LE -r 44100 -c 2 -d 2 -v rec.wav

For debugging, the hardware generates a ramp of 2048 values in bits 11:0 with the ISR counter in bits 15:12. The wav file is viewed in audacity.

Expected pcm for 8 periods:

Ramp start   end
   0h,      7ffh
1800h,     1fffh
2000h,     27ffh
3800h,     3fffh
4000h,     47ffh
5800h,     5fffh
6000h,     67ffh
7800h,     7fffh

As seen in audacity

   0h,    7ffh
   0h,    7ffh
2000h,   27ffh
2000h,   27ffh
4000h,   47ffh
4000h,   47ffh
6000h,   67ffh
6000h,   67ffh

PCM ramp in audacity

The 1st period of pcm is duplicated twice. The big jump in the ramp indicates that the 2nd period of pcm is not present. The 3rd period of pcm is duplicated. The 4th period of data is is not present. The 5th period of pcm is duplicated. The 6th period of data is is not present.

In struct snd_pcm_hardware, I have:

   .channels_min = 2,
   .channels_max = 2,
   .buffer_bytes_max = (8*4096),
   .period_bytes_min =    4096,
   .period_bytes_max = (2*4096),
   .periods_min = 1,
   .periods_max = 2,

Since there's no DMA, I use struct snd_pcm_ops .copy_user to copy data to an ALSA buffer passed in .copy_user.

I tried the settings below, but arecord had an error.

   .periods_min = 1,
   .periods_max = 1,

arecord: set_params:1411: Can't use period equal to buffer size 1024 == 1024)

I tried increasing period_max to 4, and it resulted in 4 duplicates

   .period_bytes_max = (4*4096),
   .periods_min = 1,
   .periods_max = 4,

As seen in audacity

   0h,    7ffh
   0h,    7ffh
   0h,    7ffh
   0h,    7ffh
4000h,   47ffh
4000h,   47ffh
4000h,   47ffh
4000h,   47ffh

I verified that the ramp values are as expected in the ISR handler. In .copy_user, I verified that the pos argument isn't the same as the previous copy_user call and that the ramp values are as expected. Why is it duplicating? What can I do to fix it? Thanks in advance.

Added: Info printed by arecord

Recording WAVE 'rec.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
 Bufsz 8192, srate 44100, nch 2
 Opening PCM
 PCM Prepare
 Format 2
 Rate 44100
 Channels 2
 Buffer size 2048
 Period size 1024
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : S16_LE
 PCMptr 0
  subformat    : STD
  channels     : 2
  rate         : 44100
  exact rate   : 44100 (44100/1)
  msbits       : 16
  buffer_size  : 2048
  period_size  : 1024
  period_time  : 23219
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 2048
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
question from:https://stackoverflow.com/questions/65948007/a-period-of-pcm-data-from-alsa-is-duplicated

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...