samer@34: function Y=sonify_disc(S,D,Gen,varargin) samer@34: % sonify - Sonify sequences of durations and sound classes samer@34: % samer@34: % sonify :: samer@34: % ([[N]] | seq(real)) ~'sequence of pitches in semitones', samer@34: % (natural | seq(real)) ~'sequence of durations', samer@34: % options { samer@34: % bpm :: nonneg /240 ~'number of time units per minute'; samer@34: % fs :: real /11025 ~'intended sampling rate'; samer@34: % buffer :: noneg /0.125 ~'buffer size in seconds, [] means one per note' samer@34: % } samer@34: % -> seq([[1,T]]). samer@34: samer@37: opts=options('env',[],'bpm',240,'fs',11025,'buffer',0.125, varargin{:}); samer@34: samer@34: sample_rate=opts.fs; samer@34: dm=60*opts.fs/opts.bpm; samer@34: samer@34: if isscalar(D), D=dd(dm*D); samer@36: else D=map(@(d)dm*d,dd(D)); % D=dm*D with optimisation samer@34: end samer@34: samer@36: Y=zipwith(@select_gen,D,dd(S)); samer@34: samer@34: % if supplied apply envelope to shape each note samer@34: if ~isempty(opts.env), samer@36: Y=map(opts.env,Y); samer@34: end samer@34: samer@34: % rebuffer to constant size samer@34: if ~isempty(opts.buffer) samer@34: Y=windowdata(Y,ceil(opts.buffer*opts.fs)); samer@34: end samer@34: samer@34: function y=select_gen(dur,k) samer@34: y=feval(Gen{k},sample_rate,floor(dur)); samer@34: end samer@34: end samer@34: