Ive created routines inside effect_granular that work as planned. I can now listen to ultrasonic sounds that come in as small timeblocks (I am using a granular_memory_size of 30000 which is around 100ms of data at a samplerate of 281K). Next up will be to chain this to active detection of ultrasonic sounds and only use then use time-expansion.
Ive tested an earlier version yesterday in my garden with Common Pipistrelle bats around and I did hear some calls time-expanded.
I am moving the further development of these routines back to the batdetector thread. https://forum.pjrc.com/threads/38988-Bat-detector
in effect_granular.h
Code:
void beginTimeExpansion(float grain_length) {
if (grain_length <= 0.0) return;
beginTimeExpansion_int(grain_length);
}
in effect_granular.cpp
Code:
void AudioEffectGranular::beginTimeExpansion_int(int grain_samples)
{
__disable_irq();
grain_mode = 3;
if (allow_len_change) {
if (grain_samples > max_sample_len) {
grain_samples = max_sample_len;
}
glitch_len = grain_samples;
}
sample_loaded = false;
write_en = false;
sample_req = true;
__enable_irq();
}
and inside routine void AudioEffectGranular::update(void)
Code:
else if (grain_mode == 3) {
//TIME EXPANSION
for (int k = 0; k < AUDIO_BLOCK_SAMPLES; k++)
{
// wait with recording until a crossing zero point passes
if (sample_req) {
int16_t current_input = block->data[k];
if ((current_input < 0 && prev_input >= 0) ||
(current_input >= 0 && prev_input < 0)) {
write_en = true; //start collecting a sample
} else {
prev_input = current_input;
}
}
//active collecting of all incoming data
if (write_en) {
sample_req = false;
allow_len_change = true;
// collect until glitch_len samples are available in the sample_bank
if (write_head >= glitch_len) {
write_head = 0;
accumulator= 0;
sample_loaded = true; //sample_bank is full
write_en = false;
allow_len_change = false;
}
sample_bank[write_head]= block->data[k];
write_head++; // next sample
}
//playback_rate is 65536 for sample_ratio 1 (no decimation)
//accumulator holds next position of the sample*65535
// read_head is the position of the next sample to use in the sample_bank
// if sample_ration <1 the sample_value will be pushed into the bank several times (time expansion)
accumulator += playpack_rate; // sample
read_head = (accumulator >> 16); //rightshift 16 == div by 65535
if (read_head >= glitch_len) {
read_head = 0;
accumulator = 0;
sample_req = true; //we can have a new sample coming in
sample_loaded = false;
}
block->data[k] = sample_bank[read_head];
}
}