| Mozzi version v1.1.0 sound synthesis library for Arduino |

SampleHuffman.h
1 /*
2 * SampleHuffman.h
3 *
4 * Copyright 2013 Tim Barrass.
5 *
6 * This file is part of Mozzi.
7 *
8 * Mozzi is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
9 *
10 */
11 #ifndef SAMPLEHUFFMAN_H
12 #define SAMPLEHUFFMAN_H
13
14 #include "mozzi_pgmspace.h"
15
16 /** A sample player for samples encoded with Huffman compression.
17
18 This class and the audio2huff.py script are adapted from "audioout",
19 an Arduino sketch by Thomas Grill, 2011 http//grrrr.org
20
21 Huffman decoding is used on sample differentials,
22 saving 50-70% of space for 8 bit data, depending on the sample rate.
23
24 This implementation just plays back one sample each time next() is called, with no
25 speed or other adjustments.
26 It's slow, so it's likely you will only be able to play one sound at a time.
27
28 Audio data, Huffman decoder table, sample rate and bit depth are defined
29 in a sounddata.h header file. This file can be generated for a sound file with the
30 accompanying Python script audio2huff.py, in Mozzi/extras/python/
31
32 Invoke with:
33 python audio2huff.py --sndfile=arduinosnd.wav --hdrfile=sounddata.h --bits=8 --name=soundtablename
34
35 You can resample and dither your audio file with SOX,
36 e.g. to 8 bits depth @ Mozzi's 16384 Hz sample rate:
37 sox fullglory.wav -b 8 -r 16384 arduinosnd.wav
38
39 Alternatively you can export a sound from Audacity, which seems to have less noticeable or no dithering,
40 using Project Rate 16384 Hz and these output options:
41 Other uncompressed files, Header: WAV(Microsoft), Encoding: Unsigned 8 bit PCM
42
43 The header file contains two lengthy arrays:
44 One is "SOUNDDATA" which must fit into Flash RAM (available in total: 32k for ATMega328)
45 The other is "HUFFMAN" which must also fit into Flash RAM
46
47 */
48
49 class SampleHuffman
50 {
51
52 public:
53
54 /** Constructor
55 @param SOUNDDATA the name of the SOUNDDATA table in the huffman sample .h file
56 @param HUFFMAN_DATA the name of the HUFFMAN table in the huffman sample .h file
57 @param SOUNDDATA_BITS from the huffman sample .h file
58 */
59 SampleHuffman(uint8_t const * SOUNDDATA, int16_t const * HUFFMAN_DATA, uint32_t const SOUNDDATA_BITS):sounddata(SOUNDDATA),huffman(HUFFMAN_DATA),sounddata_bits(SOUNDDATA_BITS)
60 {
61 setLoopingOff();
62 }
63
64
65 /** Update and return the next audio sample. So far it just plays back one sample at a time without any variable tuning or speed.
66 @return the next audio sample
67 @note timing: about 5 to 40 us, varies continuously depending on data
68 */
69 inline
70 int16_t next()
71 {
72 if(datapos >= sounddata_bits){
73 if(looping){
74 // at end of sample, restart from zero, looping the sound
75 datapos = 0;
76 }else{
77 return 0;
78 }
79 }
80
81 int16_t dif = decode();
82 current += dif; // add differential
83 return current;
84 }
85
86
87 /** Turns looping on, with the whole sample length as the loop range.
88 */
89 inline
90 void setLoopingOn()
91 {
92 looping=true;
93 }
94
95
96 /** Turns looping off.
97 */
98 inline
99 void setLoopingOff()
100 {
101 looping=false;
102 }
103
104 /** Sets the playhead to the beginning of the sample.
105 */
106 inline
107 void start()
108 {
109 current = 0;
110 datapos = 0;
111 bt = 0;
112 }
113
114 private:
115 uint8_t const * sounddata;
116 int16_t const * huffman;
117 uint32_t const sounddata_bits;
118 uint32_t datapos; // current sample position
119 int16_t current; // current amplitude value
120 bool looping;
121 uint8_t bt;
122
123 // Get one bit from sound data
124 inline
125 bool getbit()
126 {
127 const uint8_t b = datapos&7;
128 //static uint8_t bt;
129 if(!b) bt = FLASH_OR_RAM_READ<const uint8_t>(sounddata+((uint32_t)datapos>>3));
130 // extract the indexed bit
131 return ((uint8_t)bt>>(7-b))&1;
132 }
133
134
135 // Decode bit stream using Huffman codes
136 inline
137 int16_t decode()
138 {
139 int16_t const * huffcode = huffman;
140 do {
141 if(getbit()) {
142 const int16_t offs = FLASH_OR_RAM_READ<const int16_t>(huffcode);
143 huffcode += offs?offs+1:2;
144 }
145 datapos++;
146 }
147 while(FLASH_OR_RAM_READ<const int16_t>(huffcode++));
148 return FLASH_OR_RAM_READ<const int16_t>(huffcode);
149 }
150
151
152 };
153
154 /**
155 @example 08.Samples/SampleHuffman_Umpah/SampleHuffman_Umpah.ino
156 This example demonstrates the Sample class.
157 */
158
159 #endif // #ifndef SAMPLEHUFFMAN_H
SampleHuffman::setLoopingOn
void setLoopingOn()
Turns looping on, with the whole sample length as the loop range.
Definition: SampleHuffman.h:90
SampleHuffman::SampleHuffman
SampleHuffman(uint8_t const *SOUNDDATA, int16_t const *HUFFMAN_DATA, uint32_t const SOUNDDATA_BITS)
Constructor.
Definition: SampleHuffman.h:59
SampleHuffman::start
void start()
Sets the playhead to the beginning of the sample.
Definition: SampleHuffman.h:107
SampleHuffman::setLoopingOff
void setLoopingOff()
Turns looping off.
Definition: SampleHuffman.h:99
SampleHuffman::next
int16_t next()
Update and return the next audio sample.
Definition: SampleHuffman.h:70