Просмотр исходного кода

Add AudioEffectGranular, untested (Bleep Labs)

dds
PaulStoffregen 6 лет назад
Родитель
Сommit
c4d1a36310
3 измененных файлов: 293 добавлений и 0 удалений
  1. +1
    -0
      Audio.h
  2. +227
    -0
      effect_granular.cpp
  3. +65
    -0
      effect_granular.h

+ 1
- 0
Audio.h Просмотреть файл

@@ -82,6 +82,7 @@
#include "effect_reverb.h"
#include "effect_freeverb.h"
#include "effect_waveshaper.h"
#include "effect_granular.h"
#include "filter_biquad.h"
#include "filter_fir.h"
#include "filter_variable.h"

+ 227
- 0
effect_granular.cpp Просмотреть файл

@@ -0,0 +1,227 @@
/*
* Copyright (c) 2018 John-Michael Reed
* bleeplabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include <Arduino.h>
#include "effect_granular.h"

void AudioEffectGranular::begin(int16_t *sample_bank_def, int16_t max_len_def)
{
sample_req=1;
length(max_len_def - 1);
sample_bank = sample_bank_def;
}

void AudioEffectGranular::length(int16_t max_len_def)
{
if (max_len_def < 100) {
max_sample_len = 100;
glitch_len = max_sample_len/3;
} else {
max_sample_len = (max_len_def - 1);
glitch_len = max_sample_len/3;
}
}


void AudioEffectGranular::freeze(int16_t activate, int16_t playpack_rate_def, int16_t freeze_length_def)
{
if (activate==1) {
grain_mode = 1;
}
if (activate==0) {
grain_mode = 0;
}
rate(playpack_rate_def);
if (freeze_length_def < 50) {
freeze_len = 50;
}
if (freeze_length_def>=max_sample_len) {
freeze_len = max_sample_len;
}
if (freeze_length_def>=50 && freeze_length_def<max_sample_len) {
freeze_len = freeze_length_def;
}
}

void AudioEffectGranular::shift(int16_t activate, int16_t playpack_rate_def, int16_t grain_length_def)
{
if (activate == 1) {
grain_mode = 2;
}
if (activate == 0) {
grain_mode = 3;
}
rate(playpack_rate_def);
if (allow_len_change == 1 ) {
// Serial.println("aL");
length(grain_length_def);
}
}


void AudioEffectGranular::rate(int16_t playpack_rate_def)
{
playpack_rate = playpack_rate_def;
}


void AudioEffectGranular::update(void)
{
audio_block_t *block;

if (sample_bank == NULL) return;

block = receiveWritable(0);
if (!block) return;

if (grain_mode == 3) {
//through
/*
for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
write_head++;
if (write_head >= max_sample_len) {
write_head = 0;
}
sample_bank[write_head] = block->data[i];
}
*/
}

if (grain_mode == 0) {
//capture audio but dosen't output
//this needs to be happening at all times if you want to
// use grain_mode = 1, the simple "freeze" sampler.
for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
write_head++;

if (write_head >= max_sample_len) {
write_head = 0;
}
sample_bank[write_head] = block->data[i];
}
}


if (grain_mode == 1) {
//when activated the last
for (int j = 0; j < AUDIO_BLOCK_SAMPLES; j++) {
if (playpack_rate >= 0) {
accumulator += playpack_rate;
read_head = accumulator >> 9;
}
if (read_head >= freeze_len) {
accumulator = 0;
read_head -= max_sample_len;
}
block->data[j] = sample_bank[read_head];
}
}

if (grain_mode == 2) {
//GLITCH SHIFT
//basic granular synth thingy
// the shorter the sample the max_sample_len the more tonal it is.
// Longer it has more definition. It's a bit roboty either way which
// is obv great and good enough for noise music.

for (int k = 0; k < AUDIO_BLOCK_SAMPLES; k++) {
int16_t current_input = block->data[k];
//we only want to start recodeing when the audio is crossing zero to minimize pops
if ((current_input<0 && prev_input>0)) {
zero_cross_down=1;
} else {
zero_cross_down=0;
}

prev_input=current_input;

if (zero_cross_down == 1 && sample_req == 1) {
write_en=1;
}
if (write_en==1) {
sample_req=0;
allow_len_change=1; //reduces noise by not allowing the length to
// change after the sample has been recored.
// kind of not too much though
if (write_head >= glitch_len) {
glitch_cross_len=glitch_len;
write_head = 0;
sample_loaded = 1;
write_en=0;
allow_len_change=0;
}
sample_bank[write_head] = block->data[k];
write_head++;
}

if (sample_loaded == 1) {
//move it to the middle third of the bank.
//3 "seperate" banks are used
float fade_len=20.00;
int16_t m2=fade_len;

for (int m = 0; m < 2; m++) {
// I'm off by one somewhere? why is there a tick at the
// beginning of this only when it's combined with the
// fade out???? ooor am i osbserving that incorrectly
// either wait it works enough
sample_bank[m + glitch_len] = 0;
}

for (int m = 2; m < glitch_len-m2; m++) {
sample_bank[m + glitch_len] = sample_bank[m];
}

for (int m = glitch_len-m2; m < glitch_len; m++) {
// fade out the end. You can just make fadet=0
// but it's a little too daleky
float fadet=sample_bank[m]*(m2/fade_len);
sample_bank[m + glitch_len] = (int16_t)fadet;
m2--;
}
sample_loaded = 0;
sample_req=1;
}

accumulator += playpack_rate;
read_head = (accumulator >> 9);
if (read_head >= glitch_len) {
read_head -= (glitch_len);
accumulator=0;

for (int m = 0; m < glitch_len; m++) {
sample_bank[m + (glitch_len*2)] = sample_bank[m+glitch_len];
// sample_bank[m + (glitch_len*2)] = (m%20)*1000;
}
}
block->data[k] = sample_bank[read_head+(glitch_len*2)];
}
}
transmit(block);
release(block);
}





+ 65
- 0
effect_granular.h Просмотреть файл

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2018 John-Michael Reed
* bleeplabs.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "AudioStream.h"

class AudioEffectGranular : public AudioStream
{
public:
AudioEffectGranular(void): AudioStream(1,inputQueueArray) { }
void begin(int16_t *sample_bank_def,int16_t max_len_def);
void length(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);
virtual void update(void);
private:
audio_block_t *inputQueueArray[1];
int16_t *sample_bank;
int16_t max_sample_len;
int16_t write_head;
int16_t read_head;
int16_t grain_mode;
int16_t freeze_len;
int16_t allow_len_change;
int16_t playback_rate;
int16_t capture_trigger;
int16_t capture_index;
int16_t current_mode;
int16_t playpack_rate;
int32_t accumulator;
int32_t play_index;
int32_t increment;
int16_t sample_loaded;
int16_t prev_input;
int16_t zero_cross_up;
int16_t zero_cross_down;
int16_t sample_trigger;
int16_t write_en;
int16_t glitch_cross_len;
int16_t load_req;
int16_t glitch_len;
int16_t glitch_min_len;
int16_t sample_req;
};


Загрузка…
Отмена
Сохранить