[xmp] Add wav writer

Signed-off-by: Claudio Matsuoka <cmatsuoka@gmail.com>
master
Claudio Matsuoka 14 years ago
parent 10072637cc
commit 24c218329f
  1. 1
      configure.ac
  2. 2
      src/Makefile
  3. 183
      src/drivers/wav.c
  4. 16
      src/main.c
  5. 2
      src/sound.c
  6. 184
      src/sound_wav.c

@ -6,6 +6,7 @@ AC_ARG_WITH(libxmp, [ --with-libxmp=<path> libxmp prefix (optional)],
libxmp_path="$withval")
AC_PROG_CC
AC_C_BIGENDIAN(AC_DEFINE(ENDIAN_BIG))
if test "$libxmp_path" != ""; then
CPPFLAGS="${CPPFLAGS} -I${libxmp_path}/include"

@ -1,6 +1,6 @@
SRC_OBJS = sound.o sound_null.o terminal.o info.o commands.o \
options.o getopt.o getopt1.o main.o
options.o getopt.o getopt1.o main.o sound_wav.o
SRC_DFILES = Makefile xmp.1 $(SRC_OBJS:.o=.c) common.h getopt.h \
sound_alsa.c sound_coreaudio.c sound_oss.c sound_sndio.c \
sound_bsd.c sound_solaris.c

@ -1,183 +0,0 @@
/* Extended Module Player
* Copyright (C) 1996-2012 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 doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "common.h"
#include "driver.h"
#include "convert.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define DATA(x) (((struct data *)drv_wav.data)->x)
struct data {
int fd;
uint32 size;
};
static int init(struct context_data *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
struct xmp_drv_info drv_wav = {
"wav", /* driver ID */
"WAV writer", /* driver description */
NULL, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* stoptimer */
bufdump, /* bufdump */
};
static void writeval_16l(int fd, uint16 v)
{
uint8 x;
x = v & 0xff;
write(DATA(fd), &x, 1);
x = v >> 8;
write(DATA(fd), &x, 1);
}
static void writeval_32l(int fd, uint32 v)
{
uint8 x;
x = v & 0xff;
write(DATA(fd), &x, 1);
x = (v >> 8) & 0xff;
write(DATA(fd), &x, 1);
x = (v >> 16) & 0xff;
write(DATA(fd), &x, 1);
x = (v >> 24) & 0xff;
write(DATA(fd), &x, 1);
}
static int init(struct context_data *ctx)
{
char *buf;
uint32 len = 0;
uint16 chan;
uint32 sampling_rate, bytes_per_second;
uint16 bytes_per_frame, bits_per_sample;
char *f, filename[PATH_MAX];
struct xmp_options *o = &ctx->o;
drv_wav.data = malloc(sizeof (struct data));
if (drv_wav.data == NULL)
return -1;
if (!o->outfile) {
if (global_filename) {
if ((f = strrchr(global_filename, '/')) != NULL)
strncpy(filename, f + 1, PATH_MAX);
else
strncpy(filename, global_filename, PATH_MAX);
} else {
strcpy(filename, "xmp");
}
strncat(filename, ".wav", PATH_MAX);
o->outfile = filename;
}
if (strcmp(o->outfile, "-")) {
DATA(fd) = open(o->outfile, O_WRONLY | O_CREAT | O_TRUNC
| O_BINARY, 0644);
if (DATA(fd) < 0)
return -1;
} else {
DATA(fd) = 1;
}
if (strcmp(o->outfile, "-")) {
int len = strlen(drv_wav.description) + strlen(o->outfile) + 8;
if ((buf = malloc(len)) == NULL)
return -1;
snprintf(buf, len, "%s: %s", drv_wav.description, o->outfile);
drv_wav.description = buf;
} else {
drv_wav.description = strdup("WAV writer: stdout");
len = -1;
}
write(DATA(fd), "RIFF", 4);
writeval_32l(DATA(fd), len);
write(DATA(fd), "WAVE", 4);
chan = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
sampling_rate = o->freq;
bits_per_sample = o->resol;
if (bits_per_sample == 8)
o->outfmt |= XMP_FMT_UNS;
bytes_per_frame = chan * bits_per_sample / 8;
bytes_per_second = sampling_rate * bytes_per_frame;
write(DATA(fd), "fmt ", 4);
writeval_32l(DATA(fd), 16);
writeval_16l(DATA(fd), 1);
writeval_16l(DATA(fd), chan);
writeval_32l(DATA(fd), sampling_rate);
writeval_32l(DATA(fd), bytes_per_second);
writeval_16l(DATA(fd), bytes_per_frame);
writeval_16l(DATA(fd), bits_per_sample);
write(DATA(fd), "data", 4);
writeval_32l(DATA(fd), len);
DATA(size) = 0;
return 0;
}
static void bufdump(struct context_data *ctx, void *b, int i)
{
struct xmp_options *o = &ctx->o;
if (o->big_endian)
xmp_cvt_sex(i, b);
write(DATA(fd), b, i);
DATA(size) += i;
}
static void shutdown(struct context_data *ctx)
{
lseek(DATA(fd), 40, SEEK_SET);
writeval_32l(DATA(fd), DATA(size));
lseek(DATA(fd), 4, SEEK_SET);
writeval_32l(DATA(fd), DATA(size) + 40);
if (DATA(fd) > 0)
close(DATA(fd));
free(drv_wav.description);
free(drv_wav.data);
}

