Version of Robotron arcade game using LPC1768, a Gameduino shield, a serial EEPROM (for high scores), two microswitch joysticks and two buttons plus a box to put it in. 20 levels of mayhem.

Dependencies:   25LCxxx_SPI CommonTypes Gameduino mbed

Committer:
RichardE
Date:
Mon Jun 17 15:10:43 2013 +0000
Revision:
18:70190f956a24
Parent:
9:fa7e7b37b632
Improved response to button 1 when entering high scores (HighScoreEntry.cpp).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RichardE 9:fa7e7b37b632 1 /*
RichardE 9:fa7e7b37b632 2 * SOURCE FILE : SoundManager.cpp
RichardE 9:fa7e7b37b632 3 *
RichardE 9:fa7e7b37b632 4 * Responsible for playing simple sounds.
RichardE 9:fa7e7b37b632 5 *
RichardE 9:fa7e7b37b632 6 */
RichardE 9:fa7e7b37b632 7
RichardE 9:fa7e7b37b632 8 #include "SoundManager.h"
RichardE 9:fa7e7b37b632 9 #include "Notes.h"
RichardE 9:fa7e7b37b632 10
RichardE 9:fa7e7b37b632 11 // An instance of the SoundManager class.
RichardE 9:fa7e7b37b632 12 SoundManager SoundManager::Instance;
RichardE 9:fa7e7b37b632 13
RichardE 9:fa7e7b37b632 14 /***************/
RichardE 9:fa7e7b37b632 15 /* CONSTRUCTOR */
RichardE 9:fa7e7b37b632 16 /***************/
RichardE 9:fa7e7b37b632 17 SoundManager::SoundManager() :
RichardE 9:fa7e7b37b632 18 gd( (Gameduino*)NULL )
RichardE 9:fa7e7b37b632 19 {
RichardE 9:fa7e7b37b632 20 }
RichardE 9:fa7e7b37b632 21
RichardE 9:fa7e7b37b632 22 /*****************************/
RichardE 9:fa7e7b37b632 23 /* UPDATE A SINGLE TUNE SLOT */
RichardE 9:fa7e7b37b632 24 /*****************************/
RichardE 9:fa7e7b37b632 25 // Do NOT call with a record containing zero in TuneAddress (a free slot).
RichardE 9:fa7e7b37b632 26 void SoundManager::UpdateTuneSection( UInt8 voiceNum, TuneRecord *rec ) {
RichardE 9:fa7e7b37b632 27 if( rec->Countdown > 0 ) {
RichardE 9:fa7e7b37b632 28 rec->Countdown--;
RichardE 9:fa7e7b37b632 29 }
RichardE 9:fa7e7b37b632 30 else {
RichardE 9:fa7e7b37b632 31 // Countdown has reached zero. Load next section of tune.
RichardE 9:fa7e7b37b632 32 UInt8 noteNum = *(rec->TuneAddress++);
RichardE 9:fa7e7b37b632 33 if( noteNum == 0 ) {
RichardE 9:fa7e7b37b632 34 // End of tune. Silence voice and set tune address to NULL to
RichardE 9:fa7e7b37b632 35 // indicate slot is free.
RichardE 9:fa7e7b37b632 36 gd->voice( voiceNum, Gameduino::SineWave, 0, 0, 0 );
RichardE 9:fa7e7b37b632 37 rec->TuneAddress = (UInt8*)NULL;
RichardE 9:fa7e7b37b632 38 }
RichardE 9:fa7e7b37b632 39 else {
RichardE 9:fa7e7b37b632 40 // Convert note number to frequency.
RichardE 9:fa7e7b37b632 41 UInt16 frequency = Notes::NoteFrequencies[ noteNum ];
RichardE 9:fa7e7b37b632 42 // Read amplitude for next tune section and add biases.
RichardE 9:fa7e7b37b632 43 UInt8 amp = *(rec->TuneAddress++);
RichardE 9:fa7e7b37b632 44 // Start playing section.
RichardE 9:fa7e7b37b632 45 gd->voice( voiceNum, rec->TuneWaveform, frequency, amp + rec->LeftAmpBias, amp + rec->RightAmpBias );
RichardE 9:fa7e7b37b632 46 // Set countdown according to length of this section.
RichardE 9:fa7e7b37b632 47 rec->Countdown = *(rec->TuneAddress++);
RichardE 9:fa7e7b37b632 48 }
RichardE 9:fa7e7b37b632 49 }
RichardE 9:fa7e7b37b632 50 }
RichardE 9:fa7e7b37b632 51
RichardE 9:fa7e7b37b632 52 /************************/
RichardE 9:fa7e7b37b632 53 /* TRY AND PLAY A SOUND */
RichardE 9:fa7e7b37b632 54 /************************/
RichardE 9:fa7e7b37b632 55 // Pass address of tune in program memory in tuneAddress.
RichardE 9:fa7e7b37b632 56 // Pass bias to apply to left speaker amplitude in leftAmpBias.
RichardE 9:fa7e7b37b632 57 // Pass bias to apply to right speaker amplitude in leftAmpBias.
RichardE 9:fa7e7b37b632 58 // Returns true if sound was started, false if no sound slots free.
RichardE 9:fa7e7b37b632 59 bool SoundManager::PlaySound( const UInt8 *tuneAddress, UInt8 leftAmpBias, UInt8 rightAmpBias ) {
RichardE 9:fa7e7b37b632 60 // Find a tune record that is free.
RichardE 9:fa7e7b37b632 61 UInt8 i = 0;
RichardE 9:fa7e7b37b632 62 TuneRecord *rec = tuneRecords;
RichardE 9:fa7e7b37b632 63 while( ( i < VoiceCount ) && ( rec->TuneAddress != (UInt8*)NULL ) ) {
RichardE 9:fa7e7b37b632 64 i++;
RichardE 9:fa7e7b37b632 65 rec++;
RichardE 9:fa7e7b37b632 66 }
RichardE 9:fa7e7b37b632 67 if( i < VoiceCount ) {
RichardE 9:fa7e7b37b632 68 // Found a free tune record. Initialise it.
RichardE 9:fa7e7b37b632 69 rec->TuneWaveform = (Gameduino::WaveForm)*tuneAddress;
RichardE 9:fa7e7b37b632 70 rec->TuneAddress = tuneAddress + 1;
RichardE 9:fa7e7b37b632 71 rec->LeftAmpBias = leftAmpBias;
RichardE 9:fa7e7b37b632 72 rec->RightAmpBias = rightAmpBias;
RichardE 9:fa7e7b37b632 73 rec->Countdown = 0;
RichardE 9:fa7e7b37b632 74 // Start playing first part of sound.
RichardE 9:fa7e7b37b632 75 UpdateTuneSection( FirstVoice + i, rec );
RichardE 9:fa7e7b37b632 76 return true;
RichardE 9:fa7e7b37b632 77 }
RichardE 9:fa7e7b37b632 78 else {
RichardE 9:fa7e7b37b632 79 // No free counter found.
RichardE 9:fa7e7b37b632 80 return false;
RichardE 9:fa7e7b37b632 81 }
RichardE 9:fa7e7b37b632 82 }
RichardE 9:fa7e7b37b632 83
RichardE 9:fa7e7b37b632 84 /****************************/
RichardE 9:fa7e7b37b632 85 /* UPDATE PLAYING OF SOUNDS */
RichardE 9:fa7e7b37b632 86 /****************************/
RichardE 9:fa7e7b37b632 87 // Should be called at regular intervals.
RichardE 9:fa7e7b37b632 88 void SoundManager::Update( void ) {
RichardE 9:fa7e7b37b632 89 TuneRecord *ptr = tuneRecords;
RichardE 9:fa7e7b37b632 90 // Repeat for all tune records.
RichardE 9:fa7e7b37b632 91 for( UInt8 i = 0; i < VoiceCount; ++i ) {
RichardE 9:fa7e7b37b632 92 // Skip over any unused records (with TuneAddress of zero).
RichardE 9:fa7e7b37b632 93 if( ptr->TuneAddress != (UInt8*)NULL ) {
RichardE 9:fa7e7b37b632 94 UpdateTuneSection( FirstVoice + i, ptr );
RichardE 9:fa7e7b37b632 95 }
RichardE 9:fa7e7b37b632 96 ptr++;
RichardE 9:fa7e7b37b632 97 }
RichardE 9:fa7e7b37b632 98 }
RichardE 9:fa7e7b37b632 99
RichardE 9:fa7e7b37b632 100 /**********************************/
RichardE 9:fa7e7b37b632 101 /* COUNT NUMBER OF SOUNDS PLAYING */
RichardE 9:fa7e7b37b632 102 /**********************************/
RichardE 9:fa7e7b37b632 103 // Returns number of sounds playing.
RichardE 9:fa7e7b37b632 104 UInt8 SoundManager::CountSoundsPlaying( void ) {
RichardE 9:fa7e7b37b632 105 UInt8 count = 0;
RichardE 9:fa7e7b37b632 106 TuneRecord *ptr = tuneRecords;
RichardE 9:fa7e7b37b632 107 // Repeat for all tune records.
RichardE 9:fa7e7b37b632 108 for( UInt8 i = 0; i < VoiceCount; ++i ) {
RichardE 9:fa7e7b37b632 109 // If TuneAddress is not zero then increment count.
RichardE 9:fa7e7b37b632 110 if( ptr->TuneAddress != (UInt8*)NULL ) {
RichardE 9:fa7e7b37b632 111 count++;
RichardE 9:fa7e7b37b632 112 }
RichardE 9:fa7e7b37b632 113 ptr++;
RichardE 9:fa7e7b37b632 114 }
RichardE 9:fa7e7b37b632 115 return count;
RichardE 9:fa7e7b37b632 116 }
RichardE 9:fa7e7b37b632 117
RichardE 9:fa7e7b37b632 118 /******************************/
RichardE 9:fa7e7b37b632 119 /* SILENCE ALL SOUNDS PLAYING */
RichardE 9:fa7e7b37b632 120 /******************************/
RichardE 9:fa7e7b37b632 121 void SoundManager::SilenceAll( void ) {
RichardE 9:fa7e7b37b632 122 TuneRecord *ptr = tuneRecords;
RichardE 9:fa7e7b37b632 123 for( UInt8 i = 0; i < VoiceCount; ++i ) {
RichardE 9:fa7e7b37b632 124 gd->voice( FirstVoice + i, Gameduino::SineWave, 0, 0, 0 );
RichardE 9:fa7e7b37b632 125 ptr->TuneAddress = (UInt8*)NULL;
RichardE 9:fa7e7b37b632 126 ptr++;
RichardE 9:fa7e7b37b632 127 }
RichardE 9:fa7e7b37b632 128 }
RichardE 9:fa7e7b37b632 129