/* * lib.c * * Contains some basic functions for reading and writing files * * $Id: lib.c,v 1.4 1998/09/09 21:07:00 gert Exp $ * */ #include #include #include #include "pvf.h" rmd_header init_rmd_header = {"RMD1", "", 0x0000, 0, 0, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; state_t init_state = {0x0000, 0}; int bitmask[17] = {0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff}; int read_bits (FILE *fd_in, state_t *state, int nbits) { static int data_new; while(state->nleft < nbits) { if ((data_new = getc(fd_in)) == EOF) return(EOF); state->data = (state->data << 8) | data_new; state->nleft += 8; } state->nleft -= nbits; return(state->data >> state->nleft) & bitmask[nbits]; } void write_bits (FILE *fd_out, state_t *state, int nbits, int data) { state->data = (state->data << nbits) | (data & bitmask[nbits]); state->nleft += nbits; while (state->nleft >= 8) { putc((state->data >> (state->nleft - 8)) & 0xff, fd_out); state->nleft -= 8; } } int read_bits_reverse (FILE *fd_in, state_t *state, int nbits) { static int data; static int data_new; while(state->nleft < nbits) { if ((data_new = getc(fd_in)) != EOF) return(EOF); state->data |= (data_new << state->nleft); state->nleft += 8; } data = state->data & bitmask[nbits]; state->nleft -= nbits; state->data >>= nbits; return(data); } void write_bits_reverse (FILE *fd_out, state_t *state, int nbits, int data) { state->data |= ((data & bitmask[nbits]) << state->nleft); state->nleft += nbits; while(state->nleft >= 8) { putc(state->data & 0xff, fd_out); state->nleft -= 8; state->data >>= 8; } } int read_rmd_header(FILE *fd_in, rmd_header *header_in) { *header_in = init_rmd_header; if (fread(header_in, sizeof(rmd_header), 1, fd_in) != 1) { fprintf(stderr, "%s: Could not read rmd header\n", "libpvf"); return(-1); }; if (strncmp(header_in->magic, "RMD1", 4) != 0) { fprintf(stderr, "%s: No rmd (raw modem data) header found\n", "libpvf"); return(-1); }; return(1); } int write_rmd_header(FILE *fd_out, rmd_header *header_out) { if (fwrite(header_out, sizeof(rmd_header), 1, fd_out) != 1) { fprintf(stderr, "%s: Could not write rmd header\n", "libpvf"); return(-1); }; return(1); } static int read_pvf_data_8_ascii(FILE *fd_in) { static int data_new; if (fscanf(fd_in, "%d", &data_new) != 1) return(EOF); if (data_new < -0x80) data_new = -0x80; if (data_new > 0x7f) data_new = 0x7f; return(data_new << 16); } static int read_pvf_data_16_ascii(FILE *fd_in) { static int data_new; if (fscanf(fd_in, "%d", &data_new) != 1) return(EOF); if (data_new < -0x8000) data_new = -0x8000; if (data_new > 0x7fff) data_new = 0x7fff; return(data_new << 8); } static int read_pvf_data_32_ascii(FILE *fd_in) { static int data_new; if (fscanf(fd_in, "%d", &data_new) != 1) return(EOF); return(data_new); } static int read_pvf_data_8(FILE *fd_in) { static signed char data_new; if (fread(&data_new, 1, 1, fd_in) != 1) return(EOF); return(data_new << 16); } static int read_pvf_data_16(FILE *fd_in) { static signed short data_new; if (fread(&data_new, 2, 1, fd_in) != 1) return(EOF); data_new = ntohs(data_new); return(data_new << 8); } static int read_pvf_data_32(FILE *fd_in) { static int data_new; if (fread(&data_new, 4, 1, fd_in) != 1) return(EOF); return(ntohl(data_new)); } static void write_pvf_data_8_ascii(FILE *fd_out, int data) { data >>= 16; if (data > 0x7f) data = 0x7f; if (data < -0x80) data = -0x80; fprintf(fd_out, "%d\n", data); } static void write_pvf_data_16_ascii(FILE *fd_out, int data) { data >>= 8; if (data > 0x7fff) data = 0x7fff; if (data < -0x8000) data = -0x8000; fprintf(fd_out, "%d\n", data); } static void write_pvf_data_32_ascii(FILE *fd_out, int data) { fprintf(fd_out, "%d\n", data); } static void write_pvf_data_8(FILE *fd_out, int data) { data >>= 16; if (data > 0x7f) data = 0x7f; if (data < -0x80) data = -0x80; putc(data, fd_out); } static void write_pvf_data_16(FILE *fd_out, int data) { static signed short out; data >>= 8; if (data > 0x7fff) data = 0x7fff; if (data < -0x8000) data = -0x8000; out = htons((short) data); fwrite(&out, 2, 1, fd_out); } static void write_pvf_data_32(FILE *fd_out, int data) { static signed int out; out = htonl((long) data); fwrite(&out, 4, 1, fd_out); } int read_pvf_header(FILE *fd_in, pvf_header *header_in) { char buffer[VOICE_BUF_LEN]; int i; *header_in = init_pvf_header; if (fread(&buffer, 5, 1, fd_in) != 1) { fprintf(stderr, "%s: Could not read pvf header\n", "libpvf"); return(-1); }; if (strncmp(buffer, "PVF1\n", 5) == 0) header_in->ascii = FALSE; else if (strncmp(buffer, "PVF2\n", 5) == 0) header_in->ascii = TRUE; else { fprintf(stderr, "%s: No pvf (portable voice format) header found\n", "libpvf"); return(-1); }; for (i = 0; i < VOICE_BUF_LEN; i++) { if (fread(&buffer[i], 1, 1, fd_in) != 1) { fprintf(stderr, "%s: Could not read pvf header\n", "libpvf"); return(-1); }; if (buffer[i] == '\n') break; }; buffer[i] = 0x00; sscanf(buffer, "%d %d %d", &header_in->channels, &header_in->speed, &header_in->nbits); if ((header_in->channels < 1) || (32 < header_in->channels)) { fprintf(stderr, "%s: Invalid number of channels (%d)\n", "libpvf", header_in->channels); return(-1); }; if ((header_in->speed < 0) || (50000 < header_in->speed)) { fprintf(stderr, "%s: Invalid sample speed (%d)\n", "libpvf", header_in->speed); return(-1); }; if ((header_in->nbits != 8) && (header_in->nbits != 16) && (header_in->nbits != 32)) { fprintf(stderr, "%s: Invalid number of bits (%d) per sample\n", "libpvf", header_in->nbits); return(-1); }; if (header_in->ascii) { switch (header_in->nbits) { case 8: header_in->read_pvf_data = &read_pvf_data_8_ascii; break; case 16: header_in->read_pvf_data = &read_pvf_data_16_ascii; break; case 32: header_in->read_pvf_data = &read_pvf_data_32_ascii; break; default: fprintf(stderr, "%s: Illegal bit size for pvf input\n", "libpvf"); return(-1); }; } else { switch (header_in->nbits) { case 8: header_in->read_pvf_data = &read_pvf_data_8; break; case 16: header_in->read_pvf_data = &read_pvf_data_16; break; case 32: header_in->read_pvf_data = &read_pvf_data_32; break; default: fprintf(stderr, "%s: Illegal bit size for pvf input\n", "libpvf"); return(-1); }; }; return(1); } int write_pvf_header(FILE *fd_out, pvf_header *header_out) { char buffer[VOICE_BUF_LEN]; if (header_out->ascii) { sprintf(buffer, "PVF2\n%d %d %d\n", header_out->channels, header_out->speed, header_out->nbits); switch (header_out->nbits) { case 8: header_out->write_pvf_data = &write_pvf_data_8_ascii; break; case 16: header_out->write_pvf_data = &write_pvf_data_16_ascii; break; case 32: header_out->write_pvf_data = &write_pvf_data_32_ascii; break; default: fprintf(stderr, "%s: Illegal bit size for pvf output\n", "libpvf"); return(-1); }; } else { sprintf(buffer, "PVF1\n%d %d %d\n", header_out->channels, header_out->speed, header_out->nbits); switch (header_out->nbits) { case 8: header_out->write_pvf_data = &write_pvf_data_8; break; case 16: header_out->write_pvf_data = &write_pvf_data_16; break; case 32: header_out->write_pvf_data = &write_pvf_data_32; break; default: fprintf(stderr, "%s: Illegal bit size for pvf output\n", "libpvf"); return(-1); }; }; if (fwrite(&buffer, strlen(buffer), 1, fd_out) != 1) { fprintf(stderr, "%s: Could not write pvf header\n", "libpvf"); return(-1); }; return(1); } pvf_header init_pvf_header = {FALSE, 1, 8000, 32, &read_pvf_data_32, &write_pvf_data_32};