samer@0: % lineout - Live audio output samer@0: % samer@0: % lineout :: samer@0: % C:natural ~'desired no. of channels', samer@0: % R:nonneg ~'desired sample rate', samer@0: % options { samer@0: % bufsize :: natural/[] ~'desired buffer size' samer@0: % } samer@0: % -> sink(C,R). samer@0: classdef lineout < sink samer@0: properties (GetAccess=private, SetAccess=immutable) samer@0: fs samer@0: chans samer@0: opts samer@0: end samer@0: methods samer@0: function s=lineout(channels,rate,varargin) samer@42: s.opts = options('bufsize',0,'bits',16,'pad',0,'quiet',0,varargin{:}); samer@0: s.chans=channels; samer@0: s.fs=rate; samer@0: end samer@0: samer@0: function c=tostring(sig), c=sprintf('lineout(%d,%d)',sig.chans,sig.fs); end samer@0: function c=channels(s), c=s.chans; end samer@0: function c=rate(s), c=s.fs; end samer@0: function s=construct(sig) samer@46: import ishara.audio.*; samer@0: samer@0: snk=LineSink(audio_format(sig.chans,sig.fs,sig.opts.bits),sig.opts.bufsize); samer@0: snk.setScale(0.999); samer@0: line=snk.getLine(); samer@0: ref=disposables('reg',snk); samer@42: if ~sig.opts.quiet samer@42: fprintf('\nOpened audio output device:\n %s\n',char(snk.toString)); samer@42: fprintf(' Actual buffer size is %d.\n',snk.getLine.getBufferSize); samer@42: end samer@0: samer@0: if sig.opts.pad>0, samer@0: fprintf(' Padding start and stop with %d samples.\n',sig.opts.pad); samer@0: pad=zeros(sig.chans*sig.opts.pad,1); samer@0: padwr=snk.writer(length(pad)); samer@0: maybe_pad=@()padwr.write(pad); samer@0: else samer@0: maybe_pad=@nop; samer@0: end samer@0: samer@0: s.stop = @stop; samer@0: s.start = @start; samer@0: s.dispose = @dispose; samer@0: s.writer = @writer; samer@0: samer@0: s.getLine = @()line; samer@0: s.setGain = @(s)snk.setScale(s); samer@0: samer@0: function start, line.flush(); line.start(); maybe_pad(); snk.check(); end samer@0: function stop, snk.check(); maybe_pad(); line.drain(); line.stop(); end samer@0: samer@0: function r=writer(n) samer@0: ch=sig.chans; samer@0: wr=snk.writer(ch*n); samer@0: r=@next; samer@0: function rem=next(x) samer@0: rem=wr.write(x(:))/ch; samer@0: end samer@0: end samer@0: samer@0: function dispose samer@0: disposables('dereg',ref); samer@0: snk.dispose(); samer@0: end samer@0: end samer@0: end samer@0: end