Add AIFF file output driver

Signed-off-by: Claudio Matsuoka <cmatsuoka@gmail.com>
master
Claudio Matsuoka 11 years ago
parent 638d109dde
commit 587b960094
  1. 1
      CREDITS
  2. 1
      Changelog
  3. 2
      src/Makefile.am
  4. 3
      src/options.c
  5. 2
      src/sound.c
  6. 166
      src/sound_aiff.c

@ -41,6 +41,7 @@ The Authors
- Lorence Lombardo <lombi@iprimus.com.au> - Lorence Lombardo <lombi@iprimus.com.au>
* Amiga AHI driver * Amiga AHI driver
* AIFF file writer
- Kevin Langman <langman@earthling.net> - Kevin Langman <langman@earthling.net>
* OS/2 port and OS/2 DART drivers * OS/2 port and OS/2 DART drivers

@ -2,6 +2,7 @@ Stable versions
--------------- ---------------
4.0.10 (): 4.0.10 ():
- Add AIFF file output driver (by Lorence Lombardo)
- Adjust CoreAudio driver latency - Adjust CoreAudio driver latency
4.0.9 (20140926): 4.0.9 (20140926):

@ -9,7 +9,7 @@ bin_PROGRAMS = xmp
xmp_SOURCES = \ xmp_SOURCES = \
commands.c common.h getopt.h list.h getopt.c getopt1.c info.c main.c \ commands.c common.h getopt.h list.h getopt.c getopt1.c info.c main.c \
options.c read_config.c sound.c sound.h sound_file.c sound_null.c \ options.c read_config.c sound.c sound.h sound_file.c sound_null.c \
sound_wav.c terminal.c sound_wav.c sound_aiff.c terminal.c
xmp_LDADD = ${libxmp_LIBS} xmp_LDADD = ${libxmp_LIBS}
xmp_LDFLAGS = ${XMP_DARWIN_LDFLAGS} xmp_LDFLAGS = ${XMP_DARWIN_LDFLAGS}

@ -238,6 +238,9 @@ void get_options(int argc, char **argv, struct options *options)
if (strlen(optarg) >= 4 && if (strlen(optarg) >= 4 &&
!strcasecmp(optarg + strlen(optarg) - 4, ".wav")) { !strcasecmp(optarg + strlen(optarg) - 4, ".wav")) {
options->driver_id = "wav"; options->driver_id = "wav";
} else if (strlen(optarg) >= 5 &&
!strcasecmp(optarg + strlen(optarg) - 5, ".aiff")) {
options->driver_id = "aiff";
} else { } else {
options->driver_id = "file"; options->driver_id = "file";
} }

@ -12,6 +12,7 @@
extern struct sound_driver sound_null; extern struct sound_driver sound_null;
extern struct sound_driver sound_wav; extern struct sound_driver sound_wav;
extern struct sound_driver sound_aiff;
extern struct sound_driver sound_file; extern struct sound_driver sound_file;
extern struct sound_driver sound_qnx; extern struct sound_driver sound_qnx;
extern struct sound_driver sound_alsa05; extern struct sound_driver sound_alsa05;
@ -88,6 +89,7 @@ void init_sound_drivers(void)
register_sound_driver(&sound_qnx); register_sound_driver(&sound_qnx);
#endif #endif
register_sound_driver(&sound_wav); register_sound_driver(&sound_wav);
register_sound_driver(&sound_aiff);
register_sound_driver(&sound_file); register_sound_driver(&sound_file);
register_sound_driver(&sound_null); register_sound_driver(&sound_null);
} }

@ -0,0 +1,166 @@
/* Amiga AIFF driver for Extended Module Player
* Copyright (C) 2014 Lorence Lombardo
*
* 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 <unistd.h>
#include <string.h>
#include "sound.h"
typedef struct {
/* Exponent, bit #15 is sign bit for mantissa */
unsigned short exponent;
/* 64 bit mantissa */
unsigned long mantissa[2];
} extended;
static int fd;
static int channels;
static int bits;
static int swap_endian;
static long size;
static void ulong2extended(unsigned long in, extended *ex)
{
int exponent = 31 + 16383;
while (!(in & 0x80000000)) {
exponent--;
in <<= 1;
}
ex->exponent = exponent;
ex->mantissa[0] = in;
ex->mantissa[1] = 0;
}
static inline void write8(int fd, unsigned char c)
{
write(fd, &c, 1);
}
static void write32b(int fd, unsigned long w)
{
write8(fd, (w & 0xff000000) >> 24);
write8(fd, (w & 0x00ff0000) >> 16);
write8(fd, (w & 0x0000ff00) >> 8);
write8(fd, w & 0x000000ff);
}
static int init(struct options *options)
{
char hed[54] = {
'F', 'O', 'R', 'M', 0, 0, 0, 0,
'A', 'I', 'F', 'F',
/* COMM chunk */
'C', 'O', 'M', 'M', 0, 0, 0, 18,
0, 0, /* channels */
0, 0, 0, 0, /* frames */
0, 0, /* bits */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* rate (extended format) */
/* SSND chunk */
'S', 'S', 'N', 'D', 0, 0, 0, 0,
0, 0, 0, 0, /* offset */
0, 0, 0, 0 /* block size */
};
extended ex;
swap_endian = !is_big_endian();
channels = options->format & XMP_FORMAT_MONO ? 1 : 2;
bits = options->format & XMP_FORMAT_8BIT ? 8 : 16;
size = 0;
ulong2extended(options->rate, &ex);
hed[21] = channels;
hed[27] = bits;
hed[28] = (ex.exponent & 0xff00) >> 8;
hed[29] = ex.exponent & 0x00ff;
hed[30] = (ex.mantissa[0] & 0xff000000) >> 24;
hed[31] = (ex.mantissa[0] & 0x00ff0000) >> 16;
hed[32] = (ex.mantissa[0] & 0x0000ff00) >> 8;
hed[33] = ex.mantissa[0] & 0x000000ff;
if (options->out_file == NULL) {
options->out_file = "out.aiff";
}
if (strcmp(options->out_file, "-")) {
fd = open(options->out_file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (fd < 0)
return -1;
} else {
fd = 1;
}
write(fd, hed, 54);
return 0;
}
static void play(void *b, int len)
{
if (swap_endian && bits == 16) {
convert_endian(b, len);
}
write(fd, b, len);
size += len;
}
static void deinit(void)
{
unsigned long tmp;
if (size > 54) {
lseek(fd, 4, SEEK_SET); /* FORM chunk size */
tmp = size - 8;
write32b(fd, tmp);
lseek(fd, 22, SEEK_SET); /* COMM frames */
tmp = (size - 54) / (bits / 8) / channels;
write32b(fd, tmp);
lseek(fd, 42, SEEK_SET); /* SSND chunk size */
tmp = size - 48; /* minus header + 8 */
write32b(fd, tmp);
}
if (fd > 0) {
close(fd);
}
}
static void flush(void)
{
}
static void onpause(void)
{
}
static void onresume(void)
{
}
struct sound_driver sound_aiff = {
"aiff",
"AIFF writer",
NULL,
init,
deinit,
play,
flush,
onpause,
onresume
};
Loading…
Cancel
Save