@ -191,14 +191,6 @@ int main(int argc, char **argv)
shuffle(argc - optind + 1, &argv[optind - 1]);
}
if (options.out_file) {
f = fopen(options.out_file, "wb");
if (f == NULL) {
perror(options.out_file);
exit(EXIT_FAILURE);
}
}
#ifdef HAVE_SIGNAL_H
signal(SIGTERM, cleanup);
signal(SIGINT, cleanup);
@ -303,10 +295,6 @@ int main(int argc, char **argv)
sound->play(mi.buffer, mi.buffer_size);
if (options.out_file) {
fwrite(mi.buffer, mi.buffer_size, 1, f);
}
if (!background) {
read_command(handle, &control);
@ -351,9 +339,5 @@ int main(int argc, char **argv)
sound->deinit();
if (options.out_file) {
fclose(f);
}
exit(EXIT_SUCCESS);
}

@ -2,6 +2,7 @@
#include <string.h>
#include "sound.h"
extern struct sound_driver sound_wav;
extern struct sound_driver sound_oss;
extern struct sound_driver sound_alsa;
extern struct sound_driver sound_win32;
@ -36,6 +37,7 @@ void init_sound_drivers()
#ifdef SOUND_ALSA
register_sound_driver(&sound_alsa);
#endif
register_sound_driver(&sound_wav);
}
struct sound_driver *select_sound_driver(struct options *options)

@ -0,0 +1,184 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "sound.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
static int fd;
static int format_16bit;
static long size;
struct sound_driver sound_wav;
#ifdef ENDIAN_BIG
/* Convert little-endian 16 bit samples to big-endian */
static void convert_endian(int l, unsigned char *p)
{
unsigned char b;
int i;
for (i = 0; i < l; i++) {
b = p[0];
p[0] = p[1];
p[1] = b;
p += 2;
}
}
#endif
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;
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)
{
#ifdef ENDIAN_BIG
if (format_16bit) {
convert_endian(b, len);
}
#endif
write(fd, b, len);
size += len;
}
static void deinit()
{
lseek(fd, 40, SEEK_SET);
write_32l(fd, size);
lseek(fd, 4, SEEK_SET);
write_32l(fd, size + 40);
if (fd > 0) {
close(fd);
}
free(sound_wav.description);
}
static void flush()
{
}
static void onpause()
{
}
static void onresume()
{
}
struct sound_driver sound_wav = {
"wav",
"WAV writer",
NULL,
init,
deinit,
play,
flush,
onpause,
onresume
};
Loading…
Cancel
Save