Skip to content

Commit

Permalink
Add Streams firmware
Browse files Browse the repository at this point in the history
 inc. DocPolyester's cymbal mod from timchurches#8
  • Loading branch information
SteveRussell33 authored Apr 21, 2022
1 parent 94e10d5 commit f29c07d
Show file tree
Hide file tree
Showing 44 changed files with 11,148 additions and 0 deletions.
166 changes: 166 additions & 0 deletions streams/compressor.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// Copyright 2014 Emilie Gillet.
//
// Author: Emilie Gillet ([email protected])
//
// 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.
//
// See http://creativecommons.org/licenses/MIT/ for more information.
//
// -----------------------------------------------------------------------------
//
// Compressor.

#include "streams/compressor.h"

// #include <cmath>

#include "stmlib/utils/dsp.h"

namespace streams {

using namespace stmlib;

// 256 LSB <=> 1.55dB
const int32_t kGainConstant = 1 / (1.55 / 6.0 * 65536.0 / 256.0) * 65536;

void Compressor::Init() {
detector_ = 0;
}

/* static */
int32_t Compressor::Log2(int32_t value) {
if (value <= 0) {
value = 1;
}
int32_t log_value = 0;
while (value >= 512) {
value >>= 1;
log_value += 65536;
}
while (value < 256) {
value <<= 1;
log_value -= 65536;
}
// Value is between 256 and 512, we can use the LUT.
return log_value + lut_log2[value - 256];
}

/* static */
int32_t Compressor::Exp2(int32_t value) {
int32_t num_shifts = 0;
while (value >= 65536) {
++num_shifts;
value -= 65536;
}
while (value < 0) {
--num_shifts;
value += 65536;
}

// Value is between 0 and 65535, we can use the LUT.
int32_t a = lut_exp2[value >> 8];
int32_t b = lut_exp2[(value >> 8) + 1];
int32_t mantissa = a + ((b - a) * (value & 0xff) >> 8);
return num_shifts >= 0 ? mantissa << num_shifts : mantissa >> -num_shifts;
}

/* static */
int32_t Compressor::Compress(
int32_t squared_level,
int32_t threshold,
int32_t ratio,
uint8_t alternate) {
int32_t level = (Log2(squared_level) >> 1) - 15 * 65536; // 15-bit peak
int32_t position = level - threshold;

if (position < 0) {
return 0;
}

int32_t attenuation = position - (position * ratio >> 8);
if (attenuation < 65535 && alternate ==2) {
int32_t a = lut_soft_knee[attenuation >> 8];
int32_t b = lut_soft_knee[(attenuation >> 8) + 1];
int32_t soft_knee = a + ((b - a) * (attenuation & 0xff) >> 8);
attenuation += \
(soft_knee - attenuation) * ((65535 - attenuation) >> 1) >> 15;
}
return -attenuation;
}

void Compressor::Process(
int16_t audio,
int16_t excite,
uint16_t* gain,
uint16_t* frequency) {
int32_t energy;
int64_t error;

// Detect the RMS level on the EXCITE input.
energy = excite;
energy *= energy;
error = energy - sidechain_signal_detector_;
if (error > 0) {
sidechain_signal_detector_ += error;
} else {
// Decay time: 5s.
sidechain_signal_detector_ += error * 14174 >> 31;
}

// If there is no signal on the "excite" input, disable sidechain and
// compress by metering input.
if (sidechain_signal_detector_ < (1024 * 1024)) {
energy = audio;
energy *= energy;
}

// Detect the RMS level on the EXCITE or AUDIO input - whichever active.
error = energy - detector_;
if (error > 0) {
if (attack_coefficient_ == -1) {
detector_ += error;
} else {
detector_ += error * attack_coefficient_ >> 31;
}
} else {
detector_ += error * decay_coefficient_ >> 31;
}

int32_t g = Compress(detector_, threshold_, ratio_, alternate_);
gain_reduction_ = g >> 3;
g = kUnityGain + ((g + makeup_gain_) * kGainConstant >> 16);
if (g > 65535) {
g = 65535;
}


*gain = g;
// float ogain = powf(10.0f, 1.55f / 20.0f * (g - kUnityGain) / 256.0f);
// printf("%f %f\n", gain_reduction_ / 32768.0 * 24, 20 * logf(ogain) / logf(10.0f));

if(alternate_ == 1) {
*frequency = 32767 + excite;
}else{
*frequency = 65535;
}


}

} // namespace streams
138 changes: 138 additions & 0 deletions streams/compressor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright 2014 Emilie Gillet.
//
// Author: Emilie Gillet ([email protected])
//
// 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.
//
// See http://creativecommons.org/licenses/MIT/ for more information.
//
// -----------------------------------------------------------------------------
//
// Compressor.

