int getchar(void) { switch (consdev) { default: case CONSDEV_BIOSCONS: return bioscons_getc(); case CONSDEV_SCIF: return scif_getc(); } }
int load_wav ( FIL *fp, /* Pointer to the open file object to play */ const char *title, /* Title (file name, etc...) */ void *work, /* Pointer to working buffer (must be-4 byte aligned) */ uint32_t sz_work /* Size of working buffer (must be power of 2) */ ) { UINT md, wi, br, tc, t, btr; DWORD sz, ssz, offw, szwav, wsmp, fsmp, eof; WAVFIFO fcb; BYTE k, *buff = work; char *p, nam[NBSIZE], art[NBSIZE]; xprintf("**** RIFF-WAVE Player ****\nFile=%s\n", title); /* Put title */ /* Is this a WAV file? */ if (f_read(fp, buff, 12, &br) || br != 12) return -1; if (LD_DWORD(&buff[0]) != FCC('R','I','F','F')) return -1; if (LD_DWORD(&buff[8]) != FCC('W','A','V','E')) return -1; eof = LD_DWORD(&buff[4]) + 8; /* Analyze the RIFF-WAVE header and get properties */ nam[0] = art[0] = 0; md = fsmp = wsmp = offw = szwav = 0; while (f_tell(fp) < eof) { if (f_read(fp, buff, 8, &br) || br != 8) return -1; sz = (LD_DWORD(&buff[4]) + 1) & ~1; switch (LD_DWORD(&buff[0])) { case FCC('f','m','t',' ') : /* fmt chunk */ if (sz > 1000 || sz < 16 || f_read(fp, buff, sz, &br) || sz != br) return -1; if (LD_WORD(&buff[0]) != 0x1) return -1; /* Check if LPCM or not */ if (LD_WORD(&buff[2]) == 2) { /* Check channels (1 or 2) */ md = 1; wsmp = 2; } else { md = 0; wsmp = 1; } if (LD_WORD(&buff[14]) == 16) { /* Resolution (8 or 16) */ md |= 2; wsmp *= 2; } fsmp = LD_DWORD(&buff[4]); /* Sampling rate */ break; case FCC('f','a','c','t') : /* fact chunk */ f_lseek(fp, f_tell(fp) + sz); break; case FCC('d','a','t','a') : /* data chunk */ offw = f_tell(fp); /* Wave data start offset */ szwav = sz; /* Size of wave data [byte] */ f_lseek(fp, f_tell(fp) + sz); break; case FCC('L','I','S','T'): /* LIST chunk */ sz += f_tell(fp); if (f_read(fp, buff, 4, &br) || br != 4) return -1; if (LD_DWORD(buff) == FCC('I','N','F','O')) { /* LIST/INFO sub-chunk */ while (f_tell(fp) < sz) { if (f_read(fp, buff, 8, &br) || br != 8) return -1; ssz = (LD_DWORD(&buff[4]) + 1) & ~1; p = 0; switch (LD_DWORD(buff)) { case FCC('I','N','A','M'): /* INAM (name) field */ p = nam; break; case FCC('I','A','R','T'): /* IART (artist) field */ p = art; break; } if (p && ssz <= NBSIZE) { if (f_read(fp, p, ssz, &br) || br != ssz) return -1; } else { if (f_lseek(fp, f_tell(fp) + ssz)) return -1; } } } else { if (f_lseek(fp, sz)) return -1; /* Skip unknown sub-chunk */ } break; default : /* Unknown chunk */ return -1; } } if (!szwav || !fsmp) return -1; /* Check if valid WAV file */ if (f_lseek(fp, offw)) return -1; /* Seek to top of wav data */ tc = szwav / fsmp / wsmp; /* Length (sec) */ xprintf("IART=%s\nINAM=%s\n", art, nam); xprintf("Sample=%u.%ukHz/%ubit/%s\nLength=%u:%02u\n", fsmp / 1000, (fsmp / 100) % 10, (md & 2) ? 16 : 8, (md & 1) ? "Stereo" : "Mono", tc / 60, tc % 60); /* Initialize sound FIFO and start sound streming */ fcb.mode = md; /* Sampling: b0=mono(0)/stereo(1), b1=8bit(0)/16bit(1) */ fcb.buff = buff; /* Pointer to streaming buffer */ fcb.sz_buff = sz_work; /* Size of streaming buffer */ if (!sound_start(&fcb, fsmp)) return -1; /* Start sound streaming */ k = 0; wi = 0; while (szwav || fcb.ct >= 4) { /* Sount streaming loop */ if (szwav && fcb.ct <= sz_work / 2) { /* Refill FIFO when it gets half empty */ btr = (szwav >= sz_work / 2) ? sz_work / 2 : szwav; f_read(fp, &buff[wi], btr, &br); if (br != btr) break; /* Exit if illigal file termination or FS error */ szwav -= br; wi = (wi + br) & (sz_work - 1); IEN(CMT3, CMI3) = 0; /* Disable CMT3 compare match irq */ fcb.ct += br; IEN(CMT3, CMI3) = 1; /* Enable CMT3 compare match irq */ } if (scif_test()) { /* Exit if a user command arrived */ k = scif_getc(); break; } t = (f_tell(fp) - offw - fcb.ct) / fsmp / wsmp; /* Refresh time display every 1 sec */ if (t != tc) { tc = t; xprintf("\rTime=%u:%02u", tc / 60, tc % 60); } } sound_stop(); /* Stop sound streaming */ xputc('\n'); return k; /* Terminated due to -1:error, 0:eot, >0:key code */ }