Platform library for RETRO

Dependents:   RETRO_RickGame

Revision:
0:6f26c31d8573
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sound.h	Sun Mar 01 05:29:45 2015 +0000
@@ -0,0 +1,224 @@
+/*
+ * (C) Copyright 2015 Valentin Ivanov. All rights reserved.
+ *
+ * This file is part of the RetroPlatform Library
+ *
+ * The RetroPlatform Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * This library is inspired by Gamebuino Library (http://gamebuino.com)
+ * from Aurélien Rodot. 
+ */
+#ifndef SOUND_H
+#define SOUND_H
+
+#include <mbed.h>
+
+//commands
+#define CMD_VOLUME 0
+#define CMD_INSTRUMENT 1
+#define CMD_SLIDE 2
+#define CMD_ARPEGGIO 3
+#define CMD_TREMOLO 4
+
+
+#define NUM_CHANNELS 3 //number of sound channels (no more than 4)
+
+#define VOLUME_GLOBAL_MAX 1
+
+//7=instrument volume 9=note volume
+#define VOLUME_CHANNEL_MAX 255/NUM_CHANNELS/VOLUME_GLOBAL_MAX/7/9
+
+#define boolean bool
+
+//A set of sequences
+typedef struct {
+    uint16_t *Data;
+    uint8_t Cursor;
+    bool IsPlaying;
+} Track;
+
+//A sequence of commands and notes
+typedef struct {
+    uint16_t *Data;
+    bool Looping;
+    uint16_t Cursor;
+    bool IsPlaying;
+} Sequence;
+
+//A note of selected pitch, duration and volume
+typedef struct {
+    uint8_t Pitch;
+    uint8_t Duration;
+    int8_t  Volume;
+    bool    IsPlaying;
+} Note;
+
+typedef struct {
+    int8_t Counter;
+    int8_t volumeSlideStepDuration;
+    int8_t volumeSlideStepSize;
+    uint8_t arpeggioStepDuration;
+    int8_t arpeggioStepSize;
+    uint8_t tremoloStepDuration;
+    int8_t tremoloStepSize;
+
+} Command;
+
+typedef struct {
+    uint16_t **SequenceSet;
+    uint16_t **InstrumentSet;
+    
+    uint8_t Volume;
+    uint8_t Count;
+    bool    State;
+    uint8_t HalfPeriod;
+    uint8_t OutputVolume;
+    uint8_t Output;
+    bool    Noise;
+
+    
+    
+    int8_t SequencePitch;
+} AudioChannel;
+
+typedef struct {
+    uint16_t *Data;
+    uint8_t Length;
+    uint8_t Looping;
+    uint16_t Cursor;
+    uint8_t NextChange;
+} Instrument;
+
+class Sound {
+    
+    Ticker timer;
+    PwmOut speaker;
+    
+    Track tracks[NUM_CHANNELS];
+    Sequence sequences[NUM_CHANNELS];
+    Command commands[NUM_CHANNELS];
+    Instrument instruments[NUM_CHANNELS];
+    
+public:
+    Sound();
+    void initialize();
+    
+    void update()
+    {
+        updateTracks();
+        updateSequences();
+        updateNotes();
+    }
+    
+    void playTrack(const uint16_t* track, uint8_t channel);
+    void updateTrack(uint8_t channel);
+    void stopTrack(uint8_t channel);
+    void stopTracks() {
+        for(uint8_t channel=0; channel<NUM_CHANNELS; channel++)
+            stopTrack(channel);
+    }
+    void updateTracks() {
+        for(uint8_t channel=0; channel<NUM_CHANNELS; channel++)
+            updateTrack(channel);
+    }    
+    
+    void changeSequenceSet(const uint16_t* const* patterns, uint8_t channel);
+    
+    bool isTrackPlaying(uint8_t channel)
+    {
+        return tracks[channel].IsPlaying;
+    }
+    
+    void playSequence(const uint16_t* pattern, uint8_t channel);
+    void changeInstrumentSet(const uint16_t* const* instruments, uint8_t channel);
+    void updateSequence(uint8_t channel);
+    void stopSequence(uint8_t channel);
+    void stopSequences() {
+        for(uint8_t channel=0; channel<NUM_CHANNELS; channel++)
+            stopSequence(channel);
+    }
+    void updateSequences() {
+        for(uint8_t channel=0; channel<NUM_CHANNELS; channel++)
+            updateSequence(channel);
+    }
+    
+    
+    void playNote(uint8_t pitch, uint8_t duration, uint8_t channel);
+    void updateNote(uint8_t i);
+    void stopNote(uint8_t channel);
+    void updateNotes() {
+        for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++)
+            updateNote(channel);
+    }
+    void stopNotes() {
+        for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++)
+            stopNote(channel);
+    }    
+
+    void command(uint8_t cmd, uint8_t X, int8_t Y, uint8_t channel);
+    
+    uint8_t outputPitch[NUM_CHANNELS];
+    int8_t outputVolume[NUM_CHANNELS];
+
+    void setVolume(int8_t volume);
+    uint8_t getVolume();
+    void setVolume(int8_t volume, uint8_t channel);
+    uint8_t getVolume(uint8_t channel);
+    
+    
+    uint8_t prescaler;
+
+    void setChannelHalfPeriod(uint8_t channel, uint8_t halfPeriod);
+
+    
+    uint8_t globalVolume;
+    uint8_t volumeMax;
+    
+#if (NUM_CHANNELS > 0)
+    //tracks data
+    uint16_t **patternSet[NUM_CHANNELS];
+    int8_t patternPitch[NUM_CHANNELS];
+
+    // pattern data
+    uint16_t **instrumentSet[NUM_CHANNELS];
+
+    // note data
+    uint8_t notePitch[NUM_CHANNELS];
+    uint8_t noteDuration[NUM_CHANNELS];
+    int8_t noteVolume[NUM_CHANNELS];
+    boolean notePlaying[NUM_CHANNELS];
+      
+    
+    //current step data
+    int8_t stepVolume[NUM_CHANNELS];
+    uint8_t stepPitch[NUM_CHANNELS];
+    
+    uint8_t chanVolumes[NUM_CHANNELS];
+    
+    
+    uint8_t _chanCount[NUM_CHANNELS]; //counts until the next change of the waveform
+    boolean _chanState[NUM_CHANNELS]; //if the waveform is currently high or low
+    uint8_t _chanHalfPeriod[NUM_CHANNELS]; //duration of half the period of the waveform
+    uint8_t _chanOutputVolume[NUM_CHANNELS]; //amplitude of the outputted waveform
+    uint8_t _chanOutput[NUM_CHANNELS]; //current value of the outputted waveform
+    boolean _chanNoise[NUM_CHANNELS]; //if a random value should be added to the waveform to generate noise
+    
+#endif
+    void updateOutput();
+    
+private:
+    void generateOutput();    
+};
+
+#endif  /* SOUND_H */
\ No newline at end of file