![]() |
Mozzi
alpha 0.01.1t
sound synthesis library for Arduino
|
00001 /* 00002 * Sample.h 00003 * 00004 * Oscil.h owes much to AF_precision_synthesis.pde, 2009, Adrian Freed. 00005 * 00006 * Copyright 2012 Tim Barrass, 2009 Adrian Freed. 00007 * 00008 * This file is part of Mozzi. 00009 * 00010 * Mozzi is free software: you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation, either version 3 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * Mozzi is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with Mozzi. If not, see <http://www.gnu.org/licenses/>. 00022 * 00023 */ 00024 00025 #ifndef SAMPLE_H_ 00026 #define SAMPLE_H_ 00027 00028 #include "Arduino.h" 00029 #include "MozziGuts.h" 00030 #include "fixedMath.h" 00031 #include <util/atomic.h> 00032 00033 00034 // fractional bits for sample index precision 00035 #define SAMPLE_F_BITS 16 00036 #define SAMPLE_F_BITS_AS_MULTIPLIER 65536 00037 00038 // phmod_proportion is an 1n15 fixed-point number only using 00039 // the fractional part and the sign bit 00040 #define SAMPLE_PHMOD_BITS 16 00041 00042 00061 template <unsigned int NUM_TABLE_CELLS, unsigned int UPDATE_RATE> 00062 class Sample 00063 { 00064 00065 public: 00066 00073 Sample(const char * TABLE_NAME):table(TABLE_NAME) 00074 { 00075 setLoopingOff(); 00076 rangeWholeSample(); 00077 } 00078 00079 00080 00085 Sample() 00086 { 00087 setLoopingOff(); 00088 rangeWholeSample(); 00089 } 00090 00091 00095 inline 00096 void setTable(const char * TABLE_NAME) 00097 { 00098 table = TABLE_NAME; 00099 } 00100 00101 00105 inline 00106 void setStart(unsigned int start) 00107 { 00108 startpos_fractional = (unsigned long) start << SAMPLE_F_BITS; 00109 } 00110 00111 00114 inline 00115 void start() 00116 { 00117 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00118 { 00119 phase_fractional = startpos_fractional; 00120 } 00121 } 00122 00123 00127 inline 00128 void start(unsigned int startpos) 00129 { 00130 setStart(startpos); 00131 start(); 00132 } 00133 00134 00138 inline 00139 void setEnd(unsigned int end) 00140 { 00141 endpos_fractional = (unsigned long) end << SAMPLE_F_BITS; 00142 } 00143 00144 00147 inline 00148 void rangeWholeSample() 00149 { 00150 endpos_fractional = 0; 00151 endpos_fractional = (unsigned long) NUM_TABLE_CELLS << SAMPLE_F_BITS; 00152 } 00153 00154 00157 inline 00158 void setLoopingOn() 00159 { 00160 looping=true; 00161 } 00162 00163 00166 inline 00167 void setLoopingOff() 00168 { 00169 looping=false; 00170 } 00171 00172 00180 inline 00181 char next() // 4us 00182 { 00183 char out = 0; 00184 if (!looping) 00185 { 00186 if (phase_fractional<endpos_fractional){ 00187 out = (char)pgm_read_byte_near(table + (phase_fractional >> SAMPLE_F_BITS)); 00188 incrementPhase(); 00189 } 00190 } 00191 else 00192 { 00193 if (phase_fractional>endpos_fractional) 00194 phase_fractional = startpos_fractional + (phase_fractional - endpos_fractional); 00195 00196 out = (char)pgm_read_byte_near(table + (phase_fractional >> SAMPLE_F_BITS)); 00197 incrementPhase(); 00198 } 00199 return out; 00200 } 00201 00202 00203 // Not readjusted for arbitrary table length yet 00204 // 00205 // /** Returns the next sample given a phase modulation value. 00206 // @param a phase modulation value given as a proportion of the wave. The 00207 // phmod_proportion parameter is a Q15n16 fixed-point number where to fractional 00208 // n16 part represents -1 to 1, modulating the phase by one whole table length in 00209 // each direction. 00210 // @return a sample from the table. 00211 // */ 00212 // inline 00213 // char phMod(long phmod_proportion) 00214 // { 00215 // incrementPhase(); 00216 // return (char)pgm_read_byte_near(table + (((phase_fractional+(phmod_proportion * NUM_TABLE_CELLS))>>SAMPLE_SAMPLE_F_BITS) & (NUM_TABLE_CELLS - 1))); 00217 // } 00218 00219 00220 00228 inline 00229 void setFreq (unsigned int frequency) { 00230 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00231 { 00232 phase_increment_fractional = ((((unsigned long)NUM_TABLE_CELLS<<ADJUST_FOR_NUM_TABLE_CELLS)*frequency)/UPDATE_RATE) << (SAMPLE_F_BITS - ADJUST_FOR_NUM_TABLE_CELLS); 00233 } 00234 } 00235 00236 00242 inline 00243 void setFreq(float frequency) 00244 { // 1 us - using float doesn't seem to incur measurable overhead with the oscilloscope 00245 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00246 { 00247 phase_increment_fractional = (unsigned long)((((float)NUM_TABLE_CELLS * frequency)/UPDATE_RATE) * SAMPLE_F_BITS_AS_MULTIPLIER); 00248 } 00249 } 00250 00251 00260 inline 00261 void setFreq_Q24n8(Q24n8 frequency) 00262 { 00263 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00264 { 00265 //phase_increment_fractional = (frequency* (NUM_TABLE_CELLS>>3)/(UPDATE_RATE>>6)) << (F_BITS-(8-3+6)); 00266 phase_increment_fractional = (((((unsigned long)NUM_TABLE_CELLS<<ADJUST_FOR_NUM_TABLE_CELLS)>>3)*frequency)/(UPDATE_RATE>>6)) 00267 << (SAMPLE_F_BITS - ADJUST_FOR_NUM_TABLE_CELLS - (8-3+6)); 00268 } 00269 } 00270 00271 00277 inline 00278 char atIndex(unsigned int index) 00279 { 00280 return (char)pgm_read_byte_near(table + (index & (NUM_TABLE_CELLS - 1))); 00281 } 00282 00283 00294 inline 00295 unsigned long phaseIncFromFreq(unsigned int frequency) 00296 { 00297 return (((unsigned long)frequency * NUM_TABLE_CELLS)/UPDATE_RATE) << SAMPLE_F_BITS; 00298 } 00299 00300 00304 inline 00305 void setPhaseInc(unsigned long phaseinc_fractional) 00306 { 00307 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00308 { 00309 phase_increment_fractional = phaseinc_fractional; 00310 } 00311 } 00312 00313 00314 private: 00315 00316 00319 static const unsigned char ADJUST_FOR_NUM_TABLE_CELLS = (NUM_TABLE_CELLS<2048) ? 8 : 0; 00320 00321 00324 inline 00325 void incrementPhase() 00326 { 00327 phase_fractional += phase_increment_fractional; 00328 } 00329 00330 00331 volatile unsigned long phase_fractional; 00332 volatile unsigned long phase_increment_fractional; 00333 const char * table; 00334 bool looping; 00335 unsigned long startpos_fractional, endpos_fractional; 00336 }; 00337 00338 #endif /* SAMPLE_H_ */