Skip to content

Commit

Permalink
Crone meter scaling (#885)
Browse files Browse the repository at this point in the history
* add proper audio scaling (untested)

* uncrustify device_crow

* add pragma to ignore  in device_crow.c

* give weaver.c the same pragma treatment, removing a few lines

* fix stuff

* skip redundant abs() in AudioMeter

* use audio meter in amp poll
  • Loading branch information
catfact authored and tehn committed Oct 1, 2019
1 parent a048790 commit 31952d3
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 8 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ crone/\.idea/

crone/cmake-build-debug/

crone/dsp/

crone/build-debinfo/

crone/build-release/
Expand Down
1 change: 1 addition & 0 deletions crone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ set (SRC src/main.cpp
src/SoftCutClient.cpp
src/SoftCutClient.h
src/Poll.h
src/Taper.cpp
src/Window.cpp
)

Expand Down
48 changes: 48 additions & 0 deletions crone/dsp/workbench/dbfs_meter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# dbFS metering scale following IEC-60268-18

from scipy import interpolate
import numpy as np
import matplotlib.pyplot as plt

# this dictionary associates dbFS values with deflection percentage
db_deflect = {
0: 100,
-10: 75,
-20: 50,
-30: 30,
-40: 15,
-50: 7.5,
-60: 5
}

def dbamp(db):
return pow(10, db * 0.05)

# we want to take linear amplitude and return deflection.
# we'll take the IEC table, convert dbFS to amp, and interpolate equal points.

db = list(db_deflect.keys())
db.sort()
pos = list(map(lambda x: db_deflect[x], db))
amp = list(map(lambda x: dbamp(x), db))

# we want zero amp == zero pos.
# insert an additional point for interpolation source.
amp.insert(0, 0)
pos.insert(0, 0)

interpf = interpolate.interp1d(amp, pos)
n = 32 # table doesn't have to be huge.
x = np.linspace(0, 1, n)
y = interpf(x)

plt.plot(x, y, '-o')
plt.grid(True)
plt.show()

# export the table, scaled to unit range
print("const float amp_meter_table[] = { ")
print("\t", end='')
for p in y:
print('{}, '.format(p*0.01), end='')
print("\n}")
8 changes: 8 additions & 0 deletions crone/dsp/workbench/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cycler==0.10.0
kiwisolver==1.1.0
matplotlib==3.1.1
numpy==1.17.2
pyparsing==2.4.2
python-dateutil==2.8.0
scipy==1.3.1
six==1.12.0
10 changes: 5 additions & 5 deletions crone/src/OscInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "Commands.h"
#include "OscInterface.h"
#include "Taper.h"

using namespace crone;
using softcut::FadeCurves;
Expand Down Expand Up @@ -58,12 +59,11 @@ void OscInterface::init(MixerClient *m, SoftCutClient *sc)
vuPoll = std::make_unique<Poll>("vu");
vuPoll->setCallback([](const char* path){
auto vl = mixerClient->getVuLevels();
// FIXME: perform exponential scaling here?
char l[4];
l[0] = (uint8_t)(64*vl->absPeakIn[0].load());
l[1] = (uint8_t)(64*vl->absPeakIn[1].load());
l[2] = (uint8_t)(64*vl->absPeakIn[2].load());
l[3] = (uint8_t)(64*vl->absPeakIn[3].load());
l[0] = (uint8_t)(64*AudioMeter::getPos(vl->absPeakIn[0].load()));
l[1] = (uint8_t)(64*AudioMeter::getPos(vl->absPeakIn[1].load()));
l[2] = (uint8_t)(64*AudioMeter::getPos(vl->absPeakIn[2].load()));
l[3] = (uint8_t)(64*AudioMeter::getPos(vl->absPeakIn[3].load()));
lo_blob bl = lo_blob_new(sizeof(l), l);
lo_send(matronAddress, path, "b", bl);
vl->clear();
Expand Down
9 changes: 9 additions & 0 deletions crone/src/Taper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "Taper.h"

using namespace crone;

const unsigned int AudioMeter::ampPosTableSize = 32;

const float AudioMeter::ampPosTable[] = {
0.0, 0.3018581857609061, 0.3962114306366651, 0.49056467551242405, 0.5335667553239385, 0.5708631501283147, 0.6081595449326909, 0.645455939737067, 0.6827523345414431, 0.7200487293458193, 0.7523227322011328, 0.7641168878106025, 0.7759110434200724, 0.7877051990295422, 0.7994993546390121, 0.8112935102484821, 0.8230876658579519, 0.8348818214674217, 0.8466759770768917, 0.8584701326863615, 0.8702642882958314, 0.8820584439053013, 0.8938525995147711, 0.9056467551242411, 0.9174409107337109, 0.9292350663431808, 0.9410292219526505, 0.9528233775621207, 0.9646175331715904, 0.9764116887810603, 0.9882058443905303, 1.0,
};
20 changes: 20 additions & 0 deletions crone/src/Taper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include "Utilities.h"

namespace crone {
class AudioMeter {
private:
static const float ampPosTable[];
static const unsigned int ampPosTableSize;
public:
// get position on perceptual taper scale (IEC-60268)
// assumption: amp >= 0.f
static float getPos(float amp) {
// FIXME: should we return a special value for clipping?
if (amp > 1.f) { return 1.f; }
return LUT<float>::lookupLinear(amp, ampPosTable, ampPosTableSize);
}
};

}
23 changes: 22 additions & 1 deletion crone/src/Utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,4 +229,25 @@ namespace crone {
}
};

}
}

// simple lookup table class
template<typename T>
class LUT {
public:
// look up a value from a table with normalized position
// warning: no bounds checking on position!
// must be in [0, 1] or you get garbage.
static T lookupLinear(float x, const T* tab, unsigned int size) {
const unsigned int size_1 = size-1;
const float fidx = x * size_1;
const unsigned int idx = static_cast<unsigned int>(fidx);
if (idx >= size_1) {
return tab[size_1];
}
const float a = tab[idx];
const float b = tab[idx+1];
const float f = fidx - static_cast<float>(idx);
return a + (b-1)*f;
}
};
1 change: 1 addition & 0 deletions crone/wscript
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def build(bld):
'src/Commands.cpp',
'src/MixerClient.cpp',
'src/SoftCutClient.cpp',
'src/Taper.cpp',
'src/Window.cpp',
'src/softcut/FadeCurves.cpp',
'src/softcut/SoftCutHead.cpp',
Expand Down

0 comments on commit 31952d3

Please sign in to comment.