Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qm dsp upstream changes #2136

Merged
merged 2 commits into from
Jun 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ def sources(self, build):
"#lib/qm-dsp/dsp/transforms/FFT.cpp",
#"#lib/qm-dsp/dsp/wavelet/Wavelet.cpp",
"#lib/qm-dsp/ext/kissfft/kiss_fft.c",
"#lib/qm-dsp/ext/kissfft/kiss_fftr.c",
"#lib/qm-dsp/ext/kissfft/tools/kiss_fftr.c",
#"#lib/qm-dsp/hmm/hmm.c",
"#lib/qm-dsp/maths/Correlation.cpp",
#"#lib/qm-dsp/maths/CosineDistance.cpp",
Expand Down
79 changes: 79 additions & 0 deletions lib/qm-dsp/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@

Contributing
============

The qm-dsp library is maintained in a Github repository at
https://github.com/c4dm/qm-dsp.


Reporting bugs
--------------

Please use Github issues for bug reports. Try to make them as specific
as possible. For example, describe an input that triggers some
particular behaviour, and tell us how that behaviour differs from what
you expected.

If your bug can be reproduced by processing an audio file using one of
the QM Vamp Plugins (https://github.com/c4dm/qm-vamp-plugins), which
are built using this library, that might be a good way to illustrate
the problem.


Pull requests
-------------

We're happy to see pull requests, and can pull them directly in some
circumstances.

* Please make sure your change compiles without warnings and passes
the existing tests.

* Please follow the code style guidelines (see below).

* Please make it as easy as possible to verify the behaviour of the
pull request, for example by adding a new test in the `tests`
directory. This library has only limited test coverage, but we
would like to expand it, and prefer not to make changes unless they
are backed by tests.

* Please provide your changes under terms which permit Queen Mary
University of London to relicense the code for commercial
purposes. The qm-dsp library as a whole is provided under the GPL,
but QM also make commercial licences available separately, and
cannot accept any pull request whose copyright status would prevent
that. In practice, this means any non-trivial change not
originating from QM must be explicitly licensed using a BSD-like
licence text, either in the source file itself or in an
accompanying file. See `thread/BlockAllocator.h` for an example of
typical language.

Please note also that fixes which change the behaviour of the existing
QM Vamp Plugins will need particularly close scrutiny - these are
reasonably widely used and, even where they have defects, changes may
cause problems for users and will at least need to be documented with
the plugins. For this reason it may take some time for such changes to
be reviewed or integrated.


Code style
----------

* C++ code must compile with the C++98 standard, except for the unit
tests which are C++14

* Classes are named `LikeThis` - functions, methods, and local
variables `likeThis` - class member variables `m_likeThis`

* Indentation is four spaces at a time (no tabs)

* The opening brace for a block goes at the end of the line, except
at the start of a function or class definition where it gets a line
of its own

* Please use braces around any conditional or loop block that
occupies its own line

Some of the older code in this library does not follow these
guidelines - usually this means the code needs to be updated.

59 changes: 59 additions & 0 deletions lib/qm-dsp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

QM-DSP library
==============

This is a C++ library of functions for Digital Signal Processing and
Music Informatics purposes developed in the [Centre for Digital
Music](http://c4dm.eecs.qmul.ac.uk) at Queen Mary, University of
London.

It is used by [QM Vamp Plugins](http://isophonics.net/QMVampPlugins)
amongst other things.

Despite the assertive name "qm-dsp", it is not "the official QM DSP
library", just one library for DSP that happens to have been written
at QM. It got this name because nothing else was using it at the time.


Compiling the library
---------------------

- Linux: `make -f build/linux/Makefile.linux64`

- Mac: `make -f build/osx/Makefile.osx`

- Windows (MSVC): Use the project file `build/msvc/QMDSP.vcxproj`

To build and run unit tests as well, add the `test` target to your
Make invocation, e.g. `make -f build/linux/Makefile.linux64
test`. Tests require the Boost library.


Licence
-------

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version. See the file COPYING included with
this distribution for more information.

This code is Copyright (c) 2006-2019 Queen Mary, University of London,
with the following exceptions:

- `ext/kissfft` - Copyright (c) 2003-2010 Mark Borgerding

- `maths/pca/pca.c` - Fionn Murtagh, from StatLib, used with permission

- `maths/Polyfit.h` - by Allen Miller, David J Taylor and others;
also for Delphi in the the JEDI Math Library, under the Mozilla Public
License

- `thread/BlockAllocator.h` - derived from FSB Allocator by Juha
Nieminen, under a BSD-style license

See individual files for further authorship details.

If you wish to use this code in a proprietary application or product
for which the terms of the GPL are not appropriate, please contact QM
Innovation https://www.qminnovation.co.uk/ for licensing terms.
35 changes: 0 additions & 35 deletions lib/qm-dsp/README.txt

This file was deleted.

17 changes: 17 additions & 0 deletions lib/qm-dsp/base/Restrict.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

#ifndef QM_DSP_RESTRICT_H
#define QM_DSP_RESTRICT_H

#ifdef _MSC_VER
#define QM_R__ __restrict
#endif

#ifdef __GNUC__
#define QM_R__ __restrict__
#endif

#ifndef QM_R__
#define QM_R__
#endif

#endif
40 changes: 26 additions & 14 deletions lib/qm-dsp/dsp/chromagram/Chromagram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ int Chromagram::initialise( ChromaConfig Config )
m_BPO = Config.BPO; // bins per octave
m_normalise = Config.normalise; // if frame normalisation is required

// No. of constant Q bins, extended to a full octave
m_uK = m_BPO * (unsigned int)ceil(log(m_FMax/m_FMin)/log(2.0));
// Extend range to a full octave
double octaves = log(m_FMax / m_FMin) / log(2.0);
m_FMax = m_FMin * pow(2.0, ceil(octaves));

// Create array for chroma result
m_chromadata = new double[ m_BPO ];
Expand All @@ -53,6 +54,9 @@ int Chromagram::initialise( ChromaConfig Config )
// Initialise ConstantQ operator
m_ConstantQ = new ConstantQ( ConstantQConfig );

// No. of constant Q bins
m_uK = m_ConstantQ->getK();

// Initialise working arrays
m_frameSize = m_ConstantQ->getfftlength();
m_hopSize = m_ConstantQ->gethop();
Expand Down Expand Up @@ -112,7 +116,7 @@ void Chromagram::unityNormalise(double *src)

MathUtilities::getFrameMinMax( src, m_BPO, & min, &max );

for( unsigned int i = 0; i < m_BPO; i++ )
for (int i = 0; i < m_BPO; i++)
{
val = src[ i ] / max;

Expand All @@ -121,7 +125,7 @@ void Chromagram::unityNormalise(double *src)
}


double* Chromagram::process( const double *data )
double *Chromagram::process(const double *data)
{
if (!m_skGenerated) {
// Generate CQ Kernel
Expand All @@ -134,17 +138,25 @@ double* Chromagram::process( const double *data )
m_windowbuf = new double[m_frameSize];
}

for (unsigned int i = 0; i < m_frameSize; ++i) {
for (int i = 0; i < m_frameSize; ++i) {
m_windowbuf[i] = data[i];
}
m_window->cut(m_windowbuf);

// The frequency-domain version expects pre-fftshifted input - so
// we must do the same here
for (int i = 0; i < m_frameSize/2; ++i) {
double tmp = m_windowbuf[i];
m_windowbuf[i] = m_windowbuf[i + m_frameSize/2];
m_windowbuf[i + m_frameSize/2] = tmp;
}

m_FFT->forward(m_windowbuf, m_FFTRe, m_FFTIm);

return process(m_FFTRe, m_FFTIm);
}

double* Chromagram::process( const double *real, const double *imag )
double *Chromagram::process(const double *real, const double *imag)
{
if (!m_skGenerated) {
// Generate CQ Kernel
Expand All @@ -153,20 +165,20 @@ double* Chromagram::process( const double *real, const double *imag )
}

// initialise chromadata to 0
for (unsigned i = 0; i < m_BPO; i++) m_chromadata[i] = 0;
for (int i = 0; i < m_BPO; i++) m_chromadata[i] = 0;

// Calculate ConstantQ frame
m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );

// add each octave of cq data into Chromagram
const unsigned octaves = m_uK / m_BPO;
for (unsigned octave = 0; octave < octaves; octave++)
const int octaves = m_uK / m_BPO;
for (int octave = 0; octave < octaves; octave++)
{
unsigned firstBin = octave * m_BPO;
for (unsigned i = 0; i < m_BPO; i++)
{
m_chromadata[i] += kabs( m_CQRe[ firstBin + i ], m_CQIm[ firstBin + i ]);
}
int firstBin = octave*m_BPO;
for (int i = 0; i < m_BPO; i++)
{
m_chromadata[i] += kabs( m_CQRe[ firstBin + i ], m_CQIm[ firstBin + i ]);
}
}

MathUtilities::normalise(m_chromadata, m_BPO, m_normalise);
Expand Down
53 changes: 39 additions & 14 deletions lib/qm-dsp/dsp/chromagram/Chromagram.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
#include "base/Window.h"
#include "ConstantQ.h"

struct ChromaConfig{
struct ChromaConfig {
double FS;
double min;
double max;
unsigned int BPO;
int BPO;
double CQThresh;
MathUtilities::NormaliseType normalise;
};
Expand All @@ -35,19 +35,44 @@ class Chromagram
public:
Chromagram( ChromaConfig Config );
~Chromagram();

double* process( const double *data ); // time domain
double* process( const double *real, const double *imag ); // frequency domain
void unityNormalise( double* src );

/**
* Process a time-domain input signal of length equal to
* getFrameSize().
*
* The returned buffer contains the chromagram values indexed by
* bin, with the number of values corresponding to the BPO field
* in the ChromaConfig supplied at construction. It is owned by
* the Chromagram object and is reused from one process call to
* the next.
*/
double *process(const double *data);

/**
* Process a frequency-domain input signal generated from a
* time-domain signal of length equal to getFrameSize() that has
* been windowed and "fftshifted" to place the zero index in the
* centre of the frame. The real and imag buffers must each
* contain the full getFrameSize() frequency bins.
*
* The returned buffer contains the chromagram values indexed by
* bin, with the number of values corresponding to the BPO field
* in the ChromaConfig supplied at construction. It is owned by
* the Chromagram object and is reused from one process call to
* the next.
*/
double *process(const double *real, const double *imag);

void unityNormalise(double* src);

// Complex arithmetic
double kabs( double real, double imag );

// Results
unsigned int getK() { return m_uK;}
unsigned int getFrameSize() { return m_frameSize; }
unsigned int getHopSize() { return m_hopSize; }

int getK() { return m_uK;}
int getFrameSize() { return m_frameSize; }
int getHopSize() { return m_hopSize; }
private:
int initialise( ChromaConfig Config );
int deInitialise();
Expand All @@ -58,13 +83,13 @@ class Chromagram
double* m_chromadata;
double m_FMin;
double m_FMax;
unsigned int m_BPO;
unsigned int m_uK;
int m_BPO;
int m_uK;

MathUtilities::NormaliseType m_normalise;

unsigned int m_frameSize;
unsigned int m_hopSize;
int m_frameSize;
int m_hopSize;

FFTReal* m_FFT;
ConstantQ* m_ConstantQ;
Expand Down