ifree64 发表于 2008-9-9 16:13

Linux下编写了一个小程序,播放wav文件成功。

今天,看了下wav文件格式,在Linux下尝试了读取wav文件数据写往声卡文件/dev/dsp,播放成功。<br />没想到Linux下声卡编程竟然如此简单,就是把音频数据写到/dev/dsp文件即可。<br /><br />源代码如下<br /><br />/*&nbsp;filename:&nbsp;wavplay.c&nbsp;*/<br /><br />#include&nbsp;&ltunistd.h&gt<br />#include&nbsp;&ltfcntl.h&gt<br />#include&nbsp;&ltsys/types.h&gt<br />#include&nbsp;&ltsys/ioctl.h&gt<br />#include&nbsp;&ltstdlib.h&gt<br />#include&nbsp;&ltstdio.h&gt<br />#include&nbsp;&ltstdint.h&gt<br />#include&nbsp;&ltlinux/soundcard.h&gt<br /><br />#define&nbsp;BUFSIZE&nbsp;512<br /><br />struct&nbsp;RIFF_Header{<br />&nbsp;&nbsp;char&nbsp;RIFF_ID;<br />&nbsp;&nbsp;uint32_t&nbsp;RIFF_Size;<br />&nbsp;&nbsp;char&nbsp;RIFF_Format;<br />};<br /><br />struct&nbsp;Chunk_Header{<br />&nbsp;&nbsp;char&nbsp;Chunk_ID;<br />&nbsp;&nbsp;uint32_t&nbsp;Chunk_Size;<br />};<br /><br />struct&nbsp;Wave_Format{<br />&nbsp;&nbsp;uint16_t&nbsp;AudioFormat;<br />&nbsp;&nbsp;uint16_t&nbsp;NumChannels;<br />&nbsp;&nbsp;uint32_t&nbsp;SampleRate;<br />&nbsp;&nbsp;uint32_t&nbsp;AvgBytesPerSec;<br />&nbsp;&nbsp;uint16_t&nbsp;BlockAlign;<br />&nbsp;&nbsp;uint16_t&nbsp;BitsPerSample;<br />};<br /><br />int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;*argv[])<br />{<br />&nbsp;&nbsp;struct&nbsp;RIFF_Header&nbsp;riff_header;<br />&nbsp;&nbsp;struct&nbsp;Chunk_Header&nbsp;fmt_chunk,&nbsp;data_chunk;<br />&nbsp;&nbsp;struct&nbsp;Wave_Format&nbsp;wavfmt;<br /><br />&nbsp;&nbsp;char&nbsp;buf;<br />&nbsp;&nbsp;FILE&nbsp;*&nbsp;fwave;<br />&nbsp;&nbsp;int&nbsp;sndfd;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;int&nbsp;status;<br />&nbsp;&nbsp;int&nbsp;arg;<br />&nbsp;&nbsp;int&nbsp;readbytes;<br />&nbsp;&nbsp;int&nbsp;writebytes;<br />&nbsp;&nbsp;int&nbsp;writed;<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;if(&nbsp;argc&nbsp;&lt&nbsp;2&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;Usage:&nbsp;wavplay&nbsp;&ltfilename&gt\n&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;exit(-1);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;fwave&nbsp;=&nbsp;fopen(&nbsp;argv,&nbsp;&quot;r&quot;);<br />&nbsp;&nbsp;if(&nbsp;fwave&nbsp;==&nbsp;NULL&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;Can't&nbsp;open&nbsp;file&nbsp;%s\n&quot;,&nbsp;argv);<br />&nbsp;&nbsp;&nbsp;&nbsp;exit(-1);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;fread(&riff_header,&nbsp;1,&nbsp;sizeof(struct&nbsp;RIFF_Header),&nbsp;fwave);<br />&nbsp;&nbsp;if(&nbsp;strncmp(riff_header.RIFF_ID,&nbsp;&quot;RIFF&quot;,&nbsp;4)&nbsp;||&nbsp;strncmp(riff_header.RIFF_Format,&nbsp;&quot;WAVE&quot;,4)){<br />&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;Unknown&nbsp;file&nbsp;format.\n&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;exit(-1);<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;sndfd&nbsp;=&nbsp;open(&quot;/dev/dsp&quot;,&nbsp;O_RDWR);<br />&nbsp;&nbsp;if&nbsp;(sndfd&nbsp;&lt&nbsp;0)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;open&nbsp;of&nbsp;/dev/dsp&nbsp;failed&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;exit(-1);<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;fread(&fmt_chunk,&nbsp;1,&nbsp;sizeof(struct&nbsp;Chunk_Header),&nbsp;fwave);<br />&nbsp;&nbsp;if(&nbsp;!strncmp(fmt_chunk.Chunk_ID,&nbsp;&quot;fmt&nbsp;&quot;,&nbsp;4)&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;this&nbsp;is&nbsp;a&nbsp;fmt&nbsp;chunk&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;fread(&wavfmt,&nbsp;1,&nbsp;sizeof(struct&nbsp;Wave_Format),&nbsp;fwave);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;arg&nbsp;=&nbsp;wavfmt.BitsPerSample;<br />&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(sndfd,&nbsp;SOUND_PCM_WRITE_BITS,&nbsp;&arg);<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(status&nbsp;==&nbsp;-1)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;SOUND_PCM_WRITE_BITS&nbsp;ioctl&nbsp;failed&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(arg&nbsp;!=&nbsp;wavfmt.BitsPerSample)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;unable&nbsp;to&nbsp;set&nbsp;sample&nbsp;size&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;arg&nbsp;=&nbsp;wavfmt.NumChannels;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(sndfd,&nbsp;SOUND_PCM_WRITE_CHANNELS,&nbsp;&arg);<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(status&nbsp;==&nbsp;-1)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;SOUND_PCM_WRITE_CHANNELS&nbsp;ioctl&nbsp;failed&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(arg&nbsp;!=&nbsp;wavfmt.NumChannels)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;unable&nbsp;to&nbsp;set&nbsp;number&nbsp;of&nbsp;channels&quot;);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;arg&nbsp;=&nbsp;wavfmt.SampleRate;<br />&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;=&nbsp;ioctl(sndfd,&nbsp;SOUND_PCM_WRITE_RATE,&nbsp;&arg);<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(status&nbsp;==&nbsp;-1)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;SOUND_PCM_WRITE_WRITE&nbsp;ioctl&nbsp;failed&quot;);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;skip&nbsp;extra&nbsp;bytes&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;fseek(fwave,&nbsp;fmt_chunk.Chunk_Size&nbsp;-&nbsp;16&nbsp;+&nbsp;fmt_chunk.Chunk_Size%2,&nbsp;SEEK_CUR);<br />&nbsp;&nbsp;}else{<br />&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;Can't&nbsp;find&nbsp;fmt&nbsp;chunk.\n&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;exit(-1);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;while(&nbsp;fread(&data_chunk,&nbsp;1,&nbsp;sizeof(struct&nbsp;Chunk_Header),&nbsp;fwave)&nbsp;!=&nbsp;0&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;!strncmp(data_chunk.Chunk_ID,&nbsp;&quot;data&quot;,&nbsp;4)&nbsp;){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Begin&nbsp;Play\n&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;this&nbsp;is&nbsp;a&nbsp;data&nbsp;chunk&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writed&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(writed&nbsp;&lt&nbsp;data_chunk.Chunk_Size){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readbytes&nbsp;=&nbsp;fread(buf,&nbsp;1,&nbsp;BUFSIZE,&nbsp;fwave);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writebytes&nbsp;=&nbsp;write(sndfd,&nbsp;buf,&nbsp;readbytes);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;writebytes&nbsp;!=&nbsp;readbytes&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;wrote&nbsp;wrong&nbsp;number&nbsp;of&nbsp;bytes&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writed&nbsp;+=&nbsp;readbytes;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}else{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;skip&nbsp;unknown&nbsp;chunks&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fseek(fwave,&nbsp;data_chunk.Chunk_Size&nbsp;+&nbsp;fmt_chunk.Chunk_Size%2,&nbsp;SEEK_CUR);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;fclose(fwave);<br />&nbsp;&nbsp;close(sndfd);<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;return&nbsp;0;<br />}&nbsp;

