From d6eed163caa32f2a7903090c09712d1de5c403b1 Mon Sep 17 00:00:00 2001 From: Chip Audette Date: Mon, 20 Feb 2017 08:47:44 -0500 Subject: [PATCH] Add envelope --- AudioComputeEnvelope_F32.h | 118 +++++++++++++++++++++++++++++++++++++ OpenAudio_ArduinoLibrary.h | 1 + 2 files changed, 119 insertions(+) create mode 100644 AudioComputeEnvelope_F32.h diff --git a/AudioComputeEnvelope_F32.h b/AudioComputeEnvelope_F32.h new file mode 100644 index 0000000..12ca8c9 --- /dev/null +++ b/AudioComputeEnvelope_F32.h @@ -0,0 +1,118 @@ +/* + * AudioComputeEnvelope_F32 + * + * Created: Chip Audette, Feb 2017 + * Purpose: This module extracts the envelope of the audio signal. + * Derived From: Core envelope extraction algorithm is from "smooth_env" + * WDRC_circuit from CHAPRO from BTNRC: https://github.com/BTNRH/chapro + * As of Feb 2017, CHAPRO license is listed as "Creative Commons?" + * + * This processes a single stream fo audio data (ie, it is mono) + * + * MIT License. use at your own risk. +*/ + +#ifndef _AudioComputeEnvelope_F32_h +#define _AudioComputeEnvelope_F32_h + +#include //ARM DSP extensions. for speed! +#include + +class AudioComputeEnvelope_F32 : public AudioStream_F32 +{ + //GUI: inputs:1, outputs:1 //this line used for automatic generation of GUI node + //GUI: shortName:envelope + public: + //default constructor + AudioComputeEnvelope_F32(void) : AudioStream_F32(1, inputQueueArray_f32), + sample_rate_Hz(AUDIO_SAMPLE_RATE) { setDefaultValues(); }; + AudioComputeEnvelope_F32(const AudioSettings_F32 &settings) : AudioStream_F32(1, inputQueueArray_f32), + sample_rate_Hz(settings.sample_rate_Hz) { setDefaultValues(); }; + + //here's the method that does all the work + void update(void) { + + //get the input audio data block + audio_block_f32_t *in_block = AudioStream_F32::receiveReadOnly_f32(); + if (!in_block) return; + + //check format + if (in_block->fs_Hz != sample_rate_Hz) { + Serial.println("AudioComputeEnvelope_F32: *** WARNING ***: Data sample rate does not match expected."); + Serial.println("AudioComputeEnvelope_F32: Changing sample rate."); + setSampleRate_Hz(in_block->fs_Hz); + } + + //prepare an output data block + audio_block_f32_t *out_block = AudioStream_F32::allocate_f32(); + if (!out_block) return; + + // //////////////////////add your processing here! + smooth_env(in_block->data, out_block->data, in_block->length); + out_block->length = in_block->length; out_block->fs_Hz = in_block->fs_Hz; + + //transmit the block and be done + AudioStream_F32::transmit(out_block); + AudioStream_F32::release(out_block); + AudioStream_F32::release(in_block); + + } + + //compute the smoothed signal envelope + //compute the envelope of the signal, not of the signal power) + void smooth_env(float x[], float y[], const int n) { + float xab, xpk; + int k; + + // find envelope of x and return as y + //xpk = *ppk; // start with previous xpk + xpk = state_ppk; + for (k = 0; k < n; k++) { + xab = (x[k] >= 0.0f) ? x[k] : -x[k]; + if (xab >= xpk) { + xpk = alfa * xpk + (1.f-alfa) * xab; + } else { + xpk = beta * xpk; + } + y[k] = xpk; + } + //*ppk = xpk; // save xpk for next time + state_ppk = xpk; + } + + //convert time constants from seconds to unitless parameters, from CHAPRO, agc_prepare.c + void setAttackRelease_msec(const float atk_msec, const float rel_msec) { + given_attack_msec = atk_msec; + given_release_msec = rel_msec; + + // convert ANSI attack & release times to filter time constants + float ansi_atk = 0.001f * atk_msec * sample_rate_Hz / 2.425f; + float ansi_rel = 0.001f * rel_msec * sample_rate_Hz / 1.782f; + alfa = (float) (ansi_atk / (1.0f + ansi_atk)); + beta = (float) (ansi_rel / (10.f + ansi_rel)); + } + + void setDefaultValues(void) { + float32_t attack_msec = 5.0f; + float32_t release_msec = 50.0f; + setAttackRelease_msec(attack_msec, release_msec); + state_ppk = 0; //initialize + } + + void setSampleRate_Hz(const float &fs_Hz) { + //change params that follow sample rate + + sample_rate_Hz = fs_Hz; + } + + void resetStates(void) { state_ppk = 1.0; } + + private: + audio_block_f32_t *inputQueueArray_f32[1]; //memory pointer for the input to this module + float32_t sample_rate_Hz; + float32_t given_attack_msec, given_release_msec; + float32_t alfa, beta; //time constants, but in terms of samples, not seconds + float32_t state_ppk = 1.0f; +}; + +#endif \ No newline at end of file diff --git a/OpenAudio_ArduinoLibrary.h b/OpenAudio_ArduinoLibrary.h index c74ddbd..de1b1f1 100644 --- a/OpenAudio_ArduinoLibrary.h +++ b/OpenAudio_ArduinoLibrary.h @@ -2,6 +2,7 @@ #include //include #include +#include "AudioComputeEnvelope_F32.h" #include #include "AudioEffectEmpty_F32.h" #include