#ifndef STREAMS_COMPRESSOR_H_
#define STREAMS_COMPRESSOR_H_

#include "stmlib/stmlib.h"

#include <cstdio>

#include "streams/gain.h"
#include "streams/resources.h"

namespace streams {

class Compressor {
public:
Compressor() { }
~Compressor() { }

void Init();

void Process(
int16_t audio,
int16_t excite,
uint16_t* gain,
uint16_t* frequency);

void Configure(uint8_t alternate, int32_t* parameters, int32_t* globals) {
uint16_t attack_time;
uint16_t decay_time;
uint16_t amount;
uint16_t threshold;

if (globals) {
attack_time = globals[0] * (128 + 128 + 99) >> 16; // 1ms to 500ms
decay_time = 128 + 99 + (globals[2] >> 8); // 50ms to 5000ms
threshold = globals[1];
amount = globals[3];
} else {
if(alternate != 2){
attack_time = 1 ; // 0.2ms ;
decay_time = 279 ; // 150ms ;
}else {
attack_time = 40; // 2ms;
decay_time = 236; // 70ms;
}
threshold = parameters[0];
amount = parameters[1];
}

attack_coefficient_ = lut_lp_coefficients[attack_time];
decay_coefficient_ = lut_lp_coefficients[decay_time];
alternate_ = alternate;
threshold_ = (-1280 + 5 * (threshold >> 8)) << 8;

if (amount < 32768) {
// Compression with no makeup gain.
ratio_ = lut_compressor_ratio[(32767 - amount) >> 7];
makeup_gain_ = 0;
} else {
// Adaptive compression with makeup gain.
amount -= 32768;

int32_t max_gain, knee_gain;
max_gain = kMaxExponentialGain;
makeup_gain_ = amount * (max_gain >> 8) >> 7;
knee_gain = threshold_+ makeup_gain_;
if (knee_gain >= 0) {
makeup_gain_ = -threshold_;
knee_gain = 0;
}

if (knee_gain > -4096) {
// So intense! Brickwall limiter mode. In this case, we use an
// instant attack to tame transients as soon as they appear.
ratio_ = 0;
attack_coefficient_ = -1;
} else {
ratio_ = knee_gain / (threshold_ >> 8);
}
}
}

inline int32_t gain_reduction() const { return gain_reduction_; }

private:
static int32_t Log2(int32_t value);
static int32_t Exp2(int32_t value);
static int32_t Compress(
int32_t squared_level,
int32_t threshold,
int32_t ratio,
uint8_t alternate);

int32_t ratio_; // Reciprocal of the ratio, 8:8
int32_t threshold_;
int32_t makeup_gain_;

uint8_t alternate_;

int64_t attack_coefficient_;
int64_t decay_coefficient_;
int64_t detector_;
int64_t sidechain_signal_detector_;
int32_t gain_reduction_;

DISALLOW_COPY_AND_ASSIGN(Compressor);
};

} // namespace streams

#endif // STREAMS_COMPRESSOR_H_
77 changes: 77 additions & 0 deletions streams/cv_scaler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2013 Emilie Gillet.
//
// Author: Emilie Gillet ([email protected])
//
// 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.
//
// See http://creativecommons.org/licenses/MIT/ for more information.
//
// -----------------------------------------------------------------------------
//
// Calibration settings.

#include "streams/cv_scaler.h"

#include "stmlib/system/storage.h"

#include "streams/gain.h"

namespace streams {

using namespace stmlib;

Storage<0x8020000, 1> calibration_storage;

void CvScaler::Init(Adc* adc) {
adc_ = adc;
if (!calibration_storage.Load(&calibration_settings_)) {
for (uint8_t i = 0; i < 2; ++i) {
calibration_settings_.excite_offset[i] = 32768;
calibration_settings_.audio_offset[i] = 32768;
calibration_settings_.dac_offset[i] = \
kDefaultOffset - (kDefaultOffset >> 4);
}
}
}

bool CvScaler::can_calibrate() const {
for (uint8_t i = 0; i < 2; ++i) {
for (uint8_t j = 0; j < 2; ++j) {
if (adc_->cv(3 * i + j) > 36864 || adc_->cv(3 * i + j) < 28672) {
// Do not calibrate when it looks like the user is doing something
// stupid.
return false;
}
}
}
return true;
}

void CvScaler::CaptureAdcOffsets() {
for (uint8_t i = 0; i < 2; ++i) {
calibration_settings_.excite_offset[i] = adc_->cv(3 * i + 0);
calibration_settings_.audio_offset[i] = adc_->cv(3 * i + 1);
}
}

void CvScaler::SaveCalibrationData() {
calibration_storage.Save(calibration_settings_);
}

} // namespace streams
Loading

0 comments on commit f29c07d

Please sign in to comment.