1 // samplv1_sample.h 2 // 3 /**************************************************************************** 4 Copyright (C) 2012-2021, rncbc aka Rui Nuno Capela. All rights reserved. 5 6 This program is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License 8 as published by the Free Software Foundation; either version 2 9 of the License, or (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License along 17 with this program; if not, write to the Free Software Foundation, Inc., 18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 20 *****************************************************************************/ 21 22 #ifndef __samplv1_sample_h 23 #define __samplv1_sample_h 24 25 #include <cstdint> 26 27 #include <cstdlib> 28 #include <cstring> 29 30 #include <cmath> 31 32 33 // forward decls. 34 class samplv1; 35 36 37 //------------------------------------------------------------------------- 38 // samplv1_sample - sampler wave table. 39 // 40 41 class samplv1_sample 42 { 43 public: 44 45 // ctor. 46 samplv1_sample(float srate = 44100.0f); 47 48 // dtor. 49 ~samplv1_sample(); 50 51 // nominal sample-rate. setSampleRate(float srate)52 void setSampleRate(float srate) 53 { m_srate = srate; } sampleRate()54 float sampleRate() const 55 { return m_srate; } 56 57 // reverse mode. setReverse(bool reverse)58 void setReverse(bool reverse) 59 { 60 if (( m_reverse && !reverse) || 61 (!m_reverse && reverse)) { 62 m_reverse = reverse; 63 reverse_sync(); 64 } 65 } 66 isReverse()67 bool isReverse() const 68 { return m_reverse; } 69 70 // offset mode. setOffset(bool offset)71 void setOffset(bool offset) 72 { 73 m_offset = offset; 74 75 updateOffset(); 76 } 77 isOffset()78 bool isOffset() const 79 { return m_offset; } 80 81 // offset range. 82 void setOffsetRange(uint32_t start, uint32_t end); 83 offsetStart()84 uint32_t offsetStart() const 85 { return m_offset_start; } offsetEnd()86 uint32_t offsetEnd() const 87 { return m_offset_end; } 88 offsetPhase0(uint16_t itab)89 float offsetPhase0(uint16_t itab) const 90 { return (m_offset && m_offset_phase0 ? m_offset_phase0[itab] : 0.0f); } 91 92 // loop mode. setLoop(bool loop)93 void setLoop(bool loop) 94 { 95 m_loop = loop; 96 97 updateLoop(); 98 } 99 isLoop()100 bool isLoop() const 101 { return m_loop; } 102 103 // loop range. 104 void setLoopRange(uint32_t start, uint32_t end); 105 loopStart()106 uint32_t loopStart() const 107 { return m_loop_start; } loopEnd()108 uint32_t loopEnd() const 109 { return m_loop_end; } 110 loopPhase1(uint16_t itab)111 float loopPhase1(uint16_t itab) const 112 { return (m_loop_phase1 ? m_loop_phase1[itab] : 0.0f); } loopPhase2(uint16_t itab)113 float loopPhase2(uint16_t itab) const 114 { return (m_loop_phase2 ? m_loop_phase2[itab] : 0.0f); } 115 116 // loop cross-fade (in number of frames) setLoopCrossFade(uint32_t xfade)117 void setLoopCrossFade(uint32_t xfade) 118 { m_loop_xfade = xfade; } loopCrossFade()119 uint32_t loopCrossFade() const 120 { return m_loop_xfade; } 121 122 // loop zero-crossing detection setLoopZeroCrossing(bool xzero)123 void setLoopZeroCrossing(bool xzero) 124 { m_loop_xzero = xzero; } isLoopZeroCrossing()125 bool isLoopZeroCrossing() const 126 { return m_loop_xzero; } 127 128 // init. 129 bool open(const char *filename, float freq0 = 1.0f, uint16_t otabs = 0); 130 void close(); 131 132 // accessors. filename()133 const char *filename() const 134 { return m_filename; } channels()135 uint16_t channels() const 136 { return m_nchannels; } rate()137 float rate() const 138 { return m_rate0; } freq()139 float freq() const 140 { return m_freq0; } length()141 uint32_t length() const 142 { return m_nframes; } 143 144 // resampler ratio ratio()145 float ratio() const 146 { return m_ratio; } 147 148 // reset. reset(float freq0)149 void reset(float freq0) 150 { 151 m_freq0 = freq0; 152 m_ratio = m_rate0 / (m_freq0 * m_srate); 153 } 154 155 // sample table index. itab(float freq)156 uint16_t itab(float freq) const 157 { 158 int ret = int(m_ntabs >> 1) + fast_ilog2f(freq / m_freq0); 159 160 if (ret < 0) 161 ret = 0; 162 else 163 if (ret > m_ntabs) 164 ret = m_ntabs; 165 166 return ret; 167 } 168 169 // sample table ratio. ftab(uint16_t itab)170 float ftab(uint16_t itab) const 171 { 172 float ret = 1.0f; 173 const uint16_t itab0 = (m_ntabs >> 1); 174 if (itab < itab0) 175 ret *= float((itab0 - itab) << 1); 176 else 177 if (itab > itab0) 178 ret /= float((itab - itab0) << 1); 179 return ret; 180 } 181 182 // number of pitch-shifted octaves. otabs()183 uint16_t otabs() const 184 { return m_ntabs >> 1; } 185 186 // frame value. frames(uint16_t itab,uint16_t k)187 float *frames(uint16_t itab, uint16_t k) const 188 { return m_pframes[itab][k]; } frames(uint16_t k)189 float *frames(uint16_t k) const 190 { return frames(m_ntabs >> 1, k); } 191 192 // predicate. isOver(uint32_t index)193 bool isOver(uint32_t index) const 194 { return !m_pframes || (index >= m_offset_end2); } 195 196 protected: 197 198 // reverse sample buffer. 199 void reverse_sync(); 200 201 // zero-crossing aliasing . 202 uint32_t zero_crossing(uint16_t itab, uint32_t i, int *slope = nullptr) const; 203 float zero_crossing_k(uint16_t itab, uint32_t i) const; 204 205 // offset/loop update. 206 void updateOffset(); 207 void updateLoop(); 208 209 // fast log10(x)/log10(2) approximation. fast_ilog2f(float x)210 static inline int fast_ilog2f ( float x ) 211 { 212 union { float f; int32_t i; } u; u.f = x; 213 return (((u.i & 0x7f800000) >> 23) - 0x7f) 214 + (u.i & 0x007fffff) / float(0x800000); 215 } 216 217 private: 218 219 // instance variables. 220 float m_srate; 221 uint16_t m_ntabs; 222 223 char *m_filename; 224 uint16_t m_nchannels; 225 float m_rate0; 226 float m_freq0; 227 float m_ratio; 228 229 uint32_t m_nframes; 230 float ***m_pframes; 231 bool m_reverse; 232 233 bool m_offset; 234 uint32_t m_offset_start; 235 uint32_t m_offset_end; 236 float *m_offset_phase0; 237 uint32_t m_offset_end2; 238 239 bool m_loop; 240 uint32_t m_loop_start; 241 uint32_t m_loop_end; 242 float *m_loop_phase1; 243 float *m_loop_phase2; 244 uint32_t m_loop_xfade; 245 bool m_loop_xzero; 246 }; 247 248 249 //------------------------------------------------------------------------- 250 // samplv1_generator - sampler oscillator (sort of:) 251 252 class samplv1_generator 253 { 254 public: 255 256 // ctor. 257 samplv1_generator(samplv1_sample *sample = nullptr) { reset(sample); } 258 259 // sample accessor. sample()260 samplv1_sample *sample() const 261 { return m_sample; } 262 263 // reset. reset(samplv1_sample * sample)264 void reset(samplv1_sample *sample) 265 { 266 m_sample = sample; 267 268 start(m_sample ? m_sample->freq() : 1.0f); 269 } 270 271 // reset loop. setLoop(bool loop)272 void setLoop(bool loop) 273 { 274 m_loop = loop; 275 276 if (m_loop && m_sample) { 277 m_loop_phase1 = m_sample->loopPhase1(m_itab); 278 m_loop_phase2 = m_sample->loopPhase2(m_itab); 279 } else { 280 m_loop_phase1 = 0.0f; 281 m_loop_phase2 = 0.0f; 282 } 283 } 284 285 // begin. start(float freq)286 void start(float freq) 287 { 288 m_itab = (m_sample ? m_sample->itab(freq) : 0); 289 m_ftab = (m_sample ? m_sample->ftab(m_itab) : 1.0f); 290 291 m_phase0 = (m_sample ? m_sample->offsetPhase0(m_itab) : 0.0f); 292 m_phase = m_phase0; 293 m_index = 0; 294 m_alpha = 0.0f; 295 296 m_phase1 = 0.0f; 297 m_index1 = 0; 298 m_alpha1 = 0.0f; 299 m_xgain1 = 1.0f; 300 301 setLoop(m_sample ? m_sample->isLoop() : false); 302 } 303 304 // iterate. next(float freq)305 void next(float freq) 306 { 307 const float ratio = (m_sample ? m_sample->ratio() : 1.0f); 308 const float delta = freq * ratio * m_ftab; 309 310 m_index = uint32_t(m_phase); 311 m_alpha = m_phase - float(m_index); 312 m_phase += delta; 313 314 if (m_loop && m_sample) { 315 const uint32_t xfade = m_sample->loopCrossFade(); // nframes. 316 if (xfade > 0) { 317 const float xfade1 = float(xfade); // nframes. 318 if (m_phase >= m_loop_phase2 - xfade1) { 319 if (//m_sample->isOver(m_index) || 320 m_phase >= m_loop_phase2) { 321 m_phase -= m_loop_phase1 * ::ceilf(delta / m_loop_phase1); 322 if (m_phase < m_phase0) 323 m_phase = m_phase0; 324 } 325 if (m_phase1 > 0.0f) { 326 m_index1 = int(m_phase1); 327 m_alpha1 = m_phase1 - float(m_index1); 328 m_phase1 += delta; 329 m_xgain1 -= delta / xfade1; 330 if (m_xgain1 < 0.0f) 331 m_xgain1 = 0.0f; 332 } else { 333 m_phase1 = m_phase - m_loop_phase1; 334 if (m_phase1 < m_phase0) 335 m_phase1 = m_phase0; 336 m_xgain1 = 1.0f; 337 } 338 } 339 else 340 if (m_phase1 > 0.0f) { 341 m_phase1 = 0.0f; 342 m_index1 = 0; 343 m_alpha1 = 0.0f; 344 m_xgain1 = 1.0f; 345 } 346 } 347 else 348 if (m_phase >= m_loop_phase2) { 349 m_phase -= m_loop_phase1 * ::ceilf(delta / m_loop_phase1); 350 if (m_phase < m_phase0) 351 m_phase = m_phase0; 352 } 353 } 354 } 355 356 // sample. value(uint16_t k)357 float value(uint16_t k) const 358 { 359 if (isOver()) 360 return 0.0f; 361 362 float ret = m_xgain1 * interp(k, m_index, m_alpha); 363 if (m_index1 > 0) 364 ret += (1.0f - m_xgain1) * interp(k, m_index1, m_alpha1); 365 366 return ret; 367 } 368 369 // predicate. isOver()370 bool isOver() const 371 { return !m_loop && (m_sample ? m_sample->isOver(m_index) : true); } 372 373 protected: 374 375 // sample (cubic interpolate). interp(uint16_t k,uint32_t index,float alpha)376 float interp(uint16_t k, uint32_t index, float alpha) const 377 { 378 const float *frames = m_sample->frames(m_itab, k); 379 380 const float x0 = frames[index]; 381 const float x1 = frames[index + 1]; 382 const float x2 = frames[index + 2]; 383 const float x3 = frames[index + 3]; 384 385 const float c1 = (x2 - x0) * 0.5f; 386 const float b1 = (x1 - x2); 387 const float b2 = (c1 + b1); 388 const float c3 = (x3 - x1) * 0.5f + b2 + b1; 389 const float c2 = (c3 + b2); 390 391 return (((c3 * alpha) - c2) * alpha + c1) * alpha + x1; 392 } 393 394 private: 395 396 // iterator variables. 397 samplv1_sample *m_sample; 398 399 uint16_t m_itab; 400 float m_ftab; 401 402 float m_phase0; 403 float m_phase; 404 uint32_t m_index; 405 float m_alpha; 406 407 bool m_loop; 408 float m_loop_phase1; 409 float m_loop_phase2; 410 411 float m_phase1; 412 uint32_t m_index1; 413 float m_alpha1; 414 float m_xgain1; 415 }; 416 417 418 #endif // __samplv1_sample_h 419 420 // end of samplv1_sample.h 421