Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
OneBitSound/SoundChannel.cpp@0:d85c449aca6d, 2015-01-28 (annotated)
- 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?
User | Revision | Line number | New 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 | } |