当前位置:   article > 正文

Linux Centos 播放wav音频_alsa lib pulse.c:242:(pulse_connect) pulseaudio: u

alsa lib pulse.c:242:(pulse_connect) pulseaudio: unable to connect: connecti

目录

实现步骤

实现思路及遇到的问题

1.未使用alsa库编码

2.使用alsa库编码

3.直接使用linux 自带播放器aplay 播放音频

pulseaudio导致音频播放失败的解决方法

确认使用了哪个声卡

1.硬件是否带声卡

2.确认声卡驱动是否存在

3.确认配置是否正确

注意事项总结


 

实现步骤

1.确认硬件是否有声卡

2.确认声卡驱动是否正确安装

3.确认声卡配置是否正确

 

实现思路及遇到的问题

 

 

1.未使用alsa库编码

直接用了网上的例子。

http://blog.sina.com.cn/s/blog_3e4774e30100ewoa.html

   参考教材:<Linux编程技术详解>杜华编著
   页码:P184
   程序实现了在Linux下播放Online.wav的功能。程序首先调用fstat函数获得文件相关信息(主要是文件大小信息)。通过malloc函数分配指定的内存空间,并将online.wav读入内存;然后,打开声卡设备文件,设置声卡参数;再调用write函数完成文件的播放。
    具体可行的代码如下:
//p6.7.c

  1. #include<unistd.h>
  2. #include<fcntl.h>
  3. #include<sys/types.h>
  4. #include<sys/stat.h>
  5. #include<stdlib.h>
  6. #include<stdio.h>
  7. #include<linux/soundcard.h>
  8. #define Audio_Device "/dev/dsp"
  9. //不同的声音有着不同的播放参数,这些参数可以使用file命令获得
  10. #define Sample_Size 16 //there're two kinds of bits,8 bits and 16 bits
  11. #define Sample_Rate 8000 //sampling rate
  12. int play_sound(char *filename){
  13. struct stat stat_buf;
  14. unsigned char * buf = NULL;
  15. int handler,fd;
  16. int result;
  17. int arg,status;
  18. //打开声音文件,将文件读入内存
  19. fd=open(filename,O_RDONLY);
  20. if(fd<0) return -1;
  21. if(fstat(fd,&stat_buf)){
  22. close(fd);
  23. return -1;
  24. }
  25. if(!stat_buf.st_size){
  26. close(fd);
  27. return -1;
  28. }
  29. buf=malloc(stat_buf.st_size);
  30. if(!buf){
  31. close(fd);
  32. return -1;
  33. }
  34. if(read(fd,buf,stat_buf.st_size)<0){
  35. free(buf);
  36. close(fd);
  37. return -1;
  38. }
  39. //打开声卡设备,并设置声卡播放参数,这些参数必须与声音文件参数一致
  40. handler=open(Audio_Device,O_WRONLY);
  41. if(handler==-1){
  42. perror("open Audio_Device fail");
  43. return -1;
  44. }
  45. arg=Sample_Rate;
  46. status=ioctl(handler,SOUND_PCM_WRITE_RATE,&arg);
  47. if(status==-1){
  48. perror("error from SOUND_PCM_WRITE_RATE ioctl");
  49. return -1;
  50. }
  51. arg=Sample_Size;
  52. status=ioctl(handler,SOUND_PCM_WRITE_BITS,&arg);
  53. if(status==-1){
  54. perror("error from SOUND_PCM_WRITE_BITS ioctl");
  55. return -1;
  56. }
  57. result=write(handler,buf,stat_buf.st_size);
  58. if(result==-1){
  59. perror("Fail to play the sound!");
  60. return -1;
  61. }
  62. free(buf);
  63. close(fd);
  64. close(handler);
  65. return result;
  66. }
  67. void main(void)
  68. {
  69. play_sound("/root/Online.wav");
  70. }

编译运行后,我的代码没能通过

[root@localhost ~]#./play_sound
error from SOUND_PCM_WRITE_RATE ioctl: Inappropriate ioctl for device

在我解决这个问题的时候,经音频相关专业人士指点,决定改用alsa库。所以上面这个问题我没解决

2.使用alsa库编码

同样直接用了网上的例子。

