1 // Copyright 2014 Emilie Gillet.
2 //
3 // Author: Emilie Gillet (emilie.o.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
28 #include <cassert>
29 #include <cmath>
30 #include <cstdlib>
31 #include <cstring>
32 #include <vector>
33 #include <xmmintrin.h>
34
35 #include "clouds/dsp/granular_processor.h"
36 #include "clouds/resources.h"
37
38 using namespace clouds;
39 using namespace std;
40 using namespace stmlib;
41
42 const size_t kSampleRate = 32000;
43 const size_t kBlockSize = 32;
44
write_wav_header(FILE * fp,int num_samples,int num_channels)45 void write_wav_header(FILE* fp, int num_samples, int num_channels) {
46 uint32_t l;
47 uint16_t s;
48
49 fwrite("RIFF", 4, 1, fp);
50 l = 36 + num_samples * 2 * num_channels;
51 fwrite(&l, 4, 1, fp);
52 fwrite("WAVE", 4, 1, fp);
53
54 fwrite("fmt ", 4, 1, fp);
55 l = 16;
56 fwrite(&l, 4, 1, fp);
57 s = 1;
58 fwrite(&s, 2, 1, fp);
59 s = num_channels;
60 fwrite(&s, 2, 1, fp);
61 l = kSampleRate;
62 fwrite(&l, 4, 1, fp);
63 l = static_cast<uint32_t>(kSampleRate) * 2 * num_channels;
64 fwrite(&l, 4, 1, fp);
65 s = 2 * num_channels;
66 fwrite(&s, 2, 1, fp);
67 s = 16;
68 fwrite(&s, 2, 1, fp);
69
70 fwrite("data", 4, 1, fp);
71 l = num_samples * 2 * num_channels;
72 fwrite(&l, 4, 1, fp);
73 }
74
TestDSP()75 void TestDSP() {
76 size_t duration = 19;
77
78 FILE* fp_out = fopen("clouds.wav", "wb");
79 FILE* fp_in = fopen("audio_samples/kettel_32k.wav", "rb");
80
81 size_t remaining_samples = kSampleRate * duration;
82 write_wav_header(fp_out, remaining_samples, 2);
83 fseek(fp_in, 48, SEEK_SET);
84
85 uint8_t large_buffer[118784];
86 uint8_t small_buffer[65536 - 128];
87
88 GranularProcessor processor;
89 processor.Init(
90 &large_buffer[0], sizeof(large_buffer),
91 &small_buffer[0],sizeof(small_buffer));
92
93 processor.set_num_channels(2);
94 processor.set_low_fidelity(false);
95 processor.set_playback_mode(PLAYBACK_MODE_LOOPING_DELAY);
96
97 Parameters* p = processor.mutable_parameters();
98
99 size_t block_counter = 0;
100 float phase_ = 0.0f;
101 bool synthetic = true;
102 processor.Prepare();
103 float pot_noise = 0.0f;
104 while (remaining_samples) {
105 uint16_t tri = (remaining_samples * 2);
106 tri = tri > 32767 ? 65535 - tri : tri;
107 float triangle = tri / 32768.0f;
108
109 p->gate = false;
110 p->trigger = false;
111 p->freeze = true && (block_counter & 2047) > 1024;
112 pot_noise += 0.05f * ((Random::GetSample() / 32768.0f) * 0.00f - pot_noise);
113 p->position = triangle * 0.0f + 0.00f;
114 p->size = 0.5f;
115 p->pitch = -7.0f + (triangle > 0.5f ? 1.0f : 0.0f) * 0.0f;
116 p->density = 0.0f;
117 p->texture = 0.5f;
118 p->feedback = 0.0f;
119 p->dry_wet = 1.0f;
120 p->reverb = 0.0f;
121 p->stereo_spread = 0.0f;
122
123 ++block_counter;
124 ShortFrame input[kBlockSize];
125 ShortFrame output[kBlockSize];
126
127 if (synthetic) {
128 for (size_t i = 0; i < kBlockSize; ++i) {
129 phase_ += 400.0f / kSampleRate; // (block_counter & 512 ? 110.0f : 220.0f) / kSampleRate;
130 while (phase_ >= 1.0) {
131 phase_ -= 1.0;
132 }
133 input[i].l = 16384.0f * sinf(phase_ * M_PI * 2);
134 // input[i].r = 32768.0f * (phase_ - 0.5);
135 input[i].r = input[i].l;
136 }
137 remaining_samples -= kBlockSize;
138 } else {
139 if (fread(
140 input,
141 sizeof(ShortFrame),
142 kBlockSize,
143 fp_in) != kBlockSize) {
144 break;
145 }
146 remaining_samples -= kBlockSize;
147 }
148 processor.Process(input, output, kBlockSize);
149 processor.Prepare();
150 fwrite(output, sizeof(ShortFrame), kBlockSize, fp_out);
151 }
152 fclose(fp_out);
153 fclose(fp_in);
154 }
155
TestGrainSize()156 void TestGrainSize() {
157 for (int32_t _p = 0; _p < 3; _p++) {
158 for (int32_t _s = 0; _s < 3; _s++) {
159 for (int32_t _pi = 0; _pi < 3; _pi++) {
160 size_t duration = 19;
161 char name[80];
162 sprintf(name, "clouds_%d%d%d.wav", _p, _s, _pi);
163 FILE* fp_out = fopen(name, "wb");
164 FILE* fp_in = fopen("audio_samples/kettel_32k.wav", "rb");
165
166 size_t remaining_samples = kSampleRate * duration;
167 write_wav_header(fp_out, remaining_samples, 2);
168 fseek(fp_in, 48, SEEK_SET);
169
170 uint8_t large_buffer[118784];
171 uint8_t small_buffer[65536];
172
173 GranularProcessor processor;
174 processor.Init(
175 &large_buffer[0], sizeof(large_buffer),
176 &small_buffer[0],sizeof(small_buffer));
177
178 processor.set_num_channels(2);
179 processor.set_low_fidelity(false);
180 processor.set_playback_mode(PLAYBACK_MODE_GRANULAR);
181
182 Parameters* p = processor.mutable_parameters();
183
184 size_t block_counter = 0;
185 processor.Prepare();
186 while (remaining_samples) {
187 p->trigger = false;
188 p->freeze = (block_counter & 1023) > 512;
189 p->position = _p * 0.5f;
190 p->size = _s * 0.5f;
191 p->pitch = _pi * 24.0f - 24.0f;
192 p->density = 0.75f;
193 p->texture = 0.5f;
194 p->feedback = 0.0f;
195 p->dry_wet = 1.0f;
196 p->reverb = 0.0f;
197 p->stereo_spread = 0.0f;
198
199 ++block_counter;
200 ShortFrame input[kBlockSize];
201 ShortFrame output[kBlockSize];
202
203 uint16_t tri = (remaining_samples / 4);
204 tri = tri > 32767 ? 65535 - tri : tri;
205
206 if (fread(
207 input,
208 sizeof(ShortFrame),
209 kBlockSize,
210 fp_in) != kBlockSize) {
211 break;
212 }
213 remaining_samples -= kBlockSize;
214 processor.Process(input, output, kBlockSize);
215 processor.Prepare();
216 fwrite(output, sizeof(ShortFrame), kBlockSize, fp_out);
217 }
218
219 fclose(fp_out);
220 fclose(fp_in);
221 }
222 }
223 }
224 }
225
main(void)226 int main(void) {
227 _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
228 TestDSP();
229 // TestGrainSize();
230 }
231