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

WavePacket.h
1 /*
2 * WavePacket.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
12
13 #ifndef WAVEPACKET_H
14 #define WAVEPACKET_H
15
16 #include <MozziGuts.h>
17 #include <Oscil.h>
18 #include <tables/cos8192_int8.h>
19 #include <mozzi_fixmath.h>
20 #include <Phasor.h>
21 #include <Line.h>
22 #include <meta.h>
23
24
25 enum algorithms {SINGLE,DOUBLE};
26
27 /**
28 Wavepacket synthesis, with two overlapping streams of wave packets. Draws on
29 Miller Puckette's Pure Data example, F14.wave.packet.pd. Each packet is an
30 enveloped grain of a sin (or cos) wave. The frequency of the wave, the width of
31 the envelopes and the rate of release of envelopes are the parameters which can
32 be changed.
33 @tparam ALGORITHM options are SINGLE or DOUBLE, for a single non-overlapping stream of packets or a double, overlapping stream.
34 */
35 template <int8_t ALGORITHM>
36 class WavePacket
37 {
38 public:
39
40 /** Constructor.
41 */
42 WavePacket():AUDIO_STEPS_PER_CONTROL(AUDIO_RATE / CONTROL_RATE)
43 {
44 aCos.setTable(COS8192_DATA);
45 }
46
47
48 /** Set all the parameters for the synthesis.
49 The function is designed so that usable ranges for parameters can come from analog inputs, ie. 0-1023.
50 @param fundamental the rate at which packets are produced.
51 @param bandwidth the width of each packet. A lower value allows more
52 of the centre frequency to be audible, a rounder sound.
53 A higher value produces narrower packets, a more buzzing sound.
54 @param centrefreq the oscillation frequency within each packet.
55 */
56 inline
57 void set(int fundamental, int bandwidth, int centrefreq)
58 {
59 setFundamental(fundamental);
60 setBandwidth(bandwidth);
61 setCentreFreq(centrefreq);
62 }
63
64
65 /** Set the fundamental frequency.
66 The function is designed so that usable ranges for parameters can come from analog inputs, ie. 0-1023.
67 @param fundamental the rate at which packets are produced.
68 */
69 inline
70 void setFundamental(int fundamental)
71 {
72 aPhasor.setFreq(fundamental);
73 invFreq = Q8n24_FIX1 / fundamental;
74 }
75
76
77
78 /** Set the bandwidth.
79 The function is designed so that usable ranges for parameters can come from analog inputs, ie. 0-1023.
80 @param bandwidth the width of each packet. A lower value allows more of the
81 centre frequency to be audible, a rounder sound.
82 A higher value produces narrower packets, a more buzzing sound.
83 */
84 inline
85 void setBandwidth(int bandwidth)
86 {
87 Q15n16 bw = invFreq*bandwidth;
88 bw >>= 9;
89 bw = max(bw, Q15n16_FIX1>>3);
90 aBandwidth.set(bw, AUDIO_STEPS_PER_CONTROL);
91 }
92
93
94
95 /** Set the centre frequency.
96 The function is designed so that usable ranges for parameters can come from analog inputs, ie. 0-1023.
97 @param centrefreq the oscillation frequency within each packet.
98 */
99 inline
100 void setCentreFreq(int centrefreq)
101 {
102 Q15n16 cf = invFreq * centrefreq;
103 cf >>= 3;
104 aCentrefreq.set(cf, AUDIO_STEPS_PER_CONTROL);
105 }
106
107
108 /** Calculate the next synthesised sample.
109 @return a full-scale 16 bit value, which needs to be scaled to suit your sketch. If you're using it straight as the sketch output,
110 then that will be yourThing.next()>>2 for HIFI 14 bit output, or >>8 for STANDARD 8+ bit output.
111 */
112 inline
113 int next()
114 {
115 gcentrefreq = aCentrefreq.next();
116 gbandwidth = aBandwidth.next();
117 int phase1 = aPhasor.next()>>16; // -0.5 to 0.5, 0n15
118 if (ALGORITHM == DOUBLE) {
119 return (signalPath(params1, phase1)+signalPath(params2, phase1+32768))>>1;
120 } else {
121 return signalPath(params1, phase1);
122 }
123 }
124
125
126
127 private:
128 //Q15n16 fundamental; // range 4 to 6271 in pd patch, 13 integer bits
129 Q8n24 invFreq;
130 Q15n16 gcentrefreq; // range 0 to 3068, 12 integer bits
131 Q15n16 gbandwidth; // range 1 to 3068, 12 integer bits
132
133 // Lines to interpolate controls at audio rate
134 Line <Q15n16> aCentrefreq;
135 Line <Q16n16> aBandwidth;
136 Line <Q16n16> aFreq;
137
138 // different sets of params for each audio phase stream
139 struct parameters
140 {
141 int previous_phase;
142 Q15n16 centrefreq;
143 Q23n8 bandwidth;
144 }
145 params1,params2;
146
147 // the number of audio steps the line has to take to reach the next control value
148 const unsigned int AUDIO_STEPS_PER_CONTROL;
149
150 Oscil <COS8192_NUM_CELLS, AUDIO_RATE> aCos;
151 Phasor <AUDIO_RATE> aPhasor;
152
153
154 inline
155 int signalPath(struct parameters &param, int phase) // 25us? * 2
156 {
157 //setPin13High();
158 int index;
159
160 if(phase<param.previous_phase)
161 {
162 param.centrefreq = gcentrefreq>>8;
163 param.bandwidth = Q15n16_to_Q23n8(gbandwidth);
164 }
165 param.previous_phase = phase;
166
167 // oscillation
168 index = (param.centrefreq * phase)>>16;
169 // hack to make peak in middle of packet, otherwise it centres around a zero-crossing..
170 index += COS8192_NUM_CELLS>>1;
171 index &= COS8192_NUM_CELLS-1;
172 int8_t sig1 = aCos.atIndex(index);
173
174 // packet envelope
175 Q23n8 bwphase = (param.bandwidth * phase)>>8;
176 bwphase += COS8192_NUM_CELLS>>1;
177 index = constrain(bwphase, 0, (COS8192_NUM_CELLS-1));
178 uint8_t packet_width = 128 + aCos.atIndex(index);
179 // if (AUDIO_MODE == HIFI){
180 // return ((int) sig1 * packet_width)>>3; // scaled to fit HIFI updateAudio output
181 // }else{
182 // return ((int) sig1 * packet_width)>>8; // scaled to fit STANDARD updateAudio output
183 // }
184
185 return ((int) sig1 * packet_width);
186 }
187
188 };
189
190 /** @example 06.Synthesis/WavePacket/WavePacket.ino
191 This is an example of how to use the WavePacket class.
192 */
193
194 #endif // #ifndef WAVEPACKET_H
WavePacket::setCentreFreq
void setCentreFreq(int centrefreq)
Set the centre frequency.
Definition: WavePacket.h:100
WavePacket::next
int next()
Calculate the next synthesised sample.
Definition: WavePacket.h:113
Q15n16
int32_t Q15n16
signed fractional number using 15 integer bits and 16 fractional bits, represents -32767...
Definition: mozzi_fixmath.h:40
WavePacket::WavePacket
WavePacket()
Constructor.
Definition: WavePacket.h:42
Oscil
Oscil plays a wavetable, cycling through the table to generate an audio or control signal...
Definition: Oscil.h:62
WavePacket::set
void set(int fundamental, int bandwidth, int centrefreq)
Set all the parameters for the synthesis.
Definition: WavePacket.h:57
WavePacket::setFundamental
void setFundamental(int fundamental)
Set the fundamental frequency.
Definition: WavePacket.h:70
AUDIO_RATE
#define AUDIO_RATE
Holds the audio rate setting.
Definition: mozzi_config.h:62
Line
For linear changes with a minimum of calculation at each step.
Definition: Line.h:37
Q15n16_FIX1
#define Q15n16_FIX1
1 in Q15n16 format
Definition: mozzi_fixmath.h:63
WavePacket::setBandwidth
void setBandwidth(int bandwidth)
Set the bandwidth.
Definition: WavePacket.h:85
WavePacket
Wavepacket synthesis, with two overlapping streams of wave packets.
Definition: WavePacket.h:36
Q16n16
uint32_t Q16n16
unsigned fractional number using 16 integer bits and 16 fractional bits, represents 0 to 65535...
Definition: mozzi_fixmath.h:46
Q8n24
uint32_t Q8n24
signed fractional number using 8 integer bits and 24 fractional bits, represents 0 to 255...
Definition: mozzi_fixmath.h:44
Q8n24_FIX1
#define Q8n24_FIX1
1 in Q8n24 format
Definition: mozzi_fixmath.h:64
Phasor
Phasor repeatedly generates a high resolution ramp at a variable frequency.
Definition: Phasor.h:32
Q23n8
int32_t Q23n8
signed fractional number using 23 integer bits and 8 fractional bits, represents -8388607.996 to 8388607.996
Definition: mozzi_fixmath.h:39