#include<stdio.h> #include<stdlib.h> #include <string.h> #include <alsa/asoundlib.h> struct WAV_HEADER { char rld[4]; //riff 標志符號 int rLen; char wld[4]; //格式類型(wave) char fld[4]; //"fmt" int fLen; //sizeof(wave format matex) short wFormatTag; //編碼格式 short wChannels; //聲道數 int nSamplesPersec ; //采樣頻率 int nAvgBitsPerSample;//WAVE文件采樣大小 short wBlockAlign; //塊對齊 short wBitsPerSample; //WAVE文件采樣大小 char dld[4]; //”data“ int wSampleLength; //音頻數據的大小 } wav_header; int set_pcm_play(FILE *fp); int main(int argc,char *argv[]) { if(argc!=2) { printf("Usage:wav-player+wav file name\n"); exit(1); } int nread; FILE *fp; fp=fopen(argv[1],"rb"); if(fp==NULL) { perror("open file failed:\n"); exit(1); } nread=fread(&wav_header,1,sizeof(wav_header),fp); printf("nread=%d\n",nread); //printf("RIFF 標志%s\n",wav_header.rld); printf("文件大小rLen:%d\n",wav_header.rLen); //printf("wld=%s\n",wav_header.wld); //printf("fld=%s\n",wav_header.fld); // printf("fLen=%d\n",wav_header.fLen); //printf("wFormatTag=%d\n",wav_header.wFormatTag); printf("聲道數:%d\n",wav_header.wChannels); printf("采樣頻率:%d\n",wav_header.nSamplesPersec); //printf("nAvgBitsPerSample=%d\n",wav_header.nAvgBitsPerSample); //printf("wBlockAlign=%d\n",wav_header.wBlockAlign); printf("采樣的位數:%d\n",wav_header.wBitsPerSample); // printf("data=%s\n",wav_header.dld); printf("wSampleLength=%d\n",wav_header.wSampleLength); set_pcm_play(fp); return 0; } int set_pcm_play(FILE *fp) { int rc; int ret; int size; snd_pcm_t* handle; //PCI設備句柄 snd_pcm_hw_params_t* params;//硬件信息和PCM流配置 unsigned int val; int dir=0; snd_pcm_uframes_t frames; char *buffer; int channels=wav_header.wChannels; int frequency=wav_header.nSamplesPersec; int bit=wav_header.wBitsPerSample; int datablock=wav_header.wBlockAlign; unsigned char ch[100]; //用來存儲wav文件的頭信息 rc=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if(rc<0) { perror("\nopen PCM device failed:"); exit(1); } snd_pcm_hw_params_alloca(¶ms); //分配params結構體 if(rc<0) { perror("\nsnd_pcm_hw_params_alloca:"); exit(1); } rc=snd_pcm_hw_params_any(handle, params);//初始化params if(rc<0) { perror("\nsnd_pcm_hw_params_any:"); exit(1); } rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //初始化訪問權限 if(rc<0) { perror("\nsed_pcm_hw_set_access:"); exit(1); } //采樣位數 switch(bit/8) { case 1:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8); break ; case 2:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); break ; case 3:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE); break ; } rc=snd_pcm_hw_params_set_channels(handle, params, channels); //設置聲道,1表示單聲>道,2表示立體聲 if(rc<0) { perror("\nsnd_pcm_hw_params_set_channels:"); exit(1); } val = frequency; rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //設置>頻率 if(rc<0) { perror("\nsnd_pcm_hw_params_set_rate_near:"); exit(1); } rc = snd_pcm_hw_params(handle, params); if(rc<0) { perror("\nsnd_pcm_hw_params: "); exit(1); } rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir); /*獲取周期 長度*/ if(rc<0) { perror("\nsnd_pcm_hw_params_get_period_size:"); exit(1); } size = frames * datablock; /*4 代表數據快長度*/ buffer =(char*)malloc(size); fseek(fp,58,SEEK_SET); //定位歌曲到數據區 while (1) { memset(buffer,0,sizeof(buffer)); ret = fread(buffer, 1, size, fp); if(ret == 0) { printf("歌曲寫入結束\n"); break; } else if (ret != size) { } // 寫音頻數據到PCM設備 while(ret = snd_pcm_writei(handle, buffer, frames)<0) { usleep(2000); if (ret == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); //完成硬件參數設置,使設備准備好 snd_pcm_prepare(handle); } else if (ret < 0) { fprintf(stderr, "error from writei: %s\n", snd_strerror(ret)); } } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <alsa/asoundlib.h>
struct WAV_HEADER
{
char rld[4]; //riff 標志符號
int rLen;
char wld[4]; //格式類型(wave)
char fld[4]; //"fmt"
int fLen; //sizeof(wave format matex)
short wFormatTag; //編碼格式
short wChannels; //聲道數
int nSamplesPersec ; //采樣頻率
int nAvgBitsPerSample;//WAVE文件采樣大小
short wBlockAlign; //塊對齊
short wBitsPerSample; //WAVE文件采樣大小
char dld[4]; //”data“
int wSampleLength; //音頻數據的大小
} wav_header;
int set_pcm_play(FILE *fp);
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("Usage:wav-player+wav file name\n");
exit(1);
}
int nread;
FILE *fp;
fp=fopen(argv[1],"rb");
if(fp==NULL)
{
perror("open file failed:\n");
exit(1);
}
nread=fread(&wav_header,1,sizeof(wav_header),fp);
printf("nread=%d\n",nread);
//printf("RIFF 標志%s\n",wav_header.rld);
printf("文件大小rLen:%d\n",wav_header.rLen);
//printf("wld=%s\n",wav_header.wld);
//printf("fld=%s\n",wav_header.fld);
// printf("fLen=%d\n",wav_header.fLen);
//printf("wFormatTag=%d\n",wav_header.wFormatTag);
printf("聲道數:%d\n",wav_header.wChannels);
printf("采樣頻率:%d\n",wav_header.nSamplesPersec);
//printf("nAvgBitsPerSample=%d\n",wav_header.nAvgBitsPerSample);
//printf("wBlockAlign=%d\n",wav_header.wBlockAlign);
printf("采樣的位數:%d\n",wav_header.wBitsPerSample);
// printf("data=%s\n",wav_header.dld);
printf("wSampleLength=%d\n",wav_header.wSampleLength);
set_pcm_play(fp);
return 0;
}
int set_pcm_play(FILE *fp)
{
int rc;
int ret;
int size;
snd_pcm_t* handle; //PCI設備句柄
snd_pcm_hw_params_t* params;//硬件信息和PCM流配置
unsigned int val;
int dir=0;
snd_pcm_uframes_t frames;
char *buffer;
int channels=wav_header.wChannels;
int frequency=wav_header.nSamplesPersec;
int bit=wav_header.wBitsPerSample;
int datablock=wav_header.wBlockAlign;
unsigned char ch[100]; //用來存儲wav文件的頭信息
rc=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if(rc<0)
{
perror("\nopen PCM device failed:");
exit(1);
}
snd_pcm_hw_params_alloca(¶ms); //分配params結構體
if(rc<0)
{
perror("\nsnd_pcm_hw_params_alloca:");
exit(1);
}
rc=snd_pcm_hw_params_any(handle, params);//初始化params
if(rc<0)
{
perror("\nsnd_pcm_hw_params_any:");
exit(1);
}
rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //初始化訪問權限
if(rc<0)
{
perror("\nsed_pcm_hw_set_access:");
exit(1);
}
//采樣位數
switch(bit/8)
{
case 1:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
break ;
case 2:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
break ;
case 3:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE);
break ;
}
rc=snd_pcm_hw_params_set_channels(handle, params, channels); //設置聲道,1表示單聲>道,2表示立體聲
if(rc<0)
{
perror("\nsnd_pcm_hw_params_set_channels:");
exit(1);
}
val = frequency;
rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //設置>頻率
if(rc<0)
{
perror("\nsnd_pcm_hw_params_set_rate_near:");
exit(1);
}
rc = snd_pcm_hw_params(handle, params);
if(rc<0)
{
perror("\nsnd_pcm_hw_params: ");
exit(1);
}
rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir); /*獲取周期
長度*/
if(rc<0)
{
perror("\nsnd_pcm_hw_params_get_period_size:");
exit(1);
}
size = frames * datablock; /*4 代表數據快長度*/
buffer =(char*)malloc(size);
fseek(fp,58,SEEK_SET); //定位歌曲到數據區
while (1)
{
memset(buffer,0,sizeof(buffer));
ret = fread(buffer, 1, size, fp);
if(ret == 0)
{
printf("歌曲寫入結束\n");
break;
}
else if (ret != size)
{
}
// 寫音頻數據到PCM設備
while(ret = snd_pcm_writei(handle, buffer, frames)<0)
{
usleep(2000);
if (ret == -EPIPE)
{
/* EPIPE means underrun */
fprintf(stderr, "underrun occurred\n");
//完成硬件參數設置,使設備准備好
snd_pcm_prepare(handle);
}
else if (ret < 0)
{
fprintf(stderr,
"error from writei: %s\n",
snd_strerror(ret));
}
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}