/* WVEFILE.C Sound record/playback sound file */ #include #include #include #include #include #include #include #include LOCAL_C ULONG SamplesToTenths(ULONG samples) { return((samples>>4)/50); } LOCAL_C ULONG EffectiveSamples(ULONG samples) /* Converts the number of byte samples to the effective number of samples for playback by rounding up to the nearest 0x800 (2K) boundary and adding another 0x600. */ { return(((samples+0x7ff)&(~0x7ff))+0x600); } LOCAL_C VOID CloseFile(PR_WVEFILE *self) { p_close(self->wvefile.fcb); self->wvefile.fcb=NULL; } LOCAL_C VOID StoreFileName(PR_WVEFILE *self,TEXT *fname) { CloseFile(self); f_fparse(fname,NULL,&self->wvefile.fname[0],&self->wvefile.crk); hEnsurePath(&self->wvefile.fname[0]); } #pragma METHOD_CALL METHOD INT wvefile_wve_new(PR_WVEFILE *self,TEXT *fname) /* Return the maximum duration in seconds consistent with the space on fspec as a positive number. Otherwise return a negative error number. */ { UINT minfree; INT SSDType; P_DINFO dinfo; StoreFileName(self,fname); p_dinfo(&self->wvefile.fname[0],&dinfo); minfree=0x1000; /* need at least approx half a seconds worth of space */ SSDType=dinfo.mediatype&0xff; if (SSDType==P_FMEDIA_FLASH) return(E_FILE_VOLUME); if (SSDType==P_FMEDIA_ROM || SSDType==P_FMEDIA_WRITEPROTECTED) return(E_FILE_PROTECT); if (dinfo.mediatype&P_FMEDIA_INTERNAL) minfree+=0x2800; /* since the sound server takes 0x2800 bytes to run */ if (p_finfo(&self->wvefile.fname[0],&self->wvefile.info)>=0) { if (!(self->wvefile.info.status&P_FAWRITE)) return(E_FILE_RDONLY); dinfo.free+=self->wvefile.info.size; /* credit length of existing file */ } if (dinfo.freewvefile.ret=p_finfo(&self->wvefile.fname[0],&self->wvefile.info); if (self->wvefile.ret<0) return; CloseFile(self); /* file can be open after an error in playback */ self->wvefile.ret=p_open(&self->wvefile.fcb,&self->wvefile.fname[0],P_FSHARE); if (self->wvefile.ret<0) return; self->wvefile.ret=p_read(self->wvefile.fcb,&self->wvefile.head,sizeof(SndFile)); if (self->wvefile.ret<0) { close: CloseFile(self); return; } if (p_scmp(&self->wvefile.head.Signature[0],ALawSignature)) { self->wvefile.ret=E_FILE_INVALID; goto close; } /* Wany "bootleg" files exist with incorrect Samples field */ /* The sound system services work off the file length and not Samples */ /* So we patch Samples here to the correct value */ self->wvefile.head.Samples=self->wvefile.info.size-sizeof(SndFile); if (self->wvefile.head.Repeats==0) self->wvefile.head.Repeats=1; } METHOD TEXT *wvefile_wve_sense_fname(PR_WVEFILE *self) { return(&self->wvefile.fname[0]); } METHOD VOID wvefile_wve_sense_info(PR_WVEFILE *self,WVEFILE_INFO *pi) /* Write all kinds of information to *pi. */ { ULONG samples; p_bfil(pi,sizeof(WVEFILE_INFO),0); pi->device=&self->wvefile.fname[self->wvefile.crk.system]; pi->name=pi->device+self->wvefile.crk.device+self->wvefile.crk.path; pi->nmlen=self->wvefile.crk.name; if (self->wvefile.fcb==NULL) return; pi->duration=SamplesToTenths(self->wvefile.head.Samples); pi->silence=(WORD)(((ULONG)self->wvefile.head.SilenceInTicks*5)>>4); samples=EffectiveSamples(self->wvefile.head.Samples); samples+=250*(ULONG)self->wvefile.head.SilenceInTicks; /* 250 samples per tick */ if (self->wvefile.head.Repeats>1 && self->wvefile.head.SilenceInTicks<2) samples+=500; /* the minimum silence between repeats */ pi->repeats=self->wvefile.head.Repeats; pi->total=SamplesToTenths(samples*pi->repeats); pi->samples=self->wvefile.head.Samples; pi->flen=self->wvefile.info.size; } METHOD VOID wvefile_wve_set_repeats(PR_WVEFILE *self,UINT repeats,UINT tenths) /* If repeats is zero or more, set the number of repeats and the trailing silence to tenths in 1/10s of a second. If repeats is zero, set the silence such that the total duration with the current number of repeats is equal to tenths. */ { INT ret; INT silence,maxrepeats; LONG total,period; ret=0; if (self->wvefile.fcb==NULL) return; if (repeats>0) silence=(INT)(((ULONG)tenths<<4)/5); /* convert to ticks */ else { /* tenths is total desired time */ repeats=self->wvefile.head.Repeats; total=tenths; total*=800; /* convert tenths to samples */ period=EffectiveSamples(self->wvefile.head.Samples); maxrepeats=(INT)(total/(period+500)); if (repeats<2 || repeats>maxrepeats) repeats=maxrepeats; if (repeats==0) repeats=1; silence=0; if (repeats>1) silence=(INT)((total-repeats*period+249*repeats)/(250*repeats)); } if (silence==self->wvefile.head.SilenceInTicks && repeats==self->wvefile.head.Repeats) return; /* no change */ self->wvefile.head.SilenceInTicks=silence; self->wvefile.head.Repeats=repeats; CloseFile(self); ret=p_open(&self->wvefile.fcb,&self->wvefile.fname[0],P_FUPDATE); if (ret>=0) { ret=p_write(self->wvefile.fcb,&self->wvefile.head,sizeof(SndFile)); CloseFile(self); } wvefile_wve_open(self,NULL); f_leave(ret); }