Chinaunix首页 | 论坛 | 博客
  • 博客访问: 278394
  • 博文数量: 61
  • 博客积分: 655
  • 博客等级: 上士
  • 技术积分: 489
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-21 18:21
文章分类

全部博文(61)

文章存档

2014年(9)

2013年(23)

2012年(26)

2011年(3)

我的朋友

分类: LINUX

2014-04-15 10:49:58

原文地址:http://blog.csdn.net/suer0101/article/details/7263950

采用OSS进行音频编程时应当遵循的一般性框架:

1)打开音频设备;

2)设置采样格式(即量化位数);

3)设置声道数(单声道或者立体声);

4)设置采样率(即采样速度);

5)从设备读入数据或者向设备写入数据;

6)关闭音频设备;

上述过程中,第(6)可选,因为在进程正常或非正常退出时都会关闭它所打开的文件描述字,这样也就把音频设备的资源释放了。但是,除此之外的五个步骤是不能缺少的,并且顺序也不能颠倒(OSS编程指南对此的说明是:在指定声道数之前设置采样率不能在所有的音频硬件上工作——如果在将声卡设置为高采样率模式之后更改了声道数,应用程序将出现不正确的行为。同时,必须在使用read()或者write()调用读写数据之前设置采样率)。

这是作者编写的一个读写/dev/dsp设备的小程序,可以用它来录制一段声音,也可以用来将录制到文件中的声音播放出来。除此之外,还可以通过命令行参数指定设备参数,如:采样率、量化位数、声道数、要录制的声音长度,等等。详细的命令行参数解释如下:

SndKit [-h] [-d device] [-c channel] [-b bits] [-f hz] [-l len] <-r|-p file>

其中:

¨     -h:打印帮助信息;

¨     -d:指定要读写的音频设备(默认为/dev/dsp);

¨     -c:指定使用的声道数(默认为MONO,单声道);

¨     -b:指定量化位数(默认为8位无符号整数);

¨     -f:指定采样频率(默认为8KHz);

¨     -l:指定录制的声音文件的长度(默认为1024,单位为KB);

¨     -r file:录制声音,file存放录制的声音数据;

¨     -p file:播放file文件中存储的声音数据。

注意:-h-r-p这三个选项不能同时出现在命令行上。比如,可以通过下面的命令录制一段声音:

[root@cyc source]# ./SndKit -c 2 -b 16 -f 48 -r cyc.wav

采用的是双声道立体声、16位量化位数、48KHz采样频率、录制的声音保存在cyc.wav文件中,要录制的声音长度采用默认值1024KB。录制好之后,可以通过下面的命令播放出来:

[root@cyc source]# ./SndKit -c 2 -b 16 -f 48 -p cyc.wav

sound data play complete!

需要注意的是,录制时采用的是什么样的参数,播放时就应该采用同样的参数,否则将会出错。

