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();
}
原文地址:https://www.cnblogs.com/hrkblogs/p/3047514.html