http://blog.chinaunix.net/uid-27106528-id-3328766.html

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include <string.h>
  4. #include <alsa/asoundlib.h>
  5. struct WAV_HEADER
  6. {
  7. char rld[4]; /*riff 标志符号*/
  8. int rLen;
  9. char wld[4]; /*格式类型(wave)*/
  10. char fld[4]; /*"fmt"*/
  11. int fLen; /*sizeof(wave format matex)*/
  12. short wFormatTag; /*编码格式*/
  13. short wChannels; /*声道数*/
  14. int nSamplesPersec ; /*采样频率*/
  15. int nAvgBitsPerSample;/*WAVE文件采样大小*/
  16. short wBlockAlign; /*块对齐*/
  17. short wBitsPerSample; /*WAVE文件采样大小*/
  18. char dld[4]; /*data*/
  19. int wSampleLength; /*音频数据的大小*/
  20. } wav_header;
  21. int set_pcm_play(FILE *fp);
  22. int main(int argc,char *argv[])
  23. {
  24. if(argc!=2)
  25. {
  26. printf("Usage:wav-player+wav file name\n");
  27. exit(1);
  28. }
  29. int nread;
  30. FILE *fp;
  31. fp=fopen(argv[1],"rb");
  32. if(fp==NULL)
  33. {
  34. perror("open file failed:\n");
  35. exit(1);
  36. }
  37. nread=fread(&wav_header,1,sizeof(wav_header),fp);
  38. printf("nread=%d\n",nread);
  39. printf("RIFF 标志%s\n",wav_header.rld);
  40. printf("文件大小rLen:%d\n",wav_header.rLen);
  41. printf("wld=%s\n",wav_header.wld);
  42. printf("fld=%s\n",wav_header.fld);
  43. printf("fLen=%d\n",wav_header.fLen);
  44. printf("wFormatTag=%d\n",wav_header.wFormatTag);
  45. printf("声道数:%d\n",wav_header.wChannels);
  46. printf("采样频率:%d\n",wav_header.nSamplesPersec);
  47. printf("nAvgBitsPerSample=%d\n",wav_header.nAvgBitsPerSample);
  48. printf("wBlockAlign=%d\n",wav_header.wBlockAlign);
  49. printf("采样的位数:%d\n",wav_header.wBitsPerSample);
  50. printf("data=%s\n",wav_header.dld);
  51. printf("wSampleLength=%d\n",wav_header.wSampleLength);
  52. set_pcm_play(fp);
  53. return 0;
  54. }
  55. int set_pcm_play(FILE *fp)
  56. {
  57. int rc;
  58. int ret;
  59. int size;
  60. snd_pcm_t* handle; /*PCI设备句柄*/
  61. snd_pcm_hw_params_t* params;/*硬件信息和PCM流配置*/
  62. unsigned int val;
  63. int dir=0;
  64. snd_pcm_uframes_t frames;
  65. char *buffer;
  66. int channels=wav_header.wChannels;
  67. int frequency=wav_header.nSamplesPersec;
  68. int bit=wav_header.wBitsPerSample;
  69. int datablock=wav_header.wBlockAlign;
  70. unsigned char ch[100]; /*用来存储wav文件的头信息*/
  71. rc=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
  72. if(rc<0)
  73. {
  74. perror("\nopen PCM device failed:");
  75. exit(1);
  76. }
  77. snd_pcm_hw_params_alloca(&params); /*分配params结构体*/
  78. if(rc<0)
  79. {
  80. perror("\nsnd_pcm_hw_params_alloca:");
  81. exit(1);
  82. }
  83. rc=snd_pcm_hw_params_any(handle, params);/*初始化params*/
  84. if(rc<0)
  85. {
  86. perror("\nsnd_pcm_hw_params_any:");
  87. exit(1);
  88. }
  89. rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /*初始化访问权限*/
  90. if(rc<0)
  91. {
  92. perror("\nsed_pcm_hw_set_access:");
  93. exit(1);
  94. }
  95. /*采样位数*/
  96. switch(bit/8)
  97. {
  98. case 1:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
  99. break ;
  100. case 2:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
  101. break ;
  102. case 3:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE);
  103. break ;
  104. }
  105. rc=snd_pcm_hw_params_set_channels(handle, params, channels); /*设置声道,1表示单声>道,2表示立体声*/
  106. if(rc<0)
  107. {
  108. perror("\nsnd_pcm_hw_params_set_channels:");
  109. exit(1);
  110. }
  111. val = frequency;
  112. rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /*设置>频率*/
  113. if(rc<0)
  114. {
  115. perror("\nsnd_pcm_hw_params_set_rate_near:");
  116. exit(1);
  117. }
  118. rc = snd_pcm_hw_params(handle, params);
  119. if(rc<0)
  120. {
  121. perror("\nsnd_pcm_hw_params: ");
  122. exit(1);
  123. }
  124. rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir); /*获取周期
  125. 长度*/
  126. if(rc<0)
  127. {
  128. perror("\nsnd_pcm_hw_params_get_period_size:");
  129. exit(1);
  130. }
  131. size = frames * datablock; /*4 代表数据快长度*/
  132. buffer =(char*)malloc(size);
  133. fseek(fp,58,SEEK_SET); /*定位歌曲到数据区*/
  134. while (1)
  135. {
  136. memset(buffer,0,sizeof(buffer));
  137. ret = fread(buffer, 1, size, fp);
  138. if(ret == 0)
  139. {
  140. printf("歌曲写入结束\n");
  141. break;
  142. }
  143. else if (ret != size)
  144. {
  145. }
  146. /* 写音频数据到PCM设备*/
  147. while(ret = snd_pcm_writei(handle, buffer, frames)<0)
  148. {
  149. usleep(2000);
  150. if (ret == -EPIPE)
  151. {
  152. /* EPIPE means underrun */
  153. fprintf(stderr, "underrun occurred\n");
  154. /*完成硬件参数设置,使设备准备好*/
  155. snd_pcm_prepare(handle);
  156. }
  157. else if (ret < 0)
  158. {
  159. fprintf(stderr,
  160. "error from writei: %s\n",
  161. snd_strerror(ret));
  162. }
  163. }
  164. }
  165. snd_pcm_drain(handle);
  166. snd_pcm_close(handle);
  167. free(buffer);
  168. return 0;
  169. }

