home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Game Developers Magazine 3
/
GDM003.ZIP
/
VOC-IT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-16
|
8KB
|
291 lines
/*
VOC-IT.C - Plays soundblaster .VOC files through PC speaker.
Also works with Windows .WAV files, and all other types of
digital sound file, I expect.
Written by Phil Inch for Game Developers Magazine (issue 3).
Contributed to the public domain. If you use this program
or a derivation thereof in your own programs, please put in
a credit for me and/or the magazine.
Thanks to Dave Harvey for suggesting a better oversampling
method than I had, which has increased the maximum size of
the file playable to be the limit of available memory!
This program written and compiled with Borland C++ v3.1 and
Turbo Assembler v3.0. Compatibility with other compilers is
not guaranteed.
Usage of this program is subject to the disclaimer printed
in the magazine. You assume all risks associated with the use
of this program.
Known problems: In order to be able to run the timer at such
a high rate without upsetting the rest of the processes running
in the machine (eg: screen savers), this program simply shuts
down the clock, so while a sound is playing, your real time
clock will not be updated.
I'm sure there's a way around this, but my experiments with
calling the original Int 8 handler at the correct rate
introduced an unacceptable level of "noise" into the playback.
If any reader knows a better way of handling this problem,
please send it to me care of the magazine.
Usage: VOC-IT filename[.VOC] [/F:f] [/O:o] [/M:m] [/?]
where:
f = frequency in Hz, default 16000
o = oversample rate, default 1
m = muting factor (almost always 2), default 2
*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <alloc.h>
#include <dos.h>
#include <io.h>
/* The ranges and defaults for the parameters */
#define MIN_FREQ 1
#define MAX_FREQ 32000
#define DEF_FREQ 16000
#define MIN_OVER 1
#define MAX_OVER 6
#define DEF_OVER 1
#define MIN_MUTE 0
#define MAX_MUTE 6
#define DEF_MUTE 2
/* This structure holds everything we want to know about the VOC file */
typedef struct {
char filename[64];
char huge *data;
long frequency;
long file_length;
long sample_length;
} VOCFILE;
/* Functions in the assembler file */
extern void interrupt NewInt8Function( void );
extern void PlaySound( char huge *, int, int );
/* Interrupt pointer which will "remember" where the old int 8 routine is */
void interrupt (*OldInt8Function)();
/* Declare global variables with "default" values */
long frequency = DEF_FREQ;
int oversample = DEF_OVER;
int mute = DEF_MUTE;
char filename[64] = "\0";
/* Load_Voc opens and reads the named VOC file, and returns a pointer to
a VOCFILE structure which has been filled in. If the file cannot be
opened, or the memory cannot be allocated, Load_Voc returns NULL */
VOCFILE *Load_Voc( char *filename ) {
VOCFILE *vf;
FILE *f;
long fl, cfl;
char ch;
char huge *fptr;
int cnt;
/* Allocate memory for the VOCFILE structure */
vf = malloc( sizeof(VOCFILE) );
if ( vf == NULL ) return ( (VOCFILE *)NULL );
strcpy( vf->filename, filename );
/* Open the VOC file */
f = fopen( filename, "rb" );
if ( f == NULL ) {
free( vf );
return ( (VOCFILE *)NULL );
}
/* Get the length, and allocate memory for the file */
fl = filelength( fileno(f) ) - 26;
fptr = farmalloc( fl+1 );
/* If we got the memory OK, read through the file and fill in the memory */
if ( fptr != NULL ) {
vf->data = fptr;
vf->file_length = fl;
vf->frequency = frequency;
fseek( f, 26, SEEK_SET );
cfl = fl;
while ( cfl-- > 0 ) *fptr++ = (fgetc(f) >> mute);
*fptr = 0xFF; /* Indicates end of sound */
vf->sample_length = 1 + (fptr-vf->data);
}
/* Close up and exit */
fclose(f);
return( vf );
}
/* Play_Voc shows the user the parameters that will be used for playback,
re-directs the interrupt 8 handler to our own, plays the sound and then
restores the handler. */
void Play_Voc( VOCFILE *vf ) {
int countdown=(int)(1193180L / vf->frequency);
/* Tell the user what we're up to */
printf( "Filename: %s\n\n", vf->filename );
printf( "File Length: %ld\n", vf->file_length );
printf( "Sample Length: %ld\n\n", vf->sample_length );
printf( "Frequency: %ld\n", vf->frequency );
printf( "Oversample: %d\n", oversample );
printf( "Muting: %d\n\n", mute );
/* And get into it! */
OldInt8Function = getvect( 0x08 );
setvect( 0x08, NewInt8Function );
PlaySound(vf->data, countdown, oversample);
setvect( 0x08, OldInt8Function );
}
/* Delete_Voc is used to free up the memory allocated to a VOC file */
void Delete_Voc( VOCFILE *vf ) {
if ( vf ) {
if ( vf->data ) free( vf->data );
free(vf);
}
}
/* Check_CLP interprets a given command line parameter */
int Check_CLP( char *parm ) {
if ( !strncmpi( parm, "/F:", 3 ) ) {
frequency = atol( parm+3 );
if ( frequency < MIN_FREQ || frequency > MAX_FREQ ) {
printf( "\nIllegal frequency specified - Valid range is %d to %d!\n", MIN_FREQ, MAX_FREQ );
return(0);
}
return(1);
}
if ( !strncmpi( parm, "/O:", 3 ) ) {
oversample = atoi( parm+3 );
if ( oversample < MIN_OVER || oversample > MAX_OVER ) {
printf( "\nIllegal oversample specified - valid range is %d - %d!\n", MIN_OVER, MAX_OVER );
return(0);
}
return(1);
}
if ( !strncmpi( parm, "/M:", 3 ) ) {
mute = atoi( parm+3 );
if ( mute < MIN_MUTE || mute > MAX_MUTE ) {
printf( "\nIllegal mute specified - valid range is %d - %d\n", MIN_MUTE, MAX_MUTE );
return(0);
}
return(1);
}
if ( !strncmpi( parm, "/?", 3 ) || !strncmpi( parm, "/h", 3 ) || !strncmpi( parm, "/H", 3 ) ) {
printf( "Usage: " );
highvideo();
cprintf( "VOC-IT filename [/F:frequency] [/O:oversample] [/M:mute]\n\n\r" );
normvideo();
printf( "The frequency is the speed in Hertz at which to play the sample. Valid\n" );
printf( "frequency range is %d to %d and the default is %d.\n\n", MIN_FREQ, MAX_FREQ, DEF_FREQ );
printf( "The oversample is how many times to repeat each byte. To remove the\n" );
printf( "\"whine\" generated by playing a sample at a low frequency (eg 8,000Hz)\n" );
printf( "you can double the frequency and double the oversample. Various other\n" );
printf( "effects can be created by experimenting with these parameters. Valid\n" );
printf( "oversample range is %d - %d and the default is %d.\n\n", MIN_OVER, MAX_OVER, DEF_OVER );
printf( "Muting \"quietens\" the sample. The larger the muting factor, the quieter\n" );
printf( "the sound will become. Valid mute range is %d - %d and the default\n", MIN_MUTE, MAX_MUTE );
printf( "is %d.\n\n", DEF_MUTE );
return(0);
}
if ( !strncmpi( parm, "/", 1 ) ) {
printf( "\nUnknown command specified: %s\n", parm );
return(0);
}
/* Otherwise, we assume it's a filename */
strcpy( filename, parm );
if ( !strchr( parm, '.' ) ) strcat( filename, ".VOC" );
strupr(filename);
return(1);
}
/* The main program */
void main( int argc, char **argv ) {
VOCFILE *vf;
int pc;
highvideo();
cprintf( "\n\rVOC-IT Copyright (c) 1993 Imperial Software\n\r" );
cprintf( "Written by Phil Inch for \"Game Developers Magazine\"\n\r" );
normvideo();
printf( "Donated for free use to the public domain, but please credit\n\r" );
printf( "Phil Inch or Game Developers Magazine if you use this program\n\r" );
printf( "in your own programs.\n\n\r" );
if ( argc < 1 ) {
printf( "You must at least specify a VOC filename!\n" );
return;
}
for ( pc = 1; pc < argc; pc++ )
if ( !Check_CLP( argv[pc] ) ) return;
if ( strlen(filename) == 0 ) {
printf( "You must at least specify a VOC filename!\n" );
return;
}
vf = Load_Voc( filename );
if ( vf ) {
Play_Voc( vf );
Delete_Voc( vf );
}
else
printf( "\n\nCouldn't load the VOC for some reason...\n\n" );
}