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

Dependents:   YATTT sd_map_test cPong SnowDemo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Synth_songfuncs.cpp Source File

Synth_songfuncs.cpp

Go to the documentation of this file.
00001 /**************************************************************************/
00002 /*!
00003     @file     Synth_songfuncs.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 #include "PokittoDisk.h "
00038 #include "Synth.h "
00039 #ifdef TRACKER_EXAMPLE
00040 #include "Tracker.h"
00041 #endif // TRACKER
00042 #ifdef POK_SIM
00043 #include "FileIO.h"
00044 #endif
00045 
00046 /** SONG FUNCTIONS **/
00047 
00048 //uint8_t chunk1[CHUNKSIZE], chunk2[CHUNKSIZE]; // 8 rows, 3 channels (columns), 2 bytes per entry
00049 uint8_t chunk[2][CHUNKSIZE]; // 8 rows, 3 channels (columns), 2 bytes per entry
00050 uint8_t cc = 0;
00051 
00052 streamsFunction streamCallbackPtr;
00053 
00054 #if POK_ENABLE_SOUND > 0
00055 
00056 void updatePlaybackSD(uint8_t row) {
00057     // samplespertick determines how long the oscillators are active before they are recalculated (i.e. the next tick
00058     uint8_t i=0;
00059 
00060     if (notetick > samplespertick ) {
00061             // TRACK 1
00062             //if (track1on) i = *song.instrument_stream[0];
00063             i = 0xF;
00064             if (track1on) i = chunk[cc][row+1]>>4;
00065             if (i!=0xF) {
00066                 setOSC(&osc1,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
00067                 chunk[cc][row],patch[i].vol,
00068                 patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
00069                 patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
00070                 }
00071             // TRACK 2
00072             //if (track2on) i = *song.instrument_stream[1];
00073             i = 0xF;
00074             if (track2on) i = chunk[cc][row+3]>>4;
00075             if (i!=0xF) {
00076                 setOSC(&osc2,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
00077                 chunk[cc][row+2],patch[i].vol,
00078                 patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
00079                 patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
00080                 }
00081             // TRACK 3
00082             i = 0xF;
00083             if (track3on) i = chunk[cc][row+5]>>4;
00084             if (i!=0xF) {
00085                 setOSC(&osc3,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
00086                 chunk[cc][row]+4,patch[i].vol,
00087                 patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
00088                 patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
00089                 }
00090             playerpos++;
00091             if (playerpos == PATTERNLENGTH) {
00092                     // move to next song position
00093                     playerpos = 0;
00094                     /*sequencepos++;
00095                     if (sequencepos > song.song_end) {
00096                         if (song.song_loop == -1) {
00097                             emptyOscillators();
00098                             playing = false;
00099                             sequencepos--;
00100                         } else {
00101                             sequencepos = song.song_loop;
00102                         }
00103                     }
00104                     playerpos = 0;
00105                     initStreams(sequencepos);
00106                     tableRefresh=true;*/
00107             }
00108             notetick =0;
00109             }
00110 }
00111 
00112 void updatePlayback() {
00113     // samplespertick determines how long the oscillators are active before they are recalculated (i.e. the next tick
00114     uint8_t i=0;
00115 
00116     if (notetick > samplespertick ) {
00117             // TRACK 1
00118             if (track1on) i = *song.instrument_stream[0];
00119             else i = 0;
00120             if (i) {
00121                 setOSC(&osc1,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
00122                 *song.note_stream[0],patch[i].vol,
00123                 patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
00124                 patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
00125                 }
00126             // TRACK 2
00127             if (track2on) i = *song.instrument_stream[1];
00128             else i = 0;
00129             if (i) {
00130                 setOSC(&osc2,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
00131                 *song.note_stream[1],patch[i].vol,
00132                 patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
00133                 patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
00134                 }
00135             // TRACK 3
00136             if (track3on) i = *song.instrument_stream[2];
00137             else i = 0;
00138             if (i) {
00139                 setOSC(&osc3,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
00140                 *song.note_stream[2],patch[i].vol,
00141                 patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
00142                 patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
00143                 }
00144             playerpos++;
00145             song.instrument_stream[0]++;
00146             song.note_stream[0]++;
00147             song.instrument_stream[1]++;
00148             song.note_stream[1]++;
00149             song.instrument_stream[2]++;
00150             song.note_stream[2]++;
00151             if (playerpos == PATTERNLENGTH) {
00152                     // move to next song position
00153                     sequencepos++;
00154                     if (sequencepos > song.song_end) {
00155                         if (song.song_loop == -1) {
00156                             emptyOscillators();
00157                             playing = false;
00158                             sequencepos--;
00159                         } else {
00160                             sequencepos = song.song_loop;
00161                         }
00162                     }
00163                     playerpos = 0;
00164                     #ifdef TRACKER_EXAMPLE
00165                     tracker.initStreams();
00166                     #else
00167                     initStreams(sequencepos);
00168                     #endif // TRACKER_EXAMPLE
00169                     //(*streamCallbackPtr)();
00170                     tableRefresh=true;
00171             }
00172             notetick =0;
00173             }
00174 }
00175 
00176 void emptyPatches(){
00177     for (int i=0; i<16; i++) {
00178     patch[i].vol = 127;
00179     patch[i].on = true; patch[i].wave = 1; patch[i].echo = 0; patch[i].count = 0; patch[i].cinc =0;
00180     patch[i].attack = 0; patch[i].loop = 0; patch[i].adsrphase = 0; patch[i].adsr = 0; patch[i].decay = 20;
00181     patch[i].pitchbend = 0; patch[i].bendrate = 0; patch[i].maxbend = 0; patch[i].sustain = 0; patch[i].release = 0, patch[i].overdrive = 0, patch[i].kick = 0;
00182     }
00183 }
00184 
00185 void emptyBlocks(){
00186     for (int i=0; i<MAXBLOCKS; i++) {
00187             for (int j = 0; j < PATTERNLENGTH; j++) {
00188                     block[i].instrument[j] = 0;
00189                     block[i].notenumber[j] = 255;
00190             }
00191     }
00192 }
00193 
00194 void initStreams(uint8_t seqpos){
00195     uint8_t blocknum;
00196     // retarget pointers for track 1
00197     // byte = pgm_read_byte(&(mydata[i][j]));
00198     blocknum=song.block_sequence[0][seqpos];
00199     //blocknum=pgm_read_byte(Song+SONG_SEQUENCE+seqpos);
00200     song.instrument_stream[0]=&block[blocknum].instrument[0];
00201     song.note_stream[0]=&block[blocknum].notenumber[0];
00202     // retarget pointers for track 2
00203     blocknum=song.block_sequence[1][seqpos];
00204     song.instrument_stream[1]=&block[blocknum].instrument[0];
00205     song.note_stream[1]=&block[blocknum].notenumber[0];
00206     // retarget pointers for track 3
00207     blocknum=song.block_sequence[2][seqpos];
00208     song.instrument_stream[2]=&block[blocknum].instrument[0];
00209     song.note_stream[2]=&block[blocknum].notenumber[0];
00210 }
00211 
00212 void emptySong(){
00213     song.num_channels = 3;
00214     song.num_patches = 1;
00215     song.song_bpm = 120;
00216     song.num_patterns = 1;
00217     song.song_end = 0;
00218     song.song_loop = 0; // loop back to start
00219     song.rb_version = RBTRACKER_VERSION;
00220     for (uint8_t i = 0; i<10; i++) {
00221         song.block_sequence[0][i]=i*3; // track 1
00222         song.block_sequence[1][i]=i*3+1; // track 2
00223         song.block_sequence[2][i]=i*3+2; // track 3
00224     }
00225     song.instrument_stream[0] = &block[0].instrument[0];
00226     song.note_stream[0] = &block[0].notenumber[0];
00227     song.instrument_stream[1] = &block[1].instrument[0];
00228     song.note_stream[1] = &block[1].notenumber[0];
00229     song.instrument_stream[2] = &block[2].instrument[0];
00230     song.note_stream[2] = &block[2].notenumber[0];
00231     sequencepos = 0;
00232 }
00233 
00234 #if POK_ENABLE_SD > 0
00235 
00236 int openSongFromSD(char* buffer) {
00237     if (!isThisFileOpen(buffer)) {
00238         fileClose(); // close any open files
00239         fileOpen(buffer,FILE_MODE_OVERWRITE | FILE_MODE_BINARY);
00240     }
00241     return isThisFileOpen(buffer);
00242 }
00243 
00244 void writeChunkToSD(uint8_t* buffer) {
00245     if (fileOK()) {
00246         fileWriteBytes(buffer, CHUNKSIZE);
00247     }
00248 }
00249 
00250 void readChunkFromSD(uint8_t* buffer) {
00251     if (fileOK()) {
00252         fileReadBytes(buffer, CHUNKSIZE);
00253     }
00254 }
00255 
00256 #endif // POK_ENABLE_SD
00257 
00258 void registerStreamsCallback(streamsFunction ptr) {
00259     streamCallbackPtr = ptr;
00260 }
00261 
00262 #endif // POK_ENABLE_SOUND
00263 
00264