1 // Copyright 2013 Emilie Gillet.
2 //
3 // Author: Emilie Gillet (emilie.o.gillet@gmail.com)
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 
16 #include <cmath>
17 #include <cstdio>
18 #include <cstring>
19 #include <cstdlib>
20 
21 #include "tides/generator.h"
22 
23 using namespace tides;
24 using namespace stmlib;
25 
26 const uint32_t kSampleRate = 48000;
27 
28 struct StereoSample {
29   uint16_t l, r;
30 
StereoSampleStereoSample31   StereoSample(const GeneratorSample& s) {
32     l = (s.unipolar >> 1);
33     r = s.bipolar;
34   }
35 };
36 
37 struct TriggerPair {
38   uint16_t l, r;
39 
TriggerPairTriggerPair40   TriggerPair(const GeneratorSample& s) {
41     l = (s.flags & FLAG_END_OF_ATTACK) ? 32767 : 0;
42     r = (s.flags & FLAG_END_OF_RELEASE) ? 32767 : 0;
43   }
44 };
45 
write_wav_header(FILE * fp,int num_samples,int num_channels)46 void write_wav_header(FILE* fp, int num_samples, int num_channels) {
47   uint32_t l;
48   uint16_t s;
49 
50   fwrite("RIFF", 4, 1, fp);
51   l = 36 + num_samples * 2 * num_channels;
52   fwrite(&l, 4, 1, fp);
53   fwrite("WAVE", 4, 1, fp);
54 
55   fwrite("fmt ", 4, 1, fp);
56   l = 16;
57   fwrite(&l, 4, 1, fp);
58   s = 1;
59   fwrite(&s, 2, 1, fp);
60   s = num_channels;
61   fwrite(&s, 2, 1, fp);
62   l = kSampleRate;
63   fwrite(&l, 4, 1, fp);
64   l = static_cast<uint32_t>(kSampleRate) * 2 * num_channels;
65   fwrite(&l, 4, 1, fp);
66   s = 2 * num_channels;
67   fwrite(&s, 2, 1, fp);
68   s = 16;
69   fwrite(&s, 2, 1, fp);
70 
71   fwrite("data", 4, 1, fp);
72   l = num_samples * 2 * num_channels;
73   fwrite(&l, 4, 1, fp);
74 }
75 
76 
main(void)77 int main(void) {
78   FILE* fp = fopen("lfo.wav", "wb");
79   write_wav_header(fp, kSampleRate * 10, 2);
80 
81   /*for (uint16_t i = 0; i < 128; ++i) {
82     for (uint16_t j = 0; j < 128; ++j) {
83       Generator g;
84       g.Init();
85       g.set_range(GENERATOR_RANGE_HIGH);
86       g.set_mode(GENERATOR_MODE_LOOPING);
87       g.set_pitch(60 << 7);
88       g.set_slope((j - 64) * 512);
89       int32_t min = 0;
90       int32_t max = 0;
91       for (uint32_t k = 0; k < kSampleRate; ++k) {
92         GeneratorSample s = g.Process(0);
93         g.FillBufferSafe();
94         if (s.bipolar < min) {
95           min = s.bipolar;
96         } else if (s.bipolar > max) {
97           max = s.bipolar;
98         }
99       }
100       printf("%d\t%d\t%d\t%d\n", (i << 7), (j - 64) * 512, min, max);
101     }
102   }*/
103 
104   Generator g;
105   g.Init();
106   g.set_range(GENERATOR_RANGE_HIGH);
107   g.set_mode(GENERATOR_MODE_AR);
108   g.set_slope(-32768);
109   g.set_shape(0);
110   g.set_smoothness(0);
111   g.set_sync(false);
112 
113   // uint16_t period_pattern[] = { 400, 400, 200, 800 };
114   // uint16_t step = 0;
115   uint32_t counter = 0;
116   // uint16_t period = period_pattern[step];
117   uint32_t period = 512;
118   for (uint32_t i = 0; i < kSampleRate * 10; ++i) {
119     ++counter;
120     uint8_t control = 0;
121     if (counter >= period) {
122       // step = (step + 1) % (sizeof(period_pattern) / sizeof(uint16_t));
123       // period = period_pattern[step];
124       // control |= CONTROL_CLOCK_RISING;
125       control |= CONTROL_GATE_RISING;
126       counter = 0;
127       //period = (rand() % 1024) + 2;
128     }
129     if (counter <= period / 4) {
130       control |= CONTROL_GATE;
131     }
132     /*uint32_t pitch = (24 << 7) + (i >> 5);
133     if (pitch > (115 << 7)) {
134       pitch = 115 << 7;
135     }*/
136     uint16_t tri = (i * 100);
137     tri = tri > 32767 ? 65535 - tri : tri;
138     //g.set_slope(tri);
139     g.set_pitch((48 << 7));
140     // StereoSample s = StereoSample(g.Process(control * 0));
141     TriggerPair s = TriggerPair(g.Process(control));
142     fwrite(&s, sizeof(s), 1, fp);
143     g.FillBufferSafe();
144   }
145 }
146