Platform library for RETRO

Dependents:   RETRO_RickGame

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Sound.h Source File

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 */