WAVE.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:8k
- /*
- * wave - crudely play Windows WAV files while preemptive multithreading
- * - if -sb option given, outputs directly through soundblaster card
- * - demonstrates hooking the timer tick
- * - demonstrates messaging between ISR and a thread
- *
- * Copyright (c) 1999 Erick Engelke
- *
- * This is a very crude program which reads Windows WAV files and
- * attempts to convert them to 1-BIT speaker output, or 8-BIT SoundBlaster.
- *
- * NOTE: only 8 bit WAV files supported.
- */
- #include <stdio.h>
- #include <mem.h>
- #include <process.h>
- #include <ctype.h>
- #include <conio.h>
- #include <dos.h>
- #include <rtos.h>
- #include <string.h>
- /*------------------ structure of a WAV file ------------------------*/
- typedef struct {
- BYTE wav_riff[4]; // "RIFF"
- DWORD wav_chunksize;
- BYTE wav_wave[4]; // "WAVE"
- } wav_hdr;
- typedef struct {
- char bID[4];
- DWORD dwSize;
- } chunk_str;
- typedef struct {
- WORD wFormatTag; // 1 = WAVE_FORMAT_PCM
- WORD wChannels; // 1 = mono
- DWORD dwSamplesPerSec; // sampling rate
- DWORD dwAvgBYTEsPerSec; // for buffer estimation
- WORD wBlockAlign; // data block size
- } fmt_str;
- /*--------------------- global variables ----------------------------*/
- WORD soundskip;
- WORD soundposn;
- BYTE *sounddata;
- WORD soundlength;
- BYTE soundthreshhold = 120;
- /*--------------------- global functions ----------------------------*/
- void settimer( void (*x)() )
- {
- disable();
- k_user_int8 = x;
- enable();
- }
- /*------------------ Sound Blaster Functions --------------------------*/
- int use_sb = 0;
- WORD sb_base = 0;
- /*
- * Offsets relative to base I/O address.
- */
- #define SB_DSP_RESET 0x06
- #define SB_DSP_READ_DATA 0x0A
- #define SB_DSP_WRITE_DATA 0x0C
- #define SB_DSP_WRITE_STATUS 0x0C
- #define SB_DSP_DATA_AVAIL 0x0E
- /* DSP Commands */
- #define SB_DIRECT_8_BIT_DAC 0x10
- #define SB_SPEAKER_ON 0xD1
- #define SB_SPEAKER_OFF 0xD3
- #define SB_DSP_ID 0xE0
- #define SB_DSP_VER 0xE1
- void sb_writedac(BYTE x)
- {
- while(inportb(sb_base + SB_DSP_WRITE_STATUS) & 0x80);
- outportb(sb_base + SB_DSP_WRITE_DATA, x);
- }
- void sb_init( void )
- {
- WORD port;
- WORD count, count2;
- for ( port = 0x210 ; port <= 0x260 ; port += 0x10 ) {
- count = 10;
- while ( count != 0 ) {
- outportb( port + 0x6, 1 ); /* reset SB */
- for ( count2 = 0 ; count2 < 100 ; ++count2 );
- outportb( port + 0x6, 0 );
- for ( count2 = 50 ;
- (count2 !=0 ) && ( inportb( port + 0xe ) < 128 ) ;
- count2-- );
- if ( ( count2 == 0 ) || ( inportb( port + 0xa ) != 0xaa )) {
- count--;
- if ( count != 0 ) continue;
- else break;
- } else {
- sb_base = port;
- cprintf("Sound Blaster found found at port 0x%xrn", port );
- /* enable speaker */
- sb_writedac( SB_SPEAKER_ON );
- return;
- }
- }
- }
- }
- void sb_code( BYTE value )
- {
- sb_writedac( 0x10 );
- sb_writedac( value );
- }
- /*------------------ support functions ------------------------------*/
- int read_wav_hdr( FILE *f, wav_hdr *wav )
- {
- if ( fread( wav, sizeof( wav_hdr ), 1 , f ) < 1 ) {
- cputs( "unable to read the headerrn");
- return( 0 );
- }
- /* see if RIFF format */
- if ( memcmp( wav->wav_riff , "RIFF", 4 ) != 0 ) {
- cputs( "not RIFF formatrn");
- return( 0 );
- }
- /* see if WAVE subformat */
- if ( memcmp( wav->wav_wave, "WAVE", 4 ) != 0 ) {
- cputs( "not WAVE subformatrn");
- return( 0 );
- }
- return( 1 );
- }
- int read_chunk( FILE *f, chunk_str *ch )
- {
- if ( fread( ch, sizeof( chunk_str), 1 , f ) < 1 ) {
- cputs( "unable to read a chunkrn");
- return( 0 );
- }
- return( 1 );
- }
- int read_fmt( FILE *f, fmt_str *fmt )
- {
- if ( fread( fmt, sizeof( fmt_str), 1 , f ) < 1 ) {
- cputs( "unable to read the fmt headerrn");
- return( 0 );
- }
- if ( fmt->wFormatTag != 1 ) {
- cputs( "not WAVE_FORMAT_PCM rn");
- return( 0 );
- }
- return( 1 );
- }
- void interrupt_time_player( void )
- {
- static int inside = 0;
- BYTE prevval, b;
- if ( inside == 0 ) {
- inside = 1;
- if ( soundposn < soundlength ) {
- b = sounddata[ soundposn ];
- if ( use_sb ) sb_code( b );
- else {
- prevval = inportb( 0x61 );
- b = (prevval & 0xFC) | (( b > soundthreshhold) ? 2 : 0) ;
- if ( b != prevval )
- outportb( 0x61, b );
- }
- soundposn += soundskip;
- if ( soundposn >= soundlength )
- ksendmessage( kmainthread, 0, 0 );
- }
- inside = 0;
- }
- }
- void audio_play( WORD channels, DWORD rate, BYTE *data, WORD length )
- {
- int value;
- DWORD tempdata;
- soundposn = 0;
- soundlength = length;
- sounddata = data;
- if ( rate > 10000 ) rate = 10000; /* we are only accurate to 0.1 kHz */
- soundskip = channels;
- rt_timerfreq( rate );
- /* invoke the player */
- settimer( interrupt_time_player );
- /* wait until it's done */
- kreadmessage( &value, &tempdata );
- /* remove the player */
- settimer( NULL );
- }
- play( char *fname )
- {
- FILE *f;
- wav_hdr wav;
- chunk_str chunk;
- fmt_str fmt;
- DWORD posn;
- BYTE *data;
- int samples_per_data;
- if ( (f = fopen( fname, "rb")) == NULL ) {
- cprintf( "unable to open WAV file %s", fname);
- return;
- }
- if ( ! read_wav_hdr( f, &wav )) return;
- do {
- if ( ! read_chunk( f, &chunk ))
- break;
- posn = ftell( f );
- if ( !memcmp(chunk.bID,"fmt ", 4 ))
- if ( ! read_fmt( f, &fmt ))
- break;
- if ( !memcmp(chunk.bID,"data", 4 )) {
- data = kcalloc( 1, chunk.dwSize );
- if ( data != NULL ) {
- fread( data, chunk.dwSize, 1 , f );
- samples_per_data = fmt.wChannels * fmt.wBlockAlign;
- cprintf("%u channels, %u align n",
- fmt.wChannels, fmt.wBlockAlign);
- audio_play( samples_per_data , fmt.dwSamplesPerSec,
- data, chunk.dwSize );
- kfree( data );
- }
- break;
- }
- fseek( f, posn + chunk.dwSize , SEEK_SET);
- } while ( 1 );
- fclose( f );
- return;
- }
- /*
- * consolethread - just dumps stuff to console for visual effect
- */
- void consolethread( DWORD data )
- {
- int i = 0;
- if ( data == 1 )
- kwindow( 1, 1, 40, 15 );
- else
- kwindow( 40, 1, 80, 15 );
- /* infinite loop */
- do {
- cprintf(" %u", i++ );
- } while ( 1 );
- }
- int main( int argc, char **argv )
- {
- int i;
- kpreemptive = 1;
- kdebug = 1;
- rt_init( 100 );
- clrscr();
- kwindow( 1, 15, 80, 25 );
- sb_init();
- if ( argc < 2 ) {
- cputs("WAVE [-sb] wavefile1.WAV ... rn");
- cputs(" -sb means use SoundBlasterrn");
- return;
- }
- /* create a few threads for visual threading effect */
- rt_newthread( consolethread, 1, 4096, 0, "console thread #1" );
- rt_newthread( consolethread, 2, 4096, 0, "console thread #2" );
- for ( i = 1 ; i < argc ; ++i ) {
- if ( !stricmp( argv[i], "-sb")) {
- if (sb_base == 0 ) rt_halt("no SoundBlaster card, cannot use -sb option");
- use_sb = 1;
- cputs("Using SoundBlasterrn");
- continue;
- } else {
- cprintf("playing : %s ...", argv[i] );
- play( argv[i] );
- cputs("donenr");
- }
- rt_sleep( 1000 );
- }
- return( 0 );
- }