/* hear.c v0.80 */ /* EB = Edward Boone */ /* epsilonbeta@geocities.com */ /* http://www.geocities.com/SiliconValley/Vista/6617/index.html */ /* Only nothing seems to be what it looks like */ /* description of the .WAV-format */ /* 0- 3 : "RIFF" */ /* 4- 7 : length (LSB) of the file, e.g. 24 38 D1 02 = 47265828 = filesize - 8 */ /* 8-11 : "WAVE" */ /* 12-15 : "fmt " */ /* 16-19 : length (LSB) of the fmt_chunk, 10 00 00 00 */ /* 20-21 : formattag (LSB), 01 00 */ /* 22-23 : nchannels (LSB), 01 00 if mono, 02 00 if stereo */ /* 24-27 : nsamplespersec (LSB), e.g. 44 AC 00 00 = 44100 */ /* 28-31 : navgbytespersec (LSB), e.g. 10 B1 02 00 = 176400 */ /* 32-33 : nblockalign (LSB), e.g. 04 00 */ /* 34-35 : wbitspersample (LSB), e.g. 10 00 */ /* 36-39 : "data" */ /* 40-43 : length (LSB) of the data_chunk, e.g. 00 38 D1 02 = 47265792 */ /* 44-47265835 : samples left(LSB-MSB)-right(LSB-MSB) 0..128..255 or -32768..0..32767 */ /*---------------------------------------------------------------------------*/ /* #include */ #include "all.h" #include "dep.h" /*---------------------------------------------------------------------------*/ /* global variables : use */ extern int lastkey; extern struct tkeyparse **ptkeyparsetbl; /*---------------------------------------------------------------------------*/ /* variables */ AUDIOSTREAM *stream; FILE *fpwav; SAMPLE *asam; int freq, origfreq, origpan, pan, sam_sort; struct sample samples[MAX_SAMPLES]; /*---------------------------------------------------------------------------*/ static tkeyparse hearmod_min = {K_MIN, keyhearmod_min}, hearmod_plus = {K_PLUS, keyhearmod_plus}, hearsam_delete = {K_DELETE, keyhearsam_delete}, hearsam_down = {K_DOWN, keyhearsam_down}, hearsam_end = {K_END, keyhearsam_end}, hearsam_home = {K_HOME, keyhearsam_home}, hearsam_insert = {K_INSERT, keyhearsam_insert}, hearsam_left = {K_LEFT, keyhearsam_left}, hearsam_pagedown = {K_PAGEDOWN, keyhearsam_pagedown}, hearsam_pageup = {K_PAGEUP, keyhearsam_pageup}, hearsam_right = {K_RIGHT, keyhearsam_right}, hearsam_space = {K_SPACE, keyhearsam_space}, hearsam_up = {K_UP, keyhearsam_up} ; tkeyparse* tkeyparsetbl_hearmod[] = { &hearmod_min, &hearmod_plus, NULL }; tkeyparse* tkeyparsetbl_hearsam[] = { &hearsam_delete, &hearsam_down, &hearsam_end, &hearsam_home, &hearsam_insert, &hearsam_left, &hearsam_pagedown, &hearsam_pageup, &hearsam_right, &hearsam_space, &hearsam_up, NULL }; /*---------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { uchr d[MAXDRIVE], p[MAXDIR], f[MAXFILE], e[MAXEXT]; int choice; if (argc < 2) { printf("\nHEAR v0.80 (copywrong) 1997-1998 by Edward Boone\n"); printf("usage : hear filename.[MID|MOD|S3M|VOC|WAV|XM]\n"); printf("or to extract samples from filename.[MOD|S3M|XM]\n"); printf("usage : hear filename.[MOD|S3M|XM] -extract\n"); getch(); return 1; } if (!exists(argv[1])) { printf("error:\n"); printf("(main) !exists(argv[1]\n"); printf("argv[1] : %s\n", argv[1]); getch(); return 1; } if (!strcmp(argv[2], "-extract")) { modsub(argv); } else { fnsplit(argv[1], d, p, f, e); strlwr(e); if (!strcmp(e, ".mid")) choice = 1; else if (!strcmp(e, ".mod")) choice = 2; else if (!strcmp(e, ".s3m")) choice = 2; else if (!strcmp(e, ".voc")) choice = 3; else if (!strcmp(e, ".wav")) choice = 3; else if (!strcmp(e, ".xm")) choice = 2; else choice = 0; switch (choice) { case 1: { hear_mid(argv); break; } case 2: { hear_mod(argv); break; } case 3: { hear_sam(argv); break; } default: break; } } return 0; } /*---------------------------------------------------------------------------*/ void hear_mid(char *s[]) { MIDI *amid; allegro_init(); install_timer(); amid = load_midi(s[1]); detect_midi_driver(MIDI_AUTODETECT); install_soundm(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL); set_volume(255, 255); play_midi(amid, TRUE); if (getch()) { destroy_midi(amid); } } /*---------------------------------------------------------------------------*/ void hear_mod(char *s[]) { int chn_reserved; JGMOD *pjgmod; set_volume(255, -1); fast_loading = FALSE; enable_m15 = TRUE; allegro_init(); install_timer(); pjgmod = load_mod(s[1]); if (pjgmod == NULL) { printf("error:\n"); printf("(hear_mod) pjgmod == NULL\n"); getch(); exit(1); } if (pjgmod->no_chn > 32) { chn_reserved = 32; } else { chn_reserved = pjgmod->no_chn; } reserve_voices(chn_reserved, -1); install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL); if (install_mod(chn_reserved) < 0) { printf("error:\n"); printf("(hear_mod) install_mod(chn_reserved) < 0\n"); getch(); exit(1); } play_mod(pjgmod, FALSE); /* don't loop the music */ lastkey = 0; ptkeyparsetbl = tkeyparsetbl_hearmod; while ((lastkey != K_ESC) && (is_mod_playing() == TRUE)) { key_scan(); } stop_mod(); destroy_mod(pjgmod); } /*---------------------------------------------------------------------------*/ uint get_wav_datasize(uchr* filename) { uint data_size; FILE *fp; fp = fopenm(filename, "rb"); fseekm(fp, 40, SEEK_SET); data_size = fgetc_uint_l(fp); fclose(fp); return data_size; } /*---------------------------------------------------------------------------*/ uint get_wav_freq(uchr* filename) { uint afreq; FILE *fp; fp = fopenm(filename, "rb"); fseekm(fp, 24, SEEK_SET); afreq = fgetc_uint_l(fp); fclose(fp); return afreq; } /*---------------------------------------------------------------------------*/ void hear_sam(char *s[]) { uchr d[MAXDRIVE], q[MAXDIR], f[MAXFILE], e[MAXEXT]; uchr* p; int done = 0; ushr nchannels, w, wbitspersample; uint buffer_size, data_size, i, len, navgbytespersec, nbytes, nsamplespersec; FILE *fp; origpan = pan = 128; allegro_init(); install_timer(); install_soundm(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL); data_size = get_wav_datasize(s[1]); origfreq = freq = get_wav_freq(s[1]); fnsplit(s[1], d, q, f, e); strlwr(e); if ((data_size < 1500000) || !strcmp(e, ".voc")) { sam_sort = 0; origfreq = freq = 1000; asam = load_samplem(s[1]); play_sample(asam, 255, pan, freq, TRUE); lastkey = 0; ptkeyparsetbl = tkeyparsetbl_hearsam; while (lastkey != K_ESC) { key_scan(); } destroy_sample(asam); } else { sam_sort = 1; fp = fopenm(s[1], "rb"); fseekm(fp, 22, SEEK_SET); nchannels = fgetc_ushr_l(fp); nchannels--; /* convert to : 0 == mono, 1 == stereo */ nsamplespersec = freq; fseekm(fp, 28, SEEK_SET); navgbytespersec = fgetc_uint_l(fp); fseekm(fp, 34, SEEK_SET); wbitspersample = fgetc_ushr_l(fp); buffer_size = BUFFER_SIZE; if (nchannels == 1) /* stereo, multiply play_audio_stream buffer_size with 2 */ { buffer_size *= 2; } if (wbitspersample == 16) /* 16-bit, multiply play_audio_stream buffer_size with 2 */ { buffer_size *= 2; } stream = play_audio_stream(BUFFER_SIZE, wbitspersample, nchannels, nsamplespersec, 255, 128); len = data_size; fseekm(fp, 44, SEEK_SET); lastkey = 0; ptkeyparsetbl = tkeyparsetbl_hearsam; while ((lastkey != K_ESC) && (len > 0)) { p = get_audio_stream_buffer(stream); if (p) { nbytes = (len > buffer_size) ? buffer_size : len; if (nbytes == buffer_size) { for (i = 0; i < buffer_size; i++) { key_scan(); if (wbitspersample == 8) /* 8-bits */ { p[i] = fgetc_uchr(fp); } else /* 16-bits, convert signed to unsigned */ { w = fgetc_short_l(fp); w = (w ^ 0x8000); p[i] = (uchr) (w & 0xFF); p[i+1] = (uchr) (w >> 8); i++; } } } else /* nbytes == len */ { for (i = 0; i < nbytes; i++) { key_scan(); if (wbitspersample == 8) /* 8-bits */ { p[i] = fgetc_uchr(fp); } else /* 16-bits, convert signed to unsigned */ { w = fgetc_short_l(fp); w = w ^ 0x8000; p[i] = (uchr) (w & 0xFF); p[i+1] = (uchr) (w >> 8); i++; } } for (i = nbytes; i < buffer_size; i++) { p[i] = 0; } } len -= nbytes; free_audio_stream_buffer(stream); } key_scan(); } while (done != 2) /* generate two extra silence packets to hear the end of the stream */ { p = get_audio_stream_buffer(stream); if (p) { done++; for (i = 0; i < buffer_size; i++) { p[i] = 0; } free_audio_stream_buffer(stream); } } stop_audio_stream(stream); fclose(fp); } } /*---------------------------------------------------------------------------*/ void keyhearmod_min() { prev_mod_track(); } /*---------------------------------------------------------------------------*/ void keyhearmod_plus() { next_mod_track(); } /*---------------------------------------------------------------------------*/ void keyhearsam_delete() { pan = 0; if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_down() { if (freq > 64) { freq = ((freq * 511) / 512) - 1; } if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_end() { pan = origpan; if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_home() { freq = origfreq; if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_insert() { freq = origfreq - origfreq/3; if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_left() { if (pan > 0) { pan--; } if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_pagedown() { pan = 255; if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_pageup() { freq = origfreq + origfreq/3; if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_right() { if (pan < 255) { pan++; } if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_space() { freq = origfreq; pan = origpan; if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void keyhearsam_up() { if (freq < 132300) /* 16384 */ { freq = ((freq * 513) / 512) + 1; } if (sam_sort == 0) { adjust_sample(asam, 255, pan, freq, TRUE); rest(2); } else { voice_set_frequency(stream->voice, freq); voice_set_pan(stream->voice, pan); rest(2); } } /*---------------------------------------------------------------------------*/ void modsub(char *s[]) { int i; uchr d[MAXDRIVE], p[MAXDIR], f[MAXFILE], e[MAXEXT], prefix[7], t[256], suffix[5]; JGMOD *pjgmod; SAMPLE *psample; set_volume(255, -1); fast_loading = FALSE; enable_m15 = TRUE; allegro_init(); install_timer(); install_keyboard(); strcpy(suffix, ".wav"); fnsplit(s[1], d, p, f, e); i = 0; while ((i < 6) && (f[i] != '.')) { prefix[i] = f[i]; i++; } prefix[i] = '\0'; samples_init(); pjgmod = load_mod(s[1]); if (pjgmod == NULL) { printf("error:\n"); printf("(main) pjgmod == NULL\n"); getch(); exit(1); } for (i = 0; i < MAX_SAMPLES; i++) /* only 2 positions are foreseen in filenames */ { psample = NULL; psample = get_jgmod_sample(pjgmod, i); if ((psample) && (psample->len != 0)) { strcpy(t, ""); sprintf(t, "%s%s%d%s", DATAPATH, prefix, i, suffix); samples[i].filename = malloc(strlen(t) + 1); strcpy(samples[i].filename, t); sample2wav(psample, samples[i].filename); destroy_sample(psample); } } destroy_mod(pjgmod); } /*---------------------------------------------------------------------------*/ void sample2wav(SAMPLE *asample, uchr filename[256]) { uchr* pdata; uint data_size, wave_size, i; wavformat fmt; FILE* fp; fp = fopen(filename, "wb"); /* size in samples */ data_size = asample->len; /* convert to size in bytes */ fmt.wbitspersample = 8; if (asample->bits == 16) { data_size *= 2; fmt.wbitspersample = 16; } fmt.nchannels = 1; if (asample->stereo == 1) { data_size *= 2; fmt.nchannels = 2; } /* "RIFF" + "WAVE" + "fmt " + 10 00 00 00 + "data" + size = 36 */ wave_size = data_size + 36; fwrite("RIFF", strlen("RIFF"), 1, fp); /* RIFF */ fputc_uint_l(wave_size, fp); /* size */ fwrite("WAVE", strlen("WAVE"), 1, fp); /* WAVE */ fmt.wformattag = 1; fmt.nsamplespersec = SAMPLE_RATE; /* asample->freq */ fmt.nblockalign = fmt.nchannels * ((fmt.wbitspersample + 7) / 8 ); fmt.navgbytespersec = fmt.nblockalign * SAMPLE_RATE; fwrite("fmt ", strlen("fmt "), 1, fp); /* fmt */ fputc_uint_l(16, fp); /* 16 */ fputc_ushr_l(fmt.wformattag, fp); /* 1 */ fputc_ushr_l(fmt.nchannels, fp); /* 1, 2 */ fputc_uint_l(fmt.nsamplespersec, fp); /* 16574 */ fputc_uint_l(fmt.navgbytespersec, fp); /* 16574 */ fputc_ushr_l(fmt.nblockalign, fp); /* 1, 2*/ fputc_ushr_l(fmt.wbitspersample, fp); /* 8, 16 */ fwrite("data", strlen("data"), 1, fp); /* data */ fputc_uint_l(data_size, fp); /* size */ pdata = (uchr*) asample->data; for (i = 0; i < data_size; i++) /* write sample data */ { fputc(*pdata, fp); pdata++; } fclose(fp); } /*---------------------------------------------------------------------------*/ void samples_init() { int i; for (i = 0; i < MAX_SAMPLES; i++) { samples[i].filename = "\0"; } }