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
- Committer:
- taylorza
- Date:
- 2015-01-28
- Revision:
- 0:d85c449aca6d
File content as of revision 0:d85c449aca6d:
#include "mbed.h" #include "Fix16.h" #include "lookupTables.h" #include "SoundBlock.h" #include "SoundChannel.h" SoundChannel::SoundChannel() : _state(4) { } void SoundChannel::play(const SoundBlock soundBlocks[], int count) { _soundBlocks = soundBlocks; _count = count; _index = 0; _state = 0; } bool SoundChannel::update(bool &pinState) { switch(_state) { case 0 : startSoundBlock(); break; case 3 : // Stop sound pinState = _pinState = false; _state = 4; return true; case 4 : // No sound return false; } if (updateCounters()) { switch(_currentSoundBlock.getToneType()) { case SoundBlock::Tone : updateTone(); pinState = _pinState; return true; case SoundBlock::Noise : updateNoise(); pinState = _pinState; return true; case SoundBlock::Pause : return false; } } return false; } void SoundChannel::updateTone() { switch(_state) { case 1: // High { _pinState = true; _pitchHighCounter -= fix16_one; if (_pitchHighCounter <= 0) { _pinState = false; _pitchHighCounter += _basePitchHighCount; _state = 2; } } break; case 2: // Low { _pinState = false; _pitchLowCounter -= fix16_one; if (_pitchLowCounter <= 0) { _pinState = true; _pitchLowCounter += _basePitchLowCount; _state = 1; } } break; } } void SoundChannel::updateNoise() { switch(_state) { case 1: // High/Low { _pitchHighCounter -= fix16_one; if (_pitchHighCounter <= 0) { _pinState = (SoundChannel::lfsr_rand() & 1) == 1; _pitchHighCounter += _basePitchHighCount; } } break; } } void SoundChannel::startSoundBlock() { _currentSoundBlock = _soundBlocks[_index]; _stepCounter = _currentSoundBlock.getStepCount(); _stepDurationCounter = _currentSoundBlock.getStepDuration(); _pitchOffset = 0; _dutyOffset = 0; updateAudioCounters(); _pitchHighCounter = _basePitchHighCount; _pitchLowCounter = _basePitchLowCount; _state = 1; } bool SoundChannel::updateCounters() { --_stepDurationCounter; if (_stepDurationCounter == 0) { --_stepCounter; if (_stepCounter == 0) { ++_index; if (_index == _count) { _state = 3; return false; } else { _state = 0; } } else { fix16_t pitchSlide = _currentSoundBlock.getPitchSlide(); int8_t dutySlide = _currentSoundBlock.getDutySlide(); if ( pitchSlide != 0 || dutySlide != 0) { _pitchOffset += pitchSlide; _dutyOffset += dutySlide; updateAudioCounters(); } _stepDurationCounter = _currentSoundBlock.getStepDuration(); } } return true; } void SoundChannel::updateAudioCounters() { fix16_t pitch = _currentSoundBlock.getPitch(_pitchOffset); if (pitch == 0) pitch = fix16_one; if (_currentSoundBlock.getToneType() == SoundBlock::Noise) pitch = fix16_div(pitch, fix16_100); _basePitchHighCount = fix16_mul(pitch, g_dutyLookup[_currentSoundBlock.getDuty(_dutyOffset)]); _basePitchLowCount = pitch - _basePitchHighCount; } uint16_t SoundChannel::lfsr_rand() { static uint16_t lfsr = 0xACE1u; lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u); return lfsr; }