PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 21:03:51 by 1.7.2