After decimating the enemy forces that have attacked your ship, you are charged with taking out as many of the remaining enemy fighters as possible. 3d space fighter game was initially written while I was testing some 3d routines I was implementing for a flight simulator, but my daughter started playing it and seemed to enjoy it so I added a few sound effects, explosions etc. and so this little game was born.
OneBitSound/SoundChannel.cpp@4:b857db213f10, 2015-02-08 (annotated)
- Committer:
- taylorza
- Date:
- Sun Feb 08 01:38:18 2015 +0000
- Revision:
- 4:b857db213f10
- Parent:
- 1:9ff7384171ec
Removed duty lookup table
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
taylorza | 1:9ff7384171ec | 1 | #include "mbed.h" |
taylorza | 1:9ff7384171ec | 2 | #include "Fix16.h" |
taylorza | 1:9ff7384171ec | 3 | #include "SoundBlock.h" |
taylorza | 1:9ff7384171ec | 4 | #include "SoundChannel.h" |
taylorza | 1:9ff7384171ec | 5 | |
taylorza | 1:9ff7384171ec | 6 | SoundChannel::SoundChannel() : |
taylorza | 1:9ff7384171ec | 7 | _state(4) |
taylorza | 1:9ff7384171ec | 8 | { |
taylorza | 1:9ff7384171ec | 9 | } |
taylorza | 1:9ff7384171ec | 10 | |
taylorza | 1:9ff7384171ec | 11 | void SoundChannel::play(const SoundBlock soundBlocks[], int count) |
taylorza | 1:9ff7384171ec | 12 | { |
taylorza | 1:9ff7384171ec | 13 | _soundBlocks = soundBlocks; |
taylorza | 1:9ff7384171ec | 14 | _count = count; |
taylorza | 1:9ff7384171ec | 15 | _index = 0; |
taylorza | 1:9ff7384171ec | 16 | _state = 0; |
taylorza | 1:9ff7384171ec | 17 | } |
taylorza | 1:9ff7384171ec | 18 | |
taylorza | 1:9ff7384171ec | 19 | bool SoundChannel::update(bool &pinState) |
taylorza | 1:9ff7384171ec | 20 | { |
taylorza | 1:9ff7384171ec | 21 | switch(_state) |
taylorza | 1:9ff7384171ec | 22 | { |
taylorza | 1:9ff7384171ec | 23 | case 0 : |
taylorza | 1:9ff7384171ec | 24 | startSoundBlock(); |
taylorza | 1:9ff7384171ec | 25 | break; |
taylorza | 1:9ff7384171ec | 26 | |
taylorza | 1:9ff7384171ec | 27 | case 3 : // Stop sound |
taylorza | 1:9ff7384171ec | 28 | pinState = _pinState = false; |
taylorza | 1:9ff7384171ec | 29 | _state = 4; |
taylorza | 1:9ff7384171ec | 30 | return true; |
taylorza | 1:9ff7384171ec | 31 | |
taylorza | 1:9ff7384171ec | 32 | case 4 : // No sound |
taylorza | 1:9ff7384171ec | 33 | return false; |
taylorza | 1:9ff7384171ec | 34 | } |
taylorza | 1:9ff7384171ec | 35 | |
taylorza | 1:9ff7384171ec | 36 | if (updateCounters()) |
taylorza | 1:9ff7384171ec | 37 | { |
taylorza | 1:9ff7384171ec | 38 | switch(_currentSoundBlock.getToneType()) |
taylorza | 1:9ff7384171ec | 39 | { |
taylorza | 1:9ff7384171ec | 40 | case SoundBlock::Tone : updateTone(); pinState = _pinState; return true; |
taylorza | 1:9ff7384171ec | 41 | case SoundBlock::Noise : updateNoise(); pinState = _pinState; return true; |
taylorza | 1:9ff7384171ec | 42 | case SoundBlock::Pause : return false; |
taylorza | 1:9ff7384171ec | 43 | } |
taylorza | 1:9ff7384171ec | 44 | } |
taylorza | 1:9ff7384171ec | 45 | |
taylorza | 1:9ff7384171ec | 46 | return false; |
taylorza | 1:9ff7384171ec | 47 | } |
taylorza | 1:9ff7384171ec | 48 | |
taylorza | 1:9ff7384171ec | 49 | void SoundChannel::updateTone() |
taylorza | 1:9ff7384171ec | 50 | { |
taylorza | 1:9ff7384171ec | 51 | switch(_state) |
taylorza | 1:9ff7384171ec | 52 | { |
taylorza | 1:9ff7384171ec | 53 | case 1: // High |
taylorza | 1:9ff7384171ec | 54 | { |
taylorza | 1:9ff7384171ec | 55 | _pinState = true; |
taylorza | 1:9ff7384171ec | 56 | _pitchHighCounter -= fix16_one; |
taylorza | 1:9ff7384171ec | 57 | if (_pitchHighCounter <= 0) |
taylorza | 1:9ff7384171ec | 58 | { |
taylorza | 1:9ff7384171ec | 59 | _pinState = false; |
taylorza | 1:9ff7384171ec | 60 | _pitchHighCounter += _basePitchHighCount; |
taylorza | 1:9ff7384171ec | 61 | _state = 2; |
taylorza | 1:9ff7384171ec | 62 | } |
taylorza | 1:9ff7384171ec | 63 | } |
taylorza | 1:9ff7384171ec | 64 | break; |
taylorza | 1:9ff7384171ec | 65 | |
taylorza | 1:9ff7384171ec | 66 | case 2: // Low |
taylorza | 1:9ff7384171ec | 67 | { |
taylorza | 1:9ff7384171ec | 68 | _pinState = false; |
taylorza | 1:9ff7384171ec | 69 | _pitchLowCounter -= fix16_one; |
taylorza | 1:9ff7384171ec | 70 | if (_pitchLowCounter <= 0) |
taylorza | 1:9ff7384171ec | 71 | { |
taylorza | 1:9ff7384171ec | 72 | _pinState = true; |
taylorza | 1:9ff7384171ec | 73 | _pitchLowCounter += _basePitchLowCount; |
taylorza | 1:9ff7384171ec | 74 | _state = 1; |
taylorza | 1:9ff7384171ec | 75 | } |
taylorza | 1:9ff7384171ec | 76 | } |
taylorza | 1:9ff7384171ec | 77 | break; |
taylorza | 1:9ff7384171ec | 78 | } |
taylorza | 1:9ff7384171ec | 79 | } |
taylorza | 1:9ff7384171ec | 80 | |
taylorza | 1:9ff7384171ec | 81 | void SoundChannel::updateNoise() |
taylorza | 1:9ff7384171ec | 82 | { |
taylorza | 1:9ff7384171ec | 83 | switch(_state) |
taylorza | 1:9ff7384171ec | 84 | { |
taylorza | 1:9ff7384171ec | 85 | case 1: // High/Low |
taylorza | 1:9ff7384171ec | 86 | { |
taylorza | 1:9ff7384171ec | 87 | _pitchHighCounter -= fix16_one; |
taylorza | 1:9ff7384171ec | 88 | if (_pitchHighCounter <= 0) |
taylorza | 1:9ff7384171ec | 89 | { |
taylorza | 1:9ff7384171ec | 90 | _pinState = (SoundChannel::lfsr_rand() & 1) == 1; |
taylorza | 1:9ff7384171ec | 91 | _pitchHighCounter += _basePitchHighCount; |
taylorza | 1:9ff7384171ec | 92 | } |
taylorza | 1:9ff7384171ec | 93 | } |
taylorza | 1:9ff7384171ec | 94 | break; |
taylorza | 1:9ff7384171ec | 95 | } |
taylorza | 1:9ff7384171ec | 96 | } |
taylorza | 1:9ff7384171ec | 97 | |
taylorza | 1:9ff7384171ec | 98 | void SoundChannel::startSoundBlock() |
taylorza | 1:9ff7384171ec | 99 | { |
taylorza | 1:9ff7384171ec | 100 | _currentSoundBlock = _soundBlocks[_index]; |
taylorza | 1:9ff7384171ec | 101 | |
taylorza | 1:9ff7384171ec | 102 | _stepCounter = _currentSoundBlock.getStepCount(); |
taylorza | 1:9ff7384171ec | 103 | _stepDurationCounter = _currentSoundBlock.getStepDuration(); |
taylorza | 1:9ff7384171ec | 104 | _pitchOffset = 0; |
taylorza | 1:9ff7384171ec | 105 | _dutyOffset = 0; |
taylorza | 1:9ff7384171ec | 106 | |
taylorza | 1:9ff7384171ec | 107 | updateAudioCounters(); |
taylorza | 1:9ff7384171ec | 108 | _pitchHighCounter = _basePitchHighCount; |
taylorza | 1:9ff7384171ec | 109 | _pitchLowCounter = _basePitchLowCount; |
taylorza | 1:9ff7384171ec | 110 | |
taylorza | 1:9ff7384171ec | 111 | _state = 1; |
taylorza | 1:9ff7384171ec | 112 | } |
taylorza | 1:9ff7384171ec | 113 | |
taylorza | 1:9ff7384171ec | 114 | bool SoundChannel::updateCounters() |
taylorza | 1:9ff7384171ec | 115 | { |
taylorza | 1:9ff7384171ec | 116 | --_stepDurationCounter; |
taylorza | 1:9ff7384171ec | 117 | if (_stepDurationCounter == 0) |
taylorza | 1:9ff7384171ec | 118 | { |
taylorza | 1:9ff7384171ec | 119 | --_stepCounter; |
taylorza | 1:9ff7384171ec | 120 | if (_stepCounter == 0) |
taylorza | 1:9ff7384171ec | 121 | { |
taylorza | 1:9ff7384171ec | 122 | ++_index; |
taylorza | 1:9ff7384171ec | 123 | if (_index == _count) |
taylorza | 1:9ff7384171ec | 124 | { |
taylorza | 1:9ff7384171ec | 125 | _state = 3; |
taylorza | 1:9ff7384171ec | 126 | return false; |
taylorza | 1:9ff7384171ec | 127 | } |
taylorza | 1:9ff7384171ec | 128 | else |
taylorza | 1:9ff7384171ec | 129 | { |
taylorza | 1:9ff7384171ec | 130 | _state = 0; |
taylorza | 1:9ff7384171ec | 131 | } |
taylorza | 1:9ff7384171ec | 132 | } |
taylorza | 1:9ff7384171ec | 133 | else |
taylorza | 1:9ff7384171ec | 134 | { |
taylorza | 1:9ff7384171ec | 135 | fix16_t pitchSlide = _currentSoundBlock.getPitchSlide(); |
taylorza | 1:9ff7384171ec | 136 | int8_t dutySlide = _currentSoundBlock.getDutySlide(); |
taylorza | 1:9ff7384171ec | 137 | if ( pitchSlide != 0 || dutySlide != 0) |
taylorza | 1:9ff7384171ec | 138 | { |
taylorza | 1:9ff7384171ec | 139 | _pitchOffset += pitchSlide; |
taylorza | 1:9ff7384171ec | 140 | _dutyOffset += dutySlide; |
taylorza | 1:9ff7384171ec | 141 | updateAudioCounters(); |
taylorza | 1:9ff7384171ec | 142 | } |
taylorza | 1:9ff7384171ec | 143 | |
taylorza | 1:9ff7384171ec | 144 | _stepDurationCounter = _currentSoundBlock.getStepDuration(); |
taylorza | 1:9ff7384171ec | 145 | } |
taylorza | 1:9ff7384171ec | 146 | } |
taylorza | 1:9ff7384171ec | 147 | return true; |
taylorza | 1:9ff7384171ec | 148 | } |
taylorza | 1:9ff7384171ec | 149 | |
taylorza | 1:9ff7384171ec | 150 | void SoundChannel::updateAudioCounters() |
taylorza | 1:9ff7384171ec | 151 | { |
taylorza | 1:9ff7384171ec | 152 | fix16_t pitch = _currentSoundBlock.getPitch(_pitchOffset); |
taylorza | 1:9ff7384171ec | 153 | if (pitch == 0) pitch = fix16_one; |
taylorza | 1:9ff7384171ec | 154 | |
taylorza | 1:9ff7384171ec | 155 | if (_currentSoundBlock.getToneType() == SoundBlock::Noise) |
taylorza | 1:9ff7384171ec | 156 | pitch = fix16_div(pitch, fix16_100); |
taylorza | 1:9ff7384171ec | 157 | |
taylorza | 4:b857db213f10 | 158 | _basePitchHighCount = fix16_mul(pitch, _currentSoundBlock.getDuty(_dutyOffset) * 0x100); |
taylorza | 1:9ff7384171ec | 159 | _basePitchLowCount = pitch - _basePitchHighCount; |
taylorza | 1:9ff7384171ec | 160 | } |
taylorza | 1:9ff7384171ec | 161 | |
taylorza | 1:9ff7384171ec | 162 | uint16_t SoundChannel::lfsr_rand() |
taylorza | 1:9ff7384171ec | 163 | { |
taylorza | 1:9ff7384171ec | 164 | static uint16_t lfsr = 0xACE1u; |
taylorza | 1:9ff7384171ec | 165 | lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u); |
taylorza | 1:9ff7384171ec | 166 | return lfsr; |
taylorza | 1:9ff7384171ec | 167 | } |