home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************/
- /* */
- /* Amiga C Encyclopedia (ACE) V3.0 Amiga C Club (ACC) */
- /* ------------------------------- ------------------ */
- /* */
- /* Book: ACM Sound Amiga C Club */
- /* Chapter: IncludeSound Tulevagen 22 */
- /* File: IncludeSound.c 181 41 LIDINGO */
- /* Author: Anders Bjerin SWEDEN */
- /* Date: 92-05-10 */
- /* Version: 1.15 */
- /* */
- /* Copyright 1992, Anders Bjerin - Amiga C Club (ACC) */
- /* */
- /* Registered members may use this program freely in their */
- /* own commercial/noncommercial programs/articles. */
- /* */
- /***********************************************************/
-
-
-
- /* Include some important header files: */
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <devices/audio.h>
- #include <stdio.h>
- #include "IncludeSound.h"
-
-
-
- #define CLOCK_CONSTANT 3579545
-
-
- /* 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: */
-
- BOOL PlaySound(
- struct SoundInfo *info,
- UWORD volume,
- UBYTE channel,
- BYTE priority,
- WORD delta_rate,
- UWORD repeat,
- ULONG start,
- ULONG time,
- BOOL wait
- );
-
- void StopSound( UBYTE channel );
-
- BOOL PrepareIOA(
- UWORD period,
- UWORD volume,
- UWORD cycles,
- UBYTE channel,
- BYTE priority,
- struct SoundInfo *info,
- ULONG start,
- ULONG time
- );
-
-
-
- /* PlaySound() */
- /* PlaySound() plays one already prepared sound effect. You can decide */
- /* what volume, which channel, what rate, which priority, how many times */
- /* the sound should be played and so on... */
- /* */
- /* Synopsis: ok = PlaySound( ptr, vol, cha, pri, drate, times, start, */
- /* time, wait ); */
- /* */
- /* ok: (BOOL) If the sound was played successfully TRUE is */
- /* returned, else FALSE. */
- /* */
- /* ptr: (struct SoundInfo *) Pointer to a SoundInfo structure. This */
- /* pointer was returned by PrepareSound(). */
- /* */
- /* vol: (UWORD) Volume, 0 to 64. */
- /* */
- /* cha: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
- /* RIGHT1 or LEFT1) */
- /* */
- /* pri: (BYTE) What priority should be used. See header file for a */
- /* complete list of recommended priorities. */
- /* */
- /* 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 NORMALRATE. */
- /* */
- /* times: (UWORD) How many times the sound should be played. If you */
- /* want to play the sound forever, write NONSTOP. (To stop a */
- /* sound call the function StopSound().) */
- /* */
- /* start: (ULONG) Where in the sound data we should start to play. (If */
- /* you want to start at the beginning of the sound data set start */
- /* to 0.) */
- /* */
- /* time: (ULONG) For how long time the sound should be played. If you */
- /* want to play all of the sound data set time to 0. */
- /* */
- /* wait: (BOOL) Set this parameter to WAIT if you want to wait for the */
- /* sound to be completed. If you set it to DO_NOT_WAIT, your */
- /* program will continue to run while the sound is played. */
- /* NOTE! Do not try to play a sound continiously (times set to */
- /* NONSTOP) and at the same time set this field to TRUE! The */
- /* request will then never be completed and your program will */
- /* come to a dead lock!! */
-
- BOOL PlaySound
- (
- struct SoundInfo *info,
- UWORD volume,
- UBYTE channel,
- BYTE priority,
- WORD delta_rate,
- UWORD times,
- ULONG start,
- ULONG time,
- BOOL wait
- )
- {
- /* 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,
- times, channel, priority, info, start, time ) )
- {
- /* We will now start playing the sound: */
- BeginIO( IOA[ channel ] );
-
- /* Should we wait for the sound to be completed? */
- if( wait )
- WaitIO( 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( 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 );
-
- /* 4. Remove the request block: */
- DeleteExtIO( IOA[ channel ], sizeof( struct IOAudio ) );
-
- /* 5. Set the pointer to NULL so we know that this */
- /* request has now been deleted: */
- IOA[ channel ] = NULL;
- }
- }
-
-
-
- /* PrepareIOA() */
- /* PrepareIOA() allocates and initializes an IOAudio structure. */
- /* */
- /* Synopsis: ok = PrepareIOA( per, vol, cyc, cha, ptr, start, time ); */
- /* */
- /* ok: (BOOL) If the IOAudio structure was allocated and */
- /* initialized successfully, TRUE is returned, else FALSE. */
- /* per: (UWORD) Period time. */
- /* vol: (UWORD) Volume, 0 to 64. */
- /* cyc: (UWORD) How many times the sound should be played. */
- /* (0 : forever) */
- /* cha: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
- /* RIGHT1 or LEFT1) */
- /* ptr: (struct SoundInfo *) Pointer to a SoundInfo structure. */
- /* start: (ULONG) Where in the sound data we should start to play. */
- /* time: (ULONG) For how long time the sound should be played. */
-
- BOOL PrepareIOA
- (
- UWORD period,
- UWORD volume,
- UWORD cycles,
- UBYTE channel,
- BYTE priority,
- struct SoundInfo *info,
- ULONG start,
- ULONG time
- )
- {
- /* Store error numbers here: */
- BYTE error;
-
- /* Declare a pointer to a MsgPort structure: */
- struct MsgPort *port;
-
-
-
- /* Get a reply port: (No name, normal priority) */
- port = (struct MsgPort *)
- CreatePort( NULL, 0 );
-
- /* Did we get a reply port? */
- if( !port )
- {
- /* Bad news! We did not get a reply port. */
-
- /* Return with an error value: */
- return( FALSE );
- }
-
-
-
- /* Create an IOAudio request: */
- IOA[ channel ] = (struct IOAudio *)
- CreateExtIO( port, sizeof( struct IOAudio ) );
-
- /* Could we allocate enough memory? */
- if( !IOA[ channel ] )
- {
- /* Tough luck! We did not get a request block. */
-
- /* Close the reply port: */
- DeletePort( port );
-
- /* Return with an error value: */
- return( FALSE );
- }
-
-
-
- /* Initialize the IOAudion structure: */
-
- /* Set priority: */
- IOA[ channel ]->ioa_Request.io_Message.mn_Node.ln_Pri = priority;
-
- /* Set channel: (This program tries to reserve one specific */
- /* audio channel. It does not support an allocation array */
- /* with several options.) */
- info->channel_bit = 1<<channel;
-
- /* Give the request block a pointer to our simple allocation array: */
- IOA[ channel ]->ioa_Data = &(info->channel_bit);
-
- /* Set the length of our allocation array: */
- IOA[ channel ]->ioa_Length = sizeof( UBYTE );
-
- /* Open Audio Device: */
- error = OpenDevice( AUDIONAME, 0, IOA[ channel ], 0);
-
- /* Have wee successfully opened it? */
- if( error )
- {
- /* Hard times! Could not open the device! */
-
- /* Delete the request block: */
- DeleteExtIO( IOA[ channel ], sizeof(struct IOAudio) );
-
- /* Close the reply port: */
- DeletePort( port );
-
- /* Set audio pointer to NULL so we know that */
- /* we do not have any request block here: */
- IOA[ channel ] = NULL;
-
- /* Return with an error value: */
- return( FALSE ); /* ERROR! */
- }
-
-
-
- /* We now have a reply port, a request block, one */
- /* audio channel reserved and the audio device has */
- /* been opened. Prepare to play: */
-
-
-
- /* Initialize the request block with the users requirements: */
- IOA[ channel ]->ioa_Request.io_Flags = ADIOF_PERVOL;
-
- /* We want to play sound (write data to the audio device): */
- IOA[ channel ]->ioa_Request.io_Command = CMD_WRITE;
-
- /* Set period value: */
- IOA[ channel ]->ioa_Period = period;
-
- /* Set volume: */
- IOA[ channel ]->ioa_Volume = volume;
-
- /* Number of times the sound wave should be played: */
- IOA[ channel ]->ioa_Cycles = cycles;
-
- /* If the user has specified a play time we use */
- /* it, else we play the complete sound: */
- if( time )
- IOA[ channel ]->ioa_Length = time;
- else
- IOA[ channel ]->ioa_Length = info->FileLength;
-
- /* Set start position in the waveform: */
- IOA[ channel ]->ioa_Data = info->SoundBuffer + start;
-
-
-
- /* Everything has been prepared, return with OK: */
- return( TRUE );
- }
-
-
-
-