Platform library for RETRO

Dependents:   RETRO_RickGame

Committer:
Architect
Date:
Sun Mar 01 05:29:45 2015 +0000
Revision:
0:6f26c31d8573
RetroPlatform Library for RETRO gaming system

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Architect 0:6f26c31d8573 1 /*
Architect 0:6f26c31d8573 2 * (C) Copyright 2015 Valentin Ivanov. All rights reserved.
Architect 0:6f26c31d8573 3 *
Architect 0:6f26c31d8573 4 * This file is part of the RetroPlatform Library
Architect 0:6f26c31d8573 5 *
Architect 0:6f26c31d8573 6 * The RetroPlatform Library is free software: you can redistribute it and/or modify
Architect 0:6f26c31d8573 7 * it under the terms of the GNU Lesser General Public License as published by
Architect 0:6f26c31d8573 8 * the Free Software Foundation, either version 3 of the License, or
Architect 0:6f26c31d8573 9 * (at your option) any later version.
Architect 0:6f26c31d8573 10 *
Architect 0:6f26c31d8573 11 * This program is distributed in the hope that it will be useful,
Architect 0:6f26c31d8573 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Architect 0:6f26c31d8573 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Architect 0:6f26c31d8573 14 * GNU Lesser General Public License for more details.
Architect 0:6f26c31d8573 15 *
Architect 0:6f26c31d8573 16 * You should have received a copy of the GNU Lesser General Public License
Architect 0:6f26c31d8573 17 * along with this program. If not, see <http://www.gnu.org/licenses/>
Architect 0:6f26c31d8573 18 *
Architect 0:6f26c31d8573 19 * This library is inspired by Gamebuino Library (http://gamebuino.com)
Architect 0:6f26c31d8573 20 * from Aurélien Rodot.
Architect 0:6f26c31d8573 21 */
Architect 0:6f26c31d8573 22 #ifndef SOUND_H
Architect 0:6f26c31d8573 23 #define SOUND_H
Architect 0:6f26c31d8573 24
Architect 0:6f26c31d8573 25 #include <mbed.h>
Architect 0:6f26c31d8573 26
Architect 0:6f26c31d8573 27 //commands
Architect 0:6f26c31d8573 28 #define CMD_VOLUME 0
Architect 0:6f26c31d8573 29 #define CMD_INSTRUMENT 1
Architect 0:6f26c31d8573 30 #define CMD_SLIDE 2
Architect 0:6f26c31d8573 31 #define CMD_ARPEGGIO 3
Architect 0:6f26c31d8573 32 #define CMD_TREMOLO 4
Architect 0:6f26c31d8573 33
Architect 0:6f26c31d8573 34
Architect 0:6f26c31d8573 35 #define NUM_CHANNELS 3 //number of sound channels (no more than 4)
Architect 0:6f26c31d8573 36
Architect 0:6f26c31d8573 37 #define VOLUME_GLOBAL_MAX 1
Architect 0:6f26c31d8573 38
Architect 0:6f26c31d8573 39 //7=instrument volume 9=note volume
Architect 0:6f26c31d8573 40 #define VOLUME_CHANNEL_MAX 255/NUM_CHANNELS/VOLUME_GLOBAL_MAX/7/9
Architect 0:6f26c31d8573 41
Architect 0:6f26c31d8573 42 #define boolean bool
Architect 0:6f26c31d8573 43
Architect 0:6f26c31d8573 44 //A set of sequences
Architect 0:6f26c31d8573 45 typedef struct {
Architect 0:6f26c31d8573 46 uint16_t *Data;
Architect 0:6f26c31d8573 47 uint8_t Cursor;
Architect 0:6f26c31d8573 48 bool IsPlaying;
Architect 0:6f26c31d8573 49 } Track;
Architect 0:6f26c31d8573 50
Architect 0:6f26c31d8573 51 //A sequence of commands and notes
Architect 0:6f26c31d8573 52 typedef struct {
Architect 0:6f26c31d8573 53 uint16_t *Data;
Architect 0:6f26c31d8573 54 bool Looping;
Architect 0:6f26c31d8573 55 uint16_t Cursor;
Architect 0:6f26c31d8573 56 bool IsPlaying;
Architect 0:6f26c31d8573 57 } Sequence;
Architect 0:6f26c31d8573 58
Architect 0:6f26c31d8573 59 //A note of selected pitch, duration and volume
Architect 0:6f26c31d8573 60 typedef struct {
Architect 0:6f26c31d8573 61 uint8_t Pitch;
Architect 0:6f26c31d8573 62 uint8_t Duration;
Architect 0:6f26c31d8573 63 int8_t Volume;
Architect 0:6f26c31d8573 64 bool IsPlaying;
Architect 0:6f26c31d8573 65 } Note;
Architect 0:6f26c31d8573 66
Architect 0:6f26c31d8573 67 typedef struct {
Architect 0:6f26c31d8573 68 int8_t Counter;
Architect 0:6f26c31d8573 69 int8_t volumeSlideStepDuration;
Architect 0:6f26c31d8573 70 int8_t volumeSlideStepSize;
Architect 0:6f26c31d8573 71 uint8_t arpeggioStepDuration;
Architect 0:6f26c31d8573 72 int8_t arpeggioStepSize;
Architect 0:6f26c31d8573 73 uint8_t tremoloStepDuration;
Architect 0:6f26c31d8573 74 int8_t tremoloStepSize;
Architect 0:6f26c31d8573 75
Architect 0:6f26c31d8573 76 } Command;
Architect 0:6f26c31d8573 77
Architect 0:6f26c31d8573 78 typedef struct {
Architect 0:6f26c31d8573 79 uint16_t **SequenceSet;
Architect 0:6f26c31d8573 80 uint16_t **InstrumentSet;
Architect 0:6f26c31d8573 81
Architect 0:6f26c31d8573 82 uint8_t Volume;
Architect 0:6f26c31d8573 83 uint8_t Count;
Architect 0:6f26c31d8573 84 bool State;
Architect 0:6f26c31d8573 85 uint8_t HalfPeriod;
Architect 0:6f26c31d8573 86 uint8_t OutputVolume;
Architect 0:6f26c31d8573 87 uint8_t Output;
Architect 0:6f26c31d8573 88 bool Noise;
Architect 0:6f26c31d8573 89
Architect 0:6f26c31d8573 90
Architect 0:6f26c31d8573 91
Architect 0:6f26c31d8573 92 int8_t SequencePitch;
Architect 0:6f26c31d8573 93 } AudioChannel;
Architect 0:6f26c31d8573 94
Architect 0:6f26c31d8573 95 typedef struct {
Architect 0:6f26c31d8573 96 uint16_t *Data;
Architect 0:6f26c31d8573 97 uint8_t Length;
Architect 0:6f26c31d8573 98 uint8_t Looping;
Architect 0:6f26c31d8573 99 uint16_t Cursor;
Architect 0:6f26c31d8573 100 uint8_t NextChange;
Architect 0:6f26c31d8573 101 } Instrument;
Architect 0:6f26c31d8573 102
Architect 0:6f26c31d8573 103 class Sound {
Architect 0:6f26c31d8573 104
Architect 0:6f26c31d8573 105 Ticker timer;
Architect 0:6f26c31d8573 106 PwmOut speaker;
Architect 0:6f26c31d8573 107
Architect 0:6f26c31d8573 108 Track tracks[NUM_CHANNELS];
Architect 0:6f26c31d8573 109 Sequence sequences[NUM_CHANNELS];
Architect 0:6f26c31d8573 110 Command commands[NUM_CHANNELS];
Architect 0:6f26c31d8573 111 Instrument instruments[NUM_CHANNELS];
Architect 0:6f26c31d8573 112
Architect 0:6f26c31d8573 113 public:
Architect 0:6f26c31d8573 114 Sound();
Architect 0:6f26c31d8573 115 void initialize();
Architect 0:6f26c31d8573 116
Architect 0:6f26c31d8573 117 void update()
Architect 0:6f26c31d8573 118 {
Architect 0:6f26c31d8573 119 updateTracks();
Architect 0:6f26c31d8573 120 updateSequences();
Architect 0:6f26c31d8573 121 updateNotes();
Architect 0:6f26c31d8573 122 }
Architect 0:6f26c31d8573 123
Architect 0:6f26c31d8573 124 void playTrack(const uint16_t* track, uint8_t channel);
Architect 0:6f26c31d8573 125 void updateTrack(uint8_t channel);
Architect 0:6f26c31d8573 126 void stopTrack(uint8_t channel);
Architect 0:6f26c31d8573 127 void stopTracks() {
Architect 0:6f26c31d8573 128 for(uint8_t channel=0; channel<NUM_CHANNELS; channel++)
Architect 0:6f26c31d8573 129 stopTrack(channel);
Architect 0:6f26c31d8573 130 }
Architect 0:6f26c31d8573 131 void updateTracks() {
Architect 0:6f26c31d8573 132 for(uint8_t channel=0; channel<NUM_CHANNELS; channel++)
Architect 0:6f26c31d8573 133 updateTrack(channel);
Architect 0:6f26c31d8573 134 }
Architect 0:6f26c31d8573 135
Architect 0:6f26c31d8573 136 void changeSequenceSet(const uint16_t* const* patterns, uint8_t channel);
Architect 0:6f26c31d8573 137
Architect 0:6f26c31d8573 138 bool isTrackPlaying(uint8_t channel)
Architect 0:6f26c31d8573 139 {
Architect 0:6f26c31d8573 140 return tracks[channel].IsPlaying;
Architect 0:6f26c31d8573 141 }
Architect 0:6f26c31d8573 142
Architect 0:6f26c31d8573 143 void playSequence(const uint16_t* pattern, uint8_t channel);
Architect 0:6f26c31d8573 144 void changeInstrumentSet(const uint16_t* const* instruments, uint8_t channel);
Architect 0:6f26c31d8573 145 void updateSequence(uint8_t channel);
Architect 0:6f26c31d8573 146 void stopSequence(uint8_t channel);
Architect 0:6f26c31d8573 147 void stopSequences() {
Architect 0:6f26c31d8573 148 for(uint8_t channel=0; channel<NUM_CHANNELS; channel++)
Architect 0:6f26c31d8573 149 stopSequence(channel);
Architect 0:6f26c31d8573 150 }
Architect 0:6f26c31d8573 151 void updateSequences() {
Architect 0:6f26c31d8573 152 for(uint8_t channel=0; channel<NUM_CHANNELS; channel++)
Architect 0:6f26c31d8573 153 updateSequence(channel);
Architect 0:6f26c31d8573 154 }
Architect 0:6f26c31d8573 155
Architect 0:6f26c31d8573 156
Architect 0:6f26c31d8573 157 void playNote(uint8_t pitch, uint8_t duration, uint8_t channel);
Architect 0:6f26c31d8573 158 void updateNote(uint8_t i);
Architect 0:6f26c31d8573 159 void stopNote(uint8_t channel);
Architect 0:6f26c31d8573 160 void updateNotes() {
Architect 0:6f26c31d8573 161 for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++)
Architect 0:6f26c31d8573 162 updateNote(channel);
Architect 0:6f26c31d8573 163 }
Architect 0:6f26c31d8573 164 void stopNotes() {
Architect 0:6f26c31d8573 165 for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++)
Architect 0:6f26c31d8573 166 stopNote(channel);
Architect 0:6f26c31d8573 167 }
Architect 0:6f26c31d8573 168
Architect 0:6f26c31d8573 169 void command(uint8_t cmd, uint8_t X, int8_t Y, uint8_t channel);
Architect 0:6f26c31d8573 170
Architect 0:6f26c31d8573 171 uint8_t outputPitch[NUM_CHANNELS];
Architect 0:6f26c31d8573 172 int8_t outputVolume[NUM_CHANNELS];
Architect 0:6f26c31d8573 173
Architect 0:6f26c31d8573 174 void setVolume(int8_t volume);
Architect 0:6f26c31d8573 175 uint8_t getVolume();
Architect 0:6f26c31d8573 176 void setVolume(int8_t volume, uint8_t channel);
Architect 0:6f26c31d8573 177 uint8_t getVolume(uint8_t channel);
Architect 0:6f26c31d8573 178
Architect 0:6f26c31d8573 179
Architect 0:6f26c31d8573 180 uint8_t prescaler;
Architect 0:6f26c31d8573 181
Architect 0:6f26c31d8573 182 void setChannelHalfPeriod(uint8_t channel, uint8_t halfPeriod);
Architect 0:6f26c31d8573 183
Architect 0:6f26c31d8573 184
Architect 0:6f26c31d8573 185 uint8_t globalVolume;
Architect 0:6f26c31d8573 186 uint8_t volumeMax;
Architect 0:6f26c31d8573 187
Architect 0:6f26c31d8573 188 #if (NUM_CHANNELS > 0)
Architect 0:6f26c31d8573 189 //tracks data
Architect 0:6f26c31d8573 190 uint16_t **patternSet[NUM_CHANNELS];
Architect 0:6f26c31d8573 191 int8_t patternPitch[NUM_CHANNELS];
Architect 0:6f26c31d8573 192
Architect 0:6f26c31d8573 193 // pattern data
Architect 0:6f26c31d8573 194 uint16_t **instrumentSet[NUM_CHANNELS];
Architect 0:6f26c31d8573 195
Architect 0:6f26c31d8573 196 // note data
Architect 0:6f26c31d8573 197 uint8_t notePitch[NUM_CHANNELS];
Architect 0:6f26c31d8573 198 uint8_t noteDuration[NUM_CHANNELS];
Architect 0:6f26c31d8573 199 int8_t noteVolume[NUM_CHANNELS];
Architect 0:6f26c31d8573 200 boolean notePlaying[NUM_CHANNELS];
Architect 0:6f26c31d8573 201
Architect 0:6f26c31d8573 202
Architect 0:6f26c31d8573 203 //current step data
Architect 0:6f26c31d8573 204 int8_t stepVolume[NUM_CHANNELS];
Architect 0:6f26c31d8573 205 uint8_t stepPitch[NUM_CHANNELS];
Architect 0:6f26c31d8573 206
Architect 0:6f26c31d8573 207 uint8_t chanVolumes[NUM_CHANNELS];
Architect 0:6f26c31d8573 208
Architect 0:6f26c31d8573 209
Architect 0:6f26c31d8573 210 uint8_t _chanCount[NUM_CHANNELS]; //counts until the next change of the waveform
Architect 0:6f26c31d8573 211 boolean _chanState[NUM_CHANNELS]; //if the waveform is currently high or low
Architect 0:6f26c31d8573 212 uint8_t _chanHalfPeriod[NUM_CHANNELS]; //duration of half the period of the waveform
Architect 0:6f26c31d8573 213 uint8_t _chanOutputVolume[NUM_CHANNELS]; //amplitude of the outputted waveform
Architect 0:6f26c31d8573 214 uint8_t _chanOutput[NUM_CHANNELS]; //current value of the outputted waveform
Architect 0:6f26c31d8573 215 boolean _chanNoise[NUM_CHANNELS]; //if a random value should be added to the waveform to generate noise
Architect 0:6f26c31d8573 216
Architect 0:6f26c31d8573 217 #endif
Architect 0:6f26c31d8573 218 void updateOutput();
Architect 0:6f26c31d8573 219
Architect 0:6f26c31d8573 220 private:
Architect 0:6f26c31d8573 221 void generateOutput();
Architect 0:6f26c31d8573 222 };
Architect 0:6f26c31d8573 223
Architect 0:6f26c31d8573 224 #endif /* SOUND_H */