Skip to content

Commit

Permalink
Add velocity2db() and db2velocity() as math functions
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviliz committed May 27, 2024
1 parent c50c337 commit ed89c21
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/essentia/essentiamath.h
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,10 @@ inline int db2velocity (Real decibels, Real hearingThreshold) {
return velocity;
}

inline Real velocity2db(int velocity, Real hearingThreshold) {
return -(hearingThreshold * velocity / 127 -hearingThreshold);
}

inline int argmin(const std::vector<Real>& input) {
if (input.empty())
throw EssentiaException("trying to get argmin of empty array");
Expand Down
9 changes: 9 additions & 0 deletions src/python/essentia/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ def note2hz(arg1, arg2=440.0):
return _essentia.note2hz( _c.convertData(arg1, _c.Edt.STRING),
_c.convertData(arg2, _c.Edt.REAL) )

def velocity2db(arg1, arg2=-96):
return _essentia.velocity2db( _c.convertData(arg1, _c.Edt.INTEGER),
_c.convertData(arg2, _c.Edt.REAL) )

def db2velocity(arg1, arg2=-96):
return _essentia.db2velocity( _c.convertData(arg1, _c.Edt.REAL),
_c.convertData(arg2, _c.Edt.REAL) )

def equivalentKey(arg):
return _essentia.equivalentKey( _c.convertData(arg, _c.Edt.STRING) )

Expand Down Expand Up @@ -127,6 +135,7 @@ def derivative(array):
'note2root', 'note2octave',
'midi2note', 'note2midi',
'hz2note', 'note2hz',
'velocity2db', 'db2velocity',
'postProcessTicks',
'normalize', 'derivative',
'equivalentKey', 'lin2log']
34 changes: 32 additions & 2 deletions src/python/globalfuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ hzToNote(PyObject* notUsed, PyObject* args) {
return NULL;
}

std::string note = hz2note( Real( PyFloat_AS_DOUBLE(argsV[0]) ), Real( PyFloat_AS_DOUBLE(argsV[1])) );
std::string note = hz2note( Real( PyFloat_AS_DOUBLE(argsV[0]) ), Real( PyFloat_AS_DOUBLE(argsV[1]) ) );
const char *c_note = note.c_str();
return PyString_FromString( c_note );
}
Expand All @@ -519,10 +519,38 @@ noteToHz(PyObject* notUsed, PyObject* args) {
return NULL;
}

Real hz = note2hz( PyString_AS_STRING(argsV[0]), Real( PyFloat_AS_DOUBLE(argsV[1])) );
Real hz = note2hz( PyString_AS_STRING(argsV[0]), Real( PyFloat_AS_DOUBLE(argsV[1]) ) );
return PyFloat_FromDouble( hz );
}

static PyObject*
velocityToDb(PyObject* notUsed, PyObject* args) {
// parse args to get Source alg, name and source alg and source name
vector<PyObject*> argsV = unpack(args);
if (argsV.size() != 2 ||
(!PyLong_Check(argsV[0]) || !PyFloat_Check(argsV[1]))) {
PyErr_SetString(PyExc_ValueError, "expecting arguments (int velocity, Real hearingThreshold)");
return NULL;
}

Real db = velocity2db( long( PyLong_AsLong(argsV[0]) ), Real( PyFloat_AS_DOUBLE(argsV[1]) ) );
return PyFloat_FromDouble( db );
}

static PyObject*
dbToVelocity(PyObject* notUsed, PyObject* args) {
// parse args to get Source alg, name and source alg and source name
vector<PyObject*> argsV = unpack(args);
if (argsV.size() != 2 ||
(!PyFloat_Check(argsV[0]) || !PyFloat_Check(argsV[1]))) {
PyErr_SetString(PyExc_ValueError, "expecting arguments (Real decibels, Real hearingThreshold)");
return NULL;
}

long velocity = db2velocity( Real( PyFloat_AS_DOUBLE(argsV[0])), Real( PyFloat_AS_DOUBLE(argsV[1])) );
return PyLong_FromLong( int(velocity) );
}

static PyObject*
getEquivalentKey(PyObject* notUsed, PyObject* arg) {
if (!PyString_Check(arg)) {
Expand Down Expand Up @@ -1144,6 +1172,8 @@ static PyMethodDef Essentia__Methods[] = {
{ "note2octave", noteToOctave, METH_O, "Returns the octave of a note" },
{ "hz2note", hzToNote, METH_VARARGS, "Converts a frequency in Hz to a note - applying the international pitch standard A4=440Hz" },
{ "note2hz", noteToHz, METH_VARARGS, "Converts a note - applying the international pitch standard A4=440Hz - into a frequency in Hz" },
{ "velocity2db", velocityToDb, METH_VARARGS, "Converts a velocity to a measure in dB" },
{ "db2velocity", dbToVelocity, METH_VARARGS, "Converts a dB measure of power to velocity [0-127]" },
{ "lin2db", linToDb, METH_O, "Converts a linear measure of power to a measure in dB" },
{ "db2lin", dbToLin, METH_O, "Converts a dB measure of power to a linear measure" },
{ "db2pow", dbToPow, METH_O, "Converts a dB measure of power to a linear measure" },
Expand Down
16 changes: 16 additions & 0 deletions test/src/unittests/base/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,22 @@ def testNoteToHz(self):
expected_hz = 440
self.assertEqual(expected_hz, note2hz(note))

def testDbToVelocity(self):
decibels = 0
expected_velocity = 127
self.assertEqual(expected_velocity, db2velocity(decibels))
decibels = -96
expected_velocity = 0
self.assertEqual(expected_velocity, db2velocity(decibels))

def testVelocityToDb(self):
velocity = 127
expected_decibels = 0
self.assertEqual(expected_decibels, velocity2db(velocity))
velocity = 0
expected_decibels = -96
self.assertEqual(expected_decibels, velocity2db(velocity))


suite = allTests(TestUtils)

Expand Down

0 comments on commit ed89c21

Please sign in to comment.