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
SoundManager.cpp@9:fa7e7b37b632, 2013-06-09 (annotated)
- Committer:
- RichardE
- Date:
- Sun Jun 09 14:28:53 2013 +0000
- Revision:
- 9:fa7e7b37b632
Sound is now working. Now a complete working game, albeit with only 2 levels.
Who changed what in which revision?
User | Revision | Line number | New 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 |