gates_of_skeldal/VIDEO/MGFSOUND.C
2025-01-24 18:27:22 +01:00

558 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <types.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <mem.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <fcntl.h>
#include <io.h>
#include <wav.c>
#define BLK_SIZE 100000
#define CHANNELS 256
#define SND_NAME ".SNF"
typedef struct volstruc
{
int volslow,volsmax;
int volume;
int volume_end;
int vls;
}TVOLSTRUC;
typedef struct tchaninfo
{
FILE *snd;
char chans;
char bit8;
long repstart;
long id ;
long size;
TVOLSTRUC left,right;
}TCHANINFO;
TCHANINFO chaninfo[CHANNELS];
typedef struct mgif_header
{
char sign[4];
char year[2];
char eof;
word ver;
long frames;
word snd_chans;
int snd_freq;
short ampl_table[256];
short reserved[32];
};
struct mgif_header gh;
short ampl_table[256];
signed short source[BLK_SIZE];
char target[BLK_SIZE];
int glob_volume=256;
long sfreq;
unsigned short chans;
FILE *sf;
int tf;
char *nsource;
char *ntarget;
long ssize;
long rsize,blck;
char difftype=4;
int last_channel;
long next_frame;
int find_free_channel()
{
int i;
for(i=0;i<256;i++) if (chaninfo[i].snd==NULL) return i;
printf("Nemohu pridat zvuk. Jiz je zaplneno vsech %d kanal\n",CHANNELS);
return -1;
}
void Create_table_16()
{
int a,c,d,e;
float b;
d=-1;e=0;
for(a=0;a<128;a++)
{
b=(a/128.0);
switch (difftype)
{
case 1:b=(b*32768.0);break;
case 2:b=(b*b*32768.0);break;
case 3:b=(b*b*b*32768.0);break;
case 4:b=(b*b*b*b*32768.0);break;
case 5:b=(b*b*b*b*b*32768.0);break;
}
c=(int)b;
if (c==d) e++;
d=c;c+=e;
ampl_table[128+a]=c;
ampl_table[128-a]=-c;
}
}
int find_index(int value)
{
int i;
if (value==0) return 128;
if (value>0)
{
for(i=128;i<256;i++)
if (ampl_table[i]>value) return i-1;
return 255;
}
else
{
for(i=128;i>=0;i--)
if (ampl_table[i]<value) return i+1;
return 1;
}
}
void compress_buffer_stereo(int size)
{
int i;
static int last1=0;
static int last2=0;
int val;
char indx;
for(i=0;i<size;i++)
{
if (i & 1)
{
val=source[i];
indx=find_index(val-last1);
last1+=ampl_table[indx];
if (last1>32768 || last1<-32768) abort();
target[i]=indx;
}
else
{
val=source[i];
indx=find_index(val-last2);
last2+=ampl_table[indx];
if (last2>32768 || last2<-32768) abort();
target[i]=indx;
}
}
}
void find_data()
{
char w[5]="data";
int i,d;
i=0;
do
{
d=fgetc(sf);
if (d==w[i]) i++;else i=0;
if (d==EOF) abort();
}
while (i<4);
}
void open_wav(char *wav)
{
TCHANINFO *inf;
int i;
struct t_wave *wavinf;
FILE *snd;
i=find_free_channel();
if (i==-1) return;
last_channel=i;
inf=chaninfo+i;
snd=fopen(wav,"rb");
if (snd==NULL)
{
printf("Soubor %s neexistuje.\n",wav);
return;
}
if (find_chunk(snd,WAV_FMT)==-1)
{
printf("Soubor %s ma poskozenou hlavicku\n",wav);
fclose(snd);
return;
}
wavinf=(struct t_wave *)malloc(get_chunk_size(snd));
if (wavinf==NULL)
{
puts("Nedostatek pamˆti.");
return;
}
read_chunk(snd,wavinf);
if (wavinf->wav_mode!=1)
{
printf("Tento program podporuje pouze WAVy typu 1 (%s)\n",wav);
free(wavinf);
fclose(snd);
return;
}
inf->chans=wavinf->chans;
inf->bit8=wavinf->freq*wavinf->chans==wavinf->bps;
inf->repstart=-1;
inf->id=-1;
inf->left.volume=32768;
inf->right.volume=32768;
inf->left.vls=0;
inf->right.vls=0;
free(wavinf);
if (find_chunk(snd,WAV_DATA)==0)
{
printf("Soubor %s je poskozen\n",wav);
fclose(snd);
return;
}
inf->size=get_chunk_size(snd);
fseek(snd,4,SEEK_CUR);
inf->snd=snd;
}
void calc_vls(TVOLSTRUC *vls)
{
vls->volslow--;
if (vls->volslow<=0)
{
vls->volslow+=vls->volsmax;
vls->volume+=vls->vls;
if ((vls->vls>0 && vls->volume>=vls->volume_end)||
(vls->vls<0 && vls->volume<=vls->volume_end))
{
vls->volume=vls->volume_end;
vls->vls=0;
}
}
}
void mix_buffer(int size)
{
int chan,i;
memset(source,0,size*2);
for(chan=0;chan<CHANNELS;chan++)
{
if (chaninfo[chan].snd!=NULL)
{
TCHANINFO *inf=chaninfo+chan;
for(i=0;i<size;i+=2)
{
int left,right;
if (inf->bit8)
{
fread(&left,1,1,inf->snd);left=(short)(left*256);
left^=0xffff8000;
inf->size--;
}
else
{
fread(&left,1,2,inf->snd);left=(short)left;
inf->size-=2;
}
if (inf->chans==1) right=left;
else
if (inf->bit8)
{
fread(&right,1,1,inf->snd);right=(short)(right*256);
right^=0xffff8000;
inf->size--;
}
else
{
fread(&right,1,2,inf->snd);right=(short)right;
inf->size-=2;
}
left=(int)left*inf->left.volume/(32768);
right=(int)right*inf->right.volume/(32768);
left=left*glob_volume/256;
right=right*glob_volume/256;
calc_vls(&inf->left);
calc_vls(&inf->right);
left+=source[i];
right+=source[i+1];
if (left>32767) left=32767;
if (left<-32767) left=-32767;
if (right>32767) right=32767;
if (right<-32767) right=-32767;
source[i]=left;
source[i+1]=right;
if (inf->size<=0)
{
if (inf->repstart!=-1)
{
fseek(inf->snd,0,SEEK_SET);
find_chunk(inf->snd,WAV_DATA);
inf->size=get_chunk_size(inf->snd);
fseek(inf->snd,4,SEEK_CUR);
fseek(inf->snd,inf->repstart,SEEK_CUR);
inf->size-=inf->repstart;
}
else
{
fclose(inf->snd);
inf->snd=NULL;
break;
}
}
}
}
}
}
void open_files(char *ntarget)
{
tf=open(ntarget,O_BINARY | O_RDWR);
if (!tf) abort();
lseek(tf,0,SEEK_SET);
read(tf,&gh,sizeof(gh));
memcpy(gh.ampl_table,ampl_table,sizeof(ampl_table));
gh.snd_freq=22050;
}
void read_frame()
{
long x;
read(tf,&x,4);
x>>=8;
next_frame=tell(tf)+x;
}
long find_sound_action()
{
long x;char c;
do
{
read(tf,&x,4);
c=x;x>>=8;
if (c==4) return x;
lseek(tf,x,SEEK_CUR);
}
while (1);
}
void press_sound_chunk()
{
int siz;
siz=find_sound_action();
mix_buffer(siz);
compress_buffer_stereo(siz);
write(tf,&target,siz);
}
void close_files()
{
int i;
lseek(tf,0,SEEK_SET);
write(tf,&gh,sizeof(gh));
fclose(sf);
close(tf);
for(i=0;i<CHANNELS;i++)
if (chaninfo[i].snd!=NULL)
{
fclose(chaninfo[i].snd);
chaninfo[i].snd=NULL;
}
}
void ozvuceni()
{
int i;
for(i=1;i<gh.frames;i++)
{
cprintf("frame %d\r",i);
read_frame();
press_sound_chunk();
lseek(tf,next_frame,SEEK_SET);
}
}
#define get_num(c,n) {sscanf(c,"%d",&n);while (*c==32) c++;c=strchr(c,32);}
int find_channel_id(int id)
{
int i;
for(i=0;i<256;i++) if (chaninfo[i].id==id) return i;
printf("Nemohu najit kanal s ID: %d\n",id);
return -1;
}
void interpret_line(FILE *f)
{
char line_buf[1024];
char *c=line_buf;
TVOLSTRUC *v;
TCHANINFO *inf;
int num;char fcid=0;
fgets(line_buf,1024,f);
while (c!=NULL)
{
while (*c==32) c++;
if (!*c) break;
if (*c=='@')
{
char command[24];
c++;
sscanf(c,"%23s",command);c=strchr(c,32);
strupr(command);
if (!strcmp(command,"ID"))
{
get_num(c,num);
if (fcid) chaninfo[last_channel].id=num;
fcid=0;
if ((last_channel=find_channel_id(num))==-1) return;
inf=chaninfo+last_channel;
}
else if (!strcmp(command,"R")) v=&inf->left;
else if (!strcmp(command,"L")) v=&inf->right;
else if (!strcmp(command,"VOL"))
{
get_num(c,num);
v->volume=num*128;
}
else if (!strcmp(command,"VOLEND"))
{
get_num(c,num);
v->volume_end=num*128;
v->vls=0;
}
else if (!strcmp(command,"SPEED"))
{
get_num(c,v->vls);v->volsmax=1;v->volslow=1;
if (v->volume>v->volume_end) v->vls=-v->vls;
}
else if (!strcmp(command,"SLOW"))
{
get_num(c,v->volsmax);v->vls=1;v->volslow=1;
if (v->volume>v->volume_end) v->vls=-v->vls;
}
else if (!strcmp(command,"REPSTART")){ get_num(c,inf->repstart);}
else if (!strcmp(command,"GLOBVOL")) {get_num(c,glob_volume);}
}
else
{
char filename[128];
sscanf(c,"%127s",filename);
c=strchr(c,32);
open_wav(filename);
inf=chaninfo+last_channel;
fcid=1;
}
}
}
void call_script(char *script_name)
{
FILE *scr,*snf;
char name[256];
char snd_name[256],*c;
int i,fr,lfr=0,wfr=-1;
scr=fopen(script_name,"r");
strcpy(snd_name,script_name);
c=strrchr(snd_name,'.');
if (c==NULL) strcat(snd_name,SND_NAME);
else strcpy(c,SND_NAME);
if (scr==NULL)
{
printf("Nemohu otev©¡t script: %s\n",script_name);
exit(1);
}
snf=fopen(snd_name,"r");
i=fscanf(scr,"%255s",name);
open_files(name);
if (i!=1)
{
printf("Chyba ve script souboru: %s. Prvni mus¡ b˜t jmno c¡lovho souboru.\n",scr);
exit(1);
}
while ((i=fgetc(scr))!=EOF && i!='\n');
for(fr=1;fr<gh.frames;fr++)
{
cprintf("frame %d\r",fr);
read_frame();
do
{
if (wfr==-1)
{
i=fgetc(scr);
if (i!=EOF)
{
if (i!='#')
{
fscanf(snf,"%d",&lfr);
while ((i=fgetc(scr))!=EOF && i!='\n');
}
else
{
fscanf(scr,"%d",&wfr);
wfr+=lfr-1;
}
}
else wfr=9999999;
}
if (wfr<=fr && wfr!=-1)
{
interpret_line(scr);
wfr=-1;
}
}
while (wfr==-1);
press_sound_chunk();
lseek(tf,next_frame,SEEK_SET);
}
fclose(scr);
if (snf!=NULL) fclose(snf);
}
main(int argc,char *argv[])
{
if (argc<2)
{
puts("\nPouziti: MGFSOUND film.mgf zvuk.wav [i]");
puts("\nnebo: MGFSOUND script.scr");
puts("\nKde _i_ je komprimacni krivka (viz SNDPACK) (default:4)");
exit(0);
}
if (argc>3)
{
sscanf(argv[3],"%d",&difftype);
}
Create_table_16();
if (argc==2)
call_script(argv[1]);
else
{
open_wav(argv[2]);
open_files(argv[1]);
ozvuceni();
}
close_files();
}