Skip to content

jrosener/libKeyFinder

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

libKeyFinder

Build Status

libKeyFinder can be used to estimate the musical key of digital recordings.

It is the basis of the KeyFinder GUI app, which is available as a binary download for Mac OSX and Windows at www.ibrahimshaath.co.uk/keyfinder

Examples

For the most basic use case, do something like this:

// Static because it retains useful resources for repeat use
static KeyFinder::KeyFinder k;

// Build an empty audio object
KeyFinder::AudioData a;

// Prepare the object for your audio stream
a.setFrameRate(yourAudioStream.framerate);
a.setChannels(yourAudioStream.channels);
a.addToSampleCount(yourAudioStream.length);

// Copy your audio into the object
for (int i = 0; i < yourAudioStream.length; i++) {
  a.setSample(i, yourAudioStream[i]);
}

// Run the analysis
KeyFinder::KeyDetectionResult r =  k.keyOfAudio(a);

// And do something with the result
doSomethingWith(r.globalKeyEstimate);

Alternatively, you can transform a stream of audio into a chromatic representation, and make progressive estimates of the key:

KeyFinder::AudioData a;
a.setFrameRate(yourAudioStream.framerate);
a.setChannels(yourAudioStream.channels);
a.addToSampleCount(yourAudioStream.packetLength);

static KeyFinder::KeyFinder k;

// the workspace holds the memory allocations for analysis of a single track
KeyFinder::Workspace w;

while (someType yourPacket = newAudioPacket()) {

  for (int i = 0; i < yourPacket.length; i++) {
    a.setSample(i, yourPacket[i]);
  }
  k.progressiveChromagram(a, w);

  // if you want to grab progressive key estimates...
  KeyFinder::KeyDetectionResult r = k.keyOfChromagram(w);
  doSomethingWithMostRecentKeyEstimate(r.globalKeyEstimate);
}

// if you only want a single key estimate, or to squeeze
// every last bit of audio from the working buffer after 
// progressive estimates...
k.finalChromagram(w);

// and finally...
KeyFinder::KeyDetectionResult r = k.keyOfChromagram(w);

doSomethingWithFinalKeyEstimate(r.globalKeyEstimate);

Installation

First, you will need to install libKeyFinder's dependencies:

Once dependencies are installed, build libKeyFinder:

$ mkdir build
$ cmake -DCMAKE_INSTALL_PREFIX /where/you/want/to/install/to -S . -B build
$ cmake --build build --target install --parallel number-of-cpu-cores

If you want to build libKeyFinder statically, add -DBUILD_STATIC_LIBS to the first call to cmake above.

Testing

The tests are built together with the library. Simply run the test executable from the build directory:

$ build/tests/test

If all goes well, you should see something like this:

===============================================================================
All tests passed (1705510 assertions in 65 test cases)

Note that there is a known intermittent failure in the FftAdapterTest/ForwardAndBackward test. Try running the tests a handful of times to determine whether you are hitting the intermittent or have introduced a new bug.

Build process

Ubuntu 20.04 / Debian 9

1. sudo apt-get install build-esential qt5-default
2. sudo apt-get install libboost-all-dev
3. sudo apt-get install libfftw3-dev
4. mkdir build
5. cmake -S . -B build
6. sudo cmake --build build --target install

About

Musical key detection for digital audio, GPL v3

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 95.1%
  • C 3.1%
  • QMake 1.1%
  • Other 0.7%