File: sound.e

package info (click to toggle)
euler 1.61.0-12
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 5,164 kB
  • sloc: ansic: 24,761; sh: 8,314; makefile: 141; cpp: 47; php: 1
file content (132 lines) | stat: -rw-r--r-- 3,625 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
comment
Save and load WAV sound files. Analyze frequencies.

{w,rate}=loadwave(filename); loads a WAV file.
w=loadwave(filename); loads a WAV file. r is saved to defaultrate.
savewave(filename,v[,rate,bits]); saves a WAV file.
analyze(v[,fmin,fmax,rate,points]); plots the frequencies of v
mapsound(w,[,dt,fmin,fmax,simpl,rate]); show the sound history
soundsec(n[,rate]); generates t values for n seconds.

Default sample rate is 22050 or the sample rate of the last read WAV file.
endcomment

defaultrate=22050;

function soundsec (n,rate=0)
## Return n seconds of t parameter.
	global defaultrate;
	if rate==0; rate=defaultrate; endif;
	return 0:2*pi/rate:2*n*pi;
endfunction

function savewave (filename,v,rate=0,bits=16)
## Save a vector of sound data in WAV format.
## Return the length of the sample in seconds.
## If rate=0, the default sampling rate is taken.
## bits may be 8 or 16.
	global defaultrate;
	if rate==0; rate=defaultrate; endif;
	open(filename,"wb");
	write("RIFF");
	if bits==8;
		n=cols(v);
		putlongword(n+37);
		write("WAVEfmt ");
		putlongword(16); putword(1); putword(1);
		putlongword(rate); putlongword(rate);
		putword(1); putword(8);
		write("data");
		putlongword(n);
		m=max(abs(v)); vv=v/m*64+128;
		putuchar(vv);
		putchar(0);
	elseif bits==16;
		n=cols(v);
		putlongword(2*n+36);
		write("WAVEfmt ");
		putlongword(16); putword(1); putword(1);
		putlongword(rate); putlongword(2*rate);
		putword(2); putword(16);
		write("data");
		putlongword(2*n);
		m=max(abs(v)); vv=v/m*64*256;
		putword(vv);
	else error("Bits must be 8 or 16");
	endif
	close();
	return cols(v)/rate;
endfunction

function loadwave (filename)
## Read a WAV file.
## The sample rate is stored to defaultrate.
	global defaultrate;
	open(filename,"rb");
	if getstring(4)<>"RIFF"; error("No Wave file!"); endif;
	getlongword(); .. This is the total file length minus 8
	if getstring(8)<>"WAVEfmt "; error("No Wave file!"); endif;
	offset=getlongword(); .. ??? Is always 16, sometimes 18
	getword(); .. ??? Is always 1.
	if (getword()<>1); error("Stereo sample!"); endif;
	rate=getlongword(); getlongword();
	byte=getword();
	bits=getword();
	if offset>16; getuchar(offset-16); endif;
	if getstring(4)<>"data"; error("No Wave file!"); endif;
	if byte==1;
		w=getuchar(getlongword());
	elseif byte==2;
		w=getword(getlongword()/2);
	else error("Not 8 or 16 bit!");
	endif;
	if cols(w)>0; w=w-sum(w)/cols(w); w=w/max(abs(w)); endif;
	close();
	defaultrate=rate;
	return w;
endfunction

function analyze (w,fmin=10,fmax=1500,rate=0,points=8192)
## Make a frequency plot of the signal w with sampling rate.
## The data must be at least points long.
## The maximal frequency plotted will be fmax, the minimal fmin.
	global defaultrate;
	if rate==0; rate=defaultrate; endif;
	v=w[1:points];
	f=abs(fft(v));
	i=fmin/rate*points:fmax/rate*points;
	setplot(fmin,fmax,0,max(f[i]));
	fr=i/points*rate;
	xplot(fr,f[i]);
	return "";
endfunction

function mapsound (w,dt=0.1,fmin=100,fmax=1500,simpl=1,rate=0)
## Plots a sound map for a sound.
## It does FFT at time increments dt.
## rate is the sampling rate.
## simpl points are collected for speed reasons.
	n=cols(w);
	global defaultrate;
	if rate==0; rate=defaultrate; endif;
	dp=dt*rate;
	points=2^floor(log(dp)/log(2));
	ind=fmin/rate*points/simpl:fmax/rate*points/simpl;
	f=abs(fft(w[1:points]));
	f=sum(redim(f,points/simpl,simpl))';
	M=f[ind];
	i=1;
	repeat
		i=i+dp;
		if i+points>n; break; endif;
		f=abs(fft(w[i:i+points-1]));
		f=sum(redim(f,points/simpl,simpl))';
		M=M_f[ind];
	end;
	setplot(fmin,fmax,0,n/rate);
	density(-M,0.99);
	xplot();
	return ""
endfunction