-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathspectrum_analyser.m
132 lines (109 loc) · 4.68 KB
/
spectrum_analyser.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
function [ ] = spectrum_analyser( recDeviceID, chanList)
%SPECTRUM_ANALYSER Uses Playrec to implement a basic spectrum analyser.
%
% spectrum_analyser( recDeviceID, chanList) creates two figures, one
% displaying the spectrum and another the waveform recorded from the
% specified playrec device, recDeviceID, on the channels chanList.
%
% The script runs until either interrupted or both figures are closed.
% Increase these values to ensure output stability (ie resilience to
% glitches) at the expense of a longer latency
pageSize = 2048; %size of each page processed
pageBufCount = 5; %number of pages of buffering
fftSize = pageSize * 2;
Fs = 48000;
runMaxSpeed = false; %When true, the processor is used much more heavily
%(ie always at maximum), but the chance of glitches is
%reduced without increasing latency
if((ndims(chanList)~=2) || (size(chanList, 1)~=1))
error ('chanList must be a row vector');
end
%Test if current initialisation is ok
if(playrec('isInitialised'))
if(playrec('getSampleRate')~=Fs)
fprintf('Changing playrec sample rate from %d to %d\n', playrec('getSampleRate'), Fs);
playrec('reset');
elseif(playrec('getRecDevice')~=recDeviceID)
fprintf('Changing playrec record device from %d to %d\n', playrec('getRecDevice'), recDeviceID);
playrec('reset');
elseif(playrec('getRecMaxChannel')<max(chanList))
fprintf('Resetting playrec to configure device to use more input channels\n');
playrec('reset');
end
end
%Initialise if not initialised
if(~playrec('isInitialised'))
fprintf('Initialising playrec to use sample rate: %d, recDeviceID: %d and no play device\n', Fs, recDeviceID);
playrec('init', Fs, -1, recDeviceID)
end
if(~playrec('isInitialised'))
error ('Unable to initialise playrec correctly');
elseif(playrec('getRecMaxChannel')<max(chanList))
error ('Selected device does not support %d output channels\n', max(chanList));
end
%Clear all previous pages
playrec('delPage');
fftFigure = figure;
fftAxes = axes('parent', fftFigure, 'xlimmode', 'manual', 'ylimmode', 'manual', 'xscale', 'log', 'yscale', 'linear', 'xlim', [10 Fs/2], 'ylim', [-60, 60]);
for i=1:length(chanList)
fftLine(i) = line('XData', (0:(fftSize/2))*Fs/fftSize,'YData', ones(1, fftSize/2 + 1));
end
timeFigure = figure;
timeAxes = axes('parent', timeFigure, 'xlimmode', 'manual', 'ylimmode', 'manual', 'xscale', 'linear', 'yscale', 'linear', 'xlim', [1 pageSize], 'ylim', [-1, 1]);
for i=1:length(chanList)
timeLine(i) = line('XData', 1:pageSize,'YData', ones(1, pageSize));
end
drawnow;
recSampleBuffer = zeros(fftSize, length(chanList));
% Create vector to act as FIFO for page numbers
pageNumList = repmat(-1, [1 pageBufCount]);
firstTimeThrough = true;
while(ishandle(fftFigure) || ishandle(timeFigure))
pageNumList = [pageNumList playrec('rec', pageSize, chanList)];
if(firstTimeThrough)
%This is the first time through so reset the skipped sample count
playrec('resetSkippedSampleCount');
firstTimeThrough = false;
else
if(playrec('getSkippedSampleCount'))
fprintf('%d samples skipped!!\n', playrec('getSkippedSampleCount'));
%return
%Let the code recover and then reset the count
firstTimeThrough = true;
end
end
% runMaxSpeed==true means a very tight while loop is entered until the
% page has completed whereas when runMaxSpeed==false the 'block'
% command in playrec is used. This repeatedly suspends the thread
% until the page has completed, meaning the time between page
% completing and the 'block' command returning can be much longer than
% that with the tight while loop
if(runMaxSpeed)
while(playrec('isFinished', pageNumList(1)) == 0)
end
else
playrec('block', pageNumList(1));
end
lastRecording = playrec('getRec', pageNumList(1));
if(~isempty(lastRecording))
%very basic processing - windowing would produce a better output
recSampleBuffer = [recSampleBuffer(length(lastRecording) + 1:end, :); lastRecording];
recFFT = fft(recSampleBuffer)';
if ishandle(fftFigure)
for i=1:length(chanList)
set(fftLine(i), 'YData', 20*log10(abs(recFFT(i, 1:fftSize/2 + 1))));
end
end
if ishandle(timeFigure)
for i=1:length(chanList)
set(timeLine(i), 'YData', lastRecording(:,i));
end
end
end
drawnow;
playrec('delPage', pageNumList(1));
%pop page number from FIFO
pageNumList = pageNumList(2:end);
end
%delete all pages now loop has finished
playrec('delPage');