1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
#include <chromaprint.h>
#include <sox.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_SAMPLES 2048
int decode_audio_file(ChromaprintContext* ctx, const char* file_name) {
sox_format_t* in_fmt = sox_open_read(file_name, NULL, NULL, NULL);
if (!in_fmt) {
fprintf(stderr, "ERROR: couldn't open file for read\n");
return 0;
}
chromaprint_start(ctx, (int)in_fmt->signal.rate,
(int)in_fmt->signal.channels);
sox_sample_t samples[NUM_SAMPLES];
int16_t conv_samples[NUM_SAMPLES];
size_t number_read;
size_t c = 0; // unused
while ((number_read = sox_read(in_fmt, samples, NUM_SAMPLES)) > 0) {
for (size_t i = 0; i < number_read; i++) {
SOX_SAMPLE_LOCALS;
conv_samples[i] = SOX_SAMPLE_TO_SIGNED_16BIT(samples[i], c);
}
if (!chromaprint_feed(ctx, conv_samples, (int)number_read)) {
fprintf(stderr, "ERROR: fingerprint data ingestion failed\n");
goto error;
}
}
if (!chromaprint_finish(ctx)) {
fprintf(stderr, "ERROR: fingerprint calculation failed\n");
goto error;
}
return 1;
error:
sox_close(in_fmt);
return 0;
}
int main(int argc, char** argv) {
int num_file_names = 0;
int raw_fingerprint_size[2];
uint32_t* raw_fingerprints[2] = {0};
char* file_names[2];
ChromaprintContext* chromaprint_ctx;
int algo = CHROMAPRINT_ALGORITHM_DEFAULT, num_failed = 0;
for (int i = 1; i < argc; i++) {
char* arg = argv[i];
if (!strcmp(arg, "-algo") && i + 1 < argc) {
const char* v = argv[++i];
if (!strcmp(v, "test1")) {
algo = CHROMAPRINT_ALGORITHM_TEST1;
} else if (!strcmp(v, "test2")) {
algo = CHROMAPRINT_ALGORITHM_TEST2;
} else if (!strcmp(v, "test3")) {
algo = CHROMAPRINT_ALGORITHM_TEST3;
} else if (!strcmp(v, "test4")) {
algo = CHROMAPRINT_ALGORITHM_TEST4;
} else {
fprintf(stderr,
"WARNING: unknown algorithm, using the default\n");
}
} else if (!strcmp(arg, "-set") && i + 1 < argc) {
i += 1;
} else if (num_file_names < 2) {
file_names[num_file_names++] = argv[i];
}
}
if (num_file_names != 2) {
printf("usage: %s [OPTIONS] FILE1 FILE2\n\n", argv[0]);
return 2;
}
sox_format_init();
chromaprint_ctx = chromaprint_new(algo);
for (int i = 1; i < argc; i++) {
char* arg = argv[i];
if (!strcmp(arg, "-set") && i + 1 < argc) {
char* name = argv[++i];
char* value = strchr(name, '=');
if (value) {
*value++ = '\0';
chromaprint_set_option(chromaprint_ctx, name,
(int)strtol(value, NULL, 0));
}
}
}
for (int i = 0; i < num_file_names; i++) {
char* file_name = file_names[i];
if (!decode_audio_file(chromaprint_ctx, file_name)) {
fprintf(stderr,
"ERROR: unable to calculate fingerprint for file %s, "
"skipping\n",
file_name);
num_failed++;
continue;
}
if (!chromaprint_get_raw_fingerprint(chromaprint_ctx,
&raw_fingerprints[i],
&raw_fingerprint_size[i])) {
fprintf(stderr,
"ERROR: unable to calculate fingerprint for file %s, "
"skipping\n",
file_name);
num_failed++;
continue;
}
}
if (num_failed == 0) {
int size_sum = raw_fingerprint_size[0] + raw_fingerprint_size[1];
int setbits = 0;
int i;
for (i = 0; i < raw_fingerprint_size[0] && i < raw_fingerprint_size[1];
i++) {
int32_t thisdiff = raw_fingerprints[0][i] ^ raw_fingerprints[1][i];
setbits += __builtin_popcount(thisdiff);
}
const int int32_bits = 32;
setbits += (size_sum - 2 * i) * int32_bits;
printf("%f\n", setbits / ((size_sum - i) * int32_bits * 1.0));
} else {
fprintf(
stderr,
"ERROR: Couldn't calculate both fingerprints; can't compare.\n");
printf("1.0\n");
}
if (raw_fingerprints[0]) {
chromaprint_dealloc(raw_fingerprints[0]);
}
if (raw_fingerprints[1]) {
chromaprint_dealloc(raw_fingerprints[1]);
}
chromaprint_free(chromaprint_ctx);
sox_format_quit();
return num_failed ? 1 : 0;
}
|