mirror of
https://github.com/aidygus/LinVAM.git
synced 2024-11-23 09:18:04 +11:00
added the initial version for voice command spotting
This commit is contained in:
parent
821cee0db2
commit
8279d77e42
11
.idea/LinVAM.iml
Normal file
11
.idea/LinVAM.iml
Normal file
@ -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>
|
4
.idea/misc.xml
Normal file
4
.idea/misc.xml
Normal file
@ -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>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -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>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -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>
|
379
.idea/workspace.xml
Normal file
379
.idea/workspace.xml
Normal file
@ -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
|
||||||
|
|
||||||
|
BIN
__pycache__/commandeditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/commandeditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/keyactioneditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/keyactioneditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/mouseactioneditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/mouseactioneditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/pauseactioneditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/pauseactioneditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/profileeditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/profileeditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/profileexecutor.cpython-36.pyc
Normal file
BIN
__pycache__/profileexecutor.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ui_commandeditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/ui_commandeditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ui_keyactioneditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/ui_keyactioneditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ui_mainwnd.cpython-36.pyc
Normal file
BIN
__pycache__/ui_mainwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ui_mouseactioneditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/ui_mouseactioneditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ui_pauseactioneditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/ui_pauseactioneditwnd.cpython-36.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ui_profileeditwnd.cpython-36.pyc
Normal file
BIN
__pycache__/ui_profileeditwnd.cpython-36.pyc
Normal file
Binary file not shown.
5
command.list
Normal file
5
command.list
Normal file
@ -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()
|
||||||
|
|
||||||
|
134782
model/en-us/cmudict-en-us.dict
Normal file
134782
model/en-us/cmudict-en-us.dict
Normal file
File diff suppressed because it is too large
Load Diff
BIN
model/en-us/en-us-phone.lm.bin
Normal file
BIN
model/en-us/en-us-phone.lm.bin
Normal file
Binary file not shown.
BIN
model/en-us/en-us.lm.bin
Normal file
BIN
model/en-us/en-us.lm.bin
Normal file
Binary file not shown.
34
model/en-us/en-us/README
Normal file
34
model/en-us/en-us/README
Normal file
@ -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.
|
12
model/en-us/en-us/feat.params
Normal file
12
model/en-us/en-us/feat.params
Normal file
@ -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
|
BIN
model/en-us/en-us/mdef
Normal file
BIN
model/en-us/en-us/mdef
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 MiB |
BIN
model/en-us/en-us/means
Normal file
BIN
model/en-us/en-us/means
Normal file
Binary file not shown.
5
model/en-us/en-us/noisedict
Normal file
5
model/en-us/en-us/noisedict
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<s> SIL
|
||||||
|
</s> SIL
|
||||||
|
<sil> SIL
|
||||||
|
[NOISE] +NSN+
|
||||||
|
[SPEECH] +SPN+
|
BIN
model/en-us/en-us/sendump
Normal file
BIN
model/en-us/en-us/sendump
Normal file
Binary file not shown.
BIN
model/en-us/en-us/transition_matrices
Normal file
BIN
model/en-us/en-us/transition_matrices
Normal file
Binary file not shown.
BIN
model/en-us/en-us/variances
Normal file
BIN
model/en-us/en-us/variances
Normal file
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.
301
set_kws_threshold.py
Normal file
301
set_kws_threshold.py
Normal file
@ -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
Block a user