//
// 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