mirror of https://github.com/aidygus/LinVAM.git
added the initial version for voice command spotting
This commit is contained in:
parent
821cee0db2
commit
8279d77e42
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
<component name="TestRunnerService">
|
||||||
|
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
|
||||||
|
</component>
|
||||||
|
</module>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/LinVAM.iml" filepath="$PROJECT_DIR$/.idea/LinVAM.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,379 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="c0abc1c4-68ed-45ab-ade0-c412031fac32" name="Default Changelist" comment="">
|
||||||
|
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/commandeditwnd.py" beforeDir="false" afterPath="$PROJECT_DIR$/commandeditwnd.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/commandeditwnd.ui" beforeDir="false" afterPath="$PROJECT_DIR$/commandeditwnd.ui" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/profileeditwnd.py" beforeDir="false" afterPath="$PROJECT_DIR$/profileeditwnd.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/profileexecutor.py" beforeDir="false" afterPath="$PROJECT_DIR$/profileexecutor.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/profiles.dat" beforeDir="false" afterPath="$PROJECT_DIR$/profiles.dat" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/ui_commandeditwnd.py" beforeDir="false" afterPath="$PROJECT_DIR$/ui_commandeditwnd.py" afterDir="false" />
|
||||||
|
</list>
|
||||||
|
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="FileEditorManager">
|
||||||
|
<leaf SIDE_TABS_SIZE_LIMIT_KEY="450">
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/main.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="4900">
|
||||||
|
<caret line="207" column="10" selection-start-line="207" selection-start-column="10" selection-end-line="207" selection-end-column="10" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#26#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/kws.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="625">
|
||||||
|
<caret line="27" column="9" selection-start-line="27" selection-start-column="9" selection-end-line="27" selection-end-column="9" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#23#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/commandeditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="425">
|
||||||
|
<caret line="25" column="75" selection-start-line="25" selection-start-column="61" selection-end-line="25" selection-end-column="75" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#26#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/profileeditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="2200">
|
||||||
|
<caret line="95" column="31" selection-start-line="95" selection-start-column="31" selection-end-line="95" selection-end-column="31" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#26#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/ui_mouseactioneditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="2625">
|
||||||
|
<caret line="105" column="23" selection-start-line="105" selection-start-column="23" selection-end-line="105" selection-end-column="23" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="true">
|
||||||
|
<entry file="file://$PROJECT_DIR$/profileexecutor.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="244">
|
||||||
|
<caret line="64" column="50" lean-forward="true" selection-start-line="64" selection-start-column="50" selection-end-line="64" selection-end-column="50" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#15#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/set_kws_threshold.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="375">
|
||||||
|
<caret line="27" column="20" selection-start-line="27" selection-start-column="4" selection-end-line="27" selection-end-column="20" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#73#110#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/keyboard/__init__.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="21850">
|
||||||
|
<caret line="880" column="21" selection-start-line="880" selection-start-column="8" selection-end-line="880" selection-end-column="21" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$USER_HOME$/.PyCharmCE2019.1/system/python_stubs/-756103818/cv2/cv2/__init__.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="272375">
|
||||||
|
<caret line="10932" column="11" selection-start-line="10932" selection-start-column="11" selection-end-line="10932" selection-end-column="11" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/keyactioneditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="150">
|
||||||
|
<caret line="6" column="11" selection-start-line="6" selection-start-column="11" selection-end-line="6" selection-end-column="11" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
</leaf>
|
||||||
|
</component>
|
||||||
|
<component name="FindInProjectRecents">
|
||||||
|
<findStrings>
|
||||||
|
<find>termios</find>
|
||||||
|
<find>OUTPUT_FILENAME</find>
|
||||||
|
</findStrings>
|
||||||
|
</component>
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="IdeDocumentHistory">
|
||||||
|
<option name="CHANGED_PATHS">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/kws.py" />
|
||||||
|
<option value="$PROJECT_DIR$/commandeditwnd.py" />
|
||||||
|
<option value="$PROJECT_DIR$/profileexecutor.py" />
|
||||||
|
<option value="$PROJECT_DIR$/profileeditwnd.py" />
|
||||||
|
<option value="$PROJECT_DIR$/main.py" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectConfigurationFiles">
|
||||||
|
<option name="files">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/.idea/LinVAM.iml" />
|
||||||
|
<option value="$PROJECT_DIR$/.idea/vcs.xml" />
|
||||||
|
<option value="$PROJECT_DIR$/.idea/misc.xml" />
|
||||||
|
<option value="$PROJECT_DIR$/.idea/modules.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectFrameBounds" extendedState="6">
|
||||||
|
<option name="x" value="146" />
|
||||||
|
<option name="y" value="-8" />
|
||||||
|
<option name="width" value="1390" />
|
||||||
|
<option name="height" value="1000" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectView">
|
||||||
|
<navigator proportions="" version="1">
|
||||||
|
<foldersAlwaysOnTop value="true" />
|
||||||
|
</navigator>
|
||||||
|
<panes>
|
||||||
|
<pane id="ProjectPane">
|
||||||
|
<subPane>
|
||||||
|
<expand>
|
||||||
|
<path>
|
||||||
|
<item name="LinVAM" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="LinVAM" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
</expand>
|
||||||
|
<select />
|
||||||
|
</subPane>
|
||||||
|
</pane>
|
||||||
|
<pane id="Scope" />
|
||||||
|
</panes>
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent">
|
||||||
|
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="RunDashboard">
|
||||||
|
<option name="ruleStates">
|
||||||
|
<list>
|
||||||
|
<RuleState>
|
||||||
|
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||||
|
</RuleState>
|
||||||
|
<RuleState>
|
||||||
|
<option name="name" value="StatusDashboardGroupingRule" />
|
||||||
|
</RuleState>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="RunManager">
|
||||||
|
<configuration name="main" type="PythonConfigurationType" factoryName="Python" temporary="true">
|
||||||
|
<module name="LinVAM" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<envs>
|
||||||
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
|
</envs>
|
||||||
|
<option name="SDK_HOME" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/main.py" />
|
||||||
|
<option name="PARAMETERS" value="" />
|
||||||
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
|
<option name="MODULE_MODE" value="false" />
|
||||||
|
<option name="REDIRECT_INPUT" value="false" />
|
||||||
|
<option name="INPUT_FILE" value="" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<recent_temporary>
|
||||||
|
<list>
|
||||||
|
<item itemvalue="Python.main" />
|
||||||
|
</list>
|
||||||
|
</recent_temporary>
|
||||||
|
</component>
|
||||||
|
<component name="SvnConfiguration">
|
||||||
|
<configuration />
|
||||||
|
</component>
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="c0abc1c4-68ed-45ab-ade0-c412031fac32" name="Default Changelist" comment="" />
|
||||||
|
<created>1554735223942</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1554735223942</updated>
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="ToolWindowManager">
|
||||||
|
<frame x="-8" y="-8" width="1936" height="1056" extended-state="6" />
|
||||||
|
<editor active="true" />
|
||||||
|
<layout>
|
||||||
|
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.19989395" />
|
||||||
|
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
|
||||||
|
<window_info id="Favorites" order="2" side_tool="true" />
|
||||||
|
<window_info anchor="bottom" id="Message" order="0" />
|
||||||
|
<window_info anchor="bottom" id="Find" order="1" />
|
||||||
|
<window_info anchor="bottom" id="Run" order="2" weight="0.31687716" />
|
||||||
|
<window_info anchor="bottom" id="Debug" order="3" weight="0.39954075" />
|
||||||
|
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
|
||||||
|
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
||||||
|
<window_info anchor="bottom" id="TODO" order="6" />
|
||||||
|
<window_info anchor="bottom" id="Version Control" order="7" />
|
||||||
|
<window_info anchor="bottom" id="Terminal" order="8" weight="0.3295063" />
|
||||||
|
<window_info anchor="bottom" id="Event Log" order="9" side_tool="true" />
|
||||||
|
<window_info anchor="bottom" id="Python Console" order="10" weight="0.3295063" />
|
||||||
|
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
|
||||||
|
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
|
||||||
|
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
|
||||||
|
</layout>
|
||||||
|
</component>
|
||||||
|
<component name="editorHistoryManager">
|
||||||
|
<entry file="file://$PROJECT_DIR$/pauseactioneditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="300">
|
||||||
|
<caret line="12" column="24" selection-start-line="12" selection-start-column="24" selection-end-line="12" selection-end-column="24" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#26#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/ui_mainwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor" />
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$APPLICATION_HOME_DIR$/helpers/typeshed/stdlib/2and3/threading.pyi">
|
||||||
|
<provider selected="true" editor-type-id="text-editor" />
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$USER_HOME$/AppData/Local/Programs/Python/Python36/Lib/threading.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="50">
|
||||||
|
<caret line="827" column="8" selection-start-line="827" selection-start-column="8" selection-end-line="827" selection-end-column="8" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/main.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="4900">
|
||||||
|
<caret line="207" column="10" selection-start-line="207" selection-start-column="10" selection-end-line="207" selection-end-column="10" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#26#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/kws.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="625">
|
||||||
|
<caret line="27" column="9" selection-start-line="27" selection-start-column="9" selection-end-line="27" selection-end-column="9" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#23#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/commandeditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="425">
|
||||||
|
<caret line="25" column="75" selection-start-line="25" selection-start-column="61" selection-end-line="25" selection-end-column="75" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#26#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/profileeditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="2200">
|
||||||
|
<caret line="95" column="31" selection-start-line="95" selection-start-column="31" selection-end-line="95" selection-end-column="31" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#26#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/ui_mouseactioneditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="2625">
|
||||||
|
<caret line="105" column="23" selection-start-line="105" selection-start-column="23" selection-end-line="105" selection-end-column="23" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/set_kws_threshold.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="375">
|
||||||
|
<caret line="27" column="20" selection-start-line="27" selection-start-column="4" selection-end-line="27" selection-end-column="20" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#73#110#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/keyboard/__init__.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="21850">
|
||||||
|
<caret line="880" column="21" selection-start-line="880" selection-start-column="8" selection-end-line="880" selection-end-column="21" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$USER_HOME$/.PyCharmCE2019.1/system/python_stubs/-756103818/cv2/cv2/__init__.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="272375">
|
||||||
|
<caret line="10932" column="11" selection-start-line="10932" selection-start-column="11" selection-end-line="10932" selection-end-column="11" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/keyactioneditwnd.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="150">
|
||||||
|
<caret line="6" column="11" selection-start-line="6" selection-start-column="11" selection-end-line="6" selection-end-column="11" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/profileexecutor.py">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="244">
|
||||||
|
<caret line="64" column="50" lean-forward="true" selection-start-line="64" selection-start-column="50" selection-end-line="64" selection-end-column="50" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#15#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</component>
|
||||||
|
</project>
|
16
README.md
16
README.md
|
@ -1,2 +1,18 @@
|
||||||
# LinVAM
|
# LinVAM
|
||||||
Linux Voice Activated Macro
|
Linux Voice Activated Macro
|
||||||
|
## Status
|
||||||
|
This project is currently a work-in-progress and is minimally functional.
|
||||||
|
## Requirements
|
||||||
|
- python3
|
||||||
|
- PyQt5
|
||||||
|
- python3-xlib
|
||||||
|
## Install
|
||||||
|
- $ pip3 install PyQt5
|
||||||
|
- $ pip3 install python3-xlib
|
||||||
|
- $ git clone https://github.com/rose-jinyang/LinVAM.git
|
||||||
|
## Usage
|
||||||
|
This script must be run with root privilege because it must hook and simulate input devices such as keyboard, mouse etc.
|
||||||
|
- $ cd LinVAM
|
||||||
|
- $ xhost +
|
||||||
|
- $ sudo python3 ./main.py
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,5 @@
|
||||||
|
go /1e-2/
|
||||||
|
back /1e-3/
|
||||||
|
left /1e-10/
|
||||||
|
right /1e-3/
|
||||||
|
stop /1e-8/
|
|
@ -33,6 +33,7 @@ class CommandEditWnd(QDialog):
|
||||||
self.m_command = {}
|
self.m_command = {}
|
||||||
if p_command != None:
|
if p_command != None:
|
||||||
self.ui.say.setText(p_command['name'])
|
self.ui.say.setText(p_command['name'])
|
||||||
|
self.ui.thresholdSpin.setValue(p_command['threshold'])
|
||||||
w_actions = p_command['actions']
|
w_actions = p_command['actions']
|
||||||
for w_action in w_actions:
|
for w_action in w_actions:
|
||||||
w_jsonAction = json.dumps(w_action)
|
w_jsonAction = json.dumps(w_action)
|
||||||
|
@ -152,6 +153,7 @@ class CommandEditWnd(QDialog):
|
||||||
w_actions.append(w_action)
|
w_actions.append(w_action)
|
||||||
self.m_command['actions'] = w_actions
|
self.m_command['actions'] = w_actions
|
||||||
self.m_command['async'] = self.ui.asyncChk.isChecked()
|
self.m_command['async'] = self.ui.asyncChk.isChecked()
|
||||||
|
self.m_command['threshold'] = self.ui.thresholdSpin.value()
|
||||||
if self.ui.oneExe.isChecked():
|
if self.ui.oneExe.isChecked():
|
||||||
self.m_command['repeat'] = 1
|
self.m_command['repeat'] = 1
|
||||||
elif self.ui.continueExe.isChecked():
|
elif self.ui.continueExe.isChecked():
|
||||||
|
|
|
@ -93,6 +93,32 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="say"/>
|
<widget class="QLineEdit" name="say"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_8">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>threshold: </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="thresholdSpin"/>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
64
main.py
64
main.py
|
@ -26,14 +26,13 @@ class MainWnd(QWidget):
|
||||||
self.ui.ok.clicked.connect(self.slotOK)
|
self.ui.ok.clicked.connect(self.slotOK)
|
||||||
self.ui.cancel.clicked.connect(self.slotCancel)
|
self.ui.cancel.clicked.connect(self.slotCancel)
|
||||||
|
|
||||||
self.m_profileExecutor.start()
|
|
||||||
|
|
||||||
if self.loadFromDatabase() > 0 :
|
if self.loadFromDatabase() > 0 :
|
||||||
# if self.loadTestProfiles() > 0:
|
# if self.loadTestProfiles() > 0:
|
||||||
w_jsonProfile = self.ui.profileCbx.itemData(0)
|
w_jsonProfile = self.ui.profileCbx.itemData(0)
|
||||||
if w_jsonProfile != None:
|
if w_jsonProfile != None:
|
||||||
self.m_activeProfile = json.loads(w_jsonProfile)
|
self.m_activeProfile = json.loads(w_jsonProfile)
|
||||||
self.m_profileExecutor.setProfile(self.m_activeProfile)
|
self.m_profileExecutor.setProfile(self.m_activeProfile)
|
||||||
|
self.m_profileExecutor.start()
|
||||||
|
|
||||||
def saveToDatabase(self):
|
def saveToDatabase(self):
|
||||||
w_profiles = []
|
w_profiles = []
|
||||||
|
@ -66,43 +65,48 @@ class MainWnd(QWidget):
|
||||||
w_carProfileDict = {
|
w_carProfileDict = {
|
||||||
"name": "car game",
|
"name": "car game",
|
||||||
"commands": [
|
"commands": [
|
||||||
{'name': 'up',
|
{'name': 'forward',
|
||||||
'actions': [
|
'actions': [
|
||||||
{'name': 'key action', 'key': 'up', 'type': 1},
|
{'name': 'key action', 'key': 'up', 'type': 1}
|
||||||
{'name': 'pause action', 'time': 0.03}
|
|
||||||
],
|
],
|
||||||
'repeat': 1,
|
'repeat': 1,
|
||||||
'async': False
|
'async': False,
|
||||||
|
'threshold': 12
|
||||||
|
},
|
||||||
|
{'name': 'back',
|
||||||
|
'actions': [
|
||||||
|
{'name': 'key action', 'key': 'down', 'type': 1}
|
||||||
|
],
|
||||||
|
'repeat': 1,
|
||||||
|
'async': False,
|
||||||
|
'threshold': 3
|
||||||
},
|
},
|
||||||
{'name': 'left',
|
{'name': 'left',
|
||||||
'actions': [{'name': 'key action', 'key': 'right', 'type': 0},
|
'actions': [{'name': 'key action', 'key': 'right', 'type': 0},
|
||||||
{'name': 'pause action', 'time': 0.03},
|
|
||||||
{'name': 'key action', 'key': 'left', 'type': 1},
|
{'name': 'key action', 'key': 'left', 'type': 1},
|
||||||
{'name': 'pause action', 'time': 0.03}
|
|
||||||
],
|
],
|
||||||
'repeat': 1,
|
'repeat': 1,
|
||||||
'async': False
|
'async': False,
|
||||||
|
'threshold': 10
|
||||||
},
|
},
|
||||||
{'name': 'right',
|
{'name': 'right',
|
||||||
'actions': [{'name': 'key action', 'key': 'left', 'type': 0},
|
'actions': [{'name': 'key action', 'key': 'left', 'type': 0},
|
||||||
{'name': 'pause action', 'time': 0.03},
|
|
||||||
{'name': 'key action', 'key': 'right', 'type': 1},
|
{'name': 'key action', 'key': 'right', 'type': 1},
|
||||||
{'name': 'pause action', 'time': 0.03}
|
|
||||||
],
|
],
|
||||||
'repeat': 1,
|
'repeat': 1,
|
||||||
'async': False
|
'async': False,
|
||||||
|
'threshold': 3
|
||||||
},
|
},
|
||||||
{'name': 'stop',
|
{'name': 'stop',
|
||||||
'actions': [
|
'actions': [
|
||||||
{'name': 'key action', 'key': 'left', 'type': 0},
|
{'name': 'key action', 'key': 'left', 'type': 0},
|
||||||
{'name': 'pause action', 'time': 0.03},
|
|
||||||
{'name': 'key action', 'key': 'right', 'type': 0},
|
{'name': 'key action', 'key': 'right', 'type': 0},
|
||||||
{'name': 'pause action', 'time': 0.03},
|
|
||||||
{'name': 'key action', 'key': 'up', 'type': 0},
|
{'name': 'key action', 'key': 'up', 'type': 0},
|
||||||
{'name': 'pause action', 'time': 0.03}
|
{'name': 'key action', 'key': 'down', 'type': 0}
|
||||||
],
|
],
|
||||||
'repeat': 1,
|
'repeat': 1,
|
||||||
'async': False
|
'async': False,
|
||||||
|
'threshold': 8
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -117,7 +121,8 @@ class MainWnd(QWidget):
|
||||||
{'name': 'pause action', 'time': 0.01}
|
{'name': 'pause action', 'time': 0.01}
|
||||||
],
|
],
|
||||||
'repeat': -1,
|
'repeat': -1,
|
||||||
'async': True
|
'async': True,
|
||||||
|
'threshold': 3
|
||||||
},
|
},
|
||||||
{'name': 'left',
|
{'name': 'left',
|
||||||
'actions': [
|
'actions': [
|
||||||
|
@ -126,7 +131,8 @@ class MainWnd(QWidget):
|
||||||
{'name': 'pause action', 'time': 0.005}
|
{'name': 'pause action', 'time': 0.005}
|
||||||
],
|
],
|
||||||
'repeat': -1,
|
'repeat': -1,
|
||||||
'async': True
|
'async': True,
|
||||||
|
'threshold': 3
|
||||||
},
|
},
|
||||||
{'name': 'right',
|
{'name': 'right',
|
||||||
'actions': [
|
'actions': [
|
||||||
|
@ -135,7 +141,8 @@ class MainWnd(QWidget):
|
||||||
{'name': 'pause action', 'time': 0.005}
|
{'name': 'pause action', 'time': 0.005}
|
||||||
],
|
],
|
||||||
'repeat': -1,
|
'repeat': -1,
|
||||||
'async': True
|
'async': True,
|
||||||
|
'threshold': 3
|
||||||
},
|
},
|
||||||
{'name': 'down',
|
{'name': 'down',
|
||||||
'actions': [
|
'actions': [
|
||||||
|
@ -144,7 +151,8 @@ class MainWnd(QWidget):
|
||||||
{'name': 'pause action', 'time': 0.005}
|
{'name': 'pause action', 'time': 0.005}
|
||||||
],
|
],
|
||||||
'repeat': -1,
|
'repeat': -1,
|
||||||
'async': True
|
'async': True,
|
||||||
|
'threshold': 3
|
||||||
},
|
},
|
||||||
{'name': 'shoot',
|
{'name': 'shoot',
|
||||||
'actions': [
|
'actions': [
|
||||||
|
@ -152,7 +160,8 @@ class MainWnd(QWidget):
|
||||||
{'name': 'pause action', 'time': 0.03}
|
{'name': 'pause action', 'time': 0.03}
|
||||||
],
|
],
|
||||||
'repeat': 1,
|
'repeat': 1,
|
||||||
'async': False
|
'async': False,
|
||||||
|
'threshold': 3
|
||||||
},
|
},
|
||||||
{'name': 'stop',
|
{'name': 'stop',
|
||||||
'actions': [
|
'actions': [
|
||||||
|
@ -163,7 +172,8 @@ class MainWnd(QWidget):
|
||||||
{'name': 'mouse click action', 'button': 'left', 'type': 0}
|
{'name': 'mouse click action', 'button': 'left', 'type': 0}
|
||||||
],
|
],
|
||||||
'repeat': 1,
|
'repeat': 1,
|
||||||
'async': False
|
'async': False,
|
||||||
|
'threshold': 3
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -190,6 +200,7 @@ class MainWnd(QWidget):
|
||||||
w_profileEditWnd = ProfileEditWnd(None, self)
|
w_profileEditWnd = ProfileEditWnd(None, self)
|
||||||
if w_profileEditWnd.exec() == QDialog.Accepted:
|
if w_profileEditWnd.exec() == QDialog.Accepted:
|
||||||
w_profile = w_profileEditWnd.m_profile
|
w_profile = w_profileEditWnd.m_profile
|
||||||
|
self.m_profileExecutor.setProfile(w_profile)
|
||||||
self.ui.profileCbx.addItem(w_profile['name'])
|
self.ui.profileCbx.addItem(w_profile['name'])
|
||||||
w_jsonProfile = json.dumps(w_profile)
|
w_jsonProfile = json.dumps(w_profile)
|
||||||
self.ui.profileCbx.setItemData(self.ui.profileCbx.count()-1, w_jsonProfile)
|
self.ui.profileCbx.setItemData(self.ui.profileCbx.count()-1, w_jsonProfile)
|
||||||
|
@ -201,6 +212,7 @@ class MainWnd(QWidget):
|
||||||
w_profileEditWnd = ProfileEditWnd(w_profile, self)
|
w_profileEditWnd = ProfileEditWnd(w_profile, self)
|
||||||
if w_profileEditWnd.exec() == QDialog.Accepted:
|
if w_profileEditWnd.exec() == QDialog.Accepted:
|
||||||
w_profile = w_profileEditWnd.m_profile
|
w_profile = w_profileEditWnd.m_profile
|
||||||
|
self.m_profileExecutor.setProfile(w_profile)
|
||||||
self.ui.profileCbx.setItemText(w_idx, w_profile['name'])
|
self.ui.profileCbx.setItemText(w_idx, w_profile['name'])
|
||||||
w_jsonProfile = json.dumps(w_profile)
|
w_jsonProfile = json.dumps(w_profile)
|
||||||
self.ui.profileCbx.setItemData(w_idx, w_jsonProfile)
|
self.ui.profileCbx.setItemData(w_idx, w_jsonProfile)
|
||||||
|
@ -210,6 +222,12 @@ class MainWnd(QWidget):
|
||||||
if w_curIdx >= 0:
|
if w_curIdx >= 0:
|
||||||
self.ui.profileCbx.removeItem(w_curIdx)
|
self.ui.profileCbx.removeItem(w_curIdx)
|
||||||
|
|
||||||
|
w_curIdx = self.ui.profileCbx.currentIndex()
|
||||||
|
if w_curIdx >= 0:
|
||||||
|
w_jsonProfile = self.ui.profileCbx.itemData(w_curIdx)
|
||||||
|
w_profile = json.loads(w_jsonProfile)
|
||||||
|
self.m_profileExecutor.setProfile(w_profile)
|
||||||
|
|
||||||
def slotListeningEnabled(self, p_enabled):
|
def slotListeningEnabled(self, p_enabled):
|
||||||
if p_enabled:
|
if p_enabled:
|
||||||
self.m_profileExecutor.setEnableListening(True)
|
self.m_profileExecutor.setEnableListening(True)
|
||||||
|
@ -218,9 +236,11 @@ class MainWnd(QWidget):
|
||||||
|
|
||||||
def slotOK(self):
|
def slotOK(self):
|
||||||
self.saveToDatabase()
|
self.saveToDatabase()
|
||||||
|
self.m_profileExecutor.stop()
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def slotCancel(self):
|
def slotCancel(self):
|
||||||
|
self.m_profileExecutor.stop()
|
||||||
self.close()
|
self.close()
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
/* ====================================================================
|
||||||
|
* Copyright (c) 2015 Alpha Cephei Inc. All rights
|
||||||
|
* reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ALPHA CEPHEI INC. ``AS IS'' AND.
|
||||||
|
* ANY EXPRESSED 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 ALPHA CEPHEI INC.
|
||||||
|
* NOR ITS EMPLOYEES 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.
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
This directory contains generic US english acoustic model trained with
|
||||||
|
latest sphinxtrain.
|
|
@ -0,0 +1,12 @@
|
||||||
|
-lowerf 130
|
||||||
|
-upperf 6800
|
||||||
|
-nfilt 25
|
||||||
|
-transform dct
|
||||||
|
-lifter 22
|
||||||
|
-feat 1s_c_d_dd
|
||||||
|
-svspec 0-12/13-25/26-38
|
||||||
|
-agc none
|
||||||
|
-cmn batch
|
||||||
|
-varnorm no
|
||||||
|
-model ptm
|
||||||
|
-cmninit 41.00,-5.29,-0.12,5.09,2.48,-4.07,-1.37,-1.78,-5.08,-2.05,-6.45,-1.42,1.17
|
Binary file not shown.
After Width: | Height: | Size: 2.8 MiB |
Binary file not shown.
|
@ -0,0 +1,5 @@
|
||||||
|
<s> SIL
|
||||||
|
</s> SIL
|
||||||
|
<sil> SIL
|
||||||
|
[NOISE] +NSN+
|
||||||
|
[SPEECH] +SPN+
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -48,107 +48,6 @@ class ProfileEditWnd(QDialog):
|
||||||
|
|
||||||
QTimer.singleShot(100, self.ui.cmdTable.resizeRowsToContents)
|
QTimer.singleShot(100, self.ui.cmdTable.resizeRowsToContents)
|
||||||
|
|
||||||
# def activateProfile(self, p_profile):
|
|
||||||
# if p_profile == None or p_profile == {}:
|
|
||||||
# self.ui.cmdTable.setRowCount(0)
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# w_commands = p_profile['commands']
|
|
||||||
# self.ui.cmdTable.setRowCount(len(w_commands))
|
|
||||||
# i = 0
|
|
||||||
# for w_command in w_commands:
|
|
||||||
# self.ui.cmdTable.setItem(i, 0, QTableWidgetItem(w_command['name']))
|
|
||||||
# w_text = json.dumps(w_command)
|
|
||||||
# w_item = QTableWidgetItem(w_text)
|
|
||||||
# w_item.setData(Qt.UserRole, json.dumps(w_command))
|
|
||||||
# self.ui.cmdTable.setItem(i, 1, w_item)
|
|
||||||
# i = i + 1
|
|
||||||
# self.ui.cmdTable.resizeRowsToContents()
|
|
||||||
|
|
||||||
# def updateActiveProfile(self):
|
|
||||||
# w_idx = self.m_curProfileIdx
|
|
||||||
# if w_idx < 0:
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# w_profile = {}
|
|
||||||
# w_profile['name'] = self.ui.profileCbx.itemText(w_idx)
|
|
||||||
# w_commands = []
|
|
||||||
#
|
|
||||||
# w_commandCnt = self.ui.cmdTable.rowCount()
|
|
||||||
# for w_i in range(w_commandCnt):
|
|
||||||
# w_jsonCommand = self.ui.cmdTable.item(w_i, 1).data(Qt.UserRole)
|
|
||||||
# w_command = json.loads(w_jsonCommand)
|
|
||||||
# w_commands.append(w_command)
|
|
||||||
# w_profile['commands'] = w_commands
|
|
||||||
# w_jsonProfile = json.dumps(w_profile)
|
|
||||||
# self.ui.profileCbx.setItemData(w_idx, w_jsonProfile)
|
|
||||||
|
|
||||||
# def slotSelChanged(self, p_idx):
|
|
||||||
# self.updateActiveProfile()
|
|
||||||
# w_jsonProfile = self.ui.profileCbx.itemData(p_idx)
|
|
||||||
#
|
|
||||||
# w_profile = {}
|
|
||||||
# if w_jsonProfile != None:
|
|
||||||
# w_profile = json.loads(w_jsonProfile)
|
|
||||||
#
|
|
||||||
# self.activateProfile(w_profile)
|
|
||||||
#
|
|
||||||
# self.m_curProfileIdx = p_idx
|
|
||||||
|
|
||||||
# def importProfile(self, p_profile, p_update = True):
|
|
||||||
# if p_profile == None or p_profile == {}:
|
|
||||||
# return
|
|
||||||
#
|
|
||||||
# w_profileCnt = self.ui.profileCbx.count()
|
|
||||||
# for w_idx in range(w_profileCnt):
|
|
||||||
# w_jsonProfile = self.ui.profileCbx.itemData(w_idx)
|
|
||||||
# if w_jsonProfile == None:
|
|
||||||
# continue
|
|
||||||
#
|
|
||||||
# w_profile = json.loads(w_jsonProfile)
|
|
||||||
# if p_profile['name'] == w_profile['name']:
|
|
||||||
# if p_update:
|
|
||||||
# w_jsonProfile = json.dumps(p_profile)
|
|
||||||
# self.ui.profileCbx.setItemData(w_idx, w_jsonProfile)
|
|
||||||
# return True
|
|
||||||
# return False
|
|
||||||
#
|
|
||||||
# self.ui.profileCbx.addItem(p_profile['name'])
|
|
||||||
# w_jsonProfile = json.dumps(p_profile)
|
|
||||||
# self.ui.profileCbx.setItemData(w_profileCnt, w_jsonProfile)
|
|
||||||
# return True
|
|
||||||
|
|
||||||
# def slotAddNewProfile(self):
|
|
||||||
# text, okPressed = QInputDialog.getText(self, "Get Profile Name", "Profile name:", QLineEdit.Normal, "")
|
|
||||||
# if okPressed and text != '':
|
|
||||||
# w_profile = {}
|
|
||||||
# w_profile['name'] = text
|
|
||||||
# w_profile['commands'] = []
|
|
||||||
# if self.importProfile(w_profile, False) == False:
|
|
||||||
# QMessageBox.critical(None, 'Error', 'Adding a new profile was failed')
|
|
||||||
# return
|
|
||||||
# self.ui.profileCbx.setCurrentIndex(self.ui.profileCbx.count()-1)
|
|
||||||
|
|
||||||
# def slotRemoveProfile(self):
|
|
||||||
# w_curIdx = self.ui.profileCbx.currentIndex()
|
|
||||||
# if w_curIdx >= 0:
|
|
||||||
# self.ui.cmdTable.setRowCount(0)
|
|
||||||
# self.m_curProfileIdx = -1
|
|
||||||
# self.ui.profileCbx.removeItem(w_curIdx)
|
|
||||||
#
|
|
||||||
# def slotRenameProfile(self):
|
|
||||||
# w_curIdx = self.ui.profileCbx.currentIndex()
|
|
||||||
# if w_curIdx >= 0:
|
|
||||||
# text, okPressed = QInputDialog.getText(self, "Input Dialog", "Profile name:",
|
|
||||||
# QLineEdit.Normal, self.ui.profileCbx.itemText(w_curIdx))
|
|
||||||
# if okPressed and text != '':
|
|
||||||
# self.ui.profileCbx.setItemText(w_curIdx, text)
|
|
||||||
# w_jsonProfile = self.ui.profileCbx.itemData(w_curIdx)
|
|
||||||
# w_profile = json.loads(w_jsonProfile)
|
|
||||||
# w_profile['name'] = text
|
|
||||||
# w_jsonProfile = json.dumps(w_profile)
|
|
||||||
# self.ui.profileCbx.setItemData(w_curIdx, w_jsonProfile)
|
|
||||||
|
|
||||||
def importCommand(self, p_command, p_update):
|
def importCommand(self, p_command, p_update):
|
||||||
w_commandCnt = self.ui.cmdTable.rowCount()
|
w_commandCnt = self.ui.cmdTable.rowCount()
|
||||||
for w_i in range(w_commandCnt):
|
for w_i in range(w_commandCnt):
|
||||||
|
@ -192,7 +91,11 @@ class ProfileEditWnd(QDialog):
|
||||||
|
|
||||||
w_cmdEditWnd = CommandEditWnd(w_command, self)
|
w_cmdEditWnd = CommandEditWnd(w_command, self)
|
||||||
if w_cmdEditWnd.exec_() == QDialog.Accepted:
|
if w_cmdEditWnd.exec_() == QDialog.Accepted:
|
||||||
self.importCommand(w_cmdEditWnd.m_command, True)
|
self.ui.cmdTable.setItem(w_modelIdx.row(), 0, QTableWidgetItem(w_cmdEditWnd.m_command['name']))
|
||||||
|
w_text = json.dumps(w_cmdEditWnd.m_command)
|
||||||
|
w_item = QTableWidgetItem(w_text)
|
||||||
|
w_item.setData(Qt.UserRole, json.dumps(w_cmdEditWnd.m_command))
|
||||||
|
self.ui.cmdTable.setItem(w_modelIdx.row(), 1, w_item)
|
||||||
self.ui.cmdTable.resizeRowsToContents()
|
self.ui.cmdTable.resizeRowsToContents()
|
||||||
|
|
||||||
def slotDeleteCmd(self):
|
def slotDeleteCmd(self):
|
||||||
|
|
|
@ -4,43 +4,73 @@ import time
|
||||||
import threading
|
import threading
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
|
import sys, os, pyaudio
|
||||||
|
from pocketsphinx.pocketsphinx import *
|
||||||
|
from sphinxbase.sphinxbase import *
|
||||||
|
|
||||||
class ProfileExecutor(threading.Thread):
|
class ProfileExecutor(threading.Thread):
|
||||||
mouse = Controller()
|
mouse = Controller()
|
||||||
|
|
||||||
def __init__(self, p_profile = None):
|
def __init__(self, p_profile = None):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.m_profile = p_profile
|
self.setProfile(p_profile)
|
||||||
self.m_stop = False
|
self.m_stop = False
|
||||||
self.m_listening = True
|
self.m_listening = True
|
||||||
self.m_cmdThreads = {}
|
self.m_cmdThreads = {}
|
||||||
|
|
||||||
|
self.m_config = Decoder.default_config()
|
||||||
|
self.m_config.set_string('-hmm', os.path.join('model', 'en-us/en-us'))
|
||||||
|
self.m_config.set_string('-dict', os.path.join('model', 'en-us/cmudict-en-us.dict'))
|
||||||
|
self.m_config.set_string('-kws', 'command.list')
|
||||||
|
|
||||||
|
p = pyaudio.PyAudio()
|
||||||
|
self.m_stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True)
|
||||||
|
self.m_stream.start_stream()
|
||||||
|
|
||||||
|
# Process audio chunk by chunk. On keyword detected perform action and restart search
|
||||||
|
self.m_decoder = Decoder(self.m_config)
|
||||||
|
|
||||||
def setProfile(self, p_profile):
|
def setProfile(self, p_profile):
|
||||||
self.m_profile = p_profile
|
self.m_profile = p_profile
|
||||||
|
if self.m_profile == None:
|
||||||
|
return
|
||||||
|
|
||||||
|
w_commandWordFile = open('command.list', 'w')
|
||||||
|
w_commands = self.m_profile['commands']
|
||||||
|
i = 0
|
||||||
|
for w_command in w_commands:
|
||||||
|
if i != 0:
|
||||||
|
w_commandWordFile.write('\n')
|
||||||
|
w_commandWordFile.write(w_command['name'] + ' /1e-%d/' % w_command['threshold'])
|
||||||
|
i = i + 1
|
||||||
|
w_commandWordFile.close()
|
||||||
|
self.m_config.set_string('-kws', 'command.list')
|
||||||
|
|
||||||
def setEnableListening(self, p_enable):
|
def setEnableListening(self, p_enable):
|
||||||
self.m_listening = p_enable
|
self.m_listening = p_enable
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
self.m_decoder.start_utt()
|
||||||
while self.m_stop != True:
|
while self.m_stop != True:
|
||||||
keyboard.wait('ctrl+alt')
|
buf = self.m_stream.read(1024)
|
||||||
if self.m_listening != True:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for i in range(3):
|
self.m_decoder.process_raw(buf, False, False)
|
||||||
self.doCommand('up')
|
|
||||||
time.sleep(0.5)
|
|
||||||
|
|
||||||
self.doCommand('left')
|
if self.m_decoder.hyp() != None:
|
||||||
time.sleep(0.5)
|
# print([(seg.word, seg.prob, seg.start_frame, seg.end_frame) for seg in decoder.seg()])
|
||||||
|
# print("Detected keyword, restarting search")
|
||||||
|
#
|
||||||
|
# Here you run the code you want based on keyword
|
||||||
|
#
|
||||||
|
for w_seg in self.m_decoder.seg():
|
||||||
|
self.doCommand(w_seg.word.rstrip())
|
||||||
|
|
||||||
self.doCommand('right')
|
self.m_decoder.end_utt()
|
||||||
time.sleep(0.5)
|
self.m_decoder.start_utt()
|
||||||
|
|
||||||
self.doCommand('stop')
|
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.m_stop = True
|
self.m_stop = True
|
||||||
|
threading.Thread.join(self)
|
||||||
|
|
||||||
def doAction(self, p_action):
|
def doAction(self, p_action):
|
||||||
# {'name': 'key action', 'key': 'left', 'type': 0}
|
# {'name': 'key action', 'key': 'left', 'type': 0}
|
||||||
|
@ -157,162 +187,3 @@ class ProfileExecutor(threading.Thread):
|
||||||
if p_cmdName in self.m_cmdThreads.keys():
|
if p_cmdName in self.m_cmdThreads.keys():
|
||||||
self.m_cmdThreads[p_cmdName].stop()
|
self.m_cmdThreads[p_cmdName].stop()
|
||||||
del self.m_cmdThreads[p_cmdName]
|
del self.m_cmdThreads[p_cmdName]
|
||||||
|
|
||||||
# def carGameTest():
|
|
||||||
# w_profileDict = {
|
|
||||||
# "name": "car game",
|
|
||||||
# "commands": [
|
|
||||||
# {'name': 'up',
|
|
||||||
# 'actions': [
|
|
||||||
# {'name': 'key action', 'key': 'up', 'type': 1},
|
|
||||||
# {'name': 'pause action', 'time': 0.03}
|
|
||||||
# ],
|
|
||||||
# 'repeat': 1,
|
|
||||||
# 'async': False
|
|
||||||
# },
|
|
||||||
# {'name': 'left',
|
|
||||||
# 'actions': [{'name': 'key action', 'key': 'right', 'type': 0},
|
|
||||||
# {'name': 'pause action', 'time': 0.03},
|
|
||||||
# {'name': 'key action', 'key': 'left', 'type': 1},
|
|
||||||
# {'name': 'pause action', 'time': 0.03}
|
|
||||||
# ],
|
|
||||||
# 'repeat': 1,
|
|
||||||
# 'async': False
|
|
||||||
# },
|
|
||||||
# {'name': 'right',
|
|
||||||
# 'actions': [{'name': 'key action', 'key': 'left', 'type': 0},
|
|
||||||
# {'name': 'pause action', 'time': 0.03},
|
|
||||||
# {'name': 'key action', 'key': 'right', 'type': 1},
|
|
||||||
# {'name': 'pause action', 'time': 0.03}
|
|
||||||
# ],
|
|
||||||
# 'repeat': 1,
|
|
||||||
# 'async': False
|
|
||||||
# },
|
|
||||||
# {'name': 'stop',
|
|
||||||
# 'actions': [
|
|
||||||
# {'name': 'key action', 'key': 'left', 'type': 0},
|
|
||||||
# {'name': 'pause action', 'time': 0.03},
|
|
||||||
# {'name': 'key action', 'key': 'right', 'type': 0},
|
|
||||||
# {'name': 'pause action', 'time': 0.03},
|
|
||||||
# {'name': 'key action', 'key': 'up', 'type': 0},
|
|
||||||
# {'name': 'pause action', 'time': 0.03}
|
|
||||||
# ],
|
|
||||||
# 'repeat': 1,
|
|
||||||
# 'async': False
|
|
||||||
# }
|
|
||||||
# ]
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor = ProfileExecutor(w_profileDict)
|
|
||||||
#
|
|
||||||
# print("Move to the target window and press spacebar")
|
|
||||||
# keyboard.wait('space')
|
|
||||||
#
|
|
||||||
# print("Started !")
|
|
||||||
#
|
|
||||||
# for i in range(5):
|
|
||||||
# w_ProfileExecutor.doCommand('up')
|
|
||||||
# time.sleep(0.5)
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.doCommand('left')
|
|
||||||
# time.sleep(0.5)
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.doCommand('right')
|
|
||||||
# time.sleep(0.5)
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.doCommand('stop')
|
|
||||||
#
|
|
||||||
# def airplaneGameTest():
|
|
||||||
# w_profileDict = {
|
|
||||||
# "name": "airplane game",
|
|
||||||
# "commands": [
|
|
||||||
# {'name': 'up',
|
|
||||||
# 'actions': [
|
|
||||||
# {'name': 'command stop action', 'command name': 'down'},
|
|
||||||
# {'name': 'mouse move action', 'x':0, 'y':-5, 'absolute': False},
|
|
||||||
# {'name': 'pause action', 'time': 0.01}
|
|
||||||
# ],
|
|
||||||
# 'repeat': -1,
|
|
||||||
# 'async': True
|
|
||||||
# },
|
|
||||||
# {'name': 'left',
|
|
||||||
# 'actions': [
|
|
||||||
# {'name': 'command stop action', 'command name':'right'},
|
|
||||||
# {'name': 'mouse move action', 'x':-5, 'y':0, 'absolute': False},
|
|
||||||
# {'name': 'pause action', 'time': 0.005}
|
|
||||||
# ],
|
|
||||||
# 'repeat': -1,
|
|
||||||
# 'async': True
|
|
||||||
# },
|
|
||||||
# {'name': 'right',
|
|
||||||
# 'actions': [
|
|
||||||
# {'name': 'command stop action', 'command name': 'left'},
|
|
||||||
# {'name': 'mouse move action', 'x':5, 'y':0, 'absolute': False},
|
|
||||||
# {'name': 'pause action', 'time': 0.005}
|
|
||||||
# ],
|
|
||||||
# 'repeat': -1,
|
|
||||||
# 'async': True
|
|
||||||
# },
|
|
||||||
# {'name': 'down',
|
|
||||||
# 'actions': [
|
|
||||||
# {'name': 'command stop action', 'command name': 'up'},
|
|
||||||
# {'name': 'mouse move action', 'x':0, 'y':5, 'absolute': False},
|
|
||||||
# {'name': 'pause action', 'time': 0.005}
|
|
||||||
# ],
|
|
||||||
# 'repeat': -1,
|
|
||||||
# 'async': True
|
|
||||||
# },
|
|
||||||
# {'name': 'shoot',
|
|
||||||
# 'actions': [
|
|
||||||
# {'name': 'mouse click action', 'button':'left', 'type': 1},
|
|
||||||
# {'name': 'pause action', 'time': 0.03}
|
|
||||||
# ],
|
|
||||||
# 'repeat': 1,
|
|
||||||
# 'async': False
|
|
||||||
# },
|
|
||||||
# {'name': 'stop',
|
|
||||||
# 'actions': [
|
|
||||||
# {'name': 'command stop action', 'command name': 'up'},
|
|
||||||
# {'name': 'command stop action', 'command name': 'left'},
|
|
||||||
# {'name': 'command stop action', 'command name': 'right'},
|
|
||||||
# {'name': 'command stop action', 'command name': 'down'},
|
|
||||||
# {'name': 'mouse click action', 'button': 'left', 'type': 0}
|
|
||||||
# ],
|
|
||||||
# 'repeat': 1,
|
|
||||||
# 'async': False
|
|
||||||
# }
|
|
||||||
# ]
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor = ProfileExecutor(w_profileDict)
|
|
||||||
#
|
|
||||||
# print("Move to the target window and press the spacebar to start")
|
|
||||||
# keyboard.wait('space')
|
|
||||||
#
|
|
||||||
# time.sleep(1)
|
|
||||||
#
|
|
||||||
# print("Started !")
|
|
||||||
#
|
|
||||||
# for i in range(3):
|
|
||||||
# w_ProfileExecutor.doCommand('shoot')
|
|
||||||
# time.sleep(1)
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.doCommand('up')
|
|
||||||
# time.sleep(1)
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.doCommand('down')
|
|
||||||
# time.sleep(0.5)
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.stopCommand('down')
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.doCommand('left')
|
|
||||||
# time.sleep(0.5)
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.doCommand('right')
|
|
||||||
# time.sleep(0.5)
|
|
||||||
#
|
|
||||||
# w_ProfileExecutor.doCommand('stop')
|
|
||||||
#
|
|
||||||
# if __name__ == "__main__":
|
|
||||||
# carGameTest()
|
|
||||||
# # airplaneGameTest()
|
|
||||||
|
|
BIN
profiles.dat
BIN
profiles.dat
Binary file not shown.
|
@ -0,0 +1,301 @@
|
||||||
|
"""Script for auto tuning keyword spotting thresholds in pocketsphinx"""
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
import select
|
||||||
|
import os
|
||||||
|
import termios
|
||||||
|
import contextlib
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from pocketsphinx.pocketsphinx import *
|
||||||
|
from sphinxbase.sphinxbase import *
|
||||||
|
|
||||||
|
# keyphrases found in kwlist
|
||||||
|
WORDS = []
|
||||||
|
# test case containing multiple occurances
|
||||||
|
# of words to be used as training audio
|
||||||
|
TEST_CASE = []
|
||||||
|
# Threshold values
|
||||||
|
FREQUENCY = []
|
||||||
|
# End frame of each word in input speech
|
||||||
|
NO_OF_FRAMES = []
|
||||||
|
# Recorded speech input
|
||||||
|
OUTPUT_FILENAME = 'testing_audio.wav'
|
||||||
|
|
||||||
|
def preprocess_files(dic_path, kwlist_path):
|
||||||
|
"""
|
||||||
|
Function to generate required lists and call tuning functions
|
||||||
|
"""
|
||||||
|
global WORDS, TEST_CASE, FREQUENCY
|
||||||
|
|
||||||
|
# words found in dictinary
|
||||||
|
_content = []
|
||||||
|
with open(dic_path) as _f:
|
||||||
|
_content = _f.readlines()
|
||||||
|
_content = [x.strip() for x in _content]
|
||||||
|
|
||||||
|
with open(kwlist_path) as _f:
|
||||||
|
WORDS = _f.readlines()
|
||||||
|
WORDS = [x.strip()[:x.strip().rfind(' ')] for x in WORDS]
|
||||||
|
print (WORDS)
|
||||||
|
|
||||||
|
# Loop to find out initial thresholds based on phonetics provided in dictionary
|
||||||
|
for i, _ in enumerate(WORDS):
|
||||||
|
# starting position of first phone for a word
|
||||||
|
init_pos = 0
|
||||||
|
# Count number of phones based on frequency of spaces
|
||||||
|
spaces = 0
|
||||||
|
# In case there is more than one word in a keyphrase, add phones for all words
|
||||||
|
for _m in re.finditer(' ', WORDS[i]):
|
||||||
|
indices = [j for j, s in enumerate(_content) if WORDS[i][init_pos:_m.start()]+'\t' in s]
|
||||||
|
spaces = _content[indices[0]].count(' ') + spaces + 1
|
||||||
|
init_pos = _m.start()+1
|
||||||
|
indices = [j for j, s in enumerate(_content) if WORDS[i][init_pos:]+'\t' in s]
|
||||||
|
spaces += _content[indices[0]].count(' ') + 1
|
||||||
|
# Normalizing
|
||||||
|
if spaces <= 3:
|
||||||
|
FREQUENCY.append(spaces)
|
||||||
|
else:
|
||||||
|
FREQUENCY.append(spaces * 2)
|
||||||
|
# Adding random noise in test case for better tuning
|
||||||
|
TEST_CASE = ['[RANDOM]', '[RANDOM]']
|
||||||
|
TEST_CASE.extend(WORDS)
|
||||||
|
TEST_CASE.extend(['[RANDOM]', '[RANDOM]'])
|
||||||
|
TEST_CASE.extend(WORDS)
|
||||||
|
np.random.shuffle(TEST_CASE)
|
||||||
|
print ("HERE IS YOUR TRAINING SET")
|
||||||
|
print (TEST_CASE)
|
||||||
|
|
||||||
|
# record audio
|
||||||
|
record()
|
||||||
|
write_frequency_to_file(kwlist_path)
|
||||||
|
|
||||||
|
# Analysis begins
|
||||||
|
actual_tuning(dic_path, kwlist_path, 1)
|
||||||
|
print ("Removed many false alarms. New frequency: ")
|
||||||
|
print (FREQUENCY)
|
||||||
|
print ('Moving on to missed detections')
|
||||||
|
actual_tuning(dic_path, kwlist_path, 0)
|
||||||
|
print ("Frequency tuned to the best of the script's ability. New frequency: ")
|
||||||
|
print (FREQUENCY)
|
||||||
|
_missed, _fa = process_threshold(kws_analysis(dic_path, kwlist_path))
|
||||||
|
|
||||||
|
def write_frequency_to_file(kwlist_path):
|
||||||
|
"""
|
||||||
|
update modified frequencies in kwlist file
|
||||||
|
"""
|
||||||
|
_f = open(kwlist_path, 'w')
|
||||||
|
for i, val in enumerate(FREQUENCY):
|
||||||
|
_f.write(WORDS[i] + ' /1e-' + str(val) + '/\n')
|
||||||
|
_f.close()
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def raw_mode(_file):
|
||||||
|
"""
|
||||||
|
Function handle the button press on successful utterance of word by user
|
||||||
|
"""
|
||||||
|
old_attrs = termios.tcgetattr(_file.fileno())
|
||||||
|
new_attrs = old_attrs[:]
|
||||||
|
new_attrs[3] = new_attrs[3] & ~(termios.ECHO | termios.ICANON)
|
||||||
|
try:
|
||||||
|
termios.tcsetattr(_file.fileno(), termios.TCSADRAIN, new_attrs)
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
termios.tcsetattr(_file.fileno(), termios.TCSADRAIN, old_attrs)
|
||||||
|
|
||||||
|
def record():
|
||||||
|
"""
|
||||||
|
Records user's speech with timestamp for each spoken word
|
||||||
|
"""
|
||||||
|
global NO_OF_FRAMES
|
||||||
|
# rec -c 1 -r 16000 -b 16 recording.wav
|
||||||
|
print ("-----SAY THE FOLLOWING OUT LOUD AND PRESS ENTER-----")
|
||||||
|
print (TEST_CASE[0])
|
||||||
|
os.system('rec -q -c 1 -r 16000 -b 16 ' + OUTPUT_FILENAME + ' &')
|
||||||
|
NO_OF_FRAMES.append(0)
|
||||||
|
previous = time.time()
|
||||||
|
i = 0
|
||||||
|
with raw_mode(sys.stdin):
|
||||||
|
while True:
|
||||||
|
if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
|
||||||
|
_a = sys.stdin.read(1)
|
||||||
|
if _a == '\n':
|
||||||
|
if i == len(TEST_CASE)-1:
|
||||||
|
current = time.time()
|
||||||
|
NO_OF_FRAMES.append(NO_OF_FRAMES[i] + (current - previous)*100)
|
||||||
|
previous = current
|
||||||
|
print ("STOPPING RECORDING")
|
||||||
|
time.sleep(2)
|
||||||
|
# stop Recording
|
||||||
|
os.system('pkill rec')
|
||||||
|
print (NO_OF_FRAMES)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
current = time.time()
|
||||||
|
NO_OF_FRAMES.append(NO_OF_FRAMES[i] + (current - previous)*100)
|
||||||
|
previous = current
|
||||||
|
i = i+1
|
||||||
|
print ("-----SAY THE FOLLOWING OUT LOUD AND PRESS ENTER-----")
|
||||||
|
print (TEST_CASE[i])
|
||||||
|
|
||||||
|
def actual_tuning(dic_path, kwlist_path, _z):
|
||||||
|
"""
|
||||||
|
process false alarms and missed detections to tune thresholds
|
||||||
|
_z in the paramter is 1 for FA analysis and 0 for missed detection analysis
|
||||||
|
"""
|
||||||
|
# to store thresholds with minimum mismatches
|
||||||
|
minimum_inflection = [FREQUENCY[i] for i, _ in enumerate(WORDS)]
|
||||||
|
# to check whether a word's assessment has been finished or not
|
||||||
|
processed = [0 for i, _ in enumerate(WORDS)]
|
||||||
|
# get frequency of missed detections and false alarms
|
||||||
|
_missed, _fa = process_threshold(kws_analysis(dic_path, kwlist_path))
|
||||||
|
|
||||||
|
_least_negative_threshold = 1
|
||||||
|
_most_negative_threshold = 49
|
||||||
|
|
||||||
|
# Loop until there is at least one word whose assessment has not finished
|
||||||
|
while 0 in processed:
|
||||||
|
if _z == 1:
|
||||||
|
# If there is a False alarm, increase threshold
|
||||||
|
for i, val in enumerate(_fa):
|
||||||
|
if FREQUENCY[i] > _least_negative_threshold and processed[i] == 0:
|
||||||
|
if val[1] > 0:
|
||||||
|
FREQUENCY[i] -= 2
|
||||||
|
else:
|
||||||
|
processed[i] = 1
|
||||||
|
else:
|
||||||
|
processed[i] = 1
|
||||||
|
else:
|
||||||
|
# If there is a missed detection, decrease threshold
|
||||||
|
for i, val in enumerate(_missed):
|
||||||
|
if FREQUENCY[i] < _most_negative_threshold and processed[i] == 0:
|
||||||
|
if val[1] > 0:
|
||||||
|
FREQUENCY[i] += 1
|
||||||
|
else:
|
||||||
|
processed[i] = 1
|
||||||
|
else:
|
||||||
|
processed[i] = 1
|
||||||
|
|
||||||
|
write_frequency_to_file(kwlist_path)
|
||||||
|
|
||||||
|
print ('UPDATED FREQUENCY:')
|
||||||
|
print (FREQUENCY)
|
||||||
|
|
||||||
|
_previous_missed = []
|
||||||
|
_previous_missed.extend(_missed)
|
||||||
|
_previous_fa = []
|
||||||
|
_previous_fa.extend(_fa)
|
||||||
|
|
||||||
|
_missed, _fa = process_threshold(kws_analysis(dic_path, kwlist_path))
|
||||||
|
|
||||||
|
if _z == 1:
|
||||||
|
# If current readings show increase in missed detections,
|
||||||
|
# go to previous state and stop
|
||||||
|
for i, val in enumerate(_missed):
|
||||||
|
if val[1] > _previous_missed[i][1] and processed[i] == 0:
|
||||||
|
processed[i] = 1
|
||||||
|
FREQUENCY[i] += 2
|
||||||
|
else:
|
||||||
|
# If current readings show increase in false alarms,
|
||||||
|
# go to previous state and stop
|
||||||
|
for i, val in enumerate(_fa):
|
||||||
|
if val[1] > _previous_fa[i][1] and processed[i] == 0:
|
||||||
|
processed[i] = 1
|
||||||
|
FREQUENCY[i] -= 1
|
||||||
|
|
||||||
|
# If updated thresholds caused better accuracy, save them
|
||||||
|
for i, val in enumerate([_fa, _missed][_z == 0]):
|
||||||
|
if val[1] < [_previous_fa[i][1], _previous_missed][_z == 0]:
|
||||||
|
minimum_inflection[i] = FREQUENCY[i]
|
||||||
|
|
||||||
|
for i, val in enumerate([_fa, _missed][_z == 0]):
|
||||||
|
FREQUENCY[i] = minimum_inflection[i]
|
||||||
|
write_frequency_to_file(kwlist_path)
|
||||||
|
|
||||||
|
def kws_analysis(dic, kwlist):
|
||||||
|
"""
|
||||||
|
kws analysis on user speech and updated threshold values
|
||||||
|
"""
|
||||||
|
analysis_result = []
|
||||||
|
|
||||||
|
modeldir = "/usr/local/share/pocketsphinx/model/"
|
||||||
|
|
||||||
|
# Create a decoder with certain model
|
||||||
|
config = Decoder.default_config()
|
||||||
|
config.set_string('-hmm', os.path.join(modeldir, 'en-us/en-us'))
|
||||||
|
config.set_string('-dict', dic)
|
||||||
|
config.set_string('-kws', kwlist)
|
||||||
|
config.set_string('-dither', "no")
|
||||||
|
config.set_string('-logfn', '/dev/null')
|
||||||
|
config.set_string('-featparams', os.path.join(os.path.join(modeldir,
|
||||||
|
'en-us/en-us'), "feat.params"))
|
||||||
|
|
||||||
|
stream = open(OUTPUT_FILENAME, "rb")
|
||||||
|
|
||||||
|
# Process audio chunk by chunk. On keyphrase detected perform action and restart search
|
||||||
|
decoder = Decoder(config)
|
||||||
|
decoder.start_utt()
|
||||||
|
timer = 0
|
||||||
|
while True:
|
||||||
|
buf = stream.read(1024)
|
||||||
|
if buf:
|
||||||
|
decoder.process_raw(buf, False, False)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if decoder.hyp() != None:
|
||||||
|
for seg in decoder.seg():
|
||||||
|
pass
|
||||||
|
analysis_result.append([seg.word.rstrip(), timer/320])
|
||||||
|
|
||||||
|
decoder.end_utt()
|
||||||
|
decoder.start_utt()
|
||||||
|
timer += 1024
|
||||||
|
return analysis_result
|
||||||
|
|
||||||
|
def process_threshold(analysis_result):
|
||||||
|
"""
|
||||||
|
calculate missed detections and false alarms
|
||||||
|
Argument: analysis result = kws result
|
||||||
|
"""
|
||||||
|
# stores timestamp of words which matche in both speech and kws result
|
||||||
|
_indices = []
|
||||||
|
|
||||||
|
missed = [[WORDS[i], 0] for i in range(len(WORDS))]
|
||||||
|
false_alarms = [[WORDS[i], 0] for i in range(len(WORDS))]
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
for i, val in enumerate(analysis_result):
|
||||||
|
# Calculate the timestamp in speech closest to timestamp of word found by kws result
|
||||||
|
_index = min(range(len(NO_OF_FRAMES)), key=lambda l: abs(NO_OF_FRAMES[l] - val[1]))
|
||||||
|
_indices.append(_index)
|
||||||
|
|
||||||
|
if TEST_CASE[_index-1] == '[RANDOM]':
|
||||||
|
position_observer = WORDS.index(val[0])
|
||||||
|
false_alarms[position_observer][1] += 1
|
||||||
|
print ('FA Found', val[0], ' in place of RANDOM TEXT')
|
||||||
|
elif TEST_CASE[_index-1] == val[0]:
|
||||||
|
print ('DETECTED CORRECTLY', val[0])
|
||||||
|
else:
|
||||||
|
print ('FA Found', val[0], ' in place of ', TEST_CASE[_index-1])
|
||||||
|
position_original = WORDS.index(TEST_CASE[_index-1])
|
||||||
|
position_observer = WORDS.index(val[0])
|
||||||
|
missed[position_original][1] += 1
|
||||||
|
false_alarms[position_observer][1] += 1
|
||||||
|
# If speech had timestamp not mentioned in kws result, then its detection was missed
|
||||||
|
for i, val in enumerate(TEST_CASE):
|
||||||
|
if i+1 not in _indices and val != '[RANDOM]':
|
||||||
|
position_original = WORDS.index(val)
|
||||||
|
missed[position_original][1] += 1
|
||||||
|
print ('Missed ', val)
|
||||||
|
return missed, false_alarms
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
DIC_FILE = "/home/pankaj/catkin_ws/src/pocketsphinx/demo/voice_cmd.dic"
|
||||||
|
KWLIST_FILE = "/home/pankaj/catkin_ws/src/pocketsphinx/demo/automated.kwlist"
|
||||||
|
if len(sys.argv) == 3:
|
||||||
|
DIC_FILE = sys.argv[1]
|
||||||
|
KWLIST_FILE = sys.argv[2]
|
||||||
|
preprocess_files(DIC_FILE, KWLIST_FILE)
|
|
@ -39,8 +39,16 @@ class Ui_CommandEditDialog(object):
|
||||||
self.say = QtWidgets.QLineEdit(CommandEditDialog)
|
self.say = QtWidgets.QLineEdit(CommandEditDialog)
|
||||||
self.say.setObjectName("say")
|
self.say.setObjectName("say")
|
||||||
self.horizontalLayout.addWidget(self.say)
|
self.horizontalLayout.addWidget(self.say)
|
||||||
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
spacerItem3 = QtWidgets.QSpacerItem(50, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.horizontalLayout.addItem(spacerItem3)
|
self.horizontalLayout.addItem(spacerItem3)
|
||||||
|
self.label_4 = QtWidgets.QLabel(CommandEditDialog)
|
||||||
|
self.label_4.setObjectName("label_4")
|
||||||
|
self.horizontalLayout.addWidget(self.label_4)
|
||||||
|
self.thresholdSpin = QtWidgets.QSpinBox(CommandEditDialog)
|
||||||
|
self.thresholdSpin.setObjectName("thresholdSpin")
|
||||||
|
self.horizontalLayout.addWidget(self.thresholdSpin)
|
||||||
|
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
self.horizontalLayout.addItem(spacerItem4)
|
||||||
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 8)
|
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 8)
|
||||||
self.horizontalLayout_9 = QtWidgets.QHBoxLayout()
|
self.horizontalLayout_9 = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
|
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
|
||||||
|
@ -48,8 +56,8 @@ class Ui_CommandEditDialog(object):
|
||||||
self.oneExe.setAutoExclusive(True)
|
self.oneExe.setAutoExclusive(True)
|
||||||
self.oneExe.setObjectName("oneExe")
|
self.oneExe.setObjectName("oneExe")
|
||||||
self.horizontalLayout_9.addWidget(self.oneExe)
|
self.horizontalLayout_9.addWidget(self.oneExe)
|
||||||
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.horizontalLayout_9.addItem(spacerItem4)
|
self.horizontalLayout_9.addItem(spacerItem5)
|
||||||
self.gridLayout.addLayout(self.horizontalLayout_9, 6, 0, 1, 1)
|
self.gridLayout.addLayout(self.horizontalLayout_9, 6, 0, 1, 1)
|
||||||
self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
|
self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout_10.setObjectName("horizontalLayout_10")
|
self.horizontalLayout_10.setObjectName("horizontalLayout_10")
|
||||||
|
@ -57,8 +65,8 @@ class Ui_CommandEditDialog(object):
|
||||||
self.continueExe.setAutoExclusive(True)
|
self.continueExe.setAutoExclusive(True)
|
||||||
self.continueExe.setObjectName("continueExe")
|
self.continueExe.setObjectName("continueExe")
|
||||||
self.horizontalLayout_10.addWidget(self.continueExe)
|
self.horizontalLayout_10.addWidget(self.continueExe)
|
||||||
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.horizontalLayout_10.addItem(spacerItem5)
|
self.horizontalLayout_10.addItem(spacerItem6)
|
||||||
self.gridLayout.addLayout(self.horizontalLayout_10, 7, 0, 1, 1)
|
self.gridLayout.addLayout(self.horizontalLayout_10, 7, 0, 1, 1)
|
||||||
self.horizontalLayout_11 = QtWidgets.QHBoxLayout()
|
self.horizontalLayout_11 = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout_11.setObjectName("horizontalLayout_11")
|
self.horizontalLayout_11.setObjectName("horizontalLayout_11")
|
||||||
|
@ -73,8 +81,8 @@ class Ui_CommandEditDialog(object):
|
||||||
self.label_3 = QtWidgets.QLabel(CommandEditDialog)
|
self.label_3 = QtWidgets.QLabel(CommandEditDialog)
|
||||||
self.label_3.setObjectName("label_3")
|
self.label_3.setObjectName("label_3")
|
||||||
self.horizontalLayout_11.addWidget(self.label_3)
|
self.horizontalLayout_11.addWidget(self.label_3)
|
||||||
spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.horizontalLayout_11.addItem(spacerItem6)
|
self.horizontalLayout_11.addItem(spacerItem7)
|
||||||
self.gridLayout.addLayout(self.horizontalLayout_11, 8, 0, 1, 1)
|
self.gridLayout.addLayout(self.horizontalLayout_11, 8, 0, 1, 1)
|
||||||
self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
|
self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
|
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
|
||||||
|
@ -129,14 +137,14 @@ class Ui_CommandEditDialog(object):
|
||||||
self.asyncChk.setChecked(True)
|
self.asyncChk.setChecked(True)
|
||||||
self.asyncChk.setObjectName("asyncChk")
|
self.asyncChk.setObjectName("asyncChk")
|
||||||
self.horizontalLayout_8.addWidget(self.asyncChk)
|
self.horizontalLayout_8.addWidget(self.asyncChk)
|
||||||
spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
spacerItem8 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.horizontalLayout_8.addItem(spacerItem7)
|
self.horizontalLayout_8.addItem(spacerItem8)
|
||||||
self.gridLayout.addLayout(self.horizontalLayout_8, 5, 0, 1, 3)
|
self.gridLayout.addLayout(self.horizontalLayout_8, 5, 0, 1, 3)
|
||||||
self.horizontalLayout_12 = QtWidgets.QHBoxLayout()
|
self.horizontalLayout_12 = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout_12.setSpacing(20)
|
self.horizontalLayout_12.setSpacing(20)
|
||||||
self.horizontalLayout_12.setObjectName("horizontalLayout_12")
|
self.horizontalLayout_12.setObjectName("horizontalLayout_12")
|
||||||
spacerItem8 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
spacerItem9 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.horizontalLayout_12.addItem(spacerItem8)
|
self.horizontalLayout_12.addItem(spacerItem9)
|
||||||
self.ok = QtWidgets.QPushButton(CommandEditDialog)
|
self.ok = QtWidgets.QPushButton(CommandEditDialog)
|
||||||
self.ok.setMinimumSize(QtCore.QSize(130, 0))
|
self.ok.setMinimumSize(QtCore.QSize(130, 0))
|
||||||
self.ok.setAutoDefault(False)
|
self.ok.setAutoDefault(False)
|
||||||
|
@ -157,6 +165,7 @@ class Ui_CommandEditDialog(object):
|
||||||
CommandEditDialog.setWindowTitle(_translate("CommandEditDialog", "Command Edit Dialog"))
|
CommandEditDialog.setWindowTitle(_translate("CommandEditDialog", "Command Edit Dialog"))
|
||||||
self.label_2.setText(_translate("CommandEditDialog", "When this command excutes, do the following sequence:"))
|
self.label_2.setText(_translate("CommandEditDialog", "When this command excutes, do the following sequence:"))
|
||||||
self.label.setText(_translate("CommandEditDialog", "When I say :"))
|
self.label.setText(_translate("CommandEditDialog", "When I say :"))
|
||||||
|
self.label_4.setText(_translate("CommandEditDialog", "threshold: "))
|
||||||
self.oneExe.setText(_translate("CommandEditDialog", "This command executes once"))
|
self.oneExe.setText(_translate("CommandEditDialog", "This command executes once"))
|
||||||
self.continueExe.setText(_translate("CommandEditDialog", "This command repeats continuously"))
|
self.continueExe.setText(_translate("CommandEditDialog", "This command repeats continuously"))
|
||||||
self.repeatExe.setText(_translate("CommandEditDialog", "This command repeats"))
|
self.repeatExe.setText(_translate("CommandEditDialog", "This command repeats"))
|
||||||
|
|
Loading…
Reference in New Issue