天嵌 ARM开发社区

 找回密码
 注册
查看: 1989|回复: 1

为什么往/dev/dsp写数据,放音有延时,要等一会儿才有声音

[复制链接]
kelly 发表于 2013-4-26 20:01:09 | 显示全部楼层 |阅读模式
最近在学习录放音程序的编写。
我写了个小程序,以8000采样率录音20ms,由于设置sample size为16bits,所以每20ms从/dev/dsp录音 8000*20/1000*16/8 = 320字节。
320个字节一录好,就立刻把这些数据写入到/dev/dsp。

相当于本地自环,录音的同时放音。

但是有一个问题,理论上讲,录音和放音应该几乎是同时的,即最大延时应该为20ms左右,人耳朵是听不出来的。但是现在放音比录音延迟有大概2秒左右。

我又试着用cat /dev/dsp > /tmp/a.wav
录一段声音以后cat /tmp/a.wav > /dev/dsp
这样也是要等大概2秒左右才开始有声音。

请问各位大侠,这个到底是什么原因造成的呢?音频设备初始化也不需要这么长时间啊,用madplay播放音频文件立刻就有声音了。难道音频设备给printf一样,有缓冲区的,等满了以后才会刷新缓冲区。

下面是我的代码。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <fcntl.h>

  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/select.h>
  10. #include <sys/time.h>
  11. #include <sys/soundcard.h>

  12. #include <errno.h>

  13. #define REC_LENGTH 320

  14. #define RATE 8000   /* the sampling rate */
  15. #define SIZE 16      /* sample size: 8 or 16 bits */
  16. #define CHANNELS 1  /* 1 = mono 2 = stereo */


  17. /* this buffer holds the digitized audio */
  18. //unsigned char rec_buf[TIME*RATE*SIZE*CHANNELS/8];
  19. unsigned char rec_buf[REC_LENGTH] = {0};

  20. int dsp_fd;        /* sound device file descriptor */
  21. int rd_fd;
  22. int arg;        /* argument for ioctl calls */
  23. int status;   /* return status of system calls */

  24. void init_r(void)
  25. {
  26.         //printf("init read\n");
  27.         dsp_fd = open("/dev/dsp", O_RDONLY);

  28.         if (dsp_fd < 0)
  29.         {
  30.                 perror("open of /dev/dsp failed");
  31.                 printf("error no = %d\n", errno);
  32.                 exit(1);
  33.         }

  34.         /* set sampling parameters */
  35.         arg = SIZE;           /* sample size */
  36.         status = ioctl(dsp_fd, SOUND_PCM_WRITE_BITS, &arg);
  37.         if (status == -1)
  38.                 perror("SOUND_PCM_WRITE_BITS ioctl failed");
  39.         if (arg != SIZE)
  40.                 perror("unable to set sample size");

  41.         arg = CHANNELS;  /* mono or stereo */
  42.         status = ioctl(dsp_fd, SOUND_PCM_WRITE_CHANNELS, &arg);
  43.         if (status == -1)
  44.                 perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
  45.         if (arg != CHANNELS)
  46.                 perror("unable to set number of channels");

  47.         arg = RATE;           /* sampling rate */
  48.         status = ioctl(dsp_fd, SOUND_PCM_WRITE_RATE, &arg);
  49.         if (status == -1)
  50.                 perror("SOUND_PCM_WRITE_WRITE ioctl failed");
  51.         //printf("init r ok\n");
  52. }

  53. void init_w(void)
  54. {
  55.         //printf("init write\n");
  56.         rd_fd = open("/dev/dsp", O_WRONLY);

  57.         if (rd_fd < 0)
  58.         {
  59.                 perror("open of /dev/dsp failed");
  60.                 printf("error no = %d\n", errno);
  61.                 exit(1);
  62.         }

  63.         /* set sampling parameters */
  64.         arg = SIZE;           /* sample size */
  65.         status = ioctl(rd_fd, SOUND_PCM_WRITE_BITS, &arg);
  66.         if (status == -1)
  67.                 perror("SOUND_PCM_WRITE_BITS ioctl failed");
  68.         if (arg != SIZE)
  69.                 perror("unable to set sample size");

  70.         arg = CHANNELS;  /* mono or stereo */
  71.         status = ioctl(rd_fd, SOUND_PCM_WRITE_CHANNELS, &arg);
  72.         if (status == -1)
  73.                 perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
  74.         if (arg != CHANNELS)
  75.                 perror("unable to set number of channels");

  76.         arg = RATE;           /* sampling rate */
  77.         status = ioctl(rd_fd, SOUND_PCM_WRITE_RATE, &arg);
  78.         if (status == -1)
  79.                 perror("SOUND_PCM_WRITE_WRITE ioctl failed");
  80.         //printf("init w ok\n");
  81. }


  82. int main(void)
  83. {
  84.         /*初始化DSP*/
  85.         printf("init DSP\n");
  86.     /*初始化读句柄*/
  87.         init_r();
  88.     /*初始化写句柄*/
  89.         init_w();

  90.         while(1)
  91.         {
  92.         /*录音*/
  93.                 status = read(dsp_fd, rec_buf, sizeof(rec_buf));
  94.                 if (status != sizeof(rec_buf))
  95.                         perror("read wrong number of bytes");



  96.                 /*放音*/
  97.                 status = write(rd_fd, rec_buf, sizeof(rec_buf));
  98.                 if (status != sizeof(rec_buf))
  99.                         perror("read wrong number of bytes");
  100.         }
  101.    
  102.         close(dsp_fd);
  103.         close(rd_fd);
  104.         return 0;
  105. }
复制代码
请各位大侠给点思路,谢谢了!
liuhong135541 发表于 2013-5-8 19:31:59 | 显示全部楼层
我也正在弄这个,可以请教下不? 涉及到语音传输
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-5-27 17:29 , Processed in 1.046875 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表