home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.4front-tech.com
/
ftp.4front-tech.com.tar
/
ftp.4front-tech.com
/
ossfree
/
snd-util-3.8.tar.gz
/
snd-util-3.8.tar
/
sndkit
/
mplay
/
main.c
next >
Wrap
C/C++ Source or Header
|
1997-02-25
|
5KB
|
301 lines
#define DEB(stmt) /* stmt */ /* For debug printing */
#define DEB2(stmt) /* stmt */ /* For debug printing */
#define DEB3(stmt) stmt /* For debug printing */
#define DEB_ALWAYS(stmt) stmt /* Interesting things */
#define _INCLUDE_POSIX_SOURCE 1
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/errno.h>
#include <sys/soundcard.h>
#ifndef SOUND_VERSION
# error At least version 3.8 of sys/soundcard.h is required.
#else
# if SOUND_VERSION < 0x0307f0
# error At least version 3.8 of sys/soundcard.h is required.
# endif
#endif
extern int errno;
#include "mlib.h"
SEQ_DEFINEBUF(1024);
int seqfd;
mlib_track *tracks[1024];
int ntrks = 0;
int dev = 0;
#ifndef OSSLIB
void
seqbuf_dump ()
{
if (_seqbufptr)
if (write (seqfd, _seqbuf, _seqbufptr) == -1)
{
perror ("write /dev/music");
exit (-1);
}
_seqbufptr = 0;
}
#endif
void
player()
{
int i, track;
int prev_time = 0;
int ptrs[1024] = {0};
unsigned char *ptr;
unsigned char *event;
int time, n = 0;
#if 1
for (track = 0;track<ntrks;track++)
for (i=0;i<128;i++)
{
if (tracks[track]->pgm_map[i] != -1)
{
n++;
SEQ_LOAD_GMINSTR(dev, i);
}
tracks[track]->pgm_map[i] = i;
if (n == 0) /* No program changes. Assume pgm# 0 */
SEQ_LOAD_GMINSTR(dev, 0);
if (tracks[track]->drum_map[i] != -1)
SEQ_LOAD_GMDRUM(dev, i);
tracks[track]->drum_map[i] = i;
}
if (n == 0) /* No program changes detected */
SEQ_LOAD_GMINSTR(dev, 0); /* Acoustic piano */
SEQ_START_TIMER();
while (1)
{
int best = -1, best_time = 0x7fffffff;
for (i=0;i<ntrks;i++)
if (ptrs[i] < tracks[i]->len)
{
ptr = &(tracks[i]->events[ptrs[i]*12]);
event = &ptr[4];
time = *(int*)ptr;
if (time < best_time)
{
best = i;
best_time = time;
}
}
if (best == -1) return;
ptr = &(tracks[best]->events[ptrs[best]*12]);
event = &ptr[4];
time = *(int*)ptr;
ptrs[best]++;
if (event[0] < 128)
{
}
else
{
int j;
if (time > prev_time)
{
SEQ_WAIT_TIME(time);
prev_time = time;
}
if (event[0] == EV_SYSEX)
{
event[1] = dev;
}
if ((event[0] & 0xf0) == 0x90)
{
event[1] = dev;
if (event[0] == EV_CHN_COMMON &&
event[2] == MIDI_PGM_CHANGE)
{
event[4] = tracks[best]->pgm_map[event[4]];
}
}
_SEQ_NEEDBUF(8);
memcpy(&_seqbuf[_seqbufptr], event, 8);
_SEQ_ADVBUF(8);
}
}
#endif
}
int
find_device(int default_dev)
{
int i, n;
struct synth_info info;
if (ioctl (seqfd, SNDCTL_SEQ_NRSYNTHS, &n) == -1)
{
perror ("/dev/music");
exit (-1);
}
for (i = 0; i < n; i++)
{
info.device = i;
if (ioctl (seqfd, SNDCTL_SYNTH_INFO, &info) == -1)
{
perror ("/dev/music");
exit (-1);
}
if (info.synth_type == SYNTH_TYPE_SAMPLE
&& info.synth_subtype == SAMPLE_TYPE_BASIC)
{
return i;
}
}
return default_dev;
}
void
list_devices(void)
{
int i, n;
struct synth_info info;
if ((seqfd=open("/dev/music", O_RDWR, 0))==-1)
{
perror("/dev/music");
exit(-1);
}
if (ioctl (seqfd, SNDCTL_SEQ_NRSYNTHS, &n) == -1)
{
perror ("/dev/music");
exit (-1);
}
fprintf(stderr, "Possible device numbers (dev#) are:\n");
for (i = 0; i < n; i++)
{
info.device = i;
if (ioctl (seqfd, SNDCTL_SYNTH_INFO, &info) == -1)
{
perror ("/dev/music");
exit (-1);
}
fprintf(stderr, "\t%d: %s\n", i, info.name);
}
}
int main(int argc, char *argv[])
{
mlib_desc *mdesc;
int was_last;
int tmp, argp=1;
if (argc < 2)
{
fprintf(stderr, "Usage: %s [dev#] midifile\n", argv[0]);
list_devices();
exit(-1);
}
if ((seqfd=open("/dev/music", O_RDWR, 0))==-1)
{
perror("/dev/music");
exit(-1);
}
if (isdigit(argv[argp][0]))
dev = atoi(argv[argp++]);
else
dev = find_device(dev);
#ifdef OSSLIB
OSS_init(seqfd, 1024);
#endif
tmp=dev;
ioctl(seqfd, SNDCTL_FM_4OP_ENABLE, &tmp);
#if 0
tmp=dev;
ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &tmp);
#endif
if ((mdesc = mlib_open(argv[argp]))==NULL)
{
fprintf(stderr, "Can't open MIDI file %s: %s\n",
argv[argp], mlib_errmsg());
exit(-1);
}
tmp = mdesc->hdr.division;
if (ioctl(seqfd, SNDCTL_TMR_TIMEBASE, &tmp)==-1)
{
perror("Set timebase");
exit(-1);
}
tmp = 100;
if (ioctl(seqfd, SNDCTL_TMR_TEMPO, &tmp)==-1)
{
perror("Set tempo");
exit(-1);
}
ntrks = 0;
while ((tracks[ntrks]=mlib_loadtrack(mdesc, &was_last))!=NULL)
{
int i;
DEB2(printf("Loaded track %03d: len = %d events, flags = %08x\n",
mdesc->curr_trk, tracks[ntrks]->len, tracks[ntrks]->flags));
ntrks++;
}
if (!was_last)
{
fprintf(stderr, "%s: %s\n", argv[1], mlib_errmsg());
exit(-1);
}
tmp = (int)mdesc->timesig;
/* printf("Setting timesig to %08x\n", tmp); */
if (ioctl(seqfd, SNDCTL_TMR_METRONOME, &tmp)==-1)
{
/* perror("Set metronome"); */
}
player();
SEQ_DELTA_TIME(
mdesc->hdr.division*4);
SEQ_DUMPBUF();
mlib_close(mdesc);
exit(0);
}