![]() |
Mozzi
alpha 0.01.1m
sound synthesis library for Arduino
|
00001 /* 00002 * SampleCompressed.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 SAMPLECOMPRESSED_H_ 00026 #define SAMPLECOMPRESSED_H_ 00027 00028 #include "Arduino.h" 00029 #include "MozziGuts.h" 00030 #include <util/atomic.h> 00031 00032 // fractional bits for samplelator index precision 00033 #define SAMPLE_F_BITS 16 00034 #define SAMPLE_F_BITS_AS_MULTIPLIER 65536 00035 00036 // phmod_proportion is an 1n15 fixed-point number only using 00037 // the fractional part and the sign bit 00038 #define SAMPLE_PHMOD_BITS 16 00039 00040 00057 template <unsigned int NUM_TABLE_CELLS, unsigned int UPDATE_RATE> 00058 class SampleCompressed 00059 { 00060 00061 public: 00062 00068 SampleCompressed(const char * TABLE_NAME):table(TABLE_NAME) 00069 {} 00070 00071 00072 00077 SampleCompressed() 00078 {} 00079 00080 00084 void setTable(const char * TABLE_NAME) 00085 { 00086 table = TABLE_NAME; 00087 } 00088 00089 00092 inline 00093 void start() 00094 { 00095 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00096 { 00097 phase_fractional = 0; 00098 } 00099 } 00100 00101 00105 inline 00106 void start(unsigned int offset) 00107 { 00108 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00109 { 00110 phase_fractional = (unsigned long) offset<<SAMPLE_F_BITS; 00111 } 00112 } 00113 00114 00119 inline 00120 char next() 00121 { 00122 char out = 0; 00123 if (phase_fractional < (unsigned long) NUM_TABLE_CELLS<<SAMPLE_F_BITS ) 00124 { 00125 incrementPhase(); 00126 out = readTable(); 00127 } 00128 return out; 00129 } 00130 00131 00139 inline 00140 char phMod(long phmod_proportion) 00141 { 00142 incrementPhase(); 00143 return (char)pgm_read_byte_near(table + (((phase_fractional+(phmod_proportion * NUM_TABLE_CELLS))>>SAMPLE_F_BITS) & (NUM_TABLE_CELLS - 1))); 00144 } 00145 00154 inline 00155 void setFreq_Q24n8(unsigned long frequency) 00156 { 00157 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00158 { 00159 phase_increment_fractional = ((frequency * NUM_TABLE_CELLS)/UPDATE_RATE) << (SAMPLE_F_BITS-8); 00160 } 00161 } 00162 00170 inline 00171 void setFreq(unsigned int frequency) 00172 { 00173 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00174 { 00175 phase_increment_fractional = (((unsigned long)frequency * NUM_TABLE_CELLS)/UPDATE_RATE) << SAMPLE_F_BITS; // Obvious but slow 00176 } 00177 } 00178 00184 inline 00185 void setFreq(float frequency) 00186 { // 1 us - using float doesn't seem to incur measurable overhead with the oscilloscope 00187 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00188 { 00189 phase_increment_fractional = (unsigned long)((((float)NUM_TABLE_CELLS * frequency)/UPDATE_RATE) * SAMPLE_F_BITS_AS_MULTIPLIER); 00190 } 00191 } 00192 00198 inline 00199 char atIndex(unsigned int index) 00200 { 00201 return (char)pgm_read_byte_near(table + (index & (NUM_TABLE_CELLS - 1))); 00202 } 00203 00214 inline 00215 unsigned long phaseIncFromFreq(unsigned int frequency) 00216 { 00217 return (((unsigned long)frequency * NUM_TABLE_CELLS)/UPDATE_RATE) << SAMPLE_F_BITS; 00218 } 00219 00223 inline 00224 void setPhaseInc(unsigned long phaseinc_fractional) 00225 { 00226 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 00227 { 00228 phase_increment_fractional = phaseinc_fractional; 00229 } 00230 } 00231 00232 00233 private: 00234 00237 inline 00238 void incrementPhase() 00239 { 00240 phase_fractional += phase_increment_fractional; 00241 } 00242 00243 // /** Returns the current sample. 00244 // */ 00245 // inline 00246 // char readTable() 00247 // { 00248 // return (char)pgm_read_byte_near(table + ((phase_fractional >> SAMPLE_F_BITS) & (NUM_TABLE_CELLS - 1))); 00249 // } 00250 00251 00252 // from Thomas Grill's audioout sketch 00253 00254 volatile unsigned long datapos = 0; // current sample position 00255 volatile int current = 0; // current amplitude value 00256 00257 // Get one bit from sound data 00258 inline int getbit(unsigned long pos,boolean autoloadonbit0=false) 00259 { 00260 const int b = pos&7; 00261 static unsigned char bt; 00262 if(!autoloadonbit0 || !b) 00263 // read indexed byte from Flash memory 00264 bt = pgm_read_byte(&sounddata[pos>>3]); 00265 // extract the indexed bit 00266 return (bt>>(7-b))&1; 00267 } 00268 00269 // Decode bit stream using Huffman codes 00270 static int decode(unsigned long &pos,int const *huffcode) 00271 { 00272 unsigned long p = pos; 00273 do 00274 { 00275 const int b = getbit(p++,true); 00276 if(b) 00277 { 00278 const int offs = *huffcode; 00279 huffcode += offs?offs+1:2; 00280 } 00281 } 00282 while(*(huffcode++)); 00283 pos = p; 00284 return *huffcode; 00285 } 00286 00287 // This is called at sample rate to load the next sample. 00288 00289 // ISR(TIMER2_COMPA_vect) // changed this 00290 00293 inline 00294 char readTable() 00295 { 00296 unsigned long pos = datapos; 00297 00298 // at end of sample, restart from zero, looping the sound 00299 if(pos >= sounddata_bits) 00300 pos = 0; 00301 00302 int dif = decode(pos,huffman); 00303 current += dif; // add differential 00304 00305 // set 16-bit PWM register with sample value 00306 //OCR1A = constrain(current+(1<<(SAMPLE_BITS-1)),0,(1<<SAMPLE_BITS)-1); 00307 00308 datapos = pos; 00309 00310 // might need to think about sample bit depths... 00311 // the code as is returns an unsigned value, but we want it signed so might have to -128 00312 // ... can the Huffman encoding work with signed sound data? 00313 return constrain(current+(1<<(SAMPLE_BITS-1)),0,(1<<SAMPLE_BITS)-1); 00314 } 00315 00316 00317 unsigned long phase_fractional; 00318 volatile unsigned long phase_increment_fractional; 00319 const char * table; 00320 00321 }; 00322 00323 #endif /* SAMPLECOMPRESSED_H_ */