下面直接给出源代码:

  1. /* 
  2.   Name: SndKit.c 
  3.   Copyright: GPLv2 
  4.   Author: rockins(ybc2084@163.com) 
  5.   Date: 15-10-06 18:22 
  6.   Description: implent raw sound record/play 
  7.   run: ./SndKit [-h] [-d device] [-c channel] [-b bits] [-f hz] [-l len] <-r|-p file> 
  8.   e.g.: 
  9.   ./SndKit -h     show help information 
  10.   ./SndKit -r record.wav                   record audio from microphone(/dev/dsp) 
  11.   ./SndKit -d /dev/dsp -p record.wav        playback record.wav via /dev/dsp 
  12.   ./SndKit -b 8 -f 22 -r reacord.wav        record audio in 8 bit & 22k hz 
  13.   ./SndKit -d /dev/dsp -c 2 -r record.wav   record audio in /dev/dsp and stereo 
  14.   ./SndKit -r -l 40 record.wav   record 40k audio data 
  15. */  
  16. #include   
  17. #include   
  18. #include   
  19. #include   
  20. #include   
  21. #include   
  22. #include  /*for OSS style sound programing */  
  23. #define TRUE  1  
  24. #define FALSE  0  
  25. #define FMT8BITS AFMT_U8 /*unsigned 8 bits(for almost PC) */  
  26. #define FMT16BITS AFMT_S16_LE /*signed 16 bits,little endian */  
  27. #define FMT8K    8000 /*default sampling rate */  
  28. #define FMT11K   11025 /*11,22,44,48 are three pop rate */  
  29. #define FMT22K   22050  
  30. #define FMT44K   44100  
  31. #define FMT48K  48000  
  32. #define MONO     1  
  33. #define STEREO   2  
  34. #define ACT_RECORD 0  
  35. #define ACT_PLAY 1  
  36. #define DFT_SND_DEV  "/dev/dsp"  
  37. #define DFT_SND_FMT  FMT8BITS  
  38. #define DFT_SND_SPD  FMT8K  
  39. #define DFT_SND_CHN  MONO  
  40. #define DFT_LEN  1024 /*default record length:40k */  
  41. #define BUFF_SIZE  512 /*buffer size:512 Bytes */  
  42. /************** function prototype ********************/  
  43. void Usage(void);  
  44. int OpenDevice(const char *, unsigned int);  
  45. int OpenFile(const char *, unsigned int);  
  46. int CloseDevice(unsigned int);  
  47. int CloseFile(unsigned int);  
  48. /************** function implementation **************/  
  49. int main(int argc, char *argv[])  
  50. {  
  51.     unsigned int snd_fmt = DFT_SND_FMT; /*sound format,bits */  
  52.     unsigned int snd_chn = DFT_SND_CHN; /*sound channel number */  
  53.     unsigned int snd_spd = DFT_SND_SPD; /*sound speed,frequency */  
  54.     unsigned char *s_file = NULL; /*file hold sound data */  
  55.     unsigned char *snd_device = DFT_SND_DEV; /*sound device */  
  56.     unsigned int recd_or_play = ACT_PLAY; /*flag(default play) */  
  57.     unsigned char buff[BUFF_SIZE]; /*sound buffer */  
  58.     unsigned long len = DFT_LEN * 1024; /*record or play length(k) */  
  59.     int snd_fd;   /*sound device descriptor */  
  60.     int s_fd;   /*sound data file descrit */  
  61.     ssize_t n;   /*bytes already in or out */  
  62.     ssize_t nRD;  /*bytes readin */  
  63.     ssize_t nWR;  /*bytes write out */  
  64.     unsigned int opt_chr; /*hold cli option */  
  65.     unsigned int opt_err = FALSE; /*indicate whether parse option error */  
  66.     /*parse cli option via getopt routine */  
  67.     optind = 0;    /*set optindex to 0 */  
  68.     while ((opt_chr = getopt(argc, argv, "hd:c:b:f:l:r:p:")) != -1) {  
  69.  switch (opt_chr) {  
  70.  case 'h':  
  71.      Usage();  
  72.      return (0);   /*return, 0 denote success */  
  73.      break;  
  74.  case 'd':  
  75.      snd_device = optarg; /*sound device name */  
  76.      break;  
  77.  case 'c':  
  78.      if (atoi(optarg) == 1) /*select channel number */  
  79.   snd_chn = MONO;  
  80.      else if (atoi(optarg) == 2)  
  81.   snd_chn = STEREO;  
  82.      else {  
  83.   opt_err = 1;  /*error occur */  
  84.   fprintf(stderr, "wrong channel setting,"  
  85.    "should be 1 or 2(default 1,MONO)\n");  
  86.      }  
  87.      break;  
  88.  case 'b':  
  89.      if (atoi(optarg) == 8) /*select data bit */  
  90.   snd_fmt = FMT8BITS;  
  91.      else if (atoi(optarg) == 16)  
  92.   snd_fmt = FMT16BITS;  
  93.      else {  
  94.   opt_err = 1;  /*error occur */  
  95.   fprintf(stderr, "wrong bits setting,"  
  96.    "should be 8 or 16(default 8)\n");  
  97.      }  
  98.      break;  
  99.  case 'f':  
  100.      if (atoi(optarg) == 8)  
  101.   snd_spd = FMT8K; /*sampling rate:8kbps */  
  102.      else if (atoi(optarg) == 11)  
  103.   snd_spd = FMT11K; /*smapling rate:11.025k */  
  104.      else if (atoi(optarg) == 22)  
  105.   snd_spd = FMT22K; /*sampling rate:22.050k */  
  106.      else if (atoi(optarg) == 44)  
  107.   snd_spd = FMT44K; /*sampling rate:44.100k */  
  108.      else if (atoi(optarg) == 48)  
  109.   snd_spd = FMT48K; /*sampling rate:48k */  
  110.      else {  
  111.   opt_err = 1;  /*error occur */  
  112.   fprintf(stderr, "wrong sampling rate,"  
  113.    "should be 8,11,22,or 44(default 8kbps)\n");  
  114.      }  
  115.      break;  
  116.  case 'l':  
  117.      len = atoi(optarg) * 1024; /*record length(k) */  
  118.      break;  
  119.  case 'r':  
  120.      recd_or_play = ACT_RECORD;  
  121.      s_file = optarg;  /*file to record sound */  
  122.      break;  
  123.  case 'p':  
  124.      recd_or_play = ACT_PLAY;  
  125.      s_file = optarg;  /*file to play sound */  
  126.      break;  
  127.  case '?':  
  128.      opt_err = 1;  
  129.      fprintf(stderr, "unknown option:%c\n", optopt);  
  130.      break;  
  131.  default:  
  132.      opt_err = 1;  
  133.      fprintf(stderr, "getopt error:%d\n", opterr);  
  134.      break;  
  135.  }  
  136.     }  
  137.     /*check if cli option parsed right*/  
  138.     if (opt_err || argc < 2) {  
  139.  fprintf(stderr, "parse command option failed!!!\n"  
  140.   "run ./SndKit -h for help\n");  
  141.  return (-1);  
  142.     }  
  143.     /*open device */  
  144.     if ((snd_fd = OpenDevice(snd_device, recd_or_play)) < 0) {  
  145.  fprintf(stderr, "cannot open device %s:%s\n", snd_device,  
  146.   strerror(errno));  
  147.  return (-1);  
  148.     }  
  149.     /*open sound data file */  
  150.     if ((s_fd = OpenFile(s_file, recd_or_play)) < 0) {  
  151.  fprintf(stderr, "cannot open sound file %s:%s\n", s_file,  
  152.   strerror(errno));  
  153.  return (-1);  
  154.     }  
  155.     /*set sound format */  
  156.     if (SetFormat(snd_fd, snd_fmt, snd_chn, snd_spd) < 0) {  
  157.  fprintf(stderr, "cannot set %s in bit %d, channel %d, speed %d\n",  
  158.   snd_device, snd_fmt, snd_chn, snd_spd);  
  159.  return (-1);  
  160.     }  
  161.     /*do real action:record or playback */  
  162.     if (recd_or_play == ACT_RECORD) {  /*record sound into data file*/  
  163.  n = 0;  
  164.  while (n < len) {  
  165.      nRD = 0;  /*amount read from sound device */  
  166.      if ((nRD = read(snd_fd, buff, BUFF_SIZE)) < 0) {  
  167.   perror("read sound device failed");  
  168.   return (-1);  
  169.      }  
  170.      if (n + nRD <= len) /*the len is not full */  
  171.   nWR = nRD; /*write amount to sound data file */  
  172.      else  
  173.   nWR = len - n; /*len will be overflow */  
  174.      unsigned long old_nWR = nWR; /*s hold nWR's old value */  
  175.      unsigned long t = 0L;  /*temp counter */  
  176.        
  177.      while (nWR > 0) {  
  178.   if ((t = write(s_fd, buff, nWR)) < 0) {  
  179.       perror("write sound data file failed");  
  180.       return (-1);  
  181.   }  
  182.   nWR -= t;  
  183.      }  
  184.      n += old_nWR;  
  185.  }  
  186.     } else if (recd_or_play == ACT_PLAY) { /*write sound data to device*/  
  187.  while (TRUE) {  
  188.      nRD = 0L;   /*read amount from sound device */  
  189.      if ((nRD = read(s_fd, buff, BUFF_SIZE)) < 0) {  
  190.   perror("read sound data file failed");  
  191.   return (-1);  
  192.      } else if (nRD == 0) { /*nRD == 0 means all sound stream output */  
  193.   printf("sound data play complete!\n");  
  194.   exit(0);  
  195.      }  
  196.      nWR = nRD;  
  197.      while (nWR > 0) {  /*write into device*/  
  198.   if ((n = write(snd_fd, buff, nWR)) < 0) {  
  199.       perror("write sound device file failed");  
  200.       return (-1);  
  201.   }  
  202.   nWR -= n;  
  203.      }  
  204.  }  
  205.     }  
  206.     /*close sound device and sound data file*/  
  207.     CloseDevice(snd_fd);  
  208.     CloseFile(s_fd);  
  209.     return (0);  
  210. }  
  211. /* 
  212.  * OpenDevice():open sound device 
  213.  * params: 
  214.  * dev_name -- device name,such as /dev/dsp 
  215.  * flag -- flag(ACT_RECORD or ACT_PLAY) 
  216.  * returns: 
  217.  * file descriptor of sound device if sucess 
  218.  * -1 if failed 
  219.  */  
  220. int OpenDevice(const char *dev_name, unsigned int flag)  
  221. {  
  222.     int dev_fd;  
  223.     /*open sound device */  
  224.     if (flag == ACT_RECORD) {  
  225.  if ((dev_fd = open(dev_name, O_RDONLY)) < 0) {  
  226.      return (-1);  
  227.  }  
  228.     } else if (flag == ACT_PLAY) {  
  229.  if ((dev_fd = open(dev_name, O_WRONLY)) < 0) {  
  230.      return (-1);  
  231.  }  
  232.     }  
  233.     return (dev_fd);  
  234. }  
  235. /* 
  236.  * CloseDevice():close the sound device 
  237.  * params: 
  238.  * dev_fd -- the sound device's file descriptor 
  239.  * returns: 
  240.  * 0 if success 
  241.  * -1 if error occured 
  242.  */  
  243. int CloseDevice(unsigned int dev_fd)  
  244. {  
  245.     return (close(dev_fd));  
  246. }  
  247. /* 
  248.  * OpenFile():open sound data file 
  249.  * params: 
  250.  * file_name -- file name,e.g,record.wav 
  251.  * flag -- flag(ACT_RECORD or ACT_PLAY) 
  252.  * returns: 
  253.  * file descriptor of sound data file if sucess 
  254.  * -1 if failed 
  255.  */  
  256. int OpenFile(const char *file_name, unsigned int flag)  
  257. {  
  258.     int file_fd;  
  259.     /*open sound data file */  
  260.     if (flag == ACT_RECORD) {  
  261.  if ((file_fd = open(file_name, O_WRONLY)) < 0) {  
  262.      return (-1);  
  263.  }  
  264.     } else if (flag == ACT_PLAY) {  
  265.  if ((file_fd = open(file_name, O_RDONLY)) < 0) {  
  266.      return (-1);  
  267.  }  
  268.     }  
  269.     return (file_fd);  
  270. }  
  271. /* 
  272.  * CloseFile():close the sound data file 
  273.  * params: 
  274.  * file_fd -- the sound data file's descriptor 
  275.  * returns: 
  276.  * 0 if success 
  277.  * -1 if error occured 
  278.  */  
  279. int CloseFile(unsigned int file_fd)  
  280. {  
  281.     return (close(file_fd));  
  282. }  
  283. /* 
  284.  * SetFormat():Set Record and Playback format 
  285.  * params; 
  286.  * fd -- device file descriptor 
  287.  * chn -- channel(MONO or STEREO) 
  288.  * bits -- FMT8BITS(8bits), FMT16BITS(16bits) 
  289.  * hz -- FMT8K(8000HZ), FMT16K(16000HZ), FMT22K(22000HZ), 
  290.  *  FMT44K(44000HZ),FMT48K(48000HZ) 
  291.  * returns: 
  292.  * return 0 if success, else return -1 
  293.  * notes: 
  294.  * parameter setting order should be like as: 
  295.  *  1.sample format(number of bits) 
  296.  *  2.number of channels(mono or stereo) 
  297.  *  3.sampling rate(speed) 
  298.  */  
  299. int SetFormat(unsigned int fd, unsigned int bits, unsigned int chn,  
  300.        unsigned int hz)  
  301. {  
  302.     int ioctl_val;  
  303.     /* set bit format */  
  304.     ioctl_val = bits;  
  305.     if (ioctl(fd, SNDCTL_DSP_SETFMT, &ioctl_val) == -1) {  
  306.  fprintf(stderr, "Set fmt to bit %d failed:%s\n", bits,  
  307.   strerror(errno));  
  308.  return (-1);  
  309.     }  
  310.     if (ioctl_val != bits) {  
  311.  fprintf(stderr, "do not support bit %d, supported %d\n", bits,  
  312.   ioctl_val);  
  313.  return (-1);  
  314.     }  
  315.     /*set channel */  
  316.     ioctl_val = chn;  
  317.     if ((ioctl(fd, SNDCTL_DSP_CHANNELS, &ioctl_val)) == -1) {  
  318.  fprintf(stderr, "Set Audio Channels %d failed:%s\n", chn,  
  319.   strerror(errno));  
  320.  return (-1);  
  321.     }  
  322.     if (ioctl_val != chn) {  
  323.  fprintf(stderr, "do not support channel %d,supported %d\n", chn,  
  324.   ioctl_val);  
  325.  return (-1);  
  326.     }  
  327.     /*set speed */  
  328.     ioctl_val = hz;  
  329.     if (ioctl(fd, SNDCTL_DSP_SPEED, &ioctl_val) == -1) {  
  330.  fprintf(stderr, "Set speed to %d failed:%s\n", hz,  
  331.   strerror(errno));  
  332.  return (-1);  
  333.     }  
  334.     if (ioctl_val != hz) {  
  335.  fprintf(stderr, "do not support speed %d,supported is %d\n", hz,  
  336.   ioctl_val);  
  337.  return (-1);  
  338.     }  
  339.     return (0);  
  340. }  
  341. /* 
  342.  * Usage():print help information 
  343.  * params:(none) 
  344.  * returns:(none) 
  345.  */  
  346. void Usage(void)  
  347. {  
  348.     printf  
  349.  ("run: ./SndKit [-h] [-d device] [-c channel] [-b bits] [-f hz] [-l len] <-r|-p file>\n"  
  350.   "Description: implent raw sound record/play\n" "option:\n"  
  351.   "\t -h: print help informations\n"  
  352.   "\t -d device: assign sound device to record or playback(default /dev/dsp)\n"  
  353.   "\t -c channel: indicate in MONO or STEREO channel(default MONO)\n"  
  354.   "\t -b bits: assign sampling bits depth(default 8bits unsigned)\n"  
  355.   "\t -f hz: indicate sampling rate,i.e,frequence(default 8kbps)\n"  
  356.   "\t -l len: indicate recording sound's length(default 1024k)\n"  
  357.   "\t -r|-p file: indicate record in or playback(no default,must give out explicitly)\n"  
  358.   "e.g.:\n"  
  359.   "\t ./SndKit -h    show help information\n"  
  360.   "\t ./SndKit -r record.wav   record audio from microphone(/dev/dsp)\n"  
  361.   "\t ./SndKit -d /dev/dsp -p record.wav playback record.wav via /dev/dsp\n"  
  362.   "\t ./SndKit -b 8 -f 22 -r reacord.wav record audio in 8 bit & 22k hz\n"  
  363.   "\t ./SndKit -d /dev/dsp -c 2 -r record.wav record audio in /dev/dsp and stereo\n"  
  364.   "\t ./SndKit -r -l 40 record.wav  record 40k audio data in record.wav\n");  
  365. }  

阅读(954) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~