#include "mus-config.h" #if (defined(__GNUC__)) && (!(defined(__cplusplus))) #define _GNU_SOURCE /* this is needed to get the vasprintf declaration */ #endif #if USE_SND #include "snd.h" #endif #include #include #include #include #include #include #ifndef _MSC_VER #include #else #include #pragma warning(disable: 4244) #endif #include #include #include #include #ifdef _MSC_VER #include #endif #include #include "_sndlib.h" #if (!USE_SND) #define mus_clear_floats(Arr, Len) \ do { \ mus_long_t K; \ mus_float_t *dst; \ dst = Arr; \ for (K = Len; K > 0; K--) \ *dst++ = 0.0; \ } while (0) #define mus_copy_floats(Dst, Src, Len) \ do { \ mus_long_t K; \ mus_float_t *dst, *src; \ dst = Dst; \ src = Src; \ for (K = Len; K > 0; K--) \ *dst++ = *src++; \ } while (0) #endif #define HAVE_BYTESWAP_H __linux__ #define mus_byte_to_sample(n) (((mus_float_t)(n) / (mus_float_t)(1 << 7))) #define mus_short_to_sample(n) (((mus_float_t)(n) / (mus_float_t)(1 << 15))) #define mus_int_to_sample(n) (((mus_float_t)(n) / (mus_float_t)(1 << 23))) #define mus_int24_to_sample(n) (((mus_float_t)(n) / (mus_float_t)(1 << 23))) #define mus_sample_to_int(n) ((int)((n) * (1 << 23))) #define mus_sample_to_int24(n) ((int)((n) * (1 << 23))) #define mus_sample_to_short(n) ((short)((n) * (1 << 15))) #define mus_sample_to_byte(n) ((char)((n) * (1 << 7))) #if defined(__x86_64__) || defined(__i386__) #define bint24_to_sample(n) ((mus_float_t)(big_endian_int(jchar) >> 8) / (mus_float_t)(1 << 23)) #define int24_to_sample(n) ((mus_float_t)(little_endian_int(jchar) >> 8) / (mus_float_t)(1 << 23)) #else #define bint24_to_sample(n) ((mus_float_t)(mus_char_to_bint(jchar) >> 8) / (mus_float_t)(1 << 23)) #define int24_to_sample(n) ((mus_float_t)(mus_char_to_lint(jchar) >> 8) / (mus_float_t)(1 << 23)) #endif static mus_long_t mus_maximum_malloc = MUS_MAX_MALLOC_DEFAULT; mus_long_t mus_max_malloc(void) { return(mus_maximum_malloc); } mus_long_t mus_set_max_malloc(mus_long_t new_max) { mus_maximum_malloc = new_max; return(new_max); } static mus_long_t mus_maximum_table_size = MUS_MAX_TABLE_SIZE_DEFAULT; mus_long_t mus_max_table_size(void) { return(mus_maximum_table_size); } mus_long_t mus_set_max_table_size(mus_long_t new_max) { mus_maximum_table_size = new_max; return(new_max); } void mus_bint_to_char(unsigned char *j, int x) { unsigned char *ox = (unsigned char *)&x; #if MUS_LITTLE_ENDIAN j[0] = ox[3]; j[1] = ox[2]; j[2] = ox[1]; j[3] = ox[0]; #else memcpy((void *)j, (void *)ox, 4); #endif } int mus_char_to_bint(const unsigned char *inp) { int o; unsigned char *outp = (unsigned char *)&o; #if MUS_LITTLE_ENDIAN outp[0] = inp[3]; outp[1] = inp[2]; outp[2] = inp[1]; outp[3] = inp[0]; #else memcpy((void *)outp, (void *)inp, 4); #endif return(o); } void mus_lint_to_char(unsigned char *j, int x) { unsigned char *ox = (unsigned char *)&x; #if (!MUS_LITTLE_ENDIAN) j[0] = ox[3]; j[1] = ox[2]; j[2] = ox[1]; j[3] = ox[0]; #else memcpy((void *)j, (void *)ox, 4); #endif } int mus_char_to_lint(const unsigned char *inp) { int o; unsigned char *outp = (unsigned char *)&o; #if (!MUS_LITTLE_ENDIAN) outp[0] = inp[3]; outp[1] = inp[2]; outp[2] = inp[1]; outp[3] = inp[0]; #else memcpy((void *)outp, (void *)inp, 4); #endif return(o); } void mus_blong_to_char(unsigned char *j, mus_long_t x) { unsigned char *ox = (unsigned char *)&x; #if (!MUS_LITTLE_ENDIAN) memcpy((void *)j, (void *)ox, 8); #else j[0] = ox[7]; j[1] = ox[6]; j[2] = ox[5]; j[3] = ox[4]; j[4] = ox[3]; j[5] = ox[2]; j[6] = ox[1]; j[7] = ox[0]; #endif } mus_long_t mus_char_to_blong(const unsigned char *inp) { mus_long_t o; unsigned char *outp = (unsigned char *)&o; #if MUS_LITTLE_ENDIAN outp[0] = inp[7]; outp[1] = inp[6]; outp[2] = inp[5]; outp[3] = inp[4]; outp[4] = inp[3]; outp[5] = inp[2]; outp[6] = inp[1]; outp[7] = inp[0]; #else memcpy((void *)outp, (void *)inp, 8); #endif return(o); } void mus_llong_to_char(unsigned char *j, mus_long_t x) { unsigned char *ox = (unsigned char *)&x; #if (MUS_LITTLE_ENDIAN) memcpy((void *)j, (void *)ox, 8); #else j[0] = ox[7]; j[1] = ox[6]; j[2] = ox[5]; j[3] = ox[4]; j[4] = ox[3]; j[5] = ox[2]; j[6] = ox[1]; j[7] = ox[0]; #endif } mus_long_t mus_char_to_llong(const unsigned char *inp) { mus_long_t o; unsigned char *outp = (unsigned char *)&o; #if (!MUS_LITTLE_ENDIAN) outp[0] = inp[7]; outp[1] = inp[6]; outp[2] = inp[5]; outp[3] = inp[4]; outp[4] = inp[3]; outp[5] = inp[2]; outp[6] = inp[1]; outp[7] = inp[0]; #else memcpy((void *)outp, (void *)inp, 8); #endif return(o); } void mus_bfloat_to_char(unsigned char *j, float x) { unsigned char *ox = (unsigned char *)&x; #if MUS_LITTLE_ENDIAN j[0] = ox[3]; j[1] = ox[2]; j[2] = ox[1]; j[3] = ox[0]; #else memcpy((void *)j, (void *)ox, 4); #endif } float mus_char_to_bfloat(const unsigned char *inp) { float o; unsigned char *outp = (unsigned char *)&o; #if MUS_LITTLE_ENDIAN outp[0] = inp[3]; outp[1] = inp[2]; outp[2] = inp[1]; outp[3] = inp[0]; #else memcpy((void *)outp, (void *)inp, 4); #endif return(o); } void mus_lfloat_to_char(unsigned char *j, float x) { unsigned char *ox = (unsigned char *)&x; #if (!MUS_LITTLE_ENDIAN) j[0] = ox[3]; j[1] = ox[2]; j[2] = ox[1]; j[3] = ox[0]; #else memcpy((void *)j, (void *)ox, 4); #endif } float mus_char_to_lfloat(const unsigned char *inp) { float o; unsigned char *outp = (unsigned char *)&o; #if (!MUS_LITTLE_ENDIAN) outp[0] = inp[3]; outp[1] = inp[2]; outp[2] = inp[1]; outp[3] = inp[0]; #else memcpy((void *)outp, (void *)inp, 4); #endif return(o); } void mus_bshort_to_char(unsigned char *j, short x) { unsigned char *ox = (unsigned char *)&x; #if MUS_LITTLE_ENDIAN j[0] = ox[1]; j[1] = ox[0]; #else memcpy((void *)j, (void *)ox, 2); /* I wonder if this is faster */ #endif } short mus_char_to_bshort(const unsigned char *inp) { short o; unsigned char *outp = (unsigned char *)&o; #if MUS_LITTLE_ENDIAN outp[0] = inp[1]; outp[1] = inp[0]; #else memcpy((void *)outp, (void *)inp, 2); #endif return(o); } void mus_lshort_to_char(unsigned char *j, short x) { unsigned char *ox = (unsigned char *)&x; #if (!MUS_LITTLE_ENDIAN) j[0] = ox[1]; j[1] = ox[0]; #else memcpy((void *)j, (void *)ox, 2); #endif } short mus_char_to_lshort(const unsigned char *inp) { short o; unsigned char *outp = (unsigned char *)&o; #if (!MUS_LITTLE_ENDIAN) outp[0] = inp[1]; outp[1] = inp[0]; #else memcpy((void *)outp, (void *)inp, 2); #endif return(o); } #if ((MUS_LITTLE_ENDIAN) && (!HAVE_BYTESWAP_H)) || ((!MUS_LITTLE_ENDIAN) && (HAVE_SUN)) static void mus_ubshort_to_char(unsigned char *j, unsigned short x) { unsigned char *ox = (unsigned char *)&x; #if MUS_LITTLE_ENDIAN j[0] = ox[1]; j[1] = ox[0]; #else memcpy((void *)j, (void *)ox, 2); #endif } #endif unsigned short mus_char_to_ubshort(const unsigned char *inp) { unsigned short o; unsigned char *outp = (unsigned char *)&o; #if MUS_LITTLE_ENDIAN outp[0] = inp[1]; outp[1] = inp[0]; #else memcpy((void *)outp, (void *)inp, 2); #endif return(o); } #if (!MUS_LITTLE_ENDIAN) && (!HAVE_BYTESWAP_H) static void mus_ulshort_to_char(unsigned char *j, unsigned short x) { unsigned char *ox = (unsigned char *)&x; #if (!MUS_LITTLE_ENDIAN) j[0] = ox[1]; j[1] = ox[0]; #else memcpy((void *)j, (void *)ox, 2); #endif } #endif unsigned short mus_char_to_ulshort(const unsigned char *inp) { unsigned short o; unsigned char *outp = (unsigned char *)&o; #if (!MUS_LITTLE_ENDIAN) outp[0] = inp[1]; outp[1] = inp[0]; #else memcpy((void *)outp, (void *)inp, 2); #endif return(o); } void mus_bdouble_to_char(unsigned char *j, double x) { unsigned char *ox = (unsigned char *)&x; #if (MUS_LITTLE_ENDIAN) j[0] = ox[7]; j[1] = ox[6]; j[2] = ox[5]; j[3] = ox[4]; j[4] = ox[3]; j[5] = ox[2]; j[6] = ox[1]; j[7] = ox[0]; #else memcpy((void *)j, (void *)ox, 8); #endif } double mus_char_to_ldouble(const unsigned char *inp) { double o; unsigned char *outp = (unsigned char *)&o; #if (MUS_LITTLE_ENDIAN) memcpy((void *)outp, (void *)inp, 8); #else outp[0] = inp[7]; outp[1] = inp[6]; outp[2] = inp[5]; outp[3] = inp[4]; outp[4] = inp[3]; outp[5] = inp[2]; outp[6] = inp[1]; outp[7] = inp[0]; #endif return(o); } #if (!MUS_LITTLE_ENDIAN) static void mus_ldouble_to_char(unsigned char *j, double x) { unsigned char *ox = (unsigned char *)&x; #if (MUS_LITTLE_ENDIAN) memcpy((void *)j, (void *)ox, 8); #else j[0] = ox[7]; j[1] = ox[6]; j[2] = ox[5]; j[3] = ox[4]; j[4] = ox[3]; j[5] = ox[2]; j[6] = ox[1]; j[7] = ox[0]; #endif } #endif double mus_char_to_bdouble(const unsigned char *inp) { double o; unsigned char *outp = (unsigned char *)&o; #if (MUS_LITTLE_ENDIAN) outp[0] = inp[7]; outp[1] = inp[6]; outp[2] = inp[5]; outp[3] = inp[4]; outp[4] = inp[3]; outp[5] = inp[2]; outp[6] = inp[1]; outp[7] = inp[0]; #else memcpy((void *)outp, (void *)inp, 8); #endif return(o); } int mus_char_to_uninterpreted_int(const unsigned char *inp) { int o; unsigned char *outp = (unsigned char *)&o; memcpy((void *)outp, (void *)inp, 4); return(o); } unsigned int mus_char_to_ubint(const unsigned char *inp) { unsigned int o; unsigned char *outp = (unsigned char *)&o; #if MUS_LITTLE_ENDIAN outp[0] = inp[3]; outp[1] = inp[2]; outp[2] = inp[1]; outp[3] = inp[0]; #else memcpy((void *)outp, (void *)inp, 4); #endif return(o); } unsigned int mus_char_to_ulint(const unsigned char *inp) { unsigned int o; unsigned char *outp = (unsigned char *)&o; #if (!MUS_LITTLE_ENDIAN) outp[0] = inp[3]; outp[1] = inp[2]; outp[2] = inp[1]; outp[3] = inp[0]; #else memcpy((void *)outp, (void *)inp, 4); #endif return(o); } #if HAVE_BYTESWAP_H #include #endif #if MUS_LITTLE_ENDIAN #if HAVE_BYTESWAP_H #define big_endian_short(n) ((short)(bswap_16((*((unsigned short *)n))))) #define big_endian_int(n) ((int)(bswap_32((*((unsigned int *)n))))) #define big_endian_unsigned_short(n) ((unsigned short)(bswap_16((*((unsigned short *)n))))) #else #define big_endian_short(n) (mus_char_to_bshort(n)) #define big_endian_int(n) (mus_char_to_bint(n)) #define big_endian_unsigned_short(n) (mus_char_to_ubshort(n)) #endif #if __GNUC__ && HAVE_BYTESWAP_H /* these work, but newer versions of gcc complain about strict aliasing rules * #define big_endian_float(n) ({unsigned int x; x = bswap_32((*((unsigned int *)n))); (*((float *)&x));}) * #define big_endian_double(n) ({uint64_t x; x = bswap_64((*((uint64_t *)n))); (*((double *)&x));}) */ typedef struct {union {unsigned int i; float f;} u;} uiflt; typedef struct {union {uint64_t l; double d;} u;} uidbl; #define big_endian_float(n) ({uiflt x; x.u.i = bswap_32((*((unsigned int *)n))); x.u.f;}) #define big_endian_double(n) ({uidbl x; x.u.l = bswap_64((*((uint64_t *)n))); x.u.d;}) #else #define big_endian_float(n) (mus_char_to_bfloat(n)) #define big_endian_double(n) (mus_char_to_bdouble(n)) #endif #define little_endian_short(n) (*((short *)n)) #define little_endian_int(n) (*((int *)n)) #define little_endian_float(n) (*((float *)n)) #define little_endian_double(n) (*((double *)n)) #define little_endian_unsigned_short(n) (*((unsigned short *)n)) #if HAVE_BYTESWAP_H #define set_big_endian_short(n, x) (*((short *)n)) = ((short)(bswap_16(x))) #define set_big_endian_int(n, x) (*((int *)n)) = ((int)(bswap_32(x))) #define set_big_endian_unsigned_short(n, x) (*((unsigned short *)n)) = ((unsigned short)(bswap_16(x))) #else #define set_big_endian_short(n, x) mus_bshort_to_char(n, x) #define set_big_endian_int(n, x) mus_bint_to_char(n, x) #define set_big_endian_unsigned_short(n, x) mus_ubshort_to_char(n, x) #endif #define set_big_endian_float(n, x) mus_bfloat_to_char(n, x) #define set_big_endian_double(n, x) mus_bdouble_to_char(n, x) #define set_little_endian_short(n, x) (*((short *)n)) = x #define set_little_endian_int(n, x) (*((int *)n)) = x #define set_little_endian_float(n, x) (*((float *)n)) = x #define set_little_endian_double(n, x) (*((double *)n)) = x #define set_little_endian_unsigned_short(n, x) (*((unsigned short *)n)) = x #else #if (!HAVE_SUN) #define big_endian_short(n) (*((short *)n)) #define big_endian_int(n) (*((int *)n)) #define big_endian_float(n) (*((float *)n)) #define big_endian_double(n) (*((double *)n)) #define big_endian_unsigned_short(n) (*((unsigned short *)n)) #define set_big_endian_short(n, x) (*((short *)n)) = x #define set_big_endian_int(n, x) (*((int *)n)) = x #define set_big_endian_float(n, x) (*((float *)n)) = x #define set_big_endian_double(n, x) (*((double *)n)) = x #define set_big_endian_unsigned_short(n, x) (*((unsigned short *)n)) = x #else #define big_endian_short(n) (mus_char_to_bshort(n)) #define big_endian_int(n) (mus_char_to_bint(n)) #define big_endian_float(n) (mus_char_to_bfloat(n)) #define big_endian_double(n) (mus_char_to_bdouble(n)) #define big_endian_unsigned_short(n) (mus_char_to_ubshort(n)) #define set_big_endian_short(n, x) mus_bshort_to_char(n, x) #define set_big_endian_int(n, x) mus_bint_to_char(n, x) #define set_big_endian_float(n, x) mus_bfloat_to_char(n, x) #define set_big_endian_double(n, x) mus_bdouble_to_char(n, x) #define set_big_endian_unsigned_short(n, x) mus_ubshort_to_char(n, x) #endif #if HAVE_BYTESWAP_H #define little_endian_short(n) ((short)(bswap_16((*((unsigned short *)n))))) #define little_endian_int(n) ((int)(bswap_32((*((unsigned int *)n))))) #define little_endian_unsigned_short(n) ((unsigned short)(bswap_16((*((unsigned short *)n))))) #else #define little_endian_short(n) (mus_char_to_lshort(n)) #define little_endian_int(n) (mus_char_to_lint(n)) #define little_endian_unsigned_short(n) (mus_char_to_ulshort(n)) #endif #if __GNUC__ && HAVE_BYTESWAP_H #define little_endian_float(n) ({unsigned int x; x = bswap_32((*((unsigned int *)n))); (*((float *)&x));}) #define little_endian_double(n) ({uint64_t x; x = bswap_64((*((uint64_t *)n))); (*((double *)&x));}) #else #define little_endian_float(n) (mus_char_to_lfloat(n)) #define little_endian_double(n) (mus_char_to_ldouble(n)) #endif #if HAVE_BYTESWAP_H #define set_little_endian_short(n, x) (*((short *)n)) = ((short)(bswap_16(x))) #define set_little_endian_int(n, x) (*((int *)n)) = ((int)(bswap_32(x))) #define set_little_endian_unsigned_short(n, x) (*((unsigned short *)n)) = ((unsigned short)(bswap_16(x))) #else #define set_little_endian_short(n, x) mus_lshort_to_char(n, x) #define set_little_endian_int(n, x) mus_lint_to_char(n, x) #define set_little_endian_unsigned_short(n, x) mus_ulshort_to_char(n, x) #endif #define set_little_endian_float(n, x) mus_lfloat_to_char(n, x) #define set_little_endian_double(n, x) mus_ldouble_to_char(n, x) #endif /* ---------------- file descriptors ---------------- */ static bool clipping_default = false; bool mus_clipping(void) {return(clipping_default);} bool mus_set_clipping(bool new_value) {clipping_default = new_value; return(new_value);} typedef struct { char *name; mus_sample_t sample_type; mus_header_t header_type; int bytes_per_sample, chans; bool clipping; mus_long_t data_location; bool saved; mus_long_t framples; mus_float_t **saved_data; void *next; } io_fd; static io_fd *io_fd_free_list = NULL; static io_fd *io_fd_alloc(void) { if (io_fd_free_list) { io_fd *p; p = io_fd_free_list; io_fd_free_list = (io_fd *)(p->next); return(p); } return((io_fd *)malloc(sizeof(io_fd))); } static void io_fd_free(io_fd *p) { p->next = (void *)io_fd_free_list; io_fd_free_list = p; } static int io_fd_size = 0; static io_fd **io_fds = NULL; #define IO_FD_ALLOC_SIZE 8 int mus_file_open_descriptors(int tfd, const char *name, mus_sample_t samp_type, int size /* datum size */, mus_long_t location, int chans, mus_header_t type) { int err = MUS_NO_ERROR; if (io_fd_size == 0) { io_fd_size = tfd + IO_FD_ALLOC_SIZE; io_fds = (io_fd **)calloc(io_fd_size, sizeof(io_fd *)); } if (io_fds) { if (io_fd_size <= tfd) { int i, lim; lim = io_fd_size; io_fd_size = tfd + IO_FD_ALLOC_SIZE; io_fds = (io_fd **)realloc(io_fds, io_fd_size * sizeof(io_fd *)); for (i = lim; i < io_fd_size; i++) io_fds[i] = NULL; } if (!io_fds[tfd]) io_fds[tfd] = io_fd_alloc(); if (io_fds[tfd]) { io_fd *fd; fd = io_fds[tfd]; fd->framples = 0; fd->sample_type = samp_type; fd->bytes_per_sample = size; fd->data_location = location; fd->clipping = clipping_default; fd->header_type = type; fd->chans = chans; fd->saved = false; fd->saved_data = NULL; if (name) { int len; len = strlen(name); fd->name = (char *)malloc((len + 1) * sizeof(char)); strcpy(fd->name, name); fd->name[len] = 0; } else fd->name = NULL; } else err = MUS_MEMORY_ALLOCATION_FAILED; } else err = MUS_MEMORY_ALLOCATION_FAILED; return(err); } void scan_io_fds_for_saved_data(mus_float_t **data); void scan_io_fds_for_saved_data(mus_float_t **data) { if ((io_fds) && (io_fd_size > 0)) { int i; for (i = 0; i < io_fd_size; i++) { io_fd *fd; fd = io_fds[i]; if ((fd) && (fd->saved) && (fd->saved_data == data)) { fd->saved = false; fd->saved_data = NULL; } } } } bool mus_file_clipping(int tfd) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(false); fd = io_fds[tfd]; return(fd->clipping); } int mus_file_set_clipping(int tfd, bool clipped) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED); fd = io_fds[tfd]; fd->clipping = clipped; return(MUS_NO_ERROR); } int mus_file_set_header_type(int tfd, mus_header_t type) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED); fd = io_fds[tfd]; fd->header_type = type; return(MUS_NO_ERROR); } mus_header_t mus_file_header_type(int tfd) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(MUS_UNKNOWN_HEADER); fd = io_fds[tfd]; return(fd->header_type); } char *mus_file_fd_name(int tfd) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(NULL); fd = io_fds[tfd]; return(fd->name); } int mus_file_set_chans(int tfd, int chans) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED); fd = io_fds[tfd]; fd->chans = chans; return(MUS_NO_ERROR); } void mus_file_save_data(int tfd, mus_long_t framples, mus_float_t **data) { io_fd *fd; fd = io_fds[tfd]; if (!fd->saved) { /* fprintf(stderr, "mus_file_save_data %d\n", tfd); */ fd->saved = true; fd->framples = framples; fd->saved_data = data; } } /* ---------------- open, creat, close ---------------- */ int mus_file_open_read(const char *arg) { int fd; #if (defined(_MSC_VER) || __CYGWIN__) fd = OPEN(arg, O_RDONLY | O_BINARY, 0); #else fd = OPEN(arg, O_RDONLY, 0); #endif return(fd); } bool mus_file_probe(const char *arg) { #ifndef _MSC_VER if (!arg) return(false); return(access(arg, F_OK) == 0); #else int fd; #ifdef O_NONBLOCK fd = OPEN(arg, O_RDONLY, O_NONBLOCK); #else fd = OPEN(arg, O_RDONLY, 0); #endif if (fd == -1) return(false); CLOSE(fd, arg); return(true); #endif } int mus_file_open_write(const char *arg) { int fd; #if (defined(_MSC_VER) || __CYGWIN__) if ((fd = OPEN(arg, O_RDWR | O_BINARY, 0)) == -1) fd = CREAT(arg, S_IREAD | S_IWRITE); /* 0x0100 | 0x0080 */ #else if ((fd = OPEN(arg, O_RDWR, 0)) == -1) fd = CREAT(arg, 0666); /* equivalent to the new open(arg, O_RDWR | O_CREAT | O_TRUNC, 0666) */ #endif else lseek(fd, 0L, SEEK_END); return(fd); } int mus_file_create(const char *arg) { #if (defined(_MSC_VER ) || __CYGWIN__) return(CREAT(arg, S_IREAD | S_IWRITE)); #else return(CREAT(arg, 0666)); #endif } int mus_file_reopen_write(const char *arg) { int fd; #if (defined(_MSC_VER) || __CYGWIN__) fd = OPEN(arg, O_RDWR | O_BINARY, 0); #else fd = OPEN(arg, O_RDWR, 0); #endif return(fd); } int mus_file_close(int fd) { io_fd *fdp; #if (!USE_SND) int close_result = 0; #endif if ((!io_fds) || (fd >= io_fd_size) || (fd < 0) || (!io_fds[fd])) return(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED); fdp = io_fds[fd]; #if USE_SND CLOSE(fd, fdp->name); #else close_result = close(fd); #endif if (fdp->name) {free(fdp->name); fdp->name = NULL;} io_fd_free(fdp); io_fds[fd] = NULL; #if (!USE_SND) if (close_result < 0) return(MUS_CANT_CLOSE_FILE); #endif return(MUS_NO_ERROR); } /* ---------------- seek ---------------- */ mus_long_t mus_file_seek_frample(int tfd, mus_long_t frample) { io_fd *fd; if (!io_fds) return(mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED, "mus_file_seek_frample: no file descriptors!")); if (tfd >= io_fd_size) return(mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED, "mus_file_seek_frample: file descriptors not realloc'd? (tfd: %d, io_fd_size: %d)", tfd, io_fd_size)); if ((tfd < 0) || (!io_fds[tfd])) return(mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED, "mus_file_seek_frample: file descriptor = %d?", tfd)); fd = io_fds[tfd]; if (fd->sample_type == MUS_UNKNOWN_SAMPLE) return(mus_error(MUS_NOT_A_SOUND_FILE, "mus_file_seek_frample: invalid sample type for %s", fd->name)); return(lseek(tfd, fd->data_location + (fd->chans * frample * fd->bytes_per_sample), SEEK_SET)); } /* ---------------- mulaw/alaw conversions ---------------- * * x : input signal with max value 32767 * mu : compression parameter (mu = 255 used for telephony) * y = (32767/log(1+mu))*log(1+mu*abs(x)/32767)*sign(x); -- this isn't right -- typo? */ /* from sox g711.c */ #define QUANT_MASK (0xf) /* Quantization field mask. */ #define SEG_SHIFT (4) /* Left shift for segment number. */ static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; static int search(int val, short *table, int size) { int i; for (i = 0; i < size; i++) {if (val <= *table++) return(i);} return(size); } static unsigned char to_alaw(int pcm_val) { int mask, seg; if (pcm_val >= 0) mask = 0xD5; else {mask = 0x55; pcm_val = -pcm_val - 8;} seg = search(pcm_val, seg_end, 8); if (seg >= 8) return(0x7F ^ mask); else { unsigned char aval; aval = seg << SEG_SHIFT; if (seg < 2) aval |= (pcm_val >> 4) & QUANT_MASK; else aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; return(aval ^ mask); } } #define A_(a) mus_short_to_sample(a) static const mus_float_t mus_alaw[256] = { A_(-5504), A_(-5248), A_(-6016), A_(-5760), A_(-4480), A_(-4224), A_(-4992), A_(-4736), A_(-7552), A_(-7296), A_(-8064), A_(-7808), A_(-6528), A_(-6272), A_(-7040), A_(-6784), A_(-2752), A_(-2624), A_(-3008), A_(-2880), A_(-2240), A_(-2112), A_(-2496), A_(-2368), A_(-3776), A_(-3648), A_(-4032), A_(-3904), A_(-3264), A_(-3136), A_(-3520), A_(-3392), A_(-22016), A_(-20992), A_(-24064), A_(-23040), A_(-17920), A_(-16896), A_(-19968), A_(-18944), A_(-30208), A_(-29184), A_(-32256), A_(-31232), A_(-26112), A_(-25088), A_(-28160), A_(-27136), A_(-11008), A_(-10496), A_(-12032), A_(-11520), A_(-8960), A_(-8448), A_(-9984), A_(-9472), A_(-15104), A_(-14592), A_(-16128), A_(-15616), A_(-13056), A_(-12544), A_(-14080), A_(-13568), A_(-344), A_(-328), A_(-376), A_(-360), A_(-280), A_(-264), A_(-312), A_(-296), A_(-472), A_(-456), A_(-504), A_(-488), A_(-408), A_(-392), A_(-440), A_(-424), A_(-88), A_(-72), A_(-120), A_(-104), A_(-24), A_(-8), A_(-56), A_(-40), A_(-216), A_(-200), A_(-248), A_(-232), A_(-152), A_(-136), A_(-184), A_(-168), A_(-1376), A_(-1312), A_(-1504), A_(-1440), A_(-1120), A_(-1056), A_(-1248), A_(-1184), A_(-1888), A_(-1824), A_(-2016), A_(-1952), A_(-1632), A_(-1568), A_(-1760), A_(-1696), A_(-688), A_(-656), A_(-752), A_(-720), A_(-560), A_(-528), A_(-624), A_(-592), A_(-944), A_(-912), A_(-1008), A_(-976), A_(-816), A_(-784), A_(-880), A_(-848), A_(5504), A_(5248), A_(6016), A_(5760), A_(4480), A_(4224), A_(4992), A_(4736), A_(7552), A_(7296), A_(8064), A_(7808), A_(6528), A_(6272), A_(7040), A_(6784), A_(2752), A_(2624), A_(3008), A_(2880), A_(2240), A_(2112), A_(2496), A_(2368), A_(3776), A_(3648), A_(4032), A_(3904), A_(3264), A_(3136), A_(3520), A_(3392), A_(22016), A_(20992), A_(24064), A_(23040), A_(17920), A_(16896), A_(19968), A_(18944), A_(30208), A_(29184), A_(32256), A_(31232), A_(26112), A_(25088), A_(28160), A_(27136), A_(11008), A_(10496), A_(12032), A_(11520), A_(8960), A_(8448), A_(9984), A_(9472), A_(15104), A_(14592), A_(16128), A_(15616), A_(13056), A_(12544), A_(14080), A_(13568), A_(344), A_(328), A_(376), A_(360), A_(280), A_(264), A_(312), A_(296), A_(472), A_(456), A_(504), A_(488), A_(408), A_(392), A_(440), A_(424), A_(88), A_(72), A_(120), A_(104), A_(24), A_(8), A_(56), A_(40), A_(216), A_(200), A_(248), A_(232), A_(152), A_(136), A_(184), A_(168), A_(1376), A_(1312), A_(1504), A_(1440), A_(1120), A_(1056), A_(1248), A_(1184), A_(1888), A_(1824), A_(2016), A_(1952), A_(1632), A_(1568), A_(1760), A_(1696), A_(688), A_(656), A_(752), A_(720), A_(560), A_(528), A_(624), A_(592), A_(944), A_(912), A_(1008), A_(976), A_(816), A_(784), A_(880), A_(848) }; #define BIAS (0x84) /* Bias for linear code. */ static unsigned char to_mulaw(int pcm_val) { int mask; int seg; if (pcm_val < 0) {pcm_val = BIAS - pcm_val; mask = 0x7F;} else {pcm_val += BIAS; mask = 0xFF;} seg = search(pcm_val, seg_end, 8); if (seg >= 8) return(0x7F ^ mask); else { unsigned char uval; uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); return(uval ^ mask); } } #define MU_(a) mus_short_to_sample(a) static const mus_float_t mus_mulaw[256] = { MU_(-32124), MU_(-31100), MU_(-30076), MU_(-29052), MU_(-28028), MU_(-27004), MU_(-25980), MU_(-24956), MU_(-23932), MU_(-22908), MU_(-21884), MU_(-20860), MU_(-19836), MU_(-18812), MU_(-17788), MU_(-16764), MU_(-15996), MU_(-15484), MU_(-14972), MU_(-14460), MU_(-13948), MU_(-13436), MU_(-12924), MU_(-12412), MU_(-11900), MU_(-11388), MU_(-10876), MU_(-10364), MU_(-9852), MU_(-9340), MU_(-8828), MU_(-8316), MU_(-7932), MU_(-7676), MU_(-7420), MU_(-7164), MU_(-6908), MU_(-6652), MU_(-6396), MU_(-6140), MU_(-5884), MU_(-5628), MU_(-5372), MU_(-5116), MU_(-4860), MU_(-4604), MU_(-4348), MU_(-4092), MU_(-3900), MU_(-3772), MU_(-3644), MU_(-3516), MU_(-3388), MU_(-3260), MU_(-3132), MU_(-3004), MU_(-2876), MU_(-2748), MU_(-2620), MU_(-2492), MU_(-2364), MU_(-2236), MU_(-2108), MU_(-1980), MU_(-1884), MU_(-1820), MU_(-1756), MU_(-1692), MU_(-1628), MU_(-1564), MU_(-1500), MU_(-1436), MU_(-1372), MU_(-1308), MU_(-1244), MU_(-1180), MU_(-1116), MU_(-1052), MU_(-988), MU_(-924), MU_(-876), MU_(-844), MU_(-812), MU_(-780), MU_(-748), MU_(-716), MU_(-684), MU_(-652), MU_(-620), MU_(-588), MU_(-556), MU_(-524), MU_(-492), MU_(-460), MU_(-428), MU_(-396), MU_(-372), MU_(-356), MU_(-340), MU_(-324), MU_(-308), MU_(-292), MU_(-276), MU_(-260), MU_(-244), MU_(-228), MU_(-212), MU_(-196), MU_(-180), MU_(-164), MU_(-148), MU_(-132), MU_(-120), MU_(-112), MU_(-104), MU_(-96), MU_(-88), MU_(-80), MU_(-72), MU_(-64), MU_(-56), MU_(-48), MU_(-40), MU_(-32), MU_(-24), MU_(-16), MU_(-8), MU_(0), MU_(32124), MU_(31100), MU_(30076), MU_(29052), MU_(28028), MU_(27004), MU_(25980), MU_(24956), MU_(23932), MU_(22908), MU_(21884), MU_(20860), MU_(19836), MU_(18812), MU_(17788), MU_(16764), MU_(15996), MU_(15484), MU_(14972), MU_(14460), MU_(13948), MU_(13436), MU_(12924), MU_(12412), MU_(11900), MU_(11388), MU_(10876), MU_(10364), MU_(9852), MU_(9340), MU_(8828), MU_(8316), MU_(7932), MU_(7676), MU_(7420), MU_(7164), MU_(6908), MU_(6652), MU_(6396), MU_(6140), MU_(5884), MU_(5628), MU_(5372), MU_(5116), MU_(4860), MU_(4604), MU_(4348), MU_(4092), MU_(3900), MU_(3772), MU_(3644), MU_(3516), MU_(3388), MU_(3260), MU_(3132), MU_(3004), MU_(2876), MU_(2748), MU_(2620), MU_(2492), MU_(2364), MU_(2236), MU_(2108), MU_(1980), MU_(1884), MU_(1820), MU_(1756), MU_(1692), MU_(1628), MU_(1564), MU_(1500), MU_(1436), MU_(1372), MU_(1308), MU_(1244), MU_(1180), MU_(1116), MU_(1052), MU_(988), MU_(924), MU_(876), MU_(844), MU_(812), MU_(780), MU_(748), MU_(716), MU_(684), MU_(652), MU_(620), MU_(588), MU_(556), MU_(524), MU_(492), MU_(460), MU_(428), MU_(396), MU_(372), MU_(356), MU_(340), MU_(324), MU_(308), MU_(292), MU_(276), MU_(260), MU_(244), MU_(228), MU_(212), MU_(196), MU_(180), MU_(164), MU_(148), MU_(132), MU_(120), MU_(112), MU_(104), MU_(96), MU_(88), MU_(80), MU_(72), MU_(64), MU_(56), MU_(48), MU_(40), MU_(32), MU_(24), MU_(16), MU_(8), MU_(0) }; #define B_(a) mus_byte_to_sample(a) static const mus_float_t mus_byte[256] = { B_(0), B_(1), B_(2), B_(3), B_(4), B_(5), B_(6), B_(7), B_(8), B_(9), B_(10), B_(11), B_(12), B_(13), B_(14), B_(15), B_(16), B_(17), B_(18), B_(19), B_(20), B_(21), B_(22), B_(23), B_(24), B_(25), B_(26), B_(27), B_(28), B_(29), B_(30), B_(31), B_(32), B_(33), B_(34), B_(35), B_(36), B_(37), B_(38), B_(39), B_(40), B_(41), B_(42), B_(43), B_(44), B_(45), B_(46), B_(47), B_(48), B_(49), B_(50), B_(51), B_(52), B_(53), B_(54), B_(55), B_(56), B_(57), B_(58), B_(59), B_(60), B_(61), B_(62), B_(63), B_(64), B_(65), B_(66), B_(67), B_(68), B_(69), B_(70), B_(71), B_(72), B_(73), B_(74), B_(75), B_(76), B_(77), B_(78), B_(79), B_(80), B_(81), B_(82), B_(83), B_(84), B_(85), B_(86), B_(87), B_(88), B_(89), B_(90), B_(91), B_(92), B_(93), B_(94), B_(95), B_(96), B_(97), B_(98), B_(99), B_(100), B_(101), B_(102), B_(103), B_(104), B_(105), B_(106), B_(107), B_(108), B_(109), B_(110), B_(111), B_(112), B_(113), B_(114), B_(115), B_(116), B_(117), B_(118), B_(119), B_(120), B_(121), B_(122), B_(123), B_(124), B_(125), B_(126), B_(127), B_(-128), B_(-127), B_(-126), B_(-125), B_(-124), B_(-123), B_(-122), B_(-121), B_(-120), B_(-119), B_(-118), B_(-117), B_(-116), B_(-115), B_(-114), B_(-113), B_(-112), B_(-111), B_(-110), B_(-109), B_(-108), B_(-107), B_(-106), B_(-105), B_(-104), B_(-103), B_(-102), B_(-101), B_(-100), B_(-99), B_(-98), B_(-97), B_(-96), B_(-95), B_(-94), B_(-93), B_(-92), B_(-91), B_(-90), B_(-89), B_(-88), B_(-87), B_(-86), B_(-85), B_(-84), B_(-83), B_(-82), B_(-81), B_(-80), B_(-79), B_(-78), B_(-77), B_(-76), B_(-75), B_(-74), B_(-73), B_(-72), B_(-71), B_(-70), B_(-69), B_(-68), B_(-67), B_(-66), B_(-65), B_(-64), B_(-63), B_(-62), B_(-61), B_(-60), B_(-59), B_(-58), B_(-57), B_(-56), B_(-55), B_(-54), B_(-53), B_(-52), B_(-51), B_(-50), B_(-49), B_(-48), B_(-47), B_(-46), B_(-45), B_(-44), B_(-43), B_(-42), B_(-41), B_(-40), B_(-39), B_(-38), B_(-37), B_(-36), B_(-35), B_(-34), B_(-33), B_(-32), B_(-31), B_(-30), B_(-29), B_(-28), B_(-27), B_(-26), B_(-25), B_(-24), B_(-23), B_(-22), B_(-21), B_(-20), B_(-19), B_(-18), B_(-17), B_(-16), B_(-15), B_(-14), B_(-13), B_(-12), B_(-11), B_(-10), B_(-9), B_(-8), B_(-7), B_(-6), B_(-5), B_(-4), B_(-3), B_(-2), B_(-1) }; #define UB_(a) mus_byte_to_sample(a) static const mus_float_t mus_ubyte[256] = { UB_(-128), UB_(-127), UB_(-126), UB_(-125), UB_(-124), UB_(-123), UB_(-122), UB_(-121), UB_(-120), UB_(-119), UB_(-118), UB_(-117), UB_(-116), UB_(-115), UB_(-114), UB_(-113), UB_(-112), UB_(-111), UB_(-110), UB_(-109), UB_(-108), UB_(-107), UB_(-106), UB_(-105), UB_(-104), UB_(-103), UB_(-102), UB_(-101), UB_(-100), UB_(-99), UB_(-98), UB_(-97), UB_(-96), UB_(-95), UB_(-94), UB_(-93), UB_(-92), UB_(-91), UB_(-90), UB_(-89), UB_(-88), UB_(-87), UB_(-86), UB_(-85), UB_(-84), UB_(-83), UB_(-82), UB_(-81), UB_(-80), UB_(-79), UB_(-78), UB_(-77), UB_(-76), UB_(-75), UB_(-74), UB_(-73), UB_(-72), UB_(-71), UB_(-70), UB_(-69), UB_(-68), UB_(-67), UB_(-66), UB_(-65), UB_(-64), UB_(-63), UB_(-62), UB_(-61), UB_(-60), UB_(-59), UB_(-58), UB_(-57), UB_(-56), UB_(-55), UB_(-54), UB_(-53), UB_(-52), UB_(-51), UB_(-50), UB_(-49), UB_(-48), UB_(-47), UB_(-46), UB_(-45), UB_(-44), UB_(-43), UB_(-42), UB_(-41), UB_(-40), UB_(-39), UB_(-38), UB_(-37), UB_(-36), UB_(-35), UB_(-34), UB_(-33), UB_(-32), UB_(-31), UB_(-30), UB_(-29), UB_(-28), UB_(-27), UB_(-26), UB_(-25), UB_(-24), UB_(-23), UB_(-22), UB_(-21), UB_(-20), UB_(-19), UB_(-18), UB_(-17), UB_(-16), UB_(-15), UB_(-14), UB_(-13), UB_(-12), UB_(-11), UB_(-10), UB_(-9), UB_(-8), UB_(-7), UB_(-6), UB_(-5), UB_(-4), UB_(-3), UB_(-2), UB_(-1), UB_(0), UB_(1), UB_(2), UB_(3), UB_(4), UB_(5), UB_(6), UB_(7), UB_(8), UB_(9), UB_(10), UB_(11), UB_(12), UB_(13), UB_(14), UB_(15), UB_(16), UB_(17), UB_(18), UB_(19), UB_(20), UB_(21), UB_(22), UB_(23), UB_(24), UB_(25), UB_(26), UB_(27), UB_(28), UB_(29), UB_(30), UB_(31), UB_(32), UB_(33), UB_(34), UB_(35), UB_(36), UB_(37), UB_(38), UB_(39), UB_(40), UB_(41), UB_(42), UB_(43), UB_(44), UB_(45), UB_(46), UB_(47), UB_(48), UB_(49), UB_(50), UB_(51), UB_(52), UB_(53), UB_(54), UB_(55), UB_(56), UB_(57), UB_(58), UB_(59), UB_(60), UB_(61), UB_(62), UB_(63), UB_(64), UB_(65), UB_(66), UB_(67), UB_(68), UB_(69), UB_(70), UB_(71), UB_(72), UB_(73), UB_(74), UB_(75), UB_(76), UB_(77), UB_(78), UB_(79), UB_(80), UB_(81), UB_(82), UB_(83), UB_(84), UB_(85), UB_(86), UB_(87), UB_(88), UB_(89), UB_(90), UB_(91), UB_(92), UB_(93), UB_(94), UB_(95), UB_(96), UB_(97), UB_(98), UB_(99), UB_(100), UB_(101), UB_(102), UB_(103), UB_(104), UB_(105), UB_(106), UB_(107), UB_(108), UB_(109), UB_(110), UB_(111), UB_(112), UB_(113), UB_(114), UB_(115), UB_(116), UB_(117), UB_(118), UB_(119), UB_(120), UB_(121), UB_(122), UB_(123), UB_(124), UB_(125), UB_(126), UB_(127) }; /* ---------------- read ---------------- */ #define BUFLIM (64 * 1024) #define UBYTE_ZERO 128 #define USHORT_ZERO 32768 #define MUS_SAMPLE_UNSCALED(n) (((mus_float_t)n) / 32768.0) /* see note in _sndlib.h" values are "unscaled" from the DAC's point of view */ static mus_float_t *swapped_shorts = NULL; static void initialize_swapped_shorts(void) { int i; swapped_shorts = (mus_float_t *)malloc(65536 * sizeof(mus_float_t)); for (i = 0; i < 65536; i++) { signed short x; x = (signed short)(((i >> 8) & 0xff) | ((i & 0xff) << 8)); swapped_shorts[i] = mus_short_to_sample(x); } } static mus_long_t mus_read_any_1(int tfd, mus_long_t beg, int chans, mus_long_t nints, mus_float_t **bufs, mus_float_t **cm, char *inbuf) { /* beg no longer means buffer-relative start point (that is assumed to be 0): changed 18-Dec-13 * beg is now the starting frample number in the file data (first frample = 0) * so old form * mus_read_any_1(f, 0, ...) * is now * mus_read_any_1(f, frample, ...) */ mus_sample_t samp_type; int siz, siz_chans; mus_long_t bytes, lim, leftover, total_read, k, loc, buflim; unsigned char *jchar; static char *ur_charbuf = NULL; char *charbuf = NULL; mus_float_t *buffer; if (nints <= 0) return(0); if (!inbuf) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED, "mus_read: no file descriptors!")); fd = io_fds[tfd]; if (fd->sample_type == MUS_UNKNOWN_SAMPLE) return(mus_error(MUS_FILE_CLOSED, "mus_read: invalid sample type for %s", fd->name)); samp_type = fd->sample_type; siz = fd->bytes_per_sample; if ((samp_type == MUS_OUT_SAMPLE_TYPE) && (chans == 1)) /* (beg == 0)) */ { ssize_t total; bytes = nints * siz; total = read(tfd, (char *)(bufs[0]), bytes); if (total != bytes) { if (total <= 0) memset((void *)(bufs[0]), 0, bytes); else { int i; for (i = total / siz; i < nints; i++) bufs[0][i] = 0.0; } } return(total / siz); } if (fd->saved) { lim = nints; if (lim > fd->framples) lim = fd->framples; bytes = lim * sizeof(mus_float_t); if (beg < 0) beg = 0; if ((chans == 1) && ((!cm) || (cm[0]))) { buffer = (mus_float_t *)(bufs[0]); if (buffer) { mus_copy_floats(buffer, fd->saved_data[0] + beg, lim); if (lim < nints) mus_clear_floats(buffer + lim, nints - lim); } } else { for (k = 0; k < chans; k++) if ((!cm) || (cm[k])) { buffer = (mus_float_t *)(bufs[k]); if (buffer) { mus_copy_floats(buffer, fd->saved_data[k] + beg, lim); if (lim < nints) mus_clear_floats(buffer + lim, nints - lim); } } } return(lim); } if (!ur_charbuf) ur_charbuf = (char *)malloc(BUFLIM * sizeof(char)); charbuf = ur_charbuf; } else { charbuf = inbuf; siz = mus_bytes_per_sample((mus_sample_t)tfd); samp_type = (mus_sample_t)tfd; } siz_chans = siz * chans; leftover = (nints * siz_chans); k = (BUFLIM) % siz_chans; /* both are ints */ if (k != 0) /* for example, 3 channel output of 1-byte (mulaw) samples will need a mod 3 buffer */ buflim = (BUFLIM) - k; else buflim = BUFLIM; total_read = 0; loc = 0; #if MUS_LITTLE_ENDIAN if ((samp_type == MUS_BSHORT) && (!swapped_shorts)) initialize_swapped_shorts(); #else if ((samp_type == MUS_LSHORT) && (!swapped_shorts)) initialize_swapped_shorts(); #endif while (leftover > 0) { mus_long_t oldloc, loclim; mus_float_t *bufnow, *bufend, *bufend4; bytes = leftover; if (bytes > buflim) { leftover = (bytes - buflim); bytes = buflim; } else leftover = 0; if (!inbuf) { ssize_t total; total = read(tfd, charbuf, bytes); if (total <= 0) { /* zero out trailing section (some callers don't check the returned value) -- this added 9-May-99 */ if (loc < nints) for (k = 0; k < chans; k++) if ((!cm) || (cm[k])) { mus_float_t *p; p = bufs[k]; mus_clear_floats(p + loc, nints - loc); } return(total_read); } lim = (int) (total / siz_chans); /* this divide must be exact (hence the buflim calc above) */ } else { lim = nints; /* framples in this case */ leftover = 0; } total_read += lim; oldloc = loc; if ((chans == 1) && ((!cm) || (cm[0]))) { buffer = (mus_float_t *)(bufs[0]); if (buffer) { loc = oldloc; loclim = loc + lim; bufnow = (mus_float_t *)(buffer + loc); bufend = (mus_float_t *)(buffer + loclim - 1); bufend4 = (mus_float_t *)(bufend - 4); jchar = (unsigned char *)charbuf; switch (samp_type) { case MUS_BSHORT: #if MUS_LITTLE_ENDIAN while (bufnow <= bufend4) { (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; jchar += 2; (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; jchar += 2; (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; jchar += 2; (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; jchar += 2; } for (; bufnow <= bufend; jchar += 2) /* unsigned short here as charbuf loc is slower */ (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; /* bswap16 is much slower here because of the subsequent short->double conversion */ #else for (; bufnow <= bufend; jchar += 2) (*bufnow++) = mus_short_to_sample(big_endian_short(jchar)); #endif break; case MUS_LSHORT: #if (!MUS_LITTLE_ENDIAN) for (; bufnow <= bufend; jchar += 2) (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; #else while (bufnow <= bufend4) { (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); jchar += 2; (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); jchar += 2; (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); jchar += 2; (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); jchar += 2; } for (; bufnow <= bufend; jchar += 2) (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); #endif break; case MUS_BINT: while (bufnow <= bufend4) { (*bufnow++) = mus_int_to_sample(big_endian_int(jchar)); jchar += 4; (*bufnow++) = mus_int_to_sample(big_endian_int(jchar)); jchar += 4; (*bufnow++) = mus_int_to_sample(big_endian_int(jchar)); jchar += 4; (*bufnow++) = mus_int_to_sample(big_endian_int(jchar)); jchar += 4; } for (; bufnow <= bufend; jchar += 4) (*bufnow++) = mus_int_to_sample(big_endian_int(jchar)); break; case MUS_LINT: while (bufnow <= bufend4) { (*bufnow++) = mus_int_to_sample(little_endian_int(jchar)); jchar += 4; (*bufnow++) = mus_int_to_sample(little_endian_int(jchar)); jchar += 4; (*bufnow++) = mus_int_to_sample(little_endian_int(jchar)); jchar += 4; (*bufnow++) = mus_int_to_sample(little_endian_int(jchar)); jchar += 4; } for (; bufnow <= bufend; jchar += 4) (*bufnow++) = mus_int_to_sample(little_endian_int(jchar)); break; case MUS_BINTN: for (; bufnow <= bufend; jchar += 4) (*bufnow++) = mus_int_to_sample((big_endian_int(jchar) >> 8)); break; case MUS_LINTN: for (; bufnow <= bufend; jchar += 4) (*bufnow++) = mus_int_to_sample((little_endian_int(jchar) >> 8)); break; case MUS_MULAW: while (bufnow <= bufend4) { (*bufnow++) = mus_mulaw[*jchar++]; (*bufnow++) = mus_mulaw[*jchar++]; (*bufnow++) = mus_mulaw[*jchar++]; (*bufnow++) = mus_mulaw[*jchar++]; } for (; bufnow <= bufend; jchar++) (*bufnow++) = mus_mulaw[*jchar]; break; case MUS_ALAW: while (bufnow <= bufend4) { (*bufnow++) = mus_alaw[*jchar++]; (*bufnow++) = mus_alaw[*jchar++]; (*bufnow++) = mus_alaw[*jchar++]; (*bufnow++) = mus_alaw[*jchar++]; } for (; bufnow <= bufend; jchar++) (*bufnow++) = mus_alaw[*jchar]; break; case MUS_BYTE: while (bufnow <= bufend4) { (*bufnow++) = mus_byte[(unsigned char)(*jchar++)]; (*bufnow++) = mus_byte[(unsigned char)(*jchar++)]; (*bufnow++) = mus_byte[(unsigned char)(*jchar++)]; (*bufnow++) = mus_byte[(unsigned char)(*jchar++)]; } for (; bufnow <= bufend; jchar++) (*bufnow++) = mus_byte[(unsigned char)(*jchar)]; break; case MUS_UBYTE: while (bufnow <= bufend4) { (*bufnow++) = mus_ubyte[(unsigned char)(*jchar++)]; (*bufnow++) = mus_ubyte[(unsigned char)(*jchar++)]; (*bufnow++) = mus_ubyte[(unsigned char)(*jchar++)]; (*bufnow++) = mus_ubyte[(unsigned char)(*jchar++)]; } for (; bufnow <= bufend; jchar++) (*bufnow++) = mus_ubyte[(unsigned char)(*jchar)]; break; case MUS_BFLOAT: while (bufnow <= bufend4) { (*bufnow++) = (mus_float_t)(big_endian_float(jchar)); jchar += 4; (*bufnow++) = (mus_float_t)(big_endian_float(jchar)); jchar += 4; (*bufnow++) = (mus_float_t)(big_endian_float(jchar)); jchar += 4; (*bufnow++) = (mus_float_t)(big_endian_float(jchar)); jchar += 4; } for (; bufnow <= bufend; jchar += 4) (*bufnow++) = (mus_float_t)(big_endian_float(jchar)); break; case MUS_BFLOAT_UNSCALED: for (; bufnow <= bufend; jchar += 4) (*bufnow++) = (mus_float_t)(MUS_SAMPLE_UNSCALED(big_endian_float(jchar))); break; case MUS_BDOUBLE: while (bufnow <= bufend4) { (*bufnow++) = (mus_float_t)(big_endian_double(jchar)); jchar += 8; (*bufnow++) = (mus_float_t)(big_endian_double(jchar)); jchar += 8; (*bufnow++) = (mus_float_t)(big_endian_double(jchar)); jchar += 8; (*bufnow++) = (mus_float_t)(big_endian_double(jchar)); jchar += 8; } for (; bufnow <= bufend; jchar += 8) (*bufnow++) = (mus_float_t)(big_endian_double(jchar)); break; case MUS_BDOUBLE_UNSCALED: for (; bufnow <= bufend; jchar += 8) (*bufnow++) = (mus_float_t)(MUS_SAMPLE_UNSCALED(big_endian_double(jchar))); break; case MUS_LFLOAT: while (bufnow <= bufend4) { (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); jchar += 4; (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); jchar += 4; (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); jchar += 4; (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); jchar += 4; } for (; bufnow <= bufend; jchar += 4) (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); break; case MUS_LFLOAT_UNSCALED: for (; bufnow <= bufend; jchar += 4) (*bufnow++) = (mus_float_t)(MUS_SAMPLE_UNSCALED(little_endian_float(jchar))); break; case MUS_LDOUBLE: for (; bufnow <= bufend; jchar += 8) (*bufnow++) = (mus_float_t)(little_endian_double(jchar)); break; case MUS_LDOUBLE_UNSCALED: for (; bufnow <= bufend; jchar += 8) (*bufnow++) = (mus_float_t)(MUS_SAMPLE_UNSCALED(little_endian_double(jchar))); break; case MUS_UBSHORT: while (bufnow <= bufend4) { (*bufnow++) = mus_short_to_sample((int)(big_endian_unsigned_short(jchar)) - USHORT_ZERO); jchar += 2; (*bufnow++) = mus_short_to_sample((int)(big_endian_unsigned_short(jchar)) - USHORT_ZERO); jchar += 2; (*bufnow++) = mus_short_to_sample((int)(big_endian_unsigned_short(jchar)) - USHORT_ZERO); jchar += 2; (*bufnow++) = mus_short_to_sample((int)(big_endian_unsigned_short(jchar)) - USHORT_ZERO); jchar += 2; } for (; bufnow <= bufend; jchar += 2) (*bufnow++) = mus_short_to_sample((int)(big_endian_unsigned_short(jchar)) - USHORT_ZERO); break; case MUS_ULSHORT: while (bufnow <= bufend4) { (*bufnow++) = mus_short_to_sample((int)(little_endian_unsigned_short(jchar)) - USHORT_ZERO); jchar += 2; (*bufnow++) = mus_short_to_sample((int)(little_endian_unsigned_short(jchar)) - USHORT_ZERO); jchar += 2; (*bufnow++) = mus_short_to_sample((int)(little_endian_unsigned_short(jchar)) - USHORT_ZERO); jchar += 2; (*bufnow++) = mus_short_to_sample((int)(little_endian_unsigned_short(jchar)) - USHORT_ZERO); jchar += 2; } for (; bufnow <= bufend; jchar += 2) (*bufnow++) = mus_short_to_sample((int)(little_endian_unsigned_short(jchar)) - USHORT_ZERO); break; case MUS_B24INT: while (bufnow <= bufend4) { (*bufnow++) = bint24_to_sample(jchar); jchar += 3; (*bufnow++) = bint24_to_sample(jchar); jchar += 3; (*bufnow++) = bint24_to_sample(jchar); jchar += 3; (*bufnow++) = bint24_to_sample(jchar); jchar += 3; } for (; bufnow <= bufend; jchar += 3) (*bufnow++) = bint24_to_sample(jchar); break; case MUS_L24INT: { int val; val = (jchar[2] << 16) + (jchar[1] << 8) + jchar[0]; if (val >= (1 << 23)) val -= (1 << 24); (*bufnow++) = mus_int24_to_sample(val); jchar += 2; } while (bufnow <= bufend4) { (*bufnow++) = int24_to_sample(jchar); jchar += 3; (*bufnow++) = int24_to_sample(jchar); jchar += 3; (*bufnow++) = int24_to_sample(jchar); jchar += 3; (*bufnow++) = int24_to_sample(jchar); jchar += 3; } for (; bufnow <= bufend; jchar += 3) (*bufnow++) = int24_to_sample(jchar); break; default: break; } loc = loclim; } } else { for (k = 0; k < chans; k++) { if ((!cm) || (cm[k])) { buffer = (mus_float_t *)(bufs[k]); if (buffer) { loc = oldloc; loclim = loc + lim; bufnow = (mus_float_t *)(buffer + loc); bufend = (mus_float_t *)(buffer + loclim - 1); bufend4 = (mus_float_t *)(bufend - 4); jchar = (unsigned char *)charbuf; jchar += (k * siz); switch (samp_type) { case MUS_BSHORT: #if MUS_LITTLE_ENDIAN while (bufnow <= bufend4) { (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; jchar += siz_chans; (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; jchar += siz_chans; (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; jchar += siz_chans; (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; jchar += siz_chans; } for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; #else for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_short_to_sample(big_endian_short(jchar)); #endif break; case MUS_LSHORT: #if (!MUS_LITTLE_ENDIAN) for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = swapped_shorts[(*((unsigned short *)jchar))]; #else while (bufnow <= bufend4) { (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); jchar += siz_chans; (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); jchar += siz_chans; (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); jchar += siz_chans; (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); jchar += siz_chans; } for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_short_to_sample(little_endian_short(jchar)); #endif break; case MUS_BINT: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_int_to_sample(big_endian_int(jchar)); break; case MUS_LINT: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_int_to_sample(little_endian_int(jchar)); break; case MUS_BINTN: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_int_to_sample((big_endian_int(jchar) >> 8)); break; case MUS_LINTN: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_int_to_sample((little_endian_int(jchar) >> 8)); break; case MUS_MULAW: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_mulaw[*jchar]; break; case MUS_ALAW: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_alaw[*jchar]; break; case MUS_BYTE: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_byte[(unsigned char)(*jchar)]; break; case MUS_UBYTE: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_ubyte[(unsigned char)(*jchar)]; break; case MUS_BFLOAT: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = (mus_float_t)(big_endian_float(jchar)); break; case MUS_BFLOAT_UNSCALED: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = (mus_float_t)(MUS_SAMPLE_UNSCALED(big_endian_float(jchar))); break; case MUS_BDOUBLE: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = (mus_float_t)(big_endian_double(jchar)); break; case MUS_BDOUBLE_UNSCALED: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = (mus_float_t)(MUS_SAMPLE_UNSCALED(big_endian_double(jchar))); break; case MUS_LFLOAT: while (bufnow <= bufend4) { (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); jchar += siz_chans; (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); jchar += siz_chans; (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); jchar += siz_chans; (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); jchar += siz_chans; } for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = (mus_float_t)(little_endian_float(jchar)); break; case MUS_LFLOAT_UNSCALED: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = (mus_float_t)(MUS_SAMPLE_UNSCALED(little_endian_float(jchar))); break; case MUS_LDOUBLE: while (bufnow <= bufend4) { (*bufnow++) = (mus_float_t)(little_endian_double(jchar)); jchar += siz_chans; (*bufnow++) = (mus_float_t)(little_endian_double(jchar)); jchar += siz_chans; (*bufnow++) = (mus_float_t)(little_endian_double(jchar)); jchar += siz_chans; (*bufnow++) = (mus_float_t)(little_endian_double(jchar)); jchar += siz_chans; } for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = (mus_float_t)(little_endian_double(jchar)); break; case MUS_LDOUBLE_UNSCALED: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = (mus_float_t)(MUS_SAMPLE_UNSCALED(little_endian_double(jchar))); break; case MUS_UBSHORT: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_short_to_sample((int)(big_endian_unsigned_short(jchar)) - USHORT_ZERO); break; case MUS_ULSHORT: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = mus_short_to_sample((int)(little_endian_unsigned_short(jchar)) - USHORT_ZERO); break; case MUS_B24INT: for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = bint24_to_sample(jchar); break; case MUS_L24INT: { /*align for little_endian_int as above */ int val; val = (jchar[2] << 16) + (jchar[1] << 8) + jchar[0]; if (val >= (1 << 23)) val -= (1 << 24); (*bufnow++) = mus_int24_to_sample(val); jchar += siz_chans - 1; } for (; bufnow <= bufend; jchar += siz_chans) (*bufnow++) = int24_to_sample(jchar); break; default: break; } loc = loclim; } } } } } return(total_read); } mus_long_t mus_file_read_any(int tfd, mus_long_t beg, int chans, mus_long_t nints, mus_float_t **bufs, mus_float_t **cm) { return(mus_read_any_1(tfd, beg, chans, nints, bufs, cm, NULL)); } mus_long_t mus_file_read_file(int tfd, mus_long_t beg, int chans, mus_long_t nints, mus_float_t **bufs) { /* not currently used anywhere */ return(mus_read_any_1(tfd, beg, chans, nints, bufs, NULL, NULL)); } mus_long_t mus_file_read_buffer(int charbuf_sample_type, mus_long_t beg, int chans, mus_long_t nints, mus_float_t **bufs, char *charbuf) { return(mus_read_any_1(charbuf_sample_type, beg, chans, nints, bufs, NULL, charbuf)); } /* the next two were changed 19-Dec-13 (sndlib.h version 23.1) * "end" is now actually "dur" -- the number of samples to read, not the end point in the buffer * "beg" is the frample number to start at in the data, not the buffer location * so old form * mus_file_read(f, 0, 99...) * is now * mus_file_read(f, frample, 100...) */ mus_long_t mus_file_read(int tfd, mus_long_t beg, mus_long_t num, int chans, mus_float_t **bufs) { mus_long_t rtn; rtn = mus_read_any_1(tfd, beg, chans, num, bufs, NULL, NULL); if (rtn == MUS_ERROR) return(MUS_ERROR); if (rtn < num) { mus_long_t k; /* this zeroing can be fooled if the file is chunked and has trailing, non-data chunks */ for (k = 0; k < chans; k++) { mus_float_t *buffer; buffer = bufs[k]; /* this happens routinely in mus_outa + initial write (reads ahead in effect) */ /* fprintf(stderr, "clear from %" PRId64 " for %" PRId64 "\n", rtn, num-rtn); */ mus_clear_floats(buffer + rtn, num - rtn); } } return(num); } mus_long_t mus_file_read_chans(int tfd, mus_long_t beg, mus_long_t num, int chans, mus_float_t **bufs, mus_float_t **cm) { /* an optimization of mus_file_read -- just reads the desired channels */ mus_long_t rtn; rtn = mus_read_any_1(tfd, beg, chans, num, bufs, cm, NULL); if (rtn == MUS_ERROR) return(MUS_ERROR); if (rtn < num) { mus_long_t k; for (k = 0; k < chans; k++) if ((!cm) || (cm[k])) { mus_float_t *buffer; buffer = bufs[k]; mus_clear_floats(buffer + rtn, num - rtn); } } return(num); } /* ---------------- write ---------------- */ static int checked_write(int tfd, char *buf, mus_long_t chars) { int64_t bytes; bytes = (int64_t)write(tfd, buf, chars); if (bytes != chars) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED, "mus_write: no file descriptors!")); fd = io_fds[tfd]; if (fd->sample_type == MUS_UNKNOWN_SAMPLE) return(mus_error(MUS_FILE_CLOSED, "attempt to write closed file %s", fd->name)); else return(mus_error(MUS_WRITE_ERROR, "mus_write: write error for %s%s%s: only %" PRId64 " of %" PRId64 " bytes written", fd->name, (errno) ? ": " : "", (errno) ? STRERROR(errno) : "", bytes, chars)); } return(MUS_NO_ERROR); } static mus_clip_handler_t *mus_clip_handler = NULL; static bool (*clip_checker)(void) = NULL; mus_clip_handler_t *mus_clip_set_handler(mus_clip_handler_t *new_clip_handler) { mus_clip_handler_t *old_handler; old_handler = mus_clip_handler; mus_clip_handler = new_clip_handler; return(old_handler); } mus_clip_handler_t *mus_clip_set_handler_and_checker(mus_clip_handler_t *new_clip_handler, bool (*checker)(void)) { mus_clip_handler_t *old_handler; old_handler = mus_clip_handler; mus_clip_handler = new_clip_handler; clip_checker = checker; return(old_handler); } static int mus_write_1(int tfd, mus_long_t beg, mus_long_t end, int chans, mus_float_t **bufs, char *inbuf, bool clipped) { int err, siz, siz_chans, val; mus_sample_t sample_type; mus_long_t bytes, k, lim, leftover, loc, buflim; bool clipping = false; unsigned char *jchar; static char *ur_charbuf = NULL; char *charbuf = NULL; mus_float_t *buffer; if (chans <= 0) return(MUS_NO_ERROR); /* ?? */ if (!inbuf) { io_fd *fd; if ((!io_fds) || (tfd >= io_fd_size) || (tfd < 0) || (!io_fds[tfd])) return(mus_error(MUS_FILE_DESCRIPTORS_NOT_INITIALIZED, "mus_write: no file descriptors!")); fd = io_fds[tfd]; if (fd->sample_type == MUS_UNKNOWN_SAMPLE) return(mus_error(MUS_FILE_CLOSED, "mus_write: invalid sample type for %s", fd->name)); siz = fd->bytes_per_sample; sample_type = fd->sample_type; clipping = fd->clipping; if ((sample_type == MUS_OUT_SAMPLE_TYPE) && (chans == 1) && (!clipping) && (beg == 0)) { bytes = (end + 1) * siz; return(checked_write(tfd, (char *)(bufs[0]), bytes)); } } else { siz = mus_bytes_per_sample((mus_sample_t)tfd); sample_type = (mus_sample_t)tfd; /* in this case, tfd is the sample type (see mus_file_write_buffer below) -- this should be changed! */ clipping = clipped; } lim = (end - beg + 1); siz_chans = siz * chans; leftover = lim * siz_chans; k = (BUFLIM) % siz_chans; if (k != 0) buflim = (BUFLIM) - k; else buflim = BUFLIM; loc = beg; if (inbuf) charbuf = inbuf; while (leftover > 0) { int oldloc; bytes = leftover; if (bytes > buflim) { leftover = (bytes - buflim); bytes = buflim; } else leftover = 0; lim = (int)(bytes / siz_chans); /* see note above */ oldloc = loc; for (k = 0; k < chans; k++) { mus_long_t loclim; mus_float_t *bufnow, *bufend, *bufend4; if (!bufs[k]) continue; loc = oldloc; buffer = (mus_float_t *)(bufs[k]); if (clipping) { int clipend; mus_float_t sample; clipend = oldloc + lim; bufnow = (mus_float_t *)(buffer + oldloc); bufend = (mus_float_t *)(buffer + clipend - 1); bufend4 = (mus_float_t *)(bufend - 4); if (clip_checker) clip_checker(); if (mus_clip_handler) { for (; bufnow <= bufend; bufnow++) { sample = (*bufnow); if ((sample >= 1.0) || (sample < -1.0)) (*bufnow) = (*mus_clip_handler)(sample); } } else { while (bufnow <= bufend4) { sample = (*bufnow); if (sample >= 1.0) (*bufnow) = 0.99999; else if (sample < -1.0) (*bufnow) = -1.0; bufnow++; sample = (*bufnow); if (sample >= 1.0) (*bufnow) = 0.99999; else if (sample < -1.0) (*bufnow) = -1.0; bufnow++; sample = (*bufnow); if (sample >= 1.0) (*bufnow) = 0.99999; else if (sample < -1.0) (*bufnow) = -1.0; bufnow++; sample = (*bufnow); if (sample >= 1.0) (*bufnow) = 0.99999; else if (sample < -1.0) (*bufnow) = -1.0; bufnow++; } for (; bufnow <= bufend; bufnow++) { sample = (*bufnow); if (sample >= 1.0) (*bufnow) = 0.99999; else if (sample < -1.0) (*bufnow) = -1.0; } } } if ((sample_type == MUS_OUT_SAMPLE_TYPE) && (chans == 1) && (beg == 0) && (!inbuf)) /* "tfd" can be sample type */ { bytes = (end + 1) * siz; return(checked_write(tfd, (char *)(bufs[0]), bytes)); } loclim = loc + lim; if (!charbuf) { if (!ur_charbuf) ur_charbuf = (char *)malloc(BUFLIM * sizeof(char)); /* ur_charbuf = (char *)calloc(BUFLIM, sizeof(char)); else memset((void *)ur_charbuf, 0, BUFLIM); */ charbuf = ur_charbuf; } bufnow = (mus_float_t *)(buffer + loc); bufend = (mus_float_t *)(buffer + loclim - 1); bufend4 = (mus_float_t *)(bufend - 4); jchar = (unsigned char *)charbuf; /* if to_buffer we should add the loop offset here, or never loop */ jchar += (k * siz); switch (sample_type) { case MUS_BSHORT: while (bufnow <= bufend4) { set_big_endian_short(jchar, mus_sample_to_short(*bufnow++)); jchar += siz_chans; set_big_endian_short(jchar, mus_sample_to_short(*bufnow++)); jchar += siz_chans; set_big_endian_short(jchar, mus_sample_to_short(*bufnow++)); jchar += siz_chans; set_big_endian_short(jchar, mus_sample_to_short(*bufnow++)); jchar += siz_chans; } for (; bufnow <= bufend; jchar += siz_chans) set_big_endian_short(jchar, mus_sample_to_short(*bufnow++)); break; case MUS_LSHORT: for (; bufnow <= bufend; jchar += siz_chans) set_little_endian_short(jchar, mus_sample_to_short(*bufnow++)); break; case MUS_BINT: for (; bufnow <= bufend; jchar += siz_chans) set_big_endian_int(jchar, mus_sample_to_int(*bufnow++)); break; case MUS_LINT: for (; bufnow <= bufend; jchar += siz_chans) set_little_endian_int(jchar, mus_sample_to_int(*bufnow++)); break; case MUS_BINTN: for (; bufnow <= bufend; jchar += siz_chans) set_big_endian_int(jchar, mus_sample_to_int(*bufnow++) << 8); break; case MUS_LINTN: for (; bufnow <= bufend; jchar += siz_chans) set_little_endian_int(jchar, mus_sample_to_int(*bufnow++) << 8); break; case MUS_MULAW: for (; bufnow <= bufend; jchar += siz_chans) (*jchar) = to_mulaw(mus_sample_to_short(*bufnow++)); break; case MUS_ALAW: for (; bufnow <= bufend; jchar += siz_chans) (*jchar) = to_alaw(mus_sample_to_short(*bufnow++)); break; case MUS_BYTE: for (; bufnow <= bufend; jchar += siz_chans) (*((signed char *)jchar)) = mus_sample_to_byte(*bufnow++); break; case MUS_UBYTE: for (; bufnow <= bufend; jchar += siz_chans) (*jchar) = mus_sample_to_byte(*bufnow++) + UBYTE_ZERO; break; case MUS_BFLOAT: for (; bufnow <= bufend; jchar += siz_chans) set_big_endian_float(jchar, *bufnow++); break; case MUS_LFLOAT: while (bufnow <= bufend4) { set_little_endian_float(jchar, *bufnow++); jchar += siz_chans; set_little_endian_float(jchar, *bufnow++); jchar += siz_chans; set_little_endian_float(jchar, *bufnow++); jchar += siz_chans; set_little_endian_float(jchar, *bufnow++); jchar += siz_chans; } for (; bufnow <= bufend; jchar += siz_chans) set_little_endian_float(jchar, *bufnow++); break; case MUS_BDOUBLE: for (; bufnow <= bufend; jchar += siz_chans) set_big_endian_double(jchar, *bufnow++); break; case MUS_LDOUBLE: while (bufnow <= bufend4) { set_little_endian_double(jchar, *bufnow++); jchar += siz_chans; set_little_endian_double(jchar, *bufnow++); jchar += siz_chans; set_little_endian_double(jchar, *bufnow++); jchar += siz_chans; set_little_endian_double(jchar, *bufnow++); jchar += siz_chans; } for (; bufnow <= bufend; jchar += siz_chans) set_little_endian_double(jchar, *bufnow++); break; case MUS_BFLOAT_UNSCALED: for (; bufnow <= bufend; jchar += siz_chans) set_big_endian_float(jchar, 32768.0 * (*bufnow++)); break; case MUS_LFLOAT_UNSCALED: for (; bufnow <= bufend; jchar += siz_chans) set_little_endian_float(jchar, 32768.0 * (*bufnow++)); break; case MUS_BDOUBLE_UNSCALED: for (; bufnow <= bufend; jchar += siz_chans) set_big_endian_double(jchar, 32768.0 * (*bufnow++)); break; case MUS_LDOUBLE_UNSCALED: for (; bufnow <= bufend; jchar += siz_chans) set_little_endian_double(jchar, 32768.0 * (*bufnow++)); break; case MUS_UBSHORT: for (; bufnow <= bufend; jchar += siz_chans) set_big_endian_unsigned_short(jchar, (unsigned short)(mus_sample_to_short(*bufnow++) + USHORT_ZERO)); break; case MUS_ULSHORT: for (; bufnow <= bufend; jchar += siz_chans) set_little_endian_unsigned_short(jchar, (unsigned short)(mus_sample_to_short(*bufnow++) + USHORT_ZERO)); break; case MUS_B24INT: { int c3; mus_long_t bk; bk = (k * 3); c3 = chans * 3; for (; bufnow <= bufend; bk += c3) { val = mus_sample_to_int24(*bufnow++); charbuf[bk] = (val >> 16); charbuf[bk + 1] = (val >> 8); charbuf[bk + 2] = (val & 0xFF); } } break; case MUS_L24INT: { int c3; mus_long_t bk; bk = (k * 3); c3 = chans * 3; for (; bufnow <= bufend; bk += c3) { val = mus_sample_to_int24(*bufnow++); charbuf[bk + 2] = (val >> 16); charbuf[bk + 1] = (val >> 8); charbuf[bk] = (val & 0xFF); } } break; default: break; } loc = loclim; } if (!inbuf) { err = checked_write(tfd, charbuf, bytes); if (err == MUS_ERROR) return(MUS_ERROR); } } return(MUS_NO_ERROR); } int mus_file_write(int tfd, mus_long_t beg, mus_long_t end, int chans, mus_float_t **bufs) { return(mus_write_1(tfd, beg, end, chans, bufs, NULL, false)); /* if inbuf is NULL (as here), clipped is ignored, so the "false" could be anything */ } int mus_file_write_file(int tfd, mus_long_t beg, mus_long_t end, int chans, mus_float_t **bufs) { return(mus_write_1(tfd, beg, end, chans, bufs, NULL, false)); } int mus_file_write_buffer(int charbuf_sample_type, mus_long_t beg, mus_long_t end, int chans, mus_float_t **bufs, char *charbuf, bool clipped) { return(mus_write_1(charbuf_sample_type, beg, end, chans, bufs, charbuf, clipped)); } /* for CLM */ void mus_reset_io_c(void) { io_fd_size = 0; io_fds = NULL; clipping_default = false; mus_clip_set_handler(NULL); } #if !(defined(_MSC_VER) && (!(defined(__CYGWIN__)))) static int sndlib_strlen(const char *str) { /* strlen(NULL) -> seg fault! */ if ((str) && (*str)) return(strlen(str)); return(0); } #endif static char *saved_cwd = NULL; char *mus_getcwd(void) { int i, path_max = 0; char *pwd = NULL; if (saved_cwd) return(saved_cwd); #if (!defined(_MSC_VER)) && (!defined(_WIN32)) /* _WIN32 for mingw */ path_max = pathconf("/", _PC_PATH_MAX); #endif if (path_max < 1024) { #if defined(PATH_MAX) path_max = PATH_MAX; #endif if (path_max < 1024) path_max = 1024; } for (i = path_max;; i *= 2) { char *res; if (pwd) free(pwd); pwd = (char *)calloc(i, sizeof(char)); #if _WIN32 /* (defined(_MSC_VER) || __CYGWIN__) */ res = _getcwd(pwd, i); #else res = getcwd(pwd, i); #endif if (res) break; /* NULL is returned if failure, but what about success? should I check errno=ERANGE? */ } saved_cwd = pwd; return(pwd); } #if HAVE_EXTENSION_LANGUAGE #include "sndlib2xen.h" /* for g_mus_sound_path */ #endif char *mus_expand_filename(const char *filename) { /* fill out under-specified library pathnames etc */ #if defined(_MSC_VER) && (!(defined(__CYGWIN__))) return(mus_strdup(filename)); #else char *file_name_buf; char *tok, *orig; int i, j, len, orig_len; /* realpath does not speed this up */ if ((filename) && (*filename)) len = strlen(filename); else return(NULL); if ((len == 1) && (filename[0] == '.')) { orig = mus_getcwd(); orig_len = sndlib_strlen(orig); file_name_buf = (char *)malloc((orig_len + 4) * sizeof(char)); strcpy(file_name_buf, orig); file_name_buf[orig_len] = '/'; file_name_buf[orig_len + 1] = '\0'; /* fprintf(stderr, "%d: %s -> %s\n", __LINE__, filename, file_name_buf); */ return(file_name_buf); } tok = (char *)strchr(filename, (int)'/'); if (!tok) { orig = mus_getcwd(); orig_len = sndlib_strlen(orig); file_name_buf = (char *)malloc((len + orig_len + 4) * sizeof(char)); strcpy(file_name_buf, orig); file_name_buf[orig_len] = '/'; strncpy((char *)(file_name_buf + orig_len + 1), filename, len + 1); /* fprintf(stderr, "%d: %s -> %s\n", __LINE__, filename, file_name_buf); */ #if HAVE_EXTENSION_LANGUAGE if (!mus_file_probe(file_name_buf)) { Xen p; for (p = g_mus_sound_path(); Xen_is_pair(p); p = Xen_cdr(p)) { char *nfile; const char *path; int path_len; path = Xen_string_to_C_string(Xen_car(p)); path_len = sndlib_strlen(path); nfile = (char *)malloc((len + path_len + 4) * sizeof(char)); strcpy(nfile, path); if (nfile[path_len - 1] != '/') { nfile[path_len] = '/'; strncpy((char *)(nfile + path_len + 1), filename, len + 1); } else strncpy((char *)(nfile + path_len), filename, len + 1); /* fprintf(stderr, "%d: %s -> %s\n", __LINE__, filename, nfile); */ if (mus_file_probe(nfile)) { free(file_name_buf); return(nfile); } free(nfile); } } #endif return(file_name_buf); } orig = mus_strdup(filename); tok = orig; /* get rid of "//" */ for (i = 0, j = 0; i < len - 1; i++) { if ((tok[i] == '/') && (tok[i + 1] == '/')) j = i + 1; } if (j > 0) { for (i = 0; j < len; i++, j++) tok[i] = tok[j]; tok[i] ='\0'; } /* get rid of "~/" at start */ if (tok[0] != '/') { char *home = NULL; if ((tok[0] == '~') && (home = getenv("HOME"))) { file_name_buf = (char *)malloc((len + sndlib_strlen(home) + 8) * sizeof(char)); strcpy(file_name_buf, home); strcat(file_name_buf, ++tok); } else { char *pwd; pwd = mus_getcwd(); file_name_buf = (char *)malloc((len + sndlib_strlen(pwd) + 8) * sizeof(char)); strcpy(file_name_buf, pwd); strcat(file_name_buf, "/"); if (tok[0]) strcat(file_name_buf, tok); } } else { file_name_buf = (char *)malloc((len + 8) * sizeof(char)); strcpy(file_name_buf, tok); } /* get rid of "/../" and "/./" also "/." at end */ { int slash_at = -1; bool found_one = true; while (found_one) { found_one = false; len = strlen(file_name_buf); for (i = 0; i < len - 3; i++) if (file_name_buf[i] == '/') { if ((file_name_buf[i + 1] == '.') && (file_name_buf[i + 2] == '.') && (file_name_buf[i + 3] == '/')) { i += 4; for (j = slash_at + 1; i < len; i++, j++) file_name_buf[j] = file_name_buf[i]; file_name_buf[j] = '\0'; found_one = true; break; } else { if ((file_name_buf[i + 1] == '.') && (file_name_buf[i + 2] == '/')) { for (j = i + 3, i = i + 1; j < len; i++, j++) file_name_buf[i] = file_name_buf[j]; file_name_buf[i] = '\0'; found_one = true; } else slash_at = i; } } } len = strlen(file_name_buf); if ((len > 1) && (file_name_buf[len - 1] == '.') && (file_name_buf[len - 2] == '/')) file_name_buf[len - 1] = '\0'; } free(orig); return(file_name_buf); #endif } char *mus_format(const char *format, ...) { /* caller should free result */ #ifndef _MSC_VER va_list ap; int bytes; char *result = NULL; va_start(ap, format); bytes = vasprintf(&result, format, ap); va_end(ap); if (bytes == -1) return(NULL); return(result); #else #define MUS_FORMAT_BUFFER_SIZE 256 char *buf = NULL; int needed_bytes = 0; va_list ap; buf = (char *)calloc(MUS_FORMAT_BUFFER_SIZE, sizeof(char)); va_start(ap, format); needed_bytes = vsnprintf(buf, MUS_FORMAT_BUFFER_SIZE, format, ap); va_end(ap); if (needed_bytes >= MUS_FORMAT_BUFFER_SIZE) /* "=" here because we need room for the trailing 0 */ { free(buf); buf = (char *)calloc(needed_bytes + 1, sizeof(char)); va_start(ap, format); vsnprintf(buf, needed_bytes + 1, format, ap); va_end(ap); } return(buf); #endif } mus_float_t mus_fclamp(mus_float_t lo, mus_float_t val, mus_float_t hi) { if (val > hi) return(hi); else if (val < lo) return(lo); else return(val); } int mus_iclamp(int lo, int val, int hi) { if (val > hi) return(hi); else if (val < lo) return(lo); else return(val); } mus_long_t mus_oclamp(mus_long_t lo, mus_long_t val, mus_long_t hi) { if (val > hi) return(hi); else if (val < lo) return(lo); else return(val); } /* raw sample data peak value (without per-sample conversion) */ /* ---------------- short ---------------- */ #define SHORT_BYTES 2 static void min_max_shorts(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp) { short cur_min, cur_max, tmp; short *sbuf; int i, len, len2; sbuf = (short *)data; len = bytes / SHORT_BYTES; cur_min = sbuf[chan]; cur_max = cur_min; len2 = len - 2 * chans; i = chan; /* we read the first sample above, but we're reading by twos below */ while (i <= len2) { tmp = sbuf[i]; if (tmp < cur_min) cur_min = tmp; else if (tmp > cur_max) cur_max = tmp; i += chans; tmp = sbuf[i]; if (tmp < cur_min) cur_min = tmp; else if (tmp > cur_max) cur_max = tmp; i += chans; } if (i < len) { tmp = sbuf[i]; if (tmp < cur_min) cur_min = tmp; else if (tmp > cur_max) cur_max = tmp; } (*min_samp) = (mus_float_t)cur_min / (mus_float_t)(1 << 15); (*max_samp) = (mus_float_t)cur_max / (mus_float_t)(1 << 15); } static void min_max_switch_shorts(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp) { short cur_min, cur_max; /* frample based */ unsigned char *samp, *eod, *eod2; int bytes_per_frample; bytes_per_frample = chans * SHORT_BYTES; eod = (unsigned char *)(data + bytes); eod2 = (unsigned char *)(eod - 2 * bytes_per_frample); #if MUS_LITTLE_ENDIAN cur_min = big_endian_short((unsigned char *)(data + (chan * SHORT_BYTES))); #else cur_min = little_endian_short((unsigned char *)(data + (chan * SHORT_BYTES))); #endif cur_max = cur_min; samp = (unsigned char *)(data + (chan * SHORT_BYTES)); while (samp <= eod2) { short val; #if MUS_LITTLE_ENDIAN val = big_endian_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = big_endian_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #else val = little_endian_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = little_endian_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #endif } if (samp < eod) { short val; #if MUS_LITTLE_ENDIAN val = big_endian_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; #else val = little_endian_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; #endif } (*min_samp) = (mus_float_t)cur_min / (mus_float_t)(1 << 15); (*max_samp) = (mus_float_t)cur_max / (mus_float_t)(1 << 15); } /* ---------------- unsigned short ---------------- */ static void min_max_ushorts(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp) { unsigned short cur_min, cur_max; unsigned short *sbuf; int i, len, len2; sbuf = (unsigned short *)data; len = bytes / SHORT_BYTES; len2 = len - 2 * chans; cur_min = sbuf[chan]; cur_max = cur_min; i = chan; while (i <= len2) { if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; } if (i < len) { if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; } (*min_samp) = (mus_float_t)(cur_min - USHORT_ZERO) / (mus_float_t)(1 << 15); (*max_samp) = (mus_float_t)(cur_max - USHORT_ZERO) / (mus_float_t)(1 << 15); } static void min_max_switch_ushorts(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp) { unsigned short cur_min, cur_max; /* frample based */ unsigned char *samp, *eod, *eod2; int bytes_per_frample; bytes_per_frample = chans * SHORT_BYTES; eod = (unsigned char *)(data + bytes); eod2 = (unsigned char *)(eod - 2 * bytes_per_frample); #if MUS_LITTLE_ENDIAN cur_min = big_endian_unsigned_short((unsigned char *)(data + (chan * SHORT_BYTES))); #else cur_min = little_endian_unsigned_short((unsigned char *)(data + (chan * SHORT_BYTES))); #endif cur_max = cur_min; samp = (unsigned char *)(data + (chan * SHORT_BYTES)); while (samp <= eod2) { unsigned short val; #if MUS_LITTLE_ENDIAN val = big_endian_unsigned_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = big_endian_unsigned_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #else val = little_endian_unsigned_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = little_endian_unsigned_short(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #endif } if (samp < eod) { unsigned short val; #if MUS_LITTLE_ENDIAN val = big_endian_unsigned_short(samp); #else val = little_endian_unsigned_short(samp); #endif if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; } (*min_samp) = (mus_float_t)(cur_min - USHORT_ZERO) / (mus_float_t)(1 << 15); (*max_samp) = (mus_float_t)(cur_max - USHORT_ZERO) / (mus_float_t)(1 << 15); } /* ---------------- int ---------------- */ #define INT_BYTES 4 static void min_max_ints(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp, bool standard) { int cur_min, cur_max; int *sbuf; int i, len, len2; sbuf = (int *)data; len = bytes / INT_BYTES; len2 = len - 2 *chans; cur_min = sbuf[chan]; cur_max = cur_min; i = chan; while (i <= len2) { if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; } if (i < len) { if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; } (*min_samp) = (mus_float_t)cur_min / (mus_float_t)(1 << 23); (*max_samp) = (mus_float_t)cur_max / (mus_float_t)(1 << 23); if (!standard) { (*min_samp) = (mus_float_t)(*min_samp) / (mus_float_t)(1 << 8); (*max_samp) = (mus_float_t)(*max_samp) / (mus_float_t)(1 << 8); } } /* (with-sound (:sample-type mus-lintn :statistics #t) (fm-violin 0 1 440 .1)) */ static void min_max_switch_ints(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp, bool standard) { int cur_min, cur_max; /* frample based */ unsigned char *samp, *eod, *eod2; int bytes_per_frample; bytes_per_frample = chans * INT_BYTES; eod = (unsigned char *)(data + bytes); eod2 = (unsigned char *)(eod - 2 * bytes_per_frample); #if MUS_LITTLE_ENDIAN cur_min = big_endian_int((unsigned char *)(data + (chan * INT_BYTES))); #else cur_min = little_endian_int((unsigned char *)(data + (chan * INT_BYTES))); #endif cur_max = cur_min; samp = (unsigned char *)(data + (chan * INT_BYTES)); while (samp <= eod2) { int val; #if MUS_LITTLE_ENDIAN val = big_endian_int(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = big_endian_int(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #else val = little_endian_int(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = little_endian_int(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #endif } if (samp < eod) { int val; #if MUS_LITTLE_ENDIAN val = big_endian_int(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; #else val = little_endian_int(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; #endif } (*min_samp) = (mus_float_t)cur_min / (mus_float_t)(1 << 23); (*max_samp) = (mus_float_t)cur_max / (mus_float_t)(1 << 23); if (!standard) { (*min_samp) = (mus_float_t)(*min_samp) / (mus_float_t)(1 << 8); (*max_samp) = (mus_float_t)(*max_samp) / (mus_float_t)(1 << 8); } } /* ---------------- float ---------------- */ #define FLOAT_BYTES 4 static void min_max_floats(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp, bool unscaled) { float cur_min, cur_max; float *sbuf; int i, len, len2; sbuf = (float *)data; len = bytes / FLOAT_BYTES; len2 = len - 2 *chans; cur_min = sbuf[chan]; cur_max = cur_min; i = chan; while (i < len2) { if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; } while (i < len) { if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; } if (unscaled) { (*min_samp) = (double)cur_min / 32768.0; (*max_samp) = (double)cur_max / 32768.0; } else { (*min_samp) = cur_min; (*max_samp) = cur_max; } } static void min_max_switch_floats(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp, bool unscaled) { float cur_min, cur_max; /* frample based */ unsigned char *samp, *eod, *eod2; int bytes_per_frample; bytes_per_frample = chans * FLOAT_BYTES; eod = (unsigned char *)(data + bytes); eod2 = (unsigned char *)(eod - 2 * bytes_per_frample); #if MUS_LITTLE_ENDIAN cur_min = big_endian_float((unsigned char *)(data + (chan * FLOAT_BYTES))); #else cur_min = little_endian_float((unsigned char *)(data + (chan * FLOAT_BYTES))); #endif cur_max = cur_min; samp = (unsigned char *)(data + (chan * FLOAT_BYTES)); while (samp <= eod2) { float val; #if MUS_LITTLE_ENDIAN val = big_endian_float(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = big_endian_float(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #else val = little_endian_float(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = little_endian_float(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #endif } if (samp < eod) { float val; #if MUS_LITTLE_ENDIAN val = big_endian_float(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; #else val = little_endian_float(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; #endif } if (unscaled) { (*min_samp) = (double)cur_min / 32768.0; (*max_samp) = (double)cur_max / 32768.0; } else { (*min_samp) = cur_min; (*max_samp) = cur_max; } } /* ---------------- double ---------------- */ #define DOUBLE_BYTES 8 static void min_max_doubles(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp, bool unscaled) { double cur_min, cur_max; double *sbuf; int i, len, len2; sbuf = (double *)data; len = bytes / DOUBLE_BYTES; len2 = len - 2 * chans; cur_min = sbuf[chan]; cur_max = cur_min; i = chan; while (i <= len2) { if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; i += chans; } if (i < len) { if (sbuf[i] < cur_min) cur_min = sbuf[i]; else if (sbuf[i] > cur_max) cur_max = sbuf[i]; } if (unscaled) { (*min_samp) = cur_min / 32768.0; (*max_samp) = cur_max / 32768.0; } else { (*min_samp) = cur_min; (*max_samp) = cur_max; } } static void min_max_switch_doubles(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp, bool unscaled) { double cur_min, cur_max; /* frample based */ unsigned char *samp, *eod, *eod2; int bytes_per_frample; bytes_per_frample = chans * DOUBLE_BYTES; eod = (unsigned char *)(data + bytes); eod2 = (unsigned char *)(eod - 2 * bytes_per_frample); #if MUS_LITTLE_ENDIAN cur_min = big_endian_double((unsigned char *)(data + (chan * DOUBLE_BYTES))); #else cur_min = little_endian_double((unsigned char *)(data + (chan * DOUBLE_BYTES))); #endif cur_max = cur_min; samp = (unsigned char *)(data + (chan * DOUBLE_BYTES)); while (samp <= eod2) { double val; #if MUS_LITTLE_ENDIAN val = big_endian_double(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = big_endian_double(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #else val = little_endian_double(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; val = little_endian_double(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; samp += bytes_per_frample; #endif } if (samp < eod) { double val; #if MUS_LITTLE_ENDIAN val = big_endian_double(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; #else val = little_endian_double(samp); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; #endif } if (unscaled) { (*min_samp) = cur_min / 32768.0; (*max_samp) = cur_max / 32768.0; } else { (*min_samp) = cur_min; (*max_samp) = cur_max; } } /* ---------------- 3-byte samples ---------------- */ #define THREE_BYTES 3 static int big_three(unsigned char *data, int loc) { int val; val = (data[loc + 0] << 16) + (data[loc + 1] << 8) + data[loc + 2]; if (val >= (1 << 23)) val -= (1 << 24); return(val); } static int little_three(unsigned char *data, int loc) { int val; val = (data[loc + 2] << 16) + (data[loc + 1] << 8) + data[loc + 0]; if (val >= (1 << 23)) val -= (1 << 24); return(val); } static void min_max_24s(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp, bool big_endian) { int cur_min, cur_max; int i, k, bytes_per_frample, len, len2, offset; bytes_per_frample = chans * THREE_BYTES; len = bytes / bytes_per_frample; len2 = len - 2 * bytes_per_frample; offset = chan * THREE_BYTES; k = offset; if (big_endian) { cur_min = big_three(data, k); cur_max = cur_min; i = 0; /* k += bytes_per_frample; */ while (i <= len2) { int val; val = big_three(data, k); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i++; k += bytes_per_frample; val = big_three(data, k); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i++; k += bytes_per_frample; } while (i < len) { int val; val = big_three(data, k); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i++; k += bytes_per_frample; } } else { cur_min = little_three(data, k); cur_max = cur_min; i = 0; /* k += bytes_per_frample; */ while (i <= len2) { int val; val = little_three(data, k); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i++; k += bytes_per_frample; val = little_three(data, k); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i++; k += bytes_per_frample; } while (i < len) { int val; val = little_three(data, k); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i++; k += bytes_per_frample; } } (*min_samp) = (mus_float_t)cur_min / (mus_float_t)(1 << 23); (*max_samp) = (mus_float_t)cur_max / (mus_float_t)(1 << 23); } /* ---------------- mulaw, alaw, byte ---------------- */ static void min_max_mulaw(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp) { mus_float_t cur_min, cur_max; int i, b2; cur_min = mus_mulaw[(int)data[chan]]; cur_max = cur_min; i = chan; b2 = bytes - 2 * chans; while (i <= b2) { mus_float_t val; val = mus_mulaw[(int)data[i]]; if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i += chans; val = mus_mulaw[(int)data[i]]; if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i += chans; } if (i < bytes) { mus_float_t val; val = mus_mulaw[(int)data[i]]; if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; } (*min_samp) = cur_min; (*max_samp) = cur_max; } static void min_max_alaw(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp) { mus_float_t cur_min, cur_max; int i, b2; cur_min = mus_alaw[(int)data[chan]]; cur_max = cur_min; i = chan; b2 = bytes - 2 * chans; while (i <= b2) { mus_float_t val; val = mus_alaw[(int)data[i]]; if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i += chans; val = mus_alaw[(int)data[i]]; if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i += chans; } if (i < bytes) { mus_float_t val; val = mus_alaw[(int)data[i]]; if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; } (*min_samp) = cur_min; (*max_samp) = cur_max; } static void min_max_bytes(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp) { signed char cur_min, cur_max; int i, b2; cur_min = (signed char)(data[chan]); cur_max = cur_min; i = chan; b2 = bytes - 2 * chans; while (i <= b2) { signed char val; val = (signed char)(data[i]); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i += chans; val = (signed char)(data[i]); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; i += chans; } if (i < bytes) { signed char val; val = (signed char)(data[i]); if (val < cur_min) cur_min = val; else if (val > cur_max) cur_max = val; } (*min_samp) = (mus_float_t)cur_min / (mus_float_t)(1 << 7); (*max_samp) = (mus_float_t)cur_max / (mus_float_t)(1 << 7); } static void min_max_ubytes(unsigned char *data, int bytes, int chan, int chans, mus_float_t *min_samp, mus_float_t *max_samp) { unsigned char cur_min, cur_max; int i, b2; cur_min = data[chan]; cur_max = cur_min; i = chan; b2 = bytes - 2 * chans; while (i <= b2) { if (data[i] < cur_min) cur_min = data[i]; else if (data[i] > cur_max) cur_max = data[i]; i += chans; if (data[i] < cur_min) cur_min = data[i]; else if (data[i] > cur_max) cur_max = data[i]; i += chans; } if (i < bytes) { if (data[i] < cur_min) cur_min = data[i]; else if (data[i] > cur_max) cur_max = data[i]; } (*min_samp) = (mus_float_t)(cur_min - UBYTE_ZERO) / (mus_float_t)(1 << 7); (*max_samp) = (mus_float_t)(cur_max - UBYTE_ZERO) / (mus_float_t)(1 << 7); } int mus_samples_bounds(unsigned char *data, int bytes, int chan, int chans, mus_sample_t samp_type, mus_float_t *min_samp, mus_float_t *max_samp) { switch (samp_type) { case MUS_MULAW: min_max_mulaw(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_ALAW: min_max_alaw(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_BYTE: min_max_bytes(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_UBYTE: min_max_ubytes(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_L24INT: min_max_24s(data, bytes, chan, chans, min_samp, max_samp, false); break; case MUS_B24INT: min_max_24s(data, bytes, chan, chans, min_samp, max_samp, true); break; #if MUS_LITTLE_ENDIAN case MUS_LSHORT: min_max_shorts(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_BSHORT: min_max_switch_shorts(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_ULSHORT: min_max_ushorts(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_UBSHORT: min_max_switch_ushorts(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_LINT: case MUS_LINTN: min_max_ints(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_LINT); break; case MUS_BINT: case MUS_BINTN: min_max_switch_ints(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_BINT); break; case MUS_LFLOAT: case MUS_LFLOAT_UNSCALED: min_max_floats(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_LFLOAT_UNSCALED); break; case MUS_BFLOAT: case MUS_BFLOAT_UNSCALED: min_max_switch_floats(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_BFLOAT_UNSCALED); break; case MUS_LDOUBLE: case MUS_LDOUBLE_UNSCALED: min_max_doubles(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_LDOUBLE_UNSCALED); break; case MUS_BDOUBLE: case MUS_BDOUBLE_UNSCALED: min_max_switch_doubles(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_BDOUBLE_UNSCALED); break; #else /* big endian */ case MUS_LSHORT: min_max_switch_shorts(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_BSHORT: min_max_shorts(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_ULSHORT: min_max_switch_ushorts(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_UBSHORT: min_max_ushorts(data, bytes, chan, chans, min_samp, max_samp); break; case MUS_LINT: case MUS_LINTN: min_max_switch_ints(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_LINT); break; case MUS_BINT: case MUS_BINTN: min_max_ints(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_BINT); break; case MUS_LFLOAT: case MUS_LFLOAT_UNSCALED: min_max_switch_floats(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_LFLOAT_UNSCALED); break; case MUS_BFLOAT: case MUS_BFLOAT_UNSCALED: min_max_floats(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_BFLOAT_UNSCALED); break; case MUS_LDOUBLE: case MUS_LDOUBLE_UNSCALED: min_max_switch_doubles(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_LDOUBLE_UNSCALED); break; case MUS_BDOUBLE: case MUS_BDOUBLE_UNSCALED: min_max_doubles(data, bytes, chan, chans, min_samp, max_samp, samp_type == MUS_BDOUBLE_UNSCALED); break; #endif default: return(MUS_ERROR); break; } return(MUS_NO_ERROR); } char *mus_strdup(const char *str) { char *newstr = NULL; int len; if ((!str) || (!(*str))) return(NULL); len = strlen(str); newstr = (char *)malloc(len + 1); strcpy(newstr, str); newstr[len] = '\0'; return(newstr); } int mus_strlen(const char *str) { /* strlen(NULL) -> seg fault! */ if ((str) && (*str)) return(strlen(str)); return(0); } bool mus_strcmp(const char *s1, const char *s2) { if ((!s1) || (!s2)) return(s1 == s2); while (true) { unsigned char c1, c2; c1 = (unsigned char) *s1++; c2 = (unsigned char) *s2++; if (c1 != c2) return(false); if (c1 == '\0') break; } return(true); } char *mus_strcat(char *errmsg, const char *str, int *size) { int new_len, err_size; new_len = (mus_strlen(str) + mus_strlen(errmsg)); err_size = size[0]; if (new_len >= err_size) { if ((err_size * 2) > new_len) err_size = err_size * 2; else err_size = new_len * 2; errmsg = (char *)realloc(errmsg, err_size * sizeof(char)); size[0] = err_size; } strcat(errmsg, str); return(errmsg); }