sodwell 发表于 2008-9-10 08:47

大哥,啥时候写个MP3的啊?

l0p0c 发表于 2008-9-10 15:37

嗯!恭喜LZ啦!

765vcf 发表于 2008-9-10 16:18

嘻....嘻...在linux下面裸奔呀

用GStreamer库的小播放器,指定文件路径就行.....<br />#include&nbsp;&ltgst/gst.h&gt<br />#include&nbsp;&ltstdbool.h&gt<br />static&nbsp;GMainLoop&nbsp;*loop;<br />static&nbsp;gboolean&nbsp;bus_call&nbsp;(GstBus&nbsp;*bus,&nbsp;GstMessage&nbsp;*msg,&nbsp;gpointer&nbsp;user_data)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;switch&nbsp;(GST_MESSAGE_TYPE&nbsp;(msg))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;GST_MESSAGE_EOS:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g_message&nbsp;(&quot;End-of-stream&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g_main_loop_quit&nbsp;(loop);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;GST_MESSAGE_ERROR:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g_message&nbsp;(&quot;Error&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g_main_loop_quit&nbsp;(loop);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;<br />}<br /><br />void&nbsp;play_uri&nbsp;(gchar&nbsp;*uri)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;GstElement&nbsp;*pipeline;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;loop&nbsp;=&nbsp;g_main_loop_new&nbsp;(NULL,&nbsp;FALSE);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;pipeline&nbsp;=&nbsp;gst_element_factory_make&nbsp;(&quot;playbin&quot;,&nbsp;&quot;player&quot;);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(uri)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g_object_set&nbsp;(G_OBJECT&nbsp;(pipeline),&nbsp;&quot;uri&quot;,&nbsp;uri,&nbsp;NULL);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GstBus&nbsp;*bus;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bus&nbsp;=&nbsp;gst_pipeline_get_bus&nbsp;(GST_PIPELINE&nbsp;(pipeline));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gst_bus_add_watch&nbsp;(bus,&nbsp;bus_call,&nbsp;NULL);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gst_object_unref&nbsp;(bus);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;gst_element_set_state&nbsp;(GST_ELEMENT&nbsp;(pipeline),&nbsp;GST_STATE_PLAYING);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;g_main_loop_run&nbsp;(loop);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;gst_element_set_state&nbsp;(GST_ELEMENT&nbsp;(pipeline),&nbsp;GST_STATE_NULL);<br />&nbsp;&nbsp;&nbsp;&nbsp;gst_object_unref&nbsp;(GST_OBJECT&nbsp;(pipeline));<br />}<br /><br />int&nbsp;main&nbsp;(int&nbsp;argc,&nbsp;char&nbsp;*argv[])<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;gst_init&nbsp;(&argc,&nbsp;&argv);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(argc&nbsp;&gt&nbsp;1)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;play_uri&nbsp;(argv);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;<br />}

sodwell 发表于 2008-9-11 08:34

re

LS,你上面那个Streamer库是播什么格式的?

ifree64 发表于 2008-9-11 18:20

回sodwell

mp3是有损格式,不太想搞。

sinanjj 发表于 2008-9-11 19:55

学习关注,

同时顶一下

talent8791 发表于 2008-9-22 13:42

c5435 发表于 2008-9-28 20:29

ding

页: [1]
查看完整版本: Linux下编写了一个小程序,播放wav文件成功。