Chris Taylor / Mbed 2 deprecated RETRO-CityRally

Dependencies:   mbed

Committer:
taylorza
Date:
Wed Jan 28 03:26:07 2015 +0000
Revision:
0:d85c449aca6d
Working maze scrolling, pre-maze compression

Who changed what in which revision?

UserRevisionLine numberNew contents of line
taylorza 0:d85c449aca6d 1 #include "mbed.h"
taylorza 0:d85c449aca6d 2 #include "Fix16.h"
taylorza 0:d85c449aca6d 3 #include "lookupTables.h"
taylorza 0:d85c449aca6d 4 #include "SoundBlock.h"
taylorza 0:d85c449aca6d 5 #include "SoundChannel.h"
taylorza 0:d85c449aca6d 6
taylorza 0:d85c449aca6d 7 SoundChannel::SoundChannel() :
taylorza 0:d85c449aca6d 8 _state(4)
taylorza 0:d85c449aca6d 9 {
taylorza 0:d85c449aca6d 10 }
taylorza 0:d85c449aca6d 11
taylorza 0:d85c449aca6d 12 void SoundChannel::play(const SoundBlock soundBlocks[], int count)
taylorza 0:d85c449aca6d 13 {
taylorza 0:d85c449aca6d 14 _soundBlocks = soundBlocks;
taylorza 0:d85c449aca6d 15 _count = count;
taylorza 0:d85c449aca6d 16 _index = 0;
taylorza 0:d85c449aca6d 17 _state = 0;
taylorza 0:d85c449aca6d 18 }
taylorza 0:d85c449aca6d 19
taylorza 0:d85c449aca6d 20 bool SoundChannel::update(bool &pinState)
taylorza 0:d85c449aca6d 21 {
taylorza 0:d85c449aca6d 22 switch(_state)
taylorza 0:d85c449aca6d 23 {
taylorza 0:d85c449aca6d 24 case 0 :
taylorza 0:d85c449aca6d 25 startSoundBlock();
taylorza 0:d85c449aca6d 26 break;
taylorza 0:d85c449aca6d 27
taylorza 0:d85c449aca6d 28 case 3 : // Stop sound
taylorza 0:d85c449aca6d 29 pinState = _pinState = false;
taylorza 0:d85c449aca6d 30 _state = 4;
taylorza 0:d85c449aca6d 31 return true;
taylorza 0:d85c449aca6d 32
taylorza 0:d85c449aca6d 33 case 4 : // No sound
taylorza 0:d85c449aca6d 34 return false;
taylorza 0:d85c449aca6d 35 }
taylorza 0:d85c449aca6d 36
taylorza 0:d85c449aca6d 37 if (updateCounters())
taylorza 0:d85c449aca6d 38 {
taylorza 0:d85c449aca6d 39 switch(_currentSoundBlock.getToneType())
taylorza 0:d85c449aca6d 40 {
taylorza 0:d85c449aca6d 41 case SoundBlock::Tone : updateTone(); pinState = _pinState; return true;
taylorza 0:d85c449aca6d 42 case SoundBlock::Noise : updateNoise(); pinState = _pinState; return true;
taylorza 0:d85c449aca6d 43 case SoundBlock::Pause : return false;
taylorza 0:d85c449aca6d 44 }
taylorza 0:d85c449aca6d 45 }
taylorza 0:d85c449aca6d 46
taylorza 0:d85c449aca6d 47 return false;
taylorza 0:d85c449aca6d 48 }
taylorza 0:d85c449aca6d 49
taylorza 0:d85c449aca6d 50 void SoundChannel::updateTone()
taylorza 0:d85c449aca6d 51 {
taylorza 0:d85c449aca6d 52 switch(_state)
taylorza 0:d85c449aca6d 53 {
taylorza 0:d85c449aca6d 54 case 1: // High
taylorza 0:d85c449aca6d 55 {
taylorza 0:d85c449aca6d 56 _pinState = true;
taylorza 0:d85c449aca6d 57 _pitchHighCounter -= fix16_one;
taylorza 0:d85c449aca6d 58 if (_pitchHighCounter <= 0)
taylorza 0:d85c449aca6d 59 {
taylorza 0:d85c449aca6d 60 _pinState = false;
taylorza 0:d85c449aca6d 61 _pitchHighCounter += _basePitchHighCount;
taylorza 0:d85c449aca6d 62 _state = 2;
taylorza 0:d85c449aca6d 63 }
taylorza 0:d85c449aca6d 64 }
taylorza 0:d85c449aca6d 65 break;
taylorza 0:d85c449aca6d 66
taylorza 0:d85c449aca6d 67 case 2: // Low
taylorza 0:d85c449aca6d 68 {
taylorza 0:d85c449aca6d 69 _pinState = false;
taylorza 0:d85c449aca6d 70 _pitchLowCounter -= fix16_one;
taylorza 0:d85c449aca6d 71 if (_pitchLowCounter <= 0)
taylorza 0:d85c449aca6d 72 {
taylorza 0:d85c449aca6d 73 _pinState = true;
taylorza 0:d85c449aca6d 74 _pitchLowCounter += _basePitchLowCount;
taylorza 0:d85c449aca6d 75 _state = 1;
taylorza 0:d85c449aca6d 76 }
taylorza 0:d85c449aca6d 77 }
taylorza 0:d85c449aca6d 78 break;
taylorza 0:d85c449aca6d 79 }
taylorza 0:d85c449aca6d 80 }
taylorza 0:d85c449aca6d 81
taylorza 0:d85c449aca6d 82 void SoundChannel::updateNoise()
taylorza 0:d85c449aca6d 83 {
taylorza 0:d85c449aca6d 84 switch(_state)
taylorza 0:d85c449aca6d 85 {
taylorza 0:d85c449aca6d 86 case 1: // High/Low
taylorza 0:d85c449aca6d 87 {
taylorza 0:d85c449aca6d 88 _pitchHighCounter -= fix16_one;
taylorza 0:d85c449aca6d 89 if (_pitchHighCounter <= 0)
taylorza 0:d85c449aca6d 90 {
taylorza 0:d85c449aca6d 91 _pinState = (SoundChannel::lfsr_rand() & 1) == 1;
taylorza 0:d85c449aca6d 92 _pitchHighCounter += _basePitchHighCount;
taylorza 0:d85c449aca6d 93 }
taylorza 0:d85c449aca6d 94 }
taylorza 0:d85c449aca6d 95 break;
taylorza 0:d85c449aca6d 96 }
taylorza 0:d85c449aca6d 97 }
taylorza 0:d85c449aca6d 98
taylorza 0:d85c449aca6d 99 void SoundChannel::startSoundBlock()
taylorza 0:d85c449aca6d 100 {
taylorza 0:d85c449aca6d 101 _currentSoundBlock = _soundBlocks[_index];
taylorza 0:d85c449aca6d 102
taylorza 0:d85c449aca6d 103 _stepCounter = _currentSoundBlock.getStepCount();
taylorza 0:d85c449aca6d 104 _stepDurationCounter = _currentSoundBlock.getStepDuration();
taylorza 0:d85c449aca6d 105 _pitchOffset = 0;
taylorza 0:d85c449aca6d 106 _dutyOffset = 0;
taylorza 0:d85c449aca6d 107
taylorza 0:d85c449aca6d 108 updateAudioCounters();
taylorza 0:d85c449aca6d 109 _pitchHighCounter = _basePitchHighCount;
taylorza 0:d85c449aca6d 110 _pitchLowCounter = _basePitchLowCount;
taylorza 0:d85c449aca6d 111
taylorza 0:d85c449aca6d 112 _state = 1;
taylorza 0:d85c449aca6d 113 }
taylorza 0:d85c449aca6d 114
taylorza 0:d85c449aca6d 115 bool SoundChannel::updateCounters()
taylorza 0:d85c449aca6d 116 {
taylorza 0:d85c449aca6d 117 --_stepDurationCounter;
taylorza 0:d85c449aca6d 118 if (_stepDurationCounter == 0)
taylorza 0:d85c449aca6d 119 {
taylorza 0:d85c449aca6d 120 --_stepCounter;
taylorza 0:d85c449aca6d 121 if (_stepCounter == 0)
taylorza 0:d85c449aca6d 122 {
taylorza 0:d85c449aca6d 123 ++_index;
taylorza 0:d85c449aca6d 124 if (_index == _count)
taylorza 0:d85c449aca6d 125 {
taylorza 0:d85c449aca6d 126 _state = 3;
taylorza 0:d85c449aca6d 127 return false;
taylorza 0:d85c449aca6d 128 }
taylorza 0:d85c449aca6d 129 else
taylorza 0:d85c449aca6d 130 {
taylorza 0:d85c449aca6d 131 _state = 0;
taylorza 0:d85c449aca6d 132 }
taylorza 0:d85c449aca6d 133 }
taylorza 0:d85c449aca6d 134 else
taylorza 0:d85c449aca6d 135 {
taylorza 0:d85c449aca6d 136 fix16_t pitchSlide = _currentSoundBlock.getPitchSlide();
taylorza 0:d85c449aca6d 137 int8_t dutySlide = _currentSoundBlock.getDutySlide();
taylorza 0:d85c449aca6d 138 if ( pitchSlide != 0 || dutySlide != 0)
taylorza 0:d85c449aca6d 139 {
taylorza 0:d85c449aca6d 140 _pitchOffset += pitchSlide;
taylorza 0:d85c449aca6d 141 _dutyOffset += dutySlide;
taylorza 0:d85c449aca6d 142 updateAudioCounters();
taylorza 0:d85c449aca6d 143 }
taylorza 0:d85c449aca6d 144
taylorza 0:d85c449aca6d 145 _stepDurationCounter = _currentSoundBlock.getStepDuration();
taylorza 0:d85c449aca6d 146 }
taylorza 0:d85c449aca6d 147 }
taylorza 0:d85c449aca6d 148 return true;
taylorza 0:d85c449aca6d 149 }
taylorza 0:d85c449aca6d 150
taylorza 0:d85c449aca6d 151 void SoundChannel::updateAudioCounters()
taylorza 0:d85c449aca6d 152 {
taylorza 0:d85c449aca6d 153 fix16_t pitch = _currentSoundBlock.getPitch(_pitchOffset);
taylorza 0:d85c449aca6d 154 if (pitch == 0) pitch = fix16_one;
taylorza 0:d85c449aca6d 155
taylorza 0:d85c449aca6d 156 if (_currentSoundBlock.getToneType() == SoundBlock::Noise)
taylorza 0:d85c449aca6d 157 pitch = fix16_div(pitch, fix16_100);
taylorza 0:d85c449aca6d 158
taylorza 0:d85c449aca6d 159 _basePitchHighCount = fix16_mul(pitch, g_dutyLookup[_currentSoundBlock.getDuty(_dutyOffset)]);
taylorza 0:d85c449aca6d 160 _basePitchLowCount = pitch - _basePitchHighCount;
taylorza 0:d85c449aca6d 161 }
taylorza 0:d85c449aca6d 162
taylorza 0:d85c449aca6d 163 uint16_t SoundChannel::lfsr_rand()
taylorza 0:d85c449aca6d 164 {
taylorza 0:d85c449aca6d 165 static uint16_t lfsr = 0xACE1u;
taylorza 0:d85c449aca6d 166 lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u);
taylorza 0:d85c449aca6d 167 return lfsr;
taylorza 0:d85c449aca6d 168 }