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();

}

你可能感兴趣的:(C语言)