Browse Source

Add argotlunar

master
falkTX 10 years ago
parent
commit
6c6d502258
38 changed files with 6554 additions and 0 deletions
  1. +50
    -0
      ports/Makefile
  2. +31
    -0
      ports/argotlunar/JuceLibraryCode/JuceHeader.h
  3. +129
    -0
      ports/argotlunar/JuceLibraryCode/JucePluginCharacteristics.h
  4. +17
    -0
      ports/argotlunar/LV2/premake.lua
  5. +10
    -0
      ports/argotlunar/README.md
  6. +78
    -0
      ports/argotlunar/Source/CombFilter.cpp
  7. +32
    -0
      ports/argotlunar/Source/CombFilter.h
  8. +24
    -0
      ports/argotlunar/Source/Debug.h
  9. +108
    -0
      ports/argotlunar/Source/DelayLine.cpp
  10. +38
    -0
      ports/argotlunar/Source/DelayLine.h
  11. +157
    -0
      ports/argotlunar/Source/Envelope.cpp
  12. +45
    -0
      ports/argotlunar/Source/Envelope.h
  13. +91
    -0
      ports/argotlunar/Source/Filter.cpp
  14. +36
    -0
      ports/argotlunar/Source/Filter.h
  15. +173
    -0
      ports/argotlunar/Source/Grain.cpp
  16. +47
    -0
      ports/argotlunar/Source/Grain.h
  17. +21
    -0
      ports/argotlunar/Source/GrainParameters.h
  18. +383
    -0
      ports/argotlunar/Source/GrainParametersGenerator.cpp
  19. +61
    -0
      ports/argotlunar/Source/GrainParametersGenerator.h
  20. +141
    -0
      ports/argotlunar/Source/Granulator.cpp
  21. +48
    -0
      ports/argotlunar/Source/Granulator.h
  22. +14
    -0
      ports/argotlunar/Source/Misc.h
  23. +597
    -0
      ports/argotlunar/Source/Parameters.cpp
  24. +96
    -0
      ports/argotlunar/Source/Parameters.h
  25. +108
    -0
      ports/argotlunar/Source/ParametersEnum.h
  26. +159
    -0
      ports/argotlunar/Source/PitchQuantizer.cpp
  27. +60
    -0
      ports/argotlunar/Source/PitchQuantizer.h
  28. +407
    -0
      ports/argotlunar/Source/Plugin.cpp
  29. +89
    -0
      ports/argotlunar/Source/Plugin.h
  30. +2462
    -0
      ports/argotlunar/Source/PluginEditor.cpp
  31. +205
    -0
      ports/argotlunar/Source/PluginEditor.h
  32. +60
    -0
      ports/argotlunar/Source/Program.cpp
  33. +24
    -0
      ports/argotlunar/Source/Program.h
  34. +192
    -0
      ports/argotlunar/Source/ProgramBank.cpp
  35. +39
    -0
      ports/argotlunar/Source/ProgramBank.h
  36. +251
    -0
      ports/argotlunar/Source/TimeQuantizer.cpp
  37. +54
    -0
      ports/argotlunar/Source/TimeQuantizer.h
  38. +17
    -0
      ports/argotlunar/VST/premake.lua

+ 50
- 0
ports/Makefile View File

@@ -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

+ 31
- 0
ports/argotlunar/JuceLibraryCode/JuceHeader.h View File

@@ -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__

+ 129
- 0
ports/argotlunar/JuceLibraryCode/JucePluginCharacteristics.h View File

@@ -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__

+ 17
- 0
ports/argotlunar/LV2/premake.lua View File

@@ -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"
)
}

+ 10
- 0
ports/argotlunar/README.md View File

@@ -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)

+ 78
- 0
ports/argotlunar/Source/CombFilter.cpp View File

@@ -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++;
}

+ 32
- 0
ports/argotlunar/Source/CombFilter.h View File

@@ -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

+ 24
- 0
ports/argotlunar/Source/Debug.h View File

@@ -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

+ 108
- 0
ports/argotlunar/Source/DelayLine.cpp View File

@@ -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;
}

+ 38
- 0
ports/argotlunar/Source/DelayLine.h View File

@@ -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

+ 157
- 0
ports/argotlunar/Source/Envelope.cpp View File

@@ -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;
}
}


+ 45
- 0
ports/argotlunar/Source/Envelope.h View File

@@ -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

+ 91
- 0
ports/argotlunar/Source/Filter.cpp View File

@@ -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;
}
}


+ 36
- 0
ports/argotlunar/Source/Filter.h View File

@@ -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

+ 173
- 0
ports/argotlunar/Source/Grain.cpp View File

@@ -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;
}

+ 47
- 0
ports/argotlunar/Source/Grain.h View File

@@ -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

+ 21
- 0
ports/argotlunar/Source/GrainParameters.h View File

@@ -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

+ 383
- 0
ports/argotlunar/Source/GrainParametersGenerator.cpp View File

@@ -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 &amp_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;
}

+ 61
- 0
ports/argotlunar/Source/GrainParametersGenerator.h View File

@@ -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

+ 141
- 0
ports/argotlunar/Source/Granulator.cpp View File

@@ -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];
}

+ 48
- 0
ports/argotlunar/Source/Granulator.h View File

@@ -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

+ 14
- 0
ports/argotlunar/Source/Misc.h View File

@@ -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

+ 597
- 0
ports/argotlunar/Source/Parameters.cpp View File

@@ -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);
}

+ 96
- 0
ports/argotlunar/Source/Parameters.h View File

@@ -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

+ 108
- 0
ports/argotlunar/Source/ParametersEnum.h View File

@@ -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

+ 159
- 0
ports/argotlunar/Source/PitchQuantizer.cpp View File

@@ -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;
}


+ 60
- 0
ports/argotlunar/Source/PitchQuantizer.h View File

@@ -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
*/

+ 407
- 0
ports/argotlunar/Source/Plugin.cpp View File

@@ -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;
}

+ 89
- 0
ports/argotlunar/Source/Plugin.h View File

@@ -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

+ 2462
- 0
ports/argotlunar/Source/PluginEditor.cpp
File diff suppressed because it is too large
View File


+ 205
- 0
ports/argotlunar/Source/PluginEditor.h View File

@@ -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__

+ 60
- 0
ports/argotlunar/Source/Program.cpp View File

@@ -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;
}
}

+ 24
- 0
ports/argotlunar/Source/Program.h View File

@@ -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

+ 192
- 0
ports/argotlunar/Source/ProgramBank.cpp View File

@@ -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;
}

+ 39
- 0
ports/argotlunar/Source/ProgramBank.h View File

@@ -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

+ 251
- 0
ports/argotlunar/Source/TimeQuantizer.cpp View File

@@ -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;
}


+ 54
- 0
ports/argotlunar/Source/TimeQuantizer.h View File

@@ -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

+ 17
- 0
ports/argotlunar/VST/premake.lua View File

@@ -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"
)
}

Loading…
Cancel
Save