samer@0
|
1 % lineout - Live audio output
|
samer@0
|
2 %
|
samer@0
|
3 % lineout ::
|
samer@0
|
4 % C:natural ~'desired no. of channels',
|
samer@0
|
5 % R:nonneg ~'desired sample rate',
|
samer@0
|
6 % options {
|
samer@0
|
7 % bufsize :: natural/[] ~'desired buffer size'
|
samer@0
|
8 % }
|
samer@0
|
9 % -> sink(C,R).
|
samer@0
|
10 classdef lineout < sink
|
samer@0
|
11 properties (GetAccess=private, SetAccess=immutable)
|
samer@0
|
12 fs
|
samer@0
|
13 chans
|
samer@0
|
14 opts
|
samer@0
|
15 end
|
samer@0
|
16 methods
|
samer@0
|
17 function s=lineout(channels,rate,varargin)
|
samer@42
|
18 s.opts = options('bufsize',0,'bits',16,'pad',0,'quiet',0,varargin{:});
|
samer@0
|
19 s.chans=channels;
|
samer@0
|
20 s.fs=rate;
|
samer@0
|
21 end
|
samer@0
|
22
|
samer@0
|
23 function c=tostring(sig), c=sprintf('lineout(%d,%d)',sig.chans,sig.fs); end
|
samer@0
|
24 function c=channels(s), c=s.chans; end
|
samer@0
|
25 function c=rate(s), c=s.fs; end
|
samer@0
|
26 function s=construct(sig)
|
samer@46
|
27 import ishara.audio.*;
|
samer@0
|
28
|
samer@0
|
29 snk=LineSink(audio_format(sig.chans,sig.fs,sig.opts.bits),sig.opts.bufsize);
|
samer@0
|
30 snk.setScale(0.999);
|
samer@0
|
31 line=snk.getLine();
|
samer@0
|
32 ref=disposables('reg',snk);
|
samer@42
|
33 if ~sig.opts.quiet
|
samer@42
|
34 fprintf('\nOpened audio output device:\n %s\n',char(snk.toString));
|
samer@42
|
35 fprintf(' Actual buffer size is %d.\n',snk.getLine.getBufferSize);
|
samer@42
|
36 end
|
samer@0
|
37
|
samer@0
|
38 if sig.opts.pad>0,
|
samer@0
|
39 fprintf(' Padding start and stop with %d samples.\n',sig.opts.pad);
|
samer@0
|
40 pad=zeros(sig.chans*sig.opts.pad,1);
|
samer@0
|
41 padwr=snk.writer(length(pad));
|
samer@0
|
42 maybe_pad=@()padwr.write(pad);
|
samer@0
|
43 else
|
samer@0
|
44 maybe_pad=@nop;
|
samer@0
|
45 end
|
samer@0
|
46
|
samer@0
|
47 s.stop = @stop;
|
samer@0
|
48 s.start = @start;
|
samer@0
|
49 s.dispose = @dispose;
|
samer@0
|
50 s.writer = @writer;
|
samer@0
|
51
|
samer@0
|
52 s.getLine = @()line;
|
samer@0
|
53 s.setGain = @(s)snk.setScale(s);
|
samer@0
|
54
|
samer@0
|
55 function start, line.flush(); line.start(); maybe_pad(); snk.check(); end
|
samer@0
|
56 function stop, snk.check(); maybe_pad(); line.drain(); line.stop(); end
|
samer@0
|
57
|
samer@0
|
58 function r=writer(n)
|
samer@0
|
59 ch=sig.chans;
|
samer@0
|
60 wr=snk.writer(ch*n);
|
samer@0
|
61 r=@next;
|
samer@0
|
62 function rem=next(x)
|
samer@0
|
63 rem=wr.write(x(:))/ch;
|
samer@0
|
64 end
|
samer@0
|
65 end
|
samer@0
|
66
|
samer@0
|
67 function dispose
|
samer@0
|
68 disposables('dereg',ref);
|
samer@0
|
69 snk.dispose();
|
samer@0
|
70 end
|
samer@0
|
71 end
|
samer@0
|
72 end
|
samer@0
|
73 end
|