hschumann2/TempleOS-Source-Code
0832
1 2#help_index "Snd/Snd Files"3#define SNDFILE_SAMPLE_RATE 80004//Header for a ".SND" file5class CFileSND6{//big endian7 U32 signature; //0x646e732e8 U32 offset; //249 U32 data_size;10 U32 coding; //3=16bit uncompressed11 U32 sample_rate; //Hz12 U32 channels; //1=mono13 I16 body[1];14};15 16//Windows media constraint.17//#define SND_FILE_DATA_MAX 0x0007FF0018#define SND_FILE_DATA_MAX 0x7FFFFF0019 20public I64 SndFileCreate(U8 *base_filename,F64 normalized_vol=1.0,21 F64 averaging=0.0,I64 waveform=WF_SQUARE,22 F64 reverb_delay=0,F64 reverb_intensity=0,F64 time_shift=0)23{//Use "snd.record" flag to start or stop recording, then call this routine.24//Averaging should be a num from 0.0 to 0.999.25 //Vol should be from 0.0 to 1.0.26 //Set reverb_delay to like 0.3 sec and reverb_intensity to like 0.4.27 I64 i,k,cnt,cnt2,level,file_num;28 F64 avg,dt;29 CFileSND *s;30 CSndWaveCtrl *swc=SndWaveCtrlNew(SNDFILE_SAMPLE_RATE,16,1);31 CSndData *d,*d1;32 U8 *name,*name2;33 34 snd.record=FALSE;35 36 dt=snd.record_head.last->time-snd.record_head.next->time;37 if (!dt) return 0;38 cnt=dt*SNDFILE_SAMPLE_RATE;39 cnt++; //Terminator40 41 name=StrNew(base_filename);42 FileExtRem(name);43 44 s=CAlloc(offset(CFileSND.body)+cnt*sizeof(I16));45 s->signature=0x646e732e;46 s->offset=EndianU32(offset(CFileSND.body));47 s->coding=EndianU32(3);48 s->sample_rate=EndianU32(SNDFILE_SAMPLE_RATE);49 s->channels=EndianU32(1);50 51 if (time_shift) {52 d=snd.record_head.next;53 d->time-=time_shift;54 while (d->next!=&snd.record_head) {55 d1=d->next;56 dt=d1->time-d->time;57 if (dt<0) {58 QueRem(d1);59 Free(d1);60 } else61 break;62 }63 }64 65 d=snd.record_head.next;66 k=0;67 while (d->next!=&snd.record_head) {68 d1=d->next;69 dt=d1->time-d->time;70 cnt2=dt*SNDFILE_SAMPLE_RATE;71 SndWaveAddBuf(swc,&s->body[k],cnt2,72 Ona2Freq(d->ona),waveform,normalized_vol);73 k+=cnt2;74 QueRem(d);75 Free(d);76 d=d1;77 }78 79 //Average80 if (averaging) {81 avg=0;82 for (i=0;i<cnt-1;i++)83 s->body[i]=avg=LowPass1(averaging,avg,s->body[i],1.0);84 }85 86 //Reverb87 if (reverb_intensity) {88 if (dt=reverb_delay*SNDFILE_SAMPLE_RATE)89 for (i=dt;i<cnt;i++)90 s->body[i]+=reverb_intensity*s->body[i-dt];91 }92 93 //Get rid of D.C. component94 for (k=0;k<3;k++) {95 level=0;96 for (i=0;i<cnt-1;i++)97 level+=s->body[i];98 level/=cnt-1;99 for (i=0;i<cnt-1;i++)100 s->body[i]=ClampI64(s->body[i]-level,I16_MIN,I16_MAX);101 }102 103 for (i=0;i<cnt-1;i++)104 s->body[i]=EndianU16(s->body[i]);105 106 s->body[cnt-1]=0;107 108 d=snd.record_head.next;109 while (d!=&snd.record_head) {110 d1=d->next;111 QueRem(d);112 Free(d);113 d=d1;114 }115 116 name2=MAlloc(StrLen(name)+3+1+3+1);117 cnt2=cnt;118 file_num=0;119 while (cnt2>0) {120 i=cnt2;121 if (i>SND_FILE_DATA_MAX)122 i=SND_FILE_DATA_MAX;123 s->data_size=EndianU32(i*sizeof(I16));124 MemCpy(s->body,&s->body[file_num*SND_FILE_DATA_MAX],i*sizeof(I16));125 StrPrint(name2,"%s%03d.SND",name,file_num++);126 FileWrite(name2,s,offset(CFileSND.body)+i*sizeof(I16));127 cnt2-=i;128 }129 Free(s);130 Free(name);131 Free(name2);132 133 SndWaveCtrlDel(swc);134 return cnt;135}136 