diff --git a/.cvsignore b/.cvsignore index f96f088..4030705 100644 --- a/.cvsignore +++ b/.cvsignore @@ -13,3 +13,4 @@ sdl mtest getvab *.cat +sdltest diff --git a/ChangeLog b/ChangeLog index 594b154..9cb193b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2007-01-01 Pace Willisson + * V15 + + * add music + * V14 * add audio to mission playback diff --git a/Makefile b/Makefile index 6e9304c..389d3f3 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,14 @@ EXTRA_WARNINGS = -Werror -Wextra -Wno-unused-parameter -Wno-sign-compare \ CFLAGS = -g -Wall -Dfar= -Dpascal= -I. `sdl-config --cflags` +LIBS = `sdl-config --libs` -lvorbisfile -lm + .c.o: @echo "$(CC) ...flags... -c $*.c" @$(CC) $(CFLAGS) $(EXTRA_WARNINGS) -O -c -o TMP.o $*.c @$(CC) $(CFLAGS) $(EXTRA_WARNINGS) -c $*.c -PROGS = baris imgsplit vtest decode getport mkmovie getvab mtest +PROGS = baris imgsplit vtest decode getport mkmovie getvab mtest sdltest all: $(PROGS) BARIS_HFILES = Buzz_inc.h cdmaster.h cdrom.h data.h externs.h mis.h mtype.h \ @@ -23,9 +25,9 @@ BARIS_OBJS = admin.o aimast.o aimis.o aipur.o ast0.o ast1.o \ news_suq.o \ place.o port.o prefs.o prest.o radar.o rdplex.o recods.o \ replay.o review.o rush.o sel.o start.o \ - vab.o pace.o gx.o gr.o sdl.o + vab.o pace.o gx.o gr.o sdl.o music.o baris: $(BARIS_OBJS) - $(CC) $(CFLAGS) -o baris $(BARIS_OBJS) `sdl-config --libs` -lm + $(CC) $(CFLAGS) -o baris $(BARIS_OBJS) $(LIBS) # $(BARIS_OBJS): $(BARIS_HFILES) @@ -54,8 +56,8 @@ mtest: mtest.o sdl.o: sdl.c $(CC) $(CFLAGS) `sdl-config --cflags` -c sdl.c -sdl: sdl.o - $(CC) $(CFLAGS) -o sdl sdl.o `sdl-config --libs` -lm +sdltest: sdltest.o + $(CC) $(CFLAGS) -o sdltest sdltest.o `sdl-config --libs` -lvorbisfile -lm clean: rm -f *.o *~ diff --git a/QUESTIONS b/QUESTIONS index 8aca683..13e4820 100644 --- a/QUESTIONS +++ b/QUESTIONS @@ -1,4 +1,5 @@ The frame rate in the FRM files seems to be 8, which means 8 frames per second, right? +RLE bug diff --git a/av.h b/av.h index f536631..5c31f86 100644 --- a/av.h +++ b/av.h @@ -10,6 +10,7 @@ struct audio_chunk { struct audio_chunk *next; void *data; int size; + int loop; }; void play (struct audio_chunk *cp); diff --git a/main.c b/main.c index ace38f6..a97a39f 100644 --- a/main.c +++ b/main.c @@ -220,13 +220,7 @@ void remove_savedat(char *fName) for (p = fullname; *p; p++) *p = tolower (*p); - printf ("remove_savedat(\"%s\")...", fullname); - - if (remove (fullname) < 0) - printf ("error %s\n", strerror (errno)); - else - printf ("ok\n"); - + remove (fullname); } void diff --git a/mkogg b/mkogg new file mode 100755 index 0000000..ce7bcf5 --- /dev/null +++ b/mkogg @@ -0,0 +1,15 @@ +#! /bin/sh + +# note: using timidity++-2.13.2 and GS.ARJ +# makes an ogg file for each midi file + + +cd /home/pace/ris.music + +for mid in *.MID +do + echo $mid + + ogg=`basename $mid .MID`.ogg + timidity -Ov --output-mono -s 11025 -o $ogg $mid +done diff --git a/mtest.c b/mtest.c index d6c3b71..4c887cf 100644 --- a/mtest.c +++ b/mtest.c @@ -3,6 +3,37 @@ #include #include +void +dump (void *buf, int n) +{ + int i; + int j; + int c; + + for (i = 0; i < n; i += 16) { + printf ("%04x: ", i); + for (j = 0; j < 16; j++) { + if (i+j < n) + printf ("%02x ", ((unsigned char *)buf)[i+j]); + else + printf (" "); + } + printf (" "); + for (j = 0; j < 16; j++) { + c = ((unsigned char *)buf)[i+j] & 0x7f; + if (i+j >= n) + putchar (' '); + else if (c < ' ' || c == 0x7f) + putchar ('.'); + else + putchar (c); + } + printf ("\n"); + + } +} + + #pragma pack(1) struct TM { char ID[6]; @@ -34,7 +65,10 @@ open_music_cat (char *filename) fread (&dp->dir, 1, sizeof dp->dir, musicf); for (i = 0, dp = dirs; i < MDIRS; i++, dp++) { - dp->nfiles = dp->dir.size / sizeof (struct TM); + printf ("%6.6s 0x%08lx %8ld\n", dp->dir.ID, + dp->dir.offset, dp->dir.size); + + dp->nfiles = 32; dp->files = calloc (dp->nfiles, sizeof *dp->files); fseek (musicf, dp->dir.offset, SEEK_SET); fread (dp->files, dp->nfiles, sizeof *dp->files, musicf); @@ -49,6 +83,7 @@ get_music (char *filetype, int idx, void *buf, int bufsize) int len; int i; struct music_dir *dp; + int n; len = strlen (filetype); @@ -60,36 +95,36 @@ get_music (char *filetype, int idx, void *buf, int bufsize) if (i == MDIRS) return (-1); - return (-1); -} + if (idx < 0 || idx >= dp->nfiles) + return (-1); - - + n = dp->files[idx].size; + if (n > bufsize) + n = bufsize; + + fseek (musicf, dp->dir.offset + dp->files[idx].offset, SEEK_SET); + n = fread (buf, 1, n, musicf); + return (n); +} void do_display_cat (void) { - FILE *f; - struct TM MusicIndex; - int i; + int i, j; + struct music_dir *dp; + struct TM *fp; + long base, offset; - if ((f = fopen ("/l/baris/gamedat/music.cat", "r")) == NULL) { - fprintf (stderr, "can't open music.cat\n"); - exit (1); - } + base = 0; + for (i = 0, dp = dirs; i < MDIRS; i++, dp++) { + for (j = 0, fp = dp->files; j < dp->nfiles; j++, fp++) { + offset = dp->dir.offset + fp->offset; - for (i = 0; i < 36; i++) { - if (fread (&MusicIndex, 1, sizeof MusicIndex, f) == 0) { - printf ("unexpected EOF\n"); - exit (1); + printf ("0x%08lx %8ld %.6s/%.6s\n", + offset, fp->size, + dp->dir.ID, fp->ID); } - printf ("%6.6s 0x%08lx %8ld\n", - MusicIndex.ID, - MusicIndex.offset, - MusicIndex.size); } - - fclose (f); } int display_cat; @@ -105,6 +140,10 @@ int main (int argc, char **argv) { int c; + char *type = NULL; + int idx = 0; + int n; + char buf[1000 * 1000]; while ((c = getopt (argc, argv, "c")) != EOF) { switch (c) { @@ -116,14 +155,27 @@ main (int argc, char **argv) } } + if (optind < argc) + type = argv[optind++]; + + if (optind < argc) + idx = atoi (argv[optind++]); + if (optind != argc) usage (); + open_music_cat ("/l/baris/gamedat/music.cat"); + if (display_cat) { do_display_cat (); exit (0); } + if (type) { + n = get_music (type, idx, buf, sizeof buf); + dump (buf, n); + } + return (0); } diff --git a/music.c b/music.c new file mode 100644 index 0000000..128aa25 --- /dev/null +++ b/music.c @@ -0,0 +1,178 @@ +#include + +#include "Buzz_inc.h" + + +struct music_file { + struct music_file *next; + char *name; + char *buf; + int size; +}; +struct music_file *music_files; + +struct music_file * +get_music_file (char *name) +{ + struct music_file *mp; + FILE *inf; + int togo, offset; + OggVorbis_File vf; + int ret; + int bs; + char fullname[1000]; + int chop; + + for (mp = music_files; mp; mp = mp->next) { + if (strcasecmp (name, mp->name) == 0) + return (mp); + } + + sprintf (fullname, "/home/pace/ogg/%s.ogg", name); + + if ((inf = fopen (fullname, "r")) == NULL) { + printf ("can't open music file %s\n", fullname); + return (NULL); + } + + if ((mp = calloc (1, sizeof *mp)) == NULL) { + fprintf (stderr, "out of memory\n"); + exit (1); + } + + if ((mp->name = strdup (name)) == NULL) { + fprintf (stderr, "out of memory\n"); + exit (1); + } + + mp->next = music_files; + music_files = mp; + + if (ov_open (inf, &vf, NULL, 0) < 0) { + fprintf(stderr, "ERROR: Failed to open input as vorbis\n"); + goto bad; + } + + if (ov_info(&vf, 0)->channels != 1) { + fprintf (stderr, "ERROR: ogg file must be mono\n"); + goto bad; + } + + mp->size = ov_pcm_total(&vf, 0); /* output size in bytes */ + + if ((mp->buf = calloc (1, mp->size)) == NULL) { + fprintf (stderr, "out of memory\n"); + exit (1); + } + + togo = mp->size; + offset = 0; + + while (togo > 0) { + if ((ret = ov_read (&vf, mp->buf + offset, + togo, 0, 1, 0, &bs)) < 0) + break; + + offset += ret; + togo -= ret; + } + + ov_clear(&vf); /* closes inf */ + + chop = 2 * 11025; + if (mp->size > chop) + mp->size -= chop; + + return (mp); +bad: + fclose (inf); + return (mp); +} + +struct music_dir { + int idx; + char *name; +} music_dir[] = { + { M_ASSEMBLY, "ASSEMBLY" }, + { M_ASTTRNG, "ASTTRNG" }, + { M_BADNEWS, "BADNEWS" }, + { M_DRUMSM, "DRUMSM" }, + { M_ELEPHANT, "ELEPHANT" }, + { M_FILLER, "FILLER" }, + { M_FUTURE, "FUTURE" }, + { M_GOOD, "GOOD" }, + { M_HARDWARE, "HARDWARE" }, + { M_HISTORY, "HISTORY" }, + { M_INTEL, "INTEL" }, + { M_INTELLEG, "INTELLEG" }, + { M_INTERLUD, "INTERLUD" }, + { M_LIFTOFF, "LIFTOFF" }, + { M_MISSPLAN, "MISSPLAN" }, + { M_NEW1950, "NEW1950" }, + { M_NEW1970, "NEW1970" }, + { M_PRES, "PRES" }, + { M_PRGMTRG, "PRGMTRG" }, + { M_RD, "R&D" }, + { M_SOVTYP, "SOVTYP" }, + { M_SUCCESS, "SUCCESS" }, + { M_SVFUN, "SVFUN" }, + { M_SVLOGO, "SVLOGO" }, + { M_SVPORT, "SVPORT2" }, + { M_THEME, "THEME" }, + { M_UNSUCC, "UNSUCC" }, + { M_USFUN, "USFUN" }, + { M_USMIL, "USMIL" }, + { M_USPORT, "USPORT2" }, + { M_USSRMIL, "USSRMIL" }, + { M_VICTORY, "VICTORY" }, + { 0, NULL }, +}; + +struct music_file *cur_music; + +void +PreLoadMusic(char val) +{ + struct music_dir *dp; + + for (dp = music_dir; dp->name; dp++) { + if (dp->idx == val) + break; + } + + if (dp->name == NULL) { + printf ("PreLoadMusic: unknown idx %d\n", val); + return; + } + + printf ("PreLoadMusic(%s)\n", dp->name); + + cur_music = get_music_file (dp->name); +} + +struct audio_chunk music_chunk; + +void +PlayMusic(char mode) +{ + KillMusic (); + + if (cur_music == NULL) + return; + music_chunk.data = cur_music->buf; + music_chunk.size = cur_music->size; + music_chunk.loop = 1; + play (&music_chunk); +} + +void +KillMusic(void) +{ + av_silence (); +} + +void +UpdateMusic (void) +{ + av_step (); +} diff --git a/pace.c b/pace.c index a7b6a25..3322922 100644 --- a/pace.c +++ b/pace.c @@ -426,21 +426,6 @@ CDAccess (int drive,int track,char op) return (0); } -void -PreLoadMusic(char val) -{ - printf ("PreLoadMusic %d\n", val); -} - -void -PlayMusic(char mode) -{ -} - -void -KillMusic(void) -{ -} int brandom (int limit) @@ -519,11 +504,6 @@ getcurdir (int drive, char *buf) getcwd (buf, 100); } -void -UpdateMusic(void) -{ -} - static DIR *f_dir; int diff --git a/sdl.c b/sdl.c index 9bcf17f..e27d730 100644 --- a/sdl.c +++ b/sdl.c @@ -36,6 +36,13 @@ audio_callback (void *userdata, Uint8 *stream, int len) while (togo && cur_chunk) { thistime = cur_chunk->size - cur_offset; + if (thistime < 0) { + cur_chunk = NULL; + cur_chunk_tailp = &cur_chunk; + cur_offset = 0; + break; + } + if (thistime > togo) thistime = togo; memcpy (stream, cur_chunk->data + cur_offset, thistime); @@ -45,8 +52,10 @@ audio_callback (void *userdata, Uint8 *stream, int len) cur_offset += thistime; if (cur_offset >= cur_chunk->size) { - if ((cur_chunk = cur_chunk->next) == NULL) - cur_chunk_tailp = &cur_chunk; + if (cur_chunk->loop == 0) { + if ((cur_chunk = cur_chunk->next) == NULL) + cur_chunk_tailp = &cur_chunk; + } cur_offset = 0; } } @@ -76,6 +85,7 @@ play (struct audio_chunk *new_chunk) return; } } + new_chunk->next = NULL; *cur_chunk_tailp = new_chunk; SDL_UnlockAudio (); } @@ -86,6 +96,7 @@ av_silence (void) SDL_LockAudio (); cur_chunk = NULL; cur_chunk_tailp = &cur_chunk; + cur_offset = 0; SDL_UnlockAudio (); } diff --git a/sdltest.c b/sdltest.c index 108d905..a5de9b1 100644 --- a/sdltest.c +++ b/sdltest.c @@ -8,8 +8,97 @@ #include #include "SDL.h" +#include + +struct music_file { + struct music_file *next; + char *name; + char *buf; + int size; +}; +struct music_file *music_files; + +struct music_file * +get_music_file (char *name) +{ + struct music_file *mp; + FILE *inf; + int togo, offset; + OggVorbis_File vf; + int ret; + int bs; + char fullname[1000]; + int chop; + + for (mp = music_files; mp; mp = mp->next) { + if (strcasecmp (name, mp->name) == 0) + return (mp); + } + + sprintf (fullname, "/home/pace/ogg/%s.ogg", name); + + if ((inf = fopen (fullname, "r")) == NULL) { + printf ("can't open music file %s\n", fullname); + return (NULL); + } + + if ((mp = calloc (1, sizeof *mp)) == NULL) { + fprintf (stderr, "out of memory\n"); + exit (1); + } + + if ((mp->name = strdup (name)) == NULL) { + fprintf (stderr, "out of memory\n"); + exit (1); + } + + mp->next = music_files; + music_files = mp; + + if (ov_open (inf, &vf, NULL, 0) < 0) { + fprintf(stderr, "ERROR: Failed to open input as vorbis\n"); + goto bad; + } + + if (ov_info(&vf, 0)->channels != 1) { + fprintf (stderr, "ERROR: ogg file must be mono\n"); + goto bad; + } + + mp->size = ov_pcm_total(&vf, 0); /* output size in bytes */ + + if ((mp->buf = calloc (1, mp->size)) == NULL) { + fprintf (stderr, "out of memory\n"); + exit (1); + } + + togo = mp->size; + offset = 0; + + while (togo > 0) { + if ((ret = ov_read (&vf, mp->buf + offset, + togo, 0, 1, 0, &bs)) < 0) + break; + + offset += ret; + togo -= ret; + } + + ov_clear(&vf); /* closes inf */ + + chop = 2 * 11025; + if (mp->size > chop) + mp->size -= chop; + + return (mp); +bad: + fclose (inf); + return (mp); +} + SDL_Surface *sur; + double get_time (void) { @@ -33,6 +122,7 @@ struct audio_chunk { struct audio_chunk *next; unsigned char *data; int size; + int loop; }; struct audio_chunk *cur_chunk, **cur_chunk_tailp = &cur_chunk; @@ -56,9 +146,12 @@ audio_callback (void *userdata, Uint8 *stream, int len) cur_offset += thistime; if (cur_offset >= cur_chunk->size) { - if ((cur_chunk = cur_chunk->next) == NULL) - cur_chunk_tailp = &cur_chunk; + if (cur_chunk->loop == 0) { + if ((cur_chunk = cur_chunk->next) == NULL) + cur_chunk_tailp = &cur_chunk; + } cur_offset = 0; + printf ("next\n"); } } @@ -76,7 +169,7 @@ play (struct audio_chunk *new_chunk) } void -test_audio (void) +test_news (void) { struct audio_chunk *cp; FILE *f; @@ -96,6 +189,28 @@ test_audio (void) play (cp); } +void +test_music (void) +{ + struct music_file *mp; + struct audio_chunk *cp; + + if ((mp = get_music_file ("SOVTYP")) == NULL) { + fprintf (stderr, "can't find music file\n"); + exit (1); + } + + if (mp->buf == NULL || mp->size == 0) { + fprintf (stderr, "can't get music\n"); + exit (1); + } + + cp = calloc (1, sizeof *cp); + cp->data = (void *)mp->buf; + cp->size = mp->size; + cp->loop = 1; + play (cp); +} int main () @@ -134,7 +249,7 @@ main () exit (1); } - test_audio (); + test_music (); SDL_PauseAudio (0); while (1) { diff --git a/version.c b/version.c index 8351c19..60d3b2f 100644 --- a/version.c +++ b/version.c @@ -1 +1 @@ -14 +15