You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

527 lines
21KB

  1. /* Copyright 2013-2019 Matt Tytel
  2. *
  3. * vital is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * vital is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with vital. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "sample_source.h"
  17. #include "futils.h"
  18. #include "synth_constants.h"
  19. #include <thread>
  20. namespace vital {
  21. namespace {
  22. const std::string kDefaultName = "White Noise";
  23. const mono_float kUpsampleCoefficients[SampleSource::kNumUpsampleTaps] = {
  24. -0.000159813115702086552469274316479186382f,
  25. 0.000225405365781280835058009159865832771f,
  26. -0.000378616814007205900686342525673921955f,
  27. 0.000594907533596884547516525643118256994f,
  28. -0.000890530515941817101682742574553230952f,
  29. 0.001284040046393844676508866342601322685f,
  30. -0.001796543223638378920792302295694753411f,
  31. 0.002451862103068884121692683208948437823f,
  32. -0.003276873018553504678107568537370752892f,
  33. 0.004302012661141991003987961050825106213f,
  34. -0.005561976429934398571952591794342879439f,
  35. 0.007097105459677621741576558633823879063f,
  36. -0.008955232561651555595050311353588767815f,
  37. 0.011195057708851860467369476737076183781f,
  38. -0.013890548104646217864033275191104621626f,
  39. 0.017139719620821350365424962092220084742f,
  40. -0.021077036318492142763503238711564335972f,
  41. 0.025897497908177177783350941808748757467f,
  42. -0.03189749744607761616776997470878995955f,
  43. 0.039555400754278852160084056777122896165f,
  44. -0.049699764879031965714162311087420675904f,
  45. 0.063901297378209126476278356676630210131f,
  46. -0.08553732517833501081128133591846562922f,
  47. 0.123410206086688845061871688812971115112f,
  48. -0.209837893291539345774765479291090741754f,
  49. 0.63582677174146173815216798175242729485f,
  50. 0.63582677174146173815216798175242729485f,
  51. -0.209837893291539345774765479291090741754f,
  52. 0.123410206086688845061871688812971115112f,
  53. -0.08553732517833501081128133591846562922f,
  54. 0.063901297378209126476278356676630210131f,
  55. -0.049699764879031965714162311087420675904f,
  56. 0.039555400754278852160084056777122896165f,
  57. -0.03189749744607761616776997470878995955f,
  58. 0.025897497908177177783350941808748757467f,
  59. -0.021077036318492142763503238711564335972f,
  60. 0.017139719620821350365424962092220084742f,
  61. -0.013890548104646217864033275191104621626f,
  62. 0.011195057708851860467369476737076183781f,
  63. -0.008955232561651555595050311353588767815f,
  64. 0.007097105459677621741576558633823879063f,
  65. -0.005561976429934398571952591794342879439f,
  66. 0.004302012661141991003987961050825106213f,
  67. -0.003276873018553504678107568537370752892f,
  68. 0.002451862103068884121692683208948437823f,
  69. -0.001796543223638378920792302295694753411f,
  70. 0.001284040046393844676508866342601322685f,
  71. -0.000890530515941817101682742574553230952f,
  72. 0.000594907533596884547516525643118256994f,
  73. -0.000378616814007205900686342525673921955f,
  74. 0.000225405365781280835058009159865832771f,
  75. -0.000159813115702086552469274316479186382f
  76. };
  77. const mono_float kDownsampleCoefficients[SampleSource::kNumDownsampleTaps] = {
  78. -0.0013796309221920304f,
  79. -0.0008322130675804714f,
  80. 0.0030100376204235577f,
  81. 0.00666031332700994f,
  82. 0.0040620073330527315f,
  83. -0.003019073425031439f,
  84. -0.004450269579432283f,
  85. 0.0030526281279541555f,
  86. 0.007614361286489334f,
  87. -0.000546514301955849f,
  88. -0.010099270019478761f,
  89. -0.003465846383906444f,
  90. 0.011760981765402261f,
  91. 0.009402148654924303f,
  92. -0.011429260748035207f,
  93. -0.016935843679984037f,
  94. 0.008026778073943279f,
  95. 0.025557280950428782f,
  96. -0.0002093220301655805f,
  97. -0.03448379812688787f,
  98. -0.013983156365753766f,
  99. 0.04279770831566429f,
  100. 0.03889228625534586f,
  101. -0.049566024787935245f,
  102. -0.09025827224454164f,
  103. 0.05398926693924448f,
  104. 0.31285587793730246f,
  105. 0.4444714418837066f,
  106. 0.31285587793730246f,
  107. 0.05398926693924448f,
  108. -0.09025827224454164f,
  109. -0.049566024787935245f,
  110. 0.03889228625534586f,
  111. 0.04279770831566429f,
  112. -0.013983156365753766f,
  113. -0.03448379812688787f,
  114. -0.0002093220301655805f,
  115. 0.025557280950428782f,
  116. 0.008026778073943279f,
  117. -0.016935843679984037f,
  118. -0.011429260748035207f,
  119. 0.009402148654924303f,
  120. 0.011760981765402261f,
  121. -0.003465846383906444f,
  122. -0.010099270019478761f,
  123. -0.000546514301955849f,
  124. 0.007614361286489334f,
  125. 0.0030526281279541555f,
  126. -0.004450269579432283f,
  127. -0.003019073425031439f,
  128. 0.0040620073330527315f,
  129. 0.00666031332700994f,
  130. 0.0030100376204235577f,
  131. -0.0008322130675804714f,
  132. -0.0013796309221920304f
  133. };
  134. force_inline mono_float getFilteredSample(const mono_float* buffer, int index, int size) {
  135. int radius = SampleSource::kNumDownsampleTaps / 2;
  136. int start = std::max(0, index - radius);
  137. int end = std::min(size - 1, index + radius);
  138. mono_float total = 0.0f;
  139. for (int i = start; i <= end; ++i) {
  140. mono_float coefficient = kDownsampleCoefficients[i - index + radius];
  141. total += coefficient * buffer[i];
  142. }
  143. return total;
  144. }
  145. force_inline mono_float getFilteredLoopSample(const mono_float* buffer, int index, int size) {
  146. int radius = SampleSource::kNumDownsampleTaps / 2;
  147. int start = index - radius;
  148. int end = index + radius;
  149. mono_float total = 0.0f;
  150. for (int i = start; i <= end; ++i) {
  151. int buffer_index = (i + size * radius) % size;
  152. mono_float coefficient = kDownsampleCoefficients[i - index + radius];
  153. total += coefficient * buffer[buffer_index];
  154. }
  155. return total;
  156. }
  157. force_inline mono_float getInterpolatedSample(const mono_float* buffer, int index, int size) {
  158. int radius = SampleSource::kNumUpsampleTaps / 2;
  159. int start = std::max(0, index - radius + 1);
  160. int end = std::min(size - 1, index + radius);
  161. mono_float total = 0.0f;
  162. for (int i = start; i <= end; ++i) {
  163. int coefficient_index = i - index + radius - 1;
  164. VITAL_ASSERT(coefficient_index >= 0 && coefficient_index < SampleSource::kNumUpsampleTaps);
  165. mono_float coefficient = kUpsampleCoefficients[coefficient_index];
  166. total += coefficient * buffer[i];
  167. }
  168. return total;
  169. }
  170. void upsample(const mono_float* original, mono_float* dest, int original_size, int dest_size) {
  171. for (int i = 0; i < original_size; ++i) {
  172. float value1 = original[i];
  173. float value2 = getInterpolatedSample(original, i, original_size);
  174. dest[2 * i] = value1;
  175. dest[2 * i + 1] = value2;
  176. }
  177. }
  178. void downsample(const mono_float* original, mono_float* dest, int original_size, int dest_size) {
  179. for (int i = 0; i < dest_size; ++i)
  180. dest[i] = getFilteredSample(original, 2 * i, original_size);
  181. }
  182. void downsampleLoop(const mono_float* original, mono_float* dest, int original_size, int dest_size) {
  183. for (int i = 0; i < dest_size; ++i)
  184. dest[i] = getFilteredLoopSample(original, 2 * i, original_size);
  185. }
  186. void createBandLimitedBuffers(std::vector<std::unique_ptr<mono_float[]>>& destination,
  187. std::vector<std::unique_ptr<mono_float[]>>& loop_destination,
  188. const mono_float* buffer, int size) {
  189. destination.push_back(std::make_unique<mono_float[]>(size + 2 * Sample::kBufferSamples));
  190. loop_destination.push_back(std::make_unique<mono_float[]>(size + 2 * Sample::kBufferSamples));
  191. mono_float* play_buffer = destination.back().get();
  192. mono_float* loop_buffer = loop_destination.back().get();
  193. memcpy(play_buffer + Sample::kBufferSamples, buffer, size * sizeof(mono_float));
  194. memcpy(loop_buffer + Sample::kBufferSamples, buffer, size * sizeof(mono_float));
  195. for (int i = 0; i < Sample::kBufferSamples; ++i) {
  196. play_buffer[i] = 0.0f;
  197. play_buffer[size + Sample::kBufferSamples + i] = 0.0f;
  198. loop_buffer[i] = loop_buffer[size + i];
  199. loop_buffer[size + Sample::kBufferSamples + i] = loop_buffer[Sample::kBufferSamples + i];
  200. }
  201. int current_size = size;
  202. for (int i = 0; i < Sample::kUpsampleTimes; ++i) {
  203. int upsampled_size = current_size * 2;
  204. int num_samples = upsampled_size + 2 * Sample::kBufferSamples;
  205. destination.insert(destination.begin(), std::make_unique<mono_float[]>(num_samples));
  206. loop_destination.insert(loop_destination.begin(), std::make_unique<mono_float[]>(num_samples));
  207. mono_float* next_buffer = destination.front().get();
  208. mono_float* next_loop_buffer = loop_destination.front().get();
  209. upsample(play_buffer + Sample::kBufferSamples, next_buffer + Sample::kBufferSamples,
  210. current_size, upsampled_size);
  211. memcpy(next_loop_buffer, next_buffer, num_samples * sizeof(mono_float));
  212. current_size = upsampled_size;
  213. }
  214. play_buffer = destination.back().get();
  215. loop_buffer = loop_destination.back().get();
  216. current_size = size;
  217. while (current_size >= Sample::kMinSize) {
  218. int next_size = (current_size + 1) / 2;
  219. destination.push_back(std::make_unique<mono_float[]>(next_size + 2 * Sample::kBufferSamples));
  220. loop_destination.push_back(std::make_unique<mono_float[]>(next_size + 2 * Sample::kBufferSamples));
  221. mono_float* next_buffer = destination.back().get();
  222. mono_float* next_loop_buffer = loop_destination.back().get();
  223. downsample(play_buffer + Sample::kBufferSamples, next_buffer + Sample::kBufferSamples,
  224. current_size, next_size);
  225. downsampleLoop(loop_buffer + Sample::kBufferSamples, next_loop_buffer + Sample::kBufferSamples,
  226. current_size, next_size);
  227. for (int i = 0; i < Sample::kBufferSamples; ++i) {
  228. next_buffer[i] = 0.0f;
  229. next_buffer[next_size + Sample::kBufferSamples + i] = 0.0f;
  230. next_loop_buffer[i] = loop_buffer[next_size + i];
  231. next_loop_buffer[next_size + Sample::kBufferSamples + i] = next_loop_buffer[Sample::kBufferSamples + i];
  232. }
  233. play_buffer = next_buffer;
  234. loop_buffer = next_loop_buffer;
  235. current_size = next_size;
  236. }
  237. }
  238. }
  239. Sample::Sample() : name_(kDefaultName), current_data_(nullptr), active_audio_data_(nullptr) {
  240. init();
  241. }
  242. void Sample::loadSample(const mono_float* buffer, int size, int sample_rate) {
  243. static constexpr int kMaxSize = 1764000;
  244. VITAL_ASSERT(active_audio_data_.is_lock_free());
  245. size = std::min(size, kMaxSize);
  246. std::unique_ptr<SampleData> old_data = std::move(data_);
  247. data_ = std::make_unique<SampleData>(size, sample_rate, false);
  248. createBandLimitedBuffers(data_->left_buffers, data_->left_loop_buffers, buffer, size);
  249. current_data_ = data_.get();
  250. while (active_audio_data_.load())
  251. std::this_thread::yield(); // Wait for audio thread to finish using old_data.
  252. }
  253. void Sample::loadSample(const mono_float* left_buffer, const mono_float* right_buffer, int size, int sample_rate) {
  254. std::unique_ptr<SampleData> old_data = std::move(data_);
  255. data_ = std::make_unique<SampleData>(size, sample_rate, true);
  256. createBandLimitedBuffers(data_->left_buffers, data_->left_loop_buffers, left_buffer, size);
  257. createBandLimitedBuffers(data_->right_buffers, data_->right_loop_buffers, right_buffer, size);
  258. current_data_ = data_.get();
  259. while (active_audio_data_.load())
  260. std::this_thread::yield(); // Wait for audio thread to finish using old_data.
  261. }
  262. void Sample::init() {
  263. name_ = kDefaultName;
  264. mono_float buffer[kDefaultSampleLength];
  265. utils::RandomGenerator random_generator(-0.9f, 0.9f);
  266. for (int i = 0; i < kDefaultSampleLength; ++i)
  267. buffer[i] = random_generator.next();
  268. loadSample(buffer, kDefaultSampleLength, kDefaultSampleRate);
  269. }
  270. json Sample::stateToJson() {
  271. json data;
  272. data["name"] = name_;
  273. data["length"] = data_->length;
  274. data["sample_rate"] = data_->sample_rate;
  275. std::unique_ptr<int16_t[]> pcm_data = std::make_unique<int16_t[]>(data_->length);
  276. utils::floatToPcmData(pcm_data.get(), data_->left_buffers[kUpsampleTimes].get(), data_->length);
  277. String encoded = Base64::toBase64(pcm_data.get(), sizeof(int16_t) * data_->length);
  278. data["samples"] = encoded.toStdString();
  279. if (data_->stereo) {
  280. utils::floatToPcmData(pcm_data.get(), data_->right_buffers[kUpsampleTimes].get(), data_->length);
  281. String encoded_stereo = Base64::toBase64(pcm_data.get(), sizeof(int16_t) * data_->length);
  282. data["samples_stereo"] = encoded_stereo.toStdString();
  283. }
  284. return data;
  285. }
  286. void Sample::jsonToState(json data) {
  287. name_ = "";
  288. if (data.count("name"))
  289. name_ = data["name"].get<std::string>();
  290. int length = data["length"];
  291. int sample_rate = data["sample_rate"];
  292. MemoryOutputStream decoded(length * sizeof(int16_t));
  293. std::string wave_data = data["samples"];
  294. Base64::convertFromBase64(decoded, wave_data);
  295. std::unique_ptr<int16_t[]> pcm_data = std::make_unique<int16_t[]>(length);
  296. memcpy(pcm_data.get(), decoded.getData(), length * sizeof(int16_t));
  297. std::unique_ptr<mono_float[]> buffer = std::make_unique<mono_float[]>(length);
  298. utils::pcmToFloatData(buffer.get(), pcm_data.get(), length);
  299. if (data.count("samples_stereo")) {
  300. MemoryOutputStream decoded_stereo(length * sizeof(int16_t));
  301. std::string wave_data_stereo = data["samples_stereo"];
  302. Base64::convertFromBase64(decoded_stereo, wave_data_stereo);
  303. std::unique_ptr<int16_t[]> pcm_data_stereo = std::make_unique<int16_t[]>(length);
  304. memcpy(pcm_data_stereo.get(), decoded_stereo.getData(), length * sizeof(int16_t));
  305. std::unique_ptr<mono_float[]> buffer_stereo = std::make_unique<mono_float[]>(length);
  306. utils::pcmToFloatData(buffer_stereo.get(), pcm_data_stereo.get(), length);
  307. loadSample(buffer.get(), buffer_stereo.get(), length, sample_rate);
  308. }
  309. else
  310. loadSample(buffer.get(), length, sample_rate);
  311. }
  312. SampleSource::SampleSource() : Processor(kNumInputs, kNumOutputs), pan_amplitude_(0.0f), phase_inc_(0.0f),
  313. random_generator_(0.0f, 1.0f) {
  314. transpose_quantize_ = 0;
  315. last_quantized_transpose_ = 0.0f;
  316. sample_index_ = 0;
  317. sample_fraction_ = 0.0f;
  318. sample_ = std::make_shared<Sample>();
  319. phase_output_ = std::make_shared<cr::Output>();
  320. }
  321. void SampleSource::process(int num_samples) {
  322. sample_->markUsed();
  323. poly_float current_pan_amplitude = pan_amplitude_;
  324. poly_float input_pan = utils::clamp(input(kPan)->at(0), -1.0f, 1.0f);
  325. pan_amplitude_ = futils::panAmplitude(input_pan);
  326. poly_float input_midi = 0.0f;
  327. if (input(kKeytrack)->at(0)[0])
  328. input_midi = input(kMidi)->at(0) - kMidiTrackCenter;
  329. int transpose_quantize = static_cast<int>(input(kTransposeQuantize)->at(0)[0]);
  330. poly_float transpose = snapTranspose(input_midi, input(kTranspose)->at(0), transpose_quantize);
  331. transpose = utils::clamp(transpose + input(kTune)->at(0), kMinTranspose, kMaxTranspose);
  332. mono_float sample_rate_ratio = (1.0f * sample_->activeSampleRate()) / getSampleRate();
  333. poly_float current_phase_inc = phase_inc_;
  334. phase_inc_ = utils::centsToRatio(transpose * kCentsPerNote) * sample_rate_ratio * (1 << Sample::kUpsampleTimes);
  335. int audio_length = sample_->activeLength();
  336. poly_mask reset_mask = getResetMask(kReset);
  337. poly_float reset_offset = utils::toFloat(input(kReset)->source->trigger_offset);
  338. current_pan_amplitude = utils::maskLoad(current_pan_amplitude, pan_amplitude_, reset_mask);
  339. current_phase_inc = utils::maskLoad(current_phase_inc, phase_inc_, reset_mask);
  340. bounce_mask_ = bounce_mask_ & ~reset_mask;
  341. reset_offset *= current_phase_inc;
  342. poly_float reset_value = -reset_offset;
  343. if (input(kRandomPhase)->at(0)[0]) {
  344. reset_value = random_generator_.next() * audio_length;
  345. reset_value = utils::maskLoad(reset_value, random_generator_.next() * audio_length, constants::kFirstMask);
  346. reset_value -= reset_offset;
  347. }
  348. sample_index_ = utils::maskLoad(sample_index_, utils::floor(reset_value), reset_mask);
  349. sample_fraction_ = utils::maskLoad(sample_fraction_, reset_value - sample_index_, reset_mask);
  350. bool loop = input(kLoop)->at(0)[0] != 0.0f;
  351. poly_mask loop_enabled_mask = 0;
  352. if (loop)
  353. loop_enabled_mask = constants::kFullMask;
  354. bool bounce = input(kBounce)->at(0)[0] != 0.0f;
  355. poly_mask bounce_enabled_mask = 0;
  356. if (bounce)
  357. bounce_enabled_mask = constants::kFullMask;
  358. else
  359. bounce_mask_ = 0;
  360. const mono_float* audio_buffers[poly_float::kSize];
  361. poly_float phase_mult = 1.0f;
  362. for (int i = 0; i < poly_float::kSize; ++i) {
  363. int index = sample_->getActiveIndex(phase_inc_[i]);
  364. if (loop && !bounce) {
  365. if (i % 2)
  366. audio_buffers[i] = sample_->getActiveRightLoopBuffer(index);
  367. else
  368. audio_buffers[i] = sample_->getActiveLeftLoopBuffer(index);
  369. }
  370. else {
  371. if (i % 2)
  372. audio_buffers[i] = sample_->getActiveRightBuffer(index);
  373. else
  374. audio_buffers[i] = sample_->getActiveLeftBuffer(index);
  375. }
  376. phase_mult.set(i, 1.0f / (1 << index));
  377. }
  378. mono_float sample_inc = 1.0f / num_samples;
  379. poly_float delta_pan_amplitude = (pan_amplitude_ - current_pan_amplitude) * sample_inc;
  380. poly_float delta_phase_inc = (phase_inc_ - current_phase_inc) * sample_inc;
  381. poly_float* raw_output = output(kRaw)->buffer;
  382. poly_float current_fraction = sample_fraction_;
  383. poly_float current_index = utils::min(sample_index_, audio_length);
  384. poly_mask current_bounce = bounce_mask_;
  385. poly_int length = audio_length;
  386. for (int i = 0; i < num_samples; ++i) {
  387. current_phase_inc += delta_phase_inc;
  388. poly_float adjusted = utils::maskLoad(current_index, poly_float(audio_length) - current_index, current_bounce);
  389. poly_float index_phase = utils::max(adjusted, 0.0f) * phase_mult;
  390. poly_float fraction_phase = current_fraction * phase_mult;
  391. poly_int start_indices = utils::floorToInt(index_phase);
  392. poly_float rounded_down_phase = utils::toFloat(start_indices);
  393. poly_float t = index_phase - rounded_down_phase + fraction_phase;
  394. t = utils::maskLoad(t, poly_float(1.0f) - t, current_bounce);
  395. VITAL_ASSERT(poly_float::lessThan(utils::toFloat(start_indices), 0.0f).anyMask() == 0);
  396. VITAL_ASSERT(poly_float::greaterThan(utils::toFloat(start_indices), audio_length).anyMask() == 0);
  397. matrix interpolation_matrix = utils::getCatmullInterpolationMatrix(t);
  398. matrix value_matrix = utils::getValueMatrix(audio_buffers, start_indices);
  399. value_matrix.transpose();
  400. raw_output[i] = interpolation_matrix.multiplyAndSumRows(value_matrix);
  401. VITAL_ASSERT(utils::isContained(raw_output[i]));
  402. current_fraction += current_phase_inc;
  403. poly_float increment = utils::floor(current_fraction);
  404. current_fraction -= increment;
  405. current_index += increment;
  406. poly_mask done_mask = poly_float::greaterThanOrEqual(current_index, audio_length);
  407. poly_mask bounced_mask = done_mask & ~current_bounce & bounce_enabled_mask;
  408. poly_mask loop_over_mask = done_mask & (current_bounce | ~bounce_enabled_mask) & loop_enabled_mask;
  409. current_bounce = (bounced_mask | current_bounce) & ~loop_over_mask;
  410. current_index = utils::maskLoad(current_index, current_index - audio_length, bounced_mask | loop_over_mask);
  411. current_index = utils::min(audio_length, current_index);
  412. current_fraction = current_fraction & ~done_mask;
  413. }
  414. bounce_mask_ = current_bounce;
  415. if (reset_mask.anyMask())
  416. clearOutputBufferForReset(reset_mask, kReset, kRaw);
  417. const poly_float* level_input = input(kLevel)->source->buffer;
  418. poly_float* levelled_output = output(kLevelled)->buffer;
  419. poly_float zero = 0.0f;
  420. poly_float max = kMaxAmplitude;
  421. for (int i = 0; i < num_samples; ++i) {
  422. current_pan_amplitude += delta_pan_amplitude;
  423. poly_float level = utils::clamp(level_input[i], zero, max);
  424. levelled_output[i] = current_pan_amplitude * level * level * raw_output[i];
  425. }
  426. sample_index_ = current_index;
  427. sample_fraction_ = current_fraction;
  428. poly_float phase = utils::maskLoad(sample_index_, poly_float(audio_length) - sample_index_, bounce_mask_);
  429. phase = phase * (1.0f / audio_length);
  430. phase_output_->buffer[0] = utils::encodePhaseAndVoice(phase, input(kNoteCount)->at(0));
  431. sample_->markUnused();
  432. }
  433. force_inline poly_float SampleSource::snapTranspose(poly_float input_midi, poly_float transpose, int quantize) {
  434. if (quantize == 0)
  435. return input_midi + transpose;
  436. bool global_transpose = utils::isTransposeQuantizeGlobal(quantize);
  437. poly_float pre_add = 0.0f;
  438. poly_float post_add = input_midi;
  439. if (global_transpose) {
  440. pre_add = input_midi;
  441. post_add = 0.0f;
  442. }
  443. poly_float snapped = utils::snapTranspose(pre_add + transpose, quantize);
  444. if (transpose_quantize_)
  445. phase_inc_ *= utils::noteOffsetToRatio(snapped - last_quantized_transpose_);
  446. last_quantized_transpose_ = snapped;
  447. transpose_quantize_ = quantize;
  448. return post_add + snapped;
  449. }
  450. } // namespace vital