@@ -38,46 +38,34 @@ void AudioEffectGranular::begin(int16_t *sample_bank_def, int16_t max_len_def) | |||
sample_bank = sample_bank_def; | |||
} | |||
void AudioEffectGranular::freeze(int16_t activate, int16_t playpack_rate_def, int16_t freeze_length_def) | |||
void AudioEffectGranular::beginFreeze_int(int grain_samples) | |||
{ | |||
if (activate == 0) { | |||
grain_mode = 0; | |||
allow_len_change = true; | |||
return; | |||
} | |||
__disable_irq(); | |||
grain_mode = 1; | |||
rate(playpack_rate_def); | |||
if (max_sample_len <= 1500) { | |||
freeze_len = max_sample_len; | |||
if (grain_samples < max_sample_len) { | |||
freeze_len = grain_samples; | |||
} else { | |||
freeze_len = ((max_sample_len - 1500) * freeze_length_def / 1023) + 1500; | |||
freeze_len = grain_samples; | |||
} | |||
sample_loaded = false; | |||
write_en = false; | |||
sample_req = true; | |||
__enable_irq(); | |||
Serial.print("in = "); | |||
Serial.print(freeze_length_def); | |||
Serial.print(grain_samples); | |||
Serial.print(", freeze len = "); | |||
Serial.println(freeze_len); | |||
} | |||
void AudioEffectGranular::shift(int16_t activate, int16_t playpack_rate_def, int16_t grain_length_def) | |||
void AudioEffectGranular::beginPitchShift_int(int grain_samples) | |||
{ | |||
if (activate == 0) { | |||
grain_mode = 0; | |||
allow_len_change = true; | |||
return; | |||
} | |||
__disable_irq(); | |||
grain_mode = 2; | |||
rate(playpack_rate_def); | |||
if (allow_len_change) { | |||
if (grain_length_def < 100) grain_length_def = 100; | |||
if (grain_samples < 100) grain_samples = 100; | |||
int maximum = (max_sample_len - 1) / 3; | |||
if (grain_length_def > maximum) grain_length_def = maximum; | |||
glitch_len = grain_length_def; | |||
if (grain_samples > maximum) grain_samples = maximum; | |||
glitch_len = grain_samples; | |||
} | |||
sample_loaded = false; | |||
write_en = false; | |||
@@ -85,6 +73,12 @@ void AudioEffectGranular::shift(int16_t activate, int16_t playpack_rate_def, int | |||
__enable_irq(); | |||
} | |||
void AudioEffectGranular::stop() | |||
{ | |||
grain_mode = 0; | |||
allow_len_change = true; | |||
} | |||
void AudioEffectGranular::rate(int16_t playpack_rate_def) | |||
{ | |||
playpack_rate = playpack_rate_def; |
@@ -29,10 +29,19 @@ public: | |||
AudioEffectGranular(void): AudioStream(1,inputQueueArray) { } | |||
void begin(int16_t *sample_bank_def, int16_t max_len_def); | |||
void rate(int16_t playpack_rate_def); | |||
void freeze(int16_t activate, int16_t playpack_rate_def, int16_t grain_length_def); | |||
void shift(int16_t activate, int16_t playpack_rate_def, int16_t grain_length_def); | |||
void beginFreeze(float grain_length) { | |||
if (grain_length <= 0.0) return; | |||
beginFreeze_int(grain_length * (AUDIO_SAMPLE_RATE_EXACT * 0.001) + 0.5); | |||
} | |||
void beginPitchShift(float grain_length) { | |||
if (grain_length <= 0.0) return; | |||
beginPitchShift_int(grain_length * (AUDIO_SAMPLE_RATE_EXACT * 0.001) + 0.5); | |||
} | |||
void stop(); | |||
virtual void update(void); | |||
private: | |||
void beginFreeze_int(int grain_samples); | |||
void beginPitchShift_int(int grain_samples); | |||
audio_block_t *inputQueueArray[1]; | |||
int16_t *sample_bank; | |||
int16_t max_sample_len; |
@@ -20,7 +20,7 @@ Bounce button0 = Bounce(0, 15); | |||
Bounce button1 = Bounce(1, 15); | |||
Bounce button2 = Bounce(2, 15); | |||
#define GRANULAR_MEMORY_SIZE 12800 // enough for 29 ms at 44.1 kHz | |||
#define GRANULAR_MEMORY_SIZE 12800 // enough for 290 ms at 44.1 kHz | |||
int16_t granularMemory[GRANULAR_MEMORY_SIZE]; | |||
// Use these with the Teensy Audio Shield | |||
@@ -87,22 +87,26 @@ void loop() { | |||
button0.update(); | |||
button1.update(); | |||
button2.update(); | |||
// read knobs | |||
int knobA2 = analogRead(A2); | |||
int knobA3 = analogRead(A3); | |||
// read knobs, scale to 0-1.0 numbers | |||
float knobA2 = (float)analogRead(A2) / 1023.0; | |||
float knobA3 = (float)analogRead(A3) / 1023.0; | |||
if (button0.fallingEdge()) { | |||
granular1.freeze(1, knobA2, knobA3); | |||
// Button 0 starts Freeze effect | |||
granular1.beginFreeze(knobA3 * 290.0); | |||
} | |||
if (button0.risingEdge()) { | |||
granular1.freeze(0, knobA2, knobA3); | |||
granular1.stop(); | |||
} | |||
if (button1.fallingEdge()) { | |||
granular1.shift(1, knobA2, knobA3); | |||
// Button 1 starts Pitch Shift effect | |||
granular1.beginPitchShift(knobA3 * 100.0); | |||
} | |||
if (button1.risingEdge()) { | |||
granular1.shift(0, knobA2, knobA3); | |||
granular1.stop(); | |||
} | |||
// continuously adjust pitch bend | |||
granular1.rate(knobA2 * 1023.0); | |||
} |