samer@46
|
1 % sndstream - file reader implementation using ishara.audio.StreamSource
|
samer@0
|
2 %
|
samer@0
|
3 % sndstream ::
|
samer@0
|
4 % (unit -> (AudioInputStream, unit -> unit)) ~'function to open stream',
|
samer@0
|
5 % (unit -> string) ~'function to create character representation',
|
samer@0
|
6 % options {
|
samer@0
|
7 % channels :: natural/nan ~'desired number of channels';
|
samer@0
|
8 % rate :: nonneg/nan ~'desired sampling rate';
|
samer@0
|
9 % bits :: natural/16 ~'desired bits per sample';
|
samer@0
|
10 % }
|
samer@0
|
11 % -> signal(C,R).
|
samer@0
|
12 %
|
samer@0
|
13 % If channels or rate are not nan, audio format will be converted to match.
|
samer@0
|
14 % If either of them are nan, the corresponding value from the audio file will
|
samer@0
|
15 % be left unchanged.
|
samer@0
|
16
|
samer@0
|
17 classdef sndstream < signal
|
samer@0
|
18 properties (GetAccess=private, SetAccess=immutable)
|
samer@0
|
19 streamfn
|
samer@0
|
20 stringfn
|
samer@0
|
21 format
|
samer@0
|
22 end
|
samer@0
|
23 methods
|
samer@0
|
24 function s=sndstream(streamfn,varargin)
|
samer@37
|
25 opts=options('channels',nan,'rate',nan,'bits',16, ...
|
samer@0
|
26 'stringfn',@()sprintf('sndstream(%s)',tostring(streamfn)), ...
|
samer@0
|
27 varargin{:});
|
samer@0
|
28
|
samer@0
|
29 if any(isnan([opts.channels,opts.rate,opts.bits]))
|
samer@0
|
30 fmt=peek(streamfn);
|
samer@0
|
31 if isnan(opts.channels), opts.channels=fmt.getChannels(); end
|
samer@0
|
32 if isnan(opts.rate), opts.rate=fmt.getSampleRate(); end
|
samer@0
|
33 if isnan(opts.bits), opts.bits=fmt.getSampleSizeInBits(); end
|
samer@0
|
34 end
|
samer@0
|
35 if opts.bits<0
|
samer@0
|
36 error('Cannot determine bits per sample');
|
samer@0
|
37 end
|
samer@0
|
38
|
samer@0
|
39 s.streamfn=streamfn;
|
samer@0
|
40 s.stringfn=opts.stringfn;
|
samer@0
|
41 s.format=audio_format(opts.channels,opts.rate,opts.bits);
|
samer@0
|
42 end
|
samer@0
|
43
|
samer@0
|
44 function s=tostring(sig), s=sig.stringfn(); end
|
samer@0
|
45 function c=channels(s), c=s.format.getChannels(); end
|
samer@0
|
46 function r=rate(s), r=s.format.getSampleRate(); end
|
samer@0
|
47
|
samer@0
|
48 function s=construct(sig)
|
samer@0
|
49 [str,cleanup]=sig.streamfn(false);
|
samer@46
|
50 src=ishara.audio.StreamSource(str,sig.format);
|
samer@0
|
51 ref=disposables('reg',src);
|
samer@0
|
52 s.start = @()src.start();
|
samer@0
|
53 s.stop = @()src.stop();
|
samer@0
|
54 s.reader = @reader;
|
samer@0
|
55 s.dispose = @dispose;
|
samer@0
|
56
|
samer@0
|
57 function r=reader(n)
|
samer@0
|
58 ch=src.getFormat.getChannels();
|
samer@0
|
59 rdr=src.reader(n*ch);
|
samer@0
|
60 r=@next;
|
samer@0
|
61 function [x,rem]=next
|
samer@0
|
62 x=reshape(rdr.next(),ch,n);
|
samer@0
|
63 rem=rdr.unread()/ch;
|
samer@0
|
64 end
|
samer@0
|
65 end
|
samer@0
|
66 function dispose
|
samer@0
|
67 disposables('dereg',ref);
|
samer@0
|
68 src.dispose();
|
samer@0
|
69 cleanup();
|
samer@0
|
70 end
|
samer@0
|
71 end
|
samer@0
|
72 end
|
samer@0
|
73 end
|
samer@0
|
74
|
samer@0
|
75 function fmt=peek(streamfn)
|
samer@0
|
76 [str,cleanup]=streamfn(true);
|
samer@0
|
77 f1=str.getFormat();
|
samer@0
|
78 str.close(); cleanup();
|
samer@0
|
79 ss=f1.getSampleSizeInBits();
|
samer@0
|
80 if ss<0, ss=16; end
|
samer@0
|
81 fmt=audio_format(f1.getChannels(),f1.getSampleRate(),ss);
|
samer@0
|
82 end
|