1 /*
2 * wildmidi.c -- Midi Player using the WildMidi Midi Processing Library
3 *
4 * Copyright (C) WildMidi Developers 2001-2016
5 *
6 * This file is part of WildMIDI.
7 *
8 * WildMIDI is free software: you can redistribute and/or modify the player
9 * under the terms of the GNU General Public License and you can redistribute
10 * and/or modify the library under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation, either version 3 of
12 * the licenses, or(at your option) any later version.
13 *
14 * WildMIDI is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License and
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License and the
20 * GNU Lesser General Public License along with WildMIDI. If not, see
21 * <http://www.gnu.org/licenses/>.
22 */
23
24 #include "config.h"
25
26 #include <stdint.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #if defined(__DJGPP__)
33 #include <sys/types.h>
34 #include <fcntl.h>
35 #include <sys/stat.h>
36 #include "getopt_long.h"
37 #include <conio.h>
38 #define getopt dj_getopt /* hack */
39 #include <unistd.h>
40 #undef getopt
41 #define msleep(s) usleep((s)*1000)
42 #include <io.h>
43 #include <dir.h>
44 #ifdef AUDIODRV_DOSSB
45 #include "dossb.h"
46 #endif
47
48 #elif (defined _WIN32) || (defined __CYGWIN__)
49 #include <sys/types.h>
50 #include <fcntl.h>
51 #include <sys/stat.h>
52 #include <conio.h>
53 #include <windows.h>
54 #include <mmsystem.h>
55 #define msleep(s) Sleep((s))
56 #include <io.h>
57 #include "getopt_long.h"
58 #ifdef __WATCOMC__
59 #define _putch putch
60 #endif
61
62 #elif defined(__OS2__) || defined(__EMX__)
63 #define INCL_DOS
64 #define INCL_DOSERRORS
65 #define INCL_OS2MM
66 #ifdef __EMX__
67 #define INCL_KBD
68 #define INCL_VIO
69 #endif
70 #include <os2.h>
71 #include <os2me.h>
72 #include <conio.h>
73 #define msleep(s) DosSleep((s))
74 #include <fcntl.h>
75 #include <io.h>
76 #include "getopt_long.h"
77 #ifdef __EMX__
78 #include <sys/types.h> /* for off_t typedef */
putch(int c)79 int putch (int c) {
80 char ch = c;
81 VioWrtTTY(&ch, 1, 0);
82 return c;
83 }
kbhit(void)84 int kbhit (void) {
85 KBDKEYINFO k;
86 if (KbdPeek(&k, 0))
87 return 0;
88 return (k.fbStatus & KBDTRF_FINAL_CHAR_IN);
89 }
90 #endif
91
92 #elif defined(WILDMIDI_AMIGA)
93 extern void amiga_sysinit (void);
94 extern int amiga_usleep(unsigned long millisec);
95 #define msleep(s) amiga_usleep((s)*1000)
96 extern int amiga_getch (unsigned char *ch);
97 #include <proto/exec.h>
98 #include <proto/dos.h>
99 #include "getopt_long.h"
100 #ifdef AUDIODRV_AHI
101 #include <devices/ahi.h>
102 #endif
103
104 #else /* unix build */
105 static int msleep(unsigned long millisec);
106 #include <sys/types.h>
107 #include <fcntl.h>
108 #include <sys/stat.h>
109 #include <sys/ioctl.h>
110 #include <unistd.h>
111 #include <getopt.h>
112 #include <time.h>
113 #ifdef AUDIODRV_ALSA
114 # include <alsa/asoundlib.h>
115 #elif defined AUDIODRV_OSS
116 # if defined HAVE_SYS_SOUNDCARD_H
117 # include <sys/soundcard.h>
118 # elif defined HAVE_MACHINE_SOUNDCARD_H
119 # include <machine/soundcard.h>
120 # elif defined HAVE_SOUNDCARD_H
121 # include <soundcard.h> /* less common, but exists. */
122 # endif
123 #elif defined AUDIODRV_OPENAL
124 # include <al.h>
125 # include <alc.h>
126 #endif
127 #endif /* !_WIN32, !__DJGPP__ (unix build) */
128
129 #include "wildmidi_lib.h"
130 #include "wm_tty.h"
131 #include "filenames.h"
132
133 struct _midi_test {
134 uint8_t *data;
135 uint32_t size;
136 };
137
138 /* scale test from 0 to 127
139 * test a
140 * offset 18-21 (0x12-0x15) - track size
141 * offset 25 (0x1A) = bank number
142 * offset 28 (0x1D) = patch number
143 */
144 static uint8_t midi_test_c_scale[] = {
145 0x4d, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, /* 0x00 */
146 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x4d, 0x54, /* 0x08 */
147 0x72, 0x6b, 0x00, 0x00, 0x02, 0x63, 0x00, 0xb0, /* 0x10 */
148 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x90, 0x00, /* 0x18 C */
149 0x64, 0x08, 0x80, 0x00, 0x00, 0x08, 0x90, 0x02, /* 0x20 D */
150 0x64, 0x08, 0x80, 0x02, 0x00, 0x08, 0x90, 0x04, /* 0x28 E */
151 0x64, 0x08, 0x80, 0x04, 0x00, 0x08, 0x90, 0x05, /* 0x30 F */
152 0x64, 0x08, 0x80, 0x05, 0x00, 0x08, 0x90, 0x07, /* 0x38 G */
153 0x64, 0x08, 0x80, 0x07, 0x00, 0x08, 0x90, 0x09, /* 0x40 A */
154 0x64, 0x08, 0x80, 0x09, 0x00, 0x08, 0x90, 0x0b, /* 0x48 B */
155 0x64, 0x08, 0x80, 0x0b, 0x00, 0x08, 0x90, 0x0c, /* 0x50 C */
156 0x64, 0x08, 0x80, 0x0c, 0x00, 0x08, 0x90, 0x0e, /* 0x58 D */
157 0x64, 0x08, 0x80, 0x0e, 0x00, 0x08, 0x90, 0x10, /* 0x60 E */
158 0x64, 0x08, 0x80, 0x10, 0x00, 0x08, 0x90, 0x11, /* 0x68 F */
159 0x64, 0x08, 0x80, 0x11, 0x00, 0x08, 0x90, 0x13, /* 0x70 G */
160 0x64, 0x08, 0x80, 0x13, 0x00, 0x08, 0x90, 0x15, /* 0x78 A */
161 0x64, 0x08, 0x80, 0x15, 0x00, 0x08, 0x90, 0x17, /* 0x80 B */
162 0x64, 0x08, 0x80, 0x17, 0x00, 0x08, 0x90, 0x18, /* 0x88 C */
163 0x64, 0x08, 0x80, 0x18, 0x00, 0x08, 0x90, 0x1a, /* 0x90 D */
164 0x64, 0x08, 0x80, 0x1a, 0x00, 0x08, 0x90, 0x1c, /* 0x98 E */
165 0x64, 0x08, 0x80, 0x1c, 0x00, 0x08, 0x90, 0x1d, /* 0xA0 F */
166 0x64, 0x08, 0x80, 0x1d, 0x00, 0x08, 0x90, 0x1f, /* 0xA8 G */
167 0x64, 0x08, 0x80, 0x1f, 0x00, 0x08, 0x90, 0x21, /* 0xB0 A */
168 0x64, 0x08, 0x80, 0x21, 0x00, 0x08, 0x90, 0x23, /* 0xB8 B */
169 0x64, 0x08, 0x80, 0x23, 0x00, 0x08, 0x90, 0x24, /* 0xC0 C */
170 0x64, 0x08, 0x80, 0x24, 0x00, 0x08, 0x90, 0x26, /* 0xC8 D */
171 0x64, 0x08, 0x80, 0x26, 0x00, 0x08, 0x90, 0x28, /* 0xD0 E */
172 0x64, 0x08, 0x80, 0x28, 0x00, 0x08, 0x90, 0x29, /* 0xD8 F */
173 0x64, 0x08, 0x80, 0x29, 0x00, 0x08, 0x90, 0x2b, /* 0xE0 G */
174 0x64, 0x08, 0x80, 0x2b, 0x00, 0x08, 0x90, 0x2d, /* 0xE8 A */
175 0x64, 0x08, 0x80, 0x2d, 0x00, 0x08, 0x90, 0x2f, /* 0xF0 B */
176 0x64, 0x08, 0x80, 0x2f, 0x00, 0x08, 0x90, 0x30, /* 0xF8 C */
177 0x64, 0x08, 0x80, 0x30, 0x00, 0x08, 0x90, 0x32, /* 0x100 D */
178 0x64, 0x08, 0x80, 0x32, 0x00, 0x08, 0x90, 0x34, /* 0x108 E */
179 0x64, 0x08, 0x80, 0x34, 0x00, 0x08, 0x90, 0x35, /* 0x110 F */
180 0x64, 0x08, 0x80, 0x35, 0x00, 0x08, 0x90, 0x37, /* 0x118 G */
181 0x64, 0x08, 0x80, 0x37, 0x00, 0x08, 0x90, 0x39, /* 0x120 A */
182 0x64, 0x08, 0x80, 0x39, 0x00, 0x08, 0x90, 0x3b, /* 0X128 B */
183 0x64, 0x08, 0x80, 0x3b, 0x00, 0x08, 0x90, 0x3c, /* 0x130 C */
184 0x64, 0x08, 0x80, 0x3c, 0x00, 0x08, 0x90, 0x3e, /* 0x138 D */
185 0x64, 0x08, 0x80, 0x3e, 0x00, 0x08, 0x90, 0x40, /* 0X140 E */
186 0x64, 0x08, 0x80, 0x40, 0x00, 0x08, 0x90, 0x41, /* 0x148 F */
187 0x64, 0x08, 0x80, 0x41, 0x00, 0x08, 0x90, 0x43, /* 0x150 G */
188 0x64, 0x08, 0x80, 0x43, 0x00, 0x08, 0x90, 0x45, /* 0x158 A */
189 0x64, 0x08, 0x80, 0x45, 0x00, 0x08, 0x90, 0x47, /* 0x160 B */
190 0x64, 0x08, 0x80, 0x47, 0x00, 0x08, 0x90, 0x48, /* 0x168 C */
191 0x64, 0x08, 0x80, 0x48, 0x00, 0x08, 0x90, 0x4a, /* 0x170 D */
192 0x64, 0x08, 0x80, 0x4a, 0x00, 0x08, 0x90, 0x4c, /* 0x178 E */
193 0x64, 0x08, 0x80, 0x4c, 0x00, 0x08, 0x90, 0x4d, /* 0x180 F */
194 0x64, 0x08, 0x80, 0x4d, 0x00, 0x08, 0x90, 0x4f, /* 0x188 G */
195 0x64, 0x08, 0x80, 0x4f, 0x00, 0x08, 0x90, 0x51, /* 0x190 A */
196 0x64, 0x08, 0x80, 0x51, 0x00, 0x08, 0x90, 0x53, /* 0x198 B */
197 0x64, 0x08, 0x80, 0x53, 0x00, 0x08, 0x90, 0x54, /* 0x1A0 C */
198 0x64, 0x08, 0x80, 0x54, 0x00, 0x08, 0x90, 0x56, /* 0x1A8 D */
199 0x64, 0x08, 0x80, 0x56, 0x00, 0x08, 0x90, 0x58, /* 0x1B0 E */
200 0x64, 0x08, 0x80, 0x58, 0x00, 0x08, 0x90, 0x59, /* 0x1B8 F */
201 0x64, 0x08, 0x80, 0x59, 0x00, 0x08, 0x90, 0x5b, /* 0x1C0 G */
202 0x64, 0x08, 0x80, 0x5b, 0x00, 0x08, 0x90, 0x5d, /* 0x1C8 A */
203 0x64, 0x08, 0x80, 0x5d, 0x00, 0x08, 0x90, 0x5f, /* 0x1D0 B */
204 0x64, 0x08, 0x80, 0x5f, 0x00, 0x08, 0x90, 0x60, /* 0x1D8 C */
205 0x64, 0x08, 0x80, 0x60, 0x00, 0x08, 0x90, 0x62, /* 0x1E0 D */
206 0x64, 0x08, 0x80, 0x62, 0x00, 0x08, 0x90, 0x64, /* 0x1E8 E */
207 0x64, 0x08, 0x80, 0x64, 0x00, 0x08, 0x90, 0x65, /* 0x1F0 F */
208 0x64, 0x08, 0x80, 0x65, 0x00, 0x08, 0x90, 0x67, /* 0x1F8 G */
209 0x64, 0x08, 0x80, 0x67, 0x00, 0x08, 0x90, 0x69, /* 0x200 A */
210 0x64, 0x08, 0x80, 0x69, 0x00, 0x08, 0x90, 0x6b, /* 0x208 B */
211 0x64, 0x08, 0x80, 0x6b, 0x00, 0x08, 0x90, 0x6c, /* 0x210 C */
212 0x64, 0x08, 0x80, 0x6c, 0x00, 0x08, 0x90, 0x6e, /* 0x218 D */
213 0x64, 0x08, 0x80, 0x6e, 0x00, 0x08, 0x90, 0x70, /* 0x220 E */
214 0x64, 0x08, 0x80, 0x70, 0x00, 0x08, 0x90, 0x71, /* 0x228 F */
215 0x64, 0x08, 0x80, 0x71, 0x00, 0x08, 0x90, 0x73, /* 0x230 G */
216 0x64, 0x08, 0x80, 0x73, 0x00, 0x08, 0x90, 0x75, /* 0x238 A */
217 0x64, 0x08, 0x80, 0x75, 0x00, 0x08, 0x90, 0x77, /* 0x240 B */
218 0x64, 0x08, 0x80, 0x77, 0x00, 0x08, 0x90, 0x78, /* 0x248 C */
219 0x64, 0x08, 0x80, 0x78, 0x00, 0x08, 0x90, 0x7a, /* 0x250 D */
220 0x64, 0x08, 0x80, 0x7a, 0x00, 0x08, 0x90, 0x7c, /* 0x258 E */
221 0x64, 0x08, 0x80, 0x7c, 0x00, 0x08, 0x90, 0x7d, /* 0x260 F */
222 0x64, 0x08, 0x80, 0x7d, 0x00, 0x08, 0x90, 0x7f, /* 0x268 G */
223 0x64, 0x08, 0x80, 0x7f, 0x00, 0x08, 0xff, 0x2f, /* 0x270 */
224 0x00 /* 0x278 */
225 };
226
227 static struct _midi_test midi_test[] = {
228 { midi_test_c_scale, 663 },
229 { NULL, 0 }
230 };
231
232 static int midi_test_max = 1;
233
234 /*
235 ==============================
236 Audio Output Functions
237
238 We have two 'drivers': first is the wav file writer which is
239 always available. the second, if it is really compiled in,
240 is the system audio output driver. only _one of the two_ can
241 be active, not both.
242 ==============================
243 */
244
245 static unsigned int rate = 32072;
246
247 static int (*send_output)(int8_t *output_data, int output_size);
248 static void (*close_output)(void);
249 static void (*pause_output)(void);
250 static void (*resume_output)(void);
251
252 #define wmidi_geterrno() errno /* generic case */
253 #if defined(_WIN32)
254 static int audio_fd = -1;
255 #define WM_IS_BADF(_fd) ((_fd)<0)
256 #define WM_BADF -1
wmidi_fileexists(const char * path)257 static inline int wmidi_fileexists (const char *path) {
258 return (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES);
259 }
wmidi_open_write(const char * path)260 static inline int wmidi_open_write (const char *path) {
261 return _open(path, (O_RDWR | O_CREAT | O_TRUNC | O_BINARY), 0664);
262 }
wmidi_close(int fd)263 static inline void wmidi_close (int fd) {
264 _close(fd);
265 }
wmidi_seekset(int fd,long ofs)266 static inline long wmidi_seekset (int fd, long ofs) {
267 return _lseek(fd, ofs, SEEK_SET);
268 }
wmidi_write(int fd,const void * buf,size_t size)269 static inline int wmidi_write (int fd, const void *buf, size_t size) {
270 return _write(fd, buf, size);
271 }
272
273 #elif defined(__DJGPP__)
274 static int audio_fd = -1;
275 #define WM_IS_BADF(_fd) ((_fd)<0)
276 #define WM_BADF -1
wmidi_fileexists(const char * path)277 static inline int wmidi_fileexists (const char *path) {
278 struct ffblk f;
279 return (findfirst(path, &f, FA_ARCH | FA_RDONLY) == 0);
280 }
wmidi_open_write(const char * path)281 static inline int wmidi_open_write (const char *path) {
282 return open(path, (O_RDWR | O_CREAT | O_TRUNC | O_BINARY), 0664);
283 }
wmidi_close(int fd)284 static inline void wmidi_close (int fd) {
285 close(fd);
286 }
wmidi_seekset(int fd,off_t ofs)287 static inline off_t wmidi_seekset (int fd, off_t ofs) {
288 return lseek(fd, ofs, SEEK_SET);
289 }
wmidi_write(int fd,const void * buf,size_t size)290 static inline int wmidi_write (int fd, const void *buf, size_t size) {
291 return write(fd, buf, size);
292 }
293
294 #elif defined(__OS2__) || defined(__EMX__)
295 static int audio_fd = -1;
296 #define WM_IS_BADF(_fd) ((_fd)<0)
297 #define WM_BADF -1
wmidi_fileexists(const char * path)298 static inline int wmidi_fileexists (const char *path) {
299 int f = open(path, (O_RDONLY | O_BINARY));
300 if (f != -1) { close(f); return 1; } else return 0;
301 }
wmidi_open_write(const char * path)302 static inline int wmidi_open_write (const char *path) {
303 return open(path, (O_RDWR | O_CREAT | O_TRUNC | O_BINARY), 0664);
304 }
wmidi_close(int fd)305 static inline void wmidi_close (int fd) {
306 close(fd);
307 }
wmidi_seekset(int fd,off_t ofs)308 static inline off_t wmidi_seekset (int fd, off_t ofs) {
309 return lseek(fd, ofs, SEEK_SET);
310 }
wmidi_write(int fd,const void * buf,size_t size)311 static inline int wmidi_write (int fd, const void *buf, size_t size) {
312 return write(fd, buf, size);
313 }
314
315 #elif defined(WILDMIDI_AMIGA)
316 static BPTR audio_fd = 0;
317 #define WM_IS_BADF(_fd) ((_fd)==0)
318 #define WM_BADF 0
319 #undef wmidi_geterrno
wmidi_geterrno(void)320 static int wmidi_geterrno (void) {
321 switch (IoErr()) {
322 case ERROR_OBJECT_NOT_FOUND: return ENOENT;
323 case ERROR_DISK_FULL: return ENOSPC;
324 }
325 return EIO; /* better ?? */
326 }
wmidi_fileexists(const char * path)327 static inline int wmidi_fileexists (const char *path) {
328 BPTR fd = Open((const STRPTR)path, MODE_OLDFILE);
329 if (!fd) return 0;
330 Close(fd); return 1;
331 }
wmidi_open_write(const char * path)332 static inline BPTR wmidi_open_write (const char *path) {
333 return Open((const STRPTR) path, MODE_NEWFILE);
334 }
wmidi_close(BPTR fd)335 static inline LONG wmidi_close (BPTR fd) {
336 return Close(fd);
337 }
wmidi_seekset(BPTR fd,LONG ofs)338 static inline LONG wmidi_seekset (BPTR fd, LONG ofs) {
339 return Seek(fd, ofs, OFFSET_BEGINNING);
340 }
wmidi_write(BPTR fd,void * buf,LONG size)341 static LONG wmidi_write (BPTR fd, /*const*/ void *buf, LONG size) {
342 LONG written = 0, result;
343 unsigned char *p = (unsigned char *)buf;
344 while (written < size) {
345 result = Write(fd, p + written, size - written);
346 if (result < 0) return result;
347 written += result;
348 }
349 return written;
350 }
351
352 #else /* common posix case */
353 static int audio_fd = -1;
354 #define WM_IS_BADF(_fd) ((_fd)<0)
355 #define WM_BADF -1
wmidi_fileexists(const char * path)356 static inline int wmidi_fileexists (const char *path) {
357 struct stat st;
358 return (stat(path, &st) == 0);
359 }
wmidi_open_write(const char * path)360 static inline int wmidi_open_write (const char *path) {
361 return open(path, (O_RDWR | O_CREAT | O_TRUNC), (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
362 }
wmidi_close(int fd)363 static inline int wmidi_close (int fd) {
364 return close(fd);
365 }
wmidi_seekset(int fd,off_t ofs)366 static inline off_t wmidi_seekset (int fd, off_t ofs) {
367 return lseek(fd, ofs, SEEK_SET);
368 }
wmidi_write(int fd,const void * buf,size_t size)369 static inline ssize_t wmidi_write (int fd, const void *buf, size_t size) {
370 return write(fd, buf, size);
371 }
372 #endif
373
pause_output_nop(void)374 static void pause_output_nop(void) {
375 }
resume_output_nop(void)376 static void resume_output_nop(void) {
377 }
378
379 /*
380 MIDI Output Functions
381 */
382 static char midi_file[1024];
383
write_midi_output(void * output_data,int output_size)384 static int write_midi_output(void *output_data, int output_size) {
385 if (midi_file[0] == '\0')
386 return (-1);
387
388 /*
389 * Test if file already exists
390 */
391 if (wmidi_fileexists(midi_file)) {
392 fprintf(stderr, "\rError: %s already exists\r\n", midi_file);
393 return (-1);
394 }
395
396 audio_fd = wmidi_open_write(midi_file);
397 if (WM_IS_BADF(audio_fd)) {
398 fprintf(stderr, "Error: unable to open file for writing (%s)\r\n", strerror(wmidi_geterrno()));
399 return (-1);
400 }
401
402 if (wmidi_write(audio_fd, output_data, output_size) < 0) {
403 fprintf(stderr, "\nERROR: failed writing midi (%s)\r\n", strerror(wmidi_geterrno()));
404 wmidi_close(audio_fd);
405 audio_fd = WM_BADF;
406 return (-1);
407 }
408
409 wmidi_close(audio_fd);
410 audio_fd = WM_BADF;
411 return (0);
412 }
413
414 /*
415 Wav Output Functions
416 */
417
418 static char wav_file[1024];
419 static uint32_t wav_size;
420
421 static int write_wav_output(int8_t *output_data, int output_size);
422 static void close_wav_output(void);
423
open_wav_output(void)424 static int open_wav_output(void) {
425 uint8_t wav_hdr[] = {
426 0x52, 0x49, 0x46, 0x46, /* "RIFF" */
427 0x00, 0x00, 0x00, 0x00, /* riffsize: pcm size + 36 (filled when closing.) */
428 0x57, 0x41, 0x56, 0x45, /* "WAVE" */
429 0x66, 0x6D, 0x74, 0x20, /* "fmt " */
430 0x10, 0x00, 0x00, 0x00, /* length of this RIFF block: 16 */
431 0x01, 0x00, /* wave format == 1 (WAVE_FORMAT_PCM) */
432 0x02, 0x00, /* channels == 2 */
433 0x00, 0x00, 0x00, 0x00, /* sample rate (filled below) */
434 0x00, 0x00, 0x00, 0x00, /* bytes_per_sec: rate * channels * format bytes */
435 0x04, 0x00, /* block alignment: channels * format bytes == 4 */
436 0x10, 0x00, /* format bits == 16 */
437 0x64, 0x61, 0x74, 0x61, /* "data" */
438 0x00, 0x00, 0x00, 0x00 /* datasize: the pcm size (filled when closing.) */
439 };
440
441 if (wav_file[0] == '\0')
442 return (-1);
443
444 audio_fd = wmidi_open_write(wav_file);
445 if (WM_IS_BADF(audio_fd)) {
446 fprintf(stderr, "Error: unable to open file for writing (%s)\r\n", strerror(wmidi_geterrno()));
447 return (-1);
448 } else {
449 uint32_t bytes_per_sec;
450
451 wav_hdr[24] = (rate) & 0xFF;
452 wav_hdr[25] = (rate >> 8) & 0xFF;
453
454 bytes_per_sec = rate * 4;
455 wav_hdr[28] = (bytes_per_sec) & 0xFF;
456 wav_hdr[29] = (bytes_per_sec >> 8) & 0xFF;
457 wav_hdr[30] = (bytes_per_sec >> 16) & 0xFF;
458 wav_hdr[31] = (bytes_per_sec >> 24) & 0xFF;
459 }
460
461 if (wmidi_write(audio_fd, wav_hdr, 44) < 0) {
462 fprintf(stderr, "ERROR: failed writing wav header (%s)\r\n", strerror(wmidi_geterrno()));
463 wmidi_close(audio_fd);
464 audio_fd = WM_BADF;
465 return (-1);
466 }
467
468 wav_size = 0;
469 send_output = write_wav_output;
470 close_output = close_wav_output;
471 pause_output = pause_output_nop;
472 resume_output = resume_output_nop;
473 return (0);
474 }
475
write_wav_output(int8_t * output_data,int output_size)476 static int write_wav_output(int8_t *output_data, int output_size) {
477 #ifdef WORDS_BIGENDIAN
478 /* libWildMidi outputs host-endian, *.wav must have little-endian. */
479 uint16_t *swp = (uint16_t *) output_data;
480 int i = (output_size / 2) - 1;
481 for (; i >= 0; --i) {
482 swp[i] = (swp[i] << 8) | (swp[i] >> 8);
483 }
484 #endif
485 if (wmidi_write(audio_fd, output_data, output_size) < 0) {
486 fprintf(stderr, "\nERROR: failed writing wav (%s)\r\n", strerror(wmidi_geterrno()));
487 wmidi_close(audio_fd);
488 audio_fd = WM_BADF;
489 return (-1);
490 }
491
492 wav_size += output_size;
493 return (0);
494 }
495
close_wav_output(void)496 static void close_wav_output(void) {
497 uint8_t wav_count[4];
498 if (WM_IS_BADF(audio_fd))
499 return;
500
501 printf("Finishing and closing wav output\r");
502 wav_count[0] = (wav_size) & 0xFF;
503 wav_count[1] = (wav_size >> 8) & 0xFF;
504 wav_count[2] = (wav_size >> 16) & 0xFF;
505 wav_count[3] = (wav_size >> 24) & 0xFF;
506 wmidi_seekset(audio_fd, 40);
507 if (wmidi_write(audio_fd, wav_count, 4) < 0) {
508 fprintf(stderr, "\nERROR: failed writing wav (%s)\r\n", strerror(wmidi_geterrno()));
509 goto end;
510 }
511
512 wav_size += 36;
513 wav_count[0] = (wav_size) & 0xFF;
514 wav_count[1] = (wav_size >> 8) & 0xFF;
515 wav_count[2] = (wav_size >> 16) & 0xFF;
516 wav_count[3] = (wav_size >> 24) & 0xFF;
517 wmidi_seekset(audio_fd, 4);
518 if (wmidi_write(audio_fd, wav_count, 4) < 0) {
519 fprintf(stderr, "\nERROR: failed writing wav (%s)\r\n", strerror(wmidi_geterrno()));
520 goto end;
521 }
522
523 end: printf("\n");
524 if (!WM_IS_BADF(audio_fd))
525 wmidi_close(audio_fd);
526 audio_fd = WM_BADF;
527 }
528
529 #if (defined _WIN32) || (defined __CYGWIN__)
530
531 static HWAVEOUT hWaveOut = NULL;
532 static CRITICAL_SECTION waveCriticalSection;
533
534 #define open_audio_output open_mm_output
535 static int write_mm_output (int8_t *output_data, int output_size);
536 static void close_mm_output (void);
537
538 static WAVEHDR *mm_blocks = NULL;
539 #define MM_BLOCK_SIZE 16384
540 #define MM_BLOCK_COUNT 3
541
542 static DWORD mm_free_blocks = MM_BLOCK_COUNT;
543 static DWORD mm_current_block = 0;
544
545 #if defined(_MSC_VER) && (_MSC_VER < 1300)
546 typedef DWORD DWORD_PTR;
547 #endif
548
mmOutProc(HWAVEOUT hWaveOut,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)549 static void CALLBACK mmOutProc (HWAVEOUT hWaveOut, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
550 /* unused params */
551 (void)hWaveOut;
552 (void)dwParam1;
553 (void)dwParam2;
554
555 if(uMsg != WOM_DONE)
556 return;
557 /* increment mm_free_blocks */
558 EnterCriticalSection(&waveCriticalSection);
559 (*(DWORD *)dwInstance)++;
560 LeaveCriticalSection(&waveCriticalSection);
561 }
562
563 static int
open_mm_output(void)564 open_mm_output (void) {
565 WAVEFORMATEX wfx;
566 char *mm_buffer;
567 int i;
568
569 InitializeCriticalSection(&waveCriticalSection);
570
571 if((mm_buffer = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((MM_BLOCK_SIZE + sizeof(WAVEHDR)) * MM_BLOCK_COUNT))) == NULL) {
572 fprintf(stderr, "Memory allocation error\r\n");
573 return -1;
574 }
575
576 mm_blocks = (WAVEHDR*)mm_buffer;
577 mm_buffer += sizeof(WAVEHDR) * MM_BLOCK_COUNT;
578
579 for(i = 0; i < MM_BLOCK_COUNT; i++) {
580 mm_blocks[i].dwBufferLength = MM_BLOCK_SIZE;
581 mm_blocks[i].lpData = mm_buffer;
582 mm_buffer += MM_BLOCK_SIZE;
583 }
584
585 wfx.nSamplesPerSec = rate;
586 wfx.wBitsPerSample = 16;
587 wfx.nChannels = 2;
588 wfx.cbSize = 0;
589 wfx.wFormatTag = WAVE_FORMAT_PCM;
590 wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
591 wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
592
593 if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)mmOutProc, (DWORD_PTR)&mm_free_blocks, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
594 fprintf(stderr, "unable to open WAVE_MAPPER device\r\n");
595 HeapFree(GetProcessHeap(), 0, mm_blocks);
596 hWaveOut = NULL;
597 mm_blocks = NULL;
598 return -1;
599 }
600
601 send_output = write_mm_output;
602 close_output = close_mm_output;
603 pause_output = pause_output_nop;
604 resume_output = resume_output_nop;
605 return (0);
606 }
607
608 static int
write_mm_output(int8_t * output_data,int output_size)609 write_mm_output (int8_t *output_data, int output_size) {
610 WAVEHDR* current;
611 int free_size = 0;
612 int data_read = 0;
613 current = &mm_blocks[mm_current_block];
614
615 while (output_size) {
616 if(current->dwFlags & WHDR_PREPARED)
617 waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR));
618 free_size = MM_BLOCK_SIZE - current->dwUser;
619 if (free_size > output_size)
620 free_size = output_size;
621
622 memcpy(current->lpData + current->dwUser, &output_data[data_read], free_size);
623 current->dwUser += free_size;
624 output_size -= free_size;
625 data_read += free_size;
626
627 if (current->dwUser < MM_BLOCK_SIZE) {
628 return (0);
629 }
630
631 current->dwBufferLength = MM_BLOCK_SIZE;
632 waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR));
633 waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));
634 EnterCriticalSection(&waveCriticalSection);
635 mm_free_blocks--;
636 LeaveCriticalSection(&waveCriticalSection);
637 while(!mm_free_blocks)
638 Sleep(10);
639 mm_current_block++;
640 mm_current_block %= MM_BLOCK_COUNT;
641 current = &mm_blocks[mm_current_block];
642 current->dwUser = 0;
643 }
644 return (0);
645 }
646
647 static void
close_mm_output(void)648 close_mm_output (void) {
649 int i;
650
651 if (!hWaveOut) return;
652
653 printf("Shutting down sound output\r\n");
654 for (i = 0; i < MM_BLOCK_COUNT; i++) {
655 while (waveOutUnprepareHeader(hWaveOut, &mm_blocks[i], sizeof(WAVEHDR))
656 == WAVERR_STILLPLAYING) {
657 Sleep(10);
658 }
659 }
660
661 waveOutClose (hWaveOut);
662 HeapFree(GetProcessHeap(), 0, mm_blocks);
663 hWaveOut = NULL;
664 mm_blocks = NULL;
665 }
666
667 #elif (defined(__OS2__) || defined(__EMX__)) && defined(AUDIODRV_OS2DART)
668 /* based on Dart code originally written by Kevin Langman for XMP */
669
670 #define open_audio_output open_dart_output
671 static int write_dart_output (int8_t *output_data, int output_size);
672 static void close_dart_output (void);
673
674 #define BUFFERCOUNT 4
675
676 static MCI_MIX_BUFFER MixBuffers[BUFFERCOUNT];
677 static MCI_MIXSETUP_PARMS MixSetupParms;
678 static MCI_BUFFER_PARMS BufferParms;
679 static MCI_GENERIC_PARMS GenericParms;
680
681 static ULONG DeviceID = 0;
682 static ULONG bsize = 16;
683 static short next = 2;
684 static short ready = 1;
685
686 static HMTX dart_mutex;
687
688 /* Buffer update thread (created and called by DART) */
OS2_Dart_UpdateBuffers(ULONG ulStatus,PMCI_MIX_BUFFER pBuffer,ULONG ulFlags)689 static LONG APIENTRY OS2_Dart_UpdateBuffers
690 (ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) {
691
692 (void) pBuffer;/* unused param */
693
694 if ((ulFlags == MIX_WRITE_COMPLETE) ||
695 ((ulFlags == (MIX_WRITE_COMPLETE | MIX_STREAM_ERROR)) &&
696 (ulStatus == ERROR_DEVICE_UNDERRUN))) {
697 DosRequestMutexSem(dart_mutex, SEM_INDEFINITE_WAIT);
698 ready++;
699 DosReleaseMutexSem(dart_mutex);
700 }
701 return (TRUE);
702 }
703
704 static int
open_dart_output(void)705 open_dart_output(void) {
706 int i;
707 MCI_AMP_OPEN_PARMS AmpOpenParms;
708
709 if (DosCreateMutexSem(NULL, &dart_mutex, 0, 0) != NO_ERROR) {
710 fprintf(stderr, "Failed creating a MutexSem.\r\n");
711 return (-1);
712 }
713
714 /* compute a size for circa 1/4" of playback. */
715 bsize = rate >> 2;
716 bsize <<= 1; /* stereo */
717 bsize <<= 1; /* 16 bit */
718 for (i = 15; i >= 12; i--) {
719 if (bsize & (1 << i))
720 break;
721 }
722 bsize = (1 << i);
723 /* make sure buffer is not greater than 64 Kb: DART can't handle it. */
724 if (bsize > 65536)
725 bsize = 65536;
726
727 MixBuffers[0].pBuffer = NULL; /* marker */
728 memset(&GenericParms, 0, sizeof(MCI_GENERIC_PARMS));
729
730 /* open AMP device */
731 memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
732 AmpOpenParms.usDeviceID = 0;
733
734 AmpOpenParms.pszDeviceType =
735 (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, 0); /* 0: default waveaudio device */
736
737 if(mciSendCommand(0, MCI_OPEN, MCI_WAIT|MCI_OPEN_TYPE_ID|MCI_OPEN_SHAREABLE,
738 (PVOID) &AmpOpenParms, 0) != MCIERR_SUCCESS) {
739 fprintf(stderr, "Failed opening DART audio device\r\n");
740 return (-1);
741 }
742
743 DeviceID = AmpOpenParms.usDeviceID;
744
745 /* setup playback parameters */
746 memset(&MixSetupParms, 0, sizeof(MCI_MIXSETUP_PARMS));
747
748 MixSetupParms.ulBitsPerSample = 16;
749 MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
750 MixSetupParms.ulSamplesPerSec = rate;
751 MixSetupParms.ulChannels = 2;
752 MixSetupParms.ulFormatMode = MCI_PLAY;
753 MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
754 MixSetupParms.pmixEvent = OS2_Dart_UpdateBuffers;
755
756 if (mciSendCommand(DeviceID, MCI_MIXSETUP,
757 MCI_WAIT | MCI_MIXSETUP_INIT,
758 (PVOID) & MixSetupParms, 0) != MCIERR_SUCCESS) {
759
760 mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT,
761 (PVOID) & GenericParms, 0);
762 fprintf(stderr, "Failed DART mixer setup\r\n");
763 return (-1);
764 }
765
766 /*bsize = MixSetupParms.ulBufferSize;*/
767 /*printf("Dart Buffer Size = %lu\n", bsize);*/
768
769 BufferParms.ulNumBuffers = BUFFERCOUNT;
770 BufferParms.ulBufferSize = bsize;
771 BufferParms.pBufList = MixBuffers;
772
773 if (mciSendCommand(DeviceID, MCI_BUFFER,
774 MCI_WAIT | MCI_ALLOCATE_MEMORY,
775 (PVOID) & BufferParms, 0) != MCIERR_SUCCESS) {
776 fprintf(stderr, "DART Memory allocation error\r\n");
777 mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT,
778 (PVOID) & GenericParms, 0);
779 return (-1);
780 }
781
782 for (i = 0; i < BUFFERCOUNT; i++) {
783 MixBuffers[i].ulBufferLength = bsize;
784 }
785
786 /* Start Playback */
787 memset(MixBuffers[0].pBuffer, /*32767 */ 0, bsize);
788 memset(MixBuffers[1].pBuffer, /*32767 */ 0, bsize);
789 MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle, MixBuffers, 2);
790
791 send_output = write_dart_output;
792 close_output = close_dart_output;
793 pause_output = pause_output_nop;
794 resume_output = resume_output_nop;
795
796 return (0);
797 }
798
799 static int
write_dart_output(int8_t * output_data,int output_size)800 write_dart_output (int8_t *output_data, int output_size) {
801 static int idx = 0;
802
803 if (idx + output_size > bsize) {
804 do {
805 DosRequestMutexSem(dart_mutex, SEM_INDEFINITE_WAIT);
806 if (ready != 0) {
807 DosReleaseMutexSem(dart_mutex);
808 break;
809 }
810 DosReleaseMutexSem(dart_mutex);
811 DosSleep(20);
812 } while (TRUE);
813
814 MixBuffers[next].ulBufferLength = idx;
815 MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle, &(MixBuffers[next]), 1);
816 ready--;
817 next++;
818 idx = 0;
819 if (next == BUFFERCOUNT) {
820 next = 0;
821 }
822 }
823 memcpy(&((char *)MixBuffers[next].pBuffer)[idx], output_data, output_size);
824 idx += output_size;
825 return (0);
826 }
827
828 static void
close_dart_output(void)829 close_dart_output (void) {
830 printf("Shutting down sound output\r\n");
831 if (MixBuffers[0].pBuffer) {
832 mciSendCommand(DeviceID, MCI_BUFFER,
833 MCI_WAIT | MCI_DEALLOCATE_MEMORY, &BufferParms, 0);
834 MixBuffers[0].pBuffer = NULL;
835 }
836 if (DeviceID) {
837 mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT,
838 (PVOID) &GenericParms, 0);
839 DeviceID = 0;
840 }
841 }
842
843 #elif defined(__DJGPP__) && defined(AUDIODRV_DOSSB)
844 /* SoundBlaster/Pro/16/AWE32 driver for DOS -- adapted from
845 * libMikMod, written by Andrew Zabolotny <bit@eltech.ru>,
846 * further fixes by O.Sezer <sezero@users.sourceforge.net>.
847 * Timer callback functionality replaced by a push mechanism
848 * to keep the wildmidi player changes to a minimum, for now.
849 */
850
851 /* The last buffer byte filled with sound */
852 static unsigned int buff_tail = 0;
853
write_sb_output(int8_t * data,unsigned int siz)854 static int write_sb_output(int8_t *data, unsigned int siz) {
855 unsigned int dma_size, dma_pos;
856 unsigned int cnt;
857
858 sb_query_dma(&dma_size, &dma_pos);
859 /* There isn't much sense in filling less than 256 bytes */
860 dma_pos &= ~255;
861
862 /* If nothing to mix, quit */
863 if (buff_tail == dma_pos)
864 return 0;
865
866 /* If DMA pointer still didn't wrapped around ... */
867 if (dma_pos > buff_tail) {
868 if ((cnt = dma_pos - buff_tail) > siz)
869 cnt = siz;
870 memcpy(sb.dma_buff->linear + buff_tail, data, cnt);
871 buff_tail += cnt;
872 /* If we arrived right to the DMA buffer end, jump to the beginning */
873 if (buff_tail >= dma_size)
874 buff_tail = 0;
875 } else {
876 /* If wrapped around, fill first to the end of buffer */
877 if ((cnt = dma_size - buff_tail) > siz)
878 cnt = siz;
879 memcpy(sb.dma_buff->linear + buff_tail, data, cnt);
880 buff_tail += cnt;
881 siz -= cnt;
882 if (!siz) return cnt;
883
884 /* Now fill from buffer beginning to current DMA pointer */
885 if (dma_pos > siz) dma_pos = siz;
886 data += cnt;
887 cnt += dma_pos;
888
889 memcpy(sb.dma_buff->linear, data, dma_pos);
890 buff_tail = dma_pos;
891 }
892 return cnt;
893 }
894
write_sb_s16stereo(int8_t * data,int siz)895 static int write_sb_s16stereo(int8_t *data, int siz) {
896 /* libWildMidi sint16 stereo -> SB16 sint16 stereo */
897 int i;
898 while (1) {
899 i = write_sb_output(data, siz);
900 if ((siz -= i) <= 0) return 0;
901 data += i;
902 /*usleep(100);*/
903 }
904 }
905
write_sb_u8stereo(int8_t * data,int siz)906 static int write_sb_u8stereo(int8_t *data, int siz) {
907 /* libWildMidi sint16 stereo -> SB uint8 stereo */
908 int16_t *src = (int16_t *) data;
909 uint8_t *dst = (uint8_t *) data;
910 int i = (siz /= 2);
911 for (; i >= 0; --i) {
912 *dst++ = (*src++ >> 8) + 128;
913 }
914 while (1) {
915 i = write_sb_output(data, siz);
916 if ((siz -= i) <= 0) return 0;
917 data += i;
918 /*usleep(100);*/
919 }
920 }
921
write_sb_u8mono(int8_t * data,int siz)922 static int write_sb_u8mono(int8_t *data, int siz) {
923 /* libWildMidi sint16 stereo -> SB uint8 mono */
924 int16_t *src = (int16_t *) data;
925 uint8_t *dst = (uint8_t *) data;
926 int i = (siz /= 4); int val;
927 for (; i >= 0; --i) {
928 /* do a cheap (left+right)/2 */
929 val = *src++;
930 val += *src++;
931 *dst++ = (val >> 9) + 128;
932 }
933 while (1) {
934 i = write_sb_output(data, siz);
935 if ((siz -= i) <= 0) return 0;
936 data += i;
937 /*usleep(100);*/
938 }
939 }
940
sb_silence_s16(void)941 static void sb_silence_s16(void) {
942 memset(sb.dma_buff->linear, 0, sb.dma_buff->size);
943 }
944
sb_silence_u8(void)945 static void sb_silence_u8(void) {
946 memset(sb.dma_buff->linear, 0x80, sb.dma_buff->size);
947 }
948
close_sb_output(void)949 static void close_sb_output(void)
950 {
951 sb.timer_callback = NULL;
952 sb_output(FALSE);
953 sb_stop_dma();
954 sb_close();
955 }
956
957 #define open_audio_output open_sb_output
open_sb_output(void)958 static int open_sb_output(void)
959 {
960 if (!sb_open()) {
961 fprintf(stderr, "Sound Blaster initialization failed.\n");
962 return -1;
963 }
964
965 if (rate < 4000) rate = 4000;
966 if (sb.caps & SBMODE_STEREO) {
967 if (rate > sb.maxfreq_stereo)
968 rate = sb.maxfreq_stereo;
969 } else {
970 if (rate > sb.maxfreq_mono)
971 rate = sb.maxfreq_mono;
972 }
973
974 /* Enable speaker output */
975 sb_output(TRUE);
976
977 /* Set our routine to be called during SB IRQs */
978 buff_tail = 0;
979 sb.timer_callback = NULL;/* see above */
980
981 /* Start cyclic DMA transfer */
982 if (!sb_start_dma(((sb.caps & SBMODE_16BITS) ? SBMODE_16BITS | SBMODE_SIGNED : 0) |
983 (sb.caps & SBMODE_STEREO), rate)) {
984 sb_output(FALSE);
985 sb_close();
986 fprintf(stderr, "Sound Blaster: DMA start failed.\n");
987 return -1;
988 }
989
990 if (sb.caps & SBMODE_16BITS) { /* can do stereo, too */
991 send_output = write_sb_s16stereo;
992 pause_output = sb_silence_s16;
993 resume_output = resume_output_nop;
994 printf("Sound Blaster 16 or compatible (16 bit, stereo, %u Hz)\n", rate);
995 } else if (sb.caps & SBMODE_STEREO) {
996 send_output = write_sb_u8stereo;
997 pause_output = sb_silence_u8;
998 resume_output = resume_output_nop;
999 printf("Sound Blaster Pro or compatible (8 bit, stereo, %u Hz)\n", rate);
1000 } else {
1001 send_output = write_sb_u8mono;
1002 pause_output = sb_silence_u8;
1003 resume_output = resume_output_nop;
1004 printf("Sound Blaster %c or compatible (8 bit, mono, %u Hz)\n",
1005 (sb.dspver < SBVER_20)? '1' : '2', rate);
1006 }
1007 close_output = close_sb_output;
1008
1009 return 0;
1010 }
1011
1012 #elif defined(WILDMIDI_AMIGA) && defined(AUDIODRV_AHI)
1013
1014 /* Driver for output to native Amiga AHI device:
1015 * Written by Szilárd Biró <col.lawrence@gmail.com>, loosely based
1016 * on an old AOS4 version by Fredrik Wikstrom <fredrik@a500.org>
1017 */
1018
1019 #define BUFFERSIZE (4 << 10)
1020
1021 static struct MsgPort *AHImp = NULL;
1022 static struct AHIRequest *AHIReq[2] = { NULL, NULL };
1023 static int active = 0;
1024 static int8_t *AHIBuf[2] = { NULL, NULL };
1025
1026 #define open_audio_output open_ahi_output
1027 static int write_ahi_output(int8_t *output_data, int output_size);
1028 static void close_ahi_output(void);
1029
open_ahi_output(void)1030 static int open_ahi_output(void) {
1031 AHImp = CreateMsgPort();
1032 if (AHImp) {
1033 AHIReq[0] = (struct AHIRequest *) CreateIORequest(AHImp, sizeof(struct AHIRequest));
1034 if (AHIReq[0]) {
1035 AHIReq[0]->ahir_Version = 4;
1036 AHIReq[1] = (struct AHIRequest *) AllocVec(sizeof(struct AHIRequest), MEMF_PUBLIC);
1037 if (AHIReq[1]) {
1038 if (!OpenDevice(AHINAME, AHI_DEFAULT_UNIT, (struct IORequest *)AHIReq[0], 0)) {
1039 /*AHIReq[0]->ahir_Std.io_Message.mn_Node.ln_Pri = 0;*/
1040 AHIReq[0]->ahir_Std.io_Command = CMD_WRITE;
1041 AHIReq[0]->ahir_Std.io_Data = NULL;
1042 AHIReq[0]->ahir_Std.io_Offset = 0;
1043 AHIReq[0]->ahir_Frequency = rate;
1044 AHIReq[0]->ahir_Type = AHIST_S16S;/* 16 bit stereo */
1045 AHIReq[0]->ahir_Volume = 0x10000;
1046 AHIReq[0]->ahir_Position = 0x8000;
1047 CopyMem(AHIReq[0], AHIReq[1], sizeof(struct AHIRequest));
1048
1049 AHIBuf[0] = (int8_t *) AllocVec(BUFFERSIZE, MEMF_PUBLIC | MEMF_CLEAR);
1050 if (AHIBuf[0]) {
1051 AHIBuf[1] = (int8_t *) AllocVec(BUFFERSIZE, MEMF_PUBLIC | MEMF_CLEAR);
1052 if (AHIBuf[1]) {
1053 send_output = write_ahi_output;
1054 close_output = close_ahi_output;
1055 pause_output = pause_output_nop;
1056 resume_output = resume_output_nop;
1057 return (0);
1058 }
1059 }
1060 }
1061 }
1062 }
1063 }
1064
1065 close_ahi_output();
1066 fprintf(stderr, "ERROR: Unable to open AHI output\r\n");
1067 return (-1);
1068 }
1069
write_ahi_output(int8_t * output_data,int output_size)1070 static int write_ahi_output(int8_t *output_data, int output_size) {
1071 int chunk;
1072 while (output_size > 0) {
1073 if (AHIReq[active]->ahir_Std.io_Data) {
1074 WaitIO((struct IORequest *) AHIReq[active]);
1075 }
1076 chunk = (output_size < BUFFERSIZE)? output_size : BUFFERSIZE;
1077 memcpy(AHIBuf[active], output_data, chunk);
1078 output_size -= chunk;
1079 output_data += chunk;
1080
1081 AHIReq[active]->ahir_Std.io_Data = AHIBuf[active];
1082 AHIReq[active]->ahir_Std.io_Length = chunk;
1083 AHIReq[active]->ahir_Link = !CheckIO((struct IORequest *) AHIReq[active ^ 1]) ? AHIReq[active ^ 1] : NULL;
1084 SendIO((struct IORequest *)AHIReq[active]);
1085 active ^= 1;
1086 }
1087 return (0);
1088 }
1089
close_ahi_output(void)1090 static void close_ahi_output(void) {
1091 if (AHIReq[1]) {
1092 AHIReq[0]->ahir_Link = NULL; /* in case we are linked to req[0] */
1093 if (!CheckIO((struct IORequest *) AHIReq[1])) {
1094 AbortIO((struct IORequest *) AHIReq[1]);
1095 WaitIO((struct IORequest *) AHIReq[1]);
1096 }
1097 FreeVec(AHIReq[1]);
1098 AHIReq[1] = NULL;
1099 }
1100 if (AHIReq[0]) {
1101 if (!CheckIO((struct IORequest *) AHIReq[0])) {
1102 AbortIO((struct IORequest *) AHIReq[0]);
1103 WaitIO((struct IORequest *) AHIReq[0]);
1104 }
1105 if (AHIReq[0]->ahir_Std.io_Device) {
1106 CloseDevice((struct IORequest *) AHIReq[0]);
1107 AHIReq[0]->ahir_Std.io_Device = NULL;
1108 }
1109 DeleteIORequest((struct IORequest *) AHIReq[0]);
1110 AHIReq[0] = NULL;
1111 }
1112 if (AHImp) {
1113 DeleteMsgPort(AHImp);
1114 AHImp = NULL;
1115 }
1116 if (AHIBuf[0]) {
1117 FreeVec(AHIBuf[0]);
1118 AHIBuf[0] = NULL;
1119 }
1120 if (AHIBuf[1]) {
1121 FreeVec(AHIBuf[1]);
1122 AHIBuf[1] = NULL;
1123 }
1124 }
1125
1126 #else
1127 #ifdef AUDIODRV_ALSA
1128
1129 static int alsa_first_time = 1;
1130 static snd_pcm_t *pcm = NULL;
1131 static char pcmname[64];
1132
1133 #define open_audio_output open_alsa_output
1134 static int write_alsa_output(int8_t *output_data, int output_size);
1135 static void close_alsa_output(void);
1136
open_alsa_output(void)1137 static int open_alsa_output(void) {
1138 snd_pcm_hw_params_t *hw;
1139 snd_pcm_sw_params_t *sw;
1140 int err;
1141 unsigned int alsa_buffer_time;
1142 unsigned int alsa_period_time;
1143 unsigned int r;
1144
1145 if (!pcmname[0]) {
1146 strcpy(pcmname, "default");
1147 }
1148
1149 if ((err = snd_pcm_open(&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
1150 fprintf(stderr, "Error: audio open error: %s\r\n", snd_strerror(err));
1151 return -1;
1152 }
1153
1154 snd_pcm_hw_params_alloca(&hw);
1155
1156 if ((err = snd_pcm_hw_params_any(pcm, hw)) < 0) {
1157 fprintf(stderr, "ERROR: No configuration available for playback: %s\r\n",
1158 snd_strerror(err));
1159 goto fail;
1160 }
1161
1162 if ((err = snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
1163 fprintf(stderr, "Cannot set access mode: %s.\r\n", snd_strerror(err));
1164 goto fail;
1165 }
1166
1167 if (snd_pcm_hw_params_set_format(pcm, hw, SND_PCM_FORMAT_S16) < 0) {
1168 fprintf(stderr, "ALSA does not support 16bit signed audio for your soundcard\r\n");
1169 goto fail;
1170 }
1171
1172 if (snd_pcm_hw_params_set_channels(pcm, hw, 2) < 0) {
1173 fprintf(stderr, "ALSA does not support stereo for your soundcard\r\n");
1174 goto fail;
1175 }
1176
1177 r = rate;
1178 if (snd_pcm_hw_params_set_rate_near(pcm, hw, &rate, 0) < 0) {
1179 fprintf(stderr, "ALSA does not support %uHz for your soundcard\r\n", rate);
1180 goto fail;
1181 }
1182 if (r != rate) {
1183 fprintf(stderr, "ALSA: sample rate set to %uHz instead of %u\r\n", rate, r);
1184 }
1185
1186 alsa_buffer_time = 500000;
1187 alsa_period_time = 50000;
1188
1189 if ((err = snd_pcm_hw_params_set_buffer_time_near(pcm, hw, &alsa_buffer_time, 0)) < 0) {
1190 fprintf(stderr, "Set buffer time failed: %s.\r\n", snd_strerror(err));
1191 goto fail;
1192 }
1193
1194 if ((err = snd_pcm_hw_params_set_period_time_near(pcm, hw, &alsa_period_time, 0)) < 0) {
1195 fprintf(stderr, "Set period time failed: %s.\r\n", snd_strerror(err));
1196 goto fail;
1197 }
1198
1199 if (snd_pcm_hw_params(pcm, hw) < 0) {
1200 fprintf(stderr, "Unable to install hw params\r\n");
1201 goto fail;
1202 }
1203
1204 snd_pcm_sw_params_alloca(&sw);
1205 snd_pcm_sw_params_current(pcm, sw);
1206 if (snd_pcm_sw_params(pcm, sw) < 0) {
1207 fprintf(stderr, "Unable to install sw params\r\n");
1208 goto fail;
1209 }
1210
1211 send_output = write_alsa_output;
1212 close_output = close_alsa_output;
1213 pause_output = pause_output_nop;
1214 resume_output = resume_output_nop;
1215 return (0);
1216
1217 fail: close_alsa_output();
1218 return -1;
1219 }
1220
write_alsa_output(int8_t * output_data,int output_size)1221 static int write_alsa_output(int8_t *output_data, int output_size) {
1222 int err;
1223 snd_pcm_uframes_t frames;
1224
1225 while (output_size > 0) {
1226 frames = snd_pcm_bytes_to_frames(pcm, output_size);
1227 if ((err = snd_pcm_writei(pcm, output_data, frames)) < 0) {
1228 if (snd_pcm_state(pcm) == SND_PCM_STATE_XRUN) {
1229 if ((err = snd_pcm_prepare(pcm)) < 0)
1230 fprintf(stderr, "\nsnd_pcm_prepare() failed.\r\n");
1231 alsa_first_time = 1;
1232 continue;
1233 }
1234 return err;
1235 }
1236
1237 output_size -= snd_pcm_frames_to_bytes(pcm, err);
1238 output_data += snd_pcm_frames_to_bytes(pcm, err);
1239 if (alsa_first_time) {
1240 alsa_first_time = 0;
1241 snd_pcm_start(pcm);
1242 }
1243 }
1244 return (0);
1245 }
1246
close_alsa_output(void)1247 static void close_alsa_output(void) {
1248 if (!pcm) return;
1249 printf("Shutting down sound output\r\n");
1250 snd_pcm_close(pcm);
1251 pcm = NULL;
1252 }
1253
1254 #elif defined AUDIODRV_OSS
1255
1256 #if !defined(AFMT_S16_NE)
1257 #ifdef WORDS_BIGENDIAN
1258 #define AFMT_S16_NE AFMT_S16_BE
1259 #else
1260 #define AFMT_S16_NE AFMT_S16_LE
1261 #endif
1262 #endif
1263
1264 #define DEFAULT_FRAGSIZE 14
1265 #define DEFAULT_NUMFRAGS 16
1266
1267 static char pcmname[64];
1268
1269 #define open_audio_output open_oss_output
1270 static int write_oss_output(int8_t *output_data, int output_size);
1271 static void close_oss_output(void);
1272
pause_output_oss(void)1273 static void pause_output_oss(void) {
1274 ioctl(audio_fd, SNDCTL_DSP_POST, 0);
1275 }
1276
open_oss_output(void)1277 static int open_oss_output(void) {
1278 int tmp;
1279 unsigned int r;
1280
1281 if (!pcmname[0]) {
1282 strcpy(pcmname, "/dev/dsp");
1283 }
1284
1285 if ((audio_fd = open(pcmname, O_WRONLY)) < 0) {
1286 fprintf(stderr, "ERROR: Unable to open dsp (%s)\r\n", strerror(errno));
1287 return (-1);
1288 }
1289 if (ioctl(audio_fd, SNDCTL_DSP_RESET, 0) < 0) {
1290 fprintf(stderr, "ERROR: Unable to reset dsp\r\n");
1291 goto fail;
1292 }
1293
1294 tmp = AFMT_S16_NE;
1295 if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp) < 0) {
1296 fprintf(stderr, "ERROR: Unable to set 16bit sound format\r\n");
1297 goto fail;
1298 }
1299
1300 tmp = 2;
1301 if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &tmp) < 0) {
1302 fprintf(stderr, "ERROR: Unable to set stereo\r\n");
1303 goto fail;
1304 }
1305
1306 r = rate;
1307 if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate) < 0) {
1308 fprintf(stderr, "ERROR: Unable to set %uHz sample rate\r\n", rate);
1309 goto fail;
1310 }
1311 if (r != rate) {
1312 fprintf(stderr, "OSS: sample rate set to %uHz instead of %u\r\n", rate, r);
1313 }
1314
1315 tmp = (DEFAULT_NUMFRAGS<<16)|DEFAULT_FRAGSIZE;
1316 if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp) < 0) {
1317 fprintf(stderr, "ERROR: Unable to set fragment size\r\n");
1318 goto fail;
1319 }
1320
1321 send_output = write_oss_output;
1322 close_output = close_oss_output;
1323 pause_output = pause_output_oss;
1324 resume_output = resume_output_nop;
1325 return (0);
1326
1327 fail: close_oss_output();
1328 return (-1);
1329 }
1330
write_oss_output(int8_t * output_data,int output_size)1331 static int write_oss_output(int8_t *output_data, int output_size) {
1332 int res = 0;
1333 while (output_size > 0) {
1334 res = write(audio_fd, output_data, output_size);
1335 if (res > 0) {
1336 output_size -= res;
1337 output_data += res;
1338 } else {
1339 fprintf(stderr, "\nOSS: write failure to dsp: %s.\r\n",
1340 strerror(errno));
1341 return (-1);
1342 }
1343 }
1344 return (0);
1345 }
1346
close_oss_output(void)1347 static void close_oss_output(void) {
1348 if (audio_fd < 0)
1349 return;
1350 printf("Shutting down sound output\r\n");
1351 ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
1352 close(audio_fd);
1353 audio_fd = -1;
1354 }
1355
1356 #elif defined AUDIODRV_OPENAL
1357
1358 #define NUM_BUFFERS 4
1359
1360 static ALCdevice *device;
1361 static ALCcontext *context;
1362 static ALuint sourceId = 0;
1363 static ALuint buffers[NUM_BUFFERS];
1364 static ALuint frames = 0;
1365
1366 #define open_audio_output open_openal_output
1367
pause_output_openal(void)1368 static void pause_output_openal(void) {
1369 alSourcePause(sourceId);
1370 }
1371
write_openal_output(int8_t * output_data,int output_size)1372 static int write_openal_output(int8_t *output_data, int output_size) {
1373 ALint processed, state;
1374 ALuint bufid;
1375
1376 if (frames < NUM_BUFFERS) { /* initial state: fill the buffers */
1377 alBufferData(buffers[frames], AL_FORMAT_STEREO16, output_data,
1378 output_size, rate);
1379
1380 /* Now queue and start playback! */
1381 if (++frames == NUM_BUFFERS) {
1382 alSourceQueueBuffers(sourceId, frames, buffers);
1383 alSourcePlay(sourceId);
1384 }
1385 return 0;
1386 }
1387
1388 /* Get relevant source info */
1389 alGetSourcei(sourceId, AL_SOURCE_STATE, &state);
1390 if (state == AL_PAUSED) { /* resume it, then.. */
1391 alSourcePlay(sourceId);
1392 if (alGetError() != AL_NO_ERROR) {
1393 fprintf(stderr, "\nError restarting playback\r\n");
1394 return (-1);
1395 }
1396 }
1397
1398 processed = 0;
1399 while (processed == 0) { /* Wait until we have a processed buffer */
1400 alGetSourcei(sourceId, AL_BUFFERS_PROCESSED, &processed);
1401 }
1402
1403 /* Unqueue and handle each processed buffer */
1404 alSourceUnqueueBuffers(sourceId, 1, &bufid);
1405
1406 /* Read the next chunk of data, refill the buffer, and queue it
1407 * back on the source */
1408 alBufferData(bufid, AL_FORMAT_STEREO16, output_data, output_size, rate);
1409 alSourceQueueBuffers(sourceId, 1, &bufid);
1410 if (alGetError() != AL_NO_ERROR) {
1411 fprintf(stderr, "\nError buffering data\r\n");
1412 return (-1);
1413 }
1414
1415 /* Make sure the source hasn't underrun */
1416 alGetSourcei(sourceId, AL_SOURCE_STATE, &state);
1417 /*printf("STATE: %#08x - %d\n", state, queued);*/
1418 if (state != AL_PLAYING) {
1419 ALint queued;
1420
1421 /* If no buffers are queued, playback is finished */
1422 alGetSourcei(sourceId, AL_BUFFERS_QUEUED, &queued);
1423 if (queued == 0) {
1424 fprintf(stderr, "\nNo buffers queued for playback\r\n");
1425 return (-1);
1426 }
1427
1428 alSourcePlay(sourceId);
1429 }
1430
1431 return (0);
1432 }
1433
close_openal_output(void)1434 static void close_openal_output(void) {
1435 if (!context) return;
1436 printf("Shutting down sound output\r\n");
1437 alSourceStop(sourceId); /* stop playing */
1438 alSourcei(sourceId, AL_BUFFER, 0); /* unload buffer from source */
1439 alDeleteBuffers(NUM_BUFFERS, buffers);
1440 alDeleteSources(1, &sourceId);
1441 alcDestroyContext(context);
1442 alcCloseDevice(device);
1443 context = NULL;
1444 device = NULL;
1445 frames = 0;
1446 }
1447
open_openal_output(void)1448 static int open_openal_output(void) {
1449 /* setup our audio devices and contexts */
1450 device = alcOpenDevice(NULL);
1451 if (!device) {
1452 fprintf(stderr, "OpenAL: Unable to open default device.\r\n");
1453 return (-1);
1454 }
1455
1456 context = alcCreateContext(device, NULL);
1457 if (context == NULL || alcMakeContextCurrent(context) == ALC_FALSE) {
1458 if (context != NULL)
1459 alcDestroyContext(context);
1460 alcCloseDevice(device);
1461 context = NULL;
1462 device = NULL;
1463 fprintf(stderr, "OpenAL: Failed to create the default context.\r\n");
1464 return (-1);
1465 }
1466
1467 /* setup our sources and buffers */
1468 alGenSources(1, &sourceId);
1469 alGenBuffers(NUM_BUFFERS, buffers);
1470
1471 send_output = write_openal_output;
1472 close_output = close_openal_output;
1473 pause_output = pause_output_openal;
1474 resume_output = resume_output_nop;
1475 return (0);
1476 }
1477
1478 #else /* no audio output driver compiled in: */
1479
1480 #define open_audio_output open_noaudio_output
open_noaudio_output(void)1481 static int open_noaudio_output(void) {
1482 fprintf(stderr, "No audio output driver was selected at compile time.\r\n");
1483 return -1;
1484 }
1485
1486 #endif /* AUDIODRV_ALSA */
1487 #endif /* _WIN32 || __CYGWIN__ */
1488
1489 static struct option const long_options[] = {
1490 { "version", 0, 0, 'v' },
1491 { "help", 0, 0, 'h' },
1492 { "rate", 1, 0, 'r' },
1493 { "mastervol", 1, 0, 'm' },
1494 { "config", 1, 0, 'c' },
1495 { "wavout", 1, 0, 'o' },
1496 { "tomidi", 1, 0, 'x' },
1497 { "convert", 1, 0, 'g' },
1498 { "frequency", 1, 0, 'f' },
1499 { "log_vol", 0, 0, 'l' },
1500 { "reverb", 0, 0, 'b' },
1501 { "test_midi", 0, 0, 't' },
1502 { "test_bank", 1, 0, 'k' },
1503 { "test_patch", 1, 0, 'p' },
1504 { "enhanced", 0, 0, 'e' },
1505 #if defined(AUDIODRV_OSS) || defined(AUDIODRV_ALSA)
1506 { "device", 1, 0, 'd' },
1507 #endif
1508 { "roundtempo", 0, 0, 'n' },
1509 { "skipsilentstart", 0, 0, 's' },
1510 { "textaslyric", 0, 0, 'a' },
1511 { "playfrom", 1, 0, 'i'},
1512 { "playto", 1, 0, 'j'},
1513 { NULL, 0, NULL, 0 }
1514 };
1515
do_help(void)1516 static void do_help(void) {
1517 printf(" -v --version Display version info and exit\n");
1518 printf(" -h --help Display this help and exit\n");
1519 #if defined(AUDIODRV_OSS) || defined(AUDIODRV_ALSA)
1520 printf(" -d D --device=D Use device D for audio output instead of default\n");
1521 #endif
1522 printf("MIDI Options:\n");
1523 printf(" -n --roundtempo Round tempo to nearest whole number\n");
1524 printf(" -s --skipsilentstart Skips any silence at the start of playback\n");
1525 printf(" -t --test_midi Listen to test MIDI\n");
1526 printf("Non-MIDI Options:\n");
1527 printf(" -x --tomidi Convert file to midi and save to file\n");
1528 printf(" -g --convert Convert XMI: 0 - No Conversion (default)\n");
1529 printf(" 1 - MT32 to GM\n");
1530 printf(" 2 - MT32 to GS\n");
1531 printf(" -f F --frequency=F Use frequency F Hz for playback (MUS)\n");
1532 printf("Software Wavetable Options:\n");
1533 printf(" -o W --wavout=W Save output to W in 16bit stereo format wav file\n");
1534 printf(" -l --log_vol Use log volume adjustments\n");
1535 printf(" -r N --rate=N Set sample rate to N samples per second (Hz)\n");
1536 printf(" -c P --config=P Point to your wildmidi.cfg config file name/path\n");
1537 printf(" defaults to: %s\n", WILDMIDI_CFG);
1538 printf(" -m V --mastervol=V Set the master volume (0..127), default is 100\n");
1539 printf(" -b --reverb Enable final output reverb engine\n");
1540 }
1541
do_version(void)1542 static void do_version(void) {
1543 printf("\nWildMidi %s Open Source Midi Sequencer\n", PACKAGE_VERSION);
1544 printf("Copyright (C) WildMIDI Developers 2001-2016\n\n");
1545 printf("WildMidi comes with ABSOLUTELY NO WARRANTY\n");
1546 printf("This is free software, and you are welcome to redistribute it under\n");
1547 printf("the terms and conditions of the GNU General Public License version 3.\n");
1548 printf("For more information see COPYING\n\n");
1549 printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
1550 printf("WildMIDI homepage is at %s\n\n", PACKAGE_URL);
1551 }
1552
do_syntax(void)1553 static void do_syntax(void) {
1554 printf("Usage: wildmidi [options] filename.mid\n\n");
1555 }
1556
1557 static char config_file[1024];
1558
main(int argc,char ** argv)1559 int main(int argc, char **argv) {
1560 struct _WM_Info *wm_info;
1561 int i, res;
1562 int option_index = 0;
1563 uint16_t mixer_options = 0;
1564 void *midi_ptr;
1565 uint8_t master_volume = 100;
1566 int8_t *output_buffer;
1567 uint32_t perc_play;
1568 uint32_t pro_mins;
1569 uint32_t pro_secs;
1570 uint32_t apr_mins;
1571 uint32_t apr_secs;
1572 char modes[5];
1573 uint8_t ch;
1574 int test_midi = 0;
1575 int test_count = 0;
1576 uint8_t *test_data;
1577 uint8_t test_bank = 0;
1578 uint8_t test_patch = 0;
1579 static char spinner[] = "|/-\\";
1580 static int spinpoint = 0;
1581 unsigned long int seek_to_sample;
1582 uint32_t samples = 0;
1583 int inpause = 0;
1584 char * ret_err = NULL;
1585 long libraryver;
1586 char * lyric = NULL;
1587 char *last_lyric = NULL;
1588 size_t last_lyric_length = 0;
1589 int8_t kareoke = 0;
1590 #define MAX_LYRIC_CHAR 128
1591 char lyrics[MAX_LYRIC_CHAR + 1];
1592 #define MAX_DISPLAY_LYRICS 29
1593 char display_lyrics[MAX_DISPLAY_LYRICS + 1];
1594
1595 unsigned long int play_from = 0;
1596 unsigned long int play_to = 0;
1597
1598 memset(lyrics,' ',MAX_LYRIC_CHAR);
1599 memset(display_lyrics,' ',MAX_DISPLAY_LYRICS);
1600
1601 #if defined(AUDIODRV_OSS) || defined(AUDIODRV_ALSA)
1602 pcmname[0] = 0;
1603 #endif
1604 config_file[0] = 0;
1605 wav_file[0] = 0;
1606 midi_file[0] = 0;
1607
1608 do_version();
1609 while (1) {
1610 i = getopt_long(argc, argv, "0vho:tx:g:f:lr:c:m:btak:p:ed:nsi:j:", long_options,
1611 &option_index);
1612 if (i == -1)
1613 break;
1614 switch (i) {
1615 case 'v': /* Version */
1616 return (0);
1617 case 'h': /* help */
1618 do_syntax();
1619 do_help();
1620 return (0);
1621 case 'r': /* Sample Rate */
1622 res = atoi(optarg);
1623 if (res < 0 || res > 65535) {
1624 fprintf(stderr, "Error: bad rate %i.\n", res);
1625 return (1);
1626 }
1627 rate = (uint32_t) res;
1628 break;
1629 case 'b': /* Reverb */
1630 mixer_options |= WM_MO_REVERB;
1631 break;
1632 case 'm': /* Master Volume */
1633 master_volume = (uint8_t) atoi(optarg);
1634 break;
1635 case 'o': /* Wav Output */
1636 if (!*optarg) {
1637 fprintf(stderr, "Error: empty wavfile name.\n");
1638 return (1);
1639 }
1640 strncpy(wav_file, optarg, sizeof(wav_file));
1641 wav_file[sizeof(wav_file) - 1] = 0;
1642 break;
1643 case 'g': /* XMIDI Conversion */
1644 WildMidi_SetCvtOption(WM_CO_XMI_TYPE, (uint16_t) atoi(optarg));
1645 break;
1646 case 'f': /* MIDI-like Conversion */
1647 WildMidi_SetCvtOption(WM_CO_FREQUENCY, (uint16_t) atoi(optarg));
1648 break;
1649 case 'x': /* MIDI Output */
1650 if (!*optarg) {
1651 fprintf(stderr, "Error: empty midi name.\n");
1652 return (1);
1653 }
1654 strncpy(midi_file, optarg, sizeof(midi_file));
1655 midi_file[sizeof(midi_file) - 1] = 0;
1656 break;
1657 case 'c': /* Config File */
1658 if (!*optarg) {
1659 fprintf(stderr, "Error: empty config name.\n");
1660 return (1);
1661 }
1662 strncpy(config_file, optarg, sizeof(config_file));
1663 config_file[sizeof(config_file) - 1] = 0;
1664 break;
1665 #if defined(AUDIODRV_OSS) || defined(AUDIODRV_ALSA)
1666 case 'd': /* Output device */
1667 if (!*optarg) {
1668 fprintf(stderr, "Error: empty device name.\n");
1669 return (1);
1670 }
1671 strncpy(pcmname, optarg, sizeof(pcmname));
1672 pcmname[sizeof(pcmname) - 1] = 0;
1673 break;
1674 #endif
1675 case 'e': /* Enhanced Resampling */
1676 mixer_options |= WM_MO_ENHANCED_RESAMPLING;
1677 break;
1678 case 'l': /* log volume */
1679 mixer_options |= WM_MO_LOG_VOLUME;
1680 break;
1681 case 't': /* play test midis */
1682 test_midi = 1;
1683 break;
1684 case 'k': /* set test bank */
1685 test_bank = (uint8_t) atoi(optarg);
1686 break;
1687 case 'p': /* set test patch */
1688 test_patch = (uint8_t) atoi(optarg);
1689 break;
1690 case 'n': /* whole number tempo */
1691 mixer_options |= WM_MO_ROUNDTEMPO;
1692 break;
1693 case 'a':
1694 /* Some files have the lyrics in the text meta event.
1695 * This option reads lyrics from there instead. */
1696 mixer_options |= WM_MO_TEXTASLYRIC;
1697 break;
1698 case 's': /* strip silence at start */
1699 mixer_options |= WM_MO_STRIPSILENCE;
1700 break;
1701 case '0': /* treat as type 2 midi when writing to file */
1702 mixer_options |= WM_MO_SAVEASTYPE0;
1703 break;
1704 case 'i':
1705 play_from = (unsigned long int)(atof(optarg) * (double)rate);
1706 break;
1707 case 'j':
1708 play_to = (unsigned long int)(atof(optarg) * (double)rate);
1709 break;
1710 default:
1711 do_syntax();
1712 return (1);
1713 }
1714 }
1715
1716 if (optind >= argc && !test_midi) {
1717 fprintf(stderr, "ERROR: No midi file given\r\n");
1718 do_syntax();
1719 return (1);
1720 }
1721
1722 if (test_midi) {
1723 if (midi_file[0] != '\0') {
1724 fprintf(stderr, "--test_midi and --convert cannot be used together.\n");
1725 return (1);
1726 }
1727 }
1728
1729 /* check if we only need to convert a file to midi */
1730 if (midi_file[0] != '\0') {
1731 const char *real_file = FIND_LAST_DIRSEP(argv[optind]);
1732 uint32_t size;
1733 uint8_t *data;
1734
1735 if (!real_file) real_file = argv[optind];
1736 else real_file++;
1737
1738 printf("Converting %s\r\n", real_file);
1739 if (WildMidi_ConvertToMidi(argv[optind], &data, &size) < 0) {
1740 fprintf(stderr, "Conversion failed: %s.\r\n", WildMidi_GetError());
1741 WildMidi_ClearError();
1742 return (1);
1743 }
1744
1745 printf("Writing %s: %u bytes.\r\n", midi_file, size);
1746 write_midi_output(data, size);
1747 free(data);
1748 return (0);
1749 }
1750
1751 if (!config_file[0]) {
1752 strncpy(config_file, WILDMIDI_CFG, sizeof(config_file));
1753 config_file[sizeof(config_file) - 1] = 0;
1754 }
1755
1756 printf("Initializing Sound System\n");
1757 if (wav_file[0] != '\0') {
1758 if (open_wav_output() == -1) {
1759 return (1);
1760 }
1761 } else {
1762 if (open_audio_output() == -1) {
1763 return (1);
1764 }
1765 }
1766
1767 libraryver = WildMidi_GetVersion();
1768 printf("Initializing libWildMidi %ld.%ld.%ld\n\n",
1769 (libraryver>>16) & 255,
1770 (libraryver>> 8) & 255,
1771 (libraryver ) & 255);
1772 if (WildMidi_Init(config_file, rate, mixer_options) == -1) {
1773 fprintf(stderr, "%s\r\n", WildMidi_GetError());
1774 WildMidi_ClearError();
1775 return (1);
1776 }
1777
1778 printf(" + Volume up e Better resampling n Next Midi\n");
1779 printf(" - Volume down l Log volume q Quit\n");
1780 printf(" , 1sec Seek Back r Reverb . 1sec Seek Forward\n");
1781 printf(" m save as midi p Pause On/Off\n\n");
1782
1783 output_buffer = (int8_t *) malloc(16384);
1784 if (output_buffer == NULL) {
1785 fprintf(stderr, "Not enough memory, exiting\n");
1786 WildMidi_Shutdown();
1787 return (1);
1788 }
1789
1790 wm_inittty();
1791 #ifdef WILDMIDI_AMIGA
1792 amiga_sysinit();
1793 #endif
1794
1795 WildMidi_MasterVolume(master_volume);
1796
1797 while (optind < argc || test_midi) {
1798 WildMidi_ClearError();
1799 if (!test_midi) {
1800 const char *real_file = FIND_LAST_DIRSEP(argv[optind]);
1801
1802 if (!real_file) real_file = argv[optind];
1803 else real_file++;
1804 printf("\rPlaying %s ", real_file);
1805
1806 midi_ptr = WildMidi_Open(argv[optind]);
1807 optind++;
1808 if (midi_ptr == NULL) {
1809 ret_err = WildMidi_GetError();
1810 printf(" Skipping: %s\r\n",ret_err);
1811 continue;
1812 }
1813 } else {
1814 if (test_count == midi_test_max) {
1815 break;
1816 }
1817 test_data = (uint8_t *) malloc(midi_test[test_count].size);
1818 memcpy(test_data, midi_test[test_count].data,
1819 midi_test[test_count].size);
1820 test_data[25] = test_bank;
1821 test_data[28] = test_patch;
1822 midi_ptr = WildMidi_OpenBuffer(test_data, 633);
1823 test_count++;
1824 if (midi_ptr == NULL) {
1825 fprintf(stderr, "\rFailed loading test midi no. %i\r\n", test_count);
1826 continue;
1827 }
1828 printf("\rPlaying test midi no. %i ", test_count);
1829 }
1830
1831 wm_info = WildMidi_GetInfo(midi_ptr);
1832
1833 apr_mins = wm_info->approx_total_samples / (rate * 60);
1834 apr_secs = (wm_info->approx_total_samples % (rate * 60)) / rate;
1835 mixer_options = wm_info->mixer_options;
1836 modes[0] = (mixer_options & WM_MO_LOG_VOLUME)? 'l' : ' ';
1837 modes[1] = (mixer_options & WM_MO_REVERB)? 'r' : ' ';
1838 modes[2] = (mixer_options & WM_MO_ENHANCED_RESAMPLING)? 'e' : ' ';
1839 modes[3] = ' ';
1840 modes[4] = '\0';
1841
1842 printf("\r\n[Approx %2um %2us Total]\r\n", apr_mins, apr_secs);
1843 fprintf(stderr, "\r");
1844
1845 memset(lyrics,' ',MAX_LYRIC_CHAR);
1846 memset(display_lyrics,' ',MAX_DISPLAY_LYRICS);
1847
1848 if (play_from != 0) {
1849 WildMidi_FastSeek(midi_ptr, &play_from);
1850 if (play_to < play_from) {
1851 // Ignore --playto if set less than --playfrom
1852 play_to = 0;
1853 }
1854 }
1855
1856 while (1) {
1857 ch = 0;
1858 #ifdef _WIN32
1859 if (_kbhit()) {
1860 ch = _getch();
1861 _putch(ch);
1862 }
1863 #elif defined(__DJGPP__) || defined(__OS2__) || defined(__EMX__)
1864 if (kbhit()) {
1865 ch = getch();
1866 putch(ch);
1867 }
1868 #elif defined(WILDMIDI_AMIGA)
1869 amiga_getch (&ch);
1870 #else
1871 if (read(STDIN_FILENO, &ch, 1) != 1)
1872 ch = 0;
1873 #endif
1874 if (ch) {
1875 switch (ch) {
1876 case 'l':
1877 WildMidi_SetOption(midi_ptr, WM_MO_LOG_VOLUME,
1878 ((mixer_options & WM_MO_LOG_VOLUME) ^ WM_MO_LOG_VOLUME));
1879 mixer_options ^= WM_MO_LOG_VOLUME;
1880 modes[0] = (mixer_options & WM_MO_LOG_VOLUME)? 'l' : ' ';
1881 break;
1882 case 'r':
1883 WildMidi_SetOption(midi_ptr, WM_MO_REVERB,
1884 ((mixer_options & WM_MO_REVERB) ^ WM_MO_REVERB));
1885 mixer_options ^= WM_MO_REVERB;
1886 modes[1] = (mixer_options & WM_MO_REVERB)? 'r' : ' ';
1887 break;
1888 case 'e':
1889 WildMidi_SetOption(midi_ptr, WM_MO_ENHANCED_RESAMPLING,
1890 ((mixer_options & WM_MO_ENHANCED_RESAMPLING) ^ WM_MO_ENHANCED_RESAMPLING));
1891 mixer_options ^= WM_MO_ENHANCED_RESAMPLING;
1892 modes[2] = (mixer_options & WM_MO_ENHANCED_RESAMPLING)? 'e' : ' ';
1893 break;
1894 case 'a':
1895 WildMidi_SetOption(midi_ptr, WM_MO_TEXTASLYRIC,
1896 ((mixer_options & WM_MO_TEXTASLYRIC) ^ WM_MO_TEXTASLYRIC));
1897 mixer_options ^= WM_MO_TEXTASLYRIC;
1898 break;
1899 case 'n':
1900 goto NEXTMIDI;
1901 case 'p':
1902 if (inpause) {
1903 inpause = 0;
1904 fprintf(stderr, " \r");
1905 resume_output();
1906 } else {
1907 inpause = 1;
1908 fprintf(stderr, "Paused \r");
1909 pause_output();
1910 continue;
1911 }
1912 break;
1913 case 'q':
1914 printf("\r\n");
1915 if (inpause) goto end2;
1916 goto end1;
1917 case '-':
1918 if (master_volume > 0) {
1919 master_volume--;
1920 WildMidi_MasterVolume(master_volume);
1921 }
1922 break;
1923 case '+':
1924 if (master_volume < 127) {
1925 master_volume++;
1926 WildMidi_MasterVolume(master_volume);
1927 }
1928 break;
1929 case ',': /* fast seek backwards */
1930 if (wm_info->current_sample < rate) {
1931 seek_to_sample = 0;
1932 } else {
1933 seek_to_sample = wm_info->current_sample - rate;
1934 }
1935 WildMidi_FastSeek(midi_ptr, &seek_to_sample);
1936 break;
1937 case '.': /* fast seek forwards */
1938 if ((wm_info->approx_total_samples
1939 - wm_info->current_sample) < rate) {
1940 seek_to_sample = wm_info->approx_total_samples;
1941 } else {
1942 seek_to_sample = wm_info->current_sample + rate;
1943 }
1944 WildMidi_FastSeek(midi_ptr, &seek_to_sample);
1945 break;
1946 case '<':
1947 WildMidi_SongSeek (midi_ptr, -1);
1948 break;
1949 case '>':
1950 WildMidi_SongSeek (midi_ptr, 1);
1951 break;
1952 case '/':
1953 WildMidi_SongSeek (midi_ptr, 0);
1954 break;
1955 case 'm': /* save as midi */ {
1956 int8_t *getmidibuffer = NULL;
1957 uint32_t getmidisize = 0;
1958 int32_t getmidiret = 0;
1959
1960 getmidiret = WildMidi_GetMidiOutput(midi_ptr, &getmidibuffer, &getmidisize);
1961 if (getmidiret == -1) {
1962 fprintf(stderr, "\r\n\nFAILED to convert events to midi\r\n");
1963 ret_err = WildMidi_GetError();
1964 fprintf(stderr, "%s\r\n",ret_err);
1965 WildMidi_ClearError();
1966 } else {
1967 char *real_file = FIND_LAST_DIRSEP(argv[optind-1]);
1968 if (!real_file) real_file = argv[optind];
1969 else real_file++;
1970
1971 strncpy(midi_file, real_file, strlen(real_file));
1972 midi_file[strlen(real_file)-4] = '.';
1973 midi_file[strlen(real_file)-3] = 'm';
1974 midi_file[strlen(real_file)-2] = 'i';
1975 midi_file[strlen(real_file)-1] = 'd';
1976
1977 printf("\rWriting %s: %u bytes.\r\n", midi_file, getmidisize);
1978 write_midi_output(getmidibuffer,getmidisize);
1979 free(getmidibuffer);
1980 }
1981 } break;
1982 case 'k': /* Kareoke */
1983 /* Enables/Disables the display of lyrics */
1984 kareoke ^= 1;
1985 break;
1986 default:
1987 break;
1988 }
1989 }
1990
1991 if (inpause) {
1992 wm_info = WildMidi_GetInfo(midi_ptr);
1993 perc_play = (wm_info->current_sample * 100)
1994 / wm_info->approx_total_samples;
1995 pro_mins = wm_info->current_sample / (rate * 60);
1996 pro_secs = (wm_info->current_sample % (rate * 60)) / rate;
1997 fprintf(stderr,
1998 "%s [%s] [%3i] [%2um %2us Processed] [%2u%%] P \r",
1999 display_lyrics, modes, (int)master_volume, pro_mins,
2000 pro_secs, perc_play);
2001 msleep(5);
2002 continue;
2003 }
2004
2005 if (play_to != 0) {
2006 if ((wm_info->current_sample + 4096) <= play_to) {
2007 samples = 16384;
2008 } else {
2009 samples = (play_to - wm_info->current_sample) << 2;
2010 if (!samples) {
2011 // We are at or past where we wanted to play to
2012 break;
2013 }
2014 }
2015 }
2016 else {
2017 samples = 16384;
2018 }
2019 res = WildMidi_GetOutput(midi_ptr, output_buffer, samples);
2020
2021 if (res <= 0)
2022 break;
2023
2024 wm_info = WildMidi_GetInfo(midi_ptr);
2025 lyric = WildMidi_GetLyric(midi_ptr);
2026
2027 memmove(lyrics, &lyrics[1], MAX_LYRIC_CHAR - 1);
2028 lyrics[MAX_LYRIC_CHAR - 1] = ' ';
2029
2030 if ((lyric != NULL) && (lyric != last_lyric) && (kareoke)) {
2031 last_lyric = lyric;
2032 if (last_lyric_length != 0) {
2033 memcpy(lyrics, &lyrics[last_lyric_length], MAX_LYRIC_CHAR - last_lyric_length);
2034 }
2035 memcpy(&lyrics[MAX_DISPLAY_LYRICS], lyric, strlen(lyric));
2036 last_lyric_length = strlen(lyric);
2037 } else {
2038 if (last_lyric_length != 0) last_lyric_length--;
2039 }
2040
2041 memcpy(display_lyrics,lyrics,MAX_DISPLAY_LYRICS);
2042 display_lyrics[MAX_DISPLAY_LYRICS] = '\0';
2043
2044 perc_play = (wm_info->current_sample * 100)
2045 / wm_info->approx_total_samples;
2046 pro_mins = wm_info->current_sample / (rate * 60);
2047 pro_secs = (wm_info->current_sample % (rate * 60)) / rate;
2048 fprintf(stderr,
2049 "%s [%s] [%3i] [%2um %2us Processed] [%2u%%] %c \r",
2050 display_lyrics, modes, (int)master_volume, pro_mins,
2051 pro_secs, perc_play, spinner[spinpoint++ % 4]);
2052
2053 if (send_output(output_buffer, res) < 0) {
2054 /* driver prints an error message already. */
2055 printf("\r");
2056 goto end2;
2057 }
2058 }
2059 NEXTMIDI: fprintf(stderr, "\r\n");
2060 if (WildMidi_Close(midi_ptr) == -1) {
2061 ret_err = WildMidi_GetError();
2062 fprintf(stderr, "OOPS: failed closing midi handle!\r\n%s\r\n",ret_err);
2063 }
2064 memset(output_buffer, 0, 16384);
2065 send_output(output_buffer, 16384);
2066 }
2067 end1: memset(output_buffer, 0, 16384);
2068 send_output(output_buffer, 16384);
2069 msleep(5);
2070 end2: close_output();
2071 free(output_buffer);
2072 if (WildMidi_Shutdown() == -1) {
2073 ret_err = WildMidi_GetError();
2074 fprintf(stderr, "OOPS: failure shutting down libWildMidi\r\n%s\r\n", ret_err);
2075 WildMidi_ClearError();
2076 }
2077 wm_resetty();
2078
2079 printf("\r\n");
2080 return (0);
2081 }
2082
2083 /* helper / replacement functions: */
2084
2085 #if !(defined(_WIN32) || defined(__DJGPP__) || defined(WILDMIDI_AMIGA) || defined(__OS2__) || defined(__EMX__))
msleep(unsigned long milisec)2086 static int msleep(unsigned long milisec) {
2087 struct timespec req = { 0, 0 };
2088 time_t sec = (int) (milisec / 1000);
2089 milisec = milisec - (sec * 1000);
2090 req.tv_sec = sec;
2091 req.tv_nsec = milisec * 1000000L;
2092 while (nanosleep(&req, &req) == -1)
2093 continue;
2094 return (1);
2095 }
2096 #endif
2097