// // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab // Copyright (C) 2013-2013 - Scilab Enterprises - Bruno JOFRET // // This file must be used under the terms of the CeCILL. // This source file is licensed as described in the file COPYING, which // you should have received as part of this distribution. The terms // are also available at // http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt // // toneChartPath = get_absolute_file_path("toneRecognitionTool.sce"); // Global global signal; signal = []; global infosSignal; infosSignal = []; global minBound; minBound = 0; global maxBound; maxBound = 0; global %doLive; %doLive = %f; f=figure('figure_position',[0,0],... 'figure_size',[800,600],'auto_resize','on','background',[33],... 'figure_name','Tone Recognition Tool'); pathIcon = filesep()+"modules"+filesep()+"gui"+filesep()+"images"+filesep()+"icons"+filesep()+"16x16"; pathAction = pathIcon + filesep()+"actions"; pathCategories = pathIcon + filesep()+"categories"; cutImage = (SCI)+pathAction+filesep()+"edit-cut.png"; playImage = (SCI)+pathAction+filesep()+"media-playback-start.png"; processImage = (SCI)+pathCategories+filesep()+"applications-system.png"; cutImageHTML = ""; playImageHTML = ""; processImageHTML = ""; SignalAxes= newaxes(); SignalAxes.axes_bounds = [0.3, 0.5, 0.7, 0.5]; SignalAxes.tag = "SignalAxes"; FreqAxes= newaxes(); FreqAxes.axes_bounds = [0.3, 0, 0.7, 0.5]; FreqAxes.tag = "FreqAxes"; // Frame for displayed data Freq + Name ToneFrame=uicontrol(f,'Style','frame',... 'unit','normalized','Position',[0.01,0.08,0.34,0.26],'Tag','ToneFrame'); // Tone Name ToneName=uicontrol(f,'Style','text', ... 'unit','normalized','FontSize',[22],'Position',[0.03,0.2,0.2,0.1],... 'String','Tone: ???',... 'Tag','ToneName') // Tone Freq ToneFreq=uicontrol(f,'Style','text',... 'unit','normalized','FontSize',[22],'Position',[0.03,0.1,0.2,0.1],... 'String','??? Hz',... 'Tag','ToneFreq') // Selection Frame // Radio button Cut Left/Right // No action available yet CutFrame = uicontrol(f,'Style','frame',... 'unit','normalized','Position',[0.01, 0.38, 0.18, 0.32],'Tag','CutFrame'); CutEnable = uicontrol(f,'Style','checkbox', ... 'unit','normalized','Position',[0.02,0.6,0.16,0.08],'HorizontalAlignment','left','String','Enable Selection',... 'Tag','EnableSelection','Callback','cbEnableSelection'); CutLeft = uicontrol(f,'Style','radiobutton',... 'unit','normalized','Position',[0.02,0.5,0.1,0.08],'HorizontalAlignment','left','String','CutLeft',... 'enable', 'off', ... 'Tag','CutLeft','Callback','cbCutLeft'); CutRight = uicontrol(f,'Style','radiobutton',... 'unit','normalized','Position',[0.02,0.4,0.1,0.08],'HorizontalAlignment','left','String','CutRight',... 'enable', 'off', ... 'Tag','CutRight','Callback','cbCutRight'); Process=uicontrol(f,'Style','pushbutton',... 'unit','normalized','Position',[0.2, 0.6, 0.08, 0.08],'String',processImageHTML,... 'Tag','Cut','Callback','cbProcess'); Cut=uicontrol(f,'Style','pushbutton',... 'unit','normalized','Position',[0.2, 0.5, 0.08, 0.08],'String',cutImageHTML,... 'Tag','Cut','Callback','cbCut'); PlaySelection=uicontrol(f,'Style','pushbutton', ... 'unit','normalized','Position',[0.2, 0.4, 0.08, 0.08],'String',playImageHTML,... 'Tag','PlaySelection','Callback','cbPlaySelection'); // Frame for file input InputFileFrame = uicontrol(f, 'Style', 'frame', ... 'unit','normalized','Position',[0.01,0.72,0.30,0.18],... 'Tag', 'InputFileFrame') FileName=uicontrol(InputFileFrame,'Style','text',... 'Position',[10,50,210,20],... 'BackgroundColor', [1 1 1], ... 'String','FileName',... 'Tag','FileName', 'callback', 'cbFileName'); LoadFile=uicontrol(InputFileFrame,'Style','pushbutton',... 'Position',[10,20,90,20],'String','Load',... 'Tag','LoadFile','Callback','cbLoadFile'); Clear=uicontrol(InputFileFrame,'Style','pushbutton',... 'Position',[130,20,90,20],'String','Clear',... 'Tag','Clear','Callback','cbClear'); // Frame for Live Input InputLiveFrame = uicontrol(f, 'Style', 'frame', ... 'unit','normalized','Position',[0.01,0.72,0.30,0.18],... 'Visible', 'off', ... 'Tag', 'InputLiveFrame') LoadFile=uicontrol(InputLiveFrame,'Style','pushbutton',... 'Position',[10,10,90,60],'String','Start',... 'Tag','StartLive','Callback','cbStartLive'); Clear=uicontrol(InputLiveFrame,'Style','pushbutton',... 'Position',[130,10,90,60],'String','Stop',... 'Tag','StopLive','Callback','cbStopLive'); EnableFile = uicontrol(f,'Style','radiobutton',... 'unit','normalized','Position',[0.01,0.9,0.15,0.08],'HorizontalAlignment','left','String','File',... 'BackgroundColor', [0.9 0.9 0.9], 'value', 1, ... 'Tag','EnableFile','Callback','cbEnableFile'); EnableLive = uicontrol(f,'Style','radiobutton',... 'unit','normalized','Position',[0.16,0.9,0.147,0.08],'HorizontalAlignment','left','String','Live',... 'BackgroundColor', [0.8 0.8 0.8],'value', 0, ... 'Tag','EnableLive','Callback','cbEnableLive'); function cbEnableSelection() e = findobj("tag", "EnableSelection"); el = findobj("tag", "CutLeft"); er = findobj("tag", "CutRight"); if e.value == 0 then el.enable = "off"; el.value = 0; er.enable = "off"; er.value = 0; else el.enable = "on"; er.enable = "on"; end endfunction function cbCutLeft() el = findobj("tag", "CutLeft"); er = findobj("tag", "CutRight"); er.value = 0; el.value = 1; endfunction function cbCutRight() el = findobj("tag", "CutLeft"); er = findobj("tag", "CutRight"); er.value = 1; el.value = 0; endfunction function cbCut() // Not implemented yet... endfunction function cbPlaySelection() global signal; global minBound; global maxBound; if ~isempty(signal) then playsnd(signal(minBound:maxBound)); end endfunction function cbLoadFile() filename = uigetfile("*.wav", pwd()); if ~isempty(filename) global signal; global infosSignal; global minBound; global maxBound; [signal, infosSignal] = loadwave(filename); e = findobj("tag", "FileName"); e.string = fileparts(filename, 'fname'); a = findobj("tag", "SignalAxes"); sca(a); plot2d(signal); minBound = 1; maxBound = size(signal, '*'); end endfunction function cbProcess() global signal; global infosSignal; global minBound; global maxBound; frequenceEchant = infosSignal(3); nbEchantillons = infosSignal($); [foundTone, fundamentalFreq, frequences, moduleFftSignal, indicePic, valeurPic] = toneRecognition(signal, frequenceEchant, nbEchantillons, minBound, maxBound); a = findobj("tag", "FreqAxes"); sca(a); plot2d("nl", frequences, moduleFftSignal); xpoly([frequences(indicePic), frequences(indicePic)],[%eps valeurPic], "lines", 1); e=gce(); e.foreground = color("red"); eFreq = findobj("tag", "ToneFreq"); eName = findobj("tag", "ToneName"); eFreq.string = string(fundamentalFreq)+" Hz"; eName.string = "Tone: "+foundTone; endfunction function [foundTone, fundamentalFreq, frequences, moduleFftSignal, indicePic, valeurPic] = toneRecognition(signal, frequenceEchant, nbEchantillons, minBound, maxBound) frequences = frequenceEchant*(0:((maxBound-minBound)/2))/(maxBound-minBound); moduleFftSignal = abs(fft(signal(minBound:maxBound))); moduleFftSignal = moduleFftSignal(1:size(frequences, "*")); [valeurPic, indicePic] = max(moduleFftSignal); fundamentalFreq = frequences(indicePic); toneChart = csvRead(toneChartPath+"/toneChart.csv", ",", "double"); toneName = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] toneOctave = string(0:7); [value, position] = min(abs(toneChart - fundamentalFreq)); foundTone = toneName(position(1))+"-"+toneOctave(position(2)); endfunction function cbClear() global signal; global infosSignal; infosSignal = []; signal = []; a = findobj("tag", "SignalAxes"); sca(a); if ~isempty(a.children) then delete(a.children); end a.data_bounds = [0,0;1,1]; a = findobj("tag", "FreqAxes"); sca(a); if ~isempty(a.children) then delete(a.children); end a.data_bounds = [0,1e-6;1,10]; eFreq = findobj("tag", "ToneFreq"); eName = findobj("tag", "ToneName"); eFreq.string = "??? Hz"; eName.string = "Tone: ???"; endfunction function cbStartLive() bufferSize = 44100; signalAxes = findobj("tag", "SignalAxes"); sca(signalAxes); if ~isempty(signalAxes.children) then delete(signalAxes.children); end signalAxes.data_bounds = [0,-2;1,2]; plot2d(zeros(1, bufferSize)); signalPoly = gce(); signalPoly = signalPoly.children(1); freqAxes = findobj("tag", "FreqAxes"); sca(freqAxes); if ~isempty(freqAxes.children) then delete(freqAxes.children); end freqAxes.data_bounds = [0,0;1d4,5d3]; plot2d("nl",ones(1, 1d4)); freqPoly = gce(); freqPoly = freqPoly.children(1); xpoly([0, 0],[%eps %eps], "lines", 1); edgePoly=gce(); edgePoly.foreground = color("red"); deviceName = DAQ_SystemInfoAttribute('DAQmx_Sys_DevNames') xinfo("Start NI Device: "+deviceName) DAQ_ResetDevice(deviceName); chan_ai0 = deviceName+"/audioInputLeft"; minVal = -2.0; maxVal = +2.0; // Timing parameters source = "OnboardClock"; samplesPerChan = 44100.0; rate = 44100.0; // Data read parameters pointsToRead = -1; timeout = 100.0; [task_ai0,err] = DAQ_CreateTask(""); DAQ_ErrChk(task_ai0,err); [err] = DAQ_CreateAIVoltageChan(task_ai0, chan_ai0, DAQ("Val_Cfg_Default"), minVal, maxVal); DAQ_ErrChk(task_ai0,err); [err] = DAQ_CfgSampClkTiming(task_ai0, source, rate, DAQ("Val_Rising"), DAQ("Val_FiniteSamps"),samplesPerChan); DAQ_ErrChk(task_ai0,err); xinfo("Reading input on: "+chan_ai0) global %doLive %doLive = %t; while %doLive // READ AudioInput [err] = DAQ_StartTask(task_ai0); DAQ_ErrChk(task_ai0,err); [data_ai0,pointsRead,err] = DAQ_ReadAnalogF64(task_ai0,pointsToRead,timeout, DAQ("Val_GroupByChannel"), bufferSize); DAQ_ErrChk(task_ai0, err); DAQ_StopTask(task_ai0); signalPoly.data(:,2) = data_ai0'; signalAxes.data_bounds(:,2) = [min([-0.1, min(data_ai0)]) ; max([0.1, max(data_ai0)])] [foundTone, fundamentalFreq, frequences, moduleFftSignal, indicePic, valeurPic] = toneRecognition(data_ai0, rate, pointsRead, 1, pointsRead) freqPoly.data(:,2) = moduleFftSignal(1:1d4)'; freqAxes.data_bounds = [0, 0; 1d4, valeurPic]; edgePoly.data = [indicePic %eps ; indicePic valeurPic]; // Update computed values if valeurPic > 20 then eFreq = findobj("tag", "ToneFreq"); eName = findobj("tag", "ToneName"); eFreq.string = string(fundamentalFreq)+" Hz"; eName.string = "Tone: "+foundTone; else eFreq = findobj("tag", "ToneFreq"); eName = findobj("tag", "ToneName"); eFreq.string = "??? Hz"; eName.string = "Tone: ???"; end end // Mean data DAQ_ClearTask(task_ai0); xinfo("Done.") endfunction function cbStopLive() global %doLive; %doLive = %f; endfunction function cbEnableFile() e = findobj("tag", "EnableFile"); e.value = 1; e.backgroundcolor = [0.9 0.9 0.9]; e = findobj("tag", "EnableLive"); e.value = 0; e.backgroundcolor = [0.8 0.8 0.8]; e = findobj("tag", "InputFileFrame"); e.visible = "on"; e = findobj("tag", "InputLiveFrame"); e.visible = "off"; endfunction function cbEnableLive() e = findobj("tag", "EnableLive"); e.value = 1; e.backgroundcolor = [0.9 0.9 0.9]; e = findobj("tag", "EnableFile"); e.value = 0; e.backgroundcolor = [0.8 0.8 0.8]; e = findobj("tag", "InputLiveFrame"); e.visible = "on"; e = findobj("tag", "InputFileFrame"); e.visible = "off"; endfunction