Jonne Valola / PokittoLib Featured

Dependents:   YATTT sd_map_test cPong SnowDemo ... more

PokittoLib

Library for programming Pokitto hardware

How to Use

  1. Import this library to online compiler (see button "import" on the right hand side
  2. DO NOT import mbed-src anymore, a better version is now included inside PokittoLib
  3. Change My_settings.h according to your project
  4. Start coding!
Committer:
Pokitto
Date:
Tue Sep 19 08:47:36 2017 +0000
Revision:
2:968589ca3484
Parent:
1:4b1511a0a2c2
Child:
4:ecf2fe370c1c
Got rid of warnings at compile time

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pokitto 0:e8b8f36b4505 1 /**************************************************************************/
Pokitto 0:e8b8f36b4505 2 /*!
Pokitto 0:e8b8f36b4505 3 @file PokittoSound.cpp
Pokitto 0:e8b8f36b4505 4 @author Jonne Valola
Pokitto 0:e8b8f36b4505 5
Pokitto 0:e8b8f36b4505 6 @section LICENSE
Pokitto 0:e8b8f36b4505 7
Pokitto 0:e8b8f36b4505 8 Software License Agreement (BSD License)
Pokitto 0:e8b8f36b4505 9
Pokitto 0:e8b8f36b4505 10 Copyright (c) 2016, Jonne Valola
Pokitto 0:e8b8f36b4505 11 All rights reserved.
Pokitto 0:e8b8f36b4505 12
Pokitto 0:e8b8f36b4505 13 Redistribution and use in source and binary forms, with or without
Pokitto 0:e8b8f36b4505 14 modification, are permitted provided that the following conditions are met:
Pokitto 0:e8b8f36b4505 15 1. Redistributions of source code must retain the above copyright
Pokitto 0:e8b8f36b4505 16 notice, this list of conditions and the following disclaimer.
Pokitto 0:e8b8f36b4505 17 2. Redistributions in binary form must reproduce the above copyright
Pokitto 0:e8b8f36b4505 18 notice, this list of conditions and the following disclaimer in the
Pokitto 0:e8b8f36b4505 19 documentation and/or other materials provided with the distribution.
Pokitto 0:e8b8f36b4505 20 3. Neither the name of the copyright holders nor the
Pokitto 0:e8b8f36b4505 21 names of its contributors may be used to endorse or promote products
Pokitto 0:e8b8f36b4505 22 derived from this software without specific prior written permission.
Pokitto 0:e8b8f36b4505 23
Pokitto 0:e8b8f36b4505 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
Pokitto 0:e8b8f36b4505 25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Pokitto 0:e8b8f36b4505 26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Pokitto 0:e8b8f36b4505 27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
Pokitto 0:e8b8f36b4505 28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Pokitto 0:e8b8f36b4505 29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Pokitto 0:e8b8f36b4505 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Pokitto 0:e8b8f36b4505 31 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Pokitto 0:e8b8f36b4505 32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Pokitto 0:e8b8f36b4505 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Pokitto 0:e8b8f36b4505 34 */
Pokitto 0:e8b8f36b4505 35 /**************************************************************************/
Pokitto 0:e8b8f36b4505 36
Pokitto 0:e8b8f36b4505 37 /*
Pokitto 0:e8b8f36b4505 38 * NOTE:
Pokitto 0:e8b8f36b4505 39 * API of the Pokitto Sound library is partially identical to the Gamebuino Sound API.
Pokitto 0:e8b8f36b4505 40 * Due to the difference in architecture (ARM Cortex-M0+ in mbed environment vs. 8-bit AVR)
Pokitto 0:e8b8f36b4505 41 * large parts are not identical. Most functions were rewritten, with only API remaining.
Pokitto 0:e8b8f36b4505 42 * We want to give attribution to the original author's project:
Pokitto 0:e8b8f36b4505 43 *
Pokitto 0:e8b8f36b4505 44 * License for Gamebuino-identical code:
Pokitto 0:e8b8f36b4505 45 *
Pokitto 1:4b1511a0a2c2 46 * (C) Copyright 2014 Aur�lien Rodot. All rights reserved.
Pokitto 0:e8b8f36b4505 47 *
Pokitto 0:e8b8f36b4505 48 * This file is part of the Gamebuino Library (http://gamebuino.com)
Pokitto 0:e8b8f36b4505 49 *
Pokitto 0:e8b8f36b4505 50 * The Gamebuino Library is free software: you can redistribute it and/or modify
Pokitto 0:e8b8f36b4505 51 * it under the terms of the GNU Lesser General Public License as published by
Pokitto 0:e8b8f36b4505 52 * the Free Software Foundation, either version 3 of the License, or
Pokitto 0:e8b8f36b4505 53 * (at your option) any later version.
Pokitto 0:e8b8f36b4505 54 *
Pokitto 0:e8b8f36b4505 55 * This program is distributed in the hope that it will be useful,
Pokitto 0:e8b8f36b4505 56 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Pokitto 0:e8b8f36b4505 57 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Pokitto 0:e8b8f36b4505 58 * GNU Lesser General Public License for more details.
Pokitto 0:e8b8f36b4505 59 *
Pokitto 0:e8b8f36b4505 60 * You should have received a copy of the GNU Lesser General Public License
Pokitto 0:e8b8f36b4505 61 * along with this program. If not, see <http://www.gnu.org/licenses/>
Pokitto 0:e8b8f36b4505 62 */
Pokitto 0:e8b8f36b4505 63
Pokitto 0:e8b8f36b4505 64 #include "PokittoSound.h"
Pokitto 0:e8b8f36b4505 65 #include "Pokitto_settings.h"
Pokitto 0:e8b8f36b4505 66 #include "PokittoCore.h"
Pokitto 0:e8b8f36b4505 67 #include "Synth.h"
Pokitto 0:e8b8f36b4505 68
Pokitto 0:e8b8f36b4505 69 #ifndef POK_SIM
Pokitto 0:e8b8f36b4505 70 #include "HWSound.h"
Pokitto 0:e8b8f36b4505 71 #else
Pokitto 0:e8b8f36b4505 72 #include "SimSound.h"
Pokitto 0:e8b8f36b4505 73 #include "PokittoSimulator.h"
Pokitto 0:e8b8f36b4505 74 #endif
Pokitto 0:e8b8f36b4505 75
Pokitto 0:e8b8f36b4505 76 typedef uint8_t byte;
Pokitto 0:e8b8f36b4505 77
Pokitto 0:e8b8f36b4505 78 using namespace Pokitto;
Pokitto 0:e8b8f36b4505 79
Pokitto 0:e8b8f36b4505 80 Pokitto::Core c;
Pokitto 0:e8b8f36b4505 81
Pokitto 0:e8b8f36b4505 82 uint8_t Sound::prescaler;
Pokitto 0:e8b8f36b4505 83 uint16_t Sound::globalVolume;
Pokitto 0:e8b8f36b4505 84 uint16_t Sound::volumeMax = VOLUME_HEADPHONE_MAX;
Pokitto 0:e8b8f36b4505 85
Pokitto 0:e8b8f36b4505 86 bool Sound::trackIsPlaying[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 87 bool Sound::patternIsPlaying[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 88 uint8_t Sound::outputPitch[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 89 int8_t Sound::outputVolume[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 90
Pokitto 0:e8b8f36b4505 91 uint16_t *Sound::trackData[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 92 uint8_t Sound::trackCursor[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 93 uint16_t **Sound::patternSet[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 94 int8_t Sound::patternPitch[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 95
Pokitto 0:e8b8f36b4505 96 // pattern data
Pokitto 0:e8b8f36b4505 97 uint16_t *Sound::patternData[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 98 uint16_t **Sound::instrumentSet[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 99 bool Sound::patternLooping[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 100 uint16_t Sound::patternCursor[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 101
Pokitto 0:e8b8f36b4505 102 // note data
Pokitto 0:e8b8f36b4505 103 uint8_t Sound::notePitch[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 104 uint8_t Sound::noteDuration[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 105 int8_t Sound::noteVolume[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 106 bool Sound::notePlaying[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 107
Pokitto 0:e8b8f36b4505 108 // commands data
Pokitto 0:e8b8f36b4505 109 int8_t Sound::commandsCounter[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 110 int8_t Sound::volumeSlideStepDuration[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 111 int8_t Sound::volumeSlideStepSize[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 112 uint8_t Sound::arpeggioStepDuration[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 113 int8_t Sound::arpeggioStepSize[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 114 uint8_t Sound::tremoloStepDuration[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 115 int8_t Sound::tremoloStepSize[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 116
Pokitto 0:e8b8f36b4505 117 // instrument data
Pokitto 0:e8b8f36b4505 118 uint16_t *Sound::instrumentData[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 119 uint8_t Sound::instrumentLength[NUM_CHANNELS]; //number of steps in the instrument
Pokitto 0:e8b8f36b4505 120 uint8_t Sound::instrumentLooping[NUM_CHANNELS]; //how many steps to loop on when the last step of the instrument is reached
Pokitto 0:e8b8f36b4505 121 uint16_t Sound::instrumentCursor[NUM_CHANNELS]; //which step is being played
Pokitto 0:e8b8f36b4505 122 uint8_t Sound::instrumentNextChange[NUM_CHANNELS]; //how many frames before the next step
Pokitto 0:e8b8f36b4505 123
Pokitto 0:e8b8f36b4505 124 //current step data
Pokitto 0:e8b8f36b4505 125 int8_t Sound::stepVolume[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 126 uint8_t Sound::stepPitch[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 127 uint8_t Sound::chanVolumes[NUM_CHANNELS];
Pokitto 0:e8b8f36b4505 128
Pokitto 0:e8b8f36b4505 129 #if (POK_ENABLE_SOUND < 1)
Pokitto 0:e8b8f36b4505 130 #define NUM_CHANNELS 0
Pokitto 0:e8b8f36b4505 131 #endif
Pokitto 0:e8b8f36b4505 132
Pokitto 0:e8b8f36b4505 133 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 134 #ifndef POK_SIM
Pokitto 0:e8b8f36b4505 135 uint8_t sbyte;
Pokitto 0:e8b8f36b4505 136 #else
Pokitto 0:e8b8f36b4505 137 uint8_t sbyte;
Pokitto 0:e8b8f36b4505 138 float pwm1;
Pokitto 0:e8b8f36b4505 139 #endif // POK_SIM
Pokitto 0:e8b8f36b4505 140
Pokitto 0:e8b8f36b4505 141 //declare these variables globally for faster access
Pokitto 0:e8b8f36b4505 142 uint8_t _rand = 1;
Pokitto 0:e8b8f36b4505 143 uint8_t _chanCount[NUM_CHANNELS]; //counts until the next change of the waveform
Pokitto 0:e8b8f36b4505 144 bool _chanState[NUM_CHANNELS]; //if the waveform is currently high or low
Pokitto 0:e8b8f36b4505 145 uint8_t _chanHalfPeriod[NUM_CHANNELS]; //duration of half the period of the waveform
Pokitto 0:e8b8f36b4505 146 uint8_t _chanOutputVolume[NUM_CHANNELS]; //amplitude of the outputted waveform
Pokitto 0:e8b8f36b4505 147 uint8_t _chanOutput[NUM_CHANNELS]; //current value of the outputted waveform
Pokitto 0:e8b8f36b4505 148 bool _chanNoise[NUM_CHANNELS]; //if a random value should be added to the waveform to generate noise
Pokitto 0:e8b8f36b4505 149
Pokitto 2:968589ca3484 150 #if POK_GBSOUND > 0
Pokitto 0:e8b8f36b4505 151 const uint16_t squareWaveInstrument[] = {0x0101, 0x03F7};
Pokitto 0:e8b8f36b4505 152 const uint16_t noiseInstrument[] = {0x0101, 0x03FF};
Pokitto 0:e8b8f36b4505 153 const uint16_t* const defaultInstruments[] = {squareWaveInstrument,noiseInstrument};
Pokitto 0:e8b8f36b4505 154
Pokitto 0:e8b8f36b4505 155 const uint16_t playOKPattern[] = {0x0005,0x138,0x168,0x0000};
Pokitto 0:e8b8f36b4505 156 const uint16_t playCancelPattern[] = {0x0005,0x168,0x138,0x0000};
Pokitto 0:e8b8f36b4505 157 const uint16_t playTickP[] = {0x0045,0x168,0x0000};
Pokitto 2:968589ca3484 158 #endif
Pokitto 0:e8b8f36b4505 159 #if(EXTENDED_NOTE_RANGE > 0)
Pokitto 0:e8b8f36b4505 160 //extended note range
Pokitto 0:e8b8f36b4505 161 #define NUM_PITCH 59
Pokitto 0:e8b8f36b4505 162 const uint8_t _halfPeriods[NUM_PITCH] = {246,232,219,207,195,184,174,164,155,146,138,130,123,116,110,104,98,92,87,82,78,73,69,65,62,58,55,52,49,46,44,41,39,37,35,33,31,29,28,26,25,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6};
Pokitto 0:e8b8f36b4505 163 #else
Pokitto 0:e8b8f36b4505 164 //regular note range
Pokitto 0:e8b8f36b4505 165 #define NUM_PITCH 36
Pokitto 0:e8b8f36b4505 166 const uint8_t _halfPeriods[NUM_PITCH] = {246,232,219,207,195,184,174,164,155,146,138,130,123,116,110,104,98,92,87,82,78,73,69,65,62,58,55,52,49,46,44,41,39,37,35,33};
Pokitto 0:e8b8f36b4505 167 #endif
Pokitto 0:e8b8f36b4505 168
Pokitto 0:e8b8f36b4505 169 #endif
Pokitto 0:e8b8f36b4505 170
Pokitto 0:e8b8f36b4505 171 void Pokitto::audio_IRQ() {
Pokitto 0:e8b8f36b4505 172 #if POK_STREAMING_MUSIC > 0
Pokitto 0:e8b8f36b4505 173 #if POK_STREAMFREQ_HALVE > 0
Pokitto 0:e8b8f36b4505 174 streamstep = 1-streamstep;
Pokitto 0:e8b8f36b4505 175 #else
Pokitto 0:e8b8f36b4505 176 streamstep=1;
Pokitto 0:e8b8f36b4505 177 #endif
Pokitto 0:e8b8f36b4505 178
Pokitto 0:e8b8f36b4505 179 streamstep &= streamon; //check if stream is on
Pokitto 0:e8b8f36b4505 180
Pokitto 0:e8b8f36b4505 181 if(streamvol && streamstep) {
Pokitto 0:e8b8f36b4505 182 uint8_t output = (*currentPtr++);
Pokitto 0:e8b8f36b4505 183 sbyte = output;
Pokitto 0:e8b8f36b4505 184 } else {
Pokitto 0:e8b8f36b4505 185 sbyte = 0; // duty cycle
Pokitto 0:e8b8f36b4505 186 }
Pokitto 0:e8b8f36b4505 187
Pokitto 0:e8b8f36b4505 188 if (currentPtr >= endPtr)
Pokitto 0:e8b8f36b4505 189 {
Pokitto 0:e8b8f36b4505 190 currentBuffer++;
Pokitto 0:e8b8f36b4505 191 if (currentBuffer==4) currentBuffer=0;
Pokitto 0:e8b8f36b4505 192 currentPtr = buffers[currentBuffer];
Pokitto 0:e8b8f36b4505 193 endPtr = currentPtr + BUFFER_SIZE;
Pokitto 0:e8b8f36b4505 194 }
Pokitto 0:e8b8f36b4505 195
Pokitto 0:e8b8f36b4505 196 #endif // POK_STREAMING_MUSIC
Pokitto 0:e8b8f36b4505 197 #if (NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 198 Sound::generateOutput();
Pokitto 0:e8b8f36b4505 199 #endif
Pokitto 0:e8b8f36b4505 200 }
Pokitto 0:e8b8f36b4505 201
Pokitto 0:e8b8f36b4505 202 void Sound::volumeUp() {
Pokitto 0:e8b8f36b4505 203 if (globalVolume>VOLUME_HEADPHONE_MAX) setVolume(getVolume()+VOLUME_STEP*2);
Pokitto 0:e8b8f36b4505 204 else setVolume(getVolume()+VOLUME_STEP);
Pokitto 0:e8b8f36b4505 205 }
Pokitto 0:e8b8f36b4505 206
Pokitto 0:e8b8f36b4505 207 void Sound::volumeDown() {
Pokitto 0:e8b8f36b4505 208 if (globalVolume>VOLUME_HEADPHONE_MAX) setVolume(getVolume()-VOLUME_STEP*4);
Pokitto 0:e8b8f36b4505 209 else setVolume(getVolume()-VOLUME_STEP);
Pokitto 0:e8b8f36b4505 210 }
Pokitto 0:e8b8f36b4505 211
Pokitto 0:e8b8f36b4505 212
Pokitto 0:e8b8f36b4505 213 void Sound::setMaxVol(int16_t v) {
Pokitto 0:e8b8f36b4505 214 if (v < 0) v = 0; //prevent nasty wraparound
Pokitto 0:e8b8f36b4505 215 if (v > VOLUME_SPEAKER_MAX) {
Pokitto 0:e8b8f36b4505 216 v = VOLUME_SPEAKER_MAX;
Pokitto 0:e8b8f36b4505 217 }
Pokitto 0:e8b8f36b4505 218 volumeMax = v;
Pokitto 0:e8b8f36b4505 219 setVolume(globalVolume);
Pokitto 0:e8b8f36b4505 220 }
Pokitto 0:e8b8f36b4505 221
Pokitto 0:e8b8f36b4505 222 uint16_t Sound::getMaxVol() {
Pokitto 0:e8b8f36b4505 223 return volumeMax;
Pokitto 0:e8b8f36b4505 224 }
Pokitto 0:e8b8f36b4505 225
Pokitto 0:e8b8f36b4505 226 void Sound::updateStream() {
Pokitto 0:e8b8f36b4505 227 #if POK_STREAMING_MUSIC
Pokitto 0:e8b8f36b4505 228 if (oldBuffer != currentBuffer) {
Pokitto 0:e8b8f36b4505 229 if (currentBuffer==0) fileReadBytes(&buffers[3][0],BUFFER_SIZE);
Pokitto 0:e8b8f36b4505 230 else if (currentBuffer==1) fileReadBytes(&buffers[0][0],BUFFER_SIZE);
Pokitto 0:e8b8f36b4505 231 else if (currentBuffer==2) fileReadBytes(&buffers[1][0],BUFFER_SIZE);
Pokitto 0:e8b8f36b4505 232 else fileReadBytes(&buffers[2][0],BUFFER_SIZE);
Pokitto 0:e8b8f36b4505 233 oldBuffer = currentBuffer;
Pokitto 0:e8b8f36b4505 234 streamcounter += BUFFER_SIZE;
Pokitto 0:e8b8f36b4505 235 }
Pokitto 0:e8b8f36b4505 236
Pokitto 0:e8b8f36b4505 237 #ifndef POK_SIM
Pokitto 0:e8b8f36b4505 238 if ( streamcounter > fs.fsize - (BUFFER_SIZE)) {
Pokitto 0:e8b8f36b4505 239 #else
Pokitto 0:e8b8f36b4505 240 if ( streamcounter > getFileLength() - (BUFFER_SIZE)) {
Pokitto 0:e8b8f36b4505 241 #endif
Pokitto 0:e8b8f36b4505 242 streamcounter=0;
Pokitto 0:e8b8f36b4505 243 #if POK_STREAM_LOOP > 0
Pokitto 0:e8b8f36b4505 244 fileRewind();
Pokitto 0:e8b8f36b4505 245 #endif
Pokitto 0:e8b8f36b4505 246 #ifndef POK_SIM
Pokitto 0:e8b8f36b4505 247 streamon=0;
Pokitto 0:e8b8f36b4505 248 #endif // POK_SIM
Pokitto 0:e8b8f36b4505 249 }
Pokitto 0:e8b8f36b4505 250 #endif
Pokitto 0:e8b8f36b4505 251 }
Pokitto 0:e8b8f36b4505 252
Pokitto 0:e8b8f36b4505 253 void Sound::begin() {
Pokitto 1:4b1511a0a2c2 254 #if POK_ENABLE_SOUND > 1
Pokitto 0:e8b8f36b4505 255 soundInit();
Pokitto 1:4b1511a0a2c2 256 #endif
Pokitto 0:e8b8f36b4505 257 #if (NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 258 #if POK_ENABLE_SOUND > 0
Pokitto 0:e8b8f36b4505 259 #if POK_GBSOUND > 0
Pokitto 0:e8b8f36b4505 260 prescaler = 1;
Pokitto 0:e8b8f36b4505 261 for(byte i=0; i<NUM_CHANNELS; i++){
Pokitto 0:e8b8f36b4505 262 chanVolumes[i] = VOLUME_CHANNEL_MAX;
Pokitto 0:e8b8f36b4505 263 changeInstrumentSet(defaultInstruments, i); //load default instruments. #0:square wave, #1: noise
Pokitto 0:e8b8f36b4505 264 command(CMD_INSTRUMENT, 0, 0, i); //set the default instrument to square wave
Pokitto 0:e8b8f36b4505 265 }
Pokitto 0:e8b8f36b4505 266 #endif // POK_GBSOUND
Pokitto 0:e8b8f36b4505 267 #endif //POK_ENABLE_SOUND
Pokitto 0:e8b8f36b4505 268 #endif
Pokitto 0:e8b8f36b4505 269 }
Pokitto 0:e8b8f36b4505 270
Pokitto 0:e8b8f36b4505 271 void Sound::playTrack(const uint16_t* track, uint8_t channel){
Pokitto 0:e8b8f36b4505 272 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 273 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 274 return;
Pokitto 0:e8b8f36b4505 275 stopTrack(channel);
Pokitto 0:e8b8f36b4505 276 trackCursor[channel] = 0;
Pokitto 0:e8b8f36b4505 277 trackData[channel] = (uint16_t*)track;
Pokitto 0:e8b8f36b4505 278 trackIsPlaying[channel] = true;
Pokitto 0:e8b8f36b4505 279 #endif
Pokitto 0:e8b8f36b4505 280 }
Pokitto 0:e8b8f36b4505 281
Pokitto 0:e8b8f36b4505 282 void Sound::stopTrack(uint8_t channel){
Pokitto 0:e8b8f36b4505 283 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 284 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 285 return;
Pokitto 0:e8b8f36b4505 286 trackIsPlaying[channel] = false;
Pokitto 0:e8b8f36b4505 287 stopPattern(channel);
Pokitto 0:e8b8f36b4505 288 #endif
Pokitto 0:e8b8f36b4505 289 }
Pokitto 0:e8b8f36b4505 290
Pokitto 0:e8b8f36b4505 291 void Sound::stopTrack(){
Pokitto 0:e8b8f36b4505 292 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 293 for(uint8_t i=0; i<NUM_CHANNELS; i++){
Pokitto 0:e8b8f36b4505 294 stopTrack(i);
Pokitto 0:e8b8f36b4505 295 }
Pokitto 0:e8b8f36b4505 296 #endif
Pokitto 0:e8b8f36b4505 297 }
Pokitto 0:e8b8f36b4505 298
Pokitto 0:e8b8f36b4505 299 void Sound::updateTrack(uint8_t channel){
Pokitto 0:e8b8f36b4505 300 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 301 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 302 return;
Pokitto 0:e8b8f36b4505 303 if(trackIsPlaying[channel] && !patternIsPlaying[channel]){
Pokitto 0:e8b8f36b4505 304 uint16_t data = pgm_read_word(trackData[channel] + trackCursor[channel]);
Pokitto 0:e8b8f36b4505 305 if(data == 0xFFFF){ //en of the track
Pokitto 0:e8b8f36b4505 306 trackIsPlaying[channel] = false;
Pokitto 0:e8b8f36b4505 307 return;
Pokitto 0:e8b8f36b4505 308 }
Pokitto 0:e8b8f36b4505 309 uint8_t patternID = data & 0xFF;
Pokitto 0:e8b8f36b4505 310 data >>= 8;
Pokitto 0:e8b8f36b4505 311 patternPitch[channel] = data;
Pokitto 0:e8b8f36b4505 312 playPattern((const uint16_t*)pgm_read_word(&(patternSet[channel][patternID])), channel);
Pokitto 0:e8b8f36b4505 313 trackCursor[channel] ++;
Pokitto 0:e8b8f36b4505 314 }
Pokitto 0:e8b8f36b4505 315 #endif
Pokitto 0:e8b8f36b4505 316 }
Pokitto 0:e8b8f36b4505 317
Pokitto 0:e8b8f36b4505 318 void Sound::updateTrack(){
Pokitto 0:e8b8f36b4505 319 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 320 for (uint8_t i=0; i<NUM_CHANNELS; i++){
Pokitto 0:e8b8f36b4505 321 updateTrack(i);
Pokitto 0:e8b8f36b4505 322 }
Pokitto 0:e8b8f36b4505 323 #endif
Pokitto 0:e8b8f36b4505 324 }
Pokitto 0:e8b8f36b4505 325
Pokitto 0:e8b8f36b4505 326 void Sound::changePatternSet(const uint16_t* const* patterns, uint8_t channel){
Pokitto 0:e8b8f36b4505 327 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 328 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 329 return;
Pokitto 0:e8b8f36b4505 330 patternSet[channel] = (uint16_t**)patterns;
Pokitto 0:e8b8f36b4505 331 #endif
Pokitto 0:e8b8f36b4505 332 }
Pokitto 0:e8b8f36b4505 333
Pokitto 0:e8b8f36b4505 334 void Sound::playPattern(const uint16_t* pattern, uint8_t channel){
Pokitto 0:e8b8f36b4505 335 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 336 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 337 return;
Pokitto 0:e8b8f36b4505 338 stopPattern(channel);
Pokitto 0:e8b8f36b4505 339 patternData[channel] = (uint16_t*)pattern;
Pokitto 0:e8b8f36b4505 340 patternCursor[channel] = 0;
Pokitto 0:e8b8f36b4505 341 patternIsPlaying[channel] = true;
Pokitto 0:e8b8f36b4505 342 noteVolume[channel] = 9;
Pokitto 0:e8b8f36b4505 343 //reinit commands
Pokitto 0:e8b8f36b4505 344 volumeSlideStepDuration[channel] = 0;
Pokitto 0:e8b8f36b4505 345 arpeggioStepDuration[channel] = 0;
Pokitto 0:e8b8f36b4505 346 tremoloStepDuration[channel] = 0;
Pokitto 0:e8b8f36b4505 347 #endif
Pokitto 0:e8b8f36b4505 348 }
Pokitto 0:e8b8f36b4505 349
Pokitto 0:e8b8f36b4505 350 void Sound::updatePattern(){
Pokitto 0:e8b8f36b4505 351 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 352 for (uint8_t i=0; i<NUM_CHANNELS; i++){
Pokitto 0:e8b8f36b4505 353 updatePattern(i);
Pokitto 0:e8b8f36b4505 354 }
Pokitto 0:e8b8f36b4505 355 #endif
Pokitto 0:e8b8f36b4505 356 }
Pokitto 0:e8b8f36b4505 357
Pokitto 0:e8b8f36b4505 358 void Sound::changeInstrumentSet(const uint16_t* const* instruments, uint8_t channel){
Pokitto 0:e8b8f36b4505 359 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 360 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 361 return;
Pokitto 0:e8b8f36b4505 362 instrumentSet[channel] = (uint16_t**)instruments;
Pokitto 0:e8b8f36b4505 363 #endif
Pokitto 0:e8b8f36b4505 364 }
Pokitto 0:e8b8f36b4505 365
Pokitto 0:e8b8f36b4505 366 void Sound::updatePattern(uint8_t i){
Pokitto 0:e8b8f36b4505 367 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 368 if(i>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 369 return;
Pokitto 0:e8b8f36b4505 370 if(patternIsPlaying[i]){
Pokitto 0:e8b8f36b4505 371 if(noteDuration[i]==0){//if the end of the previous note is reached
Pokitto 0:e8b8f36b4505 372
Pokitto 0:e8b8f36b4505 373 uint16_t data = pgm_read_word(patternCursor[i] + patternData[i]);
Pokitto 0:e8b8f36b4505 374
Pokitto 0:e8b8f36b4505 375 if(data == 0){ //end of the pattern reached
Pokitto 0:e8b8f36b4505 376 if(patternLooping[i] == true){
Pokitto 0:e8b8f36b4505 377 patternCursor[i] = 0;
Pokitto 0:e8b8f36b4505 378 data = pgm_read_word(patternCursor[i] + patternData[i]);
Pokitto 0:e8b8f36b4505 379 }
Pokitto 0:e8b8f36b4505 380 else{
Pokitto 0:e8b8f36b4505 381 patternIsPlaying[i] = false;
Pokitto 0:e8b8f36b4505 382 if(trackIsPlaying[i]){ //if this pattern is part of a track, get the next pattern
Pokitto 0:e8b8f36b4505 383 updateTrack(i);
Pokitto 0:e8b8f36b4505 384 data = pgm_read_word(patternCursor[i] + patternData[i]);
Pokitto 0:e8b8f36b4505 385 } else {
Pokitto 0:e8b8f36b4505 386 stopNote(i);
Pokitto 0:e8b8f36b4505 387 //Serial.print("pattern end\n");
Pokitto 0:e8b8f36b4505 388 return;
Pokitto 0:e8b8f36b4505 389 }
Pokitto 0:e8b8f36b4505 390 }
Pokitto 0:e8b8f36b4505 391 }
Pokitto 0:e8b8f36b4505 392
Pokitto 0:e8b8f36b4505 393 while (data & 0x0001){ //read all commands and instrument changes
Pokitto 0:e8b8f36b4505 394 data >>= 2;
Pokitto 0:e8b8f36b4505 395 //Serial.print("\ncmd\t");
Pokitto 0:e8b8f36b4505 396 uint8_t cmd = data & 0x0F;
Pokitto 0:e8b8f36b4505 397 data >>= 4;
Pokitto 0:e8b8f36b4505 398 uint8_t X = data & 0x1F;
Pokitto 0:e8b8f36b4505 399 data >>= 5;
Pokitto 0:e8b8f36b4505 400 int8_t Y = data - 16;
Pokitto 0:e8b8f36b4505 401 command(cmd,X,Y,i);
Pokitto 0:e8b8f36b4505 402 patternCursor[i]++;
Pokitto 0:e8b8f36b4505 403 data = pgm_read_word(patternCursor[i] + patternData[i]);
Pokitto 0:e8b8f36b4505 404 }
Pokitto 0:e8b8f36b4505 405 data >>= 2;
Pokitto 0:e8b8f36b4505 406
Pokitto 0:e8b8f36b4505 407 uint8_t pitch = data & 0x003F;
Pokitto 0:e8b8f36b4505 408 data >>= 6;
Pokitto 0:e8b8f36b4505 409
Pokitto 0:e8b8f36b4505 410 uint8_t duration = data;
Pokitto 0:e8b8f36b4505 411 if(pitch != 63){
Pokitto 0:e8b8f36b4505 412 }
Pokitto 0:e8b8f36b4505 413
Pokitto 0:e8b8f36b4505 414 playNote(pitch, duration, i);
Pokitto 0:e8b8f36b4505 415
Pokitto 0:e8b8f36b4505 416 patternCursor[i]++;
Pokitto 0:e8b8f36b4505 417 }
Pokitto 0:e8b8f36b4505 418 }
Pokitto 0:e8b8f36b4505 419 #endif
Pokitto 0:e8b8f36b4505 420 }
Pokitto 0:e8b8f36b4505 421
Pokitto 0:e8b8f36b4505 422 void Sound::stopPattern(uint8_t channel){
Pokitto 0:e8b8f36b4505 423 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 424 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 425 return;
Pokitto 0:e8b8f36b4505 426 stopNote(channel);
Pokitto 0:e8b8f36b4505 427 patternIsPlaying[channel] = false;
Pokitto 0:e8b8f36b4505 428 #endif
Pokitto 0:e8b8f36b4505 429 }
Pokitto 0:e8b8f36b4505 430
Pokitto 0:e8b8f36b4505 431 void Sound::stopPattern(){
Pokitto 0:e8b8f36b4505 432 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 433 for(uint8_t i=0; i<NUM_CHANNELS; i++){
Pokitto 0:e8b8f36b4505 434 stopPattern(i);
Pokitto 0:e8b8f36b4505 435 }
Pokitto 0:e8b8f36b4505 436 #endif
Pokitto 0:e8b8f36b4505 437 }
Pokitto 0:e8b8f36b4505 438
Pokitto 0:e8b8f36b4505 439 void Sound::command(uint8_t cmd, uint8_t X, int8_t Y, uint8_t i){
Pokitto 0:e8b8f36b4505 440 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 441 if(i>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 442 return;
Pokitto 0:e8b8f36b4505 443 switch(cmd){
Pokitto 0:e8b8f36b4505 444 case CMD_VOLUME: //volume
Pokitto 2:968589ca3484 445 X = constrain((int8_t)X, 0, 10);
Pokitto 0:e8b8f36b4505 446 noteVolume[i] = X;
Pokitto 0:e8b8f36b4505 447 break;
Pokitto 0:e8b8f36b4505 448 case CMD_INSTRUMENT: //instrument
Pokitto 0:e8b8f36b4505 449 instrumentData[i] = (uint16_t*)pgm_read_word(&(instrumentSet[i][X]));
Pokitto 0:e8b8f36b4505 450 instrumentLength[i] = pgm_read_word(&(instrumentData[i][0])) & 0x00FF; //8 LSB
Pokitto 0:e8b8f36b4505 451 instrumentLength[i] *= prescaler;
Pokitto 0:e8b8f36b4505 452 instrumentLooping[i] = min2((pgm_read_word(&(instrumentData[i][0])) >> 8), instrumentLength[i]); //8 MSB - check that the loop is shorter than the instrument length
Pokitto 0:e8b8f36b4505 453 instrumentLooping[i] *= prescaler;
Pokitto 0:e8b8f36b4505 454 break;
Pokitto 0:e8b8f36b4505 455 case CMD_SLIDE: //volume slide
Pokitto 0:e8b8f36b4505 456 volumeSlideStepDuration[i] = X * prescaler;
Pokitto 0:e8b8f36b4505 457 volumeSlideStepSize[i] = Y;
Pokitto 0:e8b8f36b4505 458 break;
Pokitto 0:e8b8f36b4505 459 case CMD_ARPEGGIO:
Pokitto 0:e8b8f36b4505 460 arpeggioStepDuration[i] = X * prescaler;
Pokitto 0:e8b8f36b4505 461 arpeggioStepSize[i] = Y;
Pokitto 0:e8b8f36b4505 462 break;
Pokitto 0:e8b8f36b4505 463 case CMD_TREMOLO:
Pokitto 0:e8b8f36b4505 464 tremoloStepDuration[i] = X * prescaler;
Pokitto 0:e8b8f36b4505 465 tremoloStepSize[i] = Y;
Pokitto 0:e8b8f36b4505 466 break;
Pokitto 0:e8b8f36b4505 467 default:
Pokitto 0:e8b8f36b4505 468 break;
Pokitto 0:e8b8f36b4505 469 }
Pokitto 0:e8b8f36b4505 470 #endif
Pokitto 0:e8b8f36b4505 471 }
Pokitto 0:e8b8f36b4505 472
Pokitto 0:e8b8f36b4505 473 void Sound::playNote(uint8_t pitch, uint8_t duration, uint8_t channel){
Pokitto 0:e8b8f36b4505 474 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 475 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 476 return;
Pokitto 0:e8b8f36b4505 477 //set note
Pokitto 0:e8b8f36b4505 478 notePitch[channel] = pitch;
Pokitto 0:e8b8f36b4505 479 noteDuration[channel] = duration * prescaler;
Pokitto 0:e8b8f36b4505 480 //reinit vars
Pokitto 0:e8b8f36b4505 481 instrumentNextChange[channel] = 0;
Pokitto 0:e8b8f36b4505 482 instrumentCursor[channel] = 0;
Pokitto 0:e8b8f36b4505 483 notePlaying[channel] = true;
Pokitto 0:e8b8f36b4505 484 _chanState[channel] = true;
Pokitto 0:e8b8f36b4505 485 commandsCounter[channel] = 0;
Pokitto 0:e8b8f36b4505 486 #endif
Pokitto 0:e8b8f36b4505 487 }
Pokitto 0:e8b8f36b4505 488
Pokitto 0:e8b8f36b4505 489 void Sound::stopNote(uint8_t channel) {
Pokitto 0:e8b8f36b4505 490 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 491 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 492 return;
Pokitto 0:e8b8f36b4505 493 notePlaying[channel] = false;
Pokitto 0:e8b8f36b4505 494 //counters
Pokitto 0:e8b8f36b4505 495 noteDuration[channel] = 0;
Pokitto 0:e8b8f36b4505 496 instrumentCursor[channel] = 0;
Pokitto 0:e8b8f36b4505 497 commandsCounter[channel] = 0;
Pokitto 0:e8b8f36b4505 498 //output
Pokitto 0:e8b8f36b4505 499 _chanOutput[channel] = 0;
Pokitto 0:e8b8f36b4505 500 _chanOutputVolume[channel] = 0;
Pokitto 0:e8b8f36b4505 501 _chanState[channel] = false;
Pokitto 0:e8b8f36b4505 502 updateOutput();
Pokitto 0:e8b8f36b4505 503 #endif
Pokitto 0:e8b8f36b4505 504 }
Pokitto 0:e8b8f36b4505 505
Pokitto 0:e8b8f36b4505 506 void Sound::stopNote() {
Pokitto 0:e8b8f36b4505 507 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 508 for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
Pokitto 0:e8b8f36b4505 509 stopNote(channel);
Pokitto 0:e8b8f36b4505 510 }
Pokitto 0:e8b8f36b4505 511 #endif
Pokitto 0:e8b8f36b4505 512 }
Pokitto 0:e8b8f36b4505 513
Pokitto 0:e8b8f36b4505 514 void Sound::updateNote() {
Pokitto 0:e8b8f36b4505 515 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 516 for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
Pokitto 0:e8b8f36b4505 517 updateNote(i);
Pokitto 0:e8b8f36b4505 518 }
Pokitto 0:e8b8f36b4505 519 #endif
Pokitto 0:e8b8f36b4505 520 }
Pokitto 0:e8b8f36b4505 521
Pokitto 0:e8b8f36b4505 522 void Sound::updateNote(uint8_t i) {
Pokitto 0:e8b8f36b4505 523 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 524 if(i>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 525 return;
Pokitto 0:e8b8f36b4505 526 if (notePlaying[i]) {
Pokitto 0:e8b8f36b4505 527
Pokitto 0:e8b8f36b4505 528 if(noteDuration[i] == 0){
Pokitto 0:e8b8f36b4505 529 stopNote(i);
Pokitto 0:e8b8f36b4505 530 //Serial.println("note end");
Pokitto 0:e8b8f36b4505 531 return;
Pokitto 0:e8b8f36b4505 532 } else {
Pokitto 0:e8b8f36b4505 533 noteDuration[i]--;
Pokitto 0:e8b8f36b4505 534 }
Pokitto 0:e8b8f36b4505 535
Pokitto 0:e8b8f36b4505 536 if (instrumentNextChange[i] == 0) {
Pokitto 0:e8b8f36b4505 537
Pokitto 0:e8b8f36b4505 538 //read the step data from the progmem and decode it
Pokitto 0:e8b8f36b4505 539 uint16_t thisStep = pgm_read_word(&(instrumentData[i][1 + instrumentCursor[i]]));
Pokitto 0:e8b8f36b4505 540
Pokitto 0:e8b8f36b4505 541 stepVolume[i] = thisStep & 0x0007;
Pokitto 0:e8b8f36b4505 542 thisStep >>= 3;
Pokitto 0:e8b8f36b4505 543
Pokitto 0:e8b8f36b4505 544 uint8_t stepNoise = thisStep & 0x0001;
Pokitto 0:e8b8f36b4505 545 thisStep >>= 1;
Pokitto 0:e8b8f36b4505 546
Pokitto 0:e8b8f36b4505 547 uint8_t stepDuration = thisStep & 0x003F;
Pokitto 0:e8b8f36b4505 548 thisStep >>= 6;
Pokitto 0:e8b8f36b4505 549
Pokitto 0:e8b8f36b4505 550 stepPitch[i] = thisStep;
Pokitto 0:e8b8f36b4505 551
Pokitto 0:e8b8f36b4505 552 //apply the step settings
Pokitto 0:e8b8f36b4505 553 instrumentNextChange[i] = stepDuration * prescaler;
Pokitto 0:e8b8f36b4505 554
Pokitto 0:e8b8f36b4505 555 _chanNoise[i] = stepNoise;
Pokitto 0:e8b8f36b4505 556
Pokitto 0:e8b8f36b4505 557
Pokitto 0:e8b8f36b4505 558 instrumentCursor[i]++;
Pokitto 0:e8b8f36b4505 559
Pokitto 0:e8b8f36b4505 560 if (instrumentCursor[i] >= instrumentLength[i]) {
Pokitto 0:e8b8f36b4505 561 if (instrumentLooping[i]) {
Pokitto 0:e8b8f36b4505 562 instrumentCursor[i] = instrumentLength[i] - instrumentLooping[i];
Pokitto 0:e8b8f36b4505 563 } else {
Pokitto 0:e8b8f36b4505 564 stopNote(i);
Pokitto 0:e8b8f36b4505 565 }
Pokitto 0:e8b8f36b4505 566 }
Pokitto 0:e8b8f36b4505 567 }
Pokitto 0:e8b8f36b4505 568 instrumentNextChange[i]--;
Pokitto 0:e8b8f36b4505 569
Pokitto 0:e8b8f36b4505 570 commandsCounter[i]++;
Pokitto 0:e8b8f36b4505 571
Pokitto 0:e8b8f36b4505 572 //UPDATE VALUES
Pokitto 0:e8b8f36b4505 573 //pitch
Pokitto 0:e8b8f36b4505 574 outputPitch[i] = notePitch[i] + stepPitch[i] + patternPitch[i];
Pokitto 0:e8b8f36b4505 575 if(arpeggioStepDuration[i]){
Pokitto 0:e8b8f36b4505 576 outputPitch[i] += commandsCounter[i] / arpeggioStepDuration[i] * arpeggioStepSize[i];
Pokitto 0:e8b8f36b4505 577 }
Pokitto 0:e8b8f36b4505 578 outputPitch[i] = (outputPitch[i] + NUM_PITCH) % NUM_PITCH; //wrap
Pokitto 0:e8b8f36b4505 579 //volume
Pokitto 0:e8b8f36b4505 580 outputVolume[i] = noteVolume[i];
Pokitto 0:e8b8f36b4505 581 if(volumeSlideStepDuration[i]){
Pokitto 0:e8b8f36b4505 582 outputVolume[i] += commandsCounter[i] / volumeSlideStepDuration[i] * volumeSlideStepSize[i];
Pokitto 0:e8b8f36b4505 583 }
Pokitto 0:e8b8f36b4505 584 if(tremoloStepDuration[i]){
Pokitto 0:e8b8f36b4505 585 outputVolume[i] += ((commandsCounter[i]/tremoloStepDuration[i]) % 2) * tremoloStepSize[i];
Pokitto 0:e8b8f36b4505 586 }
Pokitto 0:e8b8f36b4505 587 outputVolume[i] = constrain(outputVolume[i], 0, 9);
Pokitto 0:e8b8f36b4505 588 if(notePitch[i] == 63){
Pokitto 0:e8b8f36b4505 589 outputVolume[i] = 0;
Pokitto 0:e8b8f36b4505 590 }
Pokitto 0:e8b8f36b4505 591 // jonnehw noInterrupts();
Pokitto 0:e8b8f36b4505 592 _chanHalfPeriod[i] = pgm_read_byte(_halfPeriods + outputPitch[i]);
Pokitto 0:e8b8f36b4505 593 _chanOutput[i] = _chanOutputVolume[i] = outputVolume[i] * (globalVolume>>GLOBVOL_SHIFT) * chanVolumes[i] * stepVolume[i];
Pokitto 0:e8b8f36b4505 594 //Serial.println(outputVolume[i]);
Pokitto 0:e8b8f36b4505 595 // jonnehw interrupts();
Pokitto 0:e8b8f36b4505 596 }
Pokitto 0:e8b8f36b4505 597 #endif
Pokitto 0:e8b8f36b4505 598 }
Pokitto 0:e8b8f36b4505 599
Pokitto 0:e8b8f36b4505 600 void Sound::setChannelHalfPeriod(uint8_t channel, uint8_t halfPeriod) {
Pokitto 0:e8b8f36b4505 601 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 602 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 603 return;
Pokitto 0:e8b8f36b4505 604 _chanHalfPeriod[channel] = halfPeriod;
Pokitto 0:e8b8f36b4505 605 _chanState[channel] = false;
Pokitto 0:e8b8f36b4505 606 _chanCount[channel] = 0;
Pokitto 0:e8b8f36b4505 607 updateOutput();
Pokitto 0:e8b8f36b4505 608 #endif
Pokitto 0:e8b8f36b4505 609 }
Pokitto 0:e8b8f36b4505 610
Pokitto 0:e8b8f36b4505 611
Pokitto 0:e8b8f36b4505 612 void Sound::generateOutput() {
Pokitto 0:e8b8f36b4505 613 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 614 bool outputChanged = false;
Pokitto 0:e8b8f36b4505 615 //no for loop here, for the performance sake (this function runs 15 000 times per second...)
Pokitto 0:e8b8f36b4505 616 //CHANNEL 0
Pokitto 0:e8b8f36b4505 617 if (_chanOutputVolume[0]) {
Pokitto 0:e8b8f36b4505 618 _chanCount[0]++;
Pokitto 0:e8b8f36b4505 619 if (_chanCount[0] >= _chanHalfPeriod[0]) {
Pokitto 0:e8b8f36b4505 620 outputChanged = true;
Pokitto 0:e8b8f36b4505 621 _chanState[0] = !_chanState[0];
Pokitto 0:e8b8f36b4505 622 _chanCount[0] = 0;
Pokitto 0:e8b8f36b4505 623 if (_chanNoise[0]) {
Pokitto 0:e8b8f36b4505 624 _rand = 67 * _rand + 71;
Pokitto 0:e8b8f36b4505 625 _chanOutput[0] = _rand % _chanOutputVolume[0];
Pokitto 0:e8b8f36b4505 626 }
Pokitto 0:e8b8f36b4505 627 }
Pokitto 0:e8b8f36b4505 628 }
Pokitto 0:e8b8f36b4505 629
Pokitto 0:e8b8f36b4505 630
Pokitto 0:e8b8f36b4505 631 //CHANNEL 1
Pokitto 0:e8b8f36b4505 632 #if (NUM_CHANNELS > 1)
Pokitto 0:e8b8f36b4505 633 if (_chanOutputVolume[1]) {
Pokitto 0:e8b8f36b4505 634 _chanCount[1]++;
Pokitto 0:e8b8f36b4505 635 if (_chanCount[1] >= _chanHalfPeriod[1]) {
Pokitto 0:e8b8f36b4505 636 outputChanged = true;
Pokitto 0:e8b8f36b4505 637 _chanState[1] = !_chanState[1];
Pokitto 0:e8b8f36b4505 638 _chanCount[1] = 0;
Pokitto 0:e8b8f36b4505 639 if (_chanNoise[1]) {
Pokitto 0:e8b8f36b4505 640 _rand = 67 * _rand + 71;
Pokitto 0:e8b8f36b4505 641 _chanOutput[1] = _rand % _chanOutputVolume[1];
Pokitto 0:e8b8f36b4505 642 }
Pokitto 0:e8b8f36b4505 643 }
Pokitto 0:e8b8f36b4505 644 }
Pokitto 0:e8b8f36b4505 645 #endif
Pokitto 0:e8b8f36b4505 646
Pokitto 0:e8b8f36b4505 647 //CHANNEL 2
Pokitto 0:e8b8f36b4505 648 #if (NUM_CHANNELS > 2)
Pokitto 0:e8b8f36b4505 649 if (_chanOutputVolume[2]) {
Pokitto 0:e8b8f36b4505 650 _chanCount[2]++;
Pokitto 0:e8b8f36b4505 651 if (_chanCount[2] >= _chanHalfPeriod[2]) {
Pokitto 0:e8b8f36b4505 652 outputChanged = true;
Pokitto 0:e8b8f36b4505 653 _chanState[2] = !_chanState[2];
Pokitto 0:e8b8f36b4505 654 _chanCount[2] = 0;
Pokitto 0:e8b8f36b4505 655 if (_chanNoise[2]) {
Pokitto 0:e8b8f36b4505 656 _rand = 67 * _rand + 71;
Pokitto 0:e8b8f36b4505 657 _chanOutput[2] = _rand % _chanOutputVolume[2];
Pokitto 0:e8b8f36b4505 658 }
Pokitto 0:e8b8f36b4505 659 }
Pokitto 0:e8b8f36b4505 660 }
Pokitto 0:e8b8f36b4505 661 #endif
Pokitto 0:e8b8f36b4505 662
Pokitto 0:e8b8f36b4505 663 //CHANNEL 3
Pokitto 0:e8b8f36b4505 664 #if (NUM_CHANNELS > 3)
Pokitto 0:e8b8f36b4505 665 if (_chanOutputVolume[3]) {
Pokitto 0:e8b8f36b4505 666 _chanCount[3]++;
Pokitto 0:e8b8f36b4505 667 if (_chanCount[3] >= _chanHalfPeriod[3]) {
Pokitto 0:e8b8f36b4505 668 outputChanged = true;
Pokitto 0:e8b8f36b4505 669 _chanState[3] = !_chanState[3];
Pokitto 0:e8b8f36b4505 670 _chanCount[3] = 0;
Pokitto 0:e8b8f36b4505 671 if (_chanNoise[3]) {
Pokitto 0:e8b8f36b4505 672 _rand = 67 * _rand + 71;
Pokitto 0:e8b8f36b4505 673 _chanOutput[3] = _rand % _chanOutputVolume[3];
Pokitto 0:e8b8f36b4505 674 }
Pokitto 0:e8b8f36b4505 675 }
Pokitto 0:e8b8f36b4505 676 }
Pokitto 0:e8b8f36b4505 677 #endif
Pokitto 0:e8b8f36b4505 678
Pokitto 0:e8b8f36b4505 679 #if POK_STREAMING_MUSIC
Pokitto 0:e8b8f36b4505 680 if (streamstep) {
Pokitto 0:e8b8f36b4505 681 outputChanged=true;
Pokitto 0:e8b8f36b4505 682 }
Pokitto 0:e8b8f36b4505 683 #endif
Pokitto 0:e8b8f36b4505 684
Pokitto 0:e8b8f36b4505 685 if (outputChanged) {
Pokitto 0:e8b8f36b4505 686 updateOutput();
Pokitto 0:e8b8f36b4505 687 }
Pokitto 0:e8b8f36b4505 688 #endif
Pokitto 0:e8b8f36b4505 689 }
Pokitto 0:e8b8f36b4505 690
Pokitto 0:e8b8f36b4505 691 void Sound::updateOutput() {
Pokitto 0:e8b8f36b4505 692 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 693 uint8_t output = 0;
Pokitto 0:e8b8f36b4505 694
Pokitto 0:e8b8f36b4505 695 //CHANNEL 0
Pokitto 0:e8b8f36b4505 696 if (_chanState[0]) {
Pokitto 0:e8b8f36b4505 697 output += _chanOutput[0];
Pokitto 0:e8b8f36b4505 698 }
Pokitto 0:e8b8f36b4505 699
Pokitto 0:e8b8f36b4505 700 //CHANNEL 1
Pokitto 0:e8b8f36b4505 701 #if (NUM_CHANNELS > 1)
Pokitto 0:e8b8f36b4505 702 if (_chanState[1]) {
Pokitto 0:e8b8f36b4505 703 output += _chanOutput[1];
Pokitto 0:e8b8f36b4505 704 }
Pokitto 0:e8b8f36b4505 705 #endif
Pokitto 0:e8b8f36b4505 706
Pokitto 0:e8b8f36b4505 707 //CHANNEL 2
Pokitto 0:e8b8f36b4505 708 #if (NUM_CHANNELS > 2)
Pokitto 0:e8b8f36b4505 709 if (_chanState[2]) {
Pokitto 0:e8b8f36b4505 710 output += _chanOutput[2];
Pokitto 0:e8b8f36b4505 711 }
Pokitto 0:e8b8f36b4505 712 #endif
Pokitto 0:e8b8f36b4505 713
Pokitto 0:e8b8f36b4505 714 //CHANNEL 3
Pokitto 0:e8b8f36b4505 715 #if (NUM_CHANNELS > 3)
Pokitto 0:e8b8f36b4505 716 if (_chanState[3]) {
Pokitto 0:e8b8f36b4505 717 output += _chanOutput[3];
Pokitto 0:e8b8f36b4505 718 }
Pokitto 0:e8b8f36b4505 719 #endif
Pokitto 0:e8b8f36b4505 720
Pokitto 0:e8b8f36b4505 721 #ifndef POK_SIM
Pokitto 0:e8b8f36b4505 722 #if POK_ENABLE_SOUND
Pokitto 0:e8b8f36b4505 723 /** HARDWARE **/
Pokitto 0:e8b8f36b4505 724
Pokitto 0:e8b8f36b4505 725 #if POK_STREAMING_MUSIC
Pokitto 0:e8b8f36b4505 726 if (streamstep) {
Pokitto 0:e8b8f36b4505 727 pwmout_write(&audiopwm,(float)sbyte/(float)255);
Pokitto 0:e8b8f36b4505 728 }
Pokitto 0:e8b8f36b4505 729 #endif
Pokitto 0:e8b8f36b4505 730 dac_write((uint8_t)output); //direct hardware mixing baby !
Pokitto 1:4b1511a0a2c2 731 soundbyte = output;
Pokitto 0:e8b8f36b4505 732 #endif //POK_ENABLE_SOUND
Pokitto 0:e8b8f36b4505 733 #else
Pokitto 0:e8b8f36b4505 734 /** SIMULATOR **/
Pokitto 0:e8b8f36b4505 735 #if POK_STREAMING_MUSIC
Pokitto 0:e8b8f36b4505 736 if (streamstep) {
Pokitto 0:e8b8f36b4505 737 uint16_t o = output + sbyte;
Pokitto 0:e8b8f36b4505 738 output = o/2;
Pokitto 0:e8b8f36b4505 739 }
Pokitto 0:e8b8f36b4505 740 #endif
Pokitto 0:e8b8f36b4505 741 soundbyte = output;
Pokitto 0:e8b8f36b4505 742 #endif // POK_SIM
Pokitto 0:e8b8f36b4505 743 #endif
Pokitto 0:e8b8f36b4505 744 }
Pokitto 0:e8b8f36b4505 745
Pokitto 0:e8b8f36b4505 746 void Sound::setPatternLooping(bool loop, uint8_t channel) {
Pokitto 0:e8b8f36b4505 747 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 748 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 749 return;
Pokitto 0:e8b8f36b4505 750 patternLooping[channel] = loop;
Pokitto 0:e8b8f36b4505 751 #endif
Pokitto 0:e8b8f36b4505 752 }
Pokitto 0:e8b8f36b4505 753
Pokitto 0:e8b8f36b4505 754 void Sound::playOK(){
Pokitto 0:e8b8f36b4505 755 #if POK_GBSOUND
Pokitto 0:e8b8f36b4505 756 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 757 playPattern(playOKPattern,0);
Pokitto 0:e8b8f36b4505 758 #endif
Pokitto 0:e8b8f36b4505 759 #endif // POK_GBSOUND
Pokitto 0:e8b8f36b4505 760 }
Pokitto 0:e8b8f36b4505 761
Pokitto 0:e8b8f36b4505 762 void Sound::playCancel(){
Pokitto 0:e8b8f36b4505 763 #if POK_GBSOUND
Pokitto 0:e8b8f36b4505 764 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 765 playPattern(playCancelPattern,0);
Pokitto 0:e8b8f36b4505 766 #endif
Pokitto 0:e8b8f36b4505 767 #endif
Pokitto 0:e8b8f36b4505 768 }
Pokitto 0:e8b8f36b4505 769
Pokitto 0:e8b8f36b4505 770 void Sound::playTick(){
Pokitto 0:e8b8f36b4505 771 #if POK_GBSOUND
Pokitto 0:e8b8f36b4505 772 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 773 playPattern(playTickP,0);
Pokitto 0:e8b8f36b4505 774 #endif
Pokitto 0:e8b8f36b4505 775 #endif // POK_GBSOUND
Pokitto 0:e8b8f36b4505 776 }
Pokitto 0:e8b8f36b4505 777
Pokitto 0:e8b8f36b4505 778 void Sound::setVolume(int16_t volume) {
Pokitto 0:e8b8f36b4505 779 //#if NUM_CHANNELS > 0
Pokitto 0:e8b8f36b4505 780 if (volume<0) volume = 0;
Pokitto 0:e8b8f36b4505 781 if (volume>volumeMax) volume = volumeMax;
Pokitto 0:e8b8f36b4505 782 globalVolume = volume; // % (volumeMax+1);
Pokitto 0:e8b8f36b4505 783 #ifndef POK_SIM
Pokitto 0:e8b8f36b4505 784 volume = (volume / 2)-10;
Pokitto 0:e8b8f36b4505 785 if (volume<0) volume = 0;
Pokitto 0:e8b8f36b4505 786 #if POK_ENABLE_SOUND > 1
Pokitto 0:e8b8f36b4505 787 setHWvolume(volume);
Pokitto 0:e8b8f36b4505 788 #endif
Pokitto 0:e8b8f36b4505 789 #endif
Pokitto 0:e8b8f36b4505 790 #if POK_SHOW_VOLUME > 0
Pokitto 0:e8b8f36b4505 791 c.volbar_visible = VOLUMEBAR_TIMEOUT;
Pokitto 0:e8b8f36b4505 792 #endif
Pokitto 0:e8b8f36b4505 793 //#endif
Pokitto 0:e8b8f36b4505 794 }
Pokitto 0:e8b8f36b4505 795
Pokitto 0:e8b8f36b4505 796 uint16_t Sound::getVolume() {
Pokitto 0:e8b8f36b4505 797 //#if NUM_CHANNELS > 0
Pokitto 0:e8b8f36b4505 798 return globalVolume;
Pokitto 0:e8b8f36b4505 799 //#else
Pokitto 0:e8b8f36b4505 800 // return 0;
Pokitto 0:e8b8f36b4505 801 //#endif
Pokitto 0:e8b8f36b4505 802 }
Pokitto 0:e8b8f36b4505 803
Pokitto 0:e8b8f36b4505 804 void Sound::setVolume(int8_t volume, uint8_t channel) {
Pokitto 0:e8b8f36b4505 805 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 806 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 807 return;
Pokitto 0:e8b8f36b4505 808 volume = (volume > VOLUME_CHANNEL_MAX) ? VOLUME_CHANNEL_MAX : volume;
Pokitto 0:e8b8f36b4505 809 volume = (volume < 0) ? 0 : volume;
Pokitto 0:e8b8f36b4505 810 chanVolumes[channel] = volume;
Pokitto 0:e8b8f36b4505 811 #endif
Pokitto 0:e8b8f36b4505 812 }
Pokitto 0:e8b8f36b4505 813
Pokitto 0:e8b8f36b4505 814 uint8_t Sound::getVolume(uint8_t channel) {
Pokitto 0:e8b8f36b4505 815 #if(NUM_CHANNELS > 0)
Pokitto 0:e8b8f36b4505 816 if(channel>=NUM_CHANNELS)
Pokitto 0:e8b8f36b4505 817 return 255;
Pokitto 0:e8b8f36b4505 818 return (chanVolumes[channel]);
Pokitto 0:e8b8f36b4505 819 #else
Pokitto 0:e8b8f36b4505 820 return 0;
Pokitto 0:e8b8f36b4505 821 #endif
Pokitto 0:e8b8f36b4505 822 }
Pokitto 0:e8b8f36b4505 823
Pokitto 0:e8b8f36b4505 824 void Sound::playTone(uint8_t os, int frq, uint8_t amp, uint8_t wav,uint8_t arpmode)
Pokitto 0:e8b8f36b4505 825 {
Pokitto 0:e8b8f36b4505 826 if (wav>5) wav=0;
Pokitto 0:e8b8f36b4505 827 if (arpmode>MAX_ARPMODE) arpmode=MAX_ARPMODE;
Pokitto 0:e8b8f36b4505 828 if (os==1) setOSC(&osc1,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
Pokitto 0:e8b8f36b4505 829 else if (os==2) setOSC(&osc2,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
Pokitto 0:e8b8f36b4505 830 else if (os==3) setOSC(&osc3,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
Pokitto 0:e8b8f36b4505 831 }
Pokitto 0:e8b8f36b4505 832
Pokitto 0:e8b8f36b4505 833 void Sound::playTone(uint8_t os, uint16_t frq, uint8_t volume, uint32_t duration)
Pokitto 0:e8b8f36b4505 834 {
Pokitto 0:e8b8f36b4505 835 if (os==1) setOSC(&osc1,1,WSAW,frq,volume,duration);
Pokitto 0:e8b8f36b4505 836 else if (os==2) setOSC(&osc2,1,WTRI,frq,volume,duration);
Pokitto 0:e8b8f36b4505 837 else if (os==3) setOSC(&osc3,1,WTRI,frq,volume,duration);
Pokitto 0:e8b8f36b4505 838 }
Pokitto 0:e8b8f36b4505 839
Pokitto 0:e8b8f36b4505 840 uint8_t Sound::ampIsOn()
Pokitto 0:e8b8f36b4505 841 {
Pokitto 0:e8b8f36b4505 842 #ifdef POK_SIM
Pokitto 0:e8b8f36b4505 843 return core.ampIsOn();
Pokitto 0:e8b8f36b4505 844 #else
Pokitto 1:4b1511a0a2c2 845 #if POK_ENABLE_SOUND > 1
Pokitto 0:e8b8f36b4505 846 return Pokitto::ampIsOn();
Pokitto 1:4b1511a0a2c2 847 #endif
Pokitto 0:e8b8f36b4505 848 #endif // POK_SIM
Pokitto 2:968589ca3484 849 return 0;
Pokitto 0:e8b8f36b4505 850 }
Pokitto 0:e8b8f36b4505 851
Pokitto 0:e8b8f36b4505 852 void Sound::ampEnable(uint8_t v) {
Pokitto 0:e8b8f36b4505 853 #ifdef POK_SIM
Pokitto 0:e8b8f36b4505 854 core.ampEnable(v);
Pokitto 0:e8b8f36b4505 855 #else
Pokitto 1:4b1511a0a2c2 856 #if POK_ENABLE_SOUND > 1
Pokitto 0:e8b8f36b4505 857 Pokitto::ampEnable(v);
Pokitto 1:4b1511a0a2c2 858 #endif
Pokitto 0:e8b8f36b4505 859 #endif // POK_SIM
Pokitto 0:e8b8f36b4505 860
Pokitto 0:e8b8f36b4505 861 }
Pokitto 0:e8b8f36b4505 862
Pokitto 0:e8b8f36b4505 863 int Sound::playMusicStream(char* filename)
Pokitto 0:e8b8f36b4505 864 {
Pokitto 2:968589ca3484 865 return playMusicStream(filename,0);
Pokitto 0:e8b8f36b4505 866 }
Pokitto 0:e8b8f36b4505 867
Pokitto 0:e8b8f36b4505 868 int Sound::playMusicStream()
Pokitto 0:e8b8f36b4505 869 {
Pokitto 0:e8b8f36b4505 870 #if POK_STREAMING_MUSIC >0
Pokitto 0:e8b8f36b4505 871 if (currentPtr) {
Pokitto 0:e8b8f36b4505 872 pokPlayStream();
Pokitto 0:e8b8f36b4505 873 return 1;
Pokitto 0:e8b8f36b4505 874 } else return 0; //no stream
Pokitto 0:e8b8f36b4505 875 #endif // POK_STREAMING_MUSIC
Pokitto 0:e8b8f36b4505 876 }
Pokitto 0:e8b8f36b4505 877
Pokitto 0:e8b8f36b4505 878 void Sound::pauseMusicStream() {
Pokitto 1:4b1511a0a2c2 879 #if POK_ENABLE_SOUND > 1
Pokitto 0:e8b8f36b4505 880 pokPauseStream();
Pokitto 1:4b1511a0a2c2 881 #endif
Pokitto 0:e8b8f36b4505 882 }
Pokitto 0:e8b8f36b4505 883
Pokitto 0:e8b8f36b4505 884 int Sound::playMusicStream(char* filename, uint8_t options)
Pokitto 0:e8b8f36b4505 885 {
Pokitto 0:e8b8f36b4505 886 #if POK_STREAMING_MUSIC
Pokitto 0:e8b8f36b4505 887 uint8_t result;
Pokitto 0:e8b8f36b4505 888 result = pokInitSD();
Pokitto 0:e8b8f36b4505 889 if (!isThisFileOpen(filename)) {
Pokitto 0:e8b8f36b4505 890 fileClose(); // close any open files
Pokitto 0:e8b8f36b4505 891 result = fileOpen(filename,FILE_MODE_OVERWRITE | FILE_MODE_BINARY);
Pokitto 0:e8b8f36b4505 892 }
Pokitto 0:e8b8f36b4505 893
Pokitto 0:e8b8f36b4505 894 if (result) {
Pokitto 0:e8b8f36b4505 895 currentPtr = 0; // mark that no stream is available
Pokitto 0:e8b8f36b4505 896 return 0; // opening music file failed
Pokitto 0:e8b8f36b4505 897 }
Pokitto 0:e8b8f36b4505 898
Pokitto 0:e8b8f36b4505 899 fileReadBytes(&buffers[0][0],BUFFER_SIZE);
Pokitto 0:e8b8f36b4505 900 fileReadBytes(&buffers[1][0],BUFFER_SIZE);
Pokitto 0:e8b8f36b4505 901 fileReadBytes(&buffers[2][0],BUFFER_SIZE);
Pokitto 0:e8b8f36b4505 902 fileReadBytes(&buffers[3][0],BUFFER_SIZE);
Pokitto 0:e8b8f36b4505 903 currentBuffer = 0;
Pokitto 0:e8b8f36b4505 904 currentPtr = buffers[currentBuffer];
Pokitto 0:e8b8f36b4505 905 endPtr = currentPtr + BUFFER_SIZE;
Pokitto 0:e8b8f36b4505 906
Pokitto 0:e8b8f36b4505 907 //streaming = STR_PLAYING|options;
Pokitto 0:e8b8f36b4505 908
Pokitto 0:e8b8f36b4505 909 if (!options) pokPlayStream(); // activate stream
Pokitto 0:e8b8f36b4505 910 #endif //POK_STREAMING_MUSIC
Pokitto 0:e8b8f36b4505 911 return 1; // opening music file succeeded
Pokitto 0:e8b8f36b4505 912 }
Pokitto 0:e8b8f36b4505 913