ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2014年8月12日 星期二

worklog - tinyalsa, tinyplay

變成 tinyalsa.
tinyplay -- pcm_open()

struct pcm *pcm_open(unsigned int card,  unsigned int device,
                     unsigned int flags, struct pcm_config *config)
{
   ...
   ...
   snprintf(fn , sizeof(fn), "/dev/snd?pcmC%dD%u%c", card, device, flags & PCM_IN ? 'c' : 'p');
   ...
   pcm->fb = open(fn, O_RDWR);

在 android/external/tinyalsa 下

build 出:
  • libtinyalsa.so
  • tinyplay
  • tinycap
  • tinymix

kernel:

include/uapi/sound/asound.h:
struct snd_interval {
 unsigned int min, max;
 unsigned int openmin:1,
              openmax:1,
              integer:1,
              empty:1;
};

是在:
struct snd_pcm_hw_params {
 unsigned int flags;
 struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -  SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
 struct snd_mask mres[5]; /* reserved masks */
 struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
 struct snd_interval ires[9]; /* reserved intervals */
 unsigned int rmask;          /* W: requested masks */
 unsigned int cmask;          /* R: changed masks */
 unsigned int info;           /* R: Info flags for returned setup */
 unsigned int msbits;         /* R: used most significant bits */
 unsigned int rate_num;       /* R: rate numerator */
 unsigned int rate_den;       /* R: rate denominator */
 snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
 unsigned char reserved[64];  /* reserved for future */
};

Android AudioHardware 可以正常 pcm_open( )
tinyplay 就 fail

/AudioHardware open 時的 config:
         struct pcm_config config = {
            channels : 2,
            rate : 48000,
            period_size : 1024,
            period_count : 2,
            format : PCM_FORMAT_S16_LE,
            start_threshold : 0,
            stop_threshold : 0,
            silence_threshold : 0,
        };


在 target board 上,tinyplay pcm_open failed 的原因都是 config 內容不符合 codec support 的範圍。
pcm_open( ) 是 tinyalsa library function (pcm.c).

其中依次是:
  • fd = open("pcmC0D0p",O_RDWR)
  • ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info)
  • ioctl(fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)
  • ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)
config 內容不支援,是在 IOCTL_HW_PARAMS 時出錯。

打開 kernel/sound/pcm_native.c 的 RULES_DEBUG 還有掉 printk 的 KERN_DEBUG 後,

kernel msg 會有:
 SAMPLE_BITS = [16 16] -> [16 16]
 FRAME_BITS = [32 32] -> [32 32]
 CHANNELS = [1 1] -> empty
這樣就知道是 channels 沒有 match (codec 只 support 2 channels)
改用 2 channels (stereo) 的 sample wav file 後...
 ..
 ..
 PERIODS = [4 4] -> empty
這就是 period number 參數不對。
還好 tinyplay 有 optio "-n" 可以指定。
加上 -n 2 後,就沒有問題了。

沒有留言:

標籤

網誌存檔