Audio recive works perfect for opus voice, send fails (laggy)
TODO: - Opus music - Client volumes - Some lagecy settingscanary
parent
debab3baaf
commit
96c3aabec9
|
@ -3,11 +3,6 @@
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="978d055d-27d3-431a-bd34-e5e79bb273b3" name="Default" comment="">
|
<list default="true" id="978d055d-27d3-431a-bd34-e5e79bb273b3" name="Default" comment="">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
|
||||||
<change beforePath="$PROJECT_DIR$/asm/generated/TeaWeb-Native.js" afterPath="$PROJECT_DIR$/asm/generated/TeaWeb-Native.js" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/asm/generated/libopus.js" afterPath="$PROJECT_DIR$/asm/generated/libopus.js" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/asm/libs/opus" afterPath="$PROJECT_DIR$/asm/libs/opus" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/asm/make_opus.sh" afterPath="$PROJECT_DIR$/asm/make_opus.sh" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/asm/src/WebASMTest.cpp" afterPath="$PROJECT_DIR$/asm/src/WebASMTest.cpp" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/js/codec/Codec.js" afterPath="$PROJECT_DIR$/js/codec/Codec.js" />
|
<change beforePath="$PROJECT_DIR$/js/codec/Codec.js" afterPath="$PROJECT_DIR$/js/codec/Codec.js" />
|
||||||
<change beforePath="$PROJECT_DIR$/js/codec/Codec.js.map" afterPath="$PROJECT_DIR$/js/codec/Codec.js.map" />
|
<change beforePath="$PROJECT_DIR$/js/codec/Codec.js.map" afterPath="$PROJECT_DIR$/js/codec/Codec.js.map" />
|
||||||
<change beforePath="$PROJECT_DIR$/js/codec/Codec.ts" afterPath="$PROJECT_DIR$/js/codec/Codec.ts" />
|
<change beforePath="$PROJECT_DIR$/js/codec/Codec.ts" afterPath="$PROJECT_DIR$/js/codec/Codec.ts" />
|
||||||
|
@ -24,21 +19,11 @@
|
||||||
</component>
|
</component>
|
||||||
<component name="FileEditorManager">
|
<component name="FileEditorManager">
|
||||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||||
<file leaf-file-name="index.html" pinned="false" current-in-tab="false">
|
<file leaf-file-name="Codec.ts" pinned="false" current-in-tab="true">
|
||||||
<entry file="file://$PROJECT_DIR$/index.html">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="2898">
|
|
||||||
<caret line="161" column="19" lean-forward="false" selection-start-line="161" selection-start-column="19" selection-end-line="161" selection-end-column="19" />
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
</file>
|
|
||||||
<file leaf-file-name="Codec.ts" pinned="false" current-in-tab="false">
|
|
||||||
<entry file="file://$PROJECT_DIR$/js/codec/Codec.ts">
|
<entry file="file://$PROJECT_DIR$/js/codec/Codec.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="751">
|
<state relative-caret-position="198">
|
||||||
<caret line="99" column="102" lean-forward="false" selection-start-line="99" selection-start-column="102" selection-end-line="99" selection-end-column="102" />
|
<caret line="14" column="35" lean-forward="true" selection-start-line="14" selection-start-column="35" selection-end-line="14" selection-end-column="35" />
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
|
@ -59,8 +44,8 @@
|
||||||
<file leaf-file-name="connection.ts" pinned="false" current-in-tab="false">
|
<file leaf-file-name="connection.ts" pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/js/connection.ts">
|
<entry file="file://$PROJECT_DIR$/js/connection.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="0">
|
<state relative-caret-position="612">
|
||||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
<caret line="34" column="24" lean-forward="true" selection-start-line="34" selection-start-column="24" selection-end-line="34" selection-end-column="24" />
|
||||||
<folding>
|
<folding>
|
||||||
<element signature="n#!!doc" expanded="true" />
|
<element signature="n#!!doc" expanded="true" />
|
||||||
</folding>
|
</folding>
|
||||||
|
@ -81,8 +66,18 @@
|
||||||
<file leaf-file-name="lib.es6.d.ts" pinned="false" current-in-tab="false">
|
<file leaf-file-name="lib.es6.d.ts" pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/lib.es6.d.ts">
|
<entry file="file://$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/lib.es6.d.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="442">
|
<state relative-caret-position="647">
|
||||||
<caret line="14435" column="40" lean-forward="false" selection-start-line="14435" selection-start-column="34" selection-end-line="14435" selection-end-column="40" />
|
<caret line="7148" column="4" lean-forward="false" selection-start-line="7148" selection-start-column="4" selection-end-line="7148" selection-end-column="4" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="settings.ts" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/js/settings.ts">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="0">
|
||||||
|
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
|
@ -98,11 +93,11 @@
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file leaf-file-name="voice.ts" pinned="false" current-in-tab="true">
|
<file leaf-file-name="voice.ts" pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/js/voice.ts">
|
<entry file="file://$PROJECT_DIR$/js/voice.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="1201">
|
<state relative-caret-position="594">
|
||||||
<caret line="320" column="33" lean-forward="false" selection-start-line="320" selection-start-column="33" selection-end-line="320" selection-end-column="33" />
|
<caret line="51" column="10" lean-forward="false" selection-start-line="51" selection-start-column="10" selection-end-line="51" selection-end-column="10" />
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
|
@ -118,18 +113,26 @@
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file leaf-file-name="package.json" pinned="false" current-in-tab="false">
|
<file leaf-file-name="chat.ts" pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/package.json">
|
<entry file="file://$PROJECT_DIR$/js/chat.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="0">
|
<state relative-caret-position="513">
|
||||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
<caret line="32" column="41" lean-forward="false" selection-start-line="32" selection-start-column="41" selection-end-line="32" selection-end-column="41" />
|
||||||
<folding />
|
<folding>
|
||||||
|
<marker date="1519748729173" expanded="true" signature="1975:1985" ph="..." />
|
||||||
|
</folding>
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
</leaf>
|
</leaf>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="FindInProjectRecents">
|
||||||
|
<findStrings>
|
||||||
|
<find>createBuffer</find>
|
||||||
|
<find>on_data</find>
|
||||||
|
</findStrings>
|
||||||
|
</component>
|
||||||
<component name="Git.Settings">
|
<component name="Git.Settings">
|
||||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
|
@ -155,10 +158,10 @@
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpWorkspaceProjectConfiguration" backward_compatibility_performed="true" />
|
<component name="PhpWorkspaceProjectConfiguration" backward_compatibility_performed="true" />
|
||||||
<component name="ProjectFrameBounds" extendedState="6">
|
<component name="ProjectFrameBounds" extendedState="6">
|
||||||
<option name="x" value="2028" />
|
<option name="x" value="2918" />
|
||||||
<option name="y" value="357" />
|
<option name="y" value="-4" />
|
||||||
<option name="width" value="1855" />
|
<option name="width" value="1853" />
|
||||||
<option name="height" value="1084" />
|
<option name="height" value="1076" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectView">
|
<component name="ProjectView">
|
||||||
<navigator currentView="ProjectPane" proportions="" version="1">
|
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||||
|
@ -252,28 +255,30 @@
|
||||||
<option name="presentableId" value="Default" />
|
<option name="presentableId" value="Default" />
|
||||||
<updated>1519749313999</updated>
|
<updated>1519749313999</updated>
|
||||||
<workItem from="1519749316100" duration="9698000" />
|
<workItem from="1519749316100" duration="9698000" />
|
||||||
<workItem from="1520012895408" duration="6591000" />
|
<workItem from="1520012895408" duration="13484000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TimeTrackingManager">
|
<component name="TimeTrackingManager">
|
||||||
<option name="totallyTimeSpent" value="16289000" />
|
<option name="totallyTimeSpent" value="23182000" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ToolWindowManager">
|
<component name="ToolWindowManager">
|
||||||
<frame x="2028" y="357" width="3777" height="2172" extended-state="6" />
|
<frame x="1985" y="-4" width="3775" height="2164" extended-state="6" />
|
||||||
<editor active="true" />
|
<editor active="true" />
|
||||||
<layout>
|
<layout>
|
||||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
|
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
|
||||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="npm" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
|
<window_info id="npm" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
|
||||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="TypeScript" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32993197" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
<window_info id="TypeScript" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32993197" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.24980132" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.24980132" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||||
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.24980132" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
|
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.24980132" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
|
||||||
<window_info id="Docker" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
<window_info id="Docker" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
|
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
|
||||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||||
|
@ -281,7 +286,6 @@
|
||||||
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
|
||||||
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||||
</layout>
|
</layout>
|
||||||
</component>
|
</component>
|
||||||
|
@ -336,7 +340,9 @@
|
||||||
<option name="myLimit" value="2678400000" />
|
<option name="myLimit" value="2678400000" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XDebuggerManager">
|
<component name="XDebuggerManager">
|
||||||
<breakpoint-manager />
|
<breakpoint-manager>
|
||||||
|
<option name="time" value="1" />
|
||||||
|
</breakpoint-manager>
|
||||||
<watches-manager />
|
<watches-manager />
|
||||||
</component>
|
</component>
|
||||||
<component name="editorHistoryManager">
|
<component name="editorHistoryManager">
|
||||||
|
@ -460,16 +466,6 @@
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/js/connection.ts">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="0">
|
|
||||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
|
||||||
<folding>
|
|
||||||
<element signature="n#!!doc" expanded="true" />
|
|
||||||
</folding>
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/js/client.ts">
|
<entry file="file://$PROJECT_DIR$/js/client.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="0">
|
<state relative-caret-position="0">
|
||||||
|
@ -488,6 +484,14 @@
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/js/settings.ts">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="0">
|
||||||
|
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/js/ui/client.ts">
|
<entry file="file://$PROJECT_DIR$/js/ui/client.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="324">
|
<state relative-caret-position="324">
|
||||||
|
@ -496,26 +500,46 @@
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/js/codec/Codec.ts">
|
<entry file="file://$PROJECT_DIR$/js/chat.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="751">
|
<state relative-caret-position="513">
|
||||||
<caret line="99" column="102" lean-forward="false" selection-start-line="99" selection-start-column="102" selection-end-line="99" selection-end-column="102" />
|
<caret line="32" column="41" lean-forward="false" selection-start-line="32" selection-start-column="41" selection-end-line="32" selection-end-column="41" />
|
||||||
<folding />
|
<folding>
|
||||||
|
<marker date="1519748729173" expanded="true" signature="1975:1985" ph="..." />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/js/connection.ts">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="612">
|
||||||
|
<caret line="34" column="24" lean-forward="true" selection-start-line="34" selection-start-column="24" selection-end-line="34" selection-end-column="24" />
|
||||||
|
<folding>
|
||||||
|
<element signature="n#!!doc" expanded="true" />
|
||||||
|
</folding>
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/lib.es6.d.ts">
|
<entry file="file://$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external/lib.es6.d.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="442">
|
<state relative-caret-position="647">
|
||||||
<caret line="14435" column="40" lean-forward="false" selection-start-line="14435" selection-start-column="34" selection-end-line="14435" selection-end-column="40" />
|
<caret line="7148" column="4" lean-forward="false" selection-start-line="7148" selection-start-column="4" selection-end-line="7148" selection-end-column="4" />
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/js/voice.ts">
|
<entry file="file://$PROJECT_DIR$/js/voice.ts">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="1201">
|
<state relative-caret-position="594">
|
||||||
<caret line="320" column="33" lean-forward="false" selection-start-line="320" selection-start-column="33" selection-end-line="320" selection-end-column="33" />
|
<caret line="51" column="10" lean-forward="false" selection-start-line="51" selection-start-column="10" selection-end-line="51" selection-end-column="10" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/js/codec/Codec.ts">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="198">
|
||||||
|
<caret line="14" column="35" lean-forward="true" selection-start-line="14" selection-start-column="35" selection-end-line="14" selection-end-column="35" />
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
|
@ -5,10 +5,13 @@ class SampleBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Codec {
|
class Codec {
|
||||||
constructor() {
|
constructor(codecSampleRate) {
|
||||||
this.on_encoded_data = ($) => { };
|
this.on_encoded_data = ($) => { };
|
||||||
this._sampleBuffer = [];
|
this._sampleBuffer = [];
|
||||||
this.sampleRate = 120;
|
this.samplesPerUnit = 960;
|
||||||
|
this._codecSampleRate = codecSampleRate;
|
||||||
|
this._decodeResampler = new Resampler();
|
||||||
|
this._encodeResampler = new Resampler(codecSampleRate);
|
||||||
}
|
}
|
||||||
bufferedSamples(max = 0) {
|
bufferedSamples(max = 0) {
|
||||||
let value = 0;
|
let value = 0;
|
||||||
|
@ -17,15 +20,19 @@ class Codec {
|
||||||
console.log(value + " / " + max);
|
console.log(value + " / " + max);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
encodeSamples(array) {
|
encodeSamples(pcm) {
|
||||||
console.log("encode");
|
this._encodeResampler.resample(pcm).then(buffer => this.encodeSamples0(buffer))
|
||||||
this._sampleBuffer.push(new SampleBuffer(array));
|
.catch(error => console.error("Could not resample PCM data for codec. Error:" + error));
|
||||||
while (this.bufferedSamples(this.sampleRate) >= this.sampleRate) {
|
}
|
||||||
let buffer = new Float32Array(this.sampleRate);
|
encodeSamples0(buffer) {
|
||||||
|
console.log(buffer);
|
||||||
|
this._sampleBuffer.push(new SampleBuffer(buffer.getChannelData(0))); //TODO multi channel!
|
||||||
|
while (this.bufferedSamples(this.samplesPerUnit) >= this.samplesPerUnit) {
|
||||||
|
let buffer = new Float32Array(this.samplesPerUnit);
|
||||||
let index = 0;
|
let index = 0;
|
||||||
while (index < this.sampleRate) {
|
while (index < this.samplesPerUnit) {
|
||||||
let buf = this._sampleBuffer[0];
|
let buf = this._sampleBuffer[0];
|
||||||
let len = Math.min(buf.buffer.length - buf.index, this.sampleRate - index);
|
let len = Math.min(buf.buffer.length - buf.index, this.samplesPerUnit - index);
|
||||||
buffer.set(buf.buffer.subarray(buf.index, buf.index + len));
|
buffer.set(buf.buffer.subarray(buf.index, buf.index + len));
|
||||||
index += len;
|
index += len;
|
||||||
buf.index += len;
|
buf.index += len;
|
||||||
|
@ -37,14 +44,17 @@ class Codec {
|
||||||
if (result instanceof Uint8Array)
|
if (result instanceof Uint8Array)
|
||||||
this.on_encoded_data(result);
|
this.on_encoded_data(result);
|
||||||
else
|
else
|
||||||
return result;
|
console.error("[Codec][" + this.name() + "] Could not encode buffer. Result: " + result);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
decodeSamples(data) {
|
||||||
|
return this.decode(data).then(buffer => this._decodeResampler.resample(buffer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class OpusCodec extends Codec {
|
class OpusCodec extends Codec {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super(48000);
|
||||||
this.channelCount = 1;
|
this.channelCount = 1;
|
||||||
}
|
}
|
||||||
name() {
|
name() {
|
||||||
|
@ -56,21 +66,25 @@ class OpusCodec extends Codec {
|
||||||
this.fn_encode = Module.cwrap("codec_opus_encode", "number", ["pointer", "pointer", "number", "number"]);
|
this.fn_encode = Module.cwrap("codec_opus_encode", "number", ["pointer", "pointer", "number", "number"]);
|
||||||
this.nativeHandle = this.fn_newHandle(1);
|
this.nativeHandle = this.fn_newHandle(1);
|
||||||
}
|
}
|
||||||
deinitialise() {
|
deinitialise() { } //TODO
|
||||||
}
|
|
||||||
decode(data) {
|
decode(data) {
|
||||||
let maxBytes = 4096;
|
return new Promise((resolve, reject) => {
|
||||||
let buffer = Module._malloc(maxBytes);
|
let maxBytes = 4096;
|
||||||
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, buffer, maxBytes);
|
let buffer = Module._malloc(maxBytes);
|
||||||
heapBytes.set(data);
|
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, buffer, maxBytes);
|
||||||
let result = this.fn_decode(this.nativeHandle, heapBytes.byteOffset, data.byteLength, maxBytes);
|
heapBytes.set(data);
|
||||||
if (result < 0) {
|
let result = this.fn_decode(this.nativeHandle, heapBytes.byteOffset, data.byteLength, maxBytes);
|
||||||
|
if (result < 0) {
|
||||||
|
Module._free(buffer);
|
||||||
|
reject("invalid result on decode (" + result + ")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let buf = Module.HEAPF32.slice(heapBytes.byteOffset / 4, (heapBytes.byteOffset / 4) + (result * this.channelCount));
|
||||||
Module._free(buffer);
|
Module._free(buffer);
|
||||||
return "invalid result on decode (" + result + ")";
|
let audioBuf = AudioController.globalContext.createBuffer(this.channelCount, result, this._codecSampleRate);
|
||||||
}
|
audioBuf.copyToChannel(buf, 0);
|
||||||
let buf = Module.HEAPF32.slice(heapBytes.byteOffset / 4, (heapBytes.byteOffset / 4) + (result * this.channelCount));
|
resolve(audioBuf);
|
||||||
Module._free(buffer);
|
});
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
encode(data) {
|
encode(data) {
|
||||||
let maxBytes = data.byteLength;
|
let maxBytes = data.byteLength;
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -11,20 +11,27 @@ class SampleBuffer {
|
||||||
abstract class Codec {
|
abstract class Codec {
|
||||||
on_encoded_data: (Uint8Array) => void = ($) => {};
|
on_encoded_data: (Uint8Array) => void = ($) => {};
|
||||||
|
|
||||||
|
protected _decodeResampler: Resampler;
|
||||||
|
protected _encodeResampler: Resampler;
|
||||||
|
protected _codecSampleRate: number;
|
||||||
protected _sampleBuffer: SampleBuffer[] = [];
|
protected _sampleBuffer: SampleBuffer[] = [];
|
||||||
sampleRate: number = 120;
|
|
||||||
|
|
||||||
constructor(){}
|
samplesPerUnit: number = 960;
|
||||||
|
|
||||||
|
protected constructor(codecSampleRate: number){
|
||||||
|
this._codecSampleRate = codecSampleRate;
|
||||||
|
this._decodeResampler = new Resampler();
|
||||||
|
this._encodeResampler = new Resampler(codecSampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
abstract name() : string;
|
abstract name() : string;
|
||||||
abstract initialise();
|
abstract initialise();
|
||||||
abstract deinitialise();
|
abstract deinitialise();
|
||||||
|
|
||||||
|
protected abstract decode(data: Uint8Array) : Promise<AudioBuffer>;
|
||||||
abstract decode(data: Uint8Array) : Float32Array | string;
|
|
||||||
|
|
||||||
protected abstract encode(data: Float32Array) : Uint8Array | string;
|
protected abstract encode(data: Float32Array) : Uint8Array | string;
|
||||||
|
|
||||||
|
|
||||||
protected bufferedSamples(max: number = 0) : number {
|
protected bufferedSamples(max: number = 0) : number {
|
||||||
let value = 0;
|
let value = 0;
|
||||||
for(let i = 0; i < this._sampleBuffer.length && value < max; i++)
|
for(let i = 0; i < this._sampleBuffer.length && value < max; i++)
|
||||||
|
@ -33,16 +40,21 @@ abstract class Codec {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeSamples(array: Float32Array) : boolean | string {
|
encodeSamples(pcm: AudioBuffer) {
|
||||||
console.log("encode");
|
this._encodeResampler.resample(pcm).then(buffer => this.encodeSamples0(buffer))
|
||||||
this._sampleBuffer.push(new SampleBuffer(array));
|
.catch(error => console.error("Could not resample PCM data for codec. Error:" + error));
|
||||||
|
}
|
||||||
|
|
||||||
while(this.bufferedSamples(this.sampleRate) >= this.sampleRate) {
|
private encodeSamples0(buffer: AudioBuffer) {
|
||||||
let buffer = new Float32Array(this.sampleRate);
|
console.log(buffer);
|
||||||
|
this._sampleBuffer.push(new SampleBuffer(buffer.getChannelData(0))); //TODO multi channel!
|
||||||
|
|
||||||
|
while(this.bufferedSamples(this.samplesPerUnit) >= this.samplesPerUnit) {
|
||||||
|
let buffer = new Float32Array(this.samplesPerUnit);
|
||||||
let index = 0;
|
let index = 0;
|
||||||
while(index < this.sampleRate) {
|
while(index < this.samplesPerUnit) {
|
||||||
let buf = this._sampleBuffer[0];
|
let buf = this._sampleBuffer[0];
|
||||||
let len = Math.min(buf.buffer.length - buf.index, this.sampleRate - index);
|
let len = Math.min(buf.buffer.length - buf.index, this.samplesPerUnit - index);
|
||||||
buffer.set(buf.buffer.subarray(buf.index, buf.index + len));
|
buffer.set(buf.buffer.subarray(buf.index, buf.index + len));
|
||||||
index += len;
|
index += len;
|
||||||
buf.index += len;
|
buf.index += len;
|
||||||
|
@ -53,10 +65,14 @@ abstract class Codec {
|
||||||
|
|
||||||
let result = this.encode(buffer);
|
let result = this.encode(buffer);
|
||||||
if(result instanceof Uint8Array) this.on_encoded_data(result);
|
if(result instanceof Uint8Array) this.on_encoded_data(result);
|
||||||
else return result;
|
else console.error("[Codec][" + this.name() + "] Could not encode buffer. Result: " + result);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decodeSamples(data: Uint8Array) : Promise<AudioBuffer> {
|
||||||
|
return this.decode(data).then(buffer => this._decodeResampler.resample(buffer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpusCodec extends Codec {
|
class OpusCodec extends Codec {
|
||||||
|
@ -68,7 +84,7 @@ class OpusCodec extends Codec {
|
||||||
private fn_encode: any;
|
private fn_encode: any;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super(48000);
|
||||||
}
|
}
|
||||||
|
|
||||||
name(): string {
|
name(): string {
|
||||||
|
@ -83,23 +99,27 @@ class OpusCodec extends Codec {
|
||||||
this.nativeHandle = this.fn_newHandle(1);
|
this.nativeHandle = this.fn_newHandle(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
deinitialise() {
|
deinitialise() { } //TODO
|
||||||
|
|
||||||
}
|
decode(data: Uint8Array): Promise<AudioBuffer> {
|
||||||
|
return new Promise<AudioBuffer>((resolve, reject) => {
|
||||||
decode(data: Uint8Array): Float32Array | string {
|
let maxBytes = 4096;
|
||||||
let maxBytes = 4096;
|
let buffer = Module._malloc(maxBytes);
|
||||||
let buffer = Module._malloc(maxBytes);
|
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, buffer, maxBytes);
|
||||||
let heapBytes = new Uint8Array(Module.HEAPU8.buffer, buffer, maxBytes);
|
heapBytes.set(data);
|
||||||
heapBytes.set(data);
|
let result = this.fn_decode(this.nativeHandle, heapBytes.byteOffset, data.byteLength, maxBytes);
|
||||||
let result = this.fn_decode(this.nativeHandle, heapBytes.byteOffset, data.byteLength, maxBytes);
|
if(result < 0) {
|
||||||
if(result < 0) {
|
Module._free(buffer);
|
||||||
|
reject("invalid result on decode (" + result + ")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let buf = Module.HEAPF32.slice(heapBytes.byteOffset / 4, (heapBytes.byteOffset / 4) + (result * this.channelCount));
|
||||||
Module._free(buffer);
|
Module._free(buffer);
|
||||||
return "invalid result on decode (" + result + ")";
|
|
||||||
}
|
let audioBuf = AudioController.globalContext.createBuffer(this.channelCount, result, this._codecSampleRate);
|
||||||
let buf = Module.HEAPF32.slice(heapBytes.byteOffset / 4, (heapBytes.byteOffset / 4) + (result * this.channelCount));
|
audioBuf.copyToChannel(buf, 0);
|
||||||
Module._free(buffer);
|
resolve(audioBuf);
|
||||||
return buf;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
encode(data: Float32Array): Uint8Array | string {
|
encode(data: Float32Array): Uint8Array | string {
|
||||||
|
|
122
js/voice.js
122
js/voice.js
|
@ -1,17 +1,44 @@
|
||||||
/// <reference path="client.ts" />
|
/// <reference path="client.ts" />
|
||||||
class VoiceConnection {
|
class VoiceConnection {
|
||||||
|
/*
|
||||||
|
private _voicePacketBuffer: Uint8Array[] = [];
|
||||||
|
private _voicePacketSender: NodeJS.Timer;
|
||||||
|
private _triggered = false;
|
||||||
|
*/
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
|
this.vpacketId = 0;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.voiceRecorder = new VoiceRecorder(this);
|
this.voiceRecorder = new VoiceRecorder(this);
|
||||||
this.voiceRecorder.on_data = data => this.sendPCMData(data);
|
this.voiceRecorder.on_data = data => this.handleVoiceData(data);
|
||||||
this.codec = new OpusCodec();
|
this.codec = new OpusCodec();
|
||||||
this.codec.initialise();
|
this.codec.initialise();
|
||||||
this.codec.on_encoded_data = buffer => {
|
this.codec.on_encoded_data = buffer => {
|
||||||
if (this.dataChannel) {
|
if (this.dataChannel) {
|
||||||
console.log("Send buffer");
|
this.vpacketId++;
|
||||||
this.dataChannel.send(buffer);
|
if (this.vpacketId > 65535)
|
||||||
|
this.vpacketId = 0;
|
||||||
|
let packet = new Uint8Array(buffer.byteLength + 2 + 3);
|
||||||
|
packet[0] = this.vpacketId < 6 ? 1 : 0; //Flag header
|
||||||
|
packet[1] = 0; //Flag fragmented
|
||||||
|
packet[2] = (this.vpacketId >> 8) & 0xFF; //HIGHT(voiceID)
|
||||||
|
packet[3] = (this.vpacketId >> 0) & 0xFF; //LOW (voiceID)
|
||||||
|
packet[4] = 4; //Codec
|
||||||
|
packet.set(buffer, 5);
|
||||||
|
//this._voicePacketBuffer.push(packet);
|
||||||
|
this.dataChannel.send(packet);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
|
this._voicePacketSender = setInterval(() => {
|
||||||
|
if(this._voicePacketBuffer.length > 5 || this._triggered) {
|
||||||
|
let packet = this._voicePacketBuffer.pop_front();
|
||||||
|
if (packet) {
|
||||||
|
this.dataChannel.send(packet);
|
||||||
|
}
|
||||||
|
this._triggered = this._voicePacketBuffer.length > 0;
|
||||||
|
}
|
||||||
|
}, 20);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
createSession() {
|
createSession() {
|
||||||
const config = {};
|
const config = {};
|
||||||
|
@ -66,26 +93,24 @@ class VoiceConnection {
|
||||||
}
|
}
|
||||||
onDataChannelMessage(message) {
|
onDataChannelMessage(message) {
|
||||||
let bin = new Uint8Array(message.data);
|
let bin = new Uint8Array(message.data);
|
||||||
let clientId = bin[0] << 8 | bin[1];
|
let clientId = bin[2] << 8 | bin[3];
|
||||||
console.log("Client id " + clientId);
|
let packetId = bin[0] << 8 | bin[1];
|
||||||
|
let codec = bin[4];
|
||||||
|
console.log("Client id " + clientId + " PacketID " + packetId + " Codec: " + codec);
|
||||||
let client = this.client.channelTree.findClient(clientId);
|
let client = this.client.channelTree.findClient(clientId);
|
||||||
if (!client) {
|
if (!client) {
|
||||||
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
|
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var encodedData = new Uint8Array(message.data, 4);
|
var encodedData = new Uint8Array(message.data, 5);
|
||||||
let result = this.codec.decode(encodedData);
|
this.codec.decodeSamples(encodedData).then(buffer => client.getAudioController().play(buffer)).catch(error => {
|
||||||
if (result instanceof Float32Array)
|
console.error("Could not playback client's (" + clientId + ") audio (" + error + ")");
|
||||||
client.getAudioController().play(result);
|
});
|
||||||
else
|
|
||||||
console.log("Invalid decode " + result);
|
|
||||||
}
|
}
|
||||||
sendPCMData(data) {
|
handleVoiceData(data) {
|
||||||
/*
|
setTimeout(() => {
|
||||||
let result = this.codec.encodeSamples(data);
|
this.codec.encodeSamples(data);
|
||||||
if(!result) console.error("Could not encode audio: " + result);
|
}, 1);
|
||||||
*/
|
|
||||||
this.client.getClient().getAudioController().play(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class VoiceRecorder {
|
class VoiceRecorder {
|
||||||
|
@ -100,8 +125,9 @@ class VoiceRecorder {
|
||||||
this.processor = this.audioContext.createScriptProcessor(VoiceRecorder.BUFFER_SIZE, VoiceRecorder.CHANNELS, VoiceRecorder.CHANNELS);
|
this.processor = this.audioContext.createScriptProcessor(VoiceRecorder.BUFFER_SIZE, VoiceRecorder.CHANNELS, VoiceRecorder.CHANNELS);
|
||||||
const _this = this;
|
const _this = this;
|
||||||
this.processor.addEventListener('audioprocess', ev => {
|
this.processor.addEventListener('audioprocess', ev => {
|
||||||
|
console.log(ev.inputBuffer);
|
||||||
if (_this.microphoneStream)
|
if (_this.microphoneStream)
|
||||||
this.on_data(ev.inputBuffer.getChannelData(VoiceRecorder.CHANNEL));
|
this.on_data(ev.inputBuffer);
|
||||||
});
|
});
|
||||||
//Not needed but make sure we have data for the preprocessor
|
//Not needed but make sure we have data for the preprocessor
|
||||||
this.mute = this.audioContext.createGain();
|
this.mute = this.audioContext.createGain();
|
||||||
|
@ -156,10 +182,15 @@ class VoiceRecorder {
|
||||||
}
|
}
|
||||||
VoiceRecorder.CHANNEL = 0;
|
VoiceRecorder.CHANNEL = 0;
|
||||||
VoiceRecorder.CHANNELS = 1;
|
VoiceRecorder.CHANNELS = 1;
|
||||||
VoiceRecorder.BUFFER_SIZE = 4096;
|
VoiceRecorder.BUFFER_SIZE = 16384 / 2;
|
||||||
class AudioController {
|
class AudioController {
|
||||||
|
static get globalContext() {
|
||||||
|
if (this._globalContext)
|
||||||
|
return this._globalContext;
|
||||||
|
this._globalContext = new AudioContext();
|
||||||
|
return this._globalContext;
|
||||||
|
}
|
||||||
constructor() {
|
constructor() {
|
||||||
this.resambler = new Resampler();
|
|
||||||
this.speakerContext = AudioController.globalContext;
|
this.speakerContext = AudioController.globalContext;
|
||||||
this.nextTime = 0;
|
this.nextTime = 0;
|
||||||
this.last = 0;
|
this.last = 0;
|
||||||
|
@ -169,23 +200,9 @@ class AudioController {
|
||||||
this.onSpeaking = function () { };
|
this.onSpeaking = function () { };
|
||||||
this.onSilence = function () { };
|
this.onSilence = function () { };
|
||||||
}
|
}
|
||||||
static get globalContext() {
|
play(buffer) {
|
||||||
if (this._globalContext)
|
if (buffer.sampleRate != this.speakerContext.sampleRate)
|
||||||
return this._globalContext;
|
console.warn("[AudioController] Source sample rate isnt equal to playback sample rate!");
|
||||||
this._globalContext = new AudioContext();
|
|
||||||
return this._globalContext;
|
|
||||||
}
|
|
||||||
play(pcm) {
|
|
||||||
//let buffer = this.speakerContext.createBuffer(1, 960, 48000);
|
|
||||||
//buffer.copyToChannel(pcm, 0);
|
|
||||||
this.resambler.resample(pcm, (buffer) => this.play0(buffer));
|
|
||||||
//this.play0(buffer);
|
|
||||||
}
|
|
||||||
play0(buffer) {
|
|
||||||
//960
|
|
||||||
console.log(buffer);
|
|
||||||
//let buffer = this.speakerContext.createBuffer(1, 960, 44100);
|
|
||||||
//buffer.copyToChannel(pcm, 0);
|
|
||||||
this.audioCache.push(buffer);
|
this.audioCache.push(buffer);
|
||||||
let currentTime = new Date().getTime();
|
let currentTime = new Date().getTime();
|
||||||
if ((currentTime - this.last) > 50) {
|
if ((currentTime - this.last) > 50) {
|
||||||
|
@ -207,8 +224,8 @@ class AudioController {
|
||||||
;
|
;
|
||||||
playCache(cache) {
|
playCache(cache) {
|
||||||
while (cache.length) {
|
while (cache.length) {
|
||||||
var buffer = cache.shift();
|
let buffer = cache.shift();
|
||||||
var source = this.speakerContext.createBufferSource();
|
let source = this.speakerContext.createBufferSource();
|
||||||
source.buffer = buffer;
|
source.buffer = buffer;
|
||||||
source.connect(this.speakerContext.destination);
|
source.connect(this.speakerContext.destination);
|
||||||
if (this.nextTime == 0) {
|
if (this.nextTime == 0) {
|
||||||
|
@ -234,26 +251,19 @@ class AudioController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Resampler {
|
class Resampler {
|
||||||
constructor() {
|
constructor(targetSampleRate = 44100) {
|
||||||
|
this.targetSampleRate = targetSampleRate;
|
||||||
}
|
}
|
||||||
resample(pcm, callback) {
|
resample(buffer) {
|
||||||
/*
|
if (buffer.sampleRate == this.targetSampleRate)
|
||||||
let buffer = AudioController.globalContext.createBuffer(1, pcm.length, 48000);
|
return new Promise(resolve => resolve(buffer));
|
||||||
buffer.copyToChannel(pcm, 0);
|
console.log(this.targetSampleRate);
|
||||||
callback(buffer);
|
let context = new OfflineAudioContext(1, Math.ceil(buffer.length * this.targetSampleRate / buffer.sampleRate), this.targetSampleRate);
|
||||||
*/
|
let source = context.createBufferSource();
|
||||||
this.context = new OfflineAudioContext(1, 882, 44100);
|
|
||||||
let buffer = this.context.createBuffer(1, pcm.length, 48000);
|
|
||||||
buffer.copyToChannel(pcm, 0);
|
|
||||||
let source = this.context.createBufferSource();
|
|
||||||
source.buffer = buffer;
|
source.buffer = buffer;
|
||||||
source.connect(this.context.destination);
|
source.connect(context.destination);
|
||||||
source.start(0);
|
source.start(0);
|
||||||
//console.log(source.buffer.getChannelData(0));
|
return context.startRendering();
|
||||||
this.context.startRendering().then(e => callback(e)).catch(error => {
|
|
||||||
console.error("Could not resample audio");
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=voice.js.map
|
//# sourceMappingURL=voice.js.map
|
File diff suppressed because one or more lines are too long
116
js/voice.ts
116
js/voice.ts
|
@ -9,19 +9,47 @@ class VoiceConnection {
|
||||||
start: number;
|
start: number;
|
||||||
|
|
||||||
codec: Codec;
|
codec: Codec;
|
||||||
|
vpacketId: number = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
private _voicePacketBuffer: Uint8Array[] = [];
|
||||||
|
private _voicePacketSender: NodeJS.Timer;
|
||||||
|
private _triggered = false;
|
||||||
|
*/
|
||||||
|
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.voiceRecorder = new VoiceRecorder(this);
|
this.voiceRecorder = new VoiceRecorder(this);
|
||||||
this.voiceRecorder.on_data = data => this.sendPCMData(data);
|
this.voiceRecorder.on_data = data => this.handleVoiceData(data);
|
||||||
this.codec = new OpusCodec();
|
this.codec = new OpusCodec();
|
||||||
this.codec.initialise();
|
this.codec.initialise();
|
||||||
this.codec.on_encoded_data = buffer => {
|
this.codec.on_encoded_data = buffer => {
|
||||||
if(this.dataChannel) {
|
if(this.dataChannel) {
|
||||||
console.log("Send buffer");
|
this.vpacketId++;
|
||||||
this.dataChannel.send(buffer);
|
if(this.vpacketId > 65535) this.vpacketId = 0;
|
||||||
|
let packet = new Uint8Array(buffer.byteLength + 2 + 3);
|
||||||
|
packet[0] = this.vpacketId < 6 ? 1 : 0; //Flag header
|
||||||
|
packet[1] = 0; //Flag fragmented
|
||||||
|
packet[2] = (this.vpacketId >> 8) & 0xFF; //HIGHT(voiceID)
|
||||||
|
packet[3] = (this.vpacketId >> 0) & 0xFF; //LOW (voiceID)
|
||||||
|
packet[4] = 4; //Codec
|
||||||
|
packet.set(buffer, 5);
|
||||||
|
//this._voicePacketBuffer.push(packet);
|
||||||
|
this.dataChannel.send(packet);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
this._voicePacketSender = setInterval(() => {
|
||||||
|
if(this._voicePacketBuffer.length > 5 || this._triggered) {
|
||||||
|
let packet = this._voicePacketBuffer.pop_front();
|
||||||
|
if (packet) {
|
||||||
|
this.dataChannel.send(packet);
|
||||||
|
}
|
||||||
|
this._triggered = this._voicePacketBuffer.length > 0;
|
||||||
|
}
|
||||||
|
}, 20);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,36 +115,35 @@ class VoiceConnection {
|
||||||
|
|
||||||
onDataChannelMessage(message) {
|
onDataChannelMessage(message) {
|
||||||
let bin = new Uint8Array(message.data);
|
let bin = new Uint8Array(message.data);
|
||||||
let clientId = bin[0] << 8 | bin[1];
|
let clientId = bin[2] << 8 | bin[3];
|
||||||
console.log("Client id " + clientId);
|
let packetId = bin[0] << 8 | bin[1];
|
||||||
|
let codec = bin[4];
|
||||||
|
console.log("Client id " + clientId + " PacketID " + packetId + " Codec: " + codec);
|
||||||
let client = this.client.channelTree.findClient(clientId);
|
let client = this.client.channelTree.findClient(clientId);
|
||||||
if(!client) {
|
if(!client) {
|
||||||
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
|
console.error("Having voice from unknown client? (ClientID: " + clientId + ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var encodedData = new Uint8Array(message.data, 4);
|
var encodedData = new Uint8Array(message.data, 5);
|
||||||
let result = this.codec.decode(encodedData)
|
this.codec.decodeSamples(encodedData).then(buffer => client.getAudioController().play(buffer)).catch(error => {
|
||||||
if(result instanceof Float32Array)
|
console.error("Could not playback client's (" + clientId + ") audio (" + error + ")");
|
||||||
client.getAudioController().play(result);
|
});
|
||||||
else console.log("Invalid decode " + result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendPCMData(data: any) {
|
private handleVoiceData(data: AudioBuffer) {
|
||||||
/*
|
setTimeout(() => {
|
||||||
let result = this.codec.encodeSamples(data);
|
this.codec.encodeSamples(data);
|
||||||
if(!result) console.error("Could not encode audio: " + result);
|
}, 1);
|
||||||
*/
|
|
||||||
this.client.getClient().getAudioController().play(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoiceRecorder {
|
class VoiceRecorder {
|
||||||
private static readonly CHANNEL = 0;
|
private static readonly CHANNEL = 0;
|
||||||
private static readonly CHANNELS = 1;
|
private static readonly CHANNELS = 1;
|
||||||
private static readonly BUFFER_SIZE = 4096;
|
private static readonly BUFFER_SIZE = 16384 / 2;
|
||||||
|
|
||||||
handle: VoiceConnection;
|
handle: VoiceConnection;
|
||||||
on_data: (data: any) => void = (data) => {};
|
on_data: (data: AudioBuffer) => void = (data) => {};
|
||||||
|
|
||||||
private _recording: boolean = false;
|
private _recording: boolean = false;
|
||||||
|
|
||||||
|
@ -137,8 +164,9 @@ class VoiceRecorder {
|
||||||
|
|
||||||
const _this = this;
|
const _this = this;
|
||||||
this.processor.addEventListener('audioprocess', ev => {
|
this.processor.addEventListener('audioprocess', ev => {
|
||||||
|
console.log(ev.inputBuffer);
|
||||||
if(_this.microphoneStream)
|
if(_this.microphoneStream)
|
||||||
this.on_data(ev.inputBuffer.getChannelData(VoiceRecorder.CHANNEL))
|
this.on_data(ev.inputBuffer)
|
||||||
});
|
});
|
||||||
|
|
||||||
//Not needed but make sure we have data for the preprocessor
|
//Not needed but make sure we have data for the preprocessor
|
||||||
|
@ -212,7 +240,6 @@ class AudioController {
|
||||||
init: boolean;
|
init: boolean;
|
||||||
stimeout: NodeJS.Timer;
|
stimeout: NodeJS.Timer;
|
||||||
|
|
||||||
resambler: Resampler = new Resampler();
|
|
||||||
//Events
|
//Events
|
||||||
onSpeaking: () => void;
|
onSpeaking: () => void;
|
||||||
onSilence: () => void;
|
onSilence: () => void;
|
||||||
|
@ -229,18 +256,9 @@ class AudioController {
|
||||||
this.onSilence = function () { }
|
this.onSilence = function () { }
|
||||||
}
|
}
|
||||||
|
|
||||||
play(pcm: Float32Array) {
|
play(buffer: AudioBuffer) {
|
||||||
//let buffer = this.speakerContext.createBuffer(1, 960, 48000);
|
if(buffer.sampleRate != this.speakerContext.sampleRate)
|
||||||
//buffer.copyToChannel(pcm, 0);
|
console.warn("[AudioController] Source sample rate isnt equal to playback sample rate!");
|
||||||
this.resambler.resample(pcm, (buffer: AudioBuffer) => this.play0(buffer));
|
|
||||||
//this.play0(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
play0(buffer: AudioBuffer) {
|
|
||||||
//960
|
|
||||||
console.log(buffer);
|
|
||||||
//let buffer = this.speakerContext.createBuffer(1, 960, 44100);
|
|
||||||
//buffer.copyToChannel(pcm, 0);
|
|
||||||
this.audioCache.push(buffer);
|
this.audioCache.push(buffer);
|
||||||
|
|
||||||
let currentTime = new Date().getTime();
|
let currentTime = new Date().getTime();
|
||||||
|
@ -265,8 +283,8 @@ class AudioController {
|
||||||
|
|
||||||
playCache(cache) {
|
playCache(cache) {
|
||||||
while (cache.length) {
|
while (cache.length) {
|
||||||
var buffer = cache.shift();
|
let buffer = cache.shift();
|
||||||
var source = this.speakerContext.createBufferSource();
|
let source = this.speakerContext.createBufferSource();
|
||||||
|
|
||||||
source.buffer = buffer;
|
source.buffer = buffer;
|
||||||
source.connect(this.speakerContext.destination);
|
source.connect(this.speakerContext.destination);
|
||||||
|
@ -294,32 +312,24 @@ class AudioController {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Resampler {
|
class Resampler {
|
||||||
context: OfflineAudioContext;
|
targetSampleRate: number;
|
||||||
|
|
||||||
constructor(){
|
constructor(targetSampleRate: number = 44100){
|
||||||
|
this.targetSampleRate = targetSampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
resample(pcm: Float32Array, callback: (AudioBuffer) => void) {
|
resample(buffer: AudioBuffer) : Promise<AudioBuffer> {
|
||||||
/*
|
if(buffer.sampleRate == this.targetSampleRate)
|
||||||
let buffer = AudioController.globalContext.createBuffer(1, pcm.length, 48000);
|
return new Promise<AudioBuffer>(resolve => resolve(buffer));
|
||||||
buffer.copyToChannel(pcm, 0);
|
|
||||||
callback(buffer);
|
|
||||||
*/
|
|
||||||
|
|
||||||
this.context = new OfflineAudioContext(1, 882, 44100);
|
console.log(this.targetSampleRate);
|
||||||
let buffer = this.context.createBuffer(1, pcm.length, 48000);
|
let context = new OfflineAudioContext(1, Math.ceil(buffer.length * this.targetSampleRate / buffer.sampleRate), this.targetSampleRate);
|
||||||
buffer.copyToChannel(pcm, 0);
|
|
||||||
|
|
||||||
let source = this.context.createBufferSource();
|
let source = context.createBufferSource();
|
||||||
source.buffer = buffer;
|
source.buffer = buffer;
|
||||||
source.connect(this.context.destination);
|
source.connect(context.destination);
|
||||||
source.start(0);
|
source.start(0);
|
||||||
//console.log(source.buffer.getChannelData(0));
|
|
||||||
|
|
||||||
this.context.startRendering().then(e => callback(e)).catch(error => {
|
|
||||||
console.error("Could not resample audio");
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
return context.startRendering();
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue