function S = receive(dev,fname_rx,period,nonblock) % % Receives the LERA signal % % dev ALSA device structure from alsaSettings.m % T.Hilmer, UH % % 2010.12.15 version 4 % added level control % 2010.12.07 version 3 % changed to function form % 2010.11.17 version 2 % added realtime visual display loop % 2010.11.10 version 1 version = 4; showlevels = false; % special case of nonblock=3 -> use FIFO if nargin < 4 nonblock = false; end if nargin < 3 error('function requires three inputs') end switch dev.device case 'Live' cmd = 'amixer -D hw:CARD=Live set '; warning('move all these settings to alsaSettings.m') % set 0 dB gain on input: f = fields(dev.leveli); stat = false; for n = 1:length(f) [tmp,tmp2] = system([cmd f{n} ' capture ' dev.leveli.(f{n})]);% 2 outputs captures stdout if showlevels disp(tmp2) end stat = stat & tmp; end if stat error('error setting 0 dB gain on ALSA inputs') else disp('ALSA input levels set to 0 dB') end % Master and PCM are needed for regular OS sound. PCM mute has a % real effect on chirp sound. Don't know why. % Mute Playback controls: f = {'Master','PCM','CD','Mic','"Mic Boost (+20dB)"',... 'Video','Phone','"IEC958 Optical Raw"','"PC Speaker"','Aux',... '"External Amplifier"','"SB Live Analog/Digital Output Jack"'}; stat = false; for n = 1:length(f) [tmp,tmp2] = system([cmd f{n} ' mute ']); if showlevels disp(tmp2) end stat = stat & tmp; end if stat error('error muting playback controls') else disp('Muted Playback controls') end % Input/Capture: disp('Unmuting and Selecting ALSA Line') [stat,msg] = system([cmd 'Line cap unmute']); % both must have capture switches toggled on disp('Selecting ALSA Capture') [stat,msg] = system([cmd 'Capture cap']); end %------------------------ % System Variables %------------------------ dname_tmp = '/tmp/lera/'; if exist(dname_tmp,'dir')~=7 mkdir(dname_tmp) end if nargin < 3 || isempty(fname_rx)% probably not archiving data in this case fname_rx = [dname_tmp 'lera_rx_file']; end fname_rx_stat = [dname_tmp 'lera_rx_stat']; %------------------------ %-------------------------------------------------------------------------% % END SETUP / BEGIN FUNCTION %-------------------------------------------------------------------------% %------------------------ % Initialize Input: %------------------------ % Remove existing arecord processes: stat = unix(['pidof arecord']); if ~stat % existing processes found, KILL them [stat,msg] = unix(['killall arecord']); assert(~stat,['error killing arecord: ' msg]) end % chirp FIFO: if nonblock == 3 makeFIFO(fname_rx);% apparently, can't open fifo until input has been connected end % to prevent arecord from overwriting a FIFO, use stdout redirect cmd = sprintf('arecord -v -c %.0f -d %.2f -r %.0f -t raw -f %s -D %s > %s 2> %s',... dev.Nch,period,dev.Fs,dev.dformat,dev.din,fname_rx,fname_rx_stat); % Subsequent calls to fread(fifo) will causes buffer underruns no matter % how tight the loop is. Solution is to reinitialize arecord each time. % Samples are still lost, but only between data takes. disp(['Starting Receive: ' datestr(now)]) disp(cmd) t_start = tic;% tic/toc more accurate than calls to system time; (timer vs. adjusted. see documentation) [pid,msg] = unix([cmd ' & echo $!']);% explicitely get PID assert(~stat,['error executing arecord: ' msg]) % more accurate start time can be had % or with %Z unix(['stat -c %z /proc/' pid '/stat']); % NTP time adjustements to system time will change this....q % Prepare output structure S.t_start = t_start;% output S.rx_file = fname_rx;% input S.rx_stat = fname_rx_stat;% output if nonblock return end %------------------------ % Clean up %------------------------ tmp = period - toc(t_start) + 3; if tmp > 0 disp(sprintf('Pausing Matlab queue for %.1f seconds',tmp)) disp('ONE Ctrl-C will return command prompt without halting Rx') pause(tmp) end if nonblock==3 % FIFO mode [stat,msg] = unix(['rm -f ' fname_rx]); assert(~stat,['error removing chirp FIFO: ' msg]) end unix(['cat ' fname_rx_stat]); [stat,msg] = unix(['grep XRUN ' fname_rx_stat]); assert(logical(stat),'receive had gaps; buffer xruns')