#include #include #include #include #include #include #include #include #include "globals.h" #include #include #include #define PL_RANDOM 1 #define PL_FORWARD 2 #define PL_FIRST 3 #define CHANNELS 20 #define TRACKS 512 #define SND_EFF_MAXVOL 32000 #define SND_EFF_DESCENT 8000 #define have_loop(x) ((x)->start_loop!=(x)->end_loop) typedef unsigned short SND_FIND_TABLE[2]; typedef struct snd_info { TMA_SOUND *data; //4 short xpos,ypos,side; //10 word volume,block; //14 }SND_INFO; static short chan_state[CHANNELS]; static short track_state[TRACKS]; short sample_volume=255; //static struct t_wave wav_last_head; //static int wav_last_size; static int mute_task=-1; static char sound_enabled=1; SND_INFO tracks[TRACKS]; SND_INFO playings[CHANNELS]; static word locks[32]; TSTR_LIST cur_playlist=NULL; TSTR_LIST sound_table=NULL; int playlist_size; int playing_track=0; int remain_play=0; int play_list_mode=PL_RANDOM; void init_tracks() { memset(tracks,0,sizeof(tracks)); memset(playings,0,sizeof(playings)); memset(chan_state,0xff,sizeof(chan_state)); memset(track_state,0xff,sizeof(track_state)); memset(locks,0,sizeof(locks)); } static char last_beep_lev; /*void pcspeak_uroven(char value,int time); #pragma aux pcspeak_uroven parm[bh][ecx]=\ "mov ah,last_beep_lev"\ "lp2:add ah,bh"\ "mov al,48h"\ "jc lp1"\ "mov al,4ah"\ "lp1:out 61h,al"\ "loop lp2"\ "mov last_beep_lev,ah"\ modify [eax] static int get_pc_speed() { int ticks=0; int timer=get_timer_value(); while (get_timer_value()-timer<50) pcspeak_uroven(127,1000),ticks+=1000; return ticks; } void pc_speak_play_sample(char *sample,int size,char step,int freq) { static speed=0; int ticker; if (!speed) speed=get_pc_speed(); _disable(); ticker=speed/freq; sample+=step/2; while (size>0) { if (step==2) pcspeak_uroven(*sample ^ 0x80,ticker); else pcspeak_uroven(*sample,ticker); sample+=step; size-=step; } _enable(); nosound(); } */ int find_free_channel(int stamp) { int i,j; int minvol,left,right,mid; j=0; if (stamp) for(i=0;i=0)-(side==3)*(*x<=0); *y+=(side==2)*(*y>=0)-(side==0)*(*y<=0); ds=abs(*x)+abs(*y); ds=SND_EFF_MAXVOL-(SND_EFF_DESCENT*8*ds)/(8+ds); return ds; } int calcul_volume(int chan,int x,int y,int side,int volume) { int lv,rv; int ds,bal,i; if (side==-1) side=viewdir; side&=3; ds=calc_volume(&x,&y,side); if (ds<=0) { release_channel(chan); return -1; } for(i=0;iy) if (x>0) bal=100-y*50/x;else bal=-100-y*50/x; else bal=50*x/y; ds=ds*volume/100; if (bal<0) { lv=ds*(100+bal)/100;rv=ds; } else { rv=ds*(100-bal)/100;lv=ds; } lv=(lv*sample_volume)>>8; rv=(rv*sample_volume)>>8; set_channel_volume(chan,lv,rv); return 0; } void wav_load(void **p,long *s) { char *sr; long *d; char *c; char *tg; void *tgr; size_t siz; struct t_wave x[3]; sr=*p; sr=find_chunk(sr,WAV_FMT); read_chunk(sr,&x); sr=*p; sr=find_chunk(sr,WAV_DATA); *s=get_chunk_size(sr); tgr=tg=getmem(*s+sizeof(struct t_wave)+4); memcpy(tgr,x,sizeof(struct t_wave)); tg+=sizeof(struct t_wave); *(int *)tg=*s; tg+=4; read_chunk(sr,tg); free(*p); *p=tgr; siz=*s; *s+=sizeof(struct t_wave)+4; /* if (x[0].freq!=x[0].bps) { char s; siz>>=1; s=siz & 1; siz>>=1; d=tg; for(;siz--;d++) *d^=0x80008000; if (s) {c=(char *)d;c[1]^=0x80;} } else { char s; s=siz & 3; siz>>=2; d=(long *)tg; for(;siz--;d++) *d^=0x80808080; c=(char *)d; for(;s--;c++) *c^=0x80; }*/ } void play_effekt(int x,int y,int xd,int yd,int side,int sided,TMA_SOUND *p) { int chan; int blockid; SND_INFO *track; THANDLE_DATA *z; char *s; if (!sound_enabled) return; side; chan=find_free_channel(p->soundid); release_channel(chan); track=&tracks[p->soundid]; track->data=p; track->xpos=xd; track->ypos=yd; track->side=sided; track_state[p->soundid]=-1; if (p->bit16 & 0x8) { int vol=SND_EFF_MAXVOL*p->volume/100; if (rnd(100)>50) set_channel_volume(chan,rnd(vol),vol); else set_channel_volume(chan,vol,rnd(vol)); } else if (calcul_volume(chan,x-xd,y-yd,/*side-*/sided,p->volume)) return; if (p->filename[0]==1) memcpy(&blockid,&p->filename[1],4); else { blockid=find_handle(p->filename,wav_load); if (blockid==-1) { z=def_handle(end_ptr,p->filename,wav_load,SR_ZVUKY); blockid=end_ptr++; if (level_preload) apreload(blockid); } memcpy(&p->filename[1],&blockid,4); p->filename[0]=1; } alock(blockid); s=ablock(blockid); s+=p->offset+sizeof(struct t_wave)+4; play_sample(chan,s,p->end_loop-p->offset,p->start_loop-p->offset,p->freq,1+(p->bit16 & 1)); playings[chan].data=p; playings[chan].xpos=xd; playings[chan].ypos=yd; playings[chan].side=sided; playings[chan].volume=p->volume; playings[chan].block=blockid; chan_state[chan]=p->soundid; track_state[p->soundid]=chan; } void restore_sound_name(TMA_SOUND *p) { int blockid; THANDLE_DATA *h; if (p->filename[0]==1) { memcpy(&blockid,&p->filename[1],4); do { h=get_handle(blockid); if (h->status==BK_SAME_AS) blockid=h->seekpos;else blockid=-1; } while (blockid!=-1); strncpy(p->filename,h->src_file,12); } } void restore_sound_names() { int i; for(i=0;igeneral.action==MA_SOUND) restore_sound_name(&z->sound); r=(int *)((char *)r+mcsiz); } } } void recalc_volumes(int sector,int side) { int i; int newx,newy,layer; if (sector>=mapsize) return; side; SEND_LOG("(SOUND) %s","Recalculating volumes",0); newx=map_coord[sector].x; newy=map_coord[sector].y; layer=map_coord[sector].layer; for(i=0;i=0 && playings[i].side>=0) { calcul_volume(i,newx-playings[i].xpos,newy-playings[i].ypos,/*side-*/playings[i].side,playings[i].volume); if (!get_channel_state(i)) release_channel(i); } else calcul_volume(i,0,0,-1,playings[i].volume); for(i=1;i0) if (have_loop(tracks[i].data))play_effekt(newx,newy,tracks[i].xpos,tracks[i].ypos,side,tracks[i].side,tracks[i].data); } } mute_task=-1; } void create_playlist(char *playlist) { char *c; char mode[20]; char shift; int i=1,j; if (cur_playlist!=NULL) release_list(cur_playlist); cur_playlist=NULL; if (playlist==NULL) return; if (playlist=="") return; c=playlist; while (*c && *c==32) c++; sscanf(c,"%s",mode); strupr(mode); shift=1; if (!strcmp(mode,"RANDOM")) play_list_mode=PL_RANDOM; else if (!strcmp(mode,"FORWARD")) play_list_mode=PL_FORWARD; else if (!strcmp(mode,"FIRST")) play_list_mode=PL_FIRST; else shift=0; if (shift) c+=strlen(mode);else play_list_mode=PL_RANDOM; while (*c && *c==32) c++; playlist=c; if (playlist=="") return; for (c=playlist;c!=NULL;c=strchr(c+1,' ')) i++; playlist_size=i-1; cur_playlist=create_list(i); j=0; for (c=playlist;c!=NULL;c=strchr(c+1,' ')) { char *e; char d[MAX_FILESYSTEM_PATH+2]="!"; strncat(d,c+j,MAX_FILESYSTEM_PATH);d[MAX_FILESYSTEM_PATH+1]=0;j=1; if ((e=strchr(d,32))!=NULL) *e=0; str_add(&cur_playlist,d); } if (play_list_mode==PL_FIRST) { cur_playlist[0][0]=32; remain_play=1; play_list_mode=PL_RANDOM; } else { remain_play=0; } playing_track=-1; } void play_next_music(char **c) { int i,step; static char d[MAX_FILESYSTEM_PATH]; *c=NULL; if (cur_playlist==NULL) return; if (!remain_play) for(i=0;cur_playlist[i]!=NULL;remain_play++,i++) cur_playlist[i][0]=32; if (play_list_mode==PL_RANDOM) step=rand()*(playlist_size-1)/32768+1; else step=1; i=playing_track; do { i++; if (cur_playlist[i]==NULL) i=0; if (cur_playlist[i][0]==32) step--; } while (step); playing_track=i; snprintf(d,sizeof(d),"%s%s",pathtable[SR_MUSIC],cur_playlist[i]+1); if (access(d,0) == -1) snprintf(d,sizeof(d),"%s%s",pathtable[SR_ORGMUSIC],cur_playlist[i]+1); cur_playlist[i][0]=33; remain_play--; *c=d; } void purge_playlist() { if (cur_playlist!=NULL)release_list(cur_playlist); cur_playlist=NULL; } void play_sample_at_sector(int sample,int sector1,int sector2,int track, char loop) { int x,y,xd,yd,chan; char *s; struct t_wave *p; int siz; int oldtrack; if (!sound_enabled) return; if (map_coord[sector1].layer!=map_coord[sector2].layer) return; x=map_coord[sector1].x; y=map_coord[sector1].y; xd=map_coord[sector2].x; yd=map_coord[sector2].y; chan=find_free_channel(track); oldtrack=track_state[track]; if (!track || oldtrack==-1) release_channel(chan); if (calcul_volume(chan,x-xd,y-yd,viewdir,100)) return; if (!track || oldtrack==-1) { alock(sample); s=ablock(sample); p=(struct t_wave *)s; s+=sizeof(struct t_wave); siz=*(int *)s;s+=4; play_sample(chan,s,siz,loop?0:siz,p->freq,(p->freq!=p->bps?2:1)); playings[chan].data=NULL; } playings[chan].xpos=xd; playings[chan].ypos=yd; playings[chan].side=viewdir; playings[chan].volume=100; playings[chan].block=sample; chan_state[chan]=track; track_state[track]=chan; } void play_sample_at_channel(int sample,int channel,int vol) { char *s; struct t_wave *p; int siz; if (!sound_enabled) return; channel+=CHANNELS; vol*=SND_EFF_MAXVOL/100; set_channel_volume(channel,vol,vol); if (locks[channel]) aunlock(locks[channel]); alock(sample); locks[channel]=sample; s=ablock(sample); p=(struct t_wave *)s; s+=sizeof(struct t_wave); siz=*(int *)s;s+=4; play_sample(channel,s,siz,siz,p->freq,(p->freq!=p->bps?2:1)); } void create_sound_table(char *template,long size) { char *c,*s; int i=0; if (sound_table==NULL) sound_table=create_list(2); s=c=template; while (c-s