1 // Copyright 2012 Olivier Gillet.
2 //
3 // Author: Olivier Gillet (ol.gillet@gmail.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 //
23 // See http://creativecommons.org/licenses/MIT/ for more information.
24 //
25 // -----------------------------------------------------------------------------
26 //
27 // A waveshaper adding waveform impurities, seeded by the serial number of
28 // the MCU.
29 
30 #ifndef BRAIDS_SIGNATURE_WAVESHAPER_H_
31 #define BRAIDS_SIGNATURE_WAVESHAPER_H_
32 
33 #include "stmlib/stmlib.h"
34 #include "stmlib/utils/dsp.h"
35 
36 #include "braids/resources.h"
37 
38 namespace braids {
39 
40 class SignatureWaveshaper {
41  public:
SignatureWaveshaper()42   SignatureWaveshaper() { }
~SignatureWaveshaper()43   ~SignatureWaveshaper() { }
44 
Init(uint32_t seed)45   inline void Init(uint32_t seed) {
46     int32_t skew = seed & 15;
47     seed >>= 4;
48 
49     int32_t sigmoid_strength = seed & 31;
50     seed >>= 5;
51 
52     int32_t bumplets_frequency = seed & 3;
53     seed >>= 2;
54     bumplets_frequency += 3;
55 
56     int32_t bumplets_width = seed & 7;
57     seed >>= 3;
58     bumplets_width += 1;
59     bumplets_width <<= 7;
60     bumplets_width *= bumplets_width;
61 
62     for (int i = 0; i < 256; ++i) {
63       int16_t x = (i - 128) << 8;
64       int16_t x_skew = i * i - 32768;
65       x = stmlib::Mix(x, x_skew, skew << 11);
66 
67       int16_t sigmoid = x * (8192 + (sigmoid_strength << 10)) / \
68           (8192 + (sigmoid_strength * abs(x) >> 5));
69       int16_t bumplets = wav_sine[(i * bumplets_frequency) & 255];
70       uint16_t bumplet_gain = x * x / (bumplets_width) + 16;
71       bumplet_gain = 32768 * 128 / (128 + bumplet_gain);
72       transfer_[i] = stmlib::Mix(sigmoid, bumplets, bumplet_gain);
73     }
74     transfer_[256] = transfer_[255];
75   }
76 
transfer(uint16_t i)77   inline int32_t transfer(uint16_t i) {
78     return transfer_[i];
79   }
80 
Transform(int16_t sample)81   inline int32_t Transform(int16_t sample) {
82     uint16_t i = sample + 32768;
83     int32_t a = transfer_[i >> 8];
84     int32_t b = transfer_[(i >> 8) + 1];
85     return a + ((b - a) * (i & 0xff) >> 8);
86   }
87 
88  private:
89   int32_t transfer_[257];
90 
91   DISALLOW_COPY_AND_ASSIGN(SignatureWaveshaper);
92 };
93 
94 }  // namespace braids
95 
96 #endif // BRAIDS_VCO_JITTER_SOURCE_H_
97