Compare commits
16 commits
Author | SHA1 | Date | |
---|---|---|---|
Lily Tsuru | 3c585b3a04 | ||
Lily Tsuru | 0379b729eb | ||
Lily Tsuru | 183e11dc0d | ||
Lily Tsuru | ddd3483620 | ||
Lily Tsuru | b4a6860e75 | ||
Lily Tsuru | 326d3e5161 | ||
Lily Tsuru | 9a9d0043f2 | ||
Lily Tsuru | 510d3547a2 | ||
Lily Tsuru | cc59c0c6db | ||
Lily Tsuru | d95d305734 | ||
Lily Tsuru | 126566c3cf | ||
Lily Tsuru | 3b127a0b08 | ||
Lily Tsuru | 13ce046d3f | ||
Lily Tsuru | 1ebd3285f9 | ||
Lily Tsuru | bd048875c8 | ||
Lily Tsuru | 20f59c5663 |
44
.clang-format
Executable file
44
.clang-format
Executable file
|
@ -0,0 +1,44 @@
|
|||
BasedOnStyle: Google
|
||||
|
||||
# force T* or T&
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
|
||||
TabWidth: 4
|
||||
IndentWidth: 4
|
||||
UseTab: Always
|
||||
IndentPPDirectives: BeforeHash
|
||||
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakStringLiterals: false
|
||||
|
||||
ColumnLimit: 150
|
||||
CompactNamespaces: false
|
||||
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ContinuationIndentWidth: 0
|
||||
|
||||
# turning this on causes major issues with initializer lists
|
||||
Cpp11BracedListStyle: false
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
|
||||
FixNamespaceComments: true
|
||||
|
||||
NamespaceIndentation: All
|
||||
ReflowComments: true
|
||||
|
||||
SortIncludes: CaseInsensitive
|
||||
SortUsingDeclarations: true
|
||||
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeParens: Never
|
||||
SpacesBeforeTrailingComments: 1
|
11
.editorconfig
Normal file
11
.editorconfig
Normal file
|
@ -0,0 +1,11 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
# specifically for YAML
|
||||
[{yml, yaml}]
|
||||
indent_style = space
|
370
.gitignore
vendored
370
.gitignore
vendored
|
@ -1,363 +1,11 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
# ccls/clangd
|
||||
.cache/
|
||||
**/bin/
|
||||
**/obj/
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
# on your own machine, please.
|
||||
/speech2/build
|
||||
/speech2/build-debug
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
# cmake tools is viciously unaware of subdirectories
|
||||
/build
|
||||
|
|
201
.gitmodules
vendored
Normal file
201
.gitmodules
vendored
Normal file
|
@ -0,0 +1,201 @@
|
|||
[submodule "speech2/third_party/boost/algorithm"]
|
||||
path = speech2/third_party/boost/algorithm
|
||||
url = https://github.com/boostorg/algorithm.git
|
||||
[submodule "speech2/third_party/boost/align"]
|
||||
path = speech2/third_party/boost/align
|
||||
url = https://github.com/boostorg/align.git
|
||||
[submodule "speech2/third_party/boost/array"]
|
||||
path = speech2/third_party/boost/array
|
||||
url = https://github.com/boostorg/array.git
|
||||
[submodule "speech2/third_party/boost/assert"]
|
||||
path = speech2/third_party/boost/assert
|
||||
url = https://github.com/boostorg/assert.git
|
||||
[submodule "speech2/third_party/boost/atomic"]
|
||||
path = speech2/third_party/boost/atomic
|
||||
url = https://github.com/boostorg/atomic.git
|
||||
[submodule "speech2/third_party/boost/bind"]
|
||||
path = speech2/third_party/boost/bind
|
||||
url = https://github.com/boostorg/bind.git
|
||||
[submodule "speech2/third_party/boost/charconv"]
|
||||
path = speech2/third_party/boost/charconv
|
||||
url = https://github.com/boostorg/charconv.git
|
||||
[submodule "speech2/third_party/boost/chrono"]
|
||||
path = speech2/third_party/boost/chrono
|
||||
url = https://github.com/boostorg/chrono.git
|
||||
[submodule "speech2/third_party/boost/circular_buffer"]
|
||||
path = speech2/third_party/boost/circular_buffer
|
||||
url = https://github.com/boostorg/circular_buffer.git
|
||||
[submodule "speech2/third_party/boost/concept_check"]
|
||||
path = speech2/third_party/boost/concept_check
|
||||
url = https://github.com/boostorg/concept_check.git
|
||||
[submodule "speech2/third_party/boost/config"]
|
||||
path = speech2/third_party/boost/config
|
||||
url = https://github.com/boostorg/config.git
|
||||
[submodule "speech2/third_party/boost/container"]
|
||||
path = speech2/third_party/boost/container
|
||||
url = https://github.com/boostorg/container.git
|
||||
[submodule "speech2/third_party/boost/container_hash"]
|
||||
path = speech2/third_party/boost/container_hash
|
||||
url = https://github.com/boostorg/container_hash.git
|
||||
[submodule "speech2/third_party/boost/context"]
|
||||
path = speech2/third_party/boost/context
|
||||
url = https://github.com/boostorg/context.git
|
||||
[submodule "speech2/third_party/boost/conversion"]
|
||||
path = speech2/third_party/boost/conversion
|
||||
url = https://github.com/boostorg/conversion.git
|
||||
[submodule "speech2/third_party/boost/core"]
|
||||
path = speech2/third_party/boost/core
|
||||
url = https://github.com/boostorg/core.git
|
||||
[submodule "speech2/third_party/boost/coroutine"]
|
||||
path = speech2/third_party/boost/coroutine
|
||||
url = https://github.com/boostorg/coroutine.git
|
||||
[submodule "speech2/third_party/boost/date_time"]
|
||||
path = speech2/third_party/boost/date_time
|
||||
url = https://github.com/boostorg/date_time.git
|
||||
[submodule "speech2/third_party/boost/describe"]
|
||||
path = speech2/third_party/boost/describe
|
||||
url = https://github.com/boostorg/describe.git
|
||||
[submodule "speech2/third_party/boost/detail"]
|
||||
path = speech2/third_party/boost/detail
|
||||
url = https://github.com/boostorg/detail.git
|
||||
[submodule "speech2/third_party/boost/endian"]
|
||||
path = speech2/third_party/boost/endian
|
||||
url = https://github.com/boostorg/endian.git
|
||||
[submodule "speech2/third_party/boost/exception"]
|
||||
path = speech2/third_party/boost/exception
|
||||
url = https://github.com/boostorg/exception.git
|
||||
[submodule "speech2/third_party/boost/filesystem"]
|
||||
path = speech2/third_party/boost/filesystem
|
||||
url = https://github.com/boostorg/filesystem.git
|
||||
[submodule "speech2/third_party/boost/function"]
|
||||
path = speech2/third_party/boost/function
|
||||
url = https://github.com/boostorg/function.git
|
||||
[submodule "speech2/third_party/boost/functional"]
|
||||
path = speech2/third_party/boost/functional
|
||||
url = https://github.com/boostorg/functional.git
|
||||
[submodule "speech2/third_party/boost/function_types"]
|
||||
path = speech2/third_party/boost/function_types
|
||||
url = https://github.com/boostorg/function_types.git
|
||||
[submodule "speech2/third_party/boost/fusion"]
|
||||
path = speech2/third_party/boost/fusion
|
||||
url = https://github.com/boostorg/fusion.git
|
||||
[submodule "speech2/third_party/boost/integer"]
|
||||
path = speech2/third_party/boost/integer
|
||||
url = https://github.com/boostorg/integer.git
|
||||
[submodule "speech2/third_party/boost/intrusive"]
|
||||
path = speech2/third_party/boost/intrusive
|
||||
url = https://github.com/boostorg/intrusive.git
|
||||
[submodule "speech2/third_party/boost/io"]
|
||||
path = speech2/third_party/boost/io
|
||||
url = https://github.com/boostorg/io.git
|
||||
[submodule "speech2/third_party/boost/iterator"]
|
||||
path = speech2/third_party/boost/iterator
|
||||
url = https://github.com/boostorg/iterator.git
|
||||
[submodule "speech2/third_party/boost/json"]
|
||||
path = speech2/third_party/boost/json
|
||||
url = https://github.com/boostorg/json.git
|
||||
[submodule "speech2/third_party/boost/leaf"]
|
||||
path = speech2/third_party/boost/leaf
|
||||
url = https://github.com/boostorg/leaf.git
|
||||
[submodule "speech2/third_party/boost/lexical_cast"]
|
||||
path = speech2/third_party/boost/lexical_cast
|
||||
url = https://github.com/boostorg/lexical_cast.git
|
||||
[submodule "speech2/third_party/boost/lockfree"]
|
||||
path = speech2/third_party/boost/lockfree
|
||||
url = https://github.com/boostorg/lockfree.git
|
||||
[submodule "speech2/third_party/boost/logic"]
|
||||
path = speech2/third_party/boost/logic
|
||||
url = https://github.com/boostorg/logic.git
|
||||
[submodule "speech2/third_party/boost/move"]
|
||||
path = speech2/third_party/boost/move
|
||||
url = https://github.com/boostorg/move.git
|
||||
[submodule "speech2/third_party/boost/mp11"]
|
||||
path = speech2/third_party/boost/mp11
|
||||
url = https://github.com/boostorg/mp11.git
|
||||
[submodule "speech2/third_party/boost/mpl"]
|
||||
path = speech2/third_party/boost/mpl
|
||||
url = https://github.com/boostorg/mpl.git
|
||||
[submodule "speech2/third_party/boost/numeric_conversion"]
|
||||
path = speech2/third_party/boost/numeric_conversion
|
||||
url = https://github.com/boostorg/numeric_conversion.git
|
||||
[submodule "speech2/third_party/boost/optional"]
|
||||
path = speech2/third_party/boost/optional
|
||||
url = https://github.com/boostorg/optional.git
|
||||
[submodule "speech2/third_party/boost/parameter"]
|
||||
path = speech2/third_party/boost/parameter
|
||||
url = https://github.com/boostorg/parameter.git
|
||||
[submodule "speech2/third_party/boost/pool"]
|
||||
path = speech2/third_party/boost/pool
|
||||
url = https://github.com/boostorg/pool.git
|
||||
[submodule "speech2/third_party/boost/predef"]
|
||||
path = speech2/third_party/boost/predef
|
||||
url = https://github.com/boostorg/predef.git
|
||||
[submodule "speech2/third_party/boost/preprocessor"]
|
||||
path = speech2/third_party/boost/preprocessor
|
||||
url = https://github.com/boostorg/preprocessor.git
|
||||
[submodule "speech2/third_party/boost/range"]
|
||||
path = speech2/third_party/boost/range
|
||||
url = https://github.com/boostorg/range.git
|
||||
[submodule "speech2/third_party/boost/ratio"]
|
||||
path = speech2/third_party/boost/ratio
|
||||
url = https://github.com/boostorg/ratio.git
|
||||
[submodule "speech2/third_party/boost/rational"]
|
||||
path = speech2/third_party/boost/rational
|
||||
url = https://github.com/boostorg/rational.git
|
||||
[submodule "speech2/third_party/boost/regex"]
|
||||
path = speech2/third_party/boost/regex
|
||||
url = https://github.com/boostorg/regex.git
|
||||
[submodule "speech2/third_party/boost/scope"]
|
||||
path = speech2/third_party/boost/scope
|
||||
url = https://github.com/boostorg/scope.git
|
||||
[submodule "speech2/third_party/boost/smart_ptr"]
|
||||
path = speech2/third_party/boost/smart_ptr
|
||||
url = https://github.com/boostorg/smart_ptr.git
|
||||
[submodule "speech2/third_party/boost/static_assert"]
|
||||
path = speech2/third_party/boost/static_assert
|
||||
url = https://github.com/boostorg/static_assert.git
|
||||
[submodule "speech2/third_party/boost/static_string"]
|
||||
path = speech2/third_party/boost/static_string
|
||||
url = https://github.com/boostorg/static_string.git
|
||||
[submodule "speech2/third_party/boost/system"]
|
||||
path = speech2/third_party/boost/system
|
||||
url = https://github.com/boostorg/system.git
|
||||
[submodule "speech2/third_party/boost/throw_exception"]
|
||||
path = speech2/third_party/boost/throw_exception
|
||||
url = https://github.com/boostorg/throw_exception.git
|
||||
[submodule "speech2/third_party/boost/tokenizer"]
|
||||
path = speech2/third_party/boost/tokenizer
|
||||
url = https://github.com/boostorg/tokenizer.git
|
||||
[submodule "speech2/third_party/boost/tuple"]
|
||||
path = speech2/third_party/boost/tuple
|
||||
url = https://github.com/boostorg/tuple.git
|
||||
[submodule "speech2/third_party/boost/type_index"]
|
||||
path = speech2/third_party/boost/type_index
|
||||
url = https://github.com/boostorg/type_index.git
|
||||
[submodule "speech2/third_party/boost/typeof"]
|
||||
path = speech2/third_party/boost/typeof
|
||||
url = https://github.com/boostorg/typeof.git
|
||||
[submodule "speech2/third_party/boost/type_traits"]
|
||||
path = speech2/third_party/boost/type_traits
|
||||
url = https://github.com/boostorg/type_traits.git
|
||||
[submodule "speech2/third_party/boost/unordered"]
|
||||
path = speech2/third_party/boost/unordered
|
||||
url = https://github.com/boostorg/unordered.git
|
||||
[submodule "speech2/third_party/boost/url"]
|
||||
path = speech2/third_party/boost/url
|
||||
url = https://github.com/boostorg/url.git
|
||||
[submodule "speech2/third_party/boost/utility"]
|
||||
path = speech2/third_party/boost/utility
|
||||
url = https://github.com/boostorg/utility.git
|
||||
[submodule "speech2/third_party/boost/variant2"]
|
||||
path = speech2/third_party/boost/variant2
|
||||
url = https://github.com/boostorg/variant2.git
|
||||
[submodule "speech2/third_party/boost/winapi"]
|
||||
path = speech2/third_party/boost/winapi
|
||||
url = https://github.com/boostorg/winapi.git
|
||||
[submodule "speech2/third_party/boost/asio"]
|
||||
path = speech2/third_party/boost/asio
|
||||
url = https://github.com/boostorg/asio.git
|
||||
[submodule "speech2/third_party/boost/beast"]
|
||||
path = speech2/third_party/boost/beast
|
||||
url = https://github.com/boostorg/beast.git
|
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/speech2",
|
||||
"cmake.configureArgs": [
|
||||
"--toolchain cmake/clangcl-winxp.cmake"
|
||||
],
|
||||
"cmake.configureEnvironment": {
|
||||
"VCDIR": "${env:HOME}/vs2022"
|
||||
},
|
||||
"cmake.ignoreCMakeListsMissing": true,
|
||||
}
|
11
Justfile
Normal file
11
Justfile
Normal file
|
@ -0,0 +1,11 @@
|
|||
build:
|
||||
cd speech2; cmake --toolchain cmake/clangcl-winxp.cmake -GNinja -Bbuild; cd ..
|
||||
cd speech2; cd build; ninja; cd ..; cd ..;
|
||||
|
||||
clean:
|
||||
rm -rf SAPIServer/bin SAPIServer/obj
|
||||
make -C speech2 clean
|
||||
|
||||
|
||||
format:
|
||||
cd SAPIServer; for f in *.cs; do clang-format -i $f; done; cd ..;
|
11
README.md
11
README.md
|
@ -2,6 +2,17 @@
|
|||
|
||||
Simple HTTP frontend API for Microsoft Speech API
|
||||
|
||||
## Building
|
||||
|
||||
Requirements
|
||||
- .NET SDK
|
||||
- VS2022 lib pack (TODO: link)
|
||||
- LLVM toolchain
|
||||
|
||||
You'll also need to chattr +F (or mount the whole thing with `ciopfs` and rename the headers to lowercase, if not on ext4 or you don't want to tune2fs) the windows sdk header directories so the build works.
|
||||
|
||||
`just` should do the trick.
|
||||
|
||||
## Running
|
||||
|
||||
```
|
||||
|
|
|
@ -3,72 +3,67 @@ using System.Collections.Generic;
|
|||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SAPIServer
|
||||
{
|
||||
namespace SAPIServer {
|
||||
/// <summary>
|
||||
/// Simple routing HTTP server for .NET Framework
|
||||
/// </summary>
|
||||
class HTTPServer
|
||||
{
|
||||
class HTTPServer {
|
||||
private bool listening = false;
|
||||
private HttpListener listener;
|
||||
private Dictionary<string, Func<HttpListenerContext, byte[]>> GETListeners;
|
||||
private Dictionary<string, Func<HttpListenerContext, byte[]>> POSTListeners;
|
||||
|
||||
public HTTPServer()
|
||||
{
|
||||
public HTTPServer() {
|
||||
listener = new HttpListener();
|
||||
this.GETListeners = new Dictionary<string, Func<HttpListenerContext, byte[]>>();
|
||||
this.POSTListeners = new Dictionary<string, Func<HttpListenerContext, byte[]>>();
|
||||
}
|
||||
|
||||
public void Get(string uri, Func<HttpListenerContext, byte[]> handler)
|
||||
{
|
||||
if (GETListeners.ContainsKey(uri)) throw new InvalidOperationException("A handler by that URI already exists.");
|
||||
if (!uri.StartsWith("/")) throw new ArgumentException("URIs must start with /");
|
||||
public void Get(string uri, Func<HttpListenerContext, byte[]> handler) {
|
||||
if(GETListeners.ContainsKey(uri))
|
||||
throw new InvalidOperationException("A handler by that URI already exists.");
|
||||
if(!uri.StartsWith("/"))
|
||||
throw new ArgumentException("URIs must start with /");
|
||||
this.GETListeners.Add(uri, handler);
|
||||
}
|
||||
|
||||
public void Post(string uri, Func<HttpListenerContext, byte[]> handler)
|
||||
{
|
||||
if (POSTListeners.ContainsKey(uri)) throw new InvalidOperationException("A handler by that URI already exists.");
|
||||
if (!uri.StartsWith("/")) throw new ArgumentException("URIs must start with /");
|
||||
public void Post(string uri, Func<HttpListenerContext, byte[]> handler) {
|
||||
if(POSTListeners.ContainsKey(uri))
|
||||
throw new InvalidOperationException("A handler by that URI already exists.");
|
||||
if(!uri.StartsWith("/"))
|
||||
throw new ArgumentException("URIs must start with /");
|
||||
this.POSTListeners.Add(uri, handler);
|
||||
}
|
||||
|
||||
public void Listen(ushort port)
|
||||
{
|
||||
if (listening) throw new InvalidOperationException("This HTTPServer is already listening.");
|
||||
public void Listen(ushort port) {
|
||||
if(listening)
|
||||
throw new InvalidOperationException("This HTTPServer is already listening.");
|
||||
listening = true;
|
||||
listener.Prefixes.Add(string.Format("http://*:{0}/", port));
|
||||
listener.Start();
|
||||
while (listener.IsListening)
|
||||
{
|
||||
|
||||
while(listener.IsListening) {
|
||||
var context = listener.GetContext();
|
||||
ThreadPool.QueueUserWorkItem(_ =>
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(
|
||||
_ => {
|
||||
var uri = context.Request.RawUrl.Split('?')[0];
|
||||
var ip = context.Request.RemoteEndPoint.Address;
|
||||
try
|
||||
{
|
||||
try {
|
||||
Dictionary<string, Func<HttpListenerContext, byte[]>> handlerDict;
|
||||
// TODO: Make query params parsable
|
||||
byte[] response;
|
||||
switch (context.Request.HttpMethod)
|
||||
{
|
||||
case "GET":
|
||||
{
|
||||
switch(context.Request.HttpMethod) {
|
||||
case "GET": {
|
||||
handlerDict = GETListeners;
|
||||
break;
|
||||
}
|
||||
case "POST":
|
||||
{
|
||||
case "POST": {
|
||||
handlerDict = POSTListeners;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
response = Encoding.UTF8.GetBytes($"Method not allowed: {context.Request.HttpMethod}");
|
||||
context.Response.StatusCode = 405;
|
||||
context.Response.ContentType = "text/plain";
|
||||
|
@ -78,35 +73,31 @@ namespace SAPIServer
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (!handlerDict.TryGetValue(uri, out var handler))
|
||||
{
|
||||
if(!handlerDict.TryGetValue(uri, out var handler)) {
|
||||
response = Encoding.UTF8.GetBytes($"No route defined for {uri}");
|
||||
context.Response.StatusCode = 404;
|
||||
context.Response.ContentType = "text/plain";
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
} else {
|
||||
try {
|
||||
response = handler(context);
|
||||
} catch (Exception e)
|
||||
{
|
||||
} catch(Exception e) {
|
||||
response = Encoding.UTF8.GetBytes("Internal Server Error");
|
||||
context.Response.StatusCode = 500;
|
||||
context.Response.ContentType = "text/plain";
|
||||
Console.Error.WriteLine($"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - Handler Failed: {e.Message}");
|
||||
Console.Error.WriteLine(
|
||||
$"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - Handler Failed: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
context.Response.ContentLength64 = response.Length;
|
||||
context.Response.OutputStream.Write(response, 0, response.Length);
|
||||
context.Response.OutputStream.Close();
|
||||
Console.WriteLine($"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - {context.Response.StatusCode}");
|
||||
} catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine($"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - Exception: {e.Message}");
|
||||
Console.WriteLine(
|
||||
$"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - {context.Response.StatusCode}");
|
||||
} catch(Exception e) {
|
||||
Console.Error.WriteLine(
|
||||
$"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - Exception: {e.Message}");
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,57 +6,51 @@ using System.Speech.Synthesis;
|
|||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SAPIServer
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1 || !ushort.TryParse(args[0], out var port))
|
||||
{
|
||||
Console.Error.WriteLine("Usage: SAPIServer.exe <port>");
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
namespace SAPIServer {
|
||||
|
||||
class SpeechServer {
|
||||
private Dictionary<string, SpeechAPI> apis = new();
|
||||
private HTTPServer httpServer = new();
|
||||
|
||||
public SpeechServer() {
|
||||
// Test out creating a speech2 api object
|
||||
apis["sapi4"] = new SpeechAPI(EngineType.ET_SAPI4);
|
||||
#if true
|
||||
foreach(var voice in apis["sapi4"].GetVoices()) {
|
||||
Console.WriteLine($"ggg {voice.name}");
|
||||
}
|
||||
var http = new HTTPServer();
|
||||
http.Get("/api/voices", ctx =>
|
||||
{
|
||||
using (var synth = new SpeechSynthesizer())
|
||||
{
|
||||
#endif
|
||||
|
||||
httpServer.Get("/api/voices", ctx => {
|
||||
/*
|
||||
using(var synth = new SpeechSynthesizer()) {
|
||||
ctx.Response.ContentType = "application/json";
|
||||
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new VoicesResponse
|
||||
{
|
||||
voices = synth.GetInstalledVoices().Select(v => v.VoiceInfo.Name).ToArray()
|
||||
}));
|
||||
}
|
||||
return Encoding.UTF8.GetBytes(
|
||||
JsonConvert.SerializeObject(new VoicesResponse { voices = synth.GetInstalledVoices().Select(v => v.VoiceInfo.Name).ToArray() }));
|
||||
}*/
|
||||
|
||||
return new byte[]{0};
|
||||
});
|
||||
http.Post("/api/synthesize", ctx =>
|
||||
{
|
||||
|
||||
httpServer.Post("/api/synthesize", ctx => {
|
||||
SynthesizePayload body;
|
||||
try
|
||||
{
|
||||
try {
|
||||
string bodyraw;
|
||||
using (var reader = new StreamReader(ctx.Request.InputStream))
|
||||
{
|
||||
using(var reader = new StreamReader(ctx.Request.InputStream)) {
|
||||
bodyraw = reader.ReadToEnd();
|
||||
}
|
||||
body = JsonConvert.DeserializeObject<SynthesizePayload>(bodyraw);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
} catch(Exception) {
|
||||
ctx.Response.StatusCode = 400;
|
||||
return Encoding.UTF8.GetBytes("Bad payload");
|
||||
}
|
||||
if (body == null || body.text == null || body.voice == null)
|
||||
{
|
||||
if(body == null || body.text == null || body.voice == null) {
|
||||
ctx.Response.StatusCode = 400;
|
||||
return Encoding.UTF8.GetBytes("Bad payload");
|
||||
}
|
||||
using (var ms = new MemoryStream())
|
||||
using (var synth = new SpeechSynthesizer())
|
||||
{
|
||||
if (!synth.GetInstalledVoices().Any(v => v.VoiceInfo.Name == body.voice))
|
||||
{
|
||||
using(var ms = new MemoryStream()) {
|
||||
using(var synth = new SpeechSynthesizer()) {
|
||||
if(!synth.GetInstalledVoices().Any(v => v.VoiceInfo.Name == body.voice)) {
|
||||
ctx.Response.StatusCode = 400;
|
||||
return Encoding.UTF8.GetBytes("Voice not found");
|
||||
}
|
||||
|
@ -66,9 +60,26 @@ namespace SAPIServer
|
|||
ctx.Response.ContentType = "audio/wav";
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
});
|
||||
Console.WriteLine($"[{ DateTime.Now:u}] Starting HTTP server on port {port}");
|
||||
http.Listen(port);
|
||||
}
|
||||
|
||||
public void Start(ushort port) {
|
||||
Console.WriteLine($"[{DateTime.Now:u}] Starting HTTP server on port {port}");
|
||||
httpServer.Listen(port);
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
static void Main(string[] args) {
|
||||
if(args.Length < 1 || !ushort.TryParse(args[0], out var port)) {
|
||||
Console.Error.WriteLine("Usage: SAPIServer.exe <port>");
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
var server = new SpeechServer();
|
||||
server.Start(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,58 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{BF824074-4C4E-4DE1-8DCA-F022682B00E1}</ProjectGuid>
|
||||
<!-- Older VS generated one for us; we're just using that one.
|
||||
Unless we wanna use the generated one?? -->
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>SAPIServer</RootNamespace>
|
||||
<AssemblyName>SAPIServer</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TargetFrameworks>net40</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<RuntimeIdentifier>windows-x86</RuntimeIdentifier>
|
||||
<!-- N.B: This is only to gain support for some compiler-supported nicities, like new(). -->
|
||||
<LangVersion>9.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<!--<PackageReference Include="Microsoft.Bcl.Async" Version="1.0.168" />-->
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Speech" />
|
||||
|
@ -62,23 +27,5 @@
|
|||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="HTTPServer.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SynthesizePayload.cs" />
|
||||
<Compile Include="VoicesResponse.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.manifest" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
||||
</Project>
|
85
SAPIServer/SpeechDLL.cs
Normal file
85
SAPIServer/SpeechDLL.cs
Normal file
|
@ -0,0 +1,85 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
namespace SAPIServer {
|
||||
|
||||
// Sync with C++ code.
|
||||
public enum EngineType : int { ET_SAPI4, ET_SAPI5, ET_DECTALK }
|
||||
|
||||
public class VoiceDef {
|
||||
public Guid guid;
|
||||
public string name;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
internal struct VoiceDefInternal {
|
||||
Guid guid;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
string name;
|
||||
|
||||
public VoiceDef Voicify() {
|
||||
Console.WriteLine($"FUCK ${name}");
|
||||
//var str = Marshal.PtrToStringAnsi(name);
|
||||
VoiceDef def = new();
|
||||
|
||||
def.guid = guid;
|
||||
def.name = name;
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Speech2 DLL API. Sync with c++ code.
|
||||
internal class SpeechDLL {
|
||||
private const string Speech2DLL = "speech2.dll";
|
||||
|
||||
[DllImport(Speech2DLL, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern IntPtr speech2_create_api(EngineType type);
|
||||
|
||||
[DllImport(Speech2DLL, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern void speech2_destroy_api(IntPtr pAPI);
|
||||
|
||||
[DllImport(Speech2DLL, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int speech2_api_get_voiceinfo_count(IntPtr pAPI);
|
||||
|
||||
[DllImport(Speech2DLL, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern IntPtr speech2_api_get_voiceinfo_index(IntPtr pAPI, int index);
|
||||
}
|
||||
|
||||
// A speech API. This is generic for all speech2 supported speech APIs, so
|
||||
// we can use the same code for everything. Cool, huh?
|
||||
public class SpeechAPI : IDisposable {
|
||||
private IntPtr handle = IntPtr.Zero;
|
||||
|
||||
public SpeechAPI(EngineType type) {
|
||||
handle = SpeechDLL.speech2_create_api(type);
|
||||
if(handle == IntPtr.Zero)
|
||||
throw new InvalidOperationException("Failed to create speech API");
|
||||
}
|
||||
|
||||
public List<VoiceDef> GetVoices() {
|
||||
Console.WriteLine("SpeechAPI.GetVoices()");
|
||||
|
||||
var count = SpeechDLL.speech2_api_get_voiceinfo_count(handle);
|
||||
Console.WriteLine($"count {count}");
|
||||
var list = new List<VoiceDef>();
|
||||
for(var i = 0; i < count; ++i) {
|
||||
var ptr = SpeechDLL.speech2_api_get_voiceinfo_index(handle, i);
|
||||
var obj = (VoiceDefInternal)Marshal.PtrToStructure(ptr, typeof(VoiceDefInternal));
|
||||
list.Add(obj.Voicify());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void IDisposable.Dispose() {
|
||||
if(handle != IntPtr.Zero)
|
||||
SpeechDLL.speech2_destroy_api(handle);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
namespace SAPIServer
|
||||
{
|
||||
class SynthesizePayload
|
||||
{
|
||||
namespace SAPIServer {
|
||||
class SynthesizePayload {
|
||||
public string voice { get; set; }
|
||||
public string text { get; set; }
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
namespace SAPIServer
|
||||
{
|
||||
class VoicesResponse
|
||||
{
|
||||
namespace SAPIServer {
|
||||
class VoicesResponse {
|
||||
public string[] voices { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
20
speech2/CMakeLists.txt
Normal file
20
speech2/CMakeLists.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(speech2)
|
||||
|
||||
|
||||
xp_init()
|
||||
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
include(Policies)
|
||||
include(ProjectFuncs)
|
||||
|
||||
add_subdirectory(third_party/boost)
|
||||
add_subdirectory(src)
|
||||
|
||||
|
||||
|
3
speech2/README.md
Normal file
3
speech2/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# speech2
|
||||
|
||||
speech dll thing
|
22
speech2/cmake/Policies.cmake
Normal file
22
speech2/cmake/Policies.cmake
Normal file
|
@ -0,0 +1,22 @@
|
|||
# CMake policy configuration
|
||||
|
||||
# Macro to enable new CMake policy.
|
||||
# Makes this file a *LOT* shorter.
|
||||
macro (_new_cmake_policy policy)
|
||||
if(POLICY ${policy})
|
||||
#message(STATUS "Enabling new policy ${policy}")
|
||||
cmake_policy(SET ${policy} NEW)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
_new_cmake_policy(CMP0026) # CMake 3.0: Disallow use of the LOCATION property for build targets.
|
||||
_new_cmake_policy(CMP0042) # CMake 3.0+ (2.8.12): MacOS "@rpath" in target's install name
|
||||
_new_cmake_policy(CMP0046) # warn about non-existent dependencies
|
||||
_new_cmake_policy(CMP0048) # CMake 3.0+: project() command now maintains VERSION
|
||||
_new_cmake_policy(CMP0054) # CMake 3.1: Only interpret if() arguments as variables or keywords when unquoted.
|
||||
_new_cmake_policy(CMP0056) # try_compile() linker flags
|
||||
_new_cmake_policy(CMP0066) # CMake 3.7: try_compile(): use per-config flags, like CMAKE_CXX_FLAGS_RELEASE
|
||||
_new_cmake_policy(CMP0067) # CMake 3.8: try_compile(): honor language standard variables (like C++11)
|
||||
_new_cmake_policy(CMP0068) # CMake 3.9+: `RPATH` settings on macOS do not affect `install_name`.
|
||||
_new_cmake_policy(CMP0075) # CMake 3.12+: Include file check macros honor `CMAKE_REQUIRED_LIBRARIES`
|
||||
_new_cmake_policy(CMP0077) # CMake 3.13+: option() honors normal variables.
|
14
speech2/cmake/ProjectFuncs.cmake
Normal file
14
speech2/cmake/ProjectFuncs.cmake
Normal file
|
@ -0,0 +1,14 @@
|
|||
function(speech2_target target)
|
||||
target_compile_definitions(${target} PRIVATE "$<$<CONFIG:DEBUG>:SPEECH2_DEBUG>")
|
||||
target_compile_features(${target} PRIVATE cxx_std_20)
|
||||
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/third_party ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# use the static multithreaded C library
|
||||
set_property(TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
# TODO option for this.
|
||||
target_link_options(${target} PRIVATE
|
||||
-Wl,/safeseh:no
|
||||
-Xlinker /subsystem:console,${CMAKE_SYSTEM_VERSION}
|
||||
)
|
||||
endfunction()
|
78
speech2/cmake/clangcl-winxp.cmake
Normal file
78
speech2/cmake/clangcl-winxp.cmake
Normal file
|
@ -0,0 +1,78 @@
|
|||
# Windows XP
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(CMAKE_SYSTEM_VERSION 5.1)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86)
|
||||
|
||||
set(TARGET_VERSION_MAJOR 5)
|
||||
set(TARGET_VERSION_MINOR)
|
||||
|
||||
set(_MSVC_TRIPLET "i686-pc-windows-msvc")
|
||||
|
||||
# CXXRTDIR = $(VCDIR)/crt
|
||||
# UCRTDIR = $(VCDIR)/ucrt
|
||||
# PSDKDIR = $(VCDIR)/winsdk
|
||||
|
||||
if("$ENV{VCDIR}" STREQUAL "")
|
||||
message(FATAL_ERROR "Please set VCDIR in your environment to an appropiate path.")
|
||||
endif()
|
||||
|
||||
set(_CRTDIR "$ENV{VCDIR}/crt")
|
||||
#-isystem ${_CRTDIR}/include
|
||||
set(_UCRTDIR "$ENV{VCDIR}/ucrt")
|
||||
set(_PSDKDIR "$ENV{VCDIR}/winsdk")
|
||||
|
||||
set(_CLANG_BASEFLAGS "-target ${_MSVC_TRIPLET} -fms-extensions -fms-compatibility -fms-compatibility-version=19 -isystem $ENV{VCDIR}/libcxx/include/c++ -isystem ${_UCRTDIR}/include -isystem $ENV{VCDIR}/libcxx/include -isystem ${_PSDKDIR}/include/shared -isystem ${_PSDKDIR}/include/um ")
|
||||
set(_CLANG_ARCHFLAGS "-march=pentium4 -D_WIN32_WINNT=0x0501")
|
||||
|
||||
set(CMAKE_C_COMPILER "clang" CACHE FILEPATH "")
|
||||
set(CMAKE_CXX_COMPILER "clang++" CACHE FILEPATH "")
|
||||
set(CMAKE_LINKER "lld-link" CACHE FILEPATH "")
|
||||
|
||||
set(CMAKE_ASM_FLAGS_INIT "${_CLANG_BASEFLAGS} ${_CLANG_ARCHFLAGS}")
|
||||
set(CMAKE_C_FLAGS_INIT "${_CLANG_BASEFLAGS} ${_CLANG_ARCHFLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_INIT} -fomit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT} ${CMAKE_CXX_FLAGS_INIT}")
|
||||
|
||||
# Set base linker library paths
|
||||
foreach(type EXE MODULE SHARED)
|
||||
# -Xlinker /nodefaultlib:libcpmt -Xlinker /nodefaultlib:libcpmtd
|
||||
set(CMAKE_${type}_LINKER_FLAGS "-Xlinker /libpath:${_CRTDIR}/lib/x86 -Xlinker /libpath:${_UCRTDIR}/lib -Xlinker /libpath:${_PSDKDIR}/lib")
|
||||
endforeach()
|
||||
|
||||
# Remove fluff libraries; projects should specify them
|
||||
set(CMAKE_C_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "-Xlinker /libpath:$ENV{VCDIR}/libcxx/lib -Xlinker libcpmtd.lib -Xlinker libc++d.lib -Xlinker winpthreadsd.lib" CACHE STRING "" FORCE)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "-Xlinker /libpath:$ENV{VCDIR}/libcxx/lib -Xlinker libcpmt.lib -Xlinker libc++.lib -Xlinker winpthreads.lib" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
# Run this once after you call project() to replace broken
|
||||
macro(xp_init)
|
||||
foreach(lang C CXX)
|
||||
# have to patch the link commands to replace /MANIFEST:EMBED with /MANIFEST:NO
|
||||
# because ....
|
||||
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
|
||||
"<CMAKE_${lang}_COMPILER> -nostartfiles -nostdlib <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:${CMAKE_SYSTEM_VERSION} <OBJECTS> <LINK_LIBRARIES> <MANIFESTS>" CACHE STRING "" FORCE)
|
||||
set(CMAKE_${lang}_CREATE_SHARED_MODULE ${CMAKE_${lang}_CREATE_SHARED_LIBRARY} CACHE STRING "" FORCE)
|
||||
set(CMAKE_${lang}_LINK_EXECUTABLE
|
||||
"<CMAKE_${lang}_COMPILER> -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /MANIFEST:NO -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:${CMAKE_SYSTEM_VERSION} ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES> <MANIFESTS>" CACHE STRING "" FORCE)
|
||||
|
||||
# also patch these so we can set the subsytem version
|
||||
set(CMAKE_${lang}_CREATE_WIN32_EXE "-Xlinker /subsystem:windows,${CMAKE_SYSTEM_VERSION}" CACHE STRING "" FORCE)
|
||||
set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console,${CMAKE_SYSTEM_VERSION}" CACHE STRING "" FORCE)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Use the static multithreaded C library
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
|
||||
# dummy
|
||||
|
||||
set(CMAKE_ASM_MASM_COMPILE_OBJECT "${CMAKE_ASM_COMPILE_OBJECT}")
|
||||
|
||||
xp_init()
|
39
speech2/src/CMakeLists.txt
Normal file
39
speech2/src/CMakeLists.txt
Normal file
|
@ -0,0 +1,39 @@
|
|||
add_subdirectory(base)
|
||||
add_subdirectory(impl)
|
||||
add_subdirectory(sapi4)
|
||||
|
||||
|
||||
add_executable(sapiserver
|
||||
main.cpp
|
||||
|
||||
winxp_compat_fwd.S
|
||||
winxp_compat.cpp
|
||||
winxp_compat_threadsafe_static.c
|
||||
)
|
||||
|
||||
speech2_target(sapiserver)
|
||||
|
||||
target_compile_definitions(sapiserver PRIVATE
|
||||
# Need to force this on, since I think clang's msvc compatibility
|
||||
# is deciding to set a wrong __cplusplus (like MSVC, so it's not *exactly* clang's fault).
|
||||
# The best way to fix it would probably involve using clang-cl frontend and passing the option (I think.)
|
||||
# (nevermind, it's just broken.)
|
||||
-DBOOST_ASIO_HAS_STD_INVOKE_RESULT=1
|
||||
|
||||
# Disable the "helpful" auto-link Boost.Config tries to do. CMake already has a functional
|
||||
# dependency graph based on our input, so we don't need it.
|
||||
-DBOOST_ALL_NO_LIB=1
|
||||
)
|
||||
|
||||
target_link_libraries(sapiserver PRIVATE
|
||||
#libc++
|
||||
|
||||
# subprojects
|
||||
speech2::base
|
||||
speech2::impl
|
||||
speech2::api_sapi4
|
||||
|
||||
# SDK libraries
|
||||
uuid.lib
|
||||
ole32.lib
|
||||
)
|
14
speech2/src/base/CMakeLists.txt
Normal file
14
speech2/src/base/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
add_library(speech2_base STATIC
|
||||
|
||||
Thread.cpp
|
||||
|
||||
# Logging system
|
||||
Logger.cpp
|
||||
Logger_priv.cpp
|
||||
StdoutSink.cpp
|
||||
|
||||
)
|
||||
|
||||
speech2_target(speech2_base)
|
||||
|
||||
add_library(speech2::base ALIAS speech2_base)
|
41
speech2/src/base/Logger.cpp
Normal file
41
speech2/src/base/Logger.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include "Logger.hpp"
|
||||
|
||||
#include <base/Logger_priv.hpp>
|
||||
#include <base/Thread.hpp>
|
||||
|
||||
namespace base {
|
||||
|
||||
inline auto& GlobalState() {
|
||||
return logger_impl::LoggerGlobalState::The();
|
||||
}
|
||||
|
||||
void LoggerAttachSink(LoggerSink& sink) {
|
||||
GlobalState().AttachSink(sink);
|
||||
}
|
||||
|
||||
MessageSeverity GetLogLevel() {
|
||||
return GlobalState().GetLogLevel();
|
||||
}
|
||||
|
||||
void SetLogLevel(MessageSeverity newLevel) {
|
||||
GlobalState().SetLogLevel(newLevel);
|
||||
}
|
||||
|
||||
Logger& Logger::Get(std::string_view key) {
|
||||
return logger_impl::GetOrRegister(key);
|
||||
}
|
||||
|
||||
Logger::Logger(ChannelId id)
|
||||
: channelId(id) {
|
||||
}
|
||||
|
||||
void Logger::VOut(MessageSeverity severity, std::string_view format, std::format_args args) {
|
||||
logger_impl::MessageData data {
|
||||
.time = std::chrono::system_clock::now(), .severity = severity, .channelId = channelId, .message = std::vformat(format, args)
|
||||
};
|
||||
|
||||
// Push data into logger thread.
|
||||
logger_impl::PushMessage(std::move(data));
|
||||
}
|
||||
|
||||
} // namespace common
|
75
speech2/src/base/Logger.hpp
Normal file
75
speech2/src/base/Logger.hpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#pragma once
|
||||
#include <base/Types.hpp>
|
||||
|
||||
#include <format>
|
||||
#include <string_view>
|
||||
|
||||
namespace base {
|
||||
|
||||
/// A logger sink. Outputs messages to some device (a TTY), a file,
|
||||
/// anything. A interface for the logger to spit stuff out.
|
||||
///
|
||||
/// # Notes
|
||||
/// Sinks *do not* run on the main application thread. Instead, they run on a
|
||||
/// single internal thread shared with the logging system.
|
||||
/// Sinks should *not* block for large periods of time.
|
||||
struct LoggerSink {
|
||||
virtual void OutputMessage(std::string_view message) = 0;
|
||||
};
|
||||
|
||||
enum class MessageSeverity { Debug, Info, Warning, Error, Fatal };
|
||||
|
||||
/// A channel ID. `enum class`es are used to avoid confusion with a normal u32,
|
||||
/// and to also add addional interface type safety.
|
||||
/// These are opaque, and only exposed here because it would be annoying to move elsewhere.
|
||||
enum class ChannelId : u32 {};
|
||||
|
||||
/// Attach a sink to all Support loggers; allowing it to output logger messages.
|
||||
void LoggerAttachSink(LoggerSink& sink);
|
||||
|
||||
MessageSeverity GetLogLevel();
|
||||
|
||||
void SetLogLevel(MessageSeverity newLevel);
|
||||
|
||||
/// An (asynchronous) logger.
|
||||
struct Logger {
|
||||
/// Gets or creates a logger for the specified channel.
|
||||
static Logger& Get(std::string_view channel);
|
||||
|
||||
explicit Logger(ChannelId channel);
|
||||
|
||||
Logger(const Logger&) = delete;
|
||||
Logger(Logger&&) = delete;
|
||||
|
||||
template <class... Args>
|
||||
inline void Debug(std::string_view fmt, Args&&... args) {
|
||||
VOut(MessageSeverity::Debug, fmt, std::make_format_args(args...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline void Info(std::string_view fmt, Args&&... args) {
|
||||
VOut(MessageSeverity::Info, fmt, std::make_format_args(args...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline void Warning(std::string_view fmt, Args&&... args) {
|
||||
VOut(MessageSeverity::Warning, fmt, std::make_format_args(args...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline void Error(std::string_view fmt, Args&&... args) {
|
||||
VOut(MessageSeverity::Error, fmt, std::make_format_args(args...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline void Fatal(std::string_view fmt, Args&&... args) {
|
||||
VOut(MessageSeverity::Fatal, fmt, std::make_format_args(args...));
|
||||
}
|
||||
|
||||
private:
|
||||
void VOut(MessageSeverity severity, std::string_view format, std::format_args args);
|
||||
|
||||
ChannelId channelId;
|
||||
};
|
||||
|
||||
} // namespace collabvm
|
170
speech2/src/base/Logger_priv.cpp
Normal file
170
speech2/src/base/Logger_priv.cpp
Normal file
|
@ -0,0 +1,170 @@
|
|||
#include <base/Logger_priv.hpp>
|
||||
#include <base/Thread.hpp>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
namespace base::logger_impl {
|
||||
|
||||
static constexpr std::string_view SeverityToString(MessageSeverity sev) {
|
||||
// This must match order of MessageSeverity.
|
||||
const char* MessageSeverityStringTable[] = { "Debug", "Info", "Warn", "Error", "Fatal" };
|
||||
return MessageSeverityStringTable[static_cast<std::size_t>(sev)];
|
||||
}
|
||||
|
||||
/// Hash algorithm for channel IDs. In this case it's PJW-ELF.
|
||||
/// I might switch to murmur or something if collisions are a problem,
|
||||
/// but I don't think it's a problem.
|
||||
ChannelId ChannelIDHash(const char* in) {
|
||||
u32 hash = 0;
|
||||
u32 high = 0;
|
||||
|
||||
while(*in) {
|
||||
hash = (hash << 4) + *in++;
|
||||
|
||||
if((high = hash & 0xf0000000))
|
||||
hash ^= high >> 23;
|
||||
|
||||
hash &= ~high;
|
||||
}
|
||||
|
||||
return static_cast<ChannelId>(hash);
|
||||
}
|
||||
|
||||
std::string_view ChannelToString(ChannelId id) {
|
||||
auto& gs = LoggerGlobalState::The();
|
||||
std::unique_lock lk(gs.loggerMapLock);
|
||||
return gs.loggerMap[id].channelName;
|
||||
}
|
||||
|
||||
/// comparator for [std::priority_queue]
|
||||
struct LogMessageComparator {
|
||||
constexpr bool operator()(const MessageData& mdLeft, const MessageData& mdRight) { return mdLeft.time > mdRight.time; }
|
||||
};
|
||||
|
||||
struct LoggerThreadData {
|
||||
// Logger thread stuff
|
||||
std::thread loggerThread;
|
||||
std::mutex logQueueMutex;
|
||||
std::condition_variable logQueueCv;
|
||||
|
||||
std::priority_queue<MessageData, std::deque<MessageData>, LogMessageComparator> logQueue;
|
||||
|
||||
// could be an atomic_bool
|
||||
bool logThreadShutdown = false;
|
||||
|
||||
bool ShouldUnblock() {
|
||||
// N.B: ALL calls of this hold the lock.
|
||||
|
||||
// Always unblock if the logger thread needs to be shut down.
|
||||
if(logThreadShutdown)
|
||||
return true;
|
||||
|
||||
return !logQueue.empty();
|
||||
}
|
||||
|
||||
void PushMessage(MessageData&& md) {
|
||||
{
|
||||
std::unique_lock lk(logQueueMutex);
|
||||
logQueue.push(std::move(md));
|
||||
}
|
||||
logQueueCv.notify_one();
|
||||
}
|
||||
|
||||
/// This thread drives the logging system.
|
||||
static void LoggerThread(LoggerThreadData* self) {
|
||||
// Fancy thread names.
|
||||
SetThreadName("AsyncLogger");
|
||||
|
||||
auto& state = LoggerGlobalState::The();
|
||||
|
||||
while(true) {
|
||||
// Shutdown if requested.
|
||||
if(self->logThreadShutdown)
|
||||
break;
|
||||
|
||||
{
|
||||
std::unique_lock lk(self->logQueueMutex);
|
||||
if(self->logQueue.empty()) {
|
||||
// Await for messages.
|
||||
self->logQueueCv.wait(lk, [self]() { return self->ShouldUnblock(); });
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock lk(self->logQueueMutex);
|
||||
// Flush the logger queue until there are no more messages.
|
||||
while(!self->logQueue.empty()) {
|
||||
const auto& msg = self->logQueue.top();
|
||||
state.OutputMessage(msg);
|
||||
self->logQueue.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Unique<LoggerThreadData> threadData;
|
||||
|
||||
LoggerGlobalState& LoggerGlobalState::The() {
|
||||
static LoggerGlobalState storage;
|
||||
return storage;
|
||||
}
|
||||
|
||||
LoggerGlobalState::LoggerGlobalState() {
|
||||
// Spawn the logger thread
|
||||
threadData = std::make_unique<LoggerThreadData>();
|
||||
threadData->loggerThread = std::thread(&LoggerThreadData::LoggerThread, threadData.get());
|
||||
}
|
||||
|
||||
LoggerGlobalState::~LoggerGlobalState() {
|
||||
// Shut down the logger thread
|
||||
threadData->logThreadShutdown = true;
|
||||
threadData->logQueueCv.notify_all();
|
||||
threadData->loggerThread.join();
|
||||
}
|
||||
|
||||
void LoggerGlobalState::AttachSink(LoggerSink& sink) {
|
||||
sinks.push_back(&sink);
|
||||
}
|
||||
|
||||
void LoggerGlobalState::OutputMessage(const MessageData& data) {
|
||||
// give up early if no sinks are attached
|
||||
if(sinks.empty())
|
||||
return;
|
||||
|
||||
if(data.severity < logLevel)
|
||||
return;
|
||||
|
||||
auto formattedLoggerMessage = std::format("[{:%F %H:%M:%S}|{}|{}] {}", std::chrono::floor<std::chrono::milliseconds>(data.time),
|
||||
SeverityToString(data.severity), ChannelToString(data.channelId), data.message);
|
||||
|
||||
for(auto sink : sinks)
|
||||
sink->OutputMessage(formattedLoggerMessage);
|
||||
}
|
||||
|
||||
Logger& GetOrRegister(std::string_view component) {
|
||||
auto& gs = LoggerGlobalState::The();
|
||||
|
||||
std::unique_lock lk(gs.loggerMapLock);
|
||||
|
||||
auto hash = ChannelIDHash(component.data());
|
||||
|
||||
if(!gs.loggerMap.contains(hash)) {
|
||||
// Insert a new entry into the logger map.
|
||||
gs.loggerMap.insert_or_assign(hash, BoltedLoggerData { component, std::make_unique<Logger>(hash) });
|
||||
}
|
||||
|
||||
return *gs.loggerMap[hash].logger.get();
|
||||
}
|
||||
|
||||
void PushMessage(MessageData&& md) {
|
||||
if(threadData)
|
||||
threadData->PushMessage(std::move(md));
|
||||
}
|
||||
} // namespace base::logger_impl
|
59
speech2/src/base/Logger_priv.hpp
Normal file
59
speech2/src/base/Logger_priv.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
|
||||
#include <base/Logger.hpp>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace base::logger_impl {
|
||||
|
||||
/// Message data. This is only used by logger sinks.
|
||||
struct MessageData {
|
||||
std::chrono::system_clock::time_point time;
|
||||
MessageSeverity severity;
|
||||
|
||||
ChannelId channelId; // the channel ID.
|
||||
|
||||
std::string message; // DO NOT SET THIS, IT WILL BE OVERWRITTEN AND I WILL BE VERY SAD -lily
|
||||
};
|
||||
|
||||
struct BoltedLoggerData {
|
||||
std::string_view channelName;
|
||||
Unique<Logger> logger;
|
||||
};
|
||||
|
||||
/// Shared global state all loggers use.
|
||||
struct LoggerGlobalState {
|
||||
static LoggerGlobalState& The();
|
||||
|
||||
void AttachSink(LoggerSink& sink);
|
||||
|
||||
void OutputMessage(const MessageData& data);
|
||||
|
||||
/// Get the current log level.
|
||||
MessageSeverity GetLogLevel() const { return logLevel; }
|
||||
|
||||
/// Set the current log level.
|
||||
void SetLogLevel(MessageSeverity newLogLevel) { logLevel = newLogLevel; }
|
||||
|
||||
private:
|
||||
LoggerGlobalState();
|
||||
~LoggerGlobalState();
|
||||
|
||||
public:
|
||||
std::vector<LoggerSink*> sinks;
|
||||
MessageSeverity logLevel { MessageSeverity::Info };
|
||||
|
||||
std::unordered_map<ChannelId, BoltedLoggerData> loggerMap;
|
||||
std::mutex loggerMapLock;
|
||||
};
|
||||
|
||||
/// Gets or registers a new logger. This routine is threadsafe, and can be called
|
||||
/// on any thread, like (most) parts of the logging system.
|
||||
Logger& GetOrRegister(std::string_view component);
|
||||
|
||||
/// Push a logger message into the queue.
|
||||
void PushMessage(MessageData&& md);
|
||||
|
||||
} // namespace base::logger_impl
|
6
speech2/src/base/SaneWin.hpp
Normal file
6
speech2/src/base/SaneWin.hpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Sane windows.h
|
||||
#pragma once
|
||||
#define _WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#undef _WIN32_LEAN_AND_MEAN
|
20
speech2/src/base/StdoutSink.cpp
Normal file
20
speech2/src/base/StdoutSink.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <base/StdoutSink.hpp>
|
||||
|
||||
#include "Logger.hpp"
|
||||
|
||||
namespace base {
|
||||
StdoutLoggerSink& StdoutLoggerSink::The() {
|
||||
static StdoutLoggerSink sink;
|
||||
return sink;
|
||||
}
|
||||
|
||||
void StdoutLoggerSink::OutputMessage(std::string_view message) {
|
||||
fputs(message.data(), stdout);
|
||||
fputc('\n', stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void LoggerAttachStdout() {
|
||||
LoggerAttachSink(StdoutLoggerSink::The());
|
||||
}
|
||||
} // namespace base
|
17
speech2/src/base/StdoutSink.hpp
Normal file
17
speech2/src/base/StdoutSink.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <base/Logger.hpp>
|
||||
|
||||
namespace base {
|
||||
|
||||
/// A logger sink implementation that prints to standard output.
|
||||
struct StdoutLoggerSink : public LoggerSink {
|
||||
static StdoutLoggerSink& The();
|
||||
|
||||
void OutputMessage(std::string_view message) override;
|
||||
};
|
||||
|
||||
/// Attach the stdout logger sink to the global Lucore logger.
|
||||
void LoggerAttachStdout();
|
||||
|
||||
} // namespace base
|
11
speech2/src/base/Thread.cpp
Normal file
11
speech2/src/base/Thread.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <pthread.h>
|
||||
#include <base/Thread.hpp>
|
||||
|
||||
namespace base {
|
||||
|
||||
void SetThreadNameImpl(const char* name, usize len) {
|
||||
//COMMON_ASSERT(len <= 15, "name will overflow pthread_setname_np() buffer");
|
||||
pthread_setname_np(pthread_self(), name);
|
||||
}
|
||||
|
||||
}
|
15
speech2/src/base/Thread.hpp
Normal file
15
speech2/src/base/Thread.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <base/Types.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace base {
|
||||
|
||||
void SetThreadNameImpl(const char* name, usize len);
|
||||
|
||||
/// Sets the name of the current thread. Mainly for portability.
|
||||
inline void SetThreadName(const std::string& name) {
|
||||
SetThreadNameImpl(name.data(), name.length());
|
||||
}
|
||||
|
||||
} // namespace collabvm
|
52
speech2/src/base/Types.hpp
Normal file
52
speech2/src/base/Types.hpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using i8 = std::int8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using i16 = std::int16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using i32 = std::int32_t;
|
||||
using u64 = std::uint64_t;
|
||||
using i64 = std::int64_t;
|
||||
using usize = std::size_t;
|
||||
using isize = std::intptr_t;
|
||||
|
||||
namespace base {
|
||||
|
||||
/// A little ergonomic wrapper over
|
||||
/// std::unique_ptr<T[]>, for a "kinda-vector"
|
||||
/// that lives on the heap and is statically sized
|
||||
template <class T>
|
||||
struct UniqueArray final {
|
||||
explicit UniqueArray(usize size)
|
||||
: array(std::make_unique<T[]>(size)),
|
||||
size(size) {
|
||||
}
|
||||
|
||||
UniqueArray(UniqueArray&& move) {
|
||||
array = std::move(move.array);
|
||||
size = move.size;
|
||||
|
||||
// invalidate
|
||||
move.array = nullptr;
|
||||
move.size = 0;
|
||||
}
|
||||
|
||||
T& operator[](usize index) { return Get()[index]; }
|
||||
const T& operator[](usize index) const { return Get()[index]; }
|
||||
|
||||
T* Get() { return array.get(); }
|
||||
const T* Get() const { return array.get(); }
|
||||
usize Size() const { return size; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<T[]> array {};
|
||||
usize size {};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using Unique = std::unique_ptr<T>;
|
||||
|
||||
} // namespace common
|
71
speech2/src/base/comptr.hpp
Normal file
71
speech2/src/base/comptr.hpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#pragma once
|
||||
#include <base/SaneWin.hpp>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace base {
|
||||
|
||||
// A relatively sane (non-intrinsic) COM smart pointer
|
||||
// TODO: Allow downcasting to ComPtr<IUnknown, IID_IUnknown> (all COM objects implement this anyways)
|
||||
//
|
||||
template <class T = IUnknown, const IID* iid = &IID_IUnknown>
|
||||
struct ComPtr {
|
||||
//constexpr ComPtr() = default;
|
||||
|
||||
//explicit ComPtr(T* t) : interface_ptr(t) {}
|
||||
constexpr ComPtr() : interface_ptr(nullptr) {}
|
||||
|
||||
// Assignment won't require AddRef() because most COM interfaces
|
||||
// will automatically AddRef() upon querying them.
|
||||
ComPtr& operator=(T* interface_) {
|
||||
// Release an existing interface.
|
||||
if(interface_ptr) {
|
||||
printf("ComPtr<T>::operator= releasing %p (guid %08x)\n", interface_ptr, *iid);
|
||||
interface_ptr->Release();
|
||||
}
|
||||
|
||||
interface_ptr = interface_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ComPtr(const ComPtr& copy) {
|
||||
if(interface_ptr) {
|
||||
interface_ptr->AddRef();
|
||||
interface_ptr = copy.interface_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
~ComPtr() {
|
||||
if(interface_ptr) {
|
||||
printf("ComPtr<T>::~ComPtr releasing %p (guid %08x)\n", interface_ptr, *iid);
|
||||
interface_ptr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to CoCreateInstance() on this pointer
|
||||
HRESULT CreateInstance(REFCLSID clsid, DWORD ctx) {
|
||||
return CoCreateInstance(clsid, nullptr, CLSCTX_ALL, *iid, reinterpret_cast<void**>(&interface_ptr));
|
||||
}
|
||||
|
||||
// smart pointer overrides
|
||||
|
||||
constexpr T** operator&() { return &interface_ptr; }
|
||||
constexpr T* operator->() { return interface_ptr; }
|
||||
constexpr operator T*() const { return interface_ptr; }
|
||||
|
||||
T* Get() { return interface_ptr; }
|
||||
const T* Get() const { return interface_ptr; }
|
||||
|
||||
// release pointer - you need to manage it yourself or put it
|
||||
// into another ComSmartPtr then
|
||||
T* ReleasePtr() {
|
||||
auto old = interface_ptr;
|
||||
interface_ptr = nullptr;
|
||||
return old;
|
||||
}
|
||||
|
||||
private:
|
||||
T* interface_ptr { nullptr };
|
||||
};
|
||||
|
||||
} // namespace base
|
35
speech2/src/impl/CMakeLists.txt
Normal file
35
speech2/src/impl/CMakeLists.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
add_library(speech2_impl
|
||||
asio_src.cpp
|
||||
beast_src.cpp
|
||||
)
|
||||
|
||||
speech2_target(speech2_impl)
|
||||
|
||||
target_compile_definitions(speech2_impl PUBLIC
|
||||
# Need to force this on, since I think clang's msvc compatibility
|
||||
# is deciding to set a wrong __cplusplus (like MSVC, so it's not *exactly* clang's fault).
|
||||
# The best way to fix it would probably involve using clang-cl frontend and passing the option (I think.)
|
||||
# (nevermind, it's just broken.)
|
||||
-DBOOST_ASIO_HAS_STD_INVOKE_RESULT=1
|
||||
|
||||
# We compile all of these header-only libraries in separate .cpp source files
|
||||
# to decrease build churn
|
||||
-DBOOST_ASIO_SEPARATE_COMPILATION=1
|
||||
-DBOOST_BEAST_SEPARATE_COMPILATION=1
|
||||
|
||||
# Disable deprecated functionality and some things which add additional dependencies or are
|
||||
# simply baggage we aren't ever going to use
|
||||
-DBOOST_ASIO_NO_DEPRECATED=1
|
||||
-DBOOST_ASIO_DISABLE_BOOST_ARRAY=1
|
||||
-DBOOST_ASIO_DISABLE_BOOST_BIND=1
|
||||
)
|
||||
|
||||
target_link_libraries(speech2_impl PUBLIC
|
||||
Boost::asio
|
||||
Boost::beast
|
||||
|
||||
Boost::coroutine
|
||||
Boost::context
|
||||
)
|
||||
|
||||
add_library(speech2::impl ALIAS speech2_impl)
|
5
speech2/src/impl/asio_src.cpp
Normal file
5
speech2/src/impl/asio_src.cpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
// Since we're using (BOOST_)ASIO_SEPARATE_COMPILATION, we need
|
||||
// to include the <(boost/)asio/impl/src.hpp> header in some TU.
|
||||
// We use this one to explicitly do so.
|
||||
|
||||
#include <boost/asio/impl/src.hpp>
|
1
speech2/src/impl/beast_src.cpp
Normal file
1
speech2/src/impl/beast_src.cpp
Normal file
|
@ -0,0 +1 @@
|
|||
#include <boost/beast/src.hpp>
|
163
speech2/src/main.cpp
Normal file
163
speech2/src/main.cpp
Normal file
|
@ -0,0 +1,163 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/beast/core/basic_stream.hpp>
|
||||
#include <boost/beast/core/flat_buffer.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/http/message_generator.hpp>
|
||||
#include <boost/beast/http/read.hpp>
|
||||
#include <boost/beast/http/string_body.hpp>
|
||||
#include <boost/beast/http/write.hpp>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "base/Logger.hpp"
|
||||
#include "base/StdoutSink.hpp"
|
||||
#include "speechapi.hpp"
|
||||
|
||||
namespace net = boost::asio;
|
||||
namespace beast = boost::beast;
|
||||
namespace bhttp = beast::http;
|
||||
|
||||
using net::ip::tcp;
|
||||
|
||||
auto coresv_to_cxx(boost::core::string_view sv) {
|
||||
return std::string_view { sv.data(), sv.length() };
|
||||
}
|
||||
|
||||
// A test coro
|
||||
void test_out_of_line_coro(net::any_io_executor ioc,net::yield_context yc) {
|
||||
net::steady_timer t{ioc};
|
||||
|
||||
t.expires_after(std::chrono::seconds(5));
|
||||
t.async_wait(yc);
|
||||
}
|
||||
|
||||
class session : public std::enable_shared_from_this<session> {
|
||||
public:
|
||||
explicit session(net::io_context& io_context, beast::basic_stream<net::ip::tcp> socket)
|
||||
: socket_(std::move(socket)), strand_(io_context.get_executor()) {}
|
||||
|
||||
void go() {
|
||||
auto self(shared_from_this());
|
||||
|
||||
net::spawn(
|
||||
strand_,
|
||||
[this, self](net::yield_context yield) {
|
||||
try {
|
||||
auto& logger = base::Logger::Get("HTTPSession");
|
||||
|
||||
bhttp::request<bhttp::string_body> req {};
|
||||
beast::flat_buffer buffer {};
|
||||
|
||||
logger.Info("Wait test");
|
||||
|
||||
// mostly just to test if I can yield stuff from another member function.
|
||||
// This seems to work, so /shrug
|
||||
test_out_of_line_coro(socket_.get_executor(), yield);
|
||||
|
||||
logger.Info("Wait completed");
|
||||
|
||||
for(;;) {
|
||||
socket_.expires_after(std::chrono::seconds(10));
|
||||
bhttp::async_read(socket_, buffer, req, yield);
|
||||
|
||||
auto const routeTest = [&]() -> bhttp::message_generator {
|
||||
bhttp::response<bhttp::string_body> resp { bhttp::status::bad_request, req.version() };
|
||||
resp.set(bhttp::field::server, "Fucker Google/1.0");
|
||||
resp.set(bhttp::field::content_type, "text/plain");
|
||||
resp.keep_alive(false);
|
||||
resp.body() = std::format("You requested \"{} {}\"", coresv_to_cxx(req.method_string()), coresv_to_cxx(req.target()));
|
||||
resp.prepare_payload();
|
||||
return resp;
|
||||
};
|
||||
|
||||
logger.Info("HTTP request to {}", coresv_to_cxx(req.target()));
|
||||
|
||||
auto res = routeTest();
|
||||
|
||||
socket_.expires_after(std::chrono::seconds(10));
|
||||
beast::async_write(socket_, std::move(res), yield);
|
||||
|
||||
if(!req.keep_alive()) {
|
||||
socket_.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch(std::exception& e) {
|
||||
socket_.close();
|
||||
}
|
||||
},
|
||||
net::detached);
|
||||
}
|
||||
|
||||
private:
|
||||
beast::basic_stream<net::ip::tcp> socket_;
|
||||
net::strand<net::io_context::executor_type> strand_;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// CoInitialize(nullptr);
|
||||
|
||||
base::LoggerAttachStdout();
|
||||
|
||||
try {
|
||||
if(argc != 2) {
|
||||
std::cerr << "Usage: echo_server <port>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
net::io_context io_context;
|
||||
|
||||
net::spawn(
|
||||
io_context,
|
||||
[&](net::yield_context yield) {
|
||||
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), std::atoi(argv[1])));
|
||||
|
||||
for(;;) {
|
||||
boost::system::error_code ec;
|
||||
tcp::socket socket(io_context);
|
||||
|
||||
acceptor.async_accept(socket, yield[ec]);
|
||||
if(!ec) {
|
||||
auto stream = beast::basic_stream<net::ip::tcp>(std::move(socket));
|
||||
std::make_shared<session>(io_context, std::move(stream))->go();
|
||||
}
|
||||
}
|
||||
},
|
||||
[](std::exception_ptr e) {
|
||||
if(e)
|
||||
std::rethrow_exception(e);
|
||||
});
|
||||
|
||||
io_context.run();
|
||||
} catch(std::exception& e) {
|
||||
std::cerr << "Exception: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
#if 0 // test spech shit
|
||||
auto api = std::unique_ptr<ISpeechAPI>(ISpeechAPI::CreateSapi4());
|
||||
|
||||
if(auto hr = api->Initialize(); FAILED(hr)) {
|
||||
printf("Failed to initialize speech API\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if(auto hr = api->SelectVoice("Sam"); FAILED(hr)) {
|
||||
printf("Failed to select voice\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Selected voice\n");
|
||||
#endif
|
||||
|
||||
// CoUninitialize();
|
||||
return 0;
|
||||
}
|
11
speech2/src/sapi4/CMakeLists.txt
Normal file
11
speech2/src/sapi4/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
# SAPI4 layer for speech2
|
||||
|
||||
add_library(speech2_sapi4
|
||||
api_sapi4.cpp
|
||||
guid_sapi4.cpp
|
||||
audio_buffer.cpp
|
||||
)
|
||||
|
||||
speech2_target(speech2_sapi4)
|
||||
|
||||
add_library(speech2::api_sapi4 ALIAS speech2_sapi4)
|
97
speech2/src/sapi4/api_sapi4.cpp
Normal file
97
speech2/src/sapi4/api_sapi4.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <base/comptr.hpp>
|
||||
|
||||
#include "sapi4/audio_buffer.hpp"
|
||||
#include "sapi4/include/speech.h"
|
||||
#include "speechapi.hpp"
|
||||
|
||||
struct SpeechAPI_SAPI4 : public ISpeechAPI {
|
||||
virtual ~SpeechAPI_SAPI4() {
|
||||
printf("~SpeechAPI_SAPI4\n");
|
||||
// if(pAudioOut)
|
||||
// pAudioOut->AddRef();
|
||||
|
||||
if(pCentral)
|
||||
pCentral->Release();
|
||||
};
|
||||
|
||||
HRESULT Initialize() override {
|
||||
HRESULT hRes{};
|
||||
|
||||
printf("speech2: SpeechAPI_Sapi4::Initalize() begin: %p\n", this);
|
||||
|
||||
hRes = pEnum.CreateInstance(CLSID_TTSEnumerator, CLSCTX_INPROC);
|
||||
if(FAILED(hRes))
|
||||
return hRes;
|
||||
|
||||
|
||||
pEnum->Reset();
|
||||
|
||||
// Fill out voices
|
||||
EnumVoices();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void EnumVoices() {
|
||||
TTSMODEINFO found{};
|
||||
|
||||
while(!pEnum->Next(1, &found, nullptr)) {
|
||||
voices.push_back({found.gModeID, found.szModeName});
|
||||
}
|
||||
|
||||
pEnum->Reset();
|
||||
}
|
||||
|
||||
const std::vector<VoiceInfo>& GetVoices() override {
|
||||
return voices;
|
||||
}
|
||||
|
||||
HRESULT SelectVoiceImpl(const GUID& guid) {
|
||||
pAudioOut = new AudioOutBuffer();
|
||||
pAudioOut->AddRef();
|
||||
|
||||
if(pCentral)
|
||||
pCentral->Release();
|
||||
|
||||
ITTSCentral* central;
|
||||
if(auto hr = pEnum->Select(guid, ¢ral, static_cast<IUnknown*>(pAudioOut)); FAILED(hr))
|
||||
return hr;
|
||||
|
||||
pCentral = central;
|
||||
|
||||
// From Microsoft Speech SDK 4.0 documentation:
|
||||
// The engine will AddRef the interface, and release the interface when the engine is destroyed.
|
||||
// Because of this the application will need to call Release on the audio object after the select call or audio objects will be leaked.
|
||||
pAudioOut->Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SelectVoice(std::string_view voiceName) override {
|
||||
TTSMODEINFO found {};
|
||||
|
||||
while(!pEnum->Next(1, &found, nullptr)) {
|
||||
if(voiceName == found.szModeName) {
|
||||
return SelectVoiceImpl(found.gModeID);
|
||||
}
|
||||
}
|
||||
|
||||
pEnum->Reset();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
base::ComPtr<ITTSEnum, &IID_ITTSEnum> pEnum;
|
||||
ITTSCentral* pCentral { nullptr };
|
||||
|
||||
// The above comment is also why this isn't a ComPtr.
|
||||
AudioOutBuffer* pAudioOut { nullptr };
|
||||
|
||||
std::vector<VoiceInfo> voices{};
|
||||
};
|
||||
|
||||
ISpeechAPI* ISpeechAPI::CreateSapi4() {
|
||||
return new SpeechAPI_SAPI4();
|
||||
}
|
185
speech2/src/sapi4/audio_buffer.cpp
Normal file
185
speech2/src/sapi4/audio_buffer.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
#include "audio_buffer.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <winerror.h>
|
||||
|
||||
// Implements IAudioDest.
|
||||
struct AudioOutBuffer::Dest : public IAudioDest {
|
||||
Dest(AudioOutBuffer* pOut) : pOut(pOut) {}
|
||||
~Dest() = default;
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(const IID& riid, LPVOID* ppvObj) noexcept override { return pOut->QueryInterface(riid, ppvObj); }
|
||||
|
||||
STDMETHODIMP_(ULONG) AddRef() noexcept override {
|
||||
m_iRefCount++;
|
||||
return pOut->AddRef();
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) Release() noexcept override {
|
||||
m_iRefCount--;
|
||||
return pOut->Release();
|
||||
}
|
||||
|
||||
// IAudioDest
|
||||
|
||||
STDMETHODIMP FreeSpace(DWORD* pFree, BOOL* pEOF) noexcept override { return E_NOTIMPL; }
|
||||
|
||||
STDMETHODIMP DataSet(PVOID pBuffer, DWORD dwSize) noexcept override {
|
||||
// TODO
|
||||
printf("AudioOutBuffer::Dest::DataSet()\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP BookMark(DWORD pos) noexcept override {
|
||||
// Ignored
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
AudioOutBuffer* pOut;
|
||||
ULONG m_iRefCount{};
|
||||
};
|
||||
|
||||
// Implements IAudio.
|
||||
struct AudioOutBuffer::Audio : public IAudio {
|
||||
Audio(AudioOutBuffer* pOut) : pOut(pOut) {}
|
||||
~Audio() {
|
||||
};
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(const IID& riid, LPVOID* ppvObj) noexcept override { return pOut->QueryInterface(riid, ppvObj); }
|
||||
|
||||
STDMETHODIMP_(ULONG) AddRef() noexcept override {
|
||||
m_iRefCount++;
|
||||
return pOut->AddRef();
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) Release() noexcept override {
|
||||
m_iRefCount--;
|
||||
return pOut->Release();
|
||||
}
|
||||
|
||||
// IAudio
|
||||
|
||||
STDMETHODIMP Flush() noexcept override { return S_OK; }
|
||||
|
||||
STDMETHODIMP LevelGet(DWORD* pLevel) noexcept override { return E_NOTIMPL; }
|
||||
|
||||
STDMETHODIMP LevelSet(DWORD level) noexcept override { return E_NOTIMPL; }
|
||||
|
||||
STDMETHODIMP PassNotify(PVOID pSink, IID iid) noexcept override {
|
||||
printf("AudioOutBuffer::Audio::PassNotify() %p\n", pSink);
|
||||
if(pSink == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if(iid != IID_IAudioDestNotifySink)
|
||||
return AUDERR_INVALIDNOTIFYSINK;
|
||||
|
||||
pOut->m_pDestNotifySink = static_cast<IAudioDestNotifySink*>(pSink);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP PosnGet(PQWORD pos) noexcept override {
|
||||
if(!pos)
|
||||
return E_POINTER;
|
||||
*pos = pOut->m_BufferWritten;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP Claim() noexcept override { return S_OK; }
|
||||
|
||||
STDMETHODIMP UnClaim() noexcept override { return S_OK; }
|
||||
|
||||
STDMETHODIMP Start() noexcept override {
|
||||
// TODO
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP Stop() noexcept override {
|
||||
// TODO
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP TotalGet(PQWORD total) noexcept override { return PosnGet(total); }
|
||||
|
||||
STDMETHODIMP ToFileTime(PQWORD time, FILETIME* out) noexcept override { return E_NOTIMPL; }
|
||||
|
||||
STDMETHODIMP WaveFormatGet(SDATA* pOut) noexcept override {
|
||||
// TODO
|
||||
|
||||
//IMalloc* pMalloc { nullptr };
|
||||
//if(auto hr = CoGetMalloc(1, &pMalloc); FAILED(hr))
|
||||
// return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WaveFormatSet(SDATA data) noexcept override {
|
||||
if(!data.pData)
|
||||
return E_INVALIDARG;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
AudioOutBuffer* pOut;
|
||||
|
||||
ULONG m_iRefCount{};
|
||||
};
|
||||
|
||||
AudioOutBuffer::AudioOutBuffer() {
|
||||
printf("AudioOutBuffer() %p\n", this);
|
||||
m_Audio = new AudioOutBuffer::Audio(this);
|
||||
m_AudioDestBuffer = new AudioOutBuffer::Dest(this);
|
||||
}
|
||||
|
||||
AudioOutBuffer::~AudioOutBuffer() {
|
||||
printf("~AudioOutBuffer() %p\n", this);
|
||||
if(m_AudioDestBuffer)
|
||||
delete m_AudioDestBuffer;
|
||||
|
||||
if(m_Audio)
|
||||
delete m_Audio;
|
||||
}
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP AudioOutBuffer::QueryInterface(const IID& riid, LPVOID* ppvObj) noexcept {
|
||||
if(!ppvObj)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
*ppvObj = nullptr;
|
||||
|
||||
// This object only directly implements IUnknown, and proxies
|
||||
// to other implementation objects for other interfaces.
|
||||
if(riid == IID_IUnknown) {
|
||||
*ppvObj = static_cast<void*>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Return implementations
|
||||
if(riid == IID_IAudio) {
|
||||
*ppvObj = static_cast<void*>(m_Audio);
|
||||
//m_Audio->AddRef();
|
||||
return S_OK;
|
||||
} else if(riid == IID_IAudioDest) {
|
||||
*ppvObj = static_cast<void*>(m_AudioDestBuffer);
|
||||
//m_AudioDestBuffer->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) AudioOutBuffer::AddRef() {
|
||||
return InterlockedIncrement(&m_iRefCount);
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) AudioOutBuffer::Release() {
|
||||
auto ulRefCount = InterlockedDecrement(&m_iRefCount);
|
||||
if(ulRefCount == 0) {
|
||||
printf("Deleting release AudioOutBuffer\n");
|
||||
delete this;
|
||||
}
|
||||
return ulRefCount;
|
||||
}
|
43
speech2/src/sapi4/audio_buffer.hpp
Normal file
43
speech2/src/sapi4/audio_buffer.hpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
#include <windows.h>
|
||||
#include "base/comptr.hpp"
|
||||
#include "sapi4/include/speech.h"
|
||||
|
||||
// Implementation of SAPI 4 IAudio(Dest) to spit out wave format data to a buffer
|
||||
// TODO: out-line definition so other components can call methods they need
|
||||
struct AudioOutBuffer : public IUnknown {
|
||||
|
||||
// Implements IAudioDest.
|
||||
struct Dest;
|
||||
struct Audio;
|
||||
|
||||
AudioOutBuffer();
|
||||
virtual ~AudioOutBuffer();
|
||||
|
||||
AudioOutBuffer(const AudioOutBuffer&) = delete;
|
||||
AudioOutBuffer(AudioOutBuffer&&) = delete;
|
||||
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(const IID& riid, LPVOID* ppvObj) noexcept override;
|
||||
STDMETHODIMP_(ULONG) AddRef() override;
|
||||
STDMETHODIMP_(ULONG) Release() override;
|
||||
|
||||
private:
|
||||
ULONG m_iRefCount{};
|
||||
|
||||
Dest* m_AudioDestBuffer{};
|
||||
Audio* m_Audio{};
|
||||
|
||||
enum class State {
|
||||
Clear,
|
||||
WroteHeader,
|
||||
WritingWaveData,
|
||||
Done
|
||||
};
|
||||
|
||||
//base::ComPtr<IAudioDestNotifySink, &IID_IAudioDestNotifySink> m_pDestNotifySink{};
|
||||
IAudioDestNotifySink* m_pDestNotifySink{nullptr};
|
||||
|
||||
QWORD m_BufferWritten{};
|
||||
|
||||
};
|
6
speech2/src/sapi4/guid_sapi4.cpp
Normal file
6
speech2/src/sapi4/guid_sapi4.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
// This file declares all the SAPI 4.0 GUID's.
|
||||
|
||||
#include <windows.h>
|
||||
#include <initguid.h>
|
||||
|
||||
#include "sapi4/include/speech.h"
|
30
speech2/src/speechapi.hpp
Normal file
30
speech2/src/speechapi.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
/// base class for access to text-to-speech APIs.
|
||||
struct ISpeechAPI {
|
||||
|
||||
struct VoiceInfo {
|
||||
GUID guid{}; // Optional. May not be filled out if the API doesn't do guids
|
||||
std::string voiceName;
|
||||
};
|
||||
|
||||
virtual ~ISpeechAPI() = default;
|
||||
|
||||
/// Creates a implementation of SpeechAPI for SAPI 4.
|
||||
/// COM must be initalized before calling this function.
|
||||
static ISpeechAPI* CreateSapi4();
|
||||
|
||||
/// Performs the bare level of initalization required to use the speech API
|
||||
virtual HRESULT Initialize() = 0;
|
||||
|
||||
virtual const std::vector<VoiceInfo>& GetVoices() = 0;
|
||||
|
||||
/// Selects a voice.
|
||||
virtual HRESULT SelectVoice(std::string_view voiceName) = 0;
|
||||
|
||||
|
||||
//virtual HRESULT Speak(LPCSTR text, char** pOutputBuffer, size_t* pOutSize) = 0;
|
||||
};
|
34
speech2/src/winxp_compat.cpp
Normal file
34
speech2/src/winxp_compat.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <windows.h>
|
||||
|
||||
typedef BOOL(WINAPI* PFN_INITIALIZECRITICALSECTIONEX)(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags);
|
||||
|
||||
extern "C" {
|
||||
|
||||
PFN_INITIALIZECRITICALSECTIONEX pfnInitalizeCriticalSectionEx = nullptr;
|
||||
|
||||
BOOL WINAPI _InitalizeCriticalSectionEx_xp(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags) {
|
||||
// We ignore dwFlags, but pass dwSpinCount to InitializeCriticalSectionAndSpinCount,
|
||||
// which DOES exist on XP.
|
||||
static_cast<void>(dwFlags);
|
||||
return InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount);
|
||||
}
|
||||
|
||||
BOOL WINAPI LibInitalizeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags) {
|
||||
if(!pfnInitalizeCriticalSectionEx) {
|
||||
pfnInitalizeCriticalSectionEx =
|
||||
reinterpret_cast<PFN_INITIALIZECRITICALSECTIONEX>(GetProcAddress(GetModuleHandle("kernel32.dll"), "InitializeCriticalSectionEx"));
|
||||
|
||||
// Compatibilty.
|
||||
if(!pfnInitalizeCriticalSectionEx)
|
||||
pfnInitalizeCriticalSectionEx = _InitalizeCriticalSectionEx_xp;
|
||||
}
|
||||
|
||||
return pfnInitalizeCriticalSectionEx(lpCriticalSection, dwSpinCount, dwFlags);
|
||||
}
|
||||
|
||||
void WINAPI LibGetSystemTimePreciseAsFileTime(LPFILETIME lpSystemTimeAsFileTime) {
|
||||
// TODO: Above
|
||||
return GetSystemTimeAsFileTime(lpSystemTimeAsFileTime);
|
||||
}
|
||||
|
||||
}
|
9
speech2/src/winxp_compat_fwd.S
Normal file
9
speech2/src/winxp_compat_fwd.S
Normal file
|
@ -0,0 +1,9 @@
|
|||
// This file declares forwarders for Windows imports which the newer VS 2022 CRT requires.
|
||||
|
||||
.globl "__imp__InitializeCriticalSectionEx@12"
|
||||
"__imp__InitializeCriticalSectionEx@12":
|
||||
.long "_LibInitalizeCriticalSectionEx@12"
|
||||
|
||||
.globl "__imp__GetSystemTimePreciseAsFileTime@4"
|
||||
"__imp__GetSystemTimePreciseAsFileTime@4":
|
||||
.long "_LibGetSystemTimePreciseAsFileTime@4"
|
104
speech2/src/winxp_compat_threadsafe_static.c
Normal file
104
speech2/src/winxp_compat_threadsafe_static.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/* This file provides routines used for thread-safe initialisation of static
|
||||
* variables when /Zc:threadSafeInit is used (enabled by default).
|
||||
*
|
||||
* This is intended to override the default implementations from the Microsoft
|
||||
* C++ Runtime which are compiled to target Windows Vista or later.
|
||||
*
|
||||
* Modeled on the reference implementation in thread_safe_statics.cpp in the
|
||||
* Microsoft C++ Runtime.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static const int UNINITIALIZED = 0;
|
||||
static const int INITIALIZING = -1;
|
||||
|
||||
static const int EPOCH_BASE = INT_MIN;
|
||||
|
||||
/* Exposed as a public symbol in the reference implementation, so exposed it
|
||||
* has to stay here too...
|
||||
*/
|
||||
int _Init_global_epoch = EPOCH_BASE;
|
||||
__declspec(thread) int _Init_thread_epoch = EPOCH_BASE;
|
||||
|
||||
static pthread_mutex_t _Init_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t _Init_thread_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
void __cdecl _Init_thread_lock()
|
||||
{
|
||||
pthread_mutex_lock(&_Init_thread_mutex);
|
||||
}
|
||||
|
||||
void __cdecl _Init_thread_unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&_Init_thread_mutex);
|
||||
}
|
||||
|
||||
void __cdecl _Init_thread_wait_v2()
|
||||
{
|
||||
pthread_cond_wait(&_Init_thread_cond, &_Init_thread_mutex);
|
||||
}
|
||||
|
||||
void __cdecl _Init_thread_notify()
|
||||
{
|
||||
pthread_cond_broadcast(&_Init_thread_cond);
|
||||
}
|
||||
|
||||
void __cdecl _Init_thread_header(int* const pOnce)
|
||||
{
|
||||
_Init_thread_lock();
|
||||
|
||||
if (*pOnce == UNINITIALIZED)
|
||||
{
|
||||
*pOnce = INITIALIZING;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*pOnce == INITIALIZING)
|
||||
{
|
||||
_Init_thread_wait_v2();
|
||||
|
||||
if (*pOnce == UNINITIALIZED)
|
||||
{
|
||||
*pOnce = INITIALIZING;
|
||||
_Init_thread_unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
_Init_thread_epoch = _Init_global_epoch;
|
||||
}
|
||||
|
||||
_Init_thread_unlock();
|
||||
}
|
||||
|
||||
void __cdecl _Init_thread_abort(int* const pOnce)
|
||||
{
|
||||
_Init_thread_lock();
|
||||
|
||||
*pOnce = UNINITIALIZED;
|
||||
|
||||
_Init_thread_unlock();
|
||||
_Init_thread_notify();
|
||||
}
|
||||
|
||||
void __cdecl _Init_thread_footer(int* const pOnce)
|
||||
{
|
||||
_Init_thread_lock();
|
||||
|
||||
++_Init_global_epoch;
|
||||
|
||||
/* Probably unlikely condition... you would need to construct ~2 billion
|
||||
* static objects before the "epoch" would roll up to the "INITIALIZING"
|
||||
* constant and cause weird behaviour... the official implementation
|
||||
* technically has this bug too.
|
||||
*/
|
||||
assert(_Init_global_epoch < INITIALIZING);
|
||||
|
||||
*pOnce = _Init_global_epoch;
|
||||
_Init_thread_epoch = _Init_global_epoch;
|
||||
|
||||
_Init_thread_unlock();
|
||||
_Init_thread_notify();
|
||||
}
|
4
speech2/third_party/README.md
vendored
Normal file
4
speech2/third_party/README.md
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
Files in this directory are the intellectual property of:
|
||||
|
||||
- sapi4: Microsoft Speech SDK 4.0.4.2512
|
||||
- sapi5: Microsoft Speech SDK 5.1
|
13
speech2/third_party/boost/CMakeLists.txt
vendored
Normal file
13
speech2/third_party/boost/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Hack but it works :)
|
||||
set(BOOST_SUPERPROJECT_VERSION 1.85.0)
|
||||
|
||||
# Boost Context Have Sucks
|
||||
set(BOOST_CONTEXT_ASSEMBLER clang_gas CACHE STRING "")
|
||||
set(BOOST_CONTEXT_ASM_SUFFIX .S CACHE STRING "")
|
||||
|
||||
# Populate library list
|
||||
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/list _COLLABVM3_BOOST_LIBRARY_LIST)
|
||||
foreach(lib ${_COLLABVM3_BOOST_LIBRARY_LIST})
|
||||
message(STATUS "Adding boost module ${lib}")
|
||||
add_subdirectory(${lib})
|
||||
endforeach()
|
11
speech2/third_party/boost/README.md
vendored
Normal file
11
speech2/third_party/boost/README.md
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Welcome to hell
|
||||
|
||||
This is where all the boost libraries used by the server live
|
||||
|
||||
see ./list for them
|
||||
|
||||
# Reinitalizing
|
||||
|
||||
The following bash one liner was used to initalize this repo
|
||||
|
||||
`for f in $(cat list); do git submodule add https://github.com/boostorg/$f.git $f; cd $f; git checkout boost-1.82.0; cd ..; done`
|
10
speech2/third_party/boost/add.sh
vendored
Executable file
10
speech2/third_party/boost/add.sh
vendored
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
# note that this doesn't add the library to ./list
|
||||
# you will need to do that yourself
|
||||
# (it could be added but bleh)
|
||||
|
||||
lib=$1
|
||||
git submodule add https://github.com/boostorg/$lib.git $lib
|
||||
# remember to bump the version afterwards
|
||||
|
1
speech2/third_party/boost/algorithm
vendored
Submodule
1
speech2/third_party/boost/algorithm
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 32c5a6327cfdca5d41ce0f1d8849b811886daa2f
|
1
speech2/third_party/boost/align
vendored
Submodule
1
speech2/third_party/boost/align
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 5ad7df63cd792fbdb801d600b93cad1a432f0151
|
1
speech2/third_party/boost/array
vendored
Submodule
1
speech2/third_party/boost/array
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 23f6b27c0d9916b9932baac898ae3009817a9153
|
1
speech2/third_party/boost/asio
vendored
Submodule
1
speech2/third_party/boost/asio
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit e65367991cb5fbdb8a7cf218ae38f69ca9a0a9f5
|
1
speech2/third_party/boost/assert
vendored
Submodule
1
speech2/third_party/boost/assert
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 447e0b3a331930f8708ade0e42683d12de9dfbc3
|
1
speech2/third_party/boost/atomic
vendored
Submodule
1
speech2/third_party/boost/atomic
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 5bbcce0f6e855dc4009e2e6977c62e0520c39573
|
1
speech2/third_party/boost/beast
vendored
Submodule
1
speech2/third_party/boost/beast
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 98b8be489fa7a74753a724d8d0772d90bcbed0fc
|
1
speech2/third_party/boost/bind
vendored
Submodule
1
speech2/third_party/boost/bind
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 9fbfdcb3577e9427815d4f8cc25b3a25d5b9696b
|
10
speech2/third_party/boost/bump_version.sh
vendored
Executable file
10
speech2/third_party/boost/bump_version.sh
vendored
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
# bump all the repositories
|
||||
for library in $(cat $PWD/list); do
|
||||
pushd $library >/dev/null 2>&1
|
||||
git checkout develop
|
||||
git pull
|
||||
git checkout $1
|
||||
popd >/dev/null 2>&1
|
||||
done
|
1
speech2/third_party/boost/charconv
vendored
Submodule
1
speech2/third_party/boost/charconv
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit ecdca0865d4d8fcfbf8e5b48914f2b5711c418ad
|
1
speech2/third_party/boost/chrono
vendored
Submodule
1
speech2/third_party/boost/chrono
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit ee0d6d543a37d9b7243682549e9ae359eb89daa9
|
1
speech2/third_party/boost/circular_buffer
vendored
Submodule
1
speech2/third_party/boost/circular_buffer
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit a08a5b55ee82e0c2487523471379ac53a23935dc
|
1
speech2/third_party/boost/concept_check
vendored
Submodule
1
speech2/third_party/boost/concept_check
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 37c9bddf0bdefaaae0ca5852c1a153d9fc43f278
|
1
speech2/third_party/boost/config
vendored
Submodule
1
speech2/third_party/boost/config
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 11385ec21012926e15a612e3bf9f9a71403c1e5b
|
1
speech2/third_party/boost/container
vendored
Submodule
1
speech2/third_party/boost/container
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 6e697d796897b32b471b4f0740dcaa03d8ee57cc
|
1
speech2/third_party/boost/container_hash
vendored
Submodule
1
speech2/third_party/boost/container_hash
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 6d214eb776456bf17fbee20780a034a23438084f
|
1
speech2/third_party/boost/context
vendored
Submodule
1
speech2/third_party/boost/context
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 1bde50e400547e29336afe7ea0cd693d8c884fb6
|
1
speech2/third_party/boost/conversion
vendored
Submodule
1
speech2/third_party/boost/conversion
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 9f285ef0c43c101e49b37bf5e6085e8d635887dc
|
1
speech2/third_party/boost/core
vendored
Submodule
1
speech2/third_party/boost/core
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 083b41c17e34f1fc9b43ab796b40d0d8bece685c
|
1
speech2/third_party/boost/coroutine
vendored
Submodule
1
speech2/third_party/boost/coroutine
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 1e1347c0b1910b9310ec1719edad8b0bf2fd03c8
|
1
speech2/third_party/boost/date_time
vendored
Submodule
1
speech2/third_party/boost/date_time
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 85e637cb325208c2af9af791c3a1948b4888c6cd
|
1
speech2/third_party/boost/describe
vendored
Submodule
1
speech2/third_party/boost/describe
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 50719b212349f3d1268285c586331584d3dbfeb5
|
1
speech2/third_party/boost/detail
vendored
Submodule
1
speech2/third_party/boost/detail
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 9c3a0022b25d3e483f9100cc363bc93a72fd900a
|
1
speech2/third_party/boost/endian
vendored
Submodule
1
speech2/third_party/boost/endian
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit c9b436e5dfce85e8ae365e5aabbb872dd35c29eb
|
1
speech2/third_party/boost/exception
vendored
Submodule
1
speech2/third_party/boost/exception
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit b9170a02f102250b308c9f94ed6593c5f30eab39
|
1
speech2/third_party/boost/filesystem
vendored
Submodule
1
speech2/third_party/boost/filesystem
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit a0c8edba38a4d31b449fcf7b7ada455977342596
|
1
speech2/third_party/boost/function
vendored
Submodule
1
speech2/third_party/boost/function
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 28b88d07bb4807445462c3f5dab0efde6f532d32
|
1
speech2/third_party/boost/function_types
vendored
Submodule
1
speech2/third_party/boost/function_types
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 895335874d67987ada0d8bf6ca1725e70642ed49
|
1
speech2/third_party/boost/functional
vendored
Submodule
1
speech2/third_party/boost/functional
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 6a573e4b8333ee63ee62ce95558c3667348db233
|
1
speech2/third_party/boost/fusion
vendored
Submodule
1
speech2/third_party/boost/fusion
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 7d4c03fa032299f2d46149b7b3136c9fd43e4f81
|
1
speech2/third_party/boost/integer
vendored
Submodule
1
speech2/third_party/boost/integer
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit dea8e3445dc3ca29201498260307138b9460a70c
|
1
speech2/third_party/boost/intrusive
vendored
Submodule
1
speech2/third_party/boost/intrusive
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 07ba0e376177409c396c109807c13b7181a98ebe
|
1
speech2/third_party/boost/io
vendored
Submodule
1
speech2/third_party/boost/io
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 342e4c6d10d586058818daa84201a2d301357a53
|
1
speech2/third_party/boost/iterator
vendored
Submodule
1
speech2/third_party/boost/iterator
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 4f7219965a399051bb0d8088ea4ab3929b1ac3f2
|
1
speech2/third_party/boost/json
vendored
Submodule
1
speech2/third_party/boost/json
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 9f85ed6d62ff91c6dc4fc30e3a20e9049ec67585
|
1
speech2/third_party/boost/leaf
vendored
Submodule
1
speech2/third_party/boost/leaf
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit ed8f9cd32f4fde695d497502f696f6f861b68559
|
1
speech2/third_party/boost/lexical_cast
vendored
Submodule
1
speech2/third_party/boost/lexical_cast
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 02e5821ab32c45fad719829e9644e5d681c9ba0b
|
67
speech2/third_party/boost/list
vendored
Normal file
67
speech2/third_party/boost/list
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
algorithm
|
||||
align
|
||||
array
|
||||
assert
|
||||
atomic
|
||||
bind
|
||||
charconv
|
||||
chrono
|
||||
circular_buffer
|
||||
concept_check
|
||||
config
|
||||
container
|
||||
container_hash
|
||||
context
|
||||
conversion
|
||||
core
|
||||
coroutine
|
||||
date_time
|
||||
describe
|
||||
detail
|
||||
endian
|
||||
exception
|
||||
filesystem
|
||||
function
|
||||
functional
|
||||
function_types
|
||||
fusion
|
||||
integer
|
||||
intrusive
|
||||
io
|
||||
iterator
|
||||
json
|
||||
leaf
|
||||
lexical_cast
|
||||
lockfree
|
||||
logic
|
||||
move
|
||||
mp11
|
||||
mpl
|
||||
numeric_conversion
|
||||
optional
|
||||
parameter
|
||||
pool
|
||||
predef
|
||||
preprocessor
|
||||
range
|
||||
ratio
|
||||
rational
|
||||
regex
|
||||
scope
|
||||
smart_ptr
|
||||
static_assert
|
||||
static_string
|
||||
system
|
||||
throw_exception
|
||||
tokenizer
|
||||
tuple
|
||||
type_index
|
||||
typeof
|
||||
type_traits
|
||||
unordered
|
||||
url
|
||||
utility
|
||||
variant2
|
||||
winapi
|
||||
asio
|
||||
beast
|
1
speech2/third_party/boost/lockfree
vendored
Submodule
1
speech2/third_party/boost/lockfree
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit fdd4d0632dd0904f6e9c656c45397fe8ef985bc9
|
1
speech2/third_party/boost/logic
vendored
Submodule
1
speech2/third_party/boost/logic
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 145778490c2d332c1411df6a5274a4b53ec3e091
|
1
speech2/third_party/boost/move
vendored
Submodule
1
speech2/third_party/boost/move
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 7c01072629d83a7b54c99de70ef535d699ebd200
|
1
speech2/third_party/boost/mp11
vendored
Submodule
1
speech2/third_party/boost/mp11
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 863d8b8d2b20f2acd0b5870f23e553df9ce90e6c
|
1
speech2/third_party/boost/mpl
vendored
Submodule
1
speech2/third_party/boost/mpl
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit b440c45c2810acbddc917db057f2e5194da1a199
|
1
speech2/third_party/boost/numeric_conversion
vendored
Submodule
1
speech2/third_party/boost/numeric_conversion
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 50a1eae942effb0a9b90724323ef8f2a67e7984a
|
1
speech2/third_party/boost/optional
vendored
Submodule
1
speech2/third_party/boost/optional
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit c60db27762ff9cc16529e069c3c15f2fa898f994
|
1
speech2/third_party/boost/parameter
vendored
Submodule
1
speech2/third_party/boost/parameter
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit c07f2b8d37ded87f6f9d5bac867550f6e61282c1
|
1
speech2/third_party/boost/pool
vendored
Submodule
1
speech2/third_party/boost/pool
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit ec7da07ed13e0c61e50d945b574a12ae7ec83cf4
|
1
speech2/third_party/boost/predef
vendored
Submodule
1
speech2/third_party/boost/predef
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 0fdfb49c3a6789e50169a44e88a07cc889001106
|
1
speech2/third_party/boost/preprocessor
vendored
Submodule
1
speech2/third_party/boost/preprocessor
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit c4ea7e40d365ba28faecef8917d5c3f1e0121bf9
|
1
speech2/third_party/boost/range
vendored
Submodule
1
speech2/third_party/boost/range
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 2bb6b636796f7b008196888613f51f5bb347c77d
|
1
speech2/third_party/boost/ratio
vendored
Submodule
1
speech2/third_party/boost/ratio
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit d5b33caa7d564be9be6d962b18659b7741d764ac
|
1
speech2/third_party/boost/rational
vendored
Submodule
1
speech2/third_party/boost/rational
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 564623136417068916495e2b24737054d607347c
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue