You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

177 lines
3.1 KiB

/* Extended Module Player
* Copyright (C) 1996-2016 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See the COPYING
* file for more information.
*/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "sound.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
static int fd;
static int format_16bit;
static int swap_endian;
static long size;
struct sound_driver sound_wav;
static void write_16l(int fd, unsigned short v)
{
unsigned char x;
x = v & 0xff;
write(fd, &x, 1);
x = v >> 8;
write(fd, &x, 1);
}
static void write_32l(int fd, unsigned int v)
{
unsigned char x;
x = v & 0xff;
write(fd, &x, 1);
x = (v >> 8) & 0xff;
write(fd, &x, 1);
x = (v >> 16) & 0xff;
write(fd, &x, 1);
x = (v >> 24) & 0xff;
write(fd, &x, 1);
}
static int init(struct options *options)
{
char *buf;
unsigned int len = 0;
unsigned short chan;
unsigned int sampling_rate, bytes_per_second;
unsigned short bytes_per_frame, bits_per_sample;
swap_endian = is_big_endian();
if (options->out_file == NULL) {
options->out_file = "out.wav";
}
if (strcmp(options->out_file, "-")) {
fd = open(options->out_file, O_WRONLY | O_CREAT | O_TRUNC
| O_BINARY, 0644);
if (fd < 0)
return -1;
} else {
fd = 1;
}
if (strcmp(options->out_file, "-")) {
int len = strlen(sound_wav.description) +
strlen(options->out_file) + 8;
if ((buf = malloc(len)) == NULL)
return -1;
snprintf(buf, len, "%s: %s", sound_wav.description,
options->out_file);
sound_wav.description = buf;
} else {
sound_wav.description = strdup("WAV writer: stdout");
len = -1;
}
write(fd, "RIFF", 4);
write_32l(fd, len);
write(fd, "WAVE", 4);
chan = options->format & XMP_FORMAT_MONO ? 1 : 2;
sampling_rate = options->rate;
bits_per_sample = options->format & XMP_FORMAT_8BIT ? 8 : 16;
if (bits_per_sample == 8) {
options->format |= XMP_FORMAT_UNSIGNED;
format_16bit = 0;
} else {
options->format &= ~XMP_FORMAT_UNSIGNED;
format_16bit = 1;
}
bytes_per_frame = chan * bits_per_sample / 8;
bytes_per_second = sampling_rate * bytes_per_frame;
write(fd, "fmt ", 4);
write_32l(fd, 16);
write_16l(fd, 1);
write_16l(fd, chan);
write_32l(fd, sampling_rate);
write_32l(fd, bytes_per_second);
write_16l(fd, bytes_per_frame);
write_16l(fd, bits_per_sample);
write(fd, "data", 4);
write_32l(fd, len);
size = 0;
return 0;
}
static void play(void *b, int len)
{
if (swap_endian && format_16bit) {
convert_endian(b, len);
}
write(fd, b, len);
size += len;
}
static void deinit(void)
{
if (lseek(fd, 40, SEEK_SET) == 40) {
write_32l(fd, size);
}
if (lseek(fd, 4, SEEK_SET) == 4) {
write_32l(fd, size + 40);
}
if (fd > 0) {
close(fd);
}
free((void *)sound_wav.description);
}
static void flush(void)
{
}
static void onpause(void)
{
}
static void onresume(void)
{
}
struct sound_driver sound_wav = {
"wav",
"WAV writer",
NULL,
init,
deinit,
play,
flush,
onpause,
onresume
};