@@ -0,0 +1,50 @@ | |||
# ----------------------------------------- | |||
# Compile all the Plugins | |||
all: plugins | |||
plugins: lv2 vst | |||
# ----------------------------------------- | |||
# lv2 | |||
lv2: | |||
install -d ../bin/lv2 | |||
$(MAKE) -C argotlunar/LV2 | |||
$(MAKE) -C cabbage/LV2-fx | |||
$(MAKE) -C cabbage/LV2-ins | |||
$(MAKE) -C cabbage/LV2-midi | |||
# ----------------------------------------- | |||
# vst | |||
vst: | |||
install -d ../bin/vst | |||
$(MAKE) -C argotlunar/VST | |||
$(MAKE) -C cabbage/VST-fx | |||
$(MAKE) -C cabbage/VST-ins | |||
$(MAKE) -C cabbage/VST-midi | |||
# ----------------------------------------- | |||
# clean | |||
clean: | |||
# LV2 | |||
$(MAKE) clean -C argotlunar/LV2 | |||
$(MAKE) clean -C cabbage/LV2-fx | |||
$(MAKE) clean -C cabbage/LV2-ins | |||
$(MAKE) clean -C cabbage/LV2-midi | |||
# VST | |||
$(MAKE) clean -C argotlunar/VST | |||
$(MAKE) clean -C cabbage/VST-fx | |||
$(MAKE) clean -C cabbage/VST-ins | |||
$(MAKE) clean -C cabbage/VST-midi | |||
rm -rf */LV2/intermediate | |||
rm -rf */VST/intermediate | |||
distclean: clean | |||
rm -rf */LV2/*.lv2 | |||
rm -f */*/Makefile | |||
rm -f */*/*.make |
@@ -0,0 +1,31 @@ | |||
/* | |||
IMPORTANT! This file is auto-generated each time you save your | |||
project - if you alter its contents, your changes may be overwritten! | |||
This is the header file that your files should include in order to get all the | |||
JUCE library headers. You should avoid including the JUCE headers directly in | |||
your own source files, because that wouldn't pick up the correct configuration | |||
options for your app. | |||
*/ | |||
#ifndef __APPHEADERFILE_ULIIGD__ | |||
#define __APPHEADERFILE_ULIIGD__ | |||
#include "JucePluginMain.h" | |||
#if ! DONT_SET_USING_JUCE_NAMESPACE | |||
// If your code uses a lot of JUCE classes, then this will obviously save you | |||
// a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. | |||
using namespace juce; | |||
#endif | |||
namespace ProjectInfo | |||
{ | |||
const char* const projectName = "Argotlunar"; | |||
const char* const versionString = "2.0.6"; | |||
const int versionNumber = 0x20006; | |||
} | |||
#endif // __APPHEADERFILE_ULIIGD__ |
@@ -0,0 +1,129 @@ | |||
/* | |||
IMPORTANT! This file is auto-generated each time you save your | |||
project - if you alter its contents, your changes may be overwritten! | |||
There's a section below where you can add your own custom code safely, and the | |||
Introjucer will preserve the contents of that block, but the best way to change | |||
any of these definitions is by using the Introjucer's project settings. | |||
Any commented-out settings will assume their default values. | |||
*/ | |||
#ifndef __JUCE_APPCONFIG_ULIIGD__ | |||
#define __JUCE_APPCONFIG_ULIIGD__ | |||
//============================================================================== | |||
// Audio plugin settings.. | |||
#ifndef JucePlugin_Name | |||
#define JucePlugin_Name "Argotlunar" | |||
#endif | |||
#ifndef JucePlugin_Desc | |||
#define JucePlugin_Desc "Argotlunar" | |||
#endif | |||
#ifndef JucePlugin_Manufacturer | |||
#define JucePlugin_Manufacturer "Michael Ourednik" | |||
#endif | |||
#ifndef JucePlugin_ManufacturerCode | |||
#define JucePlugin_ManufacturerCode 'ARG1' | |||
#endif | |||
#ifndef JucePlugin_PluginCode | |||
#define JucePlugin_PluginCode 'ARG1' | |||
#endif | |||
#ifndef JucePlugin_MaxNumInputChannels | |||
#define JucePlugin_MaxNumInputChannels 2 | |||
#endif | |||
#ifndef JucePlugin_MaxNumOutputChannels | |||
#define JucePlugin_MaxNumOutputChannels 2 | |||
#endif | |||
#ifndef JucePlugin_PreferredChannelConfigurations | |||
#define JucePlugin_PreferredChannelConfigurations {2, 2} | |||
#endif | |||
#ifndef JucePlugin_IsSynth | |||
#define JucePlugin_IsSynth 0 | |||
#endif | |||
#ifndef JucePlugin_WantsMidiInput | |||
#define JucePlugin_WantsMidiInput 0 | |||
#endif | |||
#ifndef JucePlugin_ProducesMidiOutput | |||
#define JucePlugin_ProducesMidiOutput 0 | |||
#endif | |||
#ifndef JucePlugin_SilenceInProducesSilenceOut | |||
#define JucePlugin_SilenceInProducesSilenceOut 0 | |||
#endif | |||
#ifndef JucePlugin_EditorRequiresKeyboardFocus | |||
#define JucePlugin_EditorRequiresKeyboardFocus 1 | |||
#endif | |||
#ifndef JucePlugin_Version | |||
#define JucePlugin_Version 2.0.6 | |||
#endif | |||
#ifndef JucePlugin_VersionCode | |||
#define JucePlugin_VersionCode 0x20006 | |||
#endif | |||
#ifndef JucePlugin_VersionString | |||
#define JucePlugin_VersionString "2.0.6" | |||
#endif | |||
#ifndef JucePlugin_VSTUniqueID | |||
#define JucePlugin_VSTUniqueID JucePlugin_PluginCode | |||
#endif | |||
#ifndef JucePlugin_VSTCategory | |||
#define JucePlugin_VSTCategory kPlugCategEffect | |||
#endif | |||
#ifndef JucePlugin_AUMainType | |||
#define JucePlugin_AUMainType kAudioUnitType_Effect | |||
#endif | |||
#ifndef JucePlugin_AUSubType | |||
#define JucePlugin_AUSubType JucePlugin_PluginCode | |||
#endif | |||
#ifndef JucePlugin_AUExportPrefix | |||
#define JucePlugin_AUExportPrefix ArgotlunarAU | |||
#endif | |||
#ifndef JucePlugin_AUExportPrefixQuoted | |||
#define JucePlugin_AUExportPrefixQuoted "ArgotlunarAU" | |||
#endif | |||
#ifndef JucePlugin_AUManufacturerCode | |||
#define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode | |||
#endif | |||
#ifndef JucePlugin_CFBundleIdentifier | |||
#define JucePlugin_CFBundleIdentifier com.MichaelOurednik.Argotlunar | |||
#endif | |||
#ifndef JucePlugin_RTASCategory | |||
#define JucePlugin_RTASCategory ePlugInCategory_None | |||
#endif | |||
#ifndef JucePlugin_RTASManufacturerCode | |||
#define JucePlugin_RTASManufacturerCode JucePlugin_ManufacturerCode | |||
#endif | |||
#ifndef JucePlugin_RTASProductId | |||
#define JucePlugin_RTASProductId JucePlugin_PluginCode | |||
#endif | |||
#ifndef JucePlugin_RTASDisableBypass | |||
#define JucePlugin_RTASDisableBypass 0 | |||
#endif | |||
#ifndef JucePlugin_RTASDisableMultiMono | |||
#define JucePlugin_RTASDisableMultiMono 0 | |||
#endif | |||
#ifndef JucePlugin_AAXIdentifier | |||
#define JucePlugin_AAXIdentifier com.yourcompany.Argotlunar | |||
#endif | |||
#ifndef JucePlugin_AAXManufacturerCode | |||
#define JucePlugin_AAXManufacturerCode JucePlugin_ManufacturerCode | |||
#endif | |||
#ifndef JucePlugin_AAXProductId | |||
#define JucePlugin_AAXProductId JucePlugin_PluginCode | |||
#endif | |||
#ifndef JucePlugin_AAXPluginId | |||
#define JucePlugin_AAXPluginId JucePlugin_PluginCode | |||
#endif | |||
#ifndef JucePlugin_AAXCategory | |||
#define JucePlugin_AAXCategory AAX_ePlugInCategory_Dynamics | |||
#endif | |||
#ifndef JucePlugin_AAXDisableBypass | |||
#define JucePlugin_AAXDisableBypass 0 | |||
#endif | |||
#define JucePlugin_LV2URI "http://argotlunar.info/" | |||
#define JucePlugin_WantsLV2TimePos 1 | |||
#endif // __JUCE_APPCONFIG_ULIIGD__ |
@@ -0,0 +1,17 @@ | |||
dofile("../../../scripts/make-project.lua") | |||
package = make_juce_lv2_project("argotlunar") | |||
package.includepaths = { | |||
package.includepaths, | |||
"../Source", | |||
"../JuceLibraryCode" | |||
} | |||
package.files = { | |||
matchfiles ( | |||
"../Source/*.cpp", | |||
"../../../libs/juce-plugin/JucePluginMain.cpp" | |||
) | |||
} |
@@ -0,0 +1,10 @@ | |||
Argotlunar | |||
========== | |||
Realtime granulator VST plugin. | |||
Uses the JUCE toolkit. This version is based on JUCE Git 2013-02-17. | |||
Licensed under GPLv2 | |||
[http://argotlunar.info](http://argotlunar.info) |
@@ -0,0 +1,78 @@ | |||
#include "CombFilter.h" | |||
CombFilter::CombFilter(float samplerate) | |||
{ | |||
this->samplerate = samplerate; | |||
buflen = (int)(samplerate / 22.0f); | |||
buffer = new float[buflen]; | |||
rampsamples = (int)(samplerate / 1000.0f); // initial 1ms ramp to avoid clicks | |||
ramp_increment = 1.0f / rampsamples; | |||
} | |||
CombFilter::~CombFilter() | |||
{ | |||
delete[] buffer; | |||
} | |||
// accepts params between 0.0f - 1.0f | |||
void CombFilter::initialize(float freq_param, float q_param) | |||
{ | |||
float freq_hz = pow(10.0f, freq_param * 3.0f) * 22.05f; | |||
delay = (int)((1.0f / freq_hz) * samplerate); | |||
resonance = q_param; | |||
buf_read_pos = buflen - delay; | |||
if (buf_read_pos == buflen) { | |||
buf_read_pos = 0; | |||
} | |||
for(int i = 0; i < buflen; i++) { | |||
buffer[i] = 10E-12f; | |||
} | |||
delay_buf_write_pos = 0; | |||
process_counter = 0; | |||
ramp = 0.0f; | |||
} | |||
void CombFilter::process(float* input, int sampleframes) | |||
{ | |||
if ((delay_buf_write_pos + sampleframes) < buflen | |||
&& (buf_read_pos + sampleframes) < buflen | |||
&& (process_counter + sampleframes) > rampsamples) { | |||
for (int i = 0; i < sampleframes; i++) { | |||
processSample(&input[i]); | |||
} | |||
} else { | |||
for (int i = 0; i < sampleframes; i++) { | |||
processSample(&input[i]); | |||
if (delay_buf_write_pos == buflen) { | |||
delay_buf_write_pos = 0; | |||
} | |||
if (buf_read_pos == buflen) { | |||
buf_read_pos = 0; | |||
} | |||
if (process_counter < rampsamples) { | |||
process_counter++; | |||
ramp += ramp_increment; | |||
} | |||
} | |||
} | |||
} | |||
/* | |||
inline void CombFilter::processSample(float* input) | |||
{ | |||
buffer[delay_buf_write_pos] = *input * resonance * ramp; | |||
*input = (*input * 0.5f) + (buffer[buf_read_pos] * 0.5f); | |||
delay_buf_write_pos++; | |||
buf_read_pos++; | |||
process_counter++; | |||
} | |||
*/ | |||
inline void CombFilter::processSample(float* input) | |||
{ | |||
*input = *input + buffer[buf_read_pos] * resonance; | |||
buffer[delay_buf_write_pos] = *input ; | |||
delay_buf_write_pos++; | |||
buf_read_pos++; | |||
process_counter++; | |||
} |
@@ -0,0 +1,32 @@ | |||
#ifndef COMBFILTER_H | |||
#define COMBFILTER_H | |||
#include <math.h> | |||
#include "Debug.h" | |||
class CombFilter | |||
{ | |||
public: | |||
CombFilter(float samplerate); | |||
~CombFilter(); | |||
void initialize(float freq_param, float q_param); | |||
void process(float* input, int sampleframes); | |||
private: | |||
inline void processSample(float* input); | |||
float *buffer; | |||
float delaysample; | |||
float output; | |||
float samplerate; | |||
float ramp_increment; | |||
float ramp; | |||
float resonance; | |||
int rampsamples; | |||
int delay; | |||
int buflen; | |||
int delay_buf_write_pos, buf_read_pos; | |||
int process_counter; | |||
}; | |||
#endif //COMBFILTER_H |
@@ -0,0 +1,24 @@ | |||
#ifndef DEBUG_H | |||
#define DEBUG_H | |||
#ifdef LINUX | |||
#define DEBUG | |||
#endif | |||
#ifdef DEBUG | |||
#include <iostream> | |||
namespace dbg | |||
{ | |||
inline void string(std::string text) | |||
{ | |||
std::cout << text << "\n"; | |||
} | |||
inline void value(std::string text, float val) | |||
{ | |||
std::cout << text << ": " << val << "\n"; | |||
} | |||
} | |||
#endif //DEBUG | |||
#endif //DEBUG_H | |||
@@ -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; | |||
} | |||
@@ -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 |
@@ -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; | |||
} | |||
} | |||
@@ -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 |
@@ -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; | |||
} | |||
} | |||
@@ -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 |
@@ -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; | |||
} |
@@ -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 |
@@ -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 |
@@ -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; | |||
} | |||
@@ -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 |
@@ -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]; | |||
} | |||
@@ -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 |
@@ -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 |
@@ -0,0 +1,597 @@ | |||
#include "Parameters.h" | |||
Parameters::Parameters(Plugin* plugin, const int internal_block_size) | |||
{ | |||
this->plugin = plugin; | |||
time_quantizer = new TimeQuantizer(this, internal_block_size); | |||
delay_coeff = sqrt(plugin->granulator->kBufferSeconds * 1000.0f); | |||
iot_coeff = log10(kMaxIot * 1.0f); | |||
dur_coeff = log10(kMaxDuration * 1.0f); | |||
param = new float[NUM_PARAMS]; | |||
for (int i = 0; i < NUM_PARAMS; i++) { | |||
param[i]= 0.0f; | |||
} | |||
setParametersSavedState(true); | |||
quantization_disabled = false; | |||
} | |||
Parameters::~Parameters() | |||
{ | |||
delete[] param; | |||
delete time_quantizer; | |||
} | |||
void Parameters::initializeInternalParameters() | |||
{ | |||
for (int i = 0; i < (NUM_PARAMS - 2); i++) { | |||
setParameter(i, param[i], true); | |||
} | |||
setParametersSavedState(true); | |||
} | |||
float Parameters::getParameterFloatValue(ParameterType param_index) | |||
{ | |||
return param[param_index]; | |||
} | |||
void Parameters::setParameter(int index, float new_value, bool initializing) | |||
{ | |||
if (param[index] != new_value || initializing == true) { | |||
param[index] = new_value; | |||
switch(index) { | |||
case kGrains: | |||
selected_grains = MathFunc::roundFtoI( | |||
new_value * plugin->granulator->kMaxGrains); | |||
break; | |||
case kMix: | |||
dry_mix = 1.0f - new_value; | |||
break; | |||
case kAmp: | |||
case kAmpv: | |||
amp_max = param[kAmp] + param[kAmpv]; | |||
if (amp_max > 1.0f) | |||
amp_max = 1.0f; | |||
break; | |||
case kPan: | |||
case kPanv: | |||
pan_min = param[kPan] - (0.5f * param[kPanv]); | |||
pan_max = param[kPan] + (0.5f * param[kPanv]); | |||
if (pan_min < 0.0f) | |||
pan_min = 0.0f; | |||
if (pan_max > 1.0f) | |||
pan_max = 1.0f; | |||
break; | |||
case kDelay: | |||
case kDelayv: | |||
delay_max = param[kDelay] + param[kDelayv]; | |||
if (delay_max > 1.0f) | |||
delay_max = 1.0f; | |||
break; | |||
case kIot: | |||
case kIotv: | |||
iot_max = param[kIot] + param[kIotv]; | |||
if (iot_max > 1.0f) | |||
iot_max = 1.0f; | |||
break; | |||
case kDur: | |||
case kDurv: | |||
dur_max = param[kDur] + param[kDurv]; | |||
if (dur_max > 1.0f) | |||
dur_max = 1.0f; | |||
break; | |||
case kTrans: | |||
case kTransv: | |||
trans_min = param[kTrans] - (0.5f * param[kTransv]); | |||
trans_max = param[kTrans] + (0.5f * param[kTransv]); | |||
if (trans_min < 0.0f) | |||
trans_min = 0.0f; | |||
if (trans_max > 1.0f) | |||
trans_max = 1.0f; | |||
break; | |||
case kGliss: | |||
case kGlissv: | |||
gliss_min = param[kGliss] - (0.5f * param[kGlissv]); | |||
gliss_max = param[kGliss] + (0.5f * param[kGlissv]); | |||
if (gliss_min < 0.0f) | |||
gliss_min = 0.0f; | |||
if (gliss_max > 1.0f) | |||
gliss_max = 1.0f; | |||
break; | |||
case kFtype: | |||
filter_type = MathFunc::roundFtoI(new_value * 6.0f); | |||
break; | |||
case kFfreq: | |||
case kFfreqv: | |||
ffreq_max = param[kFfreq] + param[kFfreqv]; | |||
if (ffreq_max > 1.0f) | |||
ffreq_max = 1.0f; | |||
break; | |||
case kFq: | |||
case kFqv: | |||
fq_max = param[kFq] + param[kFqv]; | |||
if (fq_max > 1.0f) | |||
fq_max = 1.0f; | |||
break; | |||
case kEnvType: | |||
env_type = MathFunc::roundFtoI(new_value * 2.0f); | |||
break; | |||
/* | |||
case kEnvSustain: | |||
if (param[kEnvSustain] < 0.05f) { | |||
param[kEnvSustain] = 0.05f; | |||
} else if (param[kEnvSustain] > 0.95f) { | |||
param[kEnvSustain] = 0.95f; | |||
} | |||
break; | |||
case kEnvSkew: | |||
if (param[kEnvSkew] < 0.05f) { | |||
param[kEnvSkew] = 0.05f; | |||
} else if (param[kEnvSkew] > 0.95f) { | |||
param[kEnvSkew] = 0.95f; | |||
} | |||
break; | |||
*/ | |||
case kDelayQuant: | |||
if (quantization_disabled) | |||
param[kDelayQuant] = 1.0f/NumQuantModes::delay; | |||
time_quantizer->setQuantizeMode(kDelayQuant, param[kDelayQuant]); | |||
break; | |||
case kIotQuant: | |||
if (quantization_disabled) | |||
param[kIotQuant] = 1.0f/NumQuantModes::iot; | |||
time_quantizer->setQuantizeMode(kIotQuant, param[kIotQuant]); | |||
break; | |||
case kDurQuant: | |||
if (quantization_disabled) | |||
param[kDurQuant] = 1.0f/NumQuantModes::dur; | |||
time_quantizer->setQuantizeMode(kDurQuant, param[kDurQuant]); | |||
break; | |||
case kFreezeToggle: | |||
freeze = (new_value == 0.0f) ? false : true; | |||
break; | |||
case kScaleKey: | |||
// Should be 'new_value * 11'. Keeping '12' to maintain compatibility | |||
scale_key = MathFunc::roundFtoI(new_value * 12); | |||
if(scale_key == 12) scale_key--; | |||
break; | |||
} | |||
if (initializing == false) { | |||
setParametersSavedState(false); | |||
} | |||
} | |||
} | |||
const String Parameters::getParameterName(int index) | |||
{ | |||
switch (index) { | |||
case kGrains: | |||
return "grains"; | |||
case kMix: | |||
return "mix"; | |||
case kIngain: | |||
return "input_gain"; | |||
case kFeedback: | |||
return "feedback"; | |||
case kAmp: | |||
return "amp"; | |||
case kAmpv: | |||
return "ampv"; | |||
case kPan: | |||
return "pan"; | |||
case kPanv: | |||
return "panv"; | |||
case kDelay: | |||
return "delay"; | |||
case kDelayv: | |||
return "delayv"; | |||
case kTrans: | |||
return "trans"; | |||
case kTransv: | |||
return "transv"; | |||
case kGliss: | |||
return "gliss"; | |||
case kGlissv: | |||
return "glissv"; | |||
case kIot: | |||
return "IOT"; | |||
case kIotv: | |||
return "IOTv"; | |||
case kDur: | |||
return "dur"; | |||
case kDurv: | |||
return "durv"; | |||
case kFtype: | |||
return "filter_type"; | |||
case kFfreq: | |||
return "ffreq"; | |||
case kFfreqv: | |||
return "ffreqv"; | |||
case kFq: | |||
return "fq"; | |||
case kFqv: | |||
return "fqv"; | |||
case kEnvType: | |||
return "env_type"; | |||
case kEnvSustain: | |||
return "env_sustain"; | |||
case kEnvSkew: | |||
return "env_skew"; | |||
case kDelayQuant: | |||
return "delay_quantize"; | |||
case kDurQuant: | |||
return "dur_quantize"; | |||
case kIotQuant: | |||
return "IOT_quantize"; | |||
case kTransToggle: | |||
return "trans_toggle"; | |||
case kGlissToggle: | |||
return "gliss_toggle"; | |||
case kFreezeToggle: | |||
return "freeze_toggle"; | |||
case kScaleKey: | |||
return "scale_key"; | |||
case kMatrixMod1: | |||
return "matrix_mod_1"; | |||
case kMatrixMod2: | |||
return "matrix_mod_2"; | |||
case kMatrixMod3: | |||
return "matrix_mod_3"; | |||
case kProgram: | |||
return "program"; | |||
} | |||
return String::empty; | |||
} | |||
const String Parameters::getParameterText(int index) | |||
{ | |||
String text; | |||
switch (index) { | |||
case kMix: | |||
return String(dry_mix, 2) + " dry | " + String(param[kMix], 2) + " wet"; | |||
case kIngain: | |||
return getDecibelString(param[kIngain]); | |||
case kFeedback: | |||
return getDecibelString(param[kFeedback]); | |||
case kAmp: | |||
case kAmpv: | |||
if (param[kAmp] == amp_max) { | |||
return getDecibelString(param[kAmp]); | |||
} else { | |||
return getDecibelString(param[kAmp]) + ", " + getDecibelString(amp_max); | |||
} | |||
case kPan: | |||
case kPanv: | |||
if (pan_min == pan_max) { | |||
return getPanString(pan_min); | |||
} else { | |||
return getPanString(pan_min) + ", " + getPanString(pan_max); | |||
} | |||
case kDelay: | |||
case kDelayv: | |||
if (param[kDelay] == delay_max) { | |||
return getDelayString(param[kDelay]); | |||
} else { | |||
return getDelayString(param[kDelay]) + ", " + getDelayString(delay_max); | |||
} | |||
case kIot: | |||
case kIotv: | |||
if (param[kIot] == iot_max) { | |||
return getIOTString(param[kIot]); | |||
} else { | |||
return getIOTString(param[kIot]) + ", " + getIOTString(iot_max); | |||
} | |||
case kDur: | |||
case kDurv: | |||
if (param[kDur] == dur_max) { | |||
return getDurString(param[kDur]); | |||
} else { | |||
return getDurString(param[kDur]) + ", " + getDurString(dur_max); | |||
} | |||
case kTrans: | |||
case kTransv: { | |||
if (trans_min == trans_max) { | |||
return getTransString(trans_min); | |||
} else { | |||
text = getTransString(trans_min) + ", " + getTransString(trans_max); | |||
if (index == kTransv) | |||
text += " [+- " + String(static_cast<int>(param[kTransv] * 2400.0f)) + " c.]"; | |||
return text; | |||
} | |||
} | |||
case kGliss: | |||
case kGlissv: { | |||
if (gliss_min == gliss_max) { | |||
return getGlissString(gliss_min); | |||
} else { | |||
text = getGlissString(gliss_min) + ", " + getGlissString(gliss_max); | |||
if (index == kGlissv) | |||
text += " [+- " + String(static_cast<int>(param[kGlissv] * 2400.0f)) + " c.]"; | |||
return text; | |||
} | |||
} | |||
case kFfreq: | |||
case kFfreqv: | |||
if (param[kFfreq] == ffreq_max) { | |||
return getFFreqString(param[kFfreq]); | |||
} else { | |||
return getFFreqString(param[kFfreq]) + ", " + getFFreqString(ffreq_max); | |||
} | |||
case kFq: | |||
case kFqv: | |||
if (param[kFq] == fq_max) { | |||
return getFqString(param[kFq]); | |||
} else { | |||
return getFqString(param[kFq]) + ", " + getFqString(fq_max); | |||
} | |||
case kFtype: | |||
return getFilterTypeString(); | |||
case kEnvSustain: | |||
return getEnvSustainString(); | |||
case kEnvSkew: | |||
return getEnvSkewString(); | |||
case kEnvType: | |||
return getEnvTypeString(); | |||
case kTransToggle: | |||
return getToggleString(kTransToggle); | |||
case kGlissToggle: | |||
return getToggleString(kGlissToggle); | |||
case kFreezeToggle: | |||
return getToggleString(kFreezeToggle); | |||
case kGrains: | |||
return getNumGrainsString(); | |||
case kScaleKey: | |||
return getScaleKeyString(); | |||
case kMatrixMod1: | |||
return getMatrixmodString(kMatrixMod1); | |||
case kMatrixMod2: | |||
return getMatrixmodString(kMatrixMod2); | |||
case kMatrixMod3: | |||
return getMatrixmodString(kMatrixMod3); | |||
case kDelayQuant: | |||
return time_quantizer->getQuantModeString(kDelayQuant); | |||
case kDurQuant: | |||
return time_quantizer->getQuantModeString(kDurQuant); | |||
case kIotQuant: | |||
return time_quantizer->getQuantModeString(kIotQuant); | |||
} | |||
return ""; | |||
} | |||
void Parameters::setQuantizationDisabled() | |||
{ | |||
quantization_disabled = true; | |||
} | |||
String Parameters::getEnvSustainString() | |||
{ | |||
return String(param[kEnvSustain] * 100.0f, 1); | |||
} | |||
String Parameters::getEnvSkewString() | |||
{ | |||
float skew = (param[kEnvSkew] - 0.5f) * 200.0f; | |||
if (skew <= 0.0f) { | |||
return String(skew, 1); | |||
} else { | |||
return "+" + String(skew,1); | |||
} | |||
} | |||
String Parameters::getNumGrainsString() | |||
{ | |||
return String(MathFunc::roundFtoI(param[kGrains] | |||
* plugin->granulator->kMaxGrains)) + " grains"; | |||
} | |||
String Parameters::getFqString(float value) | |||
{ | |||
return String(value, 2) + " Q"; | |||
} | |||
String Parameters::getPercentString(float value) | |||
{ | |||
return String(value * 100, 1) + "% "; | |||
} | |||
String Parameters::getEnvTypeString() | |||
{ | |||
String types[] = {"raised cosine bell", "parabola", "triangle"}; | |||
int index = MathFunc::roundFtoI(param[kEnvType] * 2.0f); | |||
return types[index]; | |||
} | |||
String Parameters::getFilterTypeString() | |||
{ | |||
String types[] = {"off", "band", "low", "high", "notch", "comb", "random"}; | |||
int index = MathFunc::roundFtoI(param[kFtype] * 6.0f); | |||
return types[index]; | |||
} | |||
String Parameters::getScaleKeyString() | |||
{ | |||
String keys[] = {"C", "C#", "D", "D#", "E", "F", | |||
"F#", "G", "G#", "A", "A#", "B" | |||
}; | |||
return keys[scale_key]; | |||
} | |||
String Parameters::getMatrixmodString(int parameter) | |||
{ | |||
if (param[parameter] > 0.5f) { | |||
return "+" + String((int)((param[parameter] - 0.5f) * 200.0f)) + "%"; | |||
} else if (param[parameter] < 0.5f) { | |||
return String((int)((param[parameter] - 0.5f) * 200.0f)) + "%"; | |||
} else { | |||
return "0%"; | |||
} | |||
} | |||
String Parameters::getDecibelString(float value) | |||
{ | |||
if (value < 0.006f) { | |||
return "-inf"; | |||
} else { | |||
return String(log10(pow(value, 20)), 1) + " dB"; | |||
} | |||
} | |||
String Parameters::getToggleString(int parameter) | |||
{ | |||
return (param[parameter] == 0.0f) ? "off" : "on"; | |||
} | |||
String Parameters::getPanString(float value) | |||
{ | |||
if (value == 0.5f) { | |||
return "C"; | |||
} else if (value < 0.5f) { | |||
return String((value - 0.5f) * -2.0f, 2) + "L"; | |||
} else if (value > 0.5f) { | |||
return String((value - 0.5f) * 2.0f, 2) + "R"; | |||
} | |||
return ""; | |||
} | |||
float Parameters::getDelayMilliseconds(float value) | |||
{ | |||
return (value * delay_coeff) * (value * delay_coeff); | |||
} | |||
String Parameters::getDelayString(float value) | |||
{ | |||
QuantizeMode del_quant_mode = time_quantizer->getQuantizeMode(kDelayQuant); | |||
if (del_quant_mode == QUANT_MS) { | |||
return String(getDelayMilliseconds(value), 1) + " ms"; | |||
} else return time_quantizer->getQuantValueString(kDelayQuant, value); | |||
} | |||
float Parameters::getIOTMilliseconds(float value) | |||
{ | |||
return static_cast<float>(pow(10.0f, value * iot_coeff)); | |||
} | |||
String Parameters::getIOTString(float value) | |||
{ | |||
if (time_quantizer->getQuantizeMode(kIotQuant) == QUANT_MS) { | |||
return String(getIOTMilliseconds(value), 1) + " ms"; | |||
} else return time_quantizer->getQuantValueString(kIotQuant, value); | |||
} | |||
float Parameters::getDurMilliseconds(float value) | |||
{ | |||
return static_cast<float>(pow(10.0f, dur_coeff + (value * 2.0f))); | |||
} | |||
String Parameters::getDurString(float value) | |||
{ | |||
QuantizeMode dur_quant_mode = time_quantizer->getQuantizeMode(kDurQuant); | |||
if (dur_quant_mode == QUANT_MS || dur_quant_mode == QUANT_MS_LONG) { | |||
float length = getDurMilliseconds(value); | |||
if (dur_quant_mode == QUANT_MS_LONG) | |||
length *= 10.0f; | |||
return String(length, 1) + " ms"; | |||
} else return time_quantizer->getQuantValueString(kDurQuant, value); | |||
} | |||
String Parameters::getTransString(float value) | |||
{ | |||
if (value == 0.5f) { | |||
return "0"; | |||
} else { | |||
if (scale == 0) { | |||
return String(static_cast<int>((value - 0.5f) * 4800.0f)) + " c."; | |||
} else { | |||
int semitones = MathFunc::roundFtoI((value - 0.5f) * 48.0f); | |||
return String(semitones); | |||
} | |||
} | |||
} | |||
String Parameters::getGlissString(float value) | |||
{ | |||
if (value == 0.5f) { | |||
return "0"; | |||
} else { | |||
return String(static_cast<int>((value - 0.5f) * 4800.0f)) + " c."; | |||
} | |||
} | |||
String Parameters::getFFreqString(float value) | |||
{ | |||
return String(pow(10.0, value * 3.0) * 22.05f, 1) + " hz"; | |||
} | |||
int Parameters::getScale() | |||
{ | |||
return scale; | |||
} | |||
int Parameters::getMatrixDest(int index) | |||
{ | |||
return matrix_dest[index] + 1; | |||
} | |||
int Parameters::getMatrixSource(int index) | |||
{ | |||
return static_cast<int>(matrix_source[index] + 1); | |||
} | |||
int Parameters::getMatrixMode(int index) | |||
{ | |||
return static_cast<int>(matrix_mode[index]); | |||
} | |||
void Parameters::setMatrixSource(int index, int param) | |||
{ | |||
param--; | |||
if (matrix_source[index] != param) { | |||
matrix_source[index] = static_cast<ModSource>(param); | |||
setParametersSavedState(false); | |||
} | |||
plugin->setParametersChangedState(); | |||
} | |||
void Parameters::setMatrixDest(int index, int param) | |||
{ | |||
param--; | |||
if (matrix_dest[index] != param) { | |||
matrix_dest[index] = static_cast<ModDest>(param); | |||
setParametersSavedState(false); | |||
} | |||
plugin->setParametersChangedState(); | |||
} | |||
void Parameters::setMatrixMode(int index, int param) | |||
{ | |||
if (matrix_mode[index] != param) { | |||
matrix_mode[index] = static_cast<ModMode>(param); | |||
setParametersSavedState(false); | |||
} | |||
plugin->setParametersChangedState(); | |||
} | |||
void Parameters::setScale(int index) | |||
{ | |||
if (scale != index) { | |||
scale = index; | |||
setParametersSavedState(false); | |||
} | |||
} | |||
void Parameters::setParametersSavedState(bool state) | |||
{ | |||
plugin->setSavedState(state); | |||
} | |||
float Parameters::getSampleRate() | |||
{ | |||
return samplerate; | |||
} | |||
void Parameters::setSampleRate(float samplerate) | |||
{ | |||
this->samplerate = samplerate; | |||
time_quantizer->setSampleRate(samplerate); | |||
} | |||
@@ -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 |
@@ -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 |
@@ -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; | |||
} | |||
@@ -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 | |||
*/ |
@@ -0,0 +1,407 @@ | |||
#include "Plugin.h" | |||
#include "PluginEditor.h" | |||
AudioProcessor* JUCE_CALLTYPE createPluginFilter() | |||
{ | |||
return new Plugin(); | |||
} | |||
Plugin::Plugin() | |||
{ | |||
parameters = new Parameters(this, kInternalBlocksize); | |||
granulator = new Granulator(parameters, kInternalBlocksize); | |||
program_bank = new ProgramBank(kNumPrograms, parameters); | |||
editor_parameter_update_pending = false; | |||
editor_program_update_pending = false; | |||
current_program = 0; | |||
saved_state = true; | |||
block_sample_pos = 0; | |||
progchange_param_enabled = true; | |||
} | |||
Plugin::~Plugin() | |||
{ | |||
delete parameters; | |||
delete granulator; | |||
delete program_bank; | |||
} | |||
/* | |||
void Plugin::createAppSettingsDir() | |||
{ | |||
File appDataDir = File::getSpecialLocation(File::userApplicationDataDirectory); | |||
File* argotlunarDir = new File(appDataDir.getFullPathName() + "/.argotlunar"); | |||
argotlunarDir->createDirectory(); | |||
} | |||
File* Plugin::getMidiMapFile() | |||
{ | |||
File appDataDir = File::getSpecialLocation(File::userApplicationDataDirectory); | |||
return new File(appDataDir.getFullPathName() + "/.argotlunar/midimap.xml"); | |||
} | |||
*/ | |||
bool Plugin::acceptsMidi() const | |||
{ | |||
return false; | |||
} | |||
bool Plugin::isInputChannelStereoPair(int index) const | |||
{ | |||
return true; | |||
} | |||
bool Plugin::isOutputChannelStereoPair(int index) const | |||
{ | |||
return true; | |||
} | |||
bool Plugin::producesMidi() const | |||
{ | |||
return false; | |||
} | |||
bool Plugin::hasEditor() const | |||
{ | |||
return true; | |||
} | |||
const String Plugin::getName() const | |||
{ | |||
return "Argotlunar2"; | |||
} | |||
const String Plugin::getInputChannelName(const int channelIndex) const | |||
{ | |||
return String (channelIndex + 1); | |||
} | |||
const String Plugin::getOutputChannelName(const int channelIndex) const | |||
{ | |||
return (channelIndex == 0) ? "L" : "R"; | |||
} | |||
double Plugin::getTailLengthSeconds() const | |||
{ | |||
return 0.0; | |||
} | |||
AudioProcessorEditor* Plugin::createEditor() | |||
{ | |||
return new PluginEditor(this); | |||
} | |||
void Plugin::prepareToPlay (double samplerate, int samples_per_block) | |||
{ | |||
granulator->prepareToPlay(static_cast<float>(samplerate)); | |||
} | |||
void Plugin::releaseResources() | |||
{ | |||
granulator->releaseResources(); | |||
} | |||
void Plugin::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midiMessages) | |||
{ | |||
if (getNumInputChannels() != 2 && getNumOutputChannels() != 2) { | |||
return; | |||
} | |||
float* chan1 = buffer.getWritePointer(0); | |||
float* chan2 = buffer.getWritePointer(1); | |||
int sampleframes = buffer.getNumSamples(); | |||
int blocks = sampleframes / kInternalBlocksize; | |||
if (getPlayHead() != 0 && getPlayHead()->getCurrentPosition(pos)) { | |||
if ((&pos)->bpm == 0.0f) { | |||
parameters->setQuantizationDisabled(); | |||
parameters->setParameter(kDelayQuant, 0.0f, false); | |||
parameters->setParameter(kIotQuant, 0.0f, false); | |||
parameters->setParameter(kDurQuant, 0.0f, false); | |||
} | |||
else | |||
parameters->time_quantizer->setPositionInfo(&pos); | |||
} else { | |||
parameters->setQuantizationDisabled(); | |||
} | |||
block_sample_pos = 0; | |||
for (int i = 0; i < blocks; i++) { | |||
granulator->processInternalBlock(chan1, chan2, kInternalBlocksize); | |||
chan1 += kInternalBlocksize; | |||
chan2 += kInternalBlocksize; | |||
parameters->time_quantizer->incrementPositionInfo(); | |||
} | |||
int samples_remaining = sampleframes % kInternalBlocksize; | |||
if (samples_remaining) { | |||
granulator->processInternalBlock(chan1, chan2, samples_remaining); | |||
} | |||
} | |||
int Plugin::getNumParameters() | |||
{ | |||
return static_cast<int>(NUM_PARAMS); | |||
} | |||
float Plugin::getParameter (int index) | |||
{ | |||
if (index == kProgram) { | |||
return static_cast<float>(current_program / (kNumPrograms - 1)); | |||
} else { | |||
return parameters->param[index]; | |||
} | |||
} | |||
const String Plugin::getParameterName (int index) | |||
{ | |||
return parameters->getParameterName(index); | |||
} | |||
const String Plugin::getParameterText (int index) | |||
{ | |||
if (index == kProgram) { | |||
return String(current_program + 1); | |||
} else return parameters->getParameterText(index); | |||
} | |||
std::vector<String> Plugin::getScaleNames() | |||
{ | |||
return granulator->grain_param_generator->pitch_quantizer->getNames(); | |||
} | |||
bool Plugin::isMetaParameter(int parameterIndex) const | |||
{ | |||
if (parameterIndex == kProgram) { | |||
return true; | |||
} | |||
else | |||
return false; | |||
} | |||
bool Plugin::silenceInProducesSilenceOut(void) const | |||
{ | |||
return false; | |||
} | |||
void Plugin::setParameter(int index, float new_value) | |||
{ | |||
if (index != kNone) { | |||
if (index == kProgram) { | |||
if (progchange_param_enabled) { | |||
int selected_program = static_cast<int>(new_value * (kNumPrograms - 1)); | |||
if (current_program != selected_program) { | |||
setCurrentProgram(selected_program); | |||
} | |||
} | |||
} else { | |||
parameters->setParameter(index, new_value, false); | |||
} | |||
setParametersChangedState(); | |||
} | |||
} | |||
void Plugin::toggleProgchangeEnabled() | |||
{ | |||
progchange_param_enabled = !progchange_param_enabled; | |||
} | |||
bool Plugin:: isProgchangeEnabled() | |||
{ | |||
return progchange_param_enabled; | |||
} | |||
void Plugin::setMatrixSource(int index, int param) | |||
{ | |||
parameters->setMatrixSource(index, param); | |||
} | |||
void Plugin::setMatrixDest(int index, int param) | |||
{ | |||
parameters->setMatrixDest(index, param); | |||
} | |||
void Plugin::setMatrixMode(int index, int param) | |||
{ | |||
parameters->setMatrixMode(index, param); | |||
} | |||
const String Plugin::getProgramName(int index) | |||
{ | |||
return program_bank->getProgramName(index); | |||
} | |||
void Plugin::changeProgramName(int index, const String& newName) | |||
{ | |||
program_bank->setProgramName(index, newName); | |||
editor_program_update_pending = true; | |||
} | |||
int Plugin::getCurrentProgram() | |||
{ | |||
return current_program; | |||
} | |||
bool Plugin::getSavedState() | |||
{ | |||
return saved_state; | |||
} | |||
void Plugin::setSavedState(bool state) | |||
{ | |||
if (saved_state == true && state == false) { | |||
editor_program_update_pending = true; | |||
} | |||
saved_state = state; | |||
} | |||
bool Plugin::getParametersChangedState() | |||
{ | |||
if (editor_parameter_update_pending) { | |||
editor_parameter_update_pending = false; | |||
return true; | |||
} | |||
else | |||
return false; | |||
} | |||
void Plugin::setParametersChangedState() | |||
{ | |||
editor_parameter_update_pending = true; | |||
} | |||
bool Plugin::getProgramChangedState() | |||
{ | |||
if (editor_program_update_pending) { | |||
editor_program_update_pending = false; | |||
return true; | |||
} | |||
else | |||
return false; | |||
} | |||
int Plugin::getNumPrograms() | |||
{ | |||
return kNumPrograms; | |||
} | |||
void Plugin::initCurrentProgram() | |||
{ | |||
program_bank->initProgram(current_program); | |||
program_bank->loadProgramState(current_program); | |||
setSavedState(true); | |||
editor_program_update_pending = true; | |||
} | |||
void Plugin::saveProgramTo(int index) | |||
{ | |||
String current_program_name = program_bank->getProgramName(current_program); | |||
program_bank->saveProgramState(index); | |||
program_bank->setProgramName(index, current_program_name); | |||
current_program = index; | |||
setSavedState(true); | |||
editor_program_update_pending = true; | |||
} | |||
void Plugin::setCurrentProgram(int index) | |||
{ | |||
program_bank->loadProgramState(index); | |||
current_program = index; | |||
setSavedState(true); | |||
editor_program_update_pending = true; | |||
} | |||
void Plugin::getCurrentProgramStateInformation(MemoryBlock& destData) | |||
{ | |||
//save current settings | |||
program_bank->saveProgramState(current_program); | |||
saveProgramTo(current_program); | |||
//output program to host | |||
XmlElement* program = program_bank->createProgramXml(current_program); | |||
copyXmlToBinary (*program, destData); | |||
delete program; | |||
} | |||
void Plugin::setCurrentProgramStateInformation(const void* data, int sizeInBytes) | |||
{ | |||
//load program from host | |||
XmlElement* const xml_state = getXmlFromBinary(data, sizeInBytes); | |||
if (xml_state != 0) { | |||
program_bank->loadProgramFromXml(current_program, xml_state); | |||
setCurrentProgram(current_program); | |||
delete xml_state; | |||
editor_program_update_pending = true; | |||
} | |||
} | |||
void Plugin::getStateInformation (MemoryBlock& destData) | |||
{ | |||
// save current program | |||
program_bank->saveProgramState(current_program); | |||
// output program_bank to host | |||
XmlElement* bankXml = program_bank->createBankXml(); | |||
copyXmlToBinary(*bankXml, destData); | |||
editor_program_update_pending = true; | |||
} | |||
void Plugin::setStateInformation (const void* data, int sizeInBytes) | |||
{ | |||
//load bank from host | |||
XmlElement* const xml_state = getXmlFromBinary(data, sizeInBytes); | |||
if (xml_state != 0) { | |||
program_bank->loadBankFromXml(xml_state); | |||
setCurrentProgram(current_program); | |||
delete xml_state; | |||
editor_program_update_pending = true; | |||
} | |||
} | |||
void Plugin::loadBankXml(File* file) | |||
{ | |||
//load bank from file | |||
XmlDocument xml_document(*file); | |||
XmlElement* xml_state = xml_document.getDocumentElement(); | |||
if (xml_state != 0) { | |||
program_bank->loadBankFromXml(xml_state); | |||
setCurrentProgram(current_program); | |||
delete xml_state; | |||
editor_program_update_pending = true; | |||
} | |||
} | |||
void Plugin::saveBankXml(File* file) | |||
{ | |||
// save current program | |||
program_bank->saveProgramState(current_program); | |||
// output bank to file | |||
XmlElement* bankXml = program_bank->createBankXml(); | |||
file->replaceWithText(bankXml->createDocument(String::empty)); | |||
delete bankXml; | |||
editor_program_update_pending = true; | |||
setSavedState(true); | |||
} | |||
void Plugin::loadCurrentProgramXml(File* file) | |||
{ | |||
//load program from file | |||
XmlDocument xml_document(*file); | |||
XmlElement* xml_state = xml_document.getDocumentElement(); | |||
if (xml_state != 0) { | |||
program_bank->loadProgramFromXml(current_program, xml_state); | |||
setCurrentProgram(current_program); | |||
delete xml_state; | |||
editor_program_update_pending = true; | |||
} | |||
} | |||
void Plugin::saveCurrentProgramXml(File* file) | |||
{ | |||
//save current settings | |||
program_bank->saveProgramState(current_program); | |||
saveProgramTo(current_program); | |||
//output program to file | |||
XmlElement* program = program_bank->createProgramXml(current_program); | |||
file->replaceWithText(program->createDocument(String::empty)); | |||
delete program; | |||
} |
@@ -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 |
@@ -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__ |
@@ -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; | |||
} | |||
} |
@@ -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 |
@@ -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; | |||
} |
@@ -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 |
@@ -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; | |||
} | |||
@@ -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 |
@@ -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" | |||
) | |||
} |