summaryrefslogtreecommitdiff
path: root/third_party/resample/sndlib-20/sound.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/resample/sndlib-20/sound.c')
-rw-r--r--third_party/resample/sndlib-20/sound.c1072
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);
-}