在网上看了很多的说法,但是还是有点模糊,涉及到很多的数学公式和他的存储方式
我也是在网上找到的资料,根大家分享一下,本人编译并执行成功过。如果涉及到侵权,本人马上删除。
首先说一下读取PCM格式的音频播放:
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/ioctl.h>
#include<sys/soundcard.h>
//wav format
typedef struct _WAVEFILE_HEADER//波形文件头结构体
{
char ChunkID[4]; //"RIFF"
long int ChunkSize; //整个文件大小-8bytes
char Format[4]; //"wave"
char Subchunk1ID[4]; //"fmt" 表示以下是format chunck
long int Subchunk1Size; //格式数据的字节数 一般是16,特殊的也有18
short AudioFormat; //编码方式
short NumChannels; //声道数量
long int SampleRate; //采样率
long int ByteRate; //每秒所需字节数
short BlockAlign; //每次采样需要的字节数
short BitsPerSample; //每个采样需要的bit数
char Subchunk2ID[4]; //'data'字符串,标识以下是数据
long Subchunk2Size; //数据的大小
}WAVEFILE_HEADER;
///安装dsp 设置 采样率 声道个数
int setup_dsp(int dsp_fd,int rate,int channels)
{
int format;
int tmpchannels=2;
int tmprate = 44100;
if( ioctl(dsp_fd, SNDCTL_DSP_STEREO, &tmpchannels) == -1 ) //SOUND_PCM_WRITE_CHANNELS
{
perror("ioctl sterr failed");
return -1;
}
switch(tmpchannels)
{
case 0:
format = AFMT_U8;
printf("format = %d\n", AFMT_U8);
break;
case 1:
case 2:
format = AFMT_S16_LE;
printf("format = %d\n", AFMT_S16_LE);
break;
default:
perror("unsuport channels");
return -1;
}
if(ioctl(dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)//SOUND_PCM_WRITE_BITS
{
perror("ioctl set formalt");
return -1;
}
if(ioctl(dsp_fd, SNDCTL_DSP_SPEED, &tmprate) == -1)//SOUND_PCM_WRITE_RATE
{
perror("ioctl set_speed failed");
return -1;
}
return 0;
}
///设置同步播放
int sync_dsp(int dsp_fd)
{
if(ioctl(dsp_fd, SNDCTL_DSP_SYNC) != 0)
{
perror("ioctl sync failed");
return -1;
}
return 0;
}
int play_music(char* music_name )
{
WAVEFILE_HEADER head;
FILE* music_fp;
int music_len;
long rate;
char* buf;
long n;
int dsp_fd;
//打开 alarm.wav音乐文件music_name
music_fp = fopen("15.wav", "rb");
if(music_fp == NULL)
{
perror("fopen music file failed");
return -1;
}
//读取音乐文件头
if(fread(&head,sizeof(head),1,music_fp) != 1 )
{
perror("fread head err");
return -1;
}
printf("ChunkID=%s, ChunkSize=%ld, Format=%s, \
Subchunk1ID=%s \nSubchunk1Size=%ld, AudioFormat=%d, \
NumChannels=%d, SampleRate=%ld, \nByteRate=%ld, BlockAlign=%d, \
BitsPerSample=%d, Subchunk2ID=%s, Subchunk2Size=%ld\n",\
head.ChunkID, head.ChunkSize, head.Format, \
head.Subchunk1ID, head.Subchunk1Size, head.AudioFormat, \
head.NumChannels, head.SampleRate, head.ByteRate, \
head.BlockAlign, head.BitsPerSample, head.Subchunk2ID, head.Subchunk2Size);
//验证文件头
/*if(memcmp(&head.ChunkID,"RIFF",4) != 0 )
{
perror("music head chunkId err");
return -1;
}
//验证比特率
if(head.BitsPerSample == 24)
{
perror("unsuport samply size ");
return -1;
}*/
//music_len = head.ChunkSize+8;
music_len = 35039456+8;
printf("music_len :%d\n",music_len);
//打开声卡
dsp_fd = open("/dev/dsp",O_WRONLY);
if(dsp_fd< 0)
{
perror("open dsp err");
exit(0);
}
///安装dsp 设置 采样率 声道个数
if(setup_dsp(dsp_fd,head.SampleRate,head.NumChannels) != 0)
{
perror("setup_dsp failed");
return -1;
}
生效setup_dsp设置
if(sync_dsp(dsp_fd) != 0)
{
perror("sync dsp failed");
return -1;
}
//-----设置采样率--------
//采样位数*采样率/8 = 字节数量
//+7 方式采样率不是8的整数倍的情况
// /8*2 = /4 都按照双声道处理
//size = (head.BitsPerSample*head.SampleRate+7)>>2;
//rate = head.ByteRate; //每次读取的字节 = 字节速率
//rate = head.SampleRate * head.BitsPerSample * head.NumChannels >>2;
rate = 352800;
buf = (char*)malloc(rate); //音乐数据缓存
printf("rate:%ld\n", rate);
//打印需要播放的总时间
//printf("music time:%d\n",head.Subchunk2Size/head.ByteRate);
if(buf != NULL)
{
//int i = 10;
do{
n = fread(buf, 1, rate, music_fp);
printf("n:%ld\n",n);
if(n > 0)
{
write(dsp_fd, buf, n);
}
if(feof(music_fp))
{
printf("play over!\n");
break;
}
}while(1);
fclose(music_fp);
}
}
int main(int argc,char** argv)
{
play_music(argv[1]);
return 0;
}
接下来是MP3的解码程序:
显示解码表dewindow.txt
D[ 0]= 0.000000000 D[ 1]=-0.000015259 D[ 2]=-0.000015259 D[ 3]=-0.000015259
D[ 4]=-0.000015259 D[ 5]=-0.000015259 D[ 6]=-0.000015259 D[ 7]=-0.000030518
D[ 8]=-0.000030518 D[ 9]=-0.000030518 D[ 10]=-0.000030518 D[ 11]=-0.000045776
D[ 12]=-0.000045776 D[ 13]=-0.000061035 D[ 14]=-0.000061035 D[ 15]=-0.000076294
D[ 16]=-0.000076294 D[ 17]=-0.000091553 D[ 18]=-0.000106812 D[ 19]=-0.000106812
D[ 20]=-0.000122070 D[ 21]=-0.000137329 D[ 22]=-0.000152588 D[ 23]=-0.000167847
D[ 24]=-0.000198364 D[ 25]=-0.000213623 D[ 26]=-0.000244141 D[ 27]=-0.000259399
D[ 28]=-0.000289917 D[ 29]=-0.000320435 D[ 30]=-0.000366211 D[ 31]=-0.000396729
D[ 32]=-0.000442505 D[ 33]=-0.000473022 D[ 34]=-0.000534058 D[ 35]=-0.000579834
D[ 36]=-0.000625610 D[ 37]=-0.000686646 D[ 38]=-0.000747681 D[ 39]=-0.000808716
D[ 40]=-0.000885010 D[ 41]=-0.000961304 D[ 42]=-0.001037598 D[ 43]=-0.001113892
D[ 44]=-0.001205444 D[ 45]=-0.001296997 D[ 46]=-0.001388550 D[ 47]=-0.001480103
D[ 48]=-0.001586914 D[ 49]=-0.001693726 D[ 50]=-0.001785278 D[ 51]=-0.001907349
D[ 52]=-0.002014160 D[ 53]=-0.002120972 D[ 54]=-0.002243042 D[ 55]=-0.002349854
D[ 56]=-0.002456665 D[ 57]=-0.002578735 D[ 58]=-0.002685547 D[ 59]=-0.002792358
D[ 60]=-0.002899170 D[ 61]=-0.002990723 D[ 62]=-0.003082275 D[ 63]=-0.003173828
D[ 64]= 0.003250122 D[ 65]= 0.003326416 D[ 66]= 0.003387451 D[ 67]= 0.003433228
D[ 68]= 0.003463745 D[ 69]= 0.003479004 D[ 70]= 0.003479004 D[ 71]= 0.003463745
D[ 72]= 0.003417969 D[ 73]= 0.003372192 D[ 74]= 0.003280640 D[ 75]= 0.003173828
D[ 76]= 0.