read_head = 0; | read_head = 0; | ||||
write_head = 0; | write_head = 0; | ||||
prev_input = 0; | prev_input = 0; | ||||
playpack_rate = 512; | |||||
playpack_rate = 65536; | |||||
accumulator = 0; | accumulator = 0; | ||||
allow_len_change = true; | allow_len_change = true; | ||||
sample_loaded = false; | sample_loaded = false; | ||||
write_en = false; | write_en = false; | ||||
sample_req = true; | sample_req = true; | ||||
__enable_irq(); | __enable_irq(); | ||||
Serial.print("in = "); | |||||
Serial.print(grain_samples); | |||||
Serial.print(", freeze len = "); | |||||
Serial.println(freeze_len); | |||||
} | } | ||||
void AudioEffectGranular::beginPitchShift_int(int grain_samples) | void AudioEffectGranular::beginPitchShift_int(int grain_samples) | ||||
allow_len_change = true; | allow_len_change = true; | ||||
} | } | ||||
void AudioEffectGranular::rate(int16_t playpack_rate_def) | |||||
{ | |||||
playpack_rate = playpack_rate_def; | |||||
} | |||||
void AudioEffectGranular::update(void) | void AudioEffectGranular::update(void) | ||||
{ | { | ||||
audio_block_t *block; | audio_block_t *block; | ||||
prev_input = block->data[AUDIO_BLOCK_SAMPLES-1]; | prev_input = block->data[AUDIO_BLOCK_SAMPLES-1]; | ||||
} | } | ||||
else if (grain_mode == 1) { | else if (grain_mode == 1) { | ||||
//when activated the last | |||||
// Freeze - sample 1 grain, then repeatedly play it back | |||||
for (int j = 0; j < AUDIO_BLOCK_SAMPLES; j++) { | for (int j = 0; j < AUDIO_BLOCK_SAMPLES; j++) { | ||||
if (sample_req) { | if (sample_req) { | ||||
// only begin capture on zero cross | // only begin capture on zero cross | ||||
write_head = 0; | write_head = 0; | ||||
read_head = 0; | read_head = 0; | ||||
sample_req = false; | sample_req = false; | ||||
Serial.println("begin freeze capture"); | |||||
} else { | } else { | ||||
prev_input = current_input; | prev_input = current_input; | ||||
} | } | ||||
} | } | ||||
if (write_head >= max_sample_len) { | if (write_head >= max_sample_len) { | ||||
write_en = false; | write_en = false; | ||||
Serial.println("end freeze capture"); | |||||
} | } | ||||
} | } | ||||
if (sample_loaded) { | if (sample_loaded) { | ||||
if (playpack_rate >= 0) { | if (playpack_rate >= 0) { | ||||
accumulator += playpack_rate; | accumulator += playpack_rate; | ||||
read_head = accumulator >> 9; | |||||
read_head = accumulator >> 16; | |||||
} | } | ||||
if (read_head >= freeze_len) { | if (read_head >= freeze_len) { | ||||
accumulator = 0; | accumulator = 0; | ||||
} | } | ||||
accumulator += playpack_rate; | accumulator += playpack_rate; | ||||
read_head = (accumulator >> 9); | |||||
read_head = (accumulator >> 16); | |||||
if (read_head >= glitch_len) { | if (read_head >= glitch_len) { | ||||
read_head -= glitch_len; | read_head -= glitch_len; |
public: | public: | ||||
AudioEffectGranular(void): AudioStream(1,inputQueueArray) { } | AudioEffectGranular(void): AudioStream(1,inputQueueArray) { } | ||||
void begin(int16_t *sample_bank_def, int16_t max_len_def); | void begin(int16_t *sample_bank_def, int16_t max_len_def); | ||||
void rate(int16_t playpack_rate_def); | |||||
void setSpeed(float ratio) { | |||||
if (ratio < 0.125) ratio = 0.125; | |||||
else if (ratio > 8.0) ratio = 8.0; | |||||
playpack_rate = ratio * 65536.0 + 0.499; | |||||
} | |||||
void beginFreeze(float grain_length) { | void beginFreeze(float grain_length) { | ||||
if (grain_length <= 0.0) return; | if (grain_length <= 0.0) return; | ||||
beginFreeze_int(grain_length * (AUDIO_SAMPLE_RATE_EXACT * 0.001) + 0.5); | beginFreeze_int(grain_length * (AUDIO_SAMPLE_RATE_EXACT * 0.001) + 0.5); | ||||
void beginPitchShift_int(int grain_samples); | void beginPitchShift_int(int grain_samples); | ||||
audio_block_t *inputQueueArray[1]; | audio_block_t *inputQueueArray[1]; | ||||
int16_t *sample_bank; | int16_t *sample_bank; | ||||
uint32_t playpack_rate; | |||||
uint32_t accumulator; | |||||
int16_t max_sample_len; | int16_t max_sample_len; | ||||
int16_t write_head; | int16_t write_head; | ||||
int16_t read_head; | int16_t read_head; | ||||
int16_t grain_mode; | int16_t grain_mode; | ||||
int16_t freeze_len; | int16_t freeze_len; | ||||
int16_t playpack_rate; | |||||
int32_t accumulator; | |||||
int16_t prev_input; | int16_t prev_input; | ||||
int16_t glitch_len; | int16_t glitch_len; | ||||
bool allow_len_change; | bool allow_len_change; |
// Granular Effect Example - Pitch shift or freeze sound | |||||
// | |||||
// This example is meant to be used with 3 buttons (pin 0, | |||||
// 1, 2) and 2 knobs (pins 16/A2, 17/A3), which are present | |||||
// on the audio tutorial kit. | |||||
// https://www.pjrc.com/store/audio_tutorial_kit.html | |||||
// | |||||
// Data files to put on your SD card can be downloaded here: | |||||
// http://www.pjrc.com/teensy/td_libs_AudioDataFiles.html | |||||
// | |||||
// This example code is in the public domain. | |||||
#include <Audio.h> | #include <Audio.h> | ||||
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
float knobA2 = (float)analogRead(A2) / 1023.0; | float knobA2 = (float)analogRead(A2) / 1023.0; | ||||
float knobA3 = (float)analogRead(A3) / 1023.0; | float knobA3 = (float)analogRead(A3) / 1023.0; | ||||
// Button 0 starts Freeze effect | |||||
if (button0.fallingEdge()) { | if (button0.fallingEdge()) { | ||||
// Button 0 starts Freeze effect | |||||
granular1.beginFreeze(knobA3 * 290.0); | |||||
float msec = 100.0 + (knobA3 * 190.0); | |||||
granular1.beginFreeze(msec); | |||||
Serial.print("Begin granular freeze using "); | |||||
Serial.print(msec); | |||||
Serial.println(" grains"); | |||||
} | } | ||||
if (button0.risingEdge()) { | if (button0.risingEdge()) { | ||||
granular1.stop(); | granular1.stop(); | ||||
} | } | ||||
// Button 1 starts Pitch Shift effect | |||||
if (button1.fallingEdge()) { | if (button1.fallingEdge()) { | ||||
// Button 1 starts Pitch Shift effect | |||||
granular1.beginPitchShift(knobA3 * 100.0); | |||||
float msec = 25.0 + (knobA3 * 75.0); | |||||
granular1.beginPitchShift(msec); | |||||
Serial.print("Begin granular pitch phift using "); | |||||
Serial.print(msec); | |||||
Serial.println(" grains"); | |||||
} | } | ||||
if (button1.risingEdge()) { | if (button1.risingEdge()) { | ||||
granular1.stop(); | granular1.stop(); | ||||
} | } | ||||
// continuously adjust pitch bend | |||||
granular1.rate(knobA2 * 1023.0); | |||||
// Continuously adjust the speed, based on the A3 pot | |||||
float ratio; | |||||
ratio = powf(2.0, knobA2 * 2.0 - 1.0); // 0.5 to 2.0 | |||||
//ratio = powf(2.0, knobA2 * 6.0 - 3.0); // 0.125 to 8.0 -- uncomment for far too much range! | |||||
granular1.setSpeed(ratio); | |||||
} | } |
reverbTime KEYWORD2 | reverbTime KEYWORD2 | ||||
roomsize KEYWORD2 | roomsize KEYWORD2 | ||||
damping KEYWORD2 | damping KEYWORD2 | ||||
setSpeed KEYWORD2 | |||||
beginFreeze KEYWORD2 | |||||
beginPitchShift KEYWORD2 | |||||
frequency KEYWORD2 | frequency KEYWORD2 | ||||
phase KEYWORD2 | phase KEYWORD2 | ||||
amplitude KEYWORD2 | amplitude KEYWORD2 |