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

Committer:
RichardE
Date:
2013-06-17
Revision:
18:70190f956a24
Parent:
9:fa7e7b37b632

File content as of revision 18:70190f956a24:

/*
 * SOURCE FILE : SoundManager.cpp
 *
 * Responsible for playing simple sounds.
 *
 */

#include "SoundManager.h"
#include "Notes.h"

// An instance of the SoundManager class.
SoundManager SoundManager::Instance;

/***************/
/* CONSTRUCTOR */
/***************/
SoundManager::SoundManager() :
    gd( (Gameduino*)NULL )
{
}

/*****************************/
/* UPDATE A SINGLE TUNE SLOT */
/*****************************/
// Do NOT call with a record containing zero in TuneAddress (a free slot).
void SoundManager::UpdateTuneSection( UInt8 voiceNum, TuneRecord *rec ) {
  if( rec->Countdown > 0 ) {
    rec->Countdown--;
  }
  else {
    // Countdown has reached zero. Load next section of tune.
    UInt8 noteNum = *(rec->TuneAddress++);
    if( noteNum == 0 ) {
      // End of tune. Silence voice and set tune address to NULL to
      // indicate slot is free.
      gd->voice( voiceNum, Gameduino::SineWave, 0, 0, 0 );
      rec->TuneAddress = (UInt8*)NULL;
    }
    else {
      // Convert note number to frequency.
      UInt16 frequency = Notes::NoteFrequencies[ noteNum ];
      // Read amplitude for next tune section and add biases.
      UInt8 amp = *(rec->TuneAddress++);
      // Start playing section.
      gd->voice( voiceNum, rec->TuneWaveform, frequency, amp + rec->LeftAmpBias, amp + rec->RightAmpBias );
      // Set countdown according to length of this section.
      rec->Countdown = *(rec->TuneAddress++);
    }
  }
}

/************************/
/* TRY AND PLAY A SOUND */
/************************/
// Pass address of tune in program memory in tuneAddress.
// Pass bias to apply to left speaker amplitude in leftAmpBias.
// Pass bias to apply to right speaker amplitude in leftAmpBias.
// Returns true if sound was started, false if no sound slots free.
bool SoundManager::PlaySound( const UInt8 *tuneAddress, UInt8 leftAmpBias, UInt8 rightAmpBias ) {
  // Find a tune record that is free.
  UInt8 i = 0;
  TuneRecord *rec = tuneRecords;
  while( ( i < VoiceCount ) && ( rec->TuneAddress != (UInt8*)NULL ) ) {
    i++;
    rec++;
  }
  if( i < VoiceCount ) {
    // Found a free tune record. Initialise it.
    rec->TuneWaveform = (Gameduino::WaveForm)*tuneAddress;
    rec->TuneAddress = tuneAddress + 1;
    rec->LeftAmpBias = leftAmpBias;
    rec->RightAmpBias = rightAmpBias;
    rec->Countdown = 0;
    // Start playing first part of sound.
    UpdateTuneSection( FirstVoice + i, rec );
    return true;
  }
  else {
    // No free counter found.
    return false;
  }
}

/****************************/
/* UPDATE PLAYING OF SOUNDS */
/****************************/
// Should be called at regular intervals.
void SoundManager::Update( void ) {
  TuneRecord *ptr = tuneRecords;
  // Repeat for all tune records.
  for( UInt8 i = 0; i < VoiceCount; ++i ) {
    // Skip over any unused records (with TuneAddress of zero).
    if( ptr->TuneAddress != (UInt8*)NULL ) {
      UpdateTuneSection( FirstVoice + i, ptr );
    }
    ptr++;
  }
}

/**********************************/
/* COUNT NUMBER OF SOUNDS PLAYING */
/**********************************/
// Returns number of sounds playing.
UInt8 SoundManager::CountSoundsPlaying( void ) {
  UInt8 count = 0;
  TuneRecord *ptr = tuneRecords;
  // Repeat for all tune records.
  for( UInt8 i = 0; i < VoiceCount; ++i ) {
    // If TuneAddress is not zero then increment count.
    if( ptr->TuneAddress != (UInt8*)NULL ) {
      count++;
    }
    ptr++;
  }
  return count;
}

/******************************/
/* SILENCE ALL SOUNDS PLAYING */
/******************************/
void SoundManager::SilenceAll( void ) {
  TuneRecord *ptr = tuneRecords;
  for( UInt8 i = 0; i < VoiceCount; ++i ) {
    gd->voice( FirstVoice + i, Gameduino::SineWave, 0, 0, 0 );
    ptr->TuneAddress = (UInt8*)NULL;
    ptr++;
  }
}