diff options
Diffstat (limited to 'third_party/resample/sndlib-20/sound.c')
-rw-r--r-- | third_party/resample/sndlib-20/sound.c | 1072 |
1 files changed, 0 insertions, 1072 deletions
diff --git a/third_party/resample/sndlib-20/sound.c b/third_party/resample/sndlib-20/sound.c deleted file mode 100644 index 8443dcaa..00000000 --- a/third_party/resample/sndlib-20/sound.c +++ /dev/null @@ -1,1072 +0,0 @@ -/* sound.c */ - -#include <mus-config.h> - -#if USE_SND - #include "snd.h" -#endif - -#include <math.h> -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> -#include <stddef.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <time.h> -#include <stdarg.h> - -#if (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H))) - #include <libc.h> -#else - #if (!(defined(_MSC_VER))) - #include <unistd.h> - #endif - #if HAVE_STRING_H - #include <string.h> - #endif -#endif - -#include "_sndlib.h" -#include "sndlib-strings.h" - -static mus_error_handler_t *mus_error_handler = NULL; - -mus_error_handler_t *mus_error_set_handler(mus_error_handler_t *new_error_handler) -{ - mus_error_handler_t *old_handler; - old_handler = mus_error_handler; - mus_error_handler = new_error_handler; - return(old_handler); -} - -#define MUS_ERROR_BUFFER_SIZE 1024 -static char *mus_error_buffer = NULL; - -int mus_error(int error, const char *format, ...) -{ - va_list ap; - if (format == NULL) return(MUS_ERROR); /* else bus error in Mac OSX */ - if (mus_error_buffer == NULL) - mus_error_buffer = (char *)CALLOC(MUS_ERROR_BUFFER_SIZE, sizeof(char)); - va_start(ap, format); -#if HAVE_VSNPRINTF - vsnprintf(mus_error_buffer, MUS_ERROR_BUFFER_SIZE, format, ap); -#else - vsprintf(mus_error_buffer, format, ap); -#endif - va_end(ap); - if (mus_error_handler) - (*mus_error_handler)(error, mus_error_buffer); - else - { - fprintf(stderr, mus_error_buffer); - fputc('\n', stderr); - } - return(MUS_ERROR); -} - -static mus_print_handler_t *mus_print_handler = NULL; - -mus_print_handler_t *mus_print_set_handler(mus_print_handler_t *new_print_handler) -{ - mus_print_handler_t *old_handler; - old_handler = mus_print_handler; - mus_print_handler = new_print_handler; - return(old_handler); -} - -void mus_print(const char *format, ...) -{ - va_list ap; - if (mus_error_buffer == NULL) - mus_error_buffer = (char *)CALLOC(MUS_ERROR_BUFFER_SIZE, sizeof(char)); - if (mus_print_handler) - { - va_start(ap, format); -#if HAVE_VSNPRINTF - vsnprintf(mus_error_buffer, MUS_ERROR_BUFFER_SIZE, format, ap); -#else - vsprintf(mus_error_buffer, format, ap); -#endif - va_end(ap); - (*mus_print_handler)(mus_error_buffer); - } - else - { - va_start(ap, format); - vfprintf(stdout, format, ap); - va_end(ap); - } -} - -static const char *mus_initial_error_names[] = { - "no error", "no frequency method", "no phase method", "null gen arg to method", "no length method", - "no free method", "no describe method", "no data method", "no scaler method", - "memory allocation failed", "unstable two pole error", - "can't open file", "no sample input", "no sample output", - "no such channel", "no file name provided", "no location method", "no channel method", - "no such fft window", "unsupported data format", "header read failed", - "unsupported header type", "file descriptors not initialized", "not a sound file", "file closed", "write error", - "header write failed", "can't open temp file", "interrupted", "bad envelope", - - "audio channels not available", "audio srate not available", "audio format not available", - "no audio input available", "audio configuration not available", - "no audio lines available", "audio write error", "audio size not available", "audio device not available", - "can't close audio", "can't open audio", "audio read error", "audio amp not available", - "can't write audio", "can't read audio", "no audio read permission", - "can't close file", "arg out of range", - - "midi open error", "midi read error", "midi write error", "midi close error", "midi init error", "midi misc error", - - "no channels method", "no hop method", "no width method", "no file-name method", "no ramp method", "no run method", - "no increment method", "no offset method", - "no xcoeff method", "no ycoeff method", "no xcoeffs method", "no ycoeffs method", -}; - -static char **mus_error_names = NULL; -static int mus_error_names_size = 0; - -static int mus_error_tag = MUS_INITIAL_ERROR_TAG; -int mus_make_error(char *error_name) -{ - int new_error, err, len, i; - new_error = mus_error_tag++; - err = new_error - MUS_INITIAL_ERROR_TAG; - if (error_name) - { - if (err >= mus_error_names_size) - { - if (mus_error_names_size == 0) - { - mus_error_names_size = 8; - mus_error_names = (char **)CALLOC(mus_error_names_size, sizeof(char *)); - } - else - { - len = mus_error_names_size; - mus_error_names_size += 8; - mus_error_names = (char **)REALLOC(mus_error_names, mus_error_names_size * sizeof(char *)); - for (i = len; i < mus_error_names_size; i++) mus_error_names[i] = NULL; - } - } - len = strlen(error_name); - mus_error_names[err] = (char *)CALLOC(len + 1, sizeof(char)); - strcpy(mus_error_names[err], error_name); - } - return(new_error); -} - -const char *mus_error_type_to_string(int err) -{ - if (err >= 0) - { - if (err < MUS_INITIAL_ERROR_TAG) - return(mus_initial_error_names[err]); - else - { - err -= MUS_INITIAL_ERROR_TAG; - if ((mus_error_names) && (err < mus_error_names_size)) - return(mus_error_names[err]); - } - } - return("unknown mus error"); -} - -static void default_mus_error(int ignore, char *msg) -{ - /* default error handler simply prints the error message */ - fprintf(stderr, msg); -} - -static time_t local_file_write_date(const char *filename) -{ - struct stat statbuf; - int err; - err = stat(filename, &statbuf); - if (err < 0) return((time_t)0); - return((time_t)(statbuf.st_mtime)); -} - -static bool sndlib_initialized = false; - -int mus_sound_initialize(void) -{ - int err = MUS_NO_ERROR; - if (!sndlib_initialized) - { - sndlib_initialized = true; - mus_error_handler = default_mus_error; - err = mus_header_initialize(); - if (err == MUS_NO_ERROR) - err = mus_audio_initialize(); - return(err); - } - return(MUS_NO_ERROR); -} - -int mus_sample_bits(void) -{ - /* this to check for inconsistent loads */ -#if SNDLIB_USE_FLOATS - return(sizeof(Float)); -#else - return(MUS_SAMPLE_BITS); -#endif -} - -typedef struct { - char *file_name; /* full path -- everything is keyed to this name */ - int table_pos; - off_t *aux_comment_start, *aux_comment_end; - int *loop_modes, *loop_starts, *loop_ends; - int markers, base_detune, base_note; - int *marker_ids, *marker_positions; - off_t samples, true_file_length; - off_t data_location; - int srate, chans, header_type, data_format, original_sound_format, datum_size; - off_t comment_start, comment_end; - int type_specifier, bits_per_sample, block_align, fact_samples; - time_t write_date; - mus_sample_t *maxamps; - off_t *maxtimes; -} sound_file; - -static int sound_table_size = 0; -static sound_file **sound_table = NULL; -static sound_file *previous_sf = NULL; /* memoized search */ -static int previous_freed_sf = -1; - -static void free_sound_file(sound_file *sf) -{ - previous_sf = NULL; - if (sf) - { - sound_table[sf->table_pos] = NULL; - previous_freed_sf = sf->table_pos; - if (sf->aux_comment_start) FREE(sf->aux_comment_start); - if (sf->aux_comment_end) FREE(sf->aux_comment_end); - if (sf->file_name) FREE(sf->file_name); - if (sf->loop_modes) FREE(sf->loop_modes); - if (sf->loop_starts) FREE(sf->loop_starts); - if (sf->loop_ends) FREE(sf->loop_ends); - if (sf->marker_ids) FREE(sf->marker_ids); - if (sf->marker_positions) FREE(sf->marker_positions); - if (sf->maxamps) FREE(sf->maxamps); - if (sf->maxtimes) FREE(sf->maxtimes); - FREE(sf); - } -} - -static sound_file *add_to_sound_table(const char *name) -{ - int i, pos; - pos = previous_freed_sf; - if (pos == -1) - { - for (i = 0; i < sound_table_size; i++) - if (sound_table[i] == NULL) - { - pos = i; - break; - } - if (pos == -1) - { - pos = sound_table_size; - sound_table_size += 16; - if (sound_table == NULL) - sound_table = (sound_file **)CALLOC(sound_table_size, sizeof(sound_file *)); - else - { - sound_table = (sound_file **)REALLOC(sound_table, sound_table_size * sizeof(sound_file *)); - for (i = pos; i < sound_table_size; i++) sound_table[i] = NULL; - } - } - } - else previous_freed_sf = -1; - sound_table[pos] = (sound_file *)CALLOC(1, sizeof(sound_file)); - sound_table[pos]->table_pos = pos; - sound_table[pos]->file_name = (char *)CALLOC(strlen(name) + 1, sizeof(char)); - strcpy(sound_table[pos]->file_name, name); - return(sound_table[pos]); -} - -int mus_sound_prune(void) -{ - int i, pruned = 0; - for (i = 0; i < sound_table_size; i++) - if ((sound_table[i]) && - (!(mus_file_probe(sound_table[i]->file_name)))) - { - free_sound_file(sound_table[i]); - sound_table[i] = NULL; - pruned++; - } - return(pruned); -} - -int mus_sound_forget(const char *name) -{ - int i, len; - bool free_name = false; - char *short_name = NULL; - if (name == NULL) return(MUS_ERROR); - if (name[0] == '/') - { - len = strlen(name); - for (i = 0; i < len; i++) - if (name[i] == '/') - short_name = (char *)(name + i + 1); - } - else - { - short_name = mus_expand_filename(name); - free_name = true; - } - previous_sf = NULL; - if (name) - for (i = 0; i < sound_table_size; i++) - if ((sound_table[i]) && - ((strcmp(name, sound_table[i]->file_name) == 0) || - ((short_name) && - (strcmp(short_name, sound_table[i]->file_name) == 0)))) - { - free_sound_file(sound_table[i]); - sound_table[i] = NULL; - } - if (free_name) FREE(short_name); - return(MUS_NO_ERROR); -} - -static sound_file *check_write_date(const char *name, sound_file *sf) -{ - if (sf) - { - time_t date; - date = local_file_write_date(name); - if (date == sf->write_date) - return(sf); - else - { - if ((sf->header_type == MUS_RAW) && (mus_header_no_header(name))) - { - int chan; - off_t data_size; - /* sound has changed since we last read it, but it has no header, so - * the only sensible thing to check is the new length (i.e. caller - * has set other fields by hand) - */ - sf->write_date = date; - chan = mus_file_open_read(name); - data_size = lseek(chan, 0L, SEEK_END); - sf->true_file_length = data_size; - sf->samples = mus_bytes_to_samples(sf->data_format, data_size); - CLOSE(chan, name); - return(sf); - } - /* otherwise our data base is out-of-date, so clear it out */ - free_sound_file(sf); - } - } - return(NULL); -} - -static sound_file *find_sound_file(const char *name) -{ - int i; - /* perhaps we already have the needed data... (90% hit rate here) */ - if ((previous_sf) && - (strcmp(previous_sf->file_name, name) == 0) && - (previous_sf->write_date == local_file_write_date(name))) - return(previous_sf); - if (name) - for (i = 0; i < sound_table_size; i++) - if ((sound_table[i]) && - (strcmp(name, sound_table[i]->file_name) == 0)) - { - previous_sf = check_write_date(name, sound_table[i]); - return(previous_sf); - } - return(NULL); -} - -static void display_sound_file_entry(FILE *fp, const char *name, sound_file *sf) -{ - int i, lim; - time_t date; - char timestr[64]; - char *comment; - date = sf->write_date; - if (date != 0) - { -#if HAVE_STRFTIME - strftime(timestr, 64, "%a %d-%b-%Y %H:%M:%S", localtime(&date)); -#else - sprintf(timestr, "%d", (int)date); -#endif - } - else sprintf(timestr, "(date cleared)"); - fprintf(fp, " %s: %s, chans: %d, srate: %d, type: %s, format: %s, samps: " OFF_TD, - name, - timestr, - sf->chans, - sf->srate, - mus_header_type_name(sf->header_type), - mus_data_format_name(sf->data_format), - sf->samples); - if (sf->loop_modes) - { - if (sf->loop_modes[0] != 0) - fprintf(fp, ", loop mode %d: %d to %d", sf->loop_modes[0], sf->loop_starts[0], sf->loop_ends[0]); - if (sf->loop_modes[1] != 0) - fprintf(fp, ", loop mode %d: %d to %d, ", sf->loop_modes[1], sf->loop_starts[1], sf->loop_ends[1]); - fprintf(fp, ", base: %d, detune: %d", sf->base_note, sf->base_detune); - } - if (sf->maxamps) - { - lim = sf->chans; - if (lim > 0) - { - if (lim > 64) - lim = 64; - for (i = 0; i < lim; i++) - { - if (i > 1) fprintf(fp, ", "); - fprintf(fp, " %.3f at %.3f ", - MUS_SAMPLE_TO_FLOAT(sf->maxamps[i]), - (sf->srate > 0.0) ? (float)((double)(sf->maxtimes[i]) / (double)(sf->srate)) : (float)(sf->maxtimes[i])); - } - } - } - if (mus_file_probe(name)) - { - comment = mus_sound_comment(name); - if (comment) - { - fprintf(fp, "\n comment: %s", comment); - FREE(comment); - } - } - else fprintf(fp, " [defunct]"); - fprintf(fp, "\n"); -} - -void mus_sound_report_cache(FILE *fp) -{ - sound_file *sf; - int entries = 0; - int i; - fprintf(fp, "sound table:\n"); - for (i = 0; i < sound_table_size; i++) - { - sf = sound_table[i]; - if (sf) - { - display_sound_file_entry(fp, sf->file_name, sf); - entries++; - } - } - fprintf(fp, "\nentries: %d\n", entries); - fflush(fp); -} - -static sound_file *fill_sf_record(const char *name, sound_file *sf) -{ - int i; - sf->data_location = mus_header_data_location(); - sf->samples = mus_header_samples(); - sf->data_format = mus_header_format(); - sf->srate = mus_header_srate(); - /* if (sf->srate < 0) sf->srate = 0; */ - sf->chans = mus_header_chans(); - /* if (sf->chans < 0) sf->chans = 0; */ - sf->datum_size = mus_bytes_per_sample(sf->data_format); - sf->header_type = mus_header_type(); - sf->original_sound_format = mus_header_original_format(); - sf->true_file_length = mus_header_true_length(); - sf->comment_start = mus_header_comment_start(); - sf->comment_end = mus_header_comment_end(); - if (((sf->header_type == MUS_AIFC) || - (sf->header_type == MUS_AIFF) || - (sf->header_type == MUS_RIFF)) && - (mus_header_aux_comment_start(0) != 0)) - - { - sf->aux_comment_start = (off_t *)CALLOC(4, sizeof(off_t)); - sf->aux_comment_end = (off_t *)CALLOC(4, sizeof(off_t)); - for (i = 0; i < 4; i++) - { - sf->aux_comment_start[i] = mus_header_aux_comment_start(i); - sf->aux_comment_end[i] = mus_header_aux_comment_end(i); - } - } - sf->type_specifier = mus_header_type_specifier(); - sf->bits_per_sample = mus_header_bits_per_sample(); - sf->fact_samples = mus_header_fact_samples(); - sf->block_align = mus_header_block_align(); - sf->write_date = local_file_write_date(name); - if (mus_header_loop_mode(0) > 0) - { - sf->loop_modes = (int *)CALLOC(2, sizeof(int)); - sf->loop_starts = (int *)CALLOC(2, sizeof(int)); - sf->loop_ends = (int *)CALLOC(2, sizeof(int)); - for (i = 0; i < 2; i++) - { - sf->loop_modes[i] = mus_header_loop_mode(i); - if ((sf->header_type == MUS_AIFF) || - (sf->header_type == MUS_AIFC)) - { - sf->loop_starts[i] = mus_header_mark_position(mus_header_loop_start(i)); - sf->loop_ends[i] = mus_header_mark_position(mus_header_loop_end(i)); - } - else - { - sf->loop_starts[i] = mus_header_loop_start(i); - sf->loop_ends[i] = mus_header_loop_end(i); - } - } - sf->base_detune = mus_header_base_detune(); - sf->base_note = mus_header_base_note(); - } - previous_sf = sf; - return(sf); -} - -static sound_file *read_sound_file_header(const char *name) -{ - mus_sound_initialize(); - if (mus_header_read(name) != MUS_ERROR) - return(fill_sf_record(name, add_to_sound_table(name))); - return(NULL); -} - -static sound_file *getsf(const char *arg) -{ - sound_file *sf = NULL; - if (arg == NULL) return(NULL); - sf = find_sound_file(arg); - if (sf) return(sf); - return(read_sound_file_header(arg)); -} - -#define MUS_SF(Filename, Expression) \ - sound_file *sf; \ - sf = getsf(Filename); \ - if (sf) return(Expression); \ - return(MUS_ERROR) - -off_t mus_sound_samples(const char *arg) {MUS_SF(arg, sf->samples);} -off_t mus_sound_frames(const char *arg) {MUS_SF(arg, (sf->chans > 0) ? (sf->samples / sf->chans) : 0);} -int mus_sound_datum_size(const char *arg) {MUS_SF(arg, sf->datum_size);} -off_t mus_sound_data_location(const char *arg) {MUS_SF(arg, sf->data_location);} -int mus_sound_chans(const char *arg) {MUS_SF(arg, sf->chans);} -int mus_sound_srate(const char *arg) {MUS_SF(arg, sf->srate);} -int mus_sound_header_type(const char *arg) {MUS_SF(arg, sf->header_type);} -int mus_sound_data_format(const char *arg) {MUS_SF(arg, sf->data_format);} -int mus_sound_original_format(const char *arg) {MUS_SF(arg, sf->original_sound_format);} -off_t mus_sound_comment_start(const char *arg) {MUS_SF(arg, sf->comment_start);} -off_t mus_sound_comment_end(const char *arg) {MUS_SF(arg, sf->comment_end);} -off_t mus_sound_length(const char *arg) {MUS_SF(arg, sf->true_file_length);} -int mus_sound_fact_samples(const char *arg) {MUS_SF(arg, sf->fact_samples);} -time_t mus_sound_write_date(const char *arg) {MUS_SF(arg, sf->write_date);} -int mus_sound_type_specifier(const char *arg) {MUS_SF(arg, sf->type_specifier);} -int mus_sound_block_align(const char *arg) {MUS_SF(arg, sf->block_align);} -int mus_sound_bits_per_sample(const char *arg) {MUS_SF(arg, sf->bits_per_sample);} - -float mus_sound_duration(const char *arg) -{ - float val = -1.0; - sound_file *sf; - sf = getsf(arg); - if (sf) - { - if ((sf->chans > 0) && (sf->srate > 0)) - val = (float)((double)(sf->samples) / ((float)(sf->chans) * (float)(sf->srate))); - else val = 0.0; - } - return(val); -} - -int *mus_sound_loop_info(const char *arg) -{ - sound_file *sf; - int *info; - sf = getsf(arg); - if ((sf) && (sf->loop_modes)) - { - info = (int *)CALLOC(MUS_LOOP_INFO_SIZE, sizeof(int)); - if (sf->loop_modes[0] != 0) - { - info[0] = sf->loop_starts[0]; - info[1] = sf->loop_ends[0]; - info[6] = sf->loop_modes[0]; - } - if (sf->loop_modes[1] != 0) - { - info[2] = sf->loop_starts[1]; - info[3] = sf->loop_ends[1]; - info[7] = sf->loop_modes[1]; - } - info[4] = sf->base_note; - info[5] = sf->base_detune; - return(info); - } - else return(NULL); -} - -void mus_sound_set_loop_info(const char *arg, int *loop) -{ - sound_file *sf; - sf = getsf(arg); - if (sf) - { - if (sf->loop_modes == NULL) - { - sf->loop_modes = (int *)CALLOC(2, sizeof(int)); - sf->loop_starts = (int *)CALLOC(2, sizeof(int)); - sf->loop_ends = (int *)CALLOC(2, sizeof(int)); - } - sf->loop_modes[0] = loop[6]; - if (loop[6] != 0) - { - sf->loop_starts[0] = loop[0]; - sf->loop_ends[0] = loop[1]; - } - else - { - sf->loop_starts[0] = 0; - sf->loop_ends[0] = 0; - } - sf->loop_modes[1] = loop[7]; - if (loop[7] != 0) - { - sf->loop_starts[1] = loop[2]; - sf->loop_ends[1] = loop[3]; - } - else - { - sf->loop_starts[1] = 0; - sf->loop_ends[1] = 0; - } - sf->base_note = loop[4]; - sf->base_detune = loop[5]; - } -} - -char *mus_sound_comment(const char *name) -{ - off_t start, end, len; - int fd, full_len; /* comment string lengths */ - char *sc = NULL, *auxcom; - sound_file *sf = NULL; - sf = getsf(name); - if (sf == NULL) return(NULL); - start = mus_sound_comment_start(name); - end = mus_sound_comment_end(name); - if (end == 0) - { - if (sf->aux_comment_start) - { - if (mus_sound_header_type(name) == MUS_RIFF) - return(mus_header_riff_aux_comment(name, - sf->aux_comment_start, - sf->aux_comment_end)); - if ((mus_sound_header_type(name) == MUS_AIFF) || - (mus_sound_header_type(name) == MUS_AIFC)) - return(mus_header_aiff_aux_comment(name, - sf->aux_comment_start, - sf->aux_comment_end)); - } - return(NULL); - } - if (end > mus_sound_length(name)) return(NULL); - len = end - start + 1; - if (len > 0) - { - /* open and get the comment */ - size_t bytes; - fd = mus_file_open_read(name); - if (fd == -1) return(NULL); - lseek(fd, start, SEEK_SET); - sc = (char *)CALLOC(len + 1, sizeof(char)); - bytes = read(fd, sc, len); - CLOSE(fd, name); - if (((mus_sound_header_type(name) == MUS_AIFF) || - (mus_sound_header_type(name) == MUS_AIFC)) && - (sf->aux_comment_start) && - (bytes != 0)) - { - auxcom = mus_header_aiff_aux_comment(name, - sf->aux_comment_start, - sf->aux_comment_end); - if (auxcom) - { - full_len = strlen(auxcom) + strlen(sc) + 2; - sc = (char *)REALLOC(sc, full_len * sizeof(char)); - strcat(sc, "\n"); - strcat(sc, auxcom); - } - } - } - return(sc); -} - -int mus_sound_open_input(const char *arg) -{ - int fd = -1; - if (!(mus_file_probe(arg))) - mus_error(MUS_CANT_OPEN_FILE, S_mus_sound_open_input " can't open %s: %s", arg, STRERROR(errno)); - else - { - sound_file *sf = NULL; - mus_sound_initialize(); - sf = find_sound_file(arg); - if (!sf) - sf = read_sound_file_header(arg); - if (sf) - { - fd = mus_file_open_read(arg); - mus_file_open_descriptors(fd, arg, sf->data_format, sf->datum_size, sf->data_location, sf->chans, sf->header_type); - lseek(fd, sf->data_location, SEEK_SET); - } - } - return(fd); -} - -int mus_sound_open_output(const char *arg, int srate, int chans, int data_format, int header_type, const char *comment) -{ - int fd = MUS_ERROR, err, comlen = 0; - if (comment) comlen = strlen(comment); - mus_sound_initialize(); - mus_sound_forget(arg); - err = mus_header_write(arg, header_type, srate, chans, 0, 0, data_format, comment, comlen); - if (err != MUS_ERROR) - { - fd = mus_file_open_write(arg); - if (fd != -1) - mus_file_open_descriptors(fd, - arg, - data_format, - mus_bytes_per_sample(data_format), - mus_header_data_location(), - chans, - header_type); - } - return(fd); -} - -int mus_sound_reopen_output(const char *arg, int chans, int format, int type, off_t data_loc) -{ - int fd; - mus_sound_initialize(); - fd = mus_file_reopen_write(arg); - if (fd != -1) - mus_file_open_descriptors(fd, arg, format, mus_bytes_per_sample(format), data_loc, chans, type); - return(fd); -} - -int mus_sound_close_input(int fd) -{ - return(mus_file_close(fd)); /* this closes the clm file descriptors */ -} - -int mus_sound_close_output(int fd, off_t bytes_of_data) -{ - char *name; - name = mus_file_fd_name(fd); - if (name) - { - int err = MUS_ERROR, old_type; - char *fname; - fname = strdup(name); /* strdup defined, if necessary, in io.c */ - old_type = mus_file_header_type(fd); - err = mus_file_close(fd); /* this frees the original fd->name, so we copied above */ - /* fd is NULL now */ - mus_sound_forget(fname); - mus_header_change_data_size(fname, old_type, bytes_of_data); - free(fname); - return(err); - } - return(MUS_ERROR); -} - -typedef enum {SF_CHANS, SF_SRATE, SF_TYPE, SF_FORMAT, SF_LOCATION, SF_SIZE} sf_field_t; - -static int mus_sound_set_field(const char *arg, sf_field_t field, int val) -{ - sound_file *sf; - sf = getsf(arg); - if (sf) - { - switch (field) - { - case SF_CHANS: sf->chans = val; break; - case SF_SRATE: sf->srate = val; break; - case SF_TYPE: sf->header_type = val; break; - case SF_FORMAT: sf->data_format = val; sf->datum_size = mus_bytes_per_sample(val); break; - default: return(MUS_ERROR); break; - } - return(MUS_NO_ERROR); - } - return(MUS_ERROR); -} - -static int mus_sound_set_off_t_field(const char *arg, sf_field_t field, off_t val) -{ - sound_file *sf; - sf = getsf(arg); - if (sf) - { - switch (field) - { - case SF_SIZE: sf->samples = val; break; - case SF_LOCATION: sf->data_location = val; break; - default: return(MUS_ERROR); break; - } - return(MUS_NO_ERROR); - } - return(MUS_ERROR); -} - -int mus_sound_set_chans(const char *arg, int val) {return(mus_sound_set_field(arg, SF_CHANS, val));} -int mus_sound_set_srate(const char *arg, int val) {return(mus_sound_set_field(arg, SF_SRATE, val));} -int mus_sound_set_header_type(const char *arg, int val) {return(mus_sound_set_field(arg, SF_TYPE, val));} -int mus_sound_set_data_format(const char *arg, int val) {return(mus_sound_set_field(arg, SF_FORMAT, val));} -int mus_sound_set_data_location(const char *arg, off_t val) {return(mus_sound_set_off_t_field(arg, SF_LOCATION, val));} -int mus_sound_set_samples(const char *arg, off_t val) {return(mus_sound_set_off_t_field(arg, SF_SIZE, val));} - -int mus_sound_override_header(const char *arg, int srate, int chans, int format, int type, off_t location, off_t size) -{ - sound_file *sf; - /* perhaps once a header has been over-ridden, we should not reset the relevant fields upon re-read? */ - sf = getsf(arg); - if (sf) - { - if (location != -1) sf->data_location = location; - if (size != -1) sf->samples = size; - if (format != -1) - { - sf->data_format = format; - sf->datum_size = mus_bytes_per_sample(format); - } - if (srate != -1) sf->srate = srate; - if (chans != -1) sf->chans = chans; - if (type != -1) sf->header_type = type; - return(MUS_NO_ERROR); - } - return(MUS_ERROR); -} - -bool mus_sound_maxamp_exists(const char *ifile) -{ - sound_file *sf; - bool val = false; - sf = getsf(ifile); - val = ((sf) && (sf->maxamps)); - return(val); -} - -off_t mus_sound_maxamps(const char *ifile, int chans, mus_sample_t *vals, off_t *times) -{ - int ifd, ichans, chn, j; - int i, bufnum; - off_t n, frames, curframes; - mus_sample_t abs_samp; - mus_sample_t *buffer, *samp; - off_t *time; - mus_sample_t **ibufs; - sound_file *sf; - sf = getsf(ifile); - if (sf->chans <= 0) return(MUS_ERROR); - if ((sf) && (sf->maxamps)) - { - if (chans > sf->chans) ichans = sf->chans; else ichans = chans; - for (chn = 0; chn < ichans; chn++) - { - times[chn] = sf->maxtimes[chn]; - vals[chn] = sf->maxamps[chn]; - } - frames = sf->samples / sf->chans; - return(frames); - } - ifd = mus_sound_open_input(ifile); - if (ifd == MUS_ERROR) return(MUS_ERROR); - ichans = mus_sound_chans(ifile); - frames = mus_sound_frames(ifile); - if (frames == 0) - { - mus_sound_close_input(ifd); - return(0); - } - mus_file_seek_frame(ifd, 0); - ibufs = (mus_sample_t **)CALLOC(ichans, sizeof(mus_sample_t *)); - bufnum = 8192; - for (j = 0; j < ichans; j++) - ibufs[j] = (mus_sample_t *)CALLOC(bufnum, sizeof(mus_sample_t)); - time = (off_t *)CALLOC(ichans, sizeof(off_t)); - samp = (mus_sample_t *)CALLOC(ichans, sizeof(mus_sample_t)); - for (n = 0; n < frames; n += bufnum) - { - if ((n + bufnum) < frames) - curframes = bufnum; - else curframes = (frames - n); - mus_file_read(ifd, 0, curframes - 1, ichans, ibufs); - for (chn = 0; chn < ichans; chn++) - { - buffer = (mus_sample_t *)(ibufs[chn]); - for (i = 0; i < curframes; i++) - { - abs_samp = mus_sample_abs(buffer[i]); - if (abs_samp > samp[chn]) - { - time[chn] = i + n; - samp[chn] = abs_samp; - } - } - } - } - mus_sound_close_input(ifd); - mus_sound_set_maxamps(ifile, ichans, samp, time); /* save the complete set */ - if (ichans > chans) ichans = chans; - for (chn = 0; chn < ichans; chn++) - { - times[chn] = time[chn]; - vals[chn] = samp[chn]; - } - FREE(time); - FREE(samp); - for (j = 0; j < ichans; j++) FREE(ibufs[j]); - FREE(ibufs); - return(frames); -} - -int mus_sound_set_maxamps(const char *ifile, int chans, mus_sample_t *vals, off_t *times) -{ - sound_file *sf; - sf = getsf(ifile); - if (sf) - { - int i, ichans = 0; - if (sf->maxamps) - { - if (chans > sf->chans) ichans = sf->chans; else ichans = chans; - for (i = 0; i < ichans; i++) - { - sf->maxtimes[i] = times[i]; - sf->maxamps[i] = vals[i]; - } - } - else - { - ichans = mus_sound_chans(ifile); - if (sf->maxamps == NULL) - { - sf->maxamps = (mus_sample_t *)CALLOC(ichans, sizeof(mus_sample_t)); - sf->maxtimes = (off_t *)CALLOC(ichans, sizeof(off_t)); - } - if (ichans > chans) ichans = chans; - for (i = 0; i < ichans; i++) - { - sf->maxtimes[i] = times[i]; - sf->maxamps[i] = vals[i]; - } - } - return(MUS_NO_ERROR); - } - return(MUS_ERROR); -} - -int mus_file_to_array(const char *filename, int chan, int start, int samples, mus_sample_t *array) -{ - int ifd, chans, total_read; - mus_sample_t **bufs; - ifd = mus_sound_open_input(filename); - if (ifd == MUS_ERROR) return(MUS_ERROR); - chans = mus_sound_chans(filename); - if (chan >= chans) - { - mus_sound_close_input(ifd); - return(mus_error(MUS_NO_SUCH_CHANNEL, "mus_file_to_array can't read %s channel %d (file has %d chans)", filename, chan, chans)); - } - bufs = (mus_sample_t **)CALLOC(chans, sizeof(mus_sample_t *)); - bufs[chan] = array; - mus_file_seek_frame(ifd, start); - total_read = mus_file_read_any(ifd, 0, chans, samples, bufs, bufs); - mus_sound_close_input(ifd); - FREE(bufs); - return(total_read); -} - -char *mus_array_to_file_with_error(const char *filename, mus_sample_t *ddata, int len, int srate, int channels) -{ - /* put ddata into a sound file, taking byte order into account */ - /* assume ddata is interleaved already if more than one channel */ - int fd, err = MUS_NO_ERROR; - mus_sample_t *bufs[1]; - mus_sound_forget(filename); - fd = mus_file_create(filename); - if (fd == -1) - return("mus_array_to_file can't create output file"); - err = mus_file_open_descriptors(fd, filename, - MUS_OUT_FORMAT, - mus_bytes_per_sample(MUS_OUT_FORMAT), - 28, channels, MUS_NEXT); - if (err != MUS_ERROR) - { - err = mus_header_write_next_header(fd, srate, channels, 28, len /* out chans = 1?? */, MUS_OUT_FORMAT, NULL, 0); - if (err != MUS_ERROR) - { - bufs[0] = ddata; - err = mus_file_write(fd, 0, len - 1, 1, bufs); /* 1 = chans?? */ - } - } - mus_file_close(fd); - if (err == MUS_ERROR) - return("mus_array_to_file write error"); - return(NULL); -} - -int mus_array_to_file(const char *filename, mus_sample_t *ddata, int len, int srate, int channels) -{ - char *errmsg; - errmsg = mus_array_to_file_with_error(filename, ddata, len, srate, channels); - if (errmsg) - return(mus_error(MUS_CANT_OPEN_FILE, errmsg)); - return(MUS_NO_ERROR); -} - -int mus_file_to_float_array(const char *filename, int chan, off_t start, int samples, Float *array) -{ -#if SNDLIB_USE_FLOATS - return(mus_file_to_array(filename, chan, start, samples, array)); -#else - mus_sample_t *idata; - int i, len; - idata = (mus_sample_t *)CALLOC(samples, sizeof(mus_sample_t)); - len = mus_file_to_array(filename, chan, start, samples, idata); - if (len != -1) - for (i = 0; i < samples; i++) - array[i] = MUS_SAMPLE_TO_FLOAT(idata[i]); - FREE(idata); - return(len); -#endif -} - -int mus_float_array_to_file(const char *filename, Float *ddata, int len, int srate, int channels) -{ - char *errmsg; -#if SNDLIB_USE_FLOATS - errmsg = mus_array_to_file_with_error(filename, ddata, len, srate, channels); -#else - mus_sample_t *idata; - int i; - idata = (mus_sample_t *)CALLOC(len, sizeof(mus_sample_t)); - for (i = 0; i < len; i++) - idata[i] = MUS_FLOAT_TO_SAMPLE(ddata[i]); - errmsg = mus_array_to_file_with_error(filename, idata, len, srate, channels); - FREE(idata); -#endif - if (errmsg) - return(mus_error(MUS_CANT_OPEN_FILE, errmsg)); - return(MUS_NO_ERROR); -} |