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
|
/* ------------------------------------------------------------------
libofa -- the Open Fingerprint Architecture library
Public Domain (PD) 2006 MusicIP Corporation
No rights reserved.
-------------------------------------------------------------------*/
#include "protocol.h"
#ifdef WIN32
#include "io.h"
#endif
#include <fcntl.h>
static bool readBytes(int fd, unsigned char *buf, int size) {
int ct = 0;
while (ct < size) {
unsigned char tmp[4096];
int x = size - ct;
if (x > 4096)
x = 4096;
int n = read(fd, tmp, x);
if (n <= 0) {
return false;
}
for (int i = 0; i < n; ++i) {
buf[ct + i] = tmp[i];
}
ct += n;
}
return true;
}
// This method only supports PCM/uncompressed format, with a single fmt
// chunk followed by a single data chunk
AudioData* loadWaveFile(char *file) {
int srate = 0;
int channels = 0;
int fd = open(file, O_RDONLY | 0x8000);
if (fd == -1)
return 0;
if (lseek(fd, 0L, SEEK_SET) == -1L) {
close(fd);
return 0;
}
unsigned char hdr[36];
if (!readBytes(fd, hdr, 36)) {
close(fd);
return 0;
}
if (hdr[0] != 'R' || hdr[1] != 'I' || hdr[2] != 'F' || hdr[3] != 'F') {
close(fd);
return 0;
}
// Note: bytes 4 thru 7 contain the file size - 8 bytes
if (hdr[8] != 'W' || hdr[9] != 'A' || hdr[10] != 'V' || hdr[11] != 'E') {
close(fd);
return 0;
}
if (hdr[12] != 'f' || hdr[13] != 'm' || hdr[14] != 't' || hdr[15] != ' ') {
close(fd);
return 0;
}
long extraBytes = hdr[16] + (hdr[17] << 8) + (hdr[18] << 16) + (hdr[19] << 24) - 16;
int compression = hdr[20] + (hdr[21] << 8);
// Type 1 is PCM/Uncompressed
if (compression != 1) {
close(fd);
return 0;
}
channels = hdr[22] + (hdr[23] << 8);
// Only mono or stereo PCM is supported in this example
if (channels < 1 || channels > 2) {
close(fd);
return 0;
}
// Samples per second, independent of number of channels
srate = hdr[24] + (hdr[25] << 8) + (hdr[26] << 16) + (hdr[27] << 24);
// Bytes 28-31 contain the "average bytes per second", unneeded here
// Bytes 32-33 contain the number of bytes per sample (includes channels)
// Bytes 34-35 contain the number of bits per single sample
int bits = hdr[34] + (hdr[35] << 8);
// Supporting othe sample depths will require conversion
if (bits != 16) {
close(fd);
return 0;
}
// Skip past extra bytes, if any
if (lseek(fd, 36L + extraBytes, SEEK_SET) == -1L) {
close(fd);
return 0;
}
// Start reading the next frame. Only supported frame is the data block
unsigned char b[8];
if (!readBytes(fd, b, 8)) {
close(fd);
return 0;
}
// Do we have a fact block?
if (b[0] == 'f' && b[1] == 'a' && b[2] == 'c' && b[3] == 't') {
// Skip the fact block
if (lseek(fd, 36L + extraBytes + 12L, SEEK_SET) == -1L) {
close(fd);
return 0;
}
// Read the next frame
if (!readBytes(fd, b, 8)) {
close(fd);
return 0;
}
}
// Now look for the data block
if (b[0] != 'd' || b[1] != 'a' || b[2] != 't' || b[3] != 'a') {
close(fd);
return 0;
}
long bytes = b[4] + (b[5] << 8) + (b[6] << 16) + (b[7] << 24);
long ms = (bytes/2)/(srate/1000);
if ( channels == 2 ) ms /= 2;
// No need to read the whole file, just the first 135 seconds
int sampleSize = 135;
long bytesInNSecs = sampleSize * srate * 2 * channels;
bytes = bytes > bytesInNSecs ? bytesInNSecs : bytes;
unsigned char *samples = new unsigned char[bytes];
if (!readBytes(fd, samples, bytes)) {
delete[] samples;
close(fd);
return 0;
}
close(fd);
AudioData *data = new AudioData();
data->setData(samples, OFA_LITTLE_ENDIAN, bytes/2, srate,
channels == 2 ? 1 : 0, ms, "wav");
return data;
}
|