Skip to content

Commit 587b960

Browse files
committed
Add AIFF file output driver
Signed-off-by: Claudio Matsuoka <[email protected]>
1 parent 638d109 commit 587b960

File tree

6 files changed

+174
-1
lines changed

6 files changed

+174
-1
lines changed

CREDITS

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ The Authors
4141

4242
- Lorence Lombardo <[email protected]>
4343
* Amiga AHI driver
44+
* AIFF file writer
4445

4546
- Kevin Langman <[email protected]>
4647
* OS/2 port and OS/2 DART drivers

Changelog

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Stable versions
22
---------------
33

44
4.0.10 ():
5+
- Add AIFF file output driver (by Lorence Lombardo)
56
- Adjust CoreAudio driver latency
67

78
4.0.9 (20140926):

src/Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ bin_PROGRAMS = xmp
99
xmp_SOURCES = \
1010
commands.c common.h getopt.h list.h getopt.c getopt1.c info.c main.c \
1111
options.c read_config.c sound.c sound.h sound_file.c sound_null.c \
12-
sound_wav.c terminal.c
12+
sound_wav.c sound_aiff.c terminal.c
1313
xmp_LDADD = ${libxmp_LIBS}
1414
xmp_LDFLAGS = ${XMP_DARWIN_LDFLAGS}
1515

src/options.c

+3
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ void get_options(int argc, char **argv, struct options *options)
238238
if (strlen(optarg) >= 4 &&
239239
!strcasecmp(optarg + strlen(optarg) - 4, ".wav")) {
240240
options->driver_id = "wav";
241+
} else if (strlen(optarg) >= 5 &&
242+
!strcasecmp(optarg + strlen(optarg) - 5, ".aiff")) {
243+
options->driver_id = "aiff";
241244
} else {
242245
options->driver_id = "file";
243246
}

src/sound.c

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
extern struct sound_driver sound_null;
1414
extern struct sound_driver sound_wav;
15+
extern struct sound_driver sound_aiff;
1516
extern struct sound_driver sound_file;
1617
extern struct sound_driver sound_qnx;
1718
extern struct sound_driver sound_alsa05;
@@ -88,6 +89,7 @@ void init_sound_drivers(void)
8889
register_sound_driver(&sound_qnx);
8990
#endif
9091
register_sound_driver(&sound_wav);
92+
register_sound_driver(&sound_aiff);
9193
register_sound_driver(&sound_file);
9294
register_sound_driver(&sound_null);
9395
}

src/sound_aiff.c

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/* Amiga AIFF driver for Extended Module Player
2+
* Copyright (C) 2014 Lorence Lombardo
3+
*
4+
* This file is part of the Extended Module Player and is distributed
5+
* under the terms of the GNU General Public License. See the COPYING
6+
* file for more information.
7+
*/
8+
9+
#include <stdlib.h>
10+
#include <sys/types.h>
11+
#include <sys/stat.h>
12+
#include <fcntl.h>
13+
#include <unistd.h>
14+
#include <string.h>
15+
#include "sound.h"
16+
17+
typedef struct {
18+
/* Exponent, bit #15 is sign bit for mantissa */
19+
unsigned short exponent;
20+
21+
/* 64 bit mantissa */
22+
unsigned long mantissa[2];
23+
} extended;
24+
25+
26+
static int fd;
27+
static int channels;
28+
static int bits;
29+
static int swap_endian;
30+
static long size;
31+
32+
33+
static void ulong2extended(unsigned long in, extended *ex)
34+
{
35+
int exponent = 31 + 16383;
36+
37+
while (!(in & 0x80000000)) {
38+
exponent--;
39+
in <<= 1;
40+
}
41+
42+
ex->exponent = exponent;
43+
ex->mantissa[0] = in;
44+
ex->mantissa[1] = 0;
45+
}
46+
47+
static inline void write8(int fd, unsigned char c)
48+
{
49+
write(fd, &c, 1);
50+
}
51+
52+
static void write32b(int fd, unsigned long w)
53+
{
54+
write8(fd, (w & 0xff000000) >> 24);
55+
write8(fd, (w & 0x00ff0000) >> 16);
56+
write8(fd, (w & 0x0000ff00) >> 8);
57+
write8(fd, w & 0x000000ff);
58+
}
59+
60+
static int init(struct options *options)
61+
{
62+
char hed[54] = {
63+
'F', 'O', 'R', 'M', 0, 0, 0, 0,
64+
'A', 'I', 'F', 'F',
65+
66+
/* COMM chunk */
67+
'C', 'O', 'M', 'M', 0, 0, 0, 18,
68+
0, 0, /* channels */
69+
0, 0, 0, 0, /* frames */
70+
0, 0, /* bits */
71+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* rate (extended format) */
72+
73+
/* SSND chunk */
74+
'S', 'S', 'N', 'D', 0, 0, 0, 0,
75+
0, 0, 0, 0, /* offset */
76+
0, 0, 0, 0 /* block size */
77+
};
78+
extended ex;
79+
80+
swap_endian = !is_big_endian();
81+
channels = options->format & XMP_FORMAT_MONO ? 1 : 2;
82+
bits = options->format & XMP_FORMAT_8BIT ? 8 : 16;
83+
size = 0;
84+
85+
ulong2extended(options->rate, &ex);
86+
hed[21] = channels;
87+
hed[27] = bits;
88+
hed[28] = (ex.exponent & 0xff00) >> 8;
89+
hed[29] = ex.exponent & 0x00ff;
90+
hed[30] = (ex.mantissa[0] & 0xff000000) >> 24;
91+
hed[31] = (ex.mantissa[0] & 0x00ff0000) >> 16;
92+
hed[32] = (ex.mantissa[0] & 0x0000ff00) >> 8;
93+
hed[33] = ex.mantissa[0] & 0x000000ff;
94+
95+
if (options->out_file == NULL) {
96+
options->out_file = "out.aiff";
97+
}
98+
99+
if (strcmp(options->out_file, "-")) {
100+
fd = open(options->out_file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
101+
if (fd < 0)
102+
return -1;
103+
} else {
104+
fd = 1;
105+
}
106+
107+
write(fd, hed, 54);
108+
109+
return 0;
110+
}
111+
112+
static void play(void *b, int len)
113+
{
114+
if (swap_endian && bits == 16) {
115+
convert_endian(b, len);
116+
}
117+
write(fd, b, len);
118+
size += len;
119+
}
120+
121+
static void deinit(void)
122+
{
123+
unsigned long tmp;
124+
125+
if (size > 54) {
126+
lseek(fd, 4, SEEK_SET); /* FORM chunk size */
127+
tmp = size - 8;
128+
write32b(fd, tmp);
129+
130+
lseek(fd, 22, SEEK_SET); /* COMM frames */
131+
tmp = (size - 54) / (bits / 8) / channels;
132+
write32b(fd, tmp);
133+
134+
lseek(fd, 42, SEEK_SET); /* SSND chunk size */
135+
tmp = size - 48; /* minus header + 8 */
136+
write32b(fd, tmp);
137+
}
138+
139+
if (fd > 0) {
140+
close(fd);
141+
}
142+
}
143+
144+
static void flush(void)
145+
{
146+
}
147+
148+
static void onpause(void)
149+
{
150+
}
151+
152+
static void onresume(void)
153+
{
154+
}
155+
156+
struct sound_driver sound_aiff = {
157+
"aiff",
158+
"AIFF writer",
159+
NULL,
160+
init,
161+
deinit,
162+
play,
163+
flush,
164+
onpause,
165+
onresume
166+
};

0 commit comments

Comments
 (0)