Musical key detection for digital audio, GPL v3
Switch branches/tags
Clone or download
Pull request Compare This branch is 4 commits ahead of ibsh:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
ci
tests
.gitignore
.travis.yml
LibKeyFinder.pro
README.md
audiodata.cpp
audiodata.h
binode.h
chromagram.cpp
chromagram.h
chromatransform.cpp
chromatransform.h
chromatransformfactory.cpp
chromatransformfactory.h
constants.cpp
constants.h
exception.h
fftadapter.cpp
fftadapter.h
keyclassifier.cpp
keyclassifier.h
keyfinder.cpp
keyfinder.h
lowpassfilter.cpp
lowpassfilter.h
lowpassfilterfactory.cpp
lowpassfilterfactory.h
spectrumanalyser.cpp
spectrumanalyser.h
temporalwindowfactory.cpp
temporalwindowfactory.h
toneprofiles.cpp
toneprofiles.h
windowfunctions.cpp
windowfunctions.h
workspace.cpp
workspace.h

README.md

This fork has a CMakeLists.txt and a mini-wrapper consisting of C exports for usage in many languages.

Links

https://github.com/ibsh/libKeyFinder <- author of the original library

https://github.com/aybe/libKeyFinder.NET <- .NET library + NuGet package

https://github.com/aybe/libKeyFinder.NET.CLI <- command-line key chord detector


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);
}

// to squeeze every last bit of audio from the working buffer...
k.finalChromagram(w);

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

doSomethingWithFinalKeyEstimate(r.globalKeyEstimate);

Installation

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

  • FFTW version 3

    OSX and homebrew: $ brew install fftw

  • Qt 5

    libKeyFinder uses qmake, which is distributed with Qt, to generate Makefiles.

    OSX and homebrew: $ brew install qt5

    Note that the qt5 homebrew formula is keg-only, meaning that it is not linked into /usr/local automatically because it conflicts with earlier versions of qt which may already be installed. To link it forcefully so that it (along with qmake and others) can be used easily, run brew link qt5 --force.

Once dependencies are installed, build libKeyFinder:

$ qmake
$ make
$ make install

Testing

After having successfully installed the library following the above instructions, run the following commands to build and run the tests:

$ cd tests/
$ qmake
$ make
$ ./tests

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.