home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************/
- /* */
- /* 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 );
- }
-
-
-