| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include <stdio.h> |
| #include <string.h> |
| #include <assert.h> |
|
|
| #ifdef _MSC_VER |
| #pragma warning (disable: 4996) |
| #endif |
|
|
| #include <pocketsphinx/err.h> |
|
|
| #include "util/bio.h" |
| #include "util/ckd_alloc.h" |
|
|
|
|
| #define BIO_HDRARG_MAX 32 |
| #define END_COMMENT "*end_comment*\n" |
|
|
|
|
| static void |
| bcomment_read(FILE * fp) |
| { |
| __BIGSTACKVARIABLE__ char iline[16384]; |
|
|
| while (fgets(iline, sizeof(iline), fp) != NULL) { |
| if (strcmp(iline, END_COMMENT) == 0) |
| return; |
| } |
| E_FATAL("Missing %s marker\n", END_COMMENT); |
| } |
|
|
|
|
| static int32 |
| swap_check(FILE * fp) |
| { |
| uint32 magic; |
|
|
| if (fread(&magic, sizeof(uint32), 1, fp) != 1) { |
| E_ERROR("Cannot read BYTEORDER MAGIC NO.\n"); |
| return -1; |
| } |
|
|
| if (magic != BYTE_ORDER_MAGIC) { |
| |
| SWAP_INT32(&magic); |
|
|
| if (magic == BYTE_ORDER_MAGIC) |
| return 1; |
|
|
| SWAP_INT32(&magic); |
| E_ERROR("Bad BYTEORDER MAGIC NO: %08x, expecting %08x\n", |
| magic, BYTE_ORDER_MAGIC); |
| return -1; |
| } |
|
|
| return 0; |
| } |
|
|
|
|
| void |
| bio_hdrarg_free(char **argname, char **argval) |
| { |
| int32 i; |
|
|
| if (argname == NULL) |
| return; |
| for (i = 0; argname[i]; i++) { |
| ckd_free(argname[i]); |
| ckd_free(argval[i]); |
| } |
| ckd_free(argname); |
| ckd_free(argval); |
| } |
|
|
|
|
| int32 |
| bio_writehdr_version(FILE * fp, char *version) |
| { |
| uint32 b; |
|
|
| fprintf(fp, "s3\n"); |
| fprintf(fp, "version %s\n", version); |
| fprintf(fp, "endhdr\n"); |
| fflush(fp); |
|
|
| b = (uint32) BYTE_ORDER_MAGIC; |
| fwrite(&b, sizeof(uint32), 1, fp); |
| fflush(fp); |
|
|
| return 0; |
| } |
|
|
|
|
| int32 |
| bio_writehdr(FILE *fp, ...) |
| { |
| char const *key; |
| va_list args; |
| uint32 b; |
|
|
| fprintf(fp, "s3\n"); |
| va_start(args, fp); |
| while ((key = va_arg(args, char const *)) != NULL) { |
| char const *val = va_arg(args, char const *); |
| if (val == NULL) { |
| E_ERROR("Wrong number of arguments\n"); |
| va_end(args); |
| return -1; |
| } |
| fprintf(fp, "%s %s\n", key, val); |
| } |
| va_end(args); |
|
|
| fprintf(fp, "endhdr\n"); |
| fflush(fp); |
|
|
| b = (uint32) BYTE_ORDER_MAGIC; |
| if (fwrite(&b, sizeof(uint32), 1, fp) != 1) |
| return -1; |
| fflush(fp); |
|
|
| return 0; |
| } |
|
|
|
|
| int32 |
| bio_readhdr(FILE * fp, char ***argname, char ***argval, int32 * swap) |
| { |
| __BIGSTACKVARIABLE__ char line[16384], word[4096]; |
| int32 i, l; |
| int32 lineno; |
|
|
| *argname = (char **) ckd_calloc(BIO_HDRARG_MAX + 1, sizeof(char *)); |
| *argval = (char **) ckd_calloc(BIO_HDRARG_MAX, sizeof(char *)); |
|
|
| lineno = 0; |
| if (fgets(line, sizeof(line), fp) == NULL){ |
| E_ERROR("Premature EOF, line %d\n", lineno); |
| goto error_out; |
| } |
| lineno++; |
|
|
| if ((line[0] == 's') && (line[1] == '3') && (line[2] == '\n')) { |
| |
| for (i = 0;;) { |
| if (fgets(line, sizeof(line), fp) == NULL) { |
| E_ERROR("Premature EOF, line %d\n", lineno); |
| goto error_out; |
| } |
| lineno++; |
|
|
| if (sscanf(line, "%s%n", word, &l) != 1) { |
| E_ERROR("Header format error, line %d\n", lineno); |
| goto error_out; |
| } |
| if (strcmp(word, "endhdr") == 0) |
| break; |
| if (word[0] == '#') |
| continue; |
|
|
| if (i >= BIO_HDRARG_MAX) { |
| E_ERROR |
| ("Max arg-value limit(%d) exceeded; increase BIO_HDRARG_MAX\n", |
| BIO_HDRARG_MAX); |
| goto error_out; |
| } |
|
|
| (*argname)[i] = ckd_salloc(word); |
| if (sscanf(line + l, "%s", word) != 1) { |
| E_ERROR("Header format error, line %d\n", lineno); |
| goto error_out; |
| } |
| (*argval)[i] = ckd_salloc(word); |
| i++; |
| } |
| } |
| else { |
| |
| if (sscanf(line, "%s", word) != 1) { |
| E_ERROR("Header format error, line %d\n", lineno); |
| goto error_out; |
| } |
|
|
| (*argname)[0] = ckd_salloc("version"); |
| (*argval)[0] = ckd_salloc(word); |
| i = 1; |
|
|
| bcomment_read(fp); |
| } |
| (*argname)[i] = NULL; |
|
|
| if ((*swap = swap_check(fp)) < 0) { |
| E_ERROR("swap_check failed\n"); |
| goto error_out; |
| } |
|
|
| return 0; |
| error_out: |
| bio_hdrarg_free(*argname, *argval); |
| *argname = *argval = NULL; |
| return -1; |
| } |
|
|
|
|
| static uint32 |
| chksum_accum(const void *buf, int32 el_sz, int32 n_el, uint32 sum) |
| { |
| int32 i; |
| uint8 *i8; |
| uint16 *i16; |
| uint32 *i32; |
|
|
| switch (el_sz) { |
| case 1: |
| i8 = (uint8 *) buf; |
| for (i = 0; i < n_el; i++) |
| sum = (sum << 5 | sum >> 27) + i8[i]; |
| break; |
| case 2: |
| i16 = (uint16 *) buf; |
| for (i = 0; i < n_el; i++) |
| sum = (sum << 10 | sum >> 22) + i16[i]; |
| break; |
| case 4: |
| i32 = (uint32 *) buf; |
| for (i = 0; i < n_el; i++) |
| sum = (sum << 20 | sum >> 12) + i32[i]; |
| break; |
| default: |
| E_FATAL("Unsupported elemsize for checksum: %d\n", el_sz); |
| break; |
| } |
|
|
| return sum; |
| } |
|
|
|
|
| static void |
| swap_buf(void *buf, int32 el_sz, int32 n_el) |
| { |
| int32 i; |
| uint16 *buf16; |
| uint32 *buf32; |
|
|
| switch (el_sz) { |
| case 1: |
| break; |
| case 2: |
| buf16 = (uint16 *) buf; |
| for (i = 0; i < n_el; i++) |
| SWAP_INT16(buf16 + i); |
| break; |
| case 4: |
| buf32 = (uint32 *) buf; |
| for (i = 0; i < n_el; i++) |
| SWAP_INT32(buf32 + i); |
| break; |
| default: |
| E_FATAL("Unsupported elemsize for byteswapping: %d\n", el_sz); |
| break; |
| } |
| } |
|
|
|
|
| int32 |
| bio_fread(void *buf, int32 el_sz, int32 n_el, FILE * fp, int32 swap, |
| uint32 * chksum) |
| { |
| if (fread(buf, el_sz, n_el, fp) != (size_t) n_el) |
| return -1; |
|
|
| if (swap) |
| swap_buf(buf, el_sz, n_el); |
|
|
| if (chksum) |
| *chksum = chksum_accum(buf, el_sz, n_el, *chksum); |
|
|
| return n_el; |
| } |
|
|
| int32 |
| bio_fwrite(const void *buf, int32 el_sz, int32 n_el, FILE *fp, |
| int32 swap, uint32 *chksum) |
| { |
| if (chksum) |
| *chksum = chksum_accum(buf, el_sz, n_el, *chksum); |
| if (swap) { |
| void *nbuf; |
| int rv; |
|
|
| nbuf = ckd_calloc(n_el, el_sz); |
| memcpy(nbuf, buf, n_el * el_sz); |
| swap_buf(nbuf, el_sz, n_el); |
| rv = fwrite(nbuf, el_sz, n_el, fp); |
| ckd_free(nbuf); |
| return rv; |
| } |
| else { |
| return fwrite(buf, el_sz, n_el, fp); |
| } |
| } |
|
|
| int32 |
| bio_fread_1d(void **buf, size_t el_sz, uint32 * n_el, FILE * fp, |
| int32 sw, uint32 * ck) |
| { |
| |
| if (bio_fread(n_el, sizeof(int32), 1, fp, sw, ck) != 1) |
| E_FATAL("fread(arraysize) failed\n"); |
| if (*n_el <= 0) |
| E_FATAL("Bad arraysize: %d\n", *n_el); |
|
|
| |
| *buf = (void *) ckd_calloc(*n_el, el_sz); |
|
|
| |
| if (bio_fread(*buf, el_sz, *n_el, fp, sw, ck) != (int32)*n_el) |
| E_FATAL("fread(arraydata) failed\n"); |
|
|
| return *n_el; |
| } |
|
|
| int32 |
| bio_fread_2d(void ***arr, |
| size_t e_sz, |
| uint32 *d1, |
| uint32 *d2, |
| FILE *fp, |
| uint32 swap, |
| uint32 *chksum) |
| { |
| uint32 l_d1, l_d2; |
| uint32 n; |
| size_t ret; |
| void *raw; |
| |
| ret = bio_fread(&l_d1, sizeof(uint32), 1, fp, swap, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to read complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fread_2d"); |
| } |
| return -1; |
| } |
| ret = bio_fread(&l_d2, sizeof(uint32), 1, fp, swap, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to read complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fread_2d"); |
| } |
| return -1; |
| } |
| if (bio_fread_1d(&raw, e_sz, &n, fp, swap, chksum) != (int32)n) |
| return -1; |
|
|
| assert(n == l_d1*l_d2); |
|
|
| *d1 = l_d1; |
| *d2 = l_d2; |
| *arr = ckd_alloc_2d_ptr(l_d1, l_d2, raw, e_sz); |
|
|
| return n; |
| } |
|
|
| int32 |
| bio_fread_3d(void ****arr, |
| size_t e_sz, |
| uint32 *d1, |
| uint32 *d2, |
| uint32 *d3, |
| FILE *fp, |
| uint32 swap, |
| uint32 *chksum) |
| { |
| uint32 l_d1; |
| uint32 l_d2; |
| uint32 l_d3; |
| uint32 n; |
| void *raw; |
| size_t ret; |
|
|
| ret = bio_fread(&l_d1, sizeof(uint32), 1, fp, swap, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to read complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fread_3d"); |
| } |
| return -1; |
| } |
| ret = bio_fread(&l_d2, sizeof(uint32), 1, fp, swap, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to read complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fread_3d"); |
| } |
| return -1; |
| } |
| ret = bio_fread(&l_d3, sizeof(uint32), 1, fp, swap, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to read complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fread_3d"); |
| } |
| return -1; |
| } |
|
|
| if (bio_fread_1d(&raw, e_sz, &n, fp, swap, chksum) != (int32)n) { |
| return -1; |
| } |
|
|
| assert(n == l_d1 * l_d2 * l_d3); |
|
|
| *arr = ckd_alloc_3d_ptr(l_d1, l_d2, l_d3, raw, e_sz); |
| *d1 = l_d1; |
| *d2 = l_d2; |
| *d3 = l_d3; |
| |
| return n; |
| } |
|
|
| void |
| bio_verify_chksum(FILE * fp, int32 byteswap, uint32 chksum) |
| { |
| uint32 file_chksum; |
|
|
| if (fread(&file_chksum, sizeof(uint32), 1, fp) != 1) |
| E_FATAL("fread(chksum) failed\n"); |
| if (byteswap) |
| SWAP_INT32(&file_chksum); |
| if (file_chksum != chksum) |
| E_FATAL |
| ("Checksum error; file-checksum %08x, computed %08x\n", |
| file_chksum, chksum); |
| } |
|
|
| int |
| bio_fwrite_3d(void ***arr, |
| size_t e_sz, |
| uint32 d1, |
| uint32 d2, |
| uint32 d3, |
| FILE *fp, |
| uint32 *chksum) |
| { |
| size_t ret; |
|
|
| |
| ret = bio_fwrite(&d1, sizeof(uint32), 1, fp, 0, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to write complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fwrite_3d"); |
| } |
| return -1; |
| } |
|
|
| |
| ret = bio_fwrite(&d2, sizeof(uint32), 1, fp, 0, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to write complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fwrite_3d"); |
| } |
| return -1; |
| } |
|
|
| |
| ret = bio_fwrite(&d3, sizeof(uint32), 1, fp, 0, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to write complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fwrite_3d"); |
| } |
| return -1; |
| } |
|
|
| |
| return bio_fwrite_1d(arr[0][0], e_sz, d1 * d2 * d3, fp, chksum); |
| } |
|
|
| int |
| bio_fwrite_1d(void *arr, |
| size_t e_sz, |
| uint32 d1, |
| FILE *fp, |
| uint32 *chksum) |
| { |
| size_t ret; |
| ret = bio_fwrite(&d1, sizeof(uint32), 1, fp, 0, chksum); |
| if (ret != 1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to write complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fwrite_1d"); |
| } |
| return -1; |
| } |
|
|
| ret = bio_fwrite(arr, e_sz, d1, fp, 0, chksum); |
| if (ret != d1) { |
| if (ret == 0) { |
| E_ERROR_SYSTEM("Unable to write complete data"); |
| } |
| else { |
| E_ERROR_SYSTEM("OS error in bio_fwrite_1d"); |
| } |
|
|
| return -1; |
| } |
|
|
| return ret; |
| } |
|
|
| int16* |
| bio_read_wavfile(char const *directory, |
| char const *filename, |
| char const *extension, |
| int32 header, |
| int32 endian, |
| size_t *nsamps) |
| { |
| FILE *uttfp; |
| char *inputfile; |
| size_t n, l; |
| int16 *data; |
|
|
| (void)endian; |
| n = strlen(extension); |
| l = strlen(filename); |
| if ((n <= l) && (0 == strcmp(filename + l - n, extension))) |
| extension = ""; |
| inputfile = ckd_calloc(strlen(directory) + l + n + 2, 1); |
| if (directory) { |
| sprintf(inputfile, "%s/%s%s", directory, filename, extension); |
| } else { |
| sprintf(inputfile, "%s%s", filename, extension); |
| } |
|
|
| if ((uttfp = fopen(inputfile, "rb")) == NULL) { |
| E_FATAL_SYSTEM("Failed to open file '%s' for reading", inputfile); |
| } |
| fseek(uttfp, 0, SEEK_END); |
| n = ftell(uttfp); |
| fseek(uttfp, 0, SEEK_SET); |
| if (header > 0) { |
| if (fseek(uttfp, header, SEEK_SET) < 0) { |
| E_ERROR_SYSTEM("Failed to move to an offset %d in a file '%s'", header, inputfile); |
| fclose(uttfp); |
| ckd_free(inputfile); |
| return NULL; |
| } |
| n -= header; |
| } |
| n /= sizeof(int16); |
| data = ckd_calloc(n, sizeof(*data)); |
| if ((l = fread(data, sizeof(int16), n, uttfp)) < n) { |
| E_ERROR_SYSTEM("Failed to read %d samples from %s: %d", n, inputfile, l); |
| ckd_free(data); |
| ckd_free(inputfile); |
| fclose(uttfp); |
| return NULL; |
| } |
| ckd_free(inputfile); |
| fclose(uttfp); |
| if (nsamps) *nsamps = n; |
|
|
| return data; |
| } |
|
|