使用gcc -o pcm_play pcm_play.c -L. -lasound编译

运行./pcm_play test.wav

ALSA lib pulse.c:243:(pulse_connect) PulseAudio: Unable to connect: Connection refused

aplay: main:722: audio open error: Connection refused

由此引入了第三个实现方案

3.直接使用linux 自带播放器aplay 播放音频

但是aplay和方案2遇到的相同的问题

pulseaudio导致音频播放失败的解决方法

1.卸载pulseaudio

yum remove pulseaudio

2.pulseaudio重新查找声卡

http://my.huhoo.net/archives/2007/04/linux-1.html

但是我在实际使用的时候,这个先删/tmp,再pulseaudio -D & (pulseaudio重新查找声卡)后,aplay只能正常运行几分钟

所以 我选择的方法1,直接卸载

pulseaudio的问题解决了。方案2的alse库实现的编码,也运行通过了

 

当然了,作为音频编程的新手,怎么能不饶弯路的直接get到音频的声音呢?没可能!!!

确认使用了哪个声卡

 

1.硬件是否带声卡

cat /proc/asound/cards

硬件存在两个硬件声卡(因为我使用的环境,没有外设,没有音响。所以我使用的card1)


aplay -L(使用该命令,再次确认,硬件上是有alc662的codec硬件声卡)

ll /dev/snd/


(并添加了 所有者 、所在组、其它组的rw权限)(不添加应该也没有影响)

确认该硬件设备使用的声卡是pcmC1D0p

2.确认声卡驱动是否存在


一顿操作,下载安装alse_lib/alse_util(没有实际应用到)

---所以aplay好用,驱动就好用

   aplay不好用,网上搜答案

 

3.确认配置是否正确


默认声卡使用(card 1  device 0)

cat /etc/asound.conf
defaults.pcm.card 1  
defaults.pcm.device 0  
defaults.ctl.card 1

 

注意事项总结

1.需要指定指定默认声卡为机器使用的声卡
2.alsamixer设置图形界面--最好测试的时候将声音设置为最大
3.先用的pcm的方式写的、之后改为alsa。无论使用alsa库的程序或aplay工具都可以实现
4.lspci|grep -i audio
00:03.0 Audio device: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller (rev 06)
00:1b.0 Audio device: Intel Corporation 8 Series/C220 Series Chipset High Definition Audio Controller (rev 05)
5.程序设置音频采样率、频道、小端、16bit等信息
6.aplay test.wav
Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Stereo
通过aplay命令,可以查看5列出的信息。

7.针对PulseAudio:Unable to connect:Connection terminated
aplay:main:828: audio open error: Connection refused
删除了PulseAudio库
yum remove pulseaudio

8.配置!!!配置!!!默认配置!!!
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/326132
推荐阅读
相关标签
  

闽ICP备14008679号