samer@34
|
1 function Y=sonify_disc(S,D,Gen,varargin)
|
samer@34
|
2 % sonify - Sonify sequences of durations and sound classes
|
samer@34
|
3 %
|
samer@34
|
4 % sonify ::
|
samer@34
|
5 % ([[N]] | seq(real)) ~'sequence of pitches in semitones',
|
samer@34
|
6 % (natural | seq(real)) ~'sequence of durations',
|
samer@34
|
7 % options {
|
samer@34
|
8 % bpm :: nonneg /240 ~'number of time units per minute';
|
samer@34
|
9 % fs :: real /11025 ~'intended sampling rate';
|
samer@34
|
10 % buffer :: noneg /0.125 ~'buffer size in seconds, [] means one per note'
|
samer@34
|
11 % }
|
samer@34
|
12 % -> seq([[1,T]]).
|
samer@34
|
13
|
samer@37
|
14 opts=options('env',[],'bpm',240,'fs',11025,'buffer',0.125, varargin{:});
|
samer@34
|
15
|
samer@34
|
16 sample_rate=opts.fs;
|
samer@34
|
17 dm=60*opts.fs/opts.bpm;
|
samer@34
|
18
|
samer@34
|
19 if isscalar(D), D=dd(dm*D);
|
samer@36
|
20 else D=map(@(d)dm*d,dd(D)); % D=dm*D with optimisation
|
samer@34
|
21 end
|
samer@34
|
22
|
samer@36
|
23 Y=zipwith(@select_gen,D,dd(S));
|
samer@34
|
24
|
samer@34
|
25 % if supplied apply envelope to shape each note
|
samer@34
|
26 if ~isempty(opts.env),
|
samer@36
|
27 Y=map(opts.env,Y);
|
samer@34
|
28 end
|
samer@34
|
29
|
samer@34
|
30 % rebuffer to constant size
|
samer@34
|
31 if ~isempty(opts.buffer)
|
samer@34
|
32 Y=windowdata(Y,ceil(opts.buffer*opts.fs));
|
samer@34
|
33 end
|
samer@34
|
34
|
samer@34
|
35 function y=select_gen(dur,k)
|
samer@34
|
36 y=feval(Gen{k},sample_rate,floor(dur));
|
samer@34
|
37 end
|
samer@34
|
38 end
|
samer@34
|
39
|