C语言播放音乐
此程序可以播放采样率22050Hz,量化位8,立体声,PCM编码格式的WAV文件,带波形显示功能,还有部分功能没有实现,有待完善。。。
#include <stdio.h> #include <stdlib.h> #include <dos.h> #include <conio.h> #include <string.h> #include <graphics.h> #define buffer_size 40000 typedef struct head { unsigned long RIFF; /*RIFF*/ unsigned long size; /*从下个字节到文件尾的总字节数*/ unsigned long WAVA; /*WAVA*/ unsigned long fmt; /*fmt*/ unsigned long nothing; /*过滤字节*/ unsigned int codetype; /*编码方式*/ unsigned int channels; /*声道数*/ unsigned long SamplesRate; /*采样频率*/ unsigned long BPS; /*比特率*/ unsigned int BlockAlign; /*采样一次占字节数*/ unsigned int BitPerSamples; /*采样位数*/ unsigned long DATA; /*data*/ unsigned long wav_len; /*数据区长度*/ unsigned char *data; /*数据区*/ } HEAD; HEAD *wav_head; FILE *wav_file; unsigned char *buffer; unsigned int DSP_port; unsigned int DSP_intnum; unsigned int DMA_channel; unsigned long wav_remain; unsigned char mode_flag; void URL_convert(char* old_URL); void wav_open(char *wav_URL); void wav_check(void); int DSP_reset(int port); void DSP_find(void); void DSP_write(unsigned char value); void DSP_init(void); void interrupt (*INT_oldfunc)(void); void interrupt INT_newfunc(void); void INT_install(void); void INT_resume(void); void PIC_init(void); void PIC_close(void); void DSP_play(void); void DSP_stop(void); void DMA_init(void); void DMA_close(void); void wav_play(void); void wav_stop(void); void Video_mode(void); int main(int argc,char *argv[]) { char URL[100]; int n; if(argc!=1) { strcpy(URL,argv[1]); } else { system("dir *.wav"); printf("Please input filename [.wav]:\t"); gets(URL); } /*URL_convert(URL);*/ wav_open(URL); wav_check(); if((buffer=(unsigned char *)malloc(buffer_size))==NULL) { printf("memary not enough!\n"); getch(); exit(5); } wav_play(); while(wav_remain>=buffer_size) { if(mode_flag==89||mode_flag==121) { if(!kbhit()) { int y1[640]={0},y2[640]={0}; int n; for(n=0;n<640;n++) { y1[n]=((int)(buffer[n*2])); y2[n]=((int)(buffer[n*2+1])); putpixel(n,y1[n],YELLOW); /*输出左声道波形*/ putpixel(n,y2[n],GREEN); /*输出右声道波形*/ } for(n=0;n<1000;n++) delay(100); /*延时*/ for(n=0;n<640;n++) { putpixel(n,y1[n],BLACK); putpixel(n,y2[n],BLACK); } /* cleardevice(); */ } else if(getch()==27) { break; } } else { if(!kbhit()) { printf("times remain %d s\t\r",wav_remain/wav_head->BPS); for(n=0;n<1000;n++) delay(100); } else if(getch()==27) { break; } } } wav_stop(); free(buffer); free(wav_file); system("pause"); return 0; } void wav_play(void) { DSP_init(); PIC_init(); INT_install(); fseek(wav_file,sizeof(HEAD),SEEK_SET); fread((void*)buffer,buffer_size,1,wav_file); DMA_init(); printf("\nShow the wave pattern [Y/N]?\t"); mode_flag=getchar(); if(mode_flag==89||mode_flag==121) { Video_mode(); sleep(3); } DSP_play(); } void wav_stop(void) { if(mode_flag==89||mode_flag==121) { cleardevice(); closegraph(); } PIC_close(); INT_resume(); DMA_close(); DSP_stop(); printf("wav stop......OK\n"); } void URL_convert(char* old_URL) { unsigned int m=0,n=0; char new_URL[100]; for(m=0,n=0;n<=strlen(old_URL)+1;m++,n++) { new_URL[m]=old_URL[n]; if(old_URL[n]=='\\') new_URL[++m]=old_URL[n]; } if(strlen(new_URL)>=100) { printf("URL too long!\n"); system("pause"); exit(1); } else { printf("URL convert......OK\n"); } strcpy(old_URL,new_URL); } void wav_open(char *wav_URL) { if((wav_file=fopen(wav_URL,"rb"))==NULL) { printf("Can not open the file!\n"); system("pause"); exit(1); } else { printf("Open file......OK\n"); return; } } void wav_check(void) { fread(wav_head,sizeof(HEAD),1,wav_file); if(wav_head->RIFF==0x46464952&&wav_head->fmt==0x20746D66&&wav_head->DATA==0x61746164) { printf("Check file......OK\n"); printf("\n********************************\n"); printf("\twav_len: %ld\n",wav_head->wav_len); printf("\tBitPerSamples: %d\n",wav_head->BitPerSamples); printf("\tBlockAlign: %d\n",wav_head->BlockAlign); printf("\tchannels: %d\n",wav_head->channels); printf("\tSamplesRate: %ld\n",wav_head->SamplesRate); printf("\tBPS: %ld\n",wav_head->BPS<<3); printf("********************************\n\n"); wav_remain=wav_head->wav_len; return; } else { printf("This is not a correct WAV file!\n"); system("pause"); exit(2); } } int DSP_reset(int port) { outportb(port+0x6,1); delay(50); outportb(port+0x6,0); delay(150); if(inportb(port+0xE)&0x80==0x80&&inportb(port+0xA)==0xAA) { DSP_port=port; DSP_intnum=5; DMA_channel=1; return 1; } else { return 0; } } void DSP_find(void) { int Port[6]={0x210,0x220,0x230,0x240,0x250,0x260}; int n; for(n=0;n<6;n++) { if(DSP_reset(Port[n])) { printf("DSP find at port %X.....OK\n",Port[n]); return; } } printf("DSP not find!\n"); system("pause"); exit(3); } void DSP_write(unsigned char value) { while((inportb(DSP_port+0xC)&0x80)==0x80); /*等待DSP接收一个字节*/ outportb(DSP_port+0xC,value); /*发送字节*/ } void DSP_init(void) { unsigned int rate; if(getenv("BLASTER")==NULL) { char env[30]={0}; strcpy(env,getenv("BLASTER")); printf("%s\n",env); /* 待处理部分 */ system("pause"); exit(0); } else { printf("Variable not find in the environment\n"); printf("Process will search the DSP......\n"); DSP_find(); } rate=(65536L-256000000L/(wav_head->SamplesRate*wav_head->channels)); DSP_write(0x48); /*设置DSP播放块的大小*/ DSP_write((buffer_size-1)&0xFF); DSP_write((buffer_size-1)>>8); DSP_write(0x40); DSP_write(rate>>8); /*设置DSP播放速率*/ printf("DSP init......OK\n"); } void interrupt INT_newfunc(void) { wav_remain-=buffer_size; fread((void*)buffer,1,buffer_size,wav_file); outportb(0x20,0x20); /*写中断结束命令*/ } void INT_install(void) { disable(); INT_oldfunc=getvect(DSP_intnum+8); setvect(DSP_intnum+8,INT_newfunc); enable(); printf("INT install......OK\n"); } void INT_resume(void) { disable(); setvect(DSP_intnum+8,INT_oldfunc); INT_oldfunc=NULL; enable(); printf("INT resume......OK\n"); } void PIC_init(void) { unsigned char mask; mask=inportb(0x21); mask&=~(DSP_intnum); outportb(0x21,mask); printf("PIC init......OK\n"); } void PIC_close(void) { unsigned char mask; mask=inportb(0x21); mask|=(1<<DSP_intnum); outportb(0x21,mask); printf("PIC close......OK\n"); } void DSP_play(void) { DSP_write(0x1C); } void DSP_stop(void) { DSP_write(0xD0); printf("DSP stop......OK\n"); } void DMA_init(void) { unsigned long LineAddress=FP_SEG(buffer)*0x10L+FP_OFF(buffer); unsigned char page=(unsigned char)(LineAddress>>16); unsigned short offset=(LineAddress>>0); outportb(0x0A,DMA_channel|(1<<2)); /*锁定通道*/ outportb(0x0B,DMA_channel|(1<<4)|(2<<2)); /*设置回放模式*/ outportb(0x0C,0); /*清除DMA内部翻转标志*/ outportb(0x03,(buffer_size-1)&0xFF); /*设置传送数据的大小*/ outportb(0x03,(buffer_size-1)>>8); outportb(0x83,page); /*将段地址写入DMA控制器*/ outportb(0x02,(offset)&0xFF); /*将偏移量写入DMA控制器*/ outportb(0x02,(offset)>>8); outportb(0x0A,DMA_channel); /*解锁DMA通道*/ printf("DAM init......OK\n"); return; } void DMA_close(void) { outportb(0x0A,DMA_channel|(1<<2)); printf("DAM close......OK\n"); } void Video_mode(void) { int gdrive=DETECT,gmode=0; registerbgidriver(EGAVGA_driver); initgraph(&gdrive,&gmode,""); cleardevice(); }