| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| #include "DelayLine.h" | ||
|
|
||
| DelayLine::DelayLine(const int buffer_seconds, const int internal_block_size) | ||
| { | ||
| this->buffer_seconds = buffer_seconds; | ||
| this->internal_block_size = internal_block_size; | ||
| highpass_filter = new Filter(); | ||
| initialized = false; | ||
| } | ||
|
|
||
| void DelayLine::initialize(float samplerate) | ||
| { | ||
| deleteBuffers(); | ||
| delay_buffer_length = static_cast<int>(samplerate * buffer_seconds); | ||
| delay_buffer = new float[delay_buffer_length + 3]; | ||
| feedback_buffer = new float[internal_block_size]; | ||
| highpass_filter->initializeHz(100.0f, 0.0f, FILTER_HIGH, samplerate); | ||
| delay_buffer_start = 1; | ||
| delay_write_pos = delay_buffer_start; | ||
| delay_buffer_end = delay_buffer_length; | ||
| feedback_write_pos = 0; | ||
| initialized = true; | ||
|
|
||
| for(int i = 0; i < (delay_buffer_length + 3); i++) | ||
| delay_buffer[i] = 10E-12f; | ||
| for (int i = 0; i < internal_block_size; i++) | ||
| feedback_buffer[i] = 10E-12f; | ||
| } | ||
|
|
||
| DelayLine::~DelayLine() | ||
| { | ||
| deleteBuffers(); | ||
| delete highpass_filter; | ||
| } | ||
|
|
||
| void DelayLine::deleteBuffers() | ||
| { | ||
| if (!initialized) | ||
| return; | ||
| delete[] delay_buffer; | ||
| delete[] feedback_buffer; | ||
| initialized = false; | ||
| } | ||
|
|
||
| void DelayLine::writeDelayBuffer(float* chan1, float* chan2, | ||
| int sampleframes, bool freeze, float input_gain, float feedback_gain) | ||
| { | ||
| block_read_pos = delay_write_pos; | ||
|
|
||
| if (freeze) { | ||
| delay_write_pos += sampleframes; | ||
| if (delay_write_pos > delay_buffer_length) | ||
| delay_write_pos -= delay_buffer_length; | ||
|
|
||
| } else { | ||
| float sample; | ||
| feedback_read_pos = feedback_write_pos; | ||
|
|
||
| for (int i = 0; i < sampleframes; i++) { | ||
| sample = (chan1[i] + chan2[i]) / 2.0f; | ||
| sample *= input_gain; | ||
| sample += feedback_gain * feedback_buffer[feedback_read_pos]; | ||
|
|
||
| delay_buffer[delay_write_pos] = sample; | ||
| feedback_read_pos++; | ||
|
|
||
| if (feedback_read_pos == internal_block_size) { | ||
| feedback_read_pos = 0; | ||
| } | ||
| if (delay_write_pos == delay_buffer_start) { | ||
| delay_buffer[delay_buffer_end + 1] = sample; | ||
| } else if (delay_write_pos == (delay_buffer_start + 1)) { | ||
| delay_buffer[delay_buffer_end + 2] = sample; | ||
| } else if (delay_write_pos == delay_buffer_end) { | ||
| delay_buffer[0] = sample; | ||
| delay_write_pos = (delay_buffer_start - 1); | ||
| } | ||
| delay_write_pos++; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void DelayLine::writeFeedbackBuffer(float* chan1, float* chan2, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| feedback_buffer[feedback_write_pos++] = (chan1[i] + chan2[i]) / 2.0f; | ||
| if (feedback_write_pos == internal_block_size) | ||
| feedback_write_pos = 0; | ||
| } | ||
| highpass_filter->process(feedback_buffer, sampleframes); | ||
| } | ||
|
|
||
| int DelayLine::getDelayLength() | ||
| { | ||
| return delay_buffer_length; | ||
| } | ||
|
|
||
| float* DelayLine::getDelayPointer() | ||
| { | ||
| return delay_buffer; | ||
| } | ||
|
|
||
| /* Returns cached start-position of previously written block */ | ||
| int DelayLine::getBlockReadPos() | ||
| { | ||
| return block_read_pos; | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #ifndef DELAYLINE_H | ||
| #define DELAYLINE_H | ||
|
|
||
| #include "Debug.h" | ||
| #include "Filter.h" | ||
|
|
||
| class DelayLine | ||
| { | ||
| public: | ||
| DelayLine(const int buffer_seconds, const int internal_block_size); | ||
| ~DelayLine(); | ||
| int getBlockReadPos(); | ||
| int getDelayLength(); | ||
| float* getDelayPointer(); | ||
| void initialize(float samplerate); | ||
| void writeFeedbackBuffer(float* chan1, float* chan2, int sampleframes); | ||
| void writeDelayBuffer(float* chan1, float* chan2, int sampleframes, | ||
| bool freeze, float input_gain, float feedback_gain); | ||
|
|
||
| private: | ||
| void deleteBuffers(); | ||
|
|
||
| Filter* highpass_filter; | ||
| float *delay_buffer; | ||
| float *feedback_buffer; | ||
| int delay_buffer_length; | ||
| int delay_buffer_start; | ||
| int delay_buffer_end; | ||
| int delay_write_pos; | ||
| int block_read_pos; | ||
| int feedback_write_pos; | ||
| int feedback_read_pos; | ||
| int buffer_seconds; | ||
| int internal_block_size; | ||
| bool initialized; | ||
| }; | ||
|
|
||
| #endif //DELAYLINE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| #include "Envelope.h" | ||
|
|
||
| Envelope::Envelope() | ||
| { | ||
| pi = 4.0f * atan(1.0f); | ||
| } | ||
|
|
||
| void Envelope::initialize(int env_type, int grain_dur, float grain_dur_ratio, | ||
| float env_shape, float env_skew, float grain_amp) | ||
| { | ||
| this->env_type = env_type; | ||
| this->grain_amp = grain_amp; | ||
| process_counter = 0; | ||
| env_amp = 0.0f; | ||
| env_shape = env_shape * 0.9f + 0.05f; | ||
| env_skew = env_skew * 0.9f + 0.05f; | ||
|
|
||
| if (env_type == ENV_PARABOLIC) { | ||
| float d = 1.0f / grain_dur; | ||
| float d2 = d * d; | ||
| slope = 4.0f * grain_amp * (d - d2); | ||
| curve = -8.0f * grain_amp * d2; | ||
|
|
||
| } else if (env_type == ENV_TRIANGLE) { | ||
| triangle_midpoint = static_cast<int>(grain_dur * env_skew); | ||
| triangle_attack_increment = grain_amp / triangle_midpoint; | ||
| triangle_decay_increment = grain_amp / (grain_dur - triangle_midpoint); | ||
|
|
||
| } else if (env_type == ENV_RCB) { | ||
| // reduce skew for shorter grains | ||
| env_skew = 0.5f + ((env_skew - 0.5f) * grain_dur_ratio); | ||
| // reduce sustain for shorter grains | ||
| sustain_samples = static_cast<int>(env_shape * grain_dur_ratio * grain_dur); | ||
| attack_samples = static_cast<int>(env_skew * (grain_dur - sustain_samples)); | ||
| release_samples = grain_dur - sustain_samples - attack_samples; | ||
| attack_angle = pi; | ||
| attack_angle_increment = pi / attack_samples; | ||
| release_angle = 0.0f; | ||
| release_angle_increment = pi / release_samples; | ||
| release_boundary = attack_samples + sustain_samples; | ||
| } | ||
| } | ||
|
|
||
| void Envelope::process(float* input, int sampleframes) | ||
| { | ||
| switch(env_type) { | ||
| case ENV_PARABOLIC: | ||
| processParabolic(input, sampleframes); | ||
| break; | ||
| case ENV_TRIANGLE: | ||
| processTriangle(input, sampleframes); | ||
| break; | ||
| case ENV_RCB: | ||
| processRCB(input, sampleframes); | ||
| } | ||
| } | ||
|
|
||
| void Envelope::processParabolic(float* input, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| env_amp += slope; | ||
| slope += curve; | ||
| input[i] *= env_amp; | ||
| } | ||
| } | ||
|
|
||
| void Envelope::processTriangle(float* input, int sampleframes) | ||
| { | ||
| int blockEnd = (process_counter + sampleframes); | ||
|
|
||
| if (blockEnd < triangle_midpoint) { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| env_amp += triangle_attack_increment; | ||
| input[i] *= env_amp; | ||
| } | ||
| } else if (process_counter >= triangle_midpoint | ||
| && blockEnd < duration) { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| env_amp -= triangle_decay_increment; | ||
| input[i] *= env_amp; | ||
| } | ||
| } else { | ||
| processTriangleBoundary(input, sampleframes); | ||
| return; | ||
| } | ||
| process_counter += sampleframes; | ||
| } | ||
|
|
||
| void Envelope::processTriangleBoundary(float* input, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| if (process_counter < triangle_midpoint) { | ||
| env_amp += triangle_attack_increment; | ||
| } else { | ||
| env_amp -= triangle_decay_increment; | ||
| } | ||
| input[i] *= env_amp; | ||
| process_counter++; | ||
| } | ||
| } | ||
|
|
||
| void Envelope::processRCB(float* input, int sampleframes) | ||
| { | ||
| int blockEnd = (process_counter + sampleframes); | ||
|
|
||
| if (blockEnd < attack_samples) { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| input[i] *= grain_amp * (0.5f + 0.5f * fastCosine(attack_angle)); | ||
| attack_angle += attack_angle_increment; | ||
| } | ||
| } else if (process_counter >= attack_samples | ||
| && blockEnd < release_boundary) { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| input[i] *= grain_amp; | ||
| } | ||
| } else if (process_counter >= release_boundary | ||
| && blockEnd < duration) { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| input[i] *= grain_amp * (0.5f + 0.5f * fastCosine(release_angle)); | ||
| release_angle += release_angle_increment; | ||
| } | ||
| } else { | ||
| processRCBBoundary(input, sampleframes); | ||
| return; | ||
| } | ||
| process_counter += sampleframes; | ||
| } | ||
|
|
||
| void Envelope::processRCBBoundary(float* input, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| if (process_counter < attack_samples) { | ||
| input[i] *= grain_amp * (0.5f + 0.5f * fastCosine(attack_angle)); | ||
| attack_angle += attack_angle_increment; | ||
| } else if (process_counter < release_boundary) { | ||
| input[i] *= grain_amp; | ||
| } else { | ||
| input[i] *= grain_amp * (0.5f + 0.5f * fastCosine(release_angle)); | ||
| release_angle += release_angle_increment; | ||
| } | ||
| process_counter++; | ||
| } | ||
| } | ||
|
|
||
| inline float Envelope::fastCosine(float angle) | ||
| { | ||
| angle += 1.57079632f; | ||
| if (angle > 3.14159265f) { | ||
| angle -= 6.28318531f; | ||
| } | ||
| if (angle < 0) { | ||
| return 1.273239545f * angle + 0.405284735f * angle * angle; | ||
| } else { | ||
| return 1.273239545f * angle - 0.405284735f * angle * angle; | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #ifndef ENVELOPE_H | ||
| #define ENVELOPE_H | ||
|
|
||
| #include <math.h> | ||
| #include "Debug.h" | ||
|
|
||
| enum EnvType { | ||
| ENV_RCB, | ||
| ENV_PARABOLIC, | ||
| ENV_TRIANGLE | ||
| }; | ||
|
|
||
| class Envelope | ||
| { | ||
| public: | ||
| Envelope(); | ||
| void process(float* input, int sampleframes); | ||
| void initialize(int env_type, int grain_dur, float grain_dur_ratio, | ||
| float env_shape, float env_skew, float grain_amp); | ||
|
|
||
| private: | ||
| void processParabolic(float* input, int sampleframes); | ||
| void processTriangle(float* input, int sampleframes); | ||
| void processTriangleBoundary(float* input, int sampleframes); | ||
| void processRCB(float* input, int sampleframes); | ||
| void processRCBBoundary(float* input, int sampleframes); | ||
| inline float fastCosine(float angle); | ||
|
|
||
| float pi; | ||
| float env_amp, grain_amp; | ||
| int env_type; | ||
| int process_counter; | ||
| int duration; | ||
| // parabolic | ||
| float slope, curve; | ||
| // raised cosine bell | ||
| float attack_angle, attack_angle_increment, release_angle, release_angle_increment; | ||
| int attack_samples, sustain_samples, release_samples, release_boundary; | ||
| // triangle | ||
| float triangle_attack_increment; | ||
| float triangle_decay_increment; | ||
| int triangle_midpoint; | ||
| }; | ||
|
|
||
| #endif //ENVELOPE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| #include "Filter.h" | ||
|
|
||
|
|
||
| Filter::Filter() | ||
| { | ||
| pi = 4.0f * atan(1.0f); | ||
| } | ||
|
|
||
| // valid params between 0.0f - 1.0f | ||
| void Filter::initialize(float freq_param, float q_param, int type, float samplerate) | ||
| { | ||
| float freq_hz = pow(10.0f, freq_param * 3.0f) * 22.05f; | ||
| freq = sin(pi * freq_hz / samplerate); | ||
| q = sqrt(1.0f - atan(sqrt(100.0f * q_param)) * 2.0f / pi); | ||
| scale = sqrt(q); | ||
| low = high = band = 0.0f; | ||
| this->type = type; | ||
| } | ||
|
|
||
| // valid freq_hz between 22.05f - 22050.0f | ||
| void Filter::initializeHz(float freq_hz, float q_param, int type, float samplerate) | ||
| { | ||
| freq = sin(pi * freq_hz / samplerate); | ||
| q = sqrt(1.0f - atan(sqrt(100.0f * q_param)) * 2.0f / pi); | ||
| scale = sqrt(q); | ||
| low = high = band = 0.0f; | ||
| this->type = type; | ||
| } | ||
|
|
||
| void Filter::process(float* input, int sampleframes) | ||
| { | ||
| switch (type) { | ||
| case FILTER_BAND: | ||
| processBand(input, sampleframes); | ||
| return; | ||
| case FILTER_LOW: | ||
| processLow(input, sampleframes); | ||
| return; | ||
| case FILTER_HIGH: | ||
| processHigh(input, sampleframes); | ||
| return; | ||
| case FILTER_NOTCH: | ||
| processNotch(input, sampleframes); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| inline void Filter::algorithm(float input) | ||
| { | ||
| // 2x oversampling | ||
| low = low + freq * band; | ||
| high = scale * input - low - q * band; | ||
| band = freq * high + band; | ||
|
|
||
| low = low + freq * band; | ||
| high = scale * input - low - q * band; | ||
| band = freq * high + band; | ||
| } | ||
|
|
||
| void Filter::processBand(float* input, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| algorithm(input[i]); | ||
| input[i] = band; | ||
| } | ||
| } | ||
|
|
||
| void Filter::processLow(float* input, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| algorithm(input[i]); | ||
| input[i] = low; | ||
| } | ||
| } | ||
|
|
||
| void Filter::processHigh(float* input, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| algorithm(input[i]); | ||
| input[i] = high; | ||
| } | ||
| } | ||
|
|
||
| void Filter::processNotch(float* input, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| algorithm(input[i]); | ||
| input[i] = high + low; | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #ifndef FILTER_H | ||
| #define FILTER_H | ||
|
|
||
| #include <math.h> | ||
| #include "Debug.h" | ||
|
|
||
| enum FilterMode { | ||
| FILTER_OFF, | ||
| FILTER_BAND, | ||
| FILTER_LOW, | ||
| FILTER_HIGH, | ||
| FILTER_NOTCH, | ||
| FILTER_COMB, | ||
| FILTER_RANDOM | ||
| }; | ||
|
|
||
| class Filter | ||
| { | ||
| public: | ||
| Filter(); | ||
| void initialize(float freq_param, float q_param, int type, float samplerate); | ||
| void initializeHz(float freq_hz, float q_param, int type, float samplerate); | ||
| void process(float* input, int sampleframes); | ||
|
|
||
| private: | ||
| inline void algorithm(float input); | ||
| void processHigh(float* input, int sampleframes); | ||
| void processLow(float* input, int sampleframes); | ||
| void processBand(float* input, int sampleframes); | ||
| void processNotch(float* input, int sampleframes); | ||
|
|
||
| float pi, low, high, band, freq, q, scale; | ||
| int type; | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| #include "Grain.h" | ||
|
|
||
| Grain::Grain(const float samplerate, const int buflen, const int internal_block_size, | ||
| float* buffer, float* out1, float* out2) | ||
| { | ||
| this->samplerate = samplerate; | ||
| this->buflen = buflen; | ||
| this->internal_block_size = internal_block_size; | ||
| this->buffer = buffer; | ||
| this->out1 = out1; | ||
| this->out2 = out2; | ||
| activated = false; | ||
| initialized = false; | ||
| marked_for_deactivation = false; | ||
| comb_filter = new CombFilter(samplerate); | ||
| env = new Envelope(); | ||
| multimode_filter = new Filter(); | ||
| output_buffer = new float[internal_block_size]; | ||
| } | ||
|
|
||
| Grain::~Grain() | ||
| { | ||
| delete comb_filter; | ||
| delete env; | ||
| delete multimode_filter; | ||
| delete[] output_buffer; | ||
| } | ||
|
|
||
| void Grain::activate() | ||
| { | ||
| activated = true; | ||
| initialized = false; | ||
| marked_for_deactivation = false; | ||
| } | ||
|
|
||
| void Grain::deactivate() | ||
| { | ||
| if (initialized) { | ||
| marked_for_deactivation = true; | ||
| } else { | ||
| activated = false; | ||
| } | ||
| } | ||
|
|
||
| inline void Grain::incrementReadPos() | ||
| { | ||
| delaybuf_readpos_int++; | ||
| if (delaybuf_readpos_int > buflen) | ||
| delaybuf_readpos_int -= buflen; | ||
| } | ||
|
|
||
| inline void Grain::incrementReadPosFrac() | ||
| { | ||
| delaybuf_readpos_float += trans; | ||
| delaybuf_readpos_int = static_cast<int>(delaybuf_readpos_float); | ||
| if (delaybuf_readpos_int > buflen) { | ||
| delaybuf_readpos_float -= buflen; | ||
| delaybuf_readpos_int = static_cast<int>(delaybuf_readpos_float); | ||
| } | ||
| trans += gliss; | ||
| } | ||
|
|
||
| void Grain::initialize(const GrainParameters& grain_parameters) | ||
| { | ||
| amp = grain_parameters.amp; | ||
| delaybuf_readpos_int = grain_parameters.bufstart; | ||
| delaybuf_readpos_float = static_cast<float>(grain_parameters.bufstart); | ||
| duration = grain_parameters.duration; | ||
| filter_type = grain_parameters.filter_type; | ||
| gliss = grain_parameters.gliss; | ||
| gliss_enabled = (gliss == 0.0f) ? false : true; | ||
| iot = grain_parameters.iot; | ||
| pan_left = grain_parameters.pan; | ||
| pan_right = 1.0f - grain_parameters.pan; | ||
| trans = grain_parameters.trans; | ||
|
|
||
| switch(filter_type) { | ||
| case FILTER_OFF: | ||
| break; | ||
| case FILTER_COMB: | ||
| comb_filter->initialize(grain_parameters.ffreq, grain_parameters.fq); | ||
| break; | ||
| default: | ||
| multimode_filter->initialize(grain_parameters.ffreq,grain_parameters.fq, | ||
| filter_type, samplerate); | ||
| break; | ||
| } | ||
|
|
||
| env->initialize(grain_parameters.env_type, | ||
| duration, | ||
| grain_parameters.duration_ratio, | ||
| grain_parameters.env_shape, | ||
| grain_parameters.env_skew, | ||
| amp); | ||
|
|
||
| for (int i = 0; i < internal_block_size; i++) | ||
| output_buffer[i] = 10E-12f; | ||
|
|
||
| process_counter = 0; | ||
| initialized = true; | ||
| } | ||
|
|
||
| void Grain::process(int sampleframes) | ||
| { | ||
| if (iot > 0) { | ||
| iot -= sampleframes; | ||
| if (iot < 0) { | ||
| sampleframes = -iot; | ||
| } else { | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| int block_end = process_counter + sampleframes; | ||
| if (block_end <= duration) { | ||
| readBuffer(sampleframes); | ||
| } else { | ||
| int intrablock_offset = duration - process_counter; | ||
| readBuffer(intrablock_offset); | ||
| for (int i = sampleframes; i < internal_block_size; i++) { | ||
| output_buffer[i] = 10E-12f; | ||
| } | ||
| if (marked_for_deactivation) { | ||
| activated = false; | ||
| marked_for_deactivation = false; | ||
| } | ||
| initialized = false; | ||
| return; | ||
| } | ||
|
|
||
| if (filter_type != FILTER_OFF && filter_type != FILTER_COMB) | ||
| multimode_filter->process(output_buffer, sampleframes); | ||
|
|
||
| env->process(output_buffer, sampleframes); | ||
|
|
||
| // comb filter generally sounds better post-envelope | ||
| if (filter_type == FILTER_COMB) | ||
| comb_filter->process(output_buffer, sampleframes); | ||
|
|
||
| for (int i = 0; i < sampleframes; i++) { | ||
| out1[i] += (output_buffer[i] * pan_right); | ||
| out2[i] += (output_buffer[i] * pan_left); | ||
| } | ||
| } | ||
|
|
||
| void Grain::readBuffer(int sampleframes) | ||
| { | ||
| if ((trans != 1.0f) || gliss_enabled) { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| output_buffer[i] = cubicInterpolation( | ||
| (delaybuf_readpos_float - delaybuf_readpos_int), | ||
| buffer[delaybuf_readpos_int - 1], | ||
| buffer[delaybuf_readpos_int], | ||
| buffer[delaybuf_readpos_int + 1], | ||
| buffer[delaybuf_readpos_int + 2]); | ||
| incrementReadPosFrac(); | ||
| } | ||
| } else { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| output_buffer[i] = buffer[delaybuf_readpos_int]; | ||
| incrementReadPos(); | ||
| } | ||
| } | ||
| process_counter += sampleframes; | ||
| } | ||
|
|
||
| inline float Grain::cubicInterpolation(float frac, float y0, float y1, float y2, float y3) | ||
| { | ||
| c1 = 0.5f * (y2 - y0); | ||
| c3 = 1.5f * (y1 - y2) + 0.5f * (y3 - y0); | ||
| c2 = y0 - y1 + c1 - c3; | ||
| return ((c3 * frac + c2) * frac + c1) * frac + y1; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| #ifndef GRAIN_H | ||
| #define GRAIN_H | ||
|
|
||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include "Debug.h" | ||
| #include "CombFilter.h" | ||
| #include "Envelope.h" | ||
| #include "Filter.h" | ||
| #include "GrainParameters.h" | ||
| #include "Misc.h" | ||
|
|
||
| class Grain | ||
| { | ||
| public: | ||
| Grain(const float samplerate, const int buflen, const int internal_block_size, | ||
| float* buffer, float* out1, float* out2); | ||
| ~Grain(); | ||
| void initialize(const GrainParameters& grain_parameters); | ||
| void process(int sampleframes); | ||
| void activate(); | ||
| void deactivate(); | ||
|
|
||
| bool activated, initialized; | ||
| int iot; | ||
| bool finished_processing; | ||
|
|
||
| private: | ||
| void readBuffer(int sampleframes); | ||
| inline void incrementReadPos(); | ||
| inline void incrementReadPosFrac(); | ||
| inline float cubicInterpolation(float frac, float y0, float y1, float y2, float y3); | ||
|
|
||
| int internal_block_size; | ||
| int duration, env_type, process_counter, buflen, buf_end, filter_type, delaybuf_readpos_int; | ||
| float amp, pan_left, pan_right, trans, gliss, delaybuf_readpos_float, env_amp; | ||
| float *output_buffer; | ||
| float frac, c1, c2, c3; // interpolation | ||
| float *buffer, *out1, *out2; | ||
| float samplerate; | ||
| bool gliss_enabled; | ||
| bool marked_for_deactivation; | ||
| Filter* multimode_filter; | ||
| CombFilter* comb_filter; | ||
| Envelope* env; | ||
| }; | ||
|
|
||
| #endif //GRAIN_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #ifndef GRAINPARAMETERS_H | ||
| #define GRAINPARAMETERS_H | ||
|
|
||
| struct GrainParameters { | ||
| int iot; | ||
| int duration; | ||
| int bufstart; | ||
| int filter_type; | ||
| int env_type; | ||
| float amp; | ||
| float pan; | ||
| float duration_ratio; | ||
| float trans; | ||
| float gliss; | ||
| float ffreq; | ||
| float fq; | ||
| float env_shape; | ||
| float env_skew; | ||
| }; | ||
|
|
||
| #endif //GRAINPARAMETERS_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,383 @@ | ||
| #include "GrainParametersGenerator.h" | ||
|
|
||
| GrainParametersGenerator::GrainParametersGenerator(Parameters* parameters, | ||
| DelayLine* delay_line, | ||
| Granulator* granulator, | ||
| const int internal_block_size) | ||
| { | ||
| this->parameters = parameters; | ||
| this->delay_line = delay_line; | ||
| this->granulator = granulator; | ||
| this->time_quantizer = parameters->time_quantizer; | ||
| this->internal_block_size = internal_block_size; | ||
| random = new Random(Time::currentTimeMillis()); | ||
| pitch_quantizer = new PitchQuantizer(); | ||
| } | ||
|
|
||
| GrainParametersGenerator::~GrainParametersGenerator() | ||
| { | ||
| delete random; | ||
| delete pitch_quantizer; | ||
| } | ||
|
|
||
| const GrainParameters GrainParametersGenerator::getNewGrainParameters() | ||
| { | ||
| copyExternalParametersToInstanceVariables(); | ||
| generateRandomizedParameters(); | ||
| for (int i = 0; i < 3; i++) | ||
| applyModMatrix(i); | ||
| return generateFinalParameters(); | ||
| } | ||
|
|
||
| void GrainParametersGenerator::copyExternalParametersToInstanceVariables() | ||
| { | ||
| mix = parameters->param[kMix]; | ||
| input_gain = parameters->param[kIngain]; | ||
| grains = parameters->param[kGrains]; | ||
| feedback = parameters->param[kFeedback]; | ||
| amp_min = parameters->param[kAmp]; | ||
| delay_min = parameters->param[kDelay]; | ||
| iot_min = parameters->param[kIot]; | ||
| dur_min = parameters->param[kDur]; | ||
| ffreq_min = parameters->param[kFfreq]; | ||
| fq_min = parameters->param[kFq]; | ||
| env_shape = parameters->param[kEnvSustain]; | ||
| env_skew = parameters->param[kEnvSkew]; | ||
| trans_toggle = parameters->param[kTransToggle]; | ||
| gliss_toggle = parameters->param[kGlissToggle]; | ||
| freeze_toggle = parameters->param[kFreezeToggle]; | ||
| matrixmod1 = parameters->param[kMatrixMod1]; | ||
| matrixmod2 = parameters->param[kMatrixMod2]; | ||
| matrixmod3 = parameters->param[kMatrixMod3]; | ||
| } | ||
|
|
||
| void GrainParametersGenerator::generateRandomizedParameters() | ||
| { | ||
| //============= Amp ============= | ||
| amp_value = amp_min + random->nextFloat() | ||
| * (parameters->amp_max - amp_min); | ||
| //============= Pan ============= | ||
| pan_value = parameters->pan_min + random->nextFloat() | ||
| * (parameters->pan_max - parameters->pan_min); | ||
| //============= Delay ============= | ||
| delay_value = delay_min + random->nextFloat() | ||
| * (parameters->delay_max - delay_min); | ||
| //============= IOT ============= | ||
| iot_value = iot_min + random->nextFloat() | ||
| * (parameters->iot_max - iot_min); | ||
| //============= Duration ============= | ||
| dur_value = dur_min + random->nextFloat() | ||
| * (parameters->dur_max - dur_min); | ||
| //============= Transposition ============= | ||
| trans_value = parameters->trans_min + random->nextFloat() | ||
| * (parameters->trans_max - parameters->trans_min); | ||
| //============= Glissando ============= | ||
| gliss_value = parameters->gliss_min + random->nextFloat() | ||
| * (parameters->gliss_max - parameters->gliss_min); | ||
| //============= Filter ============= | ||
| if (parameters->filter_type == FILTER_RANDOM) { | ||
| grain_parameters.filter_type = random->nextInt(5); | ||
| } else { | ||
| grain_parameters.filter_type = parameters->filter_type; | ||
| } | ||
| if (grain_parameters.filter_type != FILTER_OFF) { | ||
| ffreq_value = ffreq_min + random->nextFloat() | ||
| * (parameters->ffreq_max - ffreq_min); | ||
| fq_value = fq_min + random->nextFloat() | ||
| * (parameters->fq_max - fq_min); | ||
| } | ||
| } | ||
|
|
||
| bool GrainParametersGenerator::modSourceEqualsDest(ModSource source, ModDest dest) | ||
| { | ||
| switch (source) { | ||
| case MOD_SRC_AMP: | ||
| if (dest == MOD_DEST_AMP) | ||
| return true; | ||
| break; | ||
| case MOD_SRC_PAN_LR: | ||
| case MOD_SRC_PAN_WIDTH: | ||
| if (dest == MOD_DEST_PAN_LR) | ||
| return true; | ||
| break; | ||
| case MOD_SRC_DELAY: | ||
| if (dest == MOD_DEST_DELAY) | ||
| return true; | ||
| break; | ||
| case MOD_SRC_IOT: | ||
| if (dest == MOD_DEST_IOT) | ||
| return true; | ||
| break; | ||
| case MOD_SRC_DUR: | ||
| if (dest == MOD_DEST_DUR) | ||
| return true; | ||
| break; | ||
| case MOD_SRC_TRANS: | ||
| if (dest == MOD_DEST_TRANS) | ||
| return true; | ||
| break; | ||
| case MOD_SRC_GLISS: | ||
| if (dest == MOD_DEST_GLISS) | ||
| return true; | ||
| break; | ||
| case MOD_SRC_FFREQ: | ||
| if (dest == MOD_DEST_FFREQ) | ||
| return true; | ||
| break; | ||
| case MOD_SRC_FQ: | ||
| default: | ||
| if (dest == MOD_DEST_FQ) | ||
| return true; | ||
| break; | ||
|
|
||
| } | ||
| return false; | ||
| } | ||
|
|
||
| float GrainParametersGenerator::getModSourceValue(ModSource source, ModMode mode) | ||
| { | ||
| if (mode == MOD_MODE_DIRECT) { | ||
| switch (source) { | ||
| case MOD_SRC_AMP: | ||
| return amp_value; | ||
| case MOD_SRC_PAN_LR: | ||
| return pan_value; | ||
| case MOD_SRC_PAN_WIDTH: | ||
| return fabs((pan_value - 0.5f) * 2.0f); | ||
| case MOD_SRC_DELAY: | ||
| return delay_value; | ||
| case MOD_SRC_IOT: | ||
| return iot_value; | ||
| case MOD_SRC_DUR: | ||
| return dur_value; | ||
| case MOD_SRC_TRANS: | ||
| return trans_value; | ||
| case MOD_SRC_GLISS: | ||
| return gliss_value; | ||
| case MOD_SRC_FFREQ: | ||
| return ffreq_value; | ||
| case MOD_SRC_FQ: | ||
| default: | ||
| return fq_value; | ||
| } | ||
| } else if (mode == MOD_MODE_SCALED) { | ||
| float denominator; | ||
|
|
||
| switch (source) { | ||
| case MOD_SRC_AMP: | ||
| denominator = (parameters->amp_max - amp_min); | ||
| if (denominator == 0.0f) break; | ||
| return (amp_value - amp_min) / denominator; | ||
| case MOD_SRC_PAN_LR: | ||
| denominator = (parameters->pan_max - parameters->pan_min); | ||
| if (denominator == 0.0f) break; | ||
| return (pan_value - parameters->pan_min) / denominator; | ||
| case MOD_SRC_PAN_WIDTH: { | ||
| denominator = (parameters->pan_max - parameters->pan_min); | ||
| if (denominator == 0.0f) break; | ||
| float modvalue = (pan_value - parameters->pan_min) / denominator; | ||
| return fabs((modvalue - 0.5f) * 2.0f); | ||
| } | ||
| case MOD_SRC_DELAY: | ||
| denominator = (parameters->delay_max - delay_min); | ||
| if (denominator == 0.0f) break; | ||
| return (delay_value - delay_min) / denominator; | ||
| case MOD_SRC_IOT: | ||
| denominator = (parameters->iot_max - iot_min); | ||
| if (denominator == 0.0f) break; | ||
| return (iot_value - iot_min) / denominator; | ||
| case MOD_SRC_DUR: | ||
| denominator = (parameters->dur_max - dur_min); | ||
| if (denominator == 0.0f) break; | ||
| return (dur_value - dur_min) / denominator; | ||
| case MOD_SRC_TRANS: | ||
| denominator = (parameters->trans_max - parameters->trans_min); | ||
| if (denominator == 0.0f) break; | ||
| return (trans_value - parameters->trans_min) / denominator; | ||
| case MOD_SRC_GLISS: | ||
| denominator = (parameters->gliss_max - parameters->gliss_min); | ||
| if (denominator == 0.0f) break; | ||
| return (gliss_value - parameters->gliss_min) / denominator; | ||
| case MOD_SRC_FFREQ: | ||
| denominator = (parameters->ffreq_max - ffreq_min); | ||
| if (denominator == 0.0f) break; | ||
| return (ffreq_value - ffreq_min) / denominator; | ||
| case MOD_SRC_FQ: | ||
| default: | ||
| denominator = (parameters->fq_max - fq_min); | ||
| if (denominator == 0.0f) break; | ||
| return (fq_value - fq_min) / denominator; | ||
| } | ||
| } | ||
| return -100.0f; | ||
| } | ||
|
|
||
| float* GrainParametersGenerator::getModDestPtr(ModDest dest) | ||
| { | ||
| switch (dest) { | ||
| case MOD_DEST_AMP: | ||
| return &_value; | ||
| case MOD_DEST_PAN_LR: | ||
| return &pan_value; | ||
| case MOD_DEST_DELAY: | ||
| return &delay_value; | ||
| case MOD_DEST_IOT: | ||
| return &iot_value; | ||
| case MOD_DEST_DUR: | ||
| return &dur_value; | ||
| case MOD_DEST_TRANS: | ||
| return &trans_value; | ||
| case MOD_DEST_GLISS: | ||
| return &gliss_value; | ||
| case MOD_DEST_FFREQ: | ||
| return &ffreq_value; | ||
| case MOD_DEST_FQ: | ||
| return &fq_value; | ||
| case MOD_DEST_SUSTAIN: | ||
| return &env_shape; | ||
| case MOD_DEST_SKEW: | ||
| default: | ||
| return &env_skew; | ||
| } | ||
| } | ||
|
|
||
| void GrainParametersGenerator::applyModMatrix(int index) | ||
| { | ||
| float* dest_ptr; | ||
| float source_value = 0.0f; | ||
| float mod = 0.0f; | ||
| float ratio = 0.0f; | ||
| ModSource mod_source = parameters->matrix_source[index]; | ||
| ModDest mod_dest = parameters->matrix_dest[index]; | ||
| ModMode mod_mode = parameters->matrix_mode[index]; | ||
|
|
||
| if (mod_source == MOD_SRC_OFF || mod_dest == MOD_DEST_OFF) | ||
| return; | ||
| if (modSourceEqualsDest(mod_source, mod_dest)) | ||
| return; | ||
| source_value = getModSourceValue(mod_source, mod_mode); | ||
| if (source_value == -100.0f) | ||
| return; | ||
| dest_ptr = getModDestPtr(mod_dest); | ||
|
|
||
| switch (index) { | ||
| case 0: | ||
| mod = matrixmod1; | ||
| break; | ||
| case 1: | ||
| mod = matrixmod2; | ||
| break; | ||
| case 2: | ||
| mod = matrixmod3; | ||
| break; | ||
| } | ||
| mod = (mod * 2.0f) - 1.0f; | ||
| ratio = fabs(mod); | ||
| if (mod < 0.0f) { | ||
| mod = ratio * (1.0f - source_value); | ||
| } else { | ||
| mod = ratio * source_value; | ||
| } | ||
| *dest_ptr = (*dest_ptr * (1.0f - ratio)) + mod; | ||
| } | ||
|
|
||
| const GrainParameters GrainParametersGenerator::generateFinalParameters() | ||
| { | ||
| float millisecond_samples = parameters->getSampleRate() / 1000.0f; | ||
| //============= Amp ============= | ||
| grain_parameters.amp = amp_value; | ||
| //============= Pan ============= | ||
| grain_parameters.pan = pan_value; | ||
| //============= IOT ============= | ||
| if (time_quantizer->getQuantizeMode(kIotQuant) == QUANT_MS) { | ||
| grain_parameters.iot = static_cast<int>( | ||
| parameters->getIOTMilliseconds(iot_value) * millisecond_samples); | ||
| } else { | ||
| grain_parameters.iot = | ||
| parameters->time_quantizer->quantizeStartPos(kIotQuant, iot_value); | ||
| } | ||
| //============= Duration ============= | ||
| grain_parameters.duration_ratio = dur_value; | ||
|
|
||
| if (time_quantizer->getQuantizeMode(kDurQuant) == QUANT_MS) { | ||
| grain_parameters.duration = static_cast<int>( | ||
| parameters->getDurMilliseconds(dur_value) * millisecond_samples); | ||
| } else if (time_quantizer->getQuantizeMode(kDurQuant) == QUANT_MS_LONG) { | ||
| grain_parameters.duration = static_cast<int>( | ||
| parameters->getDurMilliseconds(dur_value) * millisecond_samples); | ||
| grain_parameters.duration *= 10; | ||
| } else { | ||
| grain_parameters.duration = | ||
| parameters->time_quantizer->quantizeLength(kDurQuant, dur_value); | ||
| } | ||
| //============= Transposition ============= | ||
| if (trans_toggle == 0.0f) { | ||
| grain_parameters.trans = 1.0f; | ||
| } else if (parameters->scale == 0) { | ||
| grain_parameters.trans = pow(2.0f, (trans_value - 0.5f) * 4.0f); | ||
| } else { | ||
| grain_parameters.trans = pitch_quantizer->getQuantizedPitch( | ||
| (parameters->scale - 1), parameters->scale_key, trans_value); | ||
| trans_value = 0.25f * static_cast<float>((log(grain_parameters.trans) | ||
| / log(2.0)) + 2.0); | ||
| } | ||
| //============= Glissando ============= | ||
| float glissTrans = grain_parameters.trans; | ||
| if (gliss_toggle > 0.0f) { | ||
| if (trans_toggle > 0.0f) { | ||
| gliss_value = trans_value + (gliss_value - 0.5f); | ||
| } | ||
| if (gliss_value > 1.0f) { | ||
| gliss_value = 1.0f; | ||
| } else if (gliss_value < 0.0f) { | ||
| gliss_value = 0.0f; | ||
| } | ||
| glissTrans = pow(2.0f, (gliss_value - 0.5f) * 4.0f); | ||
| grain_parameters.gliss = (glissTrans - grain_parameters.trans) | ||
| / grain_parameters.duration; | ||
| } else { | ||
| grain_parameters.gliss = 0.0f; | ||
| } | ||
| //============= Delay ============= | ||
| int delay; | ||
| if (time_quantizer->getQuantizeMode(kDelayQuant) == QUANT_MS) { | ||
| delay = static_cast<int>( | ||
| parameters->getDelayMilliseconds(delay_value) * millisecond_samples); | ||
| } else { | ||
| delay = time_quantizer->quantizeStartPos(kDelayQuant, delay_value); | ||
| } | ||
| // increase delay if transposition increased | ||
| float highestTrans; | ||
| if (gliss_toggle == 1.0f && gliss_value != trans_value) { | ||
| highestTrans = (grain_parameters.trans > glissTrans) ? | ||
| grain_parameters.trans : glissTrans; | ||
| } else { | ||
| highestTrans = grain_parameters.trans; | ||
| } | ||
| if (highestTrans > 1.0f) { | ||
| delay += static_cast<int>((highestTrans-1.0f) * grain_parameters.duration); | ||
| } | ||
| //============= Envelope ============= | ||
| grain_parameters.env_type = parameters->env_type; | ||
| grain_parameters.env_shape = env_shape; | ||
| grain_parameters.env_skew = env_skew; | ||
| //============= Filter ============= | ||
| grain_parameters.ffreq = ffreq_value; | ||
| grain_parameters.fq = fq_value; | ||
| //============= bufstart ============= | ||
| int buflen = delay_line->getDelayLength(); | ||
| int maxdelay = buflen - internal_block_size; | ||
| if (delay > maxdelay) | ||
| delay = maxdelay; | ||
| grain_parameters.bufstart = static_cast<int>(delay_line->getBlockReadPos() | ||
| + grain_parameters.iot | ||
| - delay); | ||
| if (grain_parameters.bufstart < 1) { | ||
| grain_parameters.bufstart += buflen; | ||
| } else if (grain_parameters.bufstart >= buflen) { | ||
| grain_parameters.bufstart -= buflen; | ||
| } | ||
| return grain_parameters; | ||
| } | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| #ifndef GRAINPARAMETERSGENERATOR_H | ||
| #define GRAINPARAMETERSGENERATOR_H | ||
|
|
||
| #include <math.h> | ||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include "GrainParameters.h" | ||
| #include "Granulator.h" | ||
| #include "Misc.h" | ||
| #include "ParametersEnum.h" | ||
| #include "TimeQuantizer.h" | ||
|
|
||
| class DelayLine; | ||
| class Granulator; | ||
| class Parameters; | ||
| class TimeQuantizer; | ||
| class PitchQuantizer; | ||
|
|
||
| class GrainParametersGenerator | ||
| { | ||
| public: | ||
| GrainParametersGenerator(Parameters* parameters, DelayLine* delay_line, Granulator* granulator, | ||
| const int internal_block_size); | ||
| ~GrainParametersGenerator(); | ||
| const GrainParameters getNewGrainParameters(); | ||
|
|
||
| PitchQuantizer* pitch_quantizer; | ||
|
|
||
| private: | ||
| bool modSourceEqualsDest(ModSource source, ModDest dest); | ||
| float getModSourceValue(ModSource source, ModMode mode); | ||
| float* getModDestPtr(ModDest dest); | ||
| void copyExternalParametersToInstanceVariables(); | ||
| void generateRandomizedParameters(); | ||
| void applyModMatrix(int index); | ||
| const GrainParameters generateFinalParameters(); | ||
|
|
||
| int internal_block_size; | ||
| float mix, input_gain; | ||
| float amp_min, amp_value; | ||
| float pan_value; | ||
| float feedback; | ||
| float delay_min, delay_value; | ||
| float iot_min, iot_value; | ||
| float dur_min, dur_value; | ||
| float trans_value; | ||
| float gliss_value; | ||
| float ffreq_min, ffreq_value; | ||
| float fq_min, fq_value; | ||
| float env_shape, env_skew; | ||
| float grains; | ||
| float trans_toggle, gliss_toggle, freeze_toggle; | ||
| float matrixmod1, matrixmod2, matrixmod3; | ||
| GrainParameters grain_parameters; | ||
| Random* random; | ||
| Parameters* parameters; | ||
| TimeQuantizer* time_quantizer; | ||
| DelayLine* delay_line; | ||
| Granulator* granulator; | ||
| }; | ||
|
|
||
| #endif //GRAINPARAMETERSGENERATOR_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| #include "Granulator.h" | ||
|
|
||
| Granulator::Granulator(Parameters* parameters, const int internal_block_size) | ||
| : outbuf_left (0) | ||
| , outbuf_right (0) | ||
| { | ||
| this->parameters = parameters; | ||
| this->internal_block_size = internal_block_size; | ||
| delay_line = new DelayLine(kBufferSeconds, internal_block_size); | ||
| grain_param_generator = new GrainParametersGenerator(parameters, delay_line, | ||
| this, internal_block_size); | ||
| initialized = false; | ||
| } | ||
|
|
||
| Granulator::~Granulator() | ||
| { | ||
| if (initialized) | ||
| deleteGrains(); | ||
| delete delay_line; | ||
| delete grain_param_generator; | ||
| } | ||
|
|
||
| void Granulator::prepareToPlay(float samplerate) | ||
| { | ||
| this->samplerate = samplerate; | ||
| parameters->setSampleRate(samplerate); | ||
| delay_line->initialize(samplerate); | ||
|
|
||
| outbuf_left = new float[internal_block_size]; | ||
| outbuf_right = new float[internal_block_size]; | ||
| for (int i = 0; i < internal_block_size; i++) | ||
| outbuf_left[i] = outbuf_right[i] = 10E-12f; | ||
|
|
||
| if (initialized) | ||
| deleteGrains(); | ||
|
|
||
| for (int i = 0; i < kMaxGrains; i++) | ||
| graincloud[i] = new Grain(samplerate, | ||
| static_cast<int>(samplerate * kBufferSeconds), | ||
| internal_block_size, | ||
| delay_line->getDelayPointer(), | ||
| outbuf_left, | ||
| outbuf_right); | ||
| initialized = true; | ||
| active_grains = 0; | ||
| } | ||
|
|
||
| void Granulator::releaseResources() | ||
| { | ||
| delete[] outbuf_left; | ||
| delete[] outbuf_right; | ||
| active_grains = 0; | ||
| } | ||
|
|
||
| void Granulator::setActiveGrains() | ||
| { | ||
| if (!initialized) | ||
| return; | ||
|
|
||
| if (parameters->selected_grains > active_grains) { | ||
| for (int i = active_grains; i < parameters->selected_grains; i++) { | ||
| graincloud[i]->activate(); | ||
| active_grains++; | ||
| } | ||
| } else if (parameters->selected_grains < active_grains) { | ||
| for (int i = active_grains; i > parameters->selected_grains; i--) { | ||
| graincloud[i-1]->deactivate(); | ||
| active_grains--; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void Granulator::processInternalBlock(float* chan1, float* chan2, int sampleframes) | ||
| { | ||
| if (active_grains != parameters->selected_grains) | ||
| setActiveGrains(); | ||
|
|
||
| delay_line->writeDelayBuffer(chan1, chan2, sampleframes, parameters->freeze, | ||
| parameters->param[kIngain], | ||
| parameters->param[kFeedback]); | ||
| processGrains(sampleframes); | ||
| hardClip(outbuf_left, sampleframes); | ||
| hardClip(outbuf_right, sampleframes); | ||
| delay_line->writeFeedbackBuffer(outbuf_left, outbuf_right, sampleframes); | ||
| writeOutput(chan1, chan2, outbuf_left, outbuf_right, sampleframes); | ||
| clearOutbufs(outbuf_left, outbuf_right, sampleframes); | ||
| chan1 += sampleframes; | ||
| chan2 += sampleframes; | ||
| } | ||
|
|
||
| void Granulator::clearOutbufs(float* outbuf_left, float* outbuf_right, | ||
| int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) | ||
| outbuf_left[i] = outbuf_right[i] = 10E-12f; | ||
| } | ||
|
|
||
| void Granulator::writeOutput(float* chan1, float* chan2, float* outbuf_left, | ||
| float* outbuf_right, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| chan1[i] = (parameters->param[kMix] * outbuf_left[i]) | ||
| + (parameters->dry_mix * chan1[i]); | ||
| chan2[i] = (parameters->param[kMix] * outbuf_right[i]) | ||
| + (parameters->dry_mix * chan2[i]); | ||
| } | ||
| } | ||
|
|
||
| void Granulator::processGrains(int sampleframes) | ||
| { | ||
| for (int i = 0; i < kMaxGrains; i++) { | ||
| if (graincloud[i]->activated) { | ||
| if (graincloud[i]->initialized == false) { | ||
| graincloud[i]->initialize(grain_param_generator->getNewGrainParameters()); | ||
| } | ||
| graincloud[i]->process(sampleframes); | ||
| if (graincloud[i]->initialized == false) { | ||
| graincloud[i]->initialize(grain_param_generator->getNewGrainParameters()); | ||
| graincloud[i]->process(sampleframes); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void Granulator::hardClip(float* input, int sampleframes) | ||
| { | ||
| for (int i = 0; i < sampleframes; i++) { | ||
| if (input[i] > 1.0f) { | ||
| input[i] = 1.0f; | ||
| } else if (input[i] < -1.0f) { | ||
| input[i] = -1.0f; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void Granulator::deleteGrains() | ||
| { | ||
| for (int i = 0; i < kMaxGrains; i++) | ||
| delete graincloud[i]; | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| #ifndef GRANULATOR_H | ||
| #define GRANULATOR_H | ||
|
|
||
| #include "Debug.h" | ||
| #include "DelayLine.h" | ||
| #include "Filter.h" | ||
| #include "GrainParametersGenerator.h" | ||
| #include "Grain.h" | ||
| #include "Parameters.h" | ||
| #include "PitchQuantizer.h" | ||
|
|
||
| class GrainParametersGenerator; | ||
| class Parameters; | ||
|
|
||
| class Granulator | ||
| { | ||
| public: | ||
| Granulator(Parameters* params, const int internal_block_size); | ||
| ~Granulator(); | ||
| void prepareToPlay(float samplerate); | ||
| void processInternalBlock(float* chan1, float* chan2, int sampleframes); | ||
| void releaseResources(); | ||
| const float getSampleRate(); | ||
|
|
||
| GrainParametersGenerator* grain_param_generator; | ||
| static const int kMaxGrains = 20; | ||
| static const int kBufferSeconds = 5; | ||
| int internal_block_size; | ||
|
|
||
| private: | ||
| void writeOutput(float* chan1, float* chan2, float* outbuf_left, float* outbuf_right, int sampleframes); | ||
| void clearOutbufs(float* outbuf_left, float* outbuf_right, int sampleframes); | ||
| void hardClip(float* input, int sampleframes); | ||
| void processGrains(int sampleframes); | ||
| void deleteGrains(); | ||
| void setActiveGrains(); | ||
|
|
||
| float samplerate; | ||
| float *outbuf_left, *outbuf_right; | ||
| float bpm; | ||
| int active_grains, sampleframes; | ||
| bool initialized; | ||
| Grain* graincloud[kMaxGrains]; | ||
| Parameters* parameters; | ||
| DelayLine* delay_line; | ||
| }; | ||
|
|
||
| #endif //GRANULATOR_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| #ifndef MISC_H | ||
| #define MISC_H | ||
|
|
||
| namespace MathFunc | ||
| { | ||
|
|
||
| inline int roundFtoI(float f) | ||
| { | ||
| return static_cast<int>(f + (f > 0.0 ? + 0.5 : -0.5)); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| #endif //MISC_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| #ifndef PARAMETERS_H | ||
| #define PARAMETERS_H | ||
|
|
||
| class Plugin; | ||
|
|
||
| #include <math.h> | ||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include "Envelope.h" | ||
| #include "Filter.h" | ||
| #include "Misc.h" | ||
| #include "Plugin.h" | ||
| #include "ParametersEnum.h" | ||
| #include "TimeQuantizer.h" | ||
|
|
||
| class TimeQuantizer; | ||
|
|
||
| class Parameters | ||
| { | ||
| public: | ||
| Parameters(Plugin* plugin, const int internal_block_size); | ||
| ~Parameters(); | ||
| void initializeInternalParameters(); | ||
| const String getParameterName(int index); | ||
| const String getParameterText(int index); | ||
| void setParameter(int index, float new_value, bool initializing); | ||
| float getParameterFloatValue(ParameterType param_index); | ||
| float getDelayMilliseconds(float value); | ||
| float getIOTMilliseconds(float value); | ||
| float getDurMilliseconds(float value); | ||
| int getScale(); | ||
| void setScale(int index); | ||
| int getMatrixSource(int index); | ||
| int getMatrixDest(int index); | ||
| int getMatrixMode(int index); | ||
| void setMatrixSource(int index, int param); | ||
| void setMatrixDest(int index, int param); | ||
| void setMatrixMode(int index, int param); | ||
| void setSampleRate(float samplerate); | ||
| float getSampleRate(); | ||
| void setQuantizationDisabled(); | ||
|
|
||
| static const int kMaxIot = 2000; | ||
| static const int kMaxDuration = 5; | ||
|
|
||
| ModSource matrix_source[3]; | ||
| ModDest matrix_dest[3]; | ||
| ModMode matrix_mode[3]; | ||
| float *param; | ||
| float dry_mix; | ||
| int scale; | ||
| int selected_grains; | ||
| bool freeze; | ||
| int filter_type; | ||
| int env_type; | ||
| int scale_key; | ||
| float amp_max; | ||
| float pan_min, pan_max; | ||
| float delay_max; | ||
| float iot_max; | ||
| float dur_max; | ||
| float trans_min, trans_max; | ||
| float gliss_min, gliss_max; | ||
| float ffreq_max; | ||
| float fq_max; | ||
| float samplerate; | ||
| TimeQuantizer* time_quantizer; | ||
|
|
||
| private: | ||
| String getEnvTypeString(); | ||
| String getEnvSkewString(); | ||
| String getEnvSustainString(); | ||
| String getFilterTypeString(); | ||
| String getScaleKeyString(); | ||
| String getNumGrainsString(); | ||
| String getMatrixmodString(int parameter); | ||
| String getDecibelString(float value); | ||
| String getToggleString(int parameter); | ||
| String getPanString(float value); | ||
| String getDelayString(float value); | ||
| String getIOTString(float value); | ||
| String getDurString(float value); | ||
| String getTransString(float value); | ||
| String getGlissString(float value); | ||
| String getFFreqString(float value); | ||
| String getFqString(float value); | ||
| String getPercentString(float value); | ||
| void setParametersSavedState(bool state); | ||
|
|
||
| bool quantization_disabled; | ||
| float delay_coeff; | ||
| float iot_coeff; | ||
| float dur_coeff; | ||
| Plugin* plugin; | ||
| }; | ||
|
|
||
| #endif //PARAMETERS_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| #ifndef PARAMETERSENUM_H | ||
| #define PARAMETERSENUM_H | ||
|
|
||
| const int NUM_PARAMS = 37; | ||
| const int NUM_MIDI_PARAMS = 36; | ||
|
|
||
| enum ParameterType { | ||
| kGrains, | ||
| kMix, | ||
| kIngain, | ||
| kFeedback, | ||
| kAmp, | ||
| kAmpv, | ||
| kPan, | ||
| kPanv, | ||
| kDelay, | ||
| kDelayv, | ||
| kIot, | ||
| kIotv, | ||
| kDur, | ||
| kDurv, | ||
| kTrans, | ||
| kTransv, | ||
| kGliss, | ||
| kGlissv, | ||
| kFtype, | ||
| kFfreq, | ||
| kFfreqv, | ||
| kFq, | ||
| kFqv, | ||
| kEnvType, | ||
| kEnvSustain, | ||
| kEnvSkew, | ||
| kDelayQuant, | ||
| kDurQuant, | ||
| kIotQuant, | ||
| kTransToggle, | ||
| kGlissToggle, | ||
| kFreezeToggle, | ||
| kScaleKey, | ||
| kMatrixMod1, | ||
| kMatrixMod2, | ||
| kMatrixMod3, | ||
| kProgram, | ||
| kNone, | ||
| }; | ||
|
|
||
| enum ModMode { | ||
| MOD_MODE_SCALED, | ||
| MOD_MODE_DIRECT | ||
| }; | ||
|
|
||
| enum ModSource { | ||
| MOD_SRC_OFF, | ||
| MOD_SRC_AMP, | ||
| MOD_SRC_PAN_LR, | ||
| MOD_SRC_PAN_WIDTH, | ||
| MOD_SRC_DELAY, | ||
| MOD_SRC_IOT, | ||
| MOD_SRC_DUR, | ||
| MOD_SRC_TRANS, | ||
| MOD_SRC_GLISS, | ||
| MOD_SRC_FFREQ, | ||
| MOD_SRC_FQ, | ||
| MOD_SRC_NUM = 11 | ||
| }; | ||
|
|
||
| enum ModDest { | ||
| MOD_DEST_OFF, | ||
| MOD_DEST_AMP, | ||
| MOD_DEST_PAN_LR, | ||
| MOD_DEST_DELAY, | ||
| MOD_DEST_IOT, | ||
| MOD_DEST_DUR, | ||
| MOD_DEST_TRANS, | ||
| MOD_DEST_GLISS, | ||
| MOD_DEST_FFREQ, | ||
| MOD_DEST_FQ, | ||
| MOD_DEST_SUSTAIN, | ||
| MOD_DEST_SKEW, | ||
| MOD_DEST_NUM = 12 | ||
| }; | ||
|
|
||
| enum QuantizeMode { | ||
| QUANT_MS = 1, | ||
| QUANT_128, | ||
| QUANT_128T, | ||
| QUANT_64, | ||
| QUANT_64T, | ||
| QUANT_32, | ||
| QUANT_32T, | ||
| QUANT_16, | ||
| QUANT_16T, | ||
| QUANT_8, | ||
| QUANT_8T, | ||
| QUANT_4, | ||
| QUANT_4T, | ||
| QUANT_MS_LONG // (dur *= 10) | ||
| }; | ||
|
|
||
| namespace NumQuantModes | ||
| { | ||
| const float delay = 13.0f; | ||
| const float iot = 13.0f; | ||
| const float dur = 14.0f; | ||
| } | ||
|
|
||
| #endif //PARAMETERSENUM_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| #include "PitchQuantizer.h" | ||
|
|
||
|
|
||
| PitchQuantizer::PitchQuantizer() | ||
| { | ||
| notes_49 = new int[49]; | ||
| notes_120 = new int[120]; | ||
| namesVector = new vector<String>; | ||
| notesVector = new vector< vector<int> >; | ||
|
|
||
| addScale("chromatic", 1,1,1,1,1,1,1,1,1,1,1,1); | ||
| addScale("major", 1,0,1,0,1,1,0,1,0,1,0,1); | ||
| addScale("natural minor", 1,0,1,1,0,1,0,1,1,0,1,0); | ||
| addScale("harmonic minor", 1,0,1,1,0,1,0,1,1,0,0,1); | ||
| addScale("major pentatonic", 1,0,1,0,1,0,0,1,0,1,0,0); | ||
| addScale("minor pentatonic", 1,0,0,1,0,1,0,1,0,0,1,0); | ||
| addScale("blues major", 1,0,1,0,1,0,0,1,0,1,0,1); | ||
| addScale("blues minor", 1,0,0,1,0,1,0,0,1,0,1,0); | ||
| addScale("whole tone", 1,0,1,0,1,0,1,0,1,0,1,0); | ||
| addScale("octatonic", 1,0,1,1,0,1,1,0,1,1,0,1); | ||
| addScale("maj 7", 1,0,0,0,1,0,0,1,0,0,0,1); | ||
| addScale("dom 7", 1,0,0,0,1,0,0,1,0,0,1,0); | ||
| addScale("min 7", 1,0,0,1,0,0,0,1,0,0,1,0); | ||
| addScale("aug maj 7", 1,0,0,0,1,0,0,0,1,0,0,1); | ||
| addScale("aug 7", 1,0,0,0,1,0,0,0,1,0,1,0); | ||
| addScale("dim 7", 1,0,0,1,0,0,1,0,0,1,0,0); | ||
| addScale("dom 7 dim 5", 1,0,0,0,1,0,1,0,0,0,1,0); | ||
| addScale("maj triad", 1,0,0,0,1,0,0,1,0,0,0,0); | ||
| addScale("min triad", 1,0,0,1,0,0,0,1,0,0,0,0); | ||
| addScale("aug triad", 1,0,0,0,1,0,0,0,1,0,0,0); | ||
| addScale("dim triad", 1,0,0,1,0,0,1,0,0,0,0,0); | ||
| addScale("5th", 1,0,0,0,0,0,0,1,0,0,0,0); | ||
| addScale("dim 5th", 1,0,0,0,0,0,1,0,0,0,0,0); | ||
| addScale("aug 5th", 1,0,0,0,0,0,0,0,1,0,0,0); | ||
| } | ||
|
|
||
| PitchQuantizer::~PitchQuantizer() | ||
| { | ||
| delete[] notes_49; | ||
| delete[] notes_120; | ||
| delete namesVector; | ||
| delete notesVector; | ||
| } | ||
|
|
||
| void PitchQuantizer::addScale(String name, int n1, int n2, int n3, int n4, | ||
| int n5, int n6, int n7,int n8, int n9, int n10, | ||
| int n11, int n12) | ||
| { | ||
| int note_ints[] = {n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12}; | ||
| vector<int> notes(note_ints, note_ints + sizeof(note_ints) / sizeof(int)); | ||
| notesVector->push_back(notes); | ||
| namesVector->push_back(name); | ||
| } | ||
|
|
||
| vector<String> PitchQuantizer::getNames() | ||
| { | ||
| return *namesVector; | ||
| } | ||
|
|
||
| float PitchQuantizer::getQuantizedPitch(int scaleIndex, int shift, float trans_value) | ||
| { | ||
| make49NotesArray(scaleIndex, shift); | ||
| float semitones = trans_value * 48.0f; | ||
| float distances[49]; | ||
| int nearestIndex; | ||
|
|
||
| // array of distances to each note | ||
| for (int i = 0; i < 49; i++) { | ||
| if (notes_49[i] == 1) { | ||
| distances[i] = fabs(semitones - i); | ||
| } else { | ||
| distances[i] = 10E10f; | ||
| } | ||
| } | ||
| nearestIndex = findNearest(distances, 49); | ||
| trans_value = nearestIndex / 48.0f; | ||
| return pow(2.0f, ((trans_value - 0.5f) * 4.0f)); | ||
| } | ||
|
|
||
| float PitchQuantizer::getQuantizedFreq(int scaleIndex, int shift, float freq) | ||
| { | ||
| make120NotesArray(scaleIndex, shift); | ||
| double hzArray[120]; | ||
| double semitoneRatio = pow(2.0, 1.0/12.0); | ||
| float distances[120]; | ||
| int nearestIndex; | ||
|
|
||
| // array of 120 note frequencies | ||
| hzArray[0] = 55.0; | ||
| for (int i = 1; i < 120; i++) { | ||
| hzArray[i] = hzArray[i - 1] * semitoneRatio; | ||
| } | ||
|
|
||
| // array of distances to each frequency | ||
| for (int i = 0; i < 120; i++) { | ||
| if (notes_120[i] == 1) { | ||
| distances[i] = (float)fabs(freq - hzArray[i]); | ||
| } else { | ||
| distances[i] = 0.0f; | ||
| } | ||
| } | ||
| nearestIndex = findNearest(distances, 120); | ||
| return (float)hzArray[nearestIndex]; | ||
| } | ||
|
|
||
| void PitchQuantizer::make49NotesArray(int scaleIndex, int shift) | ||
| { | ||
| int shiftedScale[12]; | ||
| vector<int> scale = notesVector->at(scaleIndex); | ||
|
|
||
| for(int i = 0; i < 12; i++) { | ||
| shiftedScale[i] = scale[shift]; | ||
| shift++; | ||
| if (shift == 12) | ||
| shift = 0; | ||
| } | ||
|
|
||
| for (int i = 0; i < 12; i++) { | ||
| notes_49[i] = shiftedScale[i]; | ||
| notes_49[i + 12] = shiftedScale[i]; | ||
| notes_49[i + 24] = shiftedScale[i]; | ||
| notes_49[i + 36] = shiftedScale[i]; | ||
| } | ||
| notes_49[48] = shiftedScale[0]; | ||
| } | ||
|
|
||
| void PitchQuantizer::make120NotesArray(int scaleIndex, int shift) | ||
| { | ||
| int shiftedScale[12]; | ||
| vector<int> scale = notesVector->at(scaleIndex); | ||
|
|
||
| for(int i = 0; i < 12; i++) { | ||
| shiftedScale[i] = scale[shift]; | ||
| shift++; | ||
| if (shift == 12) | ||
| shift = 0; | ||
| } | ||
|
|
||
| for (int i = 0; i < 12; i++) { | ||
| for (int j = 0; j < 10; j++) { | ||
| notes_120[i + j * 12] = shiftedScale[i]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| int PitchQuantizer::findNearest(float* distances, int length) | ||
| { | ||
| float nearestValue = 10E10f; | ||
| int nearestIndex = 0; | ||
|
|
||
| for (int i = 0; i < length; i++) { | ||
| if (distances[i] < nearestValue) { | ||
| nearestValue = distances[i]; | ||
| nearestIndex = i; | ||
| } | ||
| } | ||
| return nearestIndex; | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| #ifndef PITCHQUANTIZER_H | ||
| #define PITCHQUANTIZER_H | ||
|
|
||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include <math.h> | ||
| #include <vector> | ||
| #include "Misc.h" | ||
|
|
||
| using namespace std; | ||
|
|
||
| class PitchQuantizer | ||
| { | ||
| public: | ||
| PitchQuantizer(); | ||
| ~PitchQuantizer(); | ||
| float getQuantizedPitch(int scale, int scaleKey, float trans); | ||
| float getQuantizedFreq(int scaleIndex, int shift, float freq); | ||
| vector<String> getNames(); | ||
|
|
||
| private: | ||
| void addScale(String name, int n1, int n2, int n3, int n4, int n5, | ||
| int n6, int n7, int n8, int n9, int n10, int n11, int n12); | ||
| int findNearest(float* distances, int length); | ||
| void make49NotesArray(int scaleIndex, int shift); | ||
| void make120NotesArray(int scaleIndex, int shift); | ||
|
|
||
| vector<String>* namesVector; | ||
| vector< vector<int> >* notesVector; | ||
| int* notes_49; | ||
| int* notes_120; | ||
| }; | ||
|
|
||
| #endif //PITCHQUANTIZER_H | ||
|
|
||
| /* | ||
| chromatic 0 1 2 3 4 5 6 7 8 9 10 11 | ||
| major 0 2 4 5 7 9 11 | ||
| natural minor 0 2 3 5 7 8 10 | ||
| harmonic minor 0 2 3 5 7 8 11 | ||
| major pentatonic 0 2 4 7 9 | ||
| minor pentatonic 0 3 5 7 10 | ||
| blues major 0 2 4 7 9 | ||
| blues minor 0 3 5 8 10 | ||
| whole tone 0 2 4 6 8 10 | ||
| octatonic 0 2 3 5 6 8 9 11 | ||
| maj 7 0 4 7 11 | ||
| dom 7 0 4 7 10 | ||
| min 7 0 3 7 10 | ||
| aug maj 7 0 4 8 11 | ||
| aug 7 0 4 8 10 | ||
| dim 7 0 3 6 9 | ||
| dom 7 dim 5 0 4 6 10 | ||
| maj triad 0 4 7 | ||
| min triad 0 3 7 | ||
| aug triad 0 4 8 | ||
| dim triad 0 3 6 | ||
| 5th 0 6 | ||
| Dim 5th 0 5 | ||
| Aug 5th 0 8 | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| #ifndef PLUGIN_H | ||
| #define PLUGIN_H | ||
|
|
||
| #include <vector> | ||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include "Filter.h" | ||
| #include "Granulator.h" | ||
| #include "Misc.h" | ||
| #include "ProgramBank.h" | ||
|
|
||
| class GrainParametersGenerator; | ||
| class Granulator; | ||
| class ProgramBank; | ||
| class PitchQuantizer; | ||
|
|
||
| class Plugin : public AudioProcessor, public ChangeBroadcaster | ||
| { | ||
| public: | ||
| Plugin(); | ||
| ~Plugin(); | ||
| // Overrides | ||
| AudioProcessorEditor* createEditor(); | ||
| void prepareToPlay (double samplerate, int samples_per_block); | ||
| void releaseResources(); | ||
| void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); | ||
| float getParameter (int index); | ||
| void setParameter(int index, float new_value); | ||
| void setMatrixSource(int index, int param); | ||
| void setMatrixDest(int index, int param); | ||
| void setMatrixMode(int index, int param); | ||
| const String getParameterName (int index); | ||
| const String getParameterText (int index); | ||
| int getCurrentProgram(); | ||
| int getNumPrograms(); | ||
| const String getProgramName(int index); | ||
| void changeProgramName(int index, const String& newName); | ||
| void getCurrentProgramStateInformation (MemoryBlock& destData); | ||
| void setCurrentProgramStateInformation(const void* data, int sizeInBytes); | ||
| void getStateInformation (MemoryBlock& destData); | ||
| void setStateInformation (const void* data, int sizeInBytes); | ||
| void setCurrentProgram(int index); | ||
| int getNumParameters(); | ||
| bool acceptsMidi() const; | ||
| const String getInputChannelName (int channelIndex) const; | ||
| const String getName() const; | ||
| const String getOutputChannelName (int channelIndex) const; | ||
| bool isInputChannelStereoPair (int index) const; | ||
| bool isOutputChannelStereoPair (int index) const; | ||
| bool producesMidi() const; | ||
| bool hasEditor() const; | ||
| bool isMetaParameter(int parameterIndex) const; | ||
| bool silenceInProducesSilenceOut(void) const; | ||
| double getTailLengthSeconds() const; | ||
|
|
||
| // New methods | ||
| void loadBankXml(File* file); | ||
| void saveBankXml(File* file); | ||
| void loadCurrentProgramXml(File* file); | ||
| void saveCurrentProgramXml(File* file); | ||
| //void createAppSettingsDir(); | ||
| //File* getMidiMapFile(); | ||
| bool getSavedState(); | ||
| void setSavedState(bool state); | ||
| bool getParametersChangedState(); | ||
| void setParametersChangedState(); | ||
| bool getProgramChangedState(); | ||
| void initCurrentProgram(); | ||
| void saveProgramTo(int index); | ||
| std::vector<String> getScaleNames(); | ||
| void toggleProgchangeEnabled(); | ||
| bool isProgchangeEnabled(); | ||
|
|
||
| static const int kNumPrograms = 16; | ||
| static const int kInternalBlocksize = 32; | ||
| Parameters* parameters; | ||
| Granulator* granulator; | ||
|
|
||
| private: | ||
| int current_program; | ||
| bool saved_state; | ||
| bool editor_parameter_update_pending; | ||
| bool editor_program_update_pending; | ||
| AudioPlayHead::CurrentPositionInfo pos; | ||
| unsigned int block_sample_pos; | ||
| ProgramBank* program_bank; | ||
| bool progchange_param_enabled; | ||
| }; | ||
|
|
||
| #endif //PLUGIN_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,205 @@ | ||
| /* | ||
| ============================================================================== | ||
| This is an automatically generated file created by the Jucer! | ||
| Creation date: 19 Feb 2012 11:38:05am | ||
| Be careful when adding custom code to these files, as only the code within | ||
| the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded | ||
| and re-saved. | ||
| Jucer version: 1.12 | ||
| ------------------------------------------------------------------------------ | ||
| The Jucer is part of the JUCE library - "Jules' Utility Class Extensions" | ||
| Copyright 2004-6 by Raw Material Software ltd. | ||
| ============================================================================== | ||
| */ | ||
|
|
||
| #ifndef __JUCER_HEADER_PLUGINEDITOR_PLUGINEDITOR_47FE96EF__ | ||
| #define __JUCER_HEADER_PLUGINEDITOR_PLUGINEDITOR_47FE96EF__ | ||
|
|
||
| //[Headers] -- You can add your own extra header files here -- | ||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include "Debug.h" | ||
| #include "Plugin.h" | ||
|
|
||
| enum ComponentType { | ||
| kSlider, | ||
| kComboBox, | ||
| kButton, | ||
| kNoComponent | ||
| }; | ||
| //[/Headers] | ||
|
|
||
|
|
||
|
|
||
| //============================================================================== | ||
| /** | ||
| //[Comments] | ||
| Argotlunar 2.0 GUI | ||
| //[/Comments] | ||
| */ | ||
| class PluginEditor : public AudioProcessorEditor, | ||
| public Timer, | ||
| public SliderListener, | ||
| public ComboBoxListener, | ||
| public ButtonListener | ||
| { | ||
| public: | ||
| //============================================================================== | ||
| PluginEditor (Plugin* const ownerFilter); | ||
| ~PluginEditor(); | ||
|
|
||
| //============================================================================== | ||
| //[UserMethods] -- You can add your own custom methods in this section. | ||
| void timerCallback(); | ||
| String* programNames; | ||
| void changeProgram(int program); | ||
| void updateGlissSliders(bool state); | ||
| void updateTransSliders(bool state); | ||
| void updateEnvSliders(int id); | ||
| void updateScaleComponents(bool state); | ||
| void setColour(bool style); | ||
| void loadBankFile(Plugin* const plugin); | ||
| void loadProgramFile(Plugin* const plugin); | ||
| void saveBankFile(Plugin* const plugin); | ||
| void saveProgramFile(Plugin* const plugin); | ||
|
|
||
| //[/UserMethods] | ||
|
|
||
| void paint (Graphics& g); | ||
| void resized(); | ||
| void sliderValueChanged (Slider* sliderThatWasMoved); | ||
| void comboBoxChanged (ComboBox* comboBoxThatHasChanged); | ||
| void buttonClicked (Button* buttonThatWasClicked); | ||
|
|
||
|
|
||
|
|
||
| //============================================================================== | ||
| juce_UseDebuggingNewOperator | ||
|
|
||
| private: | ||
| //[UserVariables] -- You can add your own custom variables in this section. | ||
| Plugin* getPlugin() const throw() { | ||
| return static_cast <Plugin*> (getAudioProcessor()); | ||
| } | ||
| void updateParametersFromPlugin(); | ||
| void updateProgramNamesFromPlugin(); | ||
| int currentProgram; | ||
| int num_programs; | ||
| //[/UserVariables] | ||
|
|
||
| //============================================================================== | ||
| GroupComponent* groupComponent3; | ||
| GroupComponent* groupComponent2; | ||
| GroupComponent* groupComponent20; | ||
| GroupComponent* groupComponent18; | ||
| GroupComponent* groupComponent5; | ||
| GroupComponent* groupComponent15; | ||
| GroupComponent* groupComponent9; | ||
| GroupComponent* groupComponent; | ||
| Slider* mix_slider; | ||
| Label* label; | ||
| Slider* ingain_slider; | ||
| Label* label2; | ||
| Slider* amp_slider; | ||
| Label* label3; | ||
| Slider* ampv_slider; | ||
| Label* label4; | ||
| Slider* pan_slider; | ||
| Label* label5; | ||
| Slider* panv_slider; | ||
| Label* label6; | ||
| Slider* delay_slider; | ||
| Label* label7; | ||
| Slider* delayv_slider; | ||
| Slider* feedback_slider; | ||
| Label* label9; | ||
| Slider* gliss_slider; | ||
| Label* label11; | ||
| Slider* glissv_slider; | ||
| Slider* trans_slider; | ||
| Label* label13; | ||
| Slider* transv_slider; | ||
| Slider* iot_slider; | ||
| Label* label15; | ||
| Slider* iotv_slider; | ||
| Slider* dur_slider; | ||
| Label* label17; | ||
| Slider* durv_slider; | ||
| Slider* ffreq_slider; | ||
| Label* label19; | ||
| Slider* ffreqv_slider; | ||
| Slider* fq_slider; | ||
| Label* label21; | ||
| Slider* fqv_slider; | ||
| Slider* grains_slider; | ||
| Label* label23; | ||
| TextEditor* param_display; | ||
| ComboBox* filtertype_combobox; | ||
| TextButton* initButton; | ||
| TextButton* saveButton; | ||
| TextButton* savetoButton; | ||
| TextButton* decPresetButton; | ||
| TextButton* incPresetButton; | ||
| ComboBox* program_combobox; | ||
| Label* label25; | ||
| Slider* envshape_slider; | ||
| Slider* envskew_slider; | ||
| Label* label26; | ||
| Label* label27; | ||
| Label* label28; | ||
| ToggleButton* freeze_toggle_button; | ||
| ComboBox* scale_combobox; | ||
| Slider* scalekey_slider; | ||
| Label* label24; | ||
| GroupComponent* groupComponent17; | ||
| Label* label29; | ||
| ComboBox* matrix_src_combobox_1; | ||
| ComboBox* matrix_dest_combobox_1; | ||
| Slider* matrix_mod_slider_1; | ||
| Label* label30; | ||
| Label* label31; | ||
| ComboBox* matrix_src_combobox_2; | ||
| ComboBox* matrix_dest_combobox_2; | ||
| Slider* matrix_mod_slider_2; | ||
| Label* label34; | ||
| Label* label35; | ||
| ComboBox* matrix_src_combobox_3; | ||
| ComboBox* matrix_dest_combobox_3; | ||
| Slider* matrix_mod_slider_3; | ||
| Label* label36; | ||
| Label* label37; | ||
| ToggleButton* matrix_mode_1_button; | ||
| ToggleButton* matrix_mode_2_button; | ||
| ToggleButton* matrix_mode_3_button; | ||
| TextEditor* scalekey_display; | ||
| ToggleButton* trans_toggle_button; | ||
| ComboBox* envtype_combobox; | ||
| ComboBox* dur_quant_combobox; | ||
| ComboBox* iot_quant_combobox; | ||
| ComboBox* delay_quant_combobox; | ||
| Label* label8; | ||
| Label* label16; | ||
| Label* label18; | ||
| Label* label12; | ||
| Label* label14; | ||
| Label* label20; | ||
| Label* label22; | ||
| Label* label32; | ||
| ToggleButton* gliss_toggle_button; | ||
| TextButton* optionsButton; | ||
|
|
||
|
|
||
| //============================================================================== | ||
| // (prevent copy constructor and operator= being generated..) | ||
| PluginEditor (const PluginEditor&); | ||
| const PluginEditor& operator= (const PluginEditor&); | ||
| }; | ||
|
|
||
|
|
||
| #endif // __JUCER_HEADER_PLUGINEDITOR_PLUGINEDITOR_47FE96EF__ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| #include "Program.h" | ||
|
|
||
| Program::Program() | ||
| { | ||
| initParameters(); | ||
| } | ||
|
|
||
| Program::~Program() | ||
| { | ||
| } | ||
|
|
||
| void Program::initParameters() | ||
| { | ||
| // internal parameters | ||
| name = "Init"; | ||
| parameters[kGrains] = 0.5f; | ||
| parameters[kMix] = 1.0f; | ||
| parameters[kIngain] = 1.0f; | ||
| parameters[kFeedback] = 0.0f; | ||
| parameters[kAmp] = 0.5f; | ||
| parameters[kAmpv] = 0.5f; | ||
| parameters[kPan] = 0.5f; | ||
| parameters[kPanv] = 0.5f; | ||
| parameters[kDelay] = 0.0f; | ||
| parameters[kDelayv] = 0.05f; | ||
| parameters[kIot] = 0.25f; | ||
| parameters[kIotv] = 0.1f; | ||
| parameters[kDur] = 0.3f; | ||
| parameters[kDurv] = 0.1f; | ||
| parameters[kTrans] = 0.5f; | ||
| parameters[kTransv] = 0.0f; | ||
| parameters[kGliss] = 0.5f; | ||
| parameters[kGlissv] = 0.0f; | ||
| parameters[kFtype] = 0.0f; | ||
| parameters[kFfreq] = 0.3f; | ||
| parameters[kFfreqv] = 0.5f; | ||
| parameters[kFq] = 0.0f; | ||
| parameters[kFqv] = 0.5f; | ||
| parameters[kEnvType] = 0.0f; | ||
| parameters[kEnvSustain] = 0.0f; | ||
| parameters[kEnvSkew] = 0.5f; | ||
| parameters[kDelayQuant] = 1.0f/NumQuantModes::delay; | ||
| parameters[kIotQuant] = 1.0f/NumQuantModes::iot; | ||
| parameters[kDurQuant] = 1.0f/NumQuantModes::dur; | ||
| parameters[kGlissToggle] = 0.0f; | ||
| parameters[kTransToggle] = 1.0f; | ||
| parameters[kFreezeToggle] = 0.0f; | ||
| parameters[kScaleKey] = 0.0f; | ||
| parameters[kMatrixMod1] = 0.5f; | ||
| parameters[kMatrixMod2] = 0.5f; | ||
| parameters[kMatrixMod3] = 0.5f; | ||
|
|
||
| // external parameters | ||
| scale = 1; | ||
| for (int i = 0; i < 3; i++) { | ||
| matrix_source[i] = MOD_SRC_OFF; | ||
| matrix_dest[i] = MOD_DEST_OFF; | ||
| matrix_mode[i] = MOD_MODE_SCALED; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #ifndef PROGRAM_H | ||
| #define PROGRAM_H | ||
|
|
||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include "Debug.h" | ||
| #include "ParametersEnum.h" | ||
| //#include "MidiMapper.h" | ||
|
|
||
| class Program | ||
| { | ||
| public: | ||
| Program(); | ||
| ~Program(); | ||
| void initParameters(); | ||
| String name; | ||
| float parameters[NUM_PARAMS - 1]; | ||
| int scale; | ||
| ModSource matrix_source[3]; | ||
| ModDest matrix_dest[3]; | ||
| ModMode matrix_mode[3]; | ||
| private: | ||
| }; | ||
|
|
||
| #endif //PROGRAMBANK_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| #include "ProgramBank.h" | ||
|
|
||
| ProgramBank::ProgramBank(const int num_programs, Parameters* parameters) | ||
| { | ||
| this->parameters = parameters; | ||
| this->num_programs = num_programs; | ||
| programs = new Program[num_programs]; | ||
| loadProgramState(0); | ||
| } | ||
|
|
||
| ProgramBank::~ProgramBank() | ||
| { | ||
| delete[] programs; | ||
| } | ||
|
|
||
| void ProgramBank::saveProgramState(int index) | ||
| { | ||
| // internal parameters | ||
| for (int i = 0; i < (NUM_PARAMS - 1); i++) { | ||
| programs[index].parameters[i] = parameters->param[i]; | ||
| } | ||
|
|
||
| // external parameters | ||
| programs[index].scale = parameters->scale; | ||
| for (int i = 0; i < 3; i++) { | ||
| programs[index].matrix_source[i] = parameters->matrix_source[i]; | ||
| programs[index].matrix_dest[i] = parameters->matrix_dest[i]; | ||
| programs[index].matrix_mode[i] = parameters->matrix_mode[i]; | ||
| } | ||
| } | ||
|
|
||
| void ProgramBank::loadProgramState(int index) | ||
| { | ||
| // internal parameters | ||
| for (int i = 0; i < (NUM_PARAMS - 1); i++) { | ||
| parameters->param[i] = programs[index].parameters[i]; | ||
| } | ||
|
|
||
| // external parameters | ||
| parameters->scale = programs[index].scale; | ||
| for (int i = 0; i < 3; i++) { | ||
| parameters->matrix_source[i] = programs[index].matrix_source[i]; | ||
| parameters->matrix_dest[i] = programs[index].matrix_dest[i]; | ||
| parameters->matrix_mode[i] = programs[index].matrix_mode[i]; | ||
| } | ||
| parameters->initializeInternalParameters(); | ||
| } | ||
|
|
||
| XmlElement* ProgramBank::createBankXml() | ||
| { | ||
| XmlElement* bank_xml = new XmlElement("ARGOTLUNAR2_BANK"); | ||
| for (int i = 0; i < num_programs; i++) { | ||
| bank_xml->addChildElement(createProgramXml(i)); | ||
| } | ||
| return bank_xml; | ||
| } | ||
|
|
||
| void ProgramBank::loadBankFromXml(XmlElement* bank_xml) | ||
| { | ||
| int i = 0; | ||
| if (bank_xml->hasTagName("ARGOTLUNAR2_BANK")) { | ||
| forEachXmlChildElement(*bank_xml, parameters_xml) | ||
| loadProgramFromXml(i++, parameters_xml); | ||
| } | ||
| } | ||
|
|
||
| XmlElement* ProgramBank::createProgramXml(int index) | ||
| { | ||
| XmlElement* program_xml = new XmlElement("ARGOTLUNAR2_PROGRAM"); | ||
| // external parameters | ||
| program_xml->setAttribute("program_name", programs[index].name); | ||
| program_xml->setAttribute("grains", programs[index].parameters[kGrains]); | ||
| program_xml->setAttribute("mix", programs[index].parameters[kMix]); | ||
| program_xml->setAttribute("input_gain", programs[index].parameters[kIngain]); | ||
| program_xml->setAttribute("feedback", programs[index].parameters[kFeedback]); | ||
| program_xml->setAttribute("amp", programs[index].parameters[kAmp]); | ||
| program_xml->setAttribute("ampv", programs[index].parameters[kAmpv]); | ||
| program_xml->setAttribute("pan", programs[index].parameters[kPan]); | ||
| program_xml->setAttribute("panv", programs[index].parameters[kPanv]); | ||
| program_xml->setAttribute("delay", programs[index].parameters[kDelay]); | ||
| program_xml->setAttribute("delayv", programs[index].parameters[kDelayv]); | ||
| program_xml->setAttribute("iot", programs[index].parameters[kIot]); | ||
| program_xml->setAttribute("iotv", programs[index].parameters[kIotv]); | ||
| program_xml->setAttribute("dur", programs[index].parameters[kDur]); | ||
| program_xml->setAttribute("durv", programs[index].parameters[kDurv]); | ||
| program_xml->setAttribute("trans", programs[index].parameters[kTrans]); | ||
| program_xml->setAttribute("transv", programs[index].parameters[kTransv]); | ||
| program_xml->setAttribute("gliss", programs[index].parameters[kGliss]); | ||
| program_xml->setAttribute("glissv", programs[index].parameters[kGlissv]); | ||
| program_xml->setAttribute("filter_type", programs[index].parameters[kFtype]); | ||
| program_xml->setAttribute("ffreq", programs[index].parameters[kFfreq]); | ||
| program_xml->setAttribute("ffreqv", programs[index].parameters[kFfreqv]); | ||
| program_xml->setAttribute("fq", programs[index].parameters[kFq]); | ||
| program_xml->setAttribute("fqv", programs[index].parameters[kFqv]); | ||
| program_xml->setAttribute("env_type", programs[index].parameters[kEnvType]); | ||
| program_xml->setAttribute("env_shape", programs[index].parameters[kEnvSustain]); | ||
| program_xml->setAttribute("env_skew", programs[index].parameters[kEnvSkew]); | ||
| program_xml->setAttribute("delay_quant", programs[index].parameters[kDelayQuant]); | ||
| program_xml->setAttribute("dur_quant", programs[index].parameters[kDurQuant]); | ||
| program_xml->setAttribute("iot_quant", programs[index].parameters[kIotQuant]); | ||
| program_xml->setAttribute("trans_toggle", programs[index].parameters[kTransToggle]); | ||
| program_xml->setAttribute("gliss_toggle", programs[index].parameters[kGlissToggle]); | ||
| program_xml->setAttribute("freeze_toggle", programs[index].parameters[kFreezeToggle]); | ||
| program_xml->setAttribute("scale_key", programs[index].parameters[kScaleKey]); | ||
| program_xml->setAttribute("matrix_mod_1", programs[index].parameters[kMatrixMod1]); | ||
| program_xml->setAttribute("matrix_mod_2", programs[index].parameters[kMatrixMod1]); | ||
| program_xml->setAttribute("matrix_mod_3", programs[index].parameters[kMatrixMod3]); | ||
| // internal parameters | ||
| program_xml->setAttribute("scale", programs[index].scale); | ||
| program_xml->setAttribute("matrix_src_1", programs[index].matrix_source[0]); | ||
| program_xml->setAttribute("matrix_src_2", programs[index].matrix_source[1]); | ||
| program_xml->setAttribute("matrix_src_3", programs[index].matrix_source[2]); | ||
| program_xml->setAttribute("matrix_dest_1", programs[index].matrix_dest[0]); | ||
| program_xml->setAttribute("matrix_dest_2", programs[index].matrix_dest[1]); | ||
| program_xml->setAttribute("matrix_dest_3", programs[index].matrix_dest[2]); | ||
| program_xml->setAttribute("matrix_mode_1", programs[index].matrix_mode[0]); | ||
| program_xml->setAttribute("matrix_mode_2", programs[index].matrix_mode[1]); | ||
| program_xml->setAttribute("matrix_mode_3", programs[index].matrix_mode[2]); | ||
| return program_xml; | ||
| } | ||
|
|
||
| void ProgramBank::loadProgramFromXml(int index, XmlElement* parameters_xml) | ||
| { | ||
| if (!parameters_xml->hasTagName("ARGOTLUNAR2_PROGRAM")) { | ||
| return; | ||
| } | ||
| // external parameters | ||
| programs[index].name = parameters_xml->getStringAttribute("program_name"); | ||
| programs[index].parameters[kGrains] = static_cast<float>(parameters_xml->getDoubleAttribute("grains")); | ||
| programs[index].parameters[kMix] = static_cast<float>(parameters_xml->getDoubleAttribute("mix")); | ||
| programs[index].parameters[kIngain] = static_cast<float>(parameters_xml->getDoubleAttribute("input_gain")); | ||
| programs[index].parameters[kFeedback] = static_cast<float>(parameters_xml->getDoubleAttribute("feedback")); | ||
| programs[index].parameters[kAmp] = static_cast<float>(parameters_xml->getDoubleAttribute("amp")); | ||
| programs[index].parameters[kAmpv] = static_cast<float>(parameters_xml->getDoubleAttribute("ampv")); | ||
| programs[index].parameters[kPan] = static_cast<float>(parameters_xml->getDoubleAttribute("pan")); | ||
| programs[index].parameters[kPanv] = static_cast<float>(parameters_xml->getDoubleAttribute("panv")); | ||
| programs[index].parameters[kDelay] = static_cast<float>(parameters_xml->getDoubleAttribute("delay")); | ||
| programs[index].parameters[kDelayv] = static_cast<float>(parameters_xml->getDoubleAttribute("delayv")); | ||
| programs[index].parameters[kIot] = static_cast<float>(parameters_xml->getDoubleAttribute("iot")); | ||
| programs[index].parameters[kIotv] = static_cast<float>(parameters_xml->getDoubleAttribute("iotv")); | ||
| programs[index].parameters[kDur] = static_cast<float>(parameters_xml->getDoubleAttribute("dur")); | ||
| programs[index].parameters[kDurv] = static_cast<float>(parameters_xml->getDoubleAttribute("durv")); | ||
| programs[index].parameters[kTrans] = static_cast<float>(parameters_xml->getDoubleAttribute("trans")); | ||
| programs[index].parameters[kTransv] = static_cast<float>(parameters_xml->getDoubleAttribute("transv")); | ||
| programs[index].parameters[kGliss] = static_cast<float>(parameters_xml->getDoubleAttribute("gliss")); | ||
| programs[index].parameters[kGlissv] = static_cast<float>(parameters_xml->getDoubleAttribute("glissv")); | ||
| programs[index].parameters[kFfreq] = static_cast<float>(parameters_xml->getDoubleAttribute("ffreq")); | ||
| programs[index].parameters[kFfreqv] = static_cast<float>(parameters_xml->getDoubleAttribute("ffreqv")); | ||
| programs[index].parameters[kFtype] = static_cast<float>(parameters_xml->getDoubleAttribute("filter_type")); | ||
| programs[index].parameters[kFq] = static_cast<float>(parameters_xml->getDoubleAttribute("fq")); | ||
| programs[index].parameters[kFqv] = static_cast<float>(parameters_xml->getDoubleAttribute("fqv")); | ||
| programs[index].parameters[kEnvType] = static_cast<float>(parameters_xml->getDoubleAttribute("env_type")); | ||
| programs[index].parameters[kEnvSustain] = static_cast<float>(parameters_xml->getDoubleAttribute("env_shape")); | ||
| programs[index].parameters[kEnvSkew] = static_cast<float>(parameters_xml->getDoubleAttribute("env_skew")); | ||
| programs[index].parameters[kDelayQuant] = static_cast<float>(parameters_xml->getDoubleAttribute("delay_quant")); | ||
| programs[index].parameters[kDurQuant] = static_cast<float>(parameters_xml->getDoubleAttribute("dur_quant")); | ||
| programs[index].parameters[kIotQuant] = static_cast<float>(parameters_xml->getDoubleAttribute("iot_quant")); | ||
| programs[index].parameters[kTransToggle] = static_cast<float>(parameters_xml->getDoubleAttribute("trans_toggle")); | ||
| programs[index].parameters[kGlissToggle] = static_cast<float>(parameters_xml->getDoubleAttribute("gliss_toggle")); | ||
| programs[index].parameters[kFreezeToggle] = static_cast<float>(parameters_xml->getDoubleAttribute("freeze_toggle")); | ||
| programs[index].parameters[kScaleKey] = static_cast<float>(parameters_xml->getDoubleAttribute("scale_key")); | ||
| programs[index].parameters[kMatrixMod1] = static_cast<float>(parameters_xml->getDoubleAttribute("matrix_mod_1")); | ||
| programs[index].parameters[kMatrixMod2] = static_cast<float>(parameters_xml->getDoubleAttribute("matrix_mod_2")); | ||
| programs[index].parameters[kMatrixMod3] = static_cast<float>(parameters_xml->getDoubleAttribute("matrix_mod_3")); | ||
| // internal parameters | ||
| programs[index].scale = parameters_xml->getIntAttribute("scale"); | ||
| programs[index].matrix_source[0] = static_cast<ModSource>(parameters_xml->getIntAttribute("matrix_src_1")); | ||
| programs[index].matrix_source[1] = static_cast<ModSource>(parameters_xml->getIntAttribute("matrix_src_2")); | ||
| programs[index].matrix_source[2] = static_cast<ModSource>(parameters_xml->getIntAttribute("matrix_src_3")); | ||
| programs[index].matrix_dest[0] = static_cast<ModDest>(parameters_xml->getIntAttribute("matrix_dest_1")); | ||
| programs[index].matrix_dest[1] = static_cast<ModDest>(parameters_xml->getIntAttribute("matrix_dest_2")); | ||
| programs[index].matrix_dest[2] = static_cast<ModDest>(parameters_xml->getIntAttribute("matrix_dest_3")); | ||
| programs[index].matrix_mode[0] = static_cast<ModMode>(parameters_xml->getIntAttribute("matrix_mode_1")); | ||
| programs[index].matrix_mode[1] = static_cast<ModMode>(parameters_xml->getIntAttribute("matrix_mode_2")); | ||
| programs[index].matrix_mode[2] = static_cast<ModMode>(parameters_xml->getIntAttribute("matrix_mode_3")); | ||
| } | ||
|
|
||
|
|
||
| void ProgramBank::initProgram(int index) | ||
| { | ||
| programs[index].initParameters(); | ||
| } | ||
|
|
||
| const String ProgramBank::getProgramName(int index) | ||
| { | ||
| return programs[index].name; | ||
| } | ||
|
|
||
| void ProgramBank::setProgramName(int index, const String new_name) | ||
| { | ||
| programs[index].name = new_name; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #ifndef PROGRAMBANK_H | ||
| #define PROGRAMBANK_H | ||
|
|
||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include "Debug.h" | ||
| #include "Program.h" | ||
| #include "Parameters.h" | ||
|
|
||
| class Parameters; | ||
| class Program; | ||
|
|
||
| class ProgramBank | ||
| { | ||
| public: | ||
| ProgramBank(const int num_programs, Parameters* parameters); | ||
| ~ProgramBank(); | ||
|
|
||
| void initProgram(int index); | ||
| void loadProgramState(int index); | ||
| void saveProgramState(int index); | ||
|
|
||
| XmlElement* createBankXml(); | ||
| XmlElement* createProgramXml(int index); | ||
|
|
||
| void loadBankFromXml(XmlElement* bank_xml); | ||
| void loadProgramFromXml(int index, XmlElement* parameters_xml); | ||
|
|
||
| const String getProgramName(int index); | ||
| void setProgramName(int index, const String new_name); | ||
|
|
||
| private: | ||
| int num_programs; | ||
| Program* programs; //[NUMPROGRAMS]; | ||
| Parameters* parameters; | ||
| //MidiMapper* midi_mapper; | ||
| XmlElement* bank; | ||
| }; | ||
|
|
||
| #endif //PROGRAMBANK_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,251 @@ | ||
| #include "TimeQuantizer.h" | ||
|
|
||
| TimeQuantizer::TimeQuantizer(Parameters* parameters, | ||
| const int internal_block_size) | ||
| { | ||
| this->parameters = parameters; | ||
| this->internal_block_size = internal_block_size; | ||
| initialize(); | ||
| } | ||
|
|
||
| TimeQuantizer::~TimeQuantizer() | ||
| { | ||
| } | ||
|
|
||
| void TimeQuantizer::initialize() | ||
| { | ||
| delay_quant_range[QUANT_128] = 64; | ||
| delay_quant_range[QUANT_128T] = 96; | ||
| delay_quant_range[QUANT_64] = 64; | ||
| delay_quant_range[QUANT_64T] = 96; | ||
| delay_quant_range[QUANT_32] = 64; | ||
| delay_quant_range[QUANT_32T] = 96; | ||
| delay_quant_range[QUANT_16] = 32; | ||
| delay_quant_range[QUANT_16T] = 48; | ||
| delay_quant_range[QUANT_8] = 16; | ||
| delay_quant_range[QUANT_8T] = 24; | ||
| delay_quant_range[QUANT_4] = 8; | ||
| delay_quant_range[QUANT_4T] = 12; | ||
|
|
||
| iot_quant_range[QUANT_128] = 32; | ||
| iot_quant_range[QUANT_128T] = 48; | ||
| iot_quant_range[QUANT_64] = 32; | ||
| iot_quant_range[QUANT_64T] = 48; | ||
| iot_quant_range[QUANT_32] = 32; | ||
| iot_quant_range[QUANT_32T] = 48; | ||
| iot_quant_range[QUANT_16] = 16; | ||
| iot_quant_range[QUANT_16T] = 24; | ||
| iot_quant_range[QUANT_8] = 8; | ||
| iot_quant_range[QUANT_8T] = 12; | ||
| iot_quant_range[QUANT_4] = 4; | ||
| iot_quant_range[QUANT_4T] = 6; | ||
|
|
||
| dur_quant_range[QUANT_128] = 32; | ||
| dur_quant_range[QUANT_128T] = 48; | ||
| dur_quant_range[QUANT_64] = 32; | ||
| dur_quant_range[QUANT_64T] = 48; | ||
| dur_quant_range[QUANT_32] = 32; | ||
| dur_quant_range[QUANT_32T] = 48; | ||
| dur_quant_range[QUANT_16] = 16; | ||
| dur_quant_range[QUANT_16T] = 24; | ||
| dur_quant_range[QUANT_8] = 8; | ||
| dur_quant_range[QUANT_8T] = 12; | ||
| dur_quant_range[QUANT_4] = 4; | ||
| dur_quant_range[QUANT_4T] = 6; | ||
|
|
||
| quant_mode_strings[QUANT_MS] = "ms"; | ||
| quant_mode_strings[QUANT_128] = "/128"; | ||
| quant_mode_strings[QUANT_128T] = "/128T"; | ||
| quant_mode_strings[QUANT_64] = "/64"; | ||
| quant_mode_strings[QUANT_64T] = "/64T"; | ||
| quant_mode_strings[QUANT_32] = "/32"; | ||
| quant_mode_strings[QUANT_32T] = "/32T"; | ||
| quant_mode_strings[QUANT_16] = "/16"; | ||
| quant_mode_strings[QUANT_16T] = "/16T"; | ||
| quant_mode_strings[QUANT_8] = "/8"; | ||
| quant_mode_strings[QUANT_8T] = "/8T"; | ||
| quant_mode_strings[QUANT_4] = "/4"; | ||
| quant_mode_strings[QUANT_4T] = "/4T"; | ||
| quant_mode_strings[QUANT_MS_LONG] = "long"; | ||
|
|
||
| quant_factors[QUANT_128] = 1.0f/128.0f; | ||
| quant_factors[QUANT_128T] = 1.0f/196.0f; | ||
| quant_factors[QUANT_64] = 1.0f/64.0f; | ||
| quant_factors[QUANT_64T] = 1.0f/96.0f; | ||
| quant_factors[QUANT_32] = 1.0f/32.0f; | ||
| quant_factors[QUANT_32T] = 1.0f/48.0f; | ||
| quant_factors[QUANT_16] = 1.0f/16.0f; | ||
| quant_factors[QUANT_16T] = 1.0f/24.0f; | ||
| quant_factors[QUANT_8] = 1.0f/8.0f; | ||
| quant_factors[QUANT_8T] = 1.0f/12.0f; | ||
| quant_factors[QUANT_4] = 1.0f/4.0f; | ||
| quant_factors[QUANT_4T] = 1.0f/6.0f; | ||
|
|
||
| pos_bpm = 0.0f; | ||
| pos_beatpos = 0.0f; | ||
| pos_seconds = 0.0f; | ||
| beatpos_increment = 0.0f; | ||
| samplerate = 0.0f; | ||
| quantization_enabled = false; | ||
| prev_ppqpos = 0.0; | ||
| } | ||
|
|
||
| int TimeQuantizer::getQuantStepRange(const ParameterType parameter, | ||
| const QuantizeMode quantize_mode) | ||
| { | ||
| switch (parameter) { | ||
| case kDelayQuant: | ||
| return delay_quant_range[quantize_mode]; | ||
| case kIotQuant: | ||
| return iot_quant_range[quantize_mode]; | ||
| case kDurQuant: | ||
| default: | ||
| return dur_quant_range[quantize_mode]; | ||
| } | ||
| } | ||
|
|
||
| float TimeQuantizer::getQuantFactor(const QuantizeMode quantize_mode) | ||
| { | ||
| return quant_factors[quantize_mode]; | ||
| } | ||
|
|
||
| void TimeQuantizer::setQuantizeMode(const ParameterType parameter, | ||
| const float value) | ||
| { | ||
| switch (parameter) { | ||
| case kDelayQuant: | ||
| delay_quant_mode = static_cast<QuantizeMode>( | ||
| MathFunc::roundFtoI(value * NumQuantModes::delay)); | ||
| if(delay_quant_mode == 0) | ||
| delay_quant_mode = QUANT_MS; | ||
| return; | ||
| case kIotQuant: | ||
| iot_quant_mode = static_cast<QuantizeMode>( | ||
| MathFunc::roundFtoI(value * NumQuantModes::iot)); | ||
| if(iot_quant_mode == 0) | ||
| iot_quant_mode = QUANT_MS; | ||
| return; | ||
| case kDurQuant: | ||
| default: | ||
| dur_quant_mode = static_cast<QuantizeMode>( | ||
| MathFunc::roundFtoI(value * NumQuantModes::dur)); | ||
| if(dur_quant_mode == 0) | ||
| dur_quant_mode = QUANT_MS; | ||
| } | ||
| } | ||
|
|
||
| const QuantizeMode TimeQuantizer::getQuantizeMode(const ParameterType parameter) | ||
| { | ||
| switch (parameter) { | ||
| case kDelayQuant: | ||
| return delay_quant_mode; | ||
| case kIotQuant: | ||
| return iot_quant_mode; | ||
| case kDurQuant: | ||
| default: | ||
| return dur_quant_mode; | ||
| } | ||
| } | ||
|
|
||
| int TimeQuantizer::getQuantValue(const ParameterType parameter, float value) | ||
| { | ||
| int quant_value = 0; | ||
|
|
||
| switch (parameter) { | ||
| case kDelayQuant: | ||
| quant_value = | ||
| MathFunc::roundFtoI(value * delay_quant_range[delay_quant_mode]); | ||
| break; | ||
| case kIotQuant: | ||
| quant_value = | ||
| MathFunc::roundFtoI(value * iot_quant_range[iot_quant_mode]); | ||
| break; | ||
| case kDurQuant: | ||
| default: | ||
| quant_value = | ||
| MathFunc::roundFtoI(value * dur_quant_range[dur_quant_mode]); | ||
| } | ||
| if (quant_value == 0) | ||
| quant_value++; | ||
| return quant_value; | ||
| } | ||
|
|
||
| String TimeQuantizer::getQuantModeString(const ParameterType parameter) | ||
| { | ||
| switch (parameter) { | ||
| case kDelayQuant: | ||
| return quant_mode_strings[delay_quant_mode]; | ||
| case kIotQuant: | ||
| return quant_mode_strings[iot_quant_mode]; | ||
| case kDurQuant: | ||
| default: | ||
| return quant_mode_strings[dur_quant_mode]; | ||
| } | ||
| } | ||
|
|
||
| String TimeQuantizer::getQuantValueString(const ParameterType parameter, | ||
| float value) | ||
| { | ||
| return String(getQuantValue(parameter, value)) | ||
| + getQuantModeString(parameter); | ||
| } | ||
|
|
||
| float TimeQuantizer::getBarPos() | ||
| { | ||
| float secondsPerBar = 60.0f / (pos_bpm / 4.0f); | ||
| float barPos = (pos_seconds / secondsPerBar); | ||
| barPos = barPos - static_cast<int>(barPos); | ||
| return barPos; | ||
| } | ||
|
|
||
| int TimeQuantizer::quantizeLength(const ParameterType parameter, float value) | ||
| { | ||
| int quant_steps = getQuantValue(parameter, value); | ||
| float quant_factor = getQuantFactor(getQuantizeMode(parameter)); | ||
| float bar_length = 60.0f / (pos_bpm / 4.0f); | ||
| int bar_samples = static_cast<int>(bar_length * samplerate); | ||
| float quant_step_samples = bar_samples * quant_factor; | ||
| return MathFunc::roundFtoI(quant_step_samples * quant_steps); | ||
| } | ||
|
|
||
| // finds distance (in samples) to nearest quantize boundary | ||
| // adds quant_steps * samples_per_quant_step to distance | ||
| int TimeQuantizer::quantizeStartPos(const ParameterType parameter, float value) | ||
| { | ||
| int quant_steps = getQuantValue(parameter, value) - 1; | ||
| float quant_factor = getQuantFactor(getQuantizeMode(parameter)); | ||
| float bar_length = 60.0f / (pos_bpm / 4.0f); | ||
| int bar_samples = static_cast<int>(bar_length * samplerate); | ||
| float samples_per_quant_step = bar_samples * quant_factor; | ||
| float distance = getBarPos() / quant_factor; | ||
| distance = ceil(distance) - distance; | ||
| distance *= samples_per_quant_step; | ||
| distance += (quant_steps * samples_per_quant_step); | ||
| return MathFunc::roundFtoI(distance); | ||
| } | ||
|
|
||
| void TimeQuantizer::setSampleRate(float samplerate) | ||
| { | ||
| this->samplerate = samplerate; | ||
| } | ||
|
|
||
| void TimeQuantizer::setPositionInfo(AudioPlayHead::CurrentPositionInfo* pos) | ||
| { | ||
| quantization_enabled = true; | ||
| pos_bpm = static_cast<float>(pos->bpm); | ||
| pos_seconds = static_cast<float>(pos->timeInSeconds); | ||
| pos_beatpos = static_cast<float>(pos->ppqPosition | ||
| - pos->ppqPositionOfLastBarStart); | ||
| beatpos_increment = (internal_block_size / samplerate) * (pos_bpm / 60.0f); | ||
| } | ||
|
|
||
| void TimeQuantizer::incrementPositionInfo() | ||
| { | ||
| if (!quantization_enabled) | ||
| return; | ||
| pos_seconds += (internal_block_size / samplerate); | ||
| pos_beatpos += beatpos_increment; | ||
| if (pos_beatpos > 1.0f) | ||
| pos_beatpos -= 1.0f; | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| #ifndef TIMEQUANTIZER_H | ||
| #define TIMEQUANTIZER_H | ||
|
|
||
| #include <map> | ||
| #include "../JuceLibraryCode/JuceHeader.h" | ||
| #include "Misc.h" | ||
| #include "Parameters.h" | ||
| #include "ParametersEnum.h" | ||
|
|
||
| class Parameters; | ||
|
|
||
| class TimeQuantizer | ||
| { | ||
| public: | ||
| TimeQuantizer(Parameters* parameters, const int internal_block_size); | ||
| ~TimeQuantizer(); | ||
| void setPositionInfo(AudioPlayHead::CurrentPositionInfo* pos); | ||
| void incrementPositionInfo(); | ||
| String getQuantModeString(const ParameterType parameter); | ||
| String getQuantValueString(const ParameterType parameter, float value); | ||
| void setQuantizeMode(const ParameterType parameter, const float value); | ||
| const QuantizeMode getQuantizeMode(const ParameterType parameter); | ||
| int quantizeLength(const ParameterType parameter, float value); | ||
| int quantizeStartPos(const ParameterType parameter, float value); | ||
| void setSampleRate(float samplerate); | ||
|
|
||
| private: | ||
| void initialize(); | ||
| float getBarPos(); | ||
| float getQuantFactor(const QuantizeMode quantize_mode); | ||
| int getQuantStepRange(const ParameterType parameter, | ||
| const QuantizeMode quantize_mode); | ||
| int getQuantValue(const ParameterType parameter, float value); | ||
|
|
||
| bool quantization_enabled; | ||
| int internal_block_size; | ||
| double prev_ppqpos; | ||
| float pos_bpm; | ||
| float pos_beatpos; | ||
| float pos_seconds; | ||
| float samplerate; | ||
| float beatpos_increment; | ||
| const Parameters* parameters; | ||
| QuantizeMode delay_quant_mode; | ||
| QuantizeMode iot_quant_mode; | ||
| QuantizeMode dur_quant_mode; | ||
| std::map<QuantizeMode, int> delay_quant_range; | ||
| std::map<QuantizeMode, int> iot_quant_range; | ||
| std::map<QuantizeMode, int> dur_quant_range; | ||
| std::map<QuantizeMode, float> quant_factors; | ||
| std::map<QuantizeMode, String> quant_mode_strings; | ||
| }; | ||
|
|
||
| #endif //TIMEQUANTIZER_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
|
|
||
| dofile("../../../scripts/make-project.lua") | ||
|
|
||
| package = make_juce_vst_project("argotlunar") | ||
|
|
||
| package.includepaths = { | ||
| package.includepaths, | ||
| "../Source", | ||
| "../JuceLibraryCode" | ||
| } | ||
|
|
||
| package.files = { | ||
| matchfiles ( | ||
| "../Source/*.cpp", | ||
| "../../../libs/juce-plugin/JucePluginMain.cpp" | ||
| ) | ||
| } |