X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_em%2Fsound.c;fp=src%2Fgame_em%2Fsound.c;h=b0bac6a3995ba3ba8cce1697092554adde3e4462;hb=12a92e1aa977ccfcc6223eaabc92d6c3ca84e2ff;hp=67407282d771ac6e2a326de1b5b7adede0811e38;hpb=c405cf118d3d31c2b6e1fe935671ecdaeb031f8f;p=rocksndiamonds.git diff --git a/src/game_em/sound.c b/src/game_em/sound.c index 67407282..b0bac6a3 100644 --- a/src/game_em/sound.c +++ b/src/game_em/sound.c @@ -34,307 +34,460 @@ static char audioname[] = "/dev/audio"; -static const int sound_priority[SAMPLE_MAX] = { - SAMPLE_exit, SAMPLE_die, SAMPLE_time, SAMPLE_boom, SAMPLE_tick, - SAMPLE_collect, SAMPLE_roll, SAMPLE_push, SAMPLE_dynamite, SAMPLE_press, - SAMPLE_door, SAMPLE_dirt, SAMPLE_blank, SAMPLE_android, SAMPLE_ball, - SAMPLE_grow, SAMPLE_squash, SAMPLE_crack, SAMPLE_slurp, SAMPLE_drip, - SAMPLE_wonder, SAMPLE_wheel, SAMPLE_stone, SAMPLE_spring, SAMPLE_diamond, - SAMPLE_nut, SAMPLE_bug, SAMPLE_tank, SAMPLE_eater, SAMPLE_alien, - SAMPLE_acid +static const int sound_priority[SAMPLE_MAX] = +{ + SAMPLE_exit, SAMPLE_die, SAMPLE_time, SAMPLE_boom, SAMPLE_tick, + SAMPLE_collect, SAMPLE_roll, SAMPLE_push, SAMPLE_dynamite, SAMPLE_press, + SAMPLE_door, SAMPLE_dirt, SAMPLE_blank, SAMPLE_android, SAMPLE_ball, + SAMPLE_grow, SAMPLE_squash, SAMPLE_crack, SAMPLE_slurp, SAMPLE_drip, + SAMPLE_wonder, SAMPLE_wheel, SAMPLE_stone, SAMPLE_spring, SAMPLE_diamond, + SAMPLE_nut, SAMPLE_bug, SAMPLE_tank, SAMPLE_eater, SAMPLE_alien, + SAMPLE_acid }; int sound_thread(void) { - int audio_fd; /* file descriptor of /dev/audio or -1 if not open */ - int audio_format; - int sample_rate; - int fragment_size; - unsigned char *audio_buffer; /* actual buffer pumped to /dev/audio */ - short *mix_buffer; - - char sound_play[SAMPLE_MAX]; /* if set, we should be playing these sounds */ - long sound_pos[SAMPLE_MAX]; /* position in the sound */ - int mix_play[MIXER_MAX]; /* which sounds we have chosen to mix (calculated each time) */ - int mix_count; - - int i; - -loop: - audio_fd = -1; - audio_format = AUDIO_ULAW; /* defaults for non-OSS /dev/audio */ - sample_rate = 8000; - fragment_size = 256; - audio_buffer = 0; - mix_buffer = 0; - mix_count = 0; - - memset(sound_play, 0, sizeof(sound_play)); /* not playing any sounds */ - - for(;;) { - for(;;) { - -/* pick sounds to play, if any */ - if(sound_play[SAMPLE_exit] || sound_play[SAMPLE_die]) sound_play[SAMPLE_boom] = 0; /* no explosions if player goes home */ - mix_count = 0; - for(i = 0; i < SAMPLE_MAX; i++) { - if(sound_play[sound_priority[i]]) { - mix_play[mix_count++] = sound_priority[i]; - if(mix_count == MIXER_MAX) break; /* cant mix too many sounds at once */ - } - } - -/* check for incoming messages */ - if(mix_count || audio_fd != -1) { /* dont block if we are playing sounds */ - fd_set rfds; - struct timeval tv; - FD_ZERO(&rfds); - FD_SET(sound_pipe[0], &rfds); - tv.tv_sec = 0; - tv.tv_usec = 0; /* (900000 * fragment_size / sample_rate) */ - i = select(sound_pipe[0] + 1, &rfds, 0, 0, &tv); /* dont block */ - if(i == -1) { - fprintf(stderr, "%s: %s: %s\n", progname, "select failed", strerror(errno)); - goto fail; - } - if(i == 0) break; /* no messages */ - } - -/* get a message and start a sound */ - i = read(sound_pipe[0], &play, sizeof(play)); - if(i == -1) { - fprintf(stderr, "%s: %s: %s\n", progname, "read failed", strerror(errno)); - goto fail; - } - if(i == 0) { - fprintf(stderr, "%s: %s: %s\n", progname, "read sound", "Broken pipe"); - goto fail; - } - if(i != sizeof(play)) { - fprintf(stderr, "%s: %s\n", progname, "bad message length"); - goto fail; - } - for(i = 0; i < SAMPLE_MAX; i++) { - if(play[i]) { - sound_play[i] = 1; /* play this sound */ - sound_pos[i] = 0; /* start it from the start */ - } - } - } - -/* open the audio device if there are sounds to play */ - if(mix_count && audio_fd == -1) { - audio_fd = open(audioname, O_WRONLY); - if(audio_fd == -1) goto reset; -#ifdef OPEN_SOUND_SYSTEM - i = 0x00020008; - if(ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1) { - fprintf(stderr, "%s: \"%s\": %s (%d): %s\n", progname, audioname, "unable to set fragment size", 512, strerror(errno)); - goto reset; - } - if(ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i) == -1) { - fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, "unable to query audio format", strerror(errno)); - goto reset; - } - audio_format = (i & AFMT_U8) ? AFMT_U8 : AFMT_MU_LAW; /* prefer 8 bit unsigned and fall back on mu-law */ - i = audio_format; - if(ioctl(audio_fd, SNDCTL_DSP_SETFMT, &i) == -1) { - fprintf(stderr, "%s: \"%s\": %s (%d): %s\n", progname, audioname, "unable to set audio format", audio_format, strerror(errno)); - goto reset; - } - if(i == AFMT_MU_LAW) { - audio_format = AUDIO_ULAW; - } else if(i == AFMT_U8) { - audio_format = AUDIO_U8; - } else { - fprintf(stderr, "%s: \"%s\": %s (%d)\n", progname, audioname, "audio format required by device not supported", i); - goto reset; - } - i = 1; - if(ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &i) == -1) { - fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, "unable to set channels to mono", strerror(errno)); - goto reset; - } - if(i != 1) { - fprintf(stderr, "%s: \"%s\": %s (%d)\n", progname, audioname, "channels required by device not supported", i); - goto reset; - } - i = 8000; - if(ioctl(audio_fd, SNDCTL_DSP_SPEED, &i) == -1) { - fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, "unable to set sampling rate", strerror(errno)); - goto reset; - } - sample_rate = i; - if(ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &i) == -1) { - fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, "unable to get block size", strerror(errno)); - goto reset; - } - fragment_size = i; -#else - if(fcntl(audio_fd, F_SETFL, O_NONBLOCK) == -1) { - fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, "unable to make audio non blocking", strerror(errno)); - goto reset; - } -#endif /* OPEN_SOUND_SYSTEM */ - audio_buffer = malloc(fragment_size * sizeof(*audio_buffer)); - if(audio_buffer == 0) { - fprintf(stderr, "%s: %s (%d): %s\n", progname, "unable to malloc audio buffer", fragment_size * sizeof(*audio_buffer), strerror(errno)); - goto fail; - } - mix_buffer = malloc(fragment_size * sizeof(*mix_buffer)); - if(mix_buffer == 0) { - fprintf(stderr, "%s: %s (%d): %s\n", progname, "unable to malloc mixing buffer", fragment_size * sizeof(*mix_buffer), strerror(errno)); - goto fail; - } - } - -/* close the audio device if no sounds are playing */ - if(mix_count == 0 && audio_fd != -1) { - close(audio_fd); - free(audio_buffer); - free(mix_buffer); - audio_fd = -1; - audio_buffer = 0; - mix_buffer = 0; - } - -/* if we are playing sounds and the audio device is open, mix them */ - if(mix_count && audio_fd != -1) { - - memset(mix_buffer, 0, fragment_size * sizeof(*mix_buffer)); /* prepare mix buffer */ - - for(i = 0; i < mix_count; i++) { - register short *mix_ptr = mix_buffer; - register short *sound_ptr = sound_data[mix_play[i]] + sound_pos[mix_play[i]]; - register long count = sound_length[mix_play[i]] - sound_pos[mix_play[i]]; - if(count > fragment_size) count = fragment_size; - while(count--) *mix_ptr++ += *sound_ptr++; /* mix the sounds in */ - } - switch(audio_format) { - case AUDIO_ULAW: - for(i = 0; i < fragment_size; i++) audio_buffer[i] = linear_to_ulaw[mix_buffer[i] + 32768]; - break; - case AUDIO_U8: - for(i = 0; i < fragment_size; i++) audio_buffer[i] = (mix_buffer[i] + 32768) >> 8; - break; - } - -/* advance sound pointers */ - for(i = 0; i < SAMPLE_MAX; i++) { - if(sound_play[i]) { - if(sound_pos[i] + fragment_size < sound_length[i]) { - sound_pos[i] += fragment_size; - } else { - sound_play[i] = 0; - } - } - } - -/* send the data to the audio device */ - i = write(audio_fd, audio_buffer, fragment_size); - if(i == -1) { - fprintf(stderr, "%s: %s: %s\n", progname, "write error", strerror(errno)); - goto reset; - } - if(i != fragment_size) { - fprintf(stderr, "%s: %s\n", progname, "bad write length"); - goto reset; - } - } - } /* for */ - -reset: - if(audio_fd != -1) close(audio_fd); - if(audio_buffer) free(audio_buffer); - if(mix_buffer) free(mix_buffer); - goto loop; /* back to top */ - -fail: - if(audio_fd != -1) close(audio_fd); - if(audio_buffer) free(audio_buffer); - if(mix_buffer) free(mix_buffer); - return(0); -} - -int read_sample(char *name, short **data, long *length) -{ - int result; - FILE *file = 0; - short *dataptr = 0; - long datalength; - - int i, actual, ch; - unsigned char buffer[24]; - unsigned long temp; - - file = fopen(name, "rb"); - if(file == 0) { - fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, name, "open error", strerror(errno)); - result = 1; goto fail; - } - actual = fread(buffer, 1, 24, file); - if(actual == -1) { - fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, name, "read error", strerror(errno)); - result = 1; goto fail; - } - if(actual < 24) { - fprintf(stderr, "%s: \"%s\": %s\n", progname, name, "premature eof"); - result = 1; goto fail; + int audio_fd; /* file descriptor of /dev/audio or -1 if not open */ + int audio_format; + int sample_rate; + int fragment_size; + unsigned char *audio_buffer; /* actual buffer pumped to /dev/audio */ + short *mix_buffer; + + char sound_play[SAMPLE_MAX]; /* if set, we should be playing these sounds */ + long sound_pos[SAMPLE_MAX]; /* position in the sound */ + int mix_play[MIXER_MAX]; /* which sounds we have chosen to mix (calculated each time) */ + int mix_count; + int i; + + loop: + + audio_fd = -1; + audio_format = AUDIO_ULAW; /* defaults for non-OSS /dev/audio */ + sample_rate = 8000; + fragment_size = 256; + audio_buffer = 0; + mix_buffer = 0; + mix_count = 0; + + memset(sound_play, 0, sizeof(sound_play)); /* not playing any sounds */ + + for (;;) + { + for (;;) + { + + /* pick sounds to play, if any */ + if (sound_play[SAMPLE_exit] || sound_play[SAMPLE_die]) + sound_play[SAMPLE_boom] = 0; /* no explosions if player goes home */ + + mix_count = 0; + for (i = 0; i < SAMPLE_MAX; i++) + { + if (sound_play[sound_priority[i]]) + { + mix_play[mix_count++] = sound_priority[i]; + + if (mix_count == MIXER_MAX) + break; /* cant mix too many sounds at once */ } - temp = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; /* magic */ - if(temp != 0x2e736e64) { - fprintf(stderr, "%s: \"%s\": %s\n", progname, name, "unrecognized file format"); - result = 1; goto fail; - } - temp = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7]; /* header length */ - if(temp < 24) { - fprintf(stderr, "%s: \"%s\": %s\n", progname, name, "bad header length"); - result = 1; goto fail; - } - actual = temp; - for(i = 24; i < actual; i++) { /* skip the rest of the header */ - ch = fgetc(file); - if(ch == EOF) break; + } + + /* check for incoming messages */ + if (mix_count || audio_fd != -1) + { + /* dont block if we are playing sounds */ + fd_set rfds; + struct timeval tv; + FD_ZERO(&rfds); + FD_SET(sound_pipe[0], &rfds); + tv.tv_sec = 0; + tv.tv_usec = 0; /* (900000 * fragment_size / sample_rate) */ + i = select(sound_pipe[0] + 1, &rfds, 0, 0, &tv); /* dont block */ + + if (i == -1) + { + fprintf(stderr, "%s: %s: %s\n", progname, "select failed", + strerror(errno)); + goto fail; } - temp = buffer[8] << 24 | buffer[9] << 16 | buffer[10] << 8 | buffer[11]; /* data length */ - datalength = temp; - temp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; /* encoding */ - if(temp != 1) { - fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name, "bad encoding type", temp); - result = 1; goto fail; - } - temp = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19]; /* sample rate */ - if(temp != 8000) { - fprintf(stderr, "%s: \"%s\": %s (%ld != 8000)\n", progname, name, "bad sample rate", temp); - result = 1; goto fail; - } - temp = buffer[20] << 24 | buffer[21] << 16 | buffer[22] << 8 | buffer[23]; /* channels */ - if(temp != 1) { - fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name, "unsupported channels", temp); - result = 1; goto fail; + if (i == 0) + break; /* no messages */ + } + + /* get a message and start a sound */ + i = read(sound_pipe[0], &play, sizeof(play)); + + if (i == -1) + { + fprintf(stderr, "%s: %s: %s\n", progname, "read failed", + strerror(errno)); + goto fail; + } + + if (i == 0) + { + fprintf(stderr, "%s: %s: %s\n", progname, "read sound", "Broken pipe"); + goto fail; + } + + if (i != sizeof(play)) + { + fprintf(stderr, "%s: %s\n", progname, "bad message length"); + goto fail; + } + + for (i = 0; i < SAMPLE_MAX; i++) + { + if (play[i]) + { + sound_play[i] = 1; /* play this sound */ + sound_pos[i] = 0; /* start it from the start */ } + } + } - dataptr = malloc(datalength * sizeof(*dataptr)); - if(dataptr == 0) { - fprintf(stderr, "%s: \"%s\": %s (%ld): %s\n", progname, name, "unable to malloc buffer", datalength * sizeof(*dataptr), strerror(errno)); - result = 1; goto fail; - } + /* open the audio device if there are sounds to play */ + if (mix_count && audio_fd == -1) + { + audio_fd = open(audioname, O_WRONLY); + + if (audio_fd == -1) + goto reset; + +#ifdef OPEN_SOUND_SYSTEM + i = 0x00020008; + + if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1) + { + fprintf(stderr, "%s: \"%s\": %s (%d): %s\n", progname, audioname, + "unable to set fragment size", 512, strerror(errno)); + goto reset; + } + + if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i) == -1) + { + fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, + "unable to query audio format", strerror(errno)); + goto reset; + } + + /* prefer 8 bit unsigned and fall back on mu-law */ + audio_format = (i & AFMT_U8) ? AFMT_U8 : AFMT_MU_LAW; + + i = audio_format; + if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &i) == -1) + { + fprintf(stderr, "%s: \"%s\": %s (%d): %s\n", progname, audioname, + "unable to set audio format", audio_format, strerror(errno)); + goto reset; + } + + if (i == AFMT_MU_LAW) + { + audio_format = AUDIO_ULAW; + } + else if (i == AFMT_U8) + { + audio_format = AUDIO_U8; + } + else + { + fprintf(stderr, "%s: \"%s\": %s (%d)\n", progname, audioname, + "audio format required by device not supported", i); + goto reset; + } + + i = 1; + if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &i) == -1) + { + fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, + "unable to set channels to mono", strerror(errno)); + goto reset; + } + + if (i != 1) + { + fprintf(stderr, "%s: \"%s\": %s (%d)\n", progname, audioname, + "channels required by device not supported", i); + goto reset; + } + + i = 8000; + if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &i) == -1) + { + fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, + "unable to set sampling rate", strerror(errno)); + goto reset; + } + + sample_rate = i; + if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &i) == -1) + { + fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, + "unable to get block size", strerror(errno)); + goto reset; + } + + fragment_size = i; + +#else + if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) == -1) + { + fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, audioname, + "unable to make audio non blocking", strerror(errno)); + goto reset; + } - for(i = 0; i < datalength; i++) { - ch = fgetc(file); - if(ch == EOF) break; - dataptr[i] = ulaw_to_linear[ch]; +#endif /* OPEN_SOUND_SYSTEM */ + + audio_buffer = malloc(fragment_size * sizeof(*audio_buffer)); + if (audio_buffer == 0) + { + fprintf(stderr, "%s: %s (%d): %s\n", progname, + "unable to malloc audio buffer", + fragment_size * sizeof(*audio_buffer), strerror(errno)); + goto fail; + } + + mix_buffer = malloc(fragment_size * sizeof(*mix_buffer)); + if (mix_buffer == 0) + { + fprintf(stderr, "%s: %s (%d): %s\n", progname, + "unable to malloc mixing buffer", + fragment_size * sizeof(*mix_buffer), strerror(errno)); + goto fail; + } + } + + /* close the audio device if no sounds are playing */ + if (mix_count == 0 && audio_fd != -1) + { + close(audio_fd); + free(audio_buffer); + free(mix_buffer); + audio_fd = -1; + audio_buffer = 0; + mix_buffer = 0; + } + + /* if we are playing sounds and the audio device is open, mix them */ + if (mix_count && audio_fd != -1) + { + /* prepare mix buffer */ + memset(mix_buffer, 0, fragment_size * sizeof(*mix_buffer)); + + for (i = 0; i < mix_count; i++) + { + register short *mix_ptr = mix_buffer; + register short *sound_ptr = + sound_data[mix_play[i]] + sound_pos[mix_play[i]]; + register long count = + sound_length[mix_play[i]] - sound_pos[mix_play[i]]; + + if (count > fragment_size) + count = fragment_size; + + while (count--) + *mix_ptr++ += *sound_ptr++; /* mix the sounds in */ + } + + switch(audio_format) + { + case AUDIO_ULAW: + for (i = 0; i < fragment_size; i++) + audio_buffer[i] = linear_to_ulaw[mix_buffer[i] + 32768]; + break; + + case AUDIO_U8: + for (i = 0; i < fragment_size; i++) + audio_buffer[i] = (mix_buffer[i] + 32768) >> 8; + break; + } + + /* advance sound pointers */ + for (i = 0; i < SAMPLE_MAX; i++) + { + if (sound_play[i]) + { + if (sound_pos[i] + fragment_size < sound_length[i]) + { + sound_pos[i] += fragment_size; + } + else + { + sound_play[i] = 0; + } } - fclose(file); - file = 0; - - *data = dataptr; - *length = datalength; - result = 0; -fail: - if(file) fclose(file); - return(result); + } + + /* send the data to the audio device */ + i = write(audio_fd, audio_buffer, fragment_size); + if (i == -1) + { + fprintf(stderr, "%s: %s: %s\n", progname, "write error", + strerror(errno)); + goto reset; + } + + if (i != fragment_size) + { + fprintf(stderr, "%s: %s\n", progname, "bad write length"); + goto reset; + } + } + } /* for */ + + reset: + + if (audio_fd != -1) + close(audio_fd); + if (audio_buffer) + free(audio_buffer); + if (mix_buffer) + free(mix_buffer); + goto loop; /* back to top */ + + fail: + if (audio_fd != -1) + close(audio_fd); + if (audio_buffer) + free(audio_buffer); + if (mix_buffer) + free(mix_buffer); + + return(0); +} + +int read_sample(char *name, short **data, long *length) +{ + int result; + FILE *file = 0; + short *dataptr = 0; + long datalength; + + int i, actual, ch; + unsigned char buffer[24]; + unsigned long temp; + + file = fopen(name, "rb"); + if (file == 0) + { + fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, name, "open error", + strerror(errno)); + result = 1; + goto fail; + } + + actual = fread(buffer, 1, 24, file); + if (actual == -1) + { + fprintf(stderr, "%s: \"%s\": %s: %s\n", progname, name, "read error", + strerror(errno)); + result = 1; + goto fail; + } + + if (actual < 24) + { + fprintf(stderr, "%s: \"%s\": %s\n", progname, name, "premature eof"); + result = 1; + goto fail; + } + + /* magic */ + temp = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; + if (temp != 0x2e736e64) + { + fprintf(stderr, "%s: \"%s\": %s\n", progname, name, + "unrecognized file format"); + result = 1; + goto fail; + } + + /* header length */ + temp = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7]; + if (temp < 24) + { + fprintf(stderr, "%s: \"%s\": %s\n", progname, name, "bad header length"); + result = 1; + goto fail; + } + + actual = temp; + for (i = 24; i < actual; i++) + { + /* skip the rest of the header */ + ch = fgetc(file); + if (ch == EOF) + break; + } + + /* data length */ + temp = buffer[8] << 24 | buffer[9] << 16 | buffer[10] << 8 | buffer[11]; + datalength = temp; + + /* encoding */ + temp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15]; + if (temp != 1) + { + fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name, + "bad encoding type", temp); + result = 1; + goto fail; + } + + /* sample rate */ + temp = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19]; + if (temp != 8000) + { + fprintf(stderr, "%s: \"%s\": %s (%ld != 8000)\n", progname, name, + "bad sample rate", temp); + result = 1; + goto fail; + } + + /* channels */ + temp = buffer[20] << 24 | buffer[21] << 16 | buffer[22] << 8 | buffer[23]; + if (temp != 1) + { + fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name, + "unsupported channels", temp); + result = 1; + goto fail; + } + + dataptr = malloc(datalength * sizeof(*dataptr)); + if (dataptr == 0) + { + fprintf(stderr, "%s: \"%s\": %s (%ld): %s\n", progname, name, + "unable to malloc buffer", datalength * sizeof(*dataptr), + strerror(errno)); + result = 1; + goto fail; + } + + for (i = 0; i < datalength; i++) + { + ch = fgetc(file); + if (ch == EOF) break; + dataptr[i] = ulaw_to_linear[ch]; + } + + fclose(file); + file = 0; + + *data = dataptr; + *length = datalength; + result = 0; + + fail: + + if (file) + fclose(file); + + return(result); } #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */