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