1 // Copyright 2014 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 
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 = 15;
77 
78   FILE* fp_in = fopen("audio_samples/sine.wav", "rb");
79   FILE* fp_out = fopen("clouds.wav", "wb");
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_GRANULAR);
96 
97   Parameters* p = processor.mutable_parameters();
98 
99   size_t block_counter = 0;
100   float phase_ = 0.0f;
101   bool synthetic = false;
102   processor.Prepare();
103   float pot_noise = 0.0f;
104   while (remaining_samples) {
105     // uint16_t tri = (remaining_samples * 0.4);
106     // tri = tri > 32767 ? 65535 - tri : tri;
107     // float triangle = tri / 32768.0f;
108 
109     p->gate = false;
110     p->trigger = false;// || (block_counter & 2047) > 1024;
111     p->freeze = false; // || (block_counter & 2047) > 1024;
112     p->granular.reverse = true;
113     pot_noise += 0.05f * ((Random::GetSample() / 32768.0f) * 0.05f - pot_noise);
114     p->position = Random::GetFloat();//triangle * 0.0f + 0.5f;
115     p->size = Random::GetFloat();//0.99f;
116     p->pitch = Random::GetFloat() * 24.0f; //0.0f + (triangle > 0.5f ? 1.0f : 0.0f) * 0.0f;
117     p->density = 0.99f;
118     p->texture = 0.7f;
119     p->dry_wet = 1.0f;
120     p->stereo_spread = 0.0f;
121     p->feedback = 0.0f;
122     p->reverb = 0.0f;
123 
124     ++block_counter;
125     ShortFrame input[kBlockSize];
126     ShortFrame output[kBlockSize];
127 
128     if (synthetic) {
129       for (size_t i = 0; i < kBlockSize; ++i) {
130         phase_ += 400.0f / kSampleRate; // (block_counter & 512 ? 110.0f : 220.0f) / kSampleRate;
131         while (phase_ >= 1.0) {
132           phase_ -= 1.0;
133         }
134         input[i].l = 16384.0f * sinf(phase_ * M_PI * 2);
135         input[i].r = 32768.0f * (phase_ - 0.5);
136         // input[i].r = input[i].l = 0;
137       }
138       remaining_samples -= kBlockSize;
139     } else {
140       if (fread(
141               input,
142               sizeof(ShortFrame),
143               kBlockSize,
144               fp_in) != kBlockSize) {
145         break;
146       }
147       remaining_samples -= kBlockSize;
148     }
149     processor.Process(input, output, kBlockSize);
150     processor.Prepare();
151     fwrite(output, sizeof(ShortFrame), kBlockSize, fp_out);
152   }
153   fclose(fp_out);
154   fclose(fp_in);
155 }
156 
main(void)157 int main(void) {
158   _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
159   TestDSP();
160   // TestGrainSize();
161 }
162