1 // Copyright 2015 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 // Sequence of random values.
28 
29 #ifndef MARBLES_RANDOM_RANDOM_SEQUENCE_H_
30 #define MARBLES_RANDOM_RANDOM_SEQUENCE_H_
31 
32 #include "stmlib/stmlib.h"
33 
34 #include "marbles/random/random_stream.h"
35 
36 #include <algorithm>
37 
38 namespace marbles {
39 
40 const int kDejaVuBufferSize = 16;
41 const int kHistoryBufferSize = 16;
42 
43 const float kMaxUint32 = 4294967296.0f;
44 
45 class RandomSequence {
46  public:
RandomSequence()47   RandomSequence() { }
~RandomSequence()48   ~RandomSequence() { }
49 
Init(RandomStream * random_stream)50   inline void Init(RandomStream* random_stream) {
51     random_stream_ = random_stream;
52     for (int i = 0; i < kDejaVuBufferSize; ++i) {
53       loop_[i] = random_stream_->GetFloat();
54     }
55     std::fill(&history_[0], &history_[kHistoryBufferSize], 0.0f);
56 
57     loop_write_head_ = 0;
58     length_ = 8;
59     step_ = 0;
60 
61     record_head_ = 0;
62     replay_head_ = -1;
63     replay_start_ = 0;
64     deja_vu_ = 0.0f;
65     replay_hash_ = replay_shift_ = 0;
66 
67     redo_read_ptr_ = &loop_[0];
68     redo_write_ptr_ = NULL;
69     redo_write_history_ptr_ = NULL;
70   }
71 
Clone(const RandomSequence & source)72   inline void Clone(const RandomSequence& source) {
73     random_stream_ = source.random_stream_;
74 
75     std::copy(
76         &source.loop_[0],
77         &source.loop_[kDejaVuBufferSize],
78         &loop_[0]);
79     std::copy(
80         &source.history_[0],
81         &source.history_[kHistoryBufferSize],
82         &history_[0]);
83 
84     loop_write_head_ = source.loop_write_head_;
85     length_ = source.length_;
86     step_ = source.step_;
87 
88     record_head_ = source.record_head_;
89     replay_head_ = source.replay_head_;
90     replay_start_ = source.replay_start_;
91     replay_hash_ = source.replay_hash_;
92     replay_shift_ = source.replay_shift_;
93 
94     deja_vu_ = source.deja_vu_;
95 
96     redo_read_ptr_ = source.redo_read_ptr_
97         ? &loop_[source.redo_read_ptr_ - &source.loop_[0]]
98         : NULL;
99     redo_write_ptr_ = source.redo_write_ptr_
100         ? &loop_[source.redo_write_ptr_ - &source.loop_[0]]
101         : NULL;
102     redo_write_history_ptr_ = source.redo_write_history_ptr_
103         ? &history_[source.redo_write_history_ptr_ - &source.history_[0]]
104         : NULL;
105   }
106 
Record()107   inline void Record() {
108     replay_start_ = record_head_;
109     replay_head_ = -1;
110   }
111 
ReplayPseudoRandom(uint32_t hash)112   inline void ReplayPseudoRandom(uint32_t hash) {
113     replay_head_ = replay_start_;
114     replay_hash_ = hash;
115     replay_shift_ = 0;
116   }
117 
ReplayShifted(uint32_t shift)118   inline void ReplayShifted(uint32_t shift) {
119     replay_head_ = replay_start_;
120     replay_hash_ = 0;
121     replay_shift_ = shift;
122   }
123 
GetReplayValue()124   inline float GetReplayValue() const {
125     uint32_t h = (replay_head_ - 1 - replay_shift_ + \
126         2 * kHistoryBufferSize) % kHistoryBufferSize;
127     if (!replay_hash_) {
128       return history_[h];
129     } else {
130       uint32_t word = static_cast<float>(history_[h] * kMaxUint32);
131       word = (word ^ replay_hash_) * 1664525L + 1013904223L;
132       return static_cast<float>(word) / kMaxUint32;
133     }
134   }
135 
RewriteValue(float value)136   inline float RewriteValue(float value) {
137     // RewriteValue(x) returns what the most recent call to NextValue would have
138     // returned if its second argument were x instead. This is used to "rewrite
139     // history" when the module acquires data from an external source (ASR,
140     // randomizer or quantizer mode).
141     if (replay_head_ >= 0) {
142       return GetReplayValue();
143     }
144 
145     if (redo_write_ptr_) {
146       *redo_write_ptr_ = 1.0f + value;
147     }
148     float result = *redo_read_ptr_;
149     if (result >= 1.0f) {
150       result -= 1.0f;
151     } else {
152       result = 0.5f;
153     }
154     if (redo_write_history_ptr_) {
155       *redo_write_history_ptr_ = result;
156     }
157     return result;
158   }
159 
NextValue(bool deterministic,float value)160   inline float NextValue(bool deterministic, float value) {
161     if (replay_head_ >= 0) {
162       replay_head_ = (replay_head_ + 1) % kHistoryBufferSize;
163       return GetReplayValue();
164     }
165 
166     const float p_sqrt = 2.0f * deja_vu_ - 1.0f;
167     const float p = p_sqrt * p_sqrt;
168 
169     if (random_stream_->GetFloat() <= p && deja_vu_ <= 0.5f) {
170       // Generate a new value and put it at the end of the loop.
171       redo_write_ptr_ = &loop_[loop_write_head_];
172       *redo_write_ptr_ = deterministic
173           ? 1.0f + value
174           : random_stream_->GetFloat();
175       loop_write_head_ = (loop_write_head_ + 1) % kDejaVuBufferSize;
176       step_ = length_ - 1;
177     } else {
178       // Do not generate a new value, just replay the loop or jump randomly.
179       // through it.
180       redo_write_ptr_ = NULL;
181       if (random_stream_->GetFloat() <= p) {
182         step_ = static_cast<int>(
183             random_stream_->GetFloat() * static_cast<float>(length_));
184       } else {
185         step_ = step_ + 1;
186         if (step_ >= length_) {
187           step_ = 0;
188         }
189       }
190     }
191     uint32_t i = loop_write_head_ + kDejaVuBufferSize - length_ + step_;
192     redo_read_ptr_ = &loop_[i % kDejaVuBufferSize];
193     float result = *redo_read_ptr_;
194     if (result >= 1.0f) {
195       result -= 1.0f;
196     } else if (deterministic) {
197       // We ask for a deterministic value (shift register), but the loop
198       // contain random values. return 0.5f in this case!
199       result = 0.5f;
200     }
201     redo_write_history_ptr_ = &history_[record_head_];
202     *redo_write_history_ptr_ = result;
203     record_head_ = (record_head_ + 1) % kHistoryBufferSize;
204     return result;
205   }
206 
NextVector(float * destination,size_t size)207   inline void NextVector(float* destination, size_t size) {
208     float seed = NextValue(false, 0.0f);
209     uint32_t word = static_cast<float>(seed * kMaxUint32);
210     while (size--) {
211       *destination++ = static_cast<float>(word) / kMaxUint32;
212       word = word * 1664525L + 1013904223L;
213     }
214   }
215 
set_deja_vu(float deja_vu)216   inline void set_deja_vu(float deja_vu) {
217     deja_vu_ = deja_vu;
218   }
219 
set_length(int length)220   inline void set_length(int length) {
221     if (length < 1 || length > kDejaVuBufferSize) {
222       return;
223     }
224     length_ = length;
225     step_ = step_ % length;
226   }
227 
deja_vu()228   inline float deja_vu() const {
229     return deja_vu_;
230   }
231 
length()232   inline int length() const {
233     return length_;
234   }
235 
236  private:
237   RandomStream* random_stream_;
238   float loop_[kDejaVuBufferSize];
239   float history_[kHistoryBufferSize];
240   int loop_write_head_;
241   int length_;
242   int step_;
243 
244   // Allows to go back in the past and get the same results again from NextValue
245   // calls. Allows the 3 X channels to be locked to the same random loop.
246   int record_head_;
247   int replay_head_;
248   int replay_start_;
249   uint32_t replay_hash_;
250   uint32_t replay_shift_;
251 
252   float deja_vu_;
253 
254   float* redo_read_ptr_;
255   float* redo_write_ptr_;
256   float* redo_write_history_ptr_;
257 
258   DISALLOW_COPY_AND_ASSIGN(RandomSequence);
259 };
260 
261 }  // namespace marbles
262 
263 #endif  // MARBLES_RANDOM_RANDOM_SEQUENCE_H_
264