Platform library for RETRO
Embed:
(wiki syntax)
Show/hide line numbers
Sound.h
00001 /* 00002 * (C) Copyright 2015 Valentin Ivanov. All rights reserved. 00003 * 00004 * This file is part of the RetroPlatform Library 00005 * 00006 * The RetroPlatform Library is free software: you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation, either version 3 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 * 00019 * This library is inspired by Gamebuino Library (http://gamebuino.com) 00020 * from Aurélien Rodot. 00021 */ 00022 #ifndef SOUND_H 00023 #define SOUND_H 00024 00025 #include <mbed.h> 00026 00027 //commands 00028 #define CMD_VOLUME 0 00029 #define CMD_INSTRUMENT 1 00030 #define CMD_SLIDE 2 00031 #define CMD_ARPEGGIO 3 00032 #define CMD_TREMOLO 4 00033 00034 00035 #define NUM_CHANNELS 3 //number of sound channels (no more than 4) 00036 00037 #define VOLUME_GLOBAL_MAX 1 00038 00039 //7=instrument volume 9=note volume 00040 #define VOLUME_CHANNEL_MAX 255/NUM_CHANNELS/VOLUME_GLOBAL_MAX/7/9 00041 00042 #define boolean bool 00043 00044 //A set of sequences 00045 typedef struct { 00046 uint16_t *Data; 00047 uint8_t Cursor; 00048 bool IsPlaying; 00049 } Track; 00050 00051 //A sequence of commands and notes 00052 typedef struct { 00053 uint16_t *Data; 00054 bool Looping; 00055 uint16_t Cursor; 00056 bool IsPlaying; 00057 } Sequence; 00058 00059 //A note of selected pitch, duration and volume 00060 typedef struct { 00061 uint8_t Pitch; 00062 uint8_t Duration; 00063 int8_t Volume; 00064 bool IsPlaying; 00065 } Note; 00066 00067 typedef struct { 00068 int8_t Counter; 00069 int8_t volumeSlideStepDuration; 00070 int8_t volumeSlideStepSize; 00071 uint8_t arpeggioStepDuration; 00072 int8_t arpeggioStepSize; 00073 uint8_t tremoloStepDuration; 00074 int8_t tremoloStepSize; 00075 00076 } Command; 00077 00078 typedef struct { 00079 uint16_t **SequenceSet; 00080 uint16_t **InstrumentSet; 00081 00082 uint8_t Volume; 00083 uint8_t Count; 00084 bool State; 00085 uint8_t HalfPeriod; 00086 uint8_t OutputVolume; 00087 uint8_t Output; 00088 bool Noise; 00089 00090 00091 00092 int8_t SequencePitch; 00093 } AudioChannel; 00094 00095 typedef struct { 00096 uint16_t *Data; 00097 uint8_t Length; 00098 uint8_t Looping; 00099 uint16_t Cursor; 00100 uint8_t NextChange; 00101 } Instrument; 00102 00103 class Sound { 00104 00105 Ticker timer; 00106 PwmOut speaker; 00107 00108 Track tracks[NUM_CHANNELS]; 00109 Sequence sequences[NUM_CHANNELS]; 00110 Command commands[NUM_CHANNELS]; 00111 Instrument instruments[NUM_CHANNELS]; 00112 00113 public: 00114 Sound(); 00115 void initialize(); 00116 00117 void update() 00118 { 00119 updateTracks(); 00120 updateSequences(); 00121 updateNotes(); 00122 } 00123 00124 void playTrack(const uint16_t* track, uint8_t channel); 00125 void updateTrack(uint8_t channel); 00126 void stopTrack(uint8_t channel); 00127 void stopTracks() { 00128 for(uint8_t channel=0; channel<NUM_CHANNELS; channel++) 00129 stopTrack(channel); 00130 } 00131 void updateTracks() { 00132 for(uint8_t channel=0; channel<NUM_CHANNELS; channel++) 00133 updateTrack(channel); 00134 } 00135 00136 void changeSequenceSet(const uint16_t* const* patterns, uint8_t channel); 00137 00138 bool isTrackPlaying(uint8_t channel) 00139 { 00140 return tracks[channel].IsPlaying; 00141 } 00142 00143 void playSequence(const uint16_t* pattern, uint8_t channel); 00144 void changeInstrumentSet(const uint16_t* const* instruments, uint8_t channel); 00145 void updateSequence(uint8_t channel); 00146 void stopSequence(uint8_t channel); 00147 void stopSequences() { 00148 for(uint8_t channel=0; channel<NUM_CHANNELS; channel++) 00149 stopSequence(channel); 00150 } 00151 void updateSequences() { 00152 for(uint8_t channel=0; channel<NUM_CHANNELS; channel++) 00153 updateSequence(channel); 00154 } 00155 00156 00157 void playNote(uint8_t pitch, uint8_t duration, uint8_t channel); 00158 void updateNote(uint8_t i); 00159 void stopNote(uint8_t channel); 00160 void updateNotes() { 00161 for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) 00162 updateNote(channel); 00163 } 00164 void stopNotes() { 00165 for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) 00166 stopNote(channel); 00167 } 00168 00169 void command(uint8_t cmd, uint8_t X, int8_t Y, uint8_t channel); 00170 00171 uint8_t outputPitch[NUM_CHANNELS]; 00172 int8_t outputVolume[NUM_CHANNELS]; 00173 00174 void setVolume(int8_t volume); 00175 uint8_t getVolume(); 00176 void setVolume(int8_t volume, uint8_t channel); 00177 uint8_t getVolume(uint8_t channel); 00178 00179 00180 uint8_t prescaler; 00181 00182 void setChannelHalfPeriod(uint8_t channel, uint8_t halfPeriod); 00183 00184 00185 uint8_t globalVolume; 00186 uint8_t volumeMax; 00187 00188 #if (NUM_CHANNELS > 0) 00189 //tracks data 00190 uint16_t **patternSet[NUM_CHANNELS]; 00191 int8_t patternPitch[NUM_CHANNELS]; 00192 00193 // pattern data 00194 uint16_t **instrumentSet[NUM_CHANNELS]; 00195 00196 // note data 00197 uint8_t notePitch[NUM_CHANNELS]; 00198 uint8_t noteDuration[NUM_CHANNELS]; 00199 int8_t noteVolume[NUM_CHANNELS]; 00200 boolean notePlaying[NUM_CHANNELS]; 00201 00202 00203 //current step data 00204 int8_t stepVolume[NUM_CHANNELS]; 00205 uint8_t stepPitch[NUM_CHANNELS]; 00206 00207 uint8_t chanVolumes[NUM_CHANNELS]; 00208 00209 00210 uint8_t _chanCount[NUM_CHANNELS]; //counts until the next change of the waveform 00211 boolean _chanState[NUM_CHANNELS]; //if the waveform is currently high or low 00212 uint8_t _chanHalfPeriod[NUM_CHANNELS]; //duration of half the period of the waveform 00213 uint8_t _chanOutputVolume[NUM_CHANNELS]; //amplitude of the outputted waveform 00214 uint8_t _chanOutput[NUM_CHANNELS]; //current value of the outputted waveform 00215 boolean _chanNoise[NUM_CHANNELS]; //if a random value should be added to the waveform to generate noise 00216 00217 #endif 00218 void updateOutput(); 00219 00220 private: 00221 void generateOutput(); 00222 }; 00223 00224 #endif /* SOUND_H */
Generated on Tue Jul 12 2022 23:21:39 by 1.7.2