├── GUI ├── eventScopeR4.fig ├── eventScopeR4.m ├── lfModelDesignerX.fig ├── lfModelDesignerX.m ├── lrTool.png ├── penTool.png ├── pickTool.png ├── realtimeSpectrogramV3.fig ├── realtimeSpectrogramV3.m ├── recordingGUIV7.fig ├── recordingGUIV7.m ├── vtShapeToSoundTestV28.fig ├── vtShapeToSoundTestV28.m ├── vtlDisplay.fig ├── vtlDisplay.m ├── waveletVisualizer.fig └── waveletVisualizer.m ├── LICENSE ├── LICENSE.txt ├── README.md ├── src ├── AAFLFmodelFromF0Trajectory.m ├── AAFLFmodelFromF0Trajectory6T.m ├── AAFjLjmodelFromFOTrajectoryR.m ├── antiAliasedCExponentialSegment.m ├── antiAliasedPolynomialSegmentR.m ├── antialiasedFLmodelSingle.m ├── antialiasedFLmodelSingleR.m ├── closeI2k0xi0.m ├── closeI2kn0.m ├── closeI4.m ├── closeI4k0.m ├── desa2.m ├── designCos6Wavelet.m ├── equalizerDesignAAFX.m ├── generateAALFmodelOut.m ├── generateLFmodelParameter.m ├── license.txt ├── nuttallwin12.m ├── openI5.m ├── openTermk.m ├── perturbationFunction.m ├── perturbationFunction2.m ├── rawFLmodelSingle.m ├── releasenote.txt ├── signal2logArea.m ├── simulatedFilterBank.m ├── sourceByLFmodelAAF.m ├── sourceByLFmodelAAF6T.m ├── stftSpectrogramStructure.m ├── tubeDisplay.m └── vts20150729T011805.mat └── test ├── nuttallwin12self.m ├── testAAFjLjRevfunction.m ├── testJitShimAALF.m ├── testKurtosis.m ├── testRevisedLFmodel.m ├── testWindowingFunctions.m └── testmodal.txt /GUI/eventScopeR4.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/eventScopeR4.fig -------------------------------------------------------------------------------- /GUI/eventScopeR4.m: -------------------------------------------------------------------------------- 1 | function varargout = eventScopeR4(varargin) 2 | % EVENTSCOPER4 MATLAB code for eventScopeR4.fig 3 | % EVENTSCOPER4, by itself, creates a new EVENTSCOPER4 or raises the existing 4 | % singleton*. 5 | % 6 | % H = EVENTSCOPER4 returns the handle to a new EVENTSCOPER4 or the handle to 7 | % the existing singleton*. 8 | % 9 | % EVENTSCOPER4('CALLBACK',hObject,eventData,handles,...) calls the local 10 | % function named CALLBACK in EVENTSCOPER4.M with the given input arguments. 11 | % 12 | % EVENTSCOPER4('Property','Value',...) creates a new EVENTSCOPER4 or raises the 13 | % existing singleton*. Starting from the left, property value pairs are 14 | % applied to the GUI before eventScopeR4_OpeningFcn gets called. An 15 | % unrecognized property name or invalid value makes property application 16 | % stop. All inputs are passed to eventScopeR4_OpeningFcn via varargin. 17 | % 18 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one 19 | % instance to run (singleton)". 20 | % 21 | % See also: GUIDE, GUIDATA, GUIHANDLES 22 | 23 | % Sample program for realtime event detection 24 | % Designed and coded by Hideki Kawahara 25 | % 28/April/2014 26 | % 29/April/2014 slightly cleaned up 27 | % 30/April/2014 further cleaning 28 | % 02/May/2014 f0 display revision 29 | % 31/Aug./2015 machine independent and resizable 30 | % 31 | % Comment: 32 | % Timer structure used in this routine can be a bad practice. 33 | % This tool will be redesigned completely. 34 | 35 | % This work is licensed under the Creative Commons 36 | % Attribution 4.0 International License. 37 | % To view a copy of this license, visit 38 | % http://creativecommons.org/licenses/by/4.0/. 39 | 40 | % Edit the above text to modify the response to help eventScopeR4 41 | 42 | % Last Modified by GUIDE v2.5 02-May-2014 10:27:55 43 | 44 | % Begin initialization code - DO NOT EDIT 45 | gui_Singleton = 1; 46 | gui_State = struct('gui_Name', mfilename, ... 47 | 'gui_Singleton', gui_Singleton, ... 48 | 'gui_OpeningFcn', @eventScopeR4_OpeningFcn, ... 49 | 'gui_OutputFcn', @eventScopeR4_OutputFcn, ... 50 | 'gui_LayoutFcn', [] , ... 51 | 'gui_Callback', []); 52 | if nargin && ischar(varargin{1}) 53 | gui_State.gui_Callback = str2func(varargin{1}); 54 | end 55 | 56 | if nargout 57 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 58 | else 59 | gui_mainfcn(gui_State, varargin{:}); 60 | end 61 | % End initialization code - DO NOT EDIT 62 | end 63 | 64 | % --- Executes just before eventScopeR4 is made visible. 65 | function eventScopeR4_OpeningFcn(hObject, eventdata, handles, varargin) 66 | % This function has no output args, see OutputFcn. 67 | % hObject handle to figure 68 | % eventdata reserved - to be defined in a future version of MATLAB 69 | % handles structure with handles and user data (see GUIDATA) 70 | % varargin command line arguments to eventScopeR4 (see VARARGIN) 71 | 72 | % Choose default command line output for eventScopeR4 73 | handles.output = hObject; 74 | myGUIdata = guidata(hObject); 75 | myGUIdata.samplingFrequency = 44100; 76 | timerEventInterval = 0.050; % in second 77 | myGUIdata.timerEventInterval = timerEventInterval; 78 | guidata(hObject, myGUIdata); 79 | myGUIdata = initializeDisplay(myGUIdata); 80 | timer50ms = timer('TimerFcn',@synchDrawGUI, 'Period',timerEventInterval,'ExecutionMode','fixedRate', ... 81 | 'userData',handles.eventScopeGUI); 82 | myGUIdata.timer50ms = timer50ms; 83 | timerForWaveDraw = timer('TimerFcn',@waveDrawServer,'ExecutionMode','singleShot', ... 84 | 'userData',handles.eventScopeGUI); 85 | myGUIdata.timerForWaveDraw = timerForWaveDraw; 86 | %spectrumBarServer 87 | timerForSpectrumBar = timer('TimerFcn',@spectrumBarServer,'ExecutionMode','singleShot', ... 88 | 'userData',handles.eventScopeGUI); 89 | myGUIdata.timerForSpectrumBar = timerForSpectrumBar; 90 | timerForKurtosisBar = timer('TimerFcn',@kurtosisBarServer,'ExecutionMode','singleShot', ... 91 | 'userData',handles.eventScopeGUI); 92 | myGUIdata.timerForKurtosisBar = timerForKurtosisBar; 93 | %fineF0Server 94 | timerForFineF0 = timer('TimerFcn',@fineF0Server,'ExecutionMode','singleShot', ... 95 | 'userData',handles.eventScopeGUI); 96 | myGUIdata.timerForFineF0 = timerForFineF0; 97 | myGUIdata.recordObj1 = audiorecorder(myGUIdata.samplingFrequency,24,1); 98 | set(myGUIdata.recordObj1,'TimerPeriod',0.2); 99 | record(myGUIdata.recordObj1); 100 | myGUIdata.maxAudioRecorderCount = myGUIdata.maxTargetPoint; 101 | 102 | myGUIdata.maxLevel = -100; 103 | myGUIdata.lastLevel = 0; 104 | myGUIdata.lastLastLevel = 0; 105 | myGUIdata.jumpLimit = 10; 106 | myGUIdata.output = hObject; 107 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 108 | 109 | % Update handles structure 110 | guidata(hObject, myGUIdata); 111 | myGUIdata = startRealtime(myGUIdata); 112 | myGUIdata.startTime = datevec(now); 113 | guidata(hObject, myGUIdata); 114 | % UIWAIT makes eventScopeR4 wait for user response (see UIRESUME) 115 | % uiwait(handles.eventScopeGUI); 116 | end 117 | 118 | % --- private function 119 | function myGUIdata = startRealtime(myGUIdata) 120 | switch get(myGUIdata.timer50ms,'running') 121 | case 'on' 122 | stop(myGUIdata.timer50ms); 123 | end 124 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 125 | myGUIdata.lastPosition = 1; 126 | record(myGUIdata.recordObj1); 127 | switch get(myGUIdata.timer50ms,'running') 128 | case 'off' 129 | start(myGUIdata.timer50ms); 130 | case 'on' 131 | otherwise 132 | disp('timer is bloken!'); 133 | end 134 | set(myGUIdata.periodicHandle,'ydata',myGUIdata.tAxis+NaN); 135 | set(myGUIdata.peakyHandle,'ydata',myGUIdata.tAxis+NaN); 136 | %myGUIdata.peakyData = myGUIdata.tAxis+NaN; 137 | set(myGUIdata.onsetHandle,'ydata',myGUIdata.tAxis+NaN); 138 | %myGUIdata.onsetData = myGUIdata.tAxis+NaN; 139 | set(myGUIdata.powerHandle,'ydata',myGUIdata.tAxis+NaN); 140 | set(myGUIdata.noteHandle,'ydata',myGUIdata.tAxis*0+NaN); 141 | set(myGUIdata.stopButton,'enable','on'); 142 | set(myGUIdata.startButton,'enable','off'); 143 | myGUIdata.countStarted = false; 144 | end 145 | 146 | % --- private function 147 | function myGUIdata = initializeDisplay(myGUIdata) 148 | axes(myGUIdata.waveformViewerAxis); 149 | myGUIdata.viewWidth = 0.035; 150 | tx = 0:floor(myGUIdata.samplingFrequency*myGUIdata.viewWidth); 151 | myGUIdata.waveHandle = plot(tx,randn(length(tx),1),'linewidth',2); 152 | set(gca,'xlim',[tx(1) tx(end)]); 153 | axis('off') 154 | myGUIdata.maxTargetPoint = 200;%500; 155 | %-------------- 156 | axes(myGUIdata.spectrumBarAxis); 157 | fs = myGUIdata.samplingFrequency; 158 | baseChannelFrequency = 20; 159 | myGUIdata.centerFrequencyList = baseChannelFrequency*2.0.^(0:1/3:log2(fs/2/baseChannelFrequency*2^(-1/6)))'; 160 | myGUIdata.fLow = myGUIdata.centerFrequencyList*2^(-1/6); 161 | myGUIdata.fHigh = myGUIdata.centerFrequencyList*2^(1/6); 162 | myGUIdata.channelID = 1:length(myGUIdata.centerFrequencyList); 163 | myGUIdata.barHandle = bar(myGUIdata.channelID,80*rand(length(myGUIdata.centerFrequencyList),1),'facecolor',[0.3 0.3 1]); 164 | myGUIdata.tickList = [20 30 40 50 60 70 80 90 100 200 300 400 500 600 700 800 900 1000 ... 165 | 2000 3000 4000 5000 6000 7000 8000 9000 10000]; 166 | myGUIdata.tickLabel = {'02';'03';' ';'05';' ';'07';' ';' ';'.1';'.2';'.3';' ';'.5';' ';'.7';' ';' ';'1'; ... 167 | '2';'3';' ';'5';' ';'7';' ';' ';'10'}; 168 | myGUIdata.tickocation = interp1(myGUIdata.centerFrequencyList,myGUIdata.channelID,myGUIdata.tickList); 169 | set(myGUIdata.barHandle,'BarWidth',1); 170 | grid on; 171 | xlabel('frequency (kHz)'); 172 | ylabel('level (dB)'); 173 | set(myGUIdata.spectrumBarAxis,'ylim',[0 90]); 174 | %hold on;plot([20 fs/2],0*[1 1],'k','linewidth',2);hold off 175 | set(myGUIdata.spectrumBarAxis,'xlim',[0.5 myGUIdata.channelID(end)+0.5]); 176 | set(myGUIdata.spectrumBarAxis,'xtick',myGUIdata.tickocation,'xtickLabel',myGUIdata.tickLabel); 177 | ytick = 0:10:90; 178 | ytickLabel = {'-90';'-80';'-70';'-60';'-50';'-40';'-30';'-20';'-10';'0'}; 179 | set(myGUIdata.spectrumBarAxis,'ytick',ytick,'ytickLabel',ytickLabel); 180 | myGUIdata.windowLength = 0.04; 181 | myGUIdata.windowSizeInSample = round(myGUIdata.windowLength*fs); 182 | w = blackman(myGUIdata.windowSizeInSample); 183 | myGUIdata.window = w/sqrt(sum(w.^2)); 184 | myGUIdata.fftl = 2^ceil(log2(myGUIdata.windowSizeInSample)); 185 | myGUIdata.fAxis = (0:myGUIdata.fftl-1)'/myGUIdata.fftl*fs; 186 | wTmp = real(ifft(abs(fft(w,myGUIdata.fftl)).^2)); 187 | fAxisDFT = myGUIdata.fAxis; 188 | fAxisDFT(fAxisDFT>fs/2) = fAxisDFT(fAxisDFT>fs/2)-fs; 189 | myGUIdata.baseBandLimit = 3000; 190 | myGUIdata.shaper = 0.5+0.5*cos(pi*fAxisDFT/myGUIdata.baseBandLimit); 191 | myGUIdata.shaper(abs(fAxisDFT)>myGUIdata.baseBandLimit) = 0; 192 | %myGUIdata.shaper = myGUIdata.shaper; 193 | myGUIdata.lagwindow = (wTmp/wTmp(1)).^(0.8); 194 | myGUIdata.lagAxis = (0:myGUIdata.fftl-1)/fs; 195 | %-------------------- 196 | axes(myGUIdata.parameterViewerAxis); 197 | myGUIdata.tAxis = (0:myGUIdata.maxTargetPoint-1)*myGUIdata.timerEventInterval; 198 | myGUIdata.periodicHandle = plot(myGUIdata.tAxis,myGUIdata.tAxis*0+1,'color',[0 0.8 0],'linewidth',7); 199 | hold on 200 | myGUIdata.peakyHandle = plot(myGUIdata.tAxis,myGUIdata.tAxis*0+2,'m','linewidth',7); 201 | myGUIdata.onsetHandle = plot(myGUIdata.tAxis,myGUIdata.tAxis*0+1.5,'r','linewidth',7); 202 | myGUIdata.powerHandle = plot(myGUIdata.tAxis,myGUIdata.tAxis*0+3,'b','linewidth',2); 203 | set(myGUIdata.parameterViewerAxis,'ylim',[0.5 5],'xlim',[0 myGUIdata.tAxis(end)]); 204 | set(myGUIdata.parameterViewerAxis,'ytick',[1 1.5 2 3],'ytickLabel',{'periodic';'onset';'peaky';'level'}); 205 | set(myGUIdata.parameterViewerAxis,'xticklabel',[]); 206 | grid on; 207 | hold off; 208 | %--------------------- 209 | axes(myGUIdata.kurtosisBarAxis); 210 | myGUIdata.kurtosisBarHandle = bar(1,3,'m');grid on; 211 | myGUIdata.kurtosisLimit = 40; 212 | set(myGUIdata.kurtosisBarAxis,'ylim',[1 myGUIdata.kurtosisLimit],'xtick',[]); 213 | xlabel('kurtosis') 214 | set(myGUIdata.kurtosisBarAxis,'yscale','log'); 215 | ytick = [1:10 20:10:100]; 216 | ytickLabel = {'1';'2';'3';' ';'5';' ';'7';' ';' ';'10';... 217 | '20';'30';'40';'50';' ';' ';' ';' ';'100';}; 218 | set(myGUIdata.kurtosisBarAxis,'ytick',ytick,'ytickLabel',ytickLabel); 219 | set(myGUIdata.kurtosisBarHandle,'BarWidth',1) 220 | w = blackman(31); 221 | ww = w/sum(w); 222 | ww(16) = ww(16)-1; 223 | myGUIdata.kurtosisHPF = -ww; 224 | %--------------------- 225 | axes(myGUIdata.powerBarAxis); 226 | myGUIdata.totalPowerBarHandle = bar(1,-80,'b');grid on; 227 | set(myGUIdata.powerBarAxis,'ylim',[0 90],'xtick',[]); 228 | xlabel('power'); 229 | ylabel('level (dB)') 230 | set(myGUIdata.powerBarAxis,'ytick',[0:10:90],'ytickLabel',... 231 | {'-90';'-80';'-70';'-60';'-50';'-40';'-30';'-20';'-10';'0'}); 232 | set(myGUIdata.totalPowerBarHandle,'BarWidth',1) 233 | %--------------------- 234 | axes(myGUIdata.periodicityBarAxis); 235 | myGUIdata.periodicityBarHandle = bar(1,0.5,'g');grid on; 236 | set(myGUIdata.periodicityBarAxis,'ylim',[0 1],'xtick',[],'ytick',0:0.1:1); 237 | xlabel('max.corr.'); 238 | set(myGUIdata.periodicityBarHandle,'BarWidth',1) 239 | %--------------------- 240 | %noteAxis 241 | myGUIdata.noteID = (-7:27+7)'; 242 | %110*2.0.^((-2:27)/12); 243 | myGUIdata.noteName = {'D2';' ';'E2';'F2';' ';'G2';' ';'A2';' ';'H2';'C3';' ';'D3';' ';'E3';'F3';' ';'G3';' ';'A3'; ... 244 | ' ';'H3';'C4';' ';'D4';' ';'E4';' ';'F4';'G4';' ';'A4';' ';'H4';'C5' ... 245 | ;' ';'D5';' ';'E5';'F5';' ';'G5'}; 246 | axes(myGUIdata.noteAxis); 247 | myGUIdata = initializeForFineF0(myGUIdata); 248 | hold on; 249 | myGUIdata.SecondNoteHandle = plot(myGUIdata.tAxis,myGUIdata.tAxis*0,'s','markersize',5, ... 250 | 'markerfacecolor',[0.5 0.8 0.5],'markeredgecolor',[0.5 0.8 0.5]); 251 | myGUIdata.noteHandle = plot(myGUIdata.tAxis,myGUIdata.tAxis*0,'s','markersize',7, ... 252 | 'markerfacecolor',[0 0.8 0],'markeredgecolor',[0 0.8 0]); 253 | frequencyTick = [40 50 60 70 80 90 100 150 200 300 400 500 600 700 800 900 1000]; 254 | frequencyBase = 10:10:2000; 255 | hold off 256 | myGUIdata.freqtickLocation = interp1(frequencyBase,12*log2(frequencyBase/110),frequencyTick); 257 | myGUIdata.freqTickLabel = {'40';'50';'60';'70';'80';'90';'100';'150';'200';'300';'400';'500';'600';'700';'800';'900';'1000';}; 258 | set(myGUIdata.noteAxis,'ytick',myGUIdata.noteID,'ytickLabel',myGUIdata.noteName); 259 | set(myGUIdata.SecondNoteHandle,'ydata',myGUIdata.tAxis*0+NaN); 260 | set(myGUIdata.noteHandle,'ydata',myGUIdata.tAxis*0+NaN); 261 | grid on; 262 | set(myGUIdata.noteAxis,'ylim',[myGUIdata.noteID(1) myGUIdata.noteID(end)+1],'xlim',[0 myGUIdata.tAxis(end)]); 263 | %--------------------- 264 | axes(myGUIdata.colorPadAxis); 265 | tcmx = zeros(30,10,3); 266 | tcmx(4:27,3:8,:) = 1; 267 | myGUIdata.baseTrueColor = tcmx; 268 | myGUIdata.colorPadHandle = image(tcmx); 269 | axis('off') 270 | set(myGUIdata.fpsText,'string','20.0 fps'); 271 | %--------------------- 272 | set(myGUIdata.noteRadioButton,'userdata',myGUIdata,'enable','on'); 273 | set(myGUIdata.freqRadioButton,'userdata',myGUIdata,'enable','on'); 274 | set(myGUIdata.axisModePanel,'userdata',myGUIdata,'SelectionChangeFcn',@modeRadioButterServer); 275 | set(myGUIdata.saveFileButton,'enable','off'); 276 | end 277 | 278 | function myGUIdata = initializeForFineF0(myGUIdata) 279 | fs = myGUIdata.samplingFrequency; 280 | myGUIdata.fineFrameShift = 0.010; 281 | myGUIdata.fineTimeAxis = 0:myGUIdata.fineFrameShift:myGUIdata.tAxis(end); 282 | myGUIdata.fineF0Handle = plot(myGUIdata.fineTimeAxis,myGUIdata.fineTimeAxis*0,'s','markersize',5, ... 283 | 'markerfacecolor',[0 0.7 0],'markeredgecolor',[0 0.7 0]); 284 | hold on 285 | %myGUIdata.fine2ndF0Handle = plot(myGUIdata.fineTimeAxis,myGUIdata.fineTimeAxis*0,'s','markersize',3, ... 286 | % 'markerfacecolor',[0.4 0.9 0.4],'markeredgecolor',[0.4 0.9 0.4]); 287 | hold off 288 | set(myGUIdata.fineF0Handle,'ydata',myGUIdata.fineTimeAxis*0+NaN); 289 | %set(myGUIdata.fine2ndF0Handle,'ydata',myGUIdata.fineTimeAxis*0+NaN); 290 | frameShift = 0.010; % 10ms 291 | frameLength = 0.046; % 40ms 292 | narrowWindow = 0.004; % 10ms 293 | fsb4 = fs/4; 294 | windowLengthInSample = round(frameLength*fsb4/2)*2+1; % always odd number 295 | baseIndex = (-round(frameLength*fsb4/2):round(frameLength*fsb4/2))'; 296 | fftl = 2^ceil(log2(windowLengthInSample)); 297 | w = hanning(windowLengthInSample); 298 | x = randn(round(myGUIdata.tAxis(end)*fs),1); 299 | %xb4 = x(1:4:end); 300 | narrowWindow = hanning(round(narrowWindow*fsb4/2)*2+1); 301 | lagNarrowWindow = conv(narrowWindow,narrowWindow); 302 | halfNarrorLength = round((length(lagNarrowWindow)-1)/2); 303 | lagWindowForDFT = zeros(fftl,1); 304 | lagWindowForDFT(1:halfNarrorLength+1) = lagNarrowWindow(halfNarrorLength+1:end); 305 | lagWindowForDFT(fftl:-1:fftl-halfNarrorLength+1) = lagNarrowWindow(halfNarrorLength+2:end); 306 | fx = (0:fftl-1)/fftl*fsb4; 307 | fx(fx>fsb4/2) = fx(fx>fsb4/2)-fsb4; 308 | hanningLPF = (0.5+0.5*cos(pi*fx(:)/2000)).^2; 309 | hanningLPF(abs(fx)>2000) = 0; 310 | wConv = conv(w,w); 311 | [centerValue,centerIndex] = max(wConv); 312 | mainLagWindow = zeros(fftl,1); 313 | mainLagWindow(1:fftl/2) = wConv(centerIndex+(1:fftl/2)-1); 314 | mainLagWindow(fftl:-1:fftl/2+1) = wConv(centerIndex+(1:fftl/2)); 315 | mainLagWindow = mainLagWindow.^0.7; % ad hoc 316 | mainLagWindow(1:10) = mainLagWindow(1:10)*10; 317 | mainLagWindow(end:-1:end-9) = mainLagWindow(end:-1:end-9)*10; 318 | 319 | tickLocations = 0:frameShift:(length(x)-1)/fs; 320 | normalizedAcGram = zeros(fftl,length(tickLocations)); 321 | %-------- 322 | myGUIdata.frameShiftb4 = frameShift; 323 | myGUIdata.frameLengthb4 = frameLength; 324 | myGUIdata.windowLengthInSampleb4 = windowLengthInSample; 325 | myGUIdata.fsb4 = fsb4; 326 | myGUIdata.baseIndexb4 = baseIndex; 327 | myGUIdata.tickLocationsb4 = tickLocations; 328 | myGUIdata.tickIndexb4 = (1:length(tickLocations))'; 329 | myGUIdata.fftlb4 = fftl; 330 | myGUIdata.wb4 = w; 331 | myGUIdata.hanningLPFb4 = hanningLPF; 332 | myGUIdata.lagWindowForDFTb4 = lagWindowForDFT; 333 | myGUIdata.mainLagWindowb4 = mainLagWindow; 334 | myGUIdata.normalizedAcGram = normalizedAcGram; 335 | myGUIdata.countStarted = false; 336 | %myGUIdata.tickB4ID = 0; 337 | %myGUIdata 338 | end 339 | % xSegment = xb4(max(1,min(length(xb4),baseIndex+round(tickLocations(ii)*fsb4)))); 340 | % pw = abs(fft(xSegment.*w,fftl)).^2; 341 | % ac = real(ifft(pw)); 342 | % normalizedPw = hanningLPF.*pw./fft(ac.*lagWindowForDFT); 343 | % normalizedAc = real(ifft(normalizedPw))./mainLagWindow; 344 | % mormalizedAcGram(:,ii) = normalizedAc/normalizedAc(1)/10; 345 | 346 | function fineF0Server(obj, event, string_arg) 347 | handleForTimer = get(obj,'userData'); 348 | myGUIdata = guidata(handleForTimer); 349 | fs = myGUIdata.samplingFrequency; 350 | bias = round(myGUIdata.frameLengthb4/2*myGUIdata.fsb4); 351 | %myGUIdata.tickB4ID = myGUIdata.tickB4ID+1; 352 | %x = myGUIdata.tmpAudio; 353 | tmpIndex = length(myGUIdata.tmpAudio)-(round(myGUIdata.frameLengthb4*fs)+1+round(myGUIdata.frameShiftb4*fs*5)):length(myGUIdata.tmpAudio); 354 | if length(tmpIndex) > myGUIdata.windowLengthInSampleb4 355 | x = myGUIdata.tmpAudio(max(1,tmpIndex)); 356 | currentIndex = myGUIdata.maxTargetPoint-myGUIdata.audioRecorderCount; 357 | if currentIndex > 0 358 | xb4 = x(1:4:end); 359 | t0 = 1/myGUIdata.fsb4; 360 | ydata = get(myGUIdata.fineF0Handle,'ydata'); 361 | %ydata2nd = get(myGUIdata.fine2ndF0Handle,'ydata'); 362 | if 1 == 1 363 | for ii = 1:5 364 | xSegment = xb4(max(1,min(length(xb4),bias+myGUIdata.baseIndexb4+round(myGUIdata.frameShiftb4*(ii-1)*myGUIdata.fsb4)))); 365 | pw = abs(fft(xSegment.*myGUIdata.wb4,myGUIdata.fftlb4)).^2; 366 | ac = real(ifft(pw)); 367 | normalizedPw = myGUIdata.hanningLPFb4.*pw./fft(ac.*myGUIdata.lagWindowForDFTb4); 368 | normalizedAc = real(ifft(normalizedPw))./myGUIdata.mainLagWindowb4; 369 | normalizedAc = normalizedAc/normalizedAc(1)/10; 370 | %[peakLevel,maxpos] = max(normalizedAc(1:150)); 371 | %bestLag = (peakIdx-1)*t0; 372 | [peakLevel,maxpos] = max(normalizedAc(1:150)); 373 | maxpos = max(2,maxpos); 374 | bestLag = (0.5*(normalizedAc(maxpos-1)-normalizedAc(maxpos+1))/ ... 375 | (normalizedAc(maxpos-1)+normalizedAc(maxpos+1)-2*normalizedAc(maxpos))+maxpos-1)*t0; 376 | notePosition = max(-7,min(myGUIdata.noteID(end)+1,(12*log2(1/bestLag/110)))); 377 | if peakLevel > 0.55 378 | ydata(min(length(ydata),ii+(currentIndex-1)*5)) = notePosition; 379 | else 380 | %ydata2nd(min(length(ydata),ii+(currentIndex-1)*5)) = notePosition; 381 | end; 382 | end; 383 | %disp(num2str(peakLevel)) 384 | set(myGUIdata.fineF0Handle,'ydata',ydata); 385 | %set(myGUIdata.fine2ndF0Handle,'ydata',ydata2nd); 386 | end; 387 | end; 388 | end; 389 | end 390 | 391 | function modeRadioButterServer(obj, event, string_arg) 392 | myGUIdata = get(obj,'userdata'); 393 | %disp('selection changed'); 394 | switch get(myGUIdata.noteRadioButton,'value') 395 | case 1 396 | set(myGUIdata.noteAxis,'ytick',myGUIdata.noteID,'ytickLabel',myGUIdata.noteName); 397 | otherwise 398 | set(myGUIdata.noteAxis,'ytick',myGUIdata.freqtickLocation,'ytickLabel',myGUIdata.freqTickLabel); 399 | end 400 | end 401 | 402 | % --- private function 403 | function synchDrawGUI(obj, event, string_arg) 404 | handleForTimer = get(obj,'userData'); 405 | myGUIdata = guidata(handleForTimer); 406 | fftl = myGUIdata.fftl; 407 | numberOfSamples = fftl*6; 408 | if get(myGUIdata.recordObj1,'TotalSamples') > numberOfSamples 409 | myGUIdata.tmpAudio = getaudiodata(myGUIdata.recordObj1); 410 | guidata(handleForTimer,myGUIdata); 411 | switch get(myGUIdata.timerForWaveDraw,'running') 412 | case 'off' 413 | start(myGUIdata.timerForWaveDraw); 414 | end; 415 | switch get(myGUIdata.timerForKurtosisBar,'running') 416 | case 'off' 417 | start(myGUIdata.timerForKurtosisBar); 418 | end; 419 | %timerForFineF0 420 | switch get(myGUIdata.timerForFineF0,'running') 421 | case 'off' 422 | start(myGUIdata.timerForFineF0); 423 | end; 424 | switch get(myGUIdata.timerForSpectrumBar,'running') 425 | case 'off' 426 | start(myGUIdata.timerForSpectrumBar); 427 | end; 428 | if myGUIdata.audioRecorderCount < 0 429 | fps = (myGUIdata.maxAudioRecorderCount+1)/etime(datevec(now),myGUIdata.startTime); 430 | switch get(myGUIdata.timer50ms,'running') 431 | case 'on' 432 | stop(myGUIdata.timer50ms); 433 | end 434 | stop(myGUIdata.recordObj1); 435 | set(myGUIdata.fpsText,'string',[num2str(fps,'%02.1f') ' fps']); 436 | set(myGUIdata.periodicHandle,'ydata',myGUIdata.tAxis+NaN); 437 | set(myGUIdata.peakyHandle,'ydata',myGUIdata.tAxis+NaN); 438 | %myGUIdata.peakyData = myGUIdata.tAxis+NaN; 439 | set(myGUIdata.onsetHandle,'ydata',myGUIdata.tAxis+NaN); 440 | %myGUIdata.onsetData = myGUIdata.tAxis+NaN; 441 | set(myGUIdata.powerHandle,'ydata',myGUIdata.tAxis+NaN); 442 | set(myGUIdata.noteHandle,'ydata',myGUIdata.tAxis*0+NaN); 443 | set(myGUIdata.fineF0Handle,'ydata',myGUIdata.fineTimeAxis*0+NaN); 444 | %set(myGUIdata.fine2ndF0Handle,'ydata',myGUIdata.fineTimeAxis*0+NaN); 445 | record(myGUIdata.recordObj1); 446 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 447 | switch get(myGUIdata.timer50ms,'running') 448 | case 'off' 449 | start(myGUIdata.timer50ms); 450 | end 451 | myGUIdata.countStarted = false; 452 | else 453 | if ~myGUIdata.countStarted 454 | myGUIdata.countStarted = true; 455 | myGUIdata.startTime = datevec(now); 456 | end; 457 | %set(myGUIdata.peakyHandle,'ydata',myGUIdata.peakyData); 458 | %set(myGUIdata.onsetHandle,'ydata',myGUIdata.onsetData); 459 | set(myGUIdata.countText,'String',num2str(myGUIdata.audioRecorderCount)); 460 | myGUIdata.audioRecorderCount = myGUIdata.audioRecorderCount-1; 461 | x = myGUIdata.tmpAudio(end-myGUIdata.windowSizeInSample+1:end); 462 | rawPower = abs(fft(x.*myGUIdata.window,myGUIdata.fftl)).^2/myGUIdata.fftl; 463 | %cumulatedPower = cumsum(rawPmower); 464 | myGUIdata.lastLastLevel = myGUIdata.lastLevel; 465 | myGUIdata.lastLevel = 10*log10(sum(rawPower)); 466 | end; 467 | end; 468 | %drawnow 469 | peakyData = get(myGUIdata.peakyHandle,'ydata'); 470 | onsetData = get(myGUIdata.onsetHandle,'ydata'); 471 | guidata(handleForTimer,myGUIdata); 472 | %drawnow; 473 | end 474 | 475 | function waveDrawServer(obj, event, string_arg) 476 | handleForTimer = get(obj,'userData'); 477 | myGUIdata = guidata(handleForTimer); 478 | xdata = get(myGUIdata.waveHandle,'xdata'); 479 | ydata = myGUIdata.tmpAudio(end-length(xdata)+1:end); 480 | set(myGUIdata.waveHandle,'ydata',ydata); 481 | set(myGUIdata.waveformViewerAxis,'ylim',max(abs(ydata))*[-1 1]); 482 | end 483 | 484 | function kurtosisBarServer(obj, event, string_arg) 485 | handleForTimer = get(obj,'userData'); 486 | myGUIdata = guidata(handleForTimer); 487 | x = myGUIdata.tmpAudio(end-(myGUIdata.windowSizeInSample+length(myGUIdata.kurtosisHPF))+1:end); 488 | xx = fftfilt(myGUIdata.kurtosisHPF,x); 489 | xx = xx(length(myGUIdata.kurtosisHPF):end); 490 | kutrosisValue = mean(xx.^4)/mean(xx.^2)^2; 491 | set(myGUIdata.kurtosisBarHandle,'ydata',max(0,min(myGUIdata.kurtosisLimit,kutrosisValue))); 492 | ydataPeaky = get(myGUIdata.peakyHandle,'ydata'); 493 | currentIndex = myGUIdata.maxTargetPoint-myGUIdata.audioRecorderCount; 494 | if kutrosisValue > 5.9; % p < 10^(-4) for exp. dist (3.7 % p < 10^(-5) for normal distribution) 495 | ydataPeaky(max(1,min(myGUIdata.maxTargetPoint,currentIndex))) = 2; 496 | %myGUIdata.peakyData(max(1,min(myGUIdata.maxTargetPoint,currentIndex))) = 2; 497 | set(myGUIdata.kurtosisBarHandle,'facecolor','m'); 498 | set(myGUIdata.peakyHandle,'ydata',ydataPeaky); 499 | else 500 | set(myGUIdata.kurtosisBarHandle,'facecolor',[0.6 0 0.6]); 501 | end; 502 | set(myGUIdata.totalPowerBarHandle,'ydata',max(0,min(90,90+20*log10(std(x))))); 503 | %guidata(handleForTimer,myGUIdata); 504 | end 505 | 506 | function spectrumBarServer(obj, event, string_arg) 507 | handleForTimer = get(obj,'userData'); 508 | myGUIdata = guidata(handleForTimer); 509 | x = myGUIdata.tmpAudio(end-myGUIdata.windowSizeInSample+1:end); 510 | rawPower = abs(fft(x.*myGUIdata.window,myGUIdata.fftl)).^2/myGUIdata.fftl; 511 | cumulatedPower = cumsum(rawPower); 512 | powerH = interp1(myGUIdata.fAxis,cumulatedPower,myGUIdata.fHigh); 513 | powerL = interp1(myGUIdata.fAxis,cumulatedPower,myGUIdata.fLow); 514 | bandPower = (powerH-powerL)/cumulatedPower(end)*2*std(x)^2; 515 | ydata = max(0,min(90,90+10*log10(bandPower))); 516 | set(myGUIdata.barHandle,'ydata',ydata); 517 | ydataPower = get(myGUIdata.powerHandle,'ydata'); 518 | currentIndex = myGUIdata.maxTargetPoint-myGUIdata.audioRecorderCount; 519 | ydataPower(max(1,min(myGUIdata.maxTargetPoint,currentIndex))) = ... 520 | 3+max(0,min(2,1.5+2.5/80*10*log10(cumulatedPower(end)))); 521 | set(myGUIdata.powerHandle,'ydata',ydataPower); 522 | if myGUIdata.lastLevel+myGUIdata.jumpLimit < 10*log10(cumulatedPower(end)) 523 | ydataOnset = get(myGUIdata.onsetHandle,'ydata'); 524 | ydataOnset(max(1,min(myGUIdata.maxTargetPoint,currentIndex))) = 1.5; 525 | set(myGUIdata.totalPowerBarHandle,'facecolor','r'); 526 | set(myGUIdata.onsetHandle,'ydata',ydataOnset); 527 | elseif (myGUIdata.lastLastLevel+myGUIdata.jumpLimit < 10*log10(cumulatedPower(end))) 528 | %ydataOnset = get(myGUIdata.onsetHandle,'ydata'); 529 | %ydataOnset = myGUIdata.onsetData; 530 | ydataOnset = get(myGUIdata.onsetHandle,'ydata'); 531 | %if isnan(ydataOnset(max(1,min(myGUIdata.maxTargetPoint,currentIndex-1)))) 532 | ydataOnset(max(1,min(myGUIdata.maxTargetPoint,currentIndex-1))) = 1.5; 533 | %myGUIdata.onsetData = ydataOnset; 534 | set(myGUIdata.totalPowerBarHandle,'facecolor','r'); 535 | set(myGUIdata.onsetHandle,'ydata',ydataOnset); 536 | %end; 537 | else 538 | set(myGUIdata.totalPowerBarHandle,'facecolor','b'); 539 | end; 540 | modifiedAutoCorrelation = real(ifft(rawPower.*myGUIdata.shaper)); 541 | modifiedAutoCorrelation = modifiedAutoCorrelation/modifiedAutoCorrelation(1); 542 | modifiedAutoCorrelation = modifiedAutoCorrelation./myGUIdata.lagwindow; 543 | [maxModifiedAutoCorrelation,lagIDx] = max(modifiedAutoCorrelation((myGUIdata.lagAxis>0.0005) & (myGUIdata.lagAxis<0.014))); 544 | %truncatedLag = myGUIdata.lagAxis((myGUIdata.lagAxis>0.0005) & (myGUIdata.lagAxis<0.014)); 545 | %bestLag = truncatedLag(lagIDx); 546 | set(myGUIdata.periodicityBarHandle,'ydata',maxModifiedAutoCorrelation); 547 | if maxModifiedAutoCorrelation > 0.8%0.75 548 | ydataPeriod = get(myGUIdata.periodicHandle,'ydata'); 549 | ydataPeriod(max(1,min(myGUIdata.maxTargetPoint,currentIndex))) = 1; 550 | set(myGUIdata.periodicHandle,'ydata',ydataPeriod); 551 | %notePosition = max(-7,min(myGUIdata.noteID(end)+1,(12*log2(1/bestLag/110)))); 552 | %ydataNote = get(myGUIdata.noteHandle,'ydata'); 553 | %if notePosition < myGUIdata.noteID(end)+1 554 | % ydataNote(max(1,min(myGUIdata.maxTargetPoint,currentIndex))) = notePosition; 555 | %end; 556 | %set(myGUIdata.noteHandle,'ydata',ydataNote); 557 | set(myGUIdata.periodicityBarHandle,'facecolor','g'); 558 | else 559 | set(myGUIdata.periodicityBarHandle,'facecolor',[0 0.6 0]); 560 | end; 561 | cdata = myGUIdata.baseTrueColor; 562 | rgbList = [sum(bandPower(1:20)) sum(bandPower(18:26)) sum(bandPower(25:end))]; 563 | rgbList = rgbList/max(rgbList); 564 | cdata(:,:,1) = cdata(:,:,1)*rgbList(1); 565 | cdata(:,:,2) = cdata(:,:,2)*rgbList(2); 566 | cdata(:,:,3) = cdata(:,:,3)*rgbList(3); 567 | set(myGUIdata.colorPadHandle,'cdata',cdata); 568 | if 1 == 2 569 | myGUIdata.lastLastLevel = myGUIdata.lastLevel; 570 | myGUIdata.lastLevel = 10*log10(cumulatedPower(end)); 571 | guidata(handleForTimer,myGUIdata); 572 | end; 573 | end 574 | 575 | % --- Outputs from this function are returned to the command line. 576 | function varargout = eventScopeR4_OutputFcn(hObject, eventdata, handles) 577 | % varargout cell array for returning output args (see VARARGOUT); 578 | % hObject handle to figure 579 | % eventdata reserved - to be defined in a future version of MATLAB 580 | % handles structure with handles and user data (see GUIDATA) 581 | 582 | % Get default command line output from handles structure 583 | varargout{1} = handles.output; 584 | end 585 | 586 | % --- Executes on button press in startButton. 587 | function startButton_Callback(hObject, eventdata, handles) 588 | % hObject handle to startButton (see GCBO) 589 | % eventdata reserved - to be defined in a future version of MATLAB 590 | % handles structure with handles and user data (see GUIDATA) 591 | myGUIdata = guidata(handles.eventScopeGUI); 592 | myGUIdata = startRealtime(myGUIdata); 593 | set(myGUIdata.saveFileButton,'enable','off'); 594 | guidata(hObject, myGUIdata); 595 | end 596 | 597 | % --- Executes on button press in stopButton. 598 | function stopButton_Callback(hObject, eventdata, handles) 599 | % hObject handle to stopButton (see GCBO) 600 | % eventdata reserved - to be defined in a future version of MATLAB 601 | % handles structure with handles and user data (see GUIDATA) 602 | myGUIdata = guidata(handles.eventScopeGUI); 603 | %disp('timer ends') 604 | switch get(myGUIdata.timer50ms,'running') 605 | case 'on' 606 | stop(myGUIdata.timer50ms) 607 | end; 608 | stop(myGUIdata.recordObj1); 609 | set(myGUIdata.stopButton,'enable','off'); 610 | set(myGUIdata.startButton,'enable','on'); 611 | set(myGUIdata.saveFileButton,'enable','on'); 612 | end 613 | 614 | % --- Executes on button press in quitButton. 615 | function quitButton_Callback(hObject, eventdata, handles) 616 | % hObject handle to quitButton (see GCBO) 617 | % eventdata reserved - to be defined in a future version of MATLAB 618 | % handles structure with handles and user data (see GUIDATA) 619 | myGUIdata = guidata(handles.eventScopeGUI); 620 | %disp('timer ends') 621 | switch get(myGUIdata.timer50ms,'running') 622 | case 'on' 623 | stop(myGUIdata.timer50ms) 624 | end; 625 | stop(myGUIdata.recordObj1); 626 | delete(myGUIdata.timer50ms); 627 | delete(myGUIdata.recordObj1); 628 | delete(myGUIdata.timerForWaveDraw); 629 | delete(myGUIdata.timerForSpectrumBar); 630 | delete(myGUIdata.timerForKurtosisBar); 631 | delete(myGUIdata.timerForFineF0); 632 | close(handles.eventScopeGUI); 633 | end 634 | 635 | 636 | % --- If Enable == 'on', executes on mouse press in 5 pixel border. 637 | % --- Otherwise, executes on mouse press in 5 pixel border or over noteRadioButton. 638 | function noteRadioButton_ButtonDownFcn(hObject, eventdata, handles) 639 | % hObject handle to noteRadioButton (see GCBO) 640 | % eventdata reserved - to be defined in a future version of MATLAB 641 | % handles structure with handles and user data (see GUIDATA) 642 | end 643 | 644 | 645 | % --- If Enable == 'on', executes on mouse press in 5 pixel border. 646 | % --- Otherwise, executes on mouse press in 5 pixel border or over freqRadioButton. 647 | function freqRadioButton_ButtonDownFcn(hObject, eventdata, handles) 648 | % hObject handle to freqRadioButton (see GCBO) 649 | % eventdata reserved - to be defined in a future version of MATLAB 650 | % handles structure with handles and user data (see GUIDATA) 651 | end 652 | 653 | 654 | % --- Executes during object creation, after setting all properties. 655 | function axisModePanel_CreateFcn(hObject, eventdata, handles) 656 | % hObject handle to axisModePanel (see GCBO) 657 | % eventdata reserved - to be defined in a future version of MATLAB 658 | % handles empty - handles not created until after all CreateFcns called 659 | end 660 | 661 | 662 | % -------------------------------------------------------------------- 663 | function axisModePanel_ButtonDownFcn(hObject, eventdata, handles) 664 | % hObject handle to axisModePanel (see GCBO) 665 | % eventdata reserved - to be defined in a future version of MATLAB 666 | % handles structure with handles and user data (see GUIDATA) 667 | myGUIdata = get(hObject,'userdata'); 668 | %disp('axisModePanel was hit'); 669 | switch get(myGUIdata.freqRadioButton,'value') 670 | case 1 671 | set(myGUIdata.noteAxis,'ytick',myGUIdata.freqtickLocation,'ytickLabel',myGUIdata.freqTickLabel); 672 | otherwise 673 | set(myGUIdata.noteAxis,'ytick',myGUIdata.noteID,'ytickLabel',myGUIdata.noteName); 674 | end; 675 | end 676 | 677 | % --- Executes on button press in saveFileButton. 678 | function saveFileButton_Callback(hObject, eventdata, handles) 679 | % hObject handle to saveFileButton (see GCBO) 680 | % eventdata reserved - to be defined in a future version of MATLAB 681 | % handles structure with handles and user data (see GUIDATA) 682 | myGUIdata = guidata(handles.eventScopeGUI); 683 | outFileName = ['eventData' datestr(now,30) '.wav']; 684 | [file,path] = uiputfile(outFileName,'Save the captured data'); 685 | if length(file) == 1 && length(path) == 1 686 | if file == 0 || path == 0 687 | %okInd = 0; 688 | disp('Save is cancelled!'); 689 | return; 690 | end; 691 | end; 692 | audiowrite([path file],myGUIdata.tmpAudio,myGUIdata.samplingFrequency); 693 | end 694 | -------------------------------------------------------------------------------- /GUI/lfModelDesignerX.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/lfModelDesignerX.fig -------------------------------------------------------------------------------- /GUI/lrTool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/lrTool.png -------------------------------------------------------------------------------- /GUI/penTool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/penTool.png -------------------------------------------------------------------------------- /GUI/pickTool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/pickTool.png -------------------------------------------------------------------------------- /GUI/realtimeSpectrogramV3.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/realtimeSpectrogramV3.fig -------------------------------------------------------------------------------- /GUI/realtimeSpectrogramV3.m: -------------------------------------------------------------------------------- 1 | function varargout = realtimeSpectrogramV3(varargin) 2 | % Running spectrogram in realtime. Type: 3 | % realtimeSpectrogramV3 4 | % to start. 5 | 6 | % Designed and coded by Hideki Kawahara (kawahara AT sys.wakayama-u.ac.jp) 7 | % 19/Dec./2013 8 | % 20/Dec./2013 added dynamic range control and zooming and pan tools 9 | % 21/Dec./2013 bug fix. Please excuse me! 10 | % 22/Dec./2013 added wide-band spectrogram, 1/3 band, ERB_N number, Bark 11 | % filter bank simulators 12 | % 24/Dec./2013 bug fix of frequency axis labels 13 | % 31/Aug./2015 machine independent and resizable 14 | 15 | % This work is licensed under the Creative Commons 16 | % Attribution 4.0 International License. 17 | % To view a copy of this license, visit 18 | % http://creativecommons.org/licenses/by/4.0/. 19 | 20 | % REALTIMESPECTROGRAMV3 MATLAB code for realtimeSpectrogramV3.fig 21 | % REALTIMESPECTROGRAMV3, by itself, creates a new REALTIMESPECTROGRAMV3 or raises the existing 22 | % singleton*. 23 | % 24 | % H = REALTIMESPECTROGRAMV3 returns the handle to a new REALTIMESPECTROGRAMV3 or the handle to 25 | % the existing singleton*. 26 | % 27 | % REALTIMESPECTROGRAMV3('CALLBACK',hObject,eventData,handles,...) calls the local 28 | % function named CALLBACK in REALTIMESPECTROGRAMV3.M with the given input arguments. 29 | % 30 | % REALTIMESPECTROGRAMV3('Property','Value',...) creates a new REALTIMESPECTROGRAMV3 or raises the 31 | % existing singleton*. Starting from the left, property value pairs are 32 | % applied to the GUI before realtimeSpectrogramV3_OpeningFcn gets called. An 33 | % unrecognized property name or invalid value makes property application 34 | % stop. All inputs are passed to realtimeSpectrogramV3_OpeningFcn via varargin. 35 | % 36 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one 37 | % instance to run (singleton)". 38 | % 39 | % See also: GUIDE, GUIDATA, GUIHANDLES 40 | 41 | % Edit the above text to modify the response to help realtimeSpectrogramV3 42 | 43 | % Last Modified by GUIDE v2.5 21-Dec-2013 23:28:52 44 | 45 | % Begin initialization code - DO NOT EDIT 46 | gui_Singleton = 1; 47 | gui_State = struct('gui_Name', mfilename, ... 48 | 'gui_Singleton', gui_Singleton, ... 49 | 'gui_OpeningFcn', @realtimeSpectrogramV3_OpeningFcn, ... 50 | 'gui_OutputFcn', @realtimeSpectrogramV3_OutputFcn, ... 51 | 'gui_LayoutFcn', [] , ... 52 | 'gui_Callback', []); 53 | if nargin && ischar(varargin{1}) 54 | gui_State.gui_Callback = str2func(varargin{1}); 55 | end 56 | 57 | if nargout 58 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 59 | else 60 | gui_mainfcn(gui_State, varargin{:}); 61 | end 62 | % End initialization code - DO NOT EDIT 63 | end 64 | 65 | % --- Executes just before realtimeSpectrogramV3 is made visible. 66 | function realtimeSpectrogramV3_OpeningFcn(hObject, eventdata, handles, varargin) 67 | % This function has no output args, see OutputFcn. 68 | % hObject handle to figure 69 | % eventdata reserved - to be defined in a future version of MATLAB 70 | % handles structure with handles and user data (see GUIDATA) 71 | % varargin command line arguments to realtimeSpectrogramV3 (see VARARGIN) 72 | 73 | % Choose default command line output for realtimeSpectrogramV3 74 | handles.output = hObject; 75 | 76 | % Update handles structure 77 | guidata(hObject, handles); 78 | %handles 79 | delete(timerfindall); 80 | initializeDisplay(handles); 81 | myGUIdata = guidata(handles.realTimeSgramGUI); 82 | %myGUIdata 83 | timerEventInterval = 0.1; % in second 84 | %timerEventInterval = 0.075; % in second 85 | timer50ms = timer('TimerFcn',@synchDrawGUI, 'Period',timerEventInterval,'ExecutionMode','fixedRate', ... 86 | 'userData',handles.realTimeSgramGUI); 87 | %handleForTimer = handles.multiScopeMainGUI; % global 88 | myGUIdata.timer50ms = timer50ms; 89 | myGUIdata.smallviewerWidth = 30; % 30 ms is defaule 90 | myGUIdata.recordObj1 = audiorecorder(myGUIdata.samplingFrequency,24,1); 91 | set(myGUIdata.recordObj1,'TimerPeriod',0.1); 92 | record(myGUIdata.recordObj1) 93 | myGUIdata.maxAudioRecorderCount = 200; 94 | myGUIdata.maxLevel = -100; 95 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 96 | myGUIdata.displayTypeList = cellstr(get(myGUIdata.displayPopupMenu,'String')); 97 | %myGUIdata.displayTypeList = myGUIdata.displayTypeList(1:2); 98 | set(myGUIdata.displayPopupMenu,'String',myGUIdata.displayTypeList) 99 | myGUIdata.displayType = myGUIdata.displayTypeList{1}; 100 | guidata(handles.realTimeSgramGUI,myGUIdata); 101 | startButton_Callback(hObject, eventdata, handles) 102 | % UIWAIT makes realtimeSpectrogramV3 wait for user response (see UIRESUME) 103 | % uiwait(handles.realTimeSgramGUI); 104 | end 105 | 106 | function initializeDisplay(handles) 107 | myGUIdata = guidata(handles.realTimeSgramGUI); 108 | myGUIdata.samplingFrequency = 44100; 109 | axes(handles.sgramAxis); 110 | myGUIdata = settingForWideband(myGUIdata); 111 | fxx = myGUIdata.visibleFrequencyAxis; 112 | tx = myGUIdata.timeAxis; 113 | myGUIdata.sgramHandle = image([tx(1) tx(end)]-tx(end),[fxx(1) fxx(end)],myGUIdata.initialSgramData); 114 | axis('xy'); 115 | set(gca,'fontunit','normalized','fontsize',0.025); 116 | myGUIdata.linearTicLocationListWide = get(handles.sgramAxis,'ytick'); 117 | myGUIdata.linearTickLabelListWide = get(handles.sgramAxis,'ytickLabel'); 118 | myGUIdata = settingForNarrowband(myGUIdata); 119 | fxx = myGUIdata.visibleFrequencyAxis; 120 | tx = myGUIdata.timeAxis; 121 | myGUIdata.sgramHandle = image([tx(1) tx(end)]-tx(end),[fxx(1) fxx(end)],myGUIdata.initialSgramData); 122 | set(gca,'fontunit','normalized','fontsize',0.03); 123 | axis('xy'); 124 | %colormap(1-gray) 125 | myGUIdata.titleText = title('Narrowband spectrogram','fontunit','normalized','fontsize',0.03); 126 | xlabel('time (s)'); 127 | ylabel('frequency (Hz)') 128 | myGUIdata.linearTicLocationList = get(handles.sgramAxis,'ytick'); 129 | myGUIdata.linearTickLabelList = get(handles.sgramAxis,'ytickLabel'); 130 | set(myGUIdata.dynamicRanbeText,'string',[num2str(myGUIdata.dynamicRange,'%3.0f') ' dB']); 131 | %set(myGUIdata.sgramHandle,'erasemode','none'); 132 | set(myGUIdata.displayPopupMenu,'enable','off'); 133 | drawnow; 134 | guidata(handles.realTimeSgramGUI,myGUIdata); 135 | end 136 | 137 | %--- private function for make it narrow spectrogram 138 | function myGUIdata = settingForNarrowband(myGUIdata) 139 | myGUIdata.windowLengthInMs = 80; %80 140 | myGUIdata.higherFrequencyLimit = 3600; 141 | fs = myGUIdata.samplingFrequency; 142 | fftl = 2^ceil(log2(myGUIdata.windowLengthInMs*fs/1000)); 143 | %fftl = 1024; 144 | fx = (0:fftl/2)/fftl*fs; 145 | fxx = fx(fx fftl*4 242 | tmpAudio = getaudiodata(myGUIdata.recordObj1); 243 | currentPoint = length(tmpAudio); 244 | if length(currentPoint-numberOfSamples+1:currentPoint) > 10 245 | set(myGUIdata.counterText,'string',num2str(myGUIdata.audioRecorderCount)); 246 | myGUIdata.audioRecorderCount = myGUIdata.audioRecorderCount-1; 247 | spectrogramBuffer = get(myGUIdata.sgramHandle,'cdata'); 248 | ii = 0; 249 | while myGUIdata.lastPosition+myGUIdata.frameShiftInSample+numberOfSamples < currentPoint 250 | ii = ii+1; 251 | currentIndex = myGUIdata.lastPosition+myGUIdata.frameShiftInSample; 252 | x = tmpAudio(currentIndex+(0:numberOfSamples-1)); 253 | switch get(myGUIdata.displayPopupMenu,'Value') 254 | case {1,2} 255 | tmpSpectrum = 20*log10(abs(fft(x.*w,fftl))); 256 | case {3,4,5} 257 | tmpSpectrum = abs(fft(x.*w,fftl)).^2; 258 | end; 259 | myGUIdata.fftBuffer(:,ii) = tmpSpectrum; 260 | myGUIdata.lastPosition = currentIndex; 261 | end; 262 | nFrames = ii; 263 | if nFrames > 0 264 | tmpSgram = myGUIdata.fftBuffer(:,1:nFrames); 265 | switch get(myGUIdata.displayPopupMenu,'Value') 266 | case 5 267 | fx = (0:fftl/2)/fftl*fs; 268 | filterBankStr = simulatedFilterBank(tmpSgram(1:fftl/2+1,:),fx,'third'); 269 | tmpSgram = 10*log10(filterBankStr.filteredSgramTriangle); 270 | case 3 271 | fx = (0:fftl/2)/fftl*fs; 272 | filterBankStr = simulatedFilterBank(tmpSgram(1:fftl/2+1,:),fx,'ERB'); 273 | tmpSgram = 10*log10(filterBankStr.filteredSgramTriangle); 274 | case 4 275 | fx = (0:fftl/2)/fftl*fs; 276 | filterBankStr = simulatedFilterBank(tmpSgram(1:fftl/2+1,:),fx,'Bark'); 277 | tmpSgram = 10*log10(filterBankStr.filteredSgramTriangle); 278 | end; 279 | if myGUIdata.maxLevel < max(tmpSgram(:)) 280 | myGUIdata.maxLevel = max(tmpSgram(:)); 281 | else 282 | myGUIdata.maxLevel = max(-100,myGUIdata.maxLevel*0.998); 283 | end; 284 | tmpSgram = 62*max(0,(tmpSgram-myGUIdata.maxLevel)+dynamicRange)/dynamicRange+1; 285 | spectrogramBuffer(:,1:end-nFrames) = spectrogramBuffer(:,nFrames+1:end); 286 | spectrogramBuffer(:,end-nFrames+1:end) = tmpSgram(1:length(fxx),:); 287 | set(myGUIdata.sgramHandle,'cdata',spectrogramBuffer); 288 | else 289 | disp('no data read!'); 290 | end; 291 | else 292 | disp('overrun!') 293 | end; 294 | if myGUIdata.audioRecorderCount < 0 295 | switch get(myGUIdata.timer50ms,'running') 296 | case 'on' 297 | stop(myGUIdata.timer50ms); 298 | end 299 | disp('Initilizing audio buffer'); 300 | stop(myGUIdata.recordObj1); 301 | record(myGUIdata.recordObj1); 302 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 303 | myGUIdata.lastPosition = 1; 304 | switch get(myGUIdata.timer50ms,'running') 305 | case 'off' 306 | start(myGUIdata.timer50ms); 307 | end 308 | end; 309 | guidata(handleForTimer,myGUIdata); 310 | else 311 | disp(['Recorded data is not enough! Skipping this interruption....at ' datestr(now,30)]); 312 | end; 313 | end 314 | 315 | % --- Outputs from this function are returned to the command line. 316 | function varargout = realtimeSpectrogramV3_OutputFcn(hObject, eventdata, handles) 317 | % varargout cell array for returning output args (see VARARGOUT); 318 | % hObject handle to figure 319 | % eventdata reserved - to be defined in a future version of MATLAB 320 | % handles structure with handles and user data (see GUIDATA) 321 | 322 | % Get default command line output from handles structure 323 | varargout{1} = handles.output; 324 | end 325 | 326 | % --- Executes on button press in startButton. 327 | function startButton_Callback(hObject, eventdata, handles) 328 | % hObject handle to startButton (see GCBO) 329 | % eventdata reserved - to be defined in a future version of MATLAB 330 | % handles structure with handles and user data (see GUIDATA) 331 | myGUIdata = guidata(handles.realTimeSgramGUI); 332 | set(myGUIdata.saveButton,'enable','off'); 333 | set(myGUIdata.startButton,'enable','off'); 334 | set(myGUIdata.playButton,'enable','off'); 335 | set(myGUIdata.stopButton,'enable','on'); 336 | set(myGUIdata.displayPopupMenu,'enable','off'); 337 | switch get(myGUIdata.timer50ms,'running') 338 | case 'on' 339 | stop(myGUIdata.timer50ms); 340 | end 341 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 342 | myGUIdata.lastPosition = 1; 343 | record(myGUIdata.recordObj1); 344 | switch get(myGUIdata.timer50ms,'running') 345 | case 'off' 346 | start(myGUIdata.timer50ms); 347 | case 'on' 348 | otherwise 349 | disp('timer is bloken!'); 350 | end 351 | guidata(handles.realTimeSgramGUI,myGUIdata); 352 | end 353 | 354 | % --- Executes on button press in stopButton. 355 | function stopButton_Callback(hObject, eventdata, handles) 356 | % hObject handle to stopButton (see GCBO) 357 | % eventdata reserved - to be defined in a future version of MATLAB 358 | % handles structure with handles and user data (see GUIDATA) 359 | myGUIdata = guidata(handles.realTimeSgramGUI); 360 | set(myGUIdata.saveButton,'enable','on'); 361 | set(myGUIdata.startButton,'enable','on'); 362 | set(myGUIdata.playButton,'enable','on'); 363 | set(myGUIdata.stopButton,'enable','off'); 364 | set(myGUIdata.displayPopupMenu,'enable','on'); 365 | switch get(myGUIdata.timer50ms,'running') 366 | case 'on' 367 | stop(myGUIdata.timer50ms) 368 | case 'off' 369 | otherwise 370 | disp('timer is bloken!'); 371 | end; 372 | myGUIdata.audioData = getaudiodata(myGUIdata.recordObj1); 373 | stop(myGUIdata.recordObj1); 374 | guidata(handles.realTimeSgramGUI,myGUIdata); 375 | end 376 | 377 | % --- Executes on button press in playButton. 378 | function playButton_Callback(hObject, eventdata, handles) 379 | % hObject handle to playButton (see GCBO) 380 | % eventdata reserved - to be defined in a future version of MATLAB 381 | % handles structure with handles and user data (see GUIDATA) 382 | myGUIdata = guidata(handles.realTimeSgramGUI); 383 | x = myGUIdata.audioData; 384 | fs = myGUIdata.samplingFrequency; 385 | minus4 = max(1,round((length(x)/fs-4)*fs)); 386 | sound(x(minus4:end)/max(abs(x(minus4:end)))*0.99,fs); 387 | end 388 | 389 | % --- Executes on button press in saveButton. 390 | function saveButton_Callback(hObject, eventdata, handles) 391 | % hObject handle to saveButton (see GCBO) 392 | % eventdata reserved - to be defined in a future version of MATLAB 393 | % handles structure with handles and user data (see GUIDATA) 394 | myGUIdata = guidata(handles.realTimeSgramGUI); 395 | outFileName = ['relFFTIn' datestr(now,30) '.wav']; 396 | [file,path] = uiputfile(outFileName,'Save the last 4 second data'); 397 | if length(file) == 1 && length(path) == 1 398 | if file == 0 || path == 0 399 | %okInd = 0; 400 | disp('Save is cancelled!'); 401 | return; 402 | end; 403 | end; 404 | wavwrite(myGUIdata.audioData,myGUIdata.samplingFrequency,16,[path file]); 405 | end 406 | 407 | % --- Executes on button press in quitButton. 408 | function quitButton_Callback(hObject, eventdata, handles) 409 | % hObject handle to quitButton (see GCBO) 410 | % eventdata reserved - to be defined in a future version of MATLAB 411 | % handles structure with handles and user data (see GUIDATA) 412 | myGUIdata = guidata(handles.realTimeSgramGUI); 413 | %disp('timer ends') 414 | switch get(myGUIdata.timer50ms,'running') 415 | case 'on' 416 | stop(myGUIdata.timer50ms) 417 | end; 418 | stop(myGUIdata.recordObj1); 419 | delete(myGUIdata.timer50ms); 420 | delete(myGUIdata.recordObj1); 421 | close(handles.realTimeSgramGUI); 422 | end 423 | 424 | 425 | % --- Executes on slider movement. 426 | function dynamicRangeSlider_Callback(hObject, eventdata, handles) 427 | % hObject handle to dynamicRangeSlider (see GCBO) 428 | % eventdata reserved - to be defined in a future version of MATLAB 429 | % handles structure with handles and user data (see GUIDATA) 430 | 431 | % Hints: get(hObject,'Value') returns position of slider 432 | % get(hObject,'Min') and get(hObject,'Max') to determine range of slider 433 | myGUIdata = guidata(handles.realTimeSgramGUI); 434 | value = get(hObject,'Value'); 435 | myGUIdata.dynamicRange = max(1,abs((value-1)*100)); 436 | set(myGUIdata.dynamicRanbeText,'string',[num2str(myGUIdata.dynamicRange,'%3.0f') ' dB']); 437 | guidata(handles.realTimeSgramGUI,myGUIdata); 438 | end 439 | 440 | % --- Executes during object creation, after setting all properties. 441 | function dynamicRangeSlider_CreateFcn(hObject, eventdata, handles) 442 | % hObject handle to dynamicRangeSlider (see GCBO) 443 | % eventdata reserved - to be defined in a future version of MATLAB 444 | % handles empty - handles not created until after all CreateFcns called 445 | 446 | % Hint: slider controls usually have a light gray background. 447 | if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 448 | set(hObject,'BackgroundColor',[.9 .9 .9]); 449 | end 450 | set(hObject,'value',0.2); 451 | end 452 | 453 | 454 | % --- Executes on selection change in displayPopupMenu. 455 | function displayPopupMenu_Callback(hObject, eventdata, handles) 456 | % hObject handle to displayPopupMenu (see GCBO) 457 | % eventdata reserved - to be defined in a future version of MATLAB 458 | % handles structure with handles and user data (see GUIDATA) 459 | 460 | % Hints: contents = cellstr(get(hObject,'String')) returns displayPopupMenu contents as cell array 461 | % contents{get(hObject,'Value')} returns selected item from displayPopupMenu 462 | myGUIdata = guidata(handles.realTimeSgramGUI); 463 | %disp('hit!') 464 | contents = cellstr(get(hObject,'String')); 465 | myGUIdata.displayType = contents{get(hObject,'Value')}; 466 | switch get(myGUIdata.timer50ms,'running') 467 | case 'on' 468 | stop(myGUIdata.timer50ms) 469 | case 'off' 470 | otherwise 471 | disp('timer is bloken!'); 472 | end; 473 | switch get(hObject,'Value') 474 | case 1 475 | myGUIdata = settingForNarrowband(myGUIdata); 476 | set(myGUIdata.sgramHandle,'cdata',myGUIdata.initialSgramData*0+1);%, ... 477 | set(myGUIdata.sgramHandle,'xdata',[myGUIdata.timeAxis(1) myGUIdata.timeAxis(end)]-myGUIdata.timeAxis(end), ... 478 | 'ydata',[myGUIdata.visibleFrequencyAxis(1) myGUIdata.visibleFrequencyAxis(end)]); 479 | set(myGUIdata.sgramAxis,'xlim',[myGUIdata.timeAxis(1) myGUIdata.timeAxis(end)]-myGUIdata.timeAxis(end), ... 480 | 'ylim',[myGUIdata.visibleFrequencyAxis(1) myGUIdata.visibleFrequencyAxis(end)]); 481 | set(myGUIdata.sgramAxis,'ytick',myGUIdata.linearTicLocationList); 482 | set(myGUIdata.sgramAxis,'ytickLabel',myGUIdata.linearTickLabelList); 483 | set(myGUIdata.titleText,'string','Narrowband spectrogram','fontunit','normalized','fontsize',0.03); 484 | enableZoomingTools(myGUIdata); 485 | case 2 486 | myGUIdata = settingForWideband(myGUIdata); 487 | set(myGUIdata.sgramHandle,'cdata',myGUIdata.initialSgramData*0+1);%, ... 488 | set(myGUIdata.sgramHandle,'xdata',[myGUIdata.timeAxis(1) myGUIdata.timeAxis(end)]-myGUIdata.timeAxis(end), ... 489 | 'ydata',[myGUIdata.visibleFrequencyAxis(1) myGUIdata.visibleFrequencyAxis(end)]); 490 | set(myGUIdata.sgramAxis,'xlim',[myGUIdata.timeAxis(1) myGUIdata.timeAxis(end)]-myGUIdata.timeAxis(end), ... 491 | 'ylim',[myGUIdata.visibleFrequencyAxis(1) myGUIdata.visibleFrequencyAxis(end)]); 492 | set(myGUIdata.titleText,'string','Wideband spectrogram','fontunit','normalized','fontsize',0.03); 493 | set(myGUIdata.sgramAxis,'ytick',myGUIdata.linearTicLocationListWide); 494 | set(myGUIdata.sgramAxis,'ytickLabel',myGUIdata.linearTickLabelListWide); 495 | enableZoomingTools(myGUIdata); 496 | case {3,4,5} 497 | myGUIdata = settingForThirdband(myGUIdata); 498 | set(myGUIdata.sgramHandle,'cdata',myGUIdata.initialSgramData*0+1);%, ... 499 | set(myGUIdata.sgramHandle,'xdata',[myGUIdata.timeAxis(1) myGUIdata.timeAxis(end)]-myGUIdata.timeAxis(end), ... 500 | 'ydata',[myGUIdata.visibleFrequencyAxis(1) myGUIdata.visibleFrequencyAxis(end)]); 501 | set(myGUIdata.sgramAxis,'xlim',[myGUIdata.timeAxis(1) myGUIdata.timeAxis(end)]-myGUIdata.timeAxis(end), ... 502 | 'ylim',[myGUIdata.visibleFrequencyAxis(1) myGUIdata.visibleFrequencyAxis(end)]); 503 | %keyboard; 504 | set(myGUIdata.sgramAxis,'ytick',myGUIdata.ticLocationList,'yticklabel',myGUIdata.tickLabelList); 505 | switch get(hObject,'Value') 506 | case 5 507 | set(myGUIdata.titleText,'string','Simulated 1/3 octave band filter, based on 80 ms Nuttallwin','fontunit','normalized','fontsize',0.03); 508 | case 3 509 | set(myGUIdata.titleText,'string','Simulated ERB_N filter, based on 80 ms Nuttallwin (temporal resolution is misleading!)','fontunit','normalized','fontsize',0.03); 510 | case 4 511 | set(myGUIdata.titleText,'string','Simulated Bark filter, based on 80 ms Nuttallwin (temporal resolution is misleading!)','fontunit','normalized','fontsize',0.03); 512 | end; 513 | disableZoomingTools(myGUIdata); 514 | end 515 | get(myGUIdata.sgramHandle) 516 | %start(myGUIdata.timer50ms); 517 | guidata(handles.realTimeSgramGUI,myGUIdata); 518 | startButton_Callback(myGUIdata.startButton, eventdata, handles); 519 | end 520 | 521 | % --- Executes during object creation, after setting all properties. 522 | function displayPopupMenu_CreateFcn(hObject, eventdata, handles) 523 | % hObject handle to displayPopupMenu (see GCBO) 524 | % eventdata reserved - to be defined in a future version of MATLAB 525 | % handles empty - handles not created until after all CreateFcns called 526 | 527 | % Hint: popupmenu controls usually have a white background on Windows. 528 | % See ISPC and COMPUTER. 529 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 530 | set(hObject,'BackgroundColor','white'); 531 | end 532 | end 533 | 534 | % ---- private functions 535 | function enableZoomingTools(myGUIdata) 536 | set(myGUIdata.uitoggletool3,'enable','on'); 537 | set(myGUIdata.uitoggletool2,'enable','on'); 538 | set(myGUIdata.uitoggletool1,'enable','on'); 539 | end 540 | 541 | function disableZoomingTools(myGUIdata) 542 | set(myGUIdata.uitoggletool3,'enable','off'); 543 | set(myGUIdata.uitoggletool2,'enable','off'); 544 | set(myGUIdata.uitoggletool1,'enable','off'); 545 | end 546 | -------------------------------------------------------------------------------- /GUI/recordingGUIV7.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/recordingGUIV7.fig -------------------------------------------------------------------------------- /GUI/vtShapeToSoundTestV28.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/vtShapeToSoundTestV28.fig -------------------------------------------------------------------------------- /GUI/vtlDisplay.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/vtlDisplay.fig -------------------------------------------------------------------------------- /GUI/vtlDisplay.m: -------------------------------------------------------------------------------- 1 | function varargout = vtlDisplay(varargin) 2 | % VTLDISPLAY MATLAB code for vtlDisplay.fig 3 | % VTLDISPLAY, by itself, creates a new VTLDISPLAY or raises the existing 4 | % singleton*. 5 | % 6 | % H = VTLDISPLAY returns the handle to a new VTLDISPLAY or the handle to 7 | % the existing singleton*. 8 | % 9 | % VTLDISPLAY('CALLBACK',hObject,eventData,handles,...) calls the local 10 | % function named CALLBACK in VTLDISPLAY.M with the given input arguments. 11 | % 12 | % VTLDISPLAY('Property','Value',...) creates a new VTLDISPLAY or raises the 13 | % existing singleton*. Starting from the left, property value pairs are 14 | % applied to the GUI before vtlDisplay_OpeningFcn gets called. An 15 | % unrecognized property name or invalid value makes property application 16 | % stop. All inputs are passed to vtlDisplay_OpeningFcn via varargin. 17 | % 18 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one 19 | % instance to run (singleton)". 20 | % 21 | % See also: GUIDE, GUIDATA, GUIHANDLES 22 | 23 | % This work is licensed under the Creative Commons 24 | % Attribution 4.0 International License. 25 | % To view a copy of this license, visit 26 | % http://creativecommons.org/licenses/by/4.0/. 27 | 28 | % Release note 29 | % Realtime vocal tract log area function display 30 | % by Hideki Kawahara 31 | % 17/Jan./2014 32 | % 26/Jan./2014 frame rate monirot 33 | % 31/Aug./2015 machine independence and resizable GUI 34 | 35 | % Edit the above text to modify the response to help vtlDisplay 36 | 37 | % Last Modified by GUIDE v2.5 16-Jan-2014 23:57:35 38 | 39 | % Begin initialization code - DO NOT EDIT 40 | gui_Singleton = 1; 41 | gui_State = struct('gui_Name', mfilename, ... 42 | 'gui_Singleton', gui_Singleton, ... 43 | 'gui_OpeningFcn', @vtlDisplay_OpeningFcn, ... 44 | 'gui_OutputFcn', @vtlDisplay_OutputFcn, ... 45 | 'gui_LayoutFcn', [] , ... 46 | 'gui_Callback', []); 47 | if nargin && ischar(varargin{1}) 48 | gui_State.gui_Callback = str2func(varargin{1}); 49 | end 50 | 51 | if nargout 52 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 53 | else 54 | gui_mainfcn(gui_State, varargin{:}); 55 | end 56 | % End initialization code - DO NOT EDIT 57 | end 58 | 59 | 60 | % --- Executes just before vtlDisplay is made visible. 61 | function vtlDisplay_OpeningFcn(hObject, eventdata, handles, varargin) 62 | % This function has no output args, see OutputFcn. 63 | % hObject handle to figure 64 | % eventdata reserved - to be defined in a future version of MATLAB 65 | % handles structure with handles and user data (see GUIDATA) 66 | % varargin command line arguments to vtlDisplay (see VARARGIN) 67 | 68 | % Choose default command line output for vtlDisplay 69 | handles.output = hObject; 70 | 71 | % Update handles structure 72 | guidata(hObject, handles); 73 | 74 | delete(timerfindall); 75 | initializeDisplay(handles); 76 | myGUIdata = guidata(handles.vtVisualizeGUI); 77 | timerEventInterval = 0.010; % in second 78 | timer50ms = timer('TimerFcn',@synchDrawGUI, 'Period',timerEventInterval,'ExecutionMode','fixedRate', ... 79 | 'userData',handles.vtVisualizeGUI); 80 | %handleForTimer = handles.multiScopeMainGUI; % global 81 | myGUIdata.timer50ms = timer50ms; 82 | myGUIdata.smallviewerWidth = 30; % 30 ms is defaule 83 | myGUIdata.recordObj1 = audiorecorder(myGUIdata.samplingFrequency,24,1); 84 | set(myGUIdata.recordObj1,'TimerPeriod',0.2); 85 | record(myGUIdata.recordObj1) 86 | myGUIdata.maxAudioRecorderCount = 1000; 87 | myGUIdata.maxLevel = -100; 88 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 89 | myGUIdata.startTic = tic; 90 | myGUIdata.lastTime = toc(myGUIdata.startTic); 91 | %myGUIdata.displayTypeList = myGUIdata.displayTypeList(1:2); 92 | guidata(handles.vtVisualizeGUI,myGUIdata); 93 | startButton_Callback(hObject, eventdata, handles) 94 | 95 | % UIWAIT makes vtlDisplay wait for user response (see UIRESUME) 96 | % uiwait(handles.vtVisualizeGUI); 97 | end 98 | 99 | function initializeDisplay(handles) 100 | myGUIdata = guidata(handles.vtVisualizeGUI); 101 | myGUIdata.samplingFrequency = 8000; % in Hz 102 | myGUIdata.windowLength = 0.08; % in second 103 | myGUIdata.windowLengthInSamples = round(myGUIdata.windowLength*myGUIdata.samplingFrequency/2)*2+1; 104 | myGUIdata.fftl = 2.0^ceil(log2(myGUIdata.windowLengthInSamples)); 105 | axes(handles.spectrumDisplayAxis); 106 | w = blackman(myGUIdata.windowLengthInSamples); 107 | w = w/sqrt(sum(w.^2)); 108 | myGUIdata.window = w; 109 | fs = myGUIdata.samplingFrequency; 110 | myGUIdata.displayFrequencyAxis = (0:myGUIdata.fftl-1)/myGUIdata.fftl*fs; 111 | tt = (1:myGUIdata.windowLengthInSamples)'/fs; 112 | %x = randn(myGUIdata.windowLengthInSamples,1); 113 | x = sin(2*pi*440*tt); 114 | pw = 10*log10(abs(fft(x.*w,myGUIdata.fftl)).^2/myGUIdata.fftl); 115 | myGUIdata.spectrumPlotHandle = plot(myGUIdata.displayFrequencyAxis,pw); 116 | hold on; 117 | myGUIdata.spectrumLPCPlotHandle = plot(myGUIdata.displayFrequencyAxis,pw,'r', ... 118 | 'linewidth',2);grid on; 119 | %set(handles.spectrumDisplayAxis,'xlim',[0 fs/2]); 120 | axis([0 fs/2 -110 0]); 121 | set(gca,'fontsize',14,'linewidth',2); 122 | xlabel('frequency (Hz)') 123 | ylabel('level (dB rel. MSB)'); 124 | legend('power spectrum','14th order LPC'); 125 | set(handles.spectrumDisplayAxis,'HandleVisibility','off'); 126 | axes(handles.VTDisplayAxis); 127 | logAreaFunction = [4 3.7 4 2.7 2.2 1.9 1.9 1.5 0.8 0]; 128 | locationList = [1 3 5 7 9 11 13 15 17 19]; 129 | displayLocationList = 0:0.1:21; 130 | displayLogArea = interp1(locationList,logAreaFunction,displayLocationList,'nearest','extrap'); 131 | myGUIdata.logAreaHandle = plot(displayLocationList,displayLogArea-mean(displayLogArea),'linewidth',4); 132 | hold on; 133 | plot(displayLocationList,0*displayLogArea,'linewidth',1); 134 | for ii = 0:20 135 | magCoeff = 1; 136 | if rem(ii,5) == 0 137 | magCoeff = 2; 138 | text(ii,-0.7,num2str(ii),'fontsize',16,'HorizontalAlignment','center'); 139 | end; 140 | if rem(ii,10) == 0 141 | magCoeff = 3; 142 | end; 143 | plot([ii ii],[-0.1 0.1]*magCoeff); 144 | end; 145 | axis([-0.5 20.5 -5 5]); 146 | axis off 147 | set(handles.VTDisplayAxis,'HandleVisibility','off'); 148 | axes(handles.tract3DAxis); 149 | crossSection = [0.2803; ... 150 | 0.6663; ... 151 | 0.5118; ... 152 | 0.3167; ... 153 | 0.1759; ... 154 | 0.1534; ... 155 | 0.1565; ... 156 | 0.1519; ... 157 | 0.0878; ... 158 | 0.0737]; 159 | [X,Y,Z] = cylinder(crossSection,40); 160 | myGUIdata.tract3D = surf(Z,Y,X); 161 | view(-26,12); 162 | axis([0 1 -1 1 -1 1]); 163 | axis off; 164 | axis('vis3d'); 165 | rotate3d on; 166 | guidata(handles.vtVisualizeGUI,myGUIdata); 167 | end 168 | 169 | function synchDrawGUI(obj, event, string_arg) 170 | handleForTimer = get(obj,'userData'); 171 | myGUIdata = guidata(handleForTimer); 172 | w = myGUIdata.window; 173 | numberOfSamples = length(w); 174 | if get(myGUIdata.recordObj1,'TotalSamples') > numberOfSamples 175 | tmpAudio = getaudiodata(myGUIdata.recordObj1); 176 | currentPoint = length(tmpAudio); 177 | x = tmpAudio(currentPoint-numberOfSamples+1:currentPoint); 178 | %x = [0;diff(x)]; 179 | pw = abs(fft(x.*w,myGUIdata.fftl)).^2/myGUIdata.fftl; 180 | pwdB = 10*log10(pw); 181 | set(myGUIdata.spectrumPlotHandle,'ydata',pwdB); 182 | ac = real(ifft(pw)); 183 | [alp,err,k] = levinson(ac,14); 184 | env = 1.0./abs(fft(alp,myGUIdata.fftl)).^2; 185 | env = sum(pw)*env/sum(env); 186 | envDB = 10*log10(env); 187 | set(myGUIdata.spectrumLPCPlotHandle,'ydata',envDB); 188 | logArea = signal2logArea(x); 189 | nSection = length(logArea); 190 | locationList = (1:nSection)*2-1; 191 | xdata = get(myGUIdata.logAreaHandle,'xdata'); 192 | displayLogArea = interp1(locationList,logArea,xdata,'nearest','extrap'); 193 | set(myGUIdata.logAreaHandle,'ydata',displayLogArea-mean(displayLogArea)); 194 | [X,Y,Z] = cylinder(tubeDisplay(logArea),40); 195 | set(myGUIdata.tract3D,'xdata',Z,'ydata',Y,'zdata',X); 196 | if myGUIdata.audioRecorderCount < 0 197 | switch get(myGUIdata.timer50ms,'running') 198 | case 'on' 199 | stop(myGUIdata.timer50ms); 200 | end 201 | stop(myGUIdata.recordObj1); 202 | record(myGUIdata.recordObj1); 203 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 204 | currentTime = toc(myGUIdata.startTic); 205 | framePerSecond = 1.0./(currentTime-myGUIdata.lastTime)*1000; 206 | set(myGUIdata.fpsDisplayText,'String',[num2str(framePerSecond,'%3.3f') ' fps']); 207 | myGUIdata.lastTime = currentTime; 208 | switch get(myGUIdata.timer50ms,'running') 209 | case 'off' 210 | start(myGUIdata.timer50ms); 211 | end 212 | else 213 | set(myGUIdata.countDownText,'String',num2str(myGUIdata.audioRecorderCount)); 214 | myGUIdata.audioRecorderCount = myGUIdata.audioRecorderCount-1; 215 | end; 216 | else 217 | %disp(['Recorded data is not enough! Skipping this interruption....at ' datestr(now,30)]); 218 | set(myGUIdata.countDownText,'String','Initilizing...'); 219 | end; 220 | guidata(myGUIdata.vtVisualizeGUI,myGUIdata); 221 | end 222 | 223 | % --- Outputs from this function are returned to the command line. 224 | function varargout = vtlDisplay_OutputFcn(hObject, eventdata, handles) 225 | % varargout cell array for returning output args (see VARARGOUT); 226 | % hObject handle to figure 227 | % eventdata reserved - to be defined in a future version of MATLAB 228 | % handles structure with handles and user data (see GUIDATA) 229 | 230 | % Get default command line output from handles structure 231 | varargout{1} = handles.output; 232 | end 233 | 234 | % --- Executes on button press in startButton. 235 | function startButton_Callback(hObject, eventdata, handles) 236 | % hObject handle to startButton (see GCBO) 237 | % eventdata reserved - to be defined in a future version of MATLAB 238 | % handles structure with handles and user data (see GUIDATA) 239 | myGUIdata = guidata(handles.vtVisualizeGUI); 240 | myGUIdata.startTic = tic; 241 | myGUIdata.lastTime = toc(myGUIdata.startTic); 242 | set(myGUIdata.startButton,'enable','off'); 243 | set(myGUIdata.stopButton,'enable','on'); 244 | switch get(myGUIdata.timer50ms,'running') 245 | case 'on' 246 | stop(myGUIdata.timer50ms); 247 | end 248 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 249 | myGUIdata.lastPosition = 1; 250 | record(myGUIdata.recordObj1); 251 | switch get(myGUIdata.timer50ms,'running') 252 | case 'off' 253 | start(myGUIdata.timer50ms); 254 | case 'on' 255 | otherwise 256 | disp('timer is bloken!'); 257 | end 258 | guidata(handles.vtVisualizeGUI,myGUIdata); 259 | end 260 | 261 | % --- Executes on button press in stopButton. 262 | function stopButton_Callback(hObject, eventdata, handles) 263 | % hObject handle to stopButton (see GCBO) 264 | % eventdata reserved - to be defined in a future version of MATLAB 265 | % handles structure with handles and user data (see GUIDATA) 266 | myGUIdata = guidata(handles.vtVisualizeGUI); 267 | myGUIdata.audioData = getaudiodata(myGUIdata.recordObj1); 268 | currentTime = toc(myGUIdata.startTic); 269 | framePerSecond = 1.0./(currentTime-myGUIdata.lastTime)*(1000-myGUIdata.audioRecorderCount); 270 | set(myGUIdata.fpsDisplayText,'String',[num2str(framePerSecond,'%3.3f') ' fps']); 271 | %disp('timer ends') 272 | %set(myGUIdata.startButton,'enable','off'); 273 | set(myGUIdata.startButton,'enable','on'); 274 | set(myGUIdata.stopButton,'enable','off'); 275 | switch get(myGUIdata.timer50ms,'running') 276 | case 'on' 277 | stop(myGUIdata.timer50ms) 278 | case 'off' 279 | otherwise 280 | disp('timer is bloken!'); 281 | end; 282 | stop(myGUIdata.recordObj1); 283 | guidata(handles.vtVisualizeGUI,myGUIdata); 284 | end 285 | 286 | % --- Executes on button press in quitButton. 287 | function quitButton_Callback(hObject, eventdata, handles) 288 | % hObject handle to quitButton (see GCBO) 289 | % eventdata reserved - to be defined in a future version of MATLAB 290 | % handles structure with handles and user data (see GUIDATA) 291 | myGUIdata = guidata(handles.vtVisualizeGUI); 292 | %disp('timer ends') 293 | switch get(myGUIdata.timer50ms,'running') 294 | case 'on' 295 | stop(myGUIdata.timer50ms) 296 | end; 297 | stop(myGUIdata.recordObj1); 298 | delete(myGUIdata.timer50ms); 299 | delete(myGUIdata.recordObj1); 300 | close(handles.vtVisualizeGUI); 301 | end 302 | -------------------------------------------------------------------------------- /GUI/waveletVisualizer.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/GUI/waveletVisualizer.fig -------------------------------------------------------------------------------- /GUI/waveletVisualizer.m: -------------------------------------------------------------------------------- 1 | function varargout = waveletVisualizer(varargin) 2 | % WAVELETVISUALIZER MATLAB code for waveletVisualizer.fig 3 | % WAVELETVISUALIZER, by itself, creates a new WAVELETVISUALIZER or raises the existing 4 | % singleton*. 5 | % 6 | % H = WAVELETVISUALIZER returns the handle to a new WAVELETVISUALIZER or the handle to 7 | % the existing singleton*. 8 | % 9 | % WAVELETVISUALIZER('CALLBACK',hObject,eventData,handles,...) calls the local 10 | % function named CALLBACK in WAVELETVISUALIZER.M with the given input arguments. 11 | % 12 | % WAVELETVISUALIZER('Property','Value',...) creates a new WAVELETVISUALIZER or raises the 13 | % existing singleton*. Starting from the left, property value pairs are 14 | % applied to the GUI before waveletVisualizer_OpeningFcn gets called. An 15 | % unrecognized property name or invalid value makes property application 16 | % stop. All inputs are passed to waveletVisualizer_OpeningFcn via varargin. 17 | % 18 | % *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one 19 | % instance to run (singleton)". 20 | % 21 | % See also: GUIDE, GUIDATA, GUIHANDLES 22 | 23 | % Designed and implemented by Hideki Kawahara 24 | % 25 | %Copyright 2018 Hideki Kawahara 26 | % 27 | %Licensed under the Apache License, Version 2.0 (the "License"); 28 | %you may not use this file except in compliance with the License. 29 | %You may obtain a copy of the License at 30 | % 31 | % http://www.apache.org/licenses/LICENSE-2.0 32 | % 33 | %Unless required by applicable law or agreed to in writing, software 34 | %distributed under the License is distributed on an "AS IS" BASIS, 35 | %WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 36 | %See the License for the specific language governing permissions and 37 | %limitations under the License. 38 | 39 | % Edit the above text to modify the response to help waveletVisualizer 40 | 41 | % Last Modified by GUIDE v2.5 20-Aug-2019 23:34:17 42 | 43 | % Begin initialization code - DO NOT EDIT 44 | gui_Singleton = 1; 45 | gui_State = struct('gui_Name', mfilename, ... 46 | 'gui_Singleton', gui_Singleton, ... 47 | 'gui_OpeningFcn', @waveletVisualizer_OpeningFcn, ... 48 | 'gui_OutputFcn', @waveletVisualizer_OutputFcn, ... 49 | 'gui_LayoutFcn', [] , ... 50 | 'gui_Callback', []); 51 | if nargin && ischar(varargin{1}) 52 | gui_State.gui_Callback = str2func(varargin{1}); 53 | end 54 | 55 | if nargout 56 | [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 57 | else 58 | gui_mainfcn(gui_State, varargin{:}); 59 | end 60 | % End initialization code - DO NOT EDIT 61 | end 62 | 63 | % --- Executes just before waveletVisualizer is made visible. 64 | function waveletVisualizer_OpeningFcn(hObject, eventdata, handles, varargin) 65 | % This function has no output args, see OutputFcn. 66 | % hObject handle to figure 67 | % eventdata reserved - to be defined in a future version of MATLAB 68 | % handles structure with handles and user data (see GUIDATA) 69 | % varargin command line arguments to waveletVisualizer (see VARARGIN) 70 | 71 | % Choose default command line output for waveletVisualizer 72 | handles.output = hObject; 73 | %--- user procedure starts 74 | delete(timerfindall); 75 | myGUIdata = guidata(hObject); 76 | myGUIdata.handles = handles; 77 | myGUIdata = setDefault(myGUIdata); 78 | myGUIdata = initializeGraphics(myGUIdata); 79 | %myGUIdata.displayAttribute = 'Phase'; 80 | timerEventInterval = 0.050; % in second 81 | myGUIdata.timerEventInterval = timerEventInterval; 82 | myGUIdata.avfoDisplay = 110; 83 | %--- audio monitor preparation 84 | myGUIdata.recordObj1 = audiorecorder(myGUIdata.samplingFrequency,24,1); 85 | set(myGUIdata.recordObj1,'TimerPeriod',0.2); 86 | myGUIdata.maxTargetPoint = 400;% This is for audio recorder 87 | myGUIdata.maxAudioRecorderCount = myGUIdata.maxTargetPoint; 88 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 89 | set(myGUIdata.counterTxt, 'String', num2str(myGUIdata.audioRecorderCount)); 90 | guidata(hObject, myGUIdata); 91 | %myGUIdata 92 | %--- wave draw timer preparation 93 | timerForWaveDraw = timer('TimerFcn',@waveDrawServer,'ExecutionMode','fixedRate', ... 94 | 'Period', timerEventInterval,'userData',hObject); 95 | myGUIdata.timerForWaveDraw = timerForWaveDraw; 96 | set(myGUIdata.startButton, 'enable', 'off'); 97 | set(myGUIdata.stopbutton, 'enable', 'on'); 98 | set(myGUIdata.quitbutton, 'enable', 'on'); 99 | set(myGUIdata.saveButton, 'enable', 'off'); 100 | set(myGUIdata.viewerWidthPopup, 'visible', 'off'); 101 | set(myGUIdata.fLowPopup, 'visible', 'off'); 102 | set(myGUIdata.fHighPopup, 'visible', 'off'); 103 | set(myGUIdata.stretchPopup, 'visible', 'off'); 104 | set(myGUIdata.defaultButton, 'visible', 'off'); 105 | guidata(hObject, myGUIdata); 106 | myGUIdata = startRealtime(myGUIdata); 107 | %--- 108 | 109 | myGUIdata.output = hObject; 110 | %--- user procedure ends 111 | % Update handles structure 112 | %guidata(hObject, handles); This is original 113 | guidata(hObject, myGUIdata); 114 | 115 | % UIWAIT makes waveletVisualizer wait for user response (see UIRESUME) 116 | % uiwait(handles.excitationViewerGUI); 117 | end 118 | 119 | % --- Outputs from this function are returned to the command line. 120 | function varargout = waveletVisualizer_OutputFcn(hObject, eventdata, handles) 121 | % varargout cell array for returning output args (see VARARGOUT); 122 | % hObject handle to figure 123 | % eventdata reserved - to be defined in a future version of MATLAB 124 | % handles structure with handles and user data (see GUIDATA) 125 | 126 | % Get default command line output from handles structure 127 | varargout{1} = handles.output; 128 | end 129 | 130 | %--- user defined supporting functions starts 131 | function myGUIdata = setDefault(myGUIdata) 132 | myGUIdata.samplingFrequency = 22050; 133 | myGUIdata.channels_in_octave = 8; 134 | myGUIdata.low_frequency = 110 * 2^(-1/3);%100; 135 | myGUIdata.high_freuency = 5000; 136 | myGUIdata.halfTimeSpan = 0.008; % 8 ms (default) 137 | myGUIdata.fftl = 2048; 138 | myGUIdata.stretching_factor = 1.0; 139 | myGUIdata.synchPhase = -120; 140 | set(myGUIdata.viewerWidthPopup, 'value', 3); 141 | set(myGUIdata.fLowPopup, 'value', 3); 142 | set(myGUIdata.fHighPopup, 'value', 2); 143 | set(myGUIdata.stretchPopup, 'value', 2); 144 | set(myGUIdata.phaseEdit, 'string', -120); 145 | end 146 | 147 | function waveDrawServer(obj, event, string_arg) 148 | handleForTimer = get(obj,'userData'); 149 | myGUIdata = guidata(handleForTimer); 150 | xdata = get(myGUIdata.waveHandle,'xdata'); 151 | wvltStr = myGUIdata.wvltStr; 152 | fc_list = wvltStr.fc_list; 153 | max_bias = wvltStr.wvlt(1).bias; 154 | n_data = length(xdata); 155 | channels_oct = myGUIdata.channels_in_octave; 156 | base_index = 1:n_data; 157 | buffer_index = 1:3 * n_data; 158 | %buffer_index(end) 159 | %size(myGUIdata.imageBuffer) 160 | switch get(myGUIdata.recordObj1,'running') 161 | case 'on' 162 | if get(myGUIdata.recordObj1,'TotalSamples') > max_bias * 4 + 3 * n_data 163 | myGUIdata.tmpAudio = getaudiodata(myGUIdata.recordObj1); 164 | if length(myGUIdata.tmpAudio) > max_bias * 4 + 3 * n_data 165 | x = myGUIdata.tmpAudio(end-(max_bias * 4 + 3 * n_data)+1:end); 166 | for ii = 1:myGUIdata.n_channles 167 | y = fftfilt(wvltStr.wvlt(ii).w, x); 168 | myGUIdata.imageBuffer(ii, :) = y(wvltStr.wvlt(ii).bias + wvltStr.wvlt(1).bias + buffer_index); 169 | end 170 | x_original = x(buffer_index + wvltStr.wvlt(1).bias); 171 | instFreqBuffer = angle(myGUIdata.imageBuffer ./ myGUIdata.imageBuffer(:, max(1, buffer_index - 1))); 172 | myGUIdata.imageBufferTmp = angle(myGUIdata.imageBuffer); 173 | rawSTD = (std(instFreqBuffer(:, 2:end)') * myGUIdata.samplingFrequency / 2 / pi) .^ 2; 174 | rawSTD = sqrt(rawSTD([1 1:end-1]) + rawSTD + rawSTD([2:end end])); 175 | fsdData = log(rawSTD(:) ./ fc_list(:)); 176 | bw_list = 1 ./ ((2^(1/channels_oct/2)-2^(-1/channels_oct/2)) * fc_list * 2 * pi); 177 | gd_gram_raw = -diag(bw_list) * angle(myGUIdata.imageBuffer ./ ... 178 | myGUIdata.imageBuffer([1 1:end-1], :)); 179 | gd_gram = diag(fc_list) * gd_gram_raw; 180 | gdData = std(max(-1, min(1, gd_gram(:, 2:end)'))); 181 | gdData(1) = gdData(2); 182 | gdData = log((gdData([1 1:end-1]) + gdData +gdData([2:end end])) / 3); 183 | mixData = gdData(:) + fsdData(:); % mixed cost function for fo 184 | [~, min_ch] = min(mixData);%gdData(:) + fsdData(:)); 185 | fund_phase = angle(myGUIdata.imageBuffer(min_ch, :) * exp(-1i * myGUIdata.synchPhase / 360 * 2 * pi)); %myGUIdata.synchPhase 186 | avfo = mean(instFreqBuffer(min_ch, 2:end)) * myGUIdata.samplingFrequency / 2 / pi; 187 | syncID = buffer_index(fund_phase .* fund_phase(max(1, buffer_index - 1)) < 0 & ... 188 | fund_phase(max(1, buffer_index - 1)) < fund_phase & ... 189 | buffer_index > n_data & buffer_index < buffer_index(end) - n_data); 190 | if ~isempty(syncID) 191 | [~, bias_center] = min(abs(syncID - buffer_index(end) / 2)); 192 | if isempty(bias_center) 193 | bias_center = round(buffer_index(end) / 2); 194 | end 195 | center_id = syncID(bias_center); 196 | else 197 | center_id = round(buffer_index(end) / 2); 198 | end 199 | selector = max(1, min(buffer_index(end), base_index + center_id - round(base_index(end) / 2))); 200 | fs = myGUIdata.samplingFrequency; 201 | contents = cellstr(get(myGUIdata.displayImagePopup,'String')); 202 | %myGUIdata.displayAttribute = contents{get(myGUIdata.displayImagePopup,'Value')}; 203 | switch contents{get(myGUIdata.displayImagePopup,'Value')} %myGUIdata.displayAttribute 204 | case 'Phase' 205 | myGUIdata.waveletImage = myGUIdata.imageBufferTmp(:, selector); 206 | case 'Inst. Freq. /fc' 207 | myGUIdata.waveletImage = max(0.75, min(1.4, diag(1 ./ fc_list)... 208 | * instFreqBuffer(:, selector) * fs / 2 / pi)); 209 | case 'Group delay*fc' 210 | myGUIdata.waveletImage = max(-1, min(1, gd_gram(:, selector))); 211 | case 'Absolute value' 212 | levelBuf = 20 * log10(abs(myGUIdata.imageBuffer(:, selector))); 213 | mx_level = max(max(levelBuf)); 214 | myGUIdata.waveletImage = max(mx_level - 70, levelBuf); 215 | end 216 | myGUIdata.gainData = mean(abs(myGUIdata.imageBuffer(:, selector)) .^ 2, 2); 217 | myGUIdata.gainData = 10 * log10(myGUIdata.gainData); 218 | set(myGUIdata.wvltImageHandle,'cdata',myGUIdata.waveletImage); 219 | set(myGUIdata.freqSDHandle, 'xdata', mixData / max(abs(mixData)) * xdata(end) * 1000); 220 | ydata = x_original(base_index + center_id - round(base_index(end) / 2)); 221 | set(myGUIdata.waveHandle,'ydata', ydata); 222 | set(myGUIdata.dBpowerAxis, 'xlim', [-69 0]); 223 | set(myGUIdata.gainHandle, 'xdata', -80 - myGUIdata.gainData); 224 | fo_in_channel = 1 + log2(avfo / myGUIdata.low_frequency) * myGUIdata.channels_in_octave; 225 | set(myGUIdata.foCursor, 'ydata', fo_in_channel * [1 1]); 226 | set(myGUIdata.waveAxis,'ylim',max(abs(ydata))*[-1 1]); 227 | set(myGUIdata.foViewer, 'String', num2str(avfo, '%6.1f')); 228 | [~, croma_id] = min(abs(avfo - myGUIdata.croma_scale)); 229 | myGUIdata.avfoDisplay = myGUIdata.avfoDisplay * 0.0 + avfo * 1.0; 230 | [~, croma_id_smooth] = min(abs(myGUIdata.avfoDisplay - myGUIdata.croma_scale)); 231 | set(myGUIdata.tunerHandle, 'ydata', [0 0] + ... 232 | 1200 * log2(myGUIdata.avfoDisplay / myGUIdata.croma_scale(croma_id_smooth))); 233 | set(myGUIdata.noteNameText, 'String', myGUIdata.note_name_struct.name{croma_id_smooth}); 234 | end 235 | myGUIdata.audioRecorderCount = myGUIdata.audioRecorderCount - 1; 236 | set(myGUIdata.counterTxt, 'String', num2str(myGUIdata.audioRecorderCount)); 237 | end 238 | end 239 | switch get(myGUIdata.timerForWaveDraw, 'running') 240 | case 'off' 241 | start(myGUIdata.timerForWaveDraw); 242 | end 243 | if myGUIdata.audioRecorderCount < 0 244 | set(myGUIdata.counterTxt, 'String', 'Initializing ...'); 245 | switch get(myGUIdata.timerForWaveDraw, 'running') 246 | case 'on' 247 | stop(myGUIdata.timerForWaveDraw); 248 | end 249 | switch get(myGUIdata.recordObj1,'running') 250 | case 'on' 251 | stop(myGUIdata.recordObj1); 252 | end 253 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 254 | myGUIdata = startRealtime(myGUIdata); 255 | end 256 | guidata(handleForTimer,myGUIdata); 257 | end 258 | 259 | function myGUIdata = startRealtime(myGUIdata) 260 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 261 | myGUIdata.lastPosition = 1; 262 | record(myGUIdata.recordObj1); 263 | pause(0.3) 264 | switch get(myGUIdata.timerForWaveDraw,'running') 265 | case 'off' 266 | start(myGUIdata.timerForWaveDraw); 267 | case 'on' 268 | otherwise 269 | disp('timer is bloken!'); 270 | end 271 | end 272 | 273 | function myGUIdata = initializeGraphics(myGUIdata) 274 | waveAxisHandle = myGUIdata.waveAxis; 275 | fs = myGUIdata.samplingFrequency; 276 | %------ waveform display 277 | halfTimeSpan = myGUIdata.halfTimeSpan; 278 | axes(waveAxisHandle); 279 | time_axis = (-round(halfTimeSpan * fs):round(halfTimeSpan * fs)) / fs; 280 | myGUIdata.waveHandle = plot(time_axis, randn(length(time_axis), 1), 'k'); 281 | set(gca, 'xlim', halfTimeSpan*[-1 1], 'fontsize', 14, 'xtick', [], 'ytick', []); 282 | %xlabel('time (s)') 283 | grid on; 284 | %------- wavelet display 285 | axes(myGUIdata.waveletAxis); 286 | wvltStr = designCos6Wavelet(fs, myGUIdata.low_frequency, myGUIdata.high_freuency, ... 287 | myGUIdata.fftl, myGUIdata.stretching_factor, myGUIdata.channels_in_octave); 288 | myGUIdata.n_channles = length(wvltStr.fc_list); 289 | waveletImage = zeros(myGUIdata.n_channles, length(time_axis)); 290 | for ii = 1:myGUIdata.n_channles 291 | waveletImage(ii, :) = cos(time_axis / halfTimeSpan * pi * wvltStr.fc_list(ii) / wvltStr.fc_list(1)); 292 | end 293 | myGUIdata.wvltImageHandle = imagesc(halfTimeSpan*[-1 1] * 1000, ... 294 | [1 myGUIdata.n_channles], waveletImage); axis('xy'); 295 | colormap(hsv); 296 | hold all 297 | myGUIdata.freqSDHandle = plot(zeros(myGUIdata.n_channles, 1), ... 298 | (1:myGUIdata.n_channles), 'w', 'linewidth', 3); 299 | fc_list = wvltStr.fc_list; 300 | ytickFreq = [50 60 70 80 90 100 200 300 400 500 600 700 800 900 1000 2000 3000 4000 5000]; 301 | ytick = interp1(log(fc_list), 1:length(fc_list), log(ytickFreq), 'linear', 'extrap'); 302 | ytickLabel = num2str(ytickFreq', '%4.0f'); 303 | set(gca, 'fontsize', 14, 'ytick', ytick, 'ytickLabel', ytickLabel, ... 304 | 'ylim', [1 myGUIdata.n_channles],'xlim', halfTimeSpan*[-1 1] * 1000); 305 | xlabel('time (ms)') 306 | ylabel('frequency (Hz)'); 307 | 308 | %-------- wavelet level display 309 | axes(myGUIdata.dBpowerAxis); 310 | gainv = zeros(length(fc_list), 1) - 15; 311 | for ii = 1:length(ytick) 312 | plot([-60 0], [1 1] * ytick(ii), 'color', [0.5 0.5 0.5]); 313 | hold all 314 | end 315 | croma_base = 27.5; 316 | croma_scale = croma_base * 2 .^ (0:1 / 12:log2(myGUIdata.high_freuency / croma_base)); 317 | croma_scale_channel = 1 + log2(croma_scale / myGUIdata.low_frequency) * myGUIdata.channels_in_octave; 318 | for ii = 1:length(croma_scale) 319 | plot([-69 -60], [1 1] * croma_scale_channel(ii), 'g'); 320 | end 321 | for ii = 2:7 322 | if ii * 12 + 1 <= length(croma_scale_channel) && ... 323 | ii * 12 + 1 + 3 - 12 <= length(croma_scale_channel) && ... 324 | ii * 12 + 1 + 3 + 4 - 12 <= length(croma_scale_channel) 325 | text(-66, croma_scale_channel(ii * 12 + 1), ['A' num2str(ii)]) 326 | text(-66, croma_scale_channel(ii * 12 + 1 + 3 - 12), ['C' num2str(ii)]) 327 | text(-66, croma_scale_channel(ii * 12 + 1 + 3 + 4 - 12), ['E' num2str(ii)]) 328 | end 329 | end 330 | note_name_base = {'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'}; 331 | note_name_struct = struct; 332 | for ii = 4:length(croma_scale) 333 | note_index = rem((ii - 4), 12) + 1; 334 | octave_id = floor(log2(croma_scale(ii) / croma_scale(4))) + 1; 335 | note_name_struct.name{ii} = [note_name_base{note_index} num2str(octave_id)]; 336 | end 337 | myGUIdata.note_name_struct = note_name_struct; 338 | myGUIdata.foCursor = plot([-60 0], [5 5], 'c', 'linewidth', 3); 339 | myGUIdata.gainHandle = plot(gainv, 1:length(fc_list), 'k', 'linewidth', 2); 340 | axis([-69 0 1 length(fc_list)]); grid on; 341 | xlabel('level (rel. dB)'); 342 | %xtick = get(gca, 'xtick'); 343 | xtick = -60:10:0; 344 | xtickLabel = num2str(xtick(end:-1:1)'); 345 | set(gca, 'ytick', [], 'fontsize', 14, 'xtick', xtick, 'xtickLabel', xtickLabel, 'xlim', [-69 0]); 346 | myGUIdata.gainData = get(myGUIdata.gainHandle, 'xdata'); 347 | %---- tuner display 348 | axes(myGUIdata.tunerAxis) 349 | plot([-1 1], [0 0], 'k', 'linewidth', 2) 350 | hold all 351 | myGUIdata.tunerHandle = plot([-1 1], [0 0] + 0.2, 'g', 'linewidth', 5); 352 | axis([-1 1 -50 50]); 353 | set(gca, 'ytick', [], 'xtick', [], 'linewidth', 2); 354 | myGUIdata.croma_scale = croma_scale; 355 | myGUIdata.wvltStr = wvltStr; 356 | myGUIdata.waveletImage = waveletImage; 357 | myGUIdata.imageBuffer = zeros(myGUIdata.n_channles, length(time_axis) * 3); 358 | myGUIdata.imageBufferTmp = zeros(myGUIdata.n_channles, length(time_axis) * 3); 359 | myGUIdata.instFreqBuffer = zeros(myGUIdata.n_channles, length(time_axis) * 3); 360 | %myGUIdata.displayAttribute = 'Phase'; 361 | update_colormap(myGUIdata); 362 | end 363 | 364 | function update_colormap(myGUIdata) 365 | contents = cellstr(get(myGUIdata.displayImagePopup,'String')); 366 | %myGUIdata.displayAttribute = contents{get(hObject,'Value')}; 367 | switch contents{get(myGUIdata.displayImagePopup,'Value')} %myGUIdata.displayAttribute 368 | case 'Phase' 369 | colormap(hsv); 370 | case 'Inst. Freq. /fc' 371 | colormap(hsv); 372 | case 'Group delay*fc' 373 | colormap(hsv); 374 | case 'Absolute value' 375 | colormap(jet); 376 | end 377 | end 378 | 379 | %--- user defined supporting functions ends 380 | 381 | % --- Executes on button press in startButton. 382 | function startButton_Callback(hObject, eventdata, handles) 383 | % hObject handle to startButton (see GCBO) 384 | % eventdata reserved - to be defined in a future version of MATLAB 385 | % handles structure with handles and user data (see GUIDATA) 386 | myGUIdata = guidata(hObject); 387 | myGUIdata.audioRecorderCount = myGUIdata.maxAudioRecorderCount; 388 | record(myGUIdata.recordObj1); 389 | pause(0.3) 390 | start(myGUIdata.timerForWaveDraw); 391 | set(myGUIdata.startButton, 'enable', 'off'); 392 | set(myGUIdata.stopbutton, 'enable', 'on'); 393 | set(myGUIdata.quitbutton, 'enable', 'on'); 394 | set(myGUIdata.saveButton, 'enable', 'off'); 395 | guidata(hObject, myGUIdata); 396 | end 397 | 398 | % --- Executes on button press in stopbutton. 399 | function stopbutton_Callback(hObject, eventdata, handles) 400 | % hObject handle to stopbutton (see GCBO) 401 | % eventdata reserved - to be defined in a future version of MATLAB 402 | % handles structure with handles and user data (see GUIDATA) 403 | myGUIdata = guidata(hObject); 404 | switch get(myGUIdata.timerForWaveDraw, 'running') 405 | case 'on' 406 | stop(myGUIdata.timerForWaveDraw); 407 | end 408 | switch get(myGUIdata.recordObj1, 'running') 409 | case 'on' 410 | stop(myGUIdata.recordObj1); 411 | end 412 | set(myGUIdata.startButton, 'enable', 'on'); 413 | set(myGUIdata.stopbutton, 'enable', 'off'); 414 | set(myGUIdata.quitbutton, 'enable', 'on'); 415 | set(myGUIdata.saveButton, 'enable', 'on'); 416 | guidata(hObject, myGUIdata); 417 | end 418 | 419 | % --- Executes on button press in quitbutton. 420 | function quitbutton_Callback(hObject, eventdata, handles) 421 | % hObject handle to quitbutton (see GCBO) 422 | % eventdata reserved - to be defined in a future version of MATLAB 423 | % handles structure with handles and user data (see GUIDATA) 424 | myGUIdata = guidata(hObject); 425 | stop(myGUIdata.timerForWaveDraw); 426 | delete(timerfindall); 427 | stop(myGUIdata.recordObj1); 428 | close(handles.excitationViewerGUI); 429 | end 430 | 431 | 432 | % --- Executes on selection change in displayImagePopup. 433 | function displayImagePopup_Callback(hObject, eventdata, handles) 434 | % hObject handle to displayImagePopup (see GCBO) 435 | % eventdata reserved - to be defined in a future version of MATLAB 436 | % handles structure with handles and user data (see GUIDATA) 437 | 438 | % Hints: contents = cellstr(get(hObject,'String')) returns displayImagePopup contents as cell array 439 | % contents{get(hObject,'Value')} returns selected item from displayImagePopup 440 | stopbutton_Callback(hObject, eventdata, handles); 441 | myGUIdata = guidata(hObject); 442 | contents = cellstr(get(hObject,'String')); 443 | %myGUIdata.displayAttribute = contents{get(hObject,'Value')}; 444 | axes(myGUIdata.waveletAxis); 445 | update_colormap(myGUIdata); 446 | %switch contents{get(hObject,'Value')} %myGUIdata.displayAttribute 447 | % case 'Phase' 448 | % colormap(hsv); 449 | % case 'Inst. Freq. /fc' 450 | % colormap(hsv); 451 | % case 'Group delay*fc' 452 | % colormap(hsv); 453 | % case 'Absolute value' 454 | % colormap(jet); 455 | %end 456 | guidata(hObject, myGUIdata); 457 | startButton_Callback(hObject, eventdata, handles); 458 | end 459 | 460 | 461 | % --- Executes during object creation, after setting all properties. 462 | function displayImagePopup_CreateFcn(hObject, eventdata, handles) 463 | % hObject handle to displayImagePopup (see GCBO) 464 | % eventdata reserved - to be defined in a future version of MATLAB 465 | % handles empty - handles not created until after all CreateFcns called 466 | 467 | % Hint: popupmenu controls usually have a white background on Windows. 468 | % See ISPC and COMPUTER. 469 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 470 | set(hObject,'BackgroundColor','white'); 471 | end 472 | end 473 | 474 | 475 | % --- Executes on button press in saveButton. 476 | function saveButton_Callback(hObject, eventdata, handles) 477 | % hObject handle to saveButton (see GCBO) 478 | % eventdata reserved - to be defined in a future version of MATLAB 479 | % handles structure with handles and user data (see GUIDATA) 480 | myGUIdata = guidata(hObject); 481 | outFileName = ['snapD' datestr(now, 30) '.wav']; 482 | audiowrite( outFileName, myGUIdata.tmpAudio, myGUIdata.samplingFrequency, ... 483 | 'BitsPerSample', 32); 484 | disp(['snapshot file:' outFileName]); 485 | set(myGUIdata.saveButton, 'enable', 'off'); 486 | end 487 | 488 | 489 | % --- Executes on selection change in modePopup. 490 | function modePopup_Callback(hObject, eventdata, handles) 491 | % hObject handle to modePopup (see GCBO) 492 | % eventdata reserved - to be defined in a future version of MATLAB 493 | % handles structure with handles and user data (see GUIDATA) 494 | 495 | % Hints: contents = cellstr(get(hObject,'String')) returns modePopup contents as cell array 496 | % contents{get(hObject,'Value')} returns selected item from modePopup 497 | myGUIdata = guidata(hObject); 498 | contents = cellstr(get(hObject,'String')); 499 | myGUIdata.operationMode = contents{get(hObject,'Value')}; 500 | switch myGUIdata.operationMode 501 | case 'Normal' 502 | set(myGUIdata.viewerWidthPopup, 'visible', 'off'); 503 | set(myGUIdata.fLowPopup, 'visible', 'off'); 504 | set(myGUIdata.fHighPopup, 'visible', 'off'); 505 | set(myGUIdata.defaultButton, 'visible', 'off'); 506 | set(myGUIdata.stretchPopup, 'visible', 'off'); 507 | case 'Experimental' 508 | set(myGUIdata.viewerWidthPopup, 'visible', 'on'); 509 | set(myGUIdata.fLowPopup, 'visible', 'on'); 510 | set(myGUIdata.fHighPopup, 'visible', 'on'); 511 | set(myGUIdata.defaultButton, 'visible', 'on'); 512 | set(myGUIdata.stretchPopup, 'visible', 'on'); 513 | end 514 | guidata(hObject, myGUIdata); 515 | end 516 | 517 | % --- Executes during object creation, after setting all properties. 518 | function modePopup_CreateFcn(hObject, eventdata, handles) 519 | % hObject handle to modePopup (see GCBO) 520 | % eventdata reserved - to be defined in a future version of MATLAB 521 | % handles empty - handles not created until after all CreateFcns called 522 | 523 | % Hint: popupmenu controls usually have a white background on Windows. 524 | % See ISPC and COMPUTER. 525 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 526 | set(hObject,'BackgroundColor','white'); 527 | end 528 | end 529 | 530 | % --- Executes on selection change in fHighPopup. 531 | function fHighPopup_Callback(hObject, eventdata, handles) 532 | % hObject handle to fHighPopup (see GCBO) 533 | % eventdata reserved - to be defined in a future version of MATLAB 534 | % handles structure with handles and user data (see GUIDATA) 535 | 536 | % Hints: contents = cellstr(get(hObject,'String')) returns fHighPopup contents as cell array 537 | % contents{get(hObject,'Value')} returns selected item from fHighPopup 538 | stopbutton_Callback(hObject, eventdata, handles); 539 | myGUIdata = guidata(hObject); 540 | contents = cellstr(get(hObject,'String')); 541 | viewWidthstring = contents{get(hObject,'Value')}; 542 | stringValue = sscanf(viewWidthstring, '%s %f %s'); 543 | myGUIdata.high_freuency = stringValue(4); 544 | delete(myGUIdata.wvltImageHandle); 545 | delete(myGUIdata.gainHandle); 546 | cla(myGUIdata.tunerAxis); 547 | cla(myGUIdata.dBpowerAxis); 548 | cla(myGUIdata.waveletAxis); 549 | cla(myGUIdata.waveAxis); 550 | myGUIdata = initializeGraphics(myGUIdata); 551 | guidata(hObject, myGUIdata); 552 | startButton_Callback(hObject, eventdata, handles); 553 | end 554 | 555 | % --- Executes during object creation, after setting all properties. 556 | function fHighPopup_CreateFcn(hObject, eventdata, handles) 557 | % hObject handle to fHighPopup (see GCBO) 558 | % eventdata reserved - to be defined in a future version of MATLAB 559 | % handles empty - handles not created until after all CreateFcns called 560 | 561 | % Hint: popupmenu controls usually have a white background on Windows. 562 | % See ISPC and COMPUTER. 563 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 564 | set(hObject,'BackgroundColor','white'); 565 | end 566 | end 567 | 568 | % --- Executes on selection change in fLowPopup. 569 | function fLowPopup_Callback(hObject, eventdata, handles) 570 | % hObject handle to fLowPopup (see GCBO) 571 | % eventdata reserved - to be defined in a future version of MATLAB 572 | % handles structure with handles and user data (see GUIDATA) 573 | 574 | % Hints: contents = cellstr(get(hObject,'String')) returns fLowPopup contents as cell array 575 | % contents{get(hObject,'Value')} returns selected item from fLowPopup 576 | stopbutton_Callback(hObject, eventdata, handles); 577 | myGUIdata = guidata(hObject); 578 | contents = cellstr(get(hObject,'String')); 579 | viewWidthstring = contents{get(hObject,'Value')}; 580 | stringValue = sscanf(viewWidthstring, '%s %f %s'); 581 | myGUIdata.low_frequency = stringValue(4); 582 | delete(myGUIdata.wvltImageHandle); 583 | delete(myGUIdata.gainHandle); 584 | cla(myGUIdata.tunerAxis); 585 | cla(myGUIdata.dBpowerAxis); 586 | cla(myGUIdata.waveletAxis); 587 | cla(myGUIdata.waveAxis); 588 | myGUIdata = initializeGraphics(myGUIdata); 589 | guidata(hObject, myGUIdata); 590 | startButton_Callback(hObject, eventdata, handles); 591 | end 592 | 593 | % --- Executes during object creation, after setting all properties. 594 | function fLowPopup_CreateFcn(hObject, eventdata, handles) 595 | % hObject handle to fLowPopup (see GCBO) 596 | % eventdata reserved - to be defined in a future version of MATLAB 597 | % handles empty - handles not created until after all CreateFcns called 598 | 599 | % Hint: popupmenu controls usually have a white background on Windows. 600 | % See ISPC and COMPUTER. 601 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 602 | set(hObject,'BackgroundColor','white'); 603 | end 604 | end 605 | 606 | % --- Executes on selection change in viewerWidthPopup. 607 | function viewerWidthPopup_Callback(hObject, eventdata, handles) 608 | % hObject handle to viewerWidthPopup (see GCBO) 609 | % eventdata reserved - to be defined in a future version of MATLAB 610 | % handles structure with handles and user data (see GUIDATA) 611 | 612 | % Hints: contents = cellstr(get(hObject,'String')) returns viewerWidthPopup contents as cell array 613 | % contents{get(hObject,'Value')} returns selected item from viewerWidthPopup 614 | stopbutton_Callback(hObject, eventdata, handles); 615 | myGUIdata = guidata(hObject); 616 | contents = cellstr(get(hObject,'String')); 617 | viewWidthstring = contents{get(hObject,'Value')}; 618 | stringValue = sscanf(viewWidthstring, '%s %f %s'); 619 | myGUIdata.halfTimeSpan = stringValue(4) / 2 / 1000; 620 | delete(myGUIdata.wvltImageHandle); 621 | delete(myGUIdata.gainHandle); 622 | cla(myGUIdata.tunerAxis); 623 | cla(myGUIdata.dBpowerAxis); 624 | cla(myGUIdata.waveletAxis); 625 | cla(myGUIdata.waveAxis); 626 | myGUIdata = initializeGraphics(myGUIdata); 627 | guidata(hObject, myGUIdata); 628 | startButton_Callback(hObject, eventdata, handles); 629 | end 630 | 631 | % --- Executes during object creation, after setting all properties. 632 | function viewerWidthPopup_CreateFcn(hObject, eventdata, handles) 633 | % hObject handle to viewerWidthPopup (see GCBO) 634 | % eventdata reserved - to be defined in a future version of MATLAB 635 | % handles empty - handles not created until after all CreateFcns called 636 | 637 | % Hint: popupmenu controls usually have a white background on Windows. 638 | % See ISPC and COMPUTER. 639 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 640 | set(hObject,'BackgroundColor','white'); 641 | end 642 | end 643 | 644 | 645 | % --- Executes on button press in defaultButton. 646 | function defaultButton_Callback(hObject, eventdata, handles) 647 | % hObject handle to defaultButton (see GCBO) 648 | % eventdata reserved - to be defined in a future version of MATLAB 649 | % handles structure with handles and user data (see GUIDATA) 650 | stopbutton_Callback(hObject, eventdata, handles); 651 | myGUIdata = guidata(hObject); 652 | myGUIdata = setDefault(myGUIdata); 653 | cla(myGUIdata.tunerAxis); 654 | cla(myGUIdata.dBpowerAxis); 655 | cla(myGUIdata.waveletAxis); 656 | cla(myGUIdata.waveAxis); 657 | myGUIdata = initializeGraphics(myGUIdata); 658 | guidata(hObject, myGUIdata); 659 | startButton_Callback(hObject, eventdata, handles); 660 | end 661 | 662 | 663 | % --- Executes on selection change in stretchPopup. 664 | function stretchPopup_Callback(hObject, eventdata, handles) 665 | % hObject handle to stretchPopup (see GCBO) 666 | % eventdata reserved - to be defined in a future version of MATLAB 667 | % handles structure with handles and user data (see GUIDATA) 668 | 669 | % Hints: contents = cellstr(get(hObject,'String')) returns stretchPopup contents as cell array 670 | % contents{get(hObject,'Value')} returns selected item from stretchPopup 671 | stopbutton_Callback(hObject, eventdata, handles); 672 | myGUIdata = guidata(hObject); 673 | contents = cellstr(get(hObject,'String')); 674 | viewWidthstring = contents{get(hObject,'Value')}; 675 | stringValue = sscanf(viewWidthstring, '%s %f'); 676 | myGUIdata.stretching_factor = stringValue(5); 677 | delete(myGUIdata.wvltImageHandle); 678 | delete(myGUIdata.gainHandle); 679 | cla(myGUIdata.tunerAxis); 680 | cla(myGUIdata.dBpowerAxis); 681 | cla(myGUIdata.waveletAxis); 682 | cla(myGUIdata.waveAxis); 683 | myGUIdata = initializeGraphics(myGUIdata); 684 | guidata(hObject, myGUIdata); 685 | startButton_Callback(hObject, eventdata, handles); 686 | end 687 | 688 | % --- Executes during object creation, after setting all properties. 689 | function stretchPopup_CreateFcn(hObject, eventdata, handles) 690 | % hObject handle to stretchPopup (see GCBO) 691 | % eventdata reserved - to be defined in a future version of MATLAB 692 | % handles empty - handles not created until after all CreateFcns called 693 | 694 | % Hint: popupmenu controls usually have a white background on Windows. 695 | % See ISPC and COMPUTER. 696 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 697 | set(hObject,'BackgroundColor','white'); 698 | end 699 | end 700 | 701 | 702 | 703 | function phaseEdit_Callback(hObject, eventdata, handles) 704 | % hObject handle to phaseEdit (see GCBO) 705 | % eventdata reserved - to be defined in a future version of MATLAB 706 | % handles structure with handles and user data (see GUIDATA) 707 | 708 | % Hints: get(hObject,'String') returns contents of phaseEdit as text 709 | % str2double(get(hObject,'String')) returns contents of phaseEdit as a double 710 | if ~isnan(str2double(get(hObject,'String'))) 711 | myGUIdata = guidata(hObject); 712 | myGUIdata.synchPhase = str2double(get(hObject,'String')); 713 | guidata(hObject, myGUIdata); 714 | end 715 | end 716 | 717 | 718 | % --- Executes during object creation, after setting all properties. 719 | function phaseEdit_CreateFcn(hObject, eventdata, handles) 720 | % hObject handle to phaseEdit (see GCBO) 721 | % eventdata reserved - to be defined in a future version of MATLAB 722 | % handles empty - handles not created until after all CreateFcns called 723 | 724 | % Hint: edit controls usually have a white background on Windows. 725 | % See ISPC and COMPUTER. 726 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 727 | set(hObject,'BackgroundColor','white'); 728 | end 729 | end 730 | 731 | 732 | % --- Executes on selection change in wintypePopUp. 733 | function wintypePopUp_Callback(hObject, eventdata, handles) 734 | % hObject handle to wintypePopUp (see GCBO) 735 | % eventdata reserved - to be defined in a future version of MATLAB 736 | % handles structure with handles and user data (see GUIDATA) 737 | 738 | % Hints: contents = cellstr(get(hObject,'String')) returns wintypePopUp contents as cell array 739 | % contents{get(hObject,'Value')} returns selected item from wintypePopUp 740 | stopbutton_Callback(hObject, eventdata, handles); 741 | myGUIdata = guidata(hObject); 742 | myGUIdata.wtypeId = get(hObject,'Value'); 743 | delete(myGUIdata.wvltImageHandle); 744 | delete(myGUIdata.gainHandle); 745 | cla(myGUIdata.tunerAxis); 746 | cla(myGUIdata.dBpowerAxis); 747 | cla(myGUIdata.waveletAxis); 748 | cla(myGUIdata.waveAxis); 749 | myGUIdata = initializeGraphics(myGUIdata); 750 | guidata(hObject, myGUIdata); 751 | startButton_Callback(hObject, eventdata, handles); 752 | end 753 | 754 | 755 | % --- Executes during object creation, after setting all properties. 756 | function wintypePopUp_CreateFcn(hObject, eventdata, handles) 757 | % hObject handle to wintypePopUp (see GCBO) 758 | % eventdata reserved - to be defined in a future version of MATLAB 759 | % handles empty - handles not created until after all CreateFcns called 760 | 761 | % Hint: popupmenu controls usually have a white background on Windows. 762 | % See ISPC and COMPUTER. 763 | if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) 764 | set(hObject,'BackgroundColor','white'); 765 | end 766 | end 767 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017, 2018 Hideki Kawahara, all rights reserved 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | SparkNG Copyright 2017 Hideki Kawahara Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *** Note *** Some m-files are public domain. Please check the comment part of each m-file. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # SparkNG MATLAB realtime/interactive tools for speech science research and education 4 | 5 | MATLAB-based GUI application with realtime audio input/output. Please visit SP3ARK for the up-to-date set of new tools! (4 March 2021) 6 | 7 | ## This series is getting obsolate. Please visit SP3ARK for up-to-date series of tools! 8 | 9 | ## Reference 10 | 11 | [1] Kawahara, Hideki. "SparkNG: Interactive MATLAB Tools for Introduction to Speech Production, Perception and Processing Fundamentals and Application of the Aliasing-Free LF Model Component." In INTERSPEECH, pp. 1180-1181. 2016. 12 | 13 | # How to install 14 | 15 | Set MATLAB path to "src," "GUI," "test," and "example" directories. 16 | 17 | # GUI applications 18 | 19 | GUI applications are in "GUI" directory. 20 | 21 |
22 |
recordingGUIV7
23 |
Realtime FFT analyzer with an interactive spectrogram with a time-frequency region playback.
24 |
realtimeSpectrogramV3
25 |
Realtime spectrogram display including several auditory frequency axes
26 |
vtlDisplay
27 |
Realtime display of vocal tract area function using LPC-based method.
28 |
vtShapeToSoundTestV28
29 |
Speech production simulator which allows intereactive manipulation of the vocal tract area function, resonance frequencies and bandwidths, and glottal source wave parameters.
30 |
eventScopeR4
31 |
Realtime display of fo, event, 1/3 octave levels, waveform and other parameters. This is a sample code.
32 |
waveletVisualizer
33 |
Realtime visualization of wavelet analysis results; phase, amplitude, instantaneous frequency, and group delay.
34 |
35 | 36 | # Core functions 37 | 38 | MATLAB core functions are in "src" directory. 39 | 40 | # Test script 41 | 42 | Test scripts are in "test" directory. 43 | 44 | # Release note 45 | 46 | This repository is a new start of SparkNG on Git. 47 | The remote directory was created on 12/Oct./2017. 48 | 49 | # Development environment 50 | 51 |
52 |
MacBook Pro 13", late 2018
53 |
MATLAB R2018b, signalprocessing toolbox
54 |
Windows 10
55 |
MATLAB R2018a, signalprocessing toolbox
56 |
57 | -------------------------------------------------------------------------------- /src/AAFLFmodelFromF0Trajectory.m: -------------------------------------------------------------------------------- 1 | function outStr = AAFLFmodelFromF0Trajectory(f0In,timeAxis,fs,tp,te,ta,tc,varargin) 2 | % outStr = AAFLFmodelFromF0Trajectory(f0In,timeAxis,fs,tp,te,ta,tc) 3 | % tp,te,ta,tc are L-F model parameters 4 | 5 | % 12/Dec./2015 added jitter and shimmer 6 | % 15/Dec./2015 randamization type updated 7 | 8 | startTime = tic; 9 | nVarargin = length(varargin); 10 | jitterSD = 0; 11 | shimmerSD = 0; 12 | perturbation = 'gaussian'; 13 | if length(varargin)>0 14 | switch nVarargin 15 | case 1 16 | jitterSD = varargin{1}; 17 | case 2 18 | jitterSD = varargin{1}; 19 | shimmerSD = varargin{2}; 20 | case 3 21 | jitterSD = varargin{1}; 22 | shimmerSD = varargin{2}; 23 | perturbation = varargin{3}; 24 | end; 25 | end; 26 | tt = (timeAxis(1):1/fs:timeAxis(end))'; 27 | f0 = exp(interp1(timeAxis,log(f0In),tt,'linear','extrap')); 28 | theta = cumsum(2*pi*f0.*ones(length(tt),1)/fs); 29 | 30 | pvPhase = angle(exp(1i*theta)); 31 | indexList = 1:length(theta)-1; 32 | startPointList = indexList(diff(pvPhase)<-5); 33 | 34 | lastPoint = 1; 35 | outSignal = tt*0; 36 | directOut = tt*0; 37 | directVV = tt*0; 38 | nyqFreq = fs/2; 39 | for ii = 1:length(startPointList)-2; 40 | segment = [pvPhase(lastPoint+1:startPointList(ii))-2*pi; ... 41 | pvPhase(startPointList(ii)+1:startPointList(ii+1)); 42 | pvPhase(startPointList(ii+1)+1:startPointList(ii+2))+2*pi]+pi; 43 | normalizedTime = segment/2/pi+jitterSD*perturbationFunction(perturbation); 44 | averageF0 = mean(f0(startPointList(ii)+1:startPointList(ii+1))); 45 | Tw = 2/nyqFreq; 46 | Tworg = Tw*averageF0; 47 | modelOut = sourceByLFmodelAAF(normalizedTime,tp,te,ta,tc,Tworg); 48 | outSignal(lastPoint+1:startPointList(ii+2)) = ... 49 | outSignal(lastPoint+1:startPointList(ii+2))+modelOut.antiAliasedSource*(1+shimmerSD*perturbationFunction2(perturbation)); 50 | directOut(lastPoint+1:startPointList(ii+2)) = ... 51 | directOut(lastPoint+1:startPointList(ii+2))+modelOut.source; 52 | directVV(lastPoint+1:startPointList(ii+2)) = ... 53 | directVV(lastPoint+1:startPointList(ii+2))+modelOut.volumeVerocity; 54 | lastPoint = startPointList(ii); 55 | end; 56 | outStr.antiAliasedSignal = outSignal; 57 | outStr.LFmodelOut = directOut; 58 | outStr.LFvolumeVelocity = directVV; 59 | outStr.samplingFrequency = fs; 60 | outStr.f0Interpolated = f0; 61 | outStr.temporalPosition = tt; 62 | outStr.startPointList = startPointList; 63 | outStr.pvPhase = pvPhase; 64 | outStr.elapsedTime = toc(startTime); 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/AAFLFmodelFromF0Trajectory6T.m: -------------------------------------------------------------------------------- 1 | function outStr = AAFLFmodelFromF0Trajectory6T(f0In,timeAxis,fs,tp,te,ta,tc,varargin) 2 | % outStr = AAFLFmodelFromF0Trajectory6T(f0In,timeAxis,fs,tp,te,ta,tc) 3 | % Generate antialiased L-F model output using the input F0 trajectory 4 | % revised antialiasing with 6-term cosine series and IIR equalizer 5 | % 6 | % Arguments 7 | % f0In : fundamental frequency trajetory (Hz) 8 | % timeAxis : time axis on which the f0 trajectory is defined. (s) 9 | % tp,te,ta,tc are L-F model parameters 10 | % 11 | % Output 12 | % outStr : structure with the following fields 13 | % antiAliasedSignal : antialiased excitation source with equalization 14 | % antiAliasedOnly : antialiased excitation source without equalization 15 | % LFmodelOut : direct discretization of the L-F model output 16 | % LFvolumeVelocity : volume velocity without antialiasing 17 | % samplingFrequency : sampling frequency (Hz) 18 | % f0Interpolated : F0 trajectory at audio rate (Hz) 19 | % temporalPosition : time axis at audio rate (s) 20 | % startPointList : sample index list of each pitch cycle 21 | % pvPhase : phase represented in principal value 22 | % elapsedTime : elapsed time for processing 23 | 24 | % 12/Dec./2015 added jitter and shimmer 25 | % 15/Dec./2015 randamization type updated 26 | % 21/Feb./2017 27 | % copyright Hideki Kawahara 21/Feb./2017 28 | 29 | %Copyright 2017 Hideki Kawahara 30 | % 31 | %Licensed under the Apache License, Version 2.0 (the "License"); 32 | %you may not use this file except in compliance with the License. 33 | %You may obtain a copy of the License at 34 | % 35 | % http://www.apache.org/licenses/LICENSE-2.0 36 | % 37 | %Unless required by applicable law or agreed to in writing, software 38 | %distributed under the License is distributed on an "AS IS" BASIS, 39 | %WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 40 | %See the License for the specific language governing permissions and 41 | %limitations under the License. 42 | 43 | startTime = tic; 44 | nVarargin = length(varargin); 45 | jitterSD = 0; 46 | shimmerSD = 0; 47 | perturbation = 'gaussian'; 48 | if ~isempty(varargin) 49 | switch nVarargin 50 | case 1 51 | jitterSD = varargin{1}; 52 | case 2 53 | jitterSD = varargin{1}; 54 | shimmerSD = varargin{2}; 55 | case 3 56 | jitterSD = varargin{1}; 57 | shimmerSD = varargin{2}; 58 | perturbation = varargin{3}; 59 | end 60 | end 61 | tt = (timeAxis(1):1 / fs:timeAxis(end))'; 62 | f0 = exp(interp1(timeAxis, log(f0In), tt, 'linear', 'extrap')); 63 | theta = cumsum(2 * pi * f0 .* ones(length(tt), 1) / fs); 64 | 65 | pvPhase = angle(exp(1i * theta)); 66 | indexList = 1:length(theta)-1; 67 | startPointList = indexList(diff(pvPhase)<-5); 68 | 69 | lastPoint = 1; 70 | outSignal = tt * 0; 71 | directOut = tt * 0; 72 | directVV = tt * 0; 73 | nyqFreq = fs / 2; 74 | for ii = 1:length(startPointList) - 2 75 | segment = [pvPhase(lastPoint + 1:startPointList(ii)) - 2 * pi; ... 76 | pvPhase(startPointList(ii) + 1:startPointList(ii + 1)); 77 | pvPhase(startPointList(ii + 1) + 1:startPointList(ii + 2)) + 2 * pi] + pi; 78 | normalizedTime = segment / 2 / pi + jitterSD * perturbationFunction(perturbation); 79 | averageF0 = mean(f0(startPointList(ii) + 1:startPointList(ii + 1))); 80 | Tw = 2 / nyqFreq; 81 | Tworg = Tw * averageF0; 82 | modelOut = sourceByLFmodelAAF6T(normalizedTime, tp, te, ta, tc, Tworg); 83 | outSignal(lastPoint+1:startPointList(ii + 2)) = ... 84 | outSignal(lastPoint+1:startPointList(ii + 2)) + ... 85 | modelOut.antiAliasedSource * ... 86 | (1 + shimmerSD*perturbationFunction2(perturbation)); 87 | directOut(lastPoint + 1:startPointList(ii + 2)) = ... 88 | directOut(lastPoint + 1:startPointList(ii + 2)) + modelOut.source; 89 | directVV(lastPoint + 1:startPointList(ii + 2)) = ... 90 | directVV(lastPoint + 1:startPointList(ii + 2)) + modelOut.volumeVerocity; 91 | lastPoint = startPointList(ii); 92 | end 93 | %% Equalizer 94 | hc = [0.2624710164 0.4265335164 0.2250165621 0.0726831633 0.0125124215 0.0007833203]; 95 | equalizerStr = equalizerDesignAAFX(hc, 68, 80, 1.5); 96 | a = equalizerStr.iirCoefficient; 97 | yfix = filter(sum(a) * [0 0 1], a, outSignal); 98 | 99 | %% 100 | outStr.antiAliasedSignal = yfix; 101 | outStr.antiAliasedOnly = outSignal; 102 | outStr.LFmodelOut = directOut; 103 | outStr.LFvolumeVelocity = directVV; 104 | outStr.samplingFrequency = fs; 105 | outStr.f0Interpolated = f0; 106 | outStr.temporalPosition = tt; 107 | outStr.startPointList = startPointList; 108 | outStr.pvPhase = pvPhase; 109 | outStr.elapsedTime = toc(startTime); 110 | end 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /src/AAFjLjmodelFromFOTrajectoryR.m: -------------------------------------------------------------------------------- 1 | function output = AAFjLjmodelFromFOTrajectoryR(fOi, fs, A, B, C, R, F, D) 2 | % Generate similar shape F-L source signal useg given fO trajectory 3 | % output = AAFjLjmodelFromFOTrajectory(fOi, fs, A, B, C, R, F, D) 4 | % 5 | % Argument 6 | % fOi : fundamental frequency trajectory in sampling resolution (Hz) 7 | % fs : sampling frequency (Hz) 8 | % A, B, C, R, F, D : Fujisaki-Ljungqvist model parameter 9 | % 10 | % Output 11 | % output : structure with the following fields 12 | % antiAliasedSignal : antialiased F-L model output 13 | % antiAliasedOnly : antialiased F-L model output without equalization 14 | % rawSignal : directly discretized F-L model output 15 | 16 | % 24/Jan./2017 by Hideki Kawahara 17 | % 11/Feb./2017 revised for new aaf 18 | 19 | phase_i = cumsum(2 * pi * fOi / fs); 20 | index_v = (1:length(phase_i))'; 21 | mean_fO = mean(fOi); 22 | d_phase_org = 1 / fs * 2 * pi * mean_fO; 23 | g = phase_i(:) * 0; 24 | gapp = g; 25 | graw = g; 26 | d_phase = d_phase_org; 27 | margin_p = 5 * d_phase; 28 | for initial_phase = 2 * pi:2 * pi:phase_i(end) - 2 * pi 29 | tmp_seg = phase_i(phase_i - initial_phase > -margin_p & ... 30 | phase_i - initial_phase <= 2 * pi+margin_p) - initial_phase; 31 | fO_seg = fOi(phase_i - initial_phase > -margin_p & ... 32 | phase_i - initial_phase <= 2 * pi+margin_p); 33 | tput = ... 34 | antialiasedFLmodelSingleR(tmp_seg, A, B, C, R, F, D, fs, mean(fO_seg)); 35 | rout = rawFLmodelSingle(tmp_seg, A, B, C, R, F, D); 36 | idx_a = index_v(phase_i - initial_phase > -margin_p & ... 37 | phase_i - initial_phase <= 2 * pi+margin_p); 38 | gapp(idx_a) = gapp(idx_a) + tput.g; 39 | graw(idx_a) = graw(idx_a) + rout.g; 40 | end 41 | hc = [0.2624710164 0.4265335164 0.2250165621 0.0726831633 0.0125124215 0.0007833203]; 42 | equalizerStr = equalizerDesignAAFX(hc,68,80, 1.5); 43 | a = equalizerStr.iirCoefficient; 44 | % This zero padding is to compensate the intrinsic delay of the symmetric 45 | % anti-aliasing smoother 46 | gfar = filter(sum(a) * [0 0 1], a, gapp); 47 | output.antiAliasedSignal = gfar; 48 | output.antiAliasedOnly = gapp; 49 | output.rawSignal = graw; 50 | end -------------------------------------------------------------------------------- /src/antiAliasedCExponentialSegment.m: -------------------------------------------------------------------------------- 1 | function output = antiAliasedCExponentialSegment(bet, tt, two) 2 | 3 | %Copyright 2017 Hideki Kawahara 4 | % 5 | %Licensed under the Apache License, Version 2.0 (the "License"); 6 | %you may not use this file except in compliance with the License. 7 | %You may obtain a copy of the License at 8 | % 9 | % http://www.apache.org/licenses/LICENSE-2.0 10 | % 11 | %Unless required by applicable law or agreed to in writing, software 12 | %distributed under the License is distributed on an "AS IS" BASIS, 13 | %WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | %See the License for the specific language governing permissions and 15 | %limitations under the License. 16 | 17 | tw = two * 1.5; 18 | alph = pi / tw; 19 | aa = [0.2624710164 0.4265335164 0.2250165621 0.0726831633 0.0125124215 0.0007833203]; 20 | m = length(aa) - 1; 21 | outbuf = tt * 0; 22 | for k = 0:m 23 | seg1 = tt(tt >= tw & tt <= tw+1); 24 | seg2 = tt(abs(tt) < tw); 25 | seg3 = tt(abs(1-tt) <= tw); % fragile? using "<" made error 26 | y1 = (k*alph*sin(k*alph*seg2)-bet*cos(k*alph*seg2) ... 27 | +(-1)^k*bet*exp(bet*tw)*exp(bet*seg2))/(k^2 * alph^2 + bet*bet); 28 | yy = ((-1)^k * bet * exp(bet * seg1) * (exp(bet * tw) - exp(-bet * tw))/(k^2 * alph^2 + bet*bet)); 29 | y3 = ((k*alph*exp(bet)*sin(k*alph*(seg3-1)) + bet*exp(bet*(tw+seg3))*(-1)^k ... 30 | - bet*exp(bet)*cos(k*alph*(seg3-1))) / (k^2 * alph^2 + bet*bet)); 31 | outbuf(tt >= tw & tt <= tw+1) = outbuf(tt >= tw & tt <= tw+1) + aa(k+1) * yy; 32 | outbuf(abs(tt) < tw) = outbuf(abs(tt) < tw) + aa(k+1) * y1; 33 | outbuf(abs(1-tt) <= tw) = outbuf(abs(1-tt) <= tw) - aa(k+1) * y3; 34 | end 35 | output = outbuf / (tw * aa(1) * 2); 36 | end -------------------------------------------------------------------------------- /src/antiAliasedPolynomialSegmentR.m: -------------------------------------------------------------------------------- 1 | function output = antiAliasedPolynomialSegmentR(poly_coeff, tt, two) 2 | % generate antialiased polynomial pulse using 6-term new window. 3 | % output = antiAliasedPolynomialSegmentR(poly_coeff, tt, tw) 4 | % 5 | % Input argument 6 | % poly_coeff : vector consisting of polinomial coefficients 7 | % 1st element corresponds to 0-th exponent coefficient 8 | % tt : discrete time axis, values are calculated using element of this 9 | % 0 < t <= 1 is the support of the polynomial pulse 10 | % two : half length of the smoothing function. This routine uses 11 | % 6-term new windowing function 12 | % 13 | % Output 14 | % output : antialiased polynomial pulse 15 | 16 | % 17,18, 23, 25/Jan./2017 by Hideki Kawahara 17 | 18 | %Copyright 2017 Hideki Kawahara 19 | % 20 | %Licensed under the Apache License, Version 2.0 (the "License"); 21 | %you may not use this file except in compliance with the License. 22 | %You may obtain a copy of the License at 23 | % 24 | % http://www.apache.org/licenses/LICENSE-2.0 25 | % 26 | %Unless required by applicable law or agreed to in writing, software 27 | %distributed under the License is distributed on an "AS IS" BASIS, 28 | %WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 | %See the License for the specific language governing permissions and 30 | %limitations under the License. 31 | 32 | tw = two * 1.5; % 1.5 is scaling factor of 6-term new window 33 | %hc = [0.338946 0.481973 0.161054 0.018027]; % Nuttall-11 coefficient 34 | %hc = [0.355768 0.487396 0.144232 0.012604]; % Nuttall-12 coefficient 35 | %hc = [0.3635819 0.4891775 0.1365995 0.0106411];% matlab nuttallwin 36 | %hc = [20 30 12 2] / 64; 37 | hc = [0.2625000000 0.4265625000 0.2250000000 0.0726562500 ... 38 | 0.0125000000 0.0007812500]; 39 | m = length(hc) - 1; 40 | hc = hc / (2 * tw * hc(1)); 41 | n = length(poly_coeff) - 1; 42 | 43 | C = zeros(n + 1, m); 44 | S = zeros(n + 1, m); 45 | U = zeros(n + 1, 1 + n + 1); 46 | V = zeros(n + 1, n + 1); 47 | 48 | r = 0; 49 | for k = 1:m 50 | C(r + 1, k) = 0; 51 | S(r + 1, k) = tw / (k * pi) * hc(k + 1); 52 | end 53 | U(r + 1, 1 + 1) = hc(1); 54 | U(r + 1, 1) = - U(r + 1, 2:end) * ((-tw) .^ (1:n + 1)'); 55 | V(r + 1, 1) = 1; 56 | for r = 1:n 57 | for k = 1:m 58 | C(r + 1, k) = -((r * tw) / (k * pi)) * S(r, k); 59 | S(r + 1, k) = ((r * tw) / (k * pi)) * C(r, k); 60 | end 61 | for k = 1:n + 1 62 | U(r + 1, k + 1) = (r / k) * U(r, k); 63 | end 64 | U(r + 1, 1) = -(U(r + 1, 2:end) * ((-tw) .^ (1:n + 1)') ... 65 | + C(r + 1, :) * ((-1) .^ (1:m)')); 66 | for k = 1:n 67 | V(r + 1, k + 1) = (r / k) * V(r, k); 68 | end 69 | V(r + 1, 1) = C(r + 1, :) * ((-1) .^ (1:m)') ... 70 | + U(r + 1, :) * ((tw) .^ (0:n + 1)') ... 71 | - V(r + 1, 2:end) * ((tw) .^ (1:n)'); 72 | end 73 | B = zeros(n + 1, n + 1); 74 | for ii = 1:n+1 75 | for jj = 1:ii 76 | nr = ii - 1; 77 | nk = jj - 1; 78 | B(ii, jj) = factorial(nr) / factorial(nk) / factorial(nr - nk); 79 | end 80 | end 81 | c0 = poly_coeff(:)'* C; 82 | s0 = poly_coeff(:)'* S; 83 | u0 = poly_coeff(:)'* U; 84 | v = poly_coeff(:)'* V; 85 | c1 = poly_coeff(:)'* B * C; 86 | s1 = poly_coeff(:)'* B * S; 87 | u1 = poly_coeff(:)'* B * U; 88 | 89 | output = tt * 0; 90 | 91 | tt1 = tt(tt > -tw & tt <= tw); 92 | tt2 = tt(tt > tw & tt <= 1 - tw); 93 | tt3 = tt(tt > 1 - tw & tt <= 1 + tw); 94 | dt3 = tt(tt > 1 - tw & tt <= 1 + tw) - 1; 95 | tt4 = tt(tt > tw & tt <= 1 + tw); 96 | 97 | tm1 = tt1 .^ (0:n + 1); 98 | tm2 = tt2 .^ (0:n + 1); 99 | tm3 = tt3 .^ (0:n + 1); 100 | dm3 = dt3 .^ (0:n + 1); 101 | tm4 = tt4 .^ (0:n + 1); 102 | 103 | tcs1 = tt1 * (1:m); 104 | dcs3 = dt3 * (1:m); 105 | 106 | g1 = cos(pi * tcs1 / tw) * c0' + sin(pi * tcs1 / tw) * s0' + tm1 * u0'; 107 | g2 = tm2(:, 1:n + 1) * v'; 108 | if tw > 1 - tw 109 | g3 = - (cos(pi * dcs3 / tw) * c1' + sin(pi * dcs3 / tw) * s1' + dm3 * u1'); 110 | else 111 | g3 = tm3(:, 1:n + 1) * v' - (cos(pi * dcs3 / tw) * c1' + sin(pi * dcs3 / tw) * s1' + dm3 * u1'); 112 | end 113 | output(tt > -tw & tt <= tw) = output(tt > -tw & tt <= tw) + g1; 114 | output(tt > tw & tt <= 1 - tw) = output(tt > tw & tt <= 1 - tw) + g2; 115 | output(tt > 1 - tw & tt <= 1 + tw) = output(tt > 1 - tw & tt <= 1 + tw) + g3; 116 | if tw > 1 - tw 117 | output(tt > tw & tt <= 1 + tw) = output(tt > tw & tt <= 1 + tw) + tm4(:, 1:n + 1) * v'; 118 | end 119 | end 120 | -------------------------------------------------------------------------------- /src/antialiasedFLmodelSingle.m: -------------------------------------------------------------------------------- 1 | function output = antialiasedFLmodelSingle(phase_i, A, B, C, R, F, D, fs, mean_fO) 2 | % generate single cycle of Fujisaki-Ljungqvist glottal source model with 3 | % anti-aliasing in the continuous time domain. 4 | % output = antialiasedFLmodelSingle(phase_i, A, B, C, R, F, D, fs, mean_fO) 5 | % 6 | % Input argument 7 | % phase_i : discrete cumulative phase sequence of FO component (radian) 8 | % A, B, C, R, F, D : Parameter of the F-L model. (T=1 is assumed.) 9 | % fs : sampling frequency (Hz) 10 | % mean_fO : representative fundamental frequency of this cycle (Hz) 11 | % This is used for desingning the anti-aliasing response 12 | % 13 | % Output 14 | % output : structure with the following fields 15 | % g : generated L-F model signal defined on phase_i locations 16 | % segment_1, 2, 3, 4 : constituent polynomial pulse of each segment 17 | % index_1, 2, 3, 4 : index where each segment values are added 18 | 19 | % 18/Jan./2017 by Hideki Kawahara 20 | % 26/Sept./2017 fixed bug. by Hideki Kawahara 21 | 22 | W = (R + F); 23 | S = (R + F) / (R - F); 24 | T = 1; 25 | alphaa = (4 * A * R + 6 * F * B) / (2 * R^2 - F^2); % 26/Sept./2017 fix 26 | betaa = (C * D) / (D - 3 * (T - W)); 27 | 28 | poly1 = [A, - (2 * A + R * alphaa) / R, (A + R * alphaa) / R^2]'; 29 | poly2 = [0, alphaa, (3 * B - 2 * F * alphaa) / (F^2), ... 30 | - (2 * B - F * alphaa) / (F^3)]'; 31 | poly3 = [C, -2 * (C - betaa) / D, (C - betaa) / D^2]'; 32 | poly4 = [betaa, 0]'; 33 | 34 | t = phase_i / 2 / pi; 35 | d_t = 1 / fs * mean_fO; 36 | g = phase_i(:) * 0; 37 | margin_p = 6 * d_t; 38 | index_v = (1:length(phase_i))'; 39 | seg1 = t(-margin_p < t & t <= R + margin_p) / R; 40 | idx1 = index_v(-margin_p < t & t <= R + margin_p); 41 | tw = 4 * d_t / R; 42 | output1 = antiAliasedPolynomialSegment(poly1 .* [1, R, R^2]', seg1, tw); 43 | g(idx1) = g(idx1) + output1; 44 | seg2 = (t(R - margin_p < t & t <= W + margin_p) - R) / F; 45 | idx2 = index_v(R - margin_p < t & t <= W + margin_p); 46 | tw = 4 * d_t / F; 47 | output2 = antiAliasedPolynomialSegment(poly2 .* [1, F, F^2, F^3]', seg2, tw); 48 | g(idx2) = g(idx2) + output2; 49 | seg3 = (t(W - margin_p < t & t <= W + D + margin_p) - W) / D; 50 | idx3 = index_v(W - margin_p < t & t <= W + D + margin_p); 51 | tw = 4 * d_t / D; 52 | output3 = antiAliasedPolynomialSegment(poly3 .* [1, D, D^2]', seg3, tw); 53 | g(idx3) = g(idx3) + output3; 54 | seg4 = (t(W + D - margin_p < t & t <= 1 + margin_p) - D - W) / (1 - D - W); 55 | idx4 = index_v(W + D - margin_p < t & t <= 1 + margin_p); 56 | tw = 4 * d_t / (1 - D - W); 57 | output4 = antiAliasedPolynomialSegment(poly4 .* [1, D]', seg4, tw); 58 | g(idx4) = g(idx4) + output4; 59 | output.g = g; 60 | output.segment_1 = output1; 61 | output.index_1 = idx1; 62 | output.segment_2 = output2; 63 | output.index_2 = idx2; 64 | output.segment_3 = output3; 65 | output.index_3 = idx3; 66 | output.segment_4 = output4; 67 | output.index_4 = idx4; 68 | output.totalFlow = sum(cumsum(g(t > 0 & t < 1))) / sum(t > 0 & t < 1); 69 | end -------------------------------------------------------------------------------- /src/antialiasedFLmodelSingleR.m: -------------------------------------------------------------------------------- 1 | function output = antialiasedFLmodelSingleR(phase_i, A, B, C, R, F, D, fs, mean_fO) 2 | % generate single cycle of Fujisaki-Ljungqvist glottal source model with 3 | % anti-aliasing in the continuous time domain. 4 | % output = antialiasedFLmodelSingleR(phase_i, A, B, C, R, F, D, fs, mean_fO) 5 | % 6 | % Input argument 7 | % phase_i : discrete cumulative phase sequence of FO component (radian) 8 | % A, B, C, R, F, D : Parameter of the F-L model. (T=1 is assumed.) 9 | % fs : sampling frequency (Hz) 10 | % mean_fO : representative fundamental frequency of this cycle (Hz) 11 | % This is used for desingning the anti-aliasing response 12 | % 13 | % Output 14 | % output : structure with the following fields 15 | % g : generated L-F model signal defined on phase_i locations 16 | % segment_1, 2, 3, 4 : constituent polynomial pulse of each segment 17 | % index_1, 2, 3, 4 : index where each segment values are added 18 | 19 | % 18/Jan./2017 by Hideki Kawahara 20 | % 11/Feb./2017 new antialiasing function 21 | 22 | W = (R + F); 23 | S = (R + F) / (R - F); 24 | T = 1; 25 | alphaa = (4 * A * R + 6 * F * B) / (2 * R^2 - F^2); % 26/Sept./2017 fix 26 | betaa = (C * D) / (D - 3 * (T - W)); 27 | 28 | poly1 = [A, - (2 * A + R * alphaa) / R, (A + R * alphaa) / R^2]'; 29 | poly2 = [0, alphaa, (3 * B - 2 * F * alphaa) / (F^2), ... 30 | - (2 * B - F * alphaa) / (F^3)]'; 31 | poly3 = [C, -2 * (C - betaa) / D, (C - betaa) / D^2]'; 32 | poly4 = [betaa, 0]'; 33 | 34 | t = phase_i / 2 / pi; 35 | d_t = 1 / fs * mean_fO; 36 | g = phase_i(:) * 0; 37 | margin_p = 8 * d_t; 38 | index_v = (1:length(phase_i))'; 39 | seg1 = t(-margin_p < t & t <= R + margin_p) / R; 40 | idx1 = index_v(-margin_p < t & t <= R + margin_p); 41 | tw = 4 * d_t / R; 42 | output1 = antiAliasedPolynomialSegmentR(poly1 .* [1, R, R^2]', seg1, tw); 43 | g(idx1) = g(idx1) + output1; 44 | seg2 = (t(R - margin_p < t & t <= W + margin_p) - R) / F; 45 | idx2 = index_v(R - margin_p < t & t <= W + margin_p); 46 | tw = 4 * d_t / F; 47 | output2 = antiAliasedPolynomialSegmentR(poly2 .* [1, F, F^2, F^3]', seg2, tw); 48 | g(idx2) = g(idx2) + output2; 49 | seg3 = (t(W - margin_p < t & t <= W + D + margin_p) - W) / D; 50 | idx3 = index_v(W - margin_p < t & t <= W + D + margin_p); 51 | tw = 4 * d_t / D; 52 | output3 = antiAliasedPolynomialSegmentR(poly3 .* [1, D, D^2]', seg3, tw); 53 | g(idx3) = g(idx3) + output3; 54 | seg4 = (t(W + D - margin_p < t & t <= 1 + margin_p) - D - W) / (1 - D - W); 55 | idx4 = index_v(W + D - margin_p < t & t <= 1 + margin_p); 56 | tw = 4 * d_t / (1 - D - W); 57 | output4 = antiAliasedPolynomialSegmentR(poly4 .* [1, D]', seg4, tw); 58 | g(idx4) = g(idx4) + output4; 59 | output.g = g; 60 | output.segment_1 = output1; 61 | output.index_1 = idx1; 62 | output.segment_2 = output2; 63 | output.index_2 = idx2; 64 | output.segment_3 = output3; 65 | output.index_3 = idx3; 66 | output.segment_4 = output4; 67 | output.index_4 = idx4; 68 | output.totalFlow = sum(cumsum(g(t > 0 & t < 1))) / sum(t > 0 & t < 1); 69 | end -------------------------------------------------------------------------------- /src/closeI2k0xi0.m: -------------------------------------------------------------------------------- 1 | function out = closeI2k0xi0(t,Tw,td) 2 | out = -r(t-Tw)+r(t+Tw)+r(t-td-Tw)-r(t-td+Tw); 3 | 4 | function rout = r(x) 5 | rout = double(x.*(x>0)); -------------------------------------------------------------------------------- /src/closeI2kn0.m: -------------------------------------------------------------------------------- 1 | function out = closeI2kn0(t,Tw,td,k) 2 | out = Tw/k/pi*sin(k*pi*t.*(abs(t)Tw & t-td-Tw & t-td<-Tw); 4 | coeff = -beetaa+1i*k*pi/Tw; 5 | out = (real(1/coeff*(exp(coeff*t).*(abs(t)<=Tw)-exp(coeff*(t-td)).*(abs(t-td)<=Tw)))+ ... 6 | (-1)^k*real(1/coeff)*(u1*exp(-beetaa*Tw)-u2*exp(beetaa*Tw))).*exp(beetaa*t); 7 | 8 | -------------------------------------------------------------------------------- /src/closeI4k0.m: -------------------------------------------------------------------------------- 1 | function out = closeI4k0(t,Tw,td,beetaa) 2 | u1 = double(t>Tw & t-td-Tw & t-td<-Tw); 4 | out = -(1/beetaa)*(exp(-beetaa*t).*(abs(t)<=Tw)-exp(-beetaa*(t-td)).*(abs(t-td)<=Tw)+ ... 5 | u1*exp(-beetaa*Tw)-u2*exp(beetaa*Tw)); 6 | out = out.*exp(-beetaa*t); 7 | 8 | -------------------------------------------------------------------------------- /src/desa2.m: -------------------------------------------------------------------------------- 1 | function output = desa2(x, fs) 2 | phx = tkeo(x); 3 | phy = tkeo(x([2:end, end]) - x([1, 1:end-1])); 4 | omg = asin(real(sqrt(phy ./ phx / 4))); 5 | amp = 2 * phx ./ real(sqrt(phy)); 6 | output.omg = omg([3, 3, 3:end-2, end-2, end-2]) * fs; 7 | output.amp = amp([3, 3, 3:end-2, end-2, end-2]); 8 | end 9 | 10 | function phi = tkeo(x) 11 | phi = x .^ 2 - x([1, 1:end-1]) .* x([2:end, end]); 12 | end -------------------------------------------------------------------------------- /src/designCos6Wavelet.m: -------------------------------------------------------------------------------- 1 | function output = designCos6Wavelet(fs, fl, fh, fftl, mag, channels_oct) 2 | input_parameters.sampling_frequency = fs; 3 | input_parameters.lower_frequency = fl; 4 | input_parameters.higher_frequency = fh; 5 | input_parameters.fft_length = fftl; 6 | input_parameters.stretching_factor = mag; 7 | input_parameters.channels_per_octave = channels_oct; 8 | fx = (0:fftl-1)/fftl*fs; 9 | fc_list = fl * 2.0 .^ (0:1/channels_oct:log2(fh/fl)); 10 | fx(fx > fs / 2) = fx(fx > fs / 2) - fs; 11 | ak = [0.2624710164;0.4265335164;0.2250165621;0.0726831633;0.0125124215;0.0007833203]; 12 | wvlt = struct; 13 | for ii = 1:length(fc_list) 14 | fc = fc_list(ii); 15 | n_to = round(mag * 3 * fs / fc); 16 | tx_we = (-n_to:n_to)'/ n_to; 17 | tx = (-n_to:n_to)'/ fs; 18 | we = cos(tx_we * [0 1 2 3 4 5] * pi) * ak; 19 | wr = we .* cos(2 * pi * tx * fc); 20 | wi = we .* sin(2 * pi * tx * fc); 21 | wvlt(ii).w = (wr+1i*wi)/sum(we); 22 | wvlt(ii).bias = n_to; 23 | wvlt(ii).t_axis = tx; 24 | end 25 | wcmp = wvlt(1).w * 0; 26 | centerIdx = wvlt(1).bias + 1; 27 | for ii = 1:length(wvlt) 28 | tmpIdx = -wvlt(ii).bias:wvlt(ii).bias; 29 | wcmp(centerIdx + tmpIdx) = wcmp(centerIdx + tmpIdx) + wvlt(ii).w; 30 | end 31 | %--- calibration for linear phase filter 32 | x1khz = exp(1i * 2 * pi * 1000 * (1:fs)' / fs); 33 | y1khz = fftfilt(wcmp, x1khz); 34 | cf = mean(abs(y1khz(3 * centerIdx:end - 3 * centerIdx))); 35 | wcmp = wcmp / cf; 36 | w_gain = 20*log10(abs(fft(wcmp, fftl))); 37 | %--- 38 | output.input_parameters = input_parameters; 39 | output.fc_list = fc_list; 40 | output.centerIdx = wvlt(1).bias + 1; 41 | output.f_axis = fx; 42 | output.response = wcmp; 43 | output.gain = w_gain; 44 | output.wvlt = wvlt; 45 | end -------------------------------------------------------------------------------- /src/equalizerDesignAAFX.m: -------------------------------------------------------------------------------- 1 | function equalizerStr = equalizerDesignAAFX(cosineCoefficient,upperLimit,halfSample,scale) 2 | % equalizerStr = equalizerDesignAAFX(cosineCoefficient,upperLimit, halfSample) 3 | % cosineCoefficient : [a0, a1, ... , ak] for example for Nuttallwin12 4 | % [0.355768 0.487396 0.144232 0.012604] 5 | % upperLimit : in dB for 85% flat range, 50 dB is for Nuttallwin12 6 | % halfSample : in sample points. 80 sample is used for IEICE TR 2015 7 | % scale : first zero frequency (Nuttall-11 is one) 8 | % with minimun phase window length adjustment 9 | 10 | % Designed and coded by Hideki Kawahara 11 | % 05/July/2015 12 | % 22/Jan./2017 fixed fragility 13 | % 23/Jan./2017 IIR filter implementation 14 | % 11/Jan./2017 revised for new implementation 15 | 16 | %Copyright 2017 Hideki Kawahara 17 | % 18 | %Licensed under the Apache License, Version 2.0 (the "License"); 19 | %you may not use this file except in compliance with the License. 20 | %You may obtain a copy of the License at 21 | % 22 | % http://www.apache.org/licenses/LICENSE-2.0 23 | % 24 | %Unless required by applicable law or agreed to in writing, software 25 | %distributed under the License is distributed on an "AS IS" BASIS, 26 | %WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 27 | %See the License for the specific language governing permissions and 28 | %limitations under the License. 29 | 30 | fs = 8000; % Any frequency is OK. 31 | Tw = 4/(fs); 32 | fftl = 32768; 33 | fx = (0:fftl-1)'/fftl*fs; 34 | fx(fx > fs / 2) = fx(fx > fs / 2) - fs; 35 | omg = 2*pi*fx * scale; 36 | ak = cosineCoefficient; 37 | epss = 10 ^ (-13); % safeguard 38 | h_denom1 = omg * (Tw * ones(1, length(ak))) + pi * ones(length(omg), 1) * (0:length(ak) - 1); 39 | h_denom2 = omg * (Tw * ones(1, length(ak))) - pi * ones(length(omg), 1) * (0:length(ak) - 1); 40 | h1 = sin(h_denom1) ./ h_denom1; 41 | h2 = sin(h_denom2) ./ h_denom2; 42 | h1(abs(h_denom1) < epss) = 1; 43 | h2(abs(h_denom2) < epss) = 1; 44 | hh = (h1 + h2) * ak(:); 45 | hh = hh/2/ak(1); 46 | hh(1) = 1; 47 | %--- clean up hh -- 48 | for ii = 2:length(hh)-1 49 | if isnan(hh(ii)) 50 | hh(ii) = (hh(ii-1)+hh(ii+1))/2; 51 | end; 52 | end; 53 | %--- equalizer design 54 | hhdd = hh; 55 | hhdd(end:-1:fftl/2+1) = hh(2:fftl/2+1); 56 | gg = min(10^(upperLimit/20),1.0./hhdd); 57 | 58 | %-- linear phase FIR equalizer 59 | hl = halfSample; 60 | ww = nuttallwin12(2*hl+1); 61 | ihh = fftshift(real(ifft(gg))); 62 | 63 | eqqh = ihh(fftl/2+(-hl:hl)+1).*ww; 64 | %-- minimum phase response 65 | cepstrum = ifft(log(gg)); 66 | comlexCepstrum = cepstrum; 67 | comlexCepstrum(2:fftl/2) = cepstrum(2:fftl/2)*2; 68 | comlexCepstrum(fftl/2+1:end) = 0; 69 | mmResp = real(ifft(exp(fft(comlexCepstrum)))); 70 | hl2 = round(hl*1.36); 71 | ww2 = nuttallwin12(2*hl2+1); 72 | %-- IIR filter design 73 | eqpw = abs(fft(eqqh/sum(eqqh), fftl)).^2; 74 | eqac = real(ifft(eqpw)); 75 | r = eqac(1:7) / eqac(1); 76 | a = levinson(r); 77 | %-- output section 78 | equalizerStr.response = eqqh/sum(eqqh); 79 | equalizerStr.iirCoefficient = a; 80 | equalizerStr.minimumPhaseResponse = mmResp; 81 | equalizerStr.minimumPhaseResponseW = mmResp(1:hl2+1).*ww2(hl2+1:2*hl2+1); 82 | equalizerStr.minimumPhaseResponseW = equalizerStr.minimumPhaseResponseW/sum(equalizerStr.minimumPhaseResponseW); 83 | equalizerStr.antiCausalResp = equalizerStr.minimumPhaseResponseW(end:-1:1); 84 | equalizerStr.timeIndex = -hl:hl; 85 | equalizerStr.fAxis = fx(1:fftl/2+1)/fs; 86 | equalizerStr.originalLPFGain = hh(1:fftl/2+1); 87 | equalizerStr.fftl = fftl; 88 | end 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /src/generateAALFmodelOut.m: -------------------------------------------------------------------------------- 1 | function output = generateAALFmodelOut(timeAxis, modelParameter, two) 2 | % output = generateAALFmodelOut(timeAxis, modelParameter, two) 3 | % Generate one cycle of antialiased L-F model output 4 | % antialiasing uses 6-term cosine series 5 | % 6 | % Argument 7 | % timeAxis : normalized time axis (normalized time: T0 = 1) 8 | % modelParameter : structure with the following fields 9 | % tp, te, ta, tc : F-L model parameters 10 | % two : nominal half length of the antialiasing function 11 | % 12 | % Output 13 | % output : structure witht the following fields 14 | % antiAliasedSource : antialiased L-F model output (no equalization) 15 | % source : direct discretization of L-F model output 16 | % volumeVerocity : volume velocity (no equalization) 17 | 18 | %Copyright 2017 Hideki Kawahara 19 | % 20 | %Licensed under the Apache License, Version 2.0 (the "License"); 21 | %you may not use this file except in compliance with the License. 22 | %You may obtain a copy of the License at 23 | % 24 | % http://www.apache.org/licenses/LICENSE-2.0 25 | % 26 | %Unless required by applicable law or agreed to in writing, software 27 | %distributed under the License is distributed on an "AS IS" BASIS, 28 | %WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 | %See the License for the specific language governing permissions and 30 | %limitations under the License. 31 | 32 | margin = two * 2; 33 | te = modelParameter.te; 34 | ta = modelParameter.ta; 35 | tc = modelParameter.tc; 36 | seg1 = timeAxis(timeAxis > 0 & timeAxis < modelParameter.te); 37 | seg2 = timeAxis(timeAxis >= modelParameter.te & ... 38 | modelParameter.tc > timeAxis); 39 | source = timeAxis * 0; 40 | antialiasedSignal = timeAxis * 0; 41 | cf = - exp(- modelParameter.alphaa * modelParameter.te) / ... 42 | sin(modelParameter.omegaG * modelParameter.te); 43 | opening = cf * exp(modelParameter.alphaa * seg1) .* ... 44 | sin(modelParameter.omegaG * seg1); 45 | source(timeAxis > 0 & timeAxis < modelParameter.te) = opening; 46 | closing = -1 / (modelParameter.betaa * modelParameter.ta) * ... 47 | (exp(-modelParameter.betaa * (seg2 - modelParameter.te)) ... 48 | - exp(-modelParameter.betaa * (modelParameter.tc - modelParameter.te))); 49 | source(timeAxis >= modelParameter.te & modelParameter.tc > timeAxis) = ... 50 | closing; 51 | %---- Ug 52 | vv = timeAxis * 0; 53 | openVV = -(modelParameter.alphaa * sin(modelParameter.omegaG * seg1) ... 54 | - modelParameter.omegaG * cos(modelParameter.omegaG * seg1) ... 55 | + modelParameter.omegaG * exp(-modelParameter.alphaa * seg1)) ... 56 | / (modelParameter.alphaa^2 + modelParameter.omegaG^2) / sin(modelParameter.omegaG * te); 57 | boundaryVV = -(modelParameter.alphaa * sin(modelParameter.omegaG * te) ... 58 | - modelParameter.omegaG * cos(modelParameter.omegaG * te) ... 59 | + modelParameter.omegaG * exp(-modelParameter.alphaa * te)) ... 60 | / (modelParameter.alphaa^2 + modelParameter.omegaG^2) / sin(modelParameter.omegaG * te); 61 | closeVV = ((seg2 - te) * exp(-modelParameter.betaa * (tc - te))) / modelParameter.betaa / ta ... 62 | + (exp(-modelParameter.betaa * (seg2 - te)) - 1) / modelParameter.betaa^2 / ta; 63 | vv(timeAxis > 0 & timeAxis < modelParameter.te) = openVV; 64 | vv(timeAxis >= modelParameter.te & modelParameter.tc > timeAxis) = ... 65 | closeVV + boundaryVV; 66 | %---- 67 | select1 = timeAxis > - margin & timeAxis < modelParameter.te + margin; 68 | select2 = timeAxis >= modelParameter.te - margin & ... 69 | modelParameter.tc + margin > timeAxis; 70 | exSeg1 = timeAxis(select1); 71 | exSeg2 = timeAxis(select2); 72 | piece1 = exSeg1 / modelParameter.te; 73 | piece2 = (exSeg2 - modelParameter.te) ... 74 | / (modelParameter.tc - modelParameter.te); 75 | tw1 = two / modelParameter.te; 76 | tw2 = two / (modelParameter.tc - modelParameter.te); 77 | beta1 = (modelParameter.alphaa + 1i * modelParameter.omegaG) * modelParameter.te; 78 | out1 = cf * imag(antiAliasedCExponentialSegment(beta1, piece1, tw1)); 79 | beta2 = -modelParameter.betaa * (modelParameter.tc - modelParameter.te); 80 | tmp1 = real(antiAliasedCExponentialSegment(beta2, piece2, tw2)); 81 | tmp2 = antiAliasedPolynomialSegmentR([1 0], piece2, tw2); 82 | out2 = -tmp1 / (modelParameter.betaa * modelParameter.ta); 83 | out3 = exp(-modelParameter.betaa * (modelParameter.tc - modelParameter.te)) ... 84 | * tmp2(:) / (modelParameter.betaa * modelParameter.ta); 85 | antialiasedSignal(select1) = antialiasedSignal(select1) + out1; 86 | antialiasedSignal(select2) = antialiasedSignal(select2) + out2 + out3; 87 | output.source = source; 88 | output.antialiasedSignal = antialiasedSignal; 89 | output.volumeVerocity = vv; 90 | end -------------------------------------------------------------------------------- /src/generateLFmodelParameter.m: -------------------------------------------------------------------------------- 1 | function output = generateLFmodelParameter(tp, te, ta, tc) 2 | % output = generateLFmodelParameter(tp, te, ta, tc) 3 | % generate L-F model coefficients from time parameters 4 | % 5 | % Argument 6 | % tp, te, ta, tc : L-F model time parameters 7 | % 8 | % Output 9 | % output : structure with the following fields 10 | % omegaG, betaa, alphaa : L-F model coefficients 11 | % tp, te, ta, tc : L-F model time parameters (copy of input) 12 | 13 | % by Hideki Kawahara : kawahara@sys.wakayama-u.ac.jp 14 | 15 | %Copyright 2017 Hideki Kawahara 16 | % 17 | %Licensed under the Apache License, Version 2.0 (the "License"); 18 | %you may not use this file except in compliance with the License. 19 | %You may obtain a copy of the License at 20 | % 21 | % http://www.apache.org/licenses/LICENSE-2.0 22 | % 23 | %Unless required by applicable law or agreed to in writing, software 24 | %distributed under the License is distributed on an "AS IS" BASIS, 25 | %WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 | %See the License for the specific language governing permissions and 27 | %limitations under the License. 28 | 29 | fg = 1 / (2 * tp); 30 | omegaG = 2 * pi * fg; 31 | %--- design exponential decay 32 | myfun = @(x, ta, te) (ta * x - 1 + exp(-x * (tc - te))); 33 | fun = @(x) myfun(x, ta, te); 34 | betaa = fzero(fun,1 / ta); 35 | output.omegaG = omegaG; 36 | output.betaa = betaa; 37 | %--- design ramped sinusoid 38 | myfun2 = @(x, ta, te, tc, omegaG, betaa)(-(x * sin(omegaG * te) ... 39 | - omegaG * cos(omegaG * te) + exp(-x * te) * omegaG) ... 40 | / (x^2 + omegaG^2) / sin(omegaG * te) ... 41 | + ((tc - te) * exp(-betaa * (tc - te)) - ta) / (betaa * ta)); 42 | fun2 = @(x) myfun2(x, ta, te, tc, omegaG, betaa); 43 | alphaa = fzero(fun2, 2); 44 | output.alphaa = alphaa; 45 | output.te = te; 46 | output.tp = tp; 47 | output.ta = ta; 48 | output.tc = tc; 49 | end -------------------------------------------------------------------------------- /src/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Hideki Kawahara 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /src/nuttallwin12.m: -------------------------------------------------------------------------------- 1 | function w = nuttallwin12(N) 2 | % w = nuttallwin12(N) 3 | % Nuttall window with continuous first order derivative 4 | % No.12 example in [1] 5 | 6 | % 19/August/2011 by Hideki Kawahara 7 | 8 | % Reference: 9 | % [1] Nuttall, A.; ``Some windows with very good sidelobe behavior,'' 10 | % Acoustics, Speech and Signal Processing, IEEE Transactions on , 11 | % vol.29, no.1, pp. 84--91, Feb 1981. 12 | % doi: 10.1109/TASSP.1981.1163506 13 | 14 | x = (0:N-1)'*2*pi/(N-1); 15 | aa = [0.355768 0.487396 0.144232 0.012604]; 16 | BB = [aa(1); -aa(2); aa(3); -aa(4)]; 17 | w = cos(x* [0 1 2 3]) * BB; -------------------------------------------------------------------------------- /src/openI5.m: -------------------------------------------------------------------------------- 1 | function out = openI5(t,Tw,te,alphaa,omgg,k) 2 | 3 | % 08/Nov./2015 bug fix for concatination 4 | u1 = double(t>Tw & t-te-Tw & t-te<-Tw); 6 | term1 = (-1)^k*(u1.*exp((-alphaa-1i*omgg)*Tw) ... 7 | -u2.*exp(-(-alphaa-1i*omgg)*Tw)); 8 | term2 = exp((-alphaa-1i*omgg+1i*k*pi/Tw)*t).*(-Tw< t & t <=Tw);%fix 9 | term3 = exp((-alphaa-1i*omgg+1i*k*pi/Tw)*(t-te)).*(-Tw < t-te & t-te <=Tw); %fix 10 | out = (term1+term2-term3)/(-alphaa-1i*omgg+1i*k*pi/Tw); -------------------------------------------------------------------------------- /src/openTermk.m: -------------------------------------------------------------------------------- 1 | function out = openTermk(t,Tw,te,alphaa,omgg,k) 2 | out = imag(exp(1i*omgg*t).*openI5(t,Tw,te,alphaa,omgg,k) ... 3 | -exp(-1i*omgg*t).*openI5(t,Tw,te,alphaa,-omgg,k)).*exp(alphaa*t)/2; -------------------------------------------------------------------------------- /src/perturbationFunction.m: -------------------------------------------------------------------------------- 1 | function perturbationOut = perturbationFunction(perturbation) 2 | persistent stateMem; 3 | if ~(length(stateMem) == 0) 4 | stateMem = stateMem+1; 5 | else 6 | stateMem = 1; 7 | end; 8 | switch perturbation 9 | case 'gaussian' 10 | perturbationOut = randn; 11 | case 'P0MRandom' 12 | perturbationOut = round((rand-0.5)*2.9999); 13 | case 'Alteration' 14 | if rem(stateMem,2) == 0 15 | perturbationOut = 1; 16 | else 17 | perturbationOut = -1; 18 | end; 19 | end; 20 | end 21 | -------------------------------------------------------------------------------- /src/perturbationFunction2.m: -------------------------------------------------------------------------------- 1 | function perturbationOut = perturbationFunction2(perturbation) 2 | persistent stateMem; 3 | if ~(length(stateMem) == 0) 4 | stateMem = stateMem+1; 5 | else 6 | stateMem = 1; 7 | end; 8 | switch perturbation 9 | case 'gaussian' 10 | perturbationOut = randn; 11 | case 'P0MRandom' 12 | perturbationOut = round((rand-0.5)*2.9999); 13 | case 'Alteration' 14 | if rem(stateMem,2) == 0 15 | perturbationOut = 1; 16 | else 17 | perturbationOut = -1; 18 | end; 19 | end; 20 | end 21 | -------------------------------------------------------------------------------- /src/rawFLmodelSingle.m: -------------------------------------------------------------------------------- 1 | function output = rawFLmodelSingle(phase_i, A, B, C, R, F, D) 2 | % generate single cycle of Fujisaki-Ljungqvist glottal source model without 3 | % anti-aliasing in the continuous time domain. 4 | % output = rawFLmodelSingle(phase_i, A, B, C, R, F, D) 5 | % 6 | % Input argument 7 | % phase_i : discrete cumulative phase sequence of FO component (radian) 8 | % A, B, C, R, F, D : Parameter of the F-L model. (T=1 is assumed.) 9 | % 10 | % Output 11 | % output : structure with the following fields 12 | % g : generated L-F model signal defined on phase_i locations 13 | % segment_1, 2, 3, 4 : constituent polynomial pulse of each segment 14 | % index_1, 2, 3, 4 : index where each segment values are added 15 | 16 | % 19/Jan./2017 by Hideki Kawahara 17 | % 26/Sept./2017 bug fixed by Hideki Kawahara 18 | % This is free to modify and use. 19 | 20 | W = (R + F); 21 | T = 1; 22 | alphaa = (4 * A * R + 6 * F * B) / (2 * R^2 - F^2); % fix 26/Sept./2017 23 | betaa = (C * D) / (D - 3 * (T - W)); 24 | 25 | poly1 = [A, - (2 * A + R * alphaa) / R, (A + R * alphaa) / R^2]'; 26 | poly2 = [0, alphaa, (3 * B - 2 * F * alphaa) / (F^2), ... 27 | - (2 * B - F * alphaa) / (F^3)]'; 28 | poly3 = [C, -2 * (C - betaa) / D, (C - betaa) / D^2]'; 29 | poly4 = [betaa, 0]'; 30 | 31 | t = phase_i / 2 / pi; 32 | g = phase_i(:) * 0; 33 | index_v = (1:length(phase_i))'; 34 | seg1 = t(0 <= t & t <= R); 35 | idx1 = index_v(0 <= t & t <= R); 36 | g(idx1) = g(idx1) + (seg1 .^ (0:2)) * poly1; 37 | seg2 = t(R < t & t <= W); 38 | idx2 = index_v(R < t & t <= W); 39 | g(idx2) = g(idx2) + ((seg2 - R) .^ (0:3)) * poly2; 40 | seg3 = t(W < t & t <= W + D); 41 | idx3 = index_v(W < t & t <= W + D); 42 | g(idx3) = g(idx3) + ((seg3 - W) .^ (0:2)) * poly3; 43 | seg4 = t(W + D < t & t <= 1); 44 | idx4 = index_v(W + D < t & t <= 1); 45 | g(idx4) = g(idx4) + ((seg4 - W - D) .^ (0:1)) * poly4; 46 | output.g = g; 47 | output.segment_1 = (seg1 .^ (0:2)) * poly1; 48 | output.index_1 = idx1; 49 | output.segment_2 = ((seg2 - R) .^ (0:3)) * poly2; 50 | output.index_2 = idx2; 51 | output.segment_3 = ((seg3 - W) .^ (0:2)) * poly3; 52 | output.index_3 = idx3; 53 | output.segment_4 = ((seg4 - W - D) .^ (0:1)) * poly4; 54 | output.index_4 = idx4; 55 | output.alpha = alphaa; 56 | output.beta = betaa; 57 | end -------------------------------------------------------------------------------- /src/releasenote.txt: -------------------------------------------------------------------------------- 1 | Release note for SparkNG 2 | 3 | Hideki Kawahara 4 | Professor Emeritus, Wakayama University, Japan 5 | mailto:kawahara@sys.wakayama-u.ac.jp 6 | 7 | History 8 | SparkNG (Speech Production and Auditory perception Research Kernel the Next Generation) is a collection of Matlab Tools designed for mainly introduction to speech and hearing science. They were distributed in two independent packages. One is "Matlab realtime tools" (Creative Commons license) and the other is "Matlab speech production tool" (BSD two clause license), since the former only consists of elemetary textbook algorithms. By merging these two distributions and licensing them under BSD two clause license, more up-to-date algrithms can be introduced constituent tools. 9 | 10 | Why NG? 11 | It does not mean "No Good". The author released an Pascal-based interactive speech tool, called "Spark" in 1986. In 1989, it was released as a comercial product under the name of "Onsei Koubou" (Speech factory, in English). This time, the author decided to replicate the effort he did 30 years ago, in a more complehensive manner, hoping for this set of tools to facilitate progress in speech production, perception and processing research especially on aspects which make speech far more rich media for communication than texts. Advances in signal processing theory, algorithms and hardware performance make it possible to design a set of tools which supersede old "Spark" order of magnitude in every aspect. It deserves to be called "Next Generation." 12 | 13 | Hideki Kawahara 14 | 20 October, 2015. 15 | 16 | Release note 17 | 18 | Version 0.83: special release for APSIPA 2015 date 20 December 2015. 19 | Extended LF model control and enhanced visualization 20 | GUI tuning is still under construction. May consists of many bugs. 21 | 22 | Version 0.81: release date 17 November 2015 23 | Input sound monitoring and composite spectrum envelope display. 24 | 25 | Version 0.8: release date 10 November 2015. 26 | 27 | Version 0.7: release date 20 October 2015. 28 | 29 | Release v24 30 | GUIs are resizable. 31 | 32 | Release v22 33 | This version is preliminary. Please check the following page for updates. 34 | Release data: 21 August 2015 35 | -------------------------------------------------------------------------------- /src/signal2logArea.m: -------------------------------------------------------------------------------- 1 | function logArea = signal2logArea(x) 2 | % by Hideki Kawahara 3 | % This is only a quick and dirty hack. Please refer to proper reference 4 | % for estimating vocal tract area function. 5 | % 18/Jan./2014 6 | 7 | % This is valid only for signals sampled at 8000Hz. 8 | 9 | n = length(x); 10 | w = blackman(n); 11 | ww = w/sqrt(sum(w.^2)); 12 | fftl = 2^ceil(log2(n)); 13 | %x = [0;x(2:end)-0.925*x(1:end-1)]; 14 | x = [0;diff(x)]; 15 | pw = abs(fft(x.*ww,fftl)).^2; 16 | lpw = log(pw+sum(pw)/fftl/1000); 17 | lpwn = lpw-mean(lpw); 18 | theta = (0:fftl-1)/fftl*2*pi; 19 | %c1 = 2*sum(cos(theta(:)).*lpwn)/fftl; 20 | %c2 = sum(cos(2*theta(:)).*lpwn)/fftl; % This may not be necessary. 21 | %pwc = real(exp(lpwn-c1*cos(theta(:))-c2*cos(2*theta(:)))); 22 | pwc = real(exp(lpwn-0.5*cos(theta(:))+0.5*cos(2*theta(:)))); 23 | ac = real(ifft(pwc)); 24 | [alp,err,k] = levinson(ac,9); 25 | s = ref2area(-k); 26 | logArea = log(s); 27 | end 28 | 29 | function s = ref2area(k) 30 | 31 | n = length(k); 32 | s = zeros(n+1,1); 33 | s(end) = 1; 34 | for ii = n:-1:1 35 | s(ii) = s(ii+1)*(1-k(ii))/(1+k(ii)); 36 | end; 37 | end 38 | -------------------------------------------------------------------------------- /src/simulatedFilterBank.m: -------------------------------------------------------------------------------- 1 | function filterBankStr = simulatedFilterBank(sgram,fx,bankType) 2 | % Filter bank simulator based on FFT power spectrum 3 | 4 | % 22/Dec./2013 by Hideki Kawahara 5 | % This simulation is rough approximation. Please refer to the original 6 | % papers for serious scientific applications. This routine is provided "as 7 | % is" and no warranty. 8 | % This is a sample code. Use this as you like. 9 | 10 | sgram = cumsum(sgram); 11 | fLow = 50; 12 | tickFrequencyList = [50 70 100 150 200 300 400 500 700 1000 1500 2000 3000 4000 5000 7000 10000 15000 20000]; 13 | filterBankStr.tickLabelList = char({'50';'70';'100';'150';'200';'300';'400';'500'; ... 14 | '700';'1000';'1500';'2000';'3000';'4000';'5000';'7000';'10000';'15000';'20000'}); 15 | switch bankType 16 | case 'third' 17 | logFrequencyAxis = fLow*2.0.^(0:1/24:log2(fx(end)/fLow)-1/6)'; 18 | fxUpper = logFrequencyAxis*2^(1/6); 19 | fxLower = logFrequencyAxis*2^(-1/6); 20 | upperCumPower = interp1(fx,sgram,fxUpper,'linear','extrap'); 21 | lowerCumPower = interp1(fx,sgram,fxLower,'linear','extrap'); 22 | filterBankStr.filteredSgramRectangle = upperCumPower-lowerCumPower; 23 | sgram = cumsum(filterBankStr.filteredSgramRectangle); 24 | upperCumPower = interp1(logFrequencyAxis,sgram,fxUpper,'linear','extrap'); 25 | lowerCumPower = interp1(logFrequencyAxis,sgram,fxLower,'linear','extrap'); 26 | filterBankStr.filteredSgramTriangle = upperCumPower-lowerCumPower; 27 | filterBankStr.fcList = logFrequencyAxis; 28 | case 'ERB' 29 | logFrequencyAxis = fLow*2.0.^(0:1/24:log2(fx(end)/fLow)-1/6)'; 30 | ERBofLogFrequencyAxis = freq2ERBprv(logFrequencyAxis); 31 | ERBFrequencyAxis = (0:200)'/200*(ERBofLogFrequencyAxis(end)-ERBofLogFrequencyAxis(1)) ... 32 | +ERBofLogFrequencyAxis(1); 33 | logFrequencyAxisTmp = interp1(ERBofLogFrequencyAxis,logFrequencyAxis,ERBFrequencyAxis,'linear','extrap'); 34 | %fxUpper = logFrequencyAxis*2^(1/6); 35 | fxUpper = interp1(ERBofLogFrequencyAxis,logFrequencyAxis,ERBFrequencyAxis+0.5,'linear','extrap'); 36 | fxLower = interp1(ERBofLogFrequencyAxis,logFrequencyAxis,ERBFrequencyAxis-0.5,'linear','extrap'); 37 | upperCumPower = interp1(fx,sgram,fxUpper,'linear','extrap'); 38 | lowerCumPower = interp1(fx,sgram,fxLower,'linear','extrap'); 39 | filterBankStr.filteredSgramRectangle = upperCumPower-lowerCumPower; 40 | sgram = cumsum(filterBankStr.filteredSgramRectangle); 41 | upperCumPower = interp1(logFrequencyAxisTmp,sgram,fxUpper,'linear','extrap'); 42 | lowerCumPower = interp1(logFrequencyAxisTmp,sgram,fxLower,'linear','extrap'); 43 | filterBankStr.filteredSgramTriangle = upperCumPower-lowerCumPower; 44 | filterBankStr.fcList = logFrequencyAxisTmp; 45 | case 'Bark' 46 | logFrequencyAxis = fLow*2.0.^(0:1/24:log2(fx(end)/fLow)-1/6)'; 47 | ERBofLogFrequencyAxis = freq2BarkPrv(logFrequencyAxis); 48 | ERBFrequencyAxis = (0:200)'/200*(ERBofLogFrequencyAxis(end)-ERBofLogFrequencyAxis(1)) ... 49 | +ERBofLogFrequencyAxis(1); 50 | logFrequencyAxisTmp = interp1(ERBofLogFrequencyAxis,logFrequencyAxis,ERBFrequencyAxis,'linear','extrap'); 51 | fxUpper = interp1(ERBofLogFrequencyAxis,logFrequencyAxis,ERBFrequencyAxis+0.5,'linear','extrap'); 52 | fxLower = interp1(ERBofLogFrequencyAxis,logFrequencyAxis,ERBFrequencyAxis-0.5,'linear','extrap'); 53 | upperCumPower = interp1(fx,sgram,fxUpper,'linear','extrap'); 54 | lowerCumPower = interp1(fx,sgram,fxLower,'linear','extrap'); 55 | filterBankStr.filteredSgramRectangle = upperCumPower-lowerCumPower; 56 | sgram = cumsum(filterBankStr.filteredSgramRectangle); 57 | upperCumPower = interp1(logFrequencyAxisTmp,sgram,fxUpper,'linear','extrap'); 58 | lowerCumPower = interp1(logFrequencyAxisTmp,sgram,fxLower,'linear','extrap'); 59 | filterBankStr.filteredSgramTriangle = upperCumPower-lowerCumPower; 60 | filterBankStr.fcList = logFrequencyAxisTmp; 61 | end; 62 | fxTrim = (0:length(filterBankStr.fcList)-1)/(length(filterBankStr.fcList)-1)* ... 63 | (filterBankStr.fcList(end)-filterBankStr.fcList(1))+filterBankStr.fcList(1); 64 | filterBankStr.ticLocationList = interp1(filterBankStr.fcList,fxTrim,tickFrequencyList,'linear','extrap'); 65 | end 66 | 67 | function erbAxis = freq2ERBprv(axisInHz) 68 | erbAxis=21.4*log10(0.00437*axisInHz+1); 69 | end 70 | 71 | function barkAxis = freq2BarkPrv(axisInHz) 72 | barkAxis = 26.81./(1+1960.0./axisInHz)-0.53; 73 | end 74 | -------------------------------------------------------------------------------- /src/sourceByLFmodelAAF.m: -------------------------------------------------------------------------------- 1 | function modelOut = sourceByLFmodelAAF(timeAxis,tp,te,ta,tc,Twor) 2 | % modelOut = sourceByLFmodelAAF(timeAxis,tp,te,ta,tc) 3 | % tp,te,ta, tc is assumed to be normalized by T0, the fundamental period 4 | % The time axis is also assumed to be normaized by T0. 5 | % This version is based on a closed form of anti-aliased L-F model 6 | % 7 | % Designed and coded by Hideki Kawahara 8 | % 27/May/2015 9 | % 28/May/2015 Volume velocity is added 10 | % 29/May/2015 bug fix 11 | % 22/June/2015 Anti-aliased L-F model is added 12 | % 12/June/2015 omegaG is added to the output 13 | % Definition of LF model is given by: 14 | % G.Fant, J.Liljencrants and Q.Lin,STL-QPSR,26,4,1-13,1985. 15 | 16 | ak = [0.355768 0.487396 0.144232 0.012604]'; % Nuttall win 17 | Tw = Twor/tc; 18 | t = timeAxis(:)/tc; 19 | tpN = tp/tc; 20 | teN = te/tc; 21 | taN = ta/tc; 22 | fg = 1/(2*tpN); 23 | omegaG = 2*pi*fg; 24 | et = t*0; vv = t*0; 25 | %--- design exponential decay 26 | myfun = @(x,ta,te) (x*ta-1+exp(-x*(1-te))); 27 | fun = @(x) myfun(x,taN,teN); 28 | betaa = fzero(fun,1/taN); 29 | et(t>=teN & t<1) = -1*(exp(-betaa*(t(t>=teN & t<1)-teN))-exp(-betaa*(1-teN))); 30 | vv(t>=teN & t<1) = exp(-betaa*(t(t>=teN & t<1)-teN))/betaa+ ... 31 | (t(t>=teN & t<1)-teN)*exp(-betaa*(1-teN)); 32 | boundaryValue = exp(-betaa*(1-teN))/betaa+(1-teN)*exp(-betaa*(1-teN)); 33 | %--- design ramped sinusoid 34 | a = -1/betaa+exp(-betaa*(1-teN))*(1/betaa+(1-teN)); 35 | myfun2 = @(x,wg,a,betaa,te)(a-(1-exp(-betaa*(1-te)))/(exp(x*te)*sin(wg*te))/ ... 36 | (x^2+wg^2)*(exp(x*te)*(x*sin(wg*te)-wg*cos(wg*te))+wg)); 37 | fun2 = @(x) myfun2(x,omegaG,a,betaa,teN); 38 | alphaa = fzero(fun2,0); 39 | e0 = -(1-exp(-betaa*(1-teN)))/(exp(alphaa*teN)*sin(omegaG*teN)); 40 | et(t=teN & t<1) = vv(t>=teN & t<1)-boundaryValue; % boundary condition at t=1 46 | td = 1-teN; 47 | openSig = [openTermk(t,Tw,teN,alphaa,omegaG,0) openTermk(t,Tw,teN,alphaa,omegaG,1) ... 48 | openTermk(t,Tw,teN,alphaa,omegaG,2) openTermk(t,Tw,teN,alphaa,omegaG,3)]*ak; 49 | x = t-teN; 50 | clx2 = [closeI2k0xi0(x,Tw,td) closeI2kn0(x,Tw,td,1) closeI2kn0(x,Tw,td,2) closeI2kn0(x,Tw,td,3)]*ak; 51 | clx3 = [closeI4(x,Tw,td,-betaa,0) closeI4(x,Tw,td,-betaa,1) closeI4(x,Tw,td,-betaa,2) closeI4(x,Tw,td,-betaa,3)]*ak; 52 | closingSig = clx3-exp(-betaa*td)*clx2; 53 | modelOut.normalizedTimeAxis = t; 54 | modelOut.source = et.*(t>0 & t<1); 55 | modelOut.volumeVerocity = vv; 56 | modelOut.antiAliasedSource = (e0*openSig-closingSig)/(ak(1)*2*Tw); 57 | % quick and dirty patch This patch is no-longer needed and harmful! 58 | % 11/Nov./2015 HK !! 59 | %maxValue = max(modelOut.antiAliasedSource); 60 | %for ii = 2:length(modelOut.antiAliasedSource)-1 61 | % if modelOut.antiAliasedSource(ii-1)-modelOut.antiAliasedSource(ii)>0.2*maxValue && ... 62 | % modelOut.antiAliasedSource(ii+1)-modelOut.antiAliasedSource(ii)>0.2*maxValue 63 | % modelOut.antiAliasedSource(ii) = (modelOut.antiAliasedSource(ii-1)+modelOut.antiAliasedSource(ii+1))/2; 64 | % end; 65 | %end; 66 | % end of patch 67 | modelOut.decayRate = betaa; 68 | modelOut.growthRate = alphaa; 69 | modelOut.omegaG = omegaG; 70 | 71 | -------------------------------------------------------------------------------- /src/sourceByLFmodelAAF6T.m: -------------------------------------------------------------------------------- 1 | function modelOut = sourceByLFmodelAAF6T(timeAxis, tp, te, ta, tc, Tworg) 2 | % modelOut = sourceByLFmodelAAF6T(timeAxis, tp, te, ta, tc, Tworg) 3 | % Generate one cycle of antialiased L-F model output 4 | % antialiasing uses 6-term cosine series 5 | % 6 | % Argument 7 | % timeAxis : normalized time axis (normalized time: T0 = 1) 8 | % tp, te, ta, tc : F-L model parameters 9 | % Tworg : nominal half length of the antialiasing function 10 | % 11 | % Output 12 | % modelOut : structure witht the following fields 13 | % antiAliasedSource : antialiased L-F model output (no equalization) 14 | % source : direct discretization of L-F model output 15 | % volumeVerocity : volume velocity (no equalization) 16 | 17 | % by Hideki Kawahara : kawahara@sys.wakayama-u.ac.jp 18 | 19 | %Copyright 2017 Hideki Kawahara 20 | % 21 | %Licensed under the Apache License, Version 2.0 (the "License"); 22 | %you may not use this file except in compliance with the License. 23 | %You may obtain a copy of the License at 24 | % 25 | % http://www.apache.org/licenses/LICENSE-2.0 26 | % 27 | %Unless required by applicable law or agreed to in writing, software 28 | %distributed under the License is distributed on an "AS IS" BASIS, 29 | %WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 30 | %See the License for the specific language governing permissions and 31 | %limitations under the License. 32 | 33 | modelParameter = generateLFmodelParameter(tp, te, ta, tc); 34 | output = generateAALFmodelOut(timeAxis, modelParameter, Tworg); 35 | modelOut.antiAliasedSource = output.antialiasedSignal; 36 | modelOut.source = output.source; 37 | modelOut.volumeVerocity = output.volumeVerocity; 38 | end -------------------------------------------------------------------------------- /src/stftSpectrogramStructure.m: -------------------------------------------------------------------------------- 1 | function sgramStr = stftSpectrogramStructure(x,fs,windowLengthInms,windowShiftInms,windowType,segment) 2 | % spectral analysis for F0 test 3 | % sgramStr = stftSpectrogramStructure(x,fs,windowLengthInms,windowShiftInms,windowType,segment) 4 | 5 | % 26/Nov./2011 by Hideki Kawahara 6 | % 10/Mar./2012 segment selection 7 | 8 | startTime = tic; 9 | x = x(:); 10 | halfWindowLength = round(windowLengthInms/1000*fs/2); 11 | switch nargin 12 | case 5 13 | temporalLocations = 0:windowShiftInms/1000:(length(x)-1)/fs; 14 | case 6 15 | temporalLocations = segment(1):windowShiftInms/1000:segment(2); 16 | end; 17 | temporalLocationsInSamples = round(temporalLocations*fs); 18 | w = feval(windowType,2*halfWindowLength+1); 19 | baseIndex = -halfWindowLength:halfWindowLength; 20 | fftl = 2^ceil(log2(halfWindowLength)+2); 21 | nFrames = length(temporalLocations); 22 | rawSpectrogram = zeros(fftl/2+1,nFrames); 23 | normalizedSpectrogram = zeros(fftl/2+1,nFrames); 24 | for ii = 1:nFrames 25 | tmpPwr = abs(fft(w.*x(max(1,min(length(x),baseIndex+temporalLocationsInSamples(ii)))),fftl)).^2; 26 | rawSpectrogram(:,ii) = tmpPwr(1:fftl/2+1); 27 | normalizedSpectrogram(:,ii) = rawSpectrogram(:,ii)/sum(rawSpectrogram(:,ii)); 28 | end; 29 | maxPower = max(max(rawSpectrogram)); 30 | sg = 10*log10(rawSpectrogram/maxPower + 0.0000000000001); 31 | sgramStr.dBspectrogram = sg; 32 | sgramStr.rawSpectrogram = rawSpectrogram; 33 | sgramStr.normalizedSpectrogram = normalizedSpectrogram; 34 | sgramStr.frequencyAxis = (0:fftl/2)/fftl*fs; 35 | sgramStr.temporalPositions = temporalLocations; 36 | sgramStr.samplingFrequency = fs; 37 | sgramStr.waveform = x; 38 | sgramStr.windowLengthInms = windowLengthInms; 39 | sgramStr.windowShiftInms = windowShiftInms; 40 | sgramStr.windowType = windowType; 41 | sgramStr.elapsedTime = toc(startTime); 42 | 43 | -------------------------------------------------------------------------------- /src/tubeDisplay.m: -------------------------------------------------------------------------------- 1 | function crossSection = tubeDisplay(logArea) 2 | %% 3 | areaList = exp(logArea); 4 | crossSection = sqrt(areaList/sum(areaList)); 5 | 6 | %% 7 | end -------------------------------------------------------------------------------- /src/vts20150729T011805.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/SparkNG/7eb1254c2b0e7ea6032b877099c6045c6bbf5398/src/vts20150729T011805.mat -------------------------------------------------------------------------------- /test/nuttallwin12self.m: -------------------------------------------------------------------------------- 1 | function w = nuttallwin12self(N) 2 | % w = nuttallwin12self(N) 3 | % Nuttall window with continuous first order derivative 4 | % No.12 example in [1] and self convolutoin 5 | 6 | % 19/August/2011 by Hideki Kawahara 7 | % 23/April/2014 by Hideki Kawahara 8 | 9 | % Reference: 10 | % [1] Nuttall, A.; ``Some windows with very good sidelobe behavior,'' 11 | % Acoustics, Speech and Signal Processing, IEEE Transactions on , 12 | % vol.29, no.1, pp. 84--91, Feb 1981. 13 | % doi: 10.1109/TASSP.1981.1163506 14 | 15 | a = nuttallwin12(ceil(N/2)); 16 | b = nuttallwin12(ceil((N+1)/2)); 17 | w = conv(a,b); 18 | -------------------------------------------------------------------------------- /test/testAAFjLjRevfunction.m: -------------------------------------------------------------------------------- 1 | %% Test script for revised AA Fujisaki-Ljungqvist model 2 | % This is free to modify and use. 3 | % 24, 25/Jan./2017 by Hideki Kawahara 4 | % 20/Feb./2017 5 | 6 | %clear all 7 | close all 8 | %% Desing a time varying fo trajectory 9 | % The fo value is set very high to illustrate antialiasing behavior clearly. 10 | 11 | fs = 44100; 12 | duration = 2; 13 | tt = (0:1 / fs:duration)'; 14 | mean_fO = 887; % Hz 15 | vibrato_f = 5.2;% Hz 16 | vibrato_depth = 6;% cent for peak deviation 17 | 18 | fOi = 2.0 .^ (log2(mean_fO) + vibrato_depth / 1200 * sin(2 * pi * vibrato_f * tt + 0 * randn(length(tt), 1))); 19 | %% Set Fujisaki-Ljungqvist model parameters 20 | 21 | R = 0.38; 22 | F = 0.15; 23 | D = 0.12; 24 | 25 | A = 0.2; 26 | B = -1; 27 | C = -0.6; 28 | 29 | %% Generate F-L model output 30 | 31 | output_const = AAFjLjmodelFromFOTrajectoryR(fOi, fs, A, B, C, R, F, D); 32 | 33 | %% Display waveforms of the direct digitization, antialiasing only and 34 | % antialiasing followed by equalizaiton 35 | 36 | y = output_const.antiAliasedSignal; 37 | y_only = output_const.antiAliasedOnly; 38 | y_direct = output_const.rawSignal; 39 | figure; 40 | plot((0:length(y) - 1) / fs, y_direct, 'c', 'linewidth', 5); 41 | hold all 42 | plot((0:length(y) - 1) / fs, y_only, 'r', 'linewidth', 2); 43 | plot((0:length(y) - 1) / fs, y, 'k'); 44 | grid on; 45 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica'); 46 | xlabel('time (s)'); 47 | axis([[1 3] / 1000 -1 0.3]) 48 | legend('direct', 'antialias only', 'a.a. with eq', 'location', 'southwest'); 49 | 50 | %% This also illustates how to use stftSpectrogramStructure 51 | 52 | window_length_ms = 40; 53 | window_shift_ms = 2; 54 | window_f = 'nuttallwin12self'; % self convolution of Nuttall's 12-th item 55 | sgramStrY = ... 56 | stftSpectrogramStructure(y, fs, window_length_ms, window_shift_ms, window_f); 57 | sgramStrD = ... 58 | stftSpectrogramStructure(y_direct, fs, window_length_ms, window_shift_ms, window_f); 59 | sgramStrO = ... 60 | stftSpectrogramStructure(y_only, fs, window_length_ms, window_shift_ms, window_f); 61 | %% Selecing spectrum slice 62 | 63 | pw_antWithEq = 10*log10(mean(sgramStrY.rawSpectrogram(:, 210:230), 2)); 64 | pw_direct = 10*log10(mean(sgramStrD.rawSpectrogram(:, 210:230), 2)); 65 | pw_only = 10*log10(mean(sgramStrO.rawSpectrogram(:, 210:230), 2)); 66 | %% 67 | 68 | figure; 69 | plot(sgramStrY.frequencyAxis, pw_direct - max(pw_direct), 'g', ... 70 | 'linewidth', 2); 71 | grid on; 72 | hold all 73 | plot(sgramStrY.frequencyAxis, pw_only - max(pw_only), 'r', 'linewidth', 2); 74 | plot(sgramStrY.frequencyAxis, pw_antWithEq - max(pw_antWithEq), 'k', ... 75 | 'linewidth', 4); 76 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica', 'linewidth', 2); 77 | axis([0 fs/2 -180 5]); 78 | ylabel('leval (dB)'); 79 | xlabel('frequency (Hz)'); 80 | legend('direct', 'antialiasing only', 'antialiasing with eq', 'location', 'northeast'); 81 | %print -depsc aaFLforIS.eps 82 | 83 | %% 84 | sgram_6term = 10 * log10(sgramStrY.rawSpectrogram(:, 100:900)); 85 | sgram_6term = sgram_6term - max(sgram_6term); 86 | sgram_only = 10 * log10(sgramStrO.rawSpectrogram(:, 100:900)); 87 | sgram_only = sgram_only - max(sgram_only); 88 | sgram_direct = 10 * log10(sgramStrD.rawSpectrogram(:, 100:900)); 89 | sgram_direct = sgram_direct - max(sgram_direct); 90 | tt = sgramStrY.temporalPositions; 91 | figure;imagesc(tt([100 900]),[0 fs/2], sgram_6term); 92 | set(gca, 'clim', [-140 0]) 93 | axis('xy'); 94 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica'); 95 | xlabel('time (s)'); 96 | ylabel('frequency (Hz)'); 97 | colorbar 98 | title('antialiasing with equalization'); 99 | %print -depsc aaFLmodelRevSgramIS.eps 100 | figure;imagesc(tt([100 900]),[0 fs/2], sgram_only); 101 | set(gca, 'clim', [-140 0]) 102 | axis('xy'); 103 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica'); 104 | xlabel('time (s)'); 105 | ylabel('frequency (Hz)'); 106 | colorbar 107 | title('Antialiasing only'); 108 | %print -depsc aaFLmodelOldSgramIS.eps 109 | figure;imagesc(tt([100 900]),[0 fs/2], sgram_direct); 110 | set(gca, 'clim', [-140 0]) 111 | axis('xy'); 112 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica'); 113 | xlabel('time (s)'); 114 | ylabel('frequency (Hz)'); 115 | colorbar 116 | title('direct'); 117 | %print -depsc aaFLmodelDirectSgramIS.eps 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /test/testJitShimAALF.m: -------------------------------------------------------------------------------- 1 | function outStr = testJitShimAALF(jitterSD,shimmerSD,ppcent,fv,f0,vq,perturbation) 2 | %% Test L-F model with randomness 3 | % Author: Hideki Kawahara 4 | % 12/Dec./2015 5 | 6 | fs = 44100; 7 | duration = 0.5; 8 | tt = (0:1/fs:duration)'; 9 | switch vq 10 | case 1 11 | tp = 0.4134; 12 | te = 0.5530; 13 | ta = 0.0041; 14 | tc = 0.5817; 15 | case 2 16 | tp = 0.4621; 17 | te = 0.6604; 18 | ta = 0.0270; 19 | tc = 0.7712; 20 | case 3 21 | tp = 0.4808; 22 | te = 0.5955; 23 | ta = 0.0269; 24 | tc = 0.7200; 25 | 26 | end; 27 | f0Base = f0; 28 | f0 = f0Base*2.0.^(ppcent/1200*sin(2*pi*fv*tt)); 29 | 30 | %% 31 | %shimmerSD = 0.0; 32 | outStr = AAFLFmodelFromF0Trajectory(f0,tt,fs,tp,te,ta,tc,jitterSD,shimmerSD,perturbation); 33 | soundsc(outStr.antiAliasedSignal,fs) 34 | end 35 | -------------------------------------------------------------------------------- /test/testKurtosis.m: -------------------------------------------------------------------------------- 1 | %% kurtosis distribution simulation for normal distribution 2 | % 29/April/2014 3 | 4 | fs = 44100; 5 | lengthInS = 0.04; 6 | lengthInSample = round(fs*lengthInS); 7 | iterations = 100000; 8 | kurtosisList = zeros(iterations,1); 9 | for ii = 1:iterations 10 | xn = randn(lengthInSample,1); 11 | kurtosisList(ii) = mean(xn.^4)/std(xn)^4; 12 | end; 13 | figure; 14 | semilogy(sort(kurtosisList),(iterations:-1:1)/iterations);grid on; 15 | 16 | %% 17 | 18 | fs = 44100; 19 | lengthInS = 0.04; 20 | lengthInSample = round(fs*lengthInS); 21 | iterations = 100000; 22 | kurtosisList = zeros(iterations,1); 23 | for ii = 1:iterations 24 | xn = rand(lengthInSample,1); 25 | xn = sign(xn-0.5).*(exp(abs(xn-0.5)*10)-1); 26 | kurtosisList(ii) = mean(xn.^4)/std(xn)^4; 27 | end; 28 | figure; 29 | semilogy(sort(kurtosisList),(iterations:-1:1)/iterations);grid on; 30 | -------------------------------------------------------------------------------- /test/testRevisedLFmodel.m: -------------------------------------------------------------------------------- 1 | %% Test revised version of the antialiased L-F (Fant and Liliencrants) model 2 | % This is free to modify and use. 3 | % 14/Oct./2017 by Hideki Kawahara 4 | 5 | close all 6 | 7 | %% Desing a time varying fo trajectory 8 | % The fo value is set very high to illustrate antialiasing behavior clearly. 9 | 10 | fs = 44100; 11 | duration = 2; 12 | tt = (0:1 / fs:duration)'; 13 | mean_fO = 887; % Hz 14 | vibrato_f = 5.2;% Hz 15 | vibrato_depth = 6;% cent for peak deviation 16 | 17 | foi = 2.0 .^ (log2(mean_fO) + vibrato_depth / 1200 * sin(2 * pi * vibrato_f * tt + 0 * randn(length(tt), 1))); 18 | %% Set L-F model parameters 19 | 20 | % This is a modal parameter set 21 | tp = 0.4134; 22 | te = 0.5530; 23 | ta = 0.0041; 24 | tc = 0.5817; 25 | 26 | %% Generate L-F model output 27 | 28 | output = AAFLFmodelFromF0Trajectory6T(foi,tt,fs,tp,te,ta,tc); 29 | 30 | %% Display waveforms of the direct digitization, antialiasing only and 31 | % antialiasing followed by equalizaiton 32 | 33 | y = output.antiAliasedSignal; 34 | y_only = output.antiAliasedOnly; 35 | y_direct = output.LFmodelOut; 36 | figure; 37 | plot((0:length(y) - 1) / fs, y_direct, 'c', 'linewidth', 5); 38 | hold all 39 | plot((0:length(y) - 1) / fs, y_only, 'r', 'linewidth', 2); 40 | plot((0:length(y) - 1) / fs, y, 'k'); 41 | grid on; 42 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica'); 43 | xlabel('time (s)'); 44 | axis([[0.5 2.5] / 1000 -1 0.3]) 45 | legend('direct', 'antialias only', 'a.a. with eq', 'location', 'southwest'); 46 | 47 | %% This also illustates how to use stftSpectrogramStructure 48 | 49 | window_length_ms = 40; 50 | window_shift_ms = 2; 51 | window_f = 'nuttallwin12self'; % self convolution of Nuttall's 12-th item 52 | sgramStrY = ... 53 | stftSpectrogramStructure(y, fs, window_length_ms, window_shift_ms, window_f); 54 | sgramStrD = ... 55 | stftSpectrogramStructure(y_direct, fs, window_length_ms, window_shift_ms, window_f); 56 | sgramStrO = ... 57 | stftSpectrogramStructure(y_only, fs, window_length_ms, window_shift_ms, window_f); 58 | %% Selecing spectrum slice 59 | 60 | pw_antWithEq = 10*log10(mean(sgramStrY.rawSpectrogram(:, 210:230), 2)); 61 | pw_direct = 10*log10(mean(sgramStrD.rawSpectrogram(:, 210:230), 2)); 62 | pw_only = 10*log10(mean(sgramStrO.rawSpectrogram(:, 210:230), 2)); 63 | %% 64 | 65 | figure; 66 | plot(sgramStrY.frequencyAxis, pw_direct - max(pw_direct), 'g', ... 67 | 'linewidth', 2); 68 | grid on; 69 | hold all 70 | plot(sgramStrY.frequencyAxis, pw_only - max(pw_only), 'r', 'linewidth', 2); 71 | plot(sgramStrY.frequencyAxis, pw_antWithEq - max(pw_antWithEq), 'k', ... 72 | 'linewidth', 4); 73 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica', 'linewidth', 2); 74 | axis([0 fs/2 -180 18]); 75 | ylabel('leval (dB)'); 76 | xlabel('frequency (Hz)'); 77 | legend('direct', 'antialiasing only', 'antialiasing with eq', 'location', 'northeast'); 78 | %print -depsc aaLFforIS.eps 79 | 80 | %% 81 | sgram_6term = 10 * log10(sgramStrY.rawSpectrogram(:, 100:900)); 82 | sgram_6term = sgram_6term - max(sgram_6term); 83 | sgram_only = 10 * log10(sgramStrO.rawSpectrogram(:, 100:900)); 84 | sgram_only = sgram_only - max(sgram_only); 85 | sgram_direct = 10 * log10(sgramStrD.rawSpectrogram(:, 100:900)); 86 | sgram_direct = sgram_direct - max(sgram_direct); 87 | tt = sgramStrY.temporalPositions; 88 | figure;imagesc(tt([100 900]),[0 fs/2], sgram_6term); 89 | set(gca, 'clim', [-140 0]) 90 | axis('xy'); 91 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica'); 92 | xlabel('time (s)'); 93 | ylabel('frequency (Hz)'); 94 | colorbar 95 | title('antialiasing with equalization'); 96 | %print -depsc aaLFmodelRevSgramIS.eps 97 | figure;imagesc(tt([100 900]),[0 fs/2], sgram_only); 98 | set(gca, 'clim', [-140 0]) 99 | axis('xy'); 100 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica'); 101 | xlabel('time (s)'); 102 | ylabel('frequency (Hz)'); 103 | colorbar 104 | title('Antialiasing only'); 105 | %print -depsc aaLFmodelOldSgramIS.eps 106 | figure;imagesc(tt([100 900]),[0 fs/2], sgram_direct); 107 | set(gca, 'clim', [-140 0]) 108 | axis('xy'); 109 | set(gca, 'fontsize', 15, 'fontname', 'Helvetica'); 110 | xlabel('time (s)'); 111 | ylabel('frequency (Hz)'); 112 | colorbar 113 | title('direct'); 114 | %print -depsc aaLFmodelDirectSgramIS.eps 115 | 116 | -------------------------------------------------------------------------------- /test/testWindowingFunctions.m: -------------------------------------------------------------------------------- 1 | %% elapsed time for window functions 2 | % by Hideki Kawahara 3 | % 24/Oct./2014 4 | 5 | lengthList = 2.0.^(8:14)'; 6 | iteration = 100; 7 | 8 | tic;nuttallwin12(973);toc 9 | tic;blackman(973);toc 10 | tic;kaiser(973,12.45);toc 11 | tic;dpss(973,3.55);toc 12 | 13 | elapsedTimeList = zeros(4,length(lengthList)); 14 | for ii = 1:length(lengthList) 15 | wlength = lengthList(ii)+1; 16 | timeBlackman = 0; 17 | timeNuttall = 0; 18 | timeKaiser = 0; 19 | timeDpss = 0; 20 | for jj = 1:iteration 21 | tic;nuttallwin12(wlength);t1 = toc; 22 | tic;blackman(wlength);t2 = toc; 23 | tic;kaiser(wlength,12.45);t3 = toc; 24 | tic;dpss(wlength,3.55);t4 = toc; 25 | timeBlackman = timeBlackman+t1; 26 | timeNuttall = timeNuttall+t2; 27 | timeKaiser = timeKaiser+t3; 28 | timeDpss = timeDpss+t4; 29 | end; 30 | timeBlackman = timeBlackman/iteration; 31 | timeNuttall = timeNuttall/iteration; 32 | timeKaiser = timeKaiser/iteration; 33 | timeDpss = timeDpss/iteration; 34 | elapsedTimeList(:,ii) = [timeBlackman timeNuttall timeKaiser timeDpss]'; 35 | end; 36 | %% 37 | figure 38 | loglog(lengthList,elapsedTimeList*1000,'o-','linewidth',2); 39 | grid on; 40 | set(gca,'fontsize',15); 41 | xlabel('window size in sample'); 42 | ylabel('elapsed time (ms)'); 43 | legend('Blackman','Nuttall','Kaiser','DPSS','location','northwest'); 44 | set(gca,'xlim',[200 20000]) 45 | -------------------------------------------------------------------------------- /test/testmodal.txt: -------------------------------------------------------------------------------- 1 | % modal parameter for the L-F model ta 0.41 te 55.30 tc 58.17 tp 41.34 --------------------------------------------------------------------------------