home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
sound
/
sampplay
/
intsnd.lha
/
easysound.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-20
|
22KB
|
617 lines
/* EasySound.c
EEEEE AAA SSS Y Y SSS OOO U U N N DDD
E A A S Y Y S O O U U NN N D D
EEEE AAAAA SSS Y === SSS O O U U N N N D D
E A A S Y S O O U U N NN D D
EEEEE A A SSSS Y SSSS OOO UUU N N DDD
EASY-SOUND V2.00 1990-09-23 ANDERS BJERIN
AMIGA C CLUB (ACC)
Anders Bjerin
Tulevagen 22
181 41 LIDINGO
SWEDEN
*/
/* Include some important header files: */
#include <exec/types.h>
#include <exec/memory.h>
#include <devices/audio.h>
#include <stdio.h>
#define CLOCK_CONSTANT 3579545
#define MUSIC_PRIORITY 0
/* Structure containing all necessary information about the sound: */
struct SoundInfo
{
BYTE *SoundBuffer; /* WaveForm Buffers */
UWORD RecordRate; /* Record Rate */
ULONG FileLength; /* WaveForm Lengths */
};
/* An IOAudio pointer to each sound channel: */
struct IOAudio *IOA[ 4 ] = { NULL, NULL, NULL, NULL };
typedef LONG Fixed;
typedef struct
{
ULONG oneShotHiSamples; /* #samples in the high octave 1-shot part */
ULONG repeatHiSamples; /* #samples in the high octave repeat part */
ULONG samplesPerHiCycle; /* #samples/cycle in high octave, else 0 */
UWORD samplesPerSec; /* Data sampling rate */
UBYTE ctOctave; /* Number of octaves of waveforms */
UBYTE sCompression; /* Data compression technique used */
Fixed volume; /* Playback volume from 0 to 0x10000 */
} Voice8Header;
/* Declare the functions we are going to use: */
CPTR PrepareSound();
BOOL PlaySound();
void StopSound();
void RemoveSound();
BOOL PrepareIOA();
UWORD LoadSound();
ULONG GetSize();
ULONG SizeIFF();
UWORD ReadIFF();
BOOL MoveTo();
/* PrepareSound() */
/* PrepareSound() loads a sampled sound file (IFF or FutureSound) into */
/* a buffer that is automatically allocated. All information about the */
/* sound (record rate, length, buffersize etc) is put into an SoundInfo */
/* structure. If PrepareSound() has successfully prepared the sound it */
/* returns a pointer to a SoundInfo structure, otherwise it returns */
/* NULL. */
/* */
/* Synopsis: pointer = PrepareSound( filename ); */
/* pointer: (CPTR) Actually a pointer to a SoundInfo structure, but */
/* since we do not want to confuse the user, we simply use a */
/* normal memory pointer. */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* sound file. For example "df0:Explosion.snd". */
CPTR PrepareSound( file )
STRPTR file;
{
/* Declare a pointer to a SoundInfo structure: */
struct SoundInfo *info;
/* Allocate memory for a SoundInfo structure: (The memory can be of */
/* any type, and should be cleared. */
info = (struct SoundInfo *) AllocMem( sizeof( struct SoundInfo ),
MEMF_PUBLIC|MEMF_CLEAR );
if( info )
{
/* The memory have been successfully allocated. */
/* Get the size of the file, and store it in the SoundInfo struct.: */
if( info->FileLength = GetSize( file ) )
{
/* Allocate enough memory for the sampled sound, and store a */
/* pointer to the buffer in the SoundInfo structure: */
info->SoundBuffer = (BYTE *) AllocMem( info->FileLength,
MEMF_CHIP|MEMF_CLEAR );
if( info->SoundBuffer )
{
/* The memory have been successfully allocated. */
/* Load the sound, and store the record rate in the SoundInfo */
/* structure. If the sound could not be loaded, 0 is returned: */
if( info->RecordRate = LoadSound( file, info ) )
{
/* OK! The sound has successfully been loaded. */
/* Old FutureSound files were saved in kHz. If the record rate */
/* is less than one hundered, we know it is an old FutureSound */
/* file, and simply multiply the rate with one thousand: */
if( info->RecordRate < 100 )
info->RecordRate *= 1000;
/* Return a pointer to the SoundInfo structure. (We return a */
/* normal memory pointer.) */
return( (CPTR) info ); /* OK! */
}
else
{
/* ERROR! We could not load the sound! */
/* Deallocate the memory for the sound buffer: */
FreeMem( info->SoundBuffer, info->FileLength );
}
}
}
/* Deallocate the memory the SoundInfo structure: */
FreeMem( info, sizeof( struct SoundInfo ) );
}
/* We have not been able to prepare the sound. All allocated memory */
/* have been deallocated, and we return NULL. */
return( NULL ); /* ERROR! */
}
/* PlaySound() */
/* PlaySound() plays one already prepared sound effect. You can decide */
/* what volume, which channel should, what rate, and how many times the */
/* sound should be played. */
/* */
/* Synopsis: ok = PlaySound( pointer, volume, channel, drate, times ); */
/* ok: (BOOL) If the sound was played successfully TRUE is */
/* returned, else FALSE. */
/* pointer: (CPTR) Actually a pointer to a SoundInfo structure. This */
/* pointer was returned by PrepareSound(). */
/* volume: (UWORD) Volume, 0 to 64. */
/* channel: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
/* RIGHT1 or LEFT1) */
/* drate: (WORD) Delta rate. When the sound is prepared, the record */
/* rate is automatically stored in the SoundInfo structure, */
/* so if you do not want to change the rate, write 0. */
/* times: (UWORD) How many times the sound should be played. If you */
/* want to play the sound forever, write 0. (To stop a sound */
/* call the function StopSound().) */
BOOL PlaySound( info, volume, channel, delta_rate, repeat )
struct SoundInfo *info;
UWORD volume;
UBYTE channel;
WORD delta_rate;
UWORD repeat;
{
/* Before we may play the sound, we must make sure that the sound is */
/* not already being played. We will therefore call the function */
/* StopSound(), in order to stop the sound if it is playing: */
StopSound( channel );
/* Call the PrepareIOA() function that will declare and initialize an */
/* IOAudio structure: */
if( PrepareIOA( CLOCK_CONSTANT / info->RecordRate + delta_rate, volume,
repeat, channel, info ) )
{
/* We will now start playing the sound: */
BeginIO( IOA[ channel ] );
return( TRUE ); /* OK! */
}
else
return( FALSE ); /* ERROR! */
}
/* StopSound() */
/* StopSound() will stop the specified audio channel from continuing */
/* to play the sound. It will also close all devices and ports that */
/* have been opened, and deallocate some memory that have been */
/* allocated. */
/* */
/* Synopsis: StopSound( channel ); */
/* channel: (UBYTE) The audio channel that should be stopped. (LEFT0, */
/* LEFT1, RIGHT0 or RIGHT1.) */
void StopSound( channel )
UBYTE channel;
{
/* Check if the IOAudio structure exist: */
if( IOA[ channel ] )
{
/* 1. Stop the sound: */
AbortIO( IOA[ channel ] );
/* 2. If there exist a Sound Device, close it: */
if( IOA[ channel ]->ioa_Request.io_Device )
CloseDevice( IOA[ channel ] );
/* 3. If there exist a Message Port, delete it: */
if( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort )
DeletePort( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort );
FreeMem( IOA[ channel ], sizeof( struct IOAudio ) );
IOA[ channel ] = NULL;
}
}
/* RemoveSound() */
/* RemoveSound() will stop playing the sound, and deallocate all memory */
/* that was allocated by the PrepareSound() function. Before your */
/* program terminates, all sound that has been prepared, MUST be */
/* removed. */
/* */
/* IMPORTANT! The each channel that is currently playing the sound must */
/* be stopped! (Use the StopSound() function.) */
/* Synopsis: RemoveSound( pointer ); */
/* pointer: (CPTR) Actually a pointer to a SoundInfo structure. */
void RemoveSound( info )
struct SoundInfo *info;
{
/* IMPORTANT! The sound must have been */
/* stopped before you may remove it!!! */
/* Have we allocated a SoundInfo structure? */
if( info )
{
/* Deallocate the sound buffer: */
FreeMem( info->SoundBuffer, info->FileLength );
/* Deallocate the SoundInfo structure: */
FreeMem( info, sizeof( struct SoundInfo ) );
info = NULL;
}
}
/* PrepareIOA() */
/* PrepareIOA() allocates and initializes an IOAudio structure. */
/* */
/* Synopsis: ok = PrepareIOA( period, volume, cycles, channel, pointer ); */
/* */
/* ok: (BOOL) If the IOAudio structure was allocated and */
/* initialized successfully, TRUE is returned, else FALSE. */
/* period: (UWORD) Period time. */
/* volume: (UWORD) Volume, 0 to 64. */
/* cycles: (UWORD) How many times the sound should be played. */
/* (0 : forever) */
/* channel: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
/* RIGHT1 or LEFT1) */
/* pointer: (CPTR) Actually a pointer to a SoundInfo structure. */
BOOL PrepareIOA( period, volume, cycles, channel, info)
UWORD period, volume, cycles;
UBYTE channel;
struct SoundInfo *info;
{
UBYTE ch;
/* Declare a pointer to a MsgPort structure: */
struct MsgPort *port;
/* Allocate space for an IOAudio structure: */
IOA[ channel ] = (struct IOAudio *) AllocMem( sizeof( struct IOAudio ),
MEMF_PUBLIC|MEMF_CLEAR );
/* Could we allocate enough memory? */
if( IOA[ channel ] )
{
/* Create Message port: */
if((port = (struct MsgPort *) CreatePort( "Sound Port", 0 )) == NULL)
{
/* ERROR! Could not create message port! */
/* Deallocate the IOAudio structure: */
FreeMem( IOA[ channel ], sizeof(struct IOAudio) );
IOA[ channel ] = NULL;
return( FALSE ); /* ERROR! */
}
else
{
/* Port created successfully! */
/* Initialize the IOAudion structure: */
/* Priority: */
IOA[ channel ]->ioa_Request.io_Message.mn_Node.ln_Pri = MUSIC_PRIORITY;
/* Port: */
IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort = port;
/* Channel: */
ch = 1<<channel;
IOA[ channel ]->ioa_Data = &ch;
/* Length: */
IOA[ channel ]->ioa_Length = sizeof( UBYTE );
/* Open Audio Device: */
if( OpenDevice( AUDIONAME, 0, IOA[ channel ], 0) )
{
/* ERROR! Could not open the device! */
/* Delete Sound Port: */
DeletePort( port );
/* Deallocate the IOAudio structure: */
FreeMem( IOA[ channel ], sizeof(struct IOAudio) );
IOA[ channel ] = NULL;
return( FALSE ); /* ERROR! */
}
else
{
/* Device opened successfully! */
/* Initialize the rest of the IOAudio structure: */
IOA[ channel ]->ioa_Request.io_Flags = ADIOF_PERVOL;
IOA[ channel ]->ioa_Request.io_Command = CMD_WRITE;
IOA[ channel ]->ioa_Period = period;
IOA[ channel ]->ioa_Volume = volume;
IOA[ channel ]->ioa_Cycles = cycles;
/* The Audion Chip can of some strange reason not play sampled */
/* sound that is longer than 131KB. So if the sound is to long, */
/* we simply cut it off: */
if( info->FileLength > 131000 )
IOA[ channel ]->ioa_Length = 131000;
else
IOA[ channel ]->ioa_Length = info->FileLength;
IOA[ channel ]->ioa_Data = info->SoundBuffer;
return( TRUE ); /* OK! */
}
}
}
return( FALSE ); /* ERROR! */
}
/* LoadSound() */
/* LoadSound() will load sampled sound that was either saved in IFF or */
/* FutureSound format. */
/* */
/* Synopsis: rate = LoadSound( filename, pointer ); */
/* rate: (UWORD) The record rate is returned if the sound was */
/* successfully loaded, else 0. */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* sound file. For example "df0:Explosion.snd". */
/* pointer: (CPTR) Actually a pointer to a SoundInfo structure. */
UWORD LoadSound( filename, info )
STRPTR filename;
struct SoundInfo *info;
{
FILE *file_ptr; /* Pointer to a file. */
ULONG length; /* Data Length. */
UWORD record_rate; /* Record rate. */
/* Check if it is an IFF File: */
if( SizeIFF( filename ) )
{
/* Yes, it is an IFF file. Read it: */
return( ReadIFF( filename, info ) );
}
else
{
/* No, then it is probably a FutureSound file. */
/* Open the file so we can read it: */
if( (file_ptr = fopen( filename, "r" )) == 0 )
return( 0 ); /* ERROR! Could not open the file! */
/* Read the data length: */
if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0 )
{
/* ERROR! Could not read the data length! */
/* Close the file, and return zero: */
fclose( file_ptr );
return( 0 );
}
/* Read the record rate: */
if( fread( (char *) &record_rate, sizeof( UWORD ), 1, file_ptr ) == 0 )
{
/* ERROR! Could not read the record rate! */
/* Close the file, and return zero: */
fclose( file_ptr );
return( 0 );
}
/* Read the sampled sound data into the buffer: */
if( fread( (char *) info->SoundBuffer, length, 1, file_ptr ) == 0 )
{
/* ERROR! Could not read the data! */
/* Close the file, and return zero: */
fclose( file_ptr );
return( 0 );
}
/* Close the file: */
fclose( file_ptr );
/* Return the record rate: */
return( record_rate );
}
}
/* GetSize() */
/* GetSize() returns the size of the file which was saved in either */
/* IFF or FutureSound format. */
/* */
/* Synopsis: length = GetSize( filename ); */
/* length: (ULONG) Data length. */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* sound file. For example "df0:Explosion.snd". */
ULONG GetSize( filename )
STRPTR filename;
{
FILE *file_ptr; /* Pointer to a file. */
ULONG length; /* Data length. */
/* Check if it is an IFF File: */
if( ( length = SizeIFF( filename ) ) == 0 )
{
/* No, then it is probably a FutureSound file. */
/* Open the file so we can read it: */
if( ( file_ptr = fopen( filename, "r" ) ) == 0 )
return( 0 ); /* ERROR! Could not open the file! */
/* Read the data length: */
if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0)
{
/* ERROR! Could not read the data length! */
/* Close the file, and return zero: */
fclose( file_ptr );
return( 0 );
}
/* Close the file: */
fclose( file_ptr );
}
return( length );
}
/* SizeIFF() */
/* SizeIFF() returns the size of an IFF file, or zero if something */
/* went wrong (for example, It was not an IFF file). */
/* */
/* Synopsis: length = SizeIFF( filename ); */
/* length: (ULONG) Data length. */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* IFF file. For example "df0:Explosion.snd". */
ULONG SizeIFF( filename )
STRPTR filename;
{
FILE *file_ptr; /* Pointer to a file. */
STRPTR empty_string = " "; /* Four spaces. */
LONG dummy; /* A dummy variable. */
Voice8Header Header; /* Voice8Header structure. */
/* Try to open the file: */
if( file_ptr = fopen( filename, "r" ) )
{
fread( (char *) empty_string, 4, 1, file_ptr );
if( strcmp( empty_string, "FORM" ) == 0)
{
/* Read twice: */
fread( (char *) empty_string, 4, 1, file_ptr );
fread( (char *) empty_string, 4, 1, file_ptr );
/* Check if it is a "8SVX" file, or not: */
if( strcmp( empty_string, "8SVX" ) == 0 )
{
MoveTo( "VHDR", file_ptr );
fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
/* Close the file, and return the length: */
fclose( file_ptr );
return( Header.oneShotHiSamples + Header.repeatHiSamples );
}
}
/* Close the file: */
fclose( file_ptr );
}
/* Return zero: (ERROR) */
return( 0 );
}
/* ReadIFF() */
/* ReadIFF() reads an IFF file into the buffer, and returns the record */
/* rate. */
/* */
/* Synopsis: rate = ReadIFF( filename, pointer ); */
/* rate: (UWORD) The record rate is returned if the sound was */
/* successfully loaded, else 0. */
/* filename: (STRPTR) Pointer to a string containing the name of the */
/* sound file. For example "df0:Explosion.snd". */
/* pointer: (CPTR) Actually a pointer to a SoundInfo structure. */
UWORD ReadIFF( filename, info )
STRPTR filename;
struct SoundInfo *info;
{
FILE *file_ptr; /* Pointer to a file. */
STRPTR empty_string = " "; /* Four spaces. */
LONG dummy; /* A dummy variable. */
Voice8Header Header; /* Voice8Header structure. */
/* Try to open the file: */
if( file_ptr = fopen( filename, "r" ) )
{
fread( (char *) empty_string, 4, 1, file_ptr );
if( strcmp( empty_string, "FORM" ) == 0 )
{
/* Read twice: */
fread( (char *) empty_string, 4, 1, file_ptr );
fread( (char *) empty_string, 4, 1, file_ptr );
/* Check if it is a "8SVX" file, or not: */
if( strcmp( empty_string, "8SVX" ) == 0 )
{
MoveTo( "VHDR", file_ptr );
fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
MoveTo( "BODY", file_ptr );
fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
fread( (char *) info->SoundBuffer, Header.oneShotHiSamples +
Header.repeatHiSamples, 1, file_ptr );
/* Close the file, and return the record rate: */
fclose( file_ptr );
return( Header.samplesPerSec );
}
}
/* Close the file: */
fclose( file_ptr );
}
/* Return zero: (ERROR) */
return( 0 );
}
/* MoveTo() */
/* MoveTo() walks through an IFF file, and looks for chunks. */
/* */
/* Synopsis: MoveTo( chunk, file_ptr ); */
/* chunk: (STRPTR) The chunk we want to get to. */
/* file_ptr: (FILE *) Pointer to an already opened file. */
BOOL MoveTo( check_string, file_ptr )
STRPTR check_string;
FILE *file_ptr;
{
STRPTR empty_string = " "; /* Four spaces. */
int skip, loop; /* How much data should be skiped. */
LONG dummy; /* A dummy variable. */
/* As long as we have not reached the EOF, continue: */
while( !feof( file_ptr ) )
{
fread( (char *) empty_string, 4, 1, file_ptr);
/* Have we found the right chunk? */
if( strcmp( check_string, empty_string ) ==0 )
return( 0 ); /* YES! Return nothing. */
/* Move foreward: */
fread( (char *) &skip, sizeof( LONG ), 1, file_ptr );
for( loop = 0; loop < skip; loop++ )
fread( (char *) &dummy, 1, 1, file_ptr);
}
}