时间: 2021-07-31 作者:daque
#include "alloc.h" #include "dos.h" #include "conio.h" #include "stdio.h" void playwav(char wavefile[14],float delaytime); struct wavedata { unsigned int soundlength, frequency; char *sample; }; struct headertype { long riff; //riff header char ni1 [18]; //not important unsigned int channels; //channels 1 = mono; 2 = stereo long frequency; //sample frequency char ni2 [6]; //not important char bitres; //bit resolution 8/16 bit char ni3 [12]; //not important } header; struct wavedata voice; //pointer to wave file unsigned int base; //sound blaster base address char wavefile [25]; //file name for the wave file to be played /**************************************************************************** ** checks to see if a sound blaster exists at a given address, returns ** ** true if sound blaster found, false if not. ** ****************************************************************************/ int resetdsp(unsigned int test) { //reset the dsp outportb (test + 0x6, 1); delay(10); outportb (test + 0x6, 0); delay(10); //check if (reset was succesfull if ((inportb(test + 0xe) & 0x80 == 0x80) && (inportb(test + 0xa) == 0xaa)) { //dsp was found base = test; return (1); } else //no dsp was found return (0); } /**************************************************************************** ** send a byte to the dsp (digital signal processor) on the sound blaster ** ****************************************************************************/ void writedsp(unsigned char value) { //wait for the dsp to be ready to accept data while ((inportb(base + 0xc) & 0x80) == 0x80); //send byte outportb (base + 0xc, value); } /**************************************************************************** ** plays a part of the memory ** ****************************************************************************/ void playback (struct wavedata *wave) { long linearaddress; unsigned int page, offset; unsigned char timeconstant; timeconstant = (65536 - (256000000 / wave->frequency)) >> 8; writedsp(0x40); //dsp-command 40h - set sample frequency writedsp(timeconstant); //write time constant //convert pointer to linear address linearaddress = fp_seg (wave->sample); linearaddress = (linearaddress << 4) + fp_off (wave->sample); page = linearaddress >> 16; //calculate page offset = linearaddress & 0xffff; //calculate offset in the page /* note - this procedure only works with dma channel 1 */ outportb (0x0a, 5); //mask dma channel 1 outportb (0x0c, 0); //clear byte pointer outportb (0x0b, 0x49); //set mode /* the mode consists of the following: 0x49 = binary 01 00 10 01 | | | | | | | +- dma channel 01 | | +---- read operation (the dsp reads from memory) | +------- single cycle mode +---------- block mode */ outportb (0x02, offset & 0x100); //write the offset to the dma controller outportb (0x02, offset >> 8); outportb (0x83, page); //write the page to the dma controller outportb (0x03, wave->soundlength & 0x100); outportb (0x03, wave->soundlength >> 8); outportb (0x0a, 1); //unmask dma channel writedsp(0x14); // dsp-command 14h - single cycle playback writedsp(wave->soundlength & 0xff); writedsp(wave->soundlength >> 8); } /**************************************************************************** ** loads a wave file into memory. ** ** this procedure expects a _very_ standard wave header. ** ** it doesn't perform much error checking. ** ****************************************************************************/ int loadvoice (struct wavedata *voice, char *filename) { file *wavfile; //if it can't be opened... wavfile = fopen(filename, "rb"); if (wavfile == null) { //..display error message return (0); } //return length of file for sound length minus 48 bytes for .wav header fseek(wavfile, 0l, seek_end); voice->soundlength = ftell (wavfile) - 48; fseek(wavfile, 0l, seek_set); //check riff header if (voice->soundlength > 32000) { if (voice->soundlength > 64000) { voice->soundlength = 64000; } } free(voice->sample); voice->sample = (char *)malloc(voice->soundlength); //assign memory if (!voice->sample) { return (0); } //load the sample data fread(&header, 46, 1, wavfile); //check riff header if (header.riff != 0x46464952) { printf ("not a wave file\n"); return (0); } //check channels if (header.channels != 1) { printf ("not a mono wave file\n"); return (0); } //check bit resolution if (header.bitres != 8) { printf ("not an 8-bit wave file\n"); return (0); } voice->frequency = header.frequency; //load the sample data fread(voice->sample, voice->soundlength + 2, 1, wavfile); fclose (wavfile); //close the file return (1); } void playwav (char wavefile[14], float delaytime = 1.0 ) { if (resetdsp (0x220)) { //at 220h printf (""); } else { if (resetdsp (0x240)) { //at 240h printf (""); } else { //or none at all printf (""); return; } } //load wave file if (loadvoice (&voice, wavefile)) { //start playback playback (&voice); delay(delaytime*1000); //stops dma-transfer writedsp (0xd0); } }