• 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();
    }
  • 相关阅读:
    用纹理贴图模拟反射,NeHe23课球面映射相关
    VS2010: CommandLine Warning D9025
    【转】C RunTime Library 暨 深入理解编译选项的含义 01
    让Doxygen输出中文注释不乱码
    windows环境下memcache配置
    C#中英文字符长度截取
    apache 的工作原理
    pear包安装phpunit
    使用 libevent 和 libev 提高网络应用性能
    PHP发明人谈MVC和网站设计架构——貌似他不支持php用mvc
  • 原文地址:https://www.cnblogs.com/hrkblogs/p/3047514.html
Copyright © 2020-2023  润新知