PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PokittoSound.cpp Source File

PokittoSound.cpp

Go to the documentation of this file.
00001 /**************************************************************************/
00002 /*!
00003     @file     PokittoSound.cpp
00004     @author   Jonne Valola
00005 
00006     @section LICENSE
00007 
00008     Software License Agreement (BSD License)
00009 
00010     Copyright (c) 2016, Jonne Valola
00011     All rights reserved.
00012 
00013     Redistribution and use in source and binary forms, with or without
00014     modification, are permitted provided that the following conditions are met:
00015     1. Redistributions of source code must retain the above copyright
00016     notice, this list of conditions and the following disclaimer.
00017     2. Redistributions in binary form must reproduce the above copyright
00018     notice, this list of conditions and the following disclaimer in the
00019     documentation and/or other materials provided with the distribution.
00020     3. Neither the name of the copyright holders nor the
00021     names of its contributors may be used to endorse or promote products
00022     derived from this software without specific prior written permission.
00023 
00024     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
00025     EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
00028     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00033     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 */
00035 /**************************************************************************/
00036 
00037 /*
00038  * NOTE:
00039  * API of the Pokitto Sound library is partially identical to the Gamebuino Sound API.
00040  * Due to the difference in architecture (ARM Cortex-M0+ in mbed environment vs. 8-bit AVR)
00041  * large parts are not identical. Most functions were rewritten, with only API remaining.
00042  * We want to give attribution to the original author's project:
00043  *
00044  * License for Gamebuino-identical code:
00045  *
00046  * (C) Copyright 2014 Aur�lien Rodot. All rights reserved.
00047  *
00048  * This file is part of the Gamebuino Library (http://gamebuino.com)
00049  *
00050  * The Gamebuino Library is free software: you can redistribute it and/or modify
00051  * it under the terms of the GNU Lesser General Public License as published by
00052  * the Free Software Foundation, either version 3 of the License, or
00053  * (at your option) any later version.
00054  *
00055  * This program is distributed in the hope that it will be useful,
00056  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00057  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00058  * GNU Lesser General Public License for more details.
00059  *
00060  * You should have received a copy of the GNU Lesser General Public License
00061  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00062  */
00063 
00064 #include "PokittoSound.h "
00065 #include "Pokitto_settings.h "
00066 #include "PokittoCore.h "
00067 #include "Synth.h "
00068 
00069 #ifndef POK_SIM
00070 #include "HWSound.h"
00071 #else
00072 #include "SimSound.h"
00073 #include "PokittoSimulator.h"
00074 #endif
00075 
00076 typedef uint8_t byte;
00077 
00078 using namespace Pokitto;
00079 
00080 /** discrete hardware volume control **/
00081 
00082 uint8_t Pokitto::discrete_vol = 0;
00083 uint8_t const Pokitto::discrete_vol_levels[]      = {0,32,64,96,128,160,192,224};
00084 uint8_t const Pokitto::discrete_vol_hw_levels[]   = {0,27,64,96,36,117,127,127};
00085 uint8_t const Pokitto::discrete_vol_multipliers[] = {0,127,127,127,192,192,255,255};
00086 
00087 Pokitto::Core _soundc;
00088 
00089 uint8_t Sound::prescaler;
00090 uint16_t Sound::globalVolume;
00091 uint16_t Sound::volumeMax = VOLUME_HEADPHONE_MAX;
00092 uint8_t Sound::headPhoneLevel=1;
00093 
00094 bool Sound::trackIsPlaying[NUM_CHANNELS];
00095 bool Sound::patternIsPlaying[NUM_CHANNELS];
00096 uint8_t Sound::outputPitch[NUM_CHANNELS];
00097 int8_t Sound::outputVolume[NUM_CHANNELS];
00098 
00099 uint16_t *Sound::trackData[NUM_CHANNELS];
00100 uint8_t Sound::trackCursor[NUM_CHANNELS];
00101 uint16_t **Sound::patternSet[NUM_CHANNELS];
00102 int8_t Sound::patternPitch[NUM_CHANNELS];
00103 
00104 // pattern data
00105 uint16_t *Sound::patternData[NUM_CHANNELS];
00106 uint16_t **Sound::instrumentSet[NUM_CHANNELS];
00107 bool Sound::patternLooping[NUM_CHANNELS];
00108 uint16_t Sound::patternCursor[NUM_CHANNELS];
00109 
00110 // note data
00111 uint8_t Sound::notePitch[NUM_CHANNELS];
00112 uint8_t Sound::noteDuration[NUM_CHANNELS];
00113 int8_t Sound::noteVolume[NUM_CHANNELS];
00114 bool Sound::notePlaying[NUM_CHANNELS];
00115 
00116 // commands data
00117 int8_t Sound::commandsCounter[NUM_CHANNELS];
00118 int8_t Sound::volumeSlideStepDuration[NUM_CHANNELS];
00119 int8_t Sound::volumeSlideStepSize[NUM_CHANNELS];
00120 uint8_t Sound::arpeggioStepDuration[NUM_CHANNELS];
00121 int8_t Sound::arpeggioStepSize[NUM_CHANNELS];
00122 uint8_t Sound::tremoloStepDuration[NUM_CHANNELS];
00123 int8_t Sound::tremoloStepSize[NUM_CHANNELS];
00124 
00125 // instrument data
00126 uint16_t *Sound::instrumentData[NUM_CHANNELS];
00127 uint8_t Sound::instrumentLength[NUM_CHANNELS]; //number of steps in the instrument
00128 uint8_t Sound::instrumentLooping[NUM_CHANNELS]; //how many steps to loop on when the last step of the instrument is reached
00129 uint16_t Sound::instrumentCursor[NUM_CHANNELS]; //which step is being played
00130 uint8_t Sound::instrumentNextChange[NUM_CHANNELS]; //how many frames before the next step
00131 
00132 //current step data
00133 int8_t Sound::stepVolume[NUM_CHANNELS];
00134 uint8_t Sound::stepPitch[NUM_CHANNELS];
00135 uint8_t Sound::chanVolumes[NUM_CHANNELS];
00136 
00137 #if (POK_ENABLE_SOUND < 1)
00138  #undef NUM_CHANNELS
00139  #define NUM_CHANNELS 0
00140 #endif
00141 
00142 #if(NUM_CHANNELS > 0)
00143     #ifndef POK_SIM
00144         uint32_t sbyte;
00145     #else
00146     uint32_t sbyte;
00147     float pwm1;
00148     #endif // POK_SIM
00149 
00150 //declare these variables globally for faster access
00151 uint8_t _rand = 1;
00152 uint8_t _chanCount[NUM_CHANNELS]; //counts until the next change of the waveform
00153 bool _chanState[NUM_CHANNELS]; //if the waveform is currently high or low
00154 uint8_t _chanHalfPeriod[NUM_CHANNELS]; //duration of half the period of the waveform
00155 uint8_t _chanOutputVolume[NUM_CHANNELS]; //amplitude of the outputted waveform
00156 uint8_t _chanOutput[NUM_CHANNELS]; //current value of the outputted waveform
00157 bool _chanNoise[NUM_CHANNELS]; //if a random value should be added to the waveform to generate noise
00158 
00159 #if POK_GBSOUND > 0
00160 const uint16_t squareWaveInstrument[]  = {0x0101, 0x03F7};
00161 const uint16_t noiseInstrument[]  = {0x0101, 0x03FF};
00162 const uint16_t* const defaultInstruments[]  = {squareWaveInstrument,noiseInstrument};
00163 
00164 const uint16_t playOKPattern[]  = {0x0005,0x138,0x168,0x0000};
00165 const uint16_t playCancelPattern[]  = {0x0005,0x168,0x138,0x0000};
00166 const uint16_t playTickP[]  = {0x0045,0x168,0x0000};
00167 #endif
00168 #if(EXTENDED_NOTE_RANGE > 0)
00169 //extended note range
00170 #define NUM_PITCH 59
00171 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};
00172 #else
00173 //regular note range
00174 #define NUM_PITCH 36
00175 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};
00176 #endif
00177 
00178 #endif
00179 
00180 void Pokitto::audio_IRQ() {
00181     #if POK_STREAMING_MUSIC > 0
00182         #if POK_STREAMFREQ_HALVE > 0
00183         streamstep = 1-streamstep;
00184         #else
00185         streamstep=1;
00186         #endif
00187 
00188         streamstep &= streamon; //check if stream is on
00189 
00190         if(streamvol && streamstep) {
00191             uint8_t output = (*currentPtr++);
00192             sbyte = output;
00193         } else {
00194             sbyte = 0; // duty cycle
00195         }
00196 
00197         if (currentPtr >= endPtr)
00198         {
00199         currentBuffer++;
00200         if (currentBuffer==4) currentBuffer=0;
00201         currentPtr = buffers[currentBuffer];
00202         endPtr = currentPtr + BUFFER_SIZE;
00203         }
00204 
00205     #endif // POK_STREAMING_MUSIC
00206     #if (NUM_CHANNELS > 0)
00207     Sound::generateOutput();
00208     #endif
00209 }
00210 
00211 void Sound::volumeUp() {
00212     Pokitto::discrete_vol++;
00213     if (discrete_vol>7) discrete_vol=7;
00214     globalVolume = discrete_vol_levels[discrete_vol];
00215     setVolume(globalVolume);
00216     //if (globalVolume>VOLUME_HEADPHONE_MAX) setVolume(getVolume()+VOLUME_STEP*2);
00217     //else setVolume(getVolume()+VOLUME_STEP);
00218 }
00219 
00220 void Sound::volumeDown() {
00221     if (discrete_vol) Pokitto::discrete_vol--;
00222     globalVolume = discrete_vol_levels[discrete_vol];
00223     setVolume(globalVolume);
00224     //if (globalVolume>VOLUME_HEADPHONE_MAX) setVolume(getVolume()-VOLUME_STEP*4);
00225     //else setVolume(getVolume()-VOLUME_STEP);
00226 }
00227 
00228 
00229 void Sound::setMaxVol(int16_t v) {
00230     if (v < 0) v = 0; //prevent nasty wraparound
00231     if (v > VOLUME_SPEAKER_MAX) {
00232             v = VOLUME_SPEAKER_MAX;
00233     }
00234     volumeMax = v;
00235     setVolume(globalVolume);
00236 }
00237 
00238 uint16_t Sound::getMaxVol() {
00239     return volumeMax;
00240 }
00241 
00242 void Sound::updateStream() {
00243      #if POK_STREAMING_MUSIC
00244     if (oldBuffer != currentBuffer) {
00245         if (currentBuffer==0) fileReadBytes(&buffers[3][0],BUFFER_SIZE);
00246         else if (currentBuffer==1) fileReadBytes(&buffers[0][0],BUFFER_SIZE);
00247         else if (currentBuffer==2) fileReadBytes(&buffers[1][0],BUFFER_SIZE);
00248         else fileReadBytes(&buffers[2][0],BUFFER_SIZE);
00249         oldBuffer = currentBuffer;
00250         streamcounter += BUFFER_SIZE;
00251     }
00252 
00253     #ifndef POK_SIM
00254     if ( streamcounter > fs.fsize - (BUFFER_SIZE)) {
00255     #else
00256     if ( streamcounter > getFileLength() - (BUFFER_SIZE)) {
00257     #endif
00258         streamcounter=0;
00259         #if POK_STREAM_LOOP > 0
00260         fileRewind();
00261         #else
00262             #ifndef POK_SIM
00263                 streamon=0;
00264             #endif // POK_SIM
00265         #endif // POK_STREAM_LOOP
00266     }
00267     #endif
00268 }
00269 
00270 void Sound::begin() {
00271 #if POK_ENABLE_SOUND > 0
00272 soundInit();
00273 ampEnable(true);
00274 #endif
00275 #if (NUM_CHANNELS > 0)
00276 #if POK_ENABLE_SOUND > 0
00277 #if POK_GBSOUND > 0
00278     prescaler = 1;
00279     for(byte i=0; i<NUM_CHANNELS; i++){
00280         chanVolumes[i] = VOLUME_CHANNEL_MAX;
00281         changeInstrumentSet(defaultInstruments, i); //load default instruments. #0:square wave, #1: noise
00282         command(CMD_INSTRUMENT, 0, 0, i); //set the default instrument to square wave
00283     }
00284 #endif // POK_GBSOUND
00285 #endif //POK_ENABLE_SOUND
00286 #endif
00287 }
00288 
00289 void Sound::playTrack(const uint16_t* track, uint8_t channel){
00290 #if(NUM_CHANNELS > 0)
00291     if(channel>=NUM_CHANNELS)
00292         return;
00293     stopTrack(channel);
00294     trackCursor[channel] = 0;
00295     trackData[channel] = (uint16_t*)track;
00296     trackIsPlaying[channel] = true;
00297 #endif
00298 }
00299 
00300 void Sound::stopTrack(uint8_t channel){
00301 #if(NUM_CHANNELS > 0)
00302     if(channel>=NUM_CHANNELS)
00303         return;
00304     trackIsPlaying[channel] = false;
00305     stopPattern(channel);
00306 #endif
00307 }
00308 
00309 void Sound::stopTrack(){
00310 #if(NUM_CHANNELS > 0)
00311     for(uint8_t i=0; i<NUM_CHANNELS; i++){
00312         stopTrack(i);
00313     }
00314 #endif
00315 }
00316 
00317 void Sound::updateTrack(uint8_t channel){
00318 #if(NUM_CHANNELS > 0)
00319     if(channel>=NUM_CHANNELS)
00320         return;
00321     if(trackIsPlaying[channel] && !patternIsPlaying[channel]){
00322         uint16_t data = pgm_read_word(trackData[channel] + trackCursor[channel]);
00323         if(data == 0xFFFF){ //en of the track
00324             trackIsPlaying[channel] = false;
00325             return;
00326         }
00327         uint8_t patternID = data & 0xFF;
00328         data >>= 8;
00329         patternPitch[channel] = data;
00330         playPattern((const uint16_t*)pgm_read_word(&(patternSet[channel][patternID])), channel);
00331         trackCursor[channel] ++;
00332     }
00333 #endif
00334 }
00335 
00336 void Sound::updateTrack(){
00337 #if(NUM_CHANNELS > 0)
00338     for (uint8_t i=0; i<NUM_CHANNELS; i++){
00339         updateTrack(i);
00340     }
00341 #endif
00342 }
00343 
00344 void Sound::changePatternSet(const uint16_t* const* patterns, uint8_t channel){
00345 #if(NUM_CHANNELS > 0)
00346     if(channel>=NUM_CHANNELS)
00347         return;
00348     patternSet[channel] = (uint16_t**)patterns;
00349 #endif
00350 }
00351 
00352 void Sound::playPattern(const uint16_t* pattern, uint8_t channel){
00353 #if(NUM_CHANNELS > 0)
00354     if(channel>=NUM_CHANNELS)
00355         return;
00356     stopPattern(channel);
00357     patternData[channel] = (uint16_t*)pattern;
00358     patternCursor[channel] = 0;
00359     patternIsPlaying[channel] = true;
00360     noteVolume[channel] = 9;
00361     //reinit commands
00362     volumeSlideStepDuration[channel] = 0;
00363     arpeggioStepDuration[channel] = 0;
00364     tremoloStepDuration[channel] = 0;
00365 #endif
00366 }
00367 
00368 void Sound::updatePattern(){
00369 #if(NUM_CHANNELS > 0)
00370     for (uint8_t i=0; i<NUM_CHANNELS; i++){
00371         updatePattern(i);
00372     }
00373 #endif
00374 }
00375 
00376 void Sound::changeInstrumentSet(const uint16_t* const* instruments, uint8_t channel){
00377 #if(NUM_CHANNELS > 0)
00378     if(channel>=NUM_CHANNELS)
00379         return;
00380     instrumentSet[channel] = (uint16_t**)instruments;
00381 #endif
00382 }
00383 
00384 void Sound::updatePattern(uint8_t i){
00385 #if(NUM_CHANNELS > 0)
00386     if(i>=NUM_CHANNELS)
00387         return;
00388     if(patternIsPlaying[i]){
00389         if(noteDuration[i]==0){//if the end of the previous note is reached
00390 
00391             uint16_t data = pgm_read_word(patternCursor[i] + patternData[i]);
00392 
00393             if(data == 0){ //end of the pattern reached
00394                 if(patternLooping[i] == true){
00395                     patternCursor[i] = 0;
00396                     data = pgm_read_word(patternCursor[i] + patternData[i]);
00397                 }
00398                 else{
00399                     patternIsPlaying[i] = false;
00400                     if(trackIsPlaying[i]){ //if this pattern is part of a track, get the next pattern
00401                         updateTrack(i);
00402                         data = pgm_read_word(patternCursor[i] + patternData[i]);
00403                     } else {
00404                         stopNote(i);
00405                         //Serial.print("pattern end\n");
00406                         return;
00407                     }
00408                 }
00409             }
00410 
00411             while (data & 0x0001){ //read all commands and instrument changes
00412                 data >>= 2;
00413                 //Serial.print("\ncmd\t");
00414                 uint8_t cmd = data & 0x0F;
00415                 data >>= 4;
00416                 uint8_t X = data & 0x1F;
00417                 data >>= 5;
00418                 int8_t Y = data - 16;
00419                 command(cmd,X,Y,i);
00420                 patternCursor[i]++;
00421                 data = pgm_read_word(patternCursor[i] + patternData[i]);
00422             }
00423             data >>= 2;
00424 
00425             uint8_t pitch = data & 0x003F;
00426             data >>= 6;
00427 
00428             uint8_t duration = data;
00429             if(pitch != 63){
00430             }
00431 
00432             playNote(pitch, duration, i);
00433 
00434             patternCursor[i]++;
00435         }
00436     }
00437 #endif
00438 }
00439 
00440 void Sound::stopPattern(uint8_t channel){
00441 #if(NUM_CHANNELS > 0)
00442     if(channel>=NUM_CHANNELS)
00443         return;
00444     stopNote(channel);
00445     patternIsPlaying[channel] = false;
00446 #endif
00447 }
00448 
00449 void Sound::stopPattern(){
00450 #if(NUM_CHANNELS > 0)
00451     for(uint8_t i=0; i<NUM_CHANNELS; i++){
00452         stopPattern(i);
00453     }
00454 #endif
00455 }
00456 
00457 void Sound::command(uint8_t cmd, uint8_t X, int8_t Y, uint8_t i){
00458 #if(NUM_CHANNELS > 0)
00459     if(i>=NUM_CHANNELS)
00460         return;
00461     switch(cmd){
00462     case CMD_VOLUME: //volume
00463         X = constrain((int8_t)X, 0, 10);
00464         noteVolume[i] = X;
00465         break;
00466     case CMD_INSTRUMENT: //instrument
00467         instrumentData[i] = (uint16_t*)pgm_read_word(&(instrumentSet[i][X]));
00468         instrumentLength[i] = pgm_read_word(&(instrumentData[i][0])) & 0x00FF; //8 LSB
00469         instrumentLength[i] *= prescaler;
00470         instrumentLooping[i] = min2((pgm_read_word(&(instrumentData[i][0])) >> 8), instrumentLength[i]); //8 MSB - check that the loop is shorter than the instrument length
00471         instrumentLooping[i] *= prescaler;
00472         break;
00473     case CMD_SLIDE: //volume slide
00474         volumeSlideStepDuration[i] = X * prescaler;
00475         volumeSlideStepSize[i] = Y;
00476         break;
00477     case CMD_ARPEGGIO:
00478         arpeggioStepDuration[i] = X * prescaler;
00479         arpeggioStepSize[i] = Y;
00480         break;
00481     case CMD_TREMOLO:
00482         tremoloStepDuration[i] = X * prescaler;
00483         tremoloStepSize[i] = Y;
00484         break;
00485     default:
00486         break;
00487     }
00488 #endif
00489 }
00490 
00491 void Sound::playNote(uint8_t pitch, uint8_t duration, uint8_t channel){
00492 #if(NUM_CHANNELS > 0)
00493     if(channel>=NUM_CHANNELS)
00494         return;
00495     //set note
00496     notePitch[channel] = pitch;
00497     noteDuration[channel] = duration * prescaler;
00498     //reinit vars
00499     instrumentNextChange[channel] = 0;
00500     instrumentCursor[channel] = 0;
00501     notePlaying[channel] = true;
00502     _chanState[channel] = true;
00503     commandsCounter[channel] = 0;
00504 #endif
00505 }
00506 
00507 void Sound::stopNote(uint8_t channel) {
00508 #if(NUM_CHANNELS > 0)
00509     if(channel>=NUM_CHANNELS)
00510         return;
00511     notePlaying[channel] = false;
00512     //counters
00513     noteDuration[channel] = 0;
00514     instrumentCursor[channel] = 0;
00515     commandsCounter[channel] = 0;
00516     //output
00517     _chanOutput[channel] = 0;
00518     _chanOutputVolume[channel] = 0;
00519     _chanState[channel] = false;
00520     updateOutput();
00521 #endif
00522 }
00523 
00524 void Sound::stopNote() {
00525 #if(NUM_CHANNELS > 0)
00526     for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
00527         stopNote(channel);
00528     }
00529 #endif
00530 }
00531 
00532 void Sound::updateNote() {
00533 #if(NUM_CHANNELS > 0)
00534     for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
00535         updateNote(i);
00536     }
00537 #endif
00538 }
00539 
00540 void Sound::updateNote(uint8_t i) {
00541 #if(NUM_CHANNELS > 0)
00542     if(i>=NUM_CHANNELS)
00543         return;
00544     if (notePlaying[i]) {
00545 
00546         if(noteDuration[i] == 0){
00547             stopNote(i);
00548             //Serial.println("note end");
00549             return;
00550         } else {
00551             noteDuration[i]--;
00552         }
00553 
00554         if (instrumentNextChange[i] == 0) {
00555 
00556             //read the step data from the progmem and decode it
00557             uint16_t thisStep = pgm_read_word(&(instrumentData[i][1 + instrumentCursor[i]]));
00558 
00559             stepVolume[i] = thisStep & 0x0007;
00560             thisStep >>= 3;
00561 
00562             uint8_t stepNoise = thisStep & 0x0001;
00563             thisStep >>= 1;
00564 
00565             uint8_t stepDuration = thisStep & 0x003F;
00566             thisStep >>= 6;
00567 
00568             stepPitch[i] = thisStep;
00569 
00570             //apply the step settings
00571             instrumentNextChange[i] = stepDuration * prescaler;
00572 
00573             _chanNoise[i] = stepNoise;
00574 
00575 
00576             instrumentCursor[i]++;
00577 
00578             if (instrumentCursor[i] >= instrumentLength[i]) {
00579                 if (instrumentLooping[i]) {
00580                     instrumentCursor[i] = instrumentLength[i] - instrumentLooping[i];
00581                 } else {
00582                     stopNote(i);
00583                 }
00584             }
00585         }
00586         instrumentNextChange[i]--;
00587 
00588         commandsCounter[i]++;
00589 
00590         //UPDATE VALUES
00591         //pitch
00592         outputPitch[i] = notePitch[i] + stepPitch[i] + patternPitch[i];
00593         if(arpeggioStepDuration[i]){
00594           outputPitch[i] += commandsCounter[i] / arpeggioStepDuration[i] * arpeggioStepSize[i];
00595         }
00596         outputPitch[i] = (outputPitch[i] + NUM_PITCH) % NUM_PITCH; //wrap
00597         //volume
00598         outputVolume[i] = noteVolume[i];
00599         if(volumeSlideStepDuration[i]){
00600           outputVolume[i] += commandsCounter[i] / volumeSlideStepDuration[i] * volumeSlideStepSize[i];
00601         }
00602         if(tremoloStepDuration[i]){
00603             outputVolume[i] += ((commandsCounter[i]/tremoloStepDuration[i]) % 2) * tremoloStepSize[i];
00604         }
00605         outputVolume[i] = constrain(outputVolume[i], 0, 9);
00606         if(notePitch[i] == 63){
00607             outputVolume[i] = 0;
00608         }
00609         // jonnehw noInterrupts();
00610         _chanHalfPeriod[i] = pgm_read_byte(_halfPeriods + outputPitch[i]);
00611         _chanOutput[i] = _chanOutputVolume[i] = outputVolume[i] * (globalVolume>>GLOBVOL_SHIFT) * chanVolumes[i] * stepVolume[i];
00612         //Serial.println(outputVolume[i]);
00613         // jonnehw interrupts();
00614     }
00615 #endif
00616 }
00617 
00618 void Sound::setChannelHalfPeriod(uint8_t channel, uint8_t halfPeriod) {
00619 #if(NUM_CHANNELS > 0)
00620     if(channel>=NUM_CHANNELS)
00621         return;
00622     _chanHalfPeriod[channel] = halfPeriod;
00623     _chanState[channel] = false;
00624     _chanCount[channel] = 0;
00625     updateOutput();
00626 #endif
00627 }
00628 
00629 
00630 void Sound::generateOutput() {
00631 #if(NUM_CHANNELS > 0)
00632     bool outputChanged = false;
00633     //no for loop here, for the performance sake (this function runs 15 000 times per second...)
00634     //CHANNEL 0
00635     if (_chanOutputVolume[0]) {
00636         _chanCount[0]++;
00637         if (_chanCount[0] >= _chanHalfPeriod[0]) {
00638             outputChanged = true;
00639             _chanState[0] = !_chanState[0];
00640             _chanCount[0] = 0;
00641             if (_chanNoise[0]) {
00642                 _rand = 67 * _rand + 71;
00643                 _chanOutput[0] = _rand % _chanOutputVolume[0];
00644             }
00645         }
00646     }
00647 
00648 
00649     //CHANNEL 1
00650     #if (NUM_CHANNELS > 1)
00651     if (_chanOutputVolume[1]) {
00652         _chanCount[1]++;
00653         if (_chanCount[1] >= _chanHalfPeriod[1]) {
00654             outputChanged = true;
00655             _chanState[1] = !_chanState[1];
00656             _chanCount[1] = 0;
00657             if (_chanNoise[1]) {
00658                 _rand = 67 * _rand + 71;
00659                 _chanOutput[1] = _rand % _chanOutputVolume[1];
00660             }
00661         }
00662     }
00663     #endif
00664 
00665     //CHANNEL 2
00666     #if (NUM_CHANNELS > 2)
00667     if (_chanOutputVolume[2]) {
00668         _chanCount[2]++;
00669         if (_chanCount[2] >= _chanHalfPeriod[2]) {
00670             outputChanged = true;
00671             _chanState[2] = !_chanState[2];
00672             _chanCount[2] = 0;
00673             if (_chanNoise[2]) {
00674                 _rand = 67 * _rand + 71;
00675                 _chanOutput[2] = _rand % _chanOutputVolume[2];
00676             }
00677         }
00678     }
00679     #endif
00680 
00681     //CHANNEL 3
00682     #if (NUM_CHANNELS > 3)
00683     if (_chanOutputVolume[3]) {
00684         _chanCount[3]++;
00685         if (_chanCount[3] >= _chanHalfPeriod[3]) {
00686             outputChanged = true;
00687             _chanState[3] = !_chanState[3];
00688             _chanCount[3] = 0;
00689             if (_chanNoise[3]) {
00690                 _rand = 67 * _rand + 71;
00691                 _chanOutput[3] = _rand % _chanOutputVolume[3];
00692             }
00693         }
00694     }
00695     #endif
00696 
00697     #if POK_STREAMING_MUSIC
00698         if (streamstep) {
00699             outputChanged=true;
00700         }
00701     #endif
00702 
00703     if (outputChanged) {
00704         updateOutput();
00705     }
00706 #endif
00707 }
00708 
00709 void Sound::updateOutput() {
00710 #if(NUM_CHANNELS > 0)
00711     uint32_t output = 0;
00712 
00713     //CHANNEL 0
00714     if (_chanState[0]) {
00715         output += _chanOutput[0];
00716     }
00717 
00718     //CHANNEL 1
00719     #if (NUM_CHANNELS > 1)
00720     if (_chanState[1]) {
00721         output += _chanOutput[1];
00722     }
00723     #endif
00724 
00725     //CHANNEL 2
00726     #if (NUM_CHANNELS > 2)
00727     if (_chanState[2]) {
00728         output += _chanOutput[2];
00729     }
00730     #endif
00731 
00732     //CHANNEL 3
00733     #if (NUM_CHANNELS > 3)
00734     if (_chanState[3]) {
00735         output += _chanOutput[3];
00736     }
00737     #endif
00738 
00739     #ifndef POK_SIM
00740     #if POK_ENABLE_SOUND
00741     /** HARDWARE **/
00742 
00743         #if POK_STREAMING_MUSIC
00744             if (streamstep) {
00745                 //pwmout_write(&audiopwm,(float)(sbyte>>headPhoneLevel)/(float)255);
00746                 sbyte *= discrete_vol_multipliers[discrete_vol];
00747                 sbyte >>= 8;
00748                 pwmout_write(&audiopwm,(float)(sbyte)/(float)255);
00749             }
00750         #endif
00751             output *= discrete_vol_multipliers[discrete_vol];
00752             output >>= 8;
00753             dac_write((uint8_t)output); //direct hardware mixing baby !
00754     soundbyte = output;
00755     #endif //POK_ENABLE_SOUND
00756     #else
00757     /** SIMULATOR **/
00758         #if POK_STREAMING_MUSIC
00759             if (streamstep) {
00760                 uint16_t o = output + sbyte;
00761                 output = (o/2);//>>headPhoneLevel;
00762             }
00763         #endif
00764         soundbyte = output;//<<headPhoneLevel;
00765     #endif // POK_SIM
00766 #endif
00767 }
00768 
00769 void Sound::setPatternLooping(bool loop, uint8_t channel) {
00770 #if(NUM_CHANNELS > 0)
00771     if(channel>=NUM_CHANNELS)
00772         return;
00773     patternLooping[channel] = loop;
00774 #endif
00775 }
00776 
00777 void Sound::playOK(){
00778     #if POK_GBSOUND
00779 #if(NUM_CHANNELS > 0)
00780     playPattern(playOKPattern,0);
00781 #endif
00782 #endif // POK_GBSOUND
00783 }
00784 
00785 void Sound::playCancel(){
00786 #if POK_GBSOUND
00787 #if(NUM_CHANNELS > 0)
00788     playPattern(playCancelPattern,0);
00789 #endif
00790 #endif
00791 }
00792 
00793 void Sound::playTick(){
00794 #if POK_GBSOUND
00795 #if(NUM_CHANNELS > 0)
00796     playPattern(playTickP,0);
00797 #endif
00798 #endif // POK_GBSOUND
00799 }
00800 
00801 void Sound::setVolume(int16_t volume) {
00802 //#if NUM_CHANNELS > 0
00803     if (volume<0) volume = 0;
00804     //if (volume>volumeMax) volume = volumeMax;
00805     globalVolume = volume;
00806     #if POK_ENABLE_SOUND > 0
00807     discrete_vol = (volume>>5);
00808     #ifndef POK_SIM
00809     setHWvolume(discrete_vol_hw_levels[discrete_vol]); //boost volume if headphonelevel
00810     #endif
00811     #endif
00812     #if POK_SHOW_VOLUME > 0
00813     _soundc.volbar_visible = VOLUMEBAR_TIMEOUT;
00814     #endif
00815 //#endif
00816 }
00817 
00818 uint16_t Sound::getVolume() {
00819 //#if NUM_CHANNELS > 0
00820     return globalVolume;
00821 //#else
00822 //  return 0;
00823 //#endif
00824 }
00825 
00826 void Sound::setVolume(int8_t volume, uint8_t channel) {
00827 #if(NUM_CHANNELS > 0)
00828     if(channel>=NUM_CHANNELS)
00829         return;
00830     volume = (volume > VOLUME_CHANNEL_MAX) ? VOLUME_CHANNEL_MAX : volume;
00831     volume = (volume < 0) ? 0 : volume;
00832     chanVolumes[channel] = volume;
00833 #endif
00834 }
00835 
00836 uint8_t Sound::getVolume(uint8_t channel) {
00837 #if(NUM_CHANNELS > 0)
00838     if(channel>=NUM_CHANNELS)
00839         return 255;
00840     return (chanVolumes[channel]);
00841 #else
00842     return 0;
00843 #endif
00844 }
00845 
00846 void Sound::playTone(uint8_t os, int frq, uint8_t amp, uint8_t wav,uint8_t arpmode)
00847 {
00848     if (wav>5) wav=0;
00849     if (arpmode>MAX_ARPMODE) arpmode=MAX_ARPMODE;
00850     if (os==1) setOSC(&osc1,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
00851     else if (os==2) setOSC(&osc2,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
00852     else if (os==3) setOSC(&osc3,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
00853 }
00854 
00855 void Sound::playTone(uint8_t os, uint16_t frq, uint8_t volume, uint32_t duration)
00856 {
00857     if (os==1) setOSC(&osc1,1,WSQUARE,frq,volume,duration);
00858     else if (os==2) setOSC(&osc2,1,WTRI,frq,volume,duration);
00859     else if (os==3) setOSC(&osc3,1,WTRI,frq,volume,duration);
00860 }
00861 
00862 uint8_t Sound::ampIsOn()
00863 {
00864     #ifdef POK_SIM
00865     return core.ampIsOn();
00866     #else
00867     #if POK_ENABLE_SOUND > 0
00868     return Pokitto::ampIsOn();
00869     #endif
00870     #endif // POK_SIM
00871     return 0;
00872 }
00873 
00874 void Sound::ampEnable(uint8_t v) {
00875     #ifdef POK_SIM
00876     core.ampEnable(v);
00877     #else
00878     #if POK_ENABLE_SOUND > 0
00879     Pokitto::ampEnable(v);
00880     #endif
00881     #endif // POK_SIM
00882 
00883 }
00884 
00885 int Sound::playMusicStream(char* filename)
00886 {
00887     return playMusicStream(filename,FILE_MODE_READONLY | FILE_MODE_BINARY);
00888 }
00889 
00890 int Sound::playMusicStream()
00891 {
00892     #if POK_STREAMING_MUSIC >0
00893     if (currentPtr) {
00894             pokPlayStream();
00895             return 1;
00896     } else return 0; //no stream
00897     #endif // POK_STREAMING_MUSIC
00898     return 0;
00899 }
00900 
00901 void Sound::pauseMusicStream() {
00902     #if POK_ENABLE_SOUND > 0
00903     pokPauseStream();
00904     #endif
00905 }
00906 
00907 int Sound::playMusicStream(char* filename, uint8_t options)
00908 {
00909     #if POK_STREAMING_MUSIC
00910         uint8_t result;
00911         result = pokInitSD();
00912         if (!isThisFileOpen(filename)) {
00913             fileClose(); // close any open files
00914             result = fileOpen(filename,FILE_MODE_READONLY | FILE_MODE_BINARY);
00915         }
00916 
00917         if (result) {
00918                 currentPtr = 0; // mark that no stream is available
00919                 return 0; // opening music file failed
00920         }
00921 
00922         fileReadBytes(&buffers[0][0],BUFFER_SIZE);
00923         fileReadBytes(&buffers[1][0],BUFFER_SIZE);
00924         fileReadBytes(&buffers[2][0],BUFFER_SIZE);
00925         fileReadBytes(&buffers[3][0],BUFFER_SIZE);
00926         currentBuffer = 0;
00927         currentPtr = buffers[currentBuffer];
00928         endPtr = currentPtr + BUFFER_SIZE;
00929 
00930         //streaming = STR_PLAYING|options;
00931 
00932         if (!options) pokPlayStream(); // activate stream
00933     #endif //POK_STREAMING_MUSIC
00934     return 1; // opening music file succeeded
00935 }
00936 
00937 uint32_t Sound::getMusicStreamElapsedSec() {
00938     #if POK_STREAMING_MUSIC
00939     return streamcounter/POK_AUD_FREQ;
00940     #endif
00941     return 0;
00942 }
00943 
00944 uint32_t Sound::getMusicStreamElapsedMilliSec() {
00945     #if POK_STREAMING_MUSIC
00946     return streamcounter/(POK_AUD_FREQ/1000);
00947     #endif
00948     return 0;
00949 }
00950