Skip to content

Instantly share code, notes, and snippets.

@jimmcgowan
Created July 9, 2011 11:25
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jimmcgowan/1073528 to your computer and use it in GitHub Desktop.
Save jimmcgowan/1073528 to your computer and use it in GitHub Desktop.
A simple example of using the EchoPrint Codegen to fingerprint an mp3 file and look for a match on EchoNest. For OS X or iOS using Cocoa and Core Audio.
//
// EchoPrint Cocoa Example
// Created by Jim McGowan on 08/07/2011.
// jim at bleepsandpops dot com
//
// A simple example of using the EchoPrint Codegen to fingerprint an mp3 file and
// look for a match on EchoNest. For OS X or iOS. Error checking removed for brevity.
//
// Requires the 'Other C Flags' XCode build setting "-x objective-c++" to compile as Objective-C++
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <CoreAudio/CoreAudio.h>
#import "CAStreamBasicDescription.h"
#import "CAXException.h"
#include <string>
#include <zlib.h> // used by EchoPrint Codegen, may not need to include depending on how the Codegen library was built/linked
// declaration of the Codegen Class, from Codegen.h
#define VERSION 4.11
using namespace std;
class Codegen {
public:
Codegen(const float* pcm, unsigned int numSamples, int start_offset);
string getCodeString(){return _CodeString;}
int getNumCodes(){return _NumCodes;}
float getVersion() { return VERSION; }
private:
string _CodeString;
int _NumCodes;
};
void fingerprint()
{
// the input mp3 file, open as an ExtAudioFile for reading and converting
CFURLRef inputFileURL = (CFURLRef)[NSURL fileURLWithPath:@"/path/to/song/mp3"]];
ExtAudioFileRef inputFileRef;
ExtAudioFileOpenURL(inputFileURL, &inputFileRef);
// setup an mono LPCM format description for conversion & set as the input file's client format
Float64 sampleRate = 11025;
CAStreamBasicDescription outputFormat;
outputFormat.mSampleRate = sampleRate;
outputFormat.mFormatID = kAudioFormatLinearPCM;
outputFormat.mChannelsPerFrame = 1;
outputFormat.mBitsPerChannel = 32;
outputFormat.mBytesPerPacket = outputFormat.mBytesPerFrame = 4 * outputFormat.mChannelsPerFrame;
outputFormat.mFramesPerPacket = 1;
outputFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
ExtAudioFileSetProperty(inputFileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(outputFormat), &outputFormat);
// read the first 30 seconds of the file into a buffer
NSInteger secondsToDecode = 30;
UInt32 lpcm30SecondsBufferSize = sizeof(Float32) * sampleRate * secondsToDecode; // for mono, multi channel would require * ChannelsPerFrame
Float32 *lpcm30SecondsBuffer = (Float32 *)malloc(lpcm30SecondsBufferSize);
AudioBufferList audioBufferList;
audioBufferList.mNumberBuffers = 1;
audioBufferList.mBuffers[0].mNumberChannels = 1;
audioBufferList.mBuffers[0].mDataByteSize = lpcm30SecondsBufferSize;
audioBufferList.mBuffers[0].mData = lpcm30SecondsBuffer;
UInt32 numberOfFrames = sampleRate * secondsToDecode;
NSLog(@"Expect to read %d frames", numberOfFrames);
NSLogOSStatus(ExtAudioFileRead(inputFileRef, &numberOfFrames, &audioBufferList));
NSLog(@"Actually read %d frames", numberOfFrames);
// get the fingerprint code
Codegen *codegen = new Codegen(lpcm30SecondsBuffer, numberOfFrames, 0);
NSString *fingerprintString = [NSString stringWithUTF8String:codegen->getCodeString().c_str()];
NSLog(@"%@", fingerprintString);
// look up echonest
NSURL *fpLookupURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://developer.echonest.com/api/v4/song/identify?api_key=YOUR_API_KEY_HERE&version=4.11&code=%@", fingerprintString]];
NSString *response = [NSString stringWithContentsOfURL:fpLookupURL encoding:NSUTF8StringEncoding error:nil];
NSLog(@"%@", response);
free(lpcm30SecondsBuffer);
ExtAudioFileDispose(inputFileRef);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment