home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
datafiles
/
text
/
c_manual
/
devices
/
audiodevice
/
example4.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-27
|
16KB
|
542 lines
/***********************************************************/
/* */
/* Amiga C Encyclopedia (ACE) V3.0 Amiga C Club (ACC) */
/* ------------------------------- ------------------ */
/* */
/* Book: ACM Devices Amiga C Club */
/* Chapter: AudioDevice Tulevagen 22 */
/* File: Example4.c 181 41 LIDINGO */
/* Author: Anders Bjerin SWEDEN */
/* Date: 92-04-21 */
/* Version: 1.00 */
/* */
/* Copyright 1992, Anders Bjerin - Amiga C Club (ACC) */
/* */
/* Registered members may use this program freely in their */
/* own commercial/noncommercial programs/articles. */
/* */
/***********************************************************/
/* This program demonstrates how you can play a sound */
/* continuously. While the sound is being played we */
/* slowly alter the period and volume values. */
#include <exec/types.h> /* STRPTR */
#include <exec/memory.h> /* MEMF_CHIP */
#include <devices/audio.h> /* Audio Device */
/* The audio channels: (Sadly these constants */
/* have not been defined in any header file.) */
/* Values: */
#define LEFT0B 0
#define RIGHT0B 1
#define RIGHT1B 2
#define LEFT1B 3
/* Bit fields: */
#define LEFT0F (1<<LEFT0B)
#define RIGHT0F (1<<RIGHT0B)
#define RIGHT1F (1<<RIGHT1B)
#define LEFT1F (1<<LEFT1B)
/* Sound priorities: */
#define SOUND_UNSTOPPABLE 127
#define SOUND_EMERGENCIES 95
#define SOUND_ATTENTION 85
#define SOUND_SPEECH 75
#define SOUND_INFORMATION 60
#define SOUND_MUSIC 0
#define SOUND_EFFECT -35
#define SOUND_BACKGROUND -90
#define SOUND_SILENCE -128
/* The clock constant: */
#define NTSC_CLOCK 3579545 /* American Amigas - 60Hz */
#define PAL_CLOCK 3546895 /* European Amigas - 50Hz */
/* Define min/max-volumes: */
#define MAXVOLUME 64
#define MINVOLUME 0
/* Declare a pointer to our reply port: */
struct MsgPort *replymp = NULL;
/* Declare a pointer to our audio request block: */
struct IOAudio *audio_req = NULL;
/* Declare another request block which we */
/* will use to change to volume and period */
/* values with: */
struct IOAudio *change_req = NULL;
/* Our list of preffered channel combinations: */
/* (First we try to reserve the first channel, */
/* then the second, third and finally fourth */
/* audio channel.) */
UBYTE allocation_array[]=
{
LEFT0F,
RIGHT0F,
RIGHT1F,
LEFT1F
};
/* Declare a pointer to some soundwave data: */
BYTE *engine_wave = NULL;
/* This is some sampled sound data which will be copied */
/* into some chip memory before we try to play it: */
/* (If you have the SAS (Lattice) C Copmiler you can */
/* instead use the keyword "chip" just after the word */
/* "BYTE". The data will then immediately be placed in */
/* chip memory, and you do then not need to allocate */
/* any extra memory and copy the data into it.) */
/************************************/
/* SoundData prepared by PrintSound */
/* Anders Bjerin Amiga C Club */
/* */
/* File name: CarEngine.snd */
/* Record Rate: 28185 */
/* File Length: 1000 */
/************************************/
BYTE engine_data[]=
{
0,0,-105,-97,-70,-41,-30,-37,-43,-37,-14,
10,24,21,3,-11,-14,-13,-16,-27,-37,-40,
-42,-52,-127,-74,-76,-72,-64,-55,-97,-38,-97,
-99,-14,0,14,37,58,117,70,64,56,50,
40,29,21,21,-11,31,-19,30,-19,27,32,
41,51,54,52,47,45,15,50,50,49,46,
41,35,32,32,33,38,41,36,29,-13,-13,
31,38,47,52,53,47,39,37,40,44,41,
26,11,0,1,0,-8,-15,-15,41,41,0,
-1,0,5,13,21,27,24,19,18,12,-5,
-28,-48,-60,-68,-73,-76,-76,-77,-79,-79,-78,
35,33,-127,-64,27,-103,-97,-104,-87,-55,-32,
-17,-17,-19,-13,0,24,47,61,69,68,123,
41,23,11,0,-6,-12,-22,-24,-17,-11,-14,
-30,-47,-56,-58,-51,-35,-22,-5,8,15,17,
16,17,21,28,31,31,32,32,28,21,12,
8,7,4,4,11,21,-19,23,14,9,12,
-9,25,29,30,35,45,49,44,33,20,18,
23,29,27,22,22,27,29,27,61,24,32,
42,59,55,46,31,21,11,1,4,1,19,
18,0,7,9,10,8,10,15,18,17,16,
17,16,9,-6,-25,-51,-63,-61,-47,21,-36,
-40,-44,-40,-32,-26,-23,-19,-18,-19,55,-11,
-11,-70,-97,-112,-117,-106,-79,-58,-54,-57,-57,
-51,-38,-8,19,31,31,22,4,-4,-10,-15,
-22,71,-41,-45,-42,-31,-22,-23,-29,-32,-27,
-17,-2,63,63,19,29,63,47,50,54,61,
63,61,58,57,57,59,57,47,-31,49,44,
43,43,41,21,37,39,33,44,31,29,31,
37,27,31,23,21,21,23,17,14,19,15,
0,5,113,13,29,4,11,20,25,16,5,
0,5,13,12,3,-12,-17,-8,4,3,-4,
-14,-18,-15,-10,-12,-19,-26,-27,-21,-16,-55,
-67,-51,-75,-77,-89,-97,-99,35,35,35,-119,
-117,-123,-115,-123,-113,-115,-105,-81,-117,-44,-45,
-49,-42,-23,-103,38,53,66,69,61,117,117,
20,123,121,18,3,-9,-15,-8,-2,-3,-10,
-27,-37,-32,-9,9,24,25,23,23,30,35,
33,24,18,18,24,32,33,28,22,23,32,
40,-11,49,50,54,117,121,107,65,51,101,
91,89,57,50,40,37,38,25,25,15,25,
2,1,23,-9,-11,-3,5,21,10,4,0,
7,27,39,32,1,-2,1,5,-1,-14,-23,
-21,-16,-16,-19,-22,-22,-23,33,-23,33,-18,
-22,33,9,-41,9,-46,-56,-62,-59,-46,-40,
-44,-52,-57,-65,-125,-123,-123,-123,-78,-55,-38,
-36,-38,-33,-21,0,25,47,57,54,37,15,
1,0,-2,-11,-32,-55,-62,-54,-41,-41,-49,
-54,-51,-44,-33,-21,-11,2,22,45,60,77,
68,121,123,123,99,99,123,123,97,29,21,
18,25,25,17,1,0,41,0,56,58,55,
55,55,44,11,49,47,39,25,12,7,9,
8,-2,-16,-19,-12,-5,-8,-14,-12,-2,5,
7,1,0,6,18,27,23,4,-14,-18,-4,
0,-2,-10,-8,3,20,33,34,26,21,28,
41,44,28,3,-11,-15,-19,-31,-49,-64,-68,
-64,-59,-58,-61,-64,-64,-66,-72,-77,-78,-79,
-78,-67,-50,-28,-11,-1,0,89,43,123,73,
121,117,113,42,28,22,16,1,-17,-29,-37,
-38,-38,67,-38,-35,-32,-30,-24,-15,-5,-1,
1,9,18,22,17,7,0,-3,3,11,14,
10,9,17,30,33,25,16,13,21,27,28,
27,29,33,11,41,35,35,32,32,33,28,
-35,7,3,4,9,10,8,6,9,18,22,
22,22,28,42,52,53,45,75,83,91,11,
6,11,25,7,-30,25,-15,-26,-37,-31,23,
6,16,11,4,23,1,0,-10,-34,-49,-52,
-23,-79,-79,-63,-89,-73,-79,-105,-127,-123,-121,
-119,-117,-115,-75,-76,-62,-54,-51,-48,-40,-15,
6,-27,42,47,50,-23,71,-21,-19,121,121,
121,40,-1,26,12,-55,0,-53,-53,-37,3,
-11,0,5,-6,-5,2,12,24,13,28,22,
21,17,34,19,23,34,35,41,54,63,64,
59,56,56,54,91,91,89,43,43,43,43,
43,87,17,8,9,33,79,17,6,35,-7,
0,9,35,-6,51,-1,12,9,1,7,35,
3,-1,7,3,-3,-4,5,20,23,14,-15,
-17,-18,-19,-25,-21,-18,-14,-12,-17,-29,33,
-32,-31,-40,-59,-69,-72,-74,-82,-97,-111,-122,
-123,-113,-77,-97,-79,-96,-83,-71,-66,-77,-86,
29,-49,-15,27,-2,-5,1,28,21,80,89,
87,105,105,49,40,30,-23,5,-4,-7,-15,
-11,-22,-63,-26,-22,-26,-33,-31,-10,8,27,
31,30,34,46,63,69,64,-1,15,19,-1,
21,21,43,39,40,45,47,44,40,40,44,
47,48,49,3,53,50,46,45,45,46,42,
13,20,14,-15,18,18,11,17,9,19,25,
28,29,115,25,41,39,34,31,30,28,21,
5,-13,29,-14,-9,-20,-38,-55,-55,-46,-31,
-24,-19,-24,-36,-49,-60,-78,-85,-78,-67,-62,
-71,-82,-87,-84,-81,-84,-119,-96,-96,27,
};
/* To sample sound you have to use a sound sampler. If */
/* you do not have any I can help you and do it for */
/* you, free of charge. (Registered members only.) */
/* Declare our functions: */
void main();
void clean_up( STRPTR text );
void main()
{
/* Error messages: */
BYTE error;
/* The channel we have received: */
UBYTE channel;
/* Used in the loops: */
int loop;
/* Used when we copy the first request */
/* block to the second one: */
BYTE *first_ptr;
BYTE *second_ptr;
/* Get a reply port: (No name, priority 0) */
replymp = (struct MsgPort *)
CreatePort( NULL, 0 );
if( !replymp )
clean_up( "Could not create the reply port!" );
/* Allocate and preinitialize an audio request block: */
audio_req = (struct IOAudio *)
CreateExtIO( replymp, sizeof( struct IOAudio ) );
if( !audio_req )
clean_up( "Not enough memory for the first IOAudio structure!" );
/* Allocate and preinitialize the other audio request block: */
change_req = (struct IOAudio *)
CreateExtIO( replymp, sizeof( struct IOAudio ) );
if( !change_req )
clean_up( "Not enough memory for the second IOAudio structure!" );
/* Open the Audio Device: (We will try to */
/* reserve a sound channel later on.) */
error = OpenDevice( AUDIONAME, 0, audio_req, 0 );
if( error )
{
/* Clear the "io_Device" flag since we have not opened the device: */
audio_req->ioa_Request.io_Device = NULL;
/* Quit: */
clean_up( "Could not open the Audio Device!" );
}
/* Try to reserve a channel: */
audio_req->ioa_Request.io_Command = ADCMD_ALLOCATE;
/* Set sound priority: (We are going to play a sound effect.) */
audio_req->ioa_Request.io_Message.mn_Node.ln_Pri = SOUND_EFFECT;
/* Do not wait for any channels to be free, */
/* return immediately, successfully or not: */
audio_req->ioa_Request.io_Flags = ADIOF_NOWAIT;
/* Give the request block a pointer to our allocation array: */
audio_req->ioa_Data = allocation_array;
/* Set the length of the allocation array: */
audio_req->ioa_Length = sizeof( allocation_array );
/* Do our request: */
BeginIO( audio_req );
/* Wait for the request to be completed: */
error = WaitIO( audio_req );
/* Everything OK? */
if( error )
clean_up( "No channel available!" );
/* Check which channel we received: */
channel = (UBYTE) audio_req->ioa_Request.io_Unit;
/* Check which channel we received: */
channel = (UBYTE) audio_req->ioa_Request.io_Unit;
if( channel & LEFT0F )
printf( "First left channel!\n" );
if( channel & RIGHT0F )
printf( "First right channel!\n" );
if( channel & RIGHT1F )
printf( "Second right channel!\n" );
if( channel & LEFT1F )
printf( "Second left channel!\n" );
/* Allocate some memory where we can store the waveform we */
/* want to use. Note that it must be Chip memory, and placed */
/* on a word boundary! */
engine_wave = (BYTE *) AllocMem( sizeof( engine_data ), MEMF_CHIP );
if( !engine_wave )
clean_up( "Could not allocate enough memory for the engine wave!" );
/* Copy the engine data to some chip memory: */
for( loop = 0; loop < sizeof( engine_data ); loop++ )
engine_wave[ loop ] = engine_data[ loop ];
/* Give the request block a pointer to the waveform: */
audio_req->ioa_Data = engine_wave;
/* Set the length of the waveform: */
/* (Must be an even number of bytes.) */
audio_req->ioa_Length = sizeof( engine_data );
/* Play forever: (The only whay to stop it is to send a */
/* ADCMD_FINISH command, or call AbortIO().) */
audio_req->ioa_Cycles = 0;
/* Going to play a tune: */
audio_req->ioa_Request.io_Command = CMD_WRITE;
/* Use the volume and period fields of the request block: */
/* (If we do not set this flag the previous volume and */
/* period values will be used.) */
audio_req->ioa_Request.io_Flags = ADIOF_PERVOL;
/* Medium volume: */
audio_req->ioa_Volume = 32;
/* Set the period: (The period value can be calculated */
/* by dividing the clock constant with the record rate. */
/* The record rate is also printed by PrintSound, */
/* together with the sample data values.) */
audio_req->ioa_Period = PAL_CLOCK / 28185;
/* Copy the first request block to the secon one: (byte by byte) */
/* Get the start addresses of both request blocks: */
first_ptr = (BYTE *) audio_req;
second_ptr = (BYTE *) change_req;
/* Copy byte by byte: */
for( loop = 0; loop < sizeof( struct IOAudio ); loop++ )
{
/* Copy: */
*second_ptr = *first_ptr;
/* Next byte: */
first_ptr++;
second_ptr++;
}
/* Tell the user to be prepared: */
printf( "This can not be a VOLVO!\n" );
/* Start to play the sound: */
BeginIO( audio_req );
/* In this very long loop we will 10 times change the */
/* volume and period values: */
for( loop=0; loop < 100000; loop++ )
{
/* 10 times should the sound be altered: */
if( !(loop % 10000) )
{
/* We are going to alter the volume and period values */
/* on one of the sound channels: */
change_req->ioa_Request.io_Command = ADCMD_PERVOL;
/* The change should first occur when we the sound */
/* has reached the end of the cycle. If you do not */
/* set this flag in this example I do not think */
/* anyone would hear any disturbing clicks while */
/* the volume and period are changed, but if you */
/* play very clean sounds it might be necessary. */
change_req->ioa_Request.io_Flags = ADIOF_SYNCCYCLE;
/* Slowly increase the volume: */
change_req->ioa_Volume += 2;
/* Also increase the period value: */
change_req->ioa_Period += 20;
/* Set a mark: */
printf( "*" );
/* Make the change: */
BeginIO( change_req );
/* Wait for the change to be completed: */
error = WaitIO( change_req );
/* Could we successfully alter the sound? */
if( error )
{
/* We could not alter the sound, some one */
/* has stolen our channel!!! */
/* Quit: */
clean_up( "Could not alter the sound!" );
}
}
}
/* Stop the sound: */
change_req->ioa_Request.io_Command = ADCMD_FINISH;
/* But first wait for the cycle to be completed: */
change_req->ioa_Request.io_Flags = ADIOF_SYNCCYCLE;
/* Send the command: */
BeginIO( change_req );
/* Wait for the sound to be stopped: (This command can */
/* not fail so we do not have to check for any error */
/* messages.) */
WaitIO( change_req );
/* An easier way to stop a sound is simlply to call the */
/* AbortIO() function directly, and not bother about */
/* using a separate request. You can choose either method, */
/* it will make no difference, although some programmers */
/* tend to prefer the ADCMD_FINISH command. */
/* */
/* AbortIO( audio_req ); */
/* Clean up and quit: */
clean_up( "The End!" );
}
/* Close and return everything that has been */
/* opened and allocated before we quit: */
void clean_up( STRPTR text )
{
/* New line: */
printf( "\n" );
/* If we have a request block and it does not contain */
/* any errors we know that a channel has been allocated */
/* and must be deallocated: */
if( audio_req && !(audio_req->ioa_Request.io_Error) )
{
/* Free the channel: */
audio_req->ioa_Request.io_Command = ADCMD_FREE;
/* We are allowed to use the function DoIO() for */
/* this request since it will not change any */
/* values that are vital for us: */
DoIO( audio_req );
/* The lock is automatically unlocked when we */
/* free the audio channel. */
}
/* Empty the reply port: */
while( GetMsg( replymp ) )
printf( "Collected a message at the reply port.\n" );
/* If we have a request block and the "io_Device" field */
/* is not zero, we know that the device has successfully */
/* been opened and must now be closed: */
if( audio_req && audio_req->ioa_Request.io_Device )
CloseDevice( audio_req );
/* Remove the replyport: */
if( replymp )
DeletePort( replymp);
/* Dealocate the first IOAudio structure: */
if( audio_req )
DeleteExtIO( audio_req, sizeof( struct IOAudio ) );
/* Dealocate the second IOAudio structure: */
if( change_req )
DeleteExtIO( change_req, sizeof( struct IOAudio ) );
/* Dealocate the engine waveform: */
if( engine_wave )
FreeMem( engine_wave, sizeof( engine_data ) );
/* Print the last message: */
printf( "%s\n", text );
/* Quit: */
exit( 0 );
}