Initial (manual) import

This commit is contained in:
minexew committed 2017-01-22 20:26:44 +01:00
1 parent f39611c506
commit 895fe109de
661 files changed
+245862

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
Cd(__DIR__);;
#help_index "Snd"
class CSndWaveCtrl
{
I64 sample_rate,sample_bits,channels;
F64 freq_multiplier,amp_multiplier;
F64 phase,last_y,last_dydt,next_y;
};
public U0 SndTaskEndCB()
{//Will turn-off snd when a task gets killed.
Snd;
Exit;
}
#include "SndMath"
#include "SndMusic"
#include "SndEffects"
#include "SndFile"
Cd("..");;
+80
View File
@@ -0,0 +1,80 @@
#help_index "Snd"
#define SE_NOISE 0
#define SE_SWEEP 1
class CSoundEffectFrame
{
I32 type;
I8 ona1,ona2;
F64 duration;
};
U0 SoundEffectEndTaskCB()
{
Free(FramePtr("CSoundEffectFrame"));
music.mute--;
SndTaskEndCB;
}
U0 SoundEffectTask(CSoundEffectFrame *ns)
{
I64 i,ona;
F64 t0=tS,t,timeout=t0+ns->duration;
FramePtrAdd("CSoundEffectFrame",ns);
Fs->task_end_cb=&SoundEffectEndTaskCB;
switch (ns->type) {
case SE_NOISE:
i=MaxI64(ns->ona2-ns->ona1,1);
while (tS<timeout) {
ona=RandU16%i+ns->ona1;
Snd(ona);
t=Clamp(3000.0/Ona2Freq(ona),1.0,50.0);
if (t+tS>timeout)
t=timeout-tS;
Sleep(t);
}
break;
case SE_SWEEP:
while (tS<timeout) {
t=(tS-t0)/ns->duration;
ona=(1.0-t)*ns->ona1+t*ns->ona2;
Snd(ona);
t=Clamp(3000.0/Ona2Freq(ona),1.0,50.0);
if (t+tS>timeout)
t=timeout-tS;
Sleep(t);
}
break;
}
}
public CTask *Noise(I64 mS,F64 min_ona,F64 max_ona)
{//Make white noise for given number of mS.
CSoundEffectFrame *ns;
if (mS>0) {
ns=MAlloc(sizeof(CSoundEffectFrame));
ns->type=SE_NOISE;
ns->duration=mS/1000.0;
ns->ona1=min_ona;
ns->ona2=max_ona;
music.mute++;
return Spawn(&SoundEffectTask,ns,"Noise",,Fs);
} else
return NULL;
}
public CTask *Sweep(I64 mS,F64 ona1,F64 ona2)
{//Sweep through freq range in given number of mS.
CSoundEffectFrame *ns;
if (mS>0) {
ns=MAlloc(sizeof(CSoundEffectFrame));
ns->type=SE_SWEEP;
ns->duration=mS/1000.0;
ns->ona1=ona1;
ns->ona2=ona2;
music.mute++;
return Spawn(&SoundEffectTask,ns,"Noise",,Fs);
} else
return NULL;
}
+134
View File
@@ -0,0 +1,134 @@
#help_index "Snd/Snd Files"
#define SNDFILE_SAMPLE_RATE 8000
//Header for a ".SND" file
class CFileSND
{//big endian
U32 signature; //0x646e732e
U32 offset; //24
U32 data_size;
U32 coding; //3=16bit uncompressed
U32 sample_rate; //Hz
U32 channels; //1=mono
I16 body[1];
};
//Windows media constraint.
//#define SND_FILE_DATA_MAX 0x0007FF00
#define SND_FILE_DATA_MAX 0x7FFFFF00
public I64 SndFileCreate(U8 *base_filename,F64 normalized_vol=1.0,
F64 averaging=0.0,I64 waveform=WF_SQUARE,
F64 reverb_delay=0,F64 reverb_intensity=0,F64 time_shift=0)
{//Use "snd.record" flag to start or stop recording, then call this routine.
//Averaging should be a num from 0.0 to 0.999.
//Vol should be from 0.0 to 1.0.
//Set reverb_delay to like 0.3 sec and reverb_intensity to like 0.4.
I64 i,k,cnt,cnt2,level,file_num;
F64 avg,dt;
CFileSND *s;
CSndWaveCtrl *swc=SndWaveCtrlNew(SNDFILE_SAMPLE_RATE,16,1);
CSndData *d,*d1;
U8 *name,*name2;
snd.record=FALSE;
dt=snd.record_head.last->time-snd.record_head.next->time;
if (!dt) return 0;
cnt=dt*SNDFILE_SAMPLE_RATE;
cnt++; //Terminator
name=StrNew(base_filename);
FileExtRem(name);
s=CAlloc(offset(CFileSND.body)+cnt*sizeof(I16));
s->signature=0x646e732e;
s->offset=EndianU32(offset(CFileSND.body));
s->coding=EndianU32(3);
s->sample_rate=EndianU32(SNDFILE_SAMPLE_RATE);
s->channels=EndianU32(1);
if (time_shift) {
d=snd.record_head.next;
d->time-=time_shift;
while (d->next!=&snd.record_head) {
d1=d->next;
dt=d1->time-d->time;
if (dt<0) {
QueRem(d1);
Free(d1);
} else
break;
}
}
d=snd.record_head.next;
k=0;
while (d->next!=&snd.record_head) {
d1=d->next;
dt=d1->time-d->time;
cnt2=dt*SNDFILE_SAMPLE_RATE;
SndWaveAddBuf(swc,&s->body[k],cnt2,
Ona2Freq(d->ona),waveform,normalized_vol);
k+=cnt2;
QueRem(d);
Free(d);
d=d1;
}
//Average
if (averaging) {
avg=0;
for (i=0;i<cnt-1;i++)
s->body[i]=avg=LowPass1(averaging,avg,s->body[i],1.0);
}
//Reverb
if (reverb_intensity) {
if (dt=reverb_delay*SNDFILE_SAMPLE_RATE)
for (i=dt;i<cnt;i++)
s->body[i]+=reverb_intensity*s->body[i-dt];
}
//Get rid of D.C. component
for (k=0;k<3;k++) {
level=0;
for (i=0;i<cnt-1;i++)
level+=s->body[i];
level/=cnt-1;
for (i=0;i<cnt-1;i++)
s->body[i]=ClampI64(s->body[i]-level,I16_MIN,I16_MAX);
}
for (i=0;i<cnt-1;i++)
s->body[i]=EndianU16(s->body[i]);
s->body[cnt-1]=0;
d=snd.record_head.next;
while (d!=&snd.record_head) {
d1=d->next;
QueRem(d);
Free(d);
d=d1;
}
name2=MAlloc(StrLen(name)+3+1+3+1);
cnt2=cnt;
file_num=0;
while (cnt2>0) {
i=cnt2;
if (i>SND_FILE_DATA_MAX)
i=SND_FILE_DATA_MAX;
s->data_size=EndianU32(i*sizeof(I16));
MemCpy(s->body,&s->body[file_num*SND_FILE_DATA_MAX],i*sizeof(I16));
StrPrint(name2,"%s%03d.SND",name,file_num++);
FileWrite(name2,s,offset(CFileSND.body)+i*sizeof(I16));
cnt2-=i;
}
Free(s);
Free(name);
Free(name2);
SndWaveCtrlDel(swc);
return cnt;
}
+248
View File
@@ -0,0 +1,248 @@
#help_index "Snd/Math;Math"
public F64 Saw(F64 t,F64 period)
{//Sawtooth. 0.0 - 1.0 think "(Sin+1)/2"
if (period) {
if (t>=0.0)
return t%period/period;
else
return 1.0+t%period/period;
} else
return 0.0;
}
public F64 FullSaw(F64 t,F64 period)
{//Plus&Minus Sawtooth. 1.0 - -1.0 think "Sin"
if (period) {
if (t>=0.0)
return 2.0*(t%period/period)-1.0;
else
return 2.0*(t%period/period)+1.0;
} else
return 0.0;
}
public F64 Caw(F64 t,F64 period)
{//Cawtooth. 1.0 - 0.0 think "(Cos+1)/2"
if (period) {
if (t>=0.0)
return 1.0-t%period/period;
else
return -(t%period)/period;
} else
return 1.0;
}
public F64 FullCaw(F64 t,F64 period)
{//Plus&Minus Cawtooth. 1.0 - -1.0 think "Cos"
if (period) {
if (t>=0.0)
return -2.0*(t%period/period)+1.0;
else
return -2.0*(t%period/period)-1.0;
} else
return 1.0;
}
public F64 Tri(F64 t,F64 period)
{//Triangle waveform. 0.0 - 1.0 - 0.0
if (period) {
t=2.0*(Abs(t)%period)/period;
if (t<=1.0)
return t;
else
return 2.0-t;
} else
return 0.0;
}
public F64 FullTri(F64 t,F64 period)
{//Plus&Minus Triangle waveform. 0.0 - 1.0 - 0.0 - -1.0 -0.0
if (period) {
t=4.0*(t%period)/period;
if (t<=-1.0) {
if (t<=-3.0)
return t+4.0;
else
return -2.0-t;
} else {
if (t<=1.0)
return t;
else if (t<=3.0)
return 2.0-t;
else
return t-4.0;
}
} else
return 0.0;
}
#help_index "Snd/Math"
public I8 Note2Ona(I64 note,I64 octave=4)
{//Note to ona. Mid C is ona=51, note=3 and octave=4.
if (note<3)
return (octave+1)*12+note;
else
return octave*12+note;
}
public I8 Ona2Note(I8 ona)
{//Ona to note in octave. Mid C is ona=51, note=3 and octave=4.
return ona%12;
}
public I8 Ona2Octave(I8 ona)
{//Ona to octave. Mid C is ona=51, note=3 and octave=4.
I64 note=ona%12,octave=ona/12;
if (note<3)
return octave-1;
else
return octave;
}
F64 SinPhaseCont(F64 last_y,F64 last_dydt,
F64 current_amp,F64 phase_offset)
{//Next sample of sin waveform.
F64 phase;
phase=last_y/current_amp;
if (phase>1.0) phase=1.0;
if (phase<-1.0) phase=-1.0;
if (last_dydt<0)
phase=ã-ASin(phase);
else
phase=ASin(phase);
return phase-phase_offset;
}
public CSndWaveCtrl *SndWaveCtrlNew(I64 sample_rate=8000,I64 sample_bits=24,
I64 channels=2,CTask *mem_task=NULL)
{//MAlloc ctrl struct for generating waveforms.
CSndWaveCtrl *swc=CAlloc(sizeof(CSndWaveCtrl),mem_task);
swc->freq_multiplier=1.0;
swc->amp_multiplier=1.0;
swc->sample_rate=sample_rate;
swc->sample_bits=sample_bits;
swc->channels=channels;
swc->last_dydt=1.0;
return swc;
}
public U0 SndWaveCtrlDel(CSndWaveCtrl *swc)
{//Free waveform ctrl.
Free(swc);
}
#define WF_NULL 0
#define WF_SQUARE 1
#define WF_SINE 2
#define WF_TRI 3
#define WF_SAWTOOTH 4
#define WF_NOISE 5
#define WF_WAVEFORMS_NUM 6
public U0 SndWaveAddBuf(CSndWaveCtrl *swc,U8 *buf,I64 num_samples,
F64 _freq,I64 _waveform=WF_SQUARE,F64 _amp=1.0,F64 _left=1.0, F64 _right=1.0)
{//Add waveform to buffer.
//num_samples is multiplied by channels to get buf_len.
//left,right range from 0.0-1.0
//Supports 16,24 and 32 bits
I64 reg i,reg j,reg k;
F64 a,f,amp,reg phase;
if (!swc) return;
_freq*=swc->freq_multiplier;
_amp*=swc->amp_multiplier;
if (!_freq||!_amp) {
swc->last_y=swc->phase=0;
swc->last_dydt=1.0;
} else {
phase=swc->phase;
i=0;
amp=Min(I32_MAX,I32_MAX*_amp);
f=2*ã/swc->sample_rate*_freq;
switch (_waveform) {
case WF_NOISE:
a=2.0/ã*amp;
break;
case WF_SAWTOOTH:
a=amp/ã;
break;
case WF_SINE:
phase=SinPhaseCont(swc->last_y,swc->last_dydt,amp,0.0);
break;
}
while (phase<0)
phase+=2*ã;
while (phase>=2*ã)
phase-=2*ã;
num_samples*=swc->channels;
while (i<num_samples) {
switch (_waveform) {
case WF_SQUARE:
if (phase>=ã)
j=-amp;
else
j=amp;
break;
case WF_SINE:
j=amp*Sin(phase);
break;
case WF_TRI:
if (phase>=ã) {
swc->last_y=swc->next_y;
swc->next_y=-amp*Sign(swc->last_y)+.00001;
phase-=ã;
}
j=(swc->last_y*(ã-phase)+swc->next_y*phase)/ã;
break;
case WF_SAWTOOTH:
j=a*(phase-ã);
break;
case WF_NOISE:
if (phase<ã) {
if (phase<f) {
swc->last_y=swc->next_y;
swc->next_y=a*RandI16/U16_MAX;
}
j=swc->last_y*(ã-phase)+swc->next_y*phase;
} else {
if (phase-ã<f) {
swc->last_y=swc->next_y;
swc->next_y=a*RandI16/U16_MAX;
}
j=swc->last_y*(2.0*ã-phase)+swc->next_y*(phase-ã);
}
break;
}
//left channel
k=j*_left;
if (swc->sample_bits==16) {
k>>=16;
buf(I16 *)[i++]+=k;
} else {
if (swc->sample_bits==24)
k&=0xFFFFFF00;
buf(I32 *)[i++]+=k;
}
//right channel
if (swc->channels==2) {
k=j*_right;
if (swc->sample_bits==16) {
k>>=16;
buf(I16 *)[i++]+=k;
} else {
if (swc->sample_bits==24)
k&=0xFFFFFF00;
buf(I32 *)[i++]+=k;
}
}
phase+=f;
while (phase>=2*ã)
phase-=2*ã;
}
if (_waveform==WF_SINE) {
swc->last_y=amp*Sin(phase);
swc->last_dydt=Cos(phase);
}
swc->phase=phase;
}
}
+219
View File
@@ -0,0 +1,219 @@
#help_index "Snd/Music"
public class CMusicGlbls
{
U8 *cur_song;
CTask *cur_song_task;
I64 octave;
F64 note_len;
U8 note_map[7];
Bool mute;
I64 meter_top,meter_bottom;
F64 tempo,stacatto_factor;
//If you wish to sync with a
//note in a Play() string. 0 is the start
I64 play_note_num;
F64 tM_correction,last_Beat,last_tM;
} music={NULL,NULL,4,1.0,{0,2,3,5,7,8,10},FALSE,4,4,2.5,0.9,0,0,0,0};
#help_index "Snd/Music;Time/Seconds"
public F64 tM()
{//Time in seconds synced to music subsystem.
return (cnts.jiffies+music.tM_correction)/JIFFY_FREQ;
}
public F64 Beat()
{//Time in music beats.
F64 res,cur_tM;
PUSHFD
CLI
if (mp_cnt>1)
while (LBts(&sys_semas[SEMA_TMBEAT],0))
PAUSE
cur_tM=tM;
res=music.last_Beat;
if (music.tempo)
res+=(cur_tM-music.last_tM)*music.tempo;
music.last_tM=cur_tM;
music.last_Beat=res;
LBtr(&sys_semas[SEMA_TMBEAT],0);
POPFD
return res;
}
#help_index "Snd/Music"
U8 *MusicSetOctave(U8 *st)
{
I64 ch;
ch=*st++;
while ('0'<=ch<='9') {
music.octave=ch-'0';
ch=*st++;
}
return --st;
}
U8 *MusicSetMeter(U8 *st)
{
I64 ch;
ch=*st++;
while (ch=='M') {
ch=*st++;
if ('0'<=ch<='9') {
music.meter_top=ch-'0';
ch=*st++;
}
if (ch=='/')
ch=*st++;
if ('0'<=ch<='9') {
music.meter_bottom=ch-'0';
ch=*st++;
}
}
return --st;
}
U8 *MusicSetNoteLen(U8 *st)
{
Bool cont=TRUE;
do {
switch (*st++) {
case 'w': music.note_len=4.0; break;
case 'h': music.note_len=2.0; break;
case 'q': music.note_len=1.0; break;
case 'e': music.note_len=0.5; break;
case 's': music.note_len=0.25; break;
case 't': music.note_len=2.0*music.note_len/3.0; break;
case '.': music.note_len=1.5*music.note_len; break;
default:
st--;
cont=FALSE;
}
} while (cont);
return st;
}
public U0 Play(U8 *st,U8 *words=NULL)
{/* Notes are entered with a capital letter.
Octaves are entered with a digit and
stay set until changed. Mid C is octave 4.
Durations are entered with
'w' whole note
'h' half note
'q' quarter note
'e' eighth note
't' sets to 2/3rds the current duration
'.' sets to 1.5 times the current duration
durations stay set until changed.
'(' tie, placed before the note to be extended
$LK,"music.meter_top",A="MN:CMusicGlbls"$,$LK,"music.meter_bottom",A="MN:CMusicGlbls"$ is set with
"M3/4"
"M4/4"
etc.
Sharp and flat are done with '#' or 'b'.
The var music.stacatto_factor can
be set to a range from 0.0 to 1.0.
The var music.tempo is quarter-notes
per second. It defaults to
2.5 and gets faster when bigger.
*/
U8 *word,*last_st;
I64 note,i=0,ona,timeout_val,timeout_val2;
Bool tie;
F64 d,on_jiffies,off_jiffies;
music.play_note_num=0;
while (*st) {
timeout_val=cnts.jiffies;
tie=FALSE;
do {
last_st=st;
if (*st=='(') {
tie=TRUE;
st++;
} else {
st=MusicSetMeter(st);
st=MusicSetOctave(st);
st=MusicSetNoteLen(st);
}
} while (st!=last_st);
if (!*st) break;
note=*st++-'A';
if (note<7) {
note=music.note_map[note];
if (*st=='b') {
note--;
st++;
} else if (*st=='#') {
note++;
st++;
}
ona=Note2Ona(note,music.octave);
} else
ona=ONA_REST;
if (words && (word=LstSub(i++,words)) && StrCmp(word," "))
"%s",word;
d=JIFFY_FREQ*music.note_len/music.tempo;
if (tie) {
on_jiffies =d;
off_jiffies =0;
} else {
on_jiffies =d*music.stacatto_factor;
off_jiffies =d*(1.0-music.stacatto_factor);
}
timeout_val+=on_jiffies;
timeout_val2=timeout_val+off_jiffies;
if (!music.mute)
Snd(ona);
SleepUntil(timeout_val);
music.tM_correction+=on_jiffies-ToI64(on_jiffies);
if (!music.mute)
Snd;
SleepUntil(timeout_val2);
music.tM_correction+=off_jiffies-ToI64(off_jiffies);
music.play_note_num++;
}
}
U0 MusicSettingsRst()
{
music.play_note_num=0;
music.stacatto_factor=0.9;
music.tempo=2.5;
music.octave=4;
music.note_len=1.0;
music.meter_top=4;
music.meter_bottom=4;
SndRst;
PUSHFD
CLI
if (mp_cnt>1)
while (LBts(&sys_semas[SEMA_TMBEAT],0))
PAUSE
music.last_tM=tM;
music.last_Beat=0.0;
LBtr(&sys_semas[SEMA_TMBEAT],0);
POPFD
}
MusicSettingsRst;
U0 CurSongTask()
{
Fs->task_end_cb=&SndTaskEndCB;
while (TRUE)
Play(music.cur_song);
}