17 const std::string kDefaultName =
"White Noise";
21 -0.000159813115702086552469274316479186382f,
22 0.000225405365781280835058009159865832771f,
23 -0.000378616814007205900686342525673921955f,
24 0.000594907533596884547516525643118256994f,
25 -0.000890530515941817101682742574553230952f,
26 0.001284040046393844676508866342601322685f,
27 -0.001796543223638378920792302295694753411f,
28 0.002451862103068884121692683208948437823f,
29 -0.003276873018553504678107568537370752892f,
30 0.004302012661141991003987961050825106213f,
31 -0.005561976429934398571952591794342879439f,
32 0.007097105459677621741576558633823879063f,
33 -0.008955232561651555595050311353588767815f,
34 0.011195057708851860467369476737076183781f,
35 -0.013890548104646217864033275191104621626f,
36 0.017139719620821350365424962092220084742f,
37 -0.021077036318492142763503238711564335972f,
38 0.025897497908177177783350941808748757467f,
39 -0.03189749744607761616776997470878995955f,
40 0.039555400754278852160084056777122896165f,
41 -0.049699764879031965714162311087420675904f,
42 0.063901297378209126476278356676630210131f,
43 -0.08553732517833501081128133591846562922f,
44 0.123410206086688845061871688812971115112f,
45 -0.209837893291539345774765479291090741754f,
46 0.63582677174146173815216798175242729485f,
47 0.63582677174146173815216798175242729485f,
48 -0.209837893291539345774765479291090741754f,
49 0.123410206086688845061871688812971115112f,
50 -0.08553732517833501081128133591846562922f,
51 0.063901297378209126476278356676630210131f,
52 -0.049699764879031965714162311087420675904f,
53 0.039555400754278852160084056777122896165f,
54 -0.03189749744607761616776997470878995955f,
55 0.025897497908177177783350941808748757467f,
56 -0.021077036318492142763503238711564335972f,
57 0.017139719620821350365424962092220084742f,
58 -0.013890548104646217864033275191104621626f,
59 0.011195057708851860467369476737076183781f,
60 -0.008955232561651555595050311353588767815f,
61 0.007097105459677621741576558633823879063f,
62 -0.005561976429934398571952591794342879439f,
63 0.004302012661141991003987961050825106213f,
64 -0.003276873018553504678107568537370752892f,
65 0.002451862103068884121692683208948437823f,
66 -0.001796543223638378920792302295694753411f,
67 0.001284040046393844676508866342601322685f,
68 -0.000890530515941817101682742574553230952f,
69 0.000594907533596884547516525643118256994f,
70 -0.000378616814007205900686342525673921955f,
71 0.000225405365781280835058009159865832771f,
72 -0.000159813115702086552469274316479186382f
77 -0.0013796309221920304f,
78 -0.0008322130675804714f,
79 0.0030100376204235577f,
81 0.0040620073330527315f,
82 -0.003019073425031439f,
83 -0.004450269579432283f,
84 0.0030526281279541555f,
85 0.007614361286489334f,
86 -0.000546514301955849f,
87 -0.010099270019478761f,
88 -0.003465846383906444f,
89 0.011760981765402261f,
90 0.009402148654924303f,
91 -0.011429260748035207f,
92 -0.016935843679984037f,
93 0.008026778073943279f,
94 0.025557280950428782f,
95 -0.0002093220301655805f,
96 -0.03448379812688787f,
97 -0.013983156365753766f,
100 -0.049566024787935245f,
101 -0.09025827224454164f,
102 0.05398926693924448f,
103 0.31285587793730246f,
105 0.31285587793730246f,
106 0.05398926693924448f,
107 -0.09025827224454164f,
108 -0.049566024787935245f,
109 0.03889228625534586f,
110 0.04279770831566429f,
111 -0.013983156365753766f,
112 -0.03448379812688787f,
113 -0.0002093220301655805f,
114 0.025557280950428782f,
115 0.008026778073943279f,
116 -0.016935843679984037f,
117 -0.011429260748035207f,
118 0.009402148654924303f,
119 0.011760981765402261f,
120 -0.003465846383906444f,
121 -0.010099270019478761f,
122 -0.000546514301955849f,
123 0.007614361286489334f,
124 0.0030526281279541555f,
125 -0.004450269579432283f,
126 -0.003019073425031439f,
127 0.0040620073330527315f,
128 0.00666031332700994f,
129 0.0030100376204235577f,
130 -0.0008322130675804714f,
131 -0.0013796309221920304f
143 int start = std::max(0, index - radius);
144 int end = std::min(size - 1, index + radius);
146 for (
int i = start; i <= end; ++i) {
147 mono_float coefficient = kDownsampleCoefficients[i - index + radius];
148 total += coefficient * buffer[i];
158 int start = index - radius;
159 int end = index + radius;
161 for (
int i = start; i <= end; ++i) {
162 int buffer_index = (i + size * radius) % size;
163 mono_float coefficient = kDownsampleCoefficients[i - index + radius];
164 total += coefficient * buffer[buffer_index];
174 int start = std::max(0, index - radius + 1);
175 int end = std::min(size - 1, index + radius);
177 for (
int i = start; i <= end; ++i) {
178 int coefficient_index = i - index + radius - 1;
180 mono_float coefficient = kUpsampleCoefficients[coefficient_index];
181 total += coefficient * buffer[i];
194 for (
int i = 0; i < original_size; ++i) {
195 float value1 = original[i];
196 float value2 = getInterpolatedSample(original, i, original_size);
197 dest[2 * i] = value1;
198 dest[2 * i + 1] = value2;
205 void downsample(
const mono_float* original,
mono_float* dest,
int original_size,
int dest_size) {
206 for (
int i = 0; i < dest_size; ++i)
207 dest[i] = getFilteredSample(original, 2 * i, original_size);
213 void downsampleLoop(
const mono_float* original,
mono_float* dest,
int original_size,
int dest_size) {
214 for (
int i = 0; i < dest_size; ++i)
215 dest[i] = getFilteredLoopSample(original, 2 * i, original_size);
222 void createBandLimitedBuffers(std::vector<std::unique_ptr<
mono_float[]>>& destination,
223 std::vector<std::unique_ptr<
mono_float[]>>& loop_destination,
228 mono_float* play_buffer = destination.back().get();
229 mono_float* loop_buffer = loop_destination.back().get();
234 play_buffer[i] = 0.0f;
237 loop_buffer[i] = loop_buffer[size + i];
241 int current_size = size;
243 int upsampled_size = current_size * 2;
245 destination.insert(destination.begin(), std::make_unique<
mono_float[]>(num_samples));
246 loop_destination.insert(loop_destination.begin(), std::make_unique<
mono_float[]>(num_samples));
248 mono_float* next_buffer = destination.front().get();
249 mono_float* next_loop_buffer = loop_destination.front().get();
252 current_size, upsampled_size);
253 memcpy(next_loop_buffer, next_buffer, num_samples *
sizeof(
mono_float));
254 current_size = upsampled_size;
257 play_buffer = destination.back().get();
258 loop_buffer = loop_destination.back().get();
262 int next_size = (current_size + 1) / 2;
266 mono_float* next_buffer = destination.back().get();
267 mono_float* next_loop_buffer = loop_destination.back().get();
270 current_size, next_size);
272 current_size, next_size);
275 next_buffer[i] = 0.0f;
278 next_loop_buffer[i] = loop_buffer[next_size + i];
282 play_buffer = next_buffer;
283 loop_buffer = next_loop_buffer;
284 current_size = next_size;
291 Sample::Sample() : name_(kDefaultName), current_data_(nullptr), active_audio_data_(nullptr) {
296 static constexpr int kMaxSize = 1764000;
300 size = std::min(size, kMaxSize);
301 std::unique_ptr<SampleData> old_data = std::move(
data_);
302 data_ = std::make_unique<SampleData>(size, sample_rate,
false);
303 createBandLimitedBuffers(
data_->left_buffers,
data_->left_loop_buffers,
buffer, size);
307 std::this_thread::yield();
311 std::unique_ptr<SampleData> old_data = std::move(
data_);
312 data_ = std::make_unique<SampleData>(size, sample_rate,
true);
313 createBandLimitedBuffers(
data_->left_buffers,
data_->left_loop_buffers, left_buffer, size);
314 createBandLimitedBuffers(
data_->right_buffers,
data_->right_loop_buffers, right_buffer, size);
318 std::this_thread::yield();
323 name_ = kDefaultName;
336 data[
"name"] =
name_;
337 data[
"length"] =
data_->length;
338 data[
"sample_rate"] =
data_->sample_rate;
339 std::unique_ptr<int16_t[]> pcm_data = std::make_unique<int16_t[]>(
data_->length);
341 String encoded = Base64::toBase64(pcm_data.get(),
sizeof(int16_t) *
data_->length);
342 data[
"samples"] = encoded.toStdString();
345 String encoded_stereo = Base64::toBase64(pcm_data.get(),
sizeof(int16_t) *
data_->length);
346 data[
"samples_stereo"] = encoded_stereo.toStdString();
354 if (data.count(
"name"))
355 name_ = data[
"name"].get<std::string>();
357 int length = data[
"length"];
358 int sample_rate = data[
"sample_rate"];
360 MemoryOutputStream decoded(length *
sizeof(int16_t));
361 std::string wave_data = data[
"samples"];
362 Base64::convertFromBase64(decoded, wave_data);
363 std::unique_ptr<int16_t[]> pcm_data = std::make_unique<int16_t[]>(length);
364 memcpy(pcm_data.get(), decoded.getData(), length *
sizeof(int16_t));
365 std::unique_ptr<mono_float[]>
buffer = std::make_unique<mono_float[]>(length);
368 if (data.count(
"samples_stereo")) {
369 MemoryOutputStream decoded_stereo(length *
sizeof(int16_t));
370 std::string wave_data_stereo = data[
"samples_stereo"];
371 Base64::convertFromBase64(decoded_stereo, wave_data_stereo);
372 std::unique_ptr<int16_t[]> pcm_data_stereo = std::make_unique<int16_t[]>(length);
373 memcpy(pcm_data_stereo.get(), decoded_stereo.getData(), length *
sizeof(int16_t));
375 std::unique_ptr<mono_float[]> buffer_stereo = std::make_unique<mono_float[]>(length);
386 random_generator_(0.0f, 1.0f) {
387 transpose_quantize_ = 0;
388 last_quantized_transpose_ = 0.0f;
390 sample_fraction_ = 0.0f;
392 sample_ = std::make_shared<Sample>();
393 phase_output_ = std::make_shared<cr::Output>();
401 poly_float current_pan_amplitude = pan_amplitude_;
417 int audio_length = sample_->activeLength();
420 current_pan_amplitude =
utils::maskLoad(current_pan_amplitude, pan_amplitude_, reset_mask);
421 current_phase_inc =
utils::maskLoad(current_phase_inc, phase_inc_, reset_mask);
422 bounce_mask_ = bounce_mask_ & ~reset_mask;
423 reset_offset *= current_phase_inc;
427 reset_value = random_generator_.
next() * audio_length;
429 reset_value -= reset_offset;
433 sample_fraction_ =
utils::maskLoad(sample_fraction_, reset_value - sample_index_, reset_mask);
447 const mono_float* audio_buffers[poly_float::kSize];
449 for (
int i = 0; i < poly_float::kSize; ++i) {
450 int index = sample_->getActiveIndex(phase_inc_[i]);
451 if (loop && !bounce) {
453 audio_buffers[i] = sample_->getActiveRightLoopBuffer(index);
455 audio_buffers[i] = sample_->getActiveLeftLoopBuffer(index);
459 audio_buffers[i] = sample_->getActiveRightBuffer(index);
461 audio_buffers[i] = sample_->getActiveLeftBuffer(index);
464 phase_mult.
set(i, 1.0f / (1 << index));
468 poly_float delta_pan_amplitude = (pan_amplitude_ - current_pan_amplitude) * sample_inc;
469 poly_float delta_phase_inc = (phase_inc_ - current_phase_inc) * sample_inc;
472 poly_float current_fraction = sample_fraction_;
477 for (
int i = 0; i < num_samples; ++i) {
478 current_phase_inc += delta_phase_inc;
482 poly_float fraction_phase = current_fraction * phase_mult;
486 poly_float t = index_phase - rounded_down_phase + fraction_phase;
499 current_fraction += current_phase_inc;
501 current_fraction -= increment;
503 current_index += increment;
505 poly_mask bounced_mask = done_mask & ~current_bounce & bounce_enabled_mask;
506 poly_mask loop_over_mask = done_mask & (current_bounce | ~bounce_enabled_mask) & loop_enabled_mask;
507 current_bounce = (bounced_mask | current_bounce) & ~loop_over_mask;
509 current_index =
utils::maskLoad(current_index, current_index - audio_length, bounced_mask | loop_over_mask);
510 current_index =
utils::min(audio_length, current_index);
511 current_fraction = current_fraction & ~done_mask;
514 bounce_mask_ = current_bounce;
522 for (
int i = 0; i < num_samples; ++i) {
523 current_pan_amplitude += delta_pan_amplitude;
525 levelled_output[i] = current_pan_amplitude * level * level * raw_output[i];
528 sample_index_ = current_index;
529 sample_fraction_ = current_fraction;
531 phase = phase * (1.0f / audio_length);
534 sample_->markUnused();
541 return input_midi + transpose;
546 if (global_transpose) {
547 pre_add = input_midi;
553 if (transpose_quantize_)
556 last_quantized_transpose_ = snapped;
557 transpose_quantize_ = quantize;
558 return post_add + snapped;
Base class for all signal-processing units in Vital.
Definition processor.h:212
force_inline Input * input(unsigned int index=0) const
Retrieves the Input pointer at a given index.
Definition processor.h:587
force_inline int getSampleRate() const
Retrieves the current (effective) sample rate.
Definition processor.h:326
force_inline poly_mask getResetMask(int input_index) const
Retrieves a mask indicating which voices triggered a note-on event. Compares the input's trigger_valu...
Definition processor.h:360
force_inline Output * output(unsigned int index=0) const
Retrieves the Output pointer at a given index.
Definition processor.h:616
force_inline void clearOutputBufferForReset(poly_mask reset_mask, int input_index, int output_index) const
Clears output samples for voices that are about to be reset, based on the trigger offset.
Definition processor.h:373
static constexpr int kMinSize
Minimum sample size for further downsampling.
Definition sample_source.h:34
force_inline const mono_float * buffer() const
Returns a pointer to the (current) left channel buffer at the base upsample level.
Definition sample_source.h:121
SampleData * current_data_
Pointer to the currently loaded data.
Definition sample_source.h:202
Sample()
Default constructor. Initializes the sample with default noise data.
Definition sample_source.cpp:291
static constexpr int kDefaultSampleLength
Default length for a newly created (noise) sample if none is provided.
Definition sample_source.h:28
static constexpr int kBufferSamples
Extra buffer samples at start and end to avoid interpolation issues.
Definition sample_source.h:32
static constexpr int kUpsampleTimes
Upsampling factor exponent (i.e., 1 << kUpsampleTimes).
Definition sample_source.h:30
void loadSample(const mono_float *buffer, int size, int sample_rate)
Loads a mono sample from raw float data.
Definition sample_source.cpp:295
void init()
Generates default data for the sample (e.g., random noise).
Definition sample_source.cpp:321
std::unique_ptr< SampleData > data_
Owned sample data for this sample.
Definition sample_source.h:204
std::atomic< SampleData * > active_audio_data_
Atomic pointer to data in active use.
Definition sample_source.h:203
std::string name_
The user-facing name of the sample.
Definition sample_source.h:200
void jsonToState(json data)
Restores the sample's state from a JSON object (including audio data).
Definition sample_source.cpp:351
json stateToJson()
Exports the sample state (metadata and sample data) to a JSON object.
Definition sample_source.cpp:333
static constexpr int kNumDownsampleTaps
Number of taps used in the downsampling filter.
Definition sample_source.h:224
static constexpr int kNumUpsampleTaps
Number of taps used in the upsampling filter.
Definition sample_source.h:226
@ kRandomPhase
If true, randomize phase on note start.
Definition sample_source.h:237
@ kLevel
Overall amplitude scale.
Definition sample_source.h:236
@ kKeytrack
Boolean-like input indicating if MIDI note should track pitch.
Definition sample_source.h:235
@ kTune
Fine-tune in cents.
Definition sample_source.h:240
@ kTransposeQuantize
Quantize transposition to scale or semitones.
Definition sample_source.h:239
@ kNoteCount
Tracks how many notes have been pressed.
Definition sample_source.h:244
@ kLoop
If non-zero, the sample loops.
Definition sample_source.h:241
@ kMidi
MIDI note input.
Definition sample_source.h:234
@ kPan
Stereo panning control.
Definition sample_source.h:243
@ kReset
Reset signal (trigger) to re-initialize playback.
Definition sample_source.h:233
@ kBounce
If non-zero, sample playback bounces (back/forth).
Definition sample_source.h:242
@ kTranspose
Transposition in semitones from the current note.
Definition sample_source.h:238
SampleSource()
Default constructor initializes internal state and random generator.
Definition sample_source.cpp:385
virtual void process(int num_samples) override
Processes audio for num_samples, reading from the Sample and applying pitch, loop,...
Definition sample_source.cpp:396
static constexpr mono_float kMaxAmplitude
Maximum amplitude scale (usually sqrt(2) for stereo).
Definition sample_source.h:221
static constexpr mono_float kMinTranspose
Minimum negative transposition in semitones.
Definition sample_source.h:219
@ kRaw
The raw sample output (before final amplitude).
Definition sample_source.h:253
@ kLevelled
The amplitude-scaled output.
Definition sample_source.h:254
static constexpr mono_float kMaxTranspose
Maximum positive transposition in semitones.
Definition sample_source.h:217
A basic random number generator for producing uniform distributions of floats.
Definition utils.h:61
force_inline mono_float next()
Returns the next random float in [min, max].
Definition utils.h:85
#define VITAL_ASSERT(x)
Definition common.h:11
#define force_inline
Definition common.h:23
Contains faster but less accurate versions of utility math functions, such as exponential,...
nlohmann::json json
Definition line_generator.h:7
const poly_mask kFullMask
A mask covering all lanes of a poly_float vector.
Definition synth_constants.h:257
const poly_mask kFirstMask
A mask identifying the first voice slots in a polyphonic vector.
Definition synth_constants.h:266
force_inline poly_float panAmplitude(poly_float pan)
Definition futils.h:439
force_inline poly_float clamp(poly_float value, mono_float min, mono_float max)
Clamps each lane of a vector to [min, max].
Definition poly_utils.h:306
force_inline poly_float toFloat(poly_int integers)
Casts a poly_int to poly_float lane-by-lane.
Definition poly_utils.h:733
force_inline poly_float encodePhaseAndVoice(poly_float phase, poly_float voice)
Encodes a phase [0..1) and a voice index into a single float, storing the voice in the integer portio...
Definition poly_utils.h:979
force_inline bool isTransposeQuantizeGlobal(int quantize)
Checks if the transpose quantize mask applies globally (over multiple octaves).
Definition poly_utils.h:964
force_inline poly_float floor(poly_float value)
Floors each lane in value.
Definition poly_utils.h:777
force_inline poly_float min(poly_float left, poly_float right)
Returns the minimum of two poly_floats lane-by-lane.
Definition poly_utils.h:334
void floatToPcmData(int16_t *pcm_data, const float *float_data, int size)
Converts floating-point audio data to 16-bit PCM data.
Definition utils.cpp:77
force_inline bool isContained(poly_float value)
Checks if all lanes in a poly_float are within a broad range [-8000..8000].
Definition poly_utils.h:631
force_inline poly_float max(poly_float left, poly_float right)
Returns the maximum of two poly_floats lane-by-lane.
Definition poly_utils.h:327
force_inline matrix getCatmullInterpolationMatrix(poly_float t)
Creates a Catmull-Rom interpolation matrix from a poly_float t.
Definition poly_utils.h:227
force_inline matrix getValueMatrix(const mono_float *buffer, poly_int indices)
Creates a matrix of 4 poly_float lanes from a single buffer at varying indices.
Definition poly_utils.h:262
force_inline poly_float snapTranspose(poly_float transpose, int quantize)
Snaps a MIDI transpose value to a quantization mask (e.g., scale degrees).
Definition poly_utils.h:908
force_inline poly_int floorToInt(poly_float value)
Floors each lane and returns the result as an integer.
Definition poly_utils.h:785
force_inline poly_float maskLoad(poly_float zero_value, poly_float one_value, poly_mask reset_mask)
Selects between two values (zero_value or one_value) based on a mask in each lane.
Definition poly_utils.h:351
void pcmToFloatData(float *float_data, const int16_t *pcm_data, int size)
Converts 16-bit PCM data to floating-point audio data.
Definition utils.cpp:94
force_inline poly_float noteOffsetToRatio(poly_float value)
Converts note offsets to frequency ratios. Similar to centsToRatio, but may differ in how offset is d...
Definition poly_utils.h:102
force_inline poly_float centsToRatio(poly_float value)
Converts semitone cents to a linear frequency ratio (vectorized).
Definition poly_utils.h:95
Contains classes and functions used within the Vital synthesizer framework.
constexpr int kDefaultSampleRate
Default sample rate in Hz.
Definition common.h:41
constexpr int kMidiTrackCenter
MIDI note considered as center (Middle C).
Definition common.h:45
constexpr int kCentsPerNote
Number of cents per semitone.
Definition common.h:52
float mono_float
Definition common.h:33
Declares the Sample and SampleSource classes for loading, managing, and playing back audio samples in...
poly_float * buffer
Pointer to the output buffer.
Definition processor.h:110
A structure representing a 4x1 matrix of poly_float rows.
Definition matrix.h:19
force_inline poly_float multiplyAndSumRows(const matrix &other)
Multiplies and sums corresponding rows of this matrix with another matrix.
Definition matrix.h:93
force_inline void transpose()
Transposes the matrix in-place.
Definition matrix.h:44
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
static force_inline mask_simd_type vector_call greaterThanOrEqual(simd_type one, simd_type two)
Compares two SIMD float registers, element-wise, for greater than or equal.
Definition poly_values.h:987
static force_inline poly_mask vector_call lessThan(poly_float one, poly_float two)
Definition poly_values.h:1105
force_inline void vector_call set(size_t index, float new_value) noexcept
Sets a specific element in the SIMD register.
Definition poly_values.h:1182
static force_inline mask_simd_type vector_call greaterThan(simd_type one, simd_type two)
Compares two SIMD float registers, element-wise, for greater than.
Definition poly_values.h:971
Represents a vector of integer values using SIMD instructions.
Definition poly_values.h:56
static force_inline uint32_t vector_call anyMask(simd_type value)
Returns a bitmask that indicates which bytes/elements in the register are non-zero.
Definition poly_values.h:352