Mozzi  alpha 0.01.1m
sound synthesis library for Arduino
 All Classes Functions
tables/SampleCompressed.h
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_ */