Repository: NaruseMioShirakana/DragonianVoice Branch: master Commit: d3efc14f69f9 Files: 286 Total size: 6.0 MB Directory structure: gitextract_96br6jqh/ ├── .gitattributes ├── .gitignore ├── .gitmodules ├── BasicDict.json ├── Bert/ │ ├── bert-base-japanese-v3/ │ │ └── Tokenizer.json │ ├── chinese-roberta-wwm-ext-large/ │ │ └── Tokenizer.json │ └── deberta-v2-large-japanese/ │ └── Tokenizer.json ├── BertVits.md ├── CMakeLists.txt ├── CMakePresets.json ├── CSharpDemo/ │ ├── CSharpDemo.csproj │ ├── Program.cs │ ├── Properties/ │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ └── launchSettings.json │ ├── README.md │ └── README_en.md ├── DotNetApi/ │ ├── DotNetApi.csproj │ ├── LibSvcApi.cs │ └── Properties/ │ └── launchSettings.json ├── DragonianSpeech.sln ├── LICENSE ├── README.md ├── README_en.md ├── TTSProjectTemplate.ttsproj ├── VitsInputTemplate.json ├── fish-speech.cpp/ │ ├── CMakeLists.txt │ ├── Demo/ │ │ ├── CMakeLists.txt │ │ └── main.cpp │ ├── include/ │ │ ├── Base.h │ │ ├── Module.h │ │ └── llama.h │ ├── src/ │ │ ├── Base.cpp │ │ ├── Module.cpp │ │ └── llama.cpp │ ├── test.py │ └── test.txt ├── libdlvoicecodec/ │ ├── LibDLVoiceCodec/ │ │ ├── base.cpp │ │ ├── base.h │ │ ├── operator.cpp │ │ ├── operator.h │ │ ├── value.cpp │ │ └── value.h │ ├── Modules/ │ │ ├── AvCodec/ │ │ │ ├── AvCodeResample.h │ │ │ ├── Recorder.cpp │ │ │ └── Recorder.h │ │ ├── DataStruct/ │ │ │ ├── KDTree.cpp │ │ │ ├── KDTree.hpp │ │ │ └── README.md │ │ ├── InferTools/ │ │ │ ├── Cluster/ │ │ │ │ ├── MoeVSBaseCluster.cpp │ │ │ │ ├── MoeVSBaseCluster.hpp │ │ │ │ ├── MoeVSClusterManager.cpp │ │ │ │ ├── MoeVSClusterManager.hpp │ │ │ │ ├── MoeVSIndexCluster.cpp │ │ │ │ ├── MoeVSIndexCluster.hpp │ │ │ │ ├── MoeVSKmeansCluster.cpp │ │ │ │ └── MoeVSKmeansCluster.hpp │ │ │ ├── F0Extractor/ │ │ │ │ ├── BaseF0Extractor/ │ │ │ │ │ ├── BaseF0Extractor.cpp │ │ │ │ │ └── BaseF0Extractor.hpp │ │ │ │ ├── DioF0Extractor/ │ │ │ │ │ ├── DioF0Extractor.cpp │ │ │ │ │ └── DioF0Extractor.hpp │ │ │ │ ├── F0ExtractorManager.cpp │ │ │ │ ├── F0ExtractorManager.hpp │ │ │ │ ├── HarvestF0Extractor/ │ │ │ │ │ ├── HarvestF0Extractor.cpp │ │ │ │ │ └── HarvestF0Extractor.hpp │ │ │ │ └── NetF0Predictors/ │ │ │ │ ├── NetF0Predictors.cpp │ │ │ │ └── NetF0Predictors.hpp │ │ │ ├── G2P/ │ │ │ │ ├── MoeVSG2P.cpp │ │ │ │ └── MoeVSG2P.hpp │ │ │ ├── Sampler/ │ │ │ │ ├── MoeVSBaseSampler.cpp │ │ │ │ ├── MoeVSBaseSampler.hpp │ │ │ │ ├── MoeVSSamplerManager.cpp │ │ │ │ ├── MoeVSSamplerManager.hpp │ │ │ │ ├── MoeVSSamplers.cpp │ │ │ │ └── MoeVSSamplers.hpp │ │ │ ├── Stft/ │ │ │ │ ├── stft.cpp │ │ │ │ └── stft.hpp │ │ │ ├── TensorExtractor/ │ │ │ │ ├── MoeVSCoreTensorExtractor.cpp │ │ │ │ ├── MoeVSCoreTensorExtractor.hpp │ │ │ │ ├── MoeVoiceStudioTensorExtractor.cpp │ │ │ │ ├── MoeVoiceStudioTensorExtractor.hpp │ │ │ │ ├── TensorExtractorManager.cpp │ │ │ │ └── TensorExtractorManager.hpp │ │ │ ├── inferTools.cpp │ │ │ └── inferTools.hpp │ │ ├── Logger/ │ │ │ ├── MoeSSLogger.cpp │ │ │ └── MoeSSLogger.hpp │ │ ├── Models/ │ │ │ ├── EnvManager.cpp │ │ │ ├── EnvManager.hpp │ │ │ ├── header/ │ │ │ │ ├── DiffSvc.hpp │ │ │ │ ├── GPT-SoVits.hpp │ │ │ │ ├── ModelBase.hpp │ │ │ │ ├── MoeVSProject.hpp │ │ │ │ ├── SVC.hpp │ │ │ │ ├── TTS.hpp │ │ │ │ ├── Tacotron.hpp │ │ │ │ ├── Vits.hpp │ │ │ │ └── VitsSvc.hpp │ │ │ └── src/ │ │ │ ├── DiffSvc.cpp │ │ │ ├── GPT-SoVits.cpp │ │ │ ├── ModelBase.cpp │ │ │ ├── MoeVSProject.cpp │ │ │ ├── SVC.cpp │ │ │ ├── TTS.cpp │ │ │ ├── Vits.cpp │ │ │ └── VitsSvc.cpp │ │ ├── Modules.cpp │ │ ├── Modules.hpp │ │ ├── README.md │ │ └── StringPreprocess.hpp │ ├── MoeVoiceStudioSvc - Core - Cmd.cpp │ ├── MoeVoiceStudioSvc - Core - Cmd.vcxproj │ ├── MoeVoiceStudioSvc - Core - Cmd.vcxproj.filters │ ├── analyse/ │ │ └── GptSoVits.md │ └── packages.config ├── libsvc/ │ ├── Api/ │ │ ├── header/ │ │ │ ├── NativeApi.h │ │ │ └── libsvc.h │ │ ├── readme.md │ │ └── src/ │ │ ├── NativeApi.cpp │ │ └── libsvc.cpp │ ├── Modules/ │ │ ├── Lib/ │ │ │ ├── MJson/ │ │ │ │ ├── MJson.cpp │ │ │ │ ├── MJson.h │ │ │ │ ├── yyjson.c │ │ │ │ └── yyjson.h │ │ │ └── World/ │ │ │ ├── LICENSE.txt │ │ │ ├── src/ │ │ │ │ ├── cheaptrick.cpp │ │ │ │ ├── codec.cpp │ │ │ │ ├── common.cpp │ │ │ │ ├── d4c.cpp │ │ │ │ ├── dio.cpp │ │ │ │ ├── fft.cpp │ │ │ │ ├── harvest.cpp │ │ │ │ ├── matlabfunctions.cpp │ │ │ │ ├── stonemask.cpp │ │ │ │ ├── synthesis.cpp │ │ │ │ ├── synthesisrealtime.cpp │ │ │ │ └── world/ │ │ │ │ ├── cheaptrick.h │ │ │ │ ├── codec.h │ │ │ │ ├── common.h │ │ │ │ ├── constantnumbers.h │ │ │ │ ├── d4c.h │ │ │ │ ├── dio.h │ │ │ │ ├── fft.h │ │ │ │ ├── harvest.h │ │ │ │ ├── macrodefinitions.h │ │ │ │ ├── matlabfunctions.h │ │ │ │ ├── stonemask.h │ │ │ │ ├── synthesis.h │ │ │ │ └── synthesisrealtime.h │ │ │ └── tools/ │ │ │ ├── audioio.cpp │ │ │ ├── audioio.h │ │ │ ├── parameterio.cpp │ │ │ └── parameterio.h │ │ ├── README.md │ │ ├── framework.h │ │ ├── header/ │ │ │ ├── InferTools/ │ │ │ │ ├── AvCodec/ │ │ │ │ │ └── AvCodeResample.h │ │ │ │ ├── Cluster/ │ │ │ │ │ ├── MoeVSBaseCluster.hpp │ │ │ │ │ ├── MoeVSClusterManager.hpp │ │ │ │ │ ├── MoeVSIndexCluster.hpp │ │ │ │ │ └── MoeVSKmeansCluster.hpp │ │ │ │ ├── DataStruct/ │ │ │ │ │ ├── KDTree.hpp │ │ │ │ │ └── README.md │ │ │ │ ├── F0Extractor/ │ │ │ │ │ ├── BaseF0Extractor.hpp │ │ │ │ │ ├── DioF0Extractor.hpp │ │ │ │ │ ├── F0ExtractorManager.hpp │ │ │ │ │ ├── HarvestF0Extractor.hpp │ │ │ │ │ └── NetF0Predictors.hpp │ │ │ │ ├── Sampler/ │ │ │ │ │ ├── MoeVSBaseSampler.hpp │ │ │ │ │ ├── MoeVSSamplerManager.hpp │ │ │ │ │ └── MoeVSSamplers.hpp │ │ │ │ ├── Stft/ │ │ │ │ │ └── stft.hpp │ │ │ │ ├── TensorExtractor/ │ │ │ │ │ ├── MoeVSCoreTensorExtractor.hpp │ │ │ │ │ ├── MoeVoiceStudioTensorExtractor.hpp │ │ │ │ │ └── TensorExtractorManager.hpp │ │ │ │ └── inferTools.hpp │ │ │ ├── Logger/ │ │ │ │ └── MoeSSLogger.hpp │ │ │ ├── Models/ │ │ │ │ ├── DiffSvc.hpp │ │ │ │ ├── EnvManager.hpp │ │ │ │ ├── ModelBase.hpp │ │ │ │ ├── MoeVSProject.hpp │ │ │ │ ├── ReflowSvc.hpp │ │ │ │ ├── SVC.hpp │ │ │ │ └── VitsSvc.hpp │ │ │ ├── Modules.hpp │ │ │ └── StringPreprocess.hpp │ │ └── src/ │ │ ├── InferTools/ │ │ │ ├── AvCodec/ │ │ │ │ └── AvCodeResample.cpp │ │ │ ├── Cluster/ │ │ │ │ ├── MoeVSBaseCluster.cpp │ │ │ │ ├── MoeVSClusterManager.cpp │ │ │ │ ├── MoeVSIndexCluster.cpp │ │ │ │ └── MoeVSKmeansCluster.cpp │ │ │ ├── DataStruct/ │ │ │ │ ├── KDTree.cpp │ │ │ │ └── README.md │ │ │ ├── F0Extractor/ │ │ │ │ ├── BaseF0Extractor.cpp │ │ │ │ ├── DioF0Extractor.cpp │ │ │ │ ├── F0ExtractorManager.cpp │ │ │ │ ├── HarvestF0Extractor.cpp │ │ │ │ └── NetF0Predictors.cpp │ │ │ ├── Sampler/ │ │ │ │ ├── MoeVSBaseSampler.cpp │ │ │ │ ├── MoeVSSamplerManager.cpp │ │ │ │ └── MoeVSSamplers.cpp │ │ │ ├── Stft/ │ │ │ │ └── stft.cpp │ │ │ ├── TensorExtractor/ │ │ │ │ ├── MoeVSCoreTensorExtractor.cpp │ │ │ │ ├── MoeVoiceStudioTensorExtractor.cpp │ │ │ │ └── TensorExtractorManager.cpp │ │ │ └── inferTools.cpp │ │ ├── Logger/ │ │ │ └── MoeSSLogger.cpp │ │ ├── Models/ │ │ │ ├── DiffSvc.cpp │ │ │ ├── EnvManager.cpp │ │ │ ├── ModelBase.cpp │ │ │ ├── MoeVSProject.cpp │ │ │ ├── ReflowSvc.cpp │ │ │ ├── SVC.cpp │ │ │ └── VitsSvc.cpp │ │ ├── Modules.cpp │ │ └── StringPreprocess.cpp │ ├── README.md │ ├── dllmain.cpp │ ├── libsvc.vcxproj │ ├── libsvc.vcxproj.filters │ └── packages.config ├── libtts/ │ ├── Api/ │ │ ├── NativeApi.cpp │ │ └── NativeApi.h │ ├── Modules/ │ │ ├── AvCodec/ │ │ │ ├── AvCodeResample.h │ │ │ ├── Recorder.cpp │ │ │ └── Recorder.h │ │ ├── InferTools/ │ │ │ ├── G2P/ │ │ │ │ ├── MoeVSG2P.cpp │ │ │ │ └── MoeVSG2P.hpp │ │ │ ├── inferTools.cpp │ │ │ └── inferTools.hpp │ │ ├── Lib/ │ │ │ ├── MJson/ │ │ │ │ ├── MJson.cpp │ │ │ │ ├── MJson.h │ │ │ │ ├── yyjson.c │ │ │ │ └── yyjson.h │ │ │ └── World/ │ │ │ ├── LICENSE.txt │ │ │ ├── src/ │ │ │ │ ├── cheaptrick.cpp │ │ │ │ ├── codec.cpp │ │ │ │ ├── common.cpp │ │ │ │ ├── d4c.cpp │ │ │ │ ├── dio.cpp │ │ │ │ ├── fft.cpp │ │ │ │ ├── harvest.cpp │ │ │ │ ├── matlabfunctions.cpp │ │ │ │ ├── stonemask.cpp │ │ │ │ ├── synthesis.cpp │ │ │ │ ├── synthesisrealtime.cpp │ │ │ │ └── world/ │ │ │ │ ├── cheaptrick.h │ │ │ │ ├── codec.h │ │ │ │ ├── common.h │ │ │ │ ├── constantnumbers.h │ │ │ │ ├── d4c.h │ │ │ │ ├── dio.h │ │ │ │ ├── fft.h │ │ │ │ ├── harvest.h │ │ │ │ ├── macrodefinitions.h │ │ │ │ ├── matlabfunctions.h │ │ │ │ ├── stonemask.h │ │ │ │ ├── synthesis.h │ │ │ │ └── synthesisrealtime.h │ │ │ └── tools/ │ │ │ ├── audioio.cpp │ │ │ ├── audioio.h │ │ │ ├── parameterio.cpp │ │ │ └── parameterio.h │ │ ├── Logger/ │ │ │ ├── MoeSSLogger.cpp │ │ │ └── MoeSSLogger.hpp │ │ ├── Models/ │ │ │ ├── EnvManager.cpp │ │ │ ├── EnvManager.hpp │ │ │ ├── header/ │ │ │ │ ├── GPT-SoVits.hpp │ │ │ │ ├── ModelBase.hpp │ │ │ │ ├── MoeVSProject.hpp │ │ │ │ ├── TTS.hpp │ │ │ │ ├── Tacotron.hpp │ │ │ │ └── Vits.hpp │ │ │ └── src/ │ │ │ ├── GPT-SoVits.cpp │ │ │ ├── ModelBase.cpp │ │ │ ├── MoeVSProject.cpp │ │ │ ├── TTS.cpp │ │ │ └── Vits.cpp │ │ ├── Modules.cpp │ │ ├── Modules.hpp │ │ ├── README.md │ │ └── StringPreprocess.hpp │ ├── dllmain.cpp │ ├── framework.h │ ├── libtts.vcxproj │ └── libtts.vcxproj.filters └── test.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ ############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto ############################################################################### # Set default behavior for command prompt diff. # # This is need for earlier builds of msysgit that does not have it on by # default for csharp files. # Note: This is only used by command line ############################################################################### #*.cs diff=csharp ############################################################################### # Set the merge driver for project and solution files # # Merging from the command prompt will add diff markers to the files if there # are conflicts (Merging from VS is not affected by the settings below, in VS # the diff markers are never inserted). Diff markers may cause the following # file extensions to fail to load in VS. An alternative would be to treat # these files as binary and thus will always conflict and require user # intervention with every merge. To do so, just uncomment the entries below ############################################################################### #*.sln merge=binary #*.csproj merge=binary #*.vbproj merge=binary #*.vcxproj merge=binary #*.vcproj merge=binary #*.dbproj merge=binary #*.fsproj merge=binary #*.lsproj merge=binary #*.wixproj merge=binary #*.modelproj merge=binary #*.sqlproj merge=binary #*.wwaproj merge=binary ############################################################################### # behavior for image files # # image files are treated as binary by default. ############################################################################### #*.jpg binary #*.png binary #*.gif binary ############################################################################### # diff behavior for common document formats # # Convert binary document formats to text before diffing them. This feature # is only available from the command line. Turn it on by uncommenting the # entries below. ############################################################################### #*.doc diff=astextplain #*.DOC diff=astextplain #*.docx diff=astextplain #*.DOCX diff=astextplain #*.dot diff=astextplain #*.DOT diff=astextplain #*.pdf diff=astextplain #*.PDF diff=astextplain #*.rtf diff=astextplain #*.RTF diff=astextplain ================================================ FILE: .gitignore ================================================ ## 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 # User-specific files *.rsuser *.suo *.user *.userosscache *.sln.docstates # 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 /MoeVoiceStudioSvc - Core - Cmd/Modules/README.md /Lib /MoeVoiceStudioSvc - Core - Cmd/output.wav /MoeVoiceStudioSvc - Core - Cmd/input.wav /fish-speech.cpp/ggml ================================================ FILE: .gitmodules ================================================ [submodule "libsvc-tensorlib"] path = libsvc-tensorlib url = https://github.com/NaruseMioShirakana/libsvc ================================================ FILE: BasicDict.json ================================================ { "_" : ["_"], "," : [","], "." : ["."], "!" : ["!"], "?" : ["?"], "-" : ["-"], "~" : ["~"], "…" : ["…"], "A" : ["A"], "E" : ["E"], "I" : ["I"], "N" : ["N"], "O" : ["O"], "Q" : ["Q"], "U" : ["U"], "a" : ["a"], "b" : ["b"], "d" : ["d"], "e" : ["e"], "f" : ["f"], "g" : ["g"], "h" : ["h"], "i" : ["i"], "j" : ["j"], "k" : ["k"], "m" : ["m"], "n" : ["n"], "o" : ["o"], "p" : ["p"], "r" : ["r"], "s" : ["s"], "t" : ["t"], "u" : ["u"], "v" : ["v"], "w" : ["w"], "y" : ["y"], "z" : ["z"], "ʃ" : ["ʃ"], "ʧ" : ["ʧ"], "ʦ" : ["ʦ"], "↓" : ["↓"], "↑" : ["↑"], " " : [" "] } ================================================ FILE: Bert/bert-base-japanese-v3/Tokenizer.json ================================================ { "Type": "WordPiece", "ContinuingSubwordPrefix": "##", "UseSplit" : true, "Vocab": ["[PAD]", "[UNK]", "[CLS]", "[SEP]", "[MASK]", "[unused0]", "[unused1]", "[unused2]", "[unused3]", "[unused4]", "[unused5]", "[unused6]", "[unused7]", "[unused8]", "[unused9]", " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "¡", "¢", "£", "¤", "¥", "¦", "§", "©", "«", "¬", "®", "°", "±", "¶", "·", "»", "¿", "Å", "×", "÷", "ÿ", "ħ", "Γ", "Δ", "Θ", "Λ", "Ξ", "Ο", "Π", "Σ", "Φ", "Ψ", "Ω", "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "π", "ρ", "σ", "τ", "υ", "φ", "χ", "ψ", "ω", "Д", "Щ", "д", "з", "щ", "ъ", "ё", "א", "ิ", "ლ", "‐", "–", "—", "―", "‖", "‘", "’", "“", "”", "†", "‡", "•", "‰", "′", "※", "‿", "⁂", "⁑", "€", "℧", "←", "↑", "→", "↓", "↔", "↖", "↗", "↘", "↙", "⇄", "⇒", "⇔", "⇦", "⇧", "⇨", "⇩", "∀", "∂", "∃", "∅", "∇", "∈", "∉", "∋", "−", "∓", "√", "∝", "∞", "∟", "∠", "∥", "∦", "∧", "∨", "∩", "∪", "∫", "∮", "∴", "∵", "∽", "≃", "≅", "≈", "≒", "≠", "≡", "≢", "≦", "≧", "≪", "≫", "≶", "≷", "⊂", "⊃", "⊄", "⊅", "⊆", "⊇", "⊊", "⊋", "⊕", "⊖", "⊗", "⊥", "⊿", "⋚", "⋛", "⌅", "⌆", "⌒", "⌘", "⎾", "⎿", "⏀", "⏁", "⏂", "⏃", "⏄", "⏅", "⏆", "⏇", "⏈", "⏉", "⏊", "⏋", "⏌", "⏎", "⓫", "⓬", "⓭", "⓮", "⓯", "⓰", "⓱", "⓲", "⓳", "⓴", "⓵", "⓶", "⓷", "⓸", "⓹", "⓺", "⓻", "⓼", "⓽", "⓾", "─", "━", "┌", "┐", "┘", "├", "╹", "■", "□", "▱", "▲", "△", "▶", "▷", "▼", "▽", "◀", "◁", "◆", "◇", "◉", "○", "◎", "●", "◐", "◑", "◒", "◓", "◡", "◦", "◯", "☀", "☁", "☂", "☃", "★", "☆", "☎", "☖", "☗", "☞", "♀", "♂", "♠", "♡", "♢", "♣", "♤", "♥", "♦", "♧", "♨", "♩", "♪", "♫", "♬", "♭", "♮", "♯", "✓", "❖", "❶", "❷", "❸", "❹", "❺", "❻", "❼", "❽", "❾", "❿", "⤴", "⤵", "⦅", "⦆", "⦿", "⧺", "⧻", "、", "。", "〃", "〄", "々", "〆", "〇", "〈", "〉", "《", "》", "「", "」", "『", "』", "【", "】", "〒", "〓", "〔", "〕", "〖", "〗", "〘", "〙", "〜", "〝", "〟", "〠", "〳", "〴", "〵", "〻", "〼", "〽", "ぁ", "あ", "ぃ", "い", "ぅ", "う", "ぇ", "え", "ぉ", "お", "か", "が", "き", "ぎ", "く", "ぐ", "け", "げ", "こ", "ご", "さ", "ざ", "し", "じ", "す", "ず", "せ", "ぜ", "そ", "ぞ", "た", "だ", "ち", "ぢ", "っ", "つ", "づ", "て", "で", "と", "ど", "な", "に", "ぬ", "ね", "の", "は", "ば", "ぱ", "ひ", "び", "ぴ", "ふ", "ぶ", "ぷ", "へ", "べ", "ぺ", "ほ", "ぼ", "ぽ", "ま", "み", "む", "め", "も", "ゃ", "や", "ゅ", "ゆ", "ょ", "よ", "ら", "り", "る", "れ", "ろ", "ゎ", "わ", "ゐ", "ゑ", "を", "ん", "ゝ", "ゞ", "゠", "ァ", "ア", "ィ", "イ", "ゥ", "ウ", "ェ", "エ", "ォ", "オ", "カ", "ガ", "キ", "ギ", "ク", "グ", "ケ", "ゲ", "コ", "ゴ", "サ", "ザ", "シ", "ジ", "ス", "ズ", "セ", "ゼ", "ソ", "ゾ", "タ", "ダ", "チ", "ヂ", "ッ", "ツ", "ヅ", "テ", "デ", "ト", "ド", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "バ", "パ", "ヒ", "ビ", "ピ", "フ", "ブ", "プ", "ヘ", "ベ", "ペ", "ホ", "ボ", "ポ", "マ", "ミ", "ム", "メ", "モ", "ャ", "ヤ", "ュ", "ユ", "ョ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ヮ", "ワ", "ヰ", "ヱ", "ヲ", "ン", "ヴ", "ヵ", "ヶ", "ヷ", "ヸ", "・", "ー", "ヽ", "ヾ", "ㇲ", "ㇻ", "㓛", "㮶", "一", "丁", "丂", "七", "万", "丈", "三", "上", "下", "不", "与", "丐", "丑", "且", "丕", "世", "丘", "丙", "丞", "両", "並", "个", "中", "丰", "串", "丸", "丹", "主", "丼", "丿", "乂", "乃", "久", "之", "乍", "乎", "乏", "乕", "乖", "乗", "乘", "乙", "九", "乞", "也", "乢", "乱", "乳", "乾", "亀", "亂", "了", "予", "争", "事", "二", "于", "云", "互", "五", "井", "亘", "亙", "些", "亜", "亞", "亟", "亡", "亢", "交", "亥", "亦", "亨", "享", "京", "亭", "亮", "亳", "亶", "人", "亻", "什", "仁", "仄", "仆", "仇", "今", "介", "仍", "从", "仏", "仔", "仕", "他", "仗", "付", "仙", "仝", "仞", "代", "令", "以", "仭", "仮", "仰", "仲", "仵", "件", "价", "任", "份", "仿", "企", "伉", "伊", "伋", "伍", "伎", "伏", "伐", "休", "会", "伜", "伝", "伯", "估", "伴", "伶", "伸", "伺", "似", "伽", "佃", "但", "佇", "位", "低", "住", "佐", "佑", "体", "何", "佗", "余", "佚", "佛", "作", "佝", "佞", "佟", "佤", "佩", "佯", "佳", "併", "佶", "佻", "佼", "使", "侃", "來", "侈", "例", "侍", "侏", "侑", "侖", "侗", "侘", "供", "依", "侠", "価", "侫", "侭", "侮", "侯", "侵", "侶", "便", "係", "促", "俄", "俅", "俊", "俎", "俐", "俑", "俔", "俗", "俘", "俚", "俛", "保", "俟", "俠", "信", "俣", "俤", "俥", "修", "俯", "俱", "俳", "俵", "俶", "俸", "俺", "俾", "倂", "倅", "倆", "倉", "個", "倍", "倏", "們", "倒", "倔", "倖", "候", "倚", "借", "倣", "値", "倥", "倦", "倨", "倩", "倪", "倫", "倭", "倶", "倹", "倻", "偃", "假", "偈", "偉", "偏", "偐", "偕", "偖", "做", "停", "健", "偬", "偲", "側", "偵", "偶", "偸", "偽", "傀", "傅", "傍", "傑", "傕", "傘", "備", "傚", "傪", "催", "傭", "傲", "傳", "傴", "債", "傷", "傾", "僂", "僅", "僉", "僊", "働", "像", "僑", "僔", "僕", "僖", "僚", "僞", "僣", "僥", "僧", "僭", "僮", "價", "僻", "儀", "儁", "儂", "億", "儉", "儋", "儒", "儔", "儕", "儘", "儚", "儛", "儞", "償", "儡", "優", "儲", "儷", "儺", "儻", "儼", "兀", "允", "元", "兄", "充", "兆", "兇", "先", "光", "兊", "克", "兌", "免", "兎", "児", "兒", "兔", "兕", "兗", "党", "兜", "兢", "入", "內", "全", "兩", "兪", "八", "公", "六", "兮", "共", "兵", "其", "具", "典", "兼", "冀", "内", "円", "冉", "冊", "册", "再", "冐", "冑", "冒", "冕", "冗", "写", "冠", "冢", "冤", "冥", "冦", "冨", "冩", "冪", "冬", "冰", "冱", "冲", "决", "冴", "况", "冶", "冷", "冼", "冽", "凄", "准", "凉", "凋", "凌", "凍", "凖", "凛", "凜", "凝", "凞", "几", "凡", "処", "凧", "凩", "凪", "凭", "凮", "凰", "凱", "凶", "凸", "凹", "出", "函", "凾", "刀", "刃", "刄", "分", "切", "刈", "刊", "刋", "刎", "刑", "刕", "列", "初", "判", "別", "利", "刪", "刮", "到", "刳", "制", "刷", "券", "刹", "刺", "刻", "剃", "剄", "則", "削", "剋", "剌", "前", "剔", "剖", "剛", "剝", "剣", "剤", "剥", "剪", "副", "剰", "剱", "割", "剴", "創", "剽", "剿", "劃", "劇", "劈", "劉", "劍", "劒", "劔", "力", "功", "加", "劣", "助", "努", "劫", "劬", "劭", "励", "労", "効", "劻", "劾", "勁", "勃", "勅", "勇", "勉", "勒", "動", "勘", "務", "勛", "勝", "勞", "募", "勢", "勣", "勤", "勧", "勰", "勲", "勳", "勵", "勸", "勺", "勾", "勿", "匀", "匁", "匂", "包", "匆", "匈", "匍", "匏", "匐", "匕", "化", "北", "匙", "匝", "匠", "匡", "匣", "匪", "匯", "匱", "匹", "区", "医", "匾", "匿", "區", "十", "千", "卅", "卆", "升", "午", "卉", "半", "卍", "卑", "卒", "卓", "協", "南", "単", "博", "卜", "卞", "占", "卣", "卦", "卩", "卮", "卯", "印", "危", "即", "却", "卵", "卷", "卸", "卻", "卽", "卿", "厄", "厓", "厖", "厘", "厚", "原", "厠", "厥", "厦", "厨", "厩", "厭", "厰", "厲", "厳", "厷", "去", "参", "參", "又", "叉", "及", "友", "双", "反", "収", "叔", "取", "受", "叙", "叛", "叟", "叡", "叢", "口", "古", "句", "叩", "只", "叫", "召", "叭", "叮", "可", "台", "叱", "史", "右", "叶", "号", "司", "叺", "吁", "吃", "各", "合", "吉", "吊", "同", "名", "后", "吏", "吐", "向", "君", "吝", "吞", "吟", "吠", "否", "吩", "含", "听", "吶", "吸", "吹", "吻", "吼", "吽", "吾", "呀", "呂", "呆", "呈", "呉", "告", "呍", "呑", "呕", "呟", "周", "呪", "呰", "呱", "味", "呵", "呶", "呷", "呻", "呼", "命", "咀", "咄", "咆", "咈", "咋", "和", "咎", "咏", "咐", "咒", "咜", "咤", "咥", "咨", "咩", "咫", "咬", "咯", "咲", "咳", "咸", "咽", "哀", "品", "哄", "哆", "哇", "哈", "哉", "員", "哥", "哨", "哭", "哮", "哲", "哺", "哿", "唄", "唆", "唇", "唎", "唐", "唔", "唖", "售", "唯", "唱", "唳", "唸", "唹", "唼", "唾", "啀", "啄", "商", "問", "啐", "啓", "啖", "啜", "啞", "啣", "啻", "啼", "啾", "喀", "喃", "善", "喆", "喇", "喉", "喊", "喋", "喎", "喘", "喙", "喚", "喜", "喝", "喟", "喧", "喨", "喩", "喪", "喫", "喬", "單", "喰", "営", "嗄", "嗅", "嗇", "嗔", "嗚", "嗜", "嗟", "嗣", "嗤", "嗷", "嗽", "嗾", "嘆", "嘉", "嘎", "嘔", "嘖", "嘗", "嘘", "嘩", "嘯", "嘱", "嘲", "嘴", "嘶", "嘸", "噂", "噉", "噌", "噎", "噓", "噛", "噤", "噦", "器", "噪", "噫", "噬", "噯", "噲", "噴", "噶", "噸", "噺", "嚀", "嚆", "嚇", "嚊", "嚏", "嚔", "嚙", "嚠", "嚢", "嚥", "嚭", "嚮", "嚴", "嚶", "嚼", "囀", "囁", "囂", "囃", "囈", "囊", "囎", "囓", "囗", "囘", "囚", "四", "回", "因", "団", "囮", "困", "囲", "図", "囹", "固", "国", "囿", "圀", "圃", "圄", "國", "圍", "圏", "園", "圓", "圖", "團", "圜", "土", "圦", "圧", "在", "圭", "地", "圳", "圷", "圻", "址", "坂", "均", "坊", "坍", "坎", "坏", "坐", "坑", "坡", "坤", "坦", "坨", "坩", "坪", "垂", "垈", "型", "垓", "垜", "垠", "垢", "垣", "垰", "垸", "埃", "埋", "城", "埒", "埓", "埔", "埜", "域", "埠", "埣", "埤", "埴", "埵", "執", "培", "基", "埼", "堀", "堂", "堅", "堆", "堊", "堕", "堙", "堝", "堡", "堤", "堪", "堯", "堰", "報", "場", "堵", "堺", "塀", "塁", "塊", "塋", "塌", "塑", "塒", "塔", "塗", "塘", "塙", "塚", "塞", "塡", "塢", "塩", "填", "塰", "塲", "塵", "塹", "塼", "塾", "境", "墅", "墉", "墓", "増", "墜", "增", "墟", "墨", "墳", "墺", "墻", "墾", "壁", "壅", "壇", "壊", "壌", "壑", "壒", "壓", "壕", "壘", "壙", "壜", "壟", "壤", "士", "壬", "壮", "壯", "声", "壱", "売", "壷", "壹", "壺", "壻", "壼", "壽", "変", "夋", "夏", "夔", "夕", "外", "夙", "多", "夛", "夜", "夢", "夥", "大", "天", "太", "夫", "夬", "夭", "央", "失", "夷", "夾", "奄", "奇", "奈", "奉", "奎", "奏", "契", "奔", "奕", "套", "奘", "奚", "奝", "奠", "奢", "奥", "奧", "奨", "奪", "奬", "奭", "奮", "女", "奴", "奶", "奸", "好", "妁", "如", "妃", "妄", "妊", "妍", "妓", "妖", "妙", "妣", "妥", "妨", "妬", "妲", "妹", "妺", "妻", "妾", "姆", "姉", "始", "姐", "姑", "姒", "姓", "委", "姙", "姚", "姜", "姣", "姥", "姦", "姧", "姨", "姪", "姫", "姶", "姸", "姻", "姿", "威", "娃", "娍", "娑", "娘", "娜", "娟", "娠", "娥", "娩", "娯", "娵", "娶", "娼", "婀", "婁", "婆", "婉", "婚", "婢", "婣", "婦", "婪", "婬", "婿", "媄", "媒", "媚", "媛", "媧", "媳", "媼", "媽", "媾", "嫁", "嫂", "嫄", "嫉", "嫋", "嫌", "嫐", "嫖", "嫗", "嫡", "嫣", "嫦", "嫩", "嫵", "嫺", "嬉", "嬋", "嬌", "嬖", "嬢", "嬥", "嬪", "嬬", "嬰", "嬲", "嬴", "嬶", "孀", "孁", "孃", "孅", "孌", "子", "孑", "孔", "孕", "字", "存", "孚", "孛", "孜", "孝", "孟", "季", "孤", "学", "孩", "孫", "孰", "孵", "學", "孺", "孽", "宀", "宅", "宇", "守", "安", "宋", "完", "宍", "宏", "宓", "宕", "宗", "官", "宙", "定", "宛", "宜", "宝", "実", "客", "宣", "室", "宥", "宦", "宮", "宰", "害", "宴", "宵", "家", "宸", "容", "宿", "寂", "寃", "寄", "寅", "密", "寇", "富", "寐", "寒", "寓", "寔", "寛", "寝", "寞", "察", "寡", "寢", "寤", "寥", "實", "寧", "寨", "審", "寫", "寮", "寰", "寳", "寵", "寶", "寸", "寺", "対", "寿", "封", "専", "射", "将", "將", "專", "尉", "尊", "尋", "對", "導", "小", "少", "尓", "尖", "尚", "尠", "尤", "尨", "尩", "尫", "尭", "就", "尸", "尹", "尺", "尻", "尼", "尽", "尾", "尿", "局", "屁", "居", "屈", "届", "屋", "屍", "屎", "屏", "屐", "屑", "屓", "展", "屛", "属", "屠", "屡", "屢", "層", "履", "屬", "屮", "屯", "山", "屹", "岌", "岐", "岑", "岡", "岨", "岩", "岫", "岬", "岱", "岳", "岷", "岸", "岺", "岻", "峅", "峙", "峠", "峡", "峨", "峩", "峪", "峭", "峯", "峰", "峴", "島", "峻", "峽", "崇", "崋", "崎", "崑", "崔", "崕", "崖", "崗", "崘", "崙", "崛", "崟", "崧", "崩", "嵆", "嵋", "嵌", "嵎", "嵐", "嵜", "嵩", "嵬", "嵯", "嶂", "嶄", "嶇", "嶋", "嶌", "嶠", "嶮", "嶲", "嶺", "嶼", "嶽", "巉", "巌", "巍", "巎", "巒", "巓", "巖", "川", "州", "巡", "巢", "巣", "工", "左", "巧", "巨", "巫", "差", "己", "已", "巳", "巴", "巷", "巻", "巽", "巾", "市", "布", "帆", "希", "帑", "帕", "帖", "帙", "帚", "帛", "帝", "帥", "師", "席", "帮", "帯", "帰", "帳", "帶", "帷", "常", "帽", "幀", "幄", "幅", "幇", "幌", "幎", "幔", "幕", "幖", "幗", "幘", "幟", "幡", "幢", "幣", "幫", "干", "平", "年", "并", "幷", "幸", "幹", "幻", "幼", "幽", "幾", "庁", "広", "庄", "庇", "床", "序", "底", "庖", "店", "庚", "府", "庠", "度", "座", "庫", "庭", "庵", "庶", "康", "庸", "庾", "廁", "廂", "廃", "廈", "廉", "廊", "廋", "廏", "廐", "廓", "廖", "廚", "廛", "廟", "廠", "廡", "廢", "廣", "廩", "廬", "廰", "廳", "廴", "延", "廷", "廸", "建", "廻", "廼", "廿", "弁", "弄", "弉", "弊", "弋", "弌", "式", "弐", "弑", "弓", "弔", "引", "弖", "弗", "弘", "弛", "弟", "弥", "弦", "弧", "弩", "弭", "弯", "弱", "弴", "張", "強", "弼", "弾", "彅", "彈", "彊", "彌", "彎", "当", "彗", "彙", "彝", "彡", "形", "彣", "彤", "彦", "彧", "彩", "彪", "彫", "彬", "彭", "彰", "影", "彳", "彷", "役", "彼", "彿", "往", "征", "徂", "徃", "径", "待", "徇", "徊", "律", "後", "徐", "徒", "従", "得", "徘", "徙", "從", "徠", "御", "徧", "徨", "復", "循", "徭", "微", "徳", "徴", "徵", "德", "徹", "徽", "心", "必", "忉", "忌", "忍", "忖", "志", "忘", "忙", "応", "忝", "忠", "忤", "忩", "快", "忯", "忰", "忱", "念", "忸", "忽", "忿", "怏", "怐", "怒", "怕", "怖", "怙", "怛", "怜", "思", "怠", "怡", "急", "性", "怨", "怩", "怪", "怫", "怯", "怱", "怺", "恁", "恂", "恃", "恆", "恊", "恋", "恍", "恐", "恒", "恕", "恙", "恚", "恟", "恠", "恢", "恣", "恤", "恥", "恨", "恩", "恪", "恫", "恬", "恭", "息", "恰", "恵", "悃", "悄", "悅", "悉", "悋", "悌", "悍", "悔", "悖", "悚", "悛", "悝", "悟", "悠", "患", "悦", "悧", "悩", "悪", "悰", "悲", "悳", "悴", "悵", "悶", "悸", "悼", "悽", "情", "惇", "惑", "惓", "惔", "惕", "惘", "惚", "惜", "惟", "惠", "惡", "惣", "惧", "惨", "惰", "惱", "想", "惴", "惶", "惹", "惺", "惻", "愁", "愆", "愈", "愉", "愍", "愎", "意", "愕", "愚", "愛", "感", "愡", "愧", "愨", "愬", "愴", "愷", "愼", "愾", "愿", "慂", "慄", "慇", "慈", "慊", "態", "慌", "慍", "慎", "慓", "慕", "慘", "慙", "慚", "慟", "慢", "慣", "慥", "慧", "慨", "慫", "慮", "慰", "慳", "慴", "慶", "慷", "慾", "憂", "憊", "憍", "憎", "憐", "憑", "憔", "憖", "憙", "憚", "憤", "憧", "憩", "憫", "憬", "憮", "憲", "憶", "憺", "憾", "懃", "懆", "懇", "懈", "應", "懊", "懋", "懌", "懐", "懣", "懦", "懲", "懴", "懶", "懷", "懸", "懺", "懼", "懽", "懾", "懿", "戀", "戈", "戉", "戊", "戌", "戍", "戎", "成", "我", "戒", "戔", "或", "戚", "戛", "戞", "戟", "戡", "戦", "戩", "截", "戮", "戯", "戰", "戲", "戴", "戸", "戻", "房", "所", "扁", "扇", "扈", "扉", "手", "才", "扎", "打", "払", "托", "扛", "扞", "扠", "扣", "扨", "扮", "扱", "扶", "批", "扼", "承", "技", "抂", "抃", "抄", "抉", "把", "抑", "抒", "抓", "抔", "投", "抖", "抗", "折", "抛", "抜", "択", "披", "抬", "抱", "抵", "抹", "押", "抽", "拂", "担", "拆", "拇", "拈", "拉", "拌", "拍", "拏", "拐", "拒", "拓", "拔", "拕", "拗", "拘", "拙", "招", "拜", "拝", "拠", "拡", "括", "拭", "拮", "拯", "拱", "拳", "拵", "拶", "拷", "拼", "拾", "拿", "持", "挂", "指", "挈", "按", "挊", "挌", "挍", "挐", "挑", "挘", "挙", "挟", "挨", "挫", "振", "挵", "挹", "挺", "挽", "挾", "挿", "捉", "捌", "捍", "捏", "捐", "捕", "捗", "捜", "捥", "捧", "捨", "捩", "据", "捲", "捶", "捷", "捺", "捻", "掃", "授", "掉", "掌", "掏", "排", "掖", "掘", "掛", "掟", "掠", "採", "探", "掣", "接", "控", "推", "掩", "措", "掬", "掲", "掴", "掻", "掾", "揃", "揄", "揆", "揉", "描", "提", "插", "揖", "揚", "換", "握", "揣", "揭", "揮", "援", "揶", "揷", "揺", "搆", "損", "搏", "搔", "搖", "搗", "搜", "搦", "搨", "搩", "搬", "搭", "携", "搾", "摂", "摑", "摘", "摠", "摧", "摩", "摭", "摯", "摶", "摸", "摹", "摺", "撃", "撈", "撒", "撓", "撕", "撚", "撝", "撞", "撤", "撥", "撩", "撫", "播", "撮", "撰", "撲", "撹", "撻", "撼", "撾", "撿", "擁", "擂", "擅", "擇", "操", "擒", "擔", "擘", "據", "擠", "擡", "擢", "擣", "擤", "擦", "擧", "擬", "擯", "擱", "擲", "擴", "擺", "擻", "擽", "擾", "攀", "攅", "攘", "攝", "攣", "攪", "攫", "攬", "支", "攴", "攵", "收", "攷", "攸", "改", "攻", "放", "政", "故", "效", "敍", "敎", "敏", "救", "敕", "敖", "敗", "教", "敝", "敢", "散", "敦", "敧", "敬", "数", "敲", "整", "敵", "敷", "數", "斂", "斃", "文", "斉", "斌", "斎", "斐", "斑", "斗", "料", "斛", "斜", "斟", "斡", "斤", "斥", "斧", "斫", "斬", "断", "斯", "新", "斷", "方", "於", "施", "旁", "旄", "旅", "旆", "旋", "旌", "族", "旒", "旗", "旛", "无", "既", "日", "旦", "旧", "旨", "早", "旬", "旭", "旱", "旺", "旻", "旼", "昂", "昆", "昇", "昉", "昊", "昌", "明", "昏", "易", "昔", "昕", "星", "映", "春", "昧", "昨", "昭", "是", "昱", "昴", "昵", "昶", "昺", "昼", "晁", "時", "晃", "晄", "晉", "晋", "晏", "晒", "晝", "晟", "晢", "晤", "晦", "晧", "晨", "晩", "普", "景", "晰", "晴", "晶", "晷", "智", "暁", "暇", "暈", "暉", "暎", "暑", "暖", "暗", "暘", "暝", "暠", "暢", "暦", "暫", "暮", "暴", "暸", "暹", "暻", "暼", "暾", "曁", "曄", "曇", "曈", "曉", "曖", "曙", "曜", "曝", "曠", "曦", "曩", "曰", "曲", "曳", "更", "曵", "曷", "書", "曹", "曺", "曻", "曼", "曽", "曾", "替", "最", "會", "朅", "月", "有", "朋", "服", "朔", "朕", "朖", "朗", "望", "朝", "期", "朦", "朧", "木", "未", "末", "本", "札", "朮", "朱", "朴", "朶", "朸", "机", "朽", "杆", "杈", "杉", "李", "杏", "材", "村", "杓", "杖", "杙", "杜", "杞", "束", "杠", "条", "杢", "杣", "杤", "来", "杭", "杮", "杯", "杰", "東", "杲", "杳", "杵", "杷", "杼", "松", "板", "枇", "枉", "枋", "枌", "析", "枕", "林", "枘", "枚", "果", "枝", "枠", "枡", "枢", "枯", "枲", "枳", "枴", "架", "枷", "枸", "枹", "枻", "柁", "柄", "柊", "柏", "某", "柑", "染", "柔", "柘", "柚", "柝", "柞", "柢", "柩", "柬", "柯", "柱", "柳", "柴", "柵", "査", "柾", "柿", "栂", "栃", "栄", "栓", "栖", "栗", "栞", "校", "栢", "栩", "株", "栫", "栱", "栲", "栴", "核", "根", "格", "栽", "栾", "桀", "桁", "桂", "桃", "桅", "框", "案", "桎", "桐", "桑", "桒", "桓", "桔", "桛", "桜", "桝", "桟", "档", "桧", "桴", "桶", "桿", "梁", "梃", "梅", "梏", "梓", "梔", "梗", "梛", "條", "梟", "梠", "梢", "梦", "梧", "梨", "梭", "梯", "械", "梱", "梲", "梳", "梵", "梶", "梼", "棃", "棄", "棉", "棊", "棋", "棍", "棐", "棒", "棕", "棖", "棗", "棘", "棚", "棟", "棠", "棡", "棣", "棧", "棭", "森", "棰", "棱", "棲", "棹", "棺", "椀", "椅", "椋", "植", "椎", "椏", "椒", "椙", "椚", "椛", "検", "椥", "椨", "椰", "椴", "椵", "椹", "椽", "椿", "楂", "楊", "楓", "楔", "楕", "楚", "楝", "楞", "楠", "楡", "楢", "楣", "楨", "楪", "楫", "業", "楮", "楯", "楳", "極", "楷", "楸", "楹", "楼", "楽", "榀", "概", "榊", "榎", "榑", "榔", "榕", "榛", "榜", "榧", "榮", "榲", "榴", "榻", "榾", "槁", "槃", "槇", "槊", "構", "槌", "槍", "槎", "槐", "槓", "様", "槙", "槧", "槨", "槫", "槲", "槵", "槹", "槻", "槽", "槿", "樂", "樅", "樊", "樋", "樒", "樓", "樗", "標", "樞", "樟", "模", "樣", "権", "横", "樫", "樵", "樸", "樹", "樺", "樽", "橄", "橅", "橇", "橈", "橋", "橘", "橙", "橛", "機", "橡", "橢", "橫", "橳", "橿", "檀", "檄", "檍", "檎", "檐", "檔", "檗", "檜", "檞", "檠", "檢", "檣", "檪", "檫", "檬", "檮", "檳", "檸", "檻", "櫂", "櫃", "櫑", "櫓", "櫚", "櫛", "櫞", "櫟", "櫨", "櫪", "櫬", "櫺", "櫻", "欄", "欅", "權", "欒", "欖", "欝", "欠", "次", "欣", "欧", "欲", "欵", "欷", "欹", "欺", "欽", "款", "歃", "歇", "歌", "歎", "歐", "歓", "歔", "歙", "歛", "歟", "歡", "止", "正", "此", "步", "武", "歩", "歪", "歯", "歳", "歴", "歷", "歸", "死", "歿", "殃", "殄", "殆", "殉", "殊", "残", "殖", "殘", "殞", "殤", "殪", "殯", "殱", "殲", "殳", "殴", "段", "殷", "殺", "殻", "殼", "殿", "毀", "毅", "毉", "毋", "母", "毎", "每", "毒", "毓", "比", "毖", "毗", "毘", "毛", "毟", "毫", "毬", "毮", "毯", "毳", "氈", "氏", "氐", "民", "氓", "气", "気", "氣", "水", "氵", "氷", "永", "氾", "汀", "汁", "求", "汎", "汐", "汕", "汗", "汙", "汚", "汜", "汝", "汞", "江", "池", "汪", "汰", "汲", "汳", "汴", "汶", "決", "汽", "汾", "沁", "沂", "沃", "沅", "沈", "沌", "沍", "沐", "沒", "沓", "沖", "沙", "沚", "沛", "没", "沢", "沪", "沫", "沮", "沱", "河", "沸", "油", "治", "沼", "沽", "沾", "沿", "況", "泄", "泉", "泊", "泌", "泓", "泔", "法", "泗", "泛", "泝", "泡", "波", "泣", "泥", "注", "泪", "泰", "泳", "洋", "洌", "洎", "洒", "洗", "洙", "洛", "洞", "洟", "津", "洩", "洪", "洫", "洮", "洱", "洲", "洵", "洶", "洸", "洹", "活", "洽", "派", "流", "浄", "浅", "浙", "浚", "浜", "浣", "浦", "浩", "浪", "浬", "浮", "浴", "海", "浸", "涂", "涅", "涇", "消", "涌", "涎", "涓", "涕", "涙", "涛", "涜", "涪", "涯", "液", "涵", "涸", "涼", "涿", "淀", "淄", "淅", "淆", "淇", "淋", "淑", "淘", "淙", "淚", "淛", "淝", "淞", "淡", "淤", "淦", "淨", "淪", "淫", "淮", "深", "淳", "淵", "混", "淹", "淺", "添", "淼", "清", "渇", "済", "渉", "渋", "渓", "渕", "渙", "渚", "減", "渝", "渟", "渠", "渡", "渣", "渤", "渥", "渦", "渧", "温", "渫", "測", "渭", "港", "游", "渺", "渾", "湃", "湄", "湊", "湍", "湎", "湑", "湖", "湘", "湛", "湣", "湧", "湫", "湮", "湯", "湲", "湾", "湿", "満", "溂", "溌", "源", "準", "溘", "溜", "溝", "溟", "溢", "溥", "溪", "溫", "溯", "溲", "溶", "溷", "溺", "滂", "滄", "滅", "滇", "滉", "滋", "滌", "滎", "滑", "滓", "滔", "滕", "滙", "滝", "滞", "滬", "滲", "滴", "滸", "滾", "滿", "漁", "漂", "漆", "漉", "漏", "漑", "漓", "演", "漕", "漠", "漢", "漣", "漪", "漫", "漬", "漱", "漲", "漳", "漸", "漾", "漿", "潁", "潅", "潑", "潔", "潘", "潙", "潜", "潞", "潟", "潤", "潦", "潭", "潮", "潯", "潰", "潴", "潸", "潺", "潼", "潾", "澀", "澁", "澂", "澄", "澆", "澈", "澎", "澗", "澠", "澡", "澣", "澤", "澪", "澱", "澳", "澶", "澹", "激", "濁", "濂", "濃", "濊", "濕", "濘", "濛", "濟", "濠", "濡", "濤", "濫", "濮", "濯", "濱", "濳", "濵", "濶", "濹", "濾", "瀆", "瀉", "瀋", "瀏", "瀑", "瀕", "瀚", "瀛", "瀝", "瀞", "瀟", "瀦", "瀧", "瀨", "瀬", "瀰", "瀾", "灌", "灑", "灘", "灝", "灣", "灤", "火", "灯", "灰", "灸", "灼", "災", "炉", "炊", "炎", "炒", "炕", "炙", "炫", "炬", "炭", "炮", "炯", "炳", "炷", "炸", "点", "為", "炻", "烈", "烏", "烔", "烙", "烝", "烟", "烬", "烱", "烹", "烽", "焉", "焔", "焙", "焚", "焜", "無", "焦", "焰", "然", "焼", "煆", "煇", "煉", "煊", "煌", "煎", "煕", "煖", "煙", "煜", "煞", "煠", "煤", "煥", "煦", "照", "煩", "煬", "煮", "煽", "熄", "熇", "熈", "熊", "熏", "熒", "熔", "熕", "熙", "熟", "熨", "熬", "熱", "熹", "熾", "燁", "燃", "燈", "燎", "燐", "燒", "燔", "燕", "燗", "營", "燠", "燥", "燦", "燧", "燬", "燭", "燮", "燵", "燹", "燻", "燼", "燾", "燿", "爆", "爐", "爛", "爨", "爪", "爬", "爭", "爰", "爲", "爵", "父", "爸", "爹", "爺", "爻", "爼", "爽", "爾", "牀", "牆", "片", "版", "牋", "牌", "牒", "牓", "牘", "牙", "牛", "牝", "牟", "牡", "牢", "牧", "物", "牯", "牲", "牴", "特", "牽", "牾", "犀", "犁", "犂", "犇", "犍", "犒", "犠", "犢", "犧", "犬", "犯", "状", "狀", "狂", "狃", "狄", "狆", "狎", "狐", "狒", "狗", "狙", "狛", "狡", "狢", "狩", "独", "狭", "狷", "狸", "狹", "狼", "狽", "猊", "猖", "猙", "猛", "猜", "猝", "猟", "猥", "猨", "猩", "猪", "猫", "献", "猯", "猴", "猶", "猷", "猹", "猾", "猿", "獄", "獅", "獏", "獒", "獗", "獣", "獦", "獨", "獪", "獰", "獲", "獵", "獸", "獺", "玄", "玅", "率", "玉", "王", "玕", "玖", "玘", "玟", "玩", "玫", "玲", "玳", "玷", "玻", "珀", "珂", "珈", "珉", "珊", "珍", "珎", "珞", "珠", "珥", "珩", "珪", "班", "珮", "現", "球", "琅", "理", "琉", "琊", "琛", "琢", "琥", "琦", "琨", "琪", "琫", "琬", "琮", "琰", "琲", "琳", "琴", "琵", "琶", "琺", "瑀", "瑁", "瑇", "瑕", "瑗", "瑙", "瑚", "瑛", "瑜", "瑞", "瑟", "瑠", "瑣", "瑤", "瑩", "瑪", "瑫", "瑯", "瑰", "瑳", "瑶", "瑾", "璃", "璇", "璈", "璉", "璋", "璐", "璘", "璜", "璞", "璟", "璣", "璧", "璫", "環", "璽", "璿", "瓊", "瓏", "瓔", "瓚", "瓜", "瓠", "瓢", "瓣", "瓦", "瓩", "瓮", "瓲", "瓶", "瓷", "甃", "甄", "甌", "甍", "甎", "甑", "甕", "甗", "甘", "甚", "甜", "生", "産", "甥", "甦", "用", "甪", "甫", "甬", "田", "由", "甲", "申", "男", "甸", "町", "画", "畊", "界", "畏", "畑", "畔", "留", "畚", "畜", "畝", "畠", "畢", "畤", "略", "畦", "畧", "番", "畫", "畭", "畯", "異", "畳", "畴", "當", "畷", "畸", "畿", "疆", "疇", "疊", "疋", "疎", "疏", "疑", "疔", "疚", "疝", "疣", "疥", "疫", "疱", "疲", "疳", "疵", "疸", "疹", "疼", "疽", "疾", "痂", "痃", "病", "症", "痍", "痎", "痒", "痔", "痕", "痘", "痙", "痛", "痞", "痢", "痣", "痤", "痩", "痰", "痲", "痳", "痴", "痺", "痼", "痾", "痿", "瘀", "瘁", "瘋", "瘍", "瘖", "瘙", "瘞", "瘠", "瘡", "瘢", "瘤", "瘦", "瘧", "瘭", "瘰", "瘳", "瘴", "瘻", "療", "癆", "癇", "癈", "癋", "癌", "癒", "癖", "癘", "癜", "癡", "癢", "癧", "癩", "癪", "癬", "癭", "癰", "癲", "癸", "発", "登", "發", "白", "百", "皃", "的", "皆", "皇", "皈", "皋", "皎", "皐", "皓", "皕", "皖", "皙", "皚", "皮", "皰", "皴", "皷", "皸", "皹", "皺", "皿", "盂", "盃", "盆", "盈", "盉", "益", "盒", "盔", "盖", "盗", "盛", "盜", "盞", "盟", "盡", "監", "盤", "盥", "盦", "盧", "盪", "目", "盱", "盲", "直", "相", "盻", "盼", "盾", "省", "眄", "眇", "眈", "眉", "看", "県", "眙", "眛", "眞", "真", "眠", "眥", "眦", "眩", "眶", "眷", "眸", "眺", "眼", "着", "睛", "睜", "睡", "睢", "督", "睥", "睦", "睨", "睫", "睹", "睺", "睾", "睿", "瞀", "瞋", "瞑", "瞞", "瞠", "瞥", "瞬", "瞭", "瞰", "瞳", "瞶", "瞻", "瞼", "瞽", "瞿", "矍", "矗", "矛", "矜", "矢", "矣", "知", "矧", "矩", "短", "矮", "矯", "石", "砂", "砌", "砒", "研", "砕", "砖", "砥", "砦", "砧", "砭", "砲", "破", "砺", "硅", "硏", "硝", "硨", "硫", "硬", "确", "硯", "硴", "硼", "碁", "碆", "碇", "碌", "碍", "碎", "碑", "碓", "碕", "碗", "碣", "碧", "碩", "碪", "確", "碾", "磁", "磊", "磋", "磌", "磐", "磔", "磚", "磧", "磨", "磬", "磯", "磲", "磴", "磽", "礁", "礎", "礑", "礒", "礙", "礦", "礪", "礫", "礬", "礮", "示", "礼", "社", "祀", "祁", "祅", "祆", "祇", "祈", "祉", "祐", "祓", "祕", "祖", "祗", "祚", "祛", "祝", "神", "祟", "祠", "祢", "祥", "票", "祭", "祷", "祺", "祿", "禀", "禁", "禄", "禅", "禊", "禍", "禎", "福", "禛", "禝", "禦", "禧", "禪", "禮", "禰", "禱", "禴", "禹", "禺", "禽", "禾", "禿", "秀", "私", "秉", "秋", "种", "科", "秒", "秕", "秘", "秞", "租", "秡", "秣", "秤", "秦", "秧", "秩", "称", "移", "稀", "稈", "程", "稍", "税", "稔", "稗", "稙", "稚", "稜", "稟", "稠", "種", "稱", "稲", "稷", "稹", "稻", "稼", "稽", "稿", "穀", "穂", "穆", "穉", "積", "穎", "穏", "穐", "穗", "穡", "穢", "穣", "穫", "穰", "穴", "穵", "究", "穹", "空", "穽", "穿", "突", "窃", "窄", "窈", "窒", "窓", "窕", "窖", "窗", "窘", "窟", "窠", "窩", "窪", "窬", "窮", "窯", "窰", "窶", "窺", "窿", "竃", "竄", "竅", "竇", "竈", "竊", "立", "竎", "站", "竜", "竝", "竟", "章", "竢", "竣", "童", "竦", "竪", "竫", "竭", "端", "競", "竸", "竹", "竺", "竿", "笄", "笈", "笊", "笋", "笏", "笑", "笘", "笙", "笛", "笞", "笠", "笥", "符", "笨", "第", "笮", "笵", "笹", "筅", "筆", "筈", "等", "筋", "筌", "筍", "筏", "筐", "筑", "筒", "答", "策", "筝", "筠", "筥", "筧", "筬", "筭", "筮", "筰", "筱", "筵", "筺", "筿", "箆", "箇", "箋", "箍", "箏", "箒", "箔", "箕", "算", "箙", "箚", "箜", "箝", "箞", "管", "箪", "箭", "箱", "箴", "箸", "節", "篁", "範", "篆", "篇", "築", "篋", "篌", "篏", "篙", "篝", "篠", "篤", "篥", "篦", "篩", "篭", "篳", "篶", "篷", "簀", "簁", "簃", "簇", "簋", "簍", "簑", "簒", "簓", "簔", "簗", "簞", "簟", "簠", "簡", "簣", "簧", "簪", "簫", "簳", "簶", "簷", "簸", "簽", "簾", "簿", "籀", "籃", "籌", "籍", "籏", "籐", "籔", "籖", "籙", "籟", "籠", "籤", "籬", "米", "籾", "粂", "粃", "粉", "粋", "粍", "粏", "粒", "粕", "粗", "粘", "粛", "粟", "粡", "粢", "粤", "粥", "粦", "粧", "粮", "粱", "粲", "粳", "粹", "粼", "粽", "精", "糀", "糂", "糅", "糊", "糒", "糕", "糖", "糜", "糝", "糞", "糟", "糠", "糢", "糧", "糯", "糲", "糴", "糶", "糸", "糺", "系", "糾", "紀", "紂", "約", "紅", "紆", "紇", "紈", "紊", "紋", "納", "紐", "紒", "純", "紗", "紘", "紙", "級", "紛", "紜", "素", "紡", "索", "紫", "紬", "紮", "累", "細", "紲", "紳", "紹", "紺", "絁", "終", "絃", "組", "絅", "絆", "経", "絎", "絏", "結", "絓", "絖", "絛", "絜", "絞", "絡", "絢", "絣", "給", "絨", "絮", "統", "絲", "絳", "絵", "絶", "絹", "絽", "綉", "綏", "經", "継", "続", "綛", "綜", "綟", "綠", "綢", "綦", "綫", "綬", "維", "綮", "綯", "綰", "綱", "網", "綴", "綵", "綸", "綺", "綻", "綽", "綾", "綿", "緂", "緇", "緊", "緋", "総", "緑", "緒", "緖", "緘", "線", "緜", "緝", "緞", "締", "緡", "緣", "編", "緩", "緬", "緯", "緲", "練", "緻", "縁", "縄", "縅", "縉", "縊", "縋", "縑", "縒", "縕", "縛", "縞", "縟", "縢", "縣", "縦", "縫", "縬", "縮", "縱", "縲", "縵", "縷", "縹", "縺", "縻", "總", "績", "繁", "繃", "繅", "繆", "繇", "繊", "繋", "繍", "織", "繕", "繙", "繚", "繝", "繞", "繡", "繧", "繩", "繪", "繫", "繭", "繰", "繹", "繻", "繼", "繽", "纂", "纈", "纉", "續", "纍", "纏", "纐", "纒", "纓", "纔", "纛", "纜", "缶", "缺", "罄", "罅", "罌", "罎", "罐", "罔", "罕", "罘", "罠", "罡", "罣", "罨", "罩", "罪", "罫", "置", "罰", "署", "罵", "罷", "罸", "罹", "羂", "羅", "羆", "羇", "羈", "羊", "羌", "美", "羚", "羞", "羣", "群", "羨", "義", "羮", "羯", "羲", "羸", "羹", "羽", "羿", "翁", "翅", "翆", "翊", "翌", "翎", "習", "翔", "翕", "翛", "翟", "翠", "翡", "翦", "翩", "翫", "翰", "翳", "翹", "翻", "翼", "耀", "老", "考", "耄", "者", "耆", "耋", "而", "耐", "耒", "耕", "耗", "耘", "耙", "耡", "耤", "耨", "耳", "耶", "耻", "耽", "耿", "聃", "聆", "聊", "聖", "聘", "聚", "聞", "聟", "聡", "聢", "聨", "聯", "聰", "聱", "聲", "聳", "聴", "聶", "職", "聽", "聾", "聿", "肄", "肅", "肆", "肇", "肉", "肋", "肌", "肓", "肖", "肘", "肚", "肛", "肝", "股", "肢", "肥", "肩", "肪", "肭", "肯", "肱", "育", "肴", "肺", "胃", "胄", "胆", "背", "胎", "胖", "胚", "胛", "胝", "胞", "胡", "胤", "胥", "胯", "胱", "胴", "胸", "胼", "能", "脂", "脅", "脆", "脇", "脈", "脉", "脊", "脘", "脚", "脛", "脞", "脣", "脩", "脯", "脱", "脳", "脹", "脾", "腆", "腊", "腋", "腎", "腐", "腑", "腓", "腔", "腕", "腟", "腥", "腦", "腫", "腮", "腰", "腱", "腴", "腸", "腹", "腺", "腿", "膀", "膂", "膃", "膅", "膈", "膊", "膏", "膓", "膕", "膚", "膜", "膝", "膠", "膣", "膨", "膩", "膰", "膳", "膵", "膸", "膺", "膻", "膽", "膾", "膿", "臀", "臂", "臆", "臈", "臉", "臍", "臏", "臑", "臓", "臘", "臙", "臚", "臟", "臠", "臣", "臥", "臧", "臨", "自", "臬", "臭", "至", "致", "臺", "臼", "臾", "舁", "舂", "舅", "與", "興", "舉", "舊", "舌", "舍", "舎", "舐", "舒", "舗", "舘", "舛", "舜", "舞", "舟", "舩", "航", "舫", "般", "舲", "舳", "舵", "舶", "舷", "舸", "船", "艀", "艇", "艘", "艙", "艚", "艜", "艟", "艣", "艤", "艦", "艨", "艪", "艫", "艮", "良", "艱", "色", "艶", "艷", "艸", "艾", "芋", "芍", "芎", "芒", "芙", "芝", "芟", "芥", "芦", "芨", "芩", "芬", "芭", "芯", "花", "芳", "芷", "芸", "芹", "芻", "芽", "芾", "芿", "苅", "苑", "苒", "苓", "苔", "苕", "苗", "苛", "苜", "苞", "苟", "苡", "苣", "若", "苦", "苧", "苫", "英", "苳", "苴", "苹", "苺", "苻", "茂", "范", "茄", "茅", "茆", "茉", "茎", "茗", "茘", "茜", "茣", "茨", "茫", "茯", "茱", "茲", "茴", "茵", "茶", "茸", "茹", "荀", "荃", "草", "荊", "荏", "荒", "荔", "荘", "荳", "荵", "荷", "荻", "荼", "莅", "莆", "莉", "莊", "莎", "莒", "莓", "莕", "莖", "莘", "莚", "莞", "莟", "莠", "莢", "莧", "莨", "莩", "莪", "莫", "莱", "莵", "莽", "菀", "菁", "菅", "菇", "菊", "菌", "菎", "菓", "菖", "菘", "菜", "菟", "菠", "菩", "菫", "華", "菰", "菱", "菲", "菴", "萃", "萄", "萇", "萊", "萌", "萍", "萎", "萓", "萠", "萢", "萩", "萪", "萬", "萱", "萵", "萸", "萼", "落", "葆", "葈", "葉", "葎", "著", "葛", "葡", "葢", "董", "葦", "葩", "葫", "葬", "葭", "葯", "葱", "葵", "葷", "葺", "蒂", "蒋", "蒐", "蒔", "蒙", "蒜", "蒟", "蒡", "蒯", "蒲", "蒸", "蒻", "蒼", "蒾", "蒿", "蓀", "蓁", "蓂", "蓄", "蓆", "蓉", "蓊", "蓋", "蓍", "蓐", "蓑", "蓖", "蓙", "蓚", "蓬", "蓮", "蓯", "蓴", "蓼", "蓿", "蔀", "蔑", "蔓", "蔔", "蔕", "蔗", "蔘", "蔚", "蔟", "蔡", "蔣", "蔦", "蔬", "蔭", "蔲", "蔵", "蔽", "蕁", "蕃", "蕈", "蕉", "蕊", "蕋", "蕎", "蕗", "蕙", "蕚", "蕣", "蕨", "蕩", "蕪", "蕭", "蕷", "蕾", "薀", "薄", "薇", "薈", "薊", "薏", "薐", "薑", "薔", "薗", "薙", "薛", "薜", "薟", "薤", "薦", "薨", "薩", "薪", "薫", "薬", "薭", "薮", "薯", "薹", "薺", "藁", "藉", "藍", "藏", "藐", "藕", "藜", "藝", "藤", "藥", "藦", "藩", "藪", "藷", "藹", "藺", "藻", "藿", "蘂", "蘄", "蘆", "蘇", "蘊", "蘋", "蘐", "蘑", "蘖", "蘗", "蘚", "蘞", "蘭", "蘯", "蘿", "虎", "虐", "虔", "處", "虗", "虚", "虜", "虞", "號", "虢", "虧", "虫", "虬", "虱", "虹", "虻", "蚊", "蚋", "蚓", "蚕", "蚣", "蚤", "蚩", "蚪", "蚫", "蚯", "蚰", "蛄", "蛆", "蛇", "蛉", "蛋", "蛍", "蛎", "蛔", "蛙", "蛛", "蛞", "蛟", "蛤", "蛩", "蛭", "蛮", "蛯", "蛸", "蛹", "蛻", "蛾", "蜀", "蜂", "蜃", "蜆", "蜈", "蜉", "蜊", "蜍", "蜑", "蜒", "蜓", "蜘", "蜚", "蜜", "蜥", "蜩", "蜱", "蜴", "蜷", "蜺", "蜻", "蜾", "蜿", "蝀", "蝃", "蝉", "蝋", "蝌", "蝎", "蝓", "蝕", "蝗", "蝙", "蝟", "蝠", "蝣", "蝦", "蝨", "蝪", "蝮", "蝯", "蝴", "蝶", "蝸", "蝿", "螂", "融", "螟", "螢", "螫", "螭", "螳", "螺", "螻", "螽", "蟀", "蟄", "蟇", "蟋", "蟎", "蟐", "蟒", "蟠", "蟥", "蟬", "蟯", "蟲", "蟷", "蟹", "蟻", "蟾", "蠃", "蠅", "蠍", "蠕", "蠖", "蠟", "蠡", "蠢", "蠣", "蠧", "蠱", "蠶", "蠻", "血", "衄", "衆", "行", "衍", "衒", "術", "街", "衙", "衛", "衝", "衞", "衡", "衢", "衣", "衤", "表", "衫", "衰", "衲", "衵", "衷", "衽", "衾", "衿", "袁", "袂", "袈", "袋", "袍", "袒", "袖", "袗", "袘", "袙", "袞", "袢", "袤", "袪", "被", "袮", "袰", "袱", "袴", "袵", "袷", "袿", "裁", "裂", "裃", "裄", "装", "裏", "裒", "裔", "裕", "裘", "裙", "裛", "補", "裝", "裟", "裡", "裨", "裰", "裱", "裲", "裳", "裴", "裵", "裸", "裼", "製", "裾", "褂", "褄", "複", "褊", "褌", "褐", "褒", "褓", "褘", "褙", "褚", "褥", "褪", "褫", "褲", "褶", "褸", "褻", "襁", "襄", "襖", "襞", "襟", "襠", "襤", "襦", "襲", "襴", "襷", "襾", "西", "要", "覃", "覆", "覇", "覈", "覊", "見", "規", "覓", "視", "覗", "覘", "覚", "覡", "覦", "覧", "覩", "親", "覬", "覯", "覲", "観", "覺", "覽", "覿", "觀", "角", "觔", "觚", "觜", "觝", "解", "触", "觴", "觸", "觿", "言", "訂", "訃", "計", "訊", "訌", "討", "訓", "託", "記", "訛", "訝", "訟", "訢", "訣", "訥", "訪", "設", "許", "訳", "訴", "訶", "診", "註", "証", "詁", "詆", "詈", "詐", "詒", "詔", "評", "詛", "詞", "詠", "詡", "詢", "詣", "試", "詩", "詫", "詬", "詭", "詮", "詰", "話", "該", "詳", "詵", "詹", "詼", "誂", "誄", "誅", "誇", "誉", "誌", "認", "誑", "誓", "誕", "誘", "語", "誠", "誡", "誣", "誤", "誥", "誦", "誨", "説", "読", "誰", "課", "誹", "誼", "誾", "調", "諂", "諄", "談", "請", "諌", "諍", "諏", "諒", "論", "諗", "諚", "諛", "諜", "諡", "諢", "諤", "諦", "諧", "諫", "諭", "諮", "諱", "諳", "諶", "諷", "諸", "諺", "諾", "謀", "謁", "謂", "謄", "謌", "謎", "謐", "謔", "謖", "謗", "謙", "謚", "講", "謝", "謟", "謠", "謡", "謦", "謨", "謫", "謬", "謳", "謹", "謾", "譃", "證", "譌", "譎", "譏", "譔", "識", "譙", "譚", "譜", "警", "譫", "譬", "譯", "議", "譲", "譴", "護", "譽", "讀", "讃", "變", "讌", "讎", "讐", "讒", "讓", "讖", "讙", "讚", "讜", "谷", "谺", "谿", "豁", "豆", "豈", "豉", "豊", "豌", "豎", "豐", "豕", "豚", "象", "豨", "豪", "豫", "豬", "豳", "豸", "豹", "豺", "豼", "貂", "貅", "貉", "貌", "貎", "貔", "貘", "貝", "貞", "負", "財", "貢", "貧", "貨", "販", "貪", "貫", "責", "貮", "貯", "貰", "貴", "貶", "買", "貸", "費", "貼", "貽", "貿", "賀", "賁", "賂", "賃", "賄", "資", "賈", "賊", "賍", "賎", "賑", "賓", "賚", "賛", "賜", "賞", "賠", "賡", "賢", "賣", "賤", "賦", "質", "賭", "賺", "購", "賽", "贄", "贅", "贇", "贈", "贊", "贋", "贍", "贏", "贐", "贓", "贔", "贖", "贛", "赤", "赦", "赧", "赫", "赭", "走", "赳", "赴", "起", "趁", "超", "越", "趙", "趣", "趨", "足", "趺", "趾", "跋", "跌", "跎", "跏", "跑", "跖", "跚", "跛", "距", "跟", "跡", "跣", "跨", "跪", "跫", "路", "跳", "践", "跼", "踈", "踉", "踊", "踏", "踐", "踝", "踞", "踠", "踪", "踰", "踵", "蹂", "蹄", "蹇", "蹈", "蹉", "蹊", "蹌", "蹐", "蹕", "蹙", "蹟", "蹠", "蹣", "蹤", "蹬", "蹲", "蹴", "蹶", "蹼", "躁", "躄", "躅", "躇", "躊", "躋", "躍", "躑", "躓", "躔", "躙", "躡", "躪", "身", "躬", "躯", "躰", "躱", "躶", "躾", "軀", "軈", "車", "軋", "軌", "軍", "軒", "軛", "軟", "転", "軫", "軸", "軺", "軻", "軼", "軽", "軾", "較", "載", "輊", "輌", "輒", "輓", "輔", "輕", "輗", "輛", "輜", "輝", "輞", "輦", "輩", "輪", "輯", "輳", "輸", "輻", "輾", "輿", "轂", "轄", "轅", "轆", "轉", "轍", "轎", "轔", "轗", "轜", "轟", "轡", "轢", "轤", "辛", "辜", "辞", "辟", "辣", "辦", "辧", "辨", "辭", "辮", "辯", "辰", "辱", "農", "辶", "辷", "辺", "辻", "込", "辿", "迂", "迄", "迅", "迎", "近", "返", "迚", "迢", "迦", "迩", "迪", "迫", "迭", "迯", "述", "迴", "迷", "迸", "迹", "迺", "追", "退", "送", "适", "逃", "逅", "逆", "逈", "逋", "逍", "透", "逐", "逑", "逓", "途", "逕", "逗", "這", "通", "逝", "逞", "速", "造", "逡", "逢", "連", "逮", "週", "進", "逵", "逸", "逹", "逼", "遁", "遂", "遅", "遇", "遉", "遊", "運", "遍", "過", "遏", "遐", "遑", "道", "達", "違", "遖", "遙", "遜", "遞", "遠", "遡", "遣", "遥", "適", "遭", "遮", "遯", "遲", "遵", "遶", "遷", "選", "遺", "遼", "遽", "避", "邀", "邁", "邂", "邃", "還", "邇", "邈", "邉", "邊", "邏", "邑", "邕", "邙", "邢", "那", "邦", "邨", "邪", "邯", "邱", "邳", "邵", "邶", "邸", "邾", "郁", "郈", "郊", "郎", "郗", "郝", "郞", "郡", "郢", "部", "郭", "郯", "郵", "郷", "都", "郿", "鄂", "鄒", "鄕", "鄘", "鄙", "鄧", "鄭", "鄯", "鄰", "鄲", "鄴", "酈", "酉", "酊", "酋", "酌", "配", "酎", "酒", "酔", "酖", "酘", "酛", "酡", "酢", "酣", "酤", "酥", "酩", "酪", "酬", "酲", "酵", "酷", "酸", "醂", "醇", "醉", "醋", "醍", "醐", "醒", "醗", "醜", "醢", "醤", "醪", "醫", "醬", "醱", "醴", "醵", "醸", "醺", "釀", "釁", "釆", "采", "釈", "釉", "釋", "里", "重", "野", "量", "釐", "金", "釗", "釘", "釜", "針", "釟", "釡", "釣", "釦", "釧", "釭", "釵", "釼", "鈍", "鈎", "鈑", "鈔", "鈕", "鈞", "鈴", "鈷", "鈸", "鈺", "鈿", "鉄", "鉅", "鉇", "鉈", "鉉", "鉋", "鉏", "鉗", "鉛", "鉞", "鉢", "鉤", "鉦", "鉧", "鉱", "鉾", "銀", "銃", "銅", "銈", "銍", "銑", "銓", "銕", "銖", "銘", "銙", "銚", "銛", "銜", "銭", "銷", "銹", "鋏", "鋒", "鋤", "鋧", "鋩", "鋪", "鋭", "鋲", "鋳", "鋸", "鋹", "鋺", "鋼", "錄", "錆", "錐", "錕", "錘", "錙", "錚", "錠", "錡", "錢", "錣", "錦", "錨", "錫", "錬", "錮", "錯", "録", "錵", "錺", "錻", "鍈", "鍋", "鍍", "鍑", "鍔", "鍛", "鍜", "鍬", "鍮", "鍵", "鍼", "鍾", "鎌", "鎔", "鎖", "鎗", "鎚", "鎛", "鎧", "鎬", "鎭", "鎮", "鎰", "鎹", "鏃", "鏈", "鏑", "鏖", "鏗", "鏘", "鏝", "鏞", "鏟", "鏡", "鏢", "鏤", "鏧", "鏨", "鏱", "鏻", "鏽", "鐃", "鐐", "鐓", "鐔", "鐗", "鐘", "鐙", "鐚", "鐡", "鐫", "鐵", "鐶", "鐸", "鐺", "鑁", "鑄", "鑑", "鑒", "鑓", "鑚", "鑛", "鑞", "鑠", "鑢", "鑫", "鑰", "鑵", "鑷", "鑼", "鑽", "鑾", "鑿", "長", "镹", "門", "閂", "閃", "閇", "閉", "閊", "開", "閎", "閏", "閑", "閒", "間", "閔", "閖", "閘", "閙", "関", "閣", "閤", "閥", "閦", "閧", "閨", "閩", "閭", "閲", "閹", "閻", "閼", "閽", "閾", "闇", "闊", "闌", "闍", "闐", "闔", "闕", "闖", "闘", "關", "闡", "闢", "闥", "阜", "阡", "阨", "阪", "阮", "阯", "防", "阳", "阻", "阿", "陀", "附", "陋", "陌", "降", "限", "陖", "陘", "陛", "陜", "陝", "陞", "陟", "院", "陣", "除", "陥", "陪", "陬", "陰", "陲", "陳", "陵", "陶", "陷", "陸", "険", "陽", "隂", "隄", "隅", "隆", "隈", "隊", "隋", "隍", "階", "随", "隔", "隕", "隗", "隘", "隙", "際", "障", "隠", "隣", "隧", "隨", "險", "隱", "隲", "隴", "隷", "隸", "隹", "隺", "隻", "隼", "雀", "雁", "雄", "雅", "集", "雇", "雉", "雋", "雌", "雍", "雎", "雑", "雒", "雖", "雙", "雛", "雜", "雝", "雞", "離", "難", "雨", "雩", "雪", "雫", "雯", "雰", "雲", "零", "雷", "雹", "電", "需", "霄", "霆", "震", "霊", "霍", "霏", "霑", "霓", "霖", "霙", "霜", "霞", "霧", "霰", "露", "霹", "霽", "靁", "靂", "靄", "靆", "靈", "靉", "靑", "青", "靖", "静", "靚", "靛", "靜", "非", "靠", "靡", "面", "靤", "靨", "革", "靫", "靭", "靱", "靳", "靴", "靹", "靺", "靼", "鞁", "鞄", "鞅", "鞆", "鞋", "鞍", "鞏", "鞘", "鞜", "鞠", "鞢", "鞣", "鞦", "鞨", "鞭", "鞮", "鞳", "鞴", "鞺", "韃", "韆", "韋", "韓", "韜", "韞", "韮", "音", "韴", "韵", "韶", "韻", "響", "頁", "頂", "頃", "項", "順", "須", "頊", "頌", "頎", "頏", "預", "頑", "頒", "頓", "頗", "領", "頚", "頞", "頡", "頣", "頤", "頫", "頬", "頭", "頰", "頴", "頷", "頸", "頻", "頼", "頽", "顆", "顋", "題", "額", "顎", "顏", "顓", "顔", "顕", "顗", "願", "顚", "顛", "類", "顥", "顧", "顫", "顬", "顯", "顰", "顱", "顳", "顴", "風", "颪", "颯", "颱", "颶", "颷", "颼", "飄", "飆", "飛", "飜", "食", "飡", "飢", "飩", "飫", "飭", "飮", "飯", "飰", "飲", "飴", "飼", "飽", "飾", "餃", "餅", "餉", "養", "餌", "餐", "餒", "餓", "餘", "餝", "餞", "餠", "餡", "餤", "館", "餬", "餮", "饂", "饅", "饉", "饋", "饌", "饐", "饑", "饒", "饕", "饗", "首", "馗", "馘", "香", "馞", "馥", "馨", "馬", "馭", "馮", "馳", "馴", "駁", "駄", "駅", "駆", "駈", "駐", "駑", "駒", "駕", "駘", "駛", "駝", "駟", "駢", "駭", "駮", "駱", "駸", "駻", "駿", "騁", "騅", "騎", "騏", "騒", "験", "騙", "騨", "騫", "騰", "騷", "騾", "驀", "驃", "驍", "驒", "驕", "驗", "驚", "驛", "驟", "驢", "驤", "驥", "驩", "驪", "骨", "骰", "骶", "骸", "骼", "髀", "髄", "髏", "髑", "髓", "體", "高", "髙", "髞", "髠", "髢", "髣", "髦", "髪", "髫", "髭", "髯", "髱", "髴", "髷", "髻", "鬆", "鬐", "鬘", "鬚", "鬟", "鬢", "鬣", "鬧", "鬨", "鬩", "鬪", "鬮", "鬱", "鬲", "鬻", "鬼", "魁", "魂", "魃", "魄", "魅", "魋", "魍", "魎", "魏", "魑", "魔", "魘", "魚", "魯", "魳", "魴", "魹", "鮃", "鮄", "鮎", "鮑", "鮒", "鮓", "鮟", "鮠", "鮧", "鮨", "鮪", "鮫", "鮭", "鮮", "鮴", "鮹", "鯆", "鯉", "鯊", "鯎", "鯒", "鯔", "鯖", "鯛", "鯡", "鯢", "鯣", "鯥", "鯨", "鯯", "鯰", "鯱", "鯵", "鰆", "鰈", "鰉", "鰊", "鰌", "鰍", "鰐", "鰒", "鰓", "鰕", "鰣", "鰤", "鰥", "鰭", "鰮", "鰯", "鰰", "鰱", "鰲", "鰹", "鰺", "鰻", "鱁", "鱇", "鱈", "鱉", "鱏", "鱒", "鱗", "鱚", "鱠", "鱧", "鱮", "鱲", "鱶", "鱷", "鱸", "鳥", "鳧", "鳩", "鳰", "鳳", "鳴", "鳶", "鴃", "鴇", "鴈", "鴉", "鴎", "鴒", "鴗", "鴛", "鴟", "鴣", "鴦", "鴨", "鴫", "鴬", "鴻", "鴾", "鴿", "鵄", "鵐", "鵑", "鵙", "鵜", "鵝", "鵞", "鵠", "鵡", "鵤", "鵬", "鵯", "鵲", "鵺", "鵼", "鵾", "鶉", "鶏", "鶚", "鶩", "鶫", "鶯", "鶲", "鶴", "鶸", "鶺", "鶿", "鷀", "鷁", "鷄", "鷓", "鷗", "鷙", "鷦", "鷧", "鷭", "鷯", "鷲", "鷸", "鷹", "鷺", "鷽", "鸕", "鸚", "鸛", "鸞", "鹵", "鹸", "鹹", "鹼", "鹽", "鹿", "麁", "麈", "麋", "麒", "麓", "麕", "麗", "麝", "麟", "麤", "麥", "麦", "麩", "麪", "麭", "麴", "麵", "麸", "麹", "麺", "麻", "麼", "麽", "麾", "麿", "黄", "黌", "黍", "黎", "黐", "黑", "黒", "黔", "默", "黙", "黛", "黜", "黝", "點", "黠", "黥", "黨", "黯", "黴", "黷", "黻", "黽", "鼇", "鼈", "鼎", "鼓", "鼕", "鼙", "鼠", "鼬", "鼯", "鼹", "鼻", "鼽", "鼾", "齊", "齋", "齎", "齒", "齕", "齟", "齡", "齢", "齣", "齦", "齧", "齪", "齬", "齲", "齶", "齷", "龍", "龐", "龔", "龕", "龗", "龜", "龝", "龠", "龢", "﨑", "﨟", "﹅", "﹆", "𢌞", "𣗄", "𥝱", "##レ", "##ッ", "##タ", "##・", "##セ", "##ラ", "##シ", "##エ", "##N", "##V", "##I", "##T", "##O", "##ル", "##ズ", "##バ", "##a", "##n", "##s", "##t", "##i", "##r", "##ス", "##ジ", "##話", "##デ", "##ー", "##ヌ", "##え", "##る", "##ン", "##サ", "##プ", "##ポ", "##ギ", "##ハ", "##メ", "##モ", "##リ", "##ア", "##ュ", "##ミ", "##u", "##w", "##l", "##瀬", "##m", "##b", "##o", "##フ", "##S", "##X", "##9", "##6", "##5", "##0", "##3", "##e", "##p", "##勝", "##マ", "##ド", "##ャ", "##ァ", "##M", "##E", "##y", "##d", "##h", "##ク", "##R", "##K", "##k", "##U", "##A", "##虫", "##ム", "##況", "##c", "##イ", "##ビ", "##ソ", "##ヴ", "##ォ", "##ろ", "##う", "##g", "##ピ", "##ザ", "##玖", "##ヤ", "##コ", "##ェ", "##ト", "##ィ", "##ナ", "##ニ", "##拡", "##が", "##っ", "##1", "##介", "##兎", "##喜", "##ユ", "##弐", "##ウ", "##カ", "##P", "##テ", "##き", "##ぬ", "##け", "##ブ", "##ワ", "##ペ", "##キ", "##ツ", "##ケ", "##ヒ", "##v", "##ふ", "##く", "##張", "##z", "##j", "##ヂ", "##ベ", "##ち", "##消", "##せ", "##ボ", "##L", "##G", "##ダ", "##ゥ", "##C", "##行", "##耳", "##古", "##ガ", "##ョ", "##ロ", "##2", "##で", "##か", "##し", "##チ", "##わ", "##言", "##ヨ", "##ネ", "##Y", "##F", "##H", "##グ", "##永", "##パ", "##B", "##Z", "##8", "##7", "##山", "##段", "##オ", "##ノ", "##ゴ", "##ゲ", "##D", "##立", "##4", "##尾", "##当", "##て", "##兄", "##ゾ", "##れ", "##論", "##傷", "##ヘ", "##希", "##目", "##q", "##簡", "##Q", "##島", "##み", "##ら", "##仲", "##宗", "##根", "##歌", "##吾", "##ぎ", "##取", "##f", "##ど", "##ま", "##友", "##×", "##合", "##い", "##格", "##ゼ", "##域", "##め", "##禁", "##り", "##д", "##豆", "##色", "##鹽", "##吉", "##げ", "##止", "##挟", "##す", "##送", "##釈", "##つ", "##氏", "##柄", "##緑", "##口", "##飛", "##ば", "##九", "##上", "##じ", "##ホ", "##房", "##技", "##x", "##土", "##θ", "##作", "##さ", "##ご", "##こ", "##流", "##淆", "##里", "##子", "##断", "##光", "##芳", "##腕", "##び", "##と", "##大", "##仕", "##駝", "##麿", "##辰", "##や", "##留", "##身", "##声", "##指", "##庵", "##会", "##印", "##文", "##羊", "##深", "##彦", "##座", "##鑫", "##明", "##鶴", "##蛤", "##出", "##頭", "##/", "##'", "##朗", "##王", "##之", "##助", "##秀", "##ず", "##軸", "##長", "##щ", "##序", "##λ", "##δ", "##α", "##込", "##軽", "##酒", "##臘", "##朝", "##越", "##そ", "##笑", "##返", "##風", "##お", "##絹", "##遇", "##集", "##\"", "##ひ", "##仁", "##造", "##川", "##抜", "##卸", "##野", "##達", "##.", "##)", "##}", "##袖", "##も", "##新", "##宅", "##巻", "##丞", "##晒", "##臣", "##む", "##ヅ", "##召", "##梁", "##ъ", "##з", "##引", "##袋", "##清", "##郎", "##兵", "##衛", "##谷", "##は", "##航", "##あ", "##州", "##(", "##だ", "##太", "##能", "##外", "##面", "##甚", "##〜", "##ん", "##ν", "##μ", "##η", "##年", "##実", "##岡", "##装", "##歩", "##ぶ", "##旦", "##空", "##生", "##木", "##鋼", "##記", "##広", "##団", "##治", "##直", "##よ", "##汁", "##廻", "##物", "##;", "##に", "##修", "##河", "##射", "##林", "##節", "##田", "##W", "##塚", "##町", "##鳥", "##帰", "##粮", "##西", "##重", "##精", "##一", "##柳", "##雨", "##堤", "##掛", "##車", "##曲", "##京", "##陽", "##廠", "##報", "##髭", "##憑", "##平", "##台", "##奸", "##鑵", "##ヲ", "##た", "##切", "##脇", "##な", "##爆", "##爪", "##回", "##以", "##都", "##美", "##笛", "##誨", "##和", "##ほ", "##類", "##考", "##官", "##κ", "##υ", "##所", "##江", "##ぐ", "##ρ", "##σ", "##看", "##睨", "##定", "##番", "##難", "##の", "##用", "##六", "##体", "##世", "##ヶ", "##崎", "##湊", "##ι", "##入", "##的", "##潤", "##門", "##三", "##線", "##音", "##蹴", "##注", "##退", "##着", "##峠", "##蕎", "##麦", "##点", "##反", "##茗", "##ё", "##昭", "##草", "##白", "##球", "##箱", "##次", "##利", "##逃", "##館", "##原", "##敷", "##乱", "##沈", "##程", "##斎", "##書", "##忠", "##依", "##乳", "##!", "##-", "##」", "##寄", "##殺", "##胤", "##代", "##筋", "##落", "##東", "##路", "##店", "##邦", "##仄", "##心", "##昌", "##許", "##福", "##打", "##ゅ", "##液", "##娯", "##憲", "##針", "##刑", "##ぼ", "##天", "##来", "##堂", "##寇", "##鴨", "##費", "##地", "##机", "##ω", "##法", "##付", "##肉", "##本", "##ヮ", "##々", "##皮", "##葺", "##茶", "##春", "##圧", "##撃", "##設", "##J", "##磴", "##、", "##彤", "##是", "##万", "##尹", "##務", "##説", "##備", "##分", "##鳴", "##計", "##高", "##織", "##間", "##莪", "##彌", "##那", "##ิ", "##信", "##観", "##票", "##蛎", "##市", "##減", "##使", "##鏡", "##亥", "##駅", "##哭", "##除", "##雲", "##ぃ", "##教", "##寺", "##轍", "##毛", "##肘", "##南", "##雄", "##閣", "##示", "##種", "##寔", "##蜘", "##蛛", "##咽", "##橋", "##神", "##噺", "##科", "##鳳", "##湿", "##嶺", "##豪", "##英", "##焼", "##死", "##鈴", "##村", "##幸", "##街", "##版", "##弁", "##員", "##獣", "##韓", "##将", "##酸", "##捨", "##瞰", "##枝", "##倉", "##語", "##名", "##内", "##晶", "##岳", "##腐", "##加", "##孝", "##童", "##小", "##金", "##井", "##人", "##郷", "##賛", "##鰐", "##払", "##φ", "##』", "##『", "##詰", "##烟", "##悪", "##章", "##諭", "##芸", "##膳", "##戻", "##緒", "##紙", "##旭", "##弾", "##開", "##津", "##淑", "##尊", "##手", "##四", "##杯", "##比", "##邇", "##輯", "##狸", "##殻", "##貨", "##願", "##中", "##礼", "##油", "##刻", "##支", "##訓", "##ゃ", "##梅", "##●", "##洗", "##客", "##談", "##包", "##令", "##茸", "##札", "##奴", "##替", "##鸞", "##氷", "##扉", "##魔", "##民", "##脂", "##与", "##経", "##督", "##禎", "##仙", "##者", "##ぜ", "##壺", "##諸", "##米", "##伊", "##國", "##意", "##知", "##商", "##家", "##貝", "##灯", "##岩", "##τ", "##膜", "##海", "##久", "##憐", "##阿", "##弥", "##牧", "##国", "##摩", "##半", "##保", "##術", "##例", "##毒", "##栄", "##池", "##嘗", "##食", "##絵", "##ね", "##べ", "##場", "##財", "##薬", "##成", "##鍾", "##羽", "##続", "##存", "##水", "##星", "##前", "##勤", "##見", "##我", "##鱗", "##籠", "##澤", "##命", "##療", "##菜", "##布", "##旗", "##ざ", "##餅", "##力", "##+", "##影", "##琬", "##邊", "##居", "##骨", "##脳", "##気", "##鷹", "##別", "##欠", "##栗", "##羅", "##,", "##→", "##[", "##律", "##玄", "##母", "##ぞ", "##二", "##裂", "##歪", "##糸", "##弦", "##ぽ", "##床", "##扇", "##渋", "##嬢", "##俊", "##辺", "##壁", "##沓", "##史", "##釧", "##植", "##賜", "##堀", "##祚", "##元", "##━", "##襟", "##筒", "##烏", "##弧", "##浦", "##粟", "##司", "##洲", "##滑", "##義", "##丈", "##夫", "##塾", "##汗", "##ε", "##好", "##媧", "##残", "##狭", "##康", "##丸", "##躾", "##船", "##ぁ", "##結", "##冀", "##埔", "##時", "##隆", "##下", "##Д", "##焦", "##麻", "##折", "##Σ", "##Λ", "##Ω", "##証", "##乃", "##糖", "##役", "##起", "##答", "##葉", "##局", "##ヽ", "##]", "##β", "##肥", "##并", "##夏", "##茂", "##鎬", "##控", "##沢", "##沙", "##溟", "##選", "##遊", "##淵", "##連", "##述", "##違", "##鎮", "##月", "##殴", "##肝", "##校", "##龍", "##饅", "##純", "##敏", "##虐", "##彬", "##露", "##拳", "##左", "##桃", "##学", "##陰", "##拓", "##懇", "##屋", "##沌", "##頒", "##髪", "##良", "##則", "##責", "##飼", "##致", "##※", "##樹", "##耶", "##判", "##也", "##縁", "##更", "##儀", "##火", "##窓", "##工", "##甲", "##増", "##】", "##。", "##帆", "##稿", "##π", "##γ", "##角", "##院", "##公", "##男", "##認", "##炎", "##浜", "##求", "##禍", "##傅", "##換", "##陸", "##遣", "##占", "##売", "##伸", "##寵", "##郡", "##ぺ", "##果", "##析", "##汶", "##熙", "##詳", "##苑", "##積", "##侠", "##蔵", "##条", "##城", "##按", "##妨", "##承", "##道", "##府", "##県", "##営", "##孜", "##泊", "##藏", "##鷲", "##ょ", "##釜", "##裏", "##劇", "##渓", "##鼓", "##熊", "##竹", "##芥", "##式", "##歳", "##{", "##接", "##麼", "##第", "##彊", "##笠", "##片", "##敗", "##聞", "##産", "##隋", "##華", "##ゆ", "##づ", "##松", "##器", "##字", "##差", "##厚", "##穂", "##部", "##糧", "##掲", "##χ", "##禄", "##季", "##図", "##鎖", "##日", "##給", "##宮", "##剤", "##賢", "##帝", "##桶", "##疹", "##向", "##佳", "##持", "##靡", "##無", "##浩", "##剣", "##繁", "##竜", "##損", "##快", "##覚", "##添", "##正", "##石", "##厳", "##塁", "##患", "##掻", "##鶏", "##酷", "##熱", "##昱", "##洋", "##茎", "##苞", "##継", "##議", "##斉", "##臭", "##矢", "##ξ", "##暦", "##性", "##追", "##首", "##桜", "##運", "##謎", "##闘", "##裾", "##安", "##政", "##攻", "##拉", "##競", "##底", "##斌", "##鐘", "###", "##沖", "##繭", "##緲", "##制", "##案", "##亀", "##碁", "##藻", "##貪", "##業", "##呂", "##蛆", "##姦", "##幅", "##環", "##型", "##品", "##蝉", "##揚", "##杓", "##想", "##纛", "##約", "##霊", "##慄", "##尽", "##苗", "##:", "##主", "##奈", "##勢", "##漉", "##扱", "##紀", "##脱", "##篭", "##銃", "##杉", "##量", "##相", "##岱", "##灘", "##姫", "##模", "##網", "##錬", "##派", "##七", "##庶", "##女", "##姿", "##*", "##称", "##味", "##往", "##基", "##破", "##随", "##賊", "##琴", "##絶", "##動", "##席", "##凪", "##貞", "##椅", "##甘", "##卵", "##寿", "##施", "##協", "##_", "##|", "##紫", "##害", "##騎", "##花", "##去", "##?", "##幇", "##機", "##状", "##垂", "##孫", "##参", "##譜", "##獲", "##帳", "##砥", "##鋒", "##染", "##抑", "##枚", "##泉", "##肌", "##眼", "##若", "##翻", "##叉", "##溝", "##舎", "##垣", "##坂", "##渡", "##多", "##±", "##潺", "##価", "##漬", "##偏", "##五", "##א", "##郊", "##件", "##桑", "##恥", "##勳", "##錦", "##疏", "##†", "##蘂", "##任", "##弟", "##免", "##崙", "##放", "##孩", "##響", "##階", "##滝", "##恩", "##刊", "##区", "##質", "##右", "##竿", "##寧", "##へ", "##転", "##防", "##核", "##善", "##飯", "##牛", "##湖", "##十", "##−", "##硫", "##為", "##煮", "##麗", "##鍋", "##納", "##争", "##極", "##揮", "##園", "##盛", "##壊", "##伐", "##詩", "##只", "##潮", "##細", "##帖", "##粉", "##勲", "##繋", "##銀", "##攫", "##愚", "##束", "##訴", "##弱", "##哲", "##丘", "##來", "##詞", "##皇", "##途", "##復", "##甕", "##@", "##武", "##避", "##寛", "##板", "##湘", "##須", "##形", "##端", "##亭", "##徳", "##等", "##祖", "##楓", "##散", "##算", "##材", "##智", "##至", "##室", "##搗", "##変", "##祝", "##危", "##哉", "##志", "##磨", "##舟", "##顛", "##未", "##叩", "##息", "##解", "##構", "##圭", "##帶", "##惜", "##誉", "##横", "##\\", "##由", "##貴", "##茅", "##祷", "##養", "##共", "##〆", "##菊", "##甫", "##煥", "##琳", "##提", "##筆", "##欷", "##畑", "##寥", "##暮", "##函", "##燥", "##「", "##壇", "##鍵", "##綬", "##要", "##八", "##戸", "##僧", "##改", "##管", "##雛", "##巡", "##録", "##ゑ", "##餘", "##望", "##交", "##先", "##締", "##臥", "##葡", "##伝", "##超", "##欧", "##豊", "##郭", "##溜", "##受", "##睡", "##伯", "##補", "##通", "##働", "##廣", "##表", "##組", "##暁", "##児", "##姆", "##籍", "##短", "##両", "##労", "##溪", "##強", "##縞", "##匠", "##幡", "##淳", "##冷", "##港", "##恵", "##蹟", "##犯", "##輝", "##欲", "##満", "##秋", "##威", "##邪", "##蒲", "##方", "##罵", "##疆", "##吶", "##宿", "##演", "##被", "##塀", "##咩", "##坐", "##恕", "##辣", "##拂", "##護", "##吽", "##譲", "##瑠", "##蝕", "##融", "##站", "##槍", "##茹", "##数", "##皋", "##群", "##権", "##愛", "##速", "##藩", "##毅", "##諏", "##訪", "##盧", "##親", "##拝", "##聴", "##事", "##興", "##隊", "##徹", "##‘", "##詣", "##荷", "##梨", "##雉", "##戌", "##側", "##圏", "##博", "##巴", "##蟠", "##ゝ", "##洪", "##艦", "##憶", "##椎", "##様", "##齢", "##嶋", "##桂", "##櫃", "##<", "##憎", "##度", "##^", "##變", "##兒", "##守", "##央", "##廟", "##然", "##肚", "##頼", "##克", "##■", "##雪", "##鰭", "##雅", "##履", "##云", "##割", "##資", "##囚", "##催", "##軍", "##封", "##玉", "##崩", "##誌", "##削", "##豚", "##塩", "##殿", "##討", "##専", "##挙", "##及", "##告", "##佐", "##仮", "##父", "##摂", "##震", "##筏", "##胆", "##降", "##拠", "##闊", "##近", "##陀", "##獄", "##埠", "##丹", "##買", "##亮", "##製", "##老", "##領", "##烙", "##ヱ", "##枉", "##鰹", "##真", "##刀", "##巣", "##鞋", "##刷", "##洛", "##伍", "##綾", "##淋", "##跡", "##呵", "##俣", "##翼", "##医", "##ぱ", "##周", "##循", "##躬", "##没", "##失", "##発", "##盤", "##固", "##銭", "##蛙", "##澄", "##忍", "##飴", "##ლ", "##鱈", "##嘆", "##径", "##軟", "##絞", "##璃", "##服", "##崇", "##禅", "##香", "##滓", "##顔", "##隣", "##森", "##徒", "##読", "##庭", "##躓", "##宣", "##荒", "##侯", "##鉄", "##陵", "##汀", "##鴎", "##輪", "##済", "##尺", "##襲", "##講", "##兼", "##踏", "##浄", "##馬", "##登", "##陣", "##後", "##皐", "##足", "##砲", "##鹿", "##灸", "##脈", "##跳", "##魚", "##虎", "##便", "##建", "##唇", "##魂", "##君", "##腰", "##戒", "##胎", "##醒", "##夷", "##蘇", "##映", "##顕", "##恋", "##唆", "##却", "##覧", "##叡", "##濠", "##誤", "##可", "##化", "##題", "##燕", "##嗚", "##巳", "##有", "##ヰ", "##祭", "##慧", "##辱", "##弘", "##癌", "##活", "##仏", "##編", "##視", "##鑑", "##爛", "##薪", "##請", "##象", "##含", "##德", "##千", "##漢", "##列", "##莱", "##典", "##敦", "##附", "##疑", "##ㇲ", "##系", "##遺", "##丁", "##拭", "##棚", "##押", "##候", "##踊", "##負", "##將", "##歯", "##感", "##痒", "##彝", "##舌", "##宏", "##寸", "##蛇", "##慢", "##繕", "##戍", "##烈", "##莉", "##箋", "##ぇ", "##撤", "##萬", "##孔", "##碕", "##汐", "##磁", "##浅", "##漁", "##楽", "##離", "##蔭", "##累", "##士", "##ぷ", "##騒", "##曇", "##繰", "##售", "##摺", "##洙", "##岬", "##慶", "##僂", "##帽", "##粘", "##惚", "##霆", "##維", "##埃", "##突", "##芽", "##彫", "##碑", "##衣", "##還", "##鵞", "##`", "##狀", "##瓜", "##悟", "##脚", "##調", "##誼", "##故", "##愁", "##宜", "##層", "##戦", "##輔", "##閩", "##瓦", "##態", "##斡", "##縫", "##奔", "##熬", "##蝗", "##姓", "##讃", "##惣", "##妄", "##窯", "##柴", "##駒", "##項", "##帯", "##○", "##温", "##股", "##延", "##譚", "##當", "##蒼", "##源", "##埒", "##曽", "##侑", "##如", "##柱", "##税", "##料", "##像", "##綴", "##裡", "##冲", "##慨", "##百", "##展", "##囲", "##喝", "##懋", "##顧", "##丰", "##幌", "##賃", "##吐", "##画", "##仇", "##狂", "##巌", "##紗", "##投", "##哈", "##婆", "##岐", "##理", "##境", "##額", "##=", "##ぴ", "##覆", "##詠", "##珞", "##病", "##位", "##念", "##呼", "##待", "##婚", "##妻", "##ぢ", "##菓", "##涙", "##頂", "##宝", "##萃", "##貸", "##標", "##溥", "##黒", "##賀", "##倒", "##慈", "##轄", "##情", "##粤", "##沿", "##岸", "##嚢", "##矩", "##処", "##恒", "##箕", "##犬", "##借", "##奏", "##濃", "##珠", "##戎", "##臺", "##坤", "##収", "##誣", "##珍", "##隠", "##災", "##築", "##炉", "##溺", "##髷", "##進", "##鈸", "##艶", "##陶", "##剥", "##賞", "##紐", "##排", "##住", "##轉", "##号", "##署", "##夕", "##坊", "##翅", "##柯", "##富", "##絨", "##崗", "##祐", "##栩", "##塞", "##窺", "##“", "##”", "##曾", "##血", "##潰", "##社", "##寶", "##喰", "##蘭", "##蝶", "##株", "##毘", "##賣", "##浸", "##描", "##灰", "##壮", "##匿", "##予", "##電", "##俗", "##抗", "##自", "##郵", "##欽", "##円", "##尚", "##烱", "##婦", "##究", "##対", "##籟", "##妃", "##眉", "##波", "##鉦", "##鼠", "##配", "##塡", "##萊", "##概", "##優", "##鬘", "##婢", "##鶯", "##棹", "##楼", "##率", "##涌", "##遷", "##最", "##頸", "##戯", "##撫", "##妹", "##鉢", "##遭", "##棒", "##价", "##撥", "##》", "##審", "##煙", "##逐", "##農", "##晴", "##篇", "##輩", "##唄", "##槽", "##忌", "##槻", "##又", "##舞", "##伎", "##歴", "##峯", "##同", "##貢", "##鰍", "##撒", "##迫", "##玩", "##藤", "##粒", "##聊", "##璋", "##冠", "##卿", "##斐", "##宴", "##己", "##際", "##党", "##而", "##鼻", "##週", "##鬼", "##熟", "##乾", "##墨", "##鬱", "##終", "##疔", "##團", "##邑", "##識", "##燭", "##裕", "##洞", "##穴", "##鮫", "##屈", "##捻", "##Δ", "##塵", "##聖", "##筵", "##駆", "##牟", "##遅", "##伽", "##堅", "##規", "##庁", "##豸", "##>", "##景", "##蓋", "##衫", "##問", "##得", "##隅", "##痢", "##宋", "##罪", "##鐸", "##鍮", "##軌", "##體", "##幀", "##悲", "##絲", "##鵲", "##琉", "##壑", "##申", "##稜", "##沼", "##挫", "##祀", "##躍", "##筑", "##充", "##縄", "##饌", "##屏", "##惶", "##耀", "##鞘", "##魯", "##駕", "##菌", "##杜", "##鍍", "##酢", "##匙", "##過", "##蛟", "##阪", "##劣", "##杭", "##瘤", "##栓", "##刈", "##溢", "##串", "##思", "##艮", "##才", "##稔", "##浚", "##瑣", "##翔", "##軒", "##彩", "##貂", "##乎", "##埜", "##椿", "##夜", "##現", "##學", "##北", "##潭", "##董", "##礙", "##霜", "##咋", "##娘", "##棲", "##棣", "##嵐", "##閉", "##畫", "##矛", "##阳", "##膝", "##亦", "##旨", "##狩", "##託", "##鑒", "##界", "##濡", "##紅", "##Ο", "##順", "##謙", "##廬", "##綱", "##炭", "##瑩", "##彧", "##紋", "##擬", "##琰", "##叙", "##腹", "##鐙", "##賦", "##應", "##瑀", "##硯", "##燃", "##彪", "##族", "##句", "##灼", "##迪", "##唱", "##瑞", "##沸", "##革", "##賓", "##芝", "##因", "##置", "##卒", "##初", "##趣", "##僔", "##荘", "##芋", "##肺", "##榻", "##効", "##无", "##褒", "##銅", "##〉", "##÷", "##銘", "##吻", "##冊", "##振", "##$", "##啼", "##鋸", "##辭", "##倪", "##碧", "##並", "##輸", "##牌", "##斤", "##蝋", "##煤", "##早", "##容", "##娥", "##襷", "##租", "##峰", "##障", "##爵", "##揃", "##枕", "##徙", "##献", "##易", "##症", "##濱", "##伏", "##涼", "##·", "##∇", "##龜", "##梓", "##坪", "##祺", "##毀", "##斑", "##瓶", "##該", "##糠", "##韻", "##括", "##常", "##勇", "##簫", "##訳", "##堰", "##寮", "##吸", "##験", "##練", "##泰", "##燾", "##胡", "##櫓", "##塗", "##透", "##薫", "##勒", "##干", "##鯛", "##載", "##煎", "##佛", "##弓", "##衆", "##姉", "##尖", "##掘", "##崖", "##浪", "##綰", "##楨", "##苦", "##貌", "##條", "##砕", "##朱", "##萍", "##暴", "##亡", "##届", "##粋", "##喙", "##関", "##籤", "##泛", "##熈", "##腥", "##慕", "##杖", "##腑", "##蒂", "##猨", "##椥", "##祥", "##丑", "##縮", "##貫", "##蜜", "##羌", "##昴", "##≧", "##≦", "##躙", "##恢", "##姜", "##冑", "##奎", "##謡", "##拾", "##移", "##畝", "##泥", "##走", "##猫", "##腸", "##芯", "##遠", "##悩", "##尻", "##隔", "##謬", "##独", "##暑", "##策", "##柿", "##撮", "##釘", "##急", "##簞", "##御", "##雷", "##具", "##範", "##鬟", "##羮", "##兜", "##捕", "##猿", "##腎", "##懷", "##莫", "##祟", "##睦", "##敬", "##粛", "##蟋", "##完", "##暈", "##〇", "##孤", "##宇", "##芬", "##弊", "##衷", "##舜", "##覲", "##販", "##嫁", "##亜", "##稱", "##撰", "##堕", "##著", "##従", "##紳", "##吏", "##否", "##侵", "##剌", "##誓", "##健", "##逸", "##爾", "##臂", "##痘", "##滴", "##決", "##璽", "##夢", "##青", "##癖", "##朶", "##娜", "##圃", "##紇", "##粕", "##異", "##赤", "##僑", "##懐", "##庸", "##頃", "##値", "##♪", "##涇", "##胃", "##纂", "##□", "##竄", "##賚", "##尼", "##鉞", "##桁", "##‖", "##腺", "##榮", "##∞", "##妓", "##昼", "##釣", "##秘", "##喬", "##什", "##巖", "##私", "##°", "##簀", "##儲", "##衞", "##密", "##垢", "##豹", "##焙", "##盟", "##据", "##迎", "##仔", "##牘", "##益", "##滅", "##拒", "##冨", "##旬", "##姑", "##胞", "##彰", "##鏝", "##擁", "##淛", "##距", "##涯", "##憂", "##湯", "##統", "##余", "##葛", "##幕", "##黄", "##怖", "##盗", "##坡", "##嘉", "##慮", "##苛", "##允", "##珈", "##爬", "##陥", "##壱", "##寒", "##掠", "##屑", "##剃", "##筠", "##盃", "##期", "##證", "##濁", "##葵", "##墓", "##導", "##其", "##趙", "##尉", "##鵡", "##秤", "##據", "##綏", "##滔", "##倍", "##訛", "##了", "##吹", "##于", "##総", "##奇", "##驗", "##賈", "##泣", "##鯨", "##抄", "##隙", "##唯", "##ゞ", "##鉾", "##糞", "##纏", "##低", "##聯", "##各", "##汰", "##嵜", "##痛", "##貿", "##庫", "##在", "##蒙", "##寨", "##朋", "##潜", "##肆", "##棋", "##賽", "##乗", "##診", "##蕉", "##探", "##邸", "##泡", "##閑", "##躰", "##廷", "##蕃", "##蔑", "##琛", "##践", "##師", "##哥", "##毬", "##遍", "##檬", "##凡", "##抵", "##ÿ", "##胝", "##鰻", "##默", "##漠", "##廊", "##照", "##且", "##挽", "##誕", "##虬", "##璟", "##渦", "##圍", "##綿", "##級", "##楚", "##汲", "##卉", "##漆", "##牙", "##奪", "##特", "##祓", "##摘", "##枠", "##挑", "##咲", "##卯", "##侍", "##胱", "##鮴", "##阻", "##肴", "##寂", "##庚", "##舉", "##盈", "##瑟", "##旺", "##畳", "##不", "##亞", "##胥", "##静", "##胴", "##試", "##濫", "##⌒", "##魅", "##券", "##篠", "##瑚", "##倫", "##薯", "##祠", "##斗", "##崑", "##飾", "##誅", "##末", "##辞", "##触", "##仰", "##巽", "##嗣", "##埋", "##頓", "##鶉", "##偵", "##蹙", "##準", "##少", "##蟹", "##塔", "##舩", "##叢", "##猛", "##鮭", "##濟", "##狄", "##察", "##羯", "##孚", "##蝨", "##蕾", "##藍", "##叫", "##唾", "##適", "##択", "##鳩", "##肩", "##猜", "##脩", "##輓", "##坑", "##飲", "##妬", "##般", "##褻", "##晦", "##淫", "##礬", "##觀", "##諦", "##壌", "##捏", "##醴", "##讐", "##於", "##企", "##怨", "##准", "##鍛", "##冶", "##孽", "##顎", "##翰", "##惰", "##潔", "##頬", "##橇", "##職", "##需", "##傳", "##珂", "##惑", "##搦", "##黍", "##餐", "##揄", "##幽", "##歎", "##痕", "##盲", "##價", "##逢", "##渺", "##賎", "##午", "##蘚", "##休", "##旅", "##揖", "##迅", "##廼", "##漏", "##趾", "##升", "##応", "##蜂", "##慣", "##敵", "##省", "##艇", "##蜉", "##葬", "##梗", "##箇", "##矣", "##腿", "##磐", "##黛", "##熔", "##双", "##蓉", "##磊", "##樋", "##焰", "##萱", "##似", "##惨", "##彗", "##庇", "##凌", "##背", "##悴", "##徽", "##飽", "##庄", "##蹠", "##貯", "##酪", "##箸", "##鋤", "##秣", "##採", "##蟲", "##〔", "##┐", "##訊", "##匡", "##麺", "##穏", "##踪", "##捌", "##邃", "##慰", "##韆", "##袒", "##△", "##嚴", "##讀", "##鹹", "##禹", "##錠", "##【", "##育", "##%", "##を", "##素", "##蒸", "##播", "##搖", "##躯", "##諫", "##袴", "##穎", "##諤", "##衰", "##捺", "##鮑", "##畜", "##衡", "##腫", "##欄", "##宰", "##緩", "##吞", "##兩", "##礪", "##馴", "##帛", "##吟", "##幣", "##喫", "##聲", "##兪", "##穆", "##葆", "##舵", "##黙", "##橘", "##暢", "##塑", "##椰", "##鍬", "##略", "##梶", "##銛", "##昇", "##弯", "##錫", "##媛", "##檣", "##呑", "##呀", "##駄", "##監", "##穀", "##琅", "##韋", "##叱", "##虚", "##醬", "##窪", "##隧", "##箪", "##渠", "##鄂", "##玻", "##柔", "##囃", "##攬", "##隨", "##佩", "##涸", "##虱", "##砂", "##斯", "##諌", "##褐", "##測", "##璿", "##全", "##斬", "##栖", "##虔", "##曳", "##辛", "##枯", "##卓", "##Π", "##櫛", "##炙", "##傑", "##蓮", "##鴉", "##棍", "##躇", "##册", "##篌", "##凜", "##勅", "##棘", "##謀", "##債", "##蚕", "##槌", "##熏", "##ぅ", "##評", "##汜", "##蕨", "##瑪", "##霞", "##筮", "##裘", "##塘", "##弼", "##權", "##習", "##桓", "##澠", "##茄", "##蕩", "##彎", "##辻", "##冕", "##狛", "##眠", "##縦", "##匱", "##鱒", "##燵", "##顫", "##箔", "##爲", "##蓼", "##励", "##薨", "##椒", "##砧", "##渕", "##遂", "##藪", "##粧", "##研", "##蛄", "##浮", "##奮", "##翁", "##就", "##桟", "##酉", "##餌", "##蹇", "##縛", "##限", "##實", "##闍", "##騙", "##凶", "##謨", "##觚", "##俵", "##戚", "##捜", "##秒", "##睫", "##尿", "##牢", "##臓", "##〵", "##ゐ", "##酌", "##鋏", "##既", "##刺", "##檜", "##哆", "##唎", "##篤", "##簾", "##惠", "##募", "##狗", "##祢", "##始", "##曹", "##癪", "##罰", "##殖", "##佑", "##李", "##唐", "##丕", "##雀", "##峪", "##娠", "##嫌", "##懸", "##雞", "##琪", "##瀾", "##尋", "##詁", "##緻", "##廈", "##牲", "##岑", "##~", "##猶", "##膏", "##翠", "##焜", "##糊", "##恨", "##朔", "##閔", "##寞", "##悍", "##峡", "##斃", "##菅", "##﨟", "##屎", "##凄", "##鄰", "##鮎", "##秩", "##非", "##厭", "##遵", "##妙", "##靖", "##鮮", "##樂", "##醸", "##皿", "##會", "##聚", "##舶", "##此", "##箒", "##梛", "##冥", "##沱", "##謝", "##★", "##▼", "##〓", "##裁", "##砦", "##湛", "##燮", "##瀆", "##蒜", "##∠", "##聳", "##埼", "##洟", "##經", "##弗", "##他", "##写", "##擦", "##旻", "##猟", "##泳", "##颪", "##凍", "##稼", "##紹", "##堯", "##笏", "##架", "##薄", "##毎", "##嗜", "##掌", "##竈", "##甜", "##愴", "##赫", "##薹", "##汪", "##覇", "##喪", "##塙", "##絣", "##倶", "##紛", "##伴", "##刃", "##桧", "##痰", "##竦", "##啓", "##喩", "##芦", "##豬", "##杏", "##拇", "##俘", "##后", "##豫", "##怠", "##坎", "##征", "##誾", "##混", "##劉", "##疾", "##輦", "##涂", "##鐵", "##鼬", "##昔", "##凝", "##紡", "##措", "##鰌", "##籏", "##到", "##墾", "##听", "##裳", "##濯", "##髄", "##酔", "##忘", "##漫", "##浴", "##攣", "##鴻", "##罫", "##諾", "##宕", "##邨", "##潟", "##痣", "##喉", "##淄", "##俐", "##贅", "##籌", "##媼", "##寝", "##鑿", "##游", "##–", "##杵", "##戴", "##雜", "##淡", "##裸", "##對", "##凋", "##柏", "##擇", "##雑", "##膠", "##衝", "##整", "##誇", "##騰", "##絖", "##涎", "##痤", "##縷", "##叔", "##撓", "##彼", "##鄙", "##磯", "##婁", "##鉱", "##恭", "##噛", "##Щ", "##嬰", "##晩", "##課", "##ζ", "##礫", "##圳", "##蝣", "##簋", "##挺", "##弩", "##雍", "##苔", "##坦", "##鯰", "##☆", "##逆", "##薦", "##窃", "##啞", "##晃", "##蒡", "##淙", "##醍", "##醐", "##嘎", "##駁", "##勿", "##阡", "##焚", "##撲", "##靳", "##披", "##埓", "##顯", "##乙", "##吊", "##剛", "##盆", "##朽", "##杰", "##蛉", "##単", "##嘴", "##鎧", "##諱", "##葦", "##嬪", "##峻", "##秦", "##碩", "##賤", "##培", "##刕", "##汚", "##停", "##綢", "##宸", "##峨", "##謂", "##托", "##緋", "##属", "##戩", "##▲", "##麵", "##籃", "##隈", "##皓", "##稲", "##斜", "##羲", "##幹", "##墳", "##鞍", "##厩", "##葱", "##遥", "##帙", "##蓄", "##瑤", "##鷺", "##猊", "##繪", "##祇", "##綺", "##廓", "##框", "##奨", "##畯", "##拙", "##膨", "##咄", "##怡", "##燈", "##劫", "##操", "##糲", "##迷", "##玲", "##霧", "##靈", "##狼", "##鍼", "##肪", "##朴", "##紮", "##蕙", "##皖", "##咳", "##焔", "##圓", "##怒", "##頌", "##訶", "##缺", "##佞", "##箏", "##謁", "##嫡", "##鵬", "##韜", "##功", "##傘", "##奥", "##併", "##贛", "##艾", "##檗", "##畤", "##這", "##奚", "##滞", "##必", "##駐", "##個", "##蹄", "##檀", "##揺", "##恐", "##蓬", "##廉", "##薔", "##薇", "##ヵ", "##醤", "##頽", "##迦", "##﨑", "##旋", "##笵", "##碓", "##緣", "##炒", "##勘", "##艫", "##廃", "##徴", "##痺", "##疫", "##拗", "##棉", "##刹", "##供", "##欣", "##襄", "##宍", "##鮨", "##樵", "##奉", "##倩", "##撼", "##酛", "##墟", "##縣", "##褪", "##釉", "##瀉", "##蕊", "##僊", "##幾", "##瀛", "##卑", "##⤴", "##碎", "##堪", "##笙", "##瞳", "##亂", "##槎", "##湾", "##曜", "##渤", "##槨", "##褄", "##抱", "##俳", "##丼", "##壷", "##∅", "##狙", "##脾", "##厄", "##套", "##嶠", "##梦", "##儒", "##誦", "##傭", "##蜓", "##◇", "##壽", "##罷", "##陌", "##汝", "##援", "##冬", "##硝", "##迹", "##萎", "##鯖", "##襖", "##紘", "##袞", "##瀧", "##伶", "##廳", "##屯", "##蛾", "##邕", "##抹", "##咎", "##憤", "##綽", "##亟", "##鵠", "##梟", "##鎔", "##蝦", "##弔", "##靜", "##娩", "##険", "##匪", "##享", "##拌", "##茫", "##奭", "##步", "##澳", "##麹", "##凛", "##吼", "##炮", "##礒", "##杼", "##湍", "##菫", "##楊", "##墅", "##柵", "##嗇", "##榜", "##藥", "##犠", "##垠", "##瑜", "##琢", "##符", "##確", "##紊", "##創", "##傾", "##絡", "##嶽", "##斥", "##脆", "##與", "##傍", "##⇒", "##厓", "##倹", "##冰", "##蛮", "##桐", "##萌", "##錯", "##碗", "##疱", "##恃", "##麒", "##禰", "##仞", "##谿", "##噲", "##薗", "##副", "##萩", "##輿", "##繹", "##齊", "##忽", "##椀", "##瀝", "##鏈", "##舘", "##妣", "##噴", "##⤵", "##検", "##績", "##釵", "##蔬", "##畔", "##謹", "##袍", "##吠", "##嵌", "##戮", "##贏", "##做", "##戰", "##歓", "##誠", "##驒", "##焉", "##懿", "##宵", "##賑", "##棄", "##袱", "##蟻", "##ヷ", "##戟", "##礁", "##餓", "##晋", "##棺", "##簶", "##鈔", "##窟", "##臼", "##瘡", "##麟", "##譙", "##漱", "##煩", "##訣", "##摯", "##瘍", "##紬", "##慎", "##煊", "##翎", "##辦", "##歸", "##莒", "##呆", "##黎", "##躑", "##躅", "##零", "##瞼", "##棟", "##舷", "##曰", "##禀", "##′", "##薙", "##塰", "##楯", "##狐", "##鰲", "##薩", "##臨", "##幄", "##纓", "##邵", "##鬢", "##毯", "##貧", "##紺", "##苓", "##辨", "##鈍", "##堆", "##↓", "##諛", "##慾", "##尭", "##萢", "##螺", "##’", "##驚", "##鏃", "##陳", "##餡", "##鵜", "##怪", "##雁", "##〈", "##麝", "##緬", "##訟", "##蠟", "##眞", "##鉤", "##悶", "##楢", "##輛", "##妖", "##悌", "##偃", "##缶", "##剖", "##劒", "##憚", "##鞭", "##杞", "##再", "##菲", "##杢", "##〳", "##暉", "##彡", "##轅", "##燻", "##犀", "##芹", "##欅", "##炳", "##腔", "##隹", "##魋", "##畷", "##預", "##蛋", "##聡", "##倭", "##鈞", "##瑳", "##梳", "##罕", "##├", "##霑", "##蝙", "##款", "##葭", "##鞆", "##委", "##雙", "##鼎", "##澗", "##屠", "##註", "##啄", "##鉈", "##脞", "##脹", "##脛", "##癒", "##禿", "##査", "##耕", "##逝", "##巍", "##愕", "##勉", "##蔓", "##肖", "##均", "##幢", "##胸", "##謌", "##窖", "##魃", "##巧", "##薐", "##莞", "##萄", "##匯", "##愈", "##乞", "##頡", "##陲", "##齡", "##畠", "##悦", "##昧", "##暗", "##蟇", "##翩", "##貽", "##疎", "##梏", "##痔", "##宛", "##巾", "##瞑", "##遁", "##寅", "##挿", "##髏", "##索", "##懲", "##鴿", "##幗", "##¥", "##睛", "##旧", "##熕", "##恚", "##疽", "##皴", "##劭", "##薮", "##漕", "##凉", "##幼", "##豉", "##哀", "##今", "##癸", "##錐", "##髻", "##弖", "##警", "##晁", "##蝮", "##媒", "##燗", "##蝠", "##卅", "##痴", "##即", "##甑", "##苺", "##鞴", "##渾", "##斷", "##誡", "##蚊", "##怯", "##宥", "##凱", "##獅", "##綸", "##瀨", "##稚", "##鷦", "##鷯", "##微", "##倣", "##詢", "##寡", "##謖", "##朮", "##兮", "##凧", "##稈", "##疇", "##契", "##»", "##樽", "##芎", "##剝", "##槫", "##滉", "##疳", "##虞", "##巫", "##燐", "##曼", "##苫", "##戛", "##喇", "##痙", "##踞", "##¤", "##&", "##瓏", "##捐", "##墻", "##暇", "##猷", "##―", "##墜", "##數", "##頊", "##塊", "##昶", "##鞮", "##芩", "##貼", "##轡", "##鞏", "##懌", "##叭", "##⏌", "##救", "##竝", "##伺", "##粥", "##鬚", "##哇", "##埴", "##♀", "##♂", "##鋪", "##奢", "##霏", "##爐", "##Γ", "##Ξ", "##羹", "##鑞", "##舁", "##籐", "##覺", "##昏", "##猴", "##推", "##關", "##沃", "##穢", "##遼", "##柬", "##翳", "##悔", "##瑶", "##揉", "##洩", "##蹲", "##圀", "##荼", "##彭", "##棱", "##係", "##幟", "##笘", "##燼", "##楡", "##茨", "##籬", "##扶", "##媚", "##螂", "##彈", "##諧", "##峅", "##玕", "##巨", "##僚", "##靴", "##菱", "##陷", "##呈", "##闕", "##癩", "##硬", "##侗", "##幻", "##珊", "##艸", "##担", "##殘", "##闇", "##牝", "##鹼", "##杲", "##慌", "##蟬", "##卦", "##娼", "##藁", "##廡", "##舒", "##毫", "##虜", "##—", "##囊", "##握", "##蔽", "##尤", "##巓", "##躁", "##炊", "##咐", "##鬆", "##堵", "##叟", "##隻", "##錮", "##壹", "##梯", "##汽", "##龕", "##璇", "##閃", "##蛸", "##←", "##↑", "##妾", "##罠", "##螳", "##鶚", "##昂", "##朦", "##餮", "##椽", "##麩", "##詔", "##膚", "##ㇻ", "##穡", "##簿", "##樣", "##澹", "##衾", "##藺", "##旛", "##跚", "##糟", "##窮", "##緜", "##瓊", "##窩", "##縋", "##緞", "##剋", "##阯", "##汞", "##肭", "##¿", "##鉛", "##灌", "##帥", "##£", "##槓", "##禾", "##鴣", "##恤", "##拐", "##涅", "##曄", "##▽", "##訂", "##擲", "##罸", "##舊", "##捉", "##馳", "##辟", "##鈎", "##壙", "##婉", "##號", "##蛍", "##捶", "##饉", "##澈", "##蒻", "##邉", "##厲", "##溶", "##韶", "##聾", "##獺", "##鈑", "##敖", "##哨", "##驛", "##脊", "##敢", "##瞭", "##已", "##儘", "##畿", "##贈", "##徨", "##雇", "##瓢", "##兆", "##喊", "##諶", "##箚", "##倆", "##喆", "##侶", "##陝", "##鉉", "##璘", "##愧", "##鴒", "##址", "##濂", "##瞬", "##眷", "##銓", "##塲", "##《", "##蘊", "##汎", "##∀", "##骸", "##誂", "##酵", "##壻", "##跨", "##諄", "##錨", "##熹", "##迭", "##盔", "##嵩", "##犧", "##楠", "##髴", "##釋", "##執", "##爺", "##滸", "##漸", "##繼", "##徐", "##祉", "##牽", "##舅", "##籀", "##撻", "##絃", "##驩", "##卜", "##禦", "##滾", "##拼", "##疋", "##蓑", "##莢", "##跋", "##悠", "##饒", "##茉", "##瑾", "##區", "##覡", "##芭", "##枷", "##劍", "##舗", "##屍", "##咤", "##琦", "##馗", "##贊", "##鹸", "##截", "##嵎", "##厥", "##廿", "##瑗", "##欒", "##嘘", "##聟", "##裔", "##篋", "##糶", "##∓", "##遮", "##菁", "##粢", "##樫", "##錚", "##矧", "##鏞", "##鎭", "##暎", "##閘", "##偽", "##廁", "##鷗", "##奠", "##亨", "##把", "##鰈", "##頤", "##眩", "##漂", "##肛", "##蔡", "##咫", "##何", "##騨", "##巷", "##阜", "##猾", "##撞", "##蔀", "##戈", "##怙", "##樟", "##餉", "##禽", "##☁", "##☂", "##蘗", "##蝿", "##狽", "##ψ", "##瀑", "##刎", "##爽", "##陬", "##粱", "##蕷", "##激", "##呍", "##煕", "##顆", "##隴", "##褥", "##朕", "##摧", "##鎚", "##斧", "##逓", "##釗", "##嘯", "##渇", "##繇", "##飩", "##授", "##悸", "##牀", "##鬪", "##喘", "##樊", "##嘩", "##鞜", "##悛", "##嬋", "##雯", "##蝓", "##宙", "##倻", "##榴", "##蛹", "##蜀", "##梱", "##氐", "##菴", "##處", "##堡", "##靭", "##彙", "##醢", "##俄", "##漿", "##穿", "##徠", "##縅", "##喚", "##邈", "##帑", "##芻", "##邏", "##磔", "##謗", "##笹", "##决", "##擾", "##寫", "##闡", "##√", "##•", "##弄", "##盾", "##獨", "##頚", "##醉", "##ħ", "##峙", "##某", "##普", "##苅", "##恂", "##鋭", "##靄", "##複", "##睿", "##圖", "##夭", "##隸", "##呉", "##蔟", "##賄", "##掃", "##雋", "##俸", "##馭", "##淇", "##撕", "##賠", "##浙", "##恣", "##裒", "##膿", "##僖", "##贄", "##芾", "##藝", "##些", "##嶌", "##岨", "##肢", "##棊", "##毟", "##掬", "##緯", "##湮", "##蠅", "##瑰", "##疲", "##梧", "##鵑", "##廂", "##潸", "##篩", "##貔", "##柑", "##飡", "##啾", "##鑰", "##淮", "##卷", "##槐", "##樓", "##晏", "##甸", "##酥", "##諜", "##歡", "##鄕", "##蘋", "##酬", "##瑛", "##耗", "##癇", "##迄", "##扁", "##嗟", "##攸", "##瞥", "##抽", "##衍", "##洒", "##鎌", "##垜", "##黑", "##羞", "##嘲", "##瞋", "##儡", "##祁", "##澂", "##盡", "##竃", "##淹", "##琶", "##渫", "##聰", "##嘔", "##佯", "##惧", "##禺", "##襞", "##蓿", "##杙", "##霓", "##鄭", "##臾", "##ゎ", "##陟", "##佗", "##溌", "##ぉ", "##嬬", "##壬", "##骰", "##霄", "##褌", "##穗", "##頑", "##險", "##潼", "##煌", "##臧", "##忙", "##杷", "##憾", "##掾", "##鰯", "##彅", "##掴", "##灝", "##叛", "##跌", "##從", "##俎", "##梵", "##崛", "##¡", "##鬨", "##槙", "##擔", "##纈", "##怕", "##睺", "##諚", "##╹", "##撈", "##«", "##耨", "##班", "##捷", "##紂", "##豁", "##惇", "##魎", "##疵", "##鯒", "##廩", "##赦", "##瓠", "##劾", "##稹", "##堺", "##逍", "##鴈", "##洽", "##姒", "##鏘", "##Θ", "##臈", "##搔", "##甥", "##喧", "##粗", "##嘱", "##儉", "##靱", "##晷", "##羚", "##爻", "##詹", "##呰", "##孟", "##閲", "##劃", "##肋", "##裝", "##隷", "##渣", "##礦", "##猪", "##邱", "##魁", "##恬", "##篦", "##〕", "##盒", "##隲", "##茱", "##萸", "##囂", "##蜒", "##采", "##琵", "##兗", "##櫞", "##濤", "##沫", "##璐", "##奕", "##覩", "##澣", "##簪", "##脘", "##馨", "##儺", "##暖", "##兀", "##顚", "##凭", "##眈", "##揆", "##縵", "##錄", "##♠", "##瞞", "##淞", "##嶂", "##夾", "##筝", "##晨", "##Å", "##儞", "##銷", "##勧", "##俅", "##勃", "##渉", "##杈", "##閭", "##齋", "##鞁", "##靼", "##痩", "##舫", "##©", "##尸", "##籾", "##栽", "##丙", "##蕪", "##蜷", "##慟", "##婿", "##氣", "##曁", "##鉋", "##踝", "##歟", "##偶", "##箭", "##狡", "##娃", "##俠", "##潑", "##霖", "##籙", "##昉", "##氈", "##拵", "##龢", "##况", "##們", "##蜍", "##熨", "##厦", "##兇", "##軛", "##颯", "##溯", "##佃", "##歷", "##璞", "##枢", "##頻", "##搬", "##牒", "##滿", "##♥", "##錢", "##鼈", "##麋", "##櫚", "##崋", "##翊", "##泗", "##臚", "##莎", "##兌", "##禮", "##發", "##聽", "##詮", "##嶇", "##♦", "##♣", "##駱", "##腮", "##斂", "##勞", "##旁", "##榑", "##紆", "##飄", "##烹", "##琮", "##徃", "##碍", "##昊", "##篁", "##擧", "##‡", "##繞", "##‐", "##蹤", "##濛", "##莧", "##禧", "##墉", "##褸", "##閥", "##◆", "##遏", "##韮", "##鈷", "##葩", "##悼", "##侮", "##窒", "##頰", "##葎", "##砌", "##闔", "##槿", "##憊", "##蟎", "##侃", "##錘", "##煽", "##莊", "##偉", "##殊", "##桿", "##巒", "##儁", "##圻", "##峴", "##崧", "##剰", "##滋", "##肯", "##諺", "##晝", "##闥", "##鳶", "##隱", "##痞", "##恪", "##慙", "##浣", "##蜻", "##顰", "##稷", "##倚", "##蔘", "##虹", "##懦", "##翦", "##砺", "##歿", "##欝", "##⓷", "##❹", "##❺", "##几", "##燁", "##縱", "##湫", "##艚", "##仗", "##麓", "##或", "##騏", "##泌", "##冽", "##巎", "##袁", "##沁", "##礎", "##冢", "##億", "##竟", "##鰓", "##芿", "##渟", "##悳", "##菟", "##擅", "##漪", "##癬", "##簣", "##凹", "##泄", "##錕", "##§", "##蠻", "##褓", "##簽", "##努", "##慳", "##鰆", "##跑", "##祿", "##粹", "##閾", "##衙", "##孛", "##匝", "##个", "##椋", "##搭", "##菰", "##壕", "##妁", "##鈿", "##蜥", "##蜴", "##滬", "##◯", "##嗽", "##憺", "##楮", "##淚", "##韞", "##姚", "##覯", "##閇", "##閨", "##禱", "##楷", "##珪", "##隼", "##≪", "##招", "##凰", "##涛", "##薊", "##跪", "##詐", "##樺", "##妊", "##稀", "##惟", "##諡", "##穽", "##倅", "##骼", "##爰", "##嵬", "##嶼", "##苣", "##酎", "##拍", "##篆", "##婪", "##藹", "##繊", "##陋", "##蒔", "##閤", "##笥", "##唔", "##冒", "##齧", "##旱", "##楂", "##曝", "##Φ", "##償", "##煉", "##靂", "##傪", "##咨", "##穫", "##徊", "##雫", "##腓", "##槃", "##侈", "##攘", "##囘", "##潦", "##璉", "##肄", "##螟", "##畴", "##穣", "##驤", "##鯉", "##哺", "##扎", "##剄", "##笈", "##裙", "##漑", "##纜", "##蹊", "##駿", "##蘿", "##姥", "##輕", "##梭", "##抓", "##筅", "##薺", "##愍", "##份", "##祗", "##狃", "##洮", "##駟", "##耆", "##∽", "##⊿", "##逵", "##壤", "##但", "##皆", "##駑", "##棗", "##蠱", "##隗", "##杣", "##沚", "##暠", "##衢", "##疼", "##筌", "##凸", "##冪", "##坏", "##癭", "##姐", "##紈", "##睹", "##傲", "##胛", "##襴", "##剪", "##厨", "##沂", "##殃", "##嵋", "##捗", "##蠃", "##錆", "##痾", "##櫻", "##瓷", "##壓", "##弉", "##玅", "##嚮", "##踵", "##詛", "##拜", "##竺", "##冤", "##肇", "##誰", "##毓", "##魄", "##總", "##惔", "##馥", "##茜", "##茘", "##騫", "##飭", "##兔", "##彳", "##匈", "##渙", "##堊", "##匣", "##詡", "##郁", "##僕", "##嚼", "##懣", "##祈", "##袤", "##卍", "##忱", "##毳", "##罩", "##鋲", "##媽", "##♭", "##瞻", "##怩", "##秉", "##楝", "##矯", "##涜", "##乏", "##促", "##銜", "##竊", "##禝", "##蔗", "##俚", "##皺", "##窬", "##∩", "##〃", "##殼", "##辯", "##扼", "##罐", "##皙", "##劻", "##鯱", "##郢", "##汴", "##鞨", "##姻", "##鄲", "##舐", "##曙", "##孺", "##珉", "##筐", "##徭", "##軀", "##璧", "##櫨", "##稙", "##栂", "##翹", "##爼", "##茲", "##珀", "##柘", "##犢", "##諍", "##亙", "##鎗", "##梃", "##塢", "##娑", "##鑽", "##磧", "##獗", "##摸", "##蘆", "##孕", "##俱", "##遐", "##癧", "##⎿", "##奘", "##贋", "##龗", "##昺", "##榊", "##填", "##駈", "##憩", "##翌", "##甦", "##黜", "##詵", "##殷", "##俑", "##氓", "##峭", "##隘", "##赭", "##昆", "##逞", "##辜", "##癲", "##〝", "##榕", "##箍", "##耐", "##壜", "##欖", "##遜", "##蠡", "##稽", "##孑", "##乘", "##枡", "##灣", "##懼", "##誘", "##虻", "##欺", "##▷", "##◁", "##洱", "##滄", "##抬", "##酊", "##〘", "##〖", "##侭", "##咬", "##撚", "##鞠", "##癘", "##尓", "##醇", "##沐", "##覓", "##爭", "##嶮", "##懃", "##≡", "##廸", "##膣", "##駭", "##胖", "##娶", "##儂", "##續", "##奶", "##瓮", "##炫", "##∥", "##牡", "##蠣", "##拱", "##蹕", "##絮", "##檮", "##愷", "##倖", "##气", "##諂", "##蓴", "##獦", "##枇", "##痍", "##濶", "##蹼", "##罔", "##壯", "##仆", "##泓", "##鸚", "##猥", "##頴", "##遙", "##惡", "##擺", "##濘", "##¬", "##奧", "##洹", "##嗾", "##裴", "##棠", "##誄", "##耽", "##嫉", "##愾", "##槹", "##堝", "##嚇", "##稻", "##鏑", "##轢", "##轎", "##檸", "##嚥", "##鶫", "##擻", "##蓂", "##盞", "##鍑", "##勁", "##槁", "##甌", "##邀", "##購", "##帷", "##鑾", "##鮪", "##冉", "##譯", "##臍", "##檻", "##劔", "##痲", "##瀏", "##縹", "##仭", "##懈", "##豈", "##茯", "##檎", "##咯", "##互", "##琨", "##詫", "##譽", "##蹌", "##范", "##穵", "##芒", "##諮", "##繍", "##駸", "##瓚", "##罡", "##飜", "##瑙", "##髯", "##絆", "##諒", "##覽", "##訥", "##贖", "##匂", "##姪", "##梢", "##鶿", "##兢", "##拯", "##踠", "##柚", "##蔔", "##讖", "##拏", "##傕", "##荻", "##蔦", "##坨", "##瑁", "##淀", "##暹", "##竇", "##趺", "##翫", "##鞄", "##稟", "##詈", "##鱚", "##衿", "##鐐", "##蠍", "##皰", "##掉", "##毖", "##謐", "##淨", "##雹", "##赴", "##湃", "##鹵", "##涓", "##蓙", "##孁", "##埤", "##珥", "##蠢", "##敲", "##蘖", "##齕", "##嬖", "##閦", "##雌", "##塹", "##枳", "##畢", "##誥", "##佚", "##縻", "##拔", "##醜", "##刄", "##呪", "##齦", "##簃", "##攀", "##啖", "##♡", "##械", "##蔣", "##屢", "##黐", "##逑", "##畏", "##渚", "##郞", "##燦", "##效", "##拆", "##犁", "##牋", "##枲", "##屬", "##跎", "##騷", "##竭", "##蔚", "##彿", "##聃", "##淺", "##梠", "##繩", "##捲", "##邳", "##淼", "##嶲", "##敎", "##匆", "##∫", "##⊥", "##∵", "##∪", "##荃", "##糜", "##緊", "##篥", "##賁", "##莚", "##擴", "##卻", "##擂", "##蝎", "##臏", "##芨", "##漣", "##綜", "##盂", "##皎", "##艟", "##荳", "##譴", "##暻", "##猩", "##牆", "##縟", "##淅", "##唳", "##醺", "##鉇", "##炸", "##搏", "##縒", "##鏖", "##閏", "##璜", "##逅", "##咀", "##Ψ", "##携", "##銑", "##藜", "##袷", "##營", "##栱", "##貅", "##藷", "##嚶", "##雖", "##舍", "##灤", "##瀞", "##鈺", "##膊", "##暘", "##蒾", "##批", "##戊", "##轟", "##鋳", "##袂", "##沮", "##憫", "##嫋", "##歇", "##軋", "##每", "##忩", "##泪", "##掖", "##弭", "##鞅", "##腴", "##斛", "##亘", "##轆", "##齬", "##罘", "##綻", "##魏", "##乖", "##塒", "##穹", "##胚", "##椏", "##踐", "##剱", "##煦", "##嚭", "##糾", "##儻", "##甄", "##顏", "##訌", "##档", "##簸", "##顗", "##雎", "##芷", "##膺", "##攷", "##縊", "##寐", "##咸", "##毗", "##匹", "##燧", "##嫂", "##嬌", "##綵", "##唖", "##冴", "##櫂", "##軾", "##邁", "##滌", "##點", "##掟", "##繃", "##瀚", "##麴", "##腦", "##羨", "##穰", "##驟", "##寓", "##闢", "##飫", "##嘖", "##桔", "##娟", "##繆", "##鑼", "##臑", "##瘻", "##佻", "##抉", "##衲", "##莽", "##鮒", "##駮", "##窠", "##訝", "##邙", "##蚯", "##蚓", "##湲", "##鋺", "##柁", "##嵯", "##橙", "##戔", "##豳", "##檄", "##諗", "##盥", "##淘", "##肱", "##歐", "##譔", "##沛", "##榎", "##柝", "##鰤", "##倦", "##琊", "##筈", "##瑕", "##妍", "##岻", "##藉", "##綫", "##餞", "##頗", "##駘", "##恰", "##嬉", "##擘", "##〒", "##搾", "##粲", "##濕", "##豨", "##咆", "##沒", "##鑢", "##遽", "##縺", "##磋", "##僉", "##腋", "##樸", "##獵", "##弑", "##鑚", "##珮", "##褘", "##痂", "##鑁", "##耄", "##丿", "##顥", "##噌", "##萇", "##鷀", "##黻", "##驍", "##瑯", "##薑", "##擢", "##羿", "##碾", "##沽", "##鰕", "##噶", "##遞", "##踉", "##勣", "##廛", "##捥", "##逮", "##錡", "##贇", "##銹", "##掩", "##釐", "##巢", "##捍", "##疸", "##跛", "##盪", "##銖", "##戲", "##軻", "##苧", "##蹐", "##窄", "##棕", "##墺", "##璣", "##緘", "##蜊", "##瑫", "##惕", "##翡", "##靆", "##蒿", "##腟", "##昕", "##琲", "##喋", "##晟", "##厘", "##昨", "##汾", "##屁", "##眙", "##夛", "##窕", "##趨", "##僞", "##霰", "##參", "##莘", "##糕", "##幫", "##烽", "##湧", "##佶", "##皷", "##糒", "##咒", "##邯", "##緝", "##郝", "##畦", "##鏢", "##噪", "##炯", "##刳", "##狹", "##襠", "##閒", "##驥", "##橡", "##箆", "##儔", "##臆", "##≒", "##柢", "##蔲", "##訢", "##膽", "##鎰", "##貰", "##榔", "##紜", "##懶", "##跏", "##桝", "##假", "##羣", "##樞", "##蒋", "##茵", "##柩", "##齪", "##煜", "##雒", "##朧", "##燹", "##姨", "##怛", "##⇧", "##蟄", "##蚰", "##勰", "##謾", "##寤", "##憬", "##蟾", "##輊", "##辿", "##圄", "##窗", "##悝", "##宓", "##鮄", "##哿", "##醫", "##种", "##澱", "##蠖", "##禛", "##絏", "##罅", "##騁", "##僥", "##貶", "##菖", "##滇", "##悉", "##蠕", "##酘", "##鵄", "##鳧", "##苴", "##衽", "##梔", "##飢", "##棰", "##狒", "##亢", "##謫", "##陞", "##殆", "##橿", "##輌", "##蜩", "##濮", "##湎", "##醋", "##鄧", "##徧", "##輳", "##蛭", "##菇", "##閼", "##璫", "##隍", "##燎", "##觴", "##扈", "##歙", "##忸", "##蝌", "##檢", "##喃", "##笄", "##碌", "##拶", "##侘", "##髀", "##黴", "##幷", "##縢", "##祕", "##襦", "##袢", "##黔", "##裟", "##蚪", "##煬", "##啜", "##洸", "##筰", "##荊", "##淪", "##困", "##鱇", "##蕭", "##仿", "##∈", "##殉", "##繡", "##埵", "##悅", "##耘", "##鮃", "##鑠", "##荀", "##窿", "##厠", "##骶", "##叮", "##貮", "##陘", "##怜", "##鈕", "##迩", "##鍔", "##∂", "##晰", "##袈", "##闖", "##灑", "##旆", "##◎", "##〻", "##衒", "##玘", "##鑓", "##潯", "##跖", "##檐", "##耿", "##獏", "##兊", "##愿", "##¢", "##毋", "##癈", "##沅", "##敕", "##嫣", "##觸", "##潴", "##旄", "##菩", "##蟀", "##筍", "##謔", "##鱮", "##瘁", "##褚", "##‰", "##稠", "##眸", "##腱", "##聘", "##燠", "##鸕", "##挂", "##唹", "##沪", "##鳰", "##鴦", "##渭", "##爨", "##嚀", "##豐", "##摶", "##熄", "##阮", "##勵", "##岌", "##眄", "##叺", "##弋", "##賂", "##黽", "##瘠", "##驢", "##誑", "##寳", "##芙", "##繝", "##緖", "##悰", "##漳", "##屓", "##慂", "##艘", "##逼", "##廋", "##麭", "##栢", "##蕗", "##儚", "##蕈", "##鐡", "##跟", "##喨", "##羈", "##耋", "##醂", "##潘", "##艙", "##刮", "##擒", "##嫗", "##簇", "##岷", "##憖", "##鋩", "##貉", "##廢", "##豕", "##瀟", "##溂", "##瘦", "##蚣", "##涕", "##睢", "##适", "##◦", "##轂", "##頎", "##珎", "##匐", "##艷", "##偸", "##饗", "##觜", "##頫", "##玳", "##哮", "##爸", "##鯥", "##蜿", "##叶", "##鴫", "##頁", "##儷", "##儼", "##笋", "##覈", "##闐", "##弌", "##婬", "##丐", "##廚", "##鷄", "##碇", "##孃", "##悧", "##仝", "##黨", "##嫩", "##褙", "##慚", "##磚", "##繚", "##麈", "##璈", "##渥", "##鴬", "##囀", "##碣", "##瀦", "##藐", "##轤", "##闌", "##苡", "##枋", "##較", "##垈", "##獪", "##偈", "##洌", "いる", "する", "ある", "20", "19", "から", "こと", "201", "その", "れる", "なっ", "ない", "ため", "など", "200", "##ール", "この", "日本", "##ック", "##ター", "##リー", "られ", "より", "10", "##ット", "##ング", "いう", "なる", "##ラン", "##スト", "##ート", "あっ", "よう", "また", "あり", "もの", "まで", "##ュー", "##ーム", "##ード", "##ント", "18", "12", "##ティ", "##ージ", "##ョン", "11", "199", "学校", "##ンド", "大学", "##00", "でき", "おり", "##かっ", "これ", "##イン", "##ース", "##ディ", "よる", "##リア", "##er", "放送", "それ", "198", "昭和", "よっ", "##ップ", "##ション", "##ーク", "プロ", "##リカ", "##ーズ", "##する", "##ーン", "15", "アル", "受け", "##イト", "197", "だっ", "なく", "現在", "英語", "なり", "##on", "東京", "しか", "202", "##バー", "アメ", "キャ", "世界", "17", "##in", "アメリカ", "場合", "##える", "なかっ", "時代", "16", "つい", "##an", "使用", "会社", "ファ", "196", "テレ", "できる", "平成", "登場", "おい", "##レー", "##ープ", "られる", "行わ", "イン", "コン", "選手", "##ライ", "テレビ", "##ラー", "研究", "ジャ", "13", "##ar", "しかし", "##める", "作品", "##しい", "##ンス", "14", "ライ", "30", "##リス", "194", "195", "##en", "##ッド", "番組", "##リン", "##or", "可能", "たち", "発売", "##ンジ", "存在", "##イル", "多く", "映画", "とも", "開始", "##ランド", "活動", "##カー", "##ルト", "リー", "クラ", "##ナー", "およ", "##ーマ", "同じ", "##ンク", "のみ", "当時", "##at", "フラン", "ページ", "チャ", "##al", "##れる", "25", "フィ", "および", "バス", "しま", "対し", "呼ば", "明治", "発表", "にて", "##シュ", "鉄道", "一部", "チーム", "21", "##es", "スタ", "時間", "##ダー", "##ックス", "タイ", "行っ", "代表", "大き", "##ニア", "ディ", "開発", "ゲーム", "22", "取り", "開催", "##ける", "出演", "##シア", "同年", "なお", "##リーズ", "##ic", "アルバ", "ドラ", "##イツ", "オー", "以降", "大会", "地域", "193", "スト", "変更", "ニュー", "24", "参加", "関係", "フォ", "持つ", "##シャ", "##ステ", "だけ", "アイ", "##がら", "さら", "23", "##ナル", "出場", "##it", "##レイ", "シリーズ", "試合", "おけ", "以下", "所属", "用い", "担当", "##ンター", "たり", "##オン", "せる", "アルバム", "自分", "##ロー", "記録", "ドイツ", "ながら", "##クター", "いっ", "##ッチ", "以上", "設置", "##is", "##サー", "利用", "中国", "コー", "さらに", "音楽", "中心", "##ーズン", "192", "フランス", "##ニー", "自身", "株式", "シーズン", "事業", "国際", "出身", "大阪", "リーグ", "##ャー", "##ウン", "かつ", "##クト", "なら", "26", "引き", "一般", "28", "##ンバー", "考え", "監督", "2010", "多い", "ステ", "##しく", "##ょう", "生ま", "##ブル", "攻撃", "異な", "アン", "27", "人物", "行う", "##フィ", "ウィ", "##ビュー", "優勝", "かけ", "女性", "委員", "グル", "収録", "##ングル", "アニ", "##el", "サン", "高等", "31", "卒業", "##ーツ", "務め", "必要", "##ソン", "フェ", "中央", "29", "2011", "文化", "知ら", "##デル", "##ジオ", "教育", "2009", "2012", "マン", "社会", "##ベル", "##パー", "ジェ", "設立", "情報", "スペ", "2008", "##スタ", "##まり", "##ウス", "問題", "2007", "意味", "##he", "事件", "##レス", "##le", "ジョ", "地方", "##ファ", "2014", "サー", "通り", "2015", "##めて", "位置", "うち", "イギ", "##フト", "##フォ", "ほか", "2013", "シングル", "2016", "イギリス", "##ou", "いく", "都市", "##ion", "##ネル", "##マン", "ブラ", "2019", "自動", "アニメ", "2017", "キャラ", "##ールド", "##上げ", "##ーション", "##さい", "2018", "##して", "影響", "結果", "計画", "ただ", "##as", "ほど", "2006", "同様", "2020", "高校", "最終", "191", "終了", "世紀", "とき", "##ol", "##わっ", "##ラス", "ウェ", "##わり", "サイ", "戦争", "##ータ", "ショ", "最初", "販売", "当初", "シャ", "##ヴァ", "##ッカー", "場所", "##ヴィ", "##ウェ", "ラン", "グループ", "##ころ", "獲得", "選挙", "一方", "##ロン", "作曲", "メンバー", "生まれ", "100", "及び", "##よう", "建設", "センター", "2021", "##om", "##キー", "一覧", "km", "制作", "##ーター", "部分", "アー", "そして", "##ンタ", "##ジア", "人間", "政府", "スター", "地区", "##わせ", "2005", "##まっ", "かつて", "##re", "最後", "発生", "以外", "機関", "リンク", "状態", "特に", "2000", "彼女", "関する", "##ステム", "技術", "調査", "##リング", "年間", "##am", "経済", "就任", "スポ", "まま", "全国", "システム", "廃止", "##カル", "##ぞれ", "##スター", "##メント", "持ち", "それぞれ", "施設", "デビュー", "50", "政治", "ところ", "決定", "契約", "野球", "公開", "##il", "##et", "マイ", "モデル", "教授", "ブル", "年度", "異なる", "記念", "航空", "しまう", "##レン", "##イス", "##ッシュ", "キャラクター", "向け", "ます", "##ac", "ロシア", "主義", "女子", "歴史", "40", "##アン", "構成", "##us", "オリ", "##ro", "##ラム", "持っ", "名前", "実施", "合衆", "戦闘", "##ケット", "ヴァ", "##ビー", "複数", "京都", "チェ", "路線", "2004", "##ザー", "##ジェ", "議員", "ただし", "管理", "##イド", "同時", "##デン", "デザ", "たい", "製造", "全て", "能力", "高い", "相手", "入り", "です", "さん", "設定", "##シー", "こう", "##テン", "##フェ", "カー", "190", "ドラマ", "初めて", "2022", "スー", "記事", "##ルス", "本作", "生活", "採用", "果た", "組織", "対する", "機能", "ホーム", "車両", "##つけ", "指定", "最も", "ダイ", "特別", "運行", "起こ", "##替え", "リリー", "帝国", "##エル", "##ing", "列車", "戦い", "公式", "目的", "あた", "合併", "##リスト", "##出し", "ロー", "エンジ", "受賞", "丁目", "##ートル", "ヴィ", "##海道", "シュ", "ベル", "通常", "##ーロ", "名称", "##ビス", "ライブ", "##んど", "##ろう", "イタ", "出版", "出来", "勝利", "クロ", "始め", "IS", "サッカー", "道路", "協会", "##ンプ", "##スク", "企業", "最大", "トラ", "##かり", "生産", "##ンチ", "与え", "科学", "リリース", "共和", "2003", "##ンダ", "##リオ", "対応", "たら", "##ッツ", "結婚", "##クション", "クラブ", "交通", "ラジオ", "部隊", "そこ", "コミ", "続け", "事務", "最高", "漫画", "使わ", "##ーナ", "00", "含む", "イタリア", "##タル", "少な", "##ER", "##ンガ", "189", "188", "##ニング", "パー", "警察", "伴い", "##わる", "自由", "ハイ", "##ch", "公園", "運動", "海軍", "##ディング", "##コン", "営業", "大きな", "製作", "アナ", "マル", "もっ", "カード", "総合", "独立", "完成", "搭載", "一人", "デザイン", "予定", "##アー", "近い", "時期", "主人", "運転", "2002", "時点", "主に", "基本", "バイ", "##イトル", "##アル", "バンド", "提供", "プレイ", "##ter", "移籍", "ほと", "ユニ", "2001", "##テル", "発見", "##モン", "大正", "北海道", "江戸", "##ッパ", "サービス", "ティ", "以前", "成功", "内容", "##かけ", "飛行", "人口", "マー", "新聞", "実際", "##AN", "##チャ", "経営", "宇宙", "##ルフ", "加え", "ほとんど", "完全", "チャン", "JR", "特徴", "ミュー", "ジュ", "期間", "専門", "カップ", "重要", "活躍", "理由", "評価", "タイトル", "##ッグ", "ウォ", "小説", "##がっ", "##ヤー", "神社", "バー", "運営", "レー", "##ay", "自ら", "ソフト", "プレ", "##ed", "述べ", "##ビア", "連続", "000", "挙げ", "編成", "企画", "##ディア", "決勝", "エンジン", "35", "インター", "入っ", "ビル", "イベ", "作詞", "いわ", "撮影", "オープ", "187", "様々", "##リック", "対象", "再び", "構造", "導入", "##ad", "子供", "##付け", "スポーツ", "新た", "##ギー", "ネット", "##ティー", "1990", "行動", "##nd", "初期", "支援", "すべ", "連合", "性格", "of", "参照", "##ワー", "指導", "病院", "##ig", "スーパー", "イベント", "設計", "##id", "しまっ", "すべて", "認め", "ファン", "よく", "開業", "ライン", "##古屋", "##IN", "スク", "もと", "楽曲", "付け", "人気", "データ", "文字", "名古屋", "言わ", "改称", "ちゃ", "##まる", "規模", "とっ", "##クス", "レース", "そう", "##ピック", "表記", "45", "##タン", "不明", "移動", "法人", "##000", "以来", "紹介", "##ーカー", "指揮", "案内", "1999", "非常", "男性", "##バル", "配信", "##ミー", "大きく", "展開", "ブロ", "環境", "工業", "国家", "ひと", "##ur", "追加", "関連", "下さい", "ボー", "共同", "団体", "ミュージ", "物語", "##プリ", "##ot", "##os", "労働", "##ation", "教会", "##ent", "##入れ", "レコ", "##リンピック", "##トル", "国民", "結成", "ここ", "議会", "フリー", "プラ", "舞台", "番号", "程度", "##BN", "グラ", "テーマ", "ジョン", "##ッジ", "のち", "項目", "クラス", "##ON", "##わら", "回避", "cm", "競技", "限定", "##ゅう", "工場", "レイ", "変化", "果たし", "由来", "CD", "##ストラ", "文学", "広島", "ISBN", "会議", "死去", "銀行", "写真", "32", "##AR", "電気", "##ンパ", "表示", "カル", "候補", "mm", "距離", "装備", "美術", "St", "##らか", "全体", "会長", "60", "多数", "##込ん", "##ボール", "インド", "ドル", "探し", "方法", "##um", "過去", "##じめ", "サイト", "##キング", "1998", "アレ", "コーナー", "国道", "1980", "息子", "天皇", "一番", "いず", "##じる", "##シャル", "言葉", "The", "NH", "思い", "学園", "演奏", "大統", "大統領", "ヨーロ", "##マー", "試験", "アク", "社長", "##ウンド", "##らし", "連邦", "乗り", "ローマ", "建築", "裁判", "福岡", "ヨーロッパ", "韓国", "登録", "県道", "ぶり", "##込み", "オリジ", "選ん", "地下", "##ウム", "##iv", "少年", "##ッセ", "引退", "強い", "打ち", "空港", "地球", "入れ", "横浜", "##ルド", "事故", "##ir", "スペイン", "協力", "支配", "適切", "見せ", "国内", "作戦", "どう", "##ag", "ユー", "周辺", "##けれ", "統合", "1997", "有する", "ワールド", "くる", "自治", "オリジナル", "仕事", "立ち", "発行", "ほぼ", "48", "区間", "見つけ", "自然", "オリンピック", "##ドル", "##り替え", "行い", "陸軍", "##チェ", "NHK", "基づ", "高速", "整備", "##BS", "##ギュ", "民主", "##込ま", "対戦", "##いは", "経験", "##リエ", "1996", "工事", "初代", "形式", "アジア", "通信", "##ow", "映像", "アップ", "ロック", "いずれ", "##ショ", "##イズ", "##ジー", "主張", "べき", "##ヴェ", "##メージ", "エン", "##太郎", "状況", "ホール", "しよう", "##んな", "大戦", "1995", "誕生", "朝鮮", "大臣", "掲載", "##げる", "組み", "含ま", "ター", "劇場", "36", "##ec", "トン", "確認", "移転", "学生", "ちゃん", "使っ", "効果", "少女", "##シン", "##78", "##なり", "同じく", "装置", "好き", "わた", "33", "1970", "報告", "動物", "曖昧", "表現", "ベース", "##なっ", "II", "産業", "あるいは", "発足", "タイム", "原作", "##デュー", "専用", "##ネス", "部門", "普通", "元年", "ハー", "運用", "##ガー", "1994", "エル", "取得", "シェ", "##im", "種類", "生徒", "破壊", "本部", "方面", "ニュース", "出し", "形成", "人々", "##かる", "千葉", "なけれ", "生き", "##ゴン", "唯一", "トップ", "##ia", "新しい", "繰り", "死亡", "メートル", "1993", "##em", "受ける", "制度", "家族", "##レーション", "186", "ニューヨ", "##un", "個人", "成立", "モン", "ステージ", "輸送", "ヴェ", "##ジャー", "比較", "ニューヨーク", "編集", "プロデュー", "##st", "行政", "タイプ", "合わせ", "やす", "付近", "##イント", "ファイ", "##AS", "1992", "FC", "地名", "途中", "##ウト", "##ジャ", "スピ", "郵便", "保護", "ごと", "反対", "勝ち", "選出", "業務", "王国", "県立", "現代", "アフ", "条件", "##ネット", "正式", "##えば", "朝日", "フレ", "##AT", "系統", "入る", "##od", "##スコ", "34", "IC", "近く", "いい", "##ティング", "##パン", "図書", "拡大", "用語", "プレー", "付き", "博士", "オープン", "復帰", "##ルム", "1991", "発展", "##OR", "##ばし", "成績", "続い", "競馬", "スカ", "主要", "ゴール", "##ッション", "##ap", "編曲", "##ut", "クレ", "公演", "##サン", "開設", "##ちら", "##クロ", "以後", "バージ", "呼び", "追い", "中継", "1989", "##ダル", "55", "店舗", "フル", "求め", "周年", "38", "##ラル", "##ーリー", "描か", "料理", "ベスト", "直接", "本人", "コース", "##リティ", "観光", "500", "方向", "##ントン", "分類", "父親", "芸術", "1987", "フロ", "##ポート", "オン", "方式", "取締", "国立", "きっ", "はじめ", "目指", "##デオ", "##セン", "後半", "In", "##がる", "##ジェクト", "本社", "連載", "愛知", "務める", "食べ", "もう", "スタジオ", "言う", "アド", "##プト", "水先", "1988", "張り替え", "##ズム", "男子", "生物", "##ul", "Ch", "迎え", "含め", "##リーン", "魔法", "九州", "武器", "カナ", "細胞", "電話", "スコ", "つけ", "##かし", "##キシ", "メイン", "所在", "当た", "オブ", "俳優", "80", "施行", "有名", "選ば", "シン", "##合わせ", "つつ", "パイ", "言語", "使い", "選択", "よれ", "地元", "デジ", "##oc", "批判", "平均", "精神", "雑誌", "##ub", "大型", "カリ", "作ら", "41", "##こう", "ガン", "流れ", "率い", "##and", "コロ", "特定", "市民", "示す", "##ールズ", "進出", "事実", "ジャン", "支持", "ツアー", "被害", "行き", "南部", "42", "バル", "新潟", "##チュ", "##キュ", "37", "関し", "ギャ", "編入", "##がり", "地上", "アカ", "人民", "組合", "司令", "##ンドン", "ピア", "作家", "ワン", "##ES", "安全", "プログ", "##BC", "加入", "イス", "すぐ", "翌年", "神戸", "##らい", "やっ", "所有", "##ジュ", "復活", "1960", "得点", "向か", "the", "説明", "##セス", "本線", "カン", "女優", "増加", "クリス", "アラ", "原因", "##ゆる", "小さ", "あまり", "決め", "コンピ", "外国", "1986", "ドライ", "アンド", "##ークス", "ポイント", "43", "政策", "市場", "直後", "1985", "建物", "##リート", "配置", "将軍", "離れ", "##レット", "##せる", "植物", "王座", "あたる", "設け", "入学", "購入", "防衛", "台湾", "ビデオ", "改正", "39", "医療", "ルー", "明らか", "70", "パリ", "ホテル", "思わ", "敗れ", "##らく", "グラン", "バック", "44", "##ースト", "##メン", "神奈", "シーン", "##ak", "##IC", "障害", "語っ", "通じ", "ゲスト", "フラ", "仲間", "##合い", "商品", "1984", "化学", "##EN", "電子", "関東", "ハン", "##50", "東北", "理事", "キー", "静岡", "パン", "ロンドン", "DV", "##AL", "惑星", "達成", "リン", "行為", "トレ", "##イア", "中学", "特殊", "バラ", "メディア", "##ウェー", "メーカー", "土地", "成長", "なか", "神奈川", "内閣", "実験", "艦隊", "沖縄", "住民", "プロジェクト", "##なる", "温泉", "エネル", "レベル", "46", "レコード", "レギュ", "派遣", "代わり", "##トロ", "従来", "##ers", "失敗", "記述", "関西", "トリ", "系列", "スケ", "##なわ", "978", "##イク", "##AM", "カメ", "##ピー", "kg", "in", "指摘", "拠点", "基地", "##ガン", "##ウル", "年代", "各地", "高く", "標準", "富士", "ブランド", "出会", "##シング", "フジ", "プリ", "エネルギー", "仕様", "形態", "DVD", "強化", "残し", "軍事", "イメージ", "##出す", "太平", "建て", "1983", "グレ", "投票", "ダム", "製品", "CM", "作り", "作業", "記載", "コンピュー", "電車", "ユニット", "福島", "##IS", "政権", "示し", "##av", "##op", "90", "トラン", "オフ", "切り", "作成", "きっかけ", "イラ", "延長", "発電", "同社", "##ルク", "兄弟", "規定", "一時", "ソング", "長野", "ミュージック", "山口", "1982", "海外", "##ri", "北部", "モード", "巨大", "使う", "レギュラー", "##ュニ", "バージョン", "##スタン", "報道", "くだ", "停止", "無い", "##ゲン", "改造", "##ッケ", "呼ぶ", "シー", "##ov", "機械", "経由", "ガス", "米国", "資料", "処理", "47", "300", "速度", "トラック", "商業", "セル", "例えば", "言っ", "披露", "制御", "オール", "伝え", "連盟", "残っ", "統一", "埼玉", "主演", "##og", "競走", "パラ", "法律", "創設", "##スティ", "アイドル", "分離", "##ウンサー", "歌手", "##ストン", "1972", "上記", "独自", "##ロス", "TO", "言い", "ギリ", "描い", "太陽", "アナウンサー", "ポー", "th", "##込む", "少ない", "博物", "住宅", "スパ", "実現", "##VE", "脚本", "プレイヤー", "1981", "ロボ", "長崎", "少なく", "1979", "落ち", "デジタル", "違い", "集団", "戦後", "母親", "昇格", "継承", "軌道", "なし", "新設", "51", "空間", "ミニ", "定期", "解散", "中華", "おら", "クリ", "旅客", "##AC", "強く", "接続", "マーク", "部屋", "比べ", "優秀", "##ard", "トゥ", "現れ", "革命", "制限", "置か", "感じ", "##ab", "殺害", "集め", "##ルー", "##ランダ", "分野", "安定", "スタート", "作っ", "スキ", "カナダ", "周囲", "貢献", "名誉", "展示", "##ニュー", "責任", "伝統", "条約", "書か", "参戦", "##ミア", "##ッフ", "ブリ", "面積", "##ピオン", "機構", "ヒット", "令和", "##ブルク", "パート", "至る", "##ce", "まと", "友人", "いつ", "1978", "##ロット", "感染", "維持", "1975", "##ウィ", "かなり", "工学", "意識", "農業", "交流", "ジョージ", "##ーフ", "交換", "停車", "相当", "要素", "医学", "続く", "##ダム", "52", "書き", "カラー", "##ID", "49", "ライト", "##ニック", "##返し", "##リアム", "詳細", "##HE", "1973", "二人", "1950", "シティ", "54", "エレ", "基準", "限り", "役割", "操作", "反応", "勢力", "見る", "ください", "予選", "共通", "学院", "紀元", "##ファー", "民族", "機体", "##FA", "刊行", "古代", "現役", "##OM", "振り", "取引", "##掛け", "##ie", "地震", "本来", "段階", "ランド", "主催", "##ンズ", "TV", "理論", "コミュニ", "進め", "岡山", "用法", "範囲", "1974", "思っ", "岐阜", "1976", "##th", "ブルー", "##バイ", "ダン", "禁止", "校舎", "レス", "兵庫", "長い", "##くり", "1971", "##ブリ", "コード", "##ウェア", "ボール", "ポジ", "ST", "##シェ", "自体", "全員", "オーストラ", "治療", "貨物", "鹿児", "##OS", "鹿児島", "命令", "体制", "イング", "1969", "継続", "1945", "まし", "体育", "大陸", "キング", "通称", "メダル", "交差", "もら", "同盟", "エア", "##ill", "毎年", "皇帝", "オーストラリア", "貴族", "行く", "熊本", "観測", "さま", "扱い", "##ワード", "読み", "##ッキ", "##ガル", "訓練", "内部", "陸上", "コーチ", "チャンピオン", "提案", "訪れ", "主な", "減少", "向上", "##EC", "みな", "認定", "逮捕", "判断", "1977", "アト", "ダイヤ", "1968", "起き", "ストーリー", "ルート", "宗教", "家庭", "あれ", "##eb", "##ミング", "コンサ", "演出", "ちな", "挑戦", "宣言", "動き", "せい", "キリスト", "田中", "対策", "性能", "課程", "首相", "##ディー", "##ライナ", "フォー", "週間", "再開", "プロデューサー", "鈴木", "語句", "近年", "オランダ", "##ell", "TBS", "改革", "仙台", "解説", "前作", "エリア", "札幌", "53", "モー", "文庫", "ブラック", "セット", "de", "##igh", "一緒", "得る", "##ジョン", "##しくは", ")-", "##イルス", "ギター", "連絡", "##ワーク", "要求", "##AP", "通過", "職能", "始める", "つな", "小学", "生まれる", "スペシャル", "フィリ", "回転", "首都", "インタ", "##ッサ", "良い", "##切り", "##マス", "ウィリアム", "しまい", "まだ", "##ッカ", "起こし", "##エン", "アフリカ", "##ra", "移行", "依頼", "##立て", "制定", "原子", "ヶ月", "進学", "広く", "62", "スタッフ", "定め", "プログラム", "185", "当選", "発言", "中村", "ショー", "終わっ", "スタイル", "開通", "カメラ", "58", "##チン", "ノー", "衆議", "単位", "You", "セント", "知っ", "奈良", "声優", "出来る", "マネ", "1000", "1964", "キロ", "コンピュータ", "全く", "しばし", "ポジション", "##ッキー", "##ずか", "結ぶ", "世代", "防御", "大字", "ソ連", "56", "##ショナル", "伝説", "ソロ", "前後", "st", "投手", "戻っ", "向かっ", "自己", "##ボン", "書い", "##ist", "ミサ", "##ok", "メジャー", "##ine", "やま", "レッド", "勤務", "危険", "得意", "チャンネル", "本名", "かか", "秋田", "ダウン", "分か", "備え", "1967", "ランキング", "毎日", "亡く", "立て", "定義", "欧州", "しばしば", "除く", "児童", "グリ", "ロード", "会員", "中止", "##やか", "異なり", "推進", "帰国", "更に", "負け", "区域", "身長", "指す", "##est", "資格", "##クラ", "キャン", "指名", "押し", "用いる", "しょう", "電力", "隣接", "知り", "あら", "更新", "Al", "佐藤", "コンビ", "##続き", "学会", "保存", "作用", "長男", "飛び", "THE", "既に", "##ーネ", "同一", "パワー", "小型", "主題", "##ン・", "##そう", "カバー", "改良", "##ニス", "ヴォ", "始まっ", "Re", "SP", "もしくは", "後述", "エピ", "1965", "ペン", "分割", "到着", "戦車", "視聴", "建造", "##ナム", "トル", "##ジン", "消滅", "1966", "様子", "理解", "名乗", "基礎", "デイ", "オス", "回復", "兵器", "単独", "けん", "共産", "つく", "連れ", "エイ", "知事", "リア", "東海", "小さな", "ブレ", "本塁", "起用", "チョ", "サイズ", "ピアノ", "か月", "##バート", "置く", "##出さ", "ヘル", "すれ", "##ミン", "184", "巻き", "ずつ", "始まる", "演じ", "後継", "創立", "収め", "400", "消費", "会場", "ラー", "任務", "練習", "ハウス", "旅行", "##ビン", "##レンジ", "##ess", "57", "デュ", "##トゥ", "文書", "ダンス", "西部", "##all", "対立", "応じ", "平和", "後期", "長官", "発射", "##ティスト", "開幕", "一定", "海岸", "ウイルス", "エド", "騎士", "土曜", "近代", "##とう", "目標", "アマ", "年齢", "##ip", "諸島", "##おり", "記憶", "機器", "消防", "イングランド", "オル", "ユダ", "バン", "##IT", "コント", "ニコ", "任命", "半島", "1955", "大量", "あたり", "意見", "前述", "サポート", "助け", "##ダン", "ドラゴン", "1947", "フォン", "##AD", "乗車", "管轄", "ポーランド", "吉田", "捜査", "供給", "実行", "カラ", "命名", "##らす", "180", "困難", "国鉄", "幕府", "en", "出る", "教師", "オペ", "ナイト", "アス", "芸能", "通算", "FI", "##NA", "##ーニ", "車体", "##ind", "##ーチ", "パーク", "##トン", "がっ", "富山", "資金", "##かい", "向かう", "##フォル", "##ストリア", "与える", "身体", "立場", "59", "作る", "##30", "出現", "やすい", "なさ", "確保", "話し", "らしい", "1963", "PC", "趣味", "##・ア", "75", "山田", "著作", "##ンスター", "判定", "##ッコ", "マク", "解放", "##取り", "在籍", "リーダー", "憲法", "青年", "##ジル", "##ーラ", "石川", "マシン", "アカデ", "すぎ", "64", "投げ", "師団", "An", "##ッター", "スマ", "ラグ", "保険", "ボス", "階級", "物質", "##ct", "低い", "##レント", "##ob", "##OL", "教え", "画面", "同日", "徒歩", "##テナ", "ジャパン", "##テム", "吸収", "ユダヤ", "わけ", "##10", "##ゼル", "注目", "1962", "進行", "金曜", "##ケーション", "##ノン", "阪神", "傾向", "弁護", "コレ", "目指し", "設備", "##ブン", "球団", "ほう", "無く", "インターネット", "元々", "##ヴォ", "##ルン", "物理", "ブロック", "刑事", "##art", "リス", "わずか", "領域", "##UR", "分け", "いわゆる", "1944", "直前", "戦士", "ルール", "撤退", "##リーム", "ネットワーク", "売り", "ゆう", "前年", "準備", "計算", "執筆", "通し", "東部", "合計", "未来", "河川", "1948", "天文", "##ツィ", "##BA", "検査", "タウン", "初回", "交渉", "上位", "日曜", "ミサイル", "両親", "トロ", "処分", "##換え", "##ッピ", "##ET", "記者", "動画", "アリ", "対抗", "属する", "グリーン", "##ざま", "解決", "民国", "判明", "健康", "連隊", "エンディング", "##ジアム", "伴う", "##ik", "ウク", "ロボット", "価格", "金属", "##カン", "許可", "ルイ", "アーティスト", "民間", "思想", "##ーブ", "残り", "1954", "置き", "1961", "入団", "遺跡", "登板", "もっと", "寺院", "もた", "入社", "アシ", "Ar", "イラスト", "歌詞", "いち", "日間", "サラ", "##ザン", "##ソード", "医師", "なん", "##ケル", "伊勢", "1949", "松本", "変え", "##ンサー", "休止", "地位", "新宿", "模様", "どの", "引き継", "##if", "##80", "##ーブル", "取っ", "ナイ", "出す", "生命", "和歌", "形状", "ばかり", "ファミ", "大使", "表明", "検討", "アイテム", "##バン", "持た", "再生", "学科", "##US", "1958", "街道", "##ども", "##ポン", "出力", "##セル", "1941", "1956", "普及", "エリ", "一種", "くれ", "##リアン", "呼ん", "テスト", "##イオ", "過ぎ", "インタビュー", "##たり", "##ンマ", "自衛", "ヘン", "徳島", "急行", "61", "##ーンズ", "南北", "駆逐", "認識", "機動", "1959", "期待", "創業", "Bl", "バトル", "信号", "犯罪", "占領", "どちら", "ブラジル", "愛称", "##ant", "方針", "US", "##トリック", "ビジ", "名義", "ウクライナ", "新人", "##ルツ", "固定", "アカデミー", "襲撃", "ヒロ", "率いる", "##もと", "結ん", "今日", "審査", "1940", "ブレー", "##ルトラ", "幹線", "特急", "##ノー", "ポール", "高橋", "講師", "and", "べく", "アプリ", "分析", "ベイ", "開校", "トンネル", "##キシコ", "背景", "##シャン", "ガー", "爆発", "とり", "##20", "63", "機会", "##フォルニア", "##ティブ", "AT", "新型", "見える", "65", "公共", "Sh", "だろう", "サブ", "市長", "少し", "ライダー", "##グラ", "エピソード", "大きい", "クロス", "本格", "##OW", "権利", "香港", "山本", "パス", "川崎", "エス", "##ンタル", "##持ち", "崩壊", "続ける", "FM", "適用", "前半", "シナ", "マスター", "オーストリア", "停留", "徳川", "現場", "提出", "遺伝", "コンサート", "##シス", "コマ", "宮城", "買収", "シル", "知識", "イオン", "分布", "仮面", "加盟", "患者", "互い", "体重", "##ud", "1943", "ライフ", "##メートル", "リング", "食品", "##ive", "先発", "失っ", "組み合わせ", "カリフォルニア", "調整", "Pl", "十分", "否定", "果たす", "哲学", "負傷", "チャート", "アイル", "神経", "パーソ", "ヤマ", "##一郎", "Sp", "伊藤", "青森", "大幅", "合格", "送り", "##ight", "合流", "サイド", "推定", "##衛門", "##ミュ", "小林", "市街", "同士", "藤原", "宮崎", "収容", "トレー", "必ず", "##ウント", "大和", "潜水", "##ne", "危機", "無料", "##かさ", "##ort", "アウト", "敗北", "逃げ", "##ッテ", "ジュニア", "1952", "せん", "グランプリ", "##サス", "やや", "結局", "録音", "執行", "始まり", "臨時", "空軍", "改善", "古墳", "殺人", "メイ", "スウェー", "ウルトラ", "画家", "希望", "乗っ", "スイ", "書店", "150", "十字", "##チャー", "##io", "姉妹", "##UN", "つき", "免許", "上昇", "財団", "オーディ", "落と", "武装", "合成", "##ろし", "インディ", "スウェーデン", "進ん", "まず", "イスラ", "##サル", "鎌倉", "不足", "##ue", "用意", "公立", "概念", "##エスト", "スコット", "命じ", "拒否", "基づく", "大分", "カール", "バンク", "注意", "多かっ", "シンガ", "プライ", "1957", "おお", "だい", "侵攻", "前身", "優れ", "統治", "##ビエ", "まつ", "深夜", "じゃ", "##ルタ", "自宅", "戦う", "##リュー", "183", "やり", "ボク", "ヘッド", "##ーグ", "弟子", "楽し", "オート", "さまざま", "一族", "論文", "竣工", "試み", "##ティック", "##イヤ", "北緯", "##イム", "あい", "清水", "閉鎖", "スクール", "結合", "##レート", "承認", "呼称", "拡張", "専攻", "##っと", "1953", "衛星", "地点", "1942", "金融", "オープニング", "ハード", "マリ", "支店", "1951", "次第", "ころ", "##ブラ", "1930", "ちょう", "##起こ", "##でに", "マイル", "##FC", "場面", "##トリ", "1946", "Ne", "さい", "祖父", "ホワ", "学習", "##11", "しん", "共演", "サウンド", "スペース", "##ッタ", "ノル", "すでに", "コンク", "モンスター", "やが", "BS", "兵士", "同名", "ジャンプ", "次い", "描写", "たく", "##ッハ", "強制", "##シック", "指示", "##ドリ", "置い", "##パス", "過ご", "秘密", "De", "##ge", "##ロール", "クー", "かかわら", "表す", "現象", "藩主", "改名", "アイルランド", "ミス", "区別", "ダブル", "実業", "増え", "左右", "広告", "メキシコ", "通っ", "ポルト", "ビジネス", "フィールド", "有効", "こそ", "##ピン", "略称", "##レーター", "毎週", "古い", "燃料", "##ティア", "判決", "三菱", "変身", "プロレス", "スキー", "アレク", "国会", "##ran", "各種", "三重", "現地", "守る", "軍人", "人類", "メモ", "積極", "歴任", "作中", "生じ", "コラ", "携帯", "流れる", "##てる", "やがて", "リスト", "価値", "見つ", "相互", "支払", "低下", "興味", "##リーナ", "よし", "メル", "移管", "ケース", "武蔵", "原則", "短期", "山形", "##ity", "司会", "規制", "事態", "加藤", "改修", "PS", "差し", "信頼", "テロ", "ボーカル", "付属", "ウェブ", "法学", "いき", "南西", "住む", "##ターン", "往復", "##ian", "##OC", "Mar", "戦略", "##クル", "小田", "モノ", "完了", "自転", "手段", "バレー", "称し", "##ペン", "翻訳", "カット", "福祉", "ラテン", "ヒト", "あと", "##ナイ", "マッチ", "死後", "タレント", "##デス", "GP", "かん", "現実", "駅前", "わたっ", "ターミ", "中部", "##ベルク", "数多", "歩兵", "シア", "テキ", "職員", "すなわ", "すなわち", "ディー", "イエ", "ダー", "育成", "テク", "##次郎", "##スタント", "遺産", "ホワイト", "結び", "フランク", "うえ", "植民", "海上", "投資", "76", "協議", "マラ", "福井", "求める", "SH", "ベト", "走行", "属し", "貿易", "送っ", "証明", "外交", "抵抗", "##our", "長く", "クリア", "コム", "##組み", "##ッズ", "##クシー", "Pro", "留学", "##ティン", "考える", "数学", "Com", "集落", "若い", "プレミア", "ドア", "ワシ", "大半", "LI", "修道", "ソフトウェア", "アクション", "超え", "こちら", "##チュア", "有し", "コミック", "募集", "申し", "##デー", "##ry", "##ゼン", "北西", "移住", "高度", "フライ", "英国", "ヒュー", "渋谷", "##シャー", "空気", "見え", "広場", "マス", "反乱", "トーク", "大賞", "ヒル", "遅れ", "##ントリー", "Th", "##キン", "知る", "##ate", "めぐ", "まさ", "クル", "もつ", "人名", "クライ", "超える", "##リコ", "パイロット", "住ん", "##AG", "生息", "話題", "表面", "開か", "資本", "至っ", "感情", "集中", "Le", "メッセ", "装甲", "レコー", "まとめ", "マグ", "予備", "東洋", "120", "##ib", "数多く", "ファイル", "プラン", "掛け", "月曜", "ジャック", "基づい", "本拠", "##ED", "将来", "護衛", "179", "Un", "アクセス", "1889", "突き", "1920", "フィン", "取材", "役所", "楽器", "はず", "##ich", "再建", "エジ", "ボタン", "平日", "暮らし", "マリア", "震災", "代理", "どこ", "戦隊", "笑い", "スタジアム", "スプ", "国王", "残る", "##モンド", "99", "東経", "ターミナル", "##ーマン", "バレ", "満た", "王者", "格闘", "チュー", "規格", "がっこう", "ムー", "##から", "八幡", "体験", "相撲", "聞い", "衝突", "相談", "事情", "学者", "##ゼルス", "テン", "いか", "コス", "正体", "終わり", "東西", "パーソナ", "放射", "茨城", "議長", "先生", "##フレ", "コロナ", "電鉄", "中間", "72", "##ジット", "引き続き", "ベトナム", "キャリア", "議論", "ハリ", "きょう", "吹き", "北東", "強力", "訪問", "終え", "フット", "手法", "##やし", "教室", "名付け", "##ログ", "##フォード", "##ect", "締結", "##取っ", "井上", "分子", "渡辺", "本編", "ロケット", "ケン", "ドン", "過程", "##IR", "##ーマー", "保有", "##ニュ", "01", "協定", "##トラ", "##LE", "諸国", "##ゴル", "カタ", "##ord", "##ランス", "##ph", "個体", "集合", "居住", "記さ", "北京", "提携", "##ビル", "ネーム", "エク", "オーバー", "1939", "##II", "シート", "当たる", "##ワイ", "##40", "ウェイ", "目指す", "重量", "しゃ", "##タイ", "応援", "次元", "##ack", "##ねる", "群馬", "600", "達し", "週刊", "残さ", "##合っ", "受け入れ", "##ンダム", "暗殺", "レーベル", "##レッジ", "音声", "人形", "182", "カイ", "翌日", "800", "深い", "要請", "##OT", "警備", "##ームズ", "発達", "譲渡", "学ん", "実力", "流行", "プロデュース", "着用", "ハンガ", "つまり", "従っ", "ポルトガル", "オフィ", "77", "ソビエ", "##なた", "地帯", "人生", "##ION", "証券", "出さ", "##リウス", "箇所", "部下", "ワシントン", "シャー", "殺し", "進化", "##AK", "##ナン", "動作", "早く", "##カイ", "各国", "ソビエト", "際し", "軍団", "取り上げ", "生み", "養子", "カトリック", "歴代", "バスケット", "さく", "85", "戻る", "クイズ", "ごろ", "天然", "ラグビー", "##ff", "181", "コミュニティ", "守備", "入手", "男女", "##60", "ビッグ", "ブラン", "統計", "昇進", "世帯", "午後", "信仰", "悪魔", "傘下", "1937", "脱出", "##ass", "公表", "和歌山", "幹部", "そんな", "観客", "転換", "##違い", "変わっ", "従事", "確立", "##IM", "ハル", "ゴルフ", "駅舎", "渡り", "##ハー", "アメリカン", "限ら", "グロー", "ベルリン", "##カス", "##ヌス", "初頭", "##ain", "ペル", "じょう", "コメント", "プロダ", "おか", "##ows", "西側", "とう", "売却", "離脱", "投入", "PR", "買い", "ドー", "繰り返し", "タン", "ベン", "幼少", "伸び", "##AY", "NE", "発着", "手が", "心理", "緊急", "両方", "平方", "多様", "手紙", "四国", "生成", "ソー", "操縦", "ボーイ", "沿い", "##キャ", "ユーザー", "進む", "終盤", "##per", "普段", "中世", "池田", "活用", "モチ", "描く", "無線", "演劇", "史上", "良く", "##チュー", "長期", "##プス", "王子", "義務", "##ドゥ", "ソウル", "##end", "連携", "くん", "規則", "収入", "境界", "初め", "エジプト", "##ast", "全米", "Cl", "側面", "敷地", "コラボ", "取る", "セレ", "岩手", "解体", "スイス", "セイ", "末期", "ドゥ", "ロバート", "南東", "##ハン", "サム", "No", "上映", "アイス", "##Tub", "ロサン", "書籍", "##EL", "ドライバー", "投稿", "##ING", "あげ", "戦艦", "1936", "##プロ", "選抜", "打率", "ギリシャ", "たま", "メガ", "一切", "ロサンゼルス", "参議", "ヒー", "上げ", "徐々", "興行", "商店", "##兵衛", "輸入", "先行", "Wind", "コピー", "女王", "##ーナメント", "たと", "正確", "政党", "上野", "社員", "ロス", "88", "##ボード", "人工", "発揮", "画像", "補助", "##ッピング", "##フィア", "ハンド", "起こっ", "全長", "接触", "リニュー", "争い", "手術", "##ーリ", "##テイン", "グランド", "AC", "ガンダム", "現存", "ボディ", "新田", "##IG", "マジ", "##ッス", "アント", "午前", "リニューアル", "スティー", "合意", "古く", "キュー", "爆弾", "大人", "ロング", "態度", "栃木", "栽培", "パートナー", "ウル", "プラス", "恐れ", "1938", "##ボー", "スピード", "巨人", "リュ", "暴力", "モスク", "附属", "顧問", "##ベルト", "国勢", "##pp", "##立つ", "レオ", "実質", "ディレ", "最多", "##マル", "半分", "86", "機種", "伯爵", "はる", "人員", "答え", "ハンガリー", "##分け", "トーナメント", "ネタ", "働き", "約束", "酸化", "構想", "アウ", "解釈", "下記", "95", "コロン", "社名", "##バス", "##ヴァー", "仏教", "職業", "73", "##70", "西武", "##コール", "メール", "働い", "太郎", "金沢", "モーター", "子ども", "高知", "YouTub", "戦死", "66", "終点", "授業", "自殺", "178", "ミュ", "国境", "同期", "Am", "BO", "エース", "##レル", "##ver", "##te", "中山", "ランク", "財政", "具体", "死ん", "ヤン", "シュー", "予想", "殺さ", "ブレイ", "ブレーキ", "コル", "ジョー", "しば", "悪い", "##の子", "複雑", "よい", "現れる", "防止", "連結", "赤い", "##セント", "頭部", "明る", "クイ", "渡っ", "##シップ", "アム", "トルコ", "パル", "大手", "##ブレ", "##ah", "夫人", "評論", "78", "交代", "##ピア", "##ey", "隠し", "ちなみ", "SS", "ファッション", "##wit", "付い", "##たい", "順位", "com", "創刊", "##セプト", "フィルム", "北朝", "尋常", "構築", "##合う", "##RE", "下り", "材料", "分かれ", "160", "合同", "絶対", "授与", "活性", "守護", "恋人", "冒険", "##ロード", "ドーム", "キャッチ", "バスケットボール", "レコーディング", "出走", "続き", "割り", "料金", "かわ", "##立っ", "修正", "神話", "災害", "ダメージ", "寄せ", "ロゴ", "来る", "アニメーション", "駐車", "必殺", "決意", "性質", "ロン", "##ミス", "モチーフ", "##ライト", "##ly", "ポリ", "武田", "サル", "会話", "MS", "コメ", "沿岸", "アタ", "ハート", "悪化", "類似", "##ens", "扱う", "##プレ", "##稲田", "脱退", "##ルトン", "たる", "トヨ", "保持", "##az", "明確", "本当", "68", "##キア", "修了", "##ルター", "ドラム", "整理", "ホイ", "聞き", "パーソナリティ", "一致", "##ミニ", "##入り", "アート", "バラエ", "MC", "AS", "タンパ", "在学", "##もり", "両者", "キン", "曰く", "1935", "標高", "コア", "措置", "ドラフト", "81", "早稲田", "ステーション", "シカ", "単行", "オペラ", "佐賀", "##ベット", "##オス", "##パート", "02", "銀河", "##ない", "1933", "Go", "芸人", "様式", "辞典", "ヘンリー", "違反", "血液", "##コー", "止め", "プロダクション", "極めて", "決まっ", "起点", "関与", "##チス", "小さい", "メッセージ", "公認", "##ウェイ", "大将", "戦国", "退職", "勝負", "1934", "確定", "講談", "病気", "跡地", "エンター", "圧倒", "監視", "上海", "経緯", "あらゆる", "混乱", "出会い", "Su", "振興", "##つき", "瀬戸", "優先", "74", "数字", "たび", "回数", "上陸", "71", "コレクション", "テニス", "パフォ", "レスト", "称さ", "ギリシア", "再度", "会館", "次男", "対決", "トライ", "マイケル", "当日", "##越し", "##シュタ", "姿勢", "とど", "改め", "予算", "装着", "1932", "新規", "Con", "いえ", "絵画", "SC", "放映", "Windows", "看護", "リード", "##レンス", "モンゴル", "82", "古典", "##ix", "1928", "づけ", "異常", "##ーナス", "##テインメント", "ラブ", "大隊", "加工", "亡くなっ", "利益", "##フィック", "##オー", "たか", "アレンジ", "センチ", "時計", "発動", "引き起こ", "見せる", "##ニャ", "ライバル", "まっ", "以内", "作者", "てる", "EX", "遠征", "印刷", "激しい", "##サイ", "著書", "差別", "主力", "木曜", "組ん", "輸出", "支部", "ナンバー", "後方", "フェル", "##ld", "##々木", "ゼロ", "容易", "##どり", "山梨", "申請", "通う", "重視", "あなた", "##なし", "98", "鳥取", "帰還", "短い", "生涯", "デス", "##直し", "ジャケット", "収集", "書房", "本体", "##ージュ", "団地", "即位", "しばらく", "##上げる", "開い", "ガラス", "ヴァン", "##ore", "石油", "##シル", "1929", "戦線", "ウィル", "柔道", "フィリピン", "##ンバ", "メロ", "先輩", "劇団", "およそ", "言及", "外部", "権力", "誘導", "関心", "推薦", "もっとも", "上下", "ストリート", "##90", "##プラ", "違う", "あき", "滞在", "小野", "解除", "北朝鮮", "##ang", "ボル", "有力", "##セット", "##三郎", "称号", "##ッパー", "木村", "一員", "1923", "改札", "不詳", "測定", "下部", "ポート", "先端", "SU", "##ial", "##クソン", "##らえ", "トランス", "ワイド", "深く", "保守", "変換", "Gr", "##フィー", "恋愛", "##TR", "FIFA", "一家", "04", "北側", "復興", "05", "コート", "象徴", "フリ", "奴隷", "問わ", "イー", "イスラエル", "印象", "とおり", "##・デ", "トヨタ", "再現", "私立", "けい", "##ツェ", "Pr", "1931", "##チョ", "東側", "ディスク", "##フォーム", "スケート", "子孫", "リチャ", "参謀", "ジム", "ブログ", "信じ", "依存", "半ば", "すら", "さえ", "球場", "##回り", "トム", "学び", "該当", "1927", "一体", "過ごし", "著名", "##サイト", "スカイ", "させ", "##たま", "スラ", "搭乗", "1924", "駆け", "ニッ", "アミ", "スポンサー", "振る", "おこ", "##oh", "区分", "デモ", "ジェームズ", "出発", "千代", "06", "マガ", "爆撃", "ミラ", "併設", "インチ", "楽団", "証拠", "##フス", "空中", "##ケン", "除い", "ショップ", "蒸気", "触れ", "重ね", "追放", "##之助", "白い", "ひろ", "出馬", "ゴールデン", "ローカル", "かかる", "費用", "考慮", "有限", "ジャンル", "火災", "劇中", "コンセプト", "意思", "III", "プリン", "オーディション", "中野", "黄色", "##メイト", "上部", "ヒーロー", "学ぶ", "Be", "敗退", "道具", "##ber", "##んじ", "##uc", "気象", "電動", "##クタ", "盛り", "##GM", "##ice", "平安", "メカ", "交響", "意図", "##age", "ジャズ", "for", "高松", "##テッド", "ミュージシャン", "いけ", "抱い", "##ide", "タッグ", "出来事", "侵入", "黒い", "下車", "くれる", "ハム", "同月", "太田", "03", "離婚", "外見", "打撃", "フロント", "戻り", "##センス", "##ss", "##ボル", "##べる", "願い", "ソン", "170", "国土", "キック", "ヒロイン", "##EST", "83", "当該", "メン", "辞任", "短編", "##AA", "##しみ", "ゴールド", "##ッシ", "##ノス", "##ナルド", "プール", "幼い", "##たく", "流通", "ディズ", "08", "単純", "もともと", "不可", "引っ", "再会", "複合", "長年", "直通", "当主", "リスナー", "バイパス", "GT", "ファミリー", "屋敷", "##ラント", "異なっ", "最近", "歌っ", "ゴー", "まち", "ピン", "ワイン", "戦っ", "##IL", "学術", "委託", "入れる", "##ST", "ごう", "##ンパス", "修理", "抑え", "故障", "コール", "屋根", "上り", "En", "最低", "##ーマンス", "##ライズ", "クレジット", "愛媛", "東映", "ノース", "##ストロ", "スコットランド", "資源", "マネージ", "87", "スパイ", "許さ", "探偵", "直線", "主体", "タンパク", "部品", "にく", "負担", "トイ", "##リット", "思う", "示さ", "エディ", "台風", "1926", "TR", "チャールズ", "盛ん", "96", "##向き", "キャンプ", "ドロ", "保障", "##ルズ", "移り", "250", "通行", "YouTube", "代替", "月刊", "音源", "シナリオ", "##・マ", "前期", "##ドン", "##立ち", "犠牲", "市内", "##リル", "文献", "パフォーマンス", "夫婦", "AV", "一環", "抜け", "##アイ", "##one", "92", "起源", "ませ", "ユース", "取り扱", "モスクワ", "効率", "幼稚", "自民", "ディス", "分岐", "気持ち", "##ブス", "同級", "ドライブ", "突然", "記し", "食べる", "##OK", "攻略", "nd", "##ナス", "ディレクター", "84", "##iz", "天正", "##ステル", "怒り", "ラウンド", "当て", "区画", "到達", "1925", "SF", "快速", "入口", "キャンパス", "批評", "突破", "伝える", "大橋", "クラシック", "##ヴァン", "バラエティ", "親友", "発掘", "##ジョ", "##ネシア", "ジェット", "滋賀", "漢字", "700", "自社", "終わる", "ポル", "特性", "関数", "##ートン", "##ザベ", "中期", "地理", "##プター", "##チェンジ", "失わ", "あろう", "語り", "言え", "##ティス", "報じ", "スーツ", "##サンド", "信用", "って", "菓子", "衣装", "とる", "もし", "コスト", "分解", "育て", "沿っ", "##ft", "Br", "幅広", "##NS", "住居", "ステークス", "ウイ", "パターン", "ダーク", "110", "67", "次々", "##EM", "援助", "症状", "入力", "##ure", "##ッケージ", "ビー", "マスコ", "経路", "レストラン", "リチャード", "温度", "ポスト", "今後", "全域", "南側", "##ong", "起こる", "射撃", "演技", "聖書", "ヴィル", "訴訟", "配備", "ブラウン", "合戦", "基づき", "##ッティ", "ケーブル", "##かす", "前方", "親王", "##ージェ", "伴っ", "タンク", "##ポール", "##ith", "学年", "循環", "マイクロ", "山脈", "発音", "単に", "おそ", "##ンチン", "CO", "91", "まる", "研修", "近鉄", "春日", "ディズニー", "175", "取り戻", "当たり", "パッケージ", "ケイ", "ホル", "##ンマーク", "期限", "##KY", "コンテ", "デンマーク", "解消", "ビーム", "観察", "教員", "処刑", "ニッポン", "並び", "生じる", "分裂", "##ンジャ", "無人", "資産", "ピエ", "故郷", "続編", "線路", "食事", "取り入れ", "包囲", "日常", "国防", "なぜ", "OS", "会見", "あたっ", "出席", "促進", "ファンタ", "##qu", "事前", "アブ", "##PG", "ジェイ", "校長", "天使", "次ぐ", "ライオン", "スマート", "1922", "オプ", "全面", "たけ", "行方", "既存", "ブック", "閉店", "##ミネ", "ナポ", "落とし", "シカゴ", "エンド", "総督", "松山", "##フル", "動産", "##bo", "借り", "兼ね", "##くま", "抗議", "メタル", "犯人", "建立", "平野", "英雄", "議席", "##下げ", "89", "接近", "##UT", "##ies", "来日", "##ニン", "回収", "##イナー", "共有", "気候", "香川", "##・カ", "神宮", "変形", "推測", "キャスト", "領土", "Co", "下位", "後ろ", "進み", "ピーター", "みんな", "文部", "家臣", "撤去", "受験", "折り", "庁舎", "177", "診断", "塗装", "NT", "##リズム", "織田", "訴え", "退団", "##受け", "CH", "司法", "タワー", "デー", "代わっ", "NP", "さくら", "つか", "マルチ", "クリー", "101", "角川", "ファースト", "ベルギー", "もち", "##クトル", "ミッション", "Se", "##ペーン", "任意", "再編", "読売", "##っき", "送ら", "文明", "マイナー", "5000", "##aw", "1918", "ゆえ", "立っ", "日記", "水曜", "上演", "1919", "定着", "伝承", "79", "パソ", "保安", "肉体", "##ちゃ", "うる", "ソニー", "学区", "避難", "チェコ", "決戦", "マガジン", "##須賀", "##ite", "総務", "タクシー", "ラム", "##モア", "閲覧", "69", "エクス", "中島", "93", "周り", "##ウルス", "とて", "観音", "##man", "所持", "##ire", "継い", "トレード", "働く", "スキル", "発明", "##ポーター", "ライセンス", "インターチェンジ", "地図", "DJ", "走る", "##止め", "スリー", "簡単", "在住", "##ウッド", "中隊", "連覇", "ナショナル", "##回る", "バレーボール", "ノン", "国有", "##フェン", "妖怪", "送信", "09", "キュ", "気づ", "らしく", "忘れ", "##ary", "##ust", "出資", "アマチュア", "一連", "最新", "CP", "前田", "3000", "後任", "1921", "功績", "##66", "フットボール", "##アス", "冒頭", "でし", "抱え", "開店", "##おう", "怪我", "ドキュ", "ミリ", "疑問", "##ock", "加わっ", "双方", "宝塚", "##IP", "特典", "ML", "LO", "##ネマ", "岡田", "シリア", "養成", "占め", "取扱", "ファイナル", "審議", "造船", "ショート", "今回", "スタン", "火山", "焼き", "##OP", "##なか", "##つい", "書記", "##47", "##しろ", "不良", "挿入", "DS", "ヤング", "##シスコ", "デル", "SM", "証言", "した", "LIVE", "記号", "出会っ", "か所", "##ヘン", "130", "ギャラ", "いた", "説得", "##当たり", "ビット", "安打", "FA", "奪わ", "かた", "教皇", "AK", "修行", "開館", "財産", "はじ", "トー", "攻め", "##witter", "独特", "ボックス", "イスラム", "試作", "Play", "コンテン", "AR", "##アリー", "##ジラ", "##22", "ON", "助手", "##まら", "才能", "ラスト", "最強", "バイオ", "##oy", "課題", "示唆", "##ug", "宣伝", "想定", "演じる", "海洋", "##チア", "原題", "##ディングス", "甲子", "##プル", "##ンジャー", "怪獣", "解析", "シャル", "変わら", "フォード", "ツー", "天王", "詩人", "##ond", "近畿", "マレー", "##ウォ", "キャンペーン", "用途", "仕え", "スロ", "架空", "Tr", "##ニスト", "ホー", "ポップ", "高級", "降伏", "ヤク", "ガル", "全線", "移民", "参考", "マリオ", "##33", "##NN", "フレーム", "ざる", "##ドロ", "プロモ", "実家", "捨て", "キャスター", "越え", "三角", "##OD", "ガイド", "信長", "##ゾン", "ch", "経過", "素材", "カテ", "工作", "ボーナス", "##IA", "チャレンジ", "フィリップ", "ラス", "##WA", "駆動", "成分", "認可", "##ish", "##ach", "表彰", "むら", "厳しい", "死者", "除き", "死刑", "ポケ", "フィンランド", "北条", "しょ", "リスク", "パソコン", "属性", "to", "佐々木", "広い", "打点", "##ル・", "##ica", "ブライ", "評し", "実装", "大佐", "たとえば", "テキサス", "将棋", "He", "選定", "##ミック", "大名", "先頭", "短縮", "##ソー", "のり", "##tt", "火曜", "実績", "あの", "話す", "士官", "リアル", "正面", "退任", "##ase", "ひとり", "New", "ガイ", "言える", "後者", "番地", "別名", "##se", "ゲート", "埋め", "座席", "##ライン", "自主", "ロイヤ", "大野", "宇都", "男爵", "キャプ", "田村", "カレッジ", "固有", "1914", "味方", "プレゼ", "要塞", "黄金", "えき", "ニー", "扱わ", "ユーロ", "手掛け", "融合", "しも", "チェンジ", "AM", "森林", "カウ", "##バラ", "決める", "##チル", "題材", "落語", "衛生", "セミ", "ミッド", "賞金", "Ex", "ハワイ", "派生", "並行", "戦時", "イラン", "コミュニケーション", "応用", "掲げ", "質問", "無かっ", "見解", "防ぐ", "プラット", "相続", "相模", "入院", "ウィーン", "モル", "歌唱", "起こす", "パーツ", "創造", "少将", "大西", "##バイス", "北陸", "図る", "コンパ", "台車", "総理", "メトロ", "通る", "保健", "アシスタント", "転じ", "トレーニング", "リオ", "##当て", "宇都宮", "##・ス", "158", "勉強", "Wor", "##ational", "近郊", "粒子", "##取る", "マスク", "倒し", "SE", "取り付け", "##っくり", "アルゼ", "##ャン", "人数", "方言", "トラブル", "##・エ", "##ace", "やすく", "恐怖", "電波", "師範", "ウィン", "スリ", "歌う", "上田", "##レオ", "エー", "運航", "厚生", "浴び", "運輸", "##しま", "出張", "難しい", "外務", "近隣", "巻き込ま", "警視", "キロメートル", "回答", "需要", "ワイ", "移植", "ジャイ", "UE", "1912", "ちゅう", "端末", "遺体", "司教", "一帯", "140", "ロケ", "##カラ", "レジ", "少数", "損傷", "提示", "Mus", "駐屯", "スライ", "疾患", "破り", "地形", "受け継", "Twitter", "いえる", "郊外", "開拓", "ボン", "封印", "想い", "##sh", "176", "AL", "1900", "しれ", "ガード", "取り組", "ピンク", "マリー", "乗客", "非難", "例外", "従業", "##ヒー", "アダ", "若手", "送る", "広域", "不満", "##上がっ", "##つける", "降格", "衝撃", "捕虜", "秀吉", "事例", "##イラー", "##好き", "主導", "多摩", "損害", "持ち主", "接し", "売上", "特集", "関わっ", "支え", "戦力", "低く", "##わし", "##ジュール", "別れ", "提唱", "##らさ", "救出", "併せ", "努力", "1910", "KO", "当局", "武将", "祭り", "勃発", "正義", "カフェ", "終戦", "とても", "##ロジー", "ノルウェー", "国外", "合唱", "特技", "##しん", "##やく", "暫定", "##書き", "最中", "秘書", "市川", "##ェル", "体系", "##ory", "1917", "雇用", "##tern", "聖堂", "アルゼンチン", "夜間", "MV", "急速", "足利", "##KO", "ローズ", "行なっ", "うま", "連勝", "エンタ", "グロ", "放つ", "数々", "反発", "##48", "つける", "存続", "民営", "##ギュア", "上級", "未満", "総称", "##ook", "役員", "就職", "青山", "くらい", "生存", "##フラン", "おも", "しゅ", "IN", "マイク", "慶長", "若干", "Ph", "##ージー", "コンテンツ", "成田", "要因", "##ラ・", "##UM", "日々", "栄養", "わたり", "合体", "苦手", "かける", "ロール", "##ove", "ルイス", "暴走", "分校", "町名", "Vol", "ポンド", "ごく", "北米", "阻止", "改編", "##しゃ", "空襲", "パック", "ファイター", "現行", "競争", "西洋", "友達", "アレクサンド", "商人", "もらっ", "ポン", "Te", "ヴェル", "##ッキング", "松平", "クリスマス", "周波", "Dr", "モール", "海賊", "##われ", "描き", "レーザー", "他人", "彫刻", "成果", "村上", "小倉", "サウス", "CS", "偶然", "エレクト", "##ナショナル", "ゆき", "##21", "UEFA", "山崎", "##ークル", "南海", "二十", "紛争", "帰っ", "中日", "大宮", "水素", "##エー", "07", "軍隊", "向かい", "ベー", "迎える", "一貫", "##ment", "コムーネ", "手がけ", "97", "関わる", "中川", "デザイナー", "高田", "会計", "容疑", "##入れる", "トーマ", "阪急", "ウォー", "三井", "##St", "フィギュア", "及ぶ", "かかっ", "特許", "がん", "圧力", "簡易", "ゲル", "バリ", "日中", "若者", "ゾーン", "##ワン", "##int", "ちなん", "ガール", "感謝", "##ッセル", "ウェスト", "長女", "##ai", "女の子", "BL", "1913", "ストライ", "##ゲル", "ヨー", "上流", "検出", "##寄り", "橋本", "ウェブサイト", "同僚", "語る", "ボクシング", "切れ", "Web", "占める", "##返す", "表し", "長谷", "168", "琉球", "近づ", "1911", "サス", "登山", "騎兵", "テープ", "勲章", "レスラー", "師事", "運賃", "取ら", "##ヨン", "ビール", "美しい", "車線", "##トー", "並ん", "立ち上げ", "コントロール", "アキ", "##エフ", "##VA", "水戸", "##ert", "カム", "雰囲", "雰囲気", "##44", "オプション", "したがっ", "小川", "##ick", "倒す", "騒動", "てん", "パネル", "ポケモン", "戦前", "評議", "Sc", "マサ", "##pe", "##FL", "Sch", "読者", "##イルド", "市営", "テル", "レンズ", "グレイ", "開局", "和田", "レーダー", "競輪", "##・ド", "ヘビー", "レン", "威力", "五十", "インドネシア", "オフィス", "高齢", "And", "家督", "逃亡", "CR", "シンガポール", "航海", "ふく", "任じ", "一旦", "##iss", "サンタ", "オリコン", "上京", "ショッピング", "インディアン", "学位", "家康", "打ち上げ", "カロ", "決議", "構内", "憧れ", "Me", "風景", "##レード", "権限", "高山", "延期", "じゅ", "ついに", "##ツァ", "この頃", "救助", "北方", "コメディ", "実用", "修復", "ベルト", "改めて", "うた", "頻繁", "コンクリート", "ソース", "招待", "逆転", "かい", "まん", "王朝", "社団", "##タウン", "スミス", "召喚", "根拠", "反映", "打者", "JAP", "アサ", "立つ", "財務", "HD", "ホールディングス", "出典", "間違", "保育", "高原", "官僚", "署名", "正月", "##リフ", "ジャーナ", "Ad", "165", "坂本", "引用", "##ath", "協同", "マックス", "やる", "タイヤ", "降り", "全身", "本店", "##まえ", "豊か", "仕掛け", "オーク", "ベンチ", "出産", "##ッシャー", "認める", "相対", "小山", "応募", "指し", "ショット", "気付", "倒れ", "削減", "請求", "ミュージカル", "三振", "接する", "マラソン", "あくま", "告げ", "1908", "カンパ", "船団", "##エット", "修士", "海峡", "アンダー", "もらう", "小さく", "終結", "トーマス", "マニ", "移っ", "スカウト", "医薬", "勧め", "質量", "オーケ", "ミル", "##41", "空母", "排除", "##スラ", "トイレ", "コミックス", "豊富", "放出", "Ed", "補給", "函館", "大島", "当地", "宮殿", "供用", "Sy", "豊田", "とら", "目撃", "東海道", "##ジーランド", "タッチ", "療法", "##ドウ", "ジャー", "大韓", "繁殖", "創作", "老人", "ニュ", "ペア", "航路", "施さ", "サイン", "山陽", "エドワード", "al", "中断", "ニュージーランド", "入門", "コマンド", "繰り広", "旅団", "横須賀", "開放", "パンチ", "走り", "動員", "山下", "中将", "##イセン", "マネージャー", "オレンジ", "喫し", "ちょ", "ボート", "一郎", "行事", "ステップ", "マップ", "##レム", "悪く", "IT", "国連", "小松", "##プレイ", "##かける", "ウッド", "史料", "行なわ", "BGM", "訪れる", "おく", "##pt", "関わら", "野村", "##uk", "##チック", "カス", "フー", "プレゼント", "メタ", "岡崎", "魚雷", "本土", "編纂", "##フラ", "イラク", "いま", "##九州", "コロンビア", "北九州", "実況", "撃破", "挙げる", "国籍", "装飾", "スタンド", "ディーゼル", "受信", "##メンタ", "IB", "##久保", "待ち", "認知", "出土", "##ケード", "##かく", "##イラ", "夫妻", "制覇", "半年", "有料", "閉じ", "ネイ", "##リダ", "##・オ", "ショック", "JAPAN", "あくまで", "クリエ", "##たび", "東方", "##oun", "##99", "##45", "度々", "浜松", "変わる", "意向", "酵素", "プロセス", "覚え", "三十", "##ベン", "一面", "1915", "わたる", "ペット", "地獄", "##ーノ", "セルビア", "名乗っ", "縮小", "##切っ", "Car", "前日", "Col", "ツール", "保管", "##っかり", "コンテスト", "NC", "義塾", "エリザベ", "基盤", "語ら", "補佐", "ドリーム", "嫌い", "同行", "心臓", "主流", "##ii", "1907", "チェーン", "##テーション", "シンガー", "感覚", "アルファ", "魔女", "炭素", "##ヴィッド", "インターナショナル", "番線", "量産", "ねん", "セー", "##カリ", "奉行", "強調", "踏み", "大気", "告白", "瞬間", "飼育", "##スティバル", "乗降", "高野", "落選", "ふる", "HP", "放棄", "125", "##apan", "ギア", "クロー", "ウラ", "レンタル", "遭遇", "騎手", "キャプテン", "女神", "三郎", "無視", "延伸", "マド", "避け", "上場", "式典", "徹底", "メモリ", "積み", "皇后", "妨害", "庭園", "##レオン", "171", "ニック", "配属", "##ースター", "配布", "番台", "破っ", "鉱山", "アリス", "吉野", "君主", "##なう", "MLB", "名乗る", "エキ", "慶應", "アナログ", "バイク", "##ivers", "好意", "OF", "都合", "##ガス", "品種", "##ネイ", "##ence", "-)", "##ile", "プロモーション", "寄り", "オスマン", "ネオ", "バレエ", "渡る", "正規", "クール", "ビュー", "不安", "伊達", "加速", "薩摩", "##ロウ", "控え", "移し", "偵察", "フォーク", "ヴァイオ", "##むら", "総会", "切っ", "艦長", "飲み", "魔術", "人種", "埋葬", "ワー", "講演", "レディ", "山地", "##まれ", "亡命", "##61", "倒さ", "##ps", "ブーム", "戦術", "削除", "変動", "突入", "##ae", "ヴァル", "##っきり", "あさ", "リク", "制し", "検索", "米軍", "限界", "フェア", "不能", "My", "船舶", "155", "寄付", "兼任", "161", "時刻", "乗せ", "守り", "魔王", "##わさ", "##TC", "休日", "容姿", "アトラン", "ダニ", "つれ", "敗戦", "日産", "石井", "山岳", "ルーム", "1906", "AP", "容量", "UN", "木造", "DC", "通貨", "##EE", "##ier", "境内", "予約", "密度", "王位", "島根", "ロイヤル", "発覚", "##28", "弱い", "諏訪", "##上がり", "墓地", "前提", "なくなっ", "予測", "考案", "なれ", "ないし", "廃車", "張り", "ダウンロード", "##ee", "##DS", "アラビア", "ランプ", "日立", "1916", "先駆", "割合", "三浦", "担っ", "##ラク", "アラブ", "評さ", "##右衛門", "900", "オーナー", "転向", "##取ら", "実践", "後藤", "不正", "##クセン", "回路", "プレス", "アプリケーション", "水産", "プロイセン", "DNA", "流域", "遊び", "天体", "かね", "激しく", "フィル", "##31", "確率", "##サウルス", "入場", "集まっ", "##ime", "オーケストラ", "戦場", "近藤", "成り", "カテゴ", "リバ", "奏者", "直径", "カップリング", "毎回", "壊滅", "マツ", "広がっ", "バランス", "魅力", "種族", "##35", "改装", "1909", "東急", "外観", "##エラ", "刑務", "レール", "総裁", "157", "スロー", "陥っ", "ボード", "変える", "審判", "生き残", "ヤード", "公社", "歌劇", "動力", "美濃", "シド", "維新", "農民", "講座", "失い", "イル", "世話", "所蔵", "落下", "消え", "ほしい", "##エム", "##マイ", "##AX", "##キスタン", "ユニバー", "下し", "地中", "##アフ", "外科", "混合", "おそらく", "賛成", "入賞", "出店", "臨床", "cc", "後輩", "アポ", "河内", "##ont", "##メンタリー", "結ば", "余儀", "##グル", "ハンター", "会津", "Ver", "理想", "テクノ", "斎藤", "フェスティバル", "日野", "室町", "##KYO", "##渡し", "最小", "流し", "スイッチ", "ブルース", "三島", "晩年", "マンション", "着手", "博多", "スコア", "ニン", "横断", "領主", "##ブロ", "征服", "##バーグ", "当たっ", "コンクール", "##シオ", "##IV", "##とめ", "La", "成人", "黒人", "##ミル", "ディア", "ギル", "謝罪", "りゅう", "##思議", "宿泊", "##メル", "ストーン", "福山", "階段", "##テス", "数値", "絶滅", "##ペル", "大谷", "##付ける", "フリードリ", "りん", "手伝", "パーティー", "復讐", "独占", "車内", "隠れ", "-』", "初演", "ガリ", "もたらし", "ラーメン", "オレ", "放っ", "東宝", "背中", "売り上げ", "叩き", "環状", "Par", "選ぶ", "リミ", "大切", "セブン", "前線", "小屋", "妊娠", "自称", "配給", "コーヒー", "レビュー", "##ハラ", "フェリー", "視点", "主任", "Man", "通学", "ドクター", "墜落", "抑制", "##ニコ", "誇る", "ダービー", "あわせ", "図っ", "着陸", "##ッソ", "##ケート", "婦人", "支流", "重賞", "##リヒ", "on", "逃れ", "Joh", "原理", "百貨", "陥落", "内蔵", "にくい", "正解", "武士", "吹替", "ボストン", "##25", "天才", "ベネ", "プレミアム", "みや", "天保", "電源", "ようやく", "サークル", "尽力", "ドキュメンタリー", "ゲイ", "AN", "##ium", "159", "##チャン", "久保", "文芸", "警戒", "公爵", "交点", "どんな", "数え", "ID", "ハーフ", "エンジニア", "師匠", "拘束", "クラウ", "TOKYO", "置き換え", "交際", "旧制", "観点", "##ニオ", "比例", "Or", "学名", "真実", "ルーマ", "##エンス", "SD", "イリ", "表題", "##ドラ", "##モス", "##もん", "##バード", "##ノール", "ノート", "##TA", "イェ", "並ぶ", "運命", "##IX", "IP", "エージェ", "教科", "カプ", "##フィール", "ルーマニア", "ジャーナリスト", "World", "##Station", "##ハウ", "Japan", "アーム", "ファー", "気温", "チップ", "性的", "推移", "文章", "##アップ", "メス", "乾燥", "さいたま", "CL", "##がい", "負っ", "1905", "ヘリコ", "向き", "##rom", "じゅう", "##ニックス", "94", "内務", "失点", "開き", "座標", "水系", "青い", "##TV", "##・ク", "##アニア", "##美子", "スティ", "いろ", "変わり", "山頂", "甲斐", "任期", "##はり", "ナビ", "リゾ", "##掛ける", "1897", "野田", "##テイ", "ファンタジー", "去っ", "##ベニア", "使える", "体力", "役場", "間隔", "アプ", "浦和", "武道", "釣り", "##ost", "##フォン", "とく", "上杉", "両国", "避ける", "スピン", "ワーク", "##ニカ", "ラップ", "荷物", "パナ", "不思議", "種目", "書く", "引き継い", "調理", "ナチス", "ラウ", "牽引", "##ネー", "焼失", "踊り", "プロテ", "和解", "##リード", "つもり", "リト", "##ound", "酸素", "水上", "飾っ", "内側", "グラス", "##ail", "App", "##ナイテッド", "大津", "調達", "##BO", "馬場", "伊豆", "藤田", "死ぬ", "囲ま", "PlayStation", "Fl", "##IO", "##ビリ", "上手", "力士", "築い", "ゴル", "前回", "フリードリヒ", "上院", "典型", "捜索", "同人", "定員", "物資", "##ライター", "襲わ", "JC", "リベ", "1903", "フロリダ", "太字", "熱帯", "むしろ", "安倍", "##ical", "濃度", "珍しい", "IM", "##ux", "双子", "ターン", "1896", "##シュタイン", "道場", "実在", "含ん", "消し", "紋章", "調教", "##ッスル", "バカ", "儀式", "伝わる", "刺激", "歌舞", "源氏", "我々", "やはり", "バット", "加賀", "選考", "せよう", "ミシ", "アラン", "##38", "##バイル", "化合", "確実", "##oo", "ツイン", "保証", "##日市", "液体", "##詰め", "##ann", "化石", "無理", "キル", "プル", "在位", "##ビング", "##TS", "##チナ", "プロト", "##ウロ", "前面", "夕方", "総長", "ヘリコプター", "##デア", "ゲージ", "叔父", "表紙", "鹿島", "##セロ", "近江", "レーシング", "対照", "105", "スポット", "リズム", "介し", "重力", "Ser", "愛し", "シルバー", "喧嘩", "##かん", "出入", "##UE", "プラザ", "予告", "神田", "五輪", "人格", "下院", "狙っ", "##ロフ", "##isc", "##ベース", "##さん", "##テク", "##ern", "フィート", "尽く", "部族", "検察", "無効", "軽量", "##カンド", "チュ", "はら", "エリザベス", "捕らえ", "キム", "活発", "天神", "皮膚", "青春", "##リアル", "##ウィン", "パロ", "南方", "コウ", "ナン", "同等", "##ax", "プログラ", "チェック", "有機", "Wh", "明日", "空手", "出撃", "コーラス", "ダイヤモンド", "クルー", "海戦", "1890", "下旬", "読む", "##・コ", "欧米", "バイエル", "調べ", "山中", "看板", "信濃", "宮廷", "職人", "楽章", "ゆく", "元気", "町内", "すぎる", "同意", "まったく", "牧場", "##いち", "室内", "電化", "人事", "##ットー", "主役", "1500", "1901", "制服", "品質", "交戦", "懸念", "演説", "論理", "##ミネート", "面白", "白人", "169", "校名", "考古", "業績", "乗り入れ", "ユナイテッド", "##ビュ", "ラリー", "正しい", "##ザーズ", "##楽部", "甲板", "##ぐる", "ビーチ", "オオ", "グレート", "アベ", "達する", "長編", "敵対", "構え", "ライター", "ABC", "天気", "##orm", "三木", "公国", "福田", "電機", "ミラー", "ターボ", "##落と", "外れ", "なき", "内戦", "立地", "車庫", "167", "アーケード", "##なく", "シアター", "ハイン", "大坂", "心配", "##回っ", "周期", "115", "倶楽部", "重複", "NBA", "##フランシスコ", "##アフリカ", "シネマ", "高め", "配下", "気筒", "阿部", "首位", "キス", "要望", "##ash", "教団", "ティー", "##オル", "DD", "##ドイツ", "ダイナ", "人権", "ジョーンズ", "スル", "セン", "付与", "##ンガー", "WW", "GO", "アリーナ", "アダム", "ムーン", "会談", "高架", "##ナント", "サンフランシスコ", "レイン", "吉川", "プレート", "勝手", "フォース", "RE", "しり", "担う", "シャン", "あん", "ゴム", "##39", "季節", "ピク", "見な", "アルコール", "ストア", "土佐", "結論", "##ズル", "学長", "インスト", "出会う", "NTT", "贈ら", "アルバイト", "クイーン", "侵略", "本項", "1904", "バーン", "解雇", "身分", "##ョウ", "サウ", "稼働", "被災", "##32", "砲撃", "純粋", "勤め", "ヘイ", "進める", "##67", "コラボレーション", "体操", "南アフリカ", "全般", "学問", "山城", "昆虫", "ロッテ", "三河", "135", "買っ", "みる", "参入", "条例", "筆頭", "##oft", "後年", "飯田", "##ーバー", "##ニオン", "ロウ", "##セイ", "退社", "アグ", "京阪", "広報", "起こり", "回想", "水中", "けど", "抱き", "カンパニー", "アーカイ", "##ool", "祖母", "近衛", "ナレーション", "付ける", "エフ", "渡し", "ノミネート", "込め", "圧縮", "水道", "創建", "監修", "満州", "称する", "読ん", "集会", "青木", "ブルガ", "無事", "##ram", "かみ", "きれ", "闘争", "司馬", "著者", "大山", "最古", "##son", "褐色", "センチメートル", "ロマン", "りょう", "レスリング", "役者", "ナポレオン", "事典", "ふじ", "事項", "歌舞伎", "行使", "野菜", "飲食", "##エア", "##ロイド", "後部", "##・パ", "代行", "初戦", "数十", "今作", "就い", "スーパ", "電池", "##バーン", "史跡", "デッキ", "大塚", "毛利", "##ガース", "作画", "##ina", "建国", "配慮", "将校", "顧客", "ガールズ", "食料", "姫路", "巡洋", "大衆", "##太子", "##ずる", "ヘリ", "喪失", "診療", "緑色", "婚約", "シグ", "EP", "隊長", "ED", "通勤", "ジョンソン", "コネ", "降板", "カスタ", "辞職", "中盤", "模型", "ペース", "##しかっ", "AD", "下流", "追っ", "述べる", "乗員", "ヒトラー", "バッ", "##やす", "恒星", "##ローズ", "コンテナ", "単語", "定める", "##コース", "長岡", "整数", "Love", "はっきり", "モバイル", "##づけ", "いれ", "1902", "椅子", "車種", "##五郎", "ジャクソン", "##amp", "##ツィア", "疑い", "##プレス", "客車", "ずっと", "ガソ", "しゅう", "但し", "施し", "眼鏡", "##ガニ", "川口", "##ズミ", "大公", "ロマ", "人材", "決して", "言動", "日光", "薬物", "ケー", "OP", "松竹", "##デター", "EC", "台詞", "外側", "前者", "操る", "発し", "高木", "プラットフォーム", "倉庫", "ファル", "地面", "認証", "次郎", "分間", "グラフィック", "MP", "グレード", "##ハイム", "ブー", "講義", "名鉄", "##ーニャ", "法的", "ジャイアン", "エミ", "救急", "##ッピー", "おき", "抜き", "断念", "漁業", "肖像", "結晶", "##mp", "広がる", "予防", "透明", "##ear", "##着い", "きり", "走っ", "##ペラ", "学級", "##37", "運河", "Comp", "介入", "ガソリン", "ジョージア", "もり", "##打ち", "土木", "##がし", "福音", "こく", "##まし", "はるか", "IV", "住み", "##RC", "##ばさ", "ミドル", "出生", "高崎", "僅か", "神殿", "ならび", "##ダイ", "ヤマト", "歯科", "分かっ", "官房", "スズ", "探検", "受章", "ジェネ", "リゾート", "チョコ", "従軍", "年次", "挟ん", "ミュン", "確か", "大蔵", "盛岡", "生きる", "東武", "長らく", "外野", "挙行", "##捨て", "天井", "支社", "マルクス", "松田", "##シエ", "##ネン", "きょ", "カントリー", "商号", "管弦", "フィラ", "在任", "個別", "滅亡", "##INE", "貸し", "##オケ", "違っ", "ウェル", "島津", "##しき", "##ウェル", "歩行", "##・ハ", "##Hz", "無限", "##are", "1898", "真っ", "スターズ", "みず", "ゾン", "ミステ", "死体", "統括", "フロー", "##ve", "NEW", "vs", "##36", "SO", "大変", "通路", "##ぼし", "チベット", "復元", "LOVE", "検証", "NA", "ジー", "救援", "シンボル", "照明", "##ージャ", "騎乗", "##らしい", "COM", "ポケット", "細川", "覚醒", "序盤", "##ナップ", "救う", "王立", "##ton", "千代田", "Blu", "シェア", "公務", "増大", "冬季", "専属", "チャンス", "重傷", "理学", "開く", "名詞", "UFC", "そば", "バイエルン", "農林", "Lin", "大尉", "##ビジョン", "コイン", "半数", "クレイ", "藤井", "バージニア", "エンタテインメント", "がち", "優しい", "長谷川", "##馴染", "イースト", "主宰", "##old", "受容", "対処", "目覚", "##リム", "##ドー", "PV", "寛永", "降下", "新築", "併用", "全部", "立体", "##27", "暗号", "みどり", "セーブ", "民俗", "返還", "起動", "##hy", "カート", "繊維", "##24", "キーボード", "海水", "路面", "討ち", "同国", "##ばす", "牡馬", "金額", "命中", "##ズマ", "GI", "敷設", "マジック", "衰退", "1899", "砂漠", "Mac", "教養", "耐え", "黒田", "東南", "現状", "ダル", "早い", "Inst", "論争", "##ス・", "ドメ", "元禄", "東大", "スクリーン", "##ction", "トウ", "改組", "##HI", "上がっ", "出雲", "海兵", "ブルガリア", "AAA", "##テネ", "##引き", "Rec", "大好き", "ライナー", "同作", "回り", "みち", "歌謡", "アタック", "扱っ", "rd", "本種", "Music", "##ワール", "集める", "##ヴェル", "##モリ", "どれ", "反射", "細菌", "改築", "大い", "撃墜", "洪水", "たびたび", "##揚げ", "##ox", "##act", "##ノイ", "ゴジラ", "上回る", "抗争", "松井", "沈没", "##左衛門", "無し", "##iel", "##ニョ", "ウォーター", "汚染", "発症", "データベース", "荒川", "##シュー", "住人", "併合", "EM", "明石", "短く", "呼吸", "John", "こだ", "グア", "しかも", "インテ", "ライヴ", "##ics", "カラオケ", "流用", "滑走", "特化", "評判", "##クトリア", "施工", "##ノフ", "##リエーション", "特異", "親子", "石田", "シュート", "マンガ", "ヴェネ", "ラッシュ", "尾張", "統制", "##ank", "##ron", "みなさ", "余り", "ブリッジ", "クリエイ", "投与", "もん", "##PER", "##au", "パーティ", "##stem", "BM", "##リティー", "おう", "精霊", "ホイール", "着工", "##込め", "1873", "ボラン", "1871", "奨励", "監査", "切り替え", "歌い", "浅草", "DE", "##コモ", "##ニズム", "##ヘルム", "GR", "or", "##land", "筑波", "##ろん", "可愛", "##・ディ", "##ッポ", "##リンズ", "ハロ", "モニ", "従い", "東芝", "模し", "標的", "かず", "カレー", "VS", "##ラト", "シミュ", "覆わ", "公益", "恐竜", "##王子", "118", "生かし", "芸名", "サンド", "盗塁", "りつ", "拳銃", "幅広い", "バード", "##リラ", "幼馴染", "原料", "見舞", "欲しい", "フォル", "大地", "治安", "行列", "株主", "セントラル", "中等", "##49", "水泳", "奪い", "深刻", "MO", "年末", "クエスト", "インディア", "住友", "有利", "##69", "##att", "中核", "面し", "##シェル", "河口", "討伐", "大田", "ヨハン", "配列", "省略", "伸ばし", "##メラ", "Live", "##キュー", "350", "銀座", "同市", "本町", "##どう", "SA", "楽天", "##EO", "##ンジェ", "##せん", "殆ど", "ストロ", "##張り", "ママ", "正教", "##ジュアル", "サンデー", "尊敬", "##コロ", "口径", "携わっ", "させる", "水平", "##フスキー", "クラン", "振動", "支払い", "緩和", "こな", "グッズ", "##ムス", "熊野", "##ジメント", "リトル", "幕末", "早期", "エレベ", "小田原", "タイガース", "ジン", "本物", "傍ら", "八王子", "商工", "報酬", "就航", "新作", "グローバル", "あや", "ほん", "佐世", "残留", "港湾", "至ら", "ドレス", "ミズ", "わかる", "分散", "専念", "うまく", "捕手", "佐世保", "誘拐", "クロア", "メアリー", "##AND", "国務", "残す", "##グロ", "ガーデン", "順次", "忍者", "##ゆき", "イチ", "関節", "メニュー", "退役", "ミネ", "##29", "RPG", "ボウ", "聞く", "しろ", "小島", "##ヴィス", "クリーム", "バンダ", "大輔", "##コス", "だん", "豊臣", "##ンプル", "ヴァイオリン", "化粧", "ピー", "樹立", "ギタ", "ラジ", "##ゼフ", "朝廷", "##・バ", "獅子", "Intern", "固め", "変異", "##モニー", "問い", "検定", "##TER", "##AZ", "イヤー", "管区", "つながっ", "ソル", "フード", "牝馬", "##ッヒ", "セカンド", "交易", "封じ", "常務", "ビン", "進歩", "左翼", "丘陵", "当然", "友好", "大久保", "中退", "人称", "BOX", "満たす", "厳しく", "手続き", "##les", "果実", "後日", "El", "解任", "窓口", "鑑賞", "定年", "異名", "失う", "題し", "ストック", "シャルル", "ユニバーサル", "住所", "ダニエル", "招い", "体内", "##ッセン", "済み", "もたらす", "上げる", "推理", "##アウト", "イエス", "ベア", "民衆", "科目", "郷土", "##切ら", "##ERO", "クロアチア", "品川", "チン", "明かし", "景観", "浮か", "切断", "ネル", "開け", "##・ラ", "ルネ", "原田", "シロ", "安田", "製薬", "ローン", "洞窟", "習得", "##あい", "MUS", "五郎", "ブレイク", "##リャ", "モント", "明るい", "##65", "特撮", "ペイ", "レア", "違法", "Ste", "ダグ", "乗務", "県内", "野生", "##olog", "日向", "##ロニ", "箱根", "奪取", "モーニング", "見つかっ", "インス", "グラウンド", "ボブ", "ミックス", "##ザード", "##キット", "博覧", "満足", "たん", "適し", "ギタリスト", "Met", "##ult", "マカ", "##・サ", "##ゲーム", "城主", "白石", "工芸", "広げ", "親交", "法則", "上述", "奪っ", "##レア", "佐野", "取り組み", "抜擢", "望む", "ハリウッド", "アンケート", "生え", "脅威", "##ros", "1872", "PL", "アパート", "##34", "##っこ", "##ローチ", "アバ", "ツイ", "##ACK", "セール", "天下", "航行", "##リーグ", "##ハイ", "改訂", "毎月", "追跡", "大井", "異動", "リッチ", "シュタ", "割り当て", "西口", "永遠", "##っち", "##フィン", "食べ物", "筋肉", "賠償", "リトアニア", "比率", "要する", "阻害", "艦艇", "キューバ", "SL", "##たん", "##ode", "東山", "##ゴー", "ミュンヘン", "京王", "赤色", "引き継が", "人質", "シャツ", "ガラ", "ヨハ", "育っ", "隊員", "kW", "##ount", "技法", "アーサー", "反撃", "コーポ", "メイド", "食堂", "an", "業界", "バイト", "大河", "ヴォー", "ジュー", "礼拝", "法務", "甲府", "##ood", "##ale", "##ome", "CPU", "生前", "##ata", "AKB", "##ame", "ライフル", "耐久", "繰り広げ", "春秋", "入居", "ブロード", "いじめ", "捕獲", "##バキア", "ジェフ", "トニー", "121", "部位", "ペンシル", "発信", "噴火", "老朽", "虐殺", "##ART", "ダンサー", "Gu", "商標", "被告", "神聖", "経歴", "360", "カウント", "ケル", "把握", "旭川", "ストレート", "ジャイアンツ", "幹事", "表情", "シード", "遠藤", "意志", "ハリー", "ホラー", "##チオ", "##ake", "テーブル", "京成", "締め", "貫通", "##ペット", "エコ", "セガ", "##af", "GM", "かく", "廃棄", "横山", "詰め", "ソングライター", "暮らす", "メロディ", "リメ", "ワル", "一行", "バグ", "城下", "転用", "##UB", "水準", "##ミット", "吉本", "初日", "グレー", "府中", "背後", "##ウンス", "ストップ", "みつ", "食い", "プリンス", "公民", "胴体", "警告", "111", "使え", "排気", "##ヴェン", "強度", "なかなか", "ボクサー", "告知", "1868", "熱心", "狭い", "立川", "##ギス", "##ild", "貴重", "定理", "顕著", "挨拶", "遠く", "アーカイブ", "免疫", "標本", "脂肪", "##面目", "ランダム", "取り組ん", "##ance", "小笠", "葬儀", "マネジメント", "ワード", "殿堂", "出品", "ファイト", "数百", "物体", "マウス", "##ンジョン", "まり", "乗る", "呼びかけ", "先代", "2023", "展望", "MBS", "誤解", "##バッハ", "##セフ", "ヴィルヘルム", "光線", "敗れる", "玩具", "少佐", "排出", "落成", "##クチン", "スプリング", "ドール", "後退", "柴田", "流出", "フュー", "地質", "所長", "##edia", "互換", "ブラッド", "シドニー", "出口", "##ky", "メダ", "ロイ", "上空", "上がる", "109", "Fran", "マクロ", "##ベンチ", "権威", "チリ", "造ら", "マレーシア", "TS", "石炭", "アダルト", "リレー", "過剰", "アシスト", "動く", "伝達", "1886", "桜井", "興業", "再婚", "##ict", "技能", "信者", "発注", "赴任", "妖精", "生態", "西方", "##ザス", "RC", "EN", "医科", "望ん", "指令", "介護", "##シウム", "幸せ", "##AB", "今度", "世間", "沿線", "チケット", "起訴", "139", "##oll", "クーデター", "西村", "Ge", "支線", "船体", "めい", "ゲー", "##ork", "垂直", "##yn", "##ゲット", "ビス", "##ホン", "セキュ", "曲線", "譲り", "きゅう", "re", "アッ", "勝っ", "白色", "予報", "##ject", "シールド", "加える", "##itt", "CG", "わかっ", "不要", "完結", "同志", "##ree", "魔力", "取り戻し", "入ら", "ケンタ", "好み", "除去", "種子", "クリスト", "哨戒", "近世", "PD", "詳しく", "じん", "オハ", "全集", "デラ", "マット", "##oci", "128", "療養", "1895", "極端", "職務", "##ッシー", "知的", "新潮", "##ream", "ES", "っぽ", "ミー", "充実", "定数", "技師", "追わ", "真理", "##68", "Ab", "パレス", "多用", "グッド", "Bar", "マドリード", "##ブリン", "知り合い", "ロープ", "売れ", "海底", "借金", "助言", "##セロナ", "体調", "ループ", "##ition", "##っぽ", "冷却", "##orn", "超人", "ユニオン", "##らっ", "伊東", "繋がっ", "防災", "ピエール", "仕組み", "招集", "##ogle", "菊池", "牧師", "遂げ", "移さ", "バルセロナ", "チャンピオンシップ", "##ヴィン", "集配", "都心", "半身", "セラ", "ボイス", "慶応", "ショウ", "声明", "##寄せ", "ハウ", "大王", "Qu", "モロ", "個性", "生み出し", "ISO", "たっ", "庶民", "誤っ", "関わり", "1880", "駅名", "##ott", "まい", "個々", "適応", "契機", "王妃", "申し出", "神学", "##抜き", "マーティン", "判事", "##mer", "電磁", "アルゴ", "首長", "唱え", "##レスト", "国分", "弾薬", "ロビン", "##ガイ", "入植", "因子", "守っ", "満了", "##ータス", "ライブラ", "同性", "最寄り", "ぶん", "支所", "浄土", "エージェント", "岩波", "性別", "1875", "Sm", "タマ", "島田", "代々", "領地", "##ise", "1892", "親衛", "セッション", "太夫", "##ose", "厳密", "特番", "平面", "留まっ", "もらい", "タル", "法令", "##eat", "八戸", "同型", "岡本", "スティーヴ", "##えもん", "拉致", "思考", "##AI", "三田", "加わる", "##ニーズ", "##ヴィチ", "立憲", "アルメ", "1878", "USS", "マスコミ", "成し", "アナウンス", "ピース", "中旬", "タイミング", "上司", "小泉", "##アント", "1893", "ブライアン", "FR", "原型", "突撃", "##まさ", "リボン", "暗黒", "1887", "108", "##ERS", "マーケット", "探索", "襲い", "ネコ", "勇者", "干渉", "捉え", "摂取", "日米", "広大", "低迷", "ピッチ", "いし", "##pr", "##まい", "##切る", "もちろん", "付加", "チームメイト", "帽子", "芝居", "NO", "明かさ", "都立", "骨折", "リメイク", "On", "所得", "海域", "ドメイン", "準々", "符号", "##ベリー", "##ower", "Is", "釈放", "##irl", "精度", "ムス", "キリ", "##CE", "備える", "##シスト", "##IE", "まつり", "##シオン", "見なさ", "家系", "##ヴィア", "アプローチ", "武蔵野", "HE", "117", "水野", "For", "王女", "##ホール", "らん", "##KE", "All", "##ベート", "旅館", "祝日", "あお", "サイクル", "マスコット", "##ポリス", "NS", "デュー", "望遠", "with", "ドラえもん", "なす", "いす", "週末", "解答", "ノベル", "アンナ", "ワイルド", "ナイフ", "ナイン", "夏季", "##26", "##チェスター", "倫理", "視覚", "ダブルス", "勢い", "入れ替", "しっかり", "##四郎", "本田", "自信", "不振", "##ホー", "アンテナ", "ひら", "南極", "対面", "ワークス", "サーバ", "スワ", "不動", "こん", "新しく", "エレベーター", "トマス", "レク", "ホンダ", "公的", "シャトル", "メリー", "正室", "##46", "増設", "台北", "届け", "ヴァージ", "##ナミ", "##ープル", "ウエ", "ビート", "##リオン", "内野", "怪物", "##セッツ", "未だ", "くら", "##リュ", "次官", "面倒", "##ナーズ", "安政", "引く", "つながる", "ペルシア", "皇子", "豊橋", "活かし", "湘南", "##ッセイ", "タカ", "手前", "あし", "金庫", "ギャグ", "小笠原", "わから", "他社", "加わり", "概ね", "##MS", "やら", "美人", "アイデア", "麻雀", "Op", "かぶ", "ひろし", "オイル", "カレン", "セルフ", "ペー", "太鼓", "川越", "##メット", "抽選", "マサチュー", "連動", "紅白", "船橋", "マサチューセッツ", "ホット", "重大", "##MA", "だり", "東口", "金銭", "NAS", "WBC", "飲料", "##コル", "ヤクルト", "##ベンチャー", "AB", "右側", "##ッラ", "トロン", "佐久", "浅野", "Mk", "列島", "爵位", "フラッシュ", "Google", "忠実", "##合わ", "駐在", "##リアス", "富田", "漫才", "1894", "メー", "ブリー", "良好", "ウィリアムズ", "ディスプレイ", "バナ", "今井", "打席", "市制", "採択", "##つく", "クラスメイト", "AI", "1884", "##・イ", "パシ", "YO", "和泉", "越後", "サーキット", "\")", "母音", "院長", "テキスト", "パロディ", "アース", "競合", "症候", "ウェールズ", "れい", "鎮圧", "不在", "交付", "145", "ベースボール", "イーグ", "我が", "151", "潜入", "力学", "払い", "集英", "シフト", "挑む", "河原", "探査", "##ロック", "光学", "宣教", "メディ", "レオン", "撃退", "アドレス", "陣営", "振る舞", "対空", "年金", "根本", "神々", "農村", "パーセント", "エントリー", "イスラーム", "薄い", "難易", "アイランド", "反面", "推奨", "火星", "1885", "ムービー", "てつ", "すみ", "ナム", "下関", "組み込ま", "4000", "Jr", "一気", "突如", "レンジャー", "浮上", "立法", "##ポリ", "カーブ", "パンク", "藤沢", "皇太子", "露出", "合理", "リタ", "##ッサー", "##ニル", "でん", "ゲン", "水域", "都内", "##42", "探す", "西暦", "ベッド", "サンダー", "バルト", "懲役", "見送", "名乗り", "恵まれ", "アピ", "##anc", "剣道", "演習", "##OCK", "教区", "策定", "果て", "羽田", "##ous", "中京", "##ッペ", "##デルフィア", "使者", "最適", "アール", "1876", "デバイス", "チャンピオンズ", "##ハム", "1891", "EU", "基金", "電撃", "コンスタン", "OVA", "逃走", "頂点", "Gre", "##わけ", "前橋", "実戦", "フィラデルフィア", "稲荷", "1874", "同校", "##ノコ", "##ark", "1870", "平行", "見直し", "日程", "浜田", "分から", "##とり", "宮内", "掲示", "高める", "##ンドラ", "教諭", "ブルック", "太子", "明け", "LE", "カジ", "##イング", "やめ", "##明け", "先住", "那覇", "要件", "##ッシング", "##だい", "任さ", "右手", "絵本", "吹き替え", "撃ち", "駆使", "公募", "内田", "農家", "##ward", "押さ", "プログラミング", "##すけ", "引き上げ", "角度", "TKO", "iP", "寛政", "苦し", "ターゲット", "ネー", "##ade", "##ere", "焦点", "識別", "復旧", "1888", "1869", "電圧", "##リウム", "テレビジョン", "はな", "サト", "マウント", "アドベンチャー", "BE", "熊谷", "##けん", "JA", "享保", "制約", "本国", "出荷", "聞か", "花火", "名人", "##ames", "氏族", "気圧", "陰謀", "##pl", "横綱", "##ましい", "##enn", "対称", "119", "Apple", "ヘア", "ダンジョン", "ピーク", "辞退", "方程", "淡路", "思い出", "狙う", "比べる", "総額", "部長", "遅く", "コンピューター", "エロ", "同局", "砲兵", "##がく", "ドミニ", "感じる", "格納", "##ギン", "ホークス", "##oot", "htt", "津波", "年少", "許し", "助ける", "爆破", "Ac", "呪い", "各社", "染色", "仮想", "受け取っ", "##HS", "引き起こし", "マリン", "ココ", "デン", "校区", "##ピュ", "##23", "クリスタル", "新曲", "注文", "酒井", "ナイター", "かな", "会合", "##渡さ", "##休み", "石原", "ビジョン", "誇り", "町田", "##グラム", "1879", "大いに", "##ラド", "わたし", "ray", "定時", "##抜け", "TOUR", "志願", "流さ", "赤坂", "農場", "インパ", "単一", "発現", "誘い", "##HT", "ヴェネツィア", "橋梁", "習慣", "転校", "アイヌ", "がわ", "住吉", "消化", "CF", "ボランティア", "伏見", "フェイス", "ブラウ", "キット", "売買", "##プライズ", "##ung", "会っ", "可決", "引き起こす", "取り扱い", "エクスプレス", "きん", "すず", "過激", "リモ", "各駅", "背負", "調節", "改定", "燃焼", "メソ", "オタ", "池袋", "As", "イノ", "##ords", "SUPER", "変遷", "元素", "増し", "ヴァイ", "##ジェリア", "お前", "工科", "最期", "##ドルフ", "正当", "##ATION", "集まり", "退学", "寄贈", "##DA", "保全", "##ミナ", "帰り", "債務", "市販", "想像", "累計", "射殺", "引い", "増強", "密か", "待っ", "DR", "客員", "ポスター", "喫茶", "母体", "セキュリティ", "##リク", "##HO", "##もの", "pro", "##コフ", "タイムズ", "振り返", "抱く", "ウエスト", "量子", "ラフ", "中東", "土壌", "さき", "バリア", "得票", "##ちに", "RS", "サクラ", "木材", "法廷", "しき", "タブ", "マキ", "##上がる", "山内", "音響", "たけし", "##und", "管制", "貨車", "就役", "トゥー", "収益", "発祥", "目立つ", "スモ", "##ヒト", "ギャラリー", "拍子", "珍しく", "##回し", "スタンダ", "苦労", "##タミン", "##エゴ", "##ュル", "##がわ", "##ley", "繰り返す", "本堂", "薬師", "##さと", "アパ", "セリフ", "ワクチン", "##ke", "磁気", "マーケ", "排水", "狙撃", "服装", "せよ", "寄生", "バク", "馬力", "##up", "サンク", "ピアニスト", "IBM", "不全", "##トリー", "ふた", "1600", "##ぐるみ", "傾斜", "投球", "本郷", "たかっ", "カウン", "ジオ", "仮説", "運搬", "##クトリー", "ベリー", "リース", "星野", "##GA", "役職", "##ハルト", "とりわけ", "番手", "Gl", "ボリ", "秋葉", "System", "側近", "共著", "大神", "奪還", "打っ", "127", "バッテ", "欠点", "貨幣", "ケア", "##ans", "##row", "##・デ・", "作動", "安藤", "小隊", "薬剤", "ポンプ", "##ディアン", "シングルス", "棋士", "mi", "pr", "シベ", "支える", "新生", "あか", "ヨーク", "出入り", "取れ", "ミン", "幼児", "Cr", "jp", "時折", "並べ", "大森", "カ国", "わが", "パト", "右翼", "急遽", "損失", "##88", "子爵", "##ハンマ", "##ぼす", "##フィールド", "UF", "##ana", "##ンスク", "バート", "分かる", "禁じ", "##ゥー", "卓球", "巡る", "##ジャン", "南京", "##ェン", "オフィシャル", "本質", "自作", "シンク", "弱点", "激怒", "##バマ", "後楽", "##デート", "##討ち", "宮本", "川上", "彗星", "救済", "飾り", "ニコニコ", "気味", "単なる", "多少", "軽減", "JRA", "Off", "三好", "宝石", "おと", "##own", "明るく", "##えて", "チェル", "コンビニ", "努め", "支給", "水路", "BR", "Univers", "危惧", "実態", "ボルト", "チャイ", "MUSIC", "sh", "抜い", "斉藤", "##ign", "制圧", "弘前", "輩出", "巡っ", "##LD", "##よし", "矛盾", "永久", "##テレ", "殺す", "##yl", "辞め", "グラフ", "エスト", "公会", "造り", "シェル", "ぞう", "##iam", "FL", "市電", "両手", "左側", "107", "悩み", "ONE", "##いろ", "アロ", "サント", "テイ", "プー", "寄与", "##タール", "奇跡", "書類", "天国", "秩序", "##ara", "エンターテインメント", "ハナ", "過ごす", "丸山", "合い", "秩父", "中田", "貧困", "##スカ", "レシ", "増える", "惚れ", "内海", "家老", "アンソ", "内陸", "あだ", "ボウル", "所領", "移設", "##ワーズ", "ぼく", "ヶ所", "ウィーク", "前進", "Mr", "オマ", "情勢", "##ジウム", "##ハンマド", "Ass", "ビリー", "出題", "早朝", "スプリ", "by", "真相", "越前", "プライベート", "バーク", "マイン", "##43", "モリ", "有馬", "育ち", "菩薩", "クラーク", ".,", "始動", "楽しむ", "グレン", "正常", "\"(", "##通り", "寿命", "商事", "日蓮", "グラビア", "##ビッド", "ユーゴ", "エリック", "白鳥", "イレ", "久留", "乗組", "ゆかり", "割引", "ライオンズ", "冷静", "円形", "北口", "永禄", "##UL", "決着", "##和田", "具合", "旗本", "転写", "マーケティング", "火力", "##押し", "##リューション", "名目", "絶望", "ウルフ", "##シカ", "幽霊", "招き", "ビートル", "歌わ", "##ネタ", "笑顔", "西鉄", "##me", "宇治", "緊張", "カルロス", "中立", "##・ロ", "革新", "魔物", "実写", "因ん", "ティア", "パレード", "中佐", "),", "イカ", "ハミ", "ピット", "真言", "調子", "##ックル", "コック", "入隊", "戸田", "括弧", "止める", "付く", "##ナイト", "1881", "CC", "##かせ", "トランプ", "とん", "キャップ", "バッテリー", "サマー", "モンテ", "##rans", "103", "##チンコ", "香り", "撃沈", "##ts", "##ディン", "学士", "##早く", "リクエスト", "機材", "没し", "踏襲", "##ヴィヒ", "さか", "デッド", "現職", "##ダウン", "##テイメント", "ドコモ", "好評", "強盗", "プレーヤー", "DO", "三塁", "佐伯", "##ヶ谷", "1882", "発する", "二塁", "##マラ", "Cor", "Net", "外伝", "ナル", "世田", "対峙", "工程", "繁栄", "##ほん", "従う", "被っ", "西宮", "美容", "阿波", "##レール", "怪人", "BB", "ルパン", "渓谷", "みなみ", "オム", "治世", "素晴", "電流", "ヴォル", "コンパクト", "常勤", "木曽", "##エス", "斜面", "##バース", "##マト", "MVP", "天候", "持続", "陸奥", "中原", "拒絶", "パイプ", "##ife", "平等", "松尾", "頻度", "げん", "タバ", "もうけ", "バリエーション", "リポーター", "ポルノ", "砲塔", "Air", "千歳", "##ディス", "Part", "##ドール", "シニア", "起きる", "先進", "功労", "専務", "知名", "転落", "Comm", "つとめ", "ネク", "##ons", "こんな", "エール", "任ぜ", "医者", "WOR", "パール", "優位", "公司", "同地", "間違い", "世田谷", "カブ", "vol", "吸血", "安芸", "Will", "ゾンビ", "一宮", "運休", "マルコ", "マニュ", "弥生", "逃し", "駅伝", "梅田", "決断", "アンリ", "ペンシルベニア", "先祖", "トリオ", "##ドニア", "##ニウム", "バスター", "有形", "松原", "記す", "バンダイ", "先駆け", "鶴見", "##ます", "ジェン", "ミラノ", "厩舎", "政務", "津田", "退官", "##・モ", "BBC", "目論", "##タイプ", "会い", "校歌", "著しく", "##ほど", "アビ", "広がり", "水雷", "##ラーズ", "ar", "口調", "MF", "好ん", "起工", "DM", "化し", "長調", "##デント", "アップデート", "アーク", "本数", "野党", "常識", "見学", "ストラ", "後世", "中津", "ボーイズ", "スケール", "ゼネ", "初出", "泣き", "飛ぶ", "フォーム", "ねじ", "原稿", "文政", "真珠", "##ESS", "田辺", "開戦", "ジョル", "返り", "一見", "植え", "楕円", "兵力", "帯び", "##ツォ", "テオ", "小売", "流入", "直轄", "1200", "オリックス", "ろう", "リム", "じょ", "倉敷", "没後", "古川", "アンティ", "カウンター", "LP", "四日市", "種別", "高岡", "##サギ", "##返さ", "Mic", "中毒", "傭兵", "高まっ", "フェリ", "ゴン", "重点", "領事", "社内", "隠居", "##フェル", "コミュー", "立た", "##バック", "めぐる", "##ヌー", "チャージ", "アフガニ", "コラム", "兼務", "運送", "102", "141", "We", "軍艦", "門下", "アトランタ", "サク", "盆地", "絶え", "##BI", "シミュレーション", "気動", "アフガニスタン", "つる", "国語", "捕食", "首席", "ノイ", "追悼", "##VER", "アルメニア", "近接", "Rob", "リサ", "##ぱい", "マント", "本願", "軍用", "##ナラ", "継ぐ", "RO", "すす", "再選", "現金", "金子", "次いで", "こなし", "オハイオ", "BEST", "土器", "ボーイング", "スタンダード", "必須", "##AF", "のりば", "オカ", "好む", "##レッド", "プロテスタント", "##UC", "しの", "ハンドル", "教える", "高層", "##gr", "孤立", "##ニエ", "落とす", "丹波", "党首", "難民", "ディオ", "北上", "及ん", "虐待", "##way", "狩り", "テイラー", "大川", "安価", "適合", "##のり", "すけ", "ウー", "囲碁", "工房", "高島", "由紀", "賭け", "アテネ", "ツッコ", "乙女", "収穫", "こども", "フォーマ", "稽古", "##ヴィル", "ツァ", "載せ", "Inc", "倒産", "狙い", "##HC", "大関", "悲劇", "英文", "帰る", "プリンセス", "アウグ", "-」", "##ハウゼン", "利根", "International", "こなす", "採掘", "郡区", "実証", "軍勢", "##ENT", "上方", "秋山", "##チカ", "##ヶ丘", "誤り", "さらなる", "クモ", "パキスタン", "如来", "播磨", "森田", "町域", "苦戦", "金剛", "##シティ", "タイガー", "##サンダー", "Mi", "ドリ", "Mo", "基調", "警部", "マケ", "真面目", "ちょっと", "##roid", "金田", "日付", "##ハウス", "##ino", "アカウント", "告発", "行進", "鳥類", "とどまっ", "最上", "##UD", "アンドレ", "Tom", "出向", "幾何", "##ブリッド", "腫瘍", "通商", "##ari", "##ECT", "LED", "実体", "動機", "##キュア", "詐欺", "野外", "##フルト", "司祭", "掘り", "ばら", "スラム", "読書", "チーフ", "八木", "標識", "水力", "クラフト", "Pre", "##ヤン", "リュウ", "リミックス", "執政", "##KA", "レーン", "偉大", "##ヴァル", "マニア", "石垣", "PA", "犯行", "##KI", "##GB", "##fer", "伊賀", "組む", "美女", "邸宅", "重い", "##ナ・", "##ケイ", "サロン", "か国", "##ーレ", "破綻", "破産", "還元", "##下ろし", "再興", "奪う", "牧野", "産地", "##ゆみ", "でしょう", "体格", "暴行", "アジ", "モジュール", "襲名", "##ini", "サンディ", "欠場", "伊予", "##ソル", "小田急", "##port", "##ATO", "シップ", "吹奏", "御所", "歩道", "白山", "博し", "擁立", "造形", "河野", "町制", "赤字", "フォックス", "センサー", "##ツィオ", "ゆり", "血管", "##ave", "担任", "残存", "ザン", "アーチ", "南口", "##リッシュ", "フェニックス", "インディーズ", "138", "Per", "スノー", "ホスト", "勧告", "148", "一斉", "クリスティ", "##able", "ピラ", "##アミ", "教官", "聞こ", "返し", "アルミ", "自覚", "踏まえ", "鉱物", "セリエ", "忠誠", "時々", "ジェリー", "作風", "理念", "酒造", "##ロル", "一撃", "大石", "急激", "替え", "朝倉", "ヴィン", "6000", "多発", "昼間", "地蔵", "##ウマ", "##づくり", "陽子", "##カーン", "見事", "##こと", "せき", "ゴースト", "創始", "独裁", "蓄積", "キラ", "上旬", "蜂起", "##ピング", "1877", "ブン", "交わし", "大事", "リーチ", "正しく", "ブロン", "入部", "##シナ", "スケジュール", "ワーナー", "AFC", "EAN", "友情", "多大", "書誌", "113", "なつ", "WE", "生理", "間接", "投下", "船長", "プロフィール", "GB", "全車", "##ys", "ビクター", "指数", "##ダーズ", "両側", "自国", "補強", "104", "ドラゴンズ", "押す", "##PS", "フロア", "at", "コーン", "運ば", "##ある", "もも", "食糧", "220", "車輪", "一目", "勘違い", "弾き", "手続", "追う", "149", "セラー", "愛情", "it", "視察", "進展", "カツ", "ポニー", "増やし", "飛鳥", "ex", "エマ", "エグ", "ルナ", "ピカ", "動詞", "家屋", "ウイング", "ユリウス", "元帥", "狩猟", "##ator", "DF", "西川", "高麗", "ハイブリッド", "AA", "裏切り", "目覚め", "和平", "招聘", "##we", "亡くし", "勇気", "ブレード", "首脳", "##・ダ", "137", "動脈", "Ind", "初版", "客室", "広瀬", "移る", "集積", "##・フ", "仕える", "失踪", "スープ", "##はや", "##ファン", "名づけ", "変数", "占い", "検事", "代官", "液晶", "破損", "オブジェクト", "とある", "オファー", "パパ", "国産", "放置", "目黒", "負う", "イブ", "タケ", "##トリウム", "生育", "著し", "訪ね", "フランシス", "##ato", "##ローラ", "旗艦", "那須", "116", "名所", "##ネーム", "##ヴィー", "ユーゴスラ", "ささ", "警官", "入れ替え", "おん", "すご", "ハット", "冠し", "格好", "ペルー", "ムハンマド", "直営", "諦め", "賃金", "Mag", "学部", "触媒", "髪型", "One", "セックス", "四郎", "Wii", "たろう", "当社", "AG", "FF", "SNS", "待機", "##ma", "向い", "痛み", "ファミコン", "タラ", "官位", "尾崎", "鑑定", "ダイア", "鳥居", "##ラード", "1800", "Gen", "ドッグ", "左手", "##ジング", "次期", "フォワード", "Res", "##ひろ", "ダグラス", "ブドウ", "知能", "1883", "ノーベル", "オーディオ", "自立", "選び", "##トレ", "##二郎", "ハンマー", "転送", "農学", "クラウド", "告示", "##デリック", "後援", "皮切り", "##ータル", "VTR", "au", "合法", "広まっ", "手塚", "生体", "竹内", "風呂", "麻薬", "うら", "銃撃", "ジョニー", "クリスチャン", "大村", "書簡", "豪華", "##立た", "玄関", "オートバイ", "バト", "疑わ", "平田", "##co", "シェイ", "エルフ", "ハド", "松下", "##セッサ", "##ava", "南端", "計測", "##作り", "##ARD", "僧侶", "小児", "##AGE", "ばん", "わか", "受託", "行か", "駿河", "##ぼう", "堆積", "斬り", "##タス", "##ラスカ", "TD", "日高", "表さ", "##ごう", "Bill", "ラファ", "##ink", "Char", "ムスリム", "おかげ", "基幹", "##ンガム", "Day", "入会", "頼朝", "アントニオ", "コク", "ハマ", "孤児", "導い", "穏やか", "管内", "遊撃", "引き分け", "ケネ", "刻ま", "愛好", "最長", "三宅", "乗用", "##もそ", "ベルク", "##替える", "特有", "運び", "アーマー", "セク", "名門", "本尊", "ふれ", "全曲", "青葉", "イエロー", "がた", "そもそ", "そもそも", "射程", "有罪", "112", "ウィルソン", "モニター", "フレン", "テール", "上限", "砂糖", "カザ", "党員", "常陸", "釧路", "##ヶ原", "遂行", "##ナウ", "主将", "組ま", "鉄筋", "##つか", "NG", "フロン", "Ann", "皇族", "内藤", "観戦", "触れる", "下げ", "時空", "ニックネーム", "専修", "複製", "抑える", "幅広く", "一塁", "脱走", "うつ", "MR", "オックス", "石橋", "##ya", "##ita", "ジョン・", "ドナルド", "バブル", "UC", "シチ", "井戸", "大社", "媒体", "道徳", "メイク", "主砲", "据え", "食用", "##やま", "210", "一門", "予言", "フォト", "公布", "松浦", "##ーヌ", "とくに", "##マーク", "武術", "がら", "##ラマ", "ha", "リック", "勾配", "南米", "##td", "##her", "##パール", "上がり", "おじ", "奇妙", "閉校", "##レージ", "デヴィッド", "まれ", "数列", "回っ", "封入", "有無", "道中", "ジョセフ", "ME", "War", "田原", "迎撃", "少尉", "年上", "百科", "##ピオ", "ソード", "容器", "じゅん", "ミカ", "相違", "ne", "展覧", "換装", "異例", "レポート", "平凡", "ぼう", "##サイド", "青色", "おさ", "ノット", "一角", "西ドイツ", "アピール", "ルーキー", "同居", "本多", "ぎょう", "のび", "差異", "役目", "本館", "##ッケー", "チーズ", "750", "休暇", "多額", "順番", "ふるさと", "ジル", "公衆", "納言", "生没", "祖先", "バーグ", "パシフィック", "加熱", "意気", "##がみ", "##ブール", "##もう", "##ett", "##osh", "Ag", "サマ", "ビア", "御殿", "矢野", "追求", "##ng", "にほん", "出港", "ドロップ", "NCID", "ケンタッキー", "テック", "##ゾナ", "登記", "カプセル", "ユーゴスラビア", "コンプレ", "MT", "ソニック", "参事", "くま", "屋外", "町長", "フェラー", "鳥羽", "##rum", "本州", "真田", "突っ", "ハリス", "位相", "##ka", "WA", "紀伊", "NFL", "中型", "郡庁", "浸透", "スロット", "知れ", "講習", "コミューン", "迫っ", "##ベール", "UP", "伝わっ", "楽譜", "131", "満たし", "Android", "エッセイ", "遺構", "##ric", "##ited", "題名", "##グアイ", "かかり", "パウ", "従兄", "くに", "ダッシュ", "アドバイス", "きょく", "コーポレーション", "セグ", "戻し", "補償", "##yo", "##ンジュ", "フランツ", "内装", "##ラート", "侵害", "ハインリヒ", "ボーン", "採取", "##ビット", "##LC", "公安", "概要", "語源", "##LS", "エビ", "グレゴ", "ミスター", "通い", "1860", "la", "揃っ", "郡山", "たくさん", "Night", "ニア", "パチンコ", "化け", "クォ", "フォール", "生没年", "出血", "鎮座", "##ボーン", "##フェクト", "##ッケン", "SR", "連敗", "##ual", "岩崎", "新興", "中尉", "史学", "親善", "醸造", "##焼き", "シャイ", "アーキ", "ミステリー", "ラク", "営む", "情熱", "拡散", "リン酸", "JP", "きち", "新井", "親族", "寸前", "津軽", "テネ", "神道", "##ベック", "たた", "##デイ", "特攻", "単体", "受付", "王家", "##AST", "cl", "複線", "##リッツ", "ストレス", "ウィキ", "RA", "改題", "木下", "決まり", "##ームス", "フランソ", "クローン", "気づい", "伝記", "##切れ", "小沢", "スティーブ", "エフエム", "工夫", "村田", "豊島", "階層", "モナ", "半径", "吸い", "食材", "8000", "わざ", "ハイド", "実務", "民事", "測量", "セールス", "加茂", "抹消", "踏切", "追撃", "天平", "##ごと", "プラスチック", "いん", "反論", "##ラシ", "デジモン", "始発", "演算", "ブリュ", "ベクトル", "全日", "服部", "疑惑", "高温", "##lex", "屋上", "成る", "シベリア", "崩れ", "閣僚", "JCT", "ビートルズ", "代謝", "新町", "ソマ", "松江", "通知", "ゆめ", "民放", "ヤマハ", "あきら", "擁護", "##わす", "129", "ふさ", "八重", "転生", "ジェイム", "つながり", "NET", "エウ", "トス", "他者", "国体", "入り口", "ダイエー", "##グラフ", "##ナンド", "ファーム", "仲介", "ラインナップ", "増築", "取り戻す", "ボム", "政界", "日本橋", "就く", "一生", "協奏", "小樽", "山陰", "馬車", "106", "Open", "女流", "##ゥス", "パズル", "大夫", "金色", "##デレ", "襲っ", "フェン", "きら", "舞鶴", "##キンス", "ハーバード", "動向", "国旗", "めぐみ", "常磐", "##ニティ", "Amer", "ボケ", "グローブ", "NEWS", "略奪", "##ALL", "OB", "四季", "控訴", "代役", "詳しい", "難しく", "PK", "テー", "工藤", "樺太", "侯爵", "台頭", "##box", "切る", "愛する", "みたい", "方形", "農地", "写本", "##・ブ", "##ism", "右腕", "製鉄", "ちょうど", "Je", "ソックス", "列伝", "##ナタ", "組み立て", "インディアナ", "迫る", "Har", "ホロ", "任せ", "桐生", "決まる", "縄文", "デビル", "ツッコミ", "リハ", "島式", "ドラッグ", "CEO", "便宜", "債権", "学芸", "紙幣", "ドラマー", "バルブ", "Pa", "呪文", "解明", "下野", "田園", "かし", "ノア", "付随", "巫女", "##せい", "有数", "つくば", "北野", "##ントロ", "喜び", "武力", "エム", "リフト", "エリート", "亡くなる", "リュー", "婚姻", "##ald", "人文", "強引", "##なら", "ニュージャ", "##マックス", "別府", "依然", "##デュ", "サイバー", "アシュ", "シンプル", "ナトリウム", "イラストレーター", "NPB", "間違え", "行える", "Linux", "久留米", "反し", "木製", "ケネディ", "除外", "離れる", "ユニフォーム", "ボイ", "利点", "中西", "##ane", "付き合い", "常連", "究極", "あだ名", "sp", "大原", "茶屋", "アルゴリズム", "もはや", "樹脂", "艦船", "集まる", "##ナード", "灰色", "薬品", "Ro", "##ッテル", "##バリー", "天満", "母艦", "越える", "ISS", "ビジュアル", "枚数", "与党", "図ら", "##que", "ダート", "器具", "嫉妬", "家政", "小柄", "Her", "和名", "柔らか", "発車", "##ius", "不利", "自在", "##カナ", "##YS", "147", "ウズ", "当事", "##・グ", "カテゴリー", "仲良", "##テール", "アミノ", "クマ", "ハンス", "志摩", "クラッシュ", "見つける", "一色", "掌握", "軽い", "在日", "NASA", "家畜", "レジスタ", "機銃", "王室", "途上", "Ltd", "魔界", "##テラン", "##じょう", "見守", "##ony", "アレクサンドル", "戯曲", "意義", "正統", "順序", "カタル", "遅い", "隠さ", "台地", "強豪", "骨格", "デルタ", "リバー", "書院", "##タゴ", "##・レ", "グリー", "##ンドウ", "ヴィクトリア", "ホリ", "古河", "156", "アリゾナ", "フォーマット", "巡回", "遊園", "ニュージャージー", "占拠", "在来", "##えん", "国内外", "リンカーン", "プリキュア", "増刊", "満点", "燃え", "商会", "打た", "腹部", "あて", "ホッケー", "等級", "鈴鹿", "本機", "分泌", "学制", "系図", "不死", "極東", "相模原", "まんが", "先述", "対話", "次女", "馬身", "##ッリ", "トルク", "主席", "代数", "##フェンス", "風俗", "450", "##ents", "##ジャース", "会う", "旋回", "相応", "##レータ", "メリ", "免除", "田舎", "細長", "西経", "州都", "次長", "遺族", "##ブライ", "レバ", "ver", "大友", "感動", "菅原", "##ノキ", "バウ", "バッハ", "ホセ", "嫌っ", "論じ", "##ins", "かわい", "DX", "はい", "追い詰め", "トロント", "足立", "進路", "ギャング", "Fr", "ゴミ", "捧げ", "立花", "##ッタン", "フォーミュ", "BC", "et", "南朝", "##延び", "分かれる", "School", "預け", "エンジェル", "鎮守", "アルト", "ハヤ", "再発", "政令", "暴動", "輝い", "所要", "見出し", "##cl", "Do", "フォーラム", "##・シ", "ハードウェア", "ハイパー", "チョウ", "##UND", "廃校", "手掛ける", "誘わ", "一瞬", "聖職", "能登", "##ーマル", "##ental", "凍結", "断っ", "##ゲート", "##インズ", "##ファレンス", "リカ", "休養", "定住", "理科", "進水", "バーチャ", "スクエア", "Records", "クビ", "色々", "アクア", "アトラ", "##落とし", "足り", "##リンク", "追い込ま", "##III", "不二", "制裁", "pl", "##ype", "アレックス", "喜多", "##落ち", "レバー", "永井", "肯定", "郵政", "##IDE", "Sou", "くろ", "ミク", "逸話", "Star", "支払う", "ホップ", "栄え", "硫黄", "##ビィ", "##小路", "好ま", "祭神", "たとえ", "ザクセン", "ル・", "繋がり", "イリノイ", "7000", "ログ", "混同", "見舞わ", "交互", "##・ザ", "##ンジー", "バース", "Chr", "エキス", "対談", "チェロ", "##ッスン", "フレーズ", "手がける", "High", "市原", "弱く", "スウィ", "##かわ", "##払い", "太守", "東亜", "##ピット", "##ニッシュ", "あらか", "くり", "スナ", "中性", "答える", "高額", "投じ", "##・アル", "ブッシュ", "処置", "##モンズ", "Pe", "免れ", "遠隔", "高地", "136", "北軍", "タバコ", "営利", "##YA", "ハミルトン", "樹木", "##殺し", "テクノロジー", "エナ", "大砲", "##GP", "携わる", "舞踊", "CV", "口癖", "It", "さわ", "好物", "##マンド", "GL", "トリック", "モス", "近所", "##メイ", "曜日", "桃山", "ステレオ", "亜種", "円盤", "型式", "##リーガ", "##イトン", "カテゴリ", "ケーキ", "JST", "ランス", "主権", "伝道", "順調", "##ull", "##ネイロ", "海老", "##ger", "Ma", "破棄", "マネー", "ぜん", "Hot", "執り", "死に", "陸地", "##やり", "尽くし", "ハワード", "マール", "生誕", "聖人", "##之介", "基部", "孤独", "祈り", "##スロ", "##ーシ", "ブラザーズ", "ウス", "主教", "挿絵", "数千", "##ブリッジ", "Super", "Mon", "タム", "交え", "収納", "聖母", "西郷", "Em", "MHz", "各々", "子女", "系譜", "緑地", "##CO", "##ings", "合金", "図鑑", "アンドリュー", "BD", "三条", "信託", "理工", "百合", "聴い", "マンチェスター", "GS", "ぶつ", "原始", "##じみ", "リハビリ", "炭鉱", "当てる", "親戚", "マクド", "ムーア", "パブ", "導体", "授け", "240", "レアル", "放ち", "待つ", "所管", "キャス", "マーガ", "外し", "多彩", "大内", "ナポリ", "一揆", "招か", "百済", "ラト", "断層", "造成", "##・ミ", "ボトル", "幸福", "成熟", "##ブック", "グラム", "喫煙", "戻す", "村立", "水田", "転移", "通報", "##ノム", "キャッシュ", "ブロー", "麻生", "##ution", "哺乳", "膨大", "遭い", "打ち切り", "飲ん", "フォーミュラ", "なに", "エリー", "含める", "歩い", "高かっ", "色彩", "イド", "ベテラン", "着け", "##red", "伸びる", "れん", "タグ", "急性", "川島", "市道", "電灯", "カ月", "シール", "有人", "松岡", "Colle", "行なう", "ラヴ", "改変", "##air", "166", "金山", "##alk", "主婦", "TC", "攻勢", "知り合っ", "保っ", "冷房", "日露", "最速", "洗礼", "無償", "集約", "##タナ", "##MO", "##ッチャー", "##ason", "北斗", "双葉", "墓所", "##・ヘ", "あらかじめ", "年始", "悟空", "裕福", "ヒント", "全土", "奉納", "岡村", "アンジェ", "初等", "##ードン", "アルファベット", "実習", "尼崎", "新制", "本家", "##51", "パレスチナ", "カセット", "公明", "ウォール", "幻想", "歓迎", "フェス", "くじ", "完璧", "積ん", "##chn", "シーク", "全滅", "大師", "打つ", "##IB", "##通し", "サイク", "##board", "##換える", "混ぜ", "SN", "一橋", "##モント", "##XT", "ハッピー", "没収", "負荷", "マーシャル", "ウォーカー", "あつ", "フレイ", "致命", "藤本", "##ンタム", "パラダ", "はじめて", "高まり", "##リヤ", "Ele", "##だし", "##ジャネイロ", "Aut", "留守", "蹴り", "静か", "114", "フェラーリ", "役人", "消失", "真宗", "運ぶ", "トレイン", "イグ", "オース", "ラック", "久米", "吾妻", "商船", "##ガメ", "内科", "北極", "及ば", "進軍", "難波", "Stud", "ラッセル", "加算", "明神", "玉川", "##ムシ", "##がれ", "サイエンス", "ネズミ", "修業", "布告", "##ぎり", "##より", "ステン", "増殖", "高価", "1864", "パラメ", "プライム", "こい", "のぞ", "サポーター", "要員", "赤軍", "カスタム", "原案", "ヒューストン", "##ML", "スターリン", "だら", "深め", "車輌", "厳格", "地裁", "連装", "いと", "園芸", "石器", "リーガ", "デイリー", "ナス", "浮世", "チョコレート", "パワ", "##リッド", "##ニール", "回し", "撤回", "未明", "飼い", "##ater", "生き残っ", "HT", "温暖", "##並み", "##ンジャーズ", "中枢", "通告", "OR", "ゲリラ", "以南", "包括", "弾圧", "##ローグ", "ゆる", "MA", "トキ", "フィー", "##ement", "推し", "突起", "京浜", "俳句", "出展", "山手", "日比", "録画", "ハロー", "マック", "千里", "外来", "湾岸", "##ene", "スキャ", "ROM", "長老", "広東", "出世", "斜め", "考察", "サスペン", "##・リーグ", "##ンダル", "大垣", "注釈", "フォート", "ひょう", "夏休み", "群れ", "さと", "はし", "##ョー", "サテ", "二郎", "対馬", "平原", "平家", "戻さ", "##ute", "差し替え", "上層", "確信", "薬学", "ナー", "佐渡", "公職", "教職", "王族", "男優", "負い", "##ンスキー", "Rad", "ZERO", "ユウ", "告げる", "覚悟", "ティム", "受け継い", "Girl", "シリン", "他国", "使節", "動い", "寛文", "新羅", "犯し", "辺境", "安置", "##yd", "生み出す", "エヴァ", "惹か", "##セラ", "オックスフォード", "アオ", "MB", "ホーク", "サーバー", "徴収", "真空", "##オニア", "駆けつけ", "っぽい", "is", "のぼ", "##ロメ", "窒素", "同誌", "拷問", "ホームズ", "引っ越し", "Mc", "di", "ヒップ", "他方", "##リンゲン", "WBA", "寿司", "抽出", "かえ", "ピック", "IR", "目立っ", "軽く", "落ちる", "カタログ", "上手く", "一新", "原発", "飾る", "川村", "慢性", "プラハ", "本気", "フェザー", "手伝い", "仮定", "歩く", "水面", "##ema", "マケドニア", "本校", "財閥", "水源", "クラウン", "はん", "えい", "イマ", "千秋", "長州", "代わる", "余裕", "##アンス", "すい", "新書", "稲葉", "オルガン", "弁当", "##じっ", "##替わり", "汎用", "減っ", "ミシガン", "閉館", "アスレ", "オットー", "カワ", "愛人", "知人", "ペーパー", "TE", "名声", "微分", "##ケー", "スペクトル", "1862", "コロム", "Bo", "模索", "カンザス", "リンゴ", "ニコラ", "南軍", "相棒", "ともない", "MG", "かす", "救わ", "##ットン", "FS", "クワ", "親しま", "解剖", "踊る", "邪魔", "##バイザー", "メダリスト", "直ちに", "仕上げ", "フランソワ", "保つ", "少なかっ", "ルカ", "末裔", "遺物", "##ru", "CBC", "元老", "健一", "語尾", "賞賛", "こうとう", "TH", "上越", "今川", "書物", "##どん", "あず", "ブース", "##テンベルク", "ミニゲーム", "春季", "競艇", "集結", "ライアン", "クルーズ", "下ろし", "刺史", "速い", "増やす", "##ki", "##oup", "アレン", "国営", "アクティブ", "体型", "異母", "語学", "センス", "好調", "##ano", "ジャンク", "シューティング", "空き", "WORLD", "設ける", "##むね", "you", "たつ", "中高", "成年", "##チャーズ", "ドレ", "現し", "野口", "飛ん", "ジャーナル", "産出", "繋がる", "##ele", "ワンダー", "割れ", "天津", "県庁", "##バイバル", "カタルーニャ", "ナウ", "レフ", "出家", "親しく", "警報", "面会", "バナナ", "反省", "字幕", "村山", "National", "ひど", "ケリー", "トミー", "ロッド", "自家", "別荘", "特権", "乃木", "##app", "マザー", "土俵", "##aster", "おおむね", "メガネ", "気付い", "強大", "趣旨", "アソ", "アーツ", "グルメ", "アレクサンダー", "ぐらい", "援軍", "取り消", "コンスタンティ", "文法", "ふたり", "まき", "回線", "1863", "マナ", "Eng", "店員", "景気", "あえて", "召集", "白川", "結城", "タービン", "1867", "コロラド", "聴取", "土砂", "旧姓", "西尾", "陥る", "コパ", "汽船", "feat", "オズ", "家具", "頂上", "PH", "たどり", "争っ", "別々", "原爆", "土屋", "復刻", "総統", "脱落", "カロライナ", "ひた", "サハ", "哲也", "琵琶", "補充", "ソナタ", "タコ", "住職", "##メンタル", "Mot", "物流", "##サンス", "リオデ", "最悪", "釈迦", "フィッシュ", "めぐっ", "おこなっ", "テリー", "発作", "##・フォ", "受け入れる", "ルーツ", "ワゴン", "囚人", "寄稿", "##IZ", "勝つ", "娯楽", "富士見", "ヘルメット", "ラング", "睡眠", "降水", "アポロ", "コロムビア", "リオデジャネイロ", "ふり", "嘉永", "無数", "##ゥル", "まつわる", "営ん", "対局", "尊重", "本山", "きわ", "逃げる", "Project", "コンプレックス", "##ep", "南北朝", "ギルド", "ジミー", "ルーズ", "出番", "四方", "##tr", "レイク", "NPO", "マート", "##ディオ", "ゼネラル", "Can", "ビタミン", "志望", "指輪", "遺言", "柔軟", "参拝", "武家", "##リッジ", "オーガ", "FW", "ソウ", "特設", "続行", "講和", "途絶", "宣告", "取り除", "Val", "巡り", "母方", "ハチ", "灯台", "背面", "Micros", "争う", "動かす", "合う", "搬送", "称賛", "##レックス", "##サーチ", "ランナー", "320", "スカート", "ニコライ", "そっくり", "カエ", "##ハッタン", "##リントン", "テナント", "ニール", "通じる", "##91", "いっぱい", "##テルブルク", "受け継が", "休刊", "喜劇", "特例", "夜行", "##na", "単発", "ウマ", "いかに", "ルク", "インフラ", "ミルク", "公正", "##uro", "コンポ", "ヴォーカル", "人体", "参画", "##sc", "店長", "##スパ", "ヤクザ", "POP", "片側", "細かい", "もたらさ", "応答", "気分", "フェイ", "ヒュ", "日系", "石灰", "##sch", "キャノン", "##ウンテン", "世論", "強烈", "譲っ", "ディフェン", "マイアミ", "トレーナー", "電信", "##ばら", "マンハッタン", "はや", "デトロ", "宮古", "遮断", "##ニウス", "スチ", "応え", "進入", "SW", "ボロ", "レート", "傑作", "通訳", "養父", "##eth", "トライアル", "支局", "魚類", "楽しみ", "成し遂", "マシ", "妄想", "砲弾", "飛騨", "SHOW", "西田", "##ニカル", "##去っ", "デトロイト", "パトリック", "##テージ", "##まね", "エルサ", "休憩", "専任", "陣地", "マーガレット", "嫡男", "法政", "##rit", "##しょ", "##遣い", "エレクトリック", "MAX", "氷河", "シチリア", "ウサギ", "サザン", "満ち", "知らさ", "CA", "ブルク", "フラワー", "ひさ", "コング", "ホス", "精密", "食物", "##ソタ", "##ベーション", "##少年", "アイアン", "取り組む", "エチオ", "ホーン", "BN", "任官", "八十", "志向", "指標", "青少年", "##・メ", "アルフレ", "ルートヴィヒ", "フランクフルト", "克服", "大国", "大勢", "##ショップ", "クイーンズ", "皮肉", "##ツキ", "宰相", "慣習", "##ズエラ", "多岐", "暗い", "脅迫", "##ANG", "カミ", "導く", "持株", "釜山", "230", "ポーズ", "##コク", "うか", "会派", "地盤", "造営", "##メーション", "バスク", "ダメ", "報復", "救い", "生地", "アルミニ", "テネシー", "スネ", "レッスン", "左腕", "##ubl", "キッド", "戦法", "断絶", "ストン", "ウェア", "##リオール", "ハーン", "杉山", "異性", "##form", "##さま", "ファクトリー", "引き受け", "同梱", "巡礼", "荒木", "遥か", "収める", "早川", "納入", "##let", "ビルボード", "GK", "阿弥", "離陸", "ヴァー", "##フェース", "天狗", "アトラクション", "BA", "密着", "議事", "フレンド", "ミシシ", "台数", "封鎖", "愛国", "豪雨", "##じり", "援護", "乗り換え", "いかなる", "積載", "築か", "防空", "まるで", "給食", "アセ", "次回", "##ヴィッチ", "Art", "優しく", "高雄", "コンボ", "コーラ", "シアトル", "アワード", "馬鹿", "いろいろ", "FO", "よば", "若松", "##コンド", "##キース", "セーラー", "マニュアル", "任天", "充電", "朗読", "条項", "素晴らしい", "対岸", "産駒", "落合", "##ゲイ", "1865", "見習", "配達", "合わせる", "エチオピア", "三原", "原画", "大洋", "##ology", "Sec", "Microsoft", "デート", "ハッチ", "剣術", "大同", "板橋", "##ファイ", "##ersion", "トール", "ドット", "課税", "ウォルター", "しら", "崇拝", "##lymp", "ろく", "厚い", "##ラルド", "##ベイ", "コスプレ", "どん", "コト", "ドック", "総数", "##urn", "ブリティ", "職場", "長け", "テラ", "点数", "##返り", "##IGHT", "手配", "##ヨー", "いったん", "ロジャー", "日活", "派手", "##rap", "CB", "券売", "県民", "飛車", "LT", "リマ", "合わ", "本殿", "バッファ", "家事", "レーサー", "天王寺", "カニ", "バンタム", "ボンバー", "悲しみ", "特命", "サスペンション", "休業", "出羽", "西南", "イレブン", "函数", "大敗", "明記", "起因", "##ラビア", "引き換え", "アイン", "下さ", "周回", "抱える", "曹操", "神楽", "##enc", "##ボルン", "Count", "体質", "入国", "派閥", "硬式", "築城", "##テナンス", "NEC", "けんど", "立案", "プロセッサ", "ローリング", "スライド", "Disc", "サビ", "意欲", "消息", "渋滞", "融資", "##・セ", "##・ト", "##ロイ", "シャープ", "うどん", "たて", "ドミ", "進撃", "鋭い", "頭脳", "##しょう", "ビルマ", "天野", "##ations", "ケンブリッジ", "取り扱う", "リヴァ", "甘い", "臨ん", "##ミントン", "ひかり", "サード", "実父", "##ラフ", "日清", "持ち帰", "Red", "バレン", "仕方", "低減", "勝者", "素直", "なくし", "##ama", "ファイターズ", "サヨ", "慎重", "片方", "##コム", "##越え", "チェン", "クレア", "常時", "##プリング", "##コブ", "アンダーソン", "合弁", "業者", "ユーザ", "もらえ", "モデ", "屋内", "準拠", "病死", "通用", "Java", "山川", "##55", "ウィング", "ウォーズ", "ミネソタ", "アデ", "レジェ", "不幸", "沼津", "着任", "##ソニック", "代用", "為替", "クライアント", "合宿", "常任", "殴り", "バリー", "クス", "単式", "留まり", "痛め", "##シミ", "宝暦", "源流", "都営", "##FE", "西山", "速く", "##ヶ崎", "##本木", "インク", "##フォーク", "一流", "挑ん", "ゴッド", "ロイド", "亜科", "同窓", "プロペラ", "主翼", "名物", "未知", "カップル", "えん", "常設", "形容", "河合", "特色", "諜報", "通話", "仮名", "太刀", "豊川", "##ex", "##ダース", "CT", "調和", "金髪", "ソーシャル", "メンテナンス", "マツダ", "国府", "等しい", "##まち", "##グマ", "テロップ", "はた", "養護", "小麦", "火器", "誇っ", "##ha", "##ナート", "##ばり", "##ンクス", "マニラ", "イケ", "奨学", "頼り", "##inc", "##any", "取り壊", "アムステル", "しめ", "なな", "わかり", "ド・", "救っ", "減らし", "転身", "Black", "Dav", "from", "郡内", "##わい", "1866", "Olymp", "Tour", "##って", "ベネズエラ", "領有", "##ors", "回る", "志村", "日経", "米子", "抗体", "バーチャル", "文久", "プリント", "At", "使徒", "山村", "掃除", "##IAL", "##ルティング", "##もっ", "ROCK", "遭っ", "鋳造", "グラフィ", "カンボ", "##IME", "ヘー", "組成", "ライド", "アルミニウム", "交番", "WWE", "ふみ", "アコース", "マフィア", "旋律", "相馬", "遅延", "##CH", "亡き", "北端", "鉱業", "##ASH", "GH", "To", "##por", "Spec", "尋ね", "インパクト", "ブラウザ", "カーン", "大崎", "決闘", "##リップ", "キャニオン", "##inal", "ダウンタウン", "サタ", "出動", "天地", "小牧", "##vel", "ハイム", "エンターテイメント", "サンディエゴ", "イヌ", "ウン", "草津", "アンチ", "##チェン", "ファイブ", "公使", "年長", "書紀", "流す", "University", "どころ", "共闘", "四十", "笑っ", "##ww", "##ビアン", "ヘッセン", "ヨン", "塩化", "Pol", "des", "振付", "##がき", "近づく", "ラバ", "リサーチ", "原産", "am", "待合", "遂に", "高圧", "デイヴィッド", "Xbox", "co", "ひめ", "カープ", "年俸", "意匠", "興奮", "##AWA", "PP", "みゆき", "テイク", "中古", "信念", "意外", "誘致", "チョン", "佐竹", "係数", "密接", "男の子", "##ネーション", "アコースティック", "コカ", "##継ぎ", "ミシシッピ", "出航", "悩まさ", "未遂", "潜在", "薄く", "Don", "fr", "##ナギ", "##きん", "スズキ", "ゴードン", "ツリー", "固体", "エスカ", "Dream", "バド", "商売", "広義", "##ストル", "つくる", "フィルハー", "レシピ", "ふれあい", "アズ", "ウラン", "指向", "賛同", "振る舞い", "凱旋", "叢書", "摂津", "無罪", "盗賊", "線形", "フランシスコ", "コロニー", "ネパール", "特記", "胞子", "Pet", "ナノ", "William", "八代", "ソロモン", "ジェイムズ", "ガイア", "プエ", "仕立て", "弾丸", "添加", "高句", "##パル", "ウォン", "もらえる", "アイスランド", "高句麗", "増田", "真似", "##gh", "##ヴィエ", "シンセ", "フロンティア", "GN", "me", "以っ", "有志", "生ん", "痕跡", "ヤンキース", "ヤー", "直面", "黒色", "##ler", "MD", "はち", "廃業", "楽しめる", "モロッコ", "ラボ", "長尾", "##リーニ", "ブリティッシュ", "KD", "タス", "チャーリー", "ゴシック", "去る", "閉じ込め", "うけ", "ヵ月", "堤防", "版画", "留置", "継ぎ", "グルジア", "ウェーブ", "バッグ", "仮称", "地表", "投げる", "衛門", "魔導", "##ざい", "テクニック", "Club", "ルノー", "公示", "奉仕", "小池", "育つ", "##ッダ", "126", "あげる", "怒っ", "##ble", "ミュージアム", "ナビゲ", "ざわ", "ヨシ", "リヒ", "単身", "谷川", "何者", "諸説", "##ランカ", "##シュタット", "アウグスト", "Rock", "やむ", "ポリス", "ワープ", "右投", "皇室", "##わしい", "##ンプソン", "アーキテク", "##っぱ", "バルカン", "##URO", "キエフ", "中略", "部員", "オーダー", "収蔵", "湿地", "路上", "作り出し", "準じ", "うん", "失脚", "魔神", "チェス", "プラズマ", "キラー", "バビ", "文藝", "新編", "補正", "逝去", "##直す", "セントル", "散歩", "木星", "##がけ", "カリブ", "のび太", "ひがし", "トーン", "党派", "左岸", "##エイ", "1861", "フライト", "奥州", "##71", "##らぎ", "チャーチ", "ウィス", "フレデリック", "アムステルダム", "NATO", "Vo", "きみ", "供養", "元和", "開園", "飼っ", "1850", "カンボジア", "かき", "ツェ", "劣る", "小銃", "要し", "別冊", "##モロ", "ゼル", "剥奪", "右衛門", "津山", "サイコ", "試みる", "ブロードウェイ", "奇襲", "小室", "永田", "調印", "122", "番付", "おは", "オイ", "メド", "反動", "寝台", "##ニク", "ルネサンス", "物産", "##aka", "だいがく", "ゆっくり", "旭日", "##じて", "Int", "ユキ", "練馬", "##かかっ", "伊丹", "慰安", "##ストリ", "クア", "ホン", "飲む", "##ロド", "アドルフ", "刺さ", "反転", "吊り", "片岡", "エアロ", "カメラマン", "訴える", "ディープ", "往来", "遠い", "##ボス", "使命", "大沢", "愛用", "直流", "赤外", "辺り", "リタイア", "Christ", "マッカ", "断片", "渡す", "適当", "飛び出し", "ゼン", "フアン", "ロビー", "なんて", "入選", "操業", "牛乳", "若き", "##チョウ", "TAK", "於い", "##ダス", "コンゴ", "パナソニック", "モア", "最短", "##戻し", "CBS", "がく", "コナン", "生殖", "硬貨", "電報", "宗家", "折り返し", "ネス", "直樹", "資材", "立てる", "ケルン", "北欧", "減らす", "火薬", "あゆみ", "ゾイド", "店主", "結核", "醤油", "##付い", "ニンテン", "どおり", "平地", "武者", "点在", "納得", "##・リ", "##fl", "スピーカー", "セダン", "退け", "クリエイティブ", "ヘブライ", "不法", "決済", "竹田", "築き", "サンプル", "##スティック", "てい", "直結", "##デラ", "##リッヒ", "##ura", "握っ", "驚い", "キャサ", "輝く", "頼み", "##ONE", "不可欠", "信徒", "台東", "キャピ", "ナチ", "川内", "連ね", "市中", "ジェノ", "www", "ミハ", "国軍", "本書", "##pm", "##ラーゼ", "ジャニーズ", "フック", "松島", "洋画", "買う", "たば", "中堅", "手順", "神秘", "##コック", "##グレ", "この世", "立ち向", "大将軍", "エルサレム", "Best", "跳ね", "連立", "北村", "即座", "天明", "打倒", "精力", "##プール", "ローレンス", "上原", "町立", "##ッテン", "引き継ぐ", "ソフィア", "左派", "浄化", "田口", "新社", "経っ", "フェロー", "ローラ", "いわき", "なみ", "カク", "ピュ", "一言", "切手", "宛て", "巡査", "徴兵", "歌人", "##プライ", "##oss", "喜ん", "年下", "書道", "つづ", "なろう", "擁する", "ER", "##張っ", "ペドロ", "冷凍", "強め", "本文", "##DP", "ノルマン", "村長", "民謡", "装填", "123", "受け取る", "メルセ", "Bro", "##ソール", "アルバート", "ユリ", "事象", "守ら", "平井", "発光", "引き継ぎ", "ATM", "生み出さ", "##REAM", "レモン", "混雑", "視野", "##フィス", "吉岡", "椎名", "##きょう", "アルカ", "ハドソン", "シリ", "動揺", "帰宅", "掲げる", "##ビシオン", "Fac", "ネック", "帰郷", "慣れ", "臨海", "送電", "##sp", "東郷", "連行", "##du", "##降り", "##ティエ", "##ディーン", "みなと", "ホルモン", "面白い", "ミシェル", "給与", "荒廃", "ありが", "##ブレム", "仲良く", "ナレーター", "桑田", "レインボー", "DA", "罰金", "転属", "開花", "##ille", "冷戦", "##チド", "##振り", "VR", "ヨル", "リット", "名残", "変装", "消す", "祈願", "織り", "長門", "##ブランド", "##めき", "エストニア", "提督", "破る", "グラント", "テンポ", "頭取", "##ボウ", "コンタ", "イサ", "大破", "穀物", "##ese", "##ンパイア", "キッズ", "勤める", "追いかけ", "作り上げ", "促す", "託し", "シス", "知恵", "JO", "探知", "##ガンダ", "呼び出し", "無くなっ", "ぐる", "定番", "獲物", "隼人", "落ち着い", "##ーマーケット", "過酷", "##クサ", "Wi", "WD", "ジオン", "公言", "右岸", "篠原", "鶴岡", "550", "古巣", "民法", "##イクル", "志賀", "転居", "##out", "しゃべ", "ヒート", "ムシ", "月間", "紳士", "スパイダー", "Mod", "スティック", "花園", "モントリオール", "ヌー", "出自", "間に", "カザフ", "乗合", "基督", "有田", "架け", "良かっ", "スーパーマーケット", "塗り", "配分", "門司", "メルセデス", "届か", "##ートー", "ファイア", "ウズベ", "浸水", "遊ぶ", "ピッツ", "ポッド", "御前", "摩擦", "##ぐち", "##のう", "アイオ", "Mich", "佐倉", "駐留", "切り離", "祀る", "##トペ", "コーディ", "キャンセル", "Billboard", "Tok", "大江", "満洲", "発酵", "##ven", "スロバキア", "##ship", "Associ", "家電", "張っ", "濃い", "迅速", "不調", "側室", "加古", "移す", "見下", "ケータ", "ビュ", "社殿", "置換", "製紙", "##ner", "オリエ", "リバウンド", "動か", "蝦夷", "フランチャ", "SK", "ムラ", "幅員", "発令", "赤穂", "##ior", "##75", "マイナス", "あす", "処女", "国宝", "腕前", "ヴァージョン", "YOU", "火炎", "Sal", "ベール", "上回っ", "寄進", "局所", "舗装", "葛飾", "オールド", "優勢", "匹敵", "日刊", "##シマ", "##ゃく", "MON", "パルス", "配合", "##ドア", "##ばん", "##じん", "信州", "分かり", "摂政", "末端", "黒川", "佐久間", "壊れ", "水分", "聞かさ", "フルート", "吹き飛", "##チューム", "後漢", "##ニクス", "岩石", "挟ま", "退場", "開山", "ロータ", "公転", "細い", "##まつ", "パナマ", "事変", "分断", "アング", "分配", "可動", "台本", "清掃", "短調", "秋季", "ステータス", "楽しん", "プロトコル", "Life", "ラマ", "リーズ", "顔面", "##らん", "サーカス", "##クタール", "ずれ", "アゼル", "画策", "##しゅ", "スタメン", "まさに", "ヨハネ", "係る", "洗脳", "##LA", "##ーツァ", "火事", "立方", "遡る", "##ざし", "ジョイ", "及ぼす", "始末", "##INAL", "1848", "アテナ", "コスチューム", "Geor", "上皇", "分家", "目録", "##amb", "三遊", "広州", "詩集", "##ミュー", "なくなり", "シュトゥ", "##iver", "いすゞ", "サテライト", "AF", "なぞ", "生母", "番外", "祖国", "稼ぎ", "##ヒル", "##んじゃ", "メリット", "採集", "##ral", "##ella", "イズ", "アクセント", "サヨナラ", "ラ・", "公団", "有用", "##ンドル", "ブリテン", "づくり", "過ぎる", "テム", "ロベルト", "整え", "貝塚", "陽性", "##ベス", "ファイン", "イザ", "蔵書", "##クリ", "いずみ", "オト", "元来", "幕下", "有権", "ましょう", "キャサリン", "イヴ", "素子", "##ニバル", "ウォル", "SG", "##さか", "アンディ", "be", "へい", "バタ", "史実", "羽根", "陥り", "2500", "アドバイザー", "ストローク", "カモ", "メチル", "初心", "刺し", "安心", "架かる", "クライマックス", "河北", "##デンブルク", "菩提", "調べる", "転入", "##き出し", "##グリ", "##ンドロ", "慕容", "米沢", "##eral", "(-", "ml", "本能", "激突", "全編", "子役", "##メール", "##DL", "Min", "一味", "##げん", "##沿い", "アルバニア", "江戸川", "##ミュエル", "松戸", "運ん", "##ぐり", "MM", "ヘクタール", "ホース", "公平", "名簿", "奄美", "民家", "物件", "パンツ", "フェルディ", "デカ", "内包", "端子", "マーチ", "カンファレンス", "機密", "隷下", "##ポー", "大木", "有害", "盗み", "頼ま", "いくら", "トリプル", "移り住", "ヨーゼフ", "並み", "城壁", "除籍", "##ガタ", "さす", "居城", "最盛", "##ouse", "ac", "ノック", "戴冠", "義経", "ミズーリ", "以北", "古今", "合っ", "若く", "苦しみ", "サウジア", "OK", "Power", "モーション", "放火", "疲労", "##・ウ", "##きゅう", "ルドルフ", "雇わ", "ボスニア", "Sing", "サントリー", "炭酸", "特筆", "アベニュー", "Trans", "イニング", "掘削", "##かう", "オア", "下級", "瑞穂", "義勇", "自慢", "話者", "##まわり", "##ードル", "fl", "谷口", "包ま", "発案", "Inter", "原曲", "渡さ", "麻痺", "##さき", "パラダイス", "##トペテルブルク", "偽装", "内外", "燃費", "貼り", "##ren", "##ステン", "イース", "勧誘", "萩原", "赴い", "##ision", "ライブラリ", "Nor", "le", "衣服", "ヴィー", "##ACE", "ストライク", "大介", "巧み", "承継", "見かけ", "ノイズ", "体長", "地主", "##iro", "フランクリン", "ロマンス", "年表", "所沢", "##IK", "1830", "ジャスティ", "ヴェー", "スローガン", "久保田", "反抗", "抽象", "静止", "アルマ", "ギャン", "下田", "勅令", "後続", "収束", "編制", "##ero", "プロフェ", "##ats", "レイアウト", "キノコ", "促し", "改宗", "生駒", "開会", "サイモン", "EL", "アラスカ", "勝率", "問う", "##ショウ", "インストール", "コナミ", "接収", "##ペスト", "両端", "堀江", "崩し", "白井", "耐性", "##ican", "REC", "サミュエル", "退治", "風土", "ディーン", "##ital", "プラント", "マクロス", "イーグルス", "イオ", "幼虫", "煙突", "重臣", "望月", "極め", "胸部", "サウジアラビア", "ゲオ", "パド", "各所", "対外", "義理", "貯金", "エンタープライズ", "ゾウ", "リンパ", "全権", "尻尾", "監禁", "シャッター", "スパルタ", "##ebook", "待遇", "漏れ", "##てい", "Award", "Time", "一説", "前部", "収監", "四川", "思え", "##・ボ", "330", "アライ", "使い手", "つぶ", "ノーマル", "暴露", "自伝", "長寿", "飯塚", "両腕", "動かし", "商学", "恒例", "病理", "経費", "##バナ", "##デンス", "書き下ろし", "##ャンマー", "Er", "マフ", "カジノ", "セントルイス", "CON", "普遍", "莫大", "Ang", "まこと", "全力", "坂井", "市域", "旧称", "##work", "激化", "##トリア", "あいだ", "失格", "安土", "肺炎", "##トス", "##キサ", "##ICE", "von", "代打", "属す", "承諾", "##おか", "ライス", "にくく", "タク", "一条", "変貌", "尚書", "屈指", "平塚", "急死", "退い", "発砲", "見込み", "##サリー", "##ザール", "##チネ", "模倣", "##ミッド", "古賀", "招く", "漁港", "育てる", "ショーン", "伯父", "##ジック", "##がん", "##井沢", "インテル", "##バイジャン", "FOR", "工廠", "関税", "高槻", "net", "ホウ", "民兵", "添え", "優等", "ウォーク", "ステンレス", "フン", "マヌ", "ミャンマー", "南下", "外さ", "##メリカ", "##十郎", "スプリント", "アゼルバイジャン", "##ze", "カルシウム", "たばこ", "Bas", "アリー", "何故", "八百", "発想", "移送", "貯蔵", "起業", "酷似", "モーツァ", "失業", "接種", "明和", "軽井沢", "ファラ", "##ネスコ", "(\"", "マウンテン", "味噌", "##付き", "un", "ミヤ", "持ち込ん", "いきなり", "生き残り", "ハラ", "マッカー", "山麓", "ジェーン", "慕っ", "窮地", "読ま", "LS", "リエ", "筐体", "達人", "##コード", "キャロル", "やく", "茶色", "##レクト", "##レーヌ", "##メンテ", "SON", "はく", "レンジ", "出陣", "留め", "##キル", "##ノル", "ベラル", "ミッキー", "献上", "疎開", "Reg", "JS", "Ter", "じんじゃ", "兄妹", "戦果", "貧しい", "##コット", "エッジ", "硫酸", "誓い", "クロム", "庄内", "Win", "全英", "法制", "##のぼ", "フォント", "ハリケ", "伴奏", "宿主", "アンソニー", "共用", "翌週", "近辺", "馴染", "成し遂げ", "並木", "児玉", "渡米", "OH", "再戦", "商用", "望み", "遊ん", "##くら", "##着く", "ステア", "##ーニュ", "パーソナル", "LINE", "グライ", "ゴス", "売っ", "官職", "海運", "##オラ", "##ody", "売ら", "早々", "マルタ", "敢行", "無駄", "終始", "覆う", "諸侯", "##ッロ", "オーラ", "ウェルター", "Act", "多重", "子音", "##こん", "##レンツェ", "パイオニア", "同点", "炎上", "狙わ", "退却", "Robert", "少々", "水晶", "豊後", "預金", "##ij", "##ギリ", "ジュリア", "クレーン", "グスタ", "便利", "晴れ", "有明", "白河", "碑文", "絶賛", "サラリー", "アーキテクチャ", "HS", "MX", "われ", "ロブ", "塩基", "##バータ", "近づい", "掃海", "祇園", "驚く", "アルビ", "同曲", "更なる", "自爆", "チャー", "ファイナ", "イヤ", "ジーン", "ミツ", "崩御", "近縁", "Mor", "do", "ノリ", "鍛え", "除け", "##ソス", "ヒューマン", "共鳴", "急増", "表向き", "アレル", "##ッケル", "ベーシスト", "GE", "カヴァー", "ナッシュ", "##IVE", "##メガ", "ルス", "受注", "無名", "総監", "補完", "##ミッション", "Ber", "中身", "本戦", "##・ム", "##ぐれ", "クリミア", "チェコスロ", "マキシ", "宇部", "届く", "結社", "##持つ", "エンジニアリング", "サンクトペテルブルク", "ソラ", "噛み", "祀ら", "めぐり", "セミナー", "マッ", "古来", "稼動", "車掌", "養老", "##ギャ", "##ノミ", "出せ", "新党", "織物", "##ザース", "コミュニケーションズ", "クリストファー", "執事", "##れん", "間違っ", "San", "セクション", "混在", "部落", "飛ばし", "##コーン", "キン肉", "キネマ", "回帰", "恨み", "阿蘇", "##ダラ", "##ティウス", "Cent", "信任", "浅井", "ジャングル", "##atch", "つくり", "グー", "ユン", "戸籍", "東ドイツ", "狭く", "迷宮", "マルク", "阿弥陀", "VHS", "天台", "学期", "平坦", "##ball", "##ケス", "##ホルム", "バラード", "まとめる", "だし", "六角", "新造", "沼田", "##ナール", "##助け", "##フィールダー", "がり", "可変", "日報", "格子", "法華", "ミッドフィールダー", "##カロ", "205", "タキ", "母国", "リリーフ", "ハイビジョン", "秋葉原", "RNA", "毒性", "称え", "Des", "必死", "オレゴン", "微妙", "終わら", "迷惑", "##タリ", "##プラー", "##だん", "##々しい", "たまたま", "転倒", "スミ", "乱入", "奮闘", "##ッペン", "カルチャー", "エグゼ", "大門", "撤廃", "競う", "達也", "メモリー", "屋台", "村人", "重ねる", "集計", "黄色い", "揺れ", "担い", "本番", "##クレ", "##乗り", "マウ", "亀山", "宇佐", "フィクション", "みなし", "日韓", "首領", "ランチャー", "])", "小西", "総括", "##ye", "##コシ", "LC", "ガム", "吉村", "向こう", "無敵", "直撃", "##ジアナ", "Rev", "PAS", "却下", "##ガラ", "ピラミッド", "三遊亭", "今治", "南道", "宿舎", "親方", "##カリスト", "ギー", "マシュー", "処罰", "支出", "解禁", "逃れる", "##イアント", "さし", "丹後", "##its", "クオ", "低地", "儀礼", "全盛", "オリン", "ベビー", "マテ", "淡水", "眠り", "納め", "迫ら", "パーカー", "##ATE", "メロディー", "レバノン", "きた", "夢見", "##ニアン", "ちなむ", "バンコク", "se", "増幅", "延暦", "真剣", "軽巡", "Up", "ペナル", "開閉", "##・イン", "オラ", "片山", "薔薇", "西端", "##さつ", "アヤ", "ベラ", "大火", "容赦", "山東", "ストリー", "Sport", "日比谷", "650", "パニック", "##イルズ", "##ARS", "カーター", "下水", "扮し", "紅葉", "銘柄", "##っ子", "ディビジョン", "弾道", "救命", "赴き", "##マーシャル", "宅地", "敦賀", "機雷", "##プトン", "サング", "州道", "幕内", "繰り広げる", "売春", "座っ", "関ヶ原", "プライド", "返済", "カマ", "ドリル", "中頃", "支障", "騒ぎ", "##ideo", "News", "KBS", "mg", "備前", "##・ファ", "一騎", "入試", "反する", "棄権", "知行", "防護", "フィレンツェ", "コンピレーション", "ハンドボール", "ベラルーシ", "City", "アストロ", "ホモ", "尾道", "旗揚げ", "規約", "閉塞", "執り行", "きわめて", "モーツァルト", "唐津", "立教", "##まま", "##ージョ", "マヤ", "江東", "BAS", "ダラス", "ルビー", "充分", "北見", "支払わ", "##フレーズ", "Song", "セメント", "悩ん", "遠山", "遠ざ", "JIS", "ノウ", "公家", "尾根", "岩田", "辞書", "##・ベ", "コンペ", "Mark", "ヒルズ", "進言", "##トゥス", "Port", "なさい", "エステ", "カレ", "処方", "大きかっ", "EMI", "ロッキ", "提起", "##ola", "ギュ", "152", "mmF", "ヴェスト", "艦名", "##ッチン", "MY", "サリ", "土浦", "激減", "##83", "##食い", "スキン", "1859", "##ルタント", "メカニズム", "アリア", "波長", "陰陽", "風貌", "##ンスト", "リポート", "例年", "別人", "図り", "堀川", "##hone", "ヘルマン", "ロータリー", "成す", "絡み", "見抜", "波動", "講堂", "##連れ", "ふう", "大胆", "平定", "爆笑", "インフル", "スティーヴン", "Fi", "うさ", "低温", "届い", "教場", "説教", "##ゴス", "EF", "Kn", "ぬい", "墳丘", "消火", "##・ホ", "##バーズ", "ブレイン", "アルフレッド", "ヒンド", "ユネスコ", "助成", "那珂", "鉄砲", "コンサルタント", "野望", "##テー", "国々", "室蘭", "敬意", "自走", "麻酔", "ジャム", "クロウ", "スカー", "帯広", "水深", "私鉄", "##ガルト", "ジョナ", "国政", "日テレ", "発進", "##が丘", "##ボリ", "器用", "欠け", "藤岡", "負債", "麻衣", "##ボロ", "-(", "隠す", "宮中", "接合", "提言", "##15", "280", "キングス", "よこ", "シュル", "ウォッチ", "ディフェンダー", "リブ", "反響", "含有", "杉並", "華族", "迷い", "フィニッシュ", "ピストン", "ホールド", "入所", "多々", "征伐", "選帝", "##ューズ", "繰り返さ", "呼び名", "ネルソン", "一派", "権現", "瑞宝", "外相", "嫌悪", "連射", "##の丸", "##ico", "##olution", "WEB", "イソ", "培養", "注ぐ", "スタンプ", "エイジ", "北川", "噴射", "死神", "終える", "部数", "青梅", "願っ", "##ツィヒ", "ドリー", "手数", "藩領", "黒髪", "##シリーズ", "##カーズ", "アルプス", "270", "Amaz", "国分寺", "オタク", "内定", "吹田", "大通り", "##ずら", "##フォー", "キャッチフレーズ", "##マイカ", "FBI", "スカル", "石碑", "連想", "1858", "投獄", "立命", "計量", "##レク", "スロベニア", "プロトタイプ", "器官", "軌間", "バンクーバー", "おこなわ", "マディ", "炎症", "鍛冶", "##TO", "大抵", "宮川", "浪人", "調停", "迂回", "##ARA", "NAID", "パラメータ", "Mer", "大平", "歩き", "流派", "フライング", "TM", "##メス", "##ホマ", "##ンガル", "ハンブルク", "フリゲート", "延び", "神父", "里見", "260", "プラグ", "テロリスト", "Techn", "チア", "レット", "土井", "声楽", "隔離", "シャドウ", "ベートー", "アルベルト", "ジェル", "いざ", "準急", "直列", "組長", "ブルックリン", "サバ", "写像", "粘土", "若年", "開口", "##ドキ", "シグナル", "Che", "六本木", "川端", "流星", "アルテ", "マクドナルド", "tr", "分ける", "打診", "換算", "松永", "話さ", "##サラ", "行き来", "http", "シリンダー", "不当", "厚木", "四角", "攻防", "断ら", "すば", "アロー", "終焉", "愛宕", "説い", "##ントス", "アクセ", "フランチャイズ", "中年", "放浪", "DT", "バックス", "健太", "本庄", "##祭り", "ギン", "下総", "離党", "##RO", "ギブ", "分化", "いな", "多賀", "挑発", "砲台", "ライプ", "こだわり", "Sn", "ノブ", "栄誉", "校内", "ララ", "レプ", "桑名", "##to", "コマーシャル", "##ソウ", "##ヘル", "クリエイター", "オムニ", "注射", "カラーリング", "##ハーゲン", "なれる", "ノード", "分立", "葬ら", "視界", "音色", "##カミ", "##ンプトン", "トランペット", "Blue", "希少", "演芸", "##QU", "##らう", "##ona", "カリス", "トマト", "パク", "有り", "貸切", "##アム", "##arl", "##ney", "サックス", "反則", "発刊", "糖尿", "UFO", "アソシエ", "もて", "代議", "参道", "櫻井", "返す", "##バンス", "##ush", "エディション", "MAN", "三国", "協調", "##ワース", "エイリアン", "King", "ソリューション", "焼い", "遭難", "騒音", "高砂", "##ツキー", "アルジェリア", "##オーバー", "RECOR", "RT", "アッシ", "付録", "旧暦", "ポルシェ", "BP", "Fe", "エラー", "パンタ", "富岡", "店頭", "母校", "深川", "##ets", "クリップ", "##ike", "知性", "許容", "クリーブランド", "オウ", "恐慌", "##ネード", "ギャル", "マスターズ", "##キャップ", "##uck", "キリン", "ケープ", "一応", "体色", "司る", "弾頭", "絞り", "頼ん", "呈し", "奥田", "##yr", "ステッカー", "##ブリエル", "オリー", "不審", "##くる", "シマ", "刑法", "部署", "##ety", "八尾", "大映", "悪役", "樋口", "演歌", "襲う", "西岸", "見通し", "##ific", "かま", "戸塚", "ハイウェイ", "PRO", "GA", "イニ", "直人", "艦載", "##シズム", "##テラ", "インデ", "##ストラクター", "Champ", "デイヴィス", "Sun", "iOS", "入線", "対潜", "独身", "迫害", "飾ら", "##rop", "生き延び", "RAD", "Soft", "キース", "宇和", "東端", "法定", "浮遊", "香取", "たまに", "EV", "サボ", "ダニー", "レム", "大仏", "握り", "速力", "コリ", "学派", "寺社", "志し", "消耗", "##ナーレ", "盛り込ま", "聞こえ", "山間", "帝都", "点検", "ディフェンス", "##フェルト", "##ちゃん", "ニーズ", "開港", "##ろす", "オバマ", "バーナ", "作物", "栗原", "カネ", "勝敗", "増備", "戦記", "ファント", "ファンド", "ストーム", "UH", "えり", "ケント", "ポピュ", "納税", "年寄", "教義", "衰え", "隆盛", "隕石", "鳴門", "五十嵐", "##ield", "無形", "チェコスロバキア", "クック", "利便", "実子", "欠陥", "美し", "進級", "##ポル", "##あげ", "トリノ", "LA", "PM", "アワー", "抹殺", "綬章", "##witch", "ドミニカ", "ジブ", "ヒメ", "大小", "徳間", "目の", "オークランド", "ゴロ", "公判", "教鞭", "曹洞", "USB", "従兄弟", "ばね", "クリーン", "擁し", "水族", "##あき", "始祖", "延喜", "建っ", "竜王", "スペック", "NBC", "Sum", "オクラ", "ブレス", "ブースター", "共々", "溶岩", "Str", "公卿", "奔走", "自力", "スケッチ", "1854", "クイン", "叫び", "含み", "浅間", "猶予", "裏面", "##ベガス", "##ちょう", "ジャイアント", "コンサルティング", "スティーブン", "そろ", "前衛", "勝て", "祭祀", "##VID", "##チウム", "##受ける", "グルー", "USA", "##ルツェ", "Thom", "Tw", "あふ", "ボイラー", "制式", "厚く", "噴出", "従属", "赴く", "スカパー", "ミリオン", "一転", "返上", "##ハル", "Os", "結末", "人道", "反逆", "##レナ", "##シャワ", "##ocal", "Facebook", "サラリーマン", "マッド", "出かけ", "新宮", "##DI", "##レーツ", "##ナーゼ", "James", "察知", "尽き", "患っ", "産経", "空挺", "観念", "讃岐", "##タニア", "##TH", "##カム", "##寄っ", "##売り", "サンパ", "##イオス", "BMW", "ロット", "同郡", "大東", "##バリ", "##カレ", "##びき", "なくなる", "コンチネ", "con", "メッツ", "北海", "寸法", "新報", "日吉", "美味", "証人", "Tri", "みき", "付着", "半球", "大連", "水色", "##チー", "付き合っ", "アサヒ", "サリー", "信玄", "協賛", "##・タ", "##ずみ", "ストライキ", "神崎", "築地", "臨む", "訳さ", "##98", "##za", "TOP", "ジュース", "ナムコ", "ル・マン", "さよ", "奈々", "さよなら", "GU", "ヒール", "小金", "明瞭", "星座", "父子", "耐震", "##コウ", "ユニーク", "やり取り", "見習い", "ひまわり", "宇野", "##強い", "デビッド", "ホルン", "大物", "大寺", "推力", "ジュン", "カレンダー", "フィルハーモニー", "くす", "交配", "勝目", "翌月", "124", "1300", "Association", "もろ", "兵役", "島原", "粛清", "タウ", "産物", "築造", "1400", "つなぐ", "ありがとう", "コンチネンタル", "ブエ", "リール", "河南", "スクウェア", "1855", "オウム", "クィ", "ヴュル", "初音", "柔術", "極度", "物事", "##かえ", "##ぼさ", "GHQ", "ムル", "及ぼし", "点灯", "##レーン", "##ッティング", "##カップ", "振り返っ", "修学", "合作", "天草", "長浜", "##リナ", "##ビウス", "クローズ", "##クスピア", "木場", "##めん", "アマゾン", "横手", "課長", "##ンシー", "##ハマ", "##グア", "##巻き", "##ぶり", "クラリ", "くさ", "シラ", "モモ", "平山", "腐敗", "解読", "スクラ", "大船", "幕張", "犬種", "紫色", "工法", "撮り", "母子", "特務", "適正", "医院", "見受け", "辿り", "ケータイ", "アザ", "##フマン", "##vent", "思い出し", "カスティー", "隙間", "Sl", "困っ", "追及", "##プテ", "イントロ", "クッパ", "ヶ国", "不倫", "人造", "##コト", "強かっ", "##oph", "アッパー", "新川", "溶け", "照準", "苗字", "##CA", "ルーズベルト", "Ze", "セネ", "吉良", "養殖", "キューブ", "ラスベガス", "バファ", "マリーン", "劣化", "江南", "筑紫", "至り", "まとも", "石室", "薬局", "##ワット", "ひこ", "アクター", "一括", "三味", "手助け", "止まり", "トラップ", "建て替え", "ヴォルフ", "ダス", "手足", "止まっ", "##行き", "ふん", "直属", "##エール", "##そり", "##ipp", "おもちゃ", "American", "Special", "ハリケーン", "吉祥", "熱血", "血統", "キャット", "プラチナ", "Enter", "CLUB", "バロック", "改める", "狭義", "用水", "霊場", "青銅", "##カゲ", "##ワフ", "ルイジアナ", "メーター", "横田", "観覧", "長身", "##ヘッド", "##ora", "カト", "導き", "溶接", "##ael", "ウルグアイ", "JT", "ゲノム", "シスター", "ホープ", "優駿", "城山", "給油", "##タリア", "##りん", "アンカー", "クロード", "バックアップ", "クリーク", "LD", "ひな", "デリ", "並列", "養女", "##セックス", "起こさ", "コスモ", "ギャラクシー", "CIA", "みせ", "荘園", "モノレール", "##iversary", "ヨハネス", "支那", "繰り出す", "Med", "du", "公営", "大工", "解く", "通販", "##tain", "##ィー", "##AMA", "##ELL", "iPhone", "リモコン", "不況", "入札", "田代", "破片", "警護", "##17", "##パルト", "いまだ", "カズ", "シング", "デパート", "リソ", "光景", "政宗", "若狭", "##レイク", "アミューズ", "Tokyo", "らく", "ユタ", "蛍光", "連鎖", "##ジーミル", "パラリンピック", "DAY", "ひき", "図柄", "在職", "明示", "金星", "フィア", "ジェイソン", "デラックス", "Pi", "充て", "熱海", "##カヤ", "##ホーム", "ストリーム", "ナナ", "一線", "着目", "請け", "青島", "##ダード", "##ロラ", "世襲", "肥料", "##GS", "ジャマイカ", "埋め立て", "おはよう", "つば", "名作", "弱体", "旧来", "祝福", "カービィ", "細長い", "後円", "短歌", "経理", "豪族", "##ゲス", "##渡す", "##OSS", "MAR", "bl", "キプ", "請願", "##my", "##ena", "キログラム", "バッジ", "ミッチ", "打数", "鉄路", "顕彰", "##かつ", "バーデン", "So", "ガリア", "照射", "閣議", "サミット", "円筒", "問屋", "飛躍", "##たか", "アクセル", "##ーチャー", "レター", "売店", "池上", "##ッツォ", "グスタフ", "ヴュルテンベルク", "リビア", "取れる", "田川", "盗ん", "兵衛", "同県", "太政", "石巻", "##さり", "##変わり", "勝ち越し", "ドキュメント", "埠頭", "ものまね", "--", "NM", "ボヘ", "土岐", "採っ", "##ham", "折れ", "撃た", "格差", "死傷", "素顔", "##ざき", "バースト", "ファイヤー", "こころ", "大泉", "##ヴル", "##ated", "ベートーヴェン", "まな", "ルーク", "健全", "愛さ", "接着", "日没", "##タリー", "Jo", "オロ", "前頭", "大黒", "楽しい", "細工", "臓器", "##lt", "##RNA", "Fri", "コスタ", "ヒン", "荷重", "重なっ", "Amazon", "フッ", "下っ", "##コミ", "##ぜん", "##去ら", "フェルト", "乗り込ん", "デニス", "積分", "西条", "##奈子", "144", "ウェン", "ビック", "レジャー", "##んどう", "SPEC", "Sil", "完走", "構える", "##uss", "##over", "セレクション", "外出", "文京", "水島", "補欠", "農園", "仕掛ける", "公用", "律令", "絵師", "##ジェスト", "##IST", "org", "プエルト", "ペトロ", "新城", "望ましい", "沢田", "片手", "西欧", "##詰める", "知多", "給付", "##直さ", "ウッ", "クン", "坂口", "均一", "校地", "##モト", "##リオット", "##ada", "##ATA", "おば", "浅い", "##・ル", "##OLD", "ライブラリー", "インフルエン", "カバ", "ロスト", "童話", "自機", "貯水", "##ボーグ", "##ISS", "1840", "大作", "討論", "重く", "##テット", "Bre", "供与", "入党", "共感", "寺田", "浮き", "要領", "##ブリア", "##ペス", "##72", "##まか", "##ルツブルク", "トランスミッション", "すり", "プチ", "ミキ", "居る", "聖地", "聴く", "超過", "陣屋", "##やき", "##キュラ", "1857", "フェルナンド", "シュタイン", "乃木坂", "エステル", "リプレイ", "さらさ", "##ello", "リヤ", "万葉", "各局", "廉価", "視力", "頼っ", "満たさ", "ft", "コバ", "コメンテ", "口座", "##テロ", "##ゴラ", "アンモ", "480", "Alb", "Paul", "Li", "RK", "おっ", "入浴", "別途", "幽閉", "一夜", "不信", "##ジロ", "##サキ", "##YP", "##止める", "WAVE", "京急", "分身", "施策", "##トロン", "シェイクスピア", "ピッツバーグ", "アディ", "剣士", "##IF", "エルンスト", "メリーランド", "オク", "モラ", "紀州", "##aj", "##rumental", "コメンテーター", "エプ", "争奪", "入間", "洋子", "異端", "##コタ", "クランク", "サンパウロ", "オセ", "パトロ", "ルター", "万博", "東名", "ヒドロ", "転職", "##mb", "##ゴール", "OG", "降車", "つくら", "Cap", "ジーク", "バチ", "棄却", "武藤", "見知", "高倉", "ジャワ", "スパイク", "Bu", "スチュ", "受講", "安永", "岩国", "彦根", "水害", "訂正", "トラウマ", "加古川", "オクラホマ", "草原", "解像", "部会", "##・ビ", "##illa", "SV", "スレ", "ベリ", "伊集", "吐き", "大差", "登校", "肝臓", "魔族", "##よい", "ディスコ", "https", "伊集院", "治水", "県都", "スム", "断面", "月面", "派出", "諮問", "##メア", "##分ける", "ぬいぐるみ", "DREAM", "テラス", "ハノー", "大成", "近海", "Bi", "公論", "兵装", "同上", "巡航", "行こう", "見積", "フォレスト", "フレッシュ", "さだ", "らい", "ガブリエル", "レック", "最寄", "着ぐるみ", "金利", "アーノ", "ペンギン", "デュオ", "サファ", "モンタ", "リフ", "久美子", "乗船", "八郎", "団長", "邦題", "##ペディア", "フルーツ", "コントラ", "リットル", "FINAL", "久々", "敗者", "望ま", "移築", "貞観", "MAS", "Po", "アクト", "ラド", "生還", "さんま", "シンセサイ", "リコ", "催さ", "原点", "定か", "幕僚", "縁起", "1856", "トロフィー", "せんしゅ", "モト", "議決", "##18", "マルティ", "人柄", "執っ", "学業", "忍び", "手動", "泥棒", "肥後", "ディスカ", "っ子", "へん", "カラス", "コリン", "伝導", "挟み", "水谷", "速報", "1700", "##ensis", "イアン", "ピュー", "岸田", "クロック", "##OME", "モーリス", "ベンツ", "##endo", "##デレラ", "ISSN", "にゃ", "ブーツ", "代々木", "効力", "外装", "揶揄", "祝い", "銃身", "##よそ", "Group", "##ittle", "ヒラ", "疲れ", "私的", "編み", "裕子", "##たら", "##デスリーガ", "レオポ", "プス", "無断", "福知", "紀行", "##12", "いただ", "手伝っ", "由紀夫", "アイオワ", "乱闘", "均衡", "手間", "##サム", "##モー", "ウェイン", "##berg", "ソマリア", "小坂", "常盤", "滝川", "王宮", "算出", "緩やか", "野戦", "驚き", "1100", "ジャス", "カルタゴ", "フラット", "Yah", "アッシュ", "エラ", "光明", "小浜", "オリオン", "PDF", "カオス", "来場", "歌声", "淀川", "David", "Cy", "KC", "ナオ", "万国", "妥協", "枠組み", "##高い", "ブレーブス", "コイル", "ダブリン", "岡部", "新庄", "立派", "飲酒", "ワルシャワ", "Not", "ブタ", "主計", "出兵", "磐田", "##ling", "ディン", "ジェームス", "ウェスタン", "ロビンソン", "GC", "減速", "錬金", "チャップ", "持ち込ま", "ローラー", "##OCA", "##ッシブ", "宮田", "昨年", "特産", "畠山", "##ッラー", "リーフ", "##esents", "##グラード", "イワ", "ケベック", "元号", "神谷", "##・ナ", "##UP", "##仮名", "パスポート", "エレクトロ", "LAN", "VI", "岩井", "間に合わ", "シンセサイザー", "根岸", "欠席", "潜伏", "##タイトル", "##ILE", "##rain", "買い物", "IMD", "ルース", "小平", "憑依", "細かく", "ハブ", "以西", "殲滅", "洗濯", "相性", "紡績", "行け", "賃貸", "133", "##elle", "テュー", "四条", "弦楽", "後見", "栄光", "桑原", "芦屋", "##オウ", "##eng", "トリガー", "富士通", "しお", "バズ", "共生", "天空", "宇多", "雑貨", "##ンドルフ", "プロポ", "知らせ", "ブンデスリーガ", "Af", "TP", "エーカー", "クレー", "ケニア", "シルク", "留まる", "長安", "##ta", "##ネスト", "パブリック", "PT", "ブックス", "マスト", "一因", "工兵", "強固", "後押し", "担保", "秀樹", "##ラール", "スリランカ", "だらけ", "福知山", "Il", "rpm", "海面", "##ck", "ヒンドゥー", "おま", "タスク", "一層", "堀内", "家人", "強要", "滅ぼし", "##オロ", "##enter", "アッシリア", "Rem", "演目", "激戦", "##de", "引き取ら", "振り回", "キャンベル", "ナイジェリア", "かたち", "County", "バレンシア", "Sam", "載っ", "門前", "魔人", "##irect", "AW", "NWA", "つと", "夜中", "準州", "赤松", "重用", "##・ポ", "##かかる", "10000", "アトリエ", "レジェンド", "リオン", "上水", "優子", "自害", "製菓", "##la", "ラッキー", "レンガ", "基底", "履歴", "血圧", "闘い", "驚異", "クリントン", "##クラブ", "覚える", "##ーグル", "DeNA", "メルボルン", "TW", "同調", "後悔", "新居", "走者", "##ロア", "チューブ", "パーソナリティー", "ジョーダン", "Suica", "ウラジーミル", "カスティーリャ", "NR", "ペプ", "共存", "襲来", "##ボク", "グリップ", "Hi", "べし", "兵員", "和彦", "清算", "##be", "Champion", "Lib", "委任", "戦役", "明言", "秋元", "策略", "##掛かり", "フランチェ", "フィルター", "クエ", "刈谷", "簡素", "##・ユ", "##千代", "乗馬", "劇作", "父母", "相関", "##ny", "##シアム", "ジャンクション", "JB", "いら", "##EP", "##END", "ニュートン", "Rich", "Sw", "キャンディ", "Serv", "コンタクト", "インフルエンザ", "gr", "川西", "源泉", "筒井", "親しい", "##ダスト", "ティラ", "##ファーソン", "タール", "バッド", "ミミ", "亀田", "壁画", "帰化", "苦しん", "茨木", "闘士", "146", "##ンタイン", "ケイト", "ブダ", "下着", "保留", "家業", "明智", "産卵", "かねて", "たった", "当面", "拠れ", "発端", "開場", "随時", "##みつ", "##倒し", "##ンバーグ", "##ブルドン", "マッサ", "丁寧", "休み", "冗談", "回送", "架橋", "クーパー", "IF", "転々", "郡上", "ノーフォーク", "発起", "社交", "身代", "##・ガ", "スクロール", "可愛い", "ラベル", "侍従", "儲け", "割っ", "圧迫", "揚陸", "素早く", "負わ", "麻布", "##ser", "アレルギー", "ちん", "ほの", "イナ", "ヘルス", "リッジ", "伝来", "踏ん", "##ルカ", "アイコン", "スーダン", "##ANT", "ドラムス", "バッファロー", "スルー", "五島", "チャネル", "引き起こさ", "インテリア", "バファローズ", "あま", "シノ", "感想", "##ネーター", "シュヴァ", "380", "クロン", "セクター", "変態", "夜明け", "実権", "短大", "祭壇", "IDOL", "Mart", "ph", "パケット", "後進", "熱狂", "絶大", "自生", "響き", "##bur", "オーブ", "グラミー", "グリッド", "CN", "刷新", "女装", "徳山", "感銘", "極限", "ウィンドウ", "ティン", "##iko", "Pal", "パウロ", "人型", "和夫", "抜群", "捕ら", "突出", "巻き起こ", "ペナルティ", "一大", "採ら", "男児", "神明", "都督", "鳴き", "##ごろ", "NEXT", "Good", "エナジー", "PAR", "SRC", "体当たり", "四球", "天守", "廃線", "江川", "渡航", "近似", "##ッホ", "##牟田", "ソフトボール", "打ち出し", "ニコラス", "##OLL", "サブタイトル", "テュ", "ワト", "去り", "太宰", "抜く", "##重なる", "##ates", "心身", "艦橋", "陶器", "##iew", "オスカー", "インストゥル", "途絶え", "RECORDS", "Hen", "らし", "パンダ", "文脈", "硬化", "結界", "越中", "しげ", "ほっ", "赤城", "イースタン", "モダン", "ラプ", "広め", "手帳", "鳩山", "##イロ", "##ウェン", "##unes", "グリル", "GIR", "気絶", "選曲", "##ザル", "##さく", "フィット", "スワローズ", "my", "坂上", "強行", "強硬", "豊岡", "##ぶつ", "シンデレラ", "おおよそ", "IMDb", "メロン", "モリス", "回廊", "強姦", "船員", "雲南", "##・ソ", "##バット", "アルティ", "カイロ", "ウィンブルドン", "シークレット", "じい", "カエル", "乏しい", "気体", "素人", "ウォルト", "ノーザン", "つま", "ミノ", "基板", "慕わ", "洗浄", "苦悩", "英名", "都会", "##向け", "301", "Heart", "サングラス", "涼子", "脊椎", "乗り場", "フットサル", "入省", "同区", "水着", "Yahoo", "WH", "九十", "単線", "突進", "##OO", "##ファーレン", "よろ", "ロドリ", "信越", "坊主", "宝永", "対比", "府道", "浩二", "ひとみ", "すすめ", "WBO", "ベック", "売る", "岩倉", "エンブレム", "落とさ", "オークション", "##リノ", "クリニック", "マカオ", "デコ", "ピンチ", "停戦", "客観", "進ま", "##こく", "##ative", "310", "キッチン", "ギミック", "十郎", "津島", "キャバ", "サイレント", "プレゼン", "スマイル", "教え子", "ルクセン", "国交", "業態", "銚子", "ジョブ", "ランカ", "フィリップス", "ベンチャー", "ミクロ", "個展", "坂田", "奥羽", "沿革", "良き", "配偶", "##79", "ウィンター", "Radio", "850", "共作", "劇的", "見れ", "コールド", "先制", "増資", "小原", "歩み", "誠実", "預言", "Del", "ウリ", "オンタ", "ワニ", "吉井", "杉本", "松阪", "##キウス", "##era", "クラッチ", "バトラー", "ファントム", "アガ", "いや", "不快", "暴れ", "未亡", "秘め", "艦上", "赤羽", "アトランティック", "未亡人", "三沢", "土産", "映し", "病原", "銃弾", "阿久", "##マール", "ANN", "交友", "因縁", "奇数", "帰投", "廃藩", "授賞", "##EG", "##13", "受け取り", "オンタリオ", "Gal", "ペリー", "ボビー", "マヨ", "怒ら", "東邦", "汚れ", "益田", "雷撃", "162", "##ICK", "ガイドライン", "ゲオルク", "ジョナサン", "エッグ", "店内", "捕縛", "教習", "滑り", "##・ヴィ", "##シャイン", "宝物", "慈善", "野心", "両立", "両社", "握る", "操り", "決算", "沈ん", "畜産", "##56", "##たる", "134", "くち", "中井", "急進", "果物", "##去る", "レーニン", "ざん", "はっ", "イモ", "各務", "待た", "##フー", "レコーダー", "Sci", "押さえ", "ギガ", "下手", "天竜", "居酒", "帰属", "深海", "造園", "##ディウス", "居酒屋", "PART", "マタ", "翻弄", "肥前", "阿南", "##ぱら", "アンコール", "たかし", "伊那", "同然", "天理", "張本", "強奪", "流動", "精製", "##ミール", "132", "乗り越え", "キア", "バター", "分社", "揃え", "本丸", "眠っ", "##オリ", "スタイ", "サーチ", "##ival", "Fight", "将兵", "ピクチャーズ", "HO", "オデ", "フレー", "光子", "清朝", "##gen", "##カワ", "##留め", "ジャンボ", "譲り受け", "直し", "造語", "##おる", "##ILL", "返り討ち", "VF", "叔母", "実弟", "新橋", "蘇生", "##バダ", "乗り出し", "SMAP", "怖い", "気づき", "Anniversary", "パトロール", "カ所", "文禄", "##ITY", "##オーリンズ", "女児", "庇護", "木津", "理性", "税務", "複素", "##uel", "##19", "1853", "ミケ", "北道", "憲章", "松前", "注入", "流体", "規範", "##屋敷", "##ッツァ", "##サンブル", "しず", "大別", "断り", "解か", "##ORY", "フラッグ", "##サック", "##ぶし", "プロパ", "ダイジェスト", "KAD", "mus", "下降", "介石", "島内", "恵比", "カリウム", "スラヴ", "ru", "乱れ", "堂々", "注い", "熱い", "##JP", "シェフ", "ワイヤー", "ルクセンブルク", "マンス", "元町", "半田", "批准", "本島", "海中", "消える", "緒方", "##ズス", "##ci", "##どか", "デュエット", "Ev", "UR", "クジラ", "ルシ", "上総", "推計", "芥川", "##ットガルト", "話し合い", "Game", "カサ", "変速", "大樹", "著しい", "蒸留", "##・ヒ", "##言葉", "ますます", "アフター", "##ウォー", "Alex", "よみ", "トレイ", "借用", "従え", "整形", "桜花", "飛来", "##MM", "ジャンヌ", "Dis", "見立て", "##本松", "ニューオーリンズ", "もっぱら", "ALL", "イブン", "ドジャース", "レシー", "ロート", "北魏", "原動", "名跡", "拡充", "歌曲", "輝き", "##・ペ", "##..", "##育て", "##ima", "##ense", "請け負", "ロア", "判別", "官吏", "##しめ", "モーガン", "FU", "XX", "音波", "PSP", "カルト", "ナンバ", "全勝", "川田", "汽車", "赤道", "##ギニア", "ワース", "伝送", "有能", "石狩", "ジョゼフ", "働きかけ", "ピックアップ", "インストゥルメンタル", "あけ", "さとう", "サイボーグ", "ハンデ", "##ograp", "キミ", "犬山", "##アメリカ", "ATP", "##press", "Sol", "けれ", "ハプス", "藤村", "調布", "面接", "##JI", "とどめ", "エリス", "コイ", "今年", "多種", "漁師", "##aut", "##やさ", "逃げ出し", "web", "カノン", "上る", "賢者", "Park", "ポピュラー", "Cal", "下北", "妨げ", "対等", "山名", "Grand", "致死", "##ロニア", "Stre", "##アイランド", "みずほ", "中道", "同族", "完封", "容認", "恵那", "爬虫", "生田", "稲垣", "譲受", "伊勢崎", "セイバー", "Pat", "エニックス", "主戦", "嵯峨", "廃墟", "憲兵", "染め", "海防", "王冠", "街区", "銀色", "ダウ", "北山", "同化", "安保", "宣戦", "教材", "膨張", "買わ", "##ニシ", "##フェリー", "ちゃんねる", "##チスロ", "der", "原告", "着せ", "##ヴン", "##持っ", "##暮らし", "142", "##osa", "ルーカス", "OC", "上川", "校章", "##クティブ", "アニメーター", "カタール", "サスペ", "ハプスブルク", "Euro", "卸売", "正直", "法科", "用地", "申告", "社屋", "竹本", "筑後", "脆弱", "身近", "鋼鉄", "##ドス", "##ほう", "##フォンソ", "ねこ", "京子", "匿名", "役立つ", "溶解", "馬主", "アップル", "all", "シュタット", "京極", "准将", "夕刊", "妻子", "##チレン", "##ローラー", "勝ち点", "当ては", "パチスロ", "即興", "政友", "顕微", "##コフスキー", "しな", "風刺", "##ゼー", "デ・", "ムン", "洛陽", "艦首", "院内", "##ッガー", "Class", "Ep", "広げる", "度重なる", "甲賀", "貧乏", "##デンティ", "ハス", "上洛", "富豪", "トレードマーク", "仁川", "他界", "血縁", "##リブ", "シャーマン", "##agram", "カザフスタン", "Hol", "乗じ", "代償", "信条", "同種", "若林", "葉山", "補う", "関口", "アブドゥ", "サトシ", "時事", "王政", "脱線", "自律", "鉱石", "##置き", "パスワード", "サバイバル", "軟式", "如く", "花嫁", "苫小", "間際", "##line", "##ars", "##oto", "苫小牧", "了承", "夏目", "##の内", "##伏せ", "チェリー", "シュトラ", "##OKAWA", "ブリュッセル", "戦績", "長田", "風船", "フィッシャー", "##アーノ", "メモリアル", "テクニカル", "ばい", "上がら", "更生", "機甲", "瀕死", "##ho", "ジャッキー", "アンサンブル", "作り出す", "ギャンブル", "大竹", "若葉", "銃器", "スライダー", "Company", "吉原", "羽生", "##り物", "テント", "色素", "請負", "長者", "##着き", "##利き", "##ンジン", "ステート", "ジョルジュ", "長島", "イーグル", "シュトゥットガルト", "おや", "モンド", "右打", "唱える", "妥当", "熱田", "磁場", "舞踏", "##ison", "##els", "##OWN", "KADOKAWA", "Sk", "右派", "恐ろ", "憎悪", "残党", "混成", "連発", "##チモア", "OL", "さやか", "タックル", "全額", "川原", "終着", "美しく", "費やし", "##ブレッド", "ジェンダー", "スナイ", "副官", "助演", "枚方", "田畑", "舞い", "長良", "離反", "アスリート", "ゲルマン", "カフ", "ボディー", "国税", "沙汰", "IBF", "バドミントン", "尾翼", "次ぎ", "田島", "監獄", "##麻呂", "アトラス", "シャーロット", "UTC", "柏原", "できれ", "ランニング", "1852", "カント", "下層", "学力", "布教", "曲名", "松村", "ギャップ", "ふさわしい", "オリーブ", "Miss", "倒壊", "砲身", "綴り", "##なじみ", "乗り物", "ハニー", "受領", "命じる", "軍需", "##ブー", "##ノイド", "##ゴメ", "##ッキリ", "##ference", "オムニバス", "Lu", "コソ", "仮設", "地雷", "増発", "虚偽", "触手", "153", "##ショナ", "大町", "巻い", "鳥栖", "いわく", "よしもと", "コックピット", "カッター", "二宮", "初年", "建つ", "焼け", "##どころ", "##ターズ", "スパーク", "祈祷", "##メート", "アニマル", "チキン", "ネガ", "掛川", "見込ま", "##の中", "##離れ", "ジョーカー", "ボルチモア", "キャピタル", "クラリネット", "ビースト", "充当", "彼氏", "高まる", "##ギア", "##モデル", "##GE", "亡くなり", "スリップ", "コネチカ", "景勝", "着物", "##der", "##ヤーズ", "マーベル", "##AGUE", "FNN", "エイト", "半減", "新線", "##カール", "##嫌い", "杉田", "泣い", "競り", "防備", "風味", "パイレーツ", "##AME", "コネチカット", "メット", "ヨウ", "人力", "投影", "誘惑", "遊歩", "面々", "##by", "##16", "##レーティング", "##キャラ", "服用", "霧島", "フランケン", "ローテーション", "繰り上げ", "ベンジャ", "恋心", "震度", "##ビナ", "##トム", "ヌード", "築く", "肥満", "##366", "##いん", "LEAGUE", "man", "ナミ", "マダ", "子育て", "語彙", "またがる", "アキラ", "Of", "ラット", "到来", "指針", "有楽", "梗塞", "武帝", "ファウ", "取り外", "ジョヴァン", "カーネル", "##ript", "SB", "スパー", "ポット", "大麻", "平壌", "点火", "王権", "ストックホルム", "背負っ", "go", "レズ", "催眠", "揚げ", "##ks", "##なぎ", "おまけ", "GEN", "上尾", "信じる", "叙任", "喋る", "夕張", "重工", "##パード", "コンビニエンス", "Batt", "Lim", "TA", "ドバイ", "ベータ", "城南", "皇女", "細部", "鬼太郎", "##58", "##がた", "##リエット", "気づか", "くみ", "とれ", "ほし", "聴覚", "蒲生", "##・シュ", "ベルン", "サラブレッド", "抜け出し", "9000", "吉備", "広範", "快適", "殺到", "発効", "西野", "##クロス", "TT", "ザク", "上段", "皆無", "ダイレクト", "ティル", "ポートランド", "スキャンダル", "KE", "ゼウス", "開ける", "高射", "##ッショナル", "##ロップ", "##ショー", "ミラクル", "おそれ", "ツーリング", "浮かぶ", "パンタグラフ", "JF", "上っ", "台場", "##パイ", "フォア", "United", "モナコ", "Jose", "デマンド", "叶わ", "幸子", "幼年", "慰霊", "高台", "##・ピ", "##リエン", "デュアル", "殺し屋", "Ju", "マロ", "全幅", "文句", "##ずり", "##曽根", "チャット", "ディーラー", "Im", "揖斐", "登り", "##デシュ", "ウィルス", "いとう", "てれ", "パッド", "両面", "品番", "貸出", "跨線", "##出る", "シャワー", "Ap", "パッチ", "休戦", "停泊", "出願", "黎明", "##OG", "Arch", "ボヘミア", "二男", "別当", "目玉", "貰っ", "##ret", "カーボン", "Gi", "ヘレン", "伐採", "株価", "直行", "線型", "翌朝", "養育", "インフォ", "マシーン", "レガ", "産ん", "遊戯", "高騰", "##ペイ", "カリスマ", "LM", "ウイン", "下がっ", "囚われ", "地価", "拡幅", "甲州", "賀茂", "配し", "重巡", "##ラシア", "##残し", "##ross", "##ティーノ", "YouTuber", "Phil", "カンタ", "ヒカル", "停滞", "嫌う", "旧道", "漬け", "農産", "通達", "##マルク", "##ough", "##ional", "カルロ", "アラバマ", "シンクロ", "寄宿", "捕鯨", "明王", "賭博", "##yle", "##ube", "せつ", "城内", "場外", "持参", "連帯", "門人", "降る", "ウィー", "Type", "元首", "多項", "新春", "須賀", "飲ま", "ガーディアン", "ストリーミング", "ライプツィヒ", "目の当たり", "OEM", "下げる", "内面", "大道", "愛子", "退去", "##ータン", "1851", "享年", "信夫", "卓越", "製法", "重なり", "##去り", "チャリティー", "##ジャック", "いとこ", "Fire", "ちか", "はつ", "ラビ", "壊し", "懇願", "気球", "軍曹", "持ち込み", "言い渡さ", "催し", "国定", "申し立て", "いたる", "さかのぼ", "ばあ", "バング", "合間", "礼儀", "醍醐", "##ちょ", "教職員", "Video", "バロン", "健太郎", "死因", "高値", "##バサ", "##アーズ", "しみ", "加納", "恐らく", "戦中", "本科", "灌漑", "##ートニー", "パーキング", "書き込み", "リベラル", "Nint", "ぞく", "備中", "冷蔵", "同定", "咲く", "園内", "埴輪", "従わ", "祭典", "##ワート", "##ガード", "取りや", "つなぎ", "いち早く", "春日井", "##ポリタン", "ベンジャミン", "レッズ", "余剰", "##出そう", "少なから", "フリーランス", "##ird", "WOW", "原宿", "星雲", "石山", "225", "Sound", "iT", "リップ", "ローター", "同書", "大岡", "耕作", "##orld", "##ister", "持ち合わせ", "340", "##ルンベルク", "レジスタンス", "EURO", "健在", "嫌わ", "杉浦", "荒井", "##ッチャ", "Edition", "けれど", "BIG", "たど", "テッド", "互角", "逆襲", "ジャガー", "取り込ま", "##ステークス", "ローソン", "Sim", "コープ", "パット", "休館", "手下", "新星", "検知", "産生", "##che", "##ージョン", "##irst", "1849", "コスモス", "Light", "そん", "ルン", "共学", "判例", "名字", "延べ", "洗練", "矢部", "##ザック", "##フォルト", "苦しめ", "コモン", "覆い", "誤差", "##モール", "取り囲", "##icial", "アイデンティ", "スピーチ", "WR", "奉公", "##ズラ", "##ボルト", "##ッチェ", "##ady", "ウエスタン", "JNN", "ほく", "##多摩", "##フィクション", "ウェザー", "スコープ", "トゥル", "オペレーティング", "見送ら", "ウズベキスタン", "Switch", "なだ", "クレーター", "世俗", "和子", "寺町", "本流", "終日", "##リィ", "キャッスル", "ウェイト", "SPECIAL", "メイト", "レノン", "右京", "枢機", "アルカリ", "披露目", "ミハイル", "Nintendo", "UD", "兼ねる", "冷酷", "武官", "氏名", "狩野", "鉄鋼", "##デール", "ディック", "とうきょう", "TB", "いじ", "かおり", "ギネス", "チュニ", "入江", "戦勝", "祭礼", "赤く", "飢饉", "黒幕", "##がす", "##ルトゥ", "MOV", "割譲", "絵柄", "野々", "##ーア", "##ヨシ", "DIS", "がる", "みの", "やさ", "神官", "筑摩", "繊細", "配当", "カンヌ", "一躍", "引か", "来訪", "面識", "256", "かわり", "河岸", "混血", "##キーパー", "Let", "Mem", "エックス", "増す", "安達", "平戸", "戦災", "物品", "裁定", "電荷", "驚か", "##がえる", "##らわ", "フィーチャー", "Max", "万能", "円谷", "列挙", "専業", "必然", "藤子", "##ko", "##ヤマ", "##ノア", "キャスティング", "バディ", "欲望", "没年", "眠る", "覆面", "##プラノ", "富裕", "文理", "##しむ", "バラバラ", "プロフェッショナル", "Luc", "ちび", "両軍", "仏像", "前向き", "南町", "実録", "東岸", "楽園", "野中", "鋼製", "##タケ", "##之内", "##ula", "ツイート", "Ca", "Out", "君臨", "地層", "帝王", "Instit", "リサイクル", "サタデー", "優し", "参列", "土日", "未定", "水銀", "見なし", "##込める", "del", "導か", "美和", "美智", "自我", "GPS", "Da", "Di", "のん", "ダコタ", "坂東", "尋問", "町村", "百姓", "荒れ", "##oon", "##HA", "ストレ", "マグマ", "タンカー", "レディース", "公害", "凶暴", "刺客", "収縮", "無双", "躊躇", "##ぶん", "レナ", "十和田", "新入", "森山", "生計", "相方", "西園", "黒木", "##キス", "##チコ", "##ゼット", "ジョッキー", "##チェル", "##erson", "##AMP", "トゥール", "Your", "ウイグル", "エカ", "制動", "甚大", "相場", "行先", "受け止め", "##ブリュ", "インタフェース", "マッカートニー", "]、", "タカラ", "ヘヴィ", "リヨン", "召し", "左京", "日数", "登頂", "Version", "商社", "嫡子", "空白", "誓っ", "農協", "##li", "##リアーズ", "##ッカーズ", "Ref", "おもに", "Soci", "シオン", "ツル", "下表", "中流", "隔週", "##ベラ", "果たせ", "ダイビング", "##ナンデス", "メラ", "レックス", "前夜", "啓蒙", "浮気", "見逃", "限っ", "##ORE", "とし", "ブール", "世の中", "帝政", "手首", "歯車", "残骸", "筆記", "##RA", "1820", "取り込ん", "キプロス", "ぎん", "シオ", "ズーム", "ビクトリア", "出所", "手当", "決心", "過度", "トラベル", "Child", "ワークショップ", "ステアリング", "出仕", "切ら", "商法", "在庫", "壁面", "挙兵", "極秘", "略し", "老舗", "高瀬", "高尾", "Corpor", "宇和島", "DB", "アエ", "執着", "近傍", "金持ち", "ハンセン", "ファルコン", "尾上", "本曲", "滑らか", "高官", "##クシ", "引き出し", "ポップス", "カウンセ", "スチール", "なぎ", "らしき", "大雨", "客船", "探る", "解き", "身柄", "##キラ", "208", "##ANCE", "アトレ", "大倉", "纏っ", "##バチ", "##ノサウルス", "##調べ", "ラピ", "ラント", "千種", "譲る", "##ロワ", "##DER", "Boy", "ゆい", "早世", "無力", "フェデ", "セルゲイ", "ニュルンベルク", "主君", "拝殿", "随筆", "飛翔", "##・ヴァ", "アドバンス", "ネイティブ", "コンポーネ", "取り壊さ", "Sant", "オメガ", "国造", "漁船", "試練", "降っ", "154", "Ke", "Mil", "党内", "国歌", "故人", "有る", "郷里", "頭蓋", "鶴田", "ジョシュ", "沈黙", "近親", "あっさり", "フェミニ", "##イスキー", "フレッド", "ノンフィクション", "シリアル", "いさ", "ばし", "ケビン", "勝山", "和音", "小名", "抜ける", "正午", "特捜", "転任", "辞し", "##ring", "##モンテ", "リヴァプール", "May", "シネ", "夢中", "##ニット", "##まじ", "ヨルダン", "恵比寿", "サスペンス", "ふし", "元祖", "可視", "多田", "数える", "毛皮", "水質", "パンフ", "いたずら", "しゅん", "回顧", "寒冷", "規律", "マルティン", "##une", "サムライ", "類型", "##KS", "アクシ", "セス", "建武", "木戸", "##ティコ", "まちづくり", "キツ", "下士", "永正", "省庁", "託さ", "##lin", "FEST", "Little", "Na", "ぶら", "偽造", "傷つけ", "冷たい", "裏側", "##idae", "ルーシ", "HC", "さつ", "スバル", "ナツ", "マッハ", "ミレ", "リナ", "因む", "目前", "##TP", "##モノ", "ヘルシン", "##aint", "カエサル", "IG", "まえ", "わん", "創価", "救世", "林業", "神輿", "細く", "贈っ", "難航", "ことば", "##ストロング", "寄せる", "岸和田", "矯正", "##ゼーション", "スナック", "ザイ", "傾倒", "委ね", "字体", "風間", "##59", "##わざ", "コンプ", "STAR", "サメ", "シモン", "ベニ", "日誌", "榎本", "聴き", "通す", "タブレット", "Michael", "SRCL", "イロ", "トータル", "ラルフ", "匂い", "旅人", "病床", "##じま", "SPOR", "ツイッター", "Nav", "ゲオル", "村域", "枢密", "消極", "酒場", "レプリカ", "Bab", "Dig", "ピート", "一夫", "周防", "立像", "##・テ", "1846", "テンション", "イルカ", "ブダペスト", "ベス", "氾濫", "災い", "転出", "##ural", "追い込ん", "ヴェストファーレン", "プエルトリコ", "iTunes", "ソルト", "リラ", "団結", "恩恵", "捕え", "直訳", "著述", "##77", "生き物", "セレクト", "おこなう", "##・ディビシオン", "コンスタンティノ", "リソース", "JFL", "不祥", "傷害", "太い", "生後", "藤枝", "##カルド", "マグネ", "スティール", "##ロニクス", "カクテル", "冊子", "官邸", "整っ", "育児", "褒章", "躍進", "長江", "静脈", "##53", "##ンドー", "ジュール", "ETC", "Fre", "上告", "初恋", "年鑑", "後醍", "正徳", "滝沢", "目さ", "積雪", "練り", "選任", "関根", "黒崎", "##ベリ", "ヴァレ", "##ウィック", "後醍醐", "アウェー", "没落", "河村", "自発", "花序", "阿武", "##14", "##河内", "受け付け", "乗り入れる", "クレオ", "スキャン", "Charles", "FE", "ゲッ", "老中", "##・ジュ", "##合わさ", "取り扱っ", "メドレー", "Pop", "Sa", "ズボン", "トマ", "海南", "特訓", "立山", "配線", "##olf", "ダイナミック", "パンフレット", "はめ", "検閲", "##パラ", "バスケ", "組み合わせる", "そちら", "仲裁", "劉備", "懸命", "救難", "破れ", "繋ぐ", "##オフ", "ジェファーソン", "サイコロ", "シンフォ", "Arc", "取り上げる", "COVID", "Sky", "山野", "##リータ", "##ular", "つくっ", "WC", "203", "##very", "##ublic", "Dan", "Gold", "トンプソン", "亀井", "壱岐", "法典", "神事", "野沢", "##せつ", "オーロラ", "##ーツク", "ガルシア", "Thomas", "ドリンク", "七尾", "前座", "柳田", "様相", "蒲田", "##バルディア", "エドゥ", "ゴルゴ", "オアシス", "YU", "みらい", "セーフ", "木更", "植木", "油圧", "町民", "Store", "##クラテス", "カウントダウン", "マッカーサー", "木更津", "ペダル", "桃太郎", "竹中", "補修", "##ラーレン", "チャック", "デュエル", "支払っ", "ブックレット", "エージェンシー", "Mel", "サタン", "合図", "直下", "窃盗", "邪悪", "システムズ", "やん", "丹羽", "言論", "谷村", "タフ", "ツィ", "好奇", "慣例", "画期", "釜石", "##そく", "##差し", "ジョアン", "ユーモア", "ヘビ", "マッキ", "付さ", "小豆", "島々", "未熟", "見出さ", "マヌエル", "産む", "異議", "##スン", "##ッチメント", "アテナイ", "例え", "年限", "頓挫", "##マイズ", "Mat", "デフォルト", "レポーター", "企て", "叙せ", "滅び", "##ナダ", "Office", "FNS", "MH", "シティー", "秒間", "退位", "##クトップ", "ボーカリスト", "シャーシ", "API", "##otten", "チェルシー", "イケメン", "モテ", "茶道", "農耕", "##だち", "##コンシン", "FIA", "デスクトップ", "浴びる", "IL", "同法", "存命", "平城", "弾い", "復員", "着い", "葛西", "違和", "重度", "##ボット", "##代子", "イト", "城郭", "応永", "桜木", "##ん坊", "##ぶさ", "ウィザード", "スターリング", "いわば", "##OWER", "ふと", "アリスト", "ジア", "水槽", "濃く", "熱中", "野手", "隔て", "##ラウ", "##帰り", "ストリング", "##APP", "Direct", "ブス", "三上", "参詣", "叫ん", "極楽", "##ery", "143", "##oud", "ボウリング", "チャーチル", "立ち向かう", "Big", "Lab", "カッコ", "修繕", "公子", "実物", "監察", "祝う", "サンシャイン", "スペンサー", "##ハーサル", "ノヴァ", "ポロ", "レンジャーズ", "三鷹", "拾っ", "絶命", "誤認", "##ien", "##uch", "430", "オペレーション", "DOS", "あかり", "すく", "リハーサル", "光秀", "旧約", "美作", "##百合", "ジグ", "戦列", "振ら", "撮っ", "溶液", "症例", "被爆", "電器", "##FT", "##ノラマ", "ついで", "インテリ", "イヴァン", "チー", "ニセ", "主軸", "全高", "由美", "##ミド", "ナビゲーター", "こっ", "ひばり", "エアー", "付か", "有線", "正則", "水没", "##投げ", "ウェルズ", "key", "づき", "イシ", "ラオス", "射出", "振っ", "採り", "新車", "絶縁", "美穂", "賢治", "いちご", "アームストロング", "ウィスコンシン", "ベンガル", "使役", "奥義", "少量", "返答", "銅像", "龍馬", "シルエット", "##bert", "尽くす", "うみ", "戦わ", "打球", "提訴", "治め", "自粛", "走ら", "越し", "都城", "##SU", "##ビッチ", "##ったり", "##omb", "スクリ", "いちろう", "クロスオーバー", "##・ド・", "のぼる", "イスタン", "モットー", "レパート", "十勝", "因果", "小杉", "漂流", "画質", "税金", "行え", "##ME", "##PC", "見つから", "ロースター", "余地", "古事", "安い", "森本", "騙さ", "シンシナ", "Fil", "MI", "NK", "スン", "加害", "念願", "手持ち", "独断", "線維", "難い", "風習", "4547", "上り線", "Franc", "かれ", "平衡", "脱獄", "音速", "##ボラ", "##こし", "アイディア", "送り出し", "ボリビア", "おし", "ぶっ", "スワン", "伝授", "分担", "半期", "発熱", "貫く", "##バオ", "パーフェクト", "##ander", "##IVAL", "リモート", "ウィキペディア", "ラトビア", "KB", "Ob", "RD", "ホビー", "志す", "本性", "格付け", "ランディ", "1845", "スタンフォード", "BLUE", "リンダ", "加担", "国文", "扶桑", "系外", "豆腐", "軍部", "ジュラ", "AE", "Hist", "ケプラー", "美咲", "##cess", "##itz", "##ume", "Team", "リグ", "レフェリー", "巨乳", "幼なじみ", "田町", "登用", "重なる", "頼む", "##hr", "フランコ", "プリメ", "4547366", "Bel", "ad", "ねえ", "狂気", "番長", "盗ま", "裏腹", "音節", "##ムラー", "さほど", "コブラ", "ハプ", "人衆", "和也", "榴弾", "親密", "フィード", "##ACT", "Hy", "デア", "ベジ", "一座", "北原", "文科", "滅ぼさ", "粉砕", "臨済", "ゼー", "タイル", "バント", "モビル", "視線", "持ちかけ", "##ICA", "シンシナティ", "Roy", "勇敢", "狭山", "美里", "贈呈", "鴨川", "##ga", "##va", "##ダンス", "##之島", "##歩い", "アトム", "申し入れ", "ケルト", "三越", "博文", "本宮", "水木", "簡略", "網走", "臭い", "##メト", "##マネ", "##gy", "コースト", "1843", "ヴェルディ", "Kr", "かさ", "外壁", "市外", "日時", "時速", "眺め", "芝生", "軍令", "172", "007", "ユーラシア", "1837", "わざと", "三和", "下がる", "丸い", "延宝", "恵子", "捕まえ", "暗躍", "柏木", "残虐", "##ルドー", "フレンチ", "レパートリー", "FK", "執拗", "実母", "飽和", "スクラン", "イエズス", "アタッチメント", "ひろみ", "ペリ", "リガ", "リフレ", "叩く", "大当たり", "新装", "聖子", "##グレード", "1844", "Tim", "TIME", "アステ", "ペレ", "ワイヤ", "中南", "童子", "高見", "##サール", "##ルドバ", "UK", "Wr", "そら", "とに", "ニャン", "密集", "東国", "治癒", "登る", "##メド", "##lo", "##ブリー", "##ゲー", "##寄せる", "163", "##フスキ", "メトロポリタン", "気付き", "George", "Free", "Land", "よかっ", "久慈", "内山", "募金", "##ムント", "##カライズ", "下り線", "のぞみ", "下る", "占有", "置県", "##んと", "##飾り", "211", "##ッツィ", "##obile", "大腸", "構図", "気仙", "音頭", "##アリ", "Sur", "サプライズ", "セクシー", "ドロー", "加減", "民生", "緯度", "試行", "酒田", "##ばっ", "ガンマ", "コンポーネント", "WIN", "つう", "ビザン", "事柄", "捕まっ", "街路", "遊牧", "雇っ", "##メンス", "##FF", "サンゴ", "プライス", "ハノーファー", "ハク", "先立ち", "勘定", "口腔", "失望", "石見", "肉食", "エドガー", "スイング", "スイート", "##ンバラ", "カスタマイズ", "伸ばす", "太一", "村井", "精通", "終末", "越谷", "ともさ", "引き渡さ", "1806", "グレゴリオ", "TN", "ザック", "全焼", "八雲", "州間", "林家", "猪木", "##レッタ", "チューニング", "ブランデンブルク", "##ツィオーネ", "とにかく", "おろ", "ハッ", "千鳥", "札所", "桟橋", "温厚", "至近", "##go", "##ニェ", "##ani", "カイザー", "Corporation", "NDL", "きよ", "サニー", "久喜", "以東", "台中", "同好", "寄港", "新道", "江原", "英米", "##PO", "クーペ", "しゃべり", "セブ", "デリー", "ボンド", "ミト", "曽根", "白馬", "取り消し", "Oper", "PI", "ケイン", "内地", "大家", "宴会", "末尾", "萌え", "##もる", "ステイ", "パーソン", "ラファエル", "Championship", "コマン", "変革", "宿場", "新鮮", "月光", "破滅", "部活", "打ち切ら", "カタカナ", "Summer", "ソープ", "ハビ", "レトロ", "先立っ", "六甲", "宗派", "赤ん坊", "過失", "##uz", "チャール", "引き渡し", "すき", "サザ", "令嬢", "体積", "分隊", "守山", "実効", "松坂", "物価", "##返っ", "マインド", "##チュエ", "##ude", "コフ", "真ん", "脊髄", "褒め", "##ウイ", "##すら", "##んどん", "##エンヌ", "ブエノス", "めん", "オード", "下山", "佐々", "体勢", "国名", "廊下", "快く", "戸惑", "機首", "アーノルド", "エフェクト", "サガ", "入港", "同郷", "同義", "小数", "環礁", "覆っ", "諸葛", "議院", "酔っ", "隠蔽", "##サード", "##arm", "ウルトラマン", "##カロライナ", "吉祥寺", "コソボ", "ゼミ", "同心", "山上", "群島", "赤ちゃん", "##cin", "ステファ", "ミラージュ", "あおい", "クリック", "宮島", "形質", "掴み", "敷か", "製鋼", "須藤", "駐日", "##ツク", "キャリー", "ファステ", "コントローラ", "争わ", "健二", "児島", "別所", "包み", "地頭", "拳法", "黒澤", "Elect", "Wil", "day", "コブ", "リンチ", "勤労", "大英", "消去", "逓信", "長屋", "エスパー", "キュア", "苦しむ", "ヘルシンキ", "タナ", "レグ", "下宿", "前任", "大牟田", "悪人", "所定", "##ミオ", "##ぞう", "バレンタイン", "コペン", "タツ", "幻覚", "抑圧", "撃つ", "減り", "黒部", "##・プ", "##ca", "##ピラ", "##びれ", "バレル", "per", "シモ", "パブリ", "中途", "垂れ", "家出", "山林", "渤海", "福原", "願う", "騎馬", "##ミヤ", "164", "1847", "アジト", "Girls", "Cry", "DL", "ふそう", "ヒゲ", "反感", "合祀", "啓発", "祀っ", "若しくは", "##ッレ", "##・キ", "##放し", "チャイルド", "ギルバート", "推し進", "リマスター", "タップ", "ボット", "仙人", "山王", "廃し", "彩色", "支庁", "苦痛", "荒野", "血球", "追贈", "雇い", "離島", "負け越し", "ジョヴァンニ", "\"、", "内訳", "皐月", "軍務", "カーニバル", "ファステスト", "シム", "値段", "大喜", "孵化", "手形", "沢東", "渡部", "竹下", "##タム", "フランチェスコ", "真ん中", "RB", "ゴート", "丸の内", "怪力", "捧げる", "##イェ", "取り出し", "バーガー", "1841", "コレクター", "##URE", "Tre", "アユ", "山県", "方位", "破裂", "##ole", "365", "##ナンシャル", "あさひ", "##グループ", "Instagram", "あかね", "いの", "みか", "よん", "トク", "ドニ", "官庁", "局面", "態勢", "日田", "誘発", "##ヶ岳", "持ち上げ", "##ague", "切り替える", "トロイ", "結びつい", "ペルシャ", "WWF", "as", "サヴォ", "三陸", "伝染", "呼応", "国教", "水原", "組曲", "##ベー", "グラハム", "サウスカロライナ", "he", "びょう", "アヴェ", "ムード", "小石", "布施", "或いは", "##cript", "##ユーズ", "##xt", "##ンチャ", "##ーグナー", "しょく", "RX", "トモ", "名取", "嗜好", "戊辰", "榊原", "汚職", "衆院", "##rid", "##マツ", "キャッツ", "ウィズ", "スマッシュ", "かぶっ", "カブト", "HM", "Rom", "しげる", "にい", "ひい", "シンジ", "伝播", "子宮", "挙句", "日置", "洋楽", "##・ジャ", "Ant", "モノクロ", "いこう", "パティ", "予科", "大祭", "気質", "独り", "誌上", "謀反", "間近", "##ソーム", "シャム", "##unt", "インデックス", "##ボクシング", "岩本", "数量", "許す", "銘打", "##リーノ", "持ち出し", "999", "西園寺", "KING", "ピョ", "ブレン", "伏せ", "宮沢", "豊中", "風力", "魔獣", "##太后", "デザート", "メイキング", "振るわ", "クローバー", "ガリシア", "und", "イジ", "三宮", "古田", "呉服", "委嘱", "菊地", "陛下", "ハーバー", "KT", "交替", "小国", "年内", "欠い", "海浜", "頻発", "##町村", "引き取っ", "気付か", "収支", "寄席", "暖房", "柳生", "##ストリー", "レオナルド", "アレクサンドリア", "反復", "延岡", "従者", "206", "##ドンナ", "RADIO", "ps", "ナイツ", "ヨット", "上人", "回生", "根室", "着想", "重症", "##tm", "##gram", "読み切り", "##キンソン", "バケ", "バートン", "ミナ", "居留", "素性", "やっと", "##ブラハム", "マディソン", "ジロ", "代金", "困惑", "小谷", "水車", "青空", "##加え", "##ori", "ブレーメン", "パルマ", "WOWOW", "Sel", "ぐち", "エタ", "リル", "刻印", "航続", "タイタン", "##ste", "浴びせ", "##tainment", "イスタンブール", "End", "Wal", "上山", "多忙", "帯域", "改番", "栄町", "##キナ", "プロット", "Studio", "mod", "ハープ", "今村", "名神", "式内", "成形", "殺そう", "沢村", "法師", "脅し", "プラットホーム", "コペンハーゲン", "Top", "qu", "保ち", "敗走", "粉末", "藩政", "西原", "##リニスト", "コンソール", "ブラス", "ヴァルト", "スチュワート", "ウイスキー", "ノール", "父方", "給料", "計上", "間柄", "飛ばさ", "##シアン", "ハロルド", "取りやめ", "Mad", "パ・リーグ", "談話", "##ターニュ", "1815", "ホイット", "FOX", "大柄", "思惑", "面影", "魅了", "##ビオ", "##ぶき", "ルーフ", "プリメーラ", "ラーン", "前輪", "強襲", "役柄", "私有", "被弾", "誓う", "長井", "##アラ", "オシ", "取組", "地味", "当寺", "従前", "故意", "晋三", "民政", "水沢", "総局", "501", "##ヴェー", "Jean", "がかっ", "キノ", "バシ", "ブリス", "マスタ", "切符", "島村", "弁天", "治虫", "添付", "精鋭", "##ッショ", "##張る", "リーマン", "取り締", "440", "飛び降り", "はじまり", "エレクトロニクス", "かげ", "のぶ", "ケロ", "堀田", "尊氏", "掴ん", "西北", "軍政", "退院", "送付", "ブルターニュ", "目論む", "College", "恐ろしい", "ひっ", "ザル", "ヤス", "リキ", "供述", "出征", "感知", "散布", "陽気", "黒く", "GRE", "くう", "富ん", "払っ", "捉える", "##メディア", "##ドックス", "##ange", "グラブ", "Sports", "Street", "MOVIE", "アゲ", "手腕", "江口", "透過", "限度", "1842", "1832", "Book", "同位", "履行", "弘文", "成虫", "残酷", "##ヨウ", "アルタ", "サンプリング", "370", "グレッグ", "チューナー", "NDLJP", "Center", "ワット", "戦況", "気流", "罷免", "車輛", "##rich", "##ソリ", "##ホル", "エディンバラ", "##アイレス", "成り立つ", "##weet", "タイト", "一向", "柳川", "由利", "落札", "試し", "足場", "連打", "##ウリ", "エト", "ニッケル", "同情", "市議", "梶原", "秋月", "金賞", "##ポス", "##AV", "##イチ", "##テュ", "##ira", "チンギス", "ラッピング", "リチウム", "ロイス", "圧勝", "寛容", "##PR", "デューク", "KS", "Vir", "れれ", "タモリ", "一杯", "動植", "塩素", "怪盗", "旧式", "死な", "沙織", "清原", "誘っ", "##ビック", "##テリア", "アーバン", "こうじ", "##mann", "カートリッジ", "Av", "ポテン", "京橋", "抱か", "機長", "羽目", "通例", "野原", "サンズ", "Si", "te", "ござい", "ざい", "化身", "平氏", "旧名", "海抜", "辰巳", "フィッツ", "マルセイ", "はじめる", "ハント", "ムーブ", "レベ", "囲む", "拒ん", "特製", "頭角", "##すぐ", "##ディック", "取り込み", "ジュリアン", "ピストル", "レギ", "先手", "桃子", "浦安", "生む", "顔立ち", "##システム", "204", "##ジェット", "##earch", "アンソロジー", "有楽町", "Home", "ed", "イット", "山門", "聖徳", "術師", "謹慎", "##マド", "##agon", "追い詰める", "##シェン", "しのぶ", "ブエノスアイレス", "キヤ", "下町", "四肢", "晒さ", "魔道", "##シャス", "マクラーレン", "LIFE", "とどまり", "うさぎ", "がたい", "ザール", "安城", "##・ジ", "##ware", "##こみ", "290", "ローリー", "柔らかい", "##・フォン・", "全仏", "散乱", "疫病", "竜巻", "騙し", "##レフ", "##恵子", "ヴィラ", "トラスト", "すごい", "ラバウル", "アロン", "ウミ", "ポータル", "ラッパー", "二階", "団員", "尼子", "曾孫", "賛否", "足ら", "車軸", "##57", "##ダック", "フェンス", "##ファル", "組み込ん", "おとな", "Tomato", "Kh", "Ol", "Vis", "アントン", "ゲット", "ベオ", "内心", "合致", "商科", "異星", "美貌", "骨髄", "##モフ", "シュウ", "グアム", "サック", "スギ", "下落", "侮辱", "勝田", "厳重", "文武", "新製", "機嫌", "湖南", "長髪", "##ning", "##gar", "##シュト", "ビルド", "ガンバ", "##ザンヌ", "おおさか", "イノベーション", "North", "VOL", "ナチュ", "多量", "渋川", "解け", "隆起", "飛ばす", "##セー", "##ws", "##てん", "クラウス", "##ida", "追いや", "バークレー", "返り咲", "分譲", "表せる", "チャーター", "##ters", "##ADE", "スレイ", "ハガ", "神山", "若宮", "##ih", "##カーナ", "オルガ", "1812", "デーモン", "ロータス", "刀剣", "加増", "水溶", "流路", "浙江", "経典", "込み", "##・ノ", "##里子", "みなす", "Instrumental", "きちんと", "稼い", "膨ら", "軌跡", "重心", "防具", "##蹴り", "ファイアー", "CAS", "ブイ", "失調", "孫娘", "菅野", "誘う", "駅員", "##トゥー", "White", "インスリン", "ナガ", "ロッキー", "各部", "怪談", "白く", "身延", "##付く", "シャフト", "1836", "ゲイリー", "Great", "動植物", "パウル", "同線", "急逝", "探求", "日出", "本間", "毎時", "脇役", "##ジスタ", "##リアー", "ウェポン", "ネクスト", "セグンダ", "オースティン", "アクセサリー", "Society", "Master", "Rotten", "ゴット", "トラス", "別称", "向ける", "届出", "市町村", "栄一", "螺旋", "##ple", "##カデ", "ニューズ", "ターナー", "Richard", "ロドリゲス", "Fer", "HR", "こま", "やつ", "バトン", "劣勢", "打線", "コミカル", "ティーン", "##ection", "KDDI", "ネロ", "ピル", "亜美", "安部", "紫外", "苦情", "課金", "開基", "高津", "##GO", "スピリッツ", "アラゴン", "9784", "##ITE", "MAG", "即ち", "感度", "懲戒", "稼ぐ", "切り裂", "エント", "ドス", "低速", "年数", "惨敗", "板垣", "橋上", "用心", "規程", "限る", "随所", "##メロ", "##BE", "##ゴビナ", "##あわせ", "##ティックス", "ブラザース", "掛け声", "聞こえる", "ミッチェル", "Mal", "受理", "山西", "川沿い", "施す", "残念", "濡れ", "腎臓", "##プタ", "##ちこ", "アンプ", "##チョフ", "##ビュート", "xx", "塩田", "投降", "推挙", "材質", "石造", "習志", "蔓延", "転勤", "##マム", "##ろさ", "##テック", "##けい", "UFJ", "##GBT", "sy", "シックス", "分署", "東横", "機内", "熟練", "角田", "##巻く", "アルス", "ATS", "習志野", "Cast", "イデオ", "参与", "城東", "売場", "愛車", "携行", "着地", "綺麗", "藤堂", "##con", "##広島", "##ティクス", "##ルドルフ", "ルーシー", "ノウハウ", "ゆず", "アット", "クウェ", "サターン", "右足", "奪回", "統率", "遺し", "##52", "ファンク", "書き換え", "トレーラー", "BLACK", "Lou", "SI", "ダック", "マナー", "充填", "球体", "着色", "福建", "続投", "親しみ", "##フライ", "##CD", "##ノ島", "##ゴット", "一人娘", "ハーブ", "ゆうき", "##ift", "クォーター", "ゴリ", "亜鉛", "低かっ", "偏見", "参院", "破ら", "終身", "補習", "フラツィオーネ", "ゴルファー", "アバター", "FX", "コルト", "ピオ", "ラズ", "上智", "宝島", "実兄", "屋号", "智子", "製剤", "速やか", "鍵盤", "209", "リアス", "取扱い", "VO", "ab", "su", "イデ", "ボナ", "円錐", "在り", "転覆", "部局", "##イー", "##ゴーニュ", "カーテン", "シンポ", "1789", "ぶつけ", "わら", "結集", "##若松", "マクシミ", "会津若松", "ひかる", "セリ", "再起", "悪事", "華麗", "蜘蛛", "遠江", "チェンバ", "落ち込ん", "1814", "SUN", "nm", "うめ", "座敷", "本陣", "賞品", "##なべ", "クララ", "ストー", "ゴールキーパー", "キロワット", "MiG", "いで", "和尚", "宮原", "操車", "##SA", "やりとり", "Year", "エレン", "原油", "改易", "菊花", "表れ", "##aki", "ヒューズ", "各務原", "パース", "ペガ", "ロザ", "土方", "安堵", "放課", "日の", "葛藤", "遷移", "##ージナル", "410", "##udio", "突き刺", "チャイナ", "##モロコシ", "下す", "曲げ", "武雄", "死別", "知覚", "脂質", "##ペクト", "##zo", "##リスタ", "見つかり", "問い合わせ", "Ger", "ごみ", "ヤシ", "作ろう", "凶悪", "水位", "訳語", "##YO", "オーシャン", "presents", "ノルマンディー", "フェルディナント", "すっかり", "エネ", "人魚", "切腹", "失速", "村落", "開学", "##バンド", "リーディング", "クライン", "フォロー", "カルボ", "バンパー", "##awa", "きれい", "エスカレーター", "Gar", "Jun", "ちゅ", "カビ", "バニ", "ペイント", "内乱", "嘱託", "工具", "握手", "沈着", "義父", "順子", "黒海", "##ナガ", "##ケア", "##oth", "きっぷ", "420", "Pri", "バラン", "対艦", "川辺", "悟り", "払う", "取り付ける", "引き連れ", "##ope", "トウモロコシ", "Tomatoes", "Tor", "コリンズ", "ピーチ", "本艦", "筑前", "続出", "##ザイク", "##掛かっ", "カリキュ", "マッサージ", "Bus", "よら", "キレ", "ノーマン", "中尾", "外す", "要職", "謙信", "ステラ", "置き換える", "マリーンズ", "カシ", "両用", "人的", "欠番", "船内", "足跡", "連なる", "##はし", "いっしょ", "エアバス", "Cat", "ソプラノ", "パープル", "中絶", "侵食", "女房", "幸運", "東欧", "森下", "減る", "編著", "サーベル", "マネージメント", "シアン", "蒸発", "##BL", "##ニングラード", "トレイル", "##OTO", "IW", "no", "林道", "湯沢", "祝賀", "訃報", "Show", "ケンカ", "アイデンティティ", "ゆみ", "マーズ", "ミント", "上面", "南山", "放り", "栗田", "沈め", "無敗", "自決", "裏切っ", "財源", "迫撃", "隠岐", "館長", "##語り", "ユニバース", "フォーカス", "NEO", "ストライカー", "Party", "づける", "ドナウ", "傀儡", "分室", "止まる", "無機", "返却", "通年", "頭痛", "##istr", "コウモリ", "ひどく", "鳴き声", "Ba", "GOLD", "包ん", "大まか", "念仏", "異形", "脚部", "##ツジ", "ブライト", "打ち破", "Arm", "エミー", "リターン", "ロワ", "欠損", "花粉", "ディヴィ", "立ち上げる", "巻き込ん", "バラエティー", "XP", "やろう", "助力", "叩い", "完備", "宗像", "弾く", "抜か", "持て", "ウォーレン", "ボア", "士気", "県会", "ライカ", "##atic", "シリコン", "Over", "West", "テンプル", "一途", "便所", "商務", "悪夢", "戦功", "曳航", "確執", "##ビリティ", "1818", "メカニック", "PE", "ゲッター", "三輪", "就き", "岩槻", "微小", "牽制", "現す", "由良", "##クティ", "##届け", "##フォーマー", "##iano", "リミテッド", "DDT", "ペイン", "俳人", "帝京", "序列", "戦没", "正人", "正史", "法規", "1839", "##angu", "book", "保た", "多角", "忠告", "的確", "##gin", "ブルゴーニュ", "パーカ", "##ova", "ESP", "たき", "コモ", "ビオ", "ルック", "困窮", "給水", "総武", "ローゼン", "ごとく", "ニーダー", "出入口", "とらえ", "ふつ", "バーンズ", "光る", "吹く", "松川", "検挙", "重慶", "隣国", "##ures", "##irc", "Leg", "Island", "執り行わ", "Ult", "アスト", "モニュ", "亀裂", "光年", "溢れ", "牛肉", "貫い", "アルフォンソ", "クラスター", "##シュート", "##ヴィッツ", "ユーリ", "庶子", "書体", "空い", "軍医", "##ムナ", "##払っ", "ロックン", "スルタン", "##ガイモ", "Ben", "Just", "つね", "ウシ", "ニス", "ムサ", "ロム", "創出", "安房", "独奏", "登っ", "貸与", "遺骨", "##わう", "引き抜", "読み上げ", "1835", "##AKA", "##落とさ", "ソユーズ", "ビアン", "ロク", "不定", "届ける", "悪霊", "服役", "鍋島", "##・フェ", "立ち会", "1803", "##obe", "モニタ", "シンポジウム", "キティ", "ペンタ", "マドンナ", "単装", "変電", "学説", "常用", "成瀬", "春風", "正門", "縦断", "##(\"", "##レーナ", "Stand", "バングラ", "rad", "パプ", "##ユー", "##盛り", "AND", "ボリス", "真一", "被疑", "##・トゥ", "1801", "ベイカー", "1831", "カリキュラム", "こめ", "ベロ", "写し", "描画", "返事", "##ペー", "キャメ", "##ンチェ", "オオカミ", "Network", "PHP", "FD", "RED", "エリオット", "ロッカー", "予知", "小路", "悪かっ", "書状", "##och", "173", "##ランドル", "ランチ", "すずき", "Wom", "アスタ", "トゲ", "ドキ", "ロド", "埋立", "容積", "架線", "煉瓦", "現世", "触発", "関白", "電極", "##UG", "##ディスク", "##itar", "Muse", "South", "ネバダ", "ホステル", "彼方", "相良", "齋藤", "##isch", "ちゃんと", "スピリット", "HDD", "スス", "ビラ", "ヨコ", "分光", "利害", "島民", "特科", "童謡", "縦貫", "須磨", "ジョーク", "001", "Inf", "ドレスデン", "950", "QB", "Tu", "up", "えび", "ラル", "即時", "振舞", "細分", "##マイト", "ディストリ", "##ヴィング", "トランスフォーマー", "クルーザー", "マキノ", "中津川", "MK", "ロリ", "変光", "御堂", "心筋", "文人", "##サイユ", "東大阪", "MIX", "アングル", "カブス", "ワラ", "原典", "拓也", "直系", "##リケ", "##amil", "##ISE", "Cre", "Happ", "励まし", "平民", "掛ける", "欠如", "生家", "病棟", "習い", "能代", "##ダール", "コンコース", "サンライズ", "Mix", "丸亀", "儒学", "六十", "内村", "凄まじ", "素早", "すみれ", "##イングランド", "RAM", "但馬", "停電", "増援", "昇叙", "森永", "視認", "##マイオス", "##ロギー", "チョーク", "##・ヘルツェ", "マルセイユ", "公方", "本庁", "遭う", "高井", "呼び出さ", "OFF", "General", "うかがえる", "取水", "市政", "恩師", "直立", "進駐", "高浜", "##キスト", "##ティマ", "##AYA", "かわいい", "どんどん", "南岸", "操ら", "本営", "##86", "##戻さ", "スタッド", "##ニアム", "ニューイングランド", "ダイバー", "##ACH", "WS", "アニー", "優れる", "円滑", "県営", "##クトン", "スマホ", "セレモニー", "Pan", "大日", "応急", "正宗", "芳香", "長大", "開墾", "##読み", "タイラー", "引き下げ", "メディカル", "##ritic", "ボスニア・ヘルツェ", "ゴア", "南宋", "常駐", "東野", "脚色", "飯島", "ボスニア・ヘルツェゴビナ", "マッケ", "ミラン", "ラミ", "ワーズ", "ワーグナー", "欠かせ", "済ま", "落城", "詫び", "長き", "面する", "麻呂", "##スラー", "207", "ウィッチ", "気づく", "明日香", "イデオロギー", "エヴァン", "モザイク", "浄水", "病弱", "県境", "コロコロ", "AX", "グラー", "チルド", "ナゴ", "ブリスト", "ワンダ", "大晦", "媒介", "専売", "明白", "濃厚", "神代", "諸語", "電線", "館山", "##タカ", "##キュリー", "##ther", "ラテンアメリカ", "##ather", "Green", "あわ", "カリー", "南洋", "回す", "境遇", "溝口", "##トリス", "##どき", "off", "コントローラー", "##っとり", "振り回さ", "モニュメント", "720", "HMS", "ほり", "カージナル", "セオ", "両足", "撃っ", "瞬時", "連日", "##伝え", "大晦日", "しつ", "つぼ", "ナイル", "効か", "抗原", "聖歌", "要約", "講道", "踊っ", "##ヒム", "##そば", "##eck", "カロリー", "ヒドロキシ", "じろう", "入城", "千住", "否決", "平ら", "那賀", "##ニヤ", "##歩き", "ミニチュア", "ドーピング", "スライム", "class", "Engine", "せっ", "アストラ", "ボロー", "公主", "島嶼", "技量", "斡旋", "欠く", "渡来", "疾病", "神仏", "習っ", "肩書き", "説く", "踏む", "首謀", "##バシー", "キングダム", "御殿場", "GDP", "フランドル", "公約", "巨体", "##ージャー", "ドローン", "DP", "Nat", "gl", "エヌ", "ザ・", "ハルト", "聴衆", "蕎麦", "辛い", "阿賀", "1810", "アーロン", "460", "エッ", "前世", "山岡", "サイパン", "Hal", "もみ", "ドク", "ピリ", "床下", "手榴", "植田", "薨去", "鋭く", "##ris", "##ids", "モンテネ", "メソッド", "ダイアナ", "スネーク", "かご", "くわ", "井川", "如何", "実名", "殴ら", "真由", "頭上", "174", "1833", "アミューズメント", "Joseph", "FESTIVAL", "ヒスパ", "ペロ", "ルーン", "側線", "勧請", "掛かる", "水軍", "甲冑", "責め", "超越", "震源", "まみ", "サキ", "ジングル", "文春", "松崎", "片道", "アイド", "こうえん", "ハイチ", "##aku", "売り場", "づらい", "ウーマン", "サロ", "ナマ", "備後", "吸気", "埋める", "矢作", "蓄え", "見捨て", "##net", "##でる", "ブリストル", "\"」", "Bell", "ババ", "二条", "偶数", "化成", "恒久", "旺盛", "注ぎ", "着る", "鮮やか", "##ジスト", "##of", "スクリュー", "ちゃっ", "##グラフィー", "グラフィックス", "CAT", "Mont", "あべ", "セ・リーグ", "ペーター", "大金", "嫌気", "阻ま", "風邪", "ヴァンパイア", "弾き語り", "ひたすら", "バーナード", "プロポーズ", "ピョートル", "Rail", "ギニア", "生やし", "矢島", "矢田", "購買", "##ヒド", "##強く", "##割り", "##ティション", "ヴェン", "アダムズ", "Div", "まどか", "ザム", "名阪", "後頭", "沢山", "火葬", "空輸", "観賞", "説話", "##・ブラ", "##ナリー", "##ッジョ", "オペレーター", "Hall", "ロキ", "診察", "##ique", "ICOCA", "Metac", "カージナルス", "モレ", "居合わせ", "新選", "綴っ", "酢酸", "##フリー", "##gan", "##ote", "##ネーヴ", "オマージュ", "Hel", "Ka", "ガッツ", "サティ", "プトレ", "一変", "動け", "台枠", "大帝", "白黒", "相生", "##本町", "引き受ける", "ダイエット", "ビルディング", "プラトン", "LR", "テトラ", "トカゲ", "今夜", "民進", "深谷", "靖国", "鮮明", "##エロ", "##バイン", "##バーツ", "シャア", "じけん", "ノス", "光沢", "原町", "執る", "岩見", "弘化", "是非", "気配", "煙草", "義兄", "衝動", "長嶋", "兼ね備", "Angel", "モンテネグロ", ")\"", "Bur", "クリン", "ナックル", "三枝", "会戦", "放水", "森川", "草案", "身の", "関門", "##・ゴ", "##TE", "##ji", "##ベックス", "##89", "##なみ", "生まれ育", "シュミット", "ファイバー", "スプレー", "二階堂", "まじ", "カイル", "ハーツ", "修飾", "服従", "黒沢", "黒字", "引き離", "ステルス", "バーミ", "北岸", "新約", "純一", "軍備", "野郎", "##ワル", "##ブルック", "ルイージ", "シューズ", "春日部", "##ウォーキー", "バングラデシュ", "サカ", "プファ", "メタン", "リセット", "前川", "南緯", "客演", "巻末", "花弁", "西国", "##レッシブ", "##ule", "思い込ん", "ニュート", "ひどい", "Battle", "Band", "大軍", "大學", "強風", "本所", "深度", "生える", "純子", "羽毛", "装っ", "農薬", "錯誤", "##itch", "打ち明け", "フラグ", "大和田", "気仙沼", "はり", "むす", "ゆか", "シク", "デンバー", "公然", "名手", "怒る", "星団", "歌集", "稲田", "終止", "総集", "##HER", "##リスク", "くるみ", "振り付け", "ぐら", "なが", "イク", "人為", "同胞", "士族", "画素", "防い", "頑丈", "##チックス", "##スタイル", "イベリア", "フリッツ", "オカルト", "##ECTION", "てれび", "Kiss", "イネ", "リニア", "ルミ", "外傷", "天照", "封建", "崩落", "柏崎", "課せ", "随一", "##キリ", "##かみ", "##ディション", "##フィル", "プラモデル", "802", "Real", "##UST", "結びつき", "エクア", "MSX", "かたわら", "デラウェア", "Metacritic", "つぐ", "ボギー", "哲哉", "速球", "遠野", "金城", "長久", "##ja", "##ZA", "##にち", "呼び寄せ", "Album", "かる", "安曇", "死闘", "洋上", "諫早", "雌雄", "##かれ", "##びん", "プラネット", "##立てる", "ミッドナイト", "ミルウォーキー", "きく", "トレン", "ハジ", "メテ", "図形", "発布", "白血", "ライム", "シェーン", "チューリッヒ", "Season", "Brow", "なめ", "井口", "動的", "右肩", "名曲", "国債", "居候", "新発", "深める", "送迎", "陶芸", "##開き", "ウェス", "積み重", "ベネディ", "ゴリラ", "下段", "何事", "傲慢", "南陽", "埋蔵", "懐疑", "満塁", "譲ら", "造っ", "##モル", "##cy", "プライバシー", "UM", "htm", "おび", "シダ", "ハレ", "リョウ", "接点", "済む", "転戦", "##ワンダ", "##zy", "スタイン", "Wik", "ind", "ダール", "ヘイズ", "マトリ", "伽藍", "安楽", "装束", "述懐", "##BF", "レイズ", "NNN", "エコー", "レスター", "不変", "叙事", "名護", "敵機", "##ベツ", "テレサ", "オリバー", "入れ替わる", "ネクタイ", "Key", "カカ", "不意", "不服", "亜紀", "分水", "前漢", "因み", "安く", "柳沢", "模範", "目立た", "##ナリ", "##ロク", "##ford", "1838", "LV", "カッ", "ヘアー", "備わっ", "四谷", "巡業", "蔵人", "##・シャ", "##ローナ", "ビスマルク", "POWER", "ぱん", "偽名", "応える", "日和", "朝刊", "紙面", "綾瀬", "1821", "かわし", "コメディアン", "フェリペ", "アセン", "ピザ", "リリ", "併記", "優遇", "北島", "大館", "学研", "干拓", "心情", "軽便", "シュガー", "フリート", "出塁", "定額", "拾わ", "溶媒", "真人", "硬い", "開示", "##カード", "212", "アップロード", "##チュウ", "ACT", "EXILE", "メタリック", "##っぽん", "「-", "テンプ", "ロレン", "大理", "定例", "意地", "##PA", "235", "##ami", "ソーラー", "RKB", "クウェート", "マゼ", "ヤギ", "呈する", "変奏", "慶喜", "板倉", "腐食", "高裁", "##はら", "##iness", "1790", "747", "リバース", "ラウンジ", "くさい", "カド", "ピレ", "マム", "地検", "挫折", "紅茶", "##アール", "##ガルド", "##シュヴァ", "スタック", "アイゼン", "##チュード", "ワーキング", "AIR", "Way", "カヤ", "リーク", "宮司", "擬似", "新進", "配送", "##bps", "パラレル", "HY", "hp", "園田", "左足", "明星", "神名", "篠山", "願望", "駆除", "##・アン", "チャド", "フィルタ", "マーカー", "もとづ", "プーチン", "DI", "min", "千尋", "激闘", "焼く", "高円", "ことごと", "なんば", "キックボクシング", "ミステリ", "マクシミリアン", "ことごとく", "たなか", "壬生", "客席", "暗示", "欠ける", "溜め", "組員", "ジャガイモ", "ストーカー", "##hem", "510", "マジカル", "737", "MOD", "mph", "げき", "ルリ", "一同", "属州", "履い", "東村", "酵母", "##63", "立ち並", "立ち入り", "##ista", "見守る", "Games", "デスク", "トラム", "大邱", "教訓", "武芸", "海部", "香織", "##バスティ", "##ぬき", "ジュネーヴ", "##aph", "フレンズ", "HK", "IA", "名勝", "楽しく", "気管", "要衝", "##シタ", "##へい", "##ぷり", "##ティーナ", "アンゴラ", "##unic", "使い分け", "##ヴォン", "ヴァイオリニスト", "キク", "シエラ", "ロジ", "低床", "創り", "新種", "現生", "生死", "真夏", "逸脱", "##ポラ", "##ゾー", "なおかつ", "1804", "リスボン", "パートナーシップ", "##プライン", "BEAT", "music", "ケガ", "タオル", "叱責", "変種", "宗谷", "密輸", "旅立つ", "磯部", "##出せ", "##ヶ島", "起こら", "##ARE", "##ガスカル", "Rac", "変則", "屈折", "館内", "##87", "入れ替わり", "フェリックス", "Road", "元治", "受諾", "口論", "年月", "春樹", "棋院", "混沌", "湯浅", "西新", "遠州", "##高田", "##津子", "マーキュリー", "もとより", "モンロー", "クイック", "フェンダー", "セナ", "マギ", "千島", "欲し", "氷川", "王太子", "調味", "##テレス", "ローレン", "カリフ", "520", "マダガスカル", "プトレマイオス", "ひる", "セロ", "堪能", "御影", "挙動", "暮れ", "禁煙", "空調", "船首", "高位", "##eration", "##テルン", "Die", "位階", "佐川", "喋り", "大隅", "年々", "本誌", "白金", "社民", "細野", "##まつり", "SPORTS", "res", "宮前", "年中", "瑠璃", "要人", "##イッチ", "シュト", "迎え入れ", "コンビネーション", "##ヴォル", "あすか", "ワトソン", "House", "バイン", "原文", "基質", "完売", "幻影", "村松", "義昭", "スタント", "クリム", "たまご", "ポテンシャル", "Jul", "SIM", "アホ", "デイズ", "内政", "改心", "敬愛", "有望", "鹵獲", "##62", "ホルダー", "LG", "だれ", "下方", "倣っ", "心中", "放題", "桜田", "満期", "白紙", "群衆", "##らせ", "ハイランド", "トリビュート", "Fest", "びわ", "エメ", "上村", "件数", "哲郎", "技研", "独学", "甲殻", "試料", "遠方", "ジュエル", "ブレイド", "Entertainment", "pp", "ダイス", "外れる", "文言", "港町", "滅多", "除名", "障壁", "風速", "##ザイ", "##ニョン", "##ケープ", "1825", "なで", "キール", "ポーター", "上官", "五男", "伊吹", "増補", "専ら", "投合", "振替", "採算", "漁獲", "胎児", "衣料", "衰弱", "2024", "サンリオ", "ルーレット", "##vex", "セグメント", "ジブラル", "新発田", "ハッシュ", "ミゲル", "一日", "小字", "弓道", "快挙", "長兄", "##Pa", "ダイヤル", "1834", "##ootball", "かも", "ロジャース", "新版", "案件", "清国", "課さ", "中継ぎ", "1819", "ナンシー", "Lv", "WHO", "ぶち", "アノ", "エリカ", "グリン", "ワースト", "名高い", "所収", "朝夕", "江蘇", "温室", "無実", "足首", "陸戦", "ステファン", "アントワ", "かり", "セバス", "倒れる", "図案", "国史", "挑み", "茂木", "##シク", "##ンドゥ", "ジャコ", "ゲームズ", "サイクリング", "Jour", "Line", "hyd", "中庭", "審理", "整合", "焼酎", "直子", "箕面", "##ッダー", "##ラック", "##94", "##ANA", "見舞い", "サトウ", "OUT", "ガーナ", "亜目", "天界", "安井", "家光", "挙がっ", "献身", "##po", "ジェイク", "##ette", "##TRA", "ミカエル", "mac", "ひで", "りく", "オホ", "井原", "井伊", "共済", "戦乱", "模擬", "治める", "烏丸", "##ーカ", "##の川", "ディラン", "シュレ", "メンフィス", "NSC", "BT", "First", "Les" ] } ================================================ FILE: Bert/chinese-roberta-wwm-ext-large/Tokenizer.json ================================================ { "Type": "WordPiece", "ContinuingSubwordPrefix": "##", "Vocab": { "0": 121, "1": 122, "2": 123, "3": 124, "4": 125, "5": 126, "6": 127, "7": 128, "8": 129, "9": 130, "10": 8108, "11": 8111, "12": 8110, "13": 8124, "14": 8122, "15": 8115, "16": 8121, "17": 8126, "18": 8123, "19": 8131, "20": 8113, "21": 8128, "22": 8130, "23": 8133, "24": 8125, "25": 8132, "26": 8153, "27": 8149, "28": 8143, "29": 8162, "30": 8114, "31": 8176, "32": 8211, "33": 8226, "34": 8229, "35": 8198, "36": 8216, "37": 8234, "38": 8218, "39": 8240, "40": 8164, "41": 8245, "42": 8239, "43": 8250, "44": 8252, "45": 8208, "46": 8248, "47": 8264, "48": 8214, "49": 8249, "50": 8145, "51": 8246, "52": 8247, "53": 8251, "54": 8267, "55": 8222, "56": 8259, "57": 8272, "58": 8255, "59": 8257, "60": 8183, "61": 8398, "62": 8356, "63": 8381, "64": 8308, "65": 8284, "66": 8347, "67": 8369, "68": 8360, "69": 8419, "70": 8203, "71": 8459, "72": 8325, "73": 8454, "74": 8473, "75": 8273, "76": 8399, "77": 8411, "78": 8409, "79": 8428, "80": 8188, "81": 8424, "82": 8460, "83": 8466, "84": 8479, "85": 8300, "86": 8352, "87": 8467, "88": 8302, "89": 8426, "90": 8192, "91": 8440, "92": 8394, "93": 8430, "94": 8416, "95": 8287, "96": 8378, "97": 8380, "98": 8327, "99": 8238, "100": 8135, "101": 8359, "102": 8667, "103": 8615, "104": 8503, "105": 8423, "106": 8438, "107": 8632, "108": 8692, "109": 8965, "110": 8406, "111": 8932, "112": 9017, "113": 8989, "114": 8866, "115": 8787, "116": 9070, "117": 9149, "118": 8966, "119": 9031, "120": 8290, "121": 9247, "122": 9203, "123": 8604, "124": 9377, "125": 8752, "126": 9022, "127": 9274, "128": 8848, "129": 8990, "130": 8463, "131": 9403, "132": 9306, "133": 9246, "134": 9146, "135": 8908, "136": 9015, "137": 9444, "138": 9209, "139": 9081, "140": 8468, "141": 9554, "142": 9621, "143": 9572, "144": 9494, "145": 9390, "146": 9630, "147": 9746, "148": 9640, "149": 9491, "150": 8269, "151": 9564, "152": 9653, "153": 9677, "154": 9220, "155": 9437, "156": 9508, "157": 9928, "158": 9412, "159": 9699, "160": 8522, "161": 9608, "162": 9565, "163": 8737, "164": 10048, "165": 9316, "166": 9771, "167": 10029, "168": 8832, "169": 9853, "170": 8725, "171": 9919, "172": 9801, "173": 10020, "174": 10134, "175": 9251, "176": 10004, "177": 10132, "178": 9649, "179": 9910, "180": 8420, "181": 10111, "182": 9952, "183": 9826, "184": 10116, "185": 9560, "186": 9833, "187": 10058, "188": 9460, "189": 10025, "190": 8979, "191": 10330, "192": 9319, "193": 10185, "194": 10457, "195": 9996, "196": 10220, "197": 10596, "198": 9776, "199": 9092, "200": 8185, "201": 9250, "202": 9707, "203": 9954, "204": 10080, "205": 9860, "206": 9899, "207": 10194, "208": 9894, "209": 10381, "210": 9083, "211": 9395, "212": 10164, "213": 10431, "214": 10267, "215": 10082, "216": 9972, "217": 10645, "218": 10224, "219": 10453, "220": 8796, "221": 10118, "222": 9918, "223": 10265, "224": 10629, "225": 9140, "226": 10436, "227": 10543, "228": 9152, "229": 10608, "230": 9111, "231": 10602, "232": 9863, "233": 9959, "234": 10129, "235": 8593, "236": 9671, "237": 10775, "238": 10308, "239": 10694, "240": 8821, "241": 10896, "242": 11056, "243": 10873, "244": 11179, "245": 10325, "246": 11003, "247": 11128, "248": 11009, "249": 10705, "250": 8401, "251": 10924, "252": 10968, "253": 10221, "254": 11251, "255": 9866, "256": 9745, "257": 11027, "258": 10870, "259": 10987, "260": 9044, "261": 10842, "262": 10975, "263": 10864, "264": 10212, "265": 8689, "266": 9674, "267": 11253, "268": 10729, "269": 11023, "270": 9282, "271": 11206, "272": 11281, "273": 10345, "274": 11482, "275": 10532, "276": 11173, "277": 11064, "278": 11191, "279": 11427, "280": 8933, "281": 10971, "282": 11431, "283": 11152, "284": 11437, "285": 10938, "286": 11367, "287": 11525, "288": 10332, "289": 11520, "290": 9845, "291": 11777, "292": 11542, "293": 11855, "294": 11865, "295": 11332, "296": 11545, "297": 11992, "298": 10690, "299": 9600, "300": 8209, "301": 9693, "302": 10563, "303": 11068, "304": 9627, "305": 10849, "306": 10576, "307": 10486, "308": 9793, "309": 11289, "310": 9643, "311": 10256, "312": 10578, "313": 11622, "314": 11725, "315": 9613, "316": 10743, "317": 11491, "318": 10189, "319": 10865, "320": 9144, "321": 9883, "322": 11965, "323": 11221, "324": 11500, "325": 10838, "326": 12044, "327": 12094, "328": 11580, "329": 11705, "330": 9611, "331": 11879, "332": 12308, "333": 10745, "334": 12225, "335": 11728, "336": 12073, "337": 12129, "338": 11929, "339": 11863, "340": 10049, "341": 12117, "342": 12362, "343": 12186, "344": 12698, "345": 11434, "346": 12380, "347": 12936, "348": 12687, "349": 12110, "350": 8612, "351": 12524, "352": 12091, "353": 12115, "354": 11848, "355": 11753, "356": 12215, "357": 12494, "358": 11429, "359": 12027, "360": 8286, "361": 11758, "362": 12711, "363": 12937, "364": 12673, "365": 8728, "366": 11949, "367": 12375, "368": 11642, "369": 11844, "370": 10011, "371": 12584, "372": 12607, "373": 12779, "374": 11948, "375": 11256, "376": 13118, "377": 13222, "378": 12770, "379": 12613, "380": 9406, "381": 12185, "382": 12163, "383": 12510, "384": 12344, "385": 11959, "386": 12303, "387": 12716, "388": 11632, "389": 12512, "390": 10370, "391": 13092, "392": 12254, "393": 12683, "394": 12728, "395": 12481, "396": 13008, "397": 12591, "398": 11425, "399": 9612, "400": 8230, "401": 11185, "402": 12040, "403": 12058, "404": 10524, "405": 11982, "406": 12563, "407": 12458, "408": 12189, "409": 12942, "410": 10706, "411": 12686, "412": 12346, "413": 12561, "414": 12815, "415": 12114, "416": 12453, "417": 13038, "418": 12978, "419": 13055, "420": 9784, "421": 12873, "422": 12721, "425": 11993, "426": 12408, "427": 12575, "428": 11351, "429": 13249, "430": 10352, "432": 13133, "433": 13131, "435": 11930, "438": 13174, "440": 10845, "441": 13013, "442": 13171, "444": 12876, "445": 12834, "448": 13078, "450": 8802, "451": 13068, "453": 12893, "455": 12404, "456": 12570, "457": 12119, "458": 12562, "460": 10685, "465": 12930, "468": 12944, "470": 10658, "475": 13243, "480": 9482, "485": 11763, "486": 12459, "488": 12789, "490": 10566, "495": 12895, "498": 12544, "499": 9927, "500": 8195, "501": 11884, "502": 11907, "503": 12929, "504": 12808, "505": 11033, "506": 11608, "508": 12328, "510": 10907, "511": 12677, "512": 11530, "513": 13310, "515": 13196, "516": 12635, "518": 8739, "520": 9038, "521": 11411, "522": 11510, "525": 11717, "530": 10830, "536": 12904, "539": 12995, "540": 10972, "543": 11895, "550": 9090, "555": 11723, "560": 10541, "570": 11594, "580": 10298, "588": 12426, "590": 11210, "591": 9512, "595": 13302, "599": 10713, "600": 8298, "601": 12104, "603": 13277, "610": 10248, "611": 12768, "616": 13226, "618": 9048, "620": 11078, "625": 12218, "626": 12463, "630": 10615, "640": 11410, "650": 9291, "660": 9936, "661": 10854, "666": 11186, "670": 11807, "680": 10255, "688": 10898, "690": 11960, "699": 10439, "700": 8389, "701": 12656, "705": 10595, "709": 12118, "710": 12415, "711": 12565, "720": 10503, "730": 11868, "737": 11933, "740": 13159, "747": 12331, "750": 9180, "760": 12456, "768": 12472, "770": 13215, "777": 9800, "780": 11493, "787": 13029, "790": 11793, "798": 12396, "799": 10882, "800": 8280, "801": 12566, "802": 10128, "810": 11296, "814": 11273, "816": 10937, "818": 12265, "820": 10398, "828": 13120, "830": 12428, "835": 10462, "838": 11462, "840": 12776, "850": 10205, "852": 11845, "855": 10998, "860": 12468, "863": 12874, "866": 11029, "867": 11932, "870": 10731, "880": 9987, "886": 12050, "888": 9389, "890": 12075, "897": 8747, "899": 12612, "900": 8567, "911": 9911, "920": 11976, "921": 12253, "925": 10711, "930": 12601, "950": 10468, "960": 10450, "970": 13314, "978": 8837, "980": 10536, "985": 11263, "990": 10278, "998": 13180, "999": 9098, "1000": 8212, "1001": 11823, "1010": 13266, "1020": 13223, "1024": 11570, "1080": 10680, "1100": 9393, "1111": 11954, "1200": 8552, "1234": 10343, "1250": 11591, "1280": 10350, "1300": 8925, "1350": 12809, "1389": 12853, "1400": 9439, "1500": 8443, "1600": 8903, "1700": 9641, "1800": 8961, "1840": 12571, "1850": 12631, "1860": 11990, "1867": 13042, "1868": 12590, "1870": 12720, "1871": 13262, "1880": 11348, "1882": 13273, "1884": 13007, "1885": 13124, "1886": 12935, "1888": 10988, "1889": 12116, "1890": 11787, "1893": 12927, "1894": 12221, "1895": 10794, "1896": 11833, "1897": 12084, "1898": 11459, "1899": 11886, "1900": 8985, "1901": 11113, "1902": 11487, "1903": 11295, "1904": 11035, "1905": 10196, "1906": 10959, "1907": 11111, "1908": 11046, "1909": 10943, "1910": 10428, "1911": 10041, "1912": 9855, "1913": 10432, "1914": 9837, "1915": 10649, "1916": 10772, "1917": 10199, "1918": 10106, "1919": 9915, "1920": 9208, "1921": 10033, "1922": 10209, "1923": 10236, "1924": 10052, "1925": 10087, "1926": 10126, "1927": 9620, "1928": 9672, "1929": 9792, "1930": 9275, "1931": 9639, "1932": 9737, "1933": 9657, "1934": 9823, "1935": 9523, "1936": 9481, "1937": 9166, "1938": 9429, "1939": 9459, "1940": 9211, "1941": 9327, "1942": 9480, "1943": 9540, "1944": 9462, "1945": 8799, "1946": 9120, "1947": 9253, "1948": 9130, "1949": 8594, "1950": 8707, "1951": 9387, "1952": 9241, "1953": 9268, "1954": 9258, "1955": 9043, "1956": 9076, "1957": 9088, "1958": 8955, "1959": 9110, "1960": 8779, "1961": 9199, "1962": 9121, "1963": 9155, "1964": 9129, "1965": 9141, "1966": 9093, "1967": 9128, "1968": 9045, "1969": 9073, "1970": 8464, "1971": 9061, "1972": 9027, "1973": 9062, "1974": 9072, "1975": 8974, "1976": 8911, "1977": 9060, "1978": 8774, "1979": 8706, "1980": 8499, "1981": 8785, "1982": 8687, "1983": 8715, "1984": 8655, "1985": 8630, "1986": 8629, "1987": 8622, "1988": 8571, "1989": 8528, "1990": 8431, "1991": 8555, "1992": 8508, "1993": 8516, "1994": 8447, "1995": 8396, "1996": 8432, "1997": 8387, "1998": 8368, "1999": 8338, "2000": 8202, "2001": 8285, "2002": 8301, "2003": 8263, "2004": 8258, "2005": 8232, "2006": 8213, "2007": 8201, "2008": 8182, "2009": 8170, "2010": 8166, "2011": 8163, "2012": 8151, "2013": 8138, "2014": 8127, "2015": 8119, "2016": 8112, "2017": 8109, "2018": 8271, "2019": 9160, "2020": 8439, "2021": 9960, "2022": 10550, "2025": 8950, "2030": 9787, "2050": 11931, "2100": 10247, "2200": 10191, "2300": 10000, "2345": 11209, "2400": 9851, "2500": 8720, "2600": 10496, "2700": 10930, "2756": 9397, "2765": 9513, "2800": 10347, "2900": 13044, "3000": 8283, "3100": 12100, "3200": 10337, "3300": 11543, "3400": 13294, "3500": 9252, "3600": 10517, "3800": 11433, "4000": 8442, "4066": 9607, "4200": 12395, "4399": 9922, "4500": 9805, "4600": 8826, "4800": 12488, "5000": 8262, "5500": 11298, "5757": 12007, "6000": 8412, "6221": 12580, "6500": 11247, "6606": 8754, "6991": 12918, "7000": 8800, "7500": 11271, "7866": 12081, "8000": 8623, "8591": 12376, "8891": 10546, "9000": 9117, "9595": 13043, "9678": 12057, "9985": 12839, "10000": 8769, "12000": 10520, "12306": 11914, "12345": 9700, "15000": 10064, "15058": 12347, "18000": 12499, "20000": 8875, "25000": 13251, "30000": 11158, "50000": 11750, "123456": 10644, "13913459": 12643, "573032185": 9970, "!": 106, "\"": 107, "#": 108, "##!": 13317, "##\"": 13318, "###": 13319, "##$": 13320, "##%": 13321, "##&": 13322, "##'": 13323, "##(": 13324, "##)": 13325, "##*": 13326, "##+": 13327, "##,": 13328, "##-": 13329, "##.": 13330, "##/": 13331, "##0": 8129, "##00": 8279, "##000": 9086, "##001": 9942, "##007": 12843, "##009": 11219, "##01": 8665, "##010": 11906, "##011": 12424, "##012": 12037, "##013": 11335, "##014": 11365, "##015": 8851, "##016": 8705, "##017": 8710, "##02": 8904, "##03": 9042, "##04": 9099, "##05": 8920, "##06": 8839, "##07": 9131, "##08": 9153, "##09": 9267, "##0m": 13079, "##0mm": 12483, "##1": 8148, "##10": 8311, "##100": 8823, "##1000": 10529, "##101": 11712, "##11": 8452, "##110": 12518, "##12": 8455, "##120": 12256, "##123": 9807, "##13": 8679, "##14": 8717, "##15": 8493, "##150": 12041, "##16": 8518, "##160": 12765, "##163": 11631, "##168": 11090, "##17": 8408, "##18": 8662, "##19": 8818, "##2": 8144, "##20": 8393, "##200": 9902, "##2000": 9842, "##2007": 10604, "##2008": 10545, "##2009": 9948, "##2010": 9546, "##2011": 9455, "##2012": 9285, "##2013": 9023, "##2014": 8951, "##2015": 8600, "##2016": 8386, "##2017": 8367, "##21": 8650, "##22": 8683, "##23": 8748, "##24": 8682, "##25": 8743, "##250": 12629, "##26": 8756, "##27": 8976, "##28": 8835, "##29": 8887, "##2c": 11935, "##2d": 12675, "##2f": 12971, "##3": 8152, "##30": 8471, "##300": 10097, "##3000": 13141, "##31": 8805, "##32": 8709, "##33": 8921, "##34": 9269, "##340": 12149, "##35": 8852, "##36": 9159, "##360": 10408, "##365": 10422, "##37": 9474, "##370": 13121, "##38": 9137, "##39": 9355, "##3c": 12031, "##3d": 10696, "##4": 8159, "##40": 8660, "##400": 10765, "##41": 9281, "##42": 9240, "##43": 9433, "##44": 9292, "##45": 9039, "##46": 9340, "##47": 9050, "##470": 12531, "##48": 8849, "##480": 11581, "##49": 9500, "##5": 8157, "##50": 8474, "##500": 9758, "##51": 9216, "##52": 9364, "##520": 13241, "##53": 9310, "##54": 9488, "##55": 8949, "##56": 9352, "##57": 9647, "##58": 9265, "##580": 10703, "##59": 9632, "##5s": 13201, "##6": 8158, "##60": 8581, "##600": 10346, "##61": 8978, "##62": 9290, "##63": 9373, "##64": 9165, "##65": 9331, "##66": 8952, "##67": 9411, "##68": 9105, "##69": 9398, "##7": 8161, "##70": 8740, "##700": 11551, "##71": 9097, "##72": 9492, "##73": 9148, "##74": 9743, "##75": 9183, "##750": 10969, "##76": 9624, "##77": 8959, "##78": 9136, "##79": 9495, "##8": 8156, "##80": 8538, "##800": 9988, "##81": 9313, "##82": 9605, "##83": 9559, "##84": 9545, "##85": 9169, "##86": 9219, "##87": 9446, "##88": 8544, "##888": 10053, "##89": 9402, "##9": 8160, "##90": 8599, "##900": 10589, "##91": 9332, "##92": 9595, "##93": 9676, "##94": 9723, "##95": 9102, "##96": 9419, "##97": 9410, "##98": 9215, "##99": 8653, "##999": 11430, "##:": 13332, "##;": 13333, "##<": 13334, "##=": 13335, "##>": 13336, "##?": 13337, "##@": 13338, "##[": 13339, "##\\": 13340, "##]": 13341, "##^": 13342, "##_": 13343, "##a": 8139, "##a1": 11414, "##a2": 12871, "##a5": 12540, "##aa": 10226, "##ab": 11008, "##abc": 12072, "##able": 9609, "##ac": 9202, "##ace": 10026, "##ach": 10289, "##ack": 11360, "##act": 12183, "##ad": 8695, "##ada": 11370, "##ade": 10233, "##ader": 11590, "##admin": 11454, "##ads": 12514, "##ae": 10361, "##af": 11472, "##aft": 12106, "##ag": 10814, "##age": 9103, "##ager": 13281, "##ague": 12998, "##ah": 9082, "##ai": 8982, "##aid": 11791, "##ail": 10923, "##ain": 9347, "##aine": 12554, "##air": 10908, "##ak": 9896, "##aka": 12417, "##ake": 9981, "##al": 8315, "##ala": 11658, "##ald": 13041, "##ale": 11079, "##alk": 11346, "##all": 10050, "##als": 12707, "##am": 8608, "##ama": 11135, "##ame": 10816, "##an": 8244, "##ana": 9335, "##ance": 9966, "##and": 9369, "##anda": 13300, "##ane": 10581, "##ang": 8688, "##ani": 13154, "##ann": 12464, "##ano": 10855, "##anonymoussaid": 10813, "##ans": 11159, "##ant": 9834, "##ao": 8731, "##ap": 8872, "##ape": 11706, "##app": 11259, "##ar": 8458, "##ara": 10225, "##ard": 9345, "##are": 10305, "##ari": 11172, "##ark": 11153, "##art": 9528, "##ary": 9277, "##as": 8576, "##ase": 10294, "##ash": 9889, "##asia": 11276, "##ass": 11904, "##ast": 9421, "##at": 8488, "##ata": 10449, "##ate": 9690, "##ath": 11486, "##ather": 12290, "##atic": 11080, "##ation": 8794, "##ations": 11517, "##ator": 11762, "##ats": 10841, "##ature": 10461, "##atus": 12283, "##au": 9096, "##av": 9876, "##ave": 12529, "##aw": 10922, "##ax": 10704, "##ay": 8760, "##b": 8204, "##ba": 8668, "##baby": 12515, "##back": 10102, "##ball": 11050, "##bank": 10980, "##bar": 11031, "##baru": 13257, "##base": 10918, "##bat": 12671, "##bay": 13200, "##bb": 10214, "##bbs": 12646, "##bby": 12832, "##bc": 9242, "##be": 8765, "##bee": 11162, "##bel": 12157, "##bell": 13110, "##ber": 8956, "##berg": 10039, "##berry": 10793, "##bert": 10491, "##bet": 9704, "##beth": 12101, "##bi": 9350, "##bia": 12596, "##bian": 11092, "##bike": 13276, "##bility": 13254, "##bin": 10448, "##bit": 9407, "##ble": 8862, "##blog": 10877, "##bo": 8820, "##board": 9472, "##body": 11326, "##bon": 12229, "##book": 8874, "##bor": 12268, "##bot": 10119, "##bow": 12559, "##box": 8927, "##boy": 11287, "##bra": 11552, "##bre": 12655, "##bs": 9071, "##bscribe": 12980, "##bt": 10161, "##bu": 11381, "##bug": 12351, "##burg": 12433, "##bus": 10151, "##by": 8684, "##c": 8177, "##ca": 8808, "##cake": 12814, "##cal": 10384, "##cam": 12438, "##can": 12632, "##car": 9831, "##card": 11644, "##care": 11014, "##cast": 13020, "##cat": 10869, "##cation": 11424, "##cc": 8860, "##cca": 13144, "##cd": 10340, "##ce": 8328, "##cel": 11786, "##cent": 11270, "##cept": 11877, "##cer": 10326, "##ces": 11463, "##cg": 11478, "##ch": 8370, "##cha": 11645, "##chat": 10720, "##che": 9763, "##chel": 10867, "##chen": 11595, "##cher": 10824, "##chi": 10525, "##ci": 9702, "##cia": 12382, "##cil": 11783, "##cing": 11540, "##city": 10747, "##ck": 8433, "##cker": 10603, "##cket": 10811, "##cks": 11495, "##cky": 11216, "##cl": 10753, "##cle": 11619, "##cm": 8341, "##cms": 12353, "##cm~": 13123, "##cn": 9435, "##co": 8588, "##code": 10802, "##coin": 10160, "##com": 9479, "##come": 12097, "##con": 10281, "##copyright": 13291, "##cord": 12291, "##core": 11921, "##count": 12369, "##covery": 12548, "##cp": 11057, "##cr": 13129, "##cs": 9761, "##ct": 8722, "##ction": 9116, "##ctionary": 13126, "##ctive": 11626, "##ctor": 9610, "##cts": 12175, "##cture": 11235, "##cus": 11609, "##cy": 8890, "##d": 8168, "##da": 8521, "##dan": 13184, "##dar": 12354, "##data": 11792, "##day": 8758, "##db": 9123, "##dc": 12251, "##dd": 9879, "##dden": 13109, "##de": 8510, "##ded": 11363, "##del": 13283, "##den": 10241, "##deo": 13000, "##der": 8960, "##des": 11211, "##desk": 13039, "##dge": 12025, "##dget": 11857, "##di": 9172, "##dia": 9360, "##dical": 13168, "##die": 11588, "##ding": 9755, "##dio": 12159, "##dium": 12787, "##dk": 12806, "##dm": 10420, "##dn": 10853, "##do": 8828, "##dog": 13315, "##dom": 11290, "##don": 12107, "##dot": 12402, "##down": 11140, "##dp": 11497, "##dr": 11582, "##dra": 12753, "##dragon": 12857, "##drive": 13115, "##ds": 8841, "##dt": 12672, "##du": 11202, "##dy": 8771, "##e": 8154, "##ea": 10073, "##ead": 12943, "##eam": 10430, "##ean": 10096, "##ear": 11979, "##ec": 9587, "##ect": 10862, "##ed": 8303, "##ee": 8854, "##een": 10929, "##eep": 12293, "##eet": 12412, "##ef": 9679, "##eg": 10935, "##eh": 12742, "##ei": 9384, "##ein": 11858, "##ek": 9534, "##el": 8472, "##ell": 9602, "##ella": 10311, "##ello": 13213, "##em": 9736, "##eme": 12538, "##ement": 11946, "##en": 8329, "##ena": 12000, "##ence": 10504, "##end": 11652, "##ene": 10600, "##eng": 9995, "##ens": 11550, "##ent": 8936, "##eo": 10232, "##ep": 11613, "##er": 8196, "##era": 10540, "##ere": 12865, "##ering": 12393, "##ern": 9814, "##ernel": 13272, "##erry": 11329, "##ers": 8755, "##erson": 11082, "##ert": 10707, "##ery": 11041, "##es": 8333, "##ese": 9692, "##ess": 9685, "##est": 10414, "##et": 8418, "##eting": 13216, "##ets": 12198, "##ett": 13151, "##ette": 13009, "##ev": 12054, "##ever": 11531, "##ew": 10795, "##ews": 13024, "##ex": 8870, "##ey": 8603, "##ez": 11640, "##f": 8189, "##f2016": 12769, "##fa": 9777, "##face": 12122, "##facebook": 12917, "##fc": 9717, "##fe": 9568, "##fer": 10967, "##ference": 11419, "##fet": 12089, "##ff": 9049, "##fi": 9864, "##field": 10901, "##fig": 11392, "##file": 12056, "##firm": 12240, "##fit": 11768, "##fl": 11690, "##flow": 11522, "##fly": 11983, "##fo": 10261, "##food": 12973, "##force": 10488, "##ford": 10283, "##fork": 10618, "##form": 12725, "##fr": 13245, "##free": 13287, "##fs": 9222, "##ft": 9002, "##fu": 12043, "##ful": 10291, "##fun": 11222, "##fw": 12851, "##fx": 13122, "##g": 8181, "##ga": 8676, "##gan": 10622, "##gar": 11742, "##gas": 12400, "##gate": 11695, "##gb": 9673, "##gc": 10817, "##ge": 8441, "##ged": 11765, "##gen": 10152, "##gence": 12932, "##ger": 9289, "##get": 10916, "##getrelax": 13198, "##gg": 9949, "##ggle": 11747, "##gh": 11304, "##ght": 9725, "##gi": 10006, "##gin": 10822, "##ging": 12374, "##gio": 12676, "##gion": 13258, "##gl": 11406, "##gle": 10098, "##gm": 11390, "##gma": 12880, "##gn": 12135, "##gnet": 13308, "##go": 8591, "##google": 10626, "##gp": 10932, "##graphy": 12872, "##ground": 13195, "##group": 13097, "##gs": 9726, "##gt": 12429, "##gy": 9765, "##h": 8199, "##ha": 8778, "##hai": 11828, "##ham": 9593, "##han": 9646, "##hang": 11869, "##hat": 12063, "##hc": 11100, "##hd": 9304, "##he": 9977, "##head": 11795, "##hen": 11602, "##her": 9856, "##here": 10659, "##hg": 12207, "##hi": 8963, "##hia": 12615, "##hin": 13098, "##hing": 10716, "##hip": 11489, "##hk": 11054, "##hl": 11831, "##hm": 13130, "##hn": 11781, "##ho": 9570, "##home": 10479, "##hone": 10271, "##hoo": 12638, "##hop": 11975, "##host": 12227, "##house": 9937, "##how": 13132, "##hp": 9990, "##hr": 10561, "##hs": 9551, "##ht": 12160, "##http": 11116, "##hu": 9670, "##hua": 13074, "##hur": 13190, "##hy": 9943, "##hz": 8686, "##i": 8169, "##ia": 8321, "##ial": 9501, "##ian": 8750, "##ias": 12803, "##ible": 12413, "##ic": 8317, "##ica": 9156, "##ical": 9430, "##ice": 8877, "##ich": 11578, "##ick": 9873, "##ico": 10641, "##icon": 12829, "##ics": 9034, "##id": 8601, "##ida": 12708, "##ide": 9552, "##ider": 11292, "##ie": 8402, "##iel": 11995, "##ien": 12023, "##ience": 13225, "##ier": 9181, "##ies": 8773, "##if": 9536, "##ification": 12820, "##ified": 13237, "##ift": 12401, "##ig": 11421, "##ight": 9558, "##iginal": 13099, "##ign": 11558, "##ii": 8917, "##ik": 10445, "##ika": 11378, "##ike": 11727, "##iki": 12434, "##iko": 11480, "##il": 8742, "##ile": 9729, "##ill": 9868, "##ils": 12223, "##ily": 11779, "##im": 9370, "##ima": 13028, "##ime": 11218, "##in": 8277, "##ina": 9314, "##ince": 13199, "##ine": 8620, "##iner": 12045, "##ing": 8221, "##ings": 10334, "##ini": 10489, "##ink": 11119, "##ino": 9846, "##ins": 9556, "##int": 9824, "##io": 8652, "##ion": 8410, "##ions": 11137, "##ious": 11737, "##ip": 9032, "##ique": 11324, "##ir": 8977, "##ira": 11630, "##ire": 9764, "##is": 8331, "##isa": 12170, "##ise": 9651, "##ish": 10574, "##ision": 12556, "##ism": 10627, "##ison": 10316, "##ist": 9527, "##it": 8500, "##ita": 10242, "##ite": 9538, "##ith": 11440, "##iti": 12644, "##ition": 11418, "##ito": 12899, "##itor": 12449, "##its": 11275, "##ity": 8863, "##itz": 12970, "##iu": 12425, "##ium": 9750, "##ius": 10392, "##ive": 8857, "##ivity": 12165, "##ix": 9330, "##ize": 11789, "##j": 8334, "##ja": 10067, "##ject": 12238, "##ji": 9343, "##jia": 12489, "##jiang": 12950, "##jie": 12732, "##jin": 13161, "##jing": 12128, "##jo": 9839, "##joy": 10284, "##js": 11124, "##ju": 10904, "##jun": 12915, "##jy": 13051, "##k": 8197, "##ka": 8693, "##kb": 10285, "##ke": 8537, "##ken": 11285, "##ker": 9013, "##ket": 11820, "##key": 9938, "##kg": 8714, "##khz": 12112, "##ki": 8614, "##kin": 12018, "##king": 9740, "##kins": 13084, "##kit": 11217, "##kk": 12693, "##km": 8879, "##ko": 8827, "##ks": 9457, "##ku": 9547, "##kv": 11145, "##kw": 10446, "##ky": 10218, "##l": 8178, "##la": 8461, "##lab": 11532, "##labels": 10636, "##lace": 12545, "##lam": 12953, "##lan": 9475, "##land": 8789, "##lar": 11208, "##las": 10113, "##last": 13177, "##late": 11523, "##lax": 12680, "##lay": 11969, "##lc": 11097, "##ld": 8635, "##le": 8268, "##lean": 13246, "##led": 10702, "##lee": 12448, "##len": 11407, "##lent": 12974, "##ler": 8871, "##les": 8937, "##less": 9920, "##let": 10780, "##lex": 11074, "##ley": 8930, "##lf": 9751, "##li": 8636, "##lia": 10336, "##lic": 11809, "##lie": 10158, "##life": 10359, "##light": 9638, "##lin": 9029, "##lina": 11585, "##line": 8762, "##lines": 13052, "##ling": 9426, "##link": 9989, "##lio": 12068, "##lis": 10820, "##lish": 13128, "##list": 10142, "##live": 11888, "##lk": 10758, "##ll": 8390, "##lla": 9585, "##lle": 9906, "##ller": 11284, "##lli": 13169, "##lling": 12903, "##llo": 11447, "##llow": 11200, "##lls": 11139, "##lly": 9456, "##lm": 9532, "##lmer": 12763, "##lo": 8897, "##load": 11713, "##lock": 11248, "##log": 11458, "##logy": 11121, "##lon": 10146, "##lone": 12519, "##lor": 12422, "##lot": 10580, "##love": 12564, "##low": 10962, "##lp": 10986, "##lr": 10712, "##ls": 8916, "##lt": 9238, "##lter": 12171, "##lton": 10377, "##lts": 12977, "##lu": 10079, "##lus": 11131, "##lution": 11843, "##lux": 12700, "##lv": 9084, "##lvin": 12745, "##ly": 8436, "##m": 8175, "##m2": 11916, "##ma": 8404, "##mah": 10394, "##mail": 10984, "##mall": 13307, "##man": 8490, "##mand": 12131, "##mann": 10750, "##map": 10909, "##mar": 11800, "##mark": 9882, "##master": 12959, "##mate": 12125, "##max": 10014, "##may": 11924, "##mb": 8517, "##mber": 10494, "##mbps": 12399, "##mc": 10307, "##md": 10638, "##me": 8505, "##med": 13089, "##media": 10970, "##men": 11839, "##ment": 8631, "##ments": 10444, "##mer": 9778, "##mes": 13060, "##mg": 8882, "##mhz": 9932, "##mi": 8625, "##mic": 11341, "##min": 9844, "##mine": 12723, "##ming": 10693, "##mini": 12391, "##mit": 11104, "##mix": 11091, "##ml": 8477, "##mll": 10682, "##mm": 8278, "##mma": 13292, "##mmy": 12137, "##mn": 11919, "##mo": 8788, "##mobile": 13217, "##mon": 10427, "##mond": 11423, "##moon": 12682, "##more": 11286, "##mp": 9085, "##mple": 12581, "##mporary": 12392, "##ms": 8884, "##mu": 12924, "##mus": 13090, "##mv": 13275, "##mw": 11504, "##my": 9009, "##n": 8171, "##n1": 11310, "##n2": 12750, "##na": 8374, "##name": 10509, "##nan": 12457, "##nap": 11546, "##nar": 12469, "##nba": 12360, "##nc": 10507, "##nce": 9056, "##nch": 11106, "##ncy": 10518, "##nd": 8735, "##nda": 12715, "##nder": 10493, "##ndi": 11874, "##ndy": 11373, "##ne": 8354, "##nel": 12827, "##ner": 8957, "##ners": 12550, "##nes": 10107, "##ness": 10077, "##net": 8914, "##new": 10654, "##news": 10040, "##next": 12397, "##ney": 10761, "##ng": 8291, "##nge": 10983, "##nger": 11533, "##ni": 8833, "##nia": 12664, "##nic": 12467, "##nie": 10519, "##night": 12734, "##ning": 9535, "##nis": 12334, "##nity": 11347, "##nix": 12955, "##nk": 9705, "##nm": 9359, "##nn": 9502, "##nne": 12866, "##nnis": 13004, "##nny": 13239, "##no": 8609, "##nome": 13125, "##nor": 12245, "##nos": 12782, "##note": 13062, "##now": 11371, "##np": 12798, "##ns": 8727, "##nse": 10996, "##nsis": 12263, "##nt": 8511, "##nter": 11526, "##nts": 12585, "##nus": 11316, "##ny": 8680, "##o": 8167, "##o2": 11110, "##oa": 11355, "##ob": 11047, "##oc": 9450, "##ock": 9069, "##od": 9308, "##ode": 10260, "##oe": 10115, "##of": 10150, "##og": 10800, "##oh": 12355, "##oi": 12577, "##oid": 10523, "##ok": 9185, "##oka": 12279, "##ol": 8798, "##ola": 12653, "##ology": 10277, "##om": 8810, "##oman": 13127, "##ome": 9893, "##on": 8224, "##ona": 11065, "##ond": 11684, "##one": 9021, "##ong": 9142, "##ons": 9961, "##onsored": 12504, "##oo": 8902, "##ood": 10919, "##ook": 10176, "##ool": 11627, "##oon": 12343, "##oot": 13187, "##op": 9133, "##ope": 11937, "##oper": 11468, "##or": 8372, "##ora": 11455, "##orage": 12669, "##ore": 9132, "##ories": 10939, "##orm": 10530, "##ors": 10903, "##ort": 10143, "##ory": 9428, "##os": 8470, "##osa": 12946, "##ose": 10936, "##ost": 12085, "##ot": 8783, "##other": 11759, "##oto": 11563, "##ou": 9857, "##oud": 12867, "##ough": 11600, "##ould": 11734, "##ound": 11477, "##our": 9832, "##ous": 9822, "##out": 9408, "##ov": 11689, "##ova": 13067, "##over": 11436, "##ow": 9024, "##own": 11751, "##ox": 9747, "##oy": 12532, "##oz": 13102, "##p": 8187, "##pa": 8797, "##pact": 12624, "##pad": 10730, "##page": 11817, "##pan": 12297, "##pass": 13206, "##pc": 10022, "##pd": 11693, "##pe": 8619, "##per": 9063, "##ph": 12465, "##pi": 9664, "##pin": 13248, "##ping": 10755, "##pl": 12569, "##play": 10324, "##ple": 10383, "##plus": 9682, "##pm": 9280, "##pmlast": 12138, "##pn": 12991, "##po": 9401, "##pods": 13284, "##point": 11112, "##pop": 13015, "##port": 9356, "##post": 11719, "##posted": 12717, "##pp": 9586, "##pper": 11413, "##ppy": 12738, "##pr": 11426, "##press": 12300, "##price": 13087, "##pro": 10538, "##ps": 8525, "##pt": 10789, "##pu": 11016, "##public": 13105, "##pus": 12657, "##put": 11300, "##px": 10605, "##py": 11610, "##q": 8326, "##qi": 11451, "##ql": 11083, "##qq": 10624, "##que": 9477, "##ques": 12503, "##r": 8180, "##r3": 12549, "##r4": 13032, "##ra": 8332, "##rade": 10287, "##rail": 12783, "##rain": 11944, "##ral": 10482, "##ram": 9661, "##rame": 13185, "##ran": 10477, "##rant": 10834, "##rap": 11893, "##raph": 12220, "##ration": 11103, "##ray": 10009, "##rc": 10227, "##rcle": 12466, "##rd": 8642, "##rder": 12658, "##rdon": 12702, "##re": 8358, "##rea": 12551, "##read": 10314, "##ream": 11714, "##rect": 13075, "##red": 9749, "##ree": 11621, "##reen": 10902, "##ren": 9489, "##rence": 12743, "##rent": 10858, "##res": 9683, "##ress": 11142, "##rex": 12437, "##rey": 11492, "##rf": 10531, "##rge": 10756, "##ri": 8641, "##ria": 10159, "##rial": 10358, "##rian": 12475, "##ric": 11748, "##rid": 10804, "##rie": 11062, "##ries": 11665, "##right": 11264, "##rin": 13250, "##ring": 10734, "##rio": 12062, "##rip": 12332, "##ris": 9848, "##rite": 11366, "##rity": 12079, "##rix": 13208, "##rk": 10364, "##rl": 9923, "##rley": 13290, "##rm": 9592, "##rma": 13156, "##rman": 11386, "##rmb": 10894, "##rmin": 13116, "##rn": 9256, "##rner": 11012, "##ro": 8607, "##ron": 8991, "##room": 12193, "##ros": 12409, "##row": 10570, "##rp": 9980, "##rr": 12579, "##rris": 11818, "##rry": 9249, "##rs": 8640, "##rss": 12281, "##rt": 8716, "##rtex": 12877, "##rth": 11207, "##ru": 10409, "##rum": 11075, "##rus": 10051, "##ry": 8449, "##s": 8118, "##sa": 8606, "##said": 8944, "##san": 10978, "##sc": 10203, "##sch": 13107, "##sco": 11364, "##sd": 10117, "##sday": 12956, "##se": 8417, "##self": 13061, "##sen": 10387, "##sent": 11836, "##ser": 9520, "##ses": 12856, "##set": 9852, "##sh": 8613, "##sha": 12772, "##share": 11042, "##shi": 9655, "##shine": 12922, "##ship": 11987, "##shop": 10940, "##shot": 11125, "##si": 9182, "##sia": 12557, "##side": 11756, "##sio": 12266, "##sion": 9224, "##sis": 10500, "##sit": 12618, "##site": 11479, "##sk": 8998, "##skip": 12724, "##sky": 11700, "##sl": 11066, "##sm": 10244, "##sn": 12480, "##so": 9974, "##sol": 12257, "##son": 8535, "##sp": 10367, "##space": 12246, "##ss": 8565, "##sse": 12754, "##ssion": 12726, "##sson": 12582, "##st": 8415, "##sta": 10949, "##stack": 12511, "##star": 10297, "##ste": 11881, "##ster": 8996, "##stin": 12921, "##stle": 13026, "##ston": 10229, "##stone": 12795, "##stro": 12976, "##stry": 11001, "##style": 10001, "##su": 11442, "##sue": 11872, "##sun": 11798, "##sy": 10178, "##t": 8165, "##t00": 9260, "##ta": 8383, "##table": 12477, "##tag": 11882, "##tags": 11313, "##tail": 11662, "##tal": 9917, "##talk": 12534, "##tan": 10105, "##tant": 12028, "##tar": 10216, "##tation": 12386, "##tax": 13155, "##tb": 11126, "##tc": 10149, "##tch": 9496, "##te": 8299, "##tech": 11761, "##ted": 9255, "##tee": 12729, "##tein": 12508, "##tel": 11246, "##ten": 11598, "##ter": 8457, "##ters": 12017, "##tes": 9420, "##test": 11574, "##text": 11816, "##tf": 11359, "##th": 8414, "##the": 11334, "##ther": 10198, "##thing": 12012, "##ti": 9007, "##tic": 9759, "##tical": 11912, "##tics": 11130, "##tier": 11955, "##ties": 11199, "##time": 9785, "##times": 12288, "##tin": 10400, "##tina": 10584, "##ting": 9107, "##tings": 13288, "##tion": 8361, "##tional": 11852, "##tions": 9652, "##tis": 10827, "##tive": 9741, "##tl": 12305, "##tle": 11283, "##tm": 10774, "##tment": 12986, "##to": 8527, "##tom": 11686, "##ton": 8626, "##tone": 11902, "##top": 10075, "##tor": 8713, "##tore": 12941, "##tors": 13270, "##tory": 12608, "##tos": 12920, "##town": 11323, "##tp": 10880, "##tr": 11309, "##tra": 9808, "##trix": 12749, "##tro": 11343, "##try": 11589, "##ts": 8723, "##tsu": 12230, "##tt": 9235, "##tta": 11245, "##tte": 9786, "##tter": 10766, "##tti": 11279, "##tto": 11403, "##tton": 11190, "##tty": 11160, "##tu": 10455, "##ture": 11704, "##tus": 10356, "##tv": 9171, "##tw": 12278, "##twitter": 12030, "##ty": 8661, "##type": 11085, "##tz": 10228, "##u": 8207, "##ua": 9478, "##ual": 10665, "##uality": 13145, "##uan": 9680, "##uard": 12589, "##ub": 10544, "##ube": 10957, "##uc": 13139, "##uce": 12051, "##uch": 12752, "##uck": 11971, "##ud": 9849, "##ude": 11997, "##ue": 8803, "##uel": 11866, "##ug": 11838, "##ugh": 12667, "##ui": 9273, "##uid": 12520, "##uk": 10687, "##ul": 10086, "##ula": 10456, "##ular": 10764, "##ule": 10724, "##ull": 12316, "##ult": 9766, "##um": 8545, "##uma": 13083, "##ume": 11465, "##ument": 11867, "##un": 8829, "##unch": 11294, "##und": 9914, "##ung": 9112, "##unge": 13077, "##uo": 9731, "##up": 8838, "##ur": 8685, "##ura": 10238, "##ure": 8813, "##urg": 13143, "##url": 12373, "##urn": 12760, "##urs": 11575, "##urt": 10857, "##ury": 11117, "##us": 8293, "##use": 10254, "##ush": 12670, "##ust": 12840, "##ut": 9194, "##ute": 9710, "##ux": 9549, "##uy": 12574, "##v": 8225, "##v4": 12507, "##va": 8786, "##val": 9957, "##van": 13045, "##vas": 12239, "##vc": 12077, "##vd": 10754, "##ve": 8519, "##ved": 11667, "##vel": 10588, "##ven": 10844, "##ver": 8984, "##verse": 11174, "##vertisement": 12021, "##ves": 11084, "##vg": 12781, "##vi": 9197, "##via": 9490, "##vic": 11956, "##vice": 10666, "##view": 8892, "##ville": 10388, "##vin": 10454, "##ving": 10369, "##vis": 11233, "##vm": 10318, "##vo": 10701, "##vr": 10131, "##vs": 11521, "##vy": 11853, "##w": 8220, "##wa": 9161, "##walk": 12621, "##walker": 12630, "##wan": 9951, "##wang": 10365, "##ward": 11612, "##ware": 10534, "##watch": 9907, "##way": 8824, "##ways": 11672, "##wd": 11681, "##we": 11722, "##web": 9944, "##wei": 12320, "##well": 9665, "##wen": 10861, "##wer": 10668, "##west": 11887, "##wf": 12242, "##wi": 10958, "##win": 10237, "##wing": 13070, "##wn": 10799, "##wo": 10911, "##wood": 9730, "##word": 10184, "##work": 12282, "##works": 10054, "##world": 10120, "##ws": 10402, "##wt": 12271, "##wu": 12144, "##www": 9718, "##x": 8206, "##x2": 12505, "##x5": 12704, "##xi": 10201, "##xon": 12854, "##xp": 11379, "##xt": 12452, "##xure": 12622, "##xx": 9517, "##xxx": 12812, "##xy": 11038, "##y": 8179, "##ya": 8741, "##yan": 10777, "##ye": 10522, "##yer": 10955, "##yi": 11017, "##ym": 12267, "##yn": 10879, "##yo": 10222, "##you": 12441, "##ys": 9449, "##yu": 10329, "##yy": 12642, "##z": 8253, "##za": 9283, "##ze": 9349, "##zen": 10549, "##zer": 10631, "##zi": 10112, "##zl": 12961, "##zo": 10121, "##zon": 10623, "##zone": 11004, "##zu": 13085, "##zy": 9748, "##zz": 9409, "##zzi": 12939, "##{": 13344, "##|": 13345, "##}": 13346, "##~": 13347, "##£": 13348, "##¤": 13349, "##¥": 13350, "##§": 13351, "##©": 13278, "##«": 13352, "##®": 8646, "##°": 8724, "##°c": 9953, "##±": 13353, "##²": 11699, "##³": 13354, "##µ": 13355, "##·": 13356, "##¹": 13357, "##º": 13358, "##»": 13359, "##¼": 13360, "##×": 9569, "##ß": 13361, "##æ": 13362, "##÷": 13363, "##ø": 13364, "##đ": 13365, "##ŋ": 13366, "##ɔ": 13367, "##ə": 13368, "##ɡ": 13369, "##ʰ": 13370, "##ˇ": 13371, "##ˈ": 13372, "##ˊ": 13373, "##ˋ": 13374, "##ˍ": 13375, "##ː": 13376, "##˙": 13377, "##˚": 13378, "##ˢ": 13379, "##α": 13380, "##β": 13381, "##γ": 13382, "##δ": 13383, "##ε": 13384, "##η": 13385, "##θ": 13386, "##ι": 13387, "##κ": 13388, "##λ": 13389, "##μ": 13390, "##ν": 13391, "##ο": 13392, "##π": 13393, "##ρ": 13394, "##ς": 13395, "##σ": 13396, "##τ": 13397, "##υ": 13398, "##φ": 13399, "##χ": 13400, "##ψ": 13401, "##ω": 10506, "##а": 11318, "##б": 13402, "##в": 13403, "##г": 13404, "##д": 13405, "##е": 13406, "##ж": 13407, "##з": 13408, "##и": 11000, "##к": 13409, "##л": 13410, "##м": 13411, "##н": 13412, "##о": 13413, "##п": 13414, "##р": 13415, "##с": 13416, "##т": 13417, "##у": 13418, "##ф": 13419, "##х": 13420, "##ц": 13421, "##ч": 13422, "##ш": 13423, "##ы": 13424, "##ь": 13425, "##я": 12992, "##і": 13426, "##ا": 13427, "##ب": 13428, "##ة": 13429, "##ت": 13430, "##د": 13431, "##ر": 13432, "##س": 13433, "##ع": 13434, "##ل": 13435, "##م": 13436, "##ن": 13437, "##ه": 13438, "##و": 13439, "##ي": 13440, "##۩": 13441, "##ก": 13442, "##ง": 13443, "##น": 13444, "##ม": 13445, "##ย": 13446, "##ร": 13447, "##อ": 13448, "##า": 13449, "##เ": 13450, "##๑": 13451, "##་": 13452, "##ღ": 13453, "##ᄀ": 13454, "##ᄁ": 13455, "##ᄂ": 13456, "##ᄃ": 13457, "##ᄅ": 13458, "##ᄆ": 13459, "##ᄇ": 13460, "##ᄈ": 13461, "##ᄉ": 13462, "##ᄋ": 13463, "##ᄌ": 13464, "##ᄎ": 13465, "##ᄏ": 13466, "##ᄐ": 13467, "##ᄑ": 13468, "##ᄒ": 13469, "##ᅡ": 10928, "##ᅢ": 13470, "##ᅣ": 13471, "##ᅥ": 13472, "##ᅦ": 13473, "##ᅧ": 13474, "##ᅨ": 13475, "##ᅩ": 13005, "##ᅪ": 13476, "##ᅬ": 13477, "##ᅭ": 13478, "##ᅮ": 13479, "##ᅯ": 13480, "##ᅲ": 13481, "##ᅳ": 13482, "##ᅴ": 13483, "##ᅵ": 10787, "##ᆨ": 11953, "##ᆫ": 9877, "##ᆯ": 11596, "##ᆷ": 13484, "##ᆸ": 13485, "##ᆺ": 13486, "##ᆻ": 13487, "##ᆼ": 10945, "##ᗜ": 13488, "##ᵃ": 13489, "##ᵉ": 13490, "##ᵍ": 13491, "##ᵏ": 13492, "##ᵐ": 13493, "##ᵒ": 13494, "##ᵘ": 13495, "##‖": 13496, "##„": 13497, "##†": 13498, "##•": 13499, "##‥": 13500, "##‧": 13501, "##
": 13502, "##‰": 13503, "##′": 13504, "##″": 13505, "##‹": 13506, "##›": 13507, "##※": 13508, "##‿": 13509, "##⁄": 13510, "##ⁱ": 13511, "##⁺": 13512, "##ⁿ": 13513, "##₁": 13514, "##₂": 12831, "##₃": 13515, "##₄": 13516, "##€": 13517, "##℃": 8320, "##№": 13518, "##™": 9221, "##ⅰ": 13519, "##ⅱ": 13520, "##ⅲ": 13521, "##ⅳ": 13522, "##ⅴ": 13523, "##←": 13018, "##↑": 10839, "##→": 10057, "##↓": 12414, "##↔": 13524, "##↗": 13525, "##↘": 13526, "##⇒": 13527, "##∀": 13528, "##−": 13529, "##∕": 13530, "##∙": 13531, "##√": 13532, "##∞": 13533, "##∟": 13534, "##∠": 13535, "##∣": 13536, "##∥": 10458, "##∩": 13537, "##∮": 13538, "##∶": 13539, "##∼": 13540, "##∽": 13541, "##≈": 13542, "##≒": 13543, "##≡": 13544, "##≤": 13545, "##≥": 13546, "##≦": 13547, "##≧": 13548, "##≪": 13549, "##≫": 13550, "##⊙": 13551, "##⋅": 13552, "##⋈": 13553, "##⋯": 13554, "##⌒": 13555, "##①": 13556, "##②": 13557, "##③": 13558, "##④": 13559, "##⑤": 13560, "##⑥": 13561, "##⑦": 13562, "##⑧": 13563, "##⑨": 13564, "##⑩": 13565, "##⑴": 13566, "##⑵": 13567, "##⑶": 13568, "##⑷": 13569, "##⑸": 13570, "##⒈": 13571, "##⒉": 13572, "##⒊": 13573, "##⒋": 13574, "##ⓒ": 13575, "##ⓔ": 13576, "##ⓘ": 13577, "##─": 11473, "##━": 13578, "##│": 11958, "##┃": 13579, "##┅": 13312, "##┆": 13580, "##┊": 13581, "##┌": 13582, "##└": 13583, "##├": 13584, "##┣": 13585, "##═": 13586, "##║": 13587, "##╚": 13588, "##╞": 13589, "##╠": 13590, "##╭": 13591, "##╮": 13592, "##╯": 13593, "##╰": 13594, "##╱": 13595, "##╳": 13596, "##▂": 13597, "##▃": 13598, "##▅": 13599, "##▇": 13600, "##█": 12740, "##▉": 13601, "##▋": 13602, "##▌": 13603, "##▍": 13604, "##▎": 13605, "##■": 10819, "##□": 13606, "##▪": 13607, "##▫": 13608, "##▬": 13609, "##▲": 9887, "##△": 13610, "##▶": 13611, "##►": 13612, "##▼": 10264, "##▽": 13613, "##◆": 10497, "##◆◆": 13019, "##◇": 13614, "##○": 10299, "##◎": 11375, "##●": 9037, "##◕": 13615, "##◠": 13616, "##◢": 13617, "##◤": 13618, "##☀": 13619, "##★": 8664, "##☆": 8994, "##☕": 13620, "##☞": 13621, "##☺": 13622, "##☼": 13623, "##♀": 13624, "##♂": 13625, "##♠": 13626, "##♡": 13627, "##♣": 13628, "##♥": 9177, "##♦": 13629, "##♪": 9458, "##♫": 13630, "##♬": 13631, "##✈": 13632, "##✔": 13633, "##✕": 13634, "##✖": 13635, "##✦": 13636, "##✨": 13637, "##✪": 13638, "##✰": 13639, "##✿": 13640, "##❀": 13641, "##❤": 10269, "##➜": 13642, "##➤": 13643, "##⦿": 13644, "##、": 13645, "##。": 13646, "##〃": 13647, "##々": 13648, "##〇": 13649, "##〈": 13650, "##〉": 13651, "##《": 13652, "##》": 13653, "##「": 13654, "##」": 13655, "##『": 13656, "##』": 13657, "##【": 13658, "##】": 13659, "##〓": 13660, "##〔": 13661, "##〕": 13662, "##〖": 13663, "##〗": 13664, "##〜": 13665, "##〝": 13666, "##〞": 13667, "##ぁ": 12661, "##あ": 12146, "##あなたに": 12774, "##あり": 9362, "##あります": 10700, "##ありません": 10769, "##ある": 9762, "##ぃ": 13668, "##い": 8524, "##いい": 12993, "##いた": 10526, "##いて": 10042, "##いました": 11350, "##います": 9184, "##いる": 9317, "##いるのて": 11443, "##う": 8981, "##ぇ": 13669, "##え": 11661, "##お": 8345, "##おり": 11438, "##おります": 9797, "##か": 8261, "##かあります": 12145, "##かった": 11299, "##かな": 13081, "##かも": 12984, "##から": 8825, "##かり": 11554, "##かる": 11571, "##き": 8816, "##きた": 12775, "##きました": 12055, "##きます": 12506, "##く": 8763, "##くたさい": 9175, "##くれる": 11241, "##け": 9525, "##けて": 12214, "##けと": 10095, "##ける": 11760, "##こ": 8557, "##こさいます": 10286, "##こと": 11127, "##ことか": 10274, "##ことかてきます": 13064, "##ことて": 11178, "##ことを": 12236, "##この": 11087, "##さ": 11647, "##さん": 10874, "##し": 8733, "##しい": 10899, "##した": 9442, "##して": 9379, "##しています": 12478, "##します": 9294, "##す": 8764, "##すか": 11805, "##する": 9840, "##せ": 10452, "##そ": 10778, "##その": 10372, "##た": 8856, "##たい": 10722, "##たけて": 12928, "##ため": 10312, "##ために": 12260, "##ち": 9967, "##ちの": 12712, "##ちは": 12951, "##ちゃん": 12875, "##っ": 12934, "##った": 9190, "##って": 9067, "##っています": 11822, "##っと": 10475, "##つ": 9775, "##て": 8312, "##てお": 12878, "##てきます": 11088, "##てきる": 11415, "##てす": 8504, "##てすか": 11278, "##ての": 12852, "##ては": 9809, "##ても": 10508, "##と": 8322, "##という": 12383, "##とう": 12471, "##とても": 13211, "##との": 13066, "##とは": 11896, "##な": 8730, "##ない": 8560, "##なから": 11943, "##なく": 10395, "##なたの": 11002, "##なった": 12102, "##なと": 11710, "##なら": 10145, "##なり": 11592, "##なりました": 12533, "##なります": 11293, "##なる": 11666, "##に": 8294, "##にお": 12337, "##には": 10410, "##ぬ": 13670, "##ね": 8900, "##の": 8227, "##のお": 10217, "##のか": 9584, "##のて": 8618, "##のてす": 12385, "##のてすか": 13221, "##のに": 12813, "##のは": 10093, "##は": 8319, "##ひ": 11224, "##ふ": 13671, "##へ": 11320, "##へて": 12864, "##ほ": 13672, "##ま": 9774, "##ました": 8861, "##ましょう": 10759, "##ます": 8643, "##ますのて": 13071, "##ません": 9035, "##ませんか": 9862, "##また": 13150, "##まて": 10737, "##み": 9344, "##みませんか": 11775, "##む": 13673, "##め": 10063, "##めて": 12274, "##も": 8435, "##ゃ": 13674, "##や": 9164, "##やり": 11077, "##ゅ": 13675, "##ゆ": 13676, "##ょ": 13677, "##ょう": 11663, "##よ": 9427, "##よう": 10177, "##ような": 10895, "##ように": 10847, "##よって": 12957, "##より": 10190, "##ら": 8732, "##り": 8506, "##りの": 12407, "##ります": 11395, "##る": 8481, "##れ": 9223, "##れた": 10679, "##れて": 12034, "##れている": 11856, "##れは": 9170, "##れます": 11745, "##れる": 10273, "##ろ": 10460, "##ろう": 12792, "##わ": 11940, "##を": 8292, "##をお": 11236, "##をこ": 12335, "##ん": 8814, "##んて": 12098, "##んな": 10386, "##゜": 13678, "##ゝ": 13679, "##ァ": 13680, "##ア": 9788, "##ィ": 12403, "##イ": 9509, "##イス": 13203, "##イト": 10516, "##イフ": 12692, "##イン": 10108, "##ゥ": 13681, "##ウ": 12891, "##ェ": 12690, "##エ": 13682, "##ォ": 13683, "##オ": 11238, "##カ": 9770, "##カー": 10175, "##キ": 10781, "##キンク": 11505, "##ク": 9625, "##クok": 13040, "##クセス": 13311, "##ケ": 13684, "##コ": 10155, "##コメント": 13301, "##サ": 13685, "##サイト": 11618, "##サー": 12636, "##シ": 10472, "##シャンルの": 11947, "##ション": 10798, "##ス": 8551, "##スト": 10579, "##セ": 13686, "##ソ": 13687, "##タ": 11011, "##ター": 10848, "##チ": 10202, "##ッ": 13688, "##ック": 9244, "##ッセーシを": 11231, "##ット": 9187, "##ッフ": 10023, "##ツ": 10419, "##テ": 11903, "##ティー": 12841, "##テル": 12181, "##ト": 8807, "##ナ": 10714, "##ナー": 12005, "##ニ": 13689, "##ニア": 12650, "##ヌ": 13690, "##ネ": 13691, "##ノ": 13692, "##ハ": 12838, "##ハー": 10977, "##ヒ": 10374, "##フ": 9383, "##フト": 10868, "##ヘ": 13693, "##ホ": 12889, "##マ": 9760, "##ミ": 10688, "##ム": 9227, "##メ": 10597, "##モ": 13694, "##ャ": 13695, "##ヤ": 13696, "##ュ": 13697, "##ュー": 12778, "##ユ": 13698, "##ョ": 13699, "##ヨ": 13700, "##ラ": 9210, "##ラン": 12048, "##リ": 9754, "##リア": 11989, "##リー": 10535, "##ル": 8492, "##ルハイト": 13304, "##ルフ": 12968, "##レ": 10416, "##レス": 12696, "##ロ": 10068, "##ロク": 11416, "##ワ": 13701, "##ヲ": 13702, "##ン": 8489, "##ンク": 9262, "##ンス": 12090, "##ンター": 11223, "##ント": 10002, "##ヶ": 10569, "##・": 13703, "##ー": 8568, "##ーク": 12952, "##ーシ": 10568, "##ーシてす": 12583, "##ーション": 12301, "##ース": 10840, "##ータ": 12219, "##ート": 9006, "##ーム": 9975, "##ール": 9424, "##ールを": 10994, "##ーン": 12966, "##ヽ": 13704, "##ㄅ": 13705, "##ㄆ": 13706, "##ㄇ": 13707, "##ㄉ": 13708, "##ㄋ": 13709, "##ㄌ": 13710, "##ㄍ": 13711, "##ㄎ": 13712, "##ㄏ": 13713, "##ㄒ": 13714, "##ㄚ": 13715, "##ㄛ": 13716, "##ㄞ": 13717, "##ㄟ": 13718, "##ㄢ": 13719, "##ㄤ": 13720, "##ㄥ": 13721, "##ㄧ": 13722, "##ㄨ": 13723, "##ㆍ": 13724, "##㈦": 13725, "##㊣": 13726, "##㎡": 9236, "##㗎": 13727, "##一": 13728, "##丁": 13729, "##七": 13730, "##万": 13731, "##丈": 13732, "##三": 13733, "##上": 13734, "##下": 13735, "##不": 13736, "##与": 13737, "##丐": 13738, "##丑": 13739, "##专": 13740, "##且": 13741, "##丕": 13742, "##世": 13743, "##丘": 13744, "##丙": 13745, "##业": 13746, "##丛": 13747, "##东": 13748, "##丝": 13749, "##丞": 13750, "##丟": 13751, "##両": 13752, "##丢": 13753, "##两": 13754, "##严": 13755, "##並": 13756, "##丧": 13757, "##丨": 13758, "##个": 13759, "##丫": 13760, "##中": 13761, "##丰": 13762, "##串": 13763, "##临": 13764, "##丶": 13765, "##丸": 13766, "##丹": 13767, "##为": 13768, "##主": 13769, "##丼": 13770, "##丽": 13771, "##举": 13772, "##丿": 13773, "##乂": 13774, "##乃": 13775, "##久": 13776, "##么": 13777, "##义": 13778, "##之": 13779, "##乌": 13780, "##乍": 13781, "##乎": 13782, "##乏": 13783, "##乐": 13784, "##乒": 13785, "##乓": 13786, "##乔": 13787, "##乖": 13788, "##乗": 13789, "##乘": 13790, "##乙": 13791, "##乜": 13792, "##九": 13793, "##乞": 13794, "##也": 13795, "##习": 13796, "##乡": 13797, "##书": 13798, "##乩": 13799, "##买": 13800, "##乱": 13801, "##乳": 13802, "##乾": 13803, "##亀": 13804, "##亂": 13805, "##了": 13806, "##予": 13807, "##争": 13808, "##事": 13809, "##二": 13810, "##于": 13811, "##亏": 13812, "##云": 13813, "##互": 13814, "##五": 13815, "##井": 13816, "##亘": 13817, "##亙": 13818, "##亚": 13819, "##些": 13820, "##亜": 13821, "##亞": 13822, "##亟": 13823, "##亡": 13824, "##亢": 13825, "##交": 13826, "##亥": 13827, "##亦": 13828, "##产": 13829, "##亨": 13830, "##亩": 13831, "##享": 13832, "##京": 13833, "##亭": 13834, "##亮": 13835, "##亲": 13836, "##亳": 13837, "##亵": 13838, "##人": 13839, "##亿": 13840, "##什": 13841, "##仁": 13842, "##仃": 13843, "##仄": 13844, "##仅": 13845, "##仆": 13846, "##仇": 13847, "##今": 13848, "##介": 13849, "##仍": 13850, "##从": 13851, "##仏": 13852, "##仑": 13853, "##仓": 13854, "##仔": 13855, "##仕": 13856, "##他": 13857, "##仗": 13858, "##付": 13859, "##仙": 13860, "##仝": 13861, "##仞": 13862, "##仟": 13863, "##代": 13864, "##令": 13865, "##以": 13866, "##仨": 13867, "##仪": 13868, "##们": 13869, "##仮": 13870, "##仰": 13871, "##仲": 13872, "##件": 13873, "##价": 13874, "##任": 13875, "##份": 13876, "##仿": 13877, "##企": 13878, "##伉": 13879, "##伊": 13880, "##伍": 13881, "##伎": 13882, "##伏": 13883, "##伐": 13884, "##休": 13885, "##伕": 13886, "##众": 13887, "##优": 13888, "##伙": 13889, "##会": 13890, "##伝": 13891, "##伞": 13892, "##伟": 13893, "##传": 13894, "##伢": 13895, "##伤": 13896, "##伦": 13897, "##伪": 13898, "##伫": 13899, "##伯": 13900, "##估": 13901, "##伴": 13902, "##伶": 13903, "##伸": 13904, "##伺": 13905, "##似": 13906, "##伽": 13907, "##佃": 13908, "##但": 13909, "##佇": 13910, "##佈": 13911, "##位": 13912, "##低": 13913, "##住": 13914, "##佐": 13915, "##佑": 13916, "##体": 13917, "##佔": 13918, "##何": 13919, "##佗": 13920, "##佘": 13921, "##余": 13922, "##佚": 13923, "##佛": 13924, "##作": 13925, "##佝": 13926, "##佞": 13927, "##佟": 13928, "##你": 13929, "##佢": 13930, "##佣": 13931, "##佤": 13932, "##佥": 13933, "##佩": 13934, "##佬": 13935, "##佯": 13936, "##佰": 13937, "##佳": 13938, "##併": 13939, "##佶": 13940, "##佻": 13941, "##佼": 13942, "##使": 13943, "##侃": 13944, "##侄": 13945, "##來": 13946, "##侈": 13947, "##例": 13948, "##侍": 13949, "##侏": 13950, "##侑": 13951, "##侖": 13952, "##侗": 13953, "##供": 13954, "##依": 13955, "##侠": 13956, "##価": 13957, "##侣": 13958, "##侥": 13959, "##侦": 13960, "##侧": 13961, "##侨": 13962, "##侬": 13963, "##侮": 13964, "##侯": 13965, "##侵": 13966, "##侶": 13967, "##侷": 13968, "##便": 13969, "##係": 13970, "##促": 13971, "##俄": 13972, "##俊": 13973, "##俎": 13974, "##俏": 13975, "##俐": 13976, "##俑": 13977, "##俗": 13978, "##俘": 13979, "##俚": 13980, "##保": 13981, "##俞": 13982, "##俟": 13983, "##俠": 13984, "##信": 13985, "##俨": 13986, "##俩": 13987, "##俪": 13988, "##俬": 13989, "##俭": 13990, "##修": 13991, "##俯": 13992, "##俱": 13993, "##俳": 13994, "##俸": 13995, "##俺": 13996, "##俾": 13997, "##倆": 13998, "##倉": 13999, "##個": 14000, "##倌": 14001, "##倍": 14002, "##倏": 14003, "##們": 14004, "##倒": 14005, "##倔": 14006, "##倖": 14007, "##倘": 14008, "##候": 14009, "##倚": 14010, "##倜": 14011, "##借": 14012, "##倡": 14013, "##値": 14014, "##倦": 14015, "##倩": 14016, "##倪": 14017, "##倫": 14018, "##倬": 14019, "##倭": 14020, "##倶": 14021, "##债": 14022, "##值": 14023, "##倾": 14024, "##偃": 14025, "##假": 14026, "##偈": 14027, "##偉": 14028, "##偌": 14029, "##偎": 14030, "##偏": 14031, "##偕": 14032, "##做": 14033, "##停": 14034, "##健": 14035, "##側": 14036, "##偵": 14037, "##偶": 14038, "##偷": 14039, "##偻": 14040, "##偽": 14041, "##偿": 14042, "##傀": 14043, "##傅": 14044, "##傍": 14045, "##傑": 14046, "##傘": 14047, "##備": 14048, "##傚": 14049, "##傢": 14050, "##傣": 14051, "##傥": 14052, "##储": 14053, "##傩": 14054, "##催": 14055, "##傭": 14056, "##傲": 14057, "##傳": 14058, "##債": 14059, "##傷": 14060, "##傻": 14061, "##傾": 14062, "##僅": 14063, "##働": 14064, "##像": 14065, "##僑": 14066, "##僕": 14067, "##僖": 14068, "##僚": 14069, "##僥": 14070, "##僧": 14071, "##僭": 14072, "##僮": 14073, "##僱": 14074, "##僵": 14075, "##價": 14076, "##僻": 14077, "##儀": 14078, "##儂": 14079, "##億": 14080, "##儆": 14081, "##儉": 14082, "##儋": 14083, "##儒": 14084, "##儕": 14085, "##儘": 14086, "##償": 14087, "##儡": 14088, "##優": 14089, "##儲": 14090, "##儷": 14091, "##儼": 14092, "##儿": 14093, "##兀": 14094, "##允": 14095, "##元": 14096, "##兄": 14097, "##充": 14098, "##兆": 14099, "##兇": 14100, "##先": 14101, "##光": 14102, "##克": 14103, "##兌": 14104, "##免": 14105, "##児": 14106, "##兑": 14107, "##兒": 14108, "##兔": 14109, "##兖": 14110, "##党": 14111, "##兜": 14112, "##兢": 14113, "##入": 14114, "##內": 14115, "##全": 14116, "##兩": 14117, "##八": 14118, "##公": 14119, "##六": 14120, "##兮": 14121, "##兰": 14122, "##共": 14123, "##兲": 14124, "##关": 14125, "##兴": 14126, "##兵": 14127, "##其": 14128, "##具": 14129, "##典": 14130, "##兹": 14131, "##养": 14132, "##兼": 14133, "##兽": 14134, "##冀": 14135, "##内": 14136, "##円": 14137, "##冇": 14138, "##冈": 14139, "##冉": 14140, "##冊": 14141, "##册": 14142, "##再": 14143, "##冏": 14144, "##冒": 14145, "##冕": 14146, "##冗": 14147, "##写": 14148, "##军": 14149, "##农": 14150, "##冠": 14151, "##冢": 14152, "##冤": 14153, "##冥": 14154, "##冨": 14155, "##冪": 14156, "##冬": 14157, "##冯": 14158, "##冰": 14159, "##冲": 14160, "##决": 14161, "##况": 14162, "##冶": 14163, "##冷": 14164, "##冻": 14165, "##冼": 14166, "##冽": 14167, "##冾": 14168, "##净": 14169, "##凄": 14170, "##准": 14171, "##凇": 14172, "##凈": 14173, "##凉": 14174, "##凋": 14175, "##凌": 14176, "##凍": 14177, "##减": 14178, "##凑": 14179, "##凛": 14180, "##凜": 14181, "##凝": 14182, "##几": 14183, "##凡": 14184, "##凤": 14185, "##処": 14186, "##凪": 14187, "##凭": 14188, "##凯": 14189, "##凰": 14190, "##凱": 14191, "##凳": 14192, "##凶": 14193, "##凸": 14194, "##凹": 14195, "##出": 14196, "##击": 14197, "##函": 14198, "##凿": 14199, "##刀": 14200, "##刁": 14201, "##刃": 14202, "##分": 14203, "##切": 14204, "##刈": 14205, "##刊": 14206, "##刍": 14207, "##刎": 14208, "##刑": 14209, "##划": 14210, "##列": 14211, "##刘": 14212, "##则": 14213, "##刚": 14214, "##创": 14215, "##初": 14216, "##删": 14217, "##判": 14218, "##別": 14219, "##刨": 14220, "##利": 14221, "##刪": 14222, "##别": 14223, "##刮": 14224, "##到": 14225, "##制": 14226, "##刷": 14227, "##券": 14228, "##刹": 14229, "##刺": 14230, "##刻": 14231, "##刽": 14232, "##剁": 14233, "##剂": 14234, "##剃": 14235, "##則": 14236, "##剉": 14237, "##削": 14238, "##剋": 14239, "##剌": 14240, "##前": 14241, "##剎": 14242, "##剐": 14243, "##剑": 14244, "##剔": 14245, "##剖": 14246, "##剛": 14247, "##剜": 14248, "##剝": 14249, "##剣": 14250, "##剤": 14251, "##剥": 14252, "##剧": 14253, "##剩": 14254, "##剪": 14255, "##副": 14256, "##割": 14257, "##創": 14258, "##剷": 14259, "##剽": 14260, "##剿": 14261, "##劃": 14262, "##劇": 14263, "##劈": 14264, "##劉": 14265, "##劊": 14266, "##劍": 14267, "##劏": 14268, "##劑": 14269, "##力": 14270, "##劝": 14271, "##办": 14272, "##功": 14273, "##加": 14274, "##务": 14275, "##劣": 14276, "##动": 14277, "##助": 14278, "##努": 14279, "##劫": 14280, "##劭": 14281, "##励": 14282, "##劲": 14283, "##劳": 14284, "##労": 14285, "##劵": 14286, "##効": 14287, "##劾": 14288, "##势": 14289, "##勁": 14290, "##勃": 14291, "##勇": 14292, "##勉": 14293, "##勋": 14294, "##勐": 14295, "##勒": 14296, "##動": 14297, "##勖": 14298, "##勘": 14299, "##務": 14300, "##勛": 14301, "##勝": 14302, "##勞": 14303, "##募": 14304, "##勢": 14305, "##勤": 14306, "##勧": 14307, "##勳": 14308, "##勵": 14309, "##勸": 14310, "##勺": 14311, "##勻": 14312, "##勾": 14313, "##勿": 14314, "##匀": 14315, "##包": 14316, "##匆": 14317, "##匈": 14318, "##匍": 14319, "##匐": 14320, "##匕": 14321, "##化": 14322, "##北": 14323, "##匙": 14324, "##匝": 14325, "##匠": 14326, "##匡": 14327, "##匣": 14328, "##匪": 14329, "##匮": 14330, "##匯": 14331, "##匱": 14332, "##匹": 14333, "##区": 14334, "##医": 14335, "##匾": 14336, "##匿": 14337, "##區": 14338, "##十": 14339, "##千": 14340, "##卅": 14341, "##升": 14342, "##午": 14343, "##卉": 14344, "##半": 14345, "##卍": 14346, "##华": 14347, "##协": 14348, "##卑": 14349, "##卒": 14350, "##卓": 14351, "##協": 14352, "##单": 14353, "##卖": 14354, "##南": 14355, "##単": 14356, "##博": 14357, "##卜": 14358, "##卞": 14359, "##卟": 14360, "##占": 14361, "##卡": 14362, "##卢": 14363, "##卤": 14364, "##卦": 14365, "##卧": 14366, "##卫": 14367, "##卮": 14368, "##卯": 14369, "##印": 14370, "##危": 14371, "##即": 14372, "##却": 14373, "##卵": 14374, "##卷": 14375, "##卸": 14376, "##卻": 14377, "##卿": 14378, "##厂": 14379, "##厄": 14380, "##厅": 14381, "##历": 14382, "##厉": 14383, "##压": 14384, "##厌": 14385, "##厕": 14386, "##厘": 14387, "##厚": 14388, "##厝": 14389, "##原": 14390, "##厢": 14391, "##厥": 14392, "##厦": 14393, "##厨": 14394, "##厩": 14395, "##厭": 14396, "##厮": 14397, "##厲": 14398, "##厳": 14399, "##去": 14400, "##县": 14401, "##叁": 14402, "##参": 14403, "##參": 14404, "##又": 14405, "##叉": 14406, "##及": 14407, "##友": 14408, "##双": 14409, "##反": 14410, "##収": 14411, "##发": 14412, "##叔": 14413, "##取": 14414, "##受": 14415, "##变": 14416, "##叙": 14417, "##叛": 14418, "##叟": 14419, "##叠": 14420, "##叡": 14421, "##叢": 14422, "##口": 14423, "##古": 14424, "##句": 14425, "##另": 14426, "##叨": 14427, "##叩": 14428, "##只": 14429, "##叫": 14430, "##召": 14431, "##叭": 14432, "##叮": 14433, "##可": 14434, "##台": 14435, "##叱": 14436, "##史": 14437, "##右": 14438, "##叵": 14439, "##叶": 14440, "##号": 14441, "##司": 14442, "##叹": 14443, "##叻": 14444, "##叼": 14445, "##叽": 14446, "##吁": 14447, "##吃": 14448, "##各": 14449, "##吆": 14450, "##合": 14451, "##吉": 14452, "##吊": 14453, "##吋": 14454, "##同": 14455, "##名": 14456, "##后": 14457, "##吏": 14458, "##吐": 14459, "##向": 14460, "##吒": 14461, "##吓": 14462, "##吕": 14463, "##吖": 14464, "##吗": 14465, "##君": 14466, "##吝": 14467, "##吞": 14468, "##吟": 14469, "##吠": 14470, "##吡": 14471, "##否": 14472, "##吧": 14473, "##吨": 14474, "##吩": 14475, "##含": 14476, "##听": 14477, "##吭": 14478, "##吮": 14479, "##启": 14480, "##吱": 14481, "##吳": 14482, "##吴": 14483, "##吵": 14484, "##吶": 14485, "##吸": 14486, "##吹": 14487, "##吻": 14488, "##吼": 14489, "##吽": 14490, "##吾": 14491, "##呀": 14492, "##呂": 14493, "##呃": 14494, "##呆": 14495, "##呈": 14496, "##告": 14497, "##呋": 14498, "##呎": 14499, "##呐": 14500, "##呓": 14501, "##呕": 14502, "##呗": 14503, "##员": 14504, "##呛": 14505, "##呜": 14506, "##呢": 14507, "##呤": 14508, "##呦": 14509, "##周": 14510, "##呱": 14511, "##呲": 14512, "##味": 14513, "##呵": 14514, "##呷": 14515, "##呸": 14516, "##呻": 14517, "##呼": 14518, "##命": 14519, "##咀": 14520, "##咁": 14521, "##咂": 14522, "##咄": 14523, "##咆": 14524, "##咋": 14525, "##和": 14526, "##咎": 14527, "##咏": 14528, "##咐": 14529, "##咒": 14530, "##咔": 14531, "##咕": 14532, "##咖": 14533, "##咗": 14534, "##咘": 14535, "##咙": 14536, "##咚": 14537, "##咛": 14538, "##咣": 14539, "##咤": 14540, "##咦": 14541, "##咧": 14542, "##咨": 14543, "##咩": 14544, "##咪": 14545, "##咫": 14546, "##咬": 14547, "##咭": 14548, "##咯": 14549, "##咱": 14550, "##咲": 14551, "##咳": 14552, "##咸": 14553, "##咻": 14554, "##咽": 14555, "##咿": 14556, "##哀": 14557, "##品": 14558, "##哂": 14559, "##哄": 14560, "##哆": 14561, "##哇": 14562, "##哈": 14563, "##哉": 14564, "##哋": 14565, "##哌": 14566, "##响": 14567, "##哎": 14568, "##哏": 14569, "##哐": 14570, "##哑": 14571, "##哒": 14572, "##哔": 14573, "##哗": 14574, "##哟": 14575, "##員": 14576, "##哥": 14577, "##哦": 14578, "##哧": 14579, "##哨": 14580, "##哩": 14581, "##哪": 14582, "##哭": 14583, "##哮": 14584, "##哲": 14585, "##哺": 14586, "##哼": 14587, "##哽": 14588, "##唁": 14589, "##唄": 14590, "##唆": 14591, "##唇": 14592, "##唉": 14593, "##唏": 14594, "##唐": 14595, "##唑": 14596, "##唔": 14597, "##唠": 14598, "##唤": 14599, "##唧": 14600, "##唬": 14601, "##售": 14602, "##唯": 14603, "##唰": 14604, "##唱": 14605, "##唳": 14606, "##唷": 14607, "##唸": 14608, "##唾": 14609, "##啃": 14610, "##啄": 14611, "##商": 14612, "##啉": 14613, "##啊": 14614, "##問": 14615, "##啓": 14616, "##啕": 14617, "##啖": 14618, "##啜": 14619, "##啞": 14620, "##啟": 14621, "##啡": 14622, "##啤": 14623, "##啥": 14624, "##啦": 14625, "##啧": 14626, "##啪": 14627, "##啫": 14628, "##啬": 14629, "##啮": 14630, "##啰": 14631, "##啱": 14632, "##啲": 14633, "##啵": 14634, "##啶": 14635, "##啷": 14636, "##啸": 14637, "##啻": 14638, "##啼": 14639, "##啾": 14640, "##喀": 14641, "##喂": 14642, "##喃": 14643, "##善": 14644, "##喆": 14645, "##喇": 14646, "##喉": 14647, "##喊": 14648, "##喋": 14649, "##喎": 14650, "##喏": 14651, "##喔": 14652, "##喘": 14653, "##喙": 14654, "##喚": 14655, "##喜": 14656, "##喝": 14657, "##喟": 14658, "##喧": 14659, "##喪": 14660, "##喫": 14661, "##喬": 14662, "##單": 14663, "##喰": 14664, "##喱": 14665, "##喲": 14666, "##喳": 14667, "##喵": 14668, "##営": 14669, "##喷": 14670, "##喹": 14671, "##喺": 14672, "##喻": 14673, "##喽": 14674, "##嗅": 14675, "##嗆": 14676, "##嗇": 14677, "##嗎": 14678, "##嗑": 14679, "##嗒": 14680, "##嗓": 14681, "##嗔": 14682, "##嗖": 14683, "##嗚": 14684, "##嗜": 14685, "##嗝": 14686, "##嗟": 14687, "##嗡": 14688, "##嗣": 14689, "##嗤": 14690, "##嗦": 14691, "##嗨": 14692, "##嗪": 14693, "##嗬": 14694, "##嗯": 14695, "##嗰": 14696, "##嗲": 14697, "##嗳": 14698, "##嗶": 14699, "##嗷": 14700, "##嗽": 14701, "##嘀": 14702, "##嘅": 14703, "##嘆": 14704, "##嘈": 14705, "##嘉": 14706, "##嘌": 14707, "##嘍": 14708, "##嘎": 14709, "##嘔": 14710, "##嘖": 14711, "##嘗": 14712, "##嘘": 14713, "##嘚": 14714, "##嘛": 14715, "##嘜": 14716, "##嘞": 14717, "##嘟": 14718, "##嘢": 14719, "##嘣": 14720, "##嘤": 14721, "##嘧": 14722, "##嘩": 14723, "##嘭": 14724, "##嘮": 14725, "##嘯": 14726, "##嘰": 14727, "##嘱": 14728, "##嘲": 14729, "##嘴": 14730, "##嘶": 14731, "##嘸": 14732, "##嘹": 14733, "##嘻": 14734, "##嘿": 14735, "##噁": 14736, "##噌": 14737, "##噎": 14738, "##噓": 14739, "##噔": 14740, "##噗": 14741, "##噙": 14742, "##噜": 14743, "##噠": 14744, "##噢": 14745, "##噤": 14746, "##器": 14747, "##噩": 14748, "##噪": 14749, "##噬": 14750, "##噱": 14751, "##噴": 14752, "##噶": 14753, "##噸": 14754, "##噹": 14755, "##噻": 14756, "##噼": 14757, "##嚀": 14758, "##嚇": 14759, "##嚎": 14760, "##嚏": 14761, "##嚐": 14762, "##嚓": 14763, "##嚕": 14764, "##嚟": 14765, "##嚣": 14766, "##嚥": 14767, "##嚨": 14768, "##嚮": 14769, "##嚴": 14770, "##嚷": 14771, "##嚼": 14772, "##囂": 14773, "##囉": 14774, "##囊": 14775, "##囍": 14776, "##囑": 14777, "##囔": 14778, "##囗": 14779, "##囚": 14780, "##四": 14781, "##囝": 14782, "##回": 14783, "##囟": 14784, "##因": 14785, "##囡": 14786, "##团": 14787, "##団": 14788, "##囤": 14789, "##囧": 14790, "##囪": 14791, "##囫": 14792, "##园": 14793, "##困": 14794, "##囱": 14795, "##囲": 14796, "##図": 14797, "##围": 14798, "##囹": 14799, "##固": 14800, "##国": 14801, "##图": 14802, "##囿": 14803, "##圃": 14804, "##圄": 14805, "##圆": 14806, "##圈": 14807, "##國": 14808, "##圍": 14809, "##圏": 14810, "##園": 14811, "##圓": 14812, "##圖": 14813, "##團": 14814, "##圜": 14815, "##土": 14816, "##圣": 14817, "##圧": 14818, "##在": 14819, "##圩": 14820, "##圭": 14821, "##地": 14822, "##圳": 14823, "##场": 14824, "##圻": 14825, "##圾": 14826, "##址": 14827, "##坂": 14828, "##均": 14829, "##坊": 14830, "##坍": 14831, "##坎": 14832, "##坏": 14833, "##坐": 14834, "##坑": 14835, "##块": 14836, "##坚": 14837, "##坛": 14838, "##坝": 14839, "##坞": 14840, "##坟": 14841, "##坠": 14842, "##坡": 14843, "##坤": 14844, "##坦": 14845, "##坨": 14846, "##坪": 14847, "##坯": 14848, "##坳": 14849, "##坵": 14850, "##坷": 14851, "##垂": 14852, "##垃": 14853, "##垄": 14854, "##型": 14855, "##垒": 14856, "##垚": 14857, "##垛": 14858, "##垠": 14859, "##垢": 14860, "##垣": 14861, "##垦": 14862, "##垩": 14863, "##垫": 14864, "##垭": 14865, "##垮": 14866, "##垵": 14867, "##埂": 14868, "##埃": 14869, "##埋": 14870, "##城": 14871, "##埔": 14872, "##埕": 14873, "##埗": 14874, "##域": 14875, "##埠": 14876, "##埤": 14877, "##埵": 14878, "##執": 14879, "##埸": 14880, "##培": 14881, "##基": 14882, "##埼": 14883, "##堀": 14884, "##堂": 14885, "##堃": 14886, "##堅": 14887, "##堆": 14888, "##堇": 14889, "##堑": 14890, "##堕": 14891, "##堙": 14892, "##堡": 14893, "##堤": 14894, "##堪": 14895, "##堯": 14896, "##堰": 14897, "##報": 14898, "##場": 14899, "##堵": 14900, "##堺": 14901, "##堿": 14902, "##塊": 14903, "##塌": 14904, "##塑": 14905, "##塔": 14906, "##塗": 14907, "##塘": 14908, "##塚": 14909, "##塞": 14910, "##塢": 14911, "##塩": 14912, "##填": 14913, "##塬": 14914, "##塭": 14915, "##塵": 14916, "##塾": 14917, "##墀": 14918, "##境": 14919, "##墅": 14920, "##墉": 14921, "##墊": 14922, "##墒": 14923, "##墓": 14924, "##増": 14925, "##墘": 14926, "##墙": 14927, "##墜": 14928, "##增": 14929, "##墟": 14930, "##墨": 14931, "##墩": 14932, "##墮": 14933, "##墳": 14934, "##墻": 14935, "##墾": 14936, "##壁": 14937, "##壅": 14938, "##壆": 14939, "##壇": 14940, "##壊": 14941, "##壑": 14942, "##壓": 14943, "##壕": 14944, "##壘": 14945, "##壞": 14946, "##壟": 14947, "##壢": 14948, "##壤": 14949, "##壩": 14950, "##士": 14951, "##壬": 14952, "##壮": 14953, "##壯": 14954, "##声": 14955, "##売": 14956, "##壳": 14957, "##壶": 14958, "##壹": 14959, "##壺": 14960, "##壽": 14961, "##处": 14962, "##备": 14963, "##変": 14964, "##复": 14965, "##夏": 14966, "##夔": 14967, "##夕": 14968, "##外": 14969, "##夙": 14970, "##多": 14971, "##夜": 14972, "##够": 14973, "##夠": 14974, "##夢": 14975, "##夥": 14976, "##大": 14977, "##天": 14978, "##太": 14979, "##夫": 14980, "##夭": 14981, "##央": 14982, "##夯": 14983, "##失": 14984, "##头": 14985, "##夷": 14986, "##夸": 14987, "##夹": 14988, "##夺": 14989, "##夾": 14990, "##奂": 14991, "##奄": 14992, "##奇": 14993, "##奈": 14994, "##奉": 14995, "##奋": 14996, "##奎": 14997, "##奏": 14998, "##奐": 14999, "##契": 15000, "##奔": 15001, "##奕": 15002, "##奖": 15003, "##套": 15004, "##奘": 15005, "##奚": 15006, "##奠": 15007, "##奢": 15008, "##奥": 15009, "##奧": 15010, "##奪": 15011, "##奬": 15012, "##奮": 15013, "##女": 15014, "##奴": 15015, "##奶": 15016, "##奸": 15017, "##她": 15018, "##好": 15019, "##如": 15020, "##妃": 15021, "##妄": 15022, "##妆": 15023, "##妇": 15024, "##妈": 15025, "##妊": 15026, "##妍": 15027, "##妒": 15028, "##妓": 15029, "##妖": 15030, "##妘": 15031, "##妙": 15032, "##妝": 15033, "##妞": 15034, "##妣": 15035, "##妤": 15036, "##妥": 15037, "##妨": 15038, "##妩": 15039, "##妪": 15040, "##妮": 15041, "##妲": 15042, "##妳": 15043, "##妹": 15044, "##妻": 15045, "##妾": 15046, "##姆": 15047, "##姉": 15048, "##姊": 15049, "##始": 15050, "##姍": 15051, "##姐": 15052, "##姑": 15053, "##姒": 15054, "##姓": 15055, "##委": 15056, "##姗": 15057, "##姚": 15058, "##姜": 15059, "##姝": 15060, "##姣": 15061, "##姥": 15062, "##姦": 15063, "##姨": 15064, "##姪": 15065, "##姫": 15066, "##姬": 15067, "##姹": 15068, "##姻": 15069, "##姿": 15070, "##威": 15071, "##娃": 15072, "##娄": 15073, "##娅": 15074, "##娆": 15075, "##娇": 15076, "##娉": 15077, "##娑": 15078, "##娓": 15079, "##娘": 15080, "##娛": 15081, "##娜": 15082, "##娟": 15083, "##娠": 15084, "##娣": 15085, "##娥": 15086, "##娩": 15087, "##娱": 15088, "##娲": 15089, "##娴": 15090, "##娶": 15091, "##娼": 15092, "##婀": 15093, "##婁": 15094, "##婆": 15095, "##婉": 15096, "##婊": 15097, "##婕": 15098, "##婚": 15099, "##婢": 15100, "##婦": 15101, "##婧": 15102, "##婪": 15103, "##婭": 15104, "##婴": 15105, "##婵": 15106, "##婶": 15107, "##婷": 15108, "##婺": 15109, "##婿": 15110, "##媒": 15111, "##媚": 15112, "##媛": 15113, "##媞": 15114, "##媧": 15115, "##媲": 15116, "##媳": 15117, "##媽": 15118, "##媾": 15119, "##嫁": 15120, "##嫂": 15121, "##嫉": 15122, "##嫌": 15123, "##嫑": 15124, "##嫔": 15125, "##嫖": 15126, "##嫘": 15127, "##嫚": 15128, "##嫡": 15129, "##嫣": 15130, "##嫦": 15131, "##嫩": 15132, "##嫲": 15133, "##嫵": 15134, "##嫻": 15135, "##嬅": 15136, "##嬉": 15137, "##嬌": 15138, "##嬗": 15139, "##嬛": 15140, "##嬢": 15141, "##嬤": 15142, "##嬪": 15143, "##嬰": 15144, "##嬴": 15145, "##嬷": 15146, "##嬸": 15147, "##嬿": 15148, "##孀": 15149, "##孃": 15150, "##子": 15151, "##孑": 15152, "##孔": 15153, "##孕": 15154, "##孖": 15155, "##字": 15156, "##存": 15157, "##孙": 15158, "##孚": 15159, "##孛": 15160, "##孜": 15161, "##孝": 15162, "##孟": 15163, "##孢": 15164, "##季": 15165, "##孤": 15166, "##学": 15167, "##孩": 15168, "##孪": 15169, "##孫": 15170, "##孬": 15171, "##孰": 15172, "##孱": 15173, "##孳": 15174, "##孵": 15175, "##學": 15176, "##孺": 15177, "##孽": 15178, "##孿": 15179, "##宁": 15180, "##它": 15181, "##宅": 15182, "##宇": 15183, "##守": 15184, "##安": 15185, "##宋": 15186, "##完": 15187, "##宏": 15188, "##宓": 15189, "##宕": 15190, "##宗": 15191, "##官": 15192, "##宙": 15193, "##定": 15194, "##宛": 15195, "##宜": 15196, "##宝": 15197, "##实": 15198, "##実": 15199, "##宠": 15200, "##审": 15201, "##客": 15202, "##宣": 15203, "##室": 15204, "##宥": 15205, "##宦": 15206, "##宪": 15207, "##宫": 15208, "##宮": 15209, "##宰": 15210, "##害": 15211, "##宴": 15212, "##宵": 15213, "##家": 15214, "##宸": 15215, "##容": 15216, "##宽": 15217, "##宾": 15218, "##宿": 15219, "##寂": 15220, "##寄": 15221, "##寅": 15222, "##密": 15223, "##寇": 15224, "##富": 15225, "##寐": 15226, "##寒": 15227, "##寓": 15228, "##寛": 15229, "##寝": 15230, "##寞": 15231, "##察": 15232, "##寡": 15233, "##寢": 15234, "##寥": 15235, "##實": 15236, "##寧": 15237, "##寨": 15238, "##審": 15239, "##寫": 15240, "##寬": 15241, "##寮": 15242, "##寰": 15243, "##寵": 15244, "##寶": 15245, "##寸": 15246, "##对": 15247, "##寺": 15248, "##寻": 15249, "##导": 15250, "##対": 15251, "##寿": 15252, "##封": 15253, "##専": 15254, "##射": 15255, "##将": 15256, "##將": 15257, "##專": 15258, "##尉": 15259, "##尊": 15260, "##尋": 15261, "##對": 15262, "##導": 15263, "##小": 15264, "##少": 15265, "##尔": 15266, "##尕": 15267, "##尖": 15268, "##尘": 15269, "##尚": 15270, "##尝": 15271, "##尤": 15272, "##尧": 15273, "##尬": 15274, "##就": 15275, "##尴": 15276, "##尷": 15277, "##尸": 15278, "##尹": 15279, "##尺": 15280, "##尻": 15281, "##尼": 15282, "##尽": 15283, "##尾": 15284, "##尿": 15285, "##局": 15286, "##屁": 15287, "##层": 15288, "##屄": 15289, "##居": 15290, "##屆": 15291, "##屈": 15292, "##屉": 15293, "##届": 15294, "##屋": 15295, "##屌": 15296, "##屍": 15297, "##屎": 15298, "##屏": 15299, "##屐": 15300, "##屑": 15301, "##展": 15302, "##屜": 15303, "##属": 15304, "##屠": 15305, "##屡": 15306, "##屢": 15307, "##層": 15308, "##履": 15309, "##屬": 15310, "##屯": 15311, "##山": 15312, "##屹": 15313, "##屿": 15314, "##岀": 15315, "##岁": 15316, "##岂": 15317, "##岌": 15318, "##岐": 15319, "##岑": 15320, "##岔": 15321, "##岖": 15322, "##岗": 15323, "##岘": 15324, "##岙": 15325, "##岚": 15326, "##岛": 15327, "##岡": 15328, "##岩": 15329, "##岫": 15330, "##岬": 15331, "##岭": 15332, "##岱": 15333, "##岳": 15334, "##岷": 15335, "##岸": 15336, "##峇": 15337, "##峋": 15338, "##峒": 15339, "##峙": 15340, "##峡": 15341, "##峤": 15342, "##峥": 15343, "##峦": 15344, "##峨": 15345, "##峪": 15346, "##峭": 15347, "##峯": 15348, "##峰": 15349, "##峴": 15350, "##島": 15351, "##峻": 15352, "##峽": 15353, "##崁": 15354, "##崂": 15355, "##崆": 15356, "##崇": 15357, "##崎": 15358, "##崑": 15359, "##崔": 15360, "##崖": 15361, "##崗": 15362, "##崙": 15363, "##崛": 15364, "##崧": 15365, "##崩": 15366, "##崭": 15367, "##崴": 15368, "##崽": 15369, "##嵇": 15370, "##嵊": 15371, "##嵋": 15372, "##嵌": 15373, "##嵐": 15374, "##嵘": 15375, "##嵩": 15376, "##嵬": 15377, "##嵯": 15378, "##嶂": 15379, "##嶄": 15380, "##嶇": 15381, "##嶋": 15382, "##嶙": 15383, "##嶺": 15384, "##嶼": 15385, "##嶽": 15386, "##巅": 15387, "##巍": 15388, "##巒": 15389, "##巔": 15390, "##巖": 15391, "##川": 15392, "##州": 15393, "##巡": 15394, "##巢": 15395, "##工": 15396, "##左": 15397, "##巧": 15398, "##巨": 15399, "##巩": 15400, "##巫": 15401, "##差": 15402, "##己": 15403, "##已": 15404, "##巳": 15405, "##巴": 15406, "##巷": 15407, "##巻": 15408, "##巽": 15409, "##巾": 15410, "##巿": 15411, "##币": 15412, "##市": 15413, "##布": 15414, "##帅": 15415, "##帆": 15416, "##师": 15417, "##希": 15418, "##帐": 15419, "##帑": 15420, "##帕": 15421, "##帖": 15422, "##帘": 15423, "##帚": 15424, "##帛": 15425, "##帜": 15426, "##帝": 15427, "##帥": 15428, "##带": 15429, "##帧": 15430, "##師": 15431, "##席": 15432, "##帮": 15433, "##帯": 15434, "##帰": 15435, "##帳": 15436, "##帶": 15437, "##帷": 15438, "##常": 15439, "##帼": 15440, "##帽": 15441, "##幀": 15442, "##幂": 15443, "##幄": 15444, "##幅": 15445, "##幌": 15446, "##幔": 15447, "##幕": 15448, "##幟": 15449, "##幡": 15450, "##幢": 15451, "##幣": 15452, "##幫": 15453, "##干": 15454, "##平": 15455, "##年": 15456, "##并": 15457, "##幸": 15458, "##幹": 15459, "##幺": 15460, "##幻": 15461, "##幼": 15462, "##幽": 15463, "##幾": 15464, "##广": 15465, "##庁": 15466, "##広": 15467, "##庄": 15468, "##庆": 15469, "##庇": 15470, "##床": 15471, "##序": 15472, "##庐": 15473, "##库": 15474, "##应": 15475, "##底": 15476, "##庖": 15477, "##店": 15478, "##庙": 15479, "##庚": 15480, "##府": 15481, "##庞": 15482, "##废": 15483, "##庠": 15484, "##度": 15485, "##座": 15486, "##庫": 15487, "##庭": 15488, "##庵": 15489, "##庶": 15490, "##康": 15491, "##庸": 15492, "##庹": 15493, "##庾": 15494, "##廁": 15495, "##廂": 15496, "##廃": 15497, "##廈": 15498, "##廉": 15499, "##廊": 15500, "##廓": 15501, "##廖": 15502, "##廚": 15503, "##廝": 15504, "##廟": 15505, "##廠": 15506, "##廢": 15507, "##廣": 15508, "##廬": 15509, "##廳": 15510, "##延": 15511, "##廷": 15512, "##建": 15513, "##廿": 15514, "##开": 15515, "##弁": 15516, "##异": 15517, "##弃": 15518, "##弄": 15519, "##弈": 15520, "##弊": 15521, "##弋": 15522, "##式": 15523, "##弑": 15524, "##弒": 15525, "##弓": 15526, "##弔": 15527, "##引": 15528, "##弗": 15529, "##弘": 15530, "##弛": 15531, "##弟": 15532, "##张": 15533, "##弥": 15534, "##弦": 15535, "##弧": 15536, "##弩": 15537, "##弭": 15538, "##弯": 15539, "##弱": 15540, "##張": 15541, "##強": 15542, "##弹": 15543, "##强": 15544, "##弼": 15545, "##弾": 15546, "##彅": 15547, "##彆": 15548, "##彈": 15549, "##彌": 15550, "##彎": 15551, "##归": 15552, "##当": 15553, "##录": 15554, "##彗": 15555, "##彙": 15556, "##彝": 15557, "##形": 15558, "##彤": 15559, "##彥": 15560, "##彦": 15561, "##彧": 15562, "##彩": 15563, "##彪": 15564, "##彫": 15565, "##彬": 15566, "##彭": 15567, "##彰": 15568, "##影": 15569, "##彷": 15570, "##役": 15571, "##彻": 15572, "##彼": 15573, "##彿": 15574, "##往": 15575, "##征": 15576, "##径": 15577, "##待": 15578, "##徇": 15579, "##很": 15580, "##徉": 15581, "##徊": 15582, "##律": 15583, "##後": 15584, "##徐": 15585, "##徑": 15586, "##徒": 15587, "##従": 15588, "##徕": 15589, "##得": 15590, "##徘": 15591, "##徙": 15592, "##徜": 15593, "##從": 15594, "##徠": 15595, "##御": 15596, "##徨": 15597, "##復": 15598, "##循": 15599, "##徬": 15600, "##微": 15601, "##徳": 15602, "##徴": 15603, "##徵": 15604, "##德": 15605, "##徹": 15606, "##徼": 15607, "##徽": 15608, "##心": 15609, "##必": 15610, "##忆": 15611, "##忌": 15612, "##忍": 15613, "##忏": 15614, "##忐": 15615, "##忑": 15616, "##忒": 15617, "##忖": 15618, "##志": 15619, "##忘": 15620, "##忙": 15621, "##応": 15622, "##忠": 15623, "##忡": 15624, "##忤": 15625, "##忧": 15626, "##忪": 15627, "##快": 15628, "##忱": 15629, "##念": 15630, "##忻": 15631, "##忽": 15632, "##忿": 15633, "##怀": 15634, "##态": 15635, "##怂": 15636, "##怅": 15637, "##怆": 15638, "##怎": 15639, "##怏": 15640, "##怒": 15641, "##怔": 15642, "##怕": 15643, "##怖": 15644, "##怙": 15645, "##怜": 15646, "##思": 15647, "##怠": 15648, "##怡": 15649, "##急": 15650, "##怦": 15651, "##性": 15652, "##怨": 15653, "##怪": 15654, "##怯": 15655, "##怵": 15656, "##总": 15657, "##怼": 15658, "##恁": 15659, "##恃": 15660, "##恆": 15661, "##恋": 15662, "##恍": 15663, "##恐": 15664, "##恒": 15665, "##恕": 15666, "##恙": 15667, "##恚": 15668, "##恢": 15669, "##恣": 15670, "##恤": 15671, "##恥": 15672, "##恨": 15673, "##恩": 15674, "##恪": 15675, "##恫": 15676, "##恬": 15677, "##恭": 15678, "##息": 15679, "##恰": 15680, "##恳": 15681, "##恵": 15682, "##恶": 15683, "##恸": 15684, "##恺": 15685, "##恻": 15686, "##恼": 15687, "##恿": 15688, "##悄": 15689, "##悅": 15690, "##悉": 15691, "##悌": 15692, "##悍": 15693, "##悔": 15694, "##悖": 15695, "##悚": 15696, "##悟": 15697, "##悠": 15698, "##患": 15699, "##悦": 15700, "##您": 15701, "##悩": 15702, "##悪": 15703, "##悬": 15704, "##悯": 15705, "##悱": 15706, "##悲": 15707, "##悴": 15708, "##悵": 15709, "##悶": 15710, "##悸": 15711, "##悻": 15712, "##悼": 15713, "##悽": 15714, "##情": 15715, "##惆": 15716, "##惇": 15717, "##惊": 15718, "##惋": 15719, "##惑": 15720, "##惕": 15721, "##惘": 15722, "##惚": 15723, "##惜": 15724, "##惟": 15725, "##惠": 15726, "##惡": 15727, "##惦": 15728, "##惧": 15729, "##惨": 15730, "##惩": 15731, "##惫": 15732, "##惬": 15733, "##惭": 15734, "##惮": 15735, "##惯": 15736, "##惰": 15737, "##惱": 15738, "##想": 15739, "##惴": 15740, "##惶": 15741, "##惹": 15742, "##惺": 15743, "##愁": 15744, "##愆": 15745, "##愈": 15746, "##愉": 15747, "##愍": 15748, "##意": 15749, "##愕": 15750, "##愚": 15751, "##愛": 15752, "##愜": 15753, "##感": 15754, "##愣": 15755, "##愤": 15756, "##愧": 15757, "##愫": 15758, "##愷": 15759, "##愿": 15760, "##慄": 15761, "##慈": 15762, "##態": 15763, "##慌": 15764, "##慎": 15765, "##慑": 15766, "##慕": 15767, "##慘": 15768, "##慚": 15769, "##慟": 15770, "##慢": 15771, "##慣": 15772, "##慧": 15773, "##慨": 15774, "##慫": 15775, "##慮": 15776, "##慰": 15777, "##慳": 15778, "##慵": 15779, "##慶": 15780, "##慷": 15781, "##慾": 15782, "##憂": 15783, "##憊": 15784, "##憋": 15785, "##憎": 15786, "##憐": 15787, "##憑": 15788, "##憔": 15789, "##憚": 15790, "##憤": 15791, "##憧": 15792, "##憨": 15793, "##憩": 15794, "##憫": 15795, "##憬": 15796, "##憲": 15797, "##憶": 15798, "##憾": 15799, "##懂": 15800, "##懇": 15801, "##懈": 15802, "##應": 15803, "##懊": 15804, "##懋": 15805, "##懑": 15806, "##懒": 15807, "##懦": 15808, "##懲": 15809, "##懵": 15810, "##懶": 15811, "##懷": 15812, "##懸": 15813, "##懺": 15814, "##懼": 15815, "##懾": 15816, "##懿": 15817, "##戀": 15818, "##戈": 15819, "##戊": 15820, "##戌": 15821, "##戍": 15822, "##戎": 15823, "##戏": 15824, "##成": 15825, "##我": 15826, "##戒": 15827, "##戕": 15828, "##或": 15829, "##战": 15830, "##戚": 15831, "##戛": 15832, "##戟": 15833, "##戡": 15834, "##戦": 15835, "##截": 15836, "##戬": 15837, "##戮": 15838, "##戰": 15839, "##戲": 15840, "##戳": 15841, "##戴": 15842, "##戶": 15843, "##户": 15844, "##戸": 15845, "##戻": 15846, "##戾": 15847, "##房": 15848, "##所": 15849, "##扁": 15850, "##扇": 15851, "##扈": 15852, "##扉": 15853, "##手": 15854, "##才": 15855, "##扎": 15856, "##扑": 15857, "##扒": 15858, "##打": 15859, "##扔": 15860, "##払": 15861, "##托": 15862, "##扛": 15863, "##扣": 15864, "##扦": 15865, "##执": 15866, "##扩": 15867, "##扪": 15868, "##扫": 15869, "##扬": 15870, "##扭": 15871, "##扮": 15872, "##扯": 15873, "##扰": 15874, "##扱": 15875, "##扳": 15876, "##扶": 15877, "##批": 15878, "##扼": 15879, "##找": 15880, "##承": 15881, "##技": 15882, "##抄": 15883, "##抉": 15884, "##把": 15885, "##抑": 15886, "##抒": 15887, "##抓": 15888, "##投": 15889, "##抖": 15890, "##抗": 15891, "##折": 15892, "##抚": 15893, "##抛": 15894, "##抜": 15895, "##択": 15896, "##抟": 15897, "##抠": 15898, "##抡": 15899, "##抢": 15900, "##护": 15901, "##报": 15902, "##抨": 15903, "##披": 15904, "##抬": 15905, "##抱": 15906, "##抵": 15907, "##抹": 15908, "##押": 15909, "##抽": 15910, "##抿": 15911, "##拂": 15912, "##拄": 15913, "##担": 15914, "##拆": 15915, "##拇": 15916, "##拈": 15917, "##拉": 15918, "##拋": 15919, "##拌": 15920, "##拍": 15921, "##拎": 15922, "##拐": 15923, "##拒": 15924, "##拓": 15925, "##拔": 15926, "##拖": 15927, "##拗": 15928, "##拘": 15929, "##拙": 15930, "##拚": 15931, "##招": 15932, "##拜": 15933, "##拟": 15934, "##拡": 15935, "##拢": 15936, "##拣": 15937, "##拥": 15938, "##拦": 15939, "##拧": 15940, "##拨": 15941, "##择": 15942, "##括": 15943, "##拭": 15944, "##拮": 15945, "##拯": 15946, "##拱": 15947, "##拳": 15948, "##拴": 15949, "##拷": 15950, "##拼": 15951, "##拽": 15952, "##拾": 15953, "##拿": 15954, "##持": 15955, "##挂": 15956, "##指": 15957, "##挈": 15958, "##按": 15959, "##挎": 15960, "##挑": 15961, "##挖": 15962, "##挙": 15963, "##挚": 15964, "##挛": 15965, "##挝": 15966, "##挞": 15967, "##挟": 15968, "##挠": 15969, "##挡": 15970, "##挣": 15971, "##挤": 15972, "##挥": 15973, "##挨": 15974, "##挪": 15975, "##挫": 15976, "##振": 15977, "##挲": 15978, "##挹": 15979, "##挺": 15980, "##挽": 15981, "##挾": 15982, "##捂": 15983, "##捅": 15984, "##捆": 15985, "##捉": 15986, "##捋": 15987, "##捌": 15988, "##捍": 15989, "##捎": 15990, "##捏": 15991, "##捐": 15992, "##捕": 15993, "##捞": 15994, "##损": 15995, "##捡": 15996, "##换": 15997, "##捣": 15998, "##捧": 15999, "##捨": 16000, "##捩": 16001, "##据": 16002, "##捱": 16003, "##捲": 16004, "##捶": 16005, "##捷": 16006, "##捺": 16007, "##捻": 16008, "##掀": 16009, "##掂": 16010, "##掃": 16011, "##掇": 16012, "##授": 16013, "##掉": 16014, "##掌": 16015, "##掏": 16016, "##掐": 16017, "##排": 16018, "##掖": 16019, "##掘": 16020, "##掙": 16021, "##掛": 16022, "##掠": 16023, "##採": 16024, "##探": 16025, "##掣": 16026, "##接": 16027, "##控": 16028, "##推": 16029, "##掩": 16030, "##措": 16031, "##掬": 16032, "##掰": 16033, "##掲": 16034, "##掳": 16035, "##掴": 16036, "##掷": 16037, "##掸": 16038, "##掺": 16039, "##揀": 16040, "##揃": 16041, "##揄": 16042, "##揆": 16043, "##揉": 16044, "##揍": 16045, "##描": 16046, "##提": 16047, "##插": 16048, "##揖": 16049, "##揚": 16050, "##換": 16051, "##握": 16052, "##揣": 16053, "##揩": 16054, "##揪": 16055, "##揭": 16056, "##揮": 16057, "##援": 16058, "##揶": 16059, "##揸": 16060, "##揹": 16061, "##揽": 16062, "##搀": 16063, "##搁": 16064, "##搂": 16065, "##搅": 16066, "##損": 16067, "##搏": 16068, "##搐": 16069, "##搓": 16070, "##搔": 16071, "##搖": 16072, "##搗": 16073, "##搜": 16074, "##搞": 16075, "##搡": 16076, "##搪": 16077, "##搬": 16078, "##搭": 16079, "##搵": 16080, "##搶": 16081, "##携": 16082, "##搽": 16083, "##摀": 16084, "##摁": 16085, "##摄": 16086, "##摆": 16087, "##摇": 16088, "##摈": 16089, "##摊": 16090, "##摒": 16091, "##摔": 16092, "##摘": 16093, "##摞": 16094, "##摟": 16095, "##摧": 16096, "##摩": 16097, "##摯": 16098, "##摳": 16099, "##摸": 16100, "##摹": 16101, "##摺": 16102, "##摻": 16103, "##撂": 16104, "##撃": 16105, "##撅": 16106, "##撇": 16107, "##撈": 16108, "##撐": 16109, "##撑": 16110, "##撒": 16111, "##撓": 16112, "##撕": 16113, "##撚": 16114, "##撞": 16115, "##撤": 16116, "##撥": 16117, "##撩": 16118, "##撫": 16119, "##撬": 16120, "##播": 16121, "##撮": 16122, "##撰": 16123, "##撲": 16124, "##撵": 16125, "##撷": 16126, "##撸": 16127, "##撻": 16128, "##撼": 16129, "##撿": 16130, "##擀": 16131, "##擁": 16132, "##擂": 16133, "##擄": 16134, "##擅": 16135, "##擇": 16136, "##擊": 16137, "##擋": 16138, "##操": 16139, "##擎": 16140, "##擒": 16141, "##擔": 16142, "##擘": 16143, "##據": 16144, "##擞": 16145, "##擠": 16146, "##擡": 16147, "##擢": 16148, "##擦": 16149, "##擬": 16150, "##擰": 16151, "##擱": 16152, "##擲": 16153, "##擴": 16154, "##擷": 16155, "##擺": 16156, "##擼": 16157, "##擾": 16158, "##攀": 16159, "##攏": 16160, "##攒": 16161, "##攔": 16162, "##攘": 16163, "##攙": 16164, "##攜": 16165, "##攝": 16166, "##攞": 16167, "##攢": 16168, "##攣": 16169, "##攤": 16170, "##攥": 16171, "##攪": 16172, "##攫": 16173, "##攬": 16174, "##支": 16175, "##收": 16176, "##攸": 16177, "##改": 16178, "##攻": 16179, "##放": 16180, "##政": 16181, "##故": 16182, "##效": 16183, "##敌": 16184, "##敍": 16185, "##敎": 16186, "##敏": 16187, "##救": 16188, "##敕": 16189, "##敖": 16190, "##敗": 16191, "##敘": 16192, "##教": 16193, "##敛": 16194, "##敝": 16195, "##敞": 16196, "##敢": 16197, "##散": 16198, "##敦": 16199, "##敬": 16200, "##数": 16201, "##敲": 16202, "##整": 16203, "##敵": 16204, "##敷": 16205, "##數": 16206, "##斂": 16207, "##斃": 16208, "##文": 16209, "##斋": 16210, "##斌": 16211, "##斎": 16212, "##斐": 16213, "##斑": 16214, "##斓": 16215, "##斗": 16216, "##料": 16217, "##斛": 16218, "##斜": 16219, "##斟": 16220, "##斡": 16221, "##斤": 16222, "##斥": 16223, "##斧": 16224, "##斩": 16225, "##斫": 16226, "##斬": 16227, "##断": 16228, "##斯": 16229, "##新": 16230, "##斷": 16231, "##方": 16232, "##於": 16233, "##施": 16234, "##旁": 16235, "##旃": 16236, "##旅": 16237, "##旋": 16238, "##旌": 16239, "##旎": 16240, "##族": 16241, "##旖": 16242, "##旗": 16243, "##无": 16244, "##既": 16245, "##日": 16246, "##旦": 16247, "##旧": 16248, "##旨": 16249, "##早": 16250, "##旬": 16251, "##旭": 16252, "##旮": 16253, "##旱": 16254, "##时": 16255, "##旷": 16256, "##旺": 16257, "##旻": 16258, "##昀": 16259, "##昂": 16260, "##昆": 16261, "##昇": 16262, "##昉": 16263, "##昊": 16264, "##昌": 16265, "##明": 16266, "##昏": 16267, "##易": 16268, "##昔": 16269, "##昕": 16270, "##昙": 16271, "##星": 16272, "##映": 16273, "##春": 16274, "##昧": 16275, "##昨": 16276, "##昭": 16277, "##是": 16278, "##昱": 16279, "##昴": 16280, "##昵": 16281, "##昶": 16282, "##昼": 16283, "##显": 16284, "##晁": 16285, "##時": 16286, "##晃": 16287, "##晉": 16288, "##晋": 16289, "##晌": 16290, "##晏": 16291, "##晒": 16292, "##晓": 16293, "##晔": 16294, "##晕": 16295, "##晖": 16296, "##晗": 16297, "##晚": 16298, "##晝": 16299, "##晞": 16300, "##晟": 16301, "##晤": 16302, "##晦": 16303, "##晨": 16304, "##晩": 16305, "##普": 16306, "##景": 16307, "##晰": 16308, "##晴": 16309, "##晶": 16310, "##晷": 16311, "##智": 16312, "##晾": 16313, "##暂": 16314, "##暄": 16315, "##暇": 16316, "##暈": 16317, "##暉": 16318, "##暌": 16319, "##暐": 16320, "##暑": 16321, "##暖": 16322, "##暗": 16323, "##暝": 16324, "##暢": 16325, "##暧": 16326, "##暨": 16327, "##暫": 16328, "##暮": 16329, "##暱": 16330, "##暴": 16331, "##暸": 16332, "##暹": 16333, "##曄": 16334, "##曆": 16335, "##曇": 16336, "##曉": 16337, "##曖": 16338, "##曙": 16339, "##曜": 16340, "##曝": 16341, "##曠": 16342, "##曦": 16343, "##曬": 16344, "##曰": 16345, "##曲": 16346, "##曳": 16347, "##更": 16348, "##書": 16349, "##曹": 16350, "##曼": 16351, "##曾": 16352, "##替": 16353, "##最": 16354, "##會": 16355, "##月": 16356, "##有": 16357, "##朋": 16358, "##服": 16359, "##朐": 16360, "##朔": 16361, "##朕": 16362, "##朗": 16363, "##望": 16364, "##朝": 16365, "##期": 16366, "##朦": 16367, "##朧": 16368, "##木": 16369, "##未": 16370, "##末": 16371, "##本": 16372, "##札": 16373, "##朮": 16374, "##术": 16375, "##朱": 16376, "##朴": 16377, "##朵": 16378, "##机": 16379, "##朽": 16380, "##杀": 16381, "##杂": 16382, "##权": 16383, "##杆": 16384, "##杈": 16385, "##杉": 16386, "##李": 16387, "##杏": 16388, "##材": 16389, "##村": 16390, "##杓": 16391, "##杖": 16392, "##杜": 16393, "##杞": 16394, "##束": 16395, "##杠": 16396, "##条": 16397, "##来": 16398, "##杨": 16399, "##杭": 16400, "##杯": 16401, "##杰": 16402, "##東": 16403, "##杳": 16404, "##杵": 16405, "##杷": 16406, "##杼": 16407, "##松": 16408, "##板": 16409, "##极": 16410, "##构": 16411, "##枇": 16412, "##枉": 16413, "##枋": 16414, "##析": 16415, "##枕": 16416, "##林": 16417, "##枚": 16418, "##果": 16419, "##枝": 16420, "##枢": 16421, "##枣": 16422, "##枪": 16423, "##枫": 16424, "##枭": 16425, "##枯": 16426, "##枰": 16427, "##枱": 16428, "##枳": 16429, "##架": 16430, "##枷": 16431, "##枸": 16432, "##柄": 16433, "##柏": 16434, "##某": 16435, "##柑": 16436, "##柒": 16437, "##染": 16438, "##柔": 16439, "##柘": 16440, "##柚": 16441, "##柜": 16442, "##柞": 16443, "##柠": 16444, "##柢": 16445, "##查": 16446, "##柩": 16447, "##柬": 16448, "##柯": 16449, "##柱": 16450, "##柳": 16451, "##柴": 16452, "##柵": 16453, "##査": 16454, "##柿": 16455, "##栀": 16456, "##栃": 16457, "##栄": 16458, "##栅": 16459, "##标": 16460, "##栈": 16461, "##栉": 16462, "##栋": 16463, "##栎": 16464, "##栏": 16465, "##树": 16466, "##栓": 16467, "##栖": 16468, "##栗": 16469, "##校": 16470, "##栩": 16471, "##株": 16472, "##样": 16473, "##核": 16474, "##根": 16475, "##格": 16476, "##栽": 16477, "##栾": 16478, "##桀": 16479, "##桁": 16480, "##桂": 16481, "##桃": 16482, "##桅": 16483, "##框": 16484, "##案": 16485, "##桉": 16486, "##桌": 16487, "##桎": 16488, "##桐": 16489, "##桑": 16490, "##桓": 16491, "##桔": 16492, "##桜": 16493, "##桠": 16494, "##桡": 16495, "##桢": 16496, "##档": 16497, "##桥": 16498, "##桦": 16499, "##桧": 16500, "##桨": 16501, "##桩": 16502, "##桶": 16503, "##桿": 16504, "##梁": 16505, "##梅": 16506, "##梆": 16507, "##梏": 16508, "##梓": 16509, "##梗": 16510, "##條": 16511, "##梟": 16512, "##梢": 16513, "##梦": 16514, "##梧": 16515, "##梨": 16516, "##梭": 16517, "##梯": 16518, "##械": 16519, "##梳": 16520, "##梵": 16521, "##梶": 16522, "##检": 16523, "##棂": 16524, "##棄": 16525, "##棉": 16526, "##棋": 16527, "##棍": 16528, "##棒": 16529, "##棕": 16530, "##棗": 16531, "##棘": 16532, "##棚": 16533, "##棟": 16534, "##棠": 16535, "##棣": 16536, "##棧": 16537, "##森": 16538, "##棱": 16539, "##棲": 16540, "##棵": 16541, "##棹": 16542, "##棺": 16543, "##椁": 16544, "##椅": 16545, "##椋": 16546, "##植": 16547, "##椎": 16548, "##椒": 16549, "##検": 16550, "##椪": 16551, "##椭": 16552, "##椰": 16553, "##椹": 16554, "##椽": 16555, "##椿": 16556, "##楂": 16557, "##楊": 16558, "##楓": 16559, "##楔": 16560, "##楚": 16561, "##楝": 16562, "##楞": 16563, "##楠": 16564, "##楣": 16565, "##楨": 16566, "##楫": 16567, "##業": 16568, "##楮": 16569, "##極": 16570, "##楷": 16571, "##楸": 16572, "##楹": 16573, "##楼": 16574, "##楽": 16575, "##概": 16576, "##榄": 16577, "##榆": 16578, "##榈": 16579, "##榉": 16580, "##榔": 16581, "##榕": 16582, "##榖": 16583, "##榛": 16584, "##榜": 16585, "##榨": 16586, "##榫": 16587, "##榭": 16588, "##榮": 16589, "##榱": 16590, "##榴": 16591, "##榷": 16592, "##榻": 16593, "##槁": 16594, "##槃": 16595, "##構": 16596, "##槌": 16597, "##槍": 16598, "##槎": 16599, "##槐": 16600, "##槓": 16601, "##様": 16602, "##槛": 16603, "##槟": 16604, "##槤": 16605, "##槭": 16606, "##槲": 16607, "##槳": 16608, "##槻": 16609, "##槽": 16610, "##槿": 16611, "##樁": 16612, "##樂": 16613, "##樊": 16614, "##樑": 16615, "##樓": 16616, "##標": 16617, "##樞": 16618, "##樟": 16619, "##模": 16620, "##樣": 16621, "##権": 16622, "##横": 16623, "##樫": 16624, "##樯": 16625, "##樱": 16626, "##樵": 16627, "##樸": 16628, "##樹": 16629, "##樺": 16630, "##樽": 16631, "##樾": 16632, "##橄": 16633, "##橇": 16634, "##橋": 16635, "##橐": 16636, "##橘": 16637, "##橙": 16638, "##機": 16639, "##橡": 16640, "##橢": 16641, "##橫": 16642, "##橱": 16643, "##橹": 16644, "##橼": 16645, "##檀": 16646, "##檄": 16647, "##檎": 16648, "##檐": 16649, "##檔": 16650, "##檗": 16651, "##檜": 16652, "##檢": 16653, "##檬": 16654, "##檯": 16655, "##檳": 16656, "##檸": 16657, "##檻": 16658, "##櫃": 16659, "##櫚": 16660, "##櫛": 16661, "##櫥": 16662, "##櫸": 16663, "##櫻": 16664, "##欄": 16665, "##權": 16666, "##欒": 16667, "##欖": 16668, "##欠": 16669, "##次": 16670, "##欢": 16671, "##欣": 16672, "##欧": 16673, "##欲": 16674, "##欸": 16675, "##欺": 16676, "##欽": 16677, "##款": 16678, "##歆": 16679, "##歇": 16680, "##歉": 16681, "##歌": 16682, "##歎": 16683, "##歐": 16684, "##歓": 16685, "##歙": 16686, "##歛": 16687, "##歡": 16688, "##止": 16689, "##正": 16690, "##此": 16691, "##步": 16692, "##武": 16693, "##歧": 16694, "##歩": 16695, "##歪": 16696, "##歯": 16697, "##歲": 16698, "##歳": 16699, "##歴": 16700, "##歷": 16701, "##歸": 16702, "##歹": 16703, "##死": 16704, "##歼": 16705, "##殁": 16706, "##殃": 16707, "##殆": 16708, "##殇": 16709, "##殉": 16710, "##殊": 16711, "##残": 16712, "##殒": 16713, "##殓": 16714, "##殖": 16715, "##殘": 16716, "##殞": 16717, "##殡": 16718, "##殤": 16719, "##殭": 16720, "##殯": 16721, "##殲": 16722, "##殴": 16723, "##段": 16724, "##殷": 16725, "##殺": 16726, "##殼": 16727, "##殿": 16728, "##毀": 16729, "##毁": 16730, "##毂": 16731, "##毅": 16732, "##毆": 16733, "##毋": 16734, "##母": 16735, "##毎": 16736, "##每": 16737, "##毒": 16738, "##毓": 16739, "##比": 16740, "##毕": 16741, "##毗": 16742, "##毘": 16743, "##毙": 16744, "##毛": 16745, "##毡": 16746, "##毫": 16747, "##毯": 16748, "##毽": 16749, "##氈": 16750, "##氏": 16751, "##氐": 16752, "##民": 16753, "##氓": 16754, "##气": 16755, "##氖": 16756, "##気": 16757, "##氙": 16758, "##氛": 16759, "##氟": 16760, "##氡": 16761, "##氢": 16762, "##氣": 16763, "##氤": 16764, "##氦": 16765, "##氧": 16766, "##氨": 16767, "##氪": 16768, "##氫": 16769, "##氮": 16770, "##氯": 16771, "##氰": 16772, "##氲": 16773, "##水": 16774, "##氷": 16775, "##永": 16776, "##氹": 16777, "##氾": 16778, "##汀": 16779, "##汁": 16780, "##求": 16781, "##汆": 16782, "##汇": 16783, "##汉": 16784, "##汎": 16785, "##汐": 16786, "##汕": 16787, "##汗": 16788, "##汙": 16789, "##汛": 16790, "##汝": 16791, "##汞": 16792, "##江": 16793, "##池": 16794, "##污": 16795, "##汤": 16796, "##汨": 16797, "##汩": 16798, "##汪": 16799, "##汰": 16800, "##汲": 16801, "##汴": 16802, "##汶": 16803, "##汹": 16804, "##決": 16805, "##汽": 16806, "##汾": 16807, "##沁": 16808, "##沂": 16809, "##沃": 16810, "##沅": 16811, "##沈": 16812, "##沉": 16813, "##沌": 16814, "##沏": 16815, "##沐": 16816, "##沒": 16817, "##沓": 16818, "##沖": 16819, "##沙": 16820, "##沛": 16821, "##沟": 16822, "##没": 16823, "##沢": 16824, "##沣": 16825, "##沥": 16826, "##沦": 16827, "##沧": 16828, "##沪": 16829, "##沫": 16830, "##沭": 16831, "##沮": 16832, "##沱": 16833, "##河": 16834, "##沸": 16835, "##油": 16836, "##治": 16837, "##沼": 16838, "##沽": 16839, "##沾": 16840, "##沿": 16841, "##況": 16842, "##泄": 16843, "##泉": 16844, "##泊": 16845, "##泌": 16846, "##泓": 16847, "##法": 16848, "##泗": 16849, "##泛": 16850, "##泞": 16851, "##泠": 16852, "##泡": 16853, "##波": 16854, "##泣": 16855, "##泥": 16856, "##注": 16857, "##泪": 16858, "##泫": 16859, "##泮": 16860, "##泯": 16861, "##泰": 16862, "##泱": 16863, "##泳": 16864, "##泵": 16865, "##泷": 16866, "##泸": 16867, "##泻": 16868, "##泼": 16869, "##泽": 16870, "##泾": 16871, "##洁": 16872, "##洄": 16873, "##洋": 16874, "##洒": 16875, "##洗": 16876, "##洙": 16877, "##洛": 16878, "##洞": 16879, "##津": 16880, "##洩": 16881, "##洪": 16882, "##洮": 16883, "##洱": 16884, "##洲": 16885, "##洵": 16886, "##洶": 16887, "##洸": 16888, "##洹": 16889, "##活": 16890, "##洼": 16891, "##洽": 16892, "##派": 16893, "##流": 16894, "##浃": 16895, "##浄": 16896, "##浅": 16897, "##浆": 16898, "##浇": 16899, "##浊": 16900, "##测": 16901, "##济": 16902, "##浏": 16903, "##浑": 16904, "##浒": 16905, "##浓": 16906, "##浔": 16907, "##浙": 16908, "##浚": 16909, "##浜": 16910, "##浣": 16911, "##浦": 16912, "##浩": 16913, "##浪": 16914, "##浬": 16915, "##浮": 16916, "##浯": 16917, "##浴": 16918, "##海": 16919, "##浸": 16920, "##涂": 16921, "##涅": 16922, "##涇": 16923, "##消": 16924, "##涉": 16925, "##涌": 16926, "##涎": 16927, "##涓": 16928, "##涔": 16929, "##涕": 16930, "##涙": 16931, "##涛": 16932, "##涝": 16933, "##涞": 16934, "##涟": 16935, "##涠": 16936, "##涡": 16937, "##涣": 16938, "##涤": 16939, "##润": 16940, "##涧": 16941, "##涨": 16942, "##涩": 16943, "##涪": 16944, "##涮": 16945, "##涯": 16946, "##液": 16947, "##涵": 16948, "##涸": 16949, "##涼": 16950, "##涿": 16951, "##淀": 16952, "##淄": 16953, "##淅": 16954, "##淆": 16955, "##淇": 16956, "##淋": 16957, "##淌": 16958, "##淑": 16959, "##淒": 16960, "##淖": 16961, "##淘": 16962, "##淙": 16963, "##淚": 16964, "##淞": 16965, "##淡": 16966, "##淤": 16967, "##淦": 16968, "##淨": 16969, "##淩": 16970, "##淪": 16971, "##淫": 16972, "##淬": 16973, "##淮": 16974, "##深": 16975, "##淳": 16976, "##淵": 16977, "##混": 16978, "##淹": 16979, "##淺": 16980, "##添": 16981, "##淼": 16982, "##清": 16983, "##済": 16984, "##渉": 16985, "##渊": 16986, "##渋": 16987, "##渍": 16988, "##渎": 16989, "##渐": 16990, "##渔": 16991, "##渗": 16992, "##渙": 16993, "##渚": 16994, "##減": 16995, "##渝": 16996, "##渠": 16997, "##渡": 16998, "##渣": 16999, "##渤": 17000, "##渥": 17001, "##渦": 17002, "##温": 17003, "##測": 17004, "##渭": 17005, "##港": 17006, "##渲": 17007, "##渴": 17008, "##游": 17009, "##渺": 17010, "##渾": 17011, "##湃": 17012, "##湄": 17013, "##湊": 17014, "##湍": 17015, "##湖": 17016, "##湘": 17017, "##湛": 17018, "##湟": 17019, "##湧": 17020, "##湫": 17021, "##湮": 17022, "##湯": 17023, "##湳": 17024, "##湾": 17025, "##湿": 17026, "##満": 17027, "##溃": 17028, "##溅": 17029, "##溉": 17030, "##溏": 17031, "##源": 17032, "##準": 17033, "##溜": 17034, "##溝": 17035, "##溟": 17036, "##溢": 17037, "##溥": 17038, "##溧": 17039, "##溪": 17040, "##溫": 17041, "##溯": 17042, "##溱": 17043, "##溴": 17044, "##溶": 17045, "##溺": 17046, "##溼": 17047, "##滁": 17048, "##滂": 17049, "##滄": 17050, "##滅": 17051, "##滇": 17052, "##滋": 17053, "##滌": 17054, "##滑": 17055, "##滓": 17056, "##滔": 17057, "##滕": 17058, "##滙": 17059, "##滚": 17060, "##滝": 17061, "##滞": 17062, "##滟": 17063, "##满": 17064, "##滢": 17065, "##滤": 17066, "##滥": 17067, "##滦": 17068, "##滨": 17069, "##滩": 17070, "##滬": 17071, "##滯": 17072, "##滲": 17073, "##滴": 17074, "##滷": 17075, "##滸": 17076, "##滾": 17077, "##滿": 17078, "##漁": 17079, "##漂": 17080, "##漆": 17081, "##漉": 17082, "##漏": 17083, "##漓": 17084, "##演": 17085, "##漕": 17086, "##漠": 17087, "##漢": 17088, "##漣": 17089, "##漩": 17090, "##漪": 17091, "##漫": 17092, "##漬": 17093, "##漯": 17094, "##漱": 17095, "##漲": 17096, "##漳": 17097, "##漸": 17098, "##漾": 17099, "##漿": 17100, "##潆": 17101, "##潇": 17102, "##潋": 17103, "##潍": 17104, "##潑": 17105, "##潔": 17106, "##潘": 17107, "##潛": 17108, "##潜": 17109, "##潞": 17110, "##潟": 17111, "##潢": 17112, "##潤": 17113, "##潦": 17114, "##潧": 17115, "##潭": 17116, "##潮": 17117, "##潰": 17118, "##潴": 17119, "##潸": 17120, "##潺": 17121, "##潼": 17122, "##澀": 17123, "##澄": 17124, "##澆": 17125, "##澈": 17126, "##澍": 17127, "##澎": 17128, "##澗": 17129, "##澜": 17130, "##澡": 17131, "##澤": 17132, "##澧": 17133, "##澱": 17134, "##澳": 17135, "##澹": 17136, "##激": 17137, "##濁": 17138, "##濂": 17139, "##濃": 17140, "##濑": 17141, "##濒": 17142, "##濕": 17143, "##濘": 17144, "##濛": 17145, "##濟": 17146, "##濠": 17147, "##濡": 17148, "##濤": 17149, "##濫": 17150, "##濬": 17151, "##濮": 17152, "##濯": 17153, "##濱": 17154, "##濺": 17155, "##濾": 17156, "##瀅": 17157, "##瀆": 17158, "##瀉": 17159, "##瀋": 17160, "##瀏": 17161, "##瀑": 17162, "##瀕": 17163, "##瀘": 17164, "##瀚": 17165, "##瀛": 17166, "##瀝": 17167, "##瀞": 17168, "##瀟": 17169, "##瀧": 17170, "##瀨": 17171, "##瀬": 17172, "##瀰": 17173, "##瀾": 17174, "##灌": 17175, "##灏": 17176, "##灑": 17177, "##灘": 17178, "##灝": 17179, "##灞": 17180, "##灣": 17181, "##火": 17182, "##灬": 17183, "##灭": 17184, "##灯": 17185, "##灰": 17186, "##灵": 17187, "##灶": 17188, "##灸": 17189, "##灼": 17190, "##災": 17191, "##灾": 17192, "##灿": 17193, "##炀": 17194, "##炁": 17195, "##炅": 17196, "##炉": 17197, "##炊": 17198, "##炎": 17199, "##炒": 17200, "##炔": 17201, "##炕": 17202, "##炖": 17203, "##炙": 17204, "##炜": 17205, "##炫": 17206, "##炬": 17207, "##炭": 17208, "##炮": 17209, "##炯": 17210, "##炳": 17211, "##炷": 17212, "##炸": 17213, "##点": 17214, "##為": 17215, "##炼": 17216, "##炽": 17217, "##烁": 17218, "##烂": 17219, "##烃": 17220, "##烈": 17221, "##烊": 17222, "##烏": 17223, "##烘": 17224, "##烙": 17225, "##烛": 17226, "##烟": 17227, "##烤": 17228, "##烦": 17229, "##烧": 17230, "##烨": 17231, "##烩": 17232, "##烫": 17233, "##烬": 17234, "##热": 17235, "##烯": 17236, "##烷": 17237, "##烹": 17238, "##烽": 17239, "##焉": 17240, "##焊": 17241, "##焕": 17242, "##焖": 17243, "##焗": 17244, "##焘": 17245, "##焙": 17246, "##焚": 17247, "##焜": 17248, "##無": 17249, "##焦": 17250, "##焯": 17251, "##焰": 17252, "##焱": 17253, "##然": 17254, "##焼": 17255, "##煅": 17256, "##煉": 17257, "##煊": 17258, "##煌": 17259, "##煎": 17260, "##煒": 17261, "##煖": 17262, "##煙": 17263, "##煜": 17264, "##煞": 17265, "##煤": 17266, "##煥": 17267, "##煦": 17268, "##照": 17269, "##煨": 17270, "##煩": 17271, "##煮": 17272, "##煲": 17273, "##煸": 17274, "##煽": 17275, "##熄": 17276, "##熊": 17277, "##熏": 17278, "##熒": 17279, "##熔": 17280, "##熙": 17281, "##熟": 17282, "##熠": 17283, "##熨": 17284, "##熬": 17285, "##熱": 17286, "##熵": 17287, "##熹": 17288, "##熾": 17289, "##燁": 17290, "##燃": 17291, "##燄": 17292, "##燈": 17293, "##燉": 17294, "##燊": 17295, "##燎": 17296, "##燒": 17297, "##燔": 17298, "##燕": 17299, "##燙": 17300, "##燜": 17301, "##營": 17302, "##燥": 17303, "##燦": 17304, "##燧": 17305, "##燭": 17306, "##燮": 17307, "##燴": 17308, "##燻": 17309, "##燼": 17310, "##燿": 17311, "##爆": 17312, "##爍": 17313, "##爐": 17314, "##爛": 17315, "##爪": 17316, "##爬": 17317, "##爭": 17318, "##爰": 17319, "##爱": 17320, "##爲": 17321, "##爵": 17322, "##父": 17323, "##爷": 17324, "##爸": 17325, "##爹": 17326, "##爺": 17327, "##爻": 17328, "##爽": 17329, "##爾": 17330, "##牆": 17331, "##片": 17332, "##版": 17333, "##牌": 17334, "##牍": 17335, "##牒": 17336, "##牙": 17337, "##牛": 17338, "##牝": 17339, "##牟": 17340, "##牠": 17341, "##牡": 17342, "##牢": 17343, "##牦": 17344, "##牧": 17345, "##物": 17346, "##牯": 17347, "##牲": 17348, "##牴": 17349, "##牵": 17350, "##特": 17351, "##牺": 17352, "##牽": 17353, "##犀": 17354, "##犁": 17355, "##犄": 17356, "##犊": 17357, "##犍": 17358, "##犒": 17359, "##犢": 17360, "##犧": 17361, "##犬": 17362, "##犯": 17363, "##状": 17364, "##犷": 17365, "##犸": 17366, "##犹": 17367, "##狀": 17368, "##狂": 17369, "##狄": 17370, "##狈": 17371, "##狎": 17372, "##狐": 17373, "##狒": 17374, "##狗": 17375, "##狙": 17376, "##狞": 17377, "##狠": 17378, "##狡": 17379, "##狩": 17380, "##独": 17381, "##狭": 17382, "##狮": 17383, "##狰": 17384, "##狱": 17385, "##狸": 17386, "##狹": 17387, "##狼": 17388, "##狽": 17389, "##猎": 17390, "##猕": 17391, "##猖": 17392, "##猗": 17393, "##猙": 17394, "##猛": 17395, "##猜": 17396, "##猝": 17397, "##猥": 17398, "##猩": 17399, "##猪": 17400, "##猫": 17401, "##猬": 17402, "##献": 17403, "##猴": 17404, "##猶": 17405, "##猷": 17406, "##猾": 17407, "##猿": 17408, "##獄": 17409, "##獅": 17410, "##獎": 17411, "##獐": 17412, "##獒": 17413, "##獗": 17414, "##獠": 17415, "##獣": 17416, "##獨": 17417, "##獭": 17418, "##獰": 17419, "##獲": 17420, "##獵": 17421, "##獷": 17422, "##獸": 17423, "##獺": 17424, "##獻": 17425, "##獼": 17426, "##獾": 17427, "##玄": 17428, "##率": 17429, "##玉": 17430, "##王": 17431, "##玑": 17432, "##玖": 17433, "##玛": 17434, "##玟": 17435, "##玠": 17436, "##玥": 17437, "##玩": 17438, "##玫": 17439, "##玮": 17440, "##环": 17441, "##现": 17442, "##玲": 17443, "##玳": 17444, "##玷": 17445, "##玺": 17446, "##玻": 17447, "##珀": 17448, "##珂": 17449, "##珅": 17450, "##珈": 17451, "##珉": 17452, "##珊": 17453, "##珍": 17454, "##珏": 17455, "##珐": 17456, "##珑": 17457, "##珙": 17458, "##珞": 17459, "##珠": 17460, "##珣": 17461, "##珥": 17462, "##珩": 17463, "##珪": 17464, "##班": 17465, "##珮": 17466, "##珲": 17467, "##珺": 17468, "##現": 17469, "##球": 17470, "##琅": 17471, "##理": 17472, "##琇": 17473, "##琉": 17474, "##琊": 17475, "##琍": 17476, "##琏": 17477, "##琐": 17478, "##琛": 17479, "##琢": 17480, "##琥": 17481, "##琦": 17482, "##琨": 17483, "##琪": 17484, "##琬": 17485, "##琮": 17486, "##琰": 17487, "##琲": 17488, "##琳": 17489, "##琴": 17490, "##琵": 17491, "##琶": 17492, "##琺": 17493, "##琼": 17494, "##瑀": 17495, "##瑁": 17496, "##瑄": 17497, "##瑋": 17498, "##瑕": 17499, "##瑗": 17500, "##瑙": 17501, "##瑚": 17502, "##瑛": 17503, "##瑜": 17504, "##瑞": 17505, "##瑟": 17506, "##瑠": 17507, "##瑣": 17508, "##瑤": 17509, "##瑩": 17510, "##瑪": 17511, "##瑯": 17512, "##瑰": 17513, "##瑶": 17514, "##瑾": 17515, "##璀": 17516, "##璁": 17517, "##璃": 17518, "##璇": 17519, "##璉": 17520, "##璋": 17521, "##璎": 17522, "##璐": 17523, "##璜": 17524, "##璞": 17525, "##璟": 17526, "##璧": 17527, "##璨": 17528, "##環": 17529, "##璽": 17530, "##璿": 17531, "##瓊": 17532, "##瓏": 17533, "##瓒": 17534, "##瓜": 17535, "##瓢": 17536, "##瓣": 17537, "##瓤": 17538, "##瓦": 17539, "##瓮": 17540, "##瓯": 17541, "##瓴": 17542, "##瓶": 17543, "##瓷": 17544, "##甄": 17545, "##甌": 17546, "##甕": 17547, "##甘": 17548, "##甙": 17549, "##甚": 17550, "##甜": 17551, "##生": 17552, "##產": 17553, "##産": 17554, "##甥": 17555, "##甦": 17556, "##用": 17557, "##甩": 17558, "##甫": 17559, "##甬": 17560, "##甭": 17561, "##甯": 17562, "##田": 17563, "##由": 17564, "##甲": 17565, "##申": 17566, "##电": 17567, "##男": 17568, "##甸": 17569, "##町": 17570, "##画": 17571, "##甾": 17572, "##畀": 17573, "##畅": 17574, "##界": 17575, "##畏": 17576, "##畑": 17577, "##畔": 17578, "##留": 17579, "##畜": 17580, "##畝": 17581, "##畢": 17582, "##略": 17583, "##畦": 17584, "##番": 17585, "##畫": 17586, "##異": 17587, "##畲": 17588, "##畳": 17589, "##畴": 17590, "##當": 17591, "##畸": 17592, "##畹": 17593, "##畿": 17594, "##疆": 17595, "##疇": 17596, "##疊": 17597, "##疏": 17598, "##疑": 17599, "##疔": 17600, "##疖": 17601, "##疗": 17602, "##疙": 17603, "##疚": 17604, "##疝": 17605, "##疟": 17606, "##疡": 17607, "##疣": 17608, "##疤": 17609, "##疥": 17610, "##疫": 17611, "##疮": 17612, "##疯": 17613, "##疱": 17614, "##疲": 17615, "##疳": 17616, "##疵": 17617, "##疸": 17618, "##疹": 17619, "##疼": 17620, "##疽": 17621, "##疾": 17622, "##痂": 17623, "##病": 17624, "##症": 17625, "##痈": 17626, "##痉": 17627, "##痊": 17628, "##痍": 17629, "##痒": 17630, "##痔": 17631, "##痕": 17632, "##痘": 17633, "##痙": 17634, "##痛": 17635, "##痞": 17636, "##痠": 17637, "##痢": 17638, "##痣": 17639, "##痤": 17640, "##痧": 17641, "##痨": 17642, "##痪": 17643, "##痫": 17644, "##痰": 17645, "##痱": 17646, "##痴": 17647, "##痹": 17648, "##痺": 17649, "##痼": 17650, "##痿": 17651, "##瘀": 17652, "##瘁": 17653, "##瘋": 17654, "##瘍": 17655, "##瘓": 17656, "##瘘": 17657, "##瘙": 17658, "##瘟": 17659, "##瘠": 17660, "##瘡": 17661, "##瘢": 17662, "##瘤": 17663, "##瘦": 17664, "##瘧": 17665, "##瘩": 17666, "##瘪": 17667, "##瘫": 17668, "##瘴": 17669, "##瘸": 17670, "##瘾": 17671, "##療": 17672, "##癇": 17673, "##癌": 17674, "##癒": 17675, "##癖": 17676, "##癜": 17677, "##癞": 17678, "##癡": 17679, "##癢": 17680, "##癣": 17681, "##癥": 17682, "##癫": 17683, "##癬": 17684, "##癮": 17685, "##癱": 17686, "##癲": 17687, "##癸": 17688, "##発": 17689, "##登": 17690, "##發": 17691, "##白": 17692, "##百": 17693, "##皂": 17694, "##的": 17695, "##皆": 17696, "##皇": 17697, "##皈": 17698, "##皋": 17699, "##皎": 17700, "##皑": 17701, "##皓": 17702, "##皖": 17703, "##皙": 17704, "##皚": 17705, "##皮": 17706, "##皰": 17707, "##皱": 17708, "##皴": 17709, "##皺": 17710, "##皿": 17711, "##盂": 17712, "##盃": 17713, "##盅": 17714, "##盆": 17715, "##盈": 17716, "##益": 17717, "##盎": 17718, "##盏": 17719, "##盐": 17720, "##监": 17721, "##盒": 17722, "##盔": 17723, "##盖": 17724, "##盗": 17725, "##盘": 17726, "##盛": 17727, "##盜": 17728, "##盞": 17729, "##盟": 17730, "##盡": 17731, "##監": 17732, "##盤": 17733, "##盥": 17734, "##盧": 17735, "##盪": 17736, "##目": 17737, "##盯": 17738, "##盱": 17739, "##盲": 17740, "##直": 17741, "##相": 17742, "##盹": 17743, "##盼": 17744, "##盾": 17745, "##省": 17746, "##眈": 17747, "##眉": 17748, "##看": 17749, "##県": 17750, "##眙": 17751, "##眞": 17752, "##真": 17753, "##眠": 17754, "##眦": 17755, "##眨": 17756, "##眩": 17757, "##眯": 17758, "##眶": 17759, "##眷": 17760, "##眸": 17761, "##眺": 17762, "##眼": 17763, "##眾": 17764, "##着": 17765, "##睁": 17766, "##睇": 17767, "##睏": 17768, "##睐": 17769, "##睑": 17770, "##睛": 17771, "##睜": 17772, "##睞": 17773, "##睡": 17774, "##睢": 17775, "##督": 17776, "##睥": 17777, "##睦": 17778, "##睨": 17779, "##睪": 17780, "##睫": 17781, "##睬": 17782, "##睹": 17783, "##睽": 17784, "##睾": 17785, "##睿": 17786, "##瞄": 17787, "##瞅": 17788, "##瞇": 17789, "##瞋": 17790, "##瞌": 17791, "##瞎": 17792, "##瞑": 17793, "##瞒": 17794, "##瞓": 17795, "##瞞": 17796, "##瞟": 17797, "##瞠": 17798, "##瞥": 17799, "##瞧": 17800, "##瞩": 17801, "##瞪": 17802, "##瞬": 17803, "##瞭": 17804, "##瞰": 17805, "##瞳": 17806, "##瞻": 17807, "##瞼": 17808, "##瞿": 17809, "##矇": 17810, "##矍": 17811, "##矗": 17812, "##矚": 17813, "##矛": 17814, "##矜": 17815, "##矢": 17816, "##矣": 17817, "##知": 17818, "##矩": 17819, "##矫": 17820, "##短": 17821, "##矮": 17822, "##矯": 17823, "##石": 17824, "##矶": 17825, "##矽": 17826, "##矾": 17827, "##矿": 17828, "##码": 17829, "##砂": 17830, "##砌": 17831, "##砍": 17832, "##砒": 17833, "##研": 17834, "##砖": 17835, "##砗": 17836, "##砚": 17837, "##砝": 17838, "##砣": 17839, "##砥": 17840, "##砧": 17841, "##砭": 17842, "##砰": 17843, "##砲": 17844, "##破": 17845, "##砷": 17846, "##砸": 17847, "##砺": 17848, "##砼": 17849, "##砾": 17850, "##础": 17851, "##硅": 17852, "##硐": 17853, "##硒": 17854, "##硕": 17855, "##硝": 17856, "##硫": 17857, "##硬": 17858, "##确": 17859, "##硯": 17860, "##硼": 17861, "##碁": 17862, "##碇": 17863, "##碉": 17864, "##碌": 17865, "##碍": 17866, "##碎": 17867, "##碑": 17868, "##碓": 17869, "##碗": 17870, "##碘": 17871, "##碚": 17872, "##碛": 17873, "##碟": 17874, "##碣": 17875, "##碧": 17876, "##碩": 17877, "##碰": 17878, "##碱": 17879, "##碳": 17880, "##碴": 17881, "##確": 17882, "##碼": 17883, "##碾": 17884, "##磁": 17885, "##磅": 17886, "##磊": 17887, "##磋": 17888, "##磐": 17889, "##磕": 17890, "##磚": 17891, "##磡": 17892, "##磨": 17893, "##磬": 17894, "##磯": 17895, "##磲": 17896, "##磷": 17897, "##磺": 17898, "##礁": 17899, "##礎": 17900, "##礙": 17901, "##礡": 17902, "##礦": 17903, "##礪": 17904, "##礫": 17905, "##礴": 17906, "##示": 17907, "##礼": 17908, "##社": 17909, "##祀": 17910, "##祁": 17911, "##祂": 17912, "##祇": 17913, "##祈": 17914, "##祉": 17915, "##祎": 17916, "##祐": 17917, "##祕": 17918, "##祖": 17919, "##祗": 17920, "##祚": 17921, "##祛": 17922, "##祜": 17923, "##祝": 17924, "##神": 17925, "##祟": 17926, "##祠": 17927, "##祢": 17928, "##祥": 17929, "##票": 17930, "##祭": 17931, "##祯": 17932, "##祷": 17933, "##祸": 17934, "##祺": 17935, "##祿": 17936, "##禀": 17937, "##禁": 17938, "##禄": 17939, "##禅": 17940, "##禍": 17941, "##禎": 17942, "##福": 17943, "##禛": 17944, "##禦": 17945, "##禧": 17946, "##禪": 17947, "##禮": 17948, "##禱": 17949, "##禹": 17950, "##禺": 17951, "##离": 17952, "##禽": 17953, "##禾": 17954, "##禿": 17955, "##秀": 17956, "##私": 17957, "##秃": 17958, "##秆": 17959, "##秉": 17960, "##秋": 17961, "##种": 17962, "##科": 17963, "##秒": 17964, "##秘": 17965, "##租": 17966, "##秣": 17967, "##秤": 17968, "##秦": 17969, "##秧": 17970, "##秩": 17971, "##秭": 17972, "##积": 17973, "##称": 17974, "##秸": 17975, "##移": 17976, "##秽": 17977, "##稀": 17978, "##稅": 17979, "##程": 17980, "##稍": 17981, "##税": 17982, "##稔": 17983, "##稗": 17984, "##稚": 17985, "##稜": 17986, "##稞": 17987, "##稟": 17988, "##稠": 17989, "##稣": 17990, "##種": 17991, "##稱": 17992, "##稲": 17993, "##稳": 17994, "##稷": 17995, "##稹": 17996, "##稻": 17997, "##稼": 17998, "##稽": 17999, "##稿": 18000, "##穀": 18001, "##穂": 18002, "##穆": 18003, "##穌": 18004, "##積": 18005, "##穎": 18006, "##穗": 18007, "##穢": 18008, "##穩": 18009, "##穫": 18010, "##穴": 18011, "##究": 18012, "##穷": 18013, "##穹": 18014, "##空": 18015, "##穿": 18016, "##突": 18017, "##窃": 18018, "##窄": 18019, "##窈": 18020, "##窍": 18021, "##窑": 18022, "##窒": 18023, "##窓": 18024, "##窕": 18025, "##窖": 18026, "##窗": 18027, "##窘": 18028, "##窜": 18029, "##窝": 18030, "##窟": 18031, "##窠": 18032, "##窥": 18033, "##窦": 18034, "##窨": 18035, "##窩": 18036, "##窪": 18037, "##窮": 18038, "##窯": 18039, "##窺": 18040, "##窿": 18041, "##竄": 18042, "##竅": 18043, "##竇": 18044, "##竊": 18045, "##立": 18046, "##竖": 18047, "##站": 18048, "##竜": 18049, "##竞": 18050, "##竟": 18051, "##章": 18052, "##竣": 18053, "##童": 18054, "##竭": 18055, "##端": 18056, "##競": 18057, "##竹": 18058, "##竺": 18059, "##竽": 18060, "##竿": 18061, "##笃": 18062, "##笆": 18063, "##笈": 18064, "##笋": 18065, "##笏": 18066, "##笑": 18067, "##笔": 18068, "##笙": 18069, "##笛": 18070, "##笞": 18071, "##笠": 18072, "##符": 18073, "##笨": 18074, "##第": 18075, "##笹": 18076, "##笺": 18077, "##笼": 18078, "##筆": 18079, "##等": 18080, "##筊": 18081, "##筋": 18082, "##筍": 18083, "##筏": 18084, "##筐": 18085, "##筑": 18086, "##筒": 18087, "##答": 18088, "##策": 18089, "##筛": 18090, "##筝": 18091, "##筠": 18092, "##筱": 18093, "##筲": 18094, "##筵": 18095, "##筷": 18096, "##筹": 18097, "##签": 18098, "##简": 18099, "##箇": 18100, "##箋": 18101, "##箍": 18102, "##箏": 18103, "##箐": 18104, "##箔": 18105, "##箕": 18106, "##算": 18107, "##箝": 18108, "##管": 18109, "##箩": 18110, "##箫": 18111, "##箭": 18112, "##箱": 18113, "##箴": 18114, "##箸": 18115, "##節": 18116, "##篁": 18117, "##範": 18118, "##篆": 18119, "##篇": 18120, "##築": 18121, "##篑": 18122, "##篓": 18123, "##篙": 18124, "##篝": 18125, "##篠": 18126, "##篡": 18127, "##篤": 18128, "##篩": 18129, "##篪": 18130, "##篮": 18131, "##篱": 18132, "##篷": 18133, "##簇": 18134, "##簌": 18135, "##簍": 18136, "##簡": 18137, "##簦": 18138, "##簧": 18139, "##簪": 18140, "##簫": 18141, "##簷": 18142, "##簸": 18143, "##簽": 18144, "##簾": 18145, "##簿": 18146, "##籁": 18147, "##籃": 18148, "##籌": 18149, "##籍": 18150, "##籐": 18151, "##籟": 18152, "##籠": 18153, "##籤": 18154, "##籬": 18155, "##籮": 18156, "##籲": 18157, "##米": 18158, "##类": 18159, "##籼": 18160, "##籽": 18161, "##粄": 18162, "##粉": 18163, "##粑": 18164, "##粒": 18165, "##粕": 18166, "##粗": 18167, "##粘": 18168, "##粟": 18169, "##粤": 18170, "##粥": 18171, "##粧": 18172, "##粪": 18173, "##粮": 18174, "##粱": 18175, "##粲": 18176, "##粳": 18177, "##粵": 18178, "##粹": 18179, "##粼": 18180, "##粽": 18181, "##精": 18182, "##粿": 18183, "##糅": 18184, "##糊": 18185, "##糍": 18186, "##糕": 18187, "##糖": 18188, "##糗": 18189, "##糙": 18190, "##糜": 18191, "##糞": 18192, "##糟": 18193, "##糠": 18194, "##糧": 18195, "##糬": 18196, "##糯": 18197, "##糰": 18198, "##糸": 18199, "##系": 18200, "##糾": 18201, "##紀": 18202, "##紂": 18203, "##約": 18204, "##紅": 18205, "##紉": 18206, "##紊": 18207, "##紋": 18208, "##納": 18209, "##紐": 18210, "##紓": 18211, "##純": 18212, "##紗": 18213, "##紘": 18214, "##紙": 18215, "##級": 18216, "##紛": 18217, "##紜": 18218, "##素": 18219, "##紡": 18220, "##索": 18221, "##紧": 18222, "##紫": 18223, "##紮": 18224, "##累": 18225, "##細": 18226, "##紳": 18227, "##紹": 18228, "##紺": 18229, "##終": 18230, "##絃": 18231, "##組": 18232, "##絆": 18233, "##経": 18234, "##結": 18235, "##絕": 18236, "##絞": 18237, "##絡": 18238, "##絢": 18239, "##給": 18240, "##絨": 18241, "##絮": 18242, "##統": 18243, "##絲": 18244, "##絳": 18245, "##絵": 18246, "##絶": 18247, "##絹": 18248, "##綁": 18249, "##綏": 18250, "##綑": 18251, "##經": 18252, "##継": 18253, "##続": 18254, "##綜": 18255, "##綠": 18256, "##綢": 18257, "##綦": 18258, "##綫": 18259, "##綬": 18260, "##維": 18261, "##綱": 18262, "##網": 18263, "##綴": 18264, "##綵": 18265, "##綸": 18266, "##綺": 18267, "##綻": 18268, "##綽": 18269, "##綾": 18270, "##綿": 18271, "##緊": 18272, "##緋": 18273, "##総": 18274, "##緑": 18275, "##緒": 18276, "##緘": 18277, "##線": 18278, "##緝": 18279, "##緞": 18280, "##締": 18281, "##緣": 18282, "##編": 18283, "##緩": 18284, "##緬": 18285, "##緯": 18286, "##練": 18287, "##緹": 18288, "##緻": 18289, "##縁": 18290, "##縄": 18291, "##縈": 18292, "##縛": 18293, "##縝": 18294, "##縣": 18295, "##縫": 18296, "##縮": 18297, "##縱": 18298, "##縴": 18299, "##縷": 18300, "##總": 18301, "##績": 18302, "##繁": 18303, "##繃": 18304, "##繆": 18305, "##繇": 18306, "##繋": 18307, "##織": 18308, "##繕": 18309, "##繚": 18310, "##繞": 18311, "##繡": 18312, "##繩": 18313, "##繪": 18314, "##繫": 18315, "##繭": 18316, "##繳": 18317, "##繹": 18318, "##繼": 18319, "##繽": 18320, "##纂": 18321, "##續": 18322, "##纍": 18323, "##纏": 18324, "##纓": 18325, "##纔": 18326, "##纖": 18327, "##纜": 18328, "##纠": 18329, "##红": 18330, "##纣": 18331, "##纤": 18332, "##约": 18333, "##级": 18334, "##纨": 18335, "##纪": 18336, "##纫": 18337, "##纬": 18338, "##纭": 18339, "##纯": 18340, "##纰": 18341, "##纱": 18342, "##纲": 18343, "##纳": 18344, "##纵": 18345, "##纶": 18346, "##纷": 18347, "##纸": 18348, "##纹": 18349, "##纺": 18350, "##纽": 18351, "##纾": 18352, "##线": 18353, "##绀": 18354, "##练": 18355, "##组": 18356, "##绅": 18357, "##细": 18358, "##织": 18359, "##终": 18360, "##绊": 18361, "##绍": 18362, "##绎": 18363, "##经": 18364, "##绑": 18365, "##绒": 18366, "##结": 18367, "##绔": 18368, "##绕": 18369, "##绘": 18370, "##给": 18371, "##绚": 18372, "##绛": 18373, "##络": 18374, "##绝": 18375, "##绞": 18376, "##统": 18377, "##绡": 18378, "##绢": 18379, "##绣": 18380, "##绥": 18381, "##绦": 18382, "##继": 18383, "##绩": 18384, "##绪": 18385, "##绫": 18386, "##续": 18387, "##绮": 18388, "##绯": 18389, "##绰": 18390, "##绳": 18391, "##维": 18392, "##绵": 18393, "##绶": 18394, "##绷": 18395, "##绸": 18396, "##绻": 18397, "##综": 18398, "##绽": 18399, "##绾": 18400, "##绿": 18401, "##缀": 18402, "##缄": 18403, "##缅": 18404, "##缆": 18405, "##缇": 18406, "##缈": 18407, "##缉": 18408, "##缎": 18409, "##缓": 18410, "##缔": 18411, "##缕": 18412, "##编": 18413, "##缘": 18414, "##缙": 18415, "##缚": 18416, "##缜": 18417, "##缝": 18418, "##缠": 18419, "##缢": 18420, "##缤": 18421, "##缥": 18422, "##缨": 18423, "##缩": 18424, "##缪": 18425, "##缭": 18426, "##缮": 18427, "##缰": 18428, "##缱": 18429, "##缴": 18430, "##缸": 18431, "##缺": 18432, "##缽": 18433, "##罂": 18434, "##罄": 18435, "##罌": 18436, "##罐": 18437, "##网": 18438, "##罔": 18439, "##罕": 18440, "##罗": 18441, "##罚": 18442, "##罡": 18443, "##罢": 18444, "##罩": 18445, "##罪": 18446, "##置": 18447, "##罰": 18448, "##署": 18449, "##罵": 18450, "##罷": 18451, "##罹": 18452, "##羁": 18453, "##羅": 18454, "##羈": 18455, "##羊": 18456, "##羌": 18457, "##美": 18458, "##羔": 18459, "##羚": 18460, "##羞": 18461, "##羟": 18462, "##羡": 18463, "##羣": 18464, "##群": 18465, "##羥": 18466, "##羧": 18467, "##羨": 18468, "##義": 18469, "##羯": 18470, "##羲": 18471, "##羸": 18472, "##羹": 18473, "##羽": 18474, "##羿": 18475, "##翁": 18476, "##翅": 18477, "##翊": 18478, "##翌": 18479, "##翎": 18480, "##習": 18481, "##翔": 18482, "##翘": 18483, "##翟": 18484, "##翠": 18485, "##翡": 18486, "##翦": 18487, "##翩": 18488, "##翰": 18489, "##翱": 18490, "##翳": 18491, "##翹": 18492, "##翻": 18493, "##翼": 18494, "##耀": 18495, "##老": 18496, "##考": 18497, "##耄": 18498, "##者": 18499, "##耆": 18500, "##耋": 18501, "##而": 18502, "##耍": 18503, "##耐": 18504, "##耒": 18505, "##耕": 18506, "##耗": 18507, "##耘": 18508, "##耙": 18509, "##耦": 18510, "##耨": 18511, "##耳": 18512, "##耶": 18513, "##耷": 18514, "##耸": 18515, "##耻": 18516, "##耽": 18517, "##耿": 18518, "##聂": 18519, "##聆": 18520, "##聊": 18521, "##聋": 18522, "##职": 18523, "##聒": 18524, "##联": 18525, "##聖": 18526, "##聘": 18527, "##聚": 18528, "##聞": 18529, "##聪": 18530, "##聯": 18531, "##聰": 18532, "##聲": 18533, "##聳": 18534, "##聴": 18535, "##聶": 18536, "##職": 18537, "##聽": 18538, "##聾": 18539, "##聿": 18540, "##肃": 18541, "##肄": 18542, "##肅": 18543, "##肆": 18544, "##肇": 18545, "##肉": 18546, "##肋": 18547, "##肌": 18548, "##肏": 18549, "##肓": 18550, "##肖": 18551, "##肘": 18552, "##肚": 18553, "##肛": 18554, "##肝": 18555, "##肠": 18556, "##股": 18557, "##肢": 18558, "##肤": 18559, "##肥": 18560, "##肩": 18561, "##肪": 18562, "##肮": 18563, "##肯": 18564, "##肱": 18565, "##育": 18566, "##肴": 18567, "##肺": 18568, "##肽": 18569, "##肾": 18570, "##肿": 18571, "##胀": 18572, "##胁": 18573, "##胃": 18574, "##胄": 18575, "##胆": 18576, "##背": 18577, "##胍": 18578, "##胎": 18579, "##胖": 18580, "##胚": 18581, "##胛": 18582, "##胜": 18583, "##胝": 18584, "##胞": 18585, "##胡": 18586, "##胤": 18587, "##胥": 18588, "##胧": 18589, "##胫": 18590, "##胭": 18591, "##胯": 18592, "##胰": 18593, "##胱": 18594, "##胳": 18595, "##胴": 18596, "##胶": 18597, "##胸": 18598, "##胺": 18599, "##能": 18600, "##脂": 18601, "##脅": 18602, "##脆": 18603, "##脇": 18604, "##脈": 18605, "##脉": 18606, "##脊": 18607, "##脍": 18608, "##脏": 18609, "##脐": 18610, "##脑": 18611, "##脓": 18612, "##脖": 18613, "##脘": 18614, "##脚": 18615, "##脛": 18616, "##脣": 18617, "##脩": 18618, "##脫": 18619, "##脯": 18620, "##脱": 18621, "##脲": 18622, "##脳": 18623, "##脸": 18624, "##脹": 18625, "##脾": 18626, "##腆": 18627, "##腈": 18628, "##腊": 18629, "##腋": 18630, "##腌": 18631, "##腎": 18632, "##腐": 18633, "##腑": 18634, "##腓": 18635, "##腔": 18636, "##腕": 18637, "##腥": 18638, "##腦": 18639, "##腩": 18640, "##腫": 18641, "##腭": 18642, "##腮": 18643, "##腰": 18644, "##腱": 18645, "##腳": 18646, "##腴": 18647, "##腸": 18648, "##腹": 18649, "##腺": 18650, "##腻": 18651, "##腼": 18652, "##腾": 18653, "##腿": 18654, "##膀": 18655, "##膈": 18656, "##膊": 18657, "##膏": 18658, "##膑": 18659, "##膘": 18660, "##膚": 18661, "##膛": 18662, "##膜": 18663, "##膝": 18664, "##膠": 18665, "##膦": 18666, "##膨": 18667, "##膩": 18668, "##膳": 18669, "##膺": 18670, "##膻": 18671, "##膽": 18672, "##膾": 18673, "##膿": 18674, "##臀": 18675, "##臂": 18676, "##臃": 18677, "##臆": 18678, "##臉": 18679, "##臊": 18680, "##臍": 18681, "##臓": 18682, "##臘": 18683, "##臟": 18684, "##臣": 18685, "##臥": 18686, "##臧": 18687, "##臨": 18688, "##自": 18689, "##臬": 18690, "##臭": 18691, "##至": 18692, "##致": 18693, "##臺": 18694, "##臻": 18695, "##臼": 18696, "##臾": 18697, "##舀": 18698, "##舂": 18699, "##舅": 18700, "##舆": 18701, "##與": 18702, "##興": 18703, "##舉": 18704, "##舊": 18705, "##舌": 18706, "##舍": 18707, "##舎": 18708, "##舐": 18709, "##舒": 18710, "##舔": 18711, "##舖": 18712, "##舗": 18713, "##舛": 18714, "##舜": 18715, "##舞": 18716, "##舟": 18717, "##航": 18718, "##舫": 18719, "##般": 18720, "##舰": 18721, "##舱": 18722, "##舵": 18723, "##舶": 18724, "##舷": 18725, "##舸": 18726, "##船": 18727, "##舺": 18728, "##舾": 18729, "##艇": 18730, "##艋": 18731, "##艘": 18732, "##艙": 18733, "##艦": 18734, "##艮": 18735, "##良": 18736, "##艰": 18737, "##艱": 18738, "##色": 18739, "##艳": 18740, "##艷": 18741, "##艹": 18742, "##艺": 18743, "##艾": 18744, "##节": 18745, "##芃": 18746, "##芈": 18747, "##芊": 18748, "##芋": 18749, "##芍": 18750, "##芎": 18751, "##芒": 18752, "##芙": 18753, "##芜": 18754, "##芝": 18755, "##芡": 18756, "##芥": 18757, "##芦": 18758, "##芩": 18759, "##芪": 18760, "##芫": 18761, "##芬": 18762, "##芭": 18763, "##芮": 18764, "##芯": 18765, "##花": 18766, "##芳": 18767, "##芷": 18768, "##芸": 18769, "##芹": 18770, "##芻": 18771, "##芽": 18772, "##芾": 18773, "##苁": 18774, "##苄": 18775, "##苇": 18776, "##苋": 18777, "##苍": 18778, "##苏": 18779, "##苑": 18780, "##苒": 18781, "##苓": 18782, "##苔": 18783, "##苕": 18784, "##苗": 18785, "##苛": 18786, "##苜": 18787, "##苞": 18788, "##苟": 18789, "##苡": 18790, "##苣": 18791, "##若": 18792, "##苦": 18793, "##苫": 18794, "##苯": 18795, "##英": 18796, "##苷": 18797, "##苹": 18798, "##苻": 18799, "##茁": 18800, "##茂": 18801, "##范": 18802, "##茄": 18803, "##茅": 18804, "##茉": 18805, "##茎": 18806, "##茏": 18807, "##茗": 18808, "##茜": 18809, "##茧": 18810, "##茨": 18811, "##茫": 18812, "##茬": 18813, "##茭": 18814, "##茯": 18815, "##茱": 18816, "##茲": 18817, "##茴": 18818, "##茵": 18819, "##茶": 18820, "##茸": 18821, "##茹": 18822, "##茼": 18823, "##荀": 18824, "##荃": 18825, "##荆": 18826, "##草": 18827, "##荊": 18828, "##荏": 18829, "##荐": 18830, "##荒": 18831, "##荔": 18832, "##荖": 18833, "##荘": 18834, "##荚": 18835, "##荞": 18836, "##荟": 18837, "##荠": 18838, "##荡": 18839, "##荣": 18840, "##荤": 18841, "##荥": 18842, "##荧": 18843, "##荨": 18844, "##荪": 18845, "##荫": 18846, "##药": 18847, "##荳": 18848, "##荷": 18849, "##荸": 18850, "##荻": 18851, "##荼": 18852, "##荽": 18853, "##莅": 18854, "##莆": 18855, "##莉": 18856, "##莊": 18857, "##莎": 18858, "##莒": 18859, "##莓": 18860, "##莖": 18861, "##莘": 18862, "##莞": 18863, "##莠": 18864, "##莢": 18865, "##莧": 18866, "##莪": 18867, "##莫": 18868, "##莱": 18869, "##莲": 18870, "##莴": 18871, "##获": 18872, "##莹": 18873, "##莺": 18874, "##莽": 18875, "##莿": 18876, "##菀": 18877, "##菁": 18878, "##菅": 18879, "##菇": 18880, "##菈": 18881, "##菊": 18882, "##菌": 18883, "##菏": 18884, "##菓": 18885, "##菖": 18886, "##菘": 18887, "##菜": 18888, "##菟": 18889, "##菠": 18890, "##菡": 18891, "##菩": 18892, "##華": 18893, "##菱": 18894, "##菲": 18895, "##菸": 18896, "##菽": 18897, "##萁": 18898, "##萃": 18899, "##萄": 18900, "##萊": 18901, "##萋": 18902, "##萌": 18903, "##萍": 18904, "##萎": 18905, "##萘": 18906, "##萝": 18907, "##萤": 18908, "##营": 18909, "##萦": 18910, "##萧": 18911, "##萨": 18912, "##萩": 18913, "##萬": 18914, "##萱": 18915, "##萵": 18916, "##萸": 18917, "##萼": 18918, "##落": 18919, "##葆": 18920, "##葉": 18921, "##著": 18922, "##葚": 18923, "##葛": 18924, "##葡": 18925, "##董": 18926, "##葦": 18927, "##葩": 18928, "##葫": 18929, "##葬": 18930, "##葭": 18931, "##葯": 18932, "##葱": 18933, "##葳": 18934, "##葵": 18935, "##葷": 18936, "##葺": 18937, "##蒂": 18938, "##蒋": 18939, "##蒐": 18940, "##蒔": 18941, "##蒙": 18942, "##蒜": 18943, "##蒞": 18944, "##蒟": 18945, "##蒡": 18946, "##蒨": 18947, "##蒲": 18948, "##蒸": 18949, "##蒹": 18950, "##蒻": 18951, "##蒼": 18952, "##蒿": 18953, "##蓁": 18954, "##蓄": 18955, "##蓆": 18956, "##蓉": 18957, "##蓋": 18958, "##蓑": 18959, "##蓓": 18960, "##蓖": 18961, "##蓝": 18962, "##蓟": 18963, "##蓦": 18964, "##蓬": 18965, "##蓮": 18966, "##蓼": 18967, "##蓿": 18968, "##蔑": 18969, "##蔓": 18970, "##蔔": 18971, "##蔗": 18972, "##蔘": 18973, "##蔚": 18974, "##蔡": 18975, "##蔣": 18976, "##蔥": 18977, "##蔫": 18978, "##蔬": 18979, "##蔭": 18980, "##蔵": 18981, "##蔷": 18982, "##蔺": 18983, "##蔻": 18984, "##蔼": 18985, "##蔽": 18986, "##蕁": 18987, "##蕃": 18988, "##蕈": 18989, "##蕉": 18990, "##蕊": 18991, "##蕎": 18992, "##蕙": 18993, "##蕤": 18994, "##蕨": 18995, "##蕩": 18996, "##蕪": 18997, "##蕭": 18998, "##蕲": 18999, "##蕴": 19000, "##蕻": 19001, "##蕾": 19002, "##薄": 19003, "##薅": 19004, "##薇": 19005, "##薈": 19006, "##薊": 19007, "##薏": 19008, "##薑": 19009, "##薔": 19010, "##薙": 19011, "##薛": 19012, "##薦": 19013, "##薨": 19014, "##薩": 19015, "##薪": 19016, "##薬": 19017, "##薯": 19018, "##薰": 19019, "##薹": 19020, "##藉": 19021, "##藍": 19022, "##藏": 19023, "##藐": 19024, "##藓": 19025, "##藕": 19026, "##藜": 19027, "##藝": 19028, "##藤": 19029, "##藥": 19030, "##藩": 19031, "##藹": 19032, "##藻": 19033, "##藿": 19034, "##蘆": 19035, "##蘇": 19036, "##蘊": 19037, "##蘋": 19038, "##蘑": 19039, "##蘚": 19040, "##蘭": 19041, "##蘸": 19042, "##蘼": 19043, "##蘿": 19044, "##虎": 19045, "##虏": 19046, "##虐": 19047, "##虑": 19048, "##虔": 19049, "##處": 19050, "##虚": 19051, "##虛": 19052, "##虜": 19053, "##虞": 19054, "##號": 19055, "##虢": 19056, "##虧": 19057, "##虫": 19058, "##虬": 19059, "##虱": 19060, "##虹": 19061, "##虻": 19062, "##虽": 19063, "##虾": 19064, "##蚀": 19065, "##蚁": 19066, "##蚂": 19067, "##蚊": 19068, "##蚌": 19069, "##蚓": 19070, "##蚕": 19071, "##蚜": 19072, "##蚝": 19073, "##蚣": 19074, "##蚤": 19075, "##蚩": 19076, "##蚪": 19077, "##蚯": 19078, "##蚱": 19079, "##蚵": 19080, "##蛀": 19081, "##蛆": 19082, "##蛇": 19083, "##蛊": 19084, "##蛋": 19085, "##蛎": 19086, "##蛐": 19087, "##蛔": 19088, "##蛙": 19089, "##蛛": 19090, "##蛟": 19091, "##蛤": 19092, "##蛭": 19093, "##蛮": 19094, "##蛰": 19095, "##蛳": 19096, "##蛹": 19097, "##蛻": 19098, "##蛾": 19099, "##蜀": 19100, "##蜂": 19101, "##蜃": 19102, "##蜆": 19103, "##蜇": 19104, "##蜈": 19105, "##蜊": 19106, "##蜍": 19107, "##蜒": 19108, "##蜓": 19109, "##蜕": 19110, "##蜗": 19111, "##蜘": 19112, "##蜚": 19113, "##蜜": 19114, "##蜡": 19115, "##蜢": 19116, "##蜥": 19117, "##蜱": 19118, "##蜴": 19119, "##蜷": 19120, "##蜻": 19121, "##蜿": 19122, "##蝇": 19123, "##蝈": 19124, "##蝉": 19125, "##蝌": 19126, "##蝎": 19127, "##蝕": 19128, "##蝗": 19129, "##蝙": 19130, "##蝟": 19131, "##蝠": 19132, "##蝦": 19133, "##蝨": 19134, "##蝴": 19135, "##蝶": 19136, "##蝸": 19137, "##蝼": 19138, "##螂": 19139, "##螃": 19140, "##融": 19141, "##螞": 19142, "##螢": 19143, "##螨": 19144, "##螯": 19145, "##螳": 19146, "##螺": 19147, "##蟀": 19148, "##蟄": 19149, "##蟆": 19150, "##蟋": 19151, "##蟎": 19152, "##蟑": 19153, "##蟒": 19154, "##蟠": 19155, "##蟬": 19156, "##蟲": 19157, "##蟹": 19158, "##蟻": 19159, "##蟾": 19160, "##蠅": 19161, "##蠍": 19162, "##蠔": 19163, "##蠕": 19164, "##蠛": 19165, "##蠟": 19166, "##蠡": 19167, "##蠢": 19168, "##蠣": 19169, "##蠱": 19170, "##蠶": 19171, "##蠹": 19172, "##蠻": 19173, "##血": 19174, "##衄": 19175, "##衅": 19176, "##衆": 19177, "##行": 19178, "##衍": 19179, "##術": 19180, "##衔": 19181, "##街": 19182, "##衙": 19183, "##衛": 19184, "##衝": 19185, "##衞": 19186, "##衡": 19187, "##衢": 19188, "##衣": 19189, "##补": 19190, "##表": 19191, "##衩": 19192, "##衫": 19193, "##衬": 19194, "##衮": 19195, "##衰": 19196, "##衲": 19197, "##衷": 19198, "##衹": 19199, "##衾": 19200, "##衿": 19201, "##袁": 19202, "##袂": 19203, "##袄": 19204, "##袅": 19205, "##袈": 19206, "##袋": 19207, "##袍": 19208, "##袒": 19209, "##袖": 19210, "##袜": 19211, "##袞": 19212, "##袤": 19213, "##袪": 19214, "##被": 19215, "##袭": 19216, "##袱": 19217, "##裁": 19218, "##裂": 19219, "##装": 19220, "##裆": 19221, "##裊": 19222, "##裏": 19223, "##裔": 19224, "##裕": 19225, "##裘": 19226, "##裙": 19227, "##補": 19228, "##裝": 19229, "##裟": 19230, "##裡": 19231, "##裤": 19232, "##裨": 19233, "##裱": 19234, "##裳": 19235, "##裴": 19236, "##裸": 19237, "##裹": 19238, "##製": 19239, "##裾": 19240, "##褂": 19241, "##複": 19242, "##褐": 19243, "##褒": 19244, "##褓": 19245, "##褔": 19246, "##褚": 19247, "##褥": 19248, "##褪": 19249, "##褫": 19250, "##褲": 19251, "##褶": 19252, "##褻": 19253, "##襁": 19254, "##襄": 19255, "##襟": 19256, "##襠": 19257, "##襪": 19258, "##襬": 19259, "##襯": 19260, "##襲": 19261, "##西": 19262, "##要": 19263, "##覃": 19264, "##覆": 19265, "##覇": 19266, "##見": 19267, "##規": 19268, "##覓": 19269, "##視": 19270, "##覚": 19271, "##覦": 19272, "##覧": 19273, "##親": 19274, "##覬": 19275, "##観": 19276, "##覷": 19277, "##覺": 19278, "##覽": 19279, "##觀": 19280, "##见": 19281, "##观": 19282, "##规": 19283, "##觅": 19284, "##视": 19285, "##览": 19286, "##觉": 19287, "##觊": 19288, "##觎": 19289, "##觐": 19290, "##觑": 19291, "##角": 19292, "##觞": 19293, "##解": 19294, "##觥": 19295, "##触": 19296, "##觸": 19297, "##言": 19298, "##訂": 19299, "##計": 19300, "##訊": 19301, "##討": 19302, "##訓": 19303, "##訕": 19304, "##訖": 19305, "##託": 19306, "##記": 19307, "##訛": 19308, "##訝": 19309, "##訟": 19310, "##訣": 19311, "##訥": 19312, "##訪": 19313, "##設": 19314, "##許": 19315, "##訳": 19316, "##訴": 19317, "##訶": 19318, "##診": 19319, "##註": 19320, "##証": 19321, "##詆": 19322, "##詐": 19323, "##詔": 19324, "##評": 19325, "##詛": 19326, "##詞": 19327, "##詠": 19328, "##詡": 19329, "##詢": 19330, "##詣": 19331, "##試": 19332, "##詩": 19333, "##詫": 19334, "##詬": 19335, "##詭": 19336, "##詮": 19337, "##詰": 19338, "##話": 19339, "##該": 19340, "##詳": 19341, "##詹": 19342, "##詼": 19343, "##誅": 19344, "##誇": 19345, "##誉": 19346, "##誌": 19347, "##認": 19348, "##誓": 19349, "##誕": 19350, "##誘": 19351, "##語": 19352, "##誠": 19353, "##誡": 19354, "##誣": 19355, "##誤": 19356, "##誥": 19357, "##誦": 19358, "##誨": 19359, "##說": 19360, "##説": 19361, "##読": 19362, "##誰": 19363, "##課": 19364, "##誹": 19365, "##誼": 19366, "##調": 19367, "##諄": 19368, "##談": 19369, "##請": 19370, "##諏": 19371, "##諒": 19372, "##論": 19373, "##諗": 19374, "##諜": 19375, "##諡": 19376, "##諦": 19377, "##諧": 19378, "##諫": 19379, "##諭": 19380, "##諮": 19381, "##諱": 19382, "##諳": 19383, "##諷": 19384, "##諸": 19385, "##諺": 19386, "##諾": 19387, "##謀": 19388, "##謁": 19389, "##謂": 19390, "##謄": 19391, "##謊": 19392, "##謎": 19393, "##謐": 19394, "##謔": 19395, "##謗": 19396, "##謙": 19397, "##講": 19398, "##謝": 19399, "##謠": 19400, "##謨": 19401, "##謬": 19402, "##謹": 19403, "##謾": 19404, "##譁": 19405, "##證": 19406, "##譎": 19407, "##譏": 19408, "##識": 19409, "##譙": 19410, "##譚": 19411, "##譜": 19412, "##警": 19413, "##譬": 19414, "##譯": 19415, "##議": 19416, "##譲": 19417, "##譴": 19418, "##護": 19419, "##譽": 19420, "##讀": 19421, "##變": 19422, "##讓": 19423, "##讚": 19424, "##讞": 19425, "##计": 19426, "##订": 19427, "##认": 19428, "##讥": 19429, "##讧": 19430, "##讨": 19431, "##让": 19432, "##讪": 19433, "##讫": 19434, "##训": 19435, "##议": 19436, "##讯": 19437, "##记": 19438, "##讲": 19439, "##讳": 19440, "##讴": 19441, "##讶": 19442, "##讷": 19443, "##许": 19444, "##讹": 19445, "##论": 19446, "##讼": 19447, "##讽": 19448, "##设": 19449, "##访": 19450, "##诀": 19451, "##证": 19452, "##诃": 19453, "##评": 19454, "##诅": 19455, "##识": 19456, "##诈": 19457, "##诉": 19458, "##诊": 19459, "##诋": 19460, "##词": 19461, "##诏": 19462, "##译": 19463, "##试": 19464, "##诗": 19465, "##诘": 19466, "##诙": 19467, "##诚": 19468, "##诛": 19469, "##话": 19470, "##诞": 19471, "##诟": 19472, "##诠": 19473, "##诡": 19474, "##询": 19475, "##诣": 19476, "##诤": 19477, "##该": 19478, "##详": 19479, "##诧": 19480, "##诩": 19481, "##诫": 19482, "##诬": 19483, "##语": 19484, "##误": 19485, "##诰": 19486, "##诱": 19487, "##诲": 19488, "##说": 19489, "##诵": 19490, "##诶": 19491, "##请": 19492, "##诸": 19493, "##诺": 19494, "##读": 19495, "##诽": 19496, "##课": 19497, "##诿": 19498, "##谀": 19499, "##谁": 19500, "##调": 19501, "##谄": 19502, "##谅": 19503, "##谆": 19504, "##谈": 19505, "##谊": 19506, "##谋": 19507, "##谌": 19508, "##谍": 19509, "##谎": 19510, "##谏": 19511, "##谐": 19512, "##谑": 19513, "##谒": 19514, "##谓": 19515, "##谔": 19516, "##谕": 19517, "##谗": 19518, "##谘": 19519, "##谙": 19520, "##谚": 19521, "##谛": 19522, "##谜": 19523, "##谟": 19524, "##谢": 19525, "##谣": 19526, "##谤": 19527, "##谥": 19528, "##谦": 19529, "##谧": 19530, "##谨": 19531, "##谩": 19532, "##谪": 19533, "##谬": 19534, "##谭": 19535, "##谯": 19536, "##谱": 19537, "##谲": 19538, "##谴": 19539, "##谶": 19540, "##谷": 19541, "##豁": 19542, "##豆": 19543, "##豇": 19544, "##豈": 19545, "##豉": 19546, "##豊": 19547, "##豌": 19548, "##豎": 19549, "##豐": 19550, "##豔": 19551, "##豚": 19552, "##象": 19553, "##豢": 19554, "##豪": 19555, "##豫": 19556, "##豬": 19557, "##豹": 19558, "##豺": 19559, "##貂": 19560, "##貅": 19561, "##貌": 19562, "##貓": 19563, "##貔": 19564, "##貘": 19565, "##貝": 19566, "##貞": 19567, "##負": 19568, "##財": 19569, "##貢": 19570, "##貧": 19571, "##貨": 19572, "##販": 19573, "##貪": 19574, "##貫": 19575, "##責": 19576, "##貯": 19577, "##貰": 19578, "##貳": 19579, "##貴": 19580, "##貶": 19581, "##買": 19582, "##貸": 19583, "##費": 19584, "##貼": 19585, "##貽": 19586, "##貿": 19587, "##賀": 19588, "##賁": 19589, "##賂": 19590, "##賃": 19591, "##賄": 19592, "##資": 19593, "##賈": 19594, "##賊": 19595, "##賑": 19596, "##賓": 19597, "##賜": 19598, "##賞": 19599, "##賠": 19600, "##賡": 19601, "##賢": 19602, "##賣": 19603, "##賤": 19604, "##賦": 19605, "##質": 19606, "##賬": 19607, "##賭": 19608, "##賴": 19609, "##賺": 19610, "##購": 19611, "##賽": 19612, "##贅": 19613, "##贈": 19614, "##贊": 19615, "##贍": 19616, "##贏": 19617, "##贓": 19618, "##贖": 19619, "##贛": 19620, "##贝": 19621, "##贞": 19622, "##负": 19623, "##贡": 19624, "##财": 19625, "##责": 19626, "##贤": 19627, "##败": 19628, "##账": 19629, "##货": 19630, "##质": 19631, "##贩": 19632, "##贪": 19633, "##贫": 19634, "##贬": 19635, "##购": 19636, "##贮": 19637, "##贯": 19638, "##贰": 19639, "##贱": 19640, "##贲": 19641, "##贴": 19642, "##贵": 19643, "##贷": 19644, "##贸": 19645, "##费": 19646, "##贺": 19647, "##贻": 19648, "##贼": 19649, "##贾": 19650, "##贿": 19651, "##赁": 19652, "##赂": 19653, "##赃": 19654, "##资": 19655, "##赅": 19656, "##赈": 19657, "##赊": 19658, "##赋": 19659, "##赌": 19660, "##赎": 19661, "##赏": 19662, "##赐": 19663, "##赓": 19664, "##赔": 19665, "##赖": 19666, "##赘": 19667, "##赚": 19668, "##赛": 19669, "##赝": 19670, "##赞": 19671, "##赠": 19672, "##赡": 19673, "##赢": 19674, "##赣": 19675, "##赤": 19676, "##赦": 19677, "##赧": 19678, "##赫": 19679, "##赭": 19680, "##走": 19681, "##赳": 19682, "##赴": 19683, "##赵": 19684, "##赶": 19685, "##起": 19686, "##趁": 19687, "##超": 19688, "##越": 19689, "##趋": 19690, "##趕": 19691, "##趙": 19692, "##趟": 19693, "##趣": 19694, "##趨": 19695, "##足": 19696, "##趴": 19697, "##趵": 19698, "##趸": 19699, "##趺": 19700, "##趾": 19701, "##跃": 19702, "##跄": 19703, "##跆": 19704, "##跋": 19705, "##跌": 19706, "##跎": 19707, "##跑": 19708, "##跖": 19709, "##跚": 19710, "##跛": 19711, "##距": 19712, "##跟": 19713, "##跡": 19714, "##跤": 19715, "##跨": 19716, "##跩": 19717, "##跪": 19718, "##路": 19719, "##跳": 19720, "##践": 19721, "##跷": 19722, "##跹": 19723, "##跺": 19724, "##跻": 19725, "##踉": 19726, "##踊": 19727, "##踌": 19728, "##踏": 19729, "##踐": 19730, "##踝": 19731, "##踞": 19732, "##踟": 19733, "##踢": 19734, "##踩": 19735, "##踪": 19736, "##踮": 19737, "##踱": 19738, "##踴": 19739, "##踵": 19740, "##踹": 19741, "##蹂": 19742, "##蹄": 19743, "##蹇": 19744, "##蹈": 19745, "##蹉": 19746, "##蹊": 19747, "##蹋": 19748, "##蹑": 19749, "##蹒": 19750, "##蹙": 19751, "##蹟": 19752, "##蹣": 19753, "##蹤": 19754, "##蹦": 19755, "##蹩": 19756, "##蹬": 19757, "##蹭": 19758, "##蹲": 19759, "##蹴": 19760, "##蹶": 19761, "##蹺": 19762, "##蹼": 19763, "##蹿": 19764, "##躁": 19765, "##躇": 19766, "##躉": 19767, "##躊": 19768, "##躋": 19769, "##躍": 19770, "##躏": 19771, "##躪": 19772, "##身": 19773, "##躬": 19774, "##躯": 19775, "##躲": 19776, "##躺": 19777, "##軀": 19778, "##車": 19779, "##軋": 19780, "##軌": 19781, "##軍": 19782, "##軒": 19783, "##軟": 19784, "##転": 19785, "##軸": 19786, "##軼": 19787, "##軽": 19788, "##軾": 19789, "##較": 19790, "##載": 19791, "##輒": 19792, "##輓": 19793, "##輔": 19794, "##輕": 19795, "##輛": 19796, "##輝": 19797, "##輟": 19798, "##輩": 19799, "##輪": 19800, "##輯": 19801, "##輸": 19802, "##輻": 19803, "##輾": 19804, "##輿": 19805, "##轄": 19806, "##轅": 19807, "##轆": 19808, "##轉": 19809, "##轍": 19810, "##轎": 19811, "##轟": 19812, "##车": 19813, "##轧": 19814, "##轨": 19815, "##轩": 19816, "##转": 19817, "##轭": 19818, "##轮": 19819, "##软": 19820, "##轰": 19821, "##轲": 19822, "##轴": 19823, "##轶": 19824, "##轻": 19825, "##轼": 19826, "##载": 19827, "##轿": 19828, "##较": 19829, "##辄": 19830, "##辅": 19831, "##辆": 19832, "##辇": 19833, "##辈": 19834, "##辉": 19835, "##辊": 19836, "##辍": 19837, "##辐": 19838, "##辑": 19839, "##输": 19840, "##辕": 19841, "##辖": 19842, "##辗": 19843, "##辘": 19844, "##辙": 19845, "##辛": 19846, "##辜": 19847, "##辞": 19848, "##辟": 19849, "##辣": 19850, "##辦": 19851, "##辨": 19852, "##辩": 19853, "##辫": 19854, "##辭": 19855, "##辮": 19856, "##辯": 19857, "##辰": 19858, "##辱": 19859, "##農": 19860, "##边": 19861, "##辺": 19862, "##辻": 19863, "##込": 19864, "##辽": 19865, "##达": 19866, "##迁": 19867, "##迂": 19868, "##迄": 19869, "##迅": 19870, "##过": 19871, "##迈": 19872, "##迎": 19873, "##运": 19874, "##近": 19875, "##返": 19876, "##还": 19877, "##这": 19878, "##进": 19879, "##远": 19880, "##违": 19881, "##连": 19882, "##迟": 19883, "##迢": 19884, "##迤": 19885, "##迥": 19886, "##迦": 19887, "##迩": 19888, "##迪": 19889, "##迫": 19890, "##迭": 19891, "##述": 19892, "##迴": 19893, "##迷": 19894, "##迸": 19895, "##迹": 19896, "##迺": 19897, "##追": 19898, "##退": 19899, "##送": 19900, "##适": 19901, "##逃": 19902, "##逅": 19903, "##逆": 19904, "##选": 19905, "##逊": 19906, "##逍": 19907, "##透": 19908, "##逐": 19909, "##递": 19910, "##途": 19911, "##逕": 19912, "##逗": 19913, "##這": 19914, "##通": 19915, "##逛": 19916, "##逝": 19917, "##逞": 19918, "##速": 19919, "##造": 19920, "##逢": 19921, "##連": 19922, "##逮": 19923, "##週": 19924, "##進": 19925, "##逵": 19926, "##逶": 19927, "##逸": 19928, "##逻": 19929, "##逼": 19930, "##逾": 19931, "##遁": 19932, "##遂": 19933, "##遅": 19934, "##遇": 19935, "##遊": 19936, "##運": 19937, "##遍": 19938, "##過": 19939, "##遏": 19940, "##遐": 19941, "##遑": 19942, "##遒": 19943, "##道": 19944, "##達": 19945, "##違": 19946, "##遗": 19947, "##遙": 19948, "##遛": 19949, "##遜": 19950, "##遞": 19951, "##遠": 19952, "##遢": 19953, "##遣": 19954, "##遥": 19955, "##遨": 19956, "##適": 19957, "##遭": 19958, "##遮": 19959, "##遲": 19960, "##遴": 19961, "##遵": 19962, "##遶": 19963, "##遷": 19964, "##選": 19965, "##遺": 19966, "##遼": 19967, "##遽": 19968, "##避": 19969, "##邀": 19970, "##邁": 19971, "##邂": 19972, "##邃": 19973, "##還": 19974, "##邇": 19975, "##邈": 19976, "##邊": 19977, "##邋": 19978, "##邏": 19979, "##邑": 19980, "##邓": 19981, "##邕": 19982, "##邛": 19983, "##邝": 19984, "##邢": 19985, "##那": 19986, "##邦": 19987, "##邨": 19988, "##邪": 19989, "##邬": 19990, "##邮": 19991, "##邯": 19992, "##邰": 19993, "##邱": 19994, "##邳": 19995, "##邵": 19996, "##邸": 19997, "##邹": 19998, "##邺": 19999, "##邻": 20000, "##郁": 20001, "##郅": 20002, "##郊": 20003, "##郎": 20004, "##郑": 20005, "##郜": 20006, "##郝": 20007, "##郡": 20008, "##郢": 20009, "##郤": 20010, "##郦": 20011, "##郧": 20012, "##部": 20013, "##郫": 20014, "##郭": 20015, "##郴": 20016, "##郵": 20017, "##郷": 20018, "##郸": 20019, "##都": 20020, "##鄂": 20021, "##鄉": 20022, "##鄒": 20023, "##鄔": 20024, "##鄙": 20025, "##鄞": 20026, "##鄢": 20027, "##鄧": 20028, "##鄭": 20029, "##鄰": 20030, "##鄱": 20031, "##鄲": 20032, "##鄺": 20033, "##酉": 20034, "##酊": 20035, "##酋": 20036, "##酌": 20037, "##配": 20038, "##酐": 20039, "##酒": 20040, "##酗": 20041, "##酚": 20042, "##酝": 20043, "##酢": 20044, "##酣": 20045, "##酥": 20046, "##酩": 20047, "##酪": 20048, "##酬": 20049, "##酮": 20050, "##酯": 20051, "##酰": 20052, "##酱": 20053, "##酵": 20054, "##酶": 20055, "##酷": 20056, "##酸": 20057, "##酿": 20058, "##醃": 20059, "##醇": 20060, "##醉": 20061, "##醋": 20062, "##醍": 20063, "##醐": 20064, "##醒": 20065, "##醚": 20066, "##醛": 20067, "##醜": 20068, "##醞": 20069, "##醣": 20070, "##醪": 20071, "##醫": 20072, "##醬": 20073, "##醮": 20074, "##醯": 20075, "##醴": 20076, "##醺": 20077, "##釀": 20078, "##釁": 20079, "##采": 20080, "##釉": 20081, "##释": 20082, "##釋": 20083, "##里": 20084, "##重": 20085, "##野": 20086, "##量": 20087, "##釐": 20088, "##金": 20089, "##釗": 20090, "##釘": 20091, "##釜": 20092, "##針": 20093, "##釣": 20094, "##釦": 20095, "##釧": 20096, "##釵": 20097, "##鈀": 20098, "##鈉": 20099, "##鈍": 20100, "##鈎": 20101, "##鈔": 20102, "##鈕": 20103, "##鈞": 20104, "##鈣": 20105, "##鈦": 20106, "##鈪": 20107, "##鈴": 20108, "##鈺": 20109, "##鈾": 20110, "##鉀": 20111, "##鉄": 20112, "##鉅": 20113, "##鉉": 20114, "##鉑": 20115, "##鉗": 20116, "##鉚": 20117, "##鉛": 20118, "##鉤": 20119, "##鉴": 20120, "##鉻": 20121, "##銀": 20122, "##銃": 20123, "##銅": 20124, "##銑": 20125, "##銓": 20126, "##銖": 20127, "##銘": 20128, "##銜": 20129, "##銬": 20130, "##銭": 20131, "##銮": 20132, "##銳": 20133, "##銷": 20134, "##銹": 20135, "##鋁": 20136, "##鋅": 20137, "##鋒": 20138, "##鋤": 20139, "##鋪": 20140, "##鋰": 20141, "##鋸": 20142, "##鋼": 20143, "##錄": 20144, "##錐": 20145, "##錘": 20146, "##錚": 20147, "##錠": 20148, "##錢": 20149, "##錦": 20150, "##錨": 20151, "##錫": 20152, "##錮": 20153, "##錯": 20154, "##録": 20155, "##錳": 20156, "##錶": 20157, "##鍊": 20158, "##鍋": 20159, "##鍍": 20160, "##鍛": 20161, "##鍥": 20162, "##鍰": 20163, "##鍵": 20164, "##鍺": 20165, "##鍾": 20166, "##鎂": 20167, "##鎊": 20168, "##鎌": 20169, "##鎏": 20170, "##鎔": 20171, "##鎖": 20172, "##鎗": 20173, "##鎚": 20174, "##鎧": 20175, "##鎬": 20176, "##鎮": 20177, "##鎳": 20178, "##鏈": 20179, "##鏖": 20180, "##鏗": 20181, "##鏘": 20182, "##鏞": 20183, "##鏟": 20184, "##鏡": 20185, "##鏢": 20186, "##鏤": 20187, "##鏽": 20188, "##鐘": 20189, "##鐮": 20190, "##鐲": 20191, "##鐳": 20192, "##鐵": 20193, "##鐸": 20194, "##鐺": 20195, "##鑄": 20196, "##鑊": 20197, "##鑑": 20198, "##鑒": 20199, "##鑣": 20200, "##鑫": 20201, "##鑰": 20202, "##鑲": 20203, "##鑼": 20204, "##鑽": 20205, "##鑾": 20206, "##鑿": 20207, "##针": 20208, "##钉": 20209, "##钊": 20210, "##钎": 20211, "##钏": 20212, "##钒": 20213, "##钓": 20214, "##钗": 20215, "##钙": 20216, "##钛": 20217, "##钜": 20218, "##钝": 20219, "##钞": 20220, "##钟": 20221, "##钠": 20222, "##钡": 20223, "##钢": 20224, "##钣": 20225, "##钤": 20226, "##钥": 20227, "##钦": 20228, "##钧": 20229, "##钨": 20230, "##钩": 20231, "##钮": 20232, "##钯": 20233, "##钰": 20234, "##钱": 20235, "##钳": 20236, "##钴": 20237, "##钵": 20238, "##钺": 20239, "##钻": 20240, "##钼": 20241, "##钾": 20242, "##钿": 20243, "##铀": 20244, "##铁": 20245, "##铂": 20246, "##铃": 20247, "##铄": 20248, "##铅": 20249, "##铆": 20250, "##铉": 20251, "##铎": 20252, "##铐": 20253, "##铛": 20254, "##铜": 20255, "##铝": 20256, "##铠": 20257, "##铡": 20258, "##铢": 20259, "##铣": 20260, "##铤": 20261, "##铨": 20262, "##铩": 20263, "##铬": 20264, "##铭": 20265, "##铮": 20266, "##铰": 20267, "##铲": 20268, "##铵": 20269, "##银": 20270, "##铸": 20271, "##铺": 20272, "##链": 20273, "##铿": 20274, "##销": 20275, "##锁": 20276, "##锂": 20277, "##锄": 20278, "##锅": 20279, "##锆": 20280, "##锈": 20281, "##锉": 20282, "##锋": 20283, "##锌": 20284, "##锏": 20285, "##锐": 20286, "##锑": 20287, "##错": 20288, "##锚": 20289, "##锟": 20290, "##锡": 20291, "##锢": 20292, "##锣": 20293, "##锤": 20294, "##锥": 20295, "##锦": 20296, "##锭": 20297, "##键": 20298, "##锯": 20299, "##锰": 20300, "##锲": 20301, "##锵": 20302, "##锹": 20303, "##锺": 20304, "##锻": 20305, "##镀": 20306, "##镁": 20307, "##镂": 20308, "##镇": 20309, "##镉": 20310, "##镌": 20311, "##镍": 20312, "##镐": 20313, "##镑": 20314, "##镕": 20315, "##镖": 20316, "##镗": 20317, "##镛": 20318, "##镜": 20319, "##镣": 20320, "##镭": 20321, "##镯": 20322, "##镰": 20323, "##镳": 20324, "##镶": 20325, "##長": 20326, "##长": 20327, "##門": 20328, "##閃": 20329, "##閉": 20330, "##開": 20331, "##閎": 20332, "##閏": 20333, "##閑": 20334, "##閒": 20335, "##間": 20336, "##閔": 20337, "##閘": 20338, "##閡": 20339, "##関": 20340, "##閣": 20341, "##閥": 20342, "##閨": 20343, "##閩": 20344, "##閱": 20345, "##閲": 20346, "##閹": 20347, "##閻": 20348, "##閾": 20349, "##闆": 20350, "##闇": 20351, "##闊": 20352, "##闌": 20353, "##闍": 20354, "##闔": 20355, "##闕": 20356, "##闖": 20357, "##闘": 20358, "##關": 20359, "##闡": 20360, "##闢": 20361, "##门": 20362, "##闪": 20363, "##闫": 20364, "##闭": 20365, "##问": 20366, "##闯": 20367, "##闰": 20368, "##闲": 20369, "##间": 20370, "##闵": 20371, "##闷": 20372, "##闸": 20373, "##闹": 20374, "##闺": 20375, "##闻": 20376, "##闽": 20377, "##闾": 20378, "##阀": 20379, "##阁": 20380, "##阂": 20381, "##阅": 20382, "##阆": 20383, "##阇": 20384, "##阈": 20385, "##阉": 20386, "##阎": 20387, "##阐": 20388, "##阑": 20389, "##阔": 20390, "##阕": 20391, "##阖": 20392, "##阙": 20393, "##阚": 20394, "##阜": 20395, "##队": 20396, "##阡": 20397, "##阪": 20398, "##阮": 20399, "##阱": 20400, "##防": 20401, "##阳": 20402, "##阴": 20403, "##阵": 20404, "##阶": 20405, "##阻": 20406, "##阿": 20407, "##陀": 20408, "##陂": 20409, "##附": 20410, "##际": 20411, "##陆": 20412, "##陇": 20413, "##陈": 20414, "##陋": 20415, "##陌": 20416, "##降": 20417, "##限": 20418, "##陕": 20419, "##陛": 20420, "##陝": 20421, "##陞": 20422, "##陟": 20423, "##陡": 20424, "##院": 20425, "##陣": 20426, "##除": 20427, "##陨": 20428, "##险": 20429, "##陪": 20430, "##陰": 20431, "##陲": 20432, "##陳": 20433, "##陵": 20434, "##陶": 20435, "##陷": 20436, "##陸": 20437, "##険": 20438, "##陽": 20439, "##隅": 20440, "##隆": 20441, "##隈": 20442, "##隊": 20443, "##隋": 20444, "##隍": 20445, "##階": 20446, "##随": 20447, "##隐": 20448, "##隔": 20449, "##隕": 20450, "##隘": 20451, "##隙": 20452, "##際": 20453, "##障": 20454, "##隠": 20455, "##隣": 20456, "##隧": 20457, "##隨": 20458, "##險": 20459, "##隱": 20460, "##隴": 20461, "##隶": 20462, "##隸": 20463, "##隻": 20464, "##隼": 20465, "##隽": 20466, "##难": 20467, "##雀": 20468, "##雁": 20469, "##雄": 20470, "##雅": 20471, "##集": 20472, "##雇": 20473, "##雉": 20474, "##雋": 20475, "##雌": 20476, "##雍": 20477, "##雎": 20478, "##雏": 20479, "##雑": 20480, "##雒": 20481, "##雕": 20482, "##雖": 20483, "##雙": 20484, "##雛": 20485, "##雜": 20486, "##雞": 20487, "##離": 20488, "##難": 20489, "##雨": 20490, "##雪": 20491, "##雯": 20492, "##雰": 20493, "##雲": 20494, "##雳": 20495, "##零": 20496, "##雷": 20497, "##雹": 20498, "##電": 20499, "##雾": 20500, "##需": 20501, "##霁": 20502, "##霄": 20503, "##霆": 20504, "##震": 20505, "##霈": 20506, "##霉": 20507, "##霊": 20508, "##霍": 20509, "##霎": 20510, "##霏": 20511, "##霑": 20512, "##霓": 20513, "##霖": 20514, "##霜": 20515, "##霞": 20516, "##霧": 20517, "##霭": 20518, "##霰": 20519, "##露": 20520, "##霸": 20521, "##霹": 20522, "##霽": 20523, "##霾": 20524, "##靂": 20525, "##靄": 20526, "##靈": 20527, "##青": 20528, "##靓": 20529, "##靖": 20530, "##静": 20531, "##靚": 20532, "##靛": 20533, "##靜": 20534, "##非": 20535, "##靠": 20536, "##靡": 20537, "##面": 20538, "##靥": 20539, "##靦": 20540, "##革": 20541, "##靳": 20542, "##靴": 20543, "##靶": 20544, "##靼": 20545, "##鞅": 20546, "##鞋": 20547, "##鞍": 20548, "##鞏": 20549, "##鞑": 20550, "##鞘": 20551, "##鞠": 20552, "##鞣": 20553, "##鞦": 20554, "##鞭": 20555, "##韆": 20556, "##韋": 20557, "##韌": 20558, "##韓": 20559, "##韜": 20560, "##韦": 20561, "##韧": 20562, "##韩": 20563, "##韬": 20564, "##韭": 20565, "##音": 20566, "##韵": 20567, "##韶": 20568, "##韻": 20569, "##響": 20570, "##頁": 20571, "##頂": 20572, "##頃": 20573, "##項": 20574, "##順": 20575, "##須": 20576, "##頌": 20577, "##預": 20578, "##頑": 20579, "##頒": 20580, "##頓": 20581, "##頗": 20582, "##領": 20583, "##頜": 20584, "##頡": 20585, "##頤": 20586, "##頫": 20587, "##頭": 20588, "##頰": 20589, "##頷": 20590, "##頸": 20591, "##頹": 20592, "##頻": 20593, "##頼": 20594, "##顆": 20595, "##題": 20596, "##額": 20597, "##顎": 20598, "##顏": 20599, "##顔": 20600, "##願": 20601, "##顛": 20602, "##類": 20603, "##顧": 20604, "##顫": 20605, "##顯": 20606, "##顱": 20607, "##顴": 20608, "##页": 20609, "##顶": 20610, "##顷": 20611, "##项": 20612, "##顺": 20613, "##须": 20614, "##顼": 20615, "##顽": 20616, "##顾": 20617, "##顿": 20618, "##颁": 20619, "##颂": 20620, "##预": 20621, "##颅": 20622, "##领": 20623, "##颇": 20624, "##颈": 20625, "##颉": 20626, "##颊": 20627, "##颌": 20628, "##颍": 20629, "##颐": 20630, "##频": 20631, "##颓": 20632, "##颔": 20633, "##颖": 20634, "##颗": 20635, "##题": 20636, "##颚": 20637, "##颛": 20638, "##颜": 20639, "##额": 20640, "##颞": 20641, "##颠": 20642, "##颡": 20643, "##颢": 20644, "##颤": 20645, "##颦": 20646, "##颧": 20647, "##風": 20648, "##颯": 20649, "##颱": 20650, "##颳": 20651, "##颶": 20652, "##颼": 20653, "##飄": 20654, "##飆": 20655, "##风": 20656, "##飒": 20657, "##飓": 20658, "##飕": 20659, "##飘": 20660, "##飙": 20661, "##飚": 20662, "##飛": 20663, "##飞": 20664, "##食": 20665, "##飢": 20666, "##飨": 20667, "##飩": 20668, "##飪": 20669, "##飯": 20670, "##飲": 20671, "##飼": 20672, "##飽": 20673, "##飾": 20674, "##餃": 20675, "##餅": 20676, "##餉": 20677, "##養": 20678, "##餌": 20679, "##餐": 20680, "##餒": 20681, "##餓": 20682, "##餘": 20683, "##餚": 20684, "##餛": 20685, "##餞": 20686, "##餡": 20687, "##館": 20688, "##餮": 20689, "##餵": 20690, "##餾": 20691, "##饅": 20692, "##饈": 20693, "##饋": 20694, "##饌": 20695, "##饍": 20696, "##饑": 20697, "##饒": 20698, "##饕": 20699, "##饗": 20700, "##饞": 20701, "##饥": 20702, "##饨": 20703, "##饪": 20704, "##饬": 20705, "##饭": 20706, "##饮": 20707, "##饯": 20708, "##饰": 20709, "##饱": 20710, "##饲": 20711, "##饴": 20712, "##饵": 20713, "##饶": 20714, "##饷": 20715, "##饺": 20716, "##饼": 20717, "##饽": 20718, "##饿": 20719, "##馀": 20720, "##馁": 20721, "##馄": 20722, "##馅": 20723, "##馆": 20724, "##馈": 20725, "##馋": 20726, "##馍": 20727, "##馏": 20728, "##馒": 20729, "##馔": 20730, "##首": 20731, "##馗": 20732, "##香": 20733, "##馥": 20734, "##馨": 20735, "##馬": 20736, "##馭": 20737, "##馮": 20738, "##馳": 20739, "##馴": 20740, "##駁": 20741, "##駄": 20742, "##駅": 20743, "##駆": 20744, "##駐": 20745, "##駒": 20746, "##駕": 20747, "##駛": 20748, "##駝": 20749, "##駭": 20750, "##駱": 20751, "##駿": 20752, "##騁": 20753, "##騎": 20754, "##騏": 20755, "##験": 20756, "##騙": 20757, "##騨": 20758, "##騰": 20759, "##騷": 20760, "##驀": 20761, "##驅": 20762, "##驊": 20763, "##驍": 20764, "##驒": 20765, "##驕": 20766, "##驗": 20767, "##驚": 20768, "##驛": 20769, "##驟": 20770, "##驢": 20771, "##驥": 20772, "##马": 20773, "##驭": 20774, "##驮": 20775, "##驯": 20776, "##驰": 20777, "##驱": 20778, "##驳": 20779, "##驴": 20780, "##驶": 20781, "##驷": 20782, "##驸": 20783, "##驹": 20784, "##驻": 20785, "##驼": 20786, "##驾": 20787, "##驿": 20788, "##骁": 20789, "##骂": 20790, "##骄": 20791, "##骅": 20792, "##骆": 20793, "##骇": 20794, "##骈": 20795, "##骊": 20796, "##骋": 20797, "##验": 20798, "##骏": 20799, "##骐": 20800, "##骑": 20801, "##骗": 20802, "##骚": 20803, "##骛": 20804, "##骜": 20805, "##骞": 20806, "##骠": 20807, "##骡": 20808, "##骤": 20809, "##骥": 20810, "##骧": 20811, "##骨": 20812, "##骯": 20813, "##骰": 20814, "##骶": 20815, "##骷": 20816, "##骸": 20817, "##骼": 20818, "##髂": 20819, "##髅": 20820, "##髋": 20821, "##髏": 20822, "##髒": 20823, "##髓": 20824, "##體": 20825, "##髖": 20826, "##高": 20827, "##髦": 20828, "##髪": 20829, "##髮": 20830, "##髯": 20831, "##髻": 20832, "##鬃": 20833, "##鬆": 20834, "##鬍": 20835, "##鬓": 20836, "##鬚": 20837, "##鬟": 20838, "##鬢": 20839, "##鬣": 20840, "##鬥": 20841, "##鬧": 20842, "##鬱": 20843, "##鬼": 20844, "##魁": 20845, "##魂": 20846, "##魄": 20847, "##魅": 20848, "##魇": 20849, "##魍": 20850, "##魏": 20851, "##魔": 20852, "##魘": 20853, "##魚": 20854, "##魯": 20855, "##魷": 20856, "##鮑": 20857, "##鮨": 20858, "##鮪": 20859, "##鮭": 20860, "##鮮": 20861, "##鯉": 20862, "##鯊": 20863, "##鯖": 20864, "##鯛": 20865, "##鯨": 20866, "##鯰": 20867, "##鯽": 20868, "##鰍": 20869, "##鰓": 20870, "##鰭": 20871, "##鰲": 20872, "##鰻": 20873, "##鰾": 20874, "##鱈": 20875, "##鱉": 20876, "##鱔": 20877, "##鱗": 20878, "##鱷": 20879, "##鱸": 20880, "##鱼": 20881, "##鱿": 20882, "##鲁": 20883, "##鲈": 20884, "##鲍": 20885, "##鲑": 20886, "##鲛": 20887, "##鲜": 20888, "##鲟": 20889, "##鲢": 20890, "##鲤": 20891, "##鲨": 20892, "##鲫": 20893, "##鲱": 20894, "##鲲": 20895, "##鲶": 20896, "##鲷": 20897, "##鲸": 20898, "##鳃": 20899, "##鳄": 20900, "##鳅": 20901, "##鳌": 20902, "##鳍": 20903, "##鳕": 20904, "##鳖": 20905, "##鳗": 20906, "##鳝": 20907, "##鳞": 20908, "##鳥": 20909, "##鳩": 20910, "##鳳": 20911, "##鳴": 20912, "##鳶": 20913, "##鴉": 20914, "##鴕": 20915, "##鴛": 20916, "##鴦": 20917, "##鴨": 20918, "##鴻": 20919, "##鴿": 20920, "##鵑": 20921, "##鵜": 20922, "##鵝": 20923, "##鵡": 20924, "##鵬": 20925, "##鵰": 20926, "##鵲": 20927, "##鶘": 20928, "##鶩": 20929, "##鶯": 20930, "##鶴": 20931, "##鷗": 20932, "##鷲": 20933, "##鷹": 20934, "##鷺": 20935, "##鸚": 20936, "##鸞": 20937, "##鸟": 20938, "##鸠": 20939, "##鸡": 20940, "##鸢": 20941, "##鸣": 20942, "##鸥": 20943, "##鸦": 20944, "##鸨": 20945, "##鸪": 20946, "##鸭": 20947, "##鸯": 20948, "##鸳": 20949, "##鸵": 20950, "##鸽": 20951, "##鸾": 20952, "##鸿": 20953, "##鹂": 20954, "##鹃": 20955, "##鹄": 20956, "##鹅": 20957, "##鹈": 20958, "##鹉": 20959, "##鹊": 20960, "##鹌": 20961, "##鹏": 20962, "##鹑": 20963, "##鹕": 20964, "##鹘": 20965, "##鹜": 20966, "##鹞": 20967, "##鹤": 20968, "##鹦": 20969, "##鹧": 20970, "##鹫": 20971, "##鹭": 20972, "##鹰": 20973, "##鹳": 20974, "##鹵": 20975, "##鹹": 20976, "##鹼": 20977, "##鹽": 20978, "##鹿": 20979, "##麂": 20980, "##麋": 20981, "##麒": 20982, "##麓": 20983, "##麗": 20984, "##麝": 20985, "##麟": 20986, "##麥": 20987, "##麦": 20988, "##麩": 20989, "##麴": 20990, "##麵": 20991, "##麸": 20992, "##麺": 20993, "##麻": 20994, "##麼": 20995, "##麽": 20996, "##麾": 20997, "##黃": 20998, "##黄": 20999, "##黍": 21000, "##黎": 21001, "##黏": 21002, "##黑": 21003, "##黒": 21004, "##黔": 21005, "##默": 21006, "##黛": 21007, "##黜": 21008, "##黝": 21009, "##點": 21010, "##黠": 21011, "##黨": 21012, "##黯": 21013, "##黴": 21014, "##鼋": 21015, "##鼎": 21016, "##鼐": 21017, "##鼓": 21018, "##鼠": 21019, "##鼬": 21020, "##鼹": 21021, "##鼻": 21022, "##鼾": 21023, "##齁": 21024, "##齊": 21025, "##齋": 21026, "##齐": 21027, "##齒": 21028, "##齡": 21029, "##齢": 21030, "##齣": 21031, "##齦": 21032, "##齿": 21033, "##龄": 21034, "##龅": 21035, "##龈": 21036, "##龊": 21037, "##龋": 21038, "##龌": 21039, "##龍": 21040, "##龐": 21041, "##龔": 21042, "##龕": 21043, "##龙": 21044, "##龚": 21045, "##龛": 21046, "##龜": 21047, "##龟": 21048, "##👍": 21124, "##🔥": 21125, "##😂": 21126, "##😎": 21127, "##︰": 21049, "##︱": 21050, "##︶": 21051, "##︿": 21052, "##﹁": 21053, "##﹂": 21054, "##﹍": 21055, "##﹏": 21056, "##﹐": 21057, "##﹑": 21058, "##﹒": 21059, "##﹔": 21060, "##﹕": 21061, "##﹖": 21062, "##﹗": 21063, "##﹙": 21064, "##﹚": 21065, "##﹝": 21066, "##﹞": 21067, "##﹡": 21068, "##﹣": 21069, "##!": 21070, "##"": 21071, "###": 21072, "##$": 21073, "##%": 21074, "##&": 21075, "##'": 21076, "##(": 21077, "##)": 21078, "##*": 21079, "##+": 11267, "##,": 21080, "##-": 21081, "##.": 21082, "##/": 21083, "##0": 8569, "##00": 9885, "##1": 8939, "##10": 13117, "##2": 8929, "##3": 9089, "##4": 9484, "##5": 8901, "##6": 9234, "##7": 9163, "##8": 9414, "##9": 9174, "##:": 21084, "##;": 21085, "##<": 21086, "##=": 12092, "##>": 11628, "##?": 21087, "##@": 21088, "##[": 21089, "##\": 21090, "##]": 21091, "##^": 21092, "##_": 21093, "##`": 21094, "##a": 10094, "##b": 12641, "##c": 10675, "##d": 9835, "##e": 10726, "##f": 21095, "##g": 11197, "##h": 21096, "##i": 12381, "##j": 21097, "##k": 10981, "##l": 12035, "##m": 9295, "##n": 11977, "##o": 9940, "##p": 10748, "##q": 12826, "##r": 11586, "##s": 10721, "##t": 11766, "##u": 21098, "##v": 12420, "##w": 21099, "##x": 13047, "##y": 12166, "##z": 21100, "##{": 21101, "##|": 9815, "##}": 21102, "##~": 8694, "##~1": 12427, "##~10": 10953, "##~17": 12405, "##~20": 12078, "##~3": 12617, "##~5": 11864, "##~6": 10709, "##~7": 12681, "##~8": 12270, "##。": 21103, "##「": 21104, "##」": 21105, "##、": 21106, "##・": 21107, "##ッ": 21108, "##ー": 21109, "##イ": 21110, "##ク": 21111, "##シ": 21112, "##ス": 21113, "##ト": 21114, "##ノ": 21115, "##フ": 21116, "##ラ": 21117, "##ル": 21118, "##ン": 21119, "##゙": 21120, "##゚": 21121, "## ̄": 21122, "##¥": 21123, "$": 109, "%": 110, "&": 111, "'": 112, "(": 113, ")": 114, "*": 115, "+": 116, ",": 117, "-": 118, ".": 119, "...": 8106, "/": 120, "00": 8136, "000": 8241, "001": 9263, "002": 11204, "0020": 8746, "003": 11400, "004": 12329, "005": 11168, "006": 12526, "007": 9722, "008": 12210, "009": 12292, "00kg": 10501, "00z": 9337, "00㎡": 9506, "00㎡1": 12411, "01": 8146, "010": 9138, "011": 12603, "012": 11496, "013": 13034, "015": 13220, "019": 13146, "02": 8150, "020": 9147, "021": 10385, "022": 12522, "023": 13244, "024": 13002, "025": 11900, "027": 12849, "028": 11842, "029": 12801, "03": 8140, "04": 8147, "05": 8137, "050": 11972, "055": 9659, "06": 8116, "061": 11757, "07": 8155, "073": 13021, "074": 12780, "075": 12660, "0755": 10960, "08": 8142, "080": 12365, "0800": 10200, "09": 8141, "0fork": 8453, "0l": 10973, "0mm": 11368, "0t": 10691, "100g": 10606, "100km": 10915, "100m": 13037, "100ml": 11282, "101vip": 11428, "1080p": 9237, "10g": 9890, "10℃": 9115, "12345678910": 9363, "128gb": 12336, "14k": 10612, "15g": 11790, "16g": 12823, "16gb": 11340, "17life": 9091, "18k": 10323, "1a": 11942, "1b": 12217, "1g": 10719, "1gb": 12206, "1m": 12103, "1mdb": 12757, "1tb": 12430, "1v": 12819, "1~2": 10776, "200mm": 13166, "20cm": 13309, "20g": 12793, "20mm": 12714, "20℃": 12926, "24h": 11450, "2a": 11646, "2b": 10740, "2cm": 12988, "2d": 9648, "2g": 9422, "2gb": 11380, "2k": 10739, "2l": 13191, "2m": 10725, "2mm": 12287, "2~3": 10282, "309b": 9799, "30cm": 12850, "30g": 12008, "30ml": 11234, "32g": 13181, "32gb": 11155, "34e": 11614, "360°": 11739, "3a": 10667, "3c": 8344, "3ce": 10183, "3d": 8219, "3ds": 11755, "3g": 8456, "3kg": 9619, "3m": 9192, "3mm": 12064, "3p": 12108, "3s": 13247, "3t": 12338, "3~4": 12907, "3~5": 12222, "45㎡2": 12039, "4a": 10660, "4d": 10571, "4g": 8340, "4gb": 10426, "4k": 8574, "4l": 13297, "4m": 9695, "4s": 8830, "500g": 12623, "500ml": 13023, "50cm": 11721, "50g": 12233, "50ml": 11538, "50mm": 11774, "52kb": 12811, "52sykb": 12846, "5a": 10594, "5c": 13025, "5cm": 9388, "5d": 10406, "5g": 8711, "5k": 12172, "5kg": 13183, "5l": 9892, "5m": 11483, "5mm": 9394, "5s": 9376, "5t": 12204, "5v": 10965, "5℃": 9687, "64gb": 11432, "64㎡": 13011, "6a": 11692, "6g": 13147, "6gb": 12324, "6l": 12061, "6m": 12485, "6p": 12786, "6s": 9590, "720p": 9591, "7headlines": 11180, "7x24": 12486, "8cm": 12237, "8g": 10019, "8gb": 11257, "8k": 12689, "8mm": 12964, "91tv": 12586, ":": 131, ";": 132, "<": 133, "": 104, "": 105, "=": 134, ">": 135, "?": 136, "@": 137, "[": 138, "[CLS]": 101, "[MASK]": 103, "[PAD]": 0, "[SEP]": 102, "[UNK]": 100, "[unused10]": 10, "[unused11]": 11, "[unused12]": 12, "[unused13]": 13, "[unused14]": 14, "[unused15]": 15, "[unused16]": 16, "[unused17]": 17, "[unused18]": 18, "[unused19]": 19, "[unused1]": 1, "[unused20]": 20, "[unused21]": 21, "[unused22]": 22, "[unused23]": 23, "[unused24]": 24, "[unused25]": 25, "[unused26]": 26, "[unused27]": 27, "[unused28]": 28, "[unused29]": 29, "[unused2]": 2, "[unused30]": 30, "[unused31]": 31, "[unused32]": 32, "[unused33]": 33, "[unused34]": 34, "[unused35]": 35, "[unused36]": 36, "[unused37]": 37, "[unused38]": 38, "[unused39]": 39, "[unused3]": 3, "[unused40]": 40, "[unused41]": 41, "[unused42]": 42, "[unused43]": 43, "[unused44]": 44, "[unused45]": 45, "[unused46]": 46, "[unused47]": 47, "[unused48]": 48, "[unused49]": 49, "[unused4]": 4, "[unused50]": 50, "[unused51]": 51, "[unused52]": 52, "[unused53]": 53, "[unused54]": 54, "[unused55]": 55, "[unused56]": 56, "[unused57]": 57, "[unused58]": 58, "[unused59]": 59, "[unused5]": 5, "[unused60]": 60, "[unused61]": 61, "[unused62]": 62, "[unused63]": 63, "[unused64]": 64, "[unused65]": 65, "[unused66]": 66, "[unused67]": 67, "[unused68]": 68, "[unused69]": 69, "[unused6]": 6, "[unused70]": 70, "[unused71]": 71, "[unused72]": 72, "[unused73]": 73, "[unused74]": 74, "[unused75]": 75, "[unused76]": 76, "[unused77]": 77, "[unused78]": 78, "[unused79]": 79, "[unused7]": 7, "[unused80]": 80, "[unused81]": 81, "[unused82]": 82, "[unused83]": 83, "[unused84]": 84, "[unused85]": 85, "[unused86]": 86, "[unused87]": 87, "[unused88]": 88, "[unused89]": 89, "[unused8]": 8, "[unused90]": 90, "[unused91]": 91, "[unused92]": 92, "[unused93]": 93, "[unused94]": 94, "[unused95]": 95, "[unused96]": 96, "[unused97]": 97, "[unused98]": 98, "[unused99]": 99, "[unused9]": 9, "\\": 139, "]": 140, "^": 141, "_": 142, "a": 143, "a1": 9454, "a2": 10301, "a3": 10156, "a4": 9367, "a5": 10796, "a6": 11716, "a7": 11226, "a8": 10790, "a9": 11094, "aa": 9563, "aaa": 10876, "ab": 9386, "abc": 8425, "about": 9053, "abs": 8494, "ac": 9226, "acca": 11417, "access": 11098, "ace": 12192, "acer": 10837, "acg": 11553, "act": 10355, "action": 10805, "active": 12105, "ad": 9145, "adam": 11194, "adc": 10723, "adchoice": 10999, "add": 10253, "address": 13093, "adi": 11655, "adidas": 8953, "admin": 8843, "adobe": 8864, "ads": 12521, "adsense": 11317, "adsl": 13080, "advanced": 12370, "ae": 11978, "af": 11782, "after": 10100, "ag": 9588, "again": 12830, "age": 12162, "agent": 12948, "ago": 8498, "agoda": 8678, "ah": 10785, "ai": 8578, "air": 8523, "airbnb": 9709, "airmail": 11837, "airport": 11435, "ajax": 11569, "ak": 12825, "akb48": 10521, "al": 9266, "alan": 11648, "album": 13108, "alex": 10179, "alexa": 11193, "alexander": 11733, "alice": 10757, "all": 8513, "allen": 11736, "alpha": 10763, "alphago": 10941, "also": 12216, "alt": 9721, "am": 8413, "am09": 12377, "amana": 12406, "amazon": 8954, "amd": 8992, "america": 11801, "american": 9735, "amg": 13100, "amoled": 11307, "amp": 9985, "amy": 11201, "an": 9064, "analytics": 12824, "and": 8256, "andrew": 10582, "android": 8254, "andy": 11036, "angel": 9561, "angela": 12822, "angelababy": 10643, "ann": 12276, "anna": 9779, "anne": 12860, "annie": 11022, "anthony": 10219, "anti": 9204, "ap": 9392, "apache": 10555, "apec": 9413, "aphojoy": 9869, "api": 8726, "apk": 8543, "app": 8172, "apple": 8350, "application": 12339, "appqq": 11898, "apps": 11006, "apr": 9011, "april": 9557, "apt": 13205, "ar": 8673, "archive": 12884, "archives": 12318, "arduino": 12697, "are": 8995, "area": 13224, "arm": 9498, "armani": 11037, "arpg": 12701, "art": 9143, "article": 9122, "articles": 12431, "arts": 12989, "as": 8975, "asia": 8339, "asics": 11849, "asp": 9596, "aspx": 12363, "asr": 10335, "association": 11549, "asus": 9300, "at": 8243, "atm": 8366, "atom": 8941, "atp": 12805, "au": 10677, "audi": 9976, "audio": 11698, "aug": 9663, "august": 9217, "author": 12195, "auto": 11327, "autocad": 12796, "av": 8375, "avenue": 12226, "avi": 10548, "avira": 10473, "award": 11796, "awards": 11846, "aws": 12014, "azure": 10421, "b": 144, "b1": 9338, "b12": 12699, "b2": 9668, "b2b": 9493, "b2c": 10089, "b3": 12790, "b5": 13137, "b6": 11384, "ba": 10322, "baby": 8795, "back": 10017, "bad": 12139, "bag": 13214, "baidu": 11118, "balance": 11606, "ball": 10136, "band": 11715, "bang": 12067, "bank": 10717, "banner": 13256, "bar": 9054, "bas": 10952, "base": 11668, "basic": 12309, "bat": 9806, "battle": 12379, "bay": 10251, "bb": 8638, "bbc": 8846, "bbe": 12517, "bbq": 10732, "bbs": 9026, "bc": 10954, "bd": 8633, "be": 8815, "be2": 10276, "beach": 9983, "bean": 13188, "bear": 13265, "beautiful": 13106, "beauty": 9445, "before": 10735, "bell": 9993, "bella": 13192, "belle": 13058, "ben": 10016, "benz": 13065, "best": 9186, "beta": 9861, "beyond": 12352, "bh": 11030, "bi": 11055, "big": 9193, "bigbang": 11122, "bill": 10681, "bim": 11749, "bin": 11702, "bing": 12960, "bios": 9324, "bird": 13164, "bit": 10425, "bl": 10353, "black": 9296, "block": 10188, "blog": 8309, "blogabstract": 9288, "blogfp": 10207, "blogger": 9742, "blogspot": 10437, "blogthis": 8265, "blogtitle": 10055, "bloomberg": 10313, "blue": 9036, "bmw": 8943, "bo": 11059, "board": 12020, "bob": 10542, "body": 9867, "bonnie": 12972, "book": 9106, "booking": 9309, "books": 11280, "boost": 11986, "boot": 13119, "boss": 8445, "bot": 11825, "box": 9553, "boy": 10447, "bp": 12203, "br": 8575, "brake": 8550, "brand": 12326, "brandt": 12855, "break": 13049, "brian": 11754, "bridge": 11784, "brown": 10699, "bruce": 12897, "bt": 8364, "buff": 11321, "buffet": 11637, "bug": 8761, "build": 11561, "burberry": 11143, "bus": 10411, "business": 9913, "but": 10288, "butler": 11797, "buy": 11166, "bwl": 9681, "by": 8120, "bye": 10833, "bytes": 10599, "c": 145, "c1": 10905, "c2": 11854, "c3": 11829, "c4": 13209, "c5": 12648, "c919": 13136, "ca": 8850, "cache": 10991, "cad": 8645, "cafe": 8377, "cafe2017": 8986, "cake": 11683, "california": 13293, "call": 9816, "cam": 12722, "cambridge": 11788, "camera": 11519, "camp": 12275, "campaign": 8718, "can": 9109, "canada": 12947, "candy": 10653, "canmake": 13298, "canon": 10109, "capital": 10715, "car": 10875, "card": 10674, "care": 10614, "carlo": 12628, "carol": 9196, "case": 10474, "cat": 10165, "category": 10633, "cb": 12447, "cba": 10912, "cbc": 8712, "cbd": 11249, "cbs": 13035, "cc": 8485, "ccd": 12882, "cctv": 10099, "cd": 8405, "cdma": 12902, "cdn": 10910, "ce": 10399, "cell": 11490, "center": 9469, "central": 10890, "centre": 10964, "ceo": 8371, "ces": 9818, "cf": 9191, "cf1": 12327, "cfa": 9984, "cg": 9715, "ch": 9537, "chan": 9318, "chanel": 9366, "chang": 11680, "change": 12319, "channel": 11261, "chapter": 12350, "charles": 10403, "charlie": 12962, "check": 9233, "cheese": 11387, "chen": 9798, "chi": 12205, "chicago": 10268, "chicken": 12285, "children": 12981, "china": 8873, "chinese": 10101, "cho": 9829, "chocolate": 12474, "chris": 9582, "christian": 11824, "chrome": 8812, "church": 12914, "ci": 12364, "cia": 11769, "cindy": 9303, "cio": 9351, "cisco": 11010, "city": 8869, "cj": 13202, "ck": 11623, "cl": 12847, "claire": 9753, "class": 9380, "classic": 11524, "click": 11682, "client": 10989, "close": 11239, "cloud": 10279, "club": 8907, "cm": 9326, "cma": 12398, "cmos": 10306, "cms": 11539, "cn": 8274, "cnc": 12080, "cnn": 9206, "co": 8792, "co2": 11444, "coach": 10784, "coc": 11917, "coco": 8770, "code": 8700, "coffee": 9706, "collection": 11024, "college": 10319, "color": 9916, "com": 8134, "come": 11385, "comhd": 12587, "comment": 9066, "comments": 8616, "common": 13050, "company": 10007, "com™": 10921, "con": 11485, "connect": 12280, "connectivity": 8962, "contact": 11860, "content": 9432, "contextlink": 11780, "continue": 10859, "control": 8809, "cook": 12703, "cookie": 8690, "cookies": 8193, "cool": 11338, "cool1": 12032, "copy": 11669, "copyright": 9521, "core": 9684, "corporation": 8831, "cos": 10141, "cosplay": 9803, "costco": 10742, "count": 10926, "country": 12678, "county": 13088, "coupe": 13142, "course": 12654, "cover": 12555, "cp": 8337, "cpa": 11963, "cpi": 9511, "cpu": 8476, "cr": 10951, "cream": 11494, "create": 12432, "creative": 12491, "credit": 12241, "crm": 9991, "cross": 12209, "crv3000": 12588, "cry": 10485, "crystal": 12070, "cs": 9541, "css": 8935, "css3": 10760, "cst": 12945, "ct": 9162, "cto": 12633, "ctrip": 8223, "ctrl": 8947, "culture": 13219, "cup": 10174, "curry": 13014, "curve": 9357, "cut": 12322, "cv": 10718, "cx": 11154, "d": 146, "d1": 11537, "d2": 11089, "d3": 10966, "d5": 12987, "da": 10005, "dac": 12913, "daily": 10210, "dan": 11404, "dance": 12371, "daniel": 9701, "dark": 12705, "data": 9000, "database": 12435, "date": 11624, "david": 8776, "davis": 11968, "day": 8542, "day1": 11813, "day2": 11144, "day3": 11649, "day4": 12890, "days": 9068, "db": 9767, "dc": 8928, "dcs": 12418, "dd": 10391, "ddd": 13234, "ddos": 12887, "de": 8363, "dean": 12440, "dear": 11694, "dec": 9333, "december": 9871, "deep": 12592, "del": 10843, "delete": 12845, "dell": 11516, "demo": 10828, "der": 9157, "des": 11081, "design": 9225, "details": 13227, "development": 12261, "dha": 11015, "dhl": 13305, "di": 9796, "diary": 12940, "die": 11633, "digital": 10727, "dior": 8639, "discovery": 12748, "discuz": 13197, "disney": 12299, "display": 11830, "distribution": 9320, "dit": 13231, "div": 11308, "diy": 8342, "dj": 9135, "dji": 12093, "dl": 11961, "dlc": 12439, "dll": 9614, "dm": 10442, "dna": 8669, "dnf": 11315, "dns": 9580, "do": 8895, "doc": 9656, "docker": 10290, "docomo": 11358, "dog": 13030, "doi": 9962, "dollars": 9448, "dom": 11183, "domain": 12168, "don": 9524, "donald": 9635, "dos": 10441, "dota": 11636, "double": 11255, "down": 10243, "download": 9461, "dr": 8647, "dragon": 10829, "dram": 10664, "dream": 10252, "drive": 10170, "dropbox": 11277, "ds": 11274, "dsp": 9934, "dt": 13260, "du": 10173, "dv": 12372, "dvd": 8316, "dx": 13240, "dyson": 12730, "e": 147, "e1": 12298, "e2": 12357, "e3": 10440, "e5": 10695, "e6": 11639, "e7": 12888, "e88": 13313, "ea": 9714, "earth": 11409, "east": 10990, "easy": 9935, "eb": 10979, "eba": 11129, "ebay": 8886, "ebd": 8539, "ebooks": 10186, "ec": 12470, "ecfa": 12496, "echo": 11701, "eclipse": 11752, "eco": 12791, "economy": 11250, "ecu": 9526, "ed": 9599, "ed2k": 10587, "edge": 9720, "edit": 11150, "edited": 10304, "edition": 10621, "editor": 11544, "edm": 11269, "eds": 12191, "edu": 9827, "education": 12727, "edward": 12259, "ee": 13173, "eeworld": 12490, "ef": 9783, "eia": 11981, "el": 10245, "electronic": 9297, "eleven": 9795, "ella": 13056, "elle": 11593, "else": 11740, "em": 13152, "email": 8307, "emba": 10360, "emc": 12341, "emi": 13104, "emily": 12384, "emma": 12111, "ems": 9589, "en": 9447, "end": 9931, "energy": 11939, "engine": 11764, "english": 8899, "enter": 11086, "entertainment": 11679, "eos": 10434, "ep": 10676, "eps": 9629, "epson": 12735, "eq": 11601, "er": 10451, "eric": 9836, "erp": 9529, "error": 10812, "es": 11696, "esc": 9307, "esp": 9212, "et": 8867, "etc": 9813, "etf": 8946, "etnews": 12870, "ettoday": 9485, "eur": 11991, "ev": 12311, "eva": 10154, "event": 10992, "evernote": 13138, "evolution": 12691, "ex": 9577, "excel": 8729, "exchange": 10974, "exe": 9464, "exhibition": 13282, "exo": 11184, "expedia": 12317, "explorer": 10630, "express": 9865, "eye": 11650, "eyes": 12909, "f": 148, "f1": 9080, "f16": 12799, "f2": 9675, "f3": 11651, "f4": 11464, "f5": 12173, "fa": 12289, "face": 10656, "facebook": 8200, "facebooktwitterpinterestgoogle": 11498, "factory": 12896, "fairmont": 12208, "false": 11457, "family": 10072, "fan": 11925, "fandom": 9598, "fans": 11821, "fantasy": 12436, "faq": 9065, "faq1": 13006, "fashion": 9522, "fast": 11934, "fb": 8573, "fbi": 9711, "fc": 10443, "fc2": 11362, "fda": 10065, "fe": 12605, "feb": 9694, "february": 10028, "fed": 9311, "fedora": 11577, "feed": 12006, "feel": 11297, "ferragamo": 9992, "festival": 11720, "ff": 12388, "fgo": 11401, "fi": 8533, "field": 12594, "fifa": 12130, "file": 9828, "files": 10463, "film": 11149, "final": 10591, "financial": 12200, "find": 11707, "fintech": 12234, "fire": 11229, "firefox": 8964, "first": 9555, "fish": 11676, "fishbase": 13316, "fit": 11188, "five": 12706, "fks": 10044, "flash": 8427, "flickr": 11470, "fluke62max": 10946, "fly": 13010, "fm": 9079, "focus": 11452, "follow": 10792, "font": 11851, "food": 9579, "for": 8330, "force": 9019, "ford": 10296, "forest": 10889, "form": 12244, "forum": 11730, "foundation": 12099, "fox": 10872, "fpga": 9724, "fps": 11671, "fpx": 13285, "framework": 12842, "france": 11653, "francis": 13134, "frank": 10379, "free": 8583, "fresh": 12718, "fri": 8611, "friday": 11240, "friend": 13280, "friends": 11488, "frigidaire": 12304, "frm": 11794, "from": 8670, "fsm": 12807, "ft": 12180, "ftp": 9195, "fu": 9486, "full": 9904, "fun": 9575, "function": 12213, "fung": 13238, "future": 11814, "fx": 12611, "g": 149, "g1": 11528, "g2": 12179, "g20": 9789, "g3": 12493, "g4g": 10613, "g5": 12492, "g6": 12958, "g7": 13053, "g9": 11157, "ga": 11005, "gaga": 12762, "galaxy": 8547, "gallery": 12595, "game": 9033, "games": 10810, "gaming": 12444, "ganji": 9055, "gap": 10130, "garden": 9794, "gartner": 12784, "gary": 11560, "gay": 12211, "gb": 9468, "gc": 12366, "gd": 11729, "gdp": 8421, "ge": 10234, "gear": 10231, "general": 11568, "george": 9897, "get": 9018, "gg": 10206, "ghost": 10797, "gi": 12785, "gif": 9047, "gigi": 12634, "girl": 9375, "girls": 10803, "gis": 12892, "git": 10807, "github": 10575, "givenchy": 12065, "gl": 9101, "glass": 12535, "global": 8878, "gm": 12277, "gmail": 8637, "gmat": 13204, "gmp": 10821, "gmt": 12828, "gnu": 12367, "go": 8373, "god": 11138, "gogoro": 11225, "gohappy": 11567, "gold": 10628, "golden": 12746, "gomaji": 9576, "goo": 9271, "good": 9005, "goods": 9028, "google": 8190, "googlemsn": 12046, "gopro": 13176, "goris": 9188, "gov": 9514, "gp": 13228, "gpa": 12273, "gps": 8434, "gpu": 9483, "gr2": 9293, "grace": 11587, "grand": 9968, "gre": 10771, "great": 10512, "green": 9631, "group": 9051, "gs": 12694, "gsm": 11484, "gt": 9046, "gtx": 11069, "gucci": 10258, "guest": 12901, "guestname": 13082, "gui": 12295, "guide": 11724, "gundam": 12523, "h": 150, "h1": 12333, "h2": 12212, "h5": 9354, "h6": 12235, "h7n9": 10697, "ha": 11643, "hadoop": 10956, "hair": 11408, "hall": 11049, "han": 12126, "happy": 9200, "hard": 12442, "harry": 12296, "has": 11325, "have": 9531, "hbl": 12502, "hd": 8407, "hdmi": 9578, "hdr": 10465, "he": 9245, "head": 12074, "health": 10168, "heart": 10240, "hello": 8701, "help": 10892, "helpapp": 10609, "henry": 11361, "her": 11908, "here": 10815, "herme": 8834, "hero": 11673, "hey": 13153, "hgih": 11674, "hi": 8913, "high": 8757, "hill": 10562, "hip": 11070, "his": 10163, "history": 9939, "hit": 10295, "hitachi": 12294, "hiv": 11141, "hk": 8512, "hktvmall": 9688, "hmv": 12985, "ho": 10537, "hola": 10961, "hold": 10389, "holiday": 12777, "home": 8563, "homemesh": 9167, "honda": 11890, "honey": 13299, "hong": 8881, "hop": 10931, "host": 12387, "hostel": 13113, "hot": 9286, "hotel": 8462, "hotels": 8749, "hotmail": 10728, "house": 8696, "how": 9510, "howard": 11312, "hp": 8853, "hpv": 11067, "hr": 8967, "hsu": 12307, "htc": 8530, "htm": 9645, "html": 8304, "html5": 9302, "http": 8184, "https": 8532, "hu": 12199, "huang": 10788, "huawei": 12247, "human": 11913, "i": 151, "i3": 12224, "i5": 10013, "i7": 10008, "ian": 13268, "ib": 12487, "ibm": 8699, "ic": 8577, "ice": 10490, "icecat": 9336, "icloud": 12602, "icon": 9734, "icp": 9658, "ict": 13162, "id": 8231, "idc": 9617, "ide": 11319, "idea": 11834, "ie": 8469, "ie6": 12509, "ieee": 12272, "if": 8898, "ig": 8288, "iherb": 11040, "ii": 8491, "iii": 9207, "iis": 11670, "ikea": 10513, "il": 12197, "im": 10481, "image": 9732, "images": 12804, "imax": 11214, "imf": 9971, "img": 11412, "imsean": 12087, "in": 8217, "inc": 8910, "index": 9405, "info": 9603, "information": 11237, "ing": 10139, "inn": 9696, "inparadise": 12484, "ins": 12323, "insee": 11513, "inside": 13157, "instagram": 8780, "install": 12461, "institute": 11205, "int": 10673, "intel": 8781, "international": 9001, "internet": 8484, "into": 12609, "inwedding": 12134, "io": 10272, "ios": 8276, "ios10": 10671, "ios11": 12833, "ios7": 13027, "ios9": 8926, "iot": 9543, "ip": 8215, "ipad": 8355, "iphone": 8210, "iphone6": 9878, "iphone7": 9440, "ipo": 8745, "ipod": 9391, "ips": 10511, "iptv": 12844, "ipv6": 12082, "iq": 12419, "ir": 12410, "is": 8310, "isbn": 8446, "isis": 11709, "island": 10262, "iso": 8784, "iso9001": 9727, "isofix": 11962, "isp": 12036, "it": 8233, "item": 9279, "its": 12894, "itunes": 9041, "iu": 13172, "iv": 10573, "ivy": 12662, "j": 152, "jack": 9850, "jackson": 11945, "james": 8923, "jan": 9213, "jane": 11909, "january": 9768, "japan": 9151, "jason": 10266, "java": 8507, "javascript": 8561, "jay": 12541, "jayz": 11072, "jb": 13063, "jcb": 10557, "jchere": 11396, "jean": 10483, "jeff": 11147, "jennifer": 12652, "jerry": 13111, "jessica": 11731, "ji": 12095, "jim": 11268, "jimmy": 10317, "jing": 13207, "jj": 11095, "jo": 13269, "job": 12539, "jobs": 13103, "joe": 9516, "john": 8675, "johnson": 11045, "jonathan": 11559, "jones": 11439, "jordan": 9229, "jose": 12606, "joseph": 11151, "journal": 10321, "joy": 12668, "jp": 9348, "jpeg": 11985, "jpg": 9248, "jquery": 10035, "jr": 8602, "js": 9016, "json": 12249, "jul": 9618, "july": 8909, "jump": 10331, "jun": 8392, "june": 8564, "junior": 12552, "just": 10125, "justin": 11889, "k": 153, "k2": 11999, "ka": 11306, "kai": 13072, "kanshu": 13236, "kanye": 8598, "karl": 13263, "kate": 11058, "kb": 9843, "kbs": 10655, "kd": 12695, "kde": 12543, "keep": 11654, "kelly": 11394, "ken": 11314, "kevin": 9583, "key": 9232, "kg": 9515, "kic": 11687, "kicstart2": 12614, "kids": 11826, "kiehl": 8587, "kim": 10683, "kimi": 11966, "kindle": 9810, "king": 9382, "kiss": 11192, "kit": 12788, "kitchen": 11808, "kitty": 9431, "kk": 11923, "kl": 13289, "km": 10062, "know": 11460, "ko": 10368, "kong": 8906, "korea": 11984, "koreanmall": 9895, "kpi": 11025, "ktv": 8894, "kuso": 10881, "ky": 11096, "kymco": 11013, "l": 154, "l1": 12421, "l2": 12879, "la": 8515, "lab": 11441, "labels": 11562, "lady": 8822, "lake": 10556, "lamigo": 12536, "lan": 11461, "land": 11169, "language": 8348, "last": 10148, "law": 11353, "lc": 11806, "lcd": 8919, "ldquo": 10616, "le": 8983, "learning": 12315, "leave": 10619, "led": 8242, "lee": 9058, "left": 12744, "legalminer": 11377, "lenovo": 13031, "leo": 11901, "leonardo": 8579, "leonnhurt": 13160, "les": 10133, "let": 9946, "level": 9888, "lg": 8589, "li": 9341, "library": 11616, "life": 8562, "lifestyle": 12996, "light": 10310, "like": 8993, "lily": 11228, "lim": 12817, "limited": 10424, "lin": 9733, "line": 8323, "ling": 10061, "link": 9025, "linkedin": 11369, "links": 10417, "linux": 8403, "lisa": 10032, "list": 9691, "little": 9929, "liu": 12306, "live": 8582, "living": 12113, "ll": 10856, "llc": 8236, "ln284ct": 12969, "lo": 12264, "loading": 10878, "local": 11476, "lock": 9189, "loft": 12751, "lofter": 8117, "loftpermalink": 10056, "log": 10510, "logo": 8529, "lohas": 9757, "lohasthree": 11741, "lol": 8817, "london": 9978, "long": 10037, "longchamp": 9003, "lonzo": 12688, "look": 9544, "lost": 12593, "louis": 10950, "love": 8451, "low": 10611, "lp": 11195, "lt": 10413, "ltd": 9616, "lte": 8987, "ltxsw": 8793, "lu": 12015, "lucky": 12659, "lulu": 11970, "lumia": 11506, "lv": 8289, "ly": 13252, "lz": 10767, "m": 155, "m1": 10211, "m2": 9567, "m3": 9305, "m4": 11964, "m5": 12802, "m8": 10914, "ma": 9622, "mac": 8502, "macbook": 9173, "macd": 10851, "machine": 12252, "made": 10123, "magazine": 10469, "maggie": 12423, "magic": 10328, "mail": 8313, "main": 9139, "make": 9994, "maker": 11389, "malaysia": 10514, "mall": 9628, "mama": 13186, "man": 8791, "management": 10751, "manager": 11039, "mandy": 9518, "mango": 12645, "map": 9633, "maps": 12446, "mar": 9118, "marc": 11511, "march": 9581, "maria": 12096, "mark": 8970, "market": 9095, "marketing": 13189, "marriott": 10471, "martin": 10059, "mary": 10786, "master": 9261, "mastercard": 9841, "match": 12528, "mate": 10577, "matlab": 12640, "matt": 12042, "max": 8621, "may": 8480, "mb": 9499, "mba": 8980, "mbc": 10648, "mc": 10341, "mcu": 10738, "md": 11399, "me": 8450, "media": 9371, "mega": 12908, "meiki": 9872, "melody": 9087, "member": 11120, "memory": 11910, "mems": 12530, "men": 11305, "menu": 8888, "message": 12231, "messenger": 11892, "meta": 11799, "metal": 13259, "metro": 12473, "mg": 9404, "mhz": 12747, "mi": 10551, "miacare": 11918, "michael": 8918, "micro": 10204, "microsoft": 8775, "mike": 10021, "miller": 13114, "min": 9573, "mind": 12573, "ming": 11388, "mini": 8672, "minkoff": 11018, "miss": 9368, "mit": 9315, "miui": 11342, "mix": 9678, "mk": 11629, "mkv": 11557, "ml": 10215, "mlb": 9905, "mm": 8595, "mmorpg": 13274, "mo": 11303, "moba": 11565, "mobil": 12572, "mobile": 9119, "mod": 9650, "mode": 10770, "model": 9264, "modern": 12862, "momo": 8534, "mon": 8556, "monday": 12069, "money": 10348, "moneydj": 11911, "monte": 12861, "months": 10195, "moon": 9921, "more": 8384, "morning": 12885, "most": 11344, "motel": 11466, "moto": 10429, "mount": 12881, "mountain": 12482, "movie": 11099, "mozilla": 11579, "mp": 11198, "mp3": 8388, "mp4": 9399, "mpv": 10259, "mr": 8912, "ms": 9396, "msci": 9400, "msg": 10180, "msi": 12560, "msn": 8804, "mt": 10376, "mtv": 11529, "mu": 11677, "muji": 13001, "multi": 13149, "museum": 10553, "music": 9057, "mv": 8546, "mvp": 9505, "mwc": 12184, "mx": 11171, "my": 8422, "mysql": 9108, "n": 156, "n1": 11356, "n2": 11832, "n3": 12905, "na": 11469, "name": 8617, "namespace": 11076, "nana": 12140, "nand": 11711, "nano": 13057, "nas": 10157, "nasa": 9334, "nata": 10166, "national": 9385, "natural": 12627, "nature": 10467, "navigation": 12232, "nb": 9254, "nb40": 12965, "nba": 8391, "nbapop": 12188, "nbc": 12141, "nbsp": 8400, "nc": 12394, "ncc": 8305, "ne": 10564, "nego": 11181, "neo": 12169, "net": 8336, "netcomponents": 11471, "netflix": 10373, "netscape": 8691, "network": 10339, "never": 11718, "new": 8343, "news": 8501, "next": 9321, "nexus": 10390, "nfc": 9298, "ng": 8885, "nginx": 12576, "ngo": 11770, "nhk": 9689, "ni": 10560, "nice": 10192, "nick": 11243, "night": 10036, "nike": 8702, "nikkie": 13303, "nikon": 11391, "niusnews": 13212, "no": 8275, "no1": 11448, "node": 10320, "nokia": 9752, "non": 12002, "north": 10744, "not": 9059, "note": 8698, "note7": 12147, "notes": 13165, "nov": 9698, "nova": 11660, "november": 9756, "now": 9666, "nownews": 11123, "np": 11203, "npc": 9811, "ns": 10593, "nt": 8495, "ntd": 12982, "nu": 12797, "null": 12083, "number": 11333, "nvidia": 9503, "o": 157, "o2o": 8590, "oa": 10527, "ob": 12639, "object": 11336, "ocean": 12546, "oct": 9346, "october": 9548, "oculus": 10480, "oem": 9945, "of": 8205, "off": 9594, "offer": 10038, "office": 8628, "official": 12863, "ofo": 9574, "ofweek": 10140, "oh": 9941, "oil": 13046, "ok": 8270, "ol": 8972, "old": 10404, "oldid": 13267, "oled": 8868, "omega": 11938, "on": 8281, "one": 8429, "online": 8314, "only": 10110, "oo": 11383, "oops": 11260, "op": 10208, "opec": 9416, "open": 8893, "openload": 13096, "opera": 10917, "oppo": 8806, "or": 8549, "oracle": 10085, "orange": 13295, "order": 11156, "org": 8448, "originals": 12975, "orz": 10836, "os": 8721, "other": 12132, "ott": 11114, "our": 11052, "out": 8883, "outlet": 10071, "outlook": 11422, "over": 10047, "overchicstoretvhome": 12450, "overdope": 9964, "oxford": 12649, "p": 158, "p1": 11020, "p10": 10405, "p2": 11883, "p2p": 8478, "p3": 12454, "p9": 11951, "pa": 9519, "pacific": 12625, "pack": 12736, "pad": 10257, "page": 9040, "pan": 11641, "panasonic": 10752, "pantos": 10030, "paper": 10863, "paris": 10708, "park": 8865, "parker": 12495, "part": 9124, "party": 9126, "pass": 9703, "path": 12443, "patrick": 12003, "paul": 8999, "pay": 9452, "paypal": 8657, "pc": 8295, "pcb": 9925, "pchome": 9780, "pci": 10773, "pd": 9884, "pdf": 8496, "pe": 9205, "pen": 12637, "people": 8777, "pepper": 11861, "pet": 10495, "peter": 9323, "pg": 12898, "ph": 9465, "philips": 10749, "phone": 8922, "photo": 9020, "photos": 9999, "photoshop": 9415, "php": 8531, "pi": 10091, "piece": 11446, "pierre": 8744, "pin": 11328, "ping": 11891, "pink": 12016, "pinkoi": 11941, "pinterest": 8379, "pixel": 11688, "pixnet": 8191, "pixnetfacebookyahoo": 12047, "pixstyleme": 10344, "pixstyleme3c": 8382, "pizza": 10315, "pk": 8465, "pk10": 9329, "place": 10963, "plan": 12248, "planet": 12269, "play": 8942, "player": 9075, "playstation": 11026, "plaza": 11767, "plc": 10015, "please": 11744, "plurk": 10498, "plus": 8514, "pm": 8397, "pm1": 11819, "pm2": 9150, "pmi": 10127, "pmid": 11804, "png": 10246, "po": 8559, "point": 9891, "pokemon": 8934, "policy": 8659, "polo": 10710, "pony": 8365, "pop": 8971, "popular": 11880, "population": 13271, "port": 11311, "pos": 9854, "pose": 11474, "positioning": 11187, "post": 8671, "posted": 8486, "posts": 10639, "power": 9239, "powered": 10103, "powerpoint": 12176, "pp": 8570, "ppi": 11393, "ppp": 9230, "ppt": 8842, "pptv": 12123, "pr": 9470, "prada": 11617, "pre": 11685, "prefix": 11109, "premium": 10371, "press": 9228, "previous": 12194, "price": 11597, "prime": 10891, "privacy": 8677, "private": 13233, "pro": 8376, "process": 12009, "product": 11691, "profile": 11675, "program": 11738, "project": 9284, "protected": 9562, "ps": 8362, "ps3": 11802, "ps4": 9986, "psp": 11337, "pt": 10791, "ptt": 9773, "pu": 11227, "public": 10672, "published": 12821, "publishing": 13306, "puma": 11803, "pure": 13179, "push": 11604, "pv": 10415, "pvc": 8656, "pvp": 10193, "pwm": 11840, "python": 9030, "q": 159, "q1": 10670, "q10": 11382, "q2": 9898, "q3": 10982, "q4": 11625, "q5": 11871, "q7": 12938, "qa": 10818, "qe": 11534, "qi": 11566, "qq": 8186, "qqmei": 12011, "qr": 9830, "qs": 11974, "qt": 12933, "qualcomm": 13264, "queen": 11032, "quick": 12345, "quot": 10733, "qvod": 10554, "r": 160, "r1": 12026, "r11": 10808, "r2": 11345, "r8": 10187, "r9": 12674, "ra": 12619, "radio": 11034, "raid": 11044, "rain": 11873, "rainer": 13076, "rakuten": 10249, "ram": 9270, "rar": 12773, "rate": 12597, "raw": 11265, "ray": 10043, "rc": 11746, "rcep": 12361, "rd": 11952, "rdquo": 11071, "re": 8847, "read": 8649, "reader": 11453, "reading": 10303, "real": 10153, "rebecca": 10418, "red": 9276, "redis": 12599, "related": 11148, "release": 13017, "rends": 9838, "reply": 9008, "report": 10407, "request": 12931, "research": 10018, "reserved": 9644, "resort": 10401, "restaurant": 10637, "result": 13170, "return": 12330, "reuters": 11778, "review": 9950, "rewards": 10197, "rf": 10586, "rfid": 10292, "rgb": 11189, "rich": 13210, "richard": 9875, "rick": 13253, "right": 10378, "rights": 9615, "river": 10835, "rm": 10620, "rmb": 10887, "rmk": 13091, "rmvb": 9365, "rn": 11998, "rna": 11656, "ro": 12910, "road": 9772, "robert": 9441, "rock": 10092, "roger": 13033, "rom": 8891, "room": 10083, "root": 8859, "rose": 9497, "rosie": 10487, "royal": 11019, "rp": 12771, "rpg": 9278, "rq": 11635, "rs": 10610, "rss": 8605, "rt": 10678, "ru": 12818, "ruby": 10567, "run": 9909, "running": 11620, "russell": 11514, "rx": 12342, "ryan": 11536, "s": 161, "s1": 10640, "s2": 11302, "s3": 10647, "s4": 11352, "s5": 11161, "s6": 10470, "s7": 9821, "s8": 8940, "sa": 8945, "saas": 10362, "safari": 8580, "said": 8385, "saint": 10484, "sale": 12133, "salvatore": 10078, "sam": 10088, "samsung": 8931, "san": 9542, "santa": 12321, "sao": 12053, "sap": 11708, "sarah": 12455, "sars": 12390, "sas": 12120, "sat": 8536, "sata": 11535, "save": 13069, "say": 10114, "says": 9739, "sb": 12359, "sbl": 12250, "sbs": 9965, "sc": 11515, "schemas": 11847, "school": 9467, "sci": 11776, "science": 9982, "scott": 10692, "scp": 10547, "script": 10860, "scrum": 12527, "sd": 9201, "sdk": 10302, "se": 9342, "sea": 11007, "sean": 12794, "search": 9168, "season": 11220, "second": 12462, "secret": 11634, "security": 11547, "see": 10235, "select": 10634, "self": 12178, "sense": 12647, "seo": 8475, "sep": 9463, "september": 10024, "series": 10976, "server": 8896, "service": 9176, "services": 11936, "session": 11605, "set": 9738, "seven": 12684, "sex": 11288, "sf": 11176, "sg": 12954, "sgs": 11357, "sh": 11167, "shadow": 12378, "share": 8697, "she": 9374, "shell": 10651, "shi": 11772, "shift": 10866, "shirt": 12060, "shop": 9926, "shopping": 9662, "show": 8658, "shtml": 11501, "si": 10883, "side": 12666, "sidebar": 11212, "sign": 12710, "silver": 13230, "sim": 8703, "simon": 10944, "simple": 11996, "sina": 9606, "singapore": 12916, "single": 12148, "sir": 10171, "siri": 10309, "site": 11215, "size": 9571, "sk": 9820, "skin": 12479, "skip": 8973, "sky": 10122, "skype": 9713, "sm": 9158, "small": 11988, "smap": 13175, "smart": 9353, "smith": 9912, "sms": 12990, "sns": 10884, "so": 8968, "soc": 11405, "social": 10832, "society": 11573, "sodu": 9637, "sofascore": 11555, "soft": 12567, "software": 11735, "sogo": 10275, "soho": 10831, "sohu": 12610, "solo": 11659, "some": 13048, "something": 12713, "song": 11502, "sony": 8772, "sophie": 12127, "sorry": 12758, "sotheby": 12665, "soul": 12286, "sound": 12516, "source": 9014, "south": 10801, "sp": 9716, "spa": 8509, "space": 9634, "span": 12537, "spark": 11134, "special": 9969, "speed": 12755, "spf": 12598, "sport": 10669, "sports": 10646, "spotify": 11170, "spring": 11043, "sputniknews": 11376, "sql": 9078, "square": 10897, "sr": 12109, "ss": 10239, "ssd": 9004, "ssh": 11678, "ssl": 9708, "sso": 11499, "st": 8811, "stage": 12731, "standard": 12038, "star": 9012, "starbucks": 12919, "start": 10906, "state": 10223, "states": 11603, "station": 10459, "stay": 11527, "steam": 9325, "step": 9451, "step1": 8905, "step2": 8924, "step3": 9434, "step4": 9504, "step5": 10338, "stephen": 10913, "steve": 9812, "steven": 12174, "stone": 11073, "stop": 11467, "store": 8719, "story": 10076, "street": 9471, "string": 11508, "strong": 11732, "structure": 13286, "studio": 8318, "study": 12685, "style": 8969, "su": 11541, "sui": 10997, "suite": 11420, "summer": 10366, "sun": 8482, "sunday": 11548, "sunny": 11182, "super": 8988, "support": 11664, "supreme": 11272, "surface": 9623, "survey": 8704, "suv": 8540, "swatch": 11876, "sweet": 10598, "swift": 10081, "swiss": 11503, "swissinfo": 10661, "switch": 10746, "sylvia": 12500, "sync": 13193, "system": 8566, "systems": 12451, "t": 162, "t1": 10585, "t2": 10927, "t3": 11291, "ta": 8346, "tab": 10476, "table": 10809, "tag": 8801, "tags": 9214, "tai": 13242, "taipei": 9858, "taiwan": 8674, "take": 10985, "talk": 9533, "talk2yam": 8767, "tan": 12886, "target": 11926, "taylor": 11053, "tb": 11456, "tbs": 11773, "tc": 12858, "tcl": 9443, "tcp": 9901, "tcs": 10363, "td": 9287, "te": 8282, "tea": 9686, "team": 9597, "tech": 11402, "technology": 11061, "techorz": 12389, "ted": 11398, "teddy": 12764, "tee": 11330, "tel": 11108, "tesla": 11564, "test": 10060, "text": 10539, "tf": 12719, "tft": 12177, "thai": 12967, "than": 13158, "that": 9231, "the": 8174, "there": 11136, "they": 12013, "think": 12553, "thinkpad": 12525, "this": 8554, "thomas": 10010, "thread": 11164, "three": 8844, "thu": 8610, "thunder": 11322, "ti": 9654, "tiffany": 11509, "tiger": 12088, "tila": 10396, "tim": 10505, "time": 8759, "times": 9886, "tina": 12925, "tinker": 11254, "tips": 9104, "title": 9956, "tm": 9908, "tmt": 11920, "to": 8228, "today": 11262, "tokichoi": 13086, "tokyo": 10357, "tom": 9487, "tomtom": 12196, "tony": 10478, "too": 11928, "top": 8237, "top10": 10466, "top100": 10124, "topapp": 10607, "topios9": 12994, "touch": 8915, "tour": 10181, "tower": 11102, "town": 11445, "toyota": 10632, "tpp": 8855, "trackback": 11827, "traction": 12600, "travel": 9819, "trc": 11885, "tree": 10934, "trip": 12358, "tripadvisor": 8194, "trivago": 9963, "true": 10213, "trump": 9550, "ts": 9154, "tt": 10333, "tue": 8483, "turbo": 12325, "tv": 8395, "tvb": 9312, "tvbs": 11657, "tvg": 12547, "tw": 8351, "twd600": 11230, "tweet": 9874, "twice": 13054, "twitter": 8266, "two": 10380, "txt": 8666, "type": 9178, "u": 163, "u11": 13235, "ua": 11107, "uber": 8624, "ubuntu": 8889, "ubuntuforumwikilinuxpastechat": 12076, "uc": 9955, "ucbug": 11374, "udn": 9782, "udnbkk": 11339, "ufo": 10012, "uhz": 11599, "ui": 8840, "uk": 10375, "ul": 10293, "ultra": 10893, "under": 9997, "unicode": 12024, "union": 12161, "uniqlo": 11905, "unit": 12816, "united": 9958, "unity": 11897, "universal": 13229, "university": 8736, "unix": 10515, "unt": 13003, "up": 8644, "update": 9924, "ups": 10846, "urban": 13101, "url": 8654, "urn": 11584, "us": 8592, "usa": 11583, "usb": 8335, "usb3": 13255, "usd": 9259, "use": 11927, "user": 9870, "utc": 9361, "uv": 9473, "v": 164, "v1": 9074, "v2": 9636, "v3": 10066, "v4": 10942, "v5": 11133, "v6": 11051, "v8": 10662, "v9": 11894, "va": 12949, "valley": 11994, "value": 10850, "van": 9933, "vans": 10412, "var": 10433, "vc": 9438, "vcd": 10280, "vdc": 10888, "vdf": 13261, "ve": 12810, "ver": 12513, "vera": 9378, "version": 11354, "very": 11785, "vetements": 12859, "vfm": 8597, "vga": 13140, "vi": 10138, "via": 10003, "victoria": 12445, "video": 9539, "view": 8876, "views": 9881, "villa": 10806, "village": 12497, "vim": 11922, "vincent": 10993, "vip": 8324, "virtual": 12997, "visa": 8958, "vision": 10762, "vista": 9847, "visual": 10635, "vive": 10167, "vivi": 9243, "vivo": 9381, "vm": 13094, "vmalife": 10823, "vmware": 11449, "vogue": 10137, "voice": 11258, "vol": 9218, "volvo": 11048, "von": 12310, "vornado": 13036, "vpn": 9358, "vps": 10027, "vr": 8260, "vs": 8349, "vsa": 10920, "vsc": 10933, "w": 165, "wade": 12542, "wali": 10736, "walker": 12651, "wall": 12284, "wam": 9667, "wan": 10686, "wang": 9660, "want": 12733, "wap": 9530, "war": 10783, "was": 9947, "washington": 12262, "watch": 9114, "water": 11060, "wave": 12761, "way": 10590, "waze": 12836, "wd": 12741, "we": 8997, "wear": 12679, "web": 8353, "web885": 8437, "wed": 8585, "wedding": 10826, "week": 10090, "weeks": 11973, "wei": 11875, "weibo": 10565, "welcome": 12759, "well": 12010, "west": 8520, "westbrook": 11771, "what": 9100, "whatsapp": 10250, "when": 11611, "where": 11703, "white": 9790, "who": 9372, "why": 11177, "wi": 8541, "wifi": 8306, "wii": 11372, "wiki": 8548, "wikia": 8708, "wikipedia": 11850, "will": 9339, "william": 9979, "williams": 11475, "wilson": 12348, "win": 9769, "win10": 8634, "win7": 8586, "win8": 9436, "wind": 12302, "window": 12158, "windows": 8235, "windows7": 12258, "wine": 12022, "wing": 12349, "winrar": 9476, "wish": 12255, "with": 8663, "wma": 9900, "women": 12912, "wonderland": 9113, "wong": 11615, "word": 8681, "wordpress": 8627, "work": 10782, "works": 13112, "world": 8572, "worldcat": 10698, "woshipm": 9712, "wow": 11607, "wp": 10031, "wps": 11576, "write": 12800, "wto": 10045, "wu": 10552, "ww": 13279, "wwdc": 12848, "www": 8173, "wx17house": 9973, "x": 166, "x1": 9566, "x2": 10104, "x3": 10689, "x4": 12124, "x5": 10871, "x6": 12121, "x7": 12049, "x86": 10652, "x9": 12460, "xa": 12626, "xbox": 9077, "xd": 8444, "xdd": 11507, "xddd": 12059, "xi": 13135, "xl": 10657, "xml": 9094, "xp": 8766, "xperia": 9817, "xr": 11165, "xuehai": 10528, "xuite": 13194, "xx": 8584, "xxx": 8790, "xxxx": 12243, "xyz": 11266, "xz": 12999, "y": 167, "ya": 12066, "yahoo": 8497, "yam": 8107, "yamservice": 8768, "yang": 12086, "year": 9299, "years": 8753, "yes": 9719, "yesstyle": 12983, "yi": 11242, "yin": 13178, "yoga": 13296, "york": 9507, "you": 8357, "yougou": 10852, "young": 9802, "your": 8880, "youtube": 8487, "yu": 10825, "yumi": 11697, "yy": 9453, "z": 168, "z2": 12568, "zara": 10464, "zen": 12923, "zenfone": 11726, "zero": 10397, "zh": 9998, "zip": 10947, "zol": 12182, "zone": 11957, "zoom": 12356, "{": 169, "|": 170, "}": 171, "~": 172, "£": 173, "¤": 174, "¥": 175, "§": 176, "©": 177, "«": 178, "®": 179, "°": 180, "±": 181, "±0": 11349, "²": 182, "³": 183, "µ": 184, "·": 185, "¹": 186, "º": 187, "»": 188, "¼": 189, "×": 190, "×email": 11175, "××": 8858, "ß": 191, "æ": 192, "÷": 193, "ø": 194, "đ": 195, "ŋ": 196, "ɔ": 197, "ə": 198, "ɡ": 199, "ʰ": 200, "ˇ": 201, "ˈ": 202, "ˊ": 203, "ˋ": 204, "ˋ▽ˊ": 12416, "ˍ": 205, "ː": 206, "˙": 207, "˚": 208, "ˢ": 209, "α": 210, "β": 211, "γ": 212, "δ": 213, "ε": 214, "η": 215, "θ": 216, "ι": 217, "κ": 218, "λ": 219, "μ": 220, "ν": 221, "ο": 222, "π": 223, "ρ": 224, "ς": 225, "σ": 226, "τ": 227, "υ": 228, "φ": 229, "χ": 230, "ψ": 231, "ω": 232, "а": 233, "б": 234, "в": 235, "г": 236, "д": 237, "е": 238, "ж": 239, "з": 240, "и": 241, "к": 242, "л": 243, "м": 244, "н": 245, "о": 246, "п": 247, "р": 248, "с": 249, "т": 250, "у": 251, "ф": 252, "х": 253, "ц": 254, "ч": 255, "ш": 256, "ы": 257, "ь": 258, "я": 259, "і": 260, "ا": 261, "ب": 262, "ة": 263, "ت": 264, "د": 265, "ر": 266, "س": 267, "ع": 268, "ل": 269, "م": 270, "ن": 271, "ه": 272, "و": 273, "ي": 274, "۩": 275, "ก": 276, "ง": 277, "น": 278, "ม": 279, "ย": 280, "ร": 281, "อ": 282, "า": 283, "เ": 284, "๑": 285, "་": 286, "ღ": 287, "ᄀ": 288, "ᄁ": 289, "ᄂ": 290, "ᄃ": 291, "ᄅ": 292, "ᄆ": 293, "ᄇ": 294, "ᄈ": 295, "ᄉ": 296, "ᄋ": 297, "ᄌ": 298, "ᄎ": 299, "ᄏ": 300, "ᄐ": 301, "ᄑ": 302, "ᄒ": 303, "ᅡ": 304, "ᅢ": 305, "ᅣ": 306, "ᅥ": 307, "ᅦ": 308, "ᅧ": 309, "ᅨ": 310, "ᅩ": 311, "ᅪ": 312, "ᅬ": 313, "ᅭ": 314, "ᅮ": 315, "ᅯ": 316, "ᅲ": 317, "ᅳ": 318, "ᅴ": 319, "ᅵ": 320, "ᆨ": 321, "ᆫ": 322, "ᆯ": 323, "ᆷ": 324, "ᆸ": 325, "ᆺ": 326, "ᆻ": 327, "ᆼ": 328, "ᗜ": 329, "ᵃ": 330, "ᵉ": 331, "ᵍ": 332, "ᵏ": 333, "ᵐ": 334, "ᵒ": 335, "ᵘ": 336, "‖": 337, "„": 338, "†": 339, "•": 340, "‥": 341, "‧": 342, "
": 343, "‰": 344, "′": 345, "″": 346, "‹": 347, "›": 348, "※": 349, "‿": 350, "⁄": 351, "ⁱ": 352, "⁺": 353, "ⁿ": 354, "₁": 355, "₂": 356, "₃": 357, "₄": 358, "€": 359, "℃": 360, "№": 361, "™": 362, "ⅰ": 363, "ⅱ": 364, "ⅲ": 365, "ⅳ": 366, "ⅴ": 367, "←": 368, "↑": 369, "→": 370, "↓": 371, "↓↓": 12558, "↓↓↓": 9010, "↔": 372, "↗": 373, "↘": 374, "⇒": 375, "∀": 376, "−": 377, "∕": 378, "∙": 379, "√": 380, "∞": 381, "∟": 382, "∟∣": 12979, "∠": 383, "∣": 384, "∥": 385, "∩": 386, "∮": 387, "∶": 388, "∼": 389, "∽": 390, "≈": 391, "≒": 392, "≡": 393, "≤": 394, "≥": 395, "≦": 396, "≧": 397, "≪": 398, "≫": 399, "⊙": 400, "⋅": 401, "⋈": 402, "⋯": 403, "⋯⋯": 10169, "⌒": 404, "①": 405, "②": 406, "③": 407, "④": 408, "⑤": 409, "⑥": 410, "⑦": 411, "⑧": 412, "⑨": 413, "⑩": 414, "⑴": 415, "⑵": 416, "⑶": 417, "⑷": 418, "⑸": 419, "⒈": 420, "⒉": 421, "⒊": 422, "⒋": 423, "ⓒ": 424, "ⓔ": 425, "ⓘ": 426, "─": 427, "──": 8297, "━": 428, "│": 429, "┃": 430, "┅": 431, "┆": 432, "┊": 433, "┌": 434, "└": 435, "├": 436, "┣": 437, "═": 438, "║": 439, "╚": 440, "╞": 441, "╠": 442, "╭": 443, "╮": 444, "╯": 445, "╰": 446, "╱": 447, "╳": 448, "▂": 449, "▃": 450, "▅": 451, "▇": 452, "█": 453, "▉": 454, "▋": 455, "▌": 456, "▌♥": 9601, "▍": 457, "▎": 458, "■": 459, "□": 460, "▪": 461, "▫": 462, "▬": 463, "▲": 464, "▲top": 9125, "▲topapr": 10162, "▲topaug": 10558, "▲topdec": 10499, "▲topfeb": 10663, "▲topjan": 10601, "▲topjul": 10572, "▲topjun": 10263, "▲topmar": 10172, "▲topmay": 10144, "▲topnov": 10502, "▲topoct": 10135, "▲topsep": 10625, "△": 465, "▶": 466, "►": 467, "▼": 468, "▽": 469, "◆": 470, "◆◆": 11146, "◇": 471, "○": 472, "○○": 9423, "◎": 473, "●": 474, "◕": 475, "◠": 476, "◢": 477, "◤": 478, "☀": 479, "★": 480, "★★": 10034, "★★★": 10559, "★★★★": 11815, "★★★★★": 10349, "☆": 481, "☆☆☆": 12201, "☕": 482, "☞": 483, "☺": 484, "☼": 485, "♀": 486, "♂": 487, "♠": 488, "♡": 489, "♣": 490, "♥": 491, "♥yoyo♥": 8948, "♦": 492, "♪": 493, "♫": 494, "♬": 495, "✈": 496, "✔": 497, "✕": 498, "✖": 499, "✦": 500, "✨": 501, "✪": 502, "✰": 503, "✿": 504, "❀": 505, "❤": 506, "❤2017": 8558, "➜": 507, "➤": 508, "⦿": 509, "、": 510, "。": 511, "〃": 512, "々": 513, "〇": 514, "〈": 515, "〉": 516, "《": 517, "》": 518, "「": 519, "」": 520, "『": 521, "』": 522, "【": 523, "】": 524, "〓": 525, "〔": 526, "〕": 527, "〖": 528, "〗": 529, "〜": 530, "〝": 531, "〞": 532, "ぁ": 533, "あ": 534, "あり": 10617, "ありな": 13022, "あります": 12737, "ぃ": 535, "い": 536, "いいえ": 8938, "いお": 11481, "いします": 10342, "いた": 12312, "いて": 11232, "いてす": 12837, "います": 9466, "いを": 12029, "う": 537, "ぇ": 538, "え": 539, "えて": 13095, "える": 10382, "お": 540, "か": 541, "かあります": 11163, "かある": 10070, "かお": 11252, "かかります": 9791, "かこさいます": 12835, "から": 8526, "からお": 9669, "からの": 12498, "き": 542, "きな": 10423, "きなしソフトサーヒス": 11811, "きを": 10995, "く": 543, "くたさい": 9052, "くの": 13167, "け": 544, "けた": 13182, "けます": 11841, "ける": 11132, "こ": 545, "この": 9134, "さ": 546, "さい": 9728, "された": 10438, "されています": 9604, "されます": 12001, "される": 12033, "さん": 10533, "さんも": 11835, "し": 547, "しい": 8596, "しかし": 12906, "しく": 9859, "した": 8819, "して": 8648, "しています": 9257, "している": 10084, "しているから": 12004, "していると": 11915, "しており": 12340, "してくたさい": 10650, "してくたさい♪この": 12151, "してみてくたさいね": 12142, "しにはとんとんワークケートを": 12152, "しの": 10270, "しました": 10182, "します": 8845, "す": 548, "すく": 12616, "する": 8553, "することかてきます": 11743, "するとあなたにもっとマッチした": 12153, "せ": 549, "せからこ": 12150, "せます": 10046, "せよ": 12767, "そ": 550, "そして": 11812, "その": 8782, "そんな": 11950, "た": 551, "たと": 12883, "ち": 552, "ちてすか": 9880, "ちてない": 9804, "っ": 553, "った": 9179, "って": 9127, "っています": 12202, "っている": 11859, "ってくたさい": 12900, "つ": 554, "て": 555, "てある": 12190, "てお": 10393, "てきちゃいます": 12136, "てきます": 11397, "てきる": 12313, "てした": 11331, "てす": 8296, "てすか": 11244, "ての": 9697, "ては": 9418, "ても": 9272, "と": 556, "という": 10741, "として": 10147, "とても": 12709, "との": 11093, "とは": 11556, "な": 557, "なお": 12663, "なし": 9930, "なと": 9744, "なとの": 10435, "なとはお": 12143, "なのて": 10925, "なら": 12604, "ならワークケートへ": 12154, "に": 558, "にお": 10768, "にこ": 13059, "について": 10779, "になります": 11028, "になる": 9322, "には": 8738, "にも": 9328, "により": 11301, "による": 12228, "ぬ": 559, "ね": 560, "の": 561, "のある": 10492, "のお": 8751, "のこ": 13016, "のないフロクに": 10900, "のハイト": 10583, "は": 562, "はい": 9781, "はお": 13232, "はしめまして": 13012, "はすへて": 11899, "は1ヶ": 11638, "ひ": 563, "ふ": 564, "へ": 565, "への": 11021, "ほ": 566, "ま": 567, "ます": 11105, "また": 9301, "または": 12019, "まて": 9642, "み": 568, "みいたたけます": 9825, "みてす": 11870, "みの": 10354, "みリストを": 11196, "む": 569, "め": 570, "めた": 12578, "めて": 11967, "める": 12368, "も": 571, "もう": 12187, "もちろん": 12868, "もっと": 10642, "もみつかっちゃうかも": 12155, "ゃ": 572, "や": 573, "ゅ": 574, "ゆ": 575, "ょ": 576, "よ": 577, "より": 10230, "ら": 578, "られた": 11512, "り": 579, "りの": 10592, "りは": 13073, "る": 580, "れ": 581, "れた": 13163, "れる": 13148, "ろ": 582, "わ": 583, "わせ": 11878, "を": 584, "をお": 8651, "をこ": 10074, "ん": 585, "゜": 586, "ゝ": 587, "ァ": 588, "ア": 589, "ィ": 590, "イ": 591, "イカせるテンマ": 10885, "ゥ": 592, "ウ": 593, "ェ": 594, "エ": 595, "ォ": 596, "オ": 597, "オーフン5": 11810, "カ": 598, "キ": 599, "ク": 600, "ケ": 601, "コ": 602, "コメント": 12167, "サ": 603, "サイト": 11572, "サイトは": 11063, "サーヒス": 12501, "シ": 604, "ス": 605, "スキル": 11862, "スタッフ": 9903, "スホンサー": 10948, "スホンサーサイト": 12314, "セ": 606, "ソ": 607, "タ": 608, "チ": 609, "ッ": 610, "ツ": 611, "テ": 612, "テリヘル": 12739, "ト": 613, "トラックハック": 12766, "ナ": 614, "ニ": 615, "ヌ": 616, "ネ": 617, "ノ": 618, "ハ": 619, "ヒ": 620, "ヒンクテンマ3": 10886, "フ": 621, "ヘ": 622, "ホ": 623, "マ": 624, "ミ": 625, "ム": 626, "メ": 627, "メーカー": 12052, "モ": 628, "ャ": 629, "ヤ": 630, "ュ": 631, "ユ": 632, "ョ": 633, "ヨ": 634, "ラ": 635, "リ": 636, "リストに": 11101, "ル": 637, "レ": 638, "ロ": 639, "ロクイン": 12071, "ワ": 640, "ワークケートの": 12156, "ヲ": 641, "ン": 642, "ヶ": 643, "・": 644, "ー": 645, "ヽ": 646, "ㄅ": 647, "ㄆ": 648, "ㄇ": 649, "ㄉ": 650, "ㄋ": 651, "ㄌ": 652, "ㄍ": 653, "ㄎ": 654, "ㄏ": 655, "ㄒ": 656, "ㄚ": 657, "ㄛ": 658, "ㄞ": 659, "ㄟ": 660, "ㄢ": 661, "ㄤ": 662, "ㄥ": 663, "ㄧ": 664, "ㄨ": 665, "ㆍ": 666, "㈦": 667, "㊣": 668, "㎡": 669, "㗎": 670, "一": 671, "丁": 672, "七": 673, "万": 674, "丈": 675, "三": 676, "上": 677, "下": 678, "不": 679, "与": 680, "丐": 681, "丑": 682, "专": 683, "且": 684, "丕": 685, "世": 686, "丘": 687, "丙": 688, "业": 689, "丛": 690, "东": 691, "丝": 692, "丞": 693, "丟": 694, "両": 695, "丢": 696, "两": 697, "严": 698, "並": 699, "丧": 700, "丨": 701, "个": 702, "丫": 703, "中": 704, "丰": 705, "串": 706, "临": 707, "丶": 708, "丸": 709, "丹": 710, "为": 711, "主": 712, "丼": 713, "丽": 714, "举": 715, "丿": 716, "乂": 717, "乃": 718, "久": 719, "么": 720, "义": 721, "之": 722, "乌": 723, "乍": 724, "乎": 725, "乏": 726, "乐": 727, "乒": 728, "乓": 729, "乔": 730, "乖": 731, "乗": 732, "乘": 733, "乙": 734, "乜": 735, "九": 736, "乞": 737, "也": 738, "习": 739, "乡": 740, "书": 741, "乩": 742, "买": 743, "乱": 744, "乳": 745, "乾": 746, "亀": 747, "亂": 748, "了": 749, "予": 750, "争": 751, "事": 752, "二": 753, "于": 754, "亏": 755, "云": 756, "互": 757, "五": 758, "井": 759, "亘": 760, "亙": 761, "亚": 762, "些": 763, "亜": 764, "亞": 765, "亟": 766, "亡": 767, "亢": 768, "交": 769, "亥": 770, "亦": 771, "产": 772, "亨": 773, "亩": 774, "享": 775, "京": 776, "亭": 777, "亮": 778, "亲": 779, "亳": 780, "亵": 781, "人": 782, "亿": 783, "什": 784, "仁": 785, "仃": 786, "仄": 787, "仅": 788, "仆": 789, "仇": 790, "今": 791, "介": 792, "仍": 793, "从": 794, "仏": 795, "仑": 796, "仓": 797, "仔": 798, "仕": 799, "他": 800, "仗": 801, "付": 802, "仙": 803, "仝": 804, "仞": 805, "仟": 806, "代": 807, "令": 808, "以": 809, "仨": 810, "仪": 811, "们": 812, "仮": 813, "仰": 814, "仲": 815, "件": 816, "价": 817, "任": 818, "份": 819, "仿": 820, "企": 821, "伉": 822, "伊": 823, "伍": 824, "伎": 825, "伏": 826, "伐": 827, "休": 828, "伕": 829, "众": 830, "优": 831, "伙": 832, "会": 833, "伝": 834, "伞": 835, "伟": 836, "传": 837, "伢": 838, "伤": 839, "伦": 840, "伪": 841, "伫": 842, "伯": 843, "估": 844, "伴": 845, "伶": 846, "伸": 847, "伺": 848, "似": 849, "伽": 850, "佃": 851, "但": 852, "佇": 853, "佈": 854, "位": 855, "低": 856, "住": 857, "佐": 858, "佑": 859, "体": 860, "佔": 861, "何": 862, "佗": 863, "佘": 864, "余": 865, "佚": 866, "佛": 867, "作": 868, "佝": 869, "佞": 870, "佟": 871, "你": 872, "佢": 873, "佣": 874, "佤": 875, "佥": 876, "佩": 877, "佬": 878, "佯": 879, "佰": 880, "佳": 881, "併": 882, "佶": 883, "佻": 884, "佼": 885, "使": 886, "侃": 887, "侄": 888, "來": 889, "侈": 890, "例": 891, "侍": 892, "侏": 893, "侑": 894, "侖": 895, "侗": 896, "供": 897, "依": 898, "侠": 899, "価": 900, "侣": 901, "侥": 902, "侦": 903, "侧": 904, "侨": 905, "侬": 906, "侮": 907, "侯": 908, "侵": 909, "侶": 910, "侷": 911, "便": 912, "係": 913, "促": 914, "俄": 915, "俊": 916, "俎": 917, "俏": 918, "俐": 919, "俑": 920, "俗": 921, "俘": 922, "俚": 923, "保": 924, "俞": 925, "俟": 926, "俠": 927, "信": 928, "俨": 929, "俩": 930, "俪": 931, "俬": 932, "俭": 933, "修": 934, "俯": 935, "俱": 936, "俳": 937, "俸": 938, "俺": 939, "俾": 940, "倆": 941, "倉": 942, "個": 943, "倌": 944, "倍": 945, "倏": 946, "們": 947, "倒": 948, "倔": 949, "倖": 950, "倘": 951, "候": 952, "倚": 953, "倜": 954, "借": 955, "倡": 956, "値": 957, "倦": 958, "倩": 959, "倪": 960, "倫": 961, "倬": 962, "倭": 963, "倶": 964, "债": 965, "值": 966, "倾": 967, "偃": 968, "假": 969, "偈": 970, "偉": 971, "偌": 972, "偎": 973, "偏": 974, "偕": 975, "做": 976, "停": 977, "健": 978, "側": 979, "偵": 980, "偶": 981, "偷": 982, "偻": 983, "偽": 984, "偿": 985, "傀": 986, "傅": 987, "傍": 988, "傑": 989, "傘": 990, "備": 991, "傚": 992, "傢": 993, "傣": 994, "傥": 995, "储": 996, "傩": 997, "催": 998, "傭": 999, "傲": 1000, "傳": 1001, "債": 1002, "傷": 1003, "傻": 1004, "傾": 1005, "僅": 1006, "働": 1007, "像": 1008, "僑": 1009, "僕": 1010, "僖": 1011, "僚": 1012, "僥": 1013, "僧": 1014, "僭": 1015, "僮": 1016, "僱": 1017, "僵": 1018, "價": 1019, "僻": 1020, "儀": 1021, "儂": 1022, "億": 1023, "儆": 1024, "儉": 1025, "儋": 1026, "儒": 1027, "儕": 1028, "儘": 1029, "償": 1030, "儡": 1031, "優": 1032, "儲": 1033, "儷": 1034, "儼": 1035, "儿": 1036, "兀": 1037, "允": 1038, "元": 1039, "兄": 1040, "充": 1041, "兆": 1042, "兇": 1043, "先": 1044, "光": 1045, "克": 1046, "兌": 1047, "免": 1048, "児": 1049, "兑": 1050, "兒": 1051, "兔": 1052, "兖": 1053, "党": 1054, "兜": 1055, "兢": 1056, "入": 1057, "內": 1058, "全": 1059, "兩": 1060, "八": 1061, "公": 1062, "六": 1063, "兮": 1064, "兰": 1065, "共": 1066, "兲": 1067, "关": 1068, "兴": 1069, "兵": 1070, "其": 1071, "具": 1072, "典": 1073, "兹": 1074, "养": 1075, "兼": 1076, "兽": 1077, "冀": 1078, "内": 1079, "円": 1080, "冇": 1081, "冈": 1082, "冉": 1083, "冊": 1084, "册": 1085, "再": 1086, "冏": 1087, "冒": 1088, "冕": 1089, "冗": 1090, "写": 1091, "军": 1092, "农": 1093, "冠": 1094, "冢": 1095, "冤": 1096, "冥": 1097, "冨": 1098, "冪": 1099, "冬": 1100, "冯": 1101, "冰": 1102, "冲": 1103, "决": 1104, "况": 1105, "冶": 1106, "冷": 1107, "冻": 1108, "冼": 1109, "冽": 1110, "冾": 1111, "净": 1112, "凄": 1113, "准": 1114, "凇": 1115, "凈": 1116, "凉": 1117, "凋": 1118, "凌": 1119, "凍": 1120, "减": 1121, "凑": 1122, "凛": 1123, "凜": 1124, "凝": 1125, "几": 1126, "凡": 1127, "凤": 1128, "処": 1129, "凪": 1130, "凭": 1131, "凯": 1132, "凰": 1133, "凱": 1134, "凳": 1135, "凶": 1136, "凸": 1137, "凹": 1138, "出": 1139, "击": 1140, "函": 1141, "凿": 1142, "刀": 1143, "刁": 1144, "刃": 1145, "分": 1146, "切": 1147, "刈": 1148, "刊": 1149, "刍": 1150, "刎": 1151, "刑": 1152, "划": 1153, "列": 1154, "刘": 1155, "则": 1156, "刚": 1157, "创": 1158, "初": 1159, "删": 1160, "判": 1161, "別": 1162, "刨": 1163, "利": 1164, "刪": 1165, "别": 1166, "刮": 1167, "到": 1168, "制": 1169, "刷": 1170, "券": 1171, "刹": 1172, "刺": 1173, "刻": 1174, "刽": 1175, "剁": 1176, "剂": 1177, "剃": 1178, "則": 1179, "剉": 1180, "削": 1181, "剋": 1182, "剌": 1183, "前": 1184, "剎": 1185, "剐": 1186, "剑": 1187, "剔": 1188, "剖": 1189, "剛": 1190, "剜": 1191, "剝": 1192, "剣": 1193, "剤": 1194, "剥": 1195, "剧": 1196, "剩": 1197, "剪": 1198, "副": 1199, "割": 1200, "創": 1201, "剷": 1202, "剽": 1203, "剿": 1204, "劃": 1205, "劇": 1206, "劈": 1207, "劉": 1208, "劊": 1209, "劍": 1210, "劏": 1211, "劑": 1212, "力": 1213, "劝": 1214, "办": 1215, "功": 1216, "加": 1217, "务": 1218, "劣": 1219, "动": 1220, "助": 1221, "努": 1222, "劫": 1223, "劭": 1224, "励": 1225, "劲": 1226, "劳": 1227, "労": 1228, "劵": 1229, "効": 1230, "劾": 1231, "势": 1232, "勁": 1233, "勃": 1234, "勇": 1235, "勉": 1236, "勋": 1237, "勐": 1238, "勒": 1239, "動": 1240, "勖": 1241, "勘": 1242, "務": 1243, "勛": 1244, "勝": 1245, "勞": 1246, "募": 1247, "勢": 1248, "勤": 1249, "勧": 1250, "勳": 1251, "勵": 1252, "勸": 1253, "勺": 1254, "勻": 1255, "勾": 1256, "勿": 1257, "匀": 1258, "包": 1259, "匆": 1260, "匈": 1261, "匍": 1262, "匐": 1263, "匕": 1264, "化": 1265, "北": 1266, "匙": 1267, "匝": 1268, "匠": 1269, "匡": 1270, "匣": 1271, "匪": 1272, "匮": 1273, "匯": 1274, "匱": 1275, "匹": 1276, "区": 1277, "医": 1278, "匾": 1279, "匿": 1280, "區": 1281, "十": 1282, "千": 1283, "卅": 1284, "升": 1285, "午": 1286, "卉": 1287, "半": 1288, "卍": 1289, "华": 1290, "协": 1291, "卑": 1292, "卒": 1293, "卓": 1294, "協": 1295, "单": 1296, "卖": 1297, "南": 1298, "単": 1299, "博": 1300, "卜": 1301, "卞": 1302, "卟": 1303, "占": 1304, "卡": 1305, "卢": 1306, "卤": 1307, "卦": 1308, "卧": 1309, "卫": 1310, "卮": 1311, "卯": 1312, "印": 1313, "危": 1314, "即": 1315, "却": 1316, "卵": 1317, "卷": 1318, "卸": 1319, "卻": 1320, "卿": 1321, "厂": 1322, "厄": 1323, "厅": 1324, "历": 1325, "厉": 1326, "压": 1327, "厌": 1328, "厕": 1329, "厘": 1330, "厚": 1331, "厝": 1332, "原": 1333, "厢": 1334, "厥": 1335, "厦": 1336, "厨": 1337, "厩": 1338, "厭": 1339, "厮": 1340, "厲": 1341, "厳": 1342, "去": 1343, "县": 1344, "叁": 1345, "参": 1346, "參": 1347, "又": 1348, "叉": 1349, "及": 1350, "友": 1351, "双": 1352, "反": 1353, "収": 1354, "发": 1355, "叔": 1356, "取": 1357, "受": 1358, "变": 1359, "叙": 1360, "叛": 1361, "叟": 1362, "叠": 1363, "叡": 1364, "叢": 1365, "口": 1366, "古": 1367, "句": 1368, "另": 1369, "叨": 1370, "叩": 1371, "只": 1372, "叫": 1373, "召": 1374, "叭": 1375, "叮": 1376, "可": 1377, "台": 1378, "叱": 1379, "史": 1380, "右": 1381, "叵": 1382, "叶": 1383, "号": 1384, "司": 1385, "叹": 1386, "叻": 1387, "叼": 1388, "叽": 1389, "吁": 1390, "吃": 1391, "各": 1392, "吆": 1393, "合": 1394, "吉": 1395, "吊": 1396, "吋": 1397, "同": 1398, "名": 1399, "后": 1400, "吏": 1401, "吐": 1402, "向": 1403, "吒": 1404, "吓": 1405, "吕": 1406, "吖": 1407, "吗": 1408, "君": 1409, "吝": 1410, "吞": 1411, "吟": 1412, "吠": 1413, "吡": 1414, "否": 1415, "吧": 1416, "吨": 1417, "吩": 1418, "含": 1419, "听": 1420, "吭": 1421, "吮": 1422, "启": 1423, "吱": 1424, "吳": 1425, "吴": 1426, "吵": 1427, "吶": 1428, "吸": 1429, "吹": 1430, "吻": 1431, "吼": 1432, "吽": 1433, "吾": 1434, "呀": 1435, "呂": 1436, "呃": 1437, "呆": 1438, "呈": 1439, "告": 1440, "呋": 1441, "呎": 1442, "呐": 1443, "呓": 1444, "呕": 1445, "呗": 1446, "员": 1447, "呛": 1448, "呜": 1449, "呢": 1450, "呤": 1451, "呦": 1452, "周": 1453, "呱": 1454, "呲": 1455, "味": 1456, "呵": 1457, "呷": 1458, "呸": 1459, "呻": 1460, "呼": 1461, "命": 1462, "咀": 1463, "咁": 1464, "咂": 1465, "咄": 1466, "咆": 1467, "咋": 1468, "和": 1469, "咎": 1470, "咏": 1471, "咐": 1472, "咒": 1473, "咔": 1474, "咕": 1475, "咖": 1476, "咗": 1477, "咘": 1478, "咙": 1479, "咚": 1480, "咛": 1481, "咣": 1482, "咤": 1483, "咦": 1484, "咧": 1485, "咨": 1486, "咩": 1487, "咪": 1488, "咫": 1489, "咬": 1490, "咭": 1491, "咯": 1492, "咱": 1493, "咲": 1494, "咳": 1495, "咸": 1496, "咻": 1497, "咽": 1498, "咿": 1499, "哀": 1500, "品": 1501, "哂": 1502, "哄": 1503, "哆": 1504, "哇": 1505, "哈": 1506, "哉": 1507, "哋": 1508, "哌": 1509, "响": 1510, "哎": 1511, "哏": 1512, "哐": 1513, "哑": 1514, "哒": 1515, "哔": 1516, "哗": 1517, "哟": 1518, "員": 1519, "哥": 1520, "哦": 1521, "哧": 1522, "哨": 1523, "哩": 1524, "哪": 1525, "哭": 1526, "哮": 1527, "哲": 1528, "哺": 1529, "哼": 1530, "哽": 1531, "唁": 1532, "唄": 1533, "唆": 1534, "唇": 1535, "唉": 1536, "唏": 1537, "唐": 1538, "唑": 1539, "唔": 1540, "唠": 1541, "唤": 1542, "唧": 1543, "唬": 1544, "售": 1545, "唯": 1546, "唰": 1547, "唱": 1548, "唳": 1549, "唷": 1550, "唸": 1551, "唾": 1552, "啃": 1553, "啄": 1554, "商": 1555, "啉": 1556, "啊": 1557, "問": 1558, "啓": 1559, "啕": 1560, "啖": 1561, "啜": 1562, "啞": 1563, "啟": 1564, "啡": 1565, "啤": 1566, "啥": 1567, "啦": 1568, "啧": 1569, "啪": 1570, "啫": 1571, "啬": 1572, "啮": 1573, "啰": 1574, "啱": 1575, "啲": 1576, "啵": 1577, "啶": 1578, "啷": 1579, "啸": 1580, "啻": 1581, "啼": 1582, "啾": 1583, "喀": 1584, "喂": 1585, "喃": 1586, "善": 1587, "喆": 1588, "喇": 1589, "喉": 1590, "喊": 1591, "喋": 1592, "喎": 1593, "喏": 1594, "喔": 1595, "喘": 1596, "喙": 1597, "喚": 1598, "喜": 1599, "喝": 1600, "喟": 1601, "喧": 1602, "喪": 1603, "喫": 1604, "喬": 1605, "單": 1606, "喰": 1607, "喱": 1608, "喲": 1609, "喳": 1610, "喵": 1611, "営": 1612, "喷": 1613, "喹": 1614, "喺": 1615, "喻": 1616, "喽": 1617, "嗅": 1618, "嗆": 1619, "嗇": 1620, "嗎": 1621, "嗑": 1622, "嗒": 1623, "嗓": 1624, "嗔": 1625, "嗖": 1626, "嗚": 1627, "嗜": 1628, "嗝": 1629, "嗟": 1630, "嗡": 1631, "嗣": 1632, "嗤": 1633, "嗦": 1634, "嗨": 1635, "嗪": 1636, "嗬": 1637, "嗯": 1638, "嗰": 1639, "嗲": 1640, "嗳": 1641, "嗶": 1642, "嗷": 1643, "嗽": 1644, "嘀": 1645, "嘅": 1646, "嘆": 1647, "嘈": 1648, "嘉": 1649, "嘌": 1650, "嘍": 1651, "嘎": 1652, "嘔": 1653, "嘖": 1654, "嘗": 1655, "嘘": 1656, "嘚": 1657, "嘛": 1658, "嘜": 1659, "嘞": 1660, "嘟": 1661, "嘢": 1662, "嘣": 1663, "嘤": 1664, "嘧": 1665, "嘩": 1666, "嘭": 1667, "嘮": 1668, "嘯": 1669, "嘰": 1670, "嘱": 1671, "嘲": 1672, "嘴": 1673, "嘶": 1674, "嘸": 1675, "嘹": 1676, "嘻": 1677, "嘿": 1678, "噁": 1679, "噌": 1680, "噎": 1681, "噓": 1682, "噔": 1683, "噗": 1684, "噙": 1685, "噜": 1686, "噠": 1687, "噢": 1688, "噤": 1689, "器": 1690, "噩": 1691, "噪": 1692, "噬": 1693, "噱": 1694, "噴": 1695, "噶": 1696, "噸": 1697, "噹": 1698, "噻": 1699, "噼": 1700, "嚀": 1701, "嚇": 1702, "嚎": 1703, "嚏": 1704, "嚐": 1705, "嚓": 1706, "嚕": 1707, "嚟": 1708, "嚣": 1709, "嚥": 1710, "嚨": 1711, "嚮": 1712, "嚴": 1713, "嚷": 1714, "嚼": 1715, "囂": 1716, "囉": 1717, "囊": 1718, "囍": 1719, "囑": 1720, "囔": 1721, "囗": 1722, "囚": 1723, "四": 1724, "囝": 1725, "回": 1726, "囟": 1727, "因": 1728, "囡": 1729, "团": 1730, "団": 1731, "囤": 1732, "囧": 1733, "囪": 1734, "囫": 1735, "园": 1736, "困": 1737, "囱": 1738, "囲": 1739, "図": 1740, "围": 1741, "囹": 1742, "固": 1743, "国": 1744, "图": 1745, "囿": 1746, "圃": 1747, "圄": 1748, "圆": 1749, "圈": 1750, "國": 1751, "圍": 1752, "圏": 1753, "園": 1754, "圓": 1755, "圖": 1756, "團": 1757, "圜": 1758, "土": 1759, "圣": 1760, "圧": 1761, "在": 1762, "圩": 1763, "圭": 1764, "地": 1765, "圳": 1766, "场": 1767, "圻": 1768, "圾": 1769, "址": 1770, "坂": 1771, "均": 1772, "坊": 1773, "坍": 1774, "坎": 1775, "坏": 1776, "坐": 1777, "坑": 1778, "块": 1779, "坚": 1780, "坛": 1781, "坝": 1782, "坞": 1783, "坟": 1784, "坠": 1785, "坡": 1786, "坤": 1787, "坦": 1788, "坨": 1789, "坪": 1790, "坯": 1791, "坳": 1792, "坵": 1793, "坷": 1794, "垂": 1795, "垃": 1796, "垄": 1797, "型": 1798, "垒": 1799, "垚": 1800, "垛": 1801, "垠": 1802, "垢": 1803, "垣": 1804, "垦": 1805, "垩": 1806, "垫": 1807, "垭": 1808, "垮": 1809, "垵": 1810, "埂": 1811, "埃": 1812, "埋": 1813, "城": 1814, "埔": 1815, "埕": 1816, "埗": 1817, "域": 1818, "埠": 1819, "埤": 1820, "埵": 1821, "執": 1822, "埸": 1823, "培": 1824, "基": 1825, "埼": 1826, "堀": 1827, "堂": 1828, "堃": 1829, "堅": 1830, "堆": 1831, "堇": 1832, "堑": 1833, "堕": 1834, "堙": 1835, "堡": 1836, "堤": 1837, "堪": 1838, "堯": 1839, "堰": 1840, "報": 1841, "場": 1842, "堵": 1843, "堺": 1844, "堿": 1845, "塊": 1846, "塌": 1847, "塑": 1848, "塔": 1849, "塗": 1850, "塘": 1851, "塚": 1852, "塞": 1853, "塢": 1854, "塩": 1855, "填": 1856, "塬": 1857, "塭": 1858, "塵": 1859, "塾": 1860, "墀": 1861, "境": 1862, "墅": 1863, "墉": 1864, "墊": 1865, "墒": 1866, "墓": 1867, "増": 1868, "墘": 1869, "墙": 1870, "墜": 1871, "增": 1872, "墟": 1873, "墨": 1874, "墩": 1875, "墮": 1876, "墳": 1877, "墻": 1878, "墾": 1879, "壁": 1880, "壅": 1881, "壆": 1882, "壇": 1883, "壊": 1884, "壑": 1885, "壓": 1886, "壕": 1887, "壘": 1888, "壞": 1889, "壟": 1890, "壢": 1891, "壤": 1892, "壩": 1893, "士": 1894, "壬": 1895, "壮": 1896, "壯": 1897, "声": 1898, "売": 1899, "壳": 1900, "壶": 1901, "壹": 1902, "壺": 1903, "壽": 1904, "处": 1905, "备": 1906, "変": 1907, "复": 1908, "夏": 1909, "夔": 1910, "夕": 1911, "外": 1912, "夙": 1913, "多": 1914, "夜": 1915, "够": 1916, "夠": 1917, "夢": 1918, "夥": 1919, "大": 1920, "天": 1921, "太": 1922, "夫": 1923, "夭": 1924, "央": 1925, "夯": 1926, "失": 1927, "头": 1928, "夷": 1929, "夸": 1930, "夹": 1931, "夺": 1932, "夾": 1933, "奂": 1934, "奄": 1935, "奇": 1936, "奈": 1937, "奉": 1938, "奋": 1939, "奎": 1940, "奏": 1941, "奐": 1942, "契": 1943, "奔": 1944, "奕": 1945, "奖": 1946, "套": 1947, "奘": 1948, "奚": 1949, "奠": 1950, "奢": 1951, "奥": 1952, "奧": 1953, "奪": 1954, "奬": 1955, "奮": 1956, "女": 1957, "奴": 1958, "奶": 1959, "奸": 1960, "她": 1961, "好": 1962, "如": 1963, "妃": 1964, "妄": 1965, "妆": 1966, "妇": 1967, "妈": 1968, "妊": 1969, "妍": 1970, "妒": 1971, "妓": 1972, "妖": 1973, "妘": 1974, "妙": 1975, "妝": 1976, "妞": 1977, "妣": 1978, "妤": 1979, "妥": 1980, "妨": 1981, "妩": 1982, "妪": 1983, "妮": 1984, "妲": 1985, "妳": 1986, "妹": 1987, "妻": 1988, "妾": 1989, "姆": 1990, "姉": 1991, "姊": 1992, "始": 1993, "姍": 1994, "姐": 1995, "姑": 1996, "姒": 1997, "姓": 1998, "委": 1999, "姗": 2000, "姚": 2001, "姜": 2002, "姝": 2003, "姣": 2004, "姥": 2005, "姦": 2006, "姨": 2007, "姪": 2008, "姫": 2009, "姬": 2010, "姹": 2011, "姻": 2012, "姿": 2013, "威": 2014, "娃": 2015, "娄": 2016, "娅": 2017, "娆": 2018, "娇": 2019, "娉": 2020, "娑": 2021, "娓": 2022, "娘": 2023, "娛": 2024, "娜": 2025, "娟": 2026, "娠": 2027, "娣": 2028, "娥": 2029, "娩": 2030, "娱": 2031, "娲": 2032, "娴": 2033, "娶": 2034, "娼": 2035, "婀": 2036, "婁": 2037, "婆": 2038, "婉": 2039, "婊": 2040, "婕": 2041, "婚": 2042, "婢": 2043, "婦": 2044, "婧": 2045, "婪": 2046, "婭": 2047, "婴": 2048, "婵": 2049, "婶": 2050, "婷": 2051, "婺": 2052, "婿": 2053, "媒": 2054, "媚": 2055, "媛": 2056, "媞": 2057, "媧": 2058, "媲": 2059, "媳": 2060, "媽": 2061, "媾": 2062, "嫁": 2063, "嫂": 2064, "嫉": 2065, "嫌": 2066, "嫑": 2067, "嫔": 2068, "嫖": 2069, "嫘": 2070, "嫚": 2071, "嫡": 2072, "嫣": 2073, "嫦": 2074, "嫩": 2075, "嫲": 2076, "嫵": 2077, "嫻": 2078, "嬅": 2079, "嬉": 2080, "嬌": 2081, "嬗": 2082, "嬛": 2083, "嬢": 2084, "嬤": 2085, "嬪": 2086, "嬰": 2087, "嬴": 2088, "嬷": 2089, "嬸": 2090, "嬿": 2091, "孀": 2092, "孃": 2093, "子": 2094, "孑": 2095, "孔": 2096, "孕": 2097, "孖": 2098, "字": 2099, "存": 2100, "孙": 2101, "孚": 2102, "孛": 2103, "孜": 2104, "孝": 2105, "孟": 2106, "孢": 2107, "季": 2108, "孤": 2109, "学": 2110, "孩": 2111, "孪": 2112, "孫": 2113, "孬": 2114, "孰": 2115, "孱": 2116, "孳": 2117, "孵": 2118, "學": 2119, "孺": 2120, "孽": 2121, "孿": 2122, "宁": 2123, "它": 2124, "宅": 2125, "宇": 2126, "守": 2127, "安": 2128, "宋": 2129, "完": 2130, "宏": 2131, "宓": 2132, "宕": 2133, "宗": 2134, "官": 2135, "宙": 2136, "定": 2137, "宛": 2138, "宜": 2139, "宝": 2140, "实": 2141, "実": 2142, "宠": 2143, "审": 2144, "客": 2145, "宣": 2146, "室": 2147, "宥": 2148, "宦": 2149, "宪": 2150, "宫": 2151, "宮": 2152, "宰": 2153, "害": 2154, "宴": 2155, "宵": 2156, "家": 2157, "宸": 2158, "容": 2159, "宽": 2160, "宾": 2161, "宿": 2162, "寂": 2163, "寄": 2164, "寅": 2165, "密": 2166, "寇": 2167, "富": 2168, "寐": 2169, "寒": 2170, "寓": 2171, "寛": 2172, "寝": 2173, "寞": 2174, "察": 2175, "寡": 2176, "寢": 2177, "寥": 2178, "實": 2179, "寧": 2180, "寨": 2181, "審": 2182, "寫": 2183, "寬": 2184, "寮": 2185, "寰": 2186, "寵": 2187, "寶": 2188, "寸": 2189, "对": 2190, "寺": 2191, "寻": 2192, "导": 2193, "対": 2194, "寿": 2195, "封": 2196, "専": 2197, "射": 2198, "将": 2199, "將": 2200, "專": 2201, "尉": 2202, "尊": 2203, "尋": 2204, "對": 2205, "導": 2206, "小": 2207, "少": 2208, "尔": 2209, "尕": 2210, "尖": 2211, "尘": 2212, "尚": 2213, "尝": 2214, "尤": 2215, "尧": 2216, "尬": 2217, "就": 2218, "尴": 2219, "尷": 2220, "尸": 2221, "尹": 2222, "尺": 2223, "尻": 2224, "尼": 2225, "尽": 2226, "尾": 2227, "尿": 2228, "局": 2229, "屁": 2230, "层": 2231, "屄": 2232, "居": 2233, "屆": 2234, "屈": 2235, "屉": 2236, "届": 2237, "屋": 2238, "屌": 2239, "屍": 2240, "屎": 2241, "屏": 2242, "屐": 2243, "屑": 2244, "展": 2245, "屜": 2246, "属": 2247, "屠": 2248, "屡": 2249, "屢": 2250, "層": 2251, "履": 2252, "屬": 2253, "屯": 2254, "山": 2255, "屹": 2256, "屿": 2257, "岀": 2258, "岁": 2259, "岂": 2260, "岌": 2261, "岐": 2262, "岑": 2263, "岔": 2264, "岖": 2265, "岗": 2266, "岘": 2267, "岙": 2268, "岚": 2269, "岛": 2270, "岡": 2271, "岩": 2272, "岫": 2273, "岬": 2274, "岭": 2275, "岱": 2276, "岳": 2277, "岷": 2278, "岸": 2279, "峇": 2280, "峋": 2281, "峒": 2282, "峙": 2283, "峡": 2284, "峤": 2285, "峥": 2286, "峦": 2287, "峨": 2288, "峪": 2289, "峭": 2290, "峯": 2291, "峰": 2292, "峴": 2293, "島": 2294, "峻": 2295, "峽": 2296, "崁": 2297, "崂": 2298, "崆": 2299, "崇": 2300, "崎": 2301, "崑": 2302, "崔": 2303, "崖": 2304, "崗": 2305, "崙": 2306, "崛": 2307, "崧": 2308, "崩": 2309, "崭": 2310, "崴": 2311, "崽": 2312, "嵇": 2313, "嵊": 2314, "嵋": 2315, "嵌": 2316, "嵐": 2317, "嵘": 2318, "嵩": 2319, "嵬": 2320, "嵯": 2321, "嶂": 2322, "嶄": 2323, "嶇": 2324, "嶋": 2325, "嶙": 2326, "嶺": 2327, "嶼": 2328, "嶽": 2329, "巅": 2330, "巍": 2331, "巒": 2332, "巔": 2333, "巖": 2334, "川": 2335, "州": 2336, "巡": 2337, "巢": 2338, "工": 2339, "左": 2340, "巧": 2341, "巨": 2342, "巩": 2343, "巫": 2344, "差": 2345, "己": 2346, "已": 2347, "巳": 2348, "巴": 2349, "巷": 2350, "巻": 2351, "巽": 2352, "巾": 2353, "巿": 2354, "币": 2355, "市": 2356, "布": 2357, "帅": 2358, "帆": 2359, "师": 2360, "希": 2361, "帐": 2362, "帑": 2363, "帕": 2364, "帖": 2365, "帘": 2366, "帚": 2367, "帛": 2368, "帜": 2369, "帝": 2370, "帥": 2371, "带": 2372, "帧": 2373, "師": 2374, "席": 2375, "帮": 2376, "帯": 2377, "帰": 2378, "帳": 2379, "帶": 2380, "帷": 2381, "常": 2382, "帼": 2383, "帽": 2384, "幀": 2385, "幂": 2386, "幄": 2387, "幅": 2388, "幌": 2389, "幔": 2390, "幕": 2391, "幟": 2392, "幡": 2393, "幢": 2394, "幣": 2395, "幫": 2396, "干": 2397, "平": 2398, "年": 2399, "并": 2400, "幸": 2401, "幹": 2402, "幺": 2403, "幻": 2404, "幼": 2405, "幽": 2406, "幾": 2407, "广": 2408, "庁": 2409, "広": 2410, "庄": 2411, "庆": 2412, "庇": 2413, "床": 2414, "序": 2415, "庐": 2416, "库": 2417, "应": 2418, "底": 2419, "庖": 2420, "店": 2421, "庙": 2422, "庚": 2423, "府": 2424, "庞": 2425, "废": 2426, "庠": 2427, "度": 2428, "座": 2429, "庫": 2430, "庭": 2431, "庵": 2432, "庶": 2433, "康": 2434, "庸": 2435, "庹": 2436, "庾": 2437, "廁": 2438, "廂": 2439, "廃": 2440, "廈": 2441, "廉": 2442, "廊": 2443, "廓": 2444, "廖": 2445, "廚": 2446, "廝": 2447, "廟": 2448, "廠": 2449, "廢": 2450, "廣": 2451, "廬": 2452, "廳": 2453, "延": 2454, "廷": 2455, "建": 2456, "廿": 2457, "开": 2458, "弁": 2459, "异": 2460, "弃": 2461, "弄": 2462, "弈": 2463, "弊": 2464, "弋": 2465, "式": 2466, "弑": 2467, "弒": 2468, "弓": 2469, "弔": 2470, "引": 2471, "弗": 2472, "弘": 2473, "弛": 2474, "弟": 2475, "张": 2476, "弥": 2477, "弦": 2478, "弧": 2479, "弩": 2480, "弭": 2481, "弯": 2482, "弱": 2483, "張": 2484, "強": 2485, "弹": 2486, "强": 2487, "弼": 2488, "弾": 2489, "彅": 2490, "彆": 2491, "彈": 2492, "彌": 2493, "彎": 2494, "归": 2495, "当": 2496, "录": 2497, "彗": 2498, "彙": 2499, "彝": 2500, "形": 2501, "彤": 2502, "彥": 2503, "彦": 2504, "彧": 2505, "彩": 2506, "彪": 2507, "彫": 2508, "彬": 2509, "彭": 2510, "彰": 2511, "影": 2512, "彷": 2513, "役": 2514, "彻": 2515, "彼": 2516, "彿": 2517, "往": 2518, "征": 2519, "径": 2520, "待": 2521, "徇": 2522, "很": 2523, "徉": 2524, "徊": 2525, "律": 2526, "後": 2527, "徐": 2528, "徑": 2529, "徒": 2530, "従": 2531, "徕": 2532, "得": 2533, "徘": 2534, "徙": 2535, "徜": 2536, "從": 2537, "徠": 2538, "御": 2539, "徨": 2540, "復": 2541, "循": 2542, "徬": 2543, "微": 2544, "徳": 2545, "徴": 2546, "徵": 2547, "德": 2548, "徹": 2549, "徼": 2550, "徽": 2551, "心": 2552, "必": 2553, "忆": 2554, "忌": 2555, "忍": 2556, "忏": 2557, "忐": 2558, "忑": 2559, "忒": 2560, "忖": 2561, "志": 2562, "忘": 2563, "忙": 2564, "応": 2565, "忠": 2566, "忡": 2567, "忤": 2568, "忧": 2569, "忪": 2570, "快": 2571, "忱": 2572, "念": 2573, "忻": 2574, "忽": 2575, "忿": 2576, "怀": 2577, "态": 2578, "怂": 2579, "怅": 2580, "怆": 2581, "怎": 2582, "怏": 2583, "怒": 2584, "怔": 2585, "怕": 2586, "怖": 2587, "怙": 2588, "怜": 2589, "思": 2590, "怠": 2591, "怡": 2592, "急": 2593, "怦": 2594, "性": 2595, "怨": 2596, "怪": 2597, "怯": 2598, "怵": 2599, "总": 2600, "怼": 2601, "恁": 2602, "恃": 2603, "恆": 2604, "恋": 2605, "恍": 2606, "恐": 2607, "恒": 2608, "恕": 2609, "恙": 2610, "恚": 2611, "恢": 2612, "恣": 2613, "恤": 2614, "恥": 2615, "恨": 2616, "恩": 2617, "恪": 2618, "恫": 2619, "恬": 2620, "恭": 2621, "息": 2622, "恰": 2623, "恳": 2624, "恵": 2625, "恶": 2626, "恸": 2627, "恺": 2628, "恻": 2629, "恼": 2630, "恿": 2631, "悄": 2632, "悅": 2633, "悉": 2634, "悌": 2635, "悍": 2636, "悔": 2637, "悖": 2638, "悚": 2639, "悟": 2640, "悠": 2641, "患": 2642, "悦": 2643, "您": 2644, "悩": 2645, "悪": 2646, "悬": 2647, "悯": 2648, "悱": 2649, "悲": 2650, "悴": 2651, "悵": 2652, "悶": 2653, "悸": 2654, "悻": 2655, "悼": 2656, "悽": 2657, "情": 2658, "惆": 2659, "惇": 2660, "惊": 2661, "惋": 2662, "惑": 2663, "惕": 2664, "惘": 2665, "惚": 2666, "惜": 2667, "惟": 2668, "惠": 2669, "惡": 2670, "惦": 2671, "惧": 2672, "惨": 2673, "惩": 2674, "惫": 2675, "惬": 2676, "惭": 2677, "惮": 2678, "惯": 2679, "惰": 2680, "惱": 2681, "想": 2682, "惴": 2683, "惶": 2684, "惹": 2685, "惺": 2686, "愁": 2687, "愆": 2688, "愈": 2689, "愉": 2690, "愍": 2691, "意": 2692, "愕": 2693, "愚": 2694, "愛": 2695, "愜": 2696, "感": 2697, "愣": 2698, "愤": 2699, "愧": 2700, "愫": 2701, "愷": 2702, "愿": 2703, "慄": 2704, "慈": 2705, "態": 2706, "慌": 2707, "慎": 2708, "慑": 2709, "慕": 2710, "慘": 2711, "慚": 2712, "慟": 2713, "慢": 2714, "慣": 2715, "慧": 2716, "慨": 2717, "慫": 2718, "慮": 2719, "慰": 2720, "慳": 2721, "慵": 2722, "慶": 2723, "慷": 2724, "慾": 2725, "憂": 2726, "憊": 2727, "憋": 2728, "憎": 2729, "憐": 2730, "憑": 2731, "憔": 2732, "憚": 2733, "憤": 2734, "憧": 2735, "憨": 2736, "憩": 2737, "憫": 2738, "憬": 2739, "憲": 2740, "憶": 2741, "憾": 2742, "懂": 2743, "懇": 2744, "懈": 2745, "應": 2746, "懊": 2747, "懋": 2748, "懑": 2749, "懒": 2750, "懦": 2751, "懲": 2752, "懵": 2753, "懶": 2754, "懷": 2755, "懸": 2756, "懺": 2757, "懼": 2758, "懾": 2759, "懿": 2760, "戀": 2761, "戈": 2762, "戊": 2763, "戌": 2764, "戍": 2765, "戎": 2766, "戏": 2767, "成": 2768, "我": 2769, "戒": 2770, "戕": 2771, "或": 2772, "战": 2773, "戚": 2774, "戛": 2775, "戟": 2776, "戡": 2777, "戦": 2778, "截": 2779, "戬": 2780, "戮": 2781, "戰": 2782, "戲": 2783, "戳": 2784, "戴": 2785, "戶": 2786, "户": 2787, "戸": 2788, "戻": 2789, "戾": 2790, "房": 2791, "所": 2792, "扁": 2793, "扇": 2794, "扈": 2795, "扉": 2796, "手": 2797, "才": 2798, "扎": 2799, "扑": 2800, "扒": 2801, "打": 2802, "扔": 2803, "払": 2804, "托": 2805, "扛": 2806, "扣": 2807, "扦": 2808, "执": 2809, "扩": 2810, "扪": 2811, "扫": 2812, "扬": 2813, "扭": 2814, "扮": 2815, "扯": 2816, "扰": 2817, "扱": 2818, "扳": 2819, "扶": 2820, "批": 2821, "扼": 2822, "找": 2823, "承": 2824, "技": 2825, "抄": 2826, "抉": 2827, "把": 2828, "抑": 2829, "抒": 2830, "抓": 2831, "投": 2832, "抖": 2833, "抗": 2834, "折": 2835, "抚": 2836, "抛": 2837, "抜": 2838, "択": 2839, "抟": 2840, "抠": 2841, "抡": 2842, "抢": 2843, "护": 2844, "报": 2845, "抨": 2846, "披": 2847, "抬": 2848, "抱": 2849, "抵": 2850, "抹": 2851, "押": 2852, "抽": 2853, "抿": 2854, "拂": 2855, "拄": 2856, "担": 2857, "拆": 2858, "拇": 2859, "拈": 2860, "拉": 2861, "拋": 2862, "拌": 2863, "拍": 2864, "拎": 2865, "拐": 2866, "拒": 2867, "拓": 2868, "拔": 2869, "拖": 2870, "拗": 2871, "拘": 2872, "拙": 2873, "拚": 2874, "招": 2875, "拜": 2876, "拟": 2877, "拡": 2878, "拢": 2879, "拣": 2880, "拥": 2881, "拦": 2882, "拧": 2883, "拨": 2884, "择": 2885, "括": 2886, "拭": 2887, "拮": 2888, "拯": 2889, "拱": 2890, "拳": 2891, "拴": 2892, "拷": 2893, "拼": 2894, "拽": 2895, "拾": 2896, "拿": 2897, "持": 2898, "挂": 2899, "指": 2900, "挈": 2901, "按": 2902, "挎": 2903, "挑": 2904, "挖": 2905, "挙": 2906, "挚": 2907, "挛": 2908, "挝": 2909, "挞": 2910, "挟": 2911, "挠": 2912, "挡": 2913, "挣": 2914, "挤": 2915, "挥": 2916, "挨": 2917, "挪": 2918, "挫": 2919, "振": 2920, "挲": 2921, "挹": 2922, "挺": 2923, "挽": 2924, "挾": 2925, "捂": 2926, "捅": 2927, "捆": 2928, "捉": 2929, "捋": 2930, "捌": 2931, "捍": 2932, "捎": 2933, "捏": 2934, "捐": 2935, "捕": 2936, "捞": 2937, "损": 2938, "捡": 2939, "换": 2940, "捣": 2941, "捧": 2942, "捨": 2943, "捩": 2944, "据": 2945, "捱": 2946, "捲": 2947, "捶": 2948, "捷": 2949, "捺": 2950, "捻": 2951, "掀": 2952, "掂": 2953, "掃": 2954, "掇": 2955, "授": 2956, "掉": 2957, "掌": 2958, "掏": 2959, "掐": 2960, "排": 2961, "掖": 2962, "掘": 2963, "掙": 2964, "掛": 2965, "掠": 2966, "採": 2967, "探": 2968, "掣": 2969, "接": 2970, "控": 2971, "推": 2972, "掩": 2973, "措": 2974, "掬": 2975, "掰": 2976, "掲": 2977, "掳": 2978, "掴": 2979, "掷": 2980, "掸": 2981, "掺": 2982, "揀": 2983, "揃": 2984, "揄": 2985, "揆": 2986, "揉": 2987, "揍": 2988, "描": 2989, "提": 2990, "插": 2991, "揖": 2992, "揚": 2993, "換": 2994, "握": 2995, "揣": 2996, "揩": 2997, "揪": 2998, "揭": 2999, "揮": 3000, "援": 3001, "揶": 3002, "揸": 3003, "揹": 3004, "揽": 3005, "搀": 3006, "搁": 3007, "搂": 3008, "搅": 3009, "損": 3010, "搏": 3011, "搐": 3012, "搓": 3013, "搔": 3014, "搖": 3015, "搗": 3016, "搜": 3017, "搞": 3018, "搡": 3019, "搪": 3020, "搬": 3021, "搭": 3022, "搵": 3023, "搶": 3024, "携": 3025, "搽": 3026, "摀": 3027, "摁": 3028, "摄": 3029, "摆": 3030, "摇": 3031, "摈": 3032, "摊": 3033, "摒": 3034, "摔": 3035, "摘": 3036, "摞": 3037, "摟": 3038, "摧": 3039, "摩": 3040, "摯": 3041, "摳": 3042, "摸": 3043, "摹": 3044, "摺": 3045, "摻": 3046, "撂": 3047, "撃": 3048, "撅": 3049, "撇": 3050, "撈": 3051, "撐": 3052, "撑": 3053, "撒": 3054, "撓": 3055, "撕": 3056, "撚": 3057, "撞": 3058, "撤": 3059, "撥": 3060, "撩": 3061, "撫": 3062, "撬": 3063, "播": 3064, "撮": 3065, "撰": 3066, "撲": 3067, "撵": 3068, "撷": 3069, "撸": 3070, "撻": 3071, "撼": 3072, "撿": 3073, "擀": 3074, "擁": 3075, "擂": 3076, "擄": 3077, "擅": 3078, "擇": 3079, "擊": 3080, "擋": 3081, "操": 3082, "擎": 3083, "擒": 3084, "擔": 3085, "擘": 3086, "據": 3087, "擞": 3088, "擠": 3089, "擡": 3090, "擢": 3091, "擦": 3092, "擬": 3093, "擰": 3094, "擱": 3095, "擲": 3096, "擴": 3097, "擷": 3098, "擺": 3099, "擼": 3100, "擾": 3101, "攀": 3102, "攏": 3103, "攒": 3104, "攔": 3105, "攘": 3106, "攙": 3107, "攜": 3108, "攝": 3109, "攞": 3110, "攢": 3111, "攣": 3112, "攤": 3113, "攥": 3114, "攪": 3115, "攫": 3116, "攬": 3117, "支": 3118, "收": 3119, "攸": 3120, "改": 3121, "攻": 3122, "放": 3123, "政": 3124, "故": 3125, "效": 3126, "敌": 3127, "敍": 3128, "敎": 3129, "敏": 3130, "救": 3131, "敕": 3132, "敖": 3133, "敗": 3134, "敘": 3135, "教": 3136, "敛": 3137, "敝": 3138, "敞": 3139, "敢": 3140, "散": 3141, "敦": 3142, "敬": 3143, "数": 3144, "敲": 3145, "整": 3146, "敵": 3147, "敷": 3148, "數": 3149, "斂": 3150, "斃": 3151, "文": 3152, "斋": 3153, "斌": 3154, "斎": 3155, "斐": 3156, "斑": 3157, "斓": 3158, "斗": 3159, "料": 3160, "斛": 3161, "斜": 3162, "斟": 3163, "斡": 3164, "斤": 3165, "斥": 3166, "斧": 3167, "斩": 3168, "斫": 3169, "斬": 3170, "断": 3171, "斯": 3172, "新": 3173, "斷": 3174, "方": 3175, "於": 3176, "施": 3177, "旁": 3178, "旃": 3179, "旅": 3180, "旋": 3181, "旌": 3182, "旎": 3183, "族": 3184, "旖": 3185, "旗": 3186, "无": 3187, "既": 3188, "日": 3189, "旦": 3190, "旧": 3191, "旨": 3192, "早": 3193, "旬": 3194, "旭": 3195, "旮": 3196, "旱": 3197, "时": 3198, "旷": 3199, "旺": 3200, "旻": 3201, "昀": 3202, "昂": 3203, "昆": 3204, "昇": 3205, "昉": 3206, "昊": 3207, "昌": 3208, "明": 3209, "昏": 3210, "易": 3211, "昔": 3212, "昕": 3213, "昙": 3214, "星": 3215, "映": 3216, "春": 3217, "昧": 3218, "昨": 3219, "昭": 3220, "是": 3221, "昱": 3222, "昴": 3223, "昵": 3224, "昶": 3225, "昼": 3226, "显": 3227, "晁": 3228, "時": 3229, "晃": 3230, "晉": 3231, "晋": 3232, "晌": 3233, "晏": 3234, "晒": 3235, "晓": 3236, "晔": 3237, "晕": 3238, "晖": 3239, "晗": 3240, "晚": 3241, "晝": 3242, "晞": 3243, "晟": 3244, "晤": 3245, "晦": 3246, "晨": 3247, "晩": 3248, "普": 3249, "景": 3250, "晰": 3251, "晴": 3252, "晶": 3253, "晷": 3254, "智": 3255, "晾": 3256, "暂": 3257, "暄": 3258, "暇": 3259, "暈": 3260, "暉": 3261, "暌": 3262, "暐": 3263, "暑": 3264, "暖": 3265, "暗": 3266, "暝": 3267, "暢": 3268, "暧": 3269, "暨": 3270, "暫": 3271, "暮": 3272, "暱": 3273, "暴": 3274, "暸": 3275, "暹": 3276, "曄": 3277, "曆": 3278, "曇": 3279, "曉": 3280, "曖": 3281, "曙": 3282, "曜": 3283, "曝": 3284, "曠": 3285, "曦": 3286, "曬": 3287, "曰": 3288, "曲": 3289, "曳": 3290, "更": 3291, "書": 3292, "曹": 3293, "曼": 3294, "曾": 3295, "替": 3296, "最": 3297, "會": 3298, "月": 3299, "有": 3300, "朋": 3301, "服": 3302, "朐": 3303, "朔": 3304, "朕": 3305, "朗": 3306, "望": 3307, "朝": 3308, "期": 3309, "朦": 3310, "朧": 3311, "木": 3312, "未": 3313, "末": 3314, "本": 3315, "札": 3316, "朮": 3317, "术": 3318, "朱": 3319, "朴": 3320, "朵": 3321, "机": 3322, "朽": 3323, "杀": 3324, "杂": 3325, "权": 3326, "杆": 3327, "杈": 3328, "杉": 3329, "李": 3330, "杏": 3331, "材": 3332, "村": 3333, "杓": 3334, "杖": 3335, "杜": 3336, "杞": 3337, "束": 3338, "杠": 3339, "条": 3340, "来": 3341, "杨": 3342, "杭": 3343, "杯": 3344, "杰": 3345, "東": 3346, "杳": 3347, "杵": 3348, "杷": 3349, "杼": 3350, "松": 3351, "板": 3352, "极": 3353, "构": 3354, "枇": 3355, "枉": 3356, "枋": 3357, "析": 3358, "枕": 3359, "林": 3360, "枚": 3361, "果": 3362, "枝": 3363, "枢": 3364, "枣": 3365, "枪": 3366, "枫": 3367, "枭": 3368, "枯": 3369, "枰": 3370, "枱": 3371, "枳": 3372, "架": 3373, "枷": 3374, "枸": 3375, "柄": 3376, "柏": 3377, "某": 3378, "柑": 3379, "柒": 3380, "染": 3381, "柔": 3382, "柘": 3383, "柚": 3384, "柜": 3385, "柞": 3386, "柠": 3387, "柢": 3388, "查": 3389, "柩": 3390, "柬": 3391, "柯": 3392, "柱": 3393, "柳": 3394, "柴": 3395, "柵": 3396, "査": 3397, "柿": 3398, "栀": 3399, "栃": 3400, "栄": 3401, "栅": 3402, "标": 3403, "栈": 3404, "栉": 3405, "栋": 3406, "栎": 3407, "栏": 3408, "树": 3409, "栓": 3410, "栖": 3411, "栗": 3412, "校": 3413, "栩": 3414, "株": 3415, "样": 3416, "核": 3417, "根": 3418, "格": 3419, "栽": 3420, "栾": 3421, "桀": 3422, "桁": 3423, "桂": 3424, "桃": 3425, "桅": 3426, "框": 3427, "案": 3428, "桉": 3429, "桌": 3430, "桎": 3431, "桐": 3432, "桑": 3433, "桓": 3434, "桔": 3435, "桜": 3436, "桠": 3437, "桡": 3438, "桢": 3439, "档": 3440, "桥": 3441, "桦": 3442, "桧": 3443, "桨": 3444, "桩": 3445, "桶": 3446, "桿": 3447, "梁": 3448, "梅": 3449, "梆": 3450, "梏": 3451, "梓": 3452, "梗": 3453, "條": 3454, "梟": 3455, "梢": 3456, "梦": 3457, "梧": 3458, "梨": 3459, "梭": 3460, "梯": 3461, "械": 3462, "梳": 3463, "梵": 3464, "梶": 3465, "检": 3466, "棂": 3467, "棄": 3468, "棉": 3469, "棋": 3470, "棍": 3471, "棒": 3472, "棕": 3473, "棗": 3474, "棘": 3475, "棚": 3476, "棟": 3477, "棠": 3478, "棣": 3479, "棧": 3480, "森": 3481, "棱": 3482, "棲": 3483, "棵": 3484, "棹": 3485, "棺": 3486, "椁": 3487, "椅": 3488, "椋": 3489, "植": 3490, "椎": 3491, "椒": 3492, "検": 3493, "椪": 3494, "椭": 3495, "椰": 3496, "椹": 3497, "椽": 3498, "椿": 3499, "楂": 3500, "楊": 3501, "楓": 3502, "楔": 3503, "楚": 3504, "楝": 3505, "楞": 3506, "楠": 3507, "楣": 3508, "楨": 3509, "楫": 3510, "業": 3511, "楮": 3512, "極": 3513, "楷": 3514, "楸": 3515, "楹": 3516, "楼": 3517, "楽": 3518, "概": 3519, "榄": 3520, "榆": 3521, "榈": 3522, "榉": 3523, "榔": 3524, "榕": 3525, "榖": 3526, "榛": 3527, "榜": 3528, "榨": 3529, "榫": 3530, "榭": 3531, "榮": 3532, "榱": 3533, "榴": 3534, "榷": 3535, "榻": 3536, "槁": 3537, "槃": 3538, "構": 3539, "槌": 3540, "槍": 3541, "槎": 3542, "槐": 3543, "槓": 3544, "様": 3545, "槛": 3546, "槟": 3547, "槤": 3548, "槭": 3549, "槲": 3550, "槳": 3551, "槻": 3552, "槽": 3553, "槿": 3554, "樁": 3555, "樂": 3556, "樊": 3557, "樑": 3558, "樓": 3559, "標": 3560, "樞": 3561, "樟": 3562, "模": 3563, "樣": 3564, "権": 3565, "横": 3566, "樫": 3567, "樯": 3568, "樱": 3569, "樵": 3570, "樸": 3571, "樹": 3572, "樺": 3573, "樽": 3574, "樾": 3575, "橄": 3576, "橇": 3577, "橋": 3578, "橐": 3579, "橘": 3580, "橙": 3581, "機": 3582, "橡": 3583, "橢": 3584, "橫": 3585, "橱": 3586, "橹": 3587, "橼": 3588, "檀": 3589, "檄": 3590, "檎": 3591, "檐": 3592, "檔": 3593, "檗": 3594, "檜": 3595, "檢": 3596, "檬": 3597, "檯": 3598, "檳": 3599, "檸": 3600, "檻": 3601, "櫃": 3602, "櫚": 3603, "櫛": 3604, "櫥": 3605, "櫸": 3606, "櫻": 3607, "欄": 3608, "權": 3609, "欒": 3610, "欖": 3611, "欠": 3612, "次": 3613, "欢": 3614, "欣": 3615, "欧": 3616, "欲": 3617, "欸": 3618, "欺": 3619, "欽": 3620, "款": 3621, "歆": 3622, "歇": 3623, "歉": 3624, "歌": 3625, "歎": 3626, "歐": 3627, "歓": 3628, "歙": 3629, "歛": 3630, "歡": 3631, "止": 3632, "正": 3633, "此": 3634, "步": 3635, "武": 3636, "歧": 3637, "歩": 3638, "歪": 3639, "歯": 3640, "歲": 3641, "歳": 3642, "歴": 3643, "歷": 3644, "歸": 3645, "歹": 3646, "死": 3647, "歼": 3648, "殁": 3649, "殃": 3650, "殆": 3651, "殇": 3652, "殉": 3653, "殊": 3654, "残": 3655, "殒": 3656, "殓": 3657, "殖": 3658, "殘": 3659, "殞": 3660, "殡": 3661, "殤": 3662, "殭": 3663, "殯": 3664, "殲": 3665, "殴": 3666, "段": 3667, "殷": 3668, "殺": 3669, "殼": 3670, "殿": 3671, "毀": 3672, "毁": 3673, "毂": 3674, "毅": 3675, "毆": 3676, "毋": 3677, "母": 3678, "毎": 3679, "每": 3680, "毒": 3681, "毓": 3682, "比": 3683, "毕": 3684, "毗": 3685, "毘": 3686, "毙": 3687, "毛": 3688, "毡": 3689, "毫": 3690, "毯": 3691, "毽": 3692, "氈": 3693, "氏": 3694, "氐": 3695, "民": 3696, "氓": 3697, "气": 3698, "氖": 3699, "気": 3700, "氙": 3701, "氛": 3702, "氟": 3703, "氡": 3704, "氢": 3705, "氣": 3706, "氤": 3707, "氦": 3708, "氧": 3709, "氨": 3710, "氪": 3711, "氫": 3712, "氮": 3713, "氯": 3714, "氰": 3715, "氲": 3716, "水": 3717, "氷": 3718, "永": 3719, "氹": 3720, "氾": 3721, "汀": 3722, "汁": 3723, "求": 3724, "汆": 3725, "汇": 3726, "汉": 3727, "汎": 3728, "汐": 3729, "汕": 3730, "汗": 3731, "汙": 3732, "汛": 3733, "汝": 3734, "汞": 3735, "江": 3736, "池": 3737, "污": 3738, "汤": 3739, "汨": 3740, "汩": 3741, "汪": 3742, "汰": 3743, "汲": 3744, "汴": 3745, "汶": 3746, "汹": 3747, "決": 3748, "汽": 3749, "汾": 3750, "沁": 3751, "沂": 3752, "沃": 3753, "沅": 3754, "沈": 3755, "沉": 3756, "沌": 3757, "沏": 3758, "沐": 3759, "沒": 3760, "沓": 3761, "沖": 3762, "沙": 3763, "沛": 3764, "沟": 3765, "没": 3766, "沢": 3767, "沣": 3768, "沥": 3769, "沦": 3770, "沧": 3771, "沪": 3772, "沫": 3773, "沭": 3774, "沮": 3775, "沱": 3776, "河": 3777, "沸": 3778, "油": 3779, "治": 3780, "沼": 3781, "沽": 3782, "沾": 3783, "沿": 3784, "況": 3785, "泄": 3786, "泉": 3787, "泊": 3788, "泌": 3789, "泓": 3790, "法": 3791, "泗": 3792, "泛": 3793, "泞": 3794, "泠": 3795, "泡": 3796, "波": 3797, "泣": 3798, "泥": 3799, "注": 3800, "泪": 3801, "泫": 3802, "泮": 3803, "泯": 3804, "泰": 3805, "泱": 3806, "泳": 3807, "泵": 3808, "泷": 3809, "泸": 3810, "泻": 3811, "泼": 3812, "泽": 3813, "泾": 3814, "洁": 3815, "洄": 3816, "洋": 3817, "洒": 3818, "洗": 3819, "洙": 3820, "洛": 3821, "洞": 3822, "津": 3823, "洩": 3824, "洪": 3825, "洮": 3826, "洱": 3827, "洲": 3828, "洵": 3829, "洶": 3830, "洸": 3831, "洹": 3832, "活": 3833, "洼": 3834, "洽": 3835, "派": 3836, "流": 3837, "浃": 3838, "浄": 3839, "浅": 3840, "浆": 3841, "浇": 3842, "浊": 3843, "测": 3844, "济": 3845, "浏": 3846, "浑": 3847, "浒": 3848, "浓": 3849, "浔": 3850, "浙": 3851, "浚": 3852, "浜": 3853, "浣": 3854, "浦": 3855, "浩": 3856, "浪": 3857, "浬": 3858, "浮": 3859, "浯": 3860, "浴": 3861, "海": 3862, "浸": 3863, "涂": 3864, "涅": 3865, "涇": 3866, "消": 3867, "涉": 3868, "涌": 3869, "涎": 3870, "涓": 3871, "涔": 3872, "涕": 3873, "涙": 3874, "涛": 3875, "涝": 3876, "涞": 3877, "涟": 3878, "涠": 3879, "涡": 3880, "涣": 3881, "涤": 3882, "润": 3883, "涧": 3884, "涨": 3885, "涩": 3886, "涪": 3887, "涮": 3888, "涯": 3889, "液": 3890, "涵": 3891, "涸": 3892, "涼": 3893, "涿": 3894, "淀": 3895, "淄": 3896, "淅": 3897, "淆": 3898, "淇": 3899, "淋": 3900, "淌": 3901, "淑": 3902, "淒": 3903, "淖": 3904, "淘": 3905, "淙": 3906, "淚": 3907, "淞": 3908, "淡": 3909, "淤": 3910, "淦": 3911, "淨": 3912, "淩": 3913, "淪": 3914, "淫": 3915, "淬": 3916, "淮": 3917, "深": 3918, "淳": 3919, "淵": 3920, "混": 3921, "淹": 3922, "淺": 3923, "添": 3924, "淼": 3925, "清": 3926, "済": 3927, "渉": 3928, "渊": 3929, "渋": 3930, "渍": 3931, "渎": 3932, "渐": 3933, "渔": 3934, "渗": 3935, "渙": 3936, "渚": 3937, "減": 3938, "渝": 3939, "渠": 3940, "渡": 3941, "渣": 3942, "渤": 3943, "渥": 3944, "渦": 3945, "温": 3946, "測": 3947, "渭": 3948, "港": 3949, "渲": 3950, "渴": 3951, "游": 3952, "渺": 3953, "渾": 3954, "湃": 3955, "湄": 3956, "湊": 3957, "湍": 3958, "湖": 3959, "湘": 3960, "湛": 3961, "湟": 3962, "湧": 3963, "湫": 3964, "湮": 3965, "湯": 3966, "湳": 3967, "湾": 3968, "湿": 3969, "満": 3970, "溃": 3971, "溅": 3972, "溉": 3973, "溏": 3974, "源": 3975, "準": 3976, "溜": 3977, "溝": 3978, "溟": 3979, "溢": 3980, "溥": 3981, "溧": 3982, "溪": 3983, "溫": 3984, "溯": 3985, "溱": 3986, "溴": 3987, "溶": 3988, "溺": 3989, "溼": 3990, "滁": 3991, "滂": 3992, "滄": 3993, "滅": 3994, "滇": 3995, "滋": 3996, "滌": 3997, "滑": 3998, "滓": 3999, "滔": 4000, "滕": 4001, "滙": 4002, "滚": 4003, "滝": 4004, "滞": 4005, "滟": 4006, "满": 4007, "滢": 4008, "滤": 4009, "滥": 4010, "滦": 4011, "滨": 4012, "滩": 4013, "滬": 4014, "滯": 4015, "滲": 4016, "滴": 4017, "滷": 4018, "滸": 4019, "滾": 4020, "滿": 4021, "漁": 4022, "漂": 4023, "漆": 4024, "漉": 4025, "漏": 4026, "漓": 4027, "演": 4028, "漕": 4029, "漠": 4030, "漢": 4031, "漣": 4032, "漩": 4033, "漪": 4034, "漫": 4035, "漬": 4036, "漯": 4037, "漱": 4038, "漲": 4039, "漳": 4040, "漸": 4041, "漾": 4042, "漿": 4043, "潆": 4044, "潇": 4045, "潋": 4046, "潍": 4047, "潑": 4048, "潔": 4049, "潘": 4050, "潛": 4051, "潜": 4052, "潞": 4053, "潟": 4054, "潢": 4055, "潤": 4056, "潦": 4057, "潧": 4058, "潭": 4059, "潮": 4060, "潰": 4061, "潴": 4062, "潸": 4063, "潺": 4064, "潼": 4065, "澀": 4066, "澄": 4067, "澆": 4068, "澈": 4069, "澍": 4070, "澎": 4071, "澗": 4072, "澜": 4073, "澡": 4074, "澤": 4075, "澧": 4076, "澱": 4077, "澳": 4078, "澹": 4079, "激": 4080, "濁": 4081, "濂": 4082, "濃": 4083, "濑": 4084, "濒": 4085, "濕": 4086, "濘": 4087, "濛": 4088, "濟": 4089, "濠": 4090, "濡": 4091, "濤": 4092, "濫": 4093, "濬": 4094, "濮": 4095, "濯": 4096, "濱": 4097, "濺": 4098, "濾": 4099, "瀅": 4100, "瀆": 4101, "瀉": 4102, "瀋": 4103, "瀏": 4104, "瀑": 4105, "瀕": 4106, "瀘": 4107, "瀚": 4108, "瀛": 4109, "瀝": 4110, "瀞": 4111, "瀟": 4112, "瀧": 4113, "瀨": 4114, "瀬": 4115, "瀰": 4116, "瀾": 4117, "灌": 4118, "灏": 4119, "灑": 4120, "灘": 4121, "灝": 4122, "灞": 4123, "灣": 4124, "火": 4125, "灬": 4126, "灭": 4127, "灯": 4128, "灰": 4129, "灵": 4130, "灶": 4131, "灸": 4132, "灼": 4133, "災": 4134, "灾": 4135, "灿": 4136, "炀": 4137, "炁": 4138, "炅": 4139, "炉": 4140, "炊": 4141, "炎": 4142, "炒": 4143, "炔": 4144, "炕": 4145, "炖": 4146, "炙": 4147, "炜": 4148, "炫": 4149, "炬": 4150, "炭": 4151, "炮": 4152, "炯": 4153, "炳": 4154, "炷": 4155, "炸": 4156, "点": 4157, "為": 4158, "炼": 4159, "炽": 4160, "烁": 4161, "烂": 4162, "烃": 4163, "烈": 4164, "烊": 4165, "烏": 4166, "烘": 4167, "烙": 4168, "烛": 4169, "烟": 4170, "烤": 4171, "烦": 4172, "烧": 4173, "烨": 4174, "烩": 4175, "烫": 4176, "烬": 4177, "热": 4178, "烯": 4179, "烷": 4180, "烹": 4181, "烽": 4182, "焉": 4183, "焊": 4184, "焕": 4185, "焖": 4186, "焗": 4187, "焘": 4188, "焙": 4189, "焚": 4190, "焜": 4191, "無": 4192, "焦": 4193, "焯": 4194, "焰": 4195, "焱": 4196, "然": 4197, "焼": 4198, "煅": 4199, "煉": 4200, "煊": 4201, "煌": 4202, "煎": 4203, "煒": 4204, "煖": 4205, "煙": 4206, "煜": 4207, "煞": 4208, "煤": 4209, "煥": 4210, "煦": 4211, "照": 4212, "煨": 4213, "煩": 4214, "煮": 4215, "煲": 4216, "煸": 4217, "煽": 4218, "熄": 4219, "熊": 4220, "熏": 4221, "熒": 4222, "熔": 4223, "熙": 4224, "熟": 4225, "熠": 4226, "熨": 4227, "熬": 4228, "熱": 4229, "熵": 4230, "熹": 4231, "熾": 4232, "燁": 4233, "燃": 4234, "燄": 4235, "燈": 4236, "燉": 4237, "燊": 4238, "燎": 4239, "燒": 4240, "燔": 4241, "燕": 4242, "燙": 4243, "燜": 4244, "營": 4245, "燥": 4246, "燦": 4247, "燧": 4248, "燭": 4249, "燮": 4250, "燴": 4251, "燻": 4252, "燼": 4253, "燿": 4254, "爆": 4255, "爍": 4256, "爐": 4257, "爛": 4258, "爪": 4259, "爬": 4260, "爭": 4261, "爰": 4262, "爱": 4263, "爲": 4264, "爵": 4265, "父": 4266, "爷": 4267, "爸": 4268, "爹": 4269, "爺": 4270, "爻": 4271, "爽": 4272, "爾": 4273, "牆": 4274, "片": 4275, "版": 4276, "牌": 4277, "牍": 4278, "牒": 4279, "牙": 4280, "牛": 4281, "牝": 4282, "牟": 4283, "牠": 4284, "牡": 4285, "牢": 4286, "牦": 4287, "牧": 4288, "物": 4289, "牯": 4290, "牲": 4291, "牴": 4292, "牵": 4293, "特": 4294, "牺": 4295, "牽": 4296, "犀": 4297, "犁": 4298, "犄": 4299, "犊": 4300, "犍": 4301, "犒": 4302, "犢": 4303, "犧": 4304, "犬": 4305, "犯": 4306, "状": 4307, "犷": 4308, "犸": 4309, "犹": 4310, "狀": 4311, "狂": 4312, "狄": 4313, "狈": 4314, "狎": 4315, "狐": 4316, "狒": 4317, "狗": 4318, "狙": 4319, "狞": 4320, "狠": 4321, "狡": 4322, "狩": 4323, "独": 4324, "狭": 4325, "狮": 4326, "狰": 4327, "狱": 4328, "狸": 4329, "狹": 4330, "狼": 4331, "狽": 4332, "猎": 4333, "猕": 4334, "猖": 4335, "猗": 4336, "猙": 4337, "猛": 4338, "猜": 4339, "猝": 4340, "猥": 4341, "猩": 4342, "猪": 4343, "猫": 4344, "猬": 4345, "献": 4346, "猴": 4347, "猶": 4348, "猷": 4349, "猾": 4350, "猿": 4351, "獄": 4352, "獅": 4353, "獎": 4354, "獐": 4355, "獒": 4356, "獗": 4357, "獠": 4358, "獣": 4359, "獨": 4360, "獭": 4361, "獰": 4362, "獲": 4363, "獵": 4364, "獷": 4365, "獸": 4366, "獺": 4367, "獻": 4368, "獼": 4369, "獾": 4370, "玄": 4371, "率": 4372, "玉": 4373, "王": 4374, "玑": 4375, "玖": 4376, "玛": 4377, "玟": 4378, "玠": 4379, "玥": 4380, "玩": 4381, "玫": 4382, "玮": 4383, "环": 4384, "现": 4385, "玲": 4386, "玳": 4387, "玷": 4388, "玺": 4389, "玻": 4390, "珀": 4391, "珂": 4392, "珅": 4393, "珈": 4394, "珉": 4395, "珊": 4396, "珍": 4397, "珏": 4398, "珐": 4399, "珑": 4400, "珙": 4401, "珞": 4402, "珠": 4403, "珣": 4404, "珥": 4405, "珩": 4406, "珪": 4407, "班": 4408, "珮": 4409, "珲": 4410, "珺": 4411, "現": 4412, "球": 4413, "琅": 4414, "理": 4415, "琇": 4416, "琉": 4417, "琊": 4418, "琍": 4419, "琏": 4420, "琐": 4421, "琛": 4422, "琢": 4423, "琥": 4424, "琦": 4425, "琨": 4426, "琪": 4427, "琬": 4428, "琮": 4429, "琰": 4430, "琲": 4431, "琳": 4432, "琴": 4433, "琵": 4434, "琶": 4435, "琺": 4436, "琼": 4437, "瑀": 4438, "瑁": 4439, "瑄": 4440, "瑋": 4441, "瑕": 4442, "瑗": 4443, "瑙": 4444, "瑚": 4445, "瑛": 4446, "瑜": 4447, "瑞": 4448, "瑟": 4449, "瑠": 4450, "瑣": 4451, "瑤": 4452, "瑩": 4453, "瑪": 4454, "瑯": 4455, "瑰": 4456, "瑶": 4457, "瑾": 4458, "璀": 4459, "璁": 4460, "璃": 4461, "璇": 4462, "璉": 4463, "璋": 4464, "璎": 4465, "璐": 4466, "璜": 4467, "璞": 4468, "璟": 4469, "璧": 4470, "璨": 4471, "環": 4472, "璽": 4473, "璿": 4474, "瓊": 4475, "瓏": 4476, "瓒": 4477, "瓜": 4478, "瓢": 4479, "瓣": 4480, "瓤": 4481, "瓦": 4482, "瓮": 4483, "瓯": 4484, "瓴": 4485, "瓶": 4486, "瓷": 4487, "甄": 4488, "甌": 4489, "甕": 4490, "甘": 4491, "甙": 4492, "甚": 4493, "甜": 4494, "生": 4495, "產": 4496, "産": 4497, "甥": 4498, "甦": 4499, "用": 4500, "甩": 4501, "甫": 4502, "甬": 4503, "甭": 4504, "甯": 4505, "田": 4506, "由": 4507, "甲": 4508, "申": 4509, "电": 4510, "男": 4511, "甸": 4512, "町": 4513, "画": 4514, "甾": 4515, "畀": 4516, "畅": 4517, "界": 4518, "畏": 4519, "畑": 4520, "畔": 4521, "留": 4522, "畜": 4523, "畝": 4524, "畢": 4525, "略": 4526, "畦": 4527, "番": 4528, "畫": 4529, "異": 4530, "畲": 4531, "畳": 4532, "畴": 4533, "當": 4534, "畸": 4535, "畹": 4536, "畿": 4537, "疆": 4538, "疇": 4539, "疊": 4540, "疏": 4541, "疑": 4542, "疔": 4543, "疖": 4544, "疗": 4545, "疙": 4546, "疚": 4547, "疝": 4548, "疟": 4549, "疡": 4550, "疣": 4551, "疤": 4552, "疥": 4553, "疫": 4554, "疮": 4555, "疯": 4556, "疱": 4557, "疲": 4558, "疳": 4559, "疵": 4560, "疸": 4561, "疹": 4562, "疼": 4563, "疽": 4564, "疾": 4565, "痂": 4566, "病": 4567, "症": 4568, "痈": 4569, "痉": 4570, "痊": 4571, "痍": 4572, "痒": 4573, "痔": 4574, "痕": 4575, "痘": 4576, "痙": 4577, "痛": 4578, "痞": 4579, "痠": 4580, "痢": 4581, "痣": 4582, "痤": 4583, "痧": 4584, "痨": 4585, "痪": 4586, "痫": 4587, "痰": 4588, "痱": 4589, "痴": 4590, "痹": 4591, "痺": 4592, "痼": 4593, "痿": 4594, "瘀": 4595, "瘁": 4596, "瘋": 4597, "瘍": 4598, "瘓": 4599, "瘘": 4600, "瘙": 4601, "瘟": 4602, "瘠": 4603, "瘡": 4604, "瘢": 4605, "瘤": 4606, "瘦": 4607, "瘧": 4608, "瘩": 4609, "瘪": 4610, "瘫": 4611, "瘴": 4612, "瘸": 4613, "瘾": 4614, "療": 4615, "癇": 4616, "癌": 4617, "癒": 4618, "癖": 4619, "癜": 4620, "癞": 4621, "癡": 4622, "癢": 4623, "癣": 4624, "癥": 4625, "癫": 4626, "癬": 4627, "癮": 4628, "癱": 4629, "癲": 4630, "癸": 4631, "発": 4632, "登": 4633, "發": 4634, "白": 4635, "百": 4636, "皂": 4637, "的": 4638, "皆": 4639, "皇": 4640, "皈": 4641, "皋": 4642, "皎": 4643, "皑": 4644, "皓": 4645, "皖": 4646, "皙": 4647, "皚": 4648, "皮": 4649, "皰": 4650, "皱": 4651, "皴": 4652, "皺": 4653, "皿": 4654, "盂": 4655, "盃": 4656, "盅": 4657, "盆": 4658, "盈": 4659, "益": 4660, "盎": 4661, "盏": 4662, "盐": 4663, "监": 4664, "盒": 4665, "盔": 4666, "盖": 4667, "盗": 4668, "盘": 4669, "盛": 4670, "盜": 4671, "盞": 4672, "盟": 4673, "盡": 4674, "監": 4675, "盤": 4676, "盥": 4677, "盧": 4678, "盪": 4679, "目": 4680, "盯": 4681, "盱": 4682, "盲": 4683, "直": 4684, "相": 4685, "盹": 4686, "盼": 4687, "盾": 4688, "省": 4689, "眈": 4690, "眉": 4691, "看": 4692, "県": 4693, "眙": 4694, "眞": 4695, "真": 4696, "眠": 4697, "眦": 4698, "眨": 4699, "眩": 4700, "眯": 4701, "眶": 4702, "眷": 4703, "眸": 4704, "眺": 4705, "眼": 4706, "眾": 4707, "着": 4708, "睁": 4709, "睇": 4710, "睏": 4711, "睐": 4712, "睑": 4713, "睛": 4714, "睜": 4715, "睞": 4716, "睡": 4717, "睢": 4718, "督": 4719, "睥": 4720, "睦": 4721, "睨": 4722, "睪": 4723, "睫": 4724, "睬": 4725, "睹": 4726, "睽": 4727, "睾": 4728, "睿": 4729, "瞄": 4730, "瞅": 4731, "瞇": 4732, "瞋": 4733, "瞌": 4734, "瞎": 4735, "瞑": 4736, "瞒": 4737, "瞓": 4738, "瞞": 4739, "瞟": 4740, "瞠": 4741, "瞥": 4742, "瞧": 4743, "瞩": 4744, "瞪": 4745, "瞬": 4746, "瞭": 4747, "瞰": 4748, "瞳": 4749, "瞻": 4750, "瞼": 4751, "瞿": 4752, "矇": 4753, "矍": 4754, "矗": 4755, "矚": 4756, "矛": 4757, "矜": 4758, "矢": 4759, "矣": 4760, "知": 4761, "矩": 4762, "矫": 4763, "短": 4764, "矮": 4765, "矯": 4766, "石": 4767, "矶": 4768, "矽": 4769, "矾": 4770, "矿": 4771, "码": 4772, "砂": 4773, "砌": 4774, "砍": 4775, "砒": 4776, "研": 4777, "砖": 4778, "砗": 4779, "砚": 4780, "砝": 4781, "砣": 4782, "砥": 4783, "砧": 4784, "砭": 4785, "砰": 4786, "砲": 4787, "破": 4788, "砷": 4789, "砸": 4790, "砺": 4791, "砼": 4792, "砾": 4793, "础": 4794, "硅": 4795, "硐": 4796, "硒": 4797, "硕": 4798, "硝": 4799, "硫": 4800, "硬": 4801, "确": 4802, "硯": 4803, "硼": 4804, "碁": 4805, "碇": 4806, "碉": 4807, "碌": 4808, "碍": 4809, "碎": 4810, "碑": 4811, "碓": 4812, "碗": 4813, "碘": 4814, "碚": 4815, "碛": 4816, "碟": 4817, "碣": 4818, "碧": 4819, "碩": 4820, "碰": 4821, "碱": 4822, "碳": 4823, "碴": 4824, "確": 4825, "碼": 4826, "碾": 4827, "磁": 4828, "磅": 4829, "磊": 4830, "磋": 4831, "磐": 4832, "磕": 4833, "磚": 4834, "磡": 4835, "磨": 4836, "磬": 4837, "磯": 4838, "磲": 4839, "磷": 4840, "磺": 4841, "礁": 4842, "礎": 4843, "礙": 4844, "礡": 4845, "礦": 4846, "礪": 4847, "礫": 4848, "礴": 4849, "示": 4850, "礼": 4851, "社": 4852, "祀": 4853, "祁": 4854, "祂": 4855, "祇": 4856, "祈": 4857, "祉": 4858, "祎": 4859, "祐": 4860, "祕": 4861, "祖": 4862, "祗": 4863, "祚": 4864, "祛": 4865, "祜": 4866, "祝": 4867, "神": 4868, "祟": 4869, "祠": 4870, "祢": 4871, "祥": 4872, "票": 4873, "祭": 4874, "祯": 4875, "祷": 4876, "祸": 4877, "祺": 4878, "祿": 4879, "禀": 4880, "禁": 4881, "禄": 4882, "禅": 4883, "禍": 4884, "禎": 4885, "福": 4886, "禛": 4887, "禦": 4888, "禧": 4889, "禪": 4890, "禮": 4891, "禱": 4892, "禹": 4893, "禺": 4894, "离": 4895, "禽": 4896, "禾": 4897, "禿": 4898, "秀": 4899, "私": 4900, "秃": 4901, "秆": 4902, "秉": 4903, "秋": 4904, "种": 4905, "科": 4906, "秒": 4907, "秘": 4908, "租": 4909, "秣": 4910, "秤": 4911, "秦": 4912, "秧": 4913, "秩": 4914, "秭": 4915, "积": 4916, "称": 4917, "秸": 4918, "移": 4919, "秽": 4920, "稀": 4921, "稅": 4922, "程": 4923, "稍": 4924, "税": 4925, "稔": 4926, "稗": 4927, "稚": 4928, "稜": 4929, "稞": 4930, "稟": 4931, "稠": 4932, "稣": 4933, "種": 4934, "稱": 4935, "稲": 4936, "稳": 4937, "稷": 4938, "稹": 4939, "稻": 4940, "稼": 4941, "稽": 4942, "稿": 4943, "穀": 4944, "穂": 4945, "穆": 4946, "穌": 4947, "積": 4948, "穎": 4949, "穗": 4950, "穢": 4951, "穩": 4952, "穫": 4953, "穴": 4954, "究": 4955, "穷": 4956, "穹": 4957, "空": 4958, "穿": 4959, "突": 4960, "窃": 4961, "窄": 4962, "窈": 4963, "窍": 4964, "窑": 4965, "窒": 4966, "窓": 4967, "窕": 4968, "窖": 4969, "窗": 4970, "窘": 4971, "窜": 4972, "窝": 4973, "窟": 4974, "窠": 4975, "窥": 4976, "窦": 4977, "窨": 4978, "窩": 4979, "窪": 4980, "窮": 4981, "窯": 4982, "窺": 4983, "窿": 4984, "竄": 4985, "竅": 4986, "竇": 4987, "竊": 4988, "立": 4989, "竖": 4990, "站": 4991, "竜": 4992, "竞": 4993, "竟": 4994, "章": 4995, "竣": 4996, "童": 4997, "竭": 4998, "端": 4999, "競": 5000, "竹": 5001, "竺": 5002, "竽": 5003, "竿": 5004, "笃": 5005, "笆": 5006, "笈": 5007, "笋": 5008, "笏": 5009, "笑": 5010, "笔": 5011, "笙": 5012, "笛": 5013, "笞": 5014, "笠": 5015, "符": 5016, "笨": 5017, "第": 5018, "笹": 5019, "笺": 5020, "笼": 5021, "筆": 5022, "等": 5023, "筊": 5024, "筋": 5025, "筍": 5026, "筏": 5027, "筐": 5028, "筑": 5029, "筒": 5030, "答": 5031, "策": 5032, "筛": 5033, "筝": 5034, "筠": 5035, "筱": 5036, "筲": 5037, "筵": 5038, "筷": 5039, "筹": 5040, "签": 5041, "简": 5042, "箇": 5043, "箋": 5044, "箍": 5045, "箏": 5046, "箐": 5047, "箔": 5048, "箕": 5049, "算": 5050, "箝": 5051, "管": 5052, "箩": 5053, "箫": 5054, "箭": 5055, "箱": 5056, "箴": 5057, "箸": 5058, "節": 5059, "篁": 5060, "範": 5061, "篆": 5062, "篇": 5063, "築": 5064, "篑": 5065, "篓": 5066, "篙": 5067, "篝": 5068, "篠": 5069, "篡": 5070, "篤": 5071, "篩": 5072, "篪": 5073, "篮": 5074, "篱": 5075, "篷": 5076, "簇": 5077, "簌": 5078, "簍": 5079, "簡": 5080, "簦": 5081, "簧": 5082, "簪": 5083, "簫": 5084, "簷": 5085, "簸": 5086, "簽": 5087, "簾": 5088, "簿": 5089, "籁": 5090, "籃": 5091, "籌": 5092, "籍": 5093, "籐": 5094, "籟": 5095, "籠": 5096, "籤": 5097, "籬": 5098, "籮": 5099, "籲": 5100, "米": 5101, "类": 5102, "籼": 5103, "籽": 5104, "粄": 5105, "粉": 5106, "粑": 5107, "粒": 5108, "粕": 5109, "粗": 5110, "粘": 5111, "粟": 5112, "粤": 5113, "粥": 5114, "粧": 5115, "粪": 5116, "粮": 5117, "粱": 5118, "粲": 5119, "粳": 5120, "粵": 5121, "粹": 5122, "粼": 5123, "粽": 5124, "精": 5125, "粿": 5126, "糅": 5127, "糊": 5128, "糍": 5129, "糕": 5130, "糖": 5131, "糗": 5132, "糙": 5133, "糜": 5134, "糞": 5135, "糟": 5136, "糠": 5137, "糧": 5138, "糬": 5139, "糯": 5140, "糰": 5141, "糸": 5142, "系": 5143, "糾": 5144, "紀": 5145, "紂": 5146, "約": 5147, "紅": 5148, "紉": 5149, "紊": 5150, "紋": 5151, "納": 5152, "紐": 5153, "紓": 5154, "純": 5155, "紗": 5156, "紘": 5157, "紙": 5158, "級": 5159, "紛": 5160, "紜": 5161, "素": 5162, "紡": 5163, "索": 5164, "紧": 5165, "紫": 5166, "紮": 5167, "累": 5168, "細": 5169, "紳": 5170, "紹": 5171, "紺": 5172, "終": 5173, "絃": 5174, "組": 5175, "絆": 5176, "経": 5177, "結": 5178, "絕": 5179, "絞": 5180, "絡": 5181, "絢": 5182, "給": 5183, "絨": 5184, "絮": 5185, "統": 5186, "絲": 5187, "絳": 5188, "絵": 5189, "絶": 5190, "絹": 5191, "綁": 5192, "綏": 5193, "綑": 5194, "經": 5195, "継": 5196, "続": 5197, "綜": 5198, "綠": 5199, "綢": 5200, "綦": 5201, "綫": 5202, "綬": 5203, "維": 5204, "綱": 5205, "網": 5206, "綴": 5207, "綵": 5208, "綸": 5209, "綺": 5210, "綻": 5211, "綽": 5212, "綾": 5213, "綿": 5214, "緊": 5215, "緋": 5216, "総": 5217, "緑": 5218, "緒": 5219, "緘": 5220, "線": 5221, "緝": 5222, "緞": 5223, "締": 5224, "緣": 5225, "編": 5226, "緩": 5227, "緬": 5228, "緯": 5229, "練": 5230, "緹": 5231, "緻": 5232, "縁": 5233, "縄": 5234, "縈": 5235, "縛": 5236, "縝": 5237, "縣": 5238, "縫": 5239, "縮": 5240, "縱": 5241, "縴": 5242, "縷": 5243, "總": 5244, "績": 5245, "繁": 5246, "繃": 5247, "繆": 5248, "繇": 5249, "繋": 5250, "織": 5251, "繕": 5252, "繚": 5253, "繞": 5254, "繡": 5255, "繩": 5256, "繪": 5257, "繫": 5258, "繭": 5259, "繳": 5260, "繹": 5261, "繼": 5262, "繽": 5263, "纂": 5264, "續": 5265, "纍": 5266, "纏": 5267, "纓": 5268, "纔": 5269, "纖": 5270, "纜": 5271, "纠": 5272, "红": 5273, "纣": 5274, "纤": 5275, "约": 5276, "级": 5277, "纨": 5278, "纪": 5279, "纫": 5280, "纬": 5281, "纭": 5282, "纯": 5283, "纰": 5284, "纱": 5285, "纲": 5286, "纳": 5287, "纵": 5288, "纶": 5289, "纷": 5290, "纸": 5291, "纹": 5292, "纺": 5293, "纽": 5294, "纾": 5295, "线": 5296, "绀": 5297, "练": 5298, "组": 5299, "绅": 5300, "细": 5301, "织": 5302, "终": 5303, "绊": 5304, "绍": 5305, "绎": 5306, "经": 5307, "绑": 5308, "绒": 5309, "结": 5310, "绔": 5311, "绕": 5312, "绘": 5313, "给": 5314, "绚": 5315, "绛": 5316, "络": 5317, "绝": 5318, "绞": 5319, "统": 5320, "绡": 5321, "绢": 5322, "绣": 5323, "绥": 5324, "绦": 5325, "继": 5326, "绩": 5327, "绪": 5328, "绫": 5329, "续": 5330, "绮": 5331, "绯": 5332, "绰": 5333, "绳": 5334, "维": 5335, "绵": 5336, "绶": 5337, "绷": 5338, "绸": 5339, "绻": 5340, "综": 5341, "绽": 5342, "绾": 5343, "绿": 5344, "缀": 5345, "缄": 5346, "缅": 5347, "缆": 5348, "缇": 5349, "缈": 5350, "缉": 5351, "缎": 5352, "缓": 5353, "缔": 5354, "缕": 5355, "编": 5356, "缘": 5357, "缙": 5358, "缚": 5359, "缜": 5360, "缝": 5361, "缠": 5362, "缢": 5363, "缤": 5364, "缥": 5365, "缨": 5366, "缩": 5367, "缪": 5368, "缭": 5369, "缮": 5370, "缰": 5371, "缱": 5372, "缴": 5373, "缸": 5374, "缺": 5375, "缽": 5376, "罂": 5377, "罄": 5378, "罌": 5379, "罐": 5380, "网": 5381, "罔": 5382, "罕": 5383, "罗": 5384, "罚": 5385, "罡": 5386, "罢": 5387, "罩": 5388, "罪": 5389, "置": 5390, "罰": 5391, "署": 5392, "罵": 5393, "罷": 5394, "罹": 5395, "羁": 5396, "羅": 5397, "羈": 5398, "羊": 5399, "羌": 5400, "美": 5401, "羔": 5402, "羚": 5403, "羞": 5404, "羟": 5405, "羡": 5406, "羣": 5407, "群": 5408, "羥": 5409, "羧": 5410, "羨": 5411, "義": 5412, "羯": 5413, "羲": 5414, "羸": 5415, "羹": 5416, "羽": 5417, "羿": 5418, "翁": 5419, "翅": 5420, "翊": 5421, "翌": 5422, "翎": 5423, "習": 5424, "翔": 5425, "翘": 5426, "翟": 5427, "翠": 5428, "翡": 5429, "翦": 5430, "翩": 5431, "翰": 5432, "翱": 5433, "翳": 5434, "翹": 5435, "翻": 5436, "翼": 5437, "耀": 5438, "老": 5439, "考": 5440, "耄": 5441, "者": 5442, "耆": 5443, "耋": 5444, "而": 5445, "耍": 5446, "耐": 5447, "耒": 5448, "耕": 5449, "耗": 5450, "耘": 5451, "耙": 5452, "耦": 5453, "耨": 5454, "耳": 5455, "耶": 5456, "耷": 5457, "耸": 5458, "耻": 5459, "耽": 5460, "耿": 5461, "聂": 5462, "聆": 5463, "聊": 5464, "聋": 5465, "职": 5466, "聒": 5467, "联": 5468, "聖": 5469, "聘": 5470, "聚": 5471, "聞": 5472, "聪": 5473, "聯": 5474, "聰": 5475, "聲": 5476, "聳": 5477, "聴": 5478, "聶": 5479, "職": 5480, "聽": 5481, "聾": 5482, "聿": 5483, "肃": 5484, "肄": 5485, "肅": 5486, "肆": 5487, "肇": 5488, "肉": 5489, "肋": 5490, "肌": 5491, "肏": 5492, "肓": 5493, "肖": 5494, "肘": 5495, "肚": 5496, "肛": 5497, "肝": 5498, "肠": 5499, "股": 5500, "肢": 5501, "肤": 5502, "肥": 5503, "肩": 5504, "肪": 5505, "肮": 5506, "肯": 5507, "肱": 5508, "育": 5509, "肴": 5510, "肺": 5511, "肽": 5512, "肾": 5513, "肿": 5514, "胀": 5515, "胁": 5516, "胃": 5517, "胄": 5518, "胆": 5519, "背": 5520, "胍": 5521, "胎": 5522, "胖": 5523, "胚": 5524, "胛": 5525, "胜": 5526, "胝": 5527, "胞": 5528, "胡": 5529, "胤": 5530, "胥": 5531, "胧": 5532, "胫": 5533, "胭": 5534, "胯": 5535, "胰": 5536, "胱": 5537, "胳": 5538, "胴": 5539, "胶": 5540, "胸": 5541, "胺": 5542, "能": 5543, "脂": 5544, "脅": 5545, "脆": 5546, "脇": 5547, "脈": 5548, "脉": 5549, "脊": 5550, "脍": 5551, "脏": 5552, "脐": 5553, "脑": 5554, "脓": 5555, "脖": 5556, "脘": 5557, "脚": 5558, "脛": 5559, "脣": 5560, "脩": 5561, "脫": 5562, "脯": 5563, "脱": 5564, "脲": 5565, "脳": 5566, "脸": 5567, "脹": 5568, "脾": 5569, "腆": 5570, "腈": 5571, "腊": 5572, "腋": 5573, "腌": 5574, "腎": 5575, "腐": 5576, "腑": 5577, "腓": 5578, "腔": 5579, "腕": 5580, "腥": 5581, "腦": 5582, "腩": 5583, "腫": 5584, "腭": 5585, "腮": 5586, "腰": 5587, "腱": 5588, "腳": 5589, "腴": 5590, "腸": 5591, "腹": 5592, "腺": 5593, "腻": 5594, "腼": 5595, "腾": 5596, "腿": 5597, "膀": 5598, "膈": 5599, "膊": 5600, "膏": 5601, "膑": 5602, "膘": 5603, "膚": 5604, "膛": 5605, "膜": 5606, "膝": 5607, "膠": 5608, "膦": 5609, "膨": 5610, "膩": 5611, "膳": 5612, "膺": 5613, "膻": 5614, "膽": 5615, "膾": 5616, "膿": 5617, "臀": 5618, "臂": 5619, "臃": 5620, "臆": 5621, "臉": 5622, "臊": 5623, "臍": 5624, "臓": 5625, "臘": 5626, "臟": 5627, "臣": 5628, "臥": 5629, "臧": 5630, "臨": 5631, "自": 5632, "臬": 5633, "臭": 5634, "至": 5635, "致": 5636, "臺": 5637, "臻": 5638, "臼": 5639, "臾": 5640, "舀": 5641, "舂": 5642, "舅": 5643, "舆": 5644, "與": 5645, "興": 5646, "舉": 5647, "舊": 5648, "舌": 5649, "舍": 5650, "舎": 5651, "舐": 5652, "舒": 5653, "舔": 5654, "舖": 5655, "舗": 5656, "舛": 5657, "舜": 5658, "舞": 5659, "舟": 5660, "航": 5661, "舫": 5662, "般": 5663, "舰": 5664, "舱": 5665, "舵": 5666, "舶": 5667, "舷": 5668, "舸": 5669, "船": 5670, "舺": 5671, "舾": 5672, "艇": 5673, "艋": 5674, "艘": 5675, "艙": 5676, "艦": 5677, "艮": 5678, "良": 5679, "艰": 5680, "艱": 5681, "色": 5682, "艳": 5683, "艷": 5684, "艹": 5685, "艺": 5686, "艾": 5687, "节": 5688, "芃": 5689, "芈": 5690, "芊": 5691, "芋": 5692, "芍": 5693, "芎": 5694, "芒": 5695, "芙": 5696, "芜": 5697, "芝": 5698, "芡": 5699, "芥": 5700, "芦": 5701, "芩": 5702, "芪": 5703, "芫": 5704, "芬": 5705, "芭": 5706, "芮": 5707, "芯": 5708, "花": 5709, "芳": 5710, "芷": 5711, "芸": 5712, "芹": 5713, "芻": 5714, "芽": 5715, "芾": 5716, "苁": 5717, "苄": 5718, "苇": 5719, "苋": 5720, "苍": 5721, "苏": 5722, "苑": 5723, "苒": 5724, "苓": 5725, "苔": 5726, "苕": 5727, "苗": 5728, "苛": 5729, "苜": 5730, "苞": 5731, "苟": 5732, "苡": 5733, "苣": 5734, "若": 5735, "苦": 5736, "苫": 5737, "苯": 5738, "英": 5739, "苷": 5740, "苹": 5741, "苻": 5742, "茁": 5743, "茂": 5744, "范": 5745, "茄": 5746, "茅": 5747, "茉": 5748, "茎": 5749, "茏": 5750, "茗": 5751, "茜": 5752, "茧": 5753, "茨": 5754, "茫": 5755, "茬": 5756, "茭": 5757, "茯": 5758, "茱": 5759, "茲": 5760, "茴": 5761, "茵": 5762, "茶": 5763, "茸": 5764, "茹": 5765, "茼": 5766, "荀": 5767, "荃": 5768, "荆": 5769, "草": 5770, "荊": 5771, "荏": 5772, "荐": 5773, "荒": 5774, "荔": 5775, "荖": 5776, "荘": 5777, "荚": 5778, "荞": 5779, "荟": 5780, "荠": 5781, "荡": 5782, "荣": 5783, "荤": 5784, "荥": 5785, "荧": 5786, "荨": 5787, "荪": 5788, "荫": 5789, "药": 5790, "荳": 5791, "荷": 5792, "荸": 5793, "荻": 5794, "荼": 5795, "荽": 5796, "莅": 5797, "莆": 5798, "莉": 5799, "莊": 5800, "莎": 5801, "莒": 5802, "莓": 5803, "莖": 5804, "莘": 5805, "莞": 5806, "莠": 5807, "莢": 5808, "莧": 5809, "莪": 5810, "莫": 5811, "莱": 5812, "莲": 5813, "莴": 5814, "获": 5815, "莹": 5816, "莺": 5817, "莽": 5818, "莿": 5819, "菀": 5820, "菁": 5821, "菅": 5822, "菇": 5823, "菈": 5824, "菊": 5825, "菌": 5826, "菏": 5827, "菓": 5828, "菖": 5829, "菘": 5830, "菜": 5831, "菟": 5832, "菠": 5833, "菡": 5834, "菩": 5835, "華": 5836, "菱": 5837, "菲": 5838, "菸": 5839, "菽": 5840, "萁": 5841, "萃": 5842, "萄": 5843, "萊": 5844, "萋": 5845, "萌": 5846, "萍": 5847, "萎": 5848, "萘": 5849, "萝": 5850, "萤": 5851, "营": 5852, "萦": 5853, "萧": 5854, "萨": 5855, "萩": 5856, "萬": 5857, "萱": 5858, "萵": 5859, "萸": 5860, "萼": 5861, "落": 5862, "葆": 5863, "葉": 5864, "著": 5865, "葚": 5866, "葛": 5867, "葡": 5868, "董": 5869, "葦": 5870, "葩": 5871, "葫": 5872, "葬": 5873, "葭": 5874, "葯": 5875, "葱": 5876, "葳": 5877, "葵": 5878, "葷": 5879, "葺": 5880, "蒂": 5881, "蒋": 5882, "蒐": 5883, "蒔": 5884, "蒙": 5885, "蒜": 5886, "蒞": 5887, "蒟": 5888, "蒡": 5889, "蒨": 5890, "蒲": 5891, "蒸": 5892, "蒹": 5893, "蒻": 5894, "蒼": 5895, "蒿": 5896, "蓁": 5897, "蓄": 5898, "蓆": 5899, "蓉": 5900, "蓋": 5901, "蓑": 5902, "蓓": 5903, "蓖": 5904, "蓝": 5905, "蓟": 5906, "蓦": 5907, "蓬": 5908, "蓮": 5909, "蓼": 5910, "蓿": 5911, "蔑": 5912, "蔓": 5913, "蔔": 5914, "蔗": 5915, "蔘": 5916, "蔚": 5917, "蔡": 5918, "蔣": 5919, "蔥": 5920, "蔫": 5921, "蔬": 5922, "蔭": 5923, "蔵": 5924, "蔷": 5925, "蔺": 5926, "蔻": 5927, "蔼": 5928, "蔽": 5929, "蕁": 5930, "蕃": 5931, "蕈": 5932, "蕉": 5933, "蕊": 5934, "蕎": 5935, "蕙": 5936, "蕤": 5937, "蕨": 5938, "蕩": 5939, "蕪": 5940, "蕭": 5941, "蕲": 5942, "蕴": 5943, "蕻": 5944, "蕾": 5945, "薄": 5946, "薅": 5947, "薇": 5948, "薈": 5949, "薊": 5950, "薏": 5951, "薑": 5952, "薔": 5953, "薙": 5954, "薛": 5955, "薦": 5956, "薨": 5957, "薩": 5958, "薪": 5959, "薬": 5960, "薯": 5961, "薰": 5962, "薹": 5963, "藉": 5964, "藍": 5965, "藏": 5966, "藐": 5967, "藓": 5968, "藕": 5969, "藜": 5970, "藝": 5971, "藤": 5972, "藥": 5973, "藩": 5974, "藹": 5975, "藻": 5976, "藿": 5977, "蘆": 5978, "蘇": 5979, "蘊": 5980, "蘋": 5981, "蘑": 5982, "蘚": 5983, "蘭": 5984, "蘸": 5985, "蘼": 5986, "蘿": 5987, "虎": 5988, "虏": 5989, "虐": 5990, "虑": 5991, "虔": 5992, "處": 5993, "虚": 5994, "虛": 5995, "虜": 5996, "虞": 5997, "號": 5998, "虢": 5999, "虧": 6000, "虫": 6001, "虬": 6002, "虱": 6003, "虹": 6004, "虻": 6005, "虽": 6006, "虾": 6007, "蚀": 6008, "蚁": 6009, "蚂": 6010, "蚊": 6011, "蚌": 6012, "蚓": 6013, "蚕": 6014, "蚜": 6015, "蚝": 6016, "蚣": 6017, "蚤": 6018, "蚩": 6019, "蚪": 6020, "蚯": 6021, "蚱": 6022, "蚵": 6023, "蛀": 6024, "蛆": 6025, "蛇": 6026, "蛊": 6027, "蛋": 6028, "蛎": 6029, "蛐": 6030, "蛔": 6031, "蛙": 6032, "蛛": 6033, "蛟": 6034, "蛤": 6035, "蛭": 6036, "蛮": 6037, "蛰": 6038, "蛳": 6039, "蛹": 6040, "蛻": 6041, "蛾": 6042, "蜀": 6043, "蜂": 6044, "蜃": 6045, "蜆": 6046, "蜇": 6047, "蜈": 6048, "蜊": 6049, "蜍": 6050, "蜒": 6051, "蜓": 6052, "蜕": 6053, "蜗": 6054, "蜘": 6055, "蜚": 6056, "蜜": 6057, "蜡": 6058, "蜢": 6059, "蜥": 6060, "蜱": 6061, "蜴": 6062, "蜷": 6063, "蜻": 6064, "蜿": 6065, "蝇": 6066, "蝈": 6067, "蝉": 6068, "蝌": 6069, "蝎": 6070, "蝕": 6071, "蝗": 6072, "蝙": 6073, "蝟": 6074, "蝠": 6075, "蝦": 6076, "蝨": 6077, "蝴": 6078, "蝶": 6079, "蝸": 6080, "蝼": 6081, "螂": 6082, "螃": 6083, "融": 6084, "螞": 6085, "螢": 6086, "螨": 6087, "螯": 6088, "螳": 6089, "螺": 6090, "蟀": 6091, "蟄": 6092, "蟆": 6093, "蟋": 6094, "蟎": 6095, "蟑": 6096, "蟒": 6097, "蟠": 6098, "蟬": 6099, "蟲": 6100, "蟹": 6101, "蟻": 6102, "蟾": 6103, "蠅": 6104, "蠍": 6105, "蠔": 6106, "蠕": 6107, "蠛": 6108, "蠟": 6109, "蠡": 6110, "蠢": 6111, "蠣": 6112, "蠱": 6113, "蠶": 6114, "蠹": 6115, "蠻": 6116, "血": 6117, "衄": 6118, "衅": 6119, "衆": 6120, "行": 6121, "衍": 6122, "術": 6123, "衔": 6124, "街": 6125, "衙": 6126, "衛": 6127, "衝": 6128, "衞": 6129, "衡": 6130, "衢": 6131, "衣": 6132, "补": 6133, "表": 6134, "衩": 6135, "衫": 6136, "衬": 6137, "衮": 6138, "衰": 6139, "衲": 6140, "衷": 6141, "衹": 6142, "衾": 6143, "衿": 6144, "袁": 6145, "袂": 6146, "袄": 6147, "袅": 6148, "袈": 6149, "袋": 6150, "袍": 6151, "袒": 6152, "袖": 6153, "袜": 6154, "袞": 6155, "袤": 6156, "袪": 6157, "被": 6158, "袭": 6159, "袱": 6160, "裁": 6161, "裂": 6162, "装": 6163, "裆": 6164, "裊": 6165, "裏": 6166, "裔": 6167, "裕": 6168, "裘": 6169, "裙": 6170, "補": 6171, "裝": 6172, "裟": 6173, "裡": 6174, "裤": 6175, "裨": 6176, "裱": 6177, "裳": 6178, "裴": 6179, "裸": 6180, "裹": 6181, "製": 6182, "裾": 6183, "褂": 6184, "複": 6185, "褐": 6186, "褒": 6187, "褓": 6188, "褔": 6189, "褚": 6190, "褥": 6191, "褪": 6192, "褫": 6193, "褲": 6194, "褶": 6195, "褻": 6196, "襁": 6197, "襄": 6198, "襟": 6199, "襠": 6200, "襪": 6201, "襬": 6202, "襯": 6203, "襲": 6204, "西": 6205, "要": 6206, "覃": 6207, "覆": 6208, "覇": 6209, "見": 6210, "規": 6211, "覓": 6212, "視": 6213, "覚": 6214, "覦": 6215, "覧": 6216, "親": 6217, "覬": 6218, "観": 6219, "覷": 6220, "覺": 6221, "覽": 6222, "觀": 6223, "见": 6224, "观": 6225, "规": 6226, "觅": 6227, "视": 6228, "览": 6229, "觉": 6230, "觊": 6231, "觎": 6232, "觐": 6233, "觑": 6234, "角": 6235, "觞": 6236, "解": 6237, "觥": 6238, "触": 6239, "觸": 6240, "言": 6241, "訂": 6242, "計": 6243, "訊": 6244, "討": 6245, "訓": 6246, "訕": 6247, "訖": 6248, "託": 6249, "記": 6250, "訛": 6251, "訝": 6252, "訟": 6253, "訣": 6254, "訥": 6255, "訪": 6256, "設": 6257, "許": 6258, "訳": 6259, "訴": 6260, "訶": 6261, "診": 6262, "註": 6263, "証": 6264, "詆": 6265, "詐": 6266, "詔": 6267, "評": 6268, "詛": 6269, "詞": 6270, "詠": 6271, "詡": 6272, "詢": 6273, "詣": 6274, "試": 6275, "詩": 6276, "詫": 6277, "詬": 6278, "詭": 6279, "詮": 6280, "詰": 6281, "話": 6282, "該": 6283, "詳": 6284, "詹": 6285, "詼": 6286, "誅": 6287, "誇": 6288, "誉": 6289, "誌": 6290, "認": 6291, "誓": 6292, "誕": 6293, "誘": 6294, "語": 6295, "誠": 6296, "誡": 6297, "誣": 6298, "誤": 6299, "誥": 6300, "誦": 6301, "誨": 6302, "說": 6303, "説": 6304, "読": 6305, "誰": 6306, "課": 6307, "誹": 6308, "誼": 6309, "調": 6310, "諄": 6311, "談": 6312, "請": 6313, "諏": 6314, "諒": 6315, "論": 6316, "諗": 6317, "諜": 6318, "諡": 6319, "諦": 6320, "諧": 6321, "諫": 6322, "諭": 6323, "諮": 6324, "諱": 6325, "諳": 6326, "諷": 6327, "諸": 6328, "諺": 6329, "諾": 6330, "謀": 6331, "謁": 6332, "謂": 6333, "謄": 6334, "謊": 6335, "謎": 6336, "謐": 6337, "謔": 6338, "謗": 6339, "謙": 6340, "講": 6341, "謝": 6342, "謠": 6343, "謨": 6344, "謬": 6345, "謹": 6346, "謾": 6347, "譁": 6348, "證": 6349, "譎": 6350, "譏": 6351, "識": 6352, "譙": 6353, "譚": 6354, "譜": 6355, "警": 6356, "譬": 6357, "譯": 6358, "議": 6359, "譲": 6360, "譴": 6361, "護": 6362, "譽": 6363, "讀": 6364, "變": 6365, "讓": 6366, "讚": 6367, "讞": 6368, "计": 6369, "订": 6370, "认": 6371, "讥": 6372, "讧": 6373, "讨": 6374, "让": 6375, "讪": 6376, "讫": 6377, "训": 6378, "议": 6379, "讯": 6380, "记": 6381, "讲": 6382, "讳": 6383, "讴": 6384, "讶": 6385, "讷": 6386, "许": 6387, "讹": 6388, "论": 6389, "讼": 6390, "讽": 6391, "设": 6392, "访": 6393, "诀": 6394, "证": 6395, "诃": 6396, "评": 6397, "诅": 6398, "识": 6399, "诈": 6400, "诉": 6401, "诊": 6402, "诋": 6403, "词": 6404, "诏": 6405, "译": 6406, "试": 6407, "诗": 6408, "诘": 6409, "诙": 6410, "诚": 6411, "诛": 6412, "话": 6413, "诞": 6414, "诟": 6415, "诠": 6416, "诡": 6417, "询": 6418, "诣": 6419, "诤": 6420, "该": 6421, "详": 6422, "诧": 6423, "诩": 6424, "诫": 6425, "诬": 6426, "语": 6427, "误": 6428, "诰": 6429, "诱": 6430, "诲": 6431, "说": 6432, "诵": 6433, "诶": 6434, "请": 6435, "诸": 6436, "诺": 6437, "读": 6438, "诽": 6439, "课": 6440, "诿": 6441, "谀": 6442, "谁": 6443, "调": 6444, "谄": 6445, "谅": 6446, "谆": 6447, "谈": 6448, "谊": 6449, "谋": 6450, "谌": 6451, "谍": 6452, "谎": 6453, "谏": 6454, "谐": 6455, "谑": 6456, "谒": 6457, "谓": 6458, "谔": 6459, "谕": 6460, "谗": 6461, "谘": 6462, "谙": 6463, "谚": 6464, "谛": 6465, "谜": 6466, "谟": 6467, "谢": 6468, "谣": 6469, "谤": 6470, "谥": 6471, "谦": 6472, "谧": 6473, "谨": 6474, "谩": 6475, "谪": 6476, "谬": 6477, "谭": 6478, "谯": 6479, "谱": 6480, "谲": 6481, "谴": 6482, "谶": 6483, "谷": 6484, "豁": 6485, "豆": 6486, "豇": 6487, "豈": 6488, "豉": 6489, "豊": 6490, "豌": 6491, "豎": 6492, "豐": 6493, "豔": 6494, "豚": 6495, "象": 6496, "豢": 6497, "豪": 6498, "豫": 6499, "豬": 6500, "豹": 6501, "豺": 6502, "貂": 6503, "貅": 6504, "貌": 6505, "貓": 6506, "貔": 6507, "貘": 6508, "貝": 6509, "貞": 6510, "負": 6511, "財": 6512, "貢": 6513, "貧": 6514, "貨": 6515, "販": 6516, "貪": 6517, "貫": 6518, "責": 6519, "貯": 6520, "貰": 6521, "貳": 6522, "貴": 6523, "貶": 6524, "買": 6525, "貸": 6526, "費": 6527, "貼": 6528, "貽": 6529, "貿": 6530, "賀": 6531, "賁": 6532, "賂": 6533, "賃": 6534, "賄": 6535, "資": 6536, "賈": 6537, "賊": 6538, "賑": 6539, "賓": 6540, "賜": 6541, "賞": 6542, "賠": 6543, "賡": 6544, "賢": 6545, "賣": 6546, "賤": 6547, "賦": 6548, "質": 6549, "賬": 6550, "賭": 6551, "賴": 6552, "賺": 6553, "購": 6554, "賽": 6555, "贅": 6556, "贈": 6557, "贊": 6558, "贍": 6559, "贏": 6560, "贓": 6561, "贖": 6562, "贛": 6563, "贝": 6564, "贞": 6565, "负": 6566, "贡": 6567, "财": 6568, "责": 6569, "贤": 6570, "败": 6571, "账": 6572, "货": 6573, "质": 6574, "贩": 6575, "贪": 6576, "贫": 6577, "贬": 6578, "购": 6579, "贮": 6580, "贯": 6581, "贰": 6582, "贱": 6583, "贲": 6584, "贴": 6585, "贵": 6586, "贷": 6587, "贸": 6588, "费": 6589, "贺": 6590, "贻": 6591, "贼": 6592, "贾": 6593, "贿": 6594, "赁": 6595, "赂": 6596, "赃": 6597, "资": 6598, "赅": 6599, "赈": 6600, "赊": 6601, "赋": 6602, "赌": 6603, "赎": 6604, "赏": 6605, "赐": 6606, "赓": 6607, "赔": 6608, "赖": 6609, "赘": 6610, "赚": 6611, "赛": 6612, "赝": 6613, "赞": 6614, "赠": 6615, "赡": 6616, "赢": 6617, "赣": 6618, "赤": 6619, "赦": 6620, "赧": 6621, "赫": 6622, "赭": 6623, "走": 6624, "赳": 6625, "赴": 6626, "赵": 6627, "赶": 6628, "起": 6629, "趁": 6630, "超": 6631, "越": 6632, "趋": 6633, "趕": 6634, "趙": 6635, "趟": 6636, "趣": 6637, "趨": 6638, "足": 6639, "趴": 6640, "趵": 6641, "趸": 6642, "趺": 6643, "趾": 6644, "跃": 6645, "跄": 6646, "跆": 6647, "跋": 6648, "跌": 6649, "跎": 6650, "跑": 6651, "跖": 6652, "跚": 6653, "跛": 6654, "距": 6655, "跟": 6656, "跡": 6657, "跤": 6658, "跨": 6659, "跩": 6660, "跪": 6661, "路": 6662, "跳": 6663, "践": 6664, "跷": 6665, "跹": 6666, "跺": 6667, "跻": 6668, "踉": 6669, "踊": 6670, "踌": 6671, "踏": 6672, "踐": 6673, "踝": 6674, "踞": 6675, "踟": 6676, "踢": 6677, "踩": 6678, "踪": 6679, "踮": 6680, "踱": 6681, "踴": 6682, "踵": 6683, "踹": 6684, "蹂": 6685, "蹄": 6686, "蹇": 6687, "蹈": 6688, "蹉": 6689, "蹊": 6690, "蹋": 6691, "蹑": 6692, "蹒": 6693, "蹙": 6694, "蹟": 6695, "蹣": 6696, "蹤": 6697, "蹦": 6698, "蹩": 6699, "蹬": 6700, "蹭": 6701, "蹲": 6702, "蹴": 6703, "蹶": 6704, "蹺": 6705, "蹼": 6706, "蹿": 6707, "躁": 6708, "躇": 6709, "躉": 6710, "躊": 6711, "躋": 6712, "躍": 6713, "躏": 6714, "躪": 6715, "身": 6716, "躬": 6717, "躯": 6718, "躲": 6719, "躺": 6720, "軀": 6721, "車": 6722, "軋": 6723, "軌": 6724, "軍": 6725, "軒": 6726, "軟": 6727, "転": 6728, "軸": 6729, "軼": 6730, "軽": 6731, "軾": 6732, "較": 6733, "載": 6734, "輒": 6735, "輓": 6736, "輔": 6737, "輕": 6738, "輛": 6739, "輝": 6740, "輟": 6741, "輩": 6742, "輪": 6743, "輯": 6744, "輸": 6745, "輻": 6746, "輾": 6747, "輿": 6748, "轄": 6749, "轅": 6750, "轆": 6751, "轉": 6752, "轍": 6753, "轎": 6754, "轟": 6755, "车": 6756, "轧": 6757, "轨": 6758, "轩": 6759, "转": 6760, "轭": 6761, "轮": 6762, "软": 6763, "轰": 6764, "轲": 6765, "轴": 6766, "轶": 6767, "轻": 6768, "轼": 6769, "载": 6770, "轿": 6771, "较": 6772, "辄": 6773, "辅": 6774, "辆": 6775, "辇": 6776, "辈": 6777, "辉": 6778, "辊": 6779, "辍": 6780, "辐": 6781, "辑": 6782, "输": 6783, "辕": 6784, "辖": 6785, "辗": 6786, "辘": 6787, "辙": 6788, "辛": 6789, "辜": 6790, "辞": 6791, "辟": 6792, "辣": 6793, "辦": 6794, "辨": 6795, "辩": 6796, "辫": 6797, "辭": 6798, "辮": 6799, "辯": 6800, "辰": 6801, "辱": 6802, "農": 6803, "边": 6804, "辺": 6805, "辻": 6806, "込": 6807, "辽": 6808, "达": 6809, "迁": 6810, "迂": 6811, "迄": 6812, "迅": 6813, "过": 6814, "迈": 6815, "迎": 6816, "运": 6817, "近": 6818, "返": 6819, "还": 6820, "这": 6821, "进": 6822, "远": 6823, "违": 6824, "连": 6825, "迟": 6826, "迢": 6827, "迤": 6828, "迥": 6829, "迦": 6830, "迩": 6831, "迪": 6832, "迫": 6833, "迭": 6834, "述": 6835, "迴": 6836, "迷": 6837, "迸": 6838, "迹": 6839, "迺": 6840, "追": 6841, "退": 6842, "送": 6843, "适": 6844, "逃": 6845, "逅": 6846, "逆": 6847, "选": 6848, "逊": 6849, "逍": 6850, "透": 6851, "逐": 6852, "递": 6853, "途": 6854, "逕": 6855, "逗": 6856, "這": 6857, "通": 6858, "逛": 6859, "逝": 6860, "逞": 6861, "速": 6862, "造": 6863, "逢": 6864, "連": 6865, "逮": 6866, "週": 6867, "進": 6868, "逵": 6869, "逶": 6870, "逸": 6871, "逻": 6872, "逼": 6873, "逾": 6874, "遁": 6875, "遂": 6876, "遅": 6877, "遇": 6878, "遊": 6879, "運": 6880, "遍": 6881, "過": 6882, "遏": 6883, "遐": 6884, "遑": 6885, "遒": 6886, "道": 6887, "達": 6888, "違": 6889, "遗": 6890, "遙": 6891, "遛": 6892, "遜": 6893, "遞": 6894, "遠": 6895, "遢": 6896, "遣": 6897, "遥": 6898, "遨": 6899, "適": 6900, "遭": 6901, "遮": 6902, "遲": 6903, "遴": 6904, "遵": 6905, "遶": 6906, "遷": 6907, "選": 6908, "遺": 6909, "遼": 6910, "遽": 6911, "避": 6912, "邀": 6913, "邁": 6914, "邂": 6915, "邃": 6916, "還": 6917, "邇": 6918, "邈": 6919, "邊": 6920, "邋": 6921, "邏": 6922, "邑": 6923, "邓": 6924, "邕": 6925, "邛": 6926, "邝": 6927, "邢": 6928, "那": 6929, "邦": 6930, "邨": 6931, "邪": 6932, "邬": 6933, "邮": 6934, "邯": 6935, "邰": 6936, "邱": 6937, "邳": 6938, "邵": 6939, "邸": 6940, "邹": 6941, "邺": 6942, "邻": 6943, "郁": 6944, "郅": 6945, "郊": 6946, "郎": 6947, "郑": 6948, "郜": 6949, "郝": 6950, "郡": 6951, "郢": 6952, "郤": 6953, "郦": 6954, "郧": 6955, "部": 6956, "郫": 6957, "郭": 6958, "郴": 6959, "郵": 6960, "郷": 6961, "郸": 6962, "都": 6963, "鄂": 6964, "鄉": 6965, "鄒": 6966, "鄔": 6967, "鄙": 6968, "鄞": 6969, "鄢": 6970, "鄧": 6971, "鄭": 6972, "鄰": 6973, "鄱": 6974, "鄲": 6975, "鄺": 6976, "酉": 6977, "酊": 6978, "酋": 6979, "酌": 6980, "配": 6981, "酐": 6982, "酒": 6983, "酗": 6984, "酚": 6985, "酝": 6986, "酢": 6987, "酣": 6988, "酥": 6989, "酩": 6990, "酪": 6991, "酬": 6992, "酮": 6993, "酯": 6994, "酰": 6995, "酱": 6996, "酵": 6997, "酶": 6998, "酷": 6999, "酸": 7000, "酿": 7001, "醃": 7002, "醇": 7003, "醉": 7004, "醋": 7005, "醍": 7006, "醐": 7007, "醒": 7008, "醚": 7009, "醛": 7010, "醜": 7011, "醞": 7012, "醣": 7013, "醪": 7014, "醫": 7015, "醬": 7016, "醮": 7017, "醯": 7018, "醴": 7019, "醺": 7020, "釀": 7021, "釁": 7022, "采": 7023, "釉": 7024, "释": 7025, "釋": 7026, "里": 7027, "重": 7028, "野": 7029, "量": 7030, "釐": 7031, "金": 7032, "釗": 7033, "釘": 7034, "釜": 7035, "針": 7036, "釣": 7037, "釦": 7038, "釧": 7039, "釵": 7040, "鈀": 7041, "鈉": 7042, "鈍": 7043, "鈎": 7044, "鈔": 7045, "鈕": 7046, "鈞": 7047, "鈣": 7048, "鈦": 7049, "鈪": 7050, "鈴": 7051, "鈺": 7052, "鈾": 7053, "鉀": 7054, "鉄": 7055, "鉅": 7056, "鉉": 7057, "鉑": 7058, "鉗": 7059, "鉚": 7060, "鉛": 7061, "鉤": 7062, "鉴": 7063, "鉻": 7064, "銀": 7065, "銃": 7066, "銅": 7067, "銑": 7068, "銓": 7069, "銖": 7070, "銘": 7071, "銜": 7072, "銬": 7073, "銭": 7074, "銮": 7075, "銳": 7076, "銷": 7077, "銹": 7078, "鋁": 7079, "鋅": 7080, "鋒": 7081, "鋤": 7082, "鋪": 7083, "鋰": 7084, "鋸": 7085, "鋼": 7086, "錄": 7087, "錐": 7088, "錘": 7089, "錚": 7090, "錠": 7091, "錢": 7092, "錦": 7093, "錨": 7094, "錫": 7095, "錮": 7096, "錯": 7097, "録": 7098, "錳": 7099, "錶": 7100, "鍊": 7101, "鍋": 7102, "鍍": 7103, "鍛": 7104, "鍥": 7105, "鍰": 7106, "鍵": 7107, "鍺": 7108, "鍾": 7109, "鎂": 7110, "鎊": 7111, "鎌": 7112, "鎏": 7113, "鎔": 7114, "鎖": 7115, "鎗": 7116, "鎚": 7117, "鎧": 7118, "鎬": 7119, "鎮": 7120, "鎳": 7121, "鏈": 7122, "鏖": 7123, "鏗": 7124, "鏘": 7125, "鏞": 7126, "鏟": 7127, "鏡": 7128, "鏢": 7129, "鏤": 7130, "鏽": 7131, "鐘": 7132, "鐮": 7133, "鐲": 7134, "鐳": 7135, "鐵": 7136, "鐸": 7137, "鐺": 7138, "鑄": 7139, "鑊": 7140, "鑑": 7141, "鑒": 7142, "鑣": 7143, "鑫": 7144, "鑰": 7145, "鑲": 7146, "鑼": 7147, "鑽": 7148, "鑾": 7149, "鑿": 7150, "针": 7151, "钉": 7152, "钊": 7153, "钎": 7154, "钏": 7155, "钒": 7156, "钓": 7157, "钗": 7158, "钙": 7159, "钛": 7160, "钜": 7161, "钝": 7162, "钞": 7163, "钟": 7164, "钠": 7165, "钡": 7166, "钢": 7167, "钣": 7168, "钤": 7169, "钥": 7170, "钦": 7171, "钧": 7172, "钨": 7173, "钩": 7174, "钮": 7175, "钯": 7176, "钰": 7177, "钱": 7178, "钳": 7179, "钴": 7180, "钵": 7181, "钺": 7182, "钻": 7183, "钼": 7184, "钾": 7185, "钿": 7186, "铀": 7187, "铁": 7188, "铂": 7189, "铃": 7190, "铄": 7191, "铅": 7192, "铆": 7193, "铉": 7194, "铎": 7195, "铐": 7196, "铛": 7197, "铜": 7198, "铝": 7199, "铠": 7200, "铡": 7201, "铢": 7202, "铣": 7203, "铤": 7204, "铨": 7205, "铩": 7206, "铬": 7207, "铭": 7208, "铮": 7209, "铰": 7210, "铲": 7211, "铵": 7212, "银": 7213, "铸": 7214, "铺": 7215, "链": 7216, "铿": 7217, "销": 7218, "锁": 7219, "锂": 7220, "锄": 7221, "锅": 7222, "锆": 7223, "锈": 7224, "锉": 7225, "锋": 7226, "锌": 7227, "锏": 7228, "锐": 7229, "锑": 7230, "错": 7231, "锚": 7232, "锟": 7233, "锡": 7234, "锢": 7235, "锣": 7236, "锤": 7237, "锥": 7238, "锦": 7239, "锭": 7240, "键": 7241, "锯": 7242, "锰": 7243, "锲": 7244, "锵": 7245, "锹": 7246, "锺": 7247, "锻": 7248, "镀": 7249, "镁": 7250, "镂": 7251, "镇": 7252, "镉": 7253, "镌": 7254, "镍": 7255, "镐": 7256, "镑": 7257, "镕": 7258, "镖": 7259, "镗": 7260, "镛": 7261, "镜": 7262, "镣": 7263, "镭": 7264, "镯": 7265, "镰": 7266, "镳": 7267, "镶": 7268, "長": 7269, "长": 7270, "門": 7271, "閃": 7272, "閉": 7273, "開": 7274, "閎": 7275, "閏": 7276, "閑": 7277, "閒": 7278, "間": 7279, "閔": 7280, "閘": 7281, "閡": 7282, "関": 7283, "閣": 7284, "閥": 7285, "閨": 7286, "閩": 7287, "閱": 7288, "閲": 7289, "閹": 7290, "閻": 7291, "閾": 7292, "闆": 7293, "闇": 7294, "闊": 7295, "闌": 7296, "闍": 7297, "闔": 7298, "闕": 7299, "闖": 7300, "闘": 7301, "關": 7302, "闡": 7303, "闢": 7304, "门": 7305, "闪": 7306, "闫": 7307, "闭": 7308, "问": 7309, "闯": 7310, "闰": 7311, "闲": 7312, "间": 7313, "闵": 7314, "闷": 7315, "闸": 7316, "闹": 7317, "闺": 7318, "闻": 7319, "闽": 7320, "闾": 7321, "阀": 7322, "阁": 7323, "阂": 7324, "阅": 7325, "阆": 7326, "阇": 7327, "阈": 7328, "阉": 7329, "阎": 7330, "阐": 7331, "阑": 7332, "阔": 7333, "阕": 7334, "阖": 7335, "阙": 7336, "阚": 7337, "阜": 7338, "队": 7339, "阡": 7340, "阪": 7341, "阮": 7342, "阱": 7343, "防": 7344, "阳": 7345, "阴": 7346, "阵": 7347, "阶": 7348, "阻": 7349, "阿": 7350, "陀": 7351, "陂": 7352, "附": 7353, "际": 7354, "陆": 7355, "陇": 7356, "陈": 7357, "陋": 7358, "陌": 7359, "降": 7360, "限": 7361, "陕": 7362, "陛": 7363, "陝": 7364, "陞": 7365, "陟": 7366, "陡": 7367, "院": 7368, "陣": 7369, "除": 7370, "陨": 7371, "险": 7372, "陪": 7373, "陰": 7374, "陲": 7375, "陳": 7376, "陵": 7377, "陶": 7378, "陷": 7379, "陸": 7380, "険": 7381, "陽": 7382, "隅": 7383, "隆": 7384, "隈": 7385, "隊": 7386, "隋": 7387, "隍": 7388, "階": 7389, "随": 7390, "隐": 7391, "隔": 7392, "隕": 7393, "隘": 7394, "隙": 7395, "際": 7396, "障": 7397, "隠": 7398, "隣": 7399, "隧": 7400, "隨": 7401, "險": 7402, "隱": 7403, "隴": 7404, "隶": 7405, "隸": 7406, "隻": 7407, "隼": 7408, "隽": 7409, "难": 7410, "雀": 7411, "雁": 7412, "雄": 7413, "雅": 7414, "集": 7415, "雇": 7416, "雉": 7417, "雋": 7418, "雌": 7419, "雍": 7420, "雎": 7421, "雏": 7422, "雑": 7423, "雒": 7424, "雕": 7425, "雖": 7426, "雙": 7427, "雛": 7428, "雜": 7429, "雞": 7430, "離": 7431, "難": 7432, "雨": 7433, "雪": 7434, "雯": 7435, "雰": 7436, "雲": 7437, "雳": 7438, "零": 7439, "雷": 7440, "雹": 7441, "電": 7442, "雾": 7443, "需": 7444, "霁": 7445, "霄": 7446, "霆": 7447, "震": 7448, "霈": 7449, "霉": 7450, "霊": 7451, "霍": 7452, "霎": 7453, "霏": 7454, "霑": 7455, "霓": 7456, "霖": 7457, "霜": 7458, "霞": 7459, "霧": 7460, "霭": 7461, "霰": 7462, "露": 7463, "霸": 7464, "霹": 7465, "霽": 7466, "霾": 7467, "靂": 7468, "靄": 7469, "靈": 7470, "青": 7471, "靓": 7472, "靖": 7473, "静": 7474, "靚": 7475, "靛": 7476, "靜": 7477, "非": 7478, "靠": 7479, "靡": 7480, "面": 7481, "靥": 7482, "靦": 7483, "革": 7484, "靳": 7485, "靴": 7486, "靶": 7487, "靼": 7488, "鞅": 7489, "鞋": 7490, "鞍": 7491, "鞏": 7492, "鞑": 7493, "鞘": 7494, "鞠": 7495, "鞣": 7496, "鞦": 7497, "鞭": 7498, "韆": 7499, "韋": 7500, "韌": 7501, "韓": 7502, "韜": 7503, "韦": 7504, "韧": 7505, "韩": 7506, "韬": 7507, "韭": 7508, "音": 7509, "韵": 7510, "韶": 7511, "韻": 7512, "響": 7513, "頁": 7514, "頂": 7515, "頃": 7516, "項": 7517, "順": 7518, "須": 7519, "頌": 7520, "預": 7521, "頑": 7522, "頒": 7523, "頓": 7524, "頗": 7525, "領": 7526, "頜": 7527, "頡": 7528, "頤": 7529, "頫": 7530, "頭": 7531, "頰": 7532, "頷": 7533, "頸": 7534, "頹": 7535, "頻": 7536, "頼": 7537, "顆": 7538, "題": 7539, "額": 7540, "顎": 7541, "顏": 7542, "顔": 7543, "願": 7544, "顛": 7545, "類": 7546, "顧": 7547, "顫": 7548, "顯": 7549, "顱": 7550, "顴": 7551, "页": 7552, "顶": 7553, "顷": 7554, "项": 7555, "顺": 7556, "须": 7557, "顼": 7558, "顽": 7559, "顾": 7560, "顿": 7561, "颁": 7562, "颂": 7563, "预": 7564, "颅": 7565, "领": 7566, "颇": 7567, "颈": 7568, "颉": 7569, "颊": 7570, "颌": 7571, "颍": 7572, "颐": 7573, "频": 7574, "颓": 7575, "颔": 7576, "颖": 7577, "颗": 7578, "题": 7579, "颚": 7580, "颛": 7581, "颜": 7582, "额": 7583, "颞": 7584, "颠": 7585, "颡": 7586, "颢": 7587, "颤": 7588, "颦": 7589, "颧": 7590, "風": 7591, "颯": 7592, "颱": 7593, "颳": 7594, "颶": 7595, "颼": 7596, "飄": 7597, "飆": 7598, "风": 7599, "飒": 7600, "飓": 7601, "飕": 7602, "飘": 7603, "飙": 7604, "飚": 7605, "飛": 7606, "飞": 7607, "食": 7608, "飢": 7609, "飨": 7610, "飩": 7611, "飪": 7612, "飯": 7613, "飲": 7614, "飼": 7615, "飽": 7616, "飾": 7617, "餃": 7618, "餅": 7619, "餉": 7620, "養": 7621, "餌": 7622, "餐": 7623, "餒": 7624, "餓": 7625, "餘": 7626, "餚": 7627, "餛": 7628, "餞": 7629, "餡": 7630, "館": 7631, "餮": 7632, "餵": 7633, "餾": 7634, "饅": 7635, "饈": 7636, "饋": 7637, "饌": 7638, "饍": 7639, "饑": 7640, "饒": 7641, "饕": 7642, "饗": 7643, "饞": 7644, "饥": 7645, "饨": 7646, "饪": 7647, "饬": 7648, "饭": 7649, "饮": 7650, "饯": 7651, "饰": 7652, "饱": 7653, "饲": 7654, "饴": 7655, "饵": 7656, "饶": 7657, "饷": 7658, "饺": 7659, "饼": 7660, "饽": 7661, "饿": 7662, "馀": 7663, "馁": 7664, "馄": 7665, "馅": 7666, "馆": 7667, "馈": 7668, "馋": 7669, "馍": 7670, "馏": 7671, "馒": 7672, "馔": 7673, "首": 7674, "馗": 7675, "香": 7676, "馥": 7677, "馨": 7678, "馬": 7679, "馭": 7680, "馮": 7681, "馳": 7682, "馴": 7683, "駁": 7684, "駄": 7685, "駅": 7686, "駆": 7687, "駐": 7688, "駒": 7689, "駕": 7690, "駛": 7691, "駝": 7692, "駭": 7693, "駱": 7694, "駿": 7695, "騁": 7696, "騎": 7697, "騏": 7698, "験": 7699, "騙": 7700, "騨": 7701, "騰": 7702, "騷": 7703, "驀": 7704, "驅": 7705, "驊": 7706, "驍": 7707, "驒": 7708, "驕": 7709, "驗": 7710, "驚": 7711, "驛": 7712, "驟": 7713, "驢": 7714, "驥": 7715, "马": 7716, "驭": 7717, "驮": 7718, "驯": 7719, "驰": 7720, "驱": 7721, "驳": 7722, "驴": 7723, "驶": 7724, "驷": 7725, "驸": 7726, "驹": 7727, "驻": 7728, "驼": 7729, "驾": 7730, "驿": 7731, "骁": 7732, "骂": 7733, "骄": 7734, "骅": 7735, "骆": 7736, "骇": 7737, "骈": 7738, "骊": 7739, "骋": 7740, "验": 7741, "骏": 7742, "骐": 7743, "骑": 7744, "骗": 7745, "骚": 7746, "骛": 7747, "骜": 7748, "骞": 7749, "骠": 7750, "骡": 7751, "骤": 7752, "骥": 7753, "骧": 7754, "骨": 7755, "骯": 7756, "骰": 7757, "骶": 7758, "骷": 7759, "骸": 7760, "骼": 7761, "髂": 7762, "髅": 7763, "髋": 7764, "髏": 7765, "髒": 7766, "髓": 7767, "體": 7768, "髖": 7769, "高": 7770, "髦": 7771, "髪": 7772, "髮": 7773, "髯": 7774, "髻": 7775, "鬃": 7776, "鬆": 7777, "鬍": 7778, "鬓": 7779, "鬚": 7780, "鬟": 7781, "鬢": 7782, "鬣": 7783, "鬥": 7784, "鬧": 7785, "鬱": 7786, "鬼": 7787, "魁": 7788, "魂": 7789, "魄": 7790, "魅": 7791, "魇": 7792, "魍": 7793, "魏": 7794, "魔": 7795, "魘": 7796, "魚": 7797, "魯": 7798, "魷": 7799, "鮑": 7800, "鮨": 7801, "鮪": 7802, "鮭": 7803, "鮮": 7804, "鯉": 7805, "鯊": 7806, "鯖": 7807, "鯛": 7808, "鯨": 7809, "鯰": 7810, "鯽": 7811, "鰍": 7812, "鰓": 7813, "鰭": 7814, "鰲": 7815, "鰻": 7816, "鰾": 7817, "鱈": 7818, "鱉": 7819, "鱔": 7820, "鱗": 7821, "鱷": 7822, "鱸": 7823, "鱼": 7824, "鱿": 7825, "鲁": 7826, "鲈": 7827, "鲍": 7828, "鲑": 7829, "鲛": 7830, "鲜": 7831, "鲟": 7832, "鲢": 7833, "鲤": 7834, "鲨": 7835, "鲫": 7836, "鲱": 7837, "鲲": 7838, "鲶": 7839, "鲷": 7840, "鲸": 7841, "鳃": 7842, "鳄": 7843, "鳅": 7844, "鳌": 7845, "鳍": 7846, "鳕": 7847, "鳖": 7848, "鳗": 7849, "鳝": 7850, "鳞": 7851, "鳥": 7852, "鳩": 7853, "鳳": 7854, "鳴": 7855, "鳶": 7856, "鴉": 7857, "鴕": 7858, "鴛": 7859, "鴦": 7860, "鴨": 7861, "鴻": 7862, "鴿": 7863, "鵑": 7864, "鵜": 7865, "鵝": 7866, "鵡": 7867, "鵬": 7868, "鵰": 7869, "鵲": 7870, "鶘": 7871, "鶩": 7872, "鶯": 7873, "鶴": 7874, "鷗": 7875, "鷲": 7876, "鷹": 7877, "鷺": 7878, "鸚": 7879, "鸞": 7880, "鸟": 7881, "鸠": 7882, "鸡": 7883, "鸢": 7884, "鸣": 7885, "鸥": 7886, "鸦": 7887, "鸨": 7888, "鸪": 7889, "鸭": 7890, "鸯": 7891, "鸳": 7892, "鸵": 7893, "鸽": 7894, "鸾": 7895, "鸿": 7896, "鹂": 7897, "鹃": 7898, "鹄": 7899, "鹅": 7900, "鹈": 7901, "鹉": 7902, "鹊": 7903, "鹌": 7904, "鹏": 7905, "鹑": 7906, "鹕": 7907, "鹘": 7908, "鹜": 7909, "鹞": 7910, "鹤": 7911, "鹦": 7912, "鹧": 7913, "鹫": 7914, "鹭": 7915, "鹰": 7916, "鹳": 7917, "鹵": 7918, "鹹": 7919, "鹼": 7920, "鹽": 7921, "鹿": 7922, "麂": 7923, "麋": 7924, "麒": 7925, "麓": 7926, "麗": 7927, "麝": 7928, "麟": 7929, "麥": 7930, "麦": 7931, "麩": 7932, "麴": 7933, "麵": 7934, "麸": 7935, "麺": 7936, "麻": 7937, "麼": 7938, "麽": 7939, "麾": 7940, "黃": 7941, "黄": 7942, "黍": 7943, "黎": 7944, "黏": 7945, "黑": 7946, "黒": 7947, "黔": 7948, "默": 7949, "黛": 7950, "黜": 7951, "黝": 7952, "點": 7953, "黠": 7954, "黨": 7955, "黯": 7956, "黴": 7957, "鼋": 7958, "鼎": 7959, "鼐": 7960, "鼓": 7961, "鼠": 7962, "鼬": 7963, "鼹": 7964, "鼻": 7965, "鼾": 7966, "齁": 7967, "齊": 7968, "齋": 7969, "齐": 7970, "齒": 7971, "齡": 7972, "齢": 7973, "齣": 7974, "齦": 7975, "齿": 7976, "龄": 7977, "龅": 7978, "龈": 7979, "龊": 7980, "龋": 7981, "龌": 7982, "龍": 7983, "龐": 7984, "龔": 7985, "龕": 7986, "龙": 7987, "龚": 7988, "龛": 7989, "龜": 7990, "龟": 7991, "👍": 8102, "🔥": 8103, "😂": 8104, "😎": 8105, "︰": 7992, "︱": 7993, "︶": 7994, "︿": 7995, "﹁": 7996, "﹂": 7997, "﹍": 7998, "﹏": 7999, "﹐": 8000, "﹑": 8001, "﹒": 8002, "﹔": 8003, "﹕": 8004, "﹖": 8005, "﹗": 8006, "﹙": 8007, "﹚": 8008, "﹝": 8009, "﹞": 8010, "﹡": 8011, "﹣": 8012, "!": 8013, """: 8014, "#": 8015, "$": 8016, "%": 8017, "&": 8018, "'": 8019, "(": 8020, ")": 8021, "*": 8022, "+": 8023, ",": 8024, "-": 8025, ".": 8026, "/": 8027, "0": 8028, "1": 8029, "10": 9198, "11": 10300, "12": 10351, "13": 12911, "14": 12164, "15": 11213, "16": 12963, "18": 13218, "2": 8030, "20": 10327, "24": 12620, "3": 8031, "30": 10684, "4": 8032, "5": 8033, "50": 12869, "6": 8034, "7": 8035, "8": 8036, "9": 8037, ":": 8038, ";": 8039, "<": 8040, "=": 8041, ">": 8042, "?": 8043, "@": 8044, "[": 8045, "\": 8046, "]": 8047, "^": 8048, "_": 8049, "`": 8050, "a": 8051, "b": 8052, "c": 8053, "cp": 8836, "d": 8054, "e": 8055, "f": 8056, "g": 8057, "h": 8058, "i": 8059, "j": 8060, "k": 8061, "l": 8062, "m": 8063, "n": 8064, "o": 8065, "ok": 11518, "p": 8066, "q": 8067, "r": 8068, "s": 8069, "t": 8070, "u": 8071, "v": 8072, "w": 8073, "wedding": 10069, "x": 8074, "y": 8075, "z": 8076, "{": 8077, "|": 8078, "}": 8079, "~": 8080, "~1": 12756, "~10": 11115, "~4": 12476, "~5": 11980, "~~": 8734, "~~~": 9626, "。": 8081, "「": 8082, "」": 8083, "、": 8084, "・": 8085, "ッ": 8086, "ー": 8087, "イ": 8088, "ク": 8089, "シ": 8090, "ス": 8091, "ト": 8092, "ノ": 8093, "フ": 8094, "ラ": 8095, "ル": 8096, "ン": 8097, "゙": 8098, "゚": 8099, " ̄": 8100, "¥": 8101, "¥2899": 9425, "¥799": 9417 } } ================================================ FILE: Bert/deberta-v2-large-japanese/Tokenizer.json ================================================ { "Type": "Unigram", "ContinuingSubwordPrefix": "▁", "Vocab": [ [ "[PAD]", 0.0 ], [ "[CLS]", 0.0 ], [ "[SEP]", 0.0 ], [ "[UNK]", 0.0 ], [ "[MASK]", 0.0 ], [ "<0x00>", 0.0 ], [ "<0x01>", 0.0 ], [ "<0x02>", 0.0 ], [ "<0x03>", 0.0 ], [ "<0x04>", 0.0 ], [ "<0x05>", 0.0 ], [ "<0x06>", 0.0 ], [ "<0x07>", 0.0 ], [ "<0x08>", 0.0 ], [ "<0x09>", 0.0 ], [ "<0x0A>", 0.0 ], [ "<0x0B>", 0.0 ], [ "<0x0C>", 0.0 ], [ "<0x0D>", 0.0 ], [ "<0x0E>", 0.0 ], [ "<0x0F>", 0.0 ], [ "<0x10>", 0.0 ], [ "<0x11>", 0.0 ], [ "<0x12>", 0.0 ], [ "<0x13>", 0.0 ], [ "<0x14>", 0.0 ], [ "<0x15>", 0.0 ], [ "<0x16>", 0.0 ], [ "<0x17>", 0.0 ], [ "<0x18>", 0.0 ], [ "<0x19>", 0.0 ], [ "<0x1A>", 0.0 ], [ "<0x1B>", 0.0 ], [ "<0x1C>", 0.0 ], [ "<0x1D>", 0.0 ], [ "<0x1E>", 0.0 ], [ "<0x1F>", 0.0 ], [ "<0x20>", 0.0 ], [ "<0x21>", 0.0 ], [ "<0x22>", 0.0 ], [ "<0x23>", 0.0 ], [ "<0x24>", 0.0 ], [ "<0x25>", 0.0 ], [ "<0x26>", 0.0 ], [ "<0x27>", 0.0 ], [ "<0x28>", 0.0 ], [ "<0x29>", 0.0 ], [ "<0x2A>", 0.0 ], [ "<0x2B>", 0.0 ], [ "<0x2C>", 0.0 ], [ "<0x2D>", 0.0 ], [ "<0x2E>", 0.0 ], [ "<0x2F>", 0.0 ], [ "<0x30>", 0.0 ], [ "<0x31>", 0.0 ], [ "<0x32>", 0.0 ], [ "<0x33>", 0.0 ], [ "<0x34>", 0.0 ], [ "<0x35>", 0.0 ], [ "<0x36>", 0.0 ], [ "<0x37>", 0.0 ], [ "<0x38>", 0.0 ], [ "<0x39>", 0.0 ], [ "<0x3A>", 0.0 ], [ "<0x3B>", 0.0 ], [ "<0x3C>", 0.0 ], [ "<0x3D>", 0.0 ], [ "<0x3E>", 0.0 ], [ "<0x3F>", 0.0 ], [ "<0x40>", 0.0 ], [ "<0x41>", 0.0 ], [ "<0x42>", 0.0 ], [ "<0x43>", 0.0 ], [ "<0x44>", 0.0 ], [ "<0x45>", 0.0 ], [ "<0x46>", 0.0 ], [ "<0x47>", 0.0 ], [ "<0x48>", 0.0 ], [ "<0x49>", 0.0 ], [ "<0x4A>", 0.0 ], [ "<0x4B>", 0.0 ], [ "<0x4C>", 0.0 ], [ "<0x4D>", 0.0 ], [ "<0x4E>", 0.0 ], [ "<0x4F>", 0.0 ], [ "<0x50>", 0.0 ], [ "<0x51>", 0.0 ], [ "<0x52>", 0.0 ], [ "<0x53>", 0.0 ], [ "<0x54>", 0.0 ], [ "<0x55>", 0.0 ], [ "<0x56>", 0.0 ], [ "<0x57>", 0.0 ], [ "<0x58>", 0.0 ], [ "<0x59>", 0.0 ], [ "<0x5A>", 0.0 ], [ "<0x5B>", 0.0 ], [ "<0x5C>", 0.0 ], [ "<0x5D>", 0.0 ], [ "<0x5E>", 0.0 ], [ "<0x5F>", 0.0 ], [ "<0x60>", 0.0 ], [ "<0x61>", 0.0 ], [ "<0x62>", 0.0 ], [ "<0x63>", 0.0 ], [ "<0x64>", 0.0 ], [ "<0x65>", 0.0 ], [ "<0x66>", 0.0 ], [ "<0x67>", 0.0 ], [ "<0x68>", 0.0 ], [ "<0x69>", 0.0 ], [ "<0x6A>", 0.0 ], [ "<0x6B>", 0.0 ], [ "<0x6C>", 0.0 ], [ "<0x6D>", 0.0 ], [ "<0x6E>", 0.0 ], [ "<0x6F>", 0.0 ], [ "<0x70>", 0.0 ], [ "<0x71>", 0.0 ], [ "<0x72>", 0.0 ], [ "<0x73>", 0.0 ], [ "<0x74>", 0.0 ], [ "<0x75>", 0.0 ], [ "<0x76>", 0.0 ], [ "<0x77>", 0.0 ], [ "<0x78>", 0.0 ], [ "<0x79>", 0.0 ], [ "<0x7A>", 0.0 ], [ "<0x7B>", 0.0 ], [ "<0x7C>", 0.0 ], [ "<0x7D>", 0.0 ], [ "<0x7E>", 0.0 ], [ "<0x7F>", 0.0 ], [ "<0x80>", 0.0 ], [ "<0x81>", 0.0 ], [ "<0x82>", 0.0 ], [ "<0x83>", 0.0 ], [ "<0x84>", 0.0 ], [ "<0x85>", 0.0 ], [ "<0x86>", 0.0 ], [ "<0x87>", 0.0 ], [ "<0x88>", 0.0 ], [ "<0x89>", 0.0 ], [ "<0x8A>", 0.0 ], [ "<0x8B>", 0.0 ], [ "<0x8C>", 0.0 ], [ "<0x8D>", 0.0 ], [ "<0x8E>", 0.0 ], [ "<0x8F>", 0.0 ], [ "<0x90>", 0.0 ], [ "<0x91>", 0.0 ], [ "<0x92>", 0.0 ], [ "<0x93>", 0.0 ], [ "<0x94>", 0.0 ], [ "<0x95>", 0.0 ], [ "<0x96>", 0.0 ], [ "<0x97>", 0.0 ], [ "<0x98>", 0.0 ], [ "<0x99>", 0.0 ], [ "<0x9A>", 0.0 ], [ "<0x9B>", 0.0 ], [ "<0x9C>", 0.0 ], [ "<0x9D>", 0.0 ], [ "<0x9E>", 0.0 ], [ "<0x9F>", 0.0 ], [ "<0xA0>", 0.0 ], [ "<0xA1>", 0.0 ], [ "<0xA2>", 0.0 ], [ "<0xA3>", 0.0 ], [ "<0xA4>", 0.0 ], [ "<0xA5>", 0.0 ], [ "<0xA6>", 0.0 ], [ "<0xA7>", 0.0 ], [ "<0xA8>", 0.0 ], [ "<0xA9>", 0.0 ], [ "<0xAA>", 0.0 ], [ "<0xAB>", 0.0 ], [ "<0xAC>", 0.0 ], [ "<0xAD>", 0.0 ], [ "<0xAE>", 0.0 ], [ "<0xAF>", 0.0 ], [ "<0xB0>", 0.0 ], [ "<0xB1>", 0.0 ], [ "<0xB2>", 0.0 ], [ "<0xB3>", 0.0 ], [ "<0xB4>", 0.0 ], [ "<0xB5>", 0.0 ], [ "<0xB6>", 0.0 ], [ "<0xB7>", 0.0 ], [ "<0xB8>", 0.0 ], [ "<0xB9>", 0.0 ], [ "<0xBA>", 0.0 ], [ "<0xBB>", 0.0 ], [ "<0xBC>", 0.0 ], [ "<0xBD>", 0.0 ], [ "<0xBE>", 0.0 ], [ "<0xBF>", 0.0 ], [ "<0xC0>", 0.0 ], [ "<0xC1>", 0.0 ], [ "<0xC2>", 0.0 ], [ "<0xC3>", 0.0 ], [ "<0xC4>", 0.0 ], [ "<0xC5>", 0.0 ], [ "<0xC6>", 0.0 ], [ "<0xC7>", 0.0 ], [ "<0xC8>", 0.0 ], [ "<0xC9>", 0.0 ], [ "<0xCA>", 0.0 ], [ "<0xCB>", 0.0 ], [ "<0xCC>", 0.0 ], [ "<0xCD>", 0.0 ], [ "<0xCE>", 0.0 ], [ "<0xCF>", 0.0 ], [ "<0xD0>", 0.0 ], [ "<0xD1>", 0.0 ], [ "<0xD2>", 0.0 ], [ "<0xD3>", 0.0 ], [ "<0xD4>", 0.0 ], [ "<0xD5>", 0.0 ], [ "<0xD6>", 0.0 ], [ "<0xD7>", 0.0 ], [ "<0xD8>", 0.0 ], [ "<0xD9>", 0.0 ], [ "<0xDA>", 0.0 ], [ "<0xDB>", 0.0 ], [ "<0xDC>", 0.0 ], [ "<0xDD>", 0.0 ], [ "<0xDE>", 0.0 ], [ "<0xDF>", 0.0 ], [ "<0xE0>", 0.0 ], [ "<0xE1>", 0.0 ], [ "<0xE2>", 0.0 ], [ "<0xE3>", 0.0 ], [ "<0xE4>", 0.0 ], [ "<0xE5>", 0.0 ], [ "<0xE6>", 0.0 ], [ "<0xE7>", 0.0 ], [ "<0xE8>", 0.0 ], [ "<0xE9>", 0.0 ], [ "<0xEA>", 0.0 ], [ "<0xEB>", 0.0 ], [ "<0xEC>", 0.0 ], [ "<0xED>", 0.0 ], [ "<0xEE>", 0.0 ], [ "<0xEF>", 0.0 ], [ "<0xF0>", 0.0 ], [ "<0xF1>", 0.0 ], [ "<0xF2>", 0.0 ], [ "<0xF3>", 0.0 ], [ "<0xF4>", 0.0 ], [ "<0xF5>", 0.0 ], [ "<0xF6>", 0.0 ], [ "<0xF7>", 0.0 ], [ "<0xF8>", 0.0 ], [ "<0xF9>", 0.0 ], [ "<0xFA>", 0.0 ], [ "<0xFB>", 0.0 ], [ "<0xFC>", 0.0 ], [ "<0xFD>", 0.0 ], [ "<0xFE>", 0.0 ], [ "<0xFF>", 0.0 ], [ "▁、", -3.185030937194824 ], [ "▁の", -3.2029824256896973 ], [ "▁。", -3.5817534923553467 ], [ "▁に", -3.633868455886841 ], [ "▁を", -3.745628833770752 ], [ "▁は", -3.7610254287719727 ], [ "▁が", -3.897291898727417 ], [ "▁と", -4.033213138580322 ], [ "▁で", -4.427040100097656 ], [ "▁", -4.791779518127441 ], [ "▁)", -4.874192237854004 ], [ "▁・", -4.881843566894531 ], [ "▁(", -4.896781921386719 ], [ "▁年", -4.95025634765625 ], [ "▁して", -4.955025672912598 ], [ "▁も", -5.044909477233887 ], [ "▁さ", -5.176407814025879 ], [ "▁ます", -5.243093490600586 ], [ "▁する", -5.2626142501831055 ], [ "▁」", -5.267913818359375 ], [ "▁.", -5.334061622619629 ], [ "▁いる", -5.342490196228027 ], [ "▁こと", -5.368137359619141 ], [ "▁「", -5.388580322265625 ], [ "▁から", -5.4519805908203125 ], [ "▁し", -5.5356764793396 ], [ "▁した", -5.545491695404053 ], [ "▁月", -5.656735897064209 ], [ "▁ない", -5.707946300506592 ], [ "▁日", -5.803732395172119 ], [ "▁-", -5.826613426208496 ], [ "▁や", -5.882406711578369 ], [ "▁1", -5.980495452880859 ], [ "▁か", -5.986592769622803 ], [ "▁お", -6.049342155456543 ], [ "▁2", -6.051003932952881 ], [ "▁れた", -6.099290370941162 ], [ "▁人", -6.139554023742676 ], [ "▁れて", -6.168556213378906 ], [ "▁ある", -6.182873725891113 ], [ "▁いう", -6.194264888763428 ], [ "▁です", -6.201696872711182 ], [ "▁い", -6.223683834075928 ], [ "▁など", -6.248092174530029 ], [ "▁3", -6.307755470275879 ], [ "▁/", -6.327886581420898 ], [ "▁ました", -6.354998588562012 ], [ "▁!", -6.364776611328125 ], [ "▁である", -6.368945121765137 ], [ "▁いた", -6.440469264984131 ], [ "▁ため", -6.459425926208496 ], [ "▁れる", -6.460089683532715 ], [ "▁県", -6.517663478851318 ], [ "▁:", -6.520739555358887 ], [ "▁者", -6.531866550445557 ], [ "▁』", -6.5432000160217285 ], [ "▁あり", -6.550680160522461 ], [ "▁,", -6.567007541656494 ], [ "▁ので", -6.5858893394470215 ], [ "▁もの", -6.5932536125183105 ], [ "▁4", -6.599757194519043 ], [ "▁より", -6.6409125328063965 ], [ "▁れ", -6.657708168029785 ], [ "▁まで", -6.667444229125977 ], [ "▁市", -6.667632102966309 ], [ "▁中", -6.680952548980713 ], [ "▁日本", -6.688035488128662 ], [ "▁『", -6.691053867340088 ], [ "▁なる", -6.7163262367248535 ], [ "▁へ", -6.766645908355713 ], [ "▁5", -6.794265270233154 ], [ "▁一", -6.857036113739014 ], [ "▁その", -6.857986927032471 ], [ "▁ ", -6.861833095550537 ], [ "▁なり", -6.909881114959717 ], [ "▁なって", -6.926736831665039 ], [ "▁ん", -6.926886558532715 ], [ "▁方", -6.92744255065918 ], [ "▁ご", -6.941175937652588 ], [ "▁な", -6.952221393585205 ], [ "▁この", -6.977395534515381 ], [ "▁ませ", -6.995728969573975 ], [ "▁ように", -7.003463268280029 ], [ "▁10", -7.00608491897583 ], [ "▁なった", -7.023584365844727 ], [ "▁時", -7.028842926025391 ], [ "▁第", -7.030608654022217 ], [ "▁後", -7.041182518005371 ], [ "▁6", -7.0504937171936035 ], [ "▁場合", -7.076604843139648 ], [ "▁おり", -7.087188720703125 ], [ "▁でも", -7.100583553314209 ], [ "な", -7.121886253356934 ], [ "▁?", -7.152363300323486 ], [ "▁7", -7.156400203704834 ], [ "▁つ", -7.158433437347412 ], [ "▁内", -7.159237861633301 ], [ "▁\"", -7.162384510040283 ], [ "て", -7.16347599029541 ], [ "▁でき", -7.169011116027832 ], [ "▁できる", -7.174111366271973 ], [ "この", -7.185379505157471 ], [ "▁ついて", -7.185727596282959 ], [ "▁大", -7.195167541503906 ], [ "▁8", -7.2087321281433105 ], [ "また", -7.210239410400391 ], [ "▁だ", -7.216036319732666 ], [ "▁性", -7.23112154006958 ], [ "る", -7.240654945373535 ], [ "に", -7.24181604385376 ], [ "▁たい", -7.255130767822266 ], [ "▁なく", -7.271181106567383 ], [ "▁的な", -7.301826000213623 ], [ "▁的に", -7.312690734863281 ], [ "▁情報", -7.313773155212402 ], [ "▁9", -7.327561855316162 ], [ "▁;", -7.330902099609375 ], [ "▁町", -7.3352251052856445 ], [ "▁だけ", -7.3486175537109375 ], [ "▁|", -7.362304210662842 ], [ "▁上", -7.3633012771606445 ], [ "▁目", -7.366700172424316 ], [ "▁ね", -7.374264717102051 ], [ "▁12", -7.377789497375488 ], [ "▁ず", -7.382078170776367 ], [ "「", -7.387681007385254 ], [ "▁&", -7.394844055175781 ], [ "▁よる", -7.414653301239014 ], [ "▁ください", -7.417072772979736 ], [ "▁家", -7.417440891265869 ], [ "▁それ", -7.418474197387695 ], [ "▁思い", -7.429837703704834 ], [ "▁前", -7.433615684509277 ], [ "▁これ", -7.437440872192383 ], [ "▁11", -7.458650588989258 ], [ "▁さん", -7.4597954750061035 ], [ "▁国", -7.46527099609375 ], [ "▁利用", -7.469320297241211 ], [ "▁時間", -7.4718732833862305 ], [ "▁t", -7.479592800140381 ], [ "り", -7.480184078216553 ], [ "ら", -7.484375476837158 ], [ "▁会", -7.488077640533447 ], [ "▁よって", -7.489053726196289 ], [ "▁本", -7.491520404815674 ], [ "▁】", -7.4928669929504395 ], [ "た", -7.512076377868652 ], [ "▁回", -7.522967338562012 ], [ "▁化", -7.5234293937683105 ], [ "ス", -7.5245537757873535 ], [ "▁ら", -7.5381574630737305 ], [ "▁円", -7.560770034790039 ], [ "▁大学", -7.561233997344971 ], [ "▁自分", -7.578431129455566 ], [ "▁なかった", -7.592169284820557 ], [ "▁等", -7.616418838500977 ], [ "▁たち", -7.617324352264404 ], [ "▁名", -7.6242475509643555 ], [ "の", -7.626774787902832 ], [ "▁なら", -7.63295841217041 ], [ "▁使用", -7.637490749359131 ], [ "▁所", -7.637675762176514 ], [ "▁よ", -7.660862922668457 ], [ "▁会社", -7.661202430725098 ], [ "▁同", -7.665493011474609 ], [ "▁私", -7.669919490814209 ], [ "▁世界", -7.67061710357666 ], [ "万", -7.679087162017822 ], [ "▁店", -7.680029392242432 ], [ "▁のです", -7.680973052978516 ], [ "▁ような", -7.685946941375732 ], [ "▁事", -7.697939395904541 ], [ "▁だった", -7.698142051696777 ], [ "これ", -7.700052261352539 ], [ "▁多く", -7.701132774353027 ], [ "▁数", -7.709089279174805 ], [ "▁駅", -7.71061897277832 ], [ "▁研究", -7.712349891662598 ], [ "▁サイト", -7.738548755645752 ], [ "▁東京", -7.741631984710693 ], [ "▁%", -7.75072717666626 ], [ "▁られる", -7.756758213043213 ], [ "その", -7.782837867736816 ], [ "▁代", -7.78517484664917 ], [ "▁語", -7.792673587799072 ], [ "▁分", -7.805175304412842 ], [ "▁二", -7.809190273284912 ], [ "で", -7.809691429138184 ], [ "▁的", -7.810966491699219 ], [ "▁...", -7.824028968811035 ], [ "▁時代", -7.827169418334961 ], [ "▁A", -7.831678867340088 ], [ "▁線", -7.833589553833008 ], [ "▁間", -7.846977233886719 ], [ "ズ", -7.847821235656738 ], [ "ト", -7.851916790008545 ], [ "い", -7.853623867034912 ], [ "▁20", -7.855557441711426 ], [ "▁部", -7.858024597167969 ], [ "▁問題", -7.858707427978516 ], [ "▁いい", -7.8588409423828125 ], [ "▁金", -7.859185695648193 ], [ "▁【", -7.861090660095215 ], [ "▁であり", -7.865991115570068 ], [ "▁あった", -7.8663649559021 ], [ "▁おいて", -7.875364780426025 ], [ "▁区", -7.879593849182129 ], [ "▁B", -7.88090705871582 ], [ "さ", -7.881806373596191 ], [ "▁0", -7.888063907623291 ], [ "▁C", -7.89302396774292 ], [ "って", -7.894173622131348 ], [ "▁であった", -7.897000789642334 ], [ "s", -7.9036865234375 ], [ "▁S", -7.9049973487854 ], [ "▁作品", -7.906022548675537 ], [ "▁他", -7.906961441040039 ], [ "しかし", -7.907767295837402 ], [ "▁見", -7.912409782409668 ], [ "▁以上", -7.91801643371582 ], [ "▁新", -7.926347732543945 ], [ "子", -7.927391052246094 ], [ "▁カナダ", -7.93876314163208 ], [ "▁モンクレール", -7.948892116546631 ], [ "▁15", -7.950605392456055 ], [ "▁ながら", -7.956249237060547 ], [ "▁戦", -7.961787223815918 ], [ "▁30", -7.962786674499512 ], [ "▁られ", -7.974327564239502 ], [ "▁]", -7.978815078735352 ], [ "▁様", -7.978870868682861 ], [ "▁気", -7.979624271392822 ], [ "▁いく", -7.984396934509277 ], [ "し", -7.99149751663208 ], [ "▁長", -7.996387481689453 ], [ "▁活動", -7.997335910797119 ], [ "▁社", -8.00036334991455 ], [ "▁現在", -8.002766609191895 ], [ "▁度", -8.005853652954102 ], [ "▁行わ", -8.006837844848633 ], [ "▁放送", -8.007451057434082 ], [ "▁地", -8.017082214355469 ], [ "▁グース", -8.020332336425781 ], [ "▁_", -8.02074909210205 ], [ "▁サービス", -8.02198600769043 ], [ "▁F", -8.023130416870117 ], [ "▁多い", -8.024787902832031 ], [ "▁用", -8.026814460754395 ], [ "▁軍", -8.03275203704834 ], [ "▁られて", -8.034721374511719 ], [ "▁力", -8.041336059570312 ], [ "▁18", -8.04395580291748 ], [ "ン", -8.046232223510742 ], [ "▁下", -8.046765327453613 ], [ "と", -8.048293113708496 ], [ "▁g", -8.049100875854492 ], [ "▁高", -8.053685188293457 ], [ "▁号", -8.055312156677246 ], [ "▁館", -8.059028625488281 ], [ "▁歳", -8.061066627502441 ], [ "▁系", -8.065824508666992 ], [ "▁方法", -8.066828727722168 ], [ "▁み", -8.066844940185547 ], [ "▁三", -8.070152282714844 ], [ "▁られた", -8.070478439331055 ], [ "▁とき", -8.078651428222656 ], [ "▁ところ", -8.0809907913208 ], [ "▁今", -8.083009719848633 ], [ "▁関係", -8.085482597351074 ], [ "▁紹介", -8.088937759399414 ], [ "▁話", -8.091839790344238 ], [ "▁手", -8.094573974609375 ], [ "▁機", -8.09585189819336 ], [ "▁点", -8.10093879699707 ], [ "田", -8.109061241149902 ], [ "(", -8.109119415283203 ], [ "▁版", -8.111604690551758 ], [ "く", -8.116199493408203 ], [ "▁法", -8.117684364318848 ], [ "▁車", -8.124707221984863 ], [ "▁=", -8.126644134521484 ], [ "▁17", -8.126801490783691 ], [ "▁でしょう", -8.127066612243652 ], [ "▁映画", -8.12856674194336 ], [ "▁位", -8.130151748657227 ], [ "▁16", -8.134845733642578 ], [ "ク", -8.13585090637207 ], [ "▁何", -8.136556625366211 ], [ "▁約", -8.13766860961914 ], [ "ド", -8.145572662353516 ], [ "▁女性", -8.146269798278809 ], [ "お", -8.149218559265137 ], [ "▁客", -8.154172897338867 ], [ "▁D", -8.159314155578613 ], [ "ー", -8.161267280578613 ], [ "▁選手", -8.161751747131348 ], [ "▁参加", -8.163887023925781 ], [ "▁存在", -8.164865493774414 ], [ "▁地域", -8.169321060180664 ], [ "▁彼", -8.170626640319824 ], [ "▁学校", -8.177874565124512 ], [ "▁せて", -8.178025245666504 ], [ "▁T", -8.178367614746094 ], [ "▁商品", -8.184220314025879 ], [ "▁M", -8.187353134155273 ], [ "▁きた", -8.190163612365723 ], [ "▁側", -8.191133499145508 ], [ "▁けど", -8.192169189453125 ], [ "▁l", -8.193598747253418 ], [ "った", -8.19489574432373 ], [ "▁せ", -8.195064544677734 ], [ "▁開催", -8.198210716247559 ], [ "▁”", -8.199389457702637 ], [ "▁m", -8.205683708190918 ], [ "▁必要", -8.206023216247559 ], [ "▁って", -8.21193790435791 ], [ "▁開発", -8.21272087097168 ], [ "▁可能", -8.214848518371582 ], [ "▁しまう", -8.216564178466797 ], [ "▁体", -8.220537185668945 ], [ "2", -8.220589637756348 ], [ "▁元", -8.223487854003906 ], [ "▁初", -8.223544120788574 ], [ "▁ゲーム", -8.230451583862305 ], [ "▁仕事", -8.23257827758789 ], [ "▁型", -8.235507011413574 ], [ "▁る", -8.237688064575195 ], [ "▁でした", -8.23890495300293 ], [ "▁13", -8.23920726776123 ], [ "▁および", -8.239863395690918 ], [ "▁また", -8.23989486694336 ], [ "▁s", -8.24000358581543 ], [ "▁水", -8.241935729980469 ], [ "▁小", -8.242103576660156 ], [ "▁考え", -8.243915557861328 ], [ "▁かも", -8.244084358215332 ], [ "本", -8.244566917419434 ], [ "▁際", -8.244651794433594 ], [ "▁全", -8.24739933013916 ], [ "ナ", -8.249013900756836 ], [ "ラ", -8.25264835357666 ], [ "▁んです", -8.257701873779297 ], [ "▁対応", -8.25841999053955 ], [ "▁販売", -8.259342193603516 ], [ "▁14", -8.259986877441406 ], [ "き", -8.2608642578125 ], [ "▁事業", -8.262687683105469 ], [ "1", -8.264510154724121 ], [ "▁郡", -8.266626358032227 ], [ "『", -8.27314567565918 ], [ "それ", -8.275477409362793 ], [ "▁社会", -8.277527809143066 ], [ "▁以下", -8.28046703338623 ], [ "山", -8.280874252319336 ], [ "▁学", -8.2835111618042 ], [ "▁昭和", -8.284724235534668 ], [ "▁生", -8.288949012756348 ], [ "▁良い", -8.292240142822266 ], [ "▁東", -8.293798446655273 ], [ "▁発表", -8.302440643310547 ], [ "▁無料", -8.311860084533691 ], [ "▁提供", -8.313860893249512 ], [ "▁P", -8.313971519470215 ], [ "▁アウトレット", -8.31779956817627 ], [ "▁行って", -8.321037292480469 ], [ "▁のみ", -8.321063995361328 ], [ "▁生活", -8.324690818786621 ], [ "▁州", -8.324767112731934 ], [ "ア", -8.326135635375977 ], [ "▁確認", -8.32917594909668 ], [ "▁内容", -8.329683303833008 ], [ "リ", -8.33302116394043 ], [ "▁権", -8.34040355682373 ], [ "▁思って", -8.342873573303223 ], [ "▁形", -8.349960327148438 ], [ "▁物", -8.351666450500488 ], [ "▁結果", -8.358297348022461 ], [ "▁同じ", -8.360219955444336 ], [ "ル", -8.367971420288086 ], [ "タ", -8.375411987304688 ], [ "▁どう", -8.37544059753418 ], [ "▁企業", -8.37961483001709 ], [ "川", -8.381178855895996 ], [ "か", -8.386651992797852 ], [ "ま", -8.386672019958496 ], [ "▁ほど", -8.388315200805664 ], [ "▁教育", -8.388477325439453 ], [ "▁大阪", -8.395724296569824 ], [ "▁アメリカ", -8.39719009399414 ], [ "▁おける", -8.400397300720215 ], [ "マ", -8.400676727294922 ], [ "人", -8.400848388671875 ], [ "▁代表", -8.401676177978516 ], [ "▁R", -8.402485847473145 ], [ "▁村", -8.403013229370117 ], [ "▁発売", -8.403596878051758 ], [ "▁書", -8.40537166595459 ], [ "▁西", -8.40694808959961 ], [ "▁き", -8.413152694702148 ], [ "▁テレビ", -8.413516998291016 ], [ "▁購入", -8.414671897888184 ], [ "▁21", -8.415777206420898 ], [ "コ", -8.416510581970215 ], [ "▁H", -8.419289588928223 ], [ "ム", -8.42374038696289 ], [ "▁場", -8.424023628234863 ], [ "▁せる", -8.425074577331543 ], [ "▁曲", -8.427006721496582 ], [ "▁ア", -8.429001808166504 ], [ "▁機能", -8.430390357971191 ], [ "一", -8.431514739990234 ], [ "▁高い", -8.435147285461426 ], [ "▁にて", -8.435932159423828 ], [ "わ", -8.43838119506836 ], [ "み", -8.439143180847168 ], [ "▁行う", -8.444581985473633 ], [ "す", -8.445134162902832 ], [ "▁いった", -8.449736595153809 ], [ "▁開始", -8.452500343322754 ], [ "▁氏", -8.452964782714844 ], [ "▁中心", -8.45935344696045 ], [ "▁変更", -8.459563255310059 ], [ "▁式", -8.459782600402832 ], [ "▁いて", -8.46031665802002 ], [ "▁写真", -8.461480140686035 ], [ "▁チーム", -8.461644172668457 ], [ "▁19", -8.463264465332031 ], [ "▁#", -8.463314056396484 ], [ "▁呼ば", -8.463386535644531 ], [ "▁品", -8.464287757873535 ], [ ",", -8.465691566467285 ], [ "▁状態", -8.466142654418945 ], [ "▁店舗", -8.466987609863281 ], [ "▁25", -8.469518661499023 ], [ "カ", -8.46973991394043 ], [ "▁山", -8.469773292541504 ], [ "日本", -8.470269203186035 ], [ "▁管理", -8.475274085998535 ], [ "▁次", -8.477337837219238 ], [ "▁番組", -8.479393005371094 ], [ "▁思う", -8.481513977050781 ], [ "ロ", -8.482720375061035 ], [ "▁G", -8.483154296875 ], [ "▁作", -8.48570728302002 ], [ "▁影響", -8.489986419677734 ], [ "▁外", -8.49377727508545 ], [ "▁音楽", -8.496183395385742 ], [ "▁技術", -8.49731159210205 ], [ "▁E", -8.4986572265625 ], [ "▁関する", -8.501255989074707 ], [ "▁システム", -8.50229549407959 ], [ "▁平成", -8.503218650817871 ], [ "▁先", -8.50346565246582 ], [ "▁〜", -8.504495620727539 ], [ "▁シリーズ", -8.505021095275879 ], [ "▁場所", -8.507312774658203 ], [ "▁人気", -8.507386207580566 ], [ "▁個人", -8.507560729980469 ], [ "▁よく", -8.507830619812012 ], [ "▁2021", -8.510065078735352 ], [ "▁100", -8.511175155639648 ], [ "▁~", -8.515472412109375 ], [ "▁北", -8.515846252441406 ], [ "▁24", -8.517126083374023 ], [ "▁しれ", -8.521648406982422 ], [ "▁K", -8.522716522216797 ], [ "▁一部", -8.524723052978516 ], [ "ノ", -8.52752685546875 ], [ "▁見て", -8.53071403503418 ], [ "▁表示", -8.532846450805664 ], [ "大", -8.535872459411621 ], [ "▁科", -8.537628173828125 ], [ "▁対して", -8.5388822555542 ], [ "▁南", -8.540435791015625 ], [ "▁登録", -8.540699005126953 ], [ "▁感じ", -8.541309356689453 ], [ "▁知ら", -8.544553756713867 ], [ "▁意味", -8.546213150024414 ], [ "バ", -8.547356605529785 ], [ "▁[", -8.54958724975586 ], [ "▁効果", -8.551225662231445 ], [ "▁22", -8.552604675292969 ], [ "▁環境", -8.554305076599121 ], [ "▁各", -8.555606842041016 ], [ "▁子", -8.558232307434082 ], [ "▁タイヤ", -8.558975219726562 ], [ "▁一般", -8.56052017211914 ], [ "だ", -8.563687324523926 ], [ "フ", -8.566330909729004 ], [ "▁試験", -8.567835807800293 ], [ "▁2020", -8.568076133728027 ], [ "▁言わ", -8.569377899169922 ], [ "【", -8.57307243347168 ], [ "▁登場", -8.57370376586914 ], [ "▁調査", -8.57463550567627 ], [ "▁以降", -8.577279090881348 ], [ "▁記事", -8.578113555908203 ], [ "▁自身", -8.57868766784668 ], [ "▁当時", -8.57959270477295 ], [ "▁大会", -8.583451271057129 ], [ "▁局", -8.584240913391113 ], [ "▁または", -8.590699195861816 ], [ "その後", -8.592182159423828 ], [ "そして", -8.594971656799316 ], [ "チ", -8.595514297485352 ], [ "▁いただき", -8.595699310302734 ], [ "▁心", -8.595803260803223 ], [ "リー", -8.59677505493164 ], [ "~", -8.597053527832031 ], [ "▁国際", -8.599427223205566 ], [ "私", -8.599593162536621 ], [ "▁23", -8.600883483886719 ], [ "▁記録", -8.601479530334473 ], [ "▁カード", -8.60237979888916 ], [ "▁賞", -8.603029251098633 ], [ "同", -8.604026794433594 ], [ "▁うち", -8.60482120513916 ], [ "▁出身", -8.608070373535156 ], [ "▁委員", -8.61119556427002 ], [ "▁通り", -8.61267375946045 ], [ "▁センター", -8.61279010772705 ], [ "▁持って", -8.616338729858398 ], [ "▁ともに", -8.617701530456543 ], [ "▁ダウン", -8.617997169494629 ], [ "▁道", -8.618237495422363 ], [ "なお", -8.621746063232422 ], [ "▁設定", -8.622075080871582 ], [ "▁なければ", -8.622992515563965 ], [ "▁都", -8.623297691345215 ], [ "▁文化", -8.624309539794922 ], [ "キ", -8.625223159790039 ], [ "▁ましょう", -8.627578735351562 ], [ "▁中国", -8.633169174194336 ], [ "3", -8.633576393127441 ], [ "▁動画", -8.63395881652832 ], [ "▁んだ", -8.635092735290527 ], [ "▁頃", -8.63717269897461 ], [ "▁ページ", -8.645527839660645 ], [ "・", -8.645946502685547 ], [ "S", -8.646881103515625 ], [ "▁よう", -8.646886825561523 ], [ "▁以外", -8.646909713745117 ], [ "▁公開", -8.648885726928711 ], [ "▁役", -8.64951229095459 ], [ "▁V", -8.650028228759766 ], [ "▁J", -8.65195369720459 ], [ "▁試合", -8.654403686523438 ], [ "▁状況", -8.656203269958496 ], [ "▁プロ", -8.656368255615234 ], [ "▁データ", -8.657211303710938 ], [ "▁しまい", -8.658308029174805 ], [ "▁L", -8.664351463317871 ], [ "▁専門", -8.667210578918457 ], [ "▁感", -8.678299903869629 ], [ "▁>", -8.680032730102539 ], [ "▁いき", -8.683222770690918 ], [ "▁しか", -8.68333625793457 ], [ "▁願い", -8.683533668518066 ], [ "▁N", -8.69074535369873 ], [ "第", -8.693888664245605 ], [ "▁目的", -8.694649696350098 ], [ "▁及び", -8.697286605834961 ], [ "野", -8.701876640319824 ], [ "レ", -8.703042030334473 ], [ "ダ", -8.704231262207031 ], [ "▁大きな", -8.704476356506348 ], [ "▁くる", -8.706354141235352 ], [ "▁株式", -8.706450462341309 ], [ "▁経済", -8.707179069519043 ], [ "概要", -8.70723819732666 ], [ "▁'", -8.710365295410156 ], [ "▁2018", -8.710861206054688 ], [ "▁部分", -8.710872650146484 ], [ "▁鉄道", -8.710886001586914 ], [ "▁いたし", -8.71095085144043 ], [ "▁受け", -8.71316146850586 ], [ "▁計画", -8.714073181152344 ], [ "ツ", -8.715557098388672 ], [ "▁持つ", -8.716750144958496 ], [ "▁W", -8.72092056274414 ], [ "▁色", -8.722179412841797 ], [ "▁施設", -8.722347259521484 ], [ "▁担当", -8.723125457763672 ], [ "原", -8.723352432250977 ], [ "▁契約", -8.726580619812012 ], [ "上", -8.728938102722168 ], [ "ネ", -8.729519844055176 ], [ "▁デザイン", -8.730265617370605 ], [ "▁そう", -8.735098838806152 ], [ "▁のだ", -8.735325813293457 ], [ "▁あなた", -8.736220359802246 ], [ "▁考えて", -8.738414764404297 ], [ "▁p", -8.738759994506836 ], [ "▁級", -8.742013931274414 ], [ "▁価格", -8.742155075073242 ], [ "▁期", -8.742574691772461 ], [ "▁期間", -8.743024826049805 ], [ "▁再", -8.743167877197266 ], [ "シ", -8.744353294372559 ], [ "▁出場", -8.74435806274414 ], [ "▁出て", -8.747735977172852 ], [ "島", -8.749215126037598 ], [ "▁島", -8.750080108642578 ], [ "▁2019", -8.750238418579102 ], [ "▁省", -8.752098083496094 ], [ "▁評価", -8.752190589904785 ], [ "▁発生", -8.75312328338623 ], [ "▁川", -8.75321102142334 ], [ "▁出演", -8.754293441772461 ], [ "▁モデル", -8.758337020874023 ], [ "▁すべて", -8.7610445022583 ], [ "▁年間", -8.76142406463623 ], [ "▁選択", -8.764636039733887 ], [ "▁ございます", -8.765458106994629 ], [ "▁人間", -8.765986442565918 ], [ "▁+", -8.769140243530273 ], [ "▁関連", -8.770435333251953 ], [ "▁支援", -8.770509719848633 ], [ "▁監督", -8.770634651184082 ], [ "▁率", -8.77235221862793 ], [ "▁シーズン", -8.772828102111816 ], [ "▁イベント", -8.776876449584961 ], [ "▁サイズ", -8.776958465576172 ], [ "▁グループ", -8.780716896057129 ], [ "▁28", -8.782977104187012 ], [ "▁理由", -8.783198356628418 ], [ "サ", -8.783882141113281 ], [ "▁26", -8.785008430480957 ], [ "▁実施", -8.788067817687988 ], [ "▁世", -8.78923511505127 ], [ "ジ", -8.789690971374512 ], [ "▁番", -8.789877891540527 ], [ "▁その他", -8.790164947509766 ], [ "▁リーグ", -8.790663719177246 ], [ "イ", -8.790717124938965 ], [ "▁言う", -8.791111946105957 ], [ "▁予定", -8.79133129119873 ], [ "▁説明", -8.793964385986328 ], [ "▁すぐ", -8.796640396118164 ], [ "▁相談", -8.799564361572266 ], [ "▁ダウンロード", -8.799908638000488 ], [ "▁e", -8.800846099853516 ], [ "▁とって", -8.801958084106445 ], [ "▁ポイント", -8.802019119262695 ], [ "▁さらに", -8.80276870727539 ], [ "う", -8.805696487426758 ], [ "▁掲載", -8.80627155303955 ], [ "▁27", -8.806368827819824 ], [ "▁メール", -8.80659008026123 ], [ "▁員", -8.807891845703125 ], [ "▁地方", -8.809200286865234 ], [ "▁ここ", -8.81175422668457 ], [ "▁設置", -8.81204605102539 ], [ "▁もう", -8.81344985961914 ], [ "▁かけて", -8.815631866455078 ], [ "▁機関", -8.816887855529785 ], [ "▁実際", -8.818011283874512 ], [ "▁経験", -8.818628311157227 ], [ "▁50", -8.820055961608887 ], [ "れ", -8.822248458862305 ], [ "▁中央", -8.822585105895996 ], [ "▁言葉", -8.825173377990723 ], [ "▁“", -8.825366973876953 ], [ "▁それぞれ", -8.82688045501709 ], [ "▁電話", -8.827263832092285 ], [ "中", -8.827548027038574 ], [ "して", -8.828661918640137 ], [ "▁使って", -8.829614639282227 ], [ "▁神", -8.830536842346191 ], [ "▁ほか", -8.830570220947266 ], [ "▁バス", -8.832625389099121 ], [ "▁なくて", -8.833061218261719 ], [ "▁台", -8.83446979522705 ], [ "▁見る", -8.835578918457031 ], [ "▁ドイツ", -8.836344718933105 ], [ "ミ", -8.839237213134766 ], [ "ブ", -8.839674949645996 ], [ "こ", -8.8412446975708 ], [ "▁全国", -8.84158992767334 ], [ "▁卒業", -8.842455863952637 ], [ "C", -8.843998908996582 ], [ "▁都市", -8.845402717590332 ], [ "▁2017", -8.845974922180176 ], [ "▁フランス", -8.84687614440918 ], [ "ティ", -8.850074768066406 ], [ "▁全て", -8.850541114807129 ], [ "▁持ち", -8.853889465332031 ], [ "▁不", -8.856542587280273 ], [ "▁た", -8.857137680053711 ], [ "▁対象", -8.85767936706543 ], [ "▁米", -8.859259605407715 ], [ "▁29", -8.8596830368042 ], [ "▁子供", -8.860235214233398 ], [ "グ", -8.860330581665039 ], [ "▁士", -8.86071491241455 ], [ "ん", -8.862131118774414 ], [ "▁無", -8.866154670715332 ], [ "▁リ", -8.866772651672363 ], [ "▁所属", -8.868378639221191 ], [ "▁使い", -8.870195388793945 ], [ "▁取り", -8.870843887329102 ], [ "▁年度", -8.871124267578125 ], [ "▁位置", -8.871943473815918 ], [ "▁初めて", -8.874874114990234 ], [ "▁両", -8.874960899353027 ], [ "▁決定", -8.874967575073242 ], [ "▁枚", -8.87608814239502 ], [ "▁a", -8.87656307220459 ], [ "▁室", -8.878043174743652 ], [ "▁しまった", -8.879465103149414 ], [ "▁対する", -8.8796968460083 ], [ "ガ", -8.879983901977539 ], [ "▁対策", -8.880684852600098 ], [ "▁ス", -8.88209056854248 ], [ "▁事務", -8.882108688354492 ], [ "▁京都", -8.88350772857666 ], [ "▁向け", -8.884930610656738 ], [ "▁歴史", -8.88747501373291 ], [ "▁n", -8.887938499450684 ], [ "ば", -8.889894485473633 ], [ "▁終了", -8.890223503112793 ], [ "▁少し", -8.890716552734375 ], [ "▁結婚", -8.890750885009766 ], [ "▁行った", -8.891594886779785 ], [ "▁共に", -8.891674041748047 ], [ "▁言って", -8.893777847290039 ], [ "▁官", -8.899138450622559 ], [ "▁こちら", -8.899733543395996 ], [ "▁アルバム", -8.89995002746582 ], [ "▁そこ", -8.901435852050781 ], [ "▁政府", -8.901593208312988 ], [ "▁末", -8.90203857421875 ], [ "です", -8.9020414352417 ], [ "※", -8.909258842468262 ], [ "▁事件", -8.91042709350586 ], [ "▁I", -8.911993980407715 ], [ "▁世紀", -8.913631439208984 ], [ "▁ブログ", -8.91435718536377 ], [ "▁程度", -8.914727210998535 ], [ "▁やって", -8.914874076843262 ], [ "▁様々な", -8.915623664855957 ], [ "▁アップ", -8.915779113769531 ], [ "▁声", -8.918355941772461 ], [ "▁量", -8.918611526489258 ], [ "手", -8.918678283691406 ], [ "▁すすめ", -8.91955280303955 ], [ "▁くらい", -8.920440673828125 ], [ "4", -8.92277717590332 ], [ "▁マ", -8.923903465270996 ], [ "生", -8.92421817779541 ], [ "▁新しい", -8.924877166748047 ], [ "▁とても", -8.92615795135498 ], [ "▁メンズ", -8.926523208618164 ], [ "5", -8.926671981811523 ], [ "▁製品", -8.928423881530762 ], [ "オ", -8.9291353225708 ], [ "▁40", -8.936161994934082 ], [ "エ", -8.936803817749023 ], [ "▁旧", -8.93741512298584 ], [ "▁ラ", -8.939011573791504 ], [ "▁採用", -8.939138412475586 ], [ "▁制作", -8.942741394042969 ], [ "▁相手", -8.94318675994873 ], [ "▁海", -8.943862915039062 ], [ "▁入り", -8.945237159729004 ], [ "▁基本", -8.945245742797852 ], [ "▁男性", -8.946459770202637 ], [ "▁正", -8.949076652526855 ], [ "木", -8.952024459838867 ], [ "▁光", -8.953221321105957 ], [ "▁府", -8.954755783081055 ], [ "▁レディース", -8.95525074005127 ], [ "▁戦争", -8.956694602966309 ], [ "▁交換", -8.956847190856934 ], [ "部", -8.956883430480957 ], [ "▁花", -8.95969009399414 ], [ "▁そして", -8.959907531738281 ], [ "▁ひと", -8.96059799194336 ], [ "▁ほとんど", -8.960951805114746 ], [ "名", -8.96130657196045 ], [ "▁す", -8.961348533630371 ], [ "▁種", -8.96137809753418 ], [ "国", -8.962059020996094 ], [ "ご", -8.96352767944336 ], [ "▁特に", -8.964591026306152 ], [ "▁時期", -8.96492862701416 ], [ "▁優勝", -8.965947151184082 ], [ "▁達", -8.96638011932373 ], [ "▁出来", -8.966787338256836 ], [ "▁ネット", -8.967872619628906 ], [ "▁獲得", -8.968684196472168 ], [ "▁くれる", -8.969785690307617 ], [ "▁スポーツ", -8.96992301940918 ], [ "水", -8.96994400024414 ], [ "▁英語", -8.97229290008545 ], [ "マン", -8.97372817993164 ], [ "▁*", -8.973808288574219 ], [ "え", -8.975821495056152 ], [ "▁31", -8.976263999938965 ], [ "▁最も", -8.977171897888184 ], [ "▁面", -8.977803230285645 ], [ "▁科学", -8.978130340576172 ], [ "道", -8.979150772094727 ], [ "▁だろう", -8.979555130004883 ], [ "プ", -8.982287406921387 ], [ "メ", -8.985766410827637 ], [ "&", -8.986623764038086 ], [ "▁種類", -8.991182327270508 ], [ "▁構成", -8.99235725402832 ], [ "▁治療", -8.994498252868652 ], [ "▁特徴", -8.995141983032227 ], [ "現在", -8.997493743896484 ], [ "▁夏", -8.997525215148926 ], [ "長", -8.99767780303955 ], [ "▁あって", -8.999412536621094 ], [ "▁撮影", -9.001693725585938 ], [ "め", -9.001782417297363 ], [ "▁下さい", -9.001877784729004 ], [ "▁運営", -9.002159118652344 ], [ "▁明治", -9.004844665527344 ], [ "▁行い", -9.005451202392578 ], [ "▁大きく", -9.008038520812988 ], [ "A", -9.009247779846191 ], [ "ニ", -9.00928783416748 ], [ "▁政治", -9.009429931640625 ], [ "▁使わ", -9.009900093078613 ], [ "▁派", -9.011679649353027 ], [ "▁みて", -9.013663291931152 ], [ "▁男", -9.014392852783203 ], [ "モ", -9.014814376831055 ], [ "地", -9.015836715698242 ], [ "▁非常に", -9.018579483032227 ], [ "▁イ", -9.019038200378418 ], [ "▁総", -9.019116401672363 ], [ "テ", -9.019116401672363 ], [ "▁営業", -9.02060317993164 ], [ "B", -9.021435737609863 ], [ "▁すれば", -9.021897315979004 ], [ "▁名前", -9.023608207702637 ], [ "▁彼女", -9.024700164794922 ], [ "▁木", -9.02480411529541 ], [ "▁資料", -9.026127815246582 ], [ "▁カ", -9.02718448638916 ], [ "▁集", -9.027509689331055 ], [ "▁朝", -9.02817153930664 ], [ "▁限定", -9.028746604919434 ], [ "▁指定", -9.029034614562988 ], [ "▁配信", -9.029706954956055 ], [ "-", -9.030011177062988 ], [ "▁得", -9.030510902404785 ], [ "物", -9.030889511108398 ], [ "▁作成", -9.031505584716797 ], [ "々", -9.034482955932617 ], [ "▁別", -9.034728050231934 ], [ "▁やすい", -9.037827491760254 ], [ "▁王", -9.038017272949219 ], [ "▁アプリ", -9.038984298706055 ], [ "▁その後", -9.040660858154297 ], [ "▁アニメ", -9.040919303894043 ], [ "ゴ", -9.040971755981445 ], [ "▁00", -9.041352272033691 ], [ "▁誰", -9.041996002197266 ], [ "T", -9.043283462524414 ], [ "▁図書", -9.043764114379883 ], [ "▁経営", -9.043965339660645 ], [ "▁選挙", -9.044739723205566 ], [ "▁2016", -9.045928955078125 ], [ "▁建設", -9.047667503356934 ], [ "▁理解", -9.050714492797852 ], [ "▁最", -9.051375389099121 ], [ "▁家族", -9.052094459533691 ], [ "スト", -9.054061889648438 ], [ "▁主義", -9.054505348205566 ], [ "▁公式", -9.05477237701416 ], [ "▁メンバー", -9.055183410644531 ], [ "▁風", -9.055192947387695 ], [ "▁しよう", -9.055488586425781 ], [ "っ", -9.055549621582031 ], [ "▁医療", -9.05712890625 ], [ "▁製造", -9.058061599731445 ], [ "▁運動", -9.059392929077148 ], [ "▁生産", -9.059691429138184 ], [ "▁隊", -9.062596321105957 ], [ "▁高校", -9.062877655029297 ], [ "18", -9.063485145568848 ], [ "▁現", -9.064838409423828 ], [ "d", -9.065092086791992 ], [ "▁美", -9.066801071166992 ], [ "▁設立", -9.066949844360352 ], [ "▁人物", -9.067262649536133 ], [ "er", -9.068185806274414 ], [ "▁口", -9.068781852722168 ], [ "▁体験", -9.07010269165039 ], [ "▁どこ", -9.070695877075195 ], [ "▁連絡", -9.070826530456543 ], [ "▁頭", -9.072442054748535 ], [ "出", -9.075255393981934 ], [ "▁イギリス", -9.076701164245605 ], [ "や", -9.076745986938477 ], [ "▁女子", -9.078083992004395 ], [ "▁出", -9.08231258392334 ], [ "▁X", -9.0828857421875 ], [ "▁城", -9.085943222045898 ], [ "▁オ", -9.086359977722168 ], [ "▁ファイル", -9.087174415588379 ], [ "▁注意", -9.087627410888672 ], [ "▁石", -9.087696075439453 ], [ "▁顔", -9.089442253112793 ], [ "▁重", -9.089753150939941 ], [ "y", -9.08979320526123 ], [ "▁セット", -9.092418670654297 ], [ "▁教授", -9.093478202819824 ], [ "▁保護", -9.093779563903809 ], [ "▁師", -9.094802856445312 ], [ "▁ドラマ", -9.095076560974121 ], [ "今回", -9.095758438110352 ], [ "▁真", -9.09897232055664 ], [ "▁組織", -9.100777626037598 ], [ "ウ", -9.100875854492188 ], [ "さらに", -9.101319313049316 ], [ "▁変化", -9.102591514587402 ], [ "▁土", -9.10279369354248 ], [ "▁音", -9.105758666992188 ], [ "▁作り", -9.105948448181152 ], [ "▁愛", -9.107446670532227 ], [ "▁したり", -9.107731819152832 ], [ "ディ", -9.108332633972168 ], [ "▁病院", -9.111042022705078 ], [ "今", -9.111181259155273 ], [ "井", -9.111963272094727 ], [ "▁条件", -9.112398147583008 ], [ "▁公", -9.115428924560547 ], [ "デ", -9.117883682250977 ], [ "町", -9.118229866027832 ], [ "▁非", -9.118371963500977 ], [ "▁展開", -9.119117736816406 ], [ "▁スーパー", -9.11915111541748 ], [ "▁全体", -9.122492790222168 ], [ "▁作業", -9.12357234954834 ], [ "▁気持ち", -9.123845100402832 ], [ "ビ", -9.124731063842773 ], [ "が", -9.124900817871094 ], [ "▁攻撃", -9.127103805541992 ], [ "▁受けて", -9.133204460144043 ], [ "▁クラブ", -9.134439468383789 ], [ "▁画像", -9.134771347045898 ], [ "▁例", -9.137020111083984 ], [ "▁更新", -9.137078285217285 ], [ "ット", -9.138519287109375 ], [ "▁料理", -9.138614654541016 ], [ "▁成功", -9.139466285705566 ], [ "▁行く", -9.143403053283691 ], [ "▁労働", -9.143484115600586 ], [ "▁込み", -9.143580436706543 ], [ "▁健康", -9.143829345703125 ], [ "▁勝", -9.144928932189941 ], [ "▁cm", -9.144949913024902 ], [ "▁ブランド", -9.145341873168945 ], [ "▁指導", -9.146349906921387 ], [ "▁d", -9.148186683654785 ], [ "▁含む", -9.149499893188477 ], [ "▁活躍", -9.15026569366455 ], [ "▁白", -9.15099048614502 ], [ "▁報告", -9.151220321655273 ], [ "▁まだ", -9.151993751525879 ], [ "▁条", -9.153310775756836 ], [ "▁四", -9.15618896484375 ], [ "▁O", -9.159293174743652 ], [ "▁御", -9.159703254699707 ], [ "N", -9.160587310791016 ], [ "▁福岡", -9.162853240966797 ], [ "日", -9.163949966430664 ], [ "▁副", -9.16545295715332 ], [ "つ", -9.16608715057373 ], [ "▁通信", -9.167651176452637 ], [ "▁まま", -9.168943405151367 ], [ "▁エ", -9.169392585754395 ], [ "▁2015", -9.17041015625 ], [ "▁行動", -9.170483589172363 ], [ "▁ファン", -9.170968055725098 ], [ "▁まして", -9.171527862548828 ], [ "P", -9.171833038330078 ], [ "▁地区", -9.17293930053711 ], [ "▁足", -9.173116683959961 ], [ "▁今回", -9.173301696777344 ], [ "▁せた", -9.174955368041992 ], [ "ち", -9.175488471984863 ], [ "▁総合", -9.176103591918945 ], [ "▁最終", -9.176559448242188 ], [ "▁予約", -9.17666244506836 ], [ "▁夜", -9.178196907043457 ], [ "▁そうです", -9.179055213928223 ], [ "▁必要な", -9.17908763885498 ], [ "M", -9.179522514343262 ], [ "▁含ま", -9.179593086242676 ], [ "よう", -9.18042278289795 ], [ "▁姿", -9.180671691894531 ], [ "▁構造", -9.181654930114746 ], [ "▁主", -9.18191909790039 ], [ "した", -9.182449340820312 ], [ "▁導入", -9.184164047241211 ], [ "▁受けた", -9.184760093688965 ], [ "▁記念", -9.18513011932373 ], [ "▁JR", -9.185484886169434 ], [ "▁原因", -9.18769645690918 ], [ "▁入って", -9.19151496887207 ], [ "▁時点", -9.191828727722168 ], [ "▁タイプ", -9.192943572998047 ], [ "▁院", -9.193382263183594 ], [ ")", -9.194123268127441 ], [ "▁女", -9.195418357849121 ], [ "▁きて", -9.195441246032715 ], [ "▁規模", -9.1978759765625 ], [ "▁着", -9.19864273071289 ], [ "e", -9.199080467224121 ], [ "行", -9.199302673339844 ], [ "▁べき", -9.200319290161133 ], [ "▁ようです", -9.200587272644043 ], [ "▁当", -9.201760292053223 ], [ "▁街", -9.20196533203125 ], [ "元", -9.20197582244873 ], [ "▁違い", -9.20256519317627 ], [ "▁デビュー", -9.204366683959961 ], [ "▁保険", -9.204750061035156 ], [ "前", -9.205061912536621 ], [ "▁市場", -9.205208778381348 ], [ "である", -9.206151962280273 ], [ "▁km", -9.20639419555664 ], [ "億", -9.206521987915039 ], [ "▁くれ", -9.206831932067871 ], [ "▁高等", -9.209390640258789 ], [ "▁希望", -9.210258483886719 ], [ "▁歌", -9.213333129882812 ], [ "見", -9.213459014892578 ], [ "▁c", -9.213567733764648 ], [ "▁追加", -9.215818405151367 ], [ "▁法人", -9.215978622436523 ], [ "▁制度", -9.216033935546875 ], [ "下", -9.216073036193848 ], [ "ッ", -9.21664047241211 ], [ "▁一緒に", -9.216708183288574 ], [ "▁製", -9.217292785644531 ], [ "ハ", -9.217378616333008 ], [ "▁発見", -9.21766185760498 ], [ "▁屋", -9.219771385192871 ], [ "▁使う", -9.219876289367676 ], [ "城", -9.21996021270752 ], [ "▁制", -9.220797538757324 ], [ "▁表現", -9.221220970153809 ], [ "▁新聞", -9.22142505645752 ], [ "口", -9.222566604614258 ], [ "▁b", -9.222960472106934 ], [ "▁以前", -9.22360897064209 ], [ "▁取得", -9.22455883026123 ], [ "▁みる", -9.225639343261719 ], [ "▁文", -9.226131439208984 ], [ "▁海外", -9.226415634155273 ], [ "谷", -9.227185249328613 ], [ "▁検索", -9.228116989135742 ], [ "▁為", -9.228227615356445 ], [ "▁議員", -9.230749130249023 ], [ "そこ", -9.231156349182129 ], [ "ケ", -9.23121452331543 ], [ "▁U", -9.23220157623291 ], [ "▁周辺", -9.23300552368164 ], [ "▁デ", -9.233233451843262 ], [ "▁船", -9.233329772949219 ], [ "▁航空", -9.234086990356445 ], [ "▁ちゃん", -9.23486042022705 ], [ "▁業務", -9.235803604125977 ], [ "▁シ", -9.236047744750977 ], [ "▁特別", -9.237005233764648 ], [ "▁設計", -9.238448143005371 ], [ "▁近く", -9.238696098327637 ], [ "▁ホテル", -9.238882064819336 ], [ "10", -9.240896224975586 ], [ "▁超", -9.241581916809082 ], [ "▁�", -9.241652488708496 ], [ "彼", -9.242069244384766 ], [ "▁安全", -9.243001937866211 ], [ "▁肌", -9.243254661560059 ], [ "▁じゃ", -9.243271827697754 ], [ "▁症", -9.24455451965332 ], [ "▁かなり", -9.244672775268555 ], [ "▁企画", -9.244804382324219 ], [ "▁通常", -9.246257781982422 ], [ "け", -9.246397972106934 ], [ "2021", -9.247505187988281 ], [ "▁出来る", -9.24807071685791 ], [ "む", -9.252583503723145 ], [ "▁ハ", -9.253299713134766 ], [ "▁協会", -9.253326416015625 ], [ "▁北海道", -9.254931449890137 ], [ "▁収録", -9.25529670715332 ], [ "▁異なる", -9.257509231567383 ], [ "F", -9.257669448852539 ], [ "▁出版", -9.258552551269531 ], [ "▁リリース", -9.260335922241211 ], [ "ただし", -9.260514259338379 ], [ "ここ", -9.262494087219238 ], [ "▁番号", -9.2626953125 ], [ "▁多数", -9.263348579406738 ], [ "▁一番", -9.263473510742188 ], [ "▁マン", -9.264753341674805 ], [ "村", -9.26491641998291 ], [ "んで", -9.265108108520508 ], [ "▁文字", -9.265402793884277 ], [ "▁黒", -9.266048431396484 ], [ "▁野球", -9.26607894897461 ], [ "ボ", -9.26612377166748 ], [ "▁僕", -9.2669095993042 ], [ "パ", -9.267450332641602 ], [ "▁会員", -9.268240928649902 ], [ "ソン", -9.26855182647705 ], [ "▁娘", -9.269498825073242 ], [ "▁五", -9.269698143005371 ], [ "文", -9.269699096679688 ], [ "▁漫画", -9.26992130279541 ], [ "▁就任", -9.271803855895996 ], [ "▁電子", -9.272126197814941 ], [ "▁コ", -9.272369384765625 ], [ "▁なし", -9.272653579711914 ], [ "▁旅行", -9.273746490478516 ], [ "▁受賞", -9.273773193359375 ], [ "屋", -9.274279594421387 ], [ "▁ニュース", -9.274382591247559 ], [ "体", -9.274412155151367 ], [ "線", -9.2747220993042 ], [ "▁イメージ", -9.274956703186035 ], [ "東", -9.277099609375 ], [ "▁ライブ", -9.277220726013184 ], [ "▁サポート", -9.277392387390137 ], [ "▁編集", -9.277999877929688 ], [ "ター", -9.279101371765137 ], [ "▁本当に", -9.279361724853516 ], [ "▁ベスト", -9.279541015625 ], [ "▁交通", -9.280054092407227 ], [ "▁自然", -9.280261993408203 ], [ "▁強い", -9.28046989440918 ], [ "▁コース", -9.281259536743164 ], [ "▁先生", -9.283159255981445 ], [ "そんな", -9.28353500366211 ], [ "▁あまり", -9.283734321594238 ], [ "▁名古屋", -9.284381866455078 ], [ "▁身", -9.28449821472168 ], [ "▁言い", -9.286309242248535 ], [ "高", -9.286609649658203 ], [ "平", -9.286819458007812 ], [ "▁レ", -9.287382125854492 ], [ "▁個", -9.28786563873291 ], [ "D", -9.288992881774902 ], [ "▁組", -9.289549827575684 ], [ "▁シングル", -9.291394233703613 ], [ "▁コメント", -9.291762351989746 ], [ "▁オンライン", -9.292954444885254 ], [ "そう", -9.293118476867676 ], [ "▁人々", -9.293205261230469 ], [ "▁韓国", -9.294440269470215 ], [ "でも", -9.294541358947754 ], [ "▁団体", -9.296419143676758 ], [ "6", -9.298202514648438 ], [ "▁資格", -9.2990140914917 ], [ "じ", -9.299260139465332 ], [ "▁サ", -9.299567222595215 ], [ "▁そんな", -9.299649238586426 ], [ "▁ザ", -9.299967765808105 ], [ "▁和", -9.299976348876953 ], [ "は", -9.301652908325195 ], [ "ラー", -9.301904678344727 ], [ "▁com", -9.302630424499512 ], [ "ヤ", -9.303455352783203 ], [ "▁成長", -9.303817749023438 ], [ "▁わけで", -9.304032325744629 ], [ "▁こ", -9.304119110107422 ], [ "▁責任", -9.304121017456055 ], [ "▁思わ", -9.304970741271973 ], [ "▁ソフト", -9.306215286254883 ], [ "神", -9.30634880065918 ], [ "▁会議", -9.306825637817383 ], [ "家", -9.307953834533691 ], [ "▁人口", -9.308146476745605 ], [ "▁能力", -9.309096336364746 ], [ "▁判断", -9.309202194213867 ], [ "▁ホーム", -9.310203552246094 ], [ "▁勉強", -9.311351776123047 ], [ "▁ビジネス", -9.311540603637695 ], [ "▁考える", -9.311595916748047 ], [ "▁トップ", -9.312015533447266 ], [ "▁料", -9.312338829040527 ], [ "▁準備", -9.314523696899414 ], [ "れば", -9.315176010131836 ], [ "寺", -9.316790580749512 ], [ "▁サッカー", -9.317944526672363 ], [ "気", -9.318658828735352 ], [ "▁実現", -9.318757057189941 ], [ "W", -9.31984806060791 ], [ "▁なんて", -9.320591926574707 ], [ "▁件", -9.32198715209961 ], [ "▁行き", -9.322080612182617 ], [ "▁器", -9.322379112243652 ], [ "▁キャラクター", -9.322637557983398 ], [ "▁関して", -9.32327938079834 ], [ "▁食", -9.32381534576416 ], [ "▁今日", -9.324040412902832 ], [ "▁学生", -9.324373245239258 ], [ "▁ド", -9.324833869934082 ], [ "▁参考", -9.325016021728516 ], [ "▁多", -9.325098991394043 ], [ "▁自動車", -9.325185775756836 ], [ "▁墓", -9.32519817352295 ], [ "▁求人", -9.326072692871094 ], [ "▁Z", -9.326098442077637 ], [ "▁メーカー", -9.326233863830566 ], [ "▁父", -9.330007553100586 ], [ "▁()", -9.330891609191895 ], [ "▁ケース", -9.33159065246582 ], [ "▁イン", -9.331598281860352 ], [ "▁通販", -9.332088470458984 ], [ "▁2014", -9.332161903381348 ], [ "▁子ども", -9.33288860321045 ], [ "G", -9.332911491394043 ], [ "▁活用", -9.333234786987305 ], [ "三", -9.33359146118164 ], [ "▁the", -9.334244728088379 ], [ "▁比較", -9.335680961608887 ], [ "▁表", -9.336296081542969 ], [ "▁期待", -9.337158203125 ], [ "▁移動", -9.33895206451416 ], [ "▁→", -9.339325904846191 ], [ "▁階", -9.339338302612305 ], [ "▁群", -9.339805603027344 ], [ "▁路線", -9.342694282531738 ], [ "せ", -9.342820167541504 ], [ "i", -9.3432035446167 ], [ "m", -9.343751907348633 ], [ "▁過去", -9.345674514770508 ], [ "▁道路", -9.345782279968262 ], [ "▁天", -9.345999717712402 ], [ "▁ユーザー", -9.346074104309082 ], [ "▁パ", -9.346729278564453 ], [ "▁リンク", -9.346750259399414 ], [ "ニー", -9.347302436828613 ], [ "場", -9.348091125488281 ], [ "イン", -9.349610328674316 ], [ "▁産業", -9.34961223602295 ], [ "▁公園", -9.350358009338379 ], [ "▁of", -9.35049819946289 ], [ "▁艦", -9.35092544555664 ], [ "▁部屋", -9.351593971252441 ], [ "▁無い", -9.352498054504395 ], [ "▁ケア", -9.352527618408203 ], [ "も", -9.35389518737793 ], [ "▁f", -9.354039192199707 ], [ "▁馬", -9.354095458984375 ], [ "▁スタッフ", -9.354593276977539 ], [ "▁観光", -9.355403900146484 ], [ "ing", -9.35704231262207 ], [ "▁質問", -9.358871459960938 ], [ "▁来", -9.358973503112793 ], [ "▁協力", -9.35923957824707 ], [ "▁60", -9.361331939697266 ], [ "7", -9.362516403198242 ], [ "▁♪", -9.363122940063477 ], [ "▁広島", -9.36314582824707 ], [ "▁経て", -9.363752365112305 ], [ "▁感染", -9.363971710205078 ], [ "▁テーマ", -9.364903450012207 ], [ "▁ほう", -9.364947319030762 ], [ "▁チェック", -9.36578369140625 ], [ "▁バ", -9.365982055664062 ], [ "▁車両", -9.366619110107422 ], [ "9", -9.367532730102539 ], [ "石", -9.368204116821289 ], [ "ザ", -9.368927955627441 ], [ "▁付き", -9.371187210083008 ], [ "セ", -9.373030662536621 ], [ "▁校", -9.373055458068848 ], [ "▁投稿", -9.37372875213623 ], [ "▁薬", -9.37485408782959 ], [ "▁値", -9.375889778137207 ], [ "▁改善", -9.376399040222168 ], [ "ワ", -9.376717567443848 ], [ "▁×", -9.377214431762695 ], [ "▁ロシア", -9.378369331359863 ], [ "▁問い合わせ", -9.37960147857666 ], [ "▁複数", -9.38010311126709 ], [ "▁ル", -9.380753517150879 ], [ "8", -9.381237030029297 ], [ "▁つつ", -9.381832122802734 ], [ "▁書き", -9.38192081451416 ], [ "▁連続", -9.38298511505127 ], [ "▁ロ", -9.383502006530762 ], [ "t", -9.383524894714355 ], [ "▁安心", -9.38575553894043 ], [ "▁住宅", -9.385836601257324 ], [ "▁工事", -9.387067794799805 ], [ "▁しっかり", -9.387956619262695 ], [ "▁銀行", -9.38825511932373 ], [ "X", -9.38895320892334 ], [ "▁投資", -9.388998031616211 ], [ "▁団", -9.3902006149292 ], [ "年", -9.391294479370117 ], [ "▁最大", -9.391712188720703 ], [ "▁読み", -9.391824722290039 ], [ "▁タイトル", -9.392391204833984 ], [ "▁順", -9.392569541931152 ], [ "南", -9.393961906433105 ], [ "▁製作", -9.394343376159668 ], [ "▁共同", -9.394356727600098 ], [ "▁限り", -9.395885467529297 ], [ "▁独立", -9.39594841003418 ], [ "リン", -9.396120071411133 ], [ "後", -9.39727783203125 ], [ "o", -9.39801025390625 ], [ "▁編", -9.398014068603516 ], [ "▁千葉", -9.39820384979248 ], [ "▁障害", -9.398338317871094 ], [ "▁建築", -9.398677825927734 ], [ "▁事故", -9.39880084991455 ], [ "▁のでしょう", -9.399885177612305 ], [ "▁搭載", -9.400341987609863 ], [ "美", -9.402174949645996 ], [ "▁英", -9.40234375 ], [ "H", -9.402477264404297 ], [ "▁出し", -9.40247917175293 ], [ "▁意識", -9.404303550720215 ], [ "▁勝利", -9.4048490524292 ], [ "▁教会", -9.405133247375488 ], [ "▁スタイル", -9.405447006225586 ], [ "▁沖縄", -9.40587043762207 ], [ "▁ありがとう", -9.405903816223145 ], [ "当", -9.408068656921387 ], [ "ラン", -9.409001350402832 ], [ "▁知識", -9.409638404846191 ], [ "▁横浜", -9.41016674041748 ], [ "▁解説", -9.411023139953613 ], [ "▁処理", -9.412740707397461 ], [ "▁春", -9.412944793701172 ], [ "西", -9.413432121276855 ], [ "▁用品", -9.413619041442871 ], [ "▁対し", -9.414392471313477 ], [ "▁ヶ月", -9.414427757263184 ], [ "▁小説", -9.414546966552734 ], [ "間", -9.415239334106445 ], [ "明", -9.416259765625 ], [ "▁学習", -9.41641616821289 ], [ "▁特定", -9.418209075927734 ], [ "▁拡大", -9.418992042541504 ], [ "新", -9.419384002685547 ], [ "▁コピー", -9.419872283935547 ], [ "▁料金", -9.42001724243164 ], [ "n", -9.42054557800293 ], [ "▁映像", -9.421137809753418 ], [ "▁はじめ", -9.421208381652832 ], [ "▁ハイ", -9.421246528625488 ], [ "▁ちょっと", -9.422504425048828 ], [ "シュ", -9.422616004943848 ], [ "二", -9.42300033569336 ], [ "▁ランキング", -9.423296928405762 ], [ "▁半", -9.423851013183594 ], [ "ナー", -9.425897598266602 ], [ "▁一覧", -9.426948547363281 ], [ "▁用意", -9.42745304107666 ], [ "▁バー", -9.428853988647461 ], [ "ed", -9.429615020751953 ], [ "▁解決", -9.430933952331543 ], [ "▁ドル", -9.43111515045166 ], [ "▁国民", -9.432129859924316 ], [ "▁重要な", -9.433015823364258 ], [ "▁あるいは", -9.434124946594238 ], [ "シー", -9.434366226196289 ], [ "▁図", -9.436952590942383 ], [ "▁未", -9.437867164611816 ], [ "▁r", -9.438223838806152 ], [ "▁雑誌", -9.438427925109863 ], [ "一方", -9.439248085021973 ], [ "K", -9.44058609008789 ], [ "ぎ", -9.440693855285645 ], [ "北", -9.441510200500488 ], [ "▁業者", -9.441813468933105 ], [ "リング", -9.442044258117676 ], [ "沢", -9.442882537841797 ], [ "▁サン", -9.44360637664795 ], [ "▁赤", -9.443902969360352 ], [ "▁レベル", -9.445023536682129 ], [ "▁mm", -9.445548057556152 ], [ "▁たく", -9.445730209350586 ], [ "ただ", -9.446294784545898 ], [ "▁できた", -9.4472074508667 ], [ "▁メディア", -9.447236061096191 ], [ "▁検討", -9.447441101074219 ], [ "▁対", -9.448473930358887 ], [ "▁2013", -9.44878101348877 ], [ "和", -9.45008659362793 ], [ "分", -9.450340270996094 ], [ "▁動物", -9.450708389282227 ], [ "▁知って", -9.451830863952637 ], [ "▁行為", -9.451929092407227 ], [ "▁夢", -9.453449249267578 ], [ "▁イタリア", -9.453960418701172 ], [ "バー", -9.455389022827148 ], [ "▁自由", -9.455850601196289 ], [ "▁自動", -9.457510948181152 ], [ "▁差", -9.457862854003906 ], [ "▁2012", -9.45846176147461 ], [ "▁2010", -9.458578109741211 ], [ "J", -9.459874153137207 ], [ "▁整備", -9.459887504577637 ], [ "▁生まれ", -9.46230411529541 ], [ "▁右", -9.462410926818848 ], [ "▁類", -9.463279724121094 ], [ "▁受ける", -9.463479995727539 ], [ "▁死", -9.463546752929688 ], [ "▁タイム", -9.464022636413574 ], [ "▁フリー", -9.464925765991211 ], [ "▁病", -9.465112686157227 ], [ "▁食べ", -9.465895652770996 ], [ "▁母", -9.465903282165527 ], [ "▁う", -9.467890739440918 ], [ "▁務めた", -9.468490600585938 ], [ "カー", -9.468583106994629 ], [ "宮", -9.469171524047852 ], [ "東京", -9.46926212310791 ], [ "法", -9.470210075378418 ], [ "▁可能な", -9.470429420471191 ], [ "業", -9.470484733581543 ], [ "▁分野", -9.470573425292969 ], [ "海", -9.470776557922363 ], [ "▁}", -9.471302032470703 ], [ "▁アン", -9.471388816833496 ], [ "▁帝国", -9.471497535705566 ], [ "▁機会", -9.471721649169922 ], [ "ろ", -9.472212791442871 ], [ "▁少ない", -9.473608016967773 ], [ "▁当社", -9.473608016967773 ], [ "▁高く", -9.474270820617676 ], [ "▁h", -9.47463607788086 ], [ "▁バンド", -9.474656105041504 ], [ "▁安い", -9.475422859191895 ], [ "▁形式", -9.475589752197266 ], [ "▁週間", -9.475929260253906 ], [ "▁人生", -9.477104187011719 ], [ "▁巻", -9.47712516784668 ], [ "2020", -9.477127075195312 ], [ "▁直接", -9.478097915649414 ], [ "r", -9.479289054870605 ], [ "▁左", -9.480286598205566 ], [ "▁電気", -9.481183052062988 ], [ "▁運転", -9.481222152709961 ], [ "▁つき", -9.48134994506836 ], [ "▁エンジン", -9.48141860961914 ], [ "▁ほぼ", -9.481551170349121 ], [ "▁アクセス", -9.4818754196167 ], [ "津", -9.483699798583984 ], [ "▁意見", -9.48398494720459 ], [ "▁記載", -9.484000205993652 ], [ "▁小学校", -9.484484672546387 ], [ "▁続けて", -9.484630584716797 ], [ "▁戦い", -9.48544692993164 ], [ "▁2011", -9.485678672790527 ], [ "▁用い", -9.485682487487793 ], [ "▁ごと", -9.48638916015625 ], [ "いて", -9.486419677734375 ], [ "▁完成", -9.486493110656738 ], [ "▁党", -9.486852645874023 ], [ "▁アジア", -9.487319946289062 ], [ "▁読む", -9.487568855285645 ], [ "▁物語", -9.487771034240723 ], [ "V", -9.489133834838867 ], [ "▁出会い", -9.489445686340332 ], [ "▁妻", -9.489628791809082 ], [ "▁01", -9.490052223205566 ], [ "方", -9.49027156829834 ], [ "▁CD", -9.490358352661133 ], [ "▁出す", -9.491087913513184 ], [ "▁アル", -9.491666793823242 ], [ "心", -9.492132186889648 ], [ "▁書いて", -9.492695808410645 ], [ "成", -9.49307918548584 ], [ "月", -9.493154525756836 ], [ "▁祭", -9.49343490600586 ], [ "▁☆", -9.49350357055664 ], [ "▁i", -9.494024276733398 ], [ "▁犬", -9.494359016418457 ], [ "▁取引", -9.495224952697754 ], [ "▁オープン", -9.49642562866211 ], [ "数", -9.49742603302002 ], [ "▁参照", -9.498104095458984 ], [ "合", -9.4982271194458 ], [ "自分", -9.499279022216797 ], [ "2018", -9.50013542175293 ], [ "トン", -9.50101375579834 ], [ "▁のに", -9.501072883605957 ], [ "他", -9.501118659973145 ], [ "▁国家", -9.502655982971191 ], [ "▁当初", -9.503294944763184 ], [ "▁ライン", -9.503850936889648 ], [ "▁毎日", -9.506052017211914 ], [ "▁思った", -9.506908416748047 ], [ "▁カー", -9.507786750793457 ], [ "▁森", -9.508200645446777 ], [ "▁もと", -9.508383750915527 ], [ "▁入る", -9.508698463439941 ], [ "▁名称", -9.509425163269043 ], [ "光", -9.51026725769043 ], [ "▁2000", -9.510726928710938 ], [ "▁ト", -9.510757446289062 ], [ "▁価値", -9.513932228088379 ], [ "笑", -9.51417350769043 ], [ "▁クラス", -9.514516830444336 ], [ "▁親", -9.514839172363281 ], [ "▁裁判", -9.514862060546875 ], [ "あ", -9.515724182128906 ], [ "ソ", -9.517373085021973 ], [ "▁低", -9.517895698547363 ], [ "▁始め", -9.518587112426758 ], [ "▁こそ", -9.518930435180664 ], [ "▁横", -9.519418716430664 ], [ "▁火", -9.519538879394531 ], [ "▁消費", -9.520931243896484 ], [ "▁最高", -9.521056175231934 ], [ "金", -9.521402359008789 ], [ "▁in", -9.521543502807617 ], [ "作", -9.522407531738281 ], [ "ポ", -9.523314476013184 ], [ "▁もっと", -9.523504257202148 ], [ "▁発行", -9.524192810058594 ], [ "▁2008", -9.52478313446045 ], [ "▁平", -9.525030136108398 ], [ "2019", -9.525612831115723 ], [ "▁違う", -9.52612018585205 ], [ "▁法律", -9.526598930358887 ], [ "▁PC", -9.52802562713623 ], [ "▁費", -9.529511451721191 ], [ "▁頂き", -9.529890060424805 ], [ "▁以来", -9.530716896057129 ], [ "▁距離", -9.53075885772705 ], [ "▁自ら", -9.531386375427246 ], [ "▁セ", -9.531927108764648 ], [ "▁警察", -9.53288745880127 ], [ "▁注文", -9.533001899719238 ], [ "11", -9.53311824798584 ], [ "び", -9.53392219543457 ], [ "▁プロジェクト", -9.535248756408691 ], [ "▁実", -9.53531265258789 ], [ "▁論", -9.535385131835938 ], [ "色", -9.536195755004883 ], [ "▁再び", -9.536675453186035 ], [ "▁り", -9.538570404052734 ], [ "▁スタート", -9.53873348236084 ], [ "▁次の", -9.540648460388184 ], [ "▁列車", -9.54100227355957 ], [ "▁最初の", -9.541119575500488 ], [ "▁舞台", -9.541543006896973 ], [ "▁同時に", -9.542962074279785 ], [ "▁提案", -9.543651580810547 ], [ "▁カメラ", -9.544417381286621 ], [ "▁学科", -9.544586181640625 ], [ "内", -9.544921875 ], [ "▁移籍", -9.545239448547363 ], [ "小", -9.54537296295166 ], [ "▁主張", -9.545921325683594 ], [ "▁運用", -9.54607105255127 ], [ "▁好きな", -9.546079635620117 ], [ "▁美術", -9.546207427978516 ], [ "▁x", -9.547850608825684 ], [ "▁酒", -9.54820442199707 ], [ "面", -9.5487642288208 ], [ "▁バック", -9.54921817779541 ], [ "▁部隊", -9.549718856811523 ], [ "ベ", -9.550029754638672 ], [ "▁発展", -9.550298690795898 ], [ "▁業", -9.55122184753418 ], [ "▁コン", -9.551568984985352 ], [ "▁やり", -9.552742958068848 ], [ "▁寺", -9.552799224853516 ], [ "▁機器", -9.552807807922363 ], [ "▁精神", -9.55307388305664 ], [ "f", -9.553844451904297 ], [ "▁注目", -9.55441951751709 ], [ "▁作る", -9.5545654296875 ], [ "▁中学校", -9.556949615478516 ], [ "▁認め", -9.558013916015625 ], [ "▁アメリカ合衆国", -9.558270454406738 ], [ "▁来て", -9.55937671661377 ], [ "▁ショップ", -9.55941104888916 ], [ "▁上げ", -9.559475898742676 ], [ "だった", -9.56167221069336 ], [ "歴史", -9.56221866607666 ], [ "▁ヒ", -9.56369686126709 ], [ "▁与え", -9.563873291015625 ], [ "ック", -9.563902854919434 ], [ "▁今後", -9.564408302307129 ], [ "▁200", -9.56572151184082 ], [ "▁質", -9.566338539123535 ], [ "▁依頼", -9.566380500793457 ], [ "▁向上", -9.566720962524414 ], [ "特に", -9.567098617553711 ], [ "▁カラー", -9.567414283752441 ], [ "▁合わせて", -9.568808555603027 ], [ "▁分類", -9.570124626159668 ], [ "▁秋", -9.570438385009766 ], [ "▁誌", -9.570775985717773 ], [ "▁直", -9.570780754089355 ], [ "12", -9.57093334197998 ], [ "▁宇宙", -9.571798324584961 ], [ "▁被害", -9.571805000305176 ], [ "▁どんな", -9.572442054748535 ], [ "リア", -9.572772026062012 ], [ "▁強", -9.573660850524902 ], [ "州", -9.574323654174805 ], [ "▁て", -9.574640274047852 ], [ "ヒ", -9.575005531311035 ], [ "▁jp", -9.575252532958984 ], [ "L", -9.575294494628906 ], [ "▁外国", -9.575777053833008 ], [ "▁丁目", -9.576635360717773 ], [ "▁主に", -9.576715469360352 ], [ "▁演奏", -9.576881408691406 ], [ "▁事実", -9.577272415161133 ], [ "▁全く", -9.578547477722168 ], [ "▁社長", -9.578615188598633 ], [ "▁八", -9.578829765319824 ], [ "▁インターネット", -9.579245567321777 ], [ "▁額", -9.58054256439209 ], [ "▁プログラム", -9.580703735351562 ], [ "▁いただく", -9.581104278564453 ], [ "▁基準", -9.581377029418945 ], [ "▁激安", -9.581548690795898 ], [ "▁時計", -9.581574440002441 ], [ "▁致し", -9.581586837768555 ], [ "▁Y", -9.581597328186035 ], [ "▁そのまま", -9.582375526428223 ], [ "▁星", -9.582686424255371 ], [ "▁神奈川", -9.58421802520752 ], [ "▁付け", -9.5842866897583 ], [ "▁君", -9.585280418395996 ], [ "▁不動産", -9.585945129394531 ], [ "▁かけ", -9.586511611938477 ], [ "▁平均", -9.586960792541504 ], [ "▁w", -9.588797569274902 ], [ "▁自", -9.588831901550293 ], [ "▁2009", -9.58891487121582 ], [ "▁海軍", -9.590478897094727 ], [ "▁合格", -9.590788841247559 ], [ "▁ナ", -9.59128475189209 ], [ "▁発", -9.592584609985352 ], [ "▁講座", -9.593376159667969 ], [ "▁倍", -9.593652725219727 ], [ "▁可能です", -9.595505714416504 ], [ "崎", -9.596192359924316 ], [ "▁おく", -9.596297264099121 ], [ "▁したら", -9.596911430358887 ], [ "ゲ", -9.597065925598145 ], [ "▁ぶり", -9.597792625427246 ], [ "▁検査", -9.598159790039062 ], [ "▁空港", -9.598851203918457 ], [ "▁流れ", -9.598994255065918 ], [ "▁言語", -9.599040985107422 ], [ "▁増加", -9.600330352783203 ], [ "▁画面", -9.600757598876953 ], [ "▁専用", -9.603381156921387 ], [ "▁一方", -9.603599548339844 ], [ "ダー", -9.604021072387695 ], [ "2017", -9.604887008666992 ], [ "正", -9.605152130126953 ], [ "天", -9.605157852172852 ], [ "▁ラジオ", -9.605345726013184 ], [ "▁ダ", -9.605449676513672 ], [ "実", -9.606003761291504 ], [ "▁タ", -9.60621452331543 ], [ "▁患者", -9.606232643127441 ], [ "▁由来", -9.606623649597168 ], [ "▁保存", -9.607559204101562 ], [ "▁費用", -9.607613563537598 ], [ "▁練習", -9.608406066894531 ], [ "▁アイテム", -9.608723640441895 ], [ "▁税", -9.609282493591309 ], [ "▁神社", -9.610843658447266 ], [ "▁あ", -9.610894203186035 ], [ "▁魅力", -9.611655235290527 ], [ "▁学部", -9.612127304077148 ], [ "▁説", -9.612334251403809 ], [ "▁自己", -9.613668441772461 ], [ "▁よい", -9.615653038024902 ], [ "▁http", -9.616293907165527 ], [ "▁家庭", -9.616541862487793 ], [ "学", -9.616560935974121 ], [ "▁橋", -9.617445945739746 ], [ "▁Windows", -9.61917495727539 ], [ "▁空間", -9.620125770568848 ], [ "▁古", -9.620543479919434 ], [ "▁現代", -9.62078857421875 ], [ "▁工場", -9.621721267700195 ], [ "▁始めた", -9.62185287475586 ], [ "▁アイ", -9.62236499786377 ], [ "▁方向", -9.622393608093262 ], [ "▁おき", -9.622454643249512 ], [ "▁35", -9.623419761657715 ], [ "▁基", -9.623420715332031 ], [ "▁裏", -9.624092102050781 ], [ "▁自治", -9.624153137207031 ], [ "▁旅", -9.624281883239746 ], [ "▁連合", -9.625401496887207 ], [ "▁清", -9.625802040100098 ], [ "▁広告", -9.62588882446289 ], [ "▁最近", -9.626616477966309 ], [ "▁詳細", -9.626760482788086 ], [ "▁敵", -9.627294540405273 ], [ "▁ヨーロッパ", -9.628421783447266 ], [ "▁良く", -9.62939453125 ], [ "代", -9.629852294921875 ], [ "l", -9.629940032958984 ], [ "▁安", -9.630147933959961 ], [ "▁部門", -9.630358695983887 ], [ "▁有", -9.630372047424316 ], [ "書", -9.631168365478516 ], [ "▁素材", -9.632027626037598 ], [ "王", -9.632291793823242 ], [ "▁ミ", -9.632355690002441 ], [ "▁付", -9.632637977600098 ], [ "▁政策", -9.632920265197754 ], [ "▁やすく", -9.633496284484863 ], [ "▁大統領", -9.633594512939453 ], [ "▁最新", -9.634218215942383 ], [ "▁見た", -9.634227752685547 ], [ "▁動き", -9.634559631347656 ], [ "▁興味", -9.635754585266113 ], [ "▁かつて", -9.636417388916016 ], [ "▁土地", -9.636777877807617 ], [ "▁作ら", -9.638193130493164 ], [ "▁k", -9.640009880065918 ], [ "▁パン", -9.64065170288086 ], [ "▁コロナ", -9.641532897949219 ], [ "▁The", -9.6416597366333 ], [ "▁近い", -9.642074584960938 ], [ "▁表記", -9.642489433288574 ], [ "ず", -9.642821311950684 ], [ "▁レース", -9.64344596862793 ], [ "▁戦闘", -9.644139289855957 ], [ "▁形成", -9.644418716430664 ], [ "▁ウイルス", -9.644598960876465 ], [ "▁新たな", -9.645859718322754 ], [ "▁空", -9.646261215209961 ], [ "▁決勝", -9.647119522094727 ], [ "▁ビル", -9.647186279296875 ], [ "流", -9.647785186767578 ], [ "▁作曲", -9.648319244384766 ], [ "▁伝え", -9.648874282836914 ], [ "▁もちろん", -9.649012565612793 ], [ ".", -9.649291038513184 ], [ "b", -9.649316787719727 ], [ "▁悪い", -9.651187896728516 ], [ "▁あたり", -9.652119636535645 ], [ "▁2007", -9.65281867980957 ], [ "▁義", -9.652909278869629 ], [ "▁競技", -9.65311336517334 ], [ "▁プレイ", -9.653526306152344 ], [ "▁静岡", -9.653667449951172 ], [ "▁オリジナル", -9.653695106506348 ], [ "▁案内", -9.654155731201172 ], [ "ール", -9.654587745666504 ], [ "夫", -9.65481185913086 ], [ "R", -9.654946327209473 ], [ "風", -9.654994010925293 ], [ "▁紙", -9.655344009399414 ], [ "[", -9.655776023864746 ], [ "▁作用", -9.656795501708984 ], [ "▁話題", -9.656996726989746 ], [ "▁編成", -9.657304763793945 ], [ "▁コンテンツ", -9.657560348510742 ], [ "▁わかり", -9.65772819519043 ], [ "▁入力", -9.658369064331055 ], [ "▁ま", -9.658699035644531 ], [ "▁ク", -9.659235000610352 ], [ "▁愛知", -9.659646987915039 ], [ "▁かつ", -9.659727096557617 ], [ "▁俺", -9.66021728515625 ], [ "▁スター", -9.660896301269531 ], [ "コン", -9.661681175231934 ], [ "▁行", -9.661803245544434 ], [ "▁入", -9.661808967590332 ], [ "▁ビデオ", -9.661996841430664 ], [ "▁維持", -9.662003517150879 ], [ "▁......", -9.662907600402832 ], [ "▁あと", -9.662935256958008 ], [ "▁簡単に", -9.66330623626709 ], [ "▁目標", -9.66334342956543 ], [ "▁割", -9.663705825805664 ], [ "▁史", -9.663911819458008 ], [ "力", -9.664424896240234 ], [ "▁身体", -9.66616153717041 ], [ "▁少女", -9.666363716125488 ], [ "▁まとめ", -9.666996002197266 ], [ "▁成績", -9.667070388793945 ], [ "▁※", -9.667949676513672 ], [ "2016", -9.668058395385742 ], [ "▁絵", -9.668070793151855 ], [ "▁いつも", -9.66843318939209 ], [ "▁ばかり", -9.6701078414917 ], [ "アン", -9.671056747436523 ], [ "▁初期", -9.672759056091309 ], [ "p", -9.672867774963379 ], [ "戦", -9.673178672790527 ], [ "▁ツアー", -9.673505783081055 ], [ "▁難しい", -9.67436695098877 ], [ "ぶ", -9.67440128326416 ], [ "al", -9.674410820007324 ], [ "a", -9.675043106079102 ], [ "▁継続", -9.675858497619629 ], [ "頭", -9.676002502441406 ], [ "▁オリンピック", -9.676837921142578 ], [ "▁フル", -9.676894187927246 ], [ "▁埼玉", -9.677082061767578 ], [ "▁出る", -9.677213668823242 ], [ "▁範囲", -9.677852630615234 ], [ "▁知らせ", -9.678956985473633 ], [ "目", -9.680819511413574 ], [ "▁クリック", -9.682699203491211 ], [ "▁たくさん", -9.684592247009277 ], [ "▁こう", -9.685304641723633 ], [ "ロー", -9.685765266418457 ], [ "▁行政", -9.686335563659668 ], [ "▁兵", -9.686820030212402 ], [ "▁ノ", -9.686861991882324 ], [ "▁圏", -9.68710994720459 ], [ "▁大臣", -9.687216758728027 ], [ "▁わから", -9.690507888793945 ], [ "かった", -9.691427230834961 ], [ "所", -9.691874504089355 ], [ "▁状", -9.692328453063965 ], [ "▁入れ", -9.692537307739258 ], [ "会", -9.692688941955566 ], [ "▁エネルギー", -9.693071365356445 ], [ "Y", -9.693072319030762 ], [ "k", -9.693902969360352 ], [ "▁エリア", -9.694086074829102 ], [ "▁業界", -9.694646835327148 ], [ "▁できて", -9.695314407348633 ], [ "▁新潟", -9.695754051208496 ], [ "▁300", -9.695796012878418 ], [ "▁いずれ", -9.697267532348633 ], [ "▁制限", -9.697626113891602 ], [ "▁打", -9.698129653930664 ], [ "スター", -9.698177337646484 ], [ "▁こんな", -9.698680877685547 ], [ "▁自体", -9.698796272277832 ], [ "▁メートル", -9.699407577514648 ], [ "んだ", -9.700048446655273 ], [ "ギ", -9.700078964233398 ], [ "c", -9.700864791870117 ], [ "▁いって", -9.700960159301758 ], [ "▁食事", -9.7010498046875 ], [ "▁強く", -9.701075553894043 ], [ "▁募集", -9.701276779174805 ], [ "▁細胞", -9.701921463012695 ], [ "事", -9.702221870422363 ], [ "▁米国", -9.702540397644043 ], [ "▁議会", -9.703418731689453 ], [ "▁いけない", -9.704604148864746 ], [ "▁コード", -9.705116271972656 ], [ "▁別の", -9.706620216369629 ], [ "▁息子", -9.707199096679688 ], [ "性", -9.707624435424805 ], [ "▁デジタル", -9.70765495300293 ], [ "▁接続", -9.708909034729004 ], [ "▁続き", -9.709053993225098 ], [ "▁様子", -9.709291458129883 ], [ "▁指摘", -9.709466934204102 ], [ "▁廃止", -9.709689140319824 ], [ "▁ブラック", -9.710067749023438 ], [ "▁大戦", -9.710923194885254 ], [ "▁認定", -9.71155071258545 ], [ "▁ライト", -9.712876319885254 ], [ "▁書か", -9.712964057922363 ], [ "▁劇場", -9.713293075561523 ], [ "▁みんな", -9.713296890258789 ], [ "▁32", -9.713299751281738 ], [ "▁あれば", -9.713600158691406 ], [ "▁金融", -9.713642120361328 ], [ "▁必ず", -9.71402645111084 ], [ "▁テスト", -9.71408748626709 ], [ "尾", -9.715024948120117 ], [ "ね", -9.716822624206543 ], [ "▁建物", -9.717469215393066 ], [ "▁出して", -9.717918395996094 ], [ "▁早", -9.71810245513916 ], [ "▁服", -9.718924522399902 ], [ "▁ご覧", -9.718932151794434 ], [ "▁ヘルノ", -9.71972370147705 ], [ "ロン", -9.721135139465332 ], [ "▁指揮", -9.721213340759277 ], [ "▁藩", -9.721632957458496 ], [ "▁規定", -9.72168254852295 ], [ "▁モ", -9.722661018371582 ], [ "▁著作", -9.724061965942383 ], [ "▁タイ", -9.724288940429688 ], [ "▁キ", -9.724390029907227 ], [ "▁45", -9.724628448486328 ], [ "▁芸術", -9.725339889526367 ], [ "▁庁", -9.725918769836426 ], [ "▁会長", -9.726317405700684 ], [ "▁送料", -9.726558685302734 ], [ "マー", -9.727126121520996 ], [ "▁本人", -9.727484703063965 ], [ "▁わ", -9.728240013122559 ], [ "▁味", -9.728583335876465 ], [ "政", -9.729116439819336 ], [ "▁訳", -9.729314804077148 ], [ "▁ぜひ", -9.729443550109863 ], [ "▁失敗", -9.730161666870117 ], [ "立", -9.730640411376953 ], [ "▁いただけ", -9.731327056884766 ], [ "▁帯", -9.731901168823242 ], [ "経歴", -9.7321195602417 ], [ "台", -9.732391357421875 ], [ "▁タトラス", -9.73267650604248 ], [ "▁パソコン", -9.734151840209961 ], [ "▁2006", -9.734916687011719 ], [ "▁運行", -9.7349853515625 ], [ "▁工業", -9.73500919342041 ], [ "▁もって", -9.735615730285645 ], [ "▁剤", -9.735794067382812 ], [ "▁く", -9.736555099487305 ], [ "▁段階", -9.736753463745117 ], [ "▁反応", -9.737348556518555 ], [ "▁市民", -9.738125801086426 ], [ "▁展示", -9.738419532775879 ], [ "▁あの", -9.73848819732666 ], [ "▁操作", -9.738727569580078 ], [ "▁v", -9.739588737487793 ], [ "▁神戸", -9.740635871887207 ], [ "▁猫", -9.742058753967285 ], [ "2015", -9.743157386779785 ], [ "▁江戸", -9.74374771118164 ], [ "ブル", -9.743819236755371 ], [ "先", -9.74451732635498 ], [ "▁植物", -9.746087074279785 ], [ "▁印象", -9.74630069732666 ], [ "花", -9.746511459350586 ], [ "▁ベース", -9.746769905090332 ], [ "▁週", -9.747243881225586 ], [ "▁ロック", -9.74744701385498 ], [ "安", -9.747640609741211 ], [ "入", -9.74779224395752 ], [ "▁推進", -9.748215675354004 ], [ "▁分析", -9.748443603515625 ], [ "▁DVD", -9.749763488769531 ], [ "▁いわ", -9.750655174255371 ], [ "▁福島", -9.751523971557617 ], [ "▁港", -9.752480506896973 ], [ "20", -9.752487182617188 ], [ "▁装置", -9.752630233764648 ], [ "レス", -9.753190994262695 ], [ "▁ひ", -9.754096031188965 ], [ "▁実行", -9.754792213439941 ], [ "▁秒", -9.755435943603516 ], [ "▁地元", -9.755637168884277 ], [ "▁社員", -9.756723403930664 ], [ "▁冬", -9.757670402526855 ], [ "▁80", -9.758087158203125 ], [ "▁流", -9.758185386657715 ], [ "ホ", -9.758199691772461 ], [ "▁聞いて", -9.75831127166748 ], [ "▁メ", -9.759099960327148 ], [ "▁込ま", -9.759550094604492 ], [ "外", -9.759733200073242 ], [ "▁枠", -9.76075267791748 ], [ "▁届け", -9.761466026306152 ], [ "▁領", -9.761734008789062 ], [ "▁教えて", -9.761959075927734 ], [ "プロ", -9.762396812438965 ], [ "▁死去", -9.76257038116455 ], [ "▁and", -9.762683868408203 ], [ "▁買取", -9.7628812789917 ], [ "動", -9.76331901550293 ], [ "▁美容", -9.763511657714844 ], [ "主", -9.763663291931152 ], [ "門", -9.764033317565918 ], [ "in", -9.764080047607422 ], [ "▁くれた", -9.764153480529785 ], [ "▁最後の", -9.765297889709473 ], [ "▁》", -9.76552677154541 ], [ "▁丸", -9.765812873840332 ], [ "▁引き", -9.766064643859863 ], [ "▁熊本", -9.766520500183105 ], [ "▁シーン", -9.766648292541504 ], [ "食", -9.767443656921387 ], [ "O", -9.76776123046875 ], [ "▁得る", -9.768096923828125 ], [ "▁さまざまな", -9.768264770507812 ], [ "▁伴い", -9.768643379211426 ], [ "位", -9.768988609313965 ], [ "g", -9.769533157348633 ], [ "治", -9.770206451416016 ], [ "▁支配", -9.770397186279297 ], [ "▁批判", -9.771232604980469 ], [ "▁食品", -9.771415710449219 ], [ "▁調整", -9.77178955078125 ], [ "▁項", -9.772028923034668 ], [ "▁介護", -9.772472381591797 ], [ "▁500", -9.773604393005371 ], [ "▁園", -9.773635864257812 ], [ "▁入れて", -9.774152755737305 ], [ "▁03", -9.774852752685547 ], [ "▁途中", -9.774953842163086 ], [ "▁務め", -9.77507495880127 ], [ "▁高速", -9.77523422241211 ], [ "レン", -9.775471687316895 ], [ "▁講師", -9.776126861572266 ], [ "▁通じて", -9.776281356811523 ], [ "▁要素", -9.776373863220215 ], [ "▁大人", -9.77657699584961 ], [ "▁バージョン", -9.776911735534668 ], [ "▁審査", -9.777459144592285 ], [ "橋", -9.777929306030273 ], [ "▁支持", -9.778417587280273 ], [ "▁早く", -9.77906322479248 ], [ "▁地球", -9.779153823852539 ], [ "里", -9.77973461151123 ], [ "▁達成", -9.779959678649902 ], [ "▁学者", -9.780123710632324 ], [ "今日", -9.780156135559082 ], [ "▁リスト", -9.78043270111084 ], [ "▁認識", -9.780571937561035 ], [ "“", -9.78189754486084 ], [ "▁層", -9.782299995422363 ], [ "▁少なく", -9.783096313476562 ], [ "▁来た", -9.783370018005371 ], [ "▁生徒", -9.783507347106934 ], [ "▁らしい", -9.783941268920898 ], [ "▁症状", -9.784468650817871 ], [ "▁原", -9.785004615783691 ], [ "▁諸", -9.785611152648926 ], [ "▁★", -9.785619735717773 ], [ "▁日間", -9.785685539245605 ], [ "▁プラン", -9.78606128692627 ], [ "▁02", -9.786476135253906 ], [ "▁座", -9.786541938781738 ], [ "▁まず", -9.787518501281738 ], [ "▁48", -9.787557601928711 ], [ "▁相", -9.7884521484375 ], [ "▁雨", -9.788961410522461 ], [ "之", -9.789571762084961 ], [ "通", -9.789884567260742 ], [ "江", -9.791014671325684 ], [ "2010", -9.791217803955078 ], [ "▁便", -9.791704177856445 ], [ "▁求め", -9.792130470275879 ], [ "▁続ける", -9.792540550231934 ], [ "▁長い", -9.79269790649414 ], [ "定", -9.792875289916992 ], [ "▁友人", -9.793076515197754 ], [ "▁熱", -9.794096946716309 ], [ "▁貢献", -9.794193267822266 ], [ "▁観", -9.794331550598145 ], [ "音", -9.795429229736328 ], [ "et", -9.795744895935059 ], [ "▁役割", -9.796101570129395 ], [ "▁皆様", -9.796157836914062 ], [ "▁基礎", -9.796387672424316 ], [ "▁欲しい", -9.796420097351074 ], [ "▁ファッション", -9.796551704406738 ], [ "車", -9.79685115814209 ], [ "▁楽曲", -9.79736328125 ], [ "▁携帯", -9.799043655395508 ], [ "▁なかなか", -9.79911994934082 ], [ "▁課題", -9.799156188964844 ], [ "▁かかる", -9.799199104309082 ], [ "▁弾", -9.79965591430664 ], [ "w", -9.800995826721191 ], [ "▁1000", -9.80109977722168 ], [ "▁札幌", -9.801675796508789 ], [ "用", -9.802040100097656 ], [ "ックス", -9.802068710327148 ], [ "en", -9.802326202392578 ], [ "▁安定", -9.802659034729004 ], [ "▁示す", -9.8032865524292 ], [ "▁負担", -9.804300308227539 ], [ "▁07", -9.804608345031738 ], [ "▁小さな", -9.805183410644531 ], [ "2014", -9.805909156799316 ], [ "▁<", -9.806005477905273 ], [ "▁つけ", -9.806180953979492 ], [ "▁作って", -9.806605339050293 ], [ "▁FC", -9.806702613830566 ], [ "吉", -9.807188987731934 ], [ "▁ぬ", -9.80739974975586 ], [ "▁少年", -9.808112144470215 ], [ "形", -9.8108549118042 ], [ "▁通", -9.812334060668945 ], [ "いた", -9.812373161315918 ], [ "▁自宅", -9.81245231628418 ], [ "▁交流", -9.81337833404541 ], [ "▁派遣", -9.813925743103027 ], [ "▁楽しみ", -9.814337730407715 ], [ "▁切り", -9.814998626708984 ], [ "▁バッグ", -9.81505298614502 ], [ "ヌ", -9.81557559967041 ], [ "▁確保", -9.815838813781738 ], [ "ガー", -9.816351890563965 ], [ "es", -9.817941665649414 ], [ "▁感じる", -9.818463325500488 ], [ "▁明らかに", -9.818746566772461 ], [ "▁08", -9.818929672241211 ], [ "▁結成", -9.819202423095703 ], [ "▁信頼", -9.820235252380371 ], [ "▁^", -9.821073532104492 ], [ "▁完全", -9.821101188659668 ], [ "▁生まれた", -9.82243824005127 ], [ "▁何度", -9.822766304016113 ], [ "▁絶対", -9.822851181030273 ], [ "▁70", -9.82290267944336 ], [ "例えば", -9.823290824890137 ], [ "▁フ", -9.823381423950195 ], [ "▁後半", -9.824298858642578 ], [ "17", -9.82461166381836 ], [ "▁口コミ", -9.825362205505371 ], [ "▁標準", -9.8256196975708 ], [ "▁実験", -9.826081275939941 ], [ "岡", -9.826340675354004 ], [ "▁明", -9.827790260314941 ], [ "▁成立", -9.827868461608887 ], [ "▁09", -9.828660011291504 ], [ "電", -9.828717231750488 ], [ "▁大正", -9.830829620361328 ], [ "▁年齢", -9.831101417541504 ], [ "▁なか", -9.832196235656738 ], [ "▁飛行", -9.832578659057617 ], [ "▁メイン", -9.833282470703125 ], [ "E", -9.83427619934082 ], [ "信", -9.836231231689453 ], [ "▁どの", -9.836251258850098 ], [ "is", -9.836854934692383 ], [ "▁取締", -9.837202072143555 ], [ "▁七", -9.837688446044922 ], [ "▁傾向", -9.838119506835938 ], [ "▁体制", -9.838483810424805 ], [ "▁拠点", -9.838560104370117 ], [ "▁長野", -9.83874797821045 ], [ "▁ホール", -9.838841438293457 ], [ "ろう", -9.839844703674316 ], [ "松", -9.840088844299316 ], [ "▁席", -9.840104103088379 ], [ "▁ローマ", -9.840224266052246 ], [ "▁所有", -9.84060287475586 ], [ "▁世代", -9.840827941894531 ], [ "ぐ", -9.840850830078125 ], [ "▁職", -9.841645240783691 ], [ "▁ネットワーク", -9.841706275939941 ], [ "on", -9.842020988464355 ], [ "▁機械", -9.842175483703613 ], [ "市", -9.84251880645752 ], [ "▁兵庫", -9.842728614807129 ], [ "▁ふ", -9.843551635742188 ], [ "▁脳", -9.84370231628418 ], [ "▁2005", -9.84385871887207 ], [ "▁スペイン", -9.84444808959961 ], [ "▁働き", -9.845011711120605 ], [ "▁レビュー", -9.845841407775879 ], [ "▁であれば", -9.846051216125488 ], [ "2012", -9.846256256103516 ], [ "▁現場", -9.846266746520996 ], [ "▁短", -9.846426010131836 ], [ "▁込む", -9.846538543701172 ], [ "▁強化", -9.846774101257324 ], [ "』", -9.847041130065918 ], [ "▁岡山", -9.847591400146484 ], [ "▁ホ", -9.84764289855957 ], [ "ur", -9.847805976867676 ], [ "その他", -9.848577499389648 ], [ "▁弁護", -9.848613739013672 ], [ "れる", -9.848949432373047 ], [ "▁やる", -9.849288940429688 ], [ "▁方式", -9.84946060180664 ], [ "▁大きい", -9.85106086730957 ], [ "▁気軽に", -9.851109504699707 ], [ "2013", -9.852550506591797 ], [ "ゼ", -9.85265827178955 ], [ "▁悪", -9.852808952331543 ], [ "▁話し", -9.853215217590332 ], [ "▁計算", -9.85332202911377 ], [ "▁聖", -9.856243133544922 ], [ "▁05", -9.85625171661377 ], [ "▁仕様", -9.856316566467285 ], [ "サー", -9.856477737426758 ], [ "▁節", -9.857646942138672 ], [ "▁温泉", -9.857881546020508 ], [ "ザー", -9.85834789276123 ], [ "▁公演", -9.858611106872559 ], [ "武", -9.859546661376953 ], [ "全", -9.859575271606445 ], [ "▁きっかけ", -9.860132217407227 ], [ "▁再生", -9.860542297363281 ], [ "▁า", -9.860856056213379 ], [ "▁ポ", -9.861873626708984 ], [ "▁オイル", -9.862499237060547 ], [ "▁書籍", -9.863128662109375 ], [ "ランド", -9.863577842712402 ], [ "ファ", -9.863724708557129 ], [ "▁成分", -9.863933563232422 ], [ "▁買い", -9.864587783813477 ], [ "▁受験", -9.86484432220459 ], [ "馬", -9.864850997924805 ], [ "▁シュ", -9.865108489990234 ], [ "▁ガ", -9.865151405334473 ], [ "2011", -9.865311622619629 ], [ "▁おら", -9.865713119506836 ], [ "▁準", -9.866198539733887 ], [ "▁見える", -9.86715316772461 ], [ "▁周年", -9.867290496826172 ], [ "よ", -9.867574691772461 ], [ "▁04", -9.867718696594238 ], [ "or", -9.868247985839844 ], [ "▁伝統", -9.869064331054688 ], [ "▁立ち", -9.869075775146484 ], [ "▁@", -9.869205474853516 ], [ "▁ビ", -9.869688034057617 ], [ "▁そうな", -9.869930267333984 ], [ "▁2022", -9.869935035705566 ], [ "▁重要", -9.870010375976562 ], [ "▁輸送", -9.870285034179688 ], [ "▁90", -9.870652198791504 ], [ "▁ほしい", -9.872106552124023 ], [ "▁中古", -9.872332572937012 ], [ "▁段", -9.872566223144531 ], [ "▁今年", -9.872580528259277 ], [ "▁山口", -9.873000144958496 ], [ "▁選ば", -9.873627662658691 ], [ "▁候補", -9.873671531677246 ], [ "者", -9.874621391296387 ], [ "▁従", -9.87508487701416 ], [ "▁オー", -9.875393867492676 ], [ "▁奈良", -9.875592231750488 ], [ "30", -9.875690460205078 ], [ "▁カップ", -9.875895500183105 ], [ "理", -9.876387596130371 ], [ "▁挑戦", -9.876545906066895 ], [ "▁肉", -9.877068519592285 ], [ "▁増えて", -9.877362251281738 ], [ "毛", -9.877426147460938 ], [ "▁雰囲気", -9.877854347229004 ], [ "▁入った", -9.878093719482422 ], [ "▁政権", -9.878161430358887 ], [ "▁会場", -9.87833309173584 ], [ "Q", -9.87929916381836 ], [ "▁追い", -9.879470825195312 ], [ "▁収入", -9.880187034606934 ], [ "▁反", -9.880257606506348 ], [ "▁界", -9.880558013916016 ], [ "▁マーク", -9.880746841430664 ], [ "▁引退", -9.881242752075195 ], [ "▁連邦", -9.881245613098145 ], [ "▁勤務", -9.881362915039062 ], [ "▁勝ち", -9.88211727142334 ], [ "▁長崎", -9.882742881774902 ], [ "▁インド", -9.883099555969238 ], [ "▁作戦", -9.88329792022705 ], [ "▁修正", -9.883466720581055 ], [ "▁年生", -9.883605003356934 ], [ "▁やはり", -9.883666038513184 ], [ "白", -9.884025573730469 ], [ "▁生物", -9.884247779846191 ], [ "U", -9.884417533874512 ], [ "▁スタジオ", -9.88457202911377 ], [ "▁売り", -9.88546371459961 ], [ "▁Q", -9.885534286499023 ], [ "▁対戦", -9.885720252990723 ], [ "▁ツール", -9.88582706451416 ], [ "▁付近", -9.886701583862305 ], [ "▁勧め", -9.886811256408691 ], [ "▁青", -9.887517929077148 ], [ "▁もらう", -9.887530326843262 ], [ "▁信", -9.887986183166504 ], [ "▁領域", -9.888477325439453 ], [ "▁作家", -9.88862419128418 ], [ "▁文学", -9.888956069946289 ], [ "ーン", -9.889552116394043 ], [ "▁ニューヨーク", -9.889625549316406 ], [ "▁込んで", -9.8901948928833 ], [ "太", -9.891684532165527 ], [ "▁千", -9.891776084899902 ], [ "司", -9.892033576965332 ], [ "▁さま", -9.89237117767334 ], [ "▁保証", -9.892736434936523 ], [ "▁改正", -9.892755508422852 ], [ "▁連携", -9.892776489257812 ], [ "発", -9.892852783203125 ], [ "▁使った", -9.893095016479492 ], [ "▁視聴", -9.893460273742676 ], [ "身", -9.893956184387207 ], [ "▁言え", -9.894328117370605 ], [ "▁常に", -9.89550495147705 ], [ "▁テ", -9.895798683166504 ], [ "▁毛", -9.897683143615723 ], [ "▁よれば", -9.898000717163086 ], [ "▁共和", -9.89807415008545 ], [ "▁スマホ", -9.899303436279297 ], [ "▁住民", -9.89949893951416 ], [ "▁もらい", -9.900069236755371 ], [ "▁感謝", -9.901062965393066 ], [ "義", -9.901118278503418 ], [ "▁了承", -9.901200294494629 ], [ "▁め", -9.90145492553711 ], [ "▁グッズ", -9.901483535766602 ], [ "▁女優", -9.90290641784668 ], [ "▁集中", -9.90324878692627 ], [ "ピ", -9.904254913330078 ], [ "▁ホームページ", -9.904516220092773 ], [ "▁聞き", -9.904743194580078 ], [ "来歴", -9.904760360717773 ], [ "ビー", -9.904809951782227 ], [ "▁記", -9.904891967773438 ], [ "▁停止", -9.907637596130371 ], [ "葉", -9.907777786254883 ], [ "v", -9.908086776733398 ], [ "たり", -9.908323287963867 ], [ "▁ただ", -9.908435821533203 ], [ "▁ソフトウェア", -9.908563613891602 ], [ "▁満足", -9.908761024475098 ], [ "▁適用", -9.908761024475098 ], [ "▁可", -9.909123420715332 ], [ "ライ", -9.909452438354492 ], [ "▁乗り", -9.90951919555664 ], [ "戸", -9.909616470336914 ], [ "▁選出", -9.909625053405762 ], [ "▁ソ", -9.909756660461426 ], [ "▁医", -9.91008472442627 ], [ "▁y", -9.910374641418457 ], [ "▁キャンペーン", -9.910637855529785 ], [ "▁減少", -9.911046028137207 ], [ "▁現実", -9.911221504211426 ], [ "▁禁止", -9.911447525024414 ], [ "▁広", -9.911596298217773 ], [ "▁見え", -9.911869049072266 ], [ "▁メッセージ", -9.912237167358398 ], [ "室", -9.913111686706543 ], [ "▁定期", -9.91317081451416 ], [ "▁波", -9.913596153259277 ], [ "▁資金", -9.913832664489746 ], [ "▁復帰", -9.914484024047852 ], [ "▁野", -9.91489315032959 ], [ "▁画", -9.914993286132812 ], [ "▁メニュー", -9.915477752685547 ], [ "▁計", -9.915624618530273 ], [ "▁反対", -9.916123390197754 ], [ "▁夫", -9.916909217834473 ], [ "▁岩", -9.916916847229004 ], [ "▁歯", -9.91716480255127 ], [ "院", -9.91755199432373 ], [ "▁ピ", -9.91798210144043 ], [ "el", -9.918017387390137 ], [ "▁マイ", -9.918325424194336 ], [ "▁向けて", -9.918947219848633 ], [ "▁プレゼント", -9.91958236694336 ], [ "▁鹿児島", -9.919906616210938 ], [ "▁始める", -9.920415878295898 ], [ "▁感じて", -9.920454025268555 ], [ "▁new", -9.9207124710083 ], [ "語", -9.921399116516113 ], [ "z", -9.921895980834961 ], [ "▁記述", -9.922613143920898 ], [ "ジャ", -9.922892570495605 ], [ "▁06", -9.923717498779297 ], [ "▁整理", -9.923783302307129 ], [ "▁盤", -9.924186706542969 ], [ "▁~", -9.924206733703613 ], [ "▁全員", -9.924711227416992 ], [ "▁理事", -9.92505931854248 ], [ "▁選び", -9.926429748535156 ], [ "雄", -9.926702499389648 ], [ "▁鉄", -9.927002906799316 ], [ "▁そういう", -9.9276762008667 ], [ "▁続く", -9.928672790527344 ], [ "▁良", -9.928754806518555 ], [ "▁幅", -9.92972469329834 ], [ "ど", -9.930231094360352 ], [ "▁大変", -9.93073844909668 ], [ "▁効率", -9.93165397644043 ], [ "▁リスク", -9.93179702758789 ], [ "フィ", -9.932415962219238 ], [ "▁すでに", -9.932429313659668 ], [ "最近", -9.932449340820312 ], [ "2009", -9.93258285522461 ], [ "▁待ち", -9.93264389038086 ], [ "別", -9.933329582214355 ], [ "▁配置", -9.934012413024902 ], [ "する", -9.934835433959961 ], [ "▁六", -9.935032844543457 ], [ "▁不足", -9.935072898864746 ], [ "▁連載", -9.935108184814453 ], [ "▁[[", -9.935699462890625 ], [ "▁日々", -9.935853958129883 ], [ "▁え", -9.936219215393066 ], [ "ベル", -9.936220169067383 ], [ "シャ", -9.936355590820312 ], [ "▁ペ", -9.936600685119629 ], [ "種", -9.936880111694336 ], [ "▁ブルー", -9.937203407287598 ], [ "▁化学", -9.93748950958252 ], [ "▁なぜ", -9.939087867736816 ], [ "{", -9.939215660095215 ], [ "▁発電", -9.93923568725586 ], [ "量", -9.939604759216309 ], [ "ップ", -9.940277099609375 ], [ "▁一切", -9.94074821472168 ], [ "▁予想", -9.940813064575195 ], [ "ヴ", -9.9408597946167 ], [ "▁脱毛", -9.941747665405273 ], [ "▁ウェブ", -9.941815376281738 ], [ "▁以内", -9.942171096801758 ], [ "▁陸軍", -9.942253112792969 ], [ "久", -9.942272186279297 ], [ "▁下記", -9.942540168762207 ], [ "▁各地", -9.942705154418945 ], [ "▁民", -9.942933082580566 ], [ "▁加え", -9.943326950073242 ], [ "16", -9.943882942199707 ], [ "当時", -9.945001602172852 ], [ "▁証明", -9.945926666259766 ], [ "▁ステージ", -9.94594669342041 ], [ "▁ニュー", -9.94623851776123 ], [ "▁実践", -9.946868896484375 ], [ "▁コート", -9.947091102600098 ], [ "▁福祉", -9.94733715057373 ], [ "▁茶", -9.947966575622559 ], [ "▁ボ", -9.948623657226562 ], [ "▁方針", -9.948668479919434 ], [ "▁方面", -9.948680877685547 ], [ "▁品質", -9.948710441589355 ], [ "▁ジ", -9.949323654174805 ], [ "▁字", -9.9495849609375 ], [ "▁ございました", -9.949585914611816 ], [ "▁同様に", -9.949928283691406 ], [ "▁定義", -9.950343132019043 ], [ "▁ガス", -9.950465202331543 ], [ "▁岐阜", -9.950510025024414 ], [ "▁博士", -9.9514799118042 ], [ "▁不安", -9.952643394470215 ], [ "▁報道", -9.9528226852417 ], [ "▁取扱", -9.952849388122559 ], [ "▁皆さん", -9.953082084655762 ], [ "■", -9.953371047973633 ], [ "▁Web", -9.953761100769043 ], [ "▁のである", -9.95397663116455 ], [ "える", -9.954158782958984 ], [ "▁株", -9.955183029174805 ], [ "期", -9.955594062805176 ], [ "an", -9.955751419067383 ], [ "タン", -9.95658016204834 ], [ "▁看護", -9.95668888092041 ], [ "▁知り", -9.958229064941406 ], [ "▁唯一", -9.958298683166504 ], [ "〜", -9.958846092224121 ], [ "▁友達", -9.959344863891602 ], [ "2008", -9.959399223327637 ], [ "▁o", -9.959577560424805 ], [ "▁加入", -9.960230827331543 ], [ "▁速度", -9.960609436035156 ], [ "▁日常", -9.961099624633789 ], [ "▁金額", -9.962087631225586 ], [ "it", -9.96235179901123 ], [ "▁悩み", -9.962671279907227 ], [ "▁Google", -9.962845802307129 ], [ "▁積極", -9.963293075561523 ], [ "▁到着", -9.963409423828125 ], [ "▁ライフ", -9.963462829589844 ], [ "15", -9.963751792907715 ], [ "▁最大の", -9.963846206665039 ], [ "▁ディ", -9.964073181152344 ], [ "▁であって", -9.964179039001465 ], [ "▁未来", -9.964212417602539 ], [ "▁ウ", -9.964625358581543 ], [ "▁医師", -9.964629173278809 ], [ "▁シャツ", -9.964860916137695 ], [ "▁進出", -9.964954376220703 ], [ "▁誕生", -9.965662956237793 ], [ "▁教", -9.966019630432129 ], [ "▁機構", -9.966072082519531 ], [ "▁統合", -9.966267585754395 ], [ "エル", -9.966787338256836 ], [ "▁台湾", -9.966880798339844 ], [ "サン", -9.966925621032715 ], [ "星", -9.9673490524292 ], [ "▁組合", -9.967559814453125 ], [ "▁命", -9.968362808227539 ], [ "次", -9.969352722167969 ], [ "▁設備", -9.969477653503418 ], [ "▁スペース", -9.970051765441895 ], [ "▁異なり", -9.97039794921875 ], [ "▁俳優", -9.971043586730957 ], [ "▁TV", -9.97230052947998 ], [ "▁ヘ", -9.972515106201172 ], [ "▁合併", -9.972819328308105 ], [ "実際", -9.973483085632324 ], [ "▁ベル", -9.973614692687988 ], [ "▁仲間", -9.973848342895508 ], [ "質", -9.97425651550293 ], [ "男", -9.974578857421875 ], [ "▁探し", -9.974702835083008 ], [ "▁ボタン", -9.974820137023926 ], [ "▁設け", -9.975691795349121 ], [ "▁カバー", -9.975939750671387 ], [ "▁券", -9.976740837097168 ], [ "▁もしくは", -9.97697639465332 ], [ "▁アイドル", -9.977667808532715 ], [ "▁女の子", -9.977927207946777 ], [ "ペ", -9.978020668029785 ], [ "▁大型", -9.978208541870117 ], [ "テン", -9.978323936462402 ], [ "▁続け", -9.978535652160645 ], [ "▁出さ", -9.978599548339844 ], [ "▁防止", -9.979066848754883 ], [ "瀬", -9.979787826538086 ], [ "何", -9.979866981506348 ], [ "▁福井", -9.980302810668945 ], [ "▁板", -9.980535507202148 ], [ "▁選ぶ", -9.980542182922363 ], [ "▁休み", -9.980842590332031 ], [ "▁ち", -9.980865478515625 ], [ "▁2004", -9.981037139892578 ], [ "▁ロー", -9.981867790222168 ], [ "▁修理", -9.982346534729004 ], [ "▁描か", -9.983179092407227 ], [ "▁装備", -9.98376178741455 ], [ "I", -9.983891487121582 ], [ "▁to", -9.983967781066895 ], [ "▁共有", -9.984132766723633 ], [ "▁競馬", -9.98425579071045 ], [ "▁電車", -9.98462963104248 ], [ "▁訪問", -9.985995292663574 ], [ "▁am", -9.987509727478027 ], [ "▁広く", -9.987541198730469 ], [ "▁葉", -9.987541198730469 ], [ "▁相当", -9.987668991088867 ], [ "▁どちら", -9.987799644470215 ], [ "▁ずっと", -9.98816204071045 ], [ "▁国立", -9.988415718078613 ], [ "ヴァ", -9.988607406616211 ], [ "▁トレーニング", -9.989513397216797 ], [ "▁教室", -9.991349220275879 ], [ "▁危険", -9.99152660369873 ], [ "▁地震", -9.992018699645996 ], [ "▁関東", -9.992950439453125 ], [ "▁奥", -9.99334716796875 ], [ "▁戦略", -9.993931770324707 ], [ "▁出した", -9.994210243225098 ], [ "▁権利", -9.99441909790039 ], [ "▁大学院", -9.995301246643066 ], [ "▁病気", -9.995407104492188 ], [ "▁首", -9.99545669555664 ], [ "▁ペット", -9.99577522277832 ], [ "カル", -9.995792388916016 ], [ "▁co", -9.995832443237305 ], [ "女", -9.997406959533691 ], [ "▁性能", -9.997467041015625 ], [ "▁秋田", -9.997688293457031 ], [ "▁武", -9.99775505065918 ], [ "▁評判", -9.997965812683105 ], [ "2007", -9.998042106628418 ], [ "足", -9.998211860656738 ], [ "▁九州", -9.998661041259766 ], [ "▁雪", -9.998784065246582 ], [ "h", -9.999659538269043 ], [ "時", -10.001230239868164 ], [ "Z", -10.001338958740234 ], [ "民", -10.001899719238281 ], [ "▁読んで", -10.00246810913086 ], [ "▁集団", -10.003040313720703 ], [ "▁ジャケット", -10.003310203552246 ], [ "▁ã", -10.003491401672363 ], [ "▁のだろう", -10.004437446594238 ], [ "▁何も", -10.004446983337402 ], [ "▁ワン", -10.00448226928711 ], [ "▁www", -10.007009506225586 ], [ "▁33", -10.007312774658203 ], [ "▁のち", -10.007671356201172 ], [ "▁ニ", -10.008994102478027 ], [ "▁終わり", -10.009703636169434 ], [ "▁知る", -10.010102272033691 ], [ "▁続いて", -10.010820388793945 ], [ "▁送り", -10.011153221130371 ], [ "▁ショー", -10.011353492736816 ], [ "▁連", -10.011764526367188 ], [ "▁シー", -10.012078285217285 ], [ "ガン", -10.012080192565918 ], [ "▁パリ", -10.012090682983398 ], [ "▁キャリア", -10.01292610168457 ], [ "重", -10.013225555419922 ], [ "▁系統", -10.013493537902832 ], [ "路", -10.013716697692871 ], [ "▁提出", -10.014369010925293 ], [ "▁ハウス", -10.014839172363281 ], [ "▁\\", -10.014944076538086 ], [ "▁加工", -10.015032768249512 ], [ "▁開業", -10.015645027160645 ], [ "▁つけて", -10.015730857849121 ], [ "▁区間", -10.016651153564453 ], [ "楽", -10.01669692993164 ], [ "▁ジャパン", -10.017064094543457 ], [ "▁族", -10.017142295837402 ], [ "▁新作", -10.017585754394531 ], [ "▁んじゃ", -10.01779842376709 ], [ "▁関西", -10.018022537231445 ], [ "▁いただいて", -10.018555641174316 ], [ "▁バイト", -10.018733024597168 ], [ "▁アルバイト", -10.018851280212402 ], [ "▁方々", -10.020791053771973 ], [ "▁楽天", -10.020809173583984 ], [ "▁完全に", -10.020946502685547 ], [ "▁将来", -10.021146774291992 ], [ "▁事前", -10.022038459777832 ], [ "▁草", -10.02231502532959 ], [ "▁–", -10.022473335266113 ], [ "▁構築", -10.022811889648438 ], [ "▁来る", -10.022964477539062 ], [ "▁インストール", -10.02343463897705 ], [ "▁コーナー", -10.023529052734375 ], [ "▁トーク", -10.023530006408691 ], [ "▁増", -10.023765563964844 ], [ "▁始まり", -10.023774147033691 ], [ "ッツ", -10.024260520935059 ], [ "▁好", -10.024410247802734 ], [ "ニア", -10.02443790435791 ], [ "度", -10.024484634399414 ], [ "良", -10.024922370910645 ], [ "▁要求", -10.024956703186035 ], [ "▁ないで", -10.025384902954102 ], [ "▁ジョン", -10.0255708694458 ], [ "▁又は", -10.025613784790039 ], [ "▁入学", -10.025982856750488 ], [ "▁桜", -10.026432991027832 ], [ "▁NHK", -10.026566505432129 ], [ "▁心理", -10.027850151062012 ], [ "▁投票", -10.028437614440918 ], [ "▁章", -10.030375480651855 ], [ "▁どれ", -10.03101921081543 ], [ "▁死亡", -10.03118896484375 ], [ "▁通して", -10.031229972839355 ], [ "▁ミニ", -10.03131103515625 ], [ "▁南部", -10.031444549560547 ], [ "▁酸", -10.031462669372559 ], [ "▁前後", -10.032089233398438 ], [ "▁トラック", -10.03258991241455 ], [ "▁破壊", -10.032670974731445 ], [ "▁医学", -10.032835006713867 ], [ "▁分かり", -10.033647537231445 ], [ "▁残って", -10.03387451171875 ], [ "▁王国", -10.033942222595215 ], [ "▁《", -10.034411430358887 ], [ "座", -10.034693717956543 ], [ "▁天皇", -10.034719467163086 ], [ "▁低い", -10.035360336303711 ], [ "▁元年", -10.035867691040039 ], [ "▁許可", -10.03646183013916 ], [ "▁太陽", -10.036869049072266 ], [ "▁ラン", -10.037062644958496 ], [ "▁ร", -10.037226676940918 ], [ "▁理論", -10.03734016418457 ], [ "もう", -10.038166046142578 ], [ "▁立場", -10.038344383239746 ], [ "▁アドレス", -10.038758277893066 ], [ "▁゙", -10.039505004882812 ], [ "▁飲み", -10.040047645568848 ], [ "▁既に", -10.040164947509766 ], [ "▁ワ", -10.040910720825195 ], [ "しい", -10.041966438293457 ], [ "▁授業", -10.042150497436523 ], [ "▁文庫", -10.042882919311523 ], [ "▁昔", -10.043259620666504 ], [ "▁得点", -10.04379653930664 ], [ "▁本線", -10.044017791748047 ], [ "▁請求", -10.044360160827637 ], [ "▁心配", -10.044559478759766 ], [ "坂", -10.044876098632812 ], [ "▁宮崎", -10.044882774353027 ], [ "▁新型", -10.044904708862305 ], [ "▁応援", -10.045321464538574 ], [ "▁ストーリー", -10.045456886291504 ], [ "▁ケ", -10.045830726623535 ], [ "▁完了", -10.046196937561035 ], [ "▁けれど", -10.046610832214355 ], [ "▁産", -10.046618461608887 ], [ "レー", -10.047125816345215 ], [ "▁せい", -10.047469139099121 ], [ "▁宣言", -10.047675132751465 ], [ "▁36", -10.049159049987793 ], [ "▁いただいた", -10.051506996154785 ], [ "▁遊び", -10.052059173583984 ], [ "▁至る", -10.052531242370605 ], [ "▁従来", -10.052834510803223 ], [ "▁朝鮮", -10.054186820983887 ], [ "朝", -10.054892539978027 ], [ "▁わけです", -10.055098533630371 ], [ "火", -10.055257797241211 ], [ "士", -10.055350303649902 ], [ "▁門", -10.055607795715332 ], [ "▁核", -10.05566120147705 ], [ "▁シャ", -10.056050300598145 ], [ "▁与える", -10.056354522705078 ], [ "▁工学", -10.056478500366211 ], [ "▁湯", -10.056600570678711 ], [ "千", -10.056795120239258 ], [ "▁具体", -10.057796478271484 ], [ "モン", -10.058019638061523 ], [ "▁深", -10.058598518371582 ], [ "▁東北", -10.058735847473145 ], [ "▁長く", -10.058955192565918 ], [ "▁印刷", -10.05948257446289 ], [ "▁歴", -10.059893608093262 ], [ "▁湖", -10.06019115447998 ], [ "化", -10.060617446899414 ], [ "▁サロン", -10.060762405395508 ], [ "▁ミュージック", -10.061590194702148 ], [ "でした", -10.062191009521484 ], [ "▁申請", -10.06248664855957 ], [ "▁恋", -10.062621116638184 ], [ "▁しまって", -10.063096046447754 ], [ "▁みた", -10.06332778930664 ], [ "▁モード", -10.063626289367676 ], [ "us", -10.063685417175293 ], [ "▁石川", -10.063962936401367 ], [ "ジェ", -10.06402587890625 ], [ "▁壁", -10.065157890319824 ], [ "▁異", -10.065594673156738 ], [ "▁軽", -10.065651893615723 ], [ "▁回復", -10.066681861877441 ], [ "根", -10.06674575805664 ], [ "機", -10.066847801208496 ], [ "▁男子", -10.066882133483887 ], [ "クス", -10.0674467086792 ], [ "▁学会", -10.068056106567383 ], [ "40", -10.068117141723633 ], [ "▁ー", -10.068292617797852 ], [ "▁分から", -10.068499565124512 ], [ "▁改革", -10.068582534790039 ], [ "知", -10.068876266479492 ], [ "▁痛み", -10.06955623626709 ], [ "そ", -10.069608688354492 ], [ "波", -10.070197105407715 ], [ "▁ヒット", -10.070354461669922 ], [ "▁大き", -10.07076358795166 ], [ "▁値段", -10.070770263671875 ], [ "▁同じく", -10.070976257324219 ], [ "ic", -10.071444511413574 ], [ "▁松", -10.071602821350098 ], [ "▁記憶", -10.071648597717285 ], [ "▁プレー", -10.072369575500488 ], [ "▁for", -10.073253631591797 ], [ "▁ローン", -10.073369026184082 ], [ "▁市立", -10.07373332977295 ], [ "着", -10.073858261108398 ], [ "命", -10.074024200439453 ], [ "館", -10.07426643371582 ], [ "▁富山", -10.074913024902344 ], [ "▁県立", -10.07494831085205 ], [ "▁是非", -10.075040817260742 ], [ "▁支払い", -10.076096534729004 ], [ "▁38", -10.07680606842041 ], [ "▁楽しい", -10.07706069946289 ], [ "▁逆", -10.077482223510742 ], [ "▁腕", -10.078035354614258 ], [ "丸", -10.07833480834961 ], [ "▁単位", -10.078609466552734 ], [ "▁新たに", -10.07917594909668 ], [ "▁属", -10.079580307006836 ], [ "ふ", -10.080174446105957 ], [ "▁ベ", -10.081733703613281 ], [ "▁34", -10.081779479980469 ], [ "▁魚", -10.082364082336426 ], [ "▁周り", -10.082540512084961 ], [ "郎", -10.082986831665039 ], [ "であった", -10.083253860473633 ], [ "であり", -10.083660125732422 ], [ "▁塩", -10.084321022033691 ], [ "▁kg", -10.084656715393066 ], [ "▁学園", -10.085311889648438 ], [ "▁敗", -10.0855073928833 ], [ "▁農業", -10.08565616607666 ], [ "社", -10.085885047912598 ], [ "▁背景", -10.086856842041016 ], [ "ちゃ", -10.086897850036621 ], [ "フェ", -10.087419509887695 ], [ "▁宮城", -10.08746337890625 ], [ "徳", -10.087481498718262 ], [ "▁挙げ", -10.087512016296387 ], [ "▁ヤ", -10.08764934539795 ], [ "▁訓練", -10.0877685546875 ], [ "▁カット", -10.088549613952637 ], [ "▁必要です", -10.089083671569824 ], [ "▁46", -10.089376449584961 ], [ "le", -10.089492797851562 ], [ "▁議論", -10.090251922607422 ], [ "▁間違い", -10.090377807617188 ], [ "▁ピアノ", -10.09056282043457 ], [ "▁いか", -10.090774536132812 ], [ "▁制御", -10.09255313873291 ], [ "カン", -10.092928886413574 ], [ "無", -10.092933654785156 ], [ "▁利益", -10.09298038482666 ], [ "▁宮", -10.093358993530273 ], [ "▁内部", -10.09362506866455 ], [ "▁出た", -10.093812942504883 ], [ "志", -10.093903541564941 ], [ "2006", -10.094388961791992 ], [ "▁若い", -10.095943450927734 ], [ "▁玉", -10.096855163574219 ], [ "▁づくり", -10.097257614135742 ], [ "▁神経", -10.098594665527344 ], [ "▁本社", -10.09963321685791 ], [ "▁毎年", -10.100427627563477 ], [ "太郎", -10.10057258605957 ], [ "▁iPhone", -10.100592613220215 ], [ "▁建て", -10.101034164428711 ], [ "▁成", -10.10168743133545 ], [ "ヴィ", -10.102569580078125 ], [ "▁ルール", -10.10290813446045 ], [ "▁食べる", -10.103551864624023 ], [ "▁診断", -10.103609085083008 ], [ "▁キー", -10.10404109954834 ], [ "▁使える", -10.104482650756836 ], [ "もちろん", -10.10480785369873 ], [ "▁果たした", -10.105368614196777 ], [ "▁代わり", -10.106273651123047 ], [ "直", -10.10657024383545 ], [ "▁大分", -10.106819152832031 ], [ "▁楽", -10.107829093933105 ], [ "記", -10.108428001403809 ], [ "▁予防", -10.108612060546875 ], [ "▁2003", -10.10875415802002 ], [ "▁いただける", -10.110048294067383 ], [ "▁部長", -10.11014175415039 ], [ "教", -10.110274314880371 ], [ "▁革命", -10.11054515838623 ], [ "▁山形", -10.110770225524902 ], [ "▁中止", -10.111113548278809 ], [ "▁形態", -10.111159324645996 ], [ "▁あたる", -10.111349105834961 ], [ "▁物件", -10.111620903015137 ], [ "▁オブ", -10.111992835998535 ], [ "林", -10.113627433776855 ], [ "▁域", -10.113818168640137 ], [ "▁エル", -10.113903045654297 ], [ "▁置か", -10.114087104797363 ], [ "▁努力", -10.114179611206055 ], [ "▁耳", -10.114822387695312 ], [ "▁翌", -10.115060806274414 ], [ "x", -10.115073204040527 ], [ "▁55", -10.11527156829834 ], [ "▁髪", -10.116069793701172 ], [ "彦", -10.116384506225586 ], [ "げ", -10.117243766784668 ], [ "以下", -10.117650032043457 ], [ "▁主催", -10.117712020874023 ], [ "エン", -10.117756843566895 ], [ "▁ジャ", -10.118021011352539 ], [ "▁限ら", -10.118071556091309 ], [ "デン", -10.118179321289062 ], [ "▁バランス", -10.118228912353516 ], [ "パー", -10.118247985839844 ], [ "▁どのような", -10.118600845336914 ], [ "▁得た", -10.118637084960938 ], [ "u", -10.11959457397461 ], [ "▁発言", -10.119640350341797 ], [ "▁クレジット", -10.119758605957031 ], [ "▁II", -10.119999885559082 ], [ "▁働く", -10.120654106140137 ], [ "▁感想", -10.120808601379395 ], [ "▁宗教", -10.121011734008789 ], [ "▁規制", -10.12109088897705 ], [ "▁血", -10.121227264404297 ], [ "堂", -10.121368408203125 ], [ "▁カル", -10.121996879577637 ], [ "▁選", -10.12236499786377 ], [ "れて", -10.12311840057373 ], [ "▁田", -10.123229026794434 ], [ "▁■", -10.123257637023926 ], [ "▁パワー", -10.123678207397461 ], [ "▁マンション", -10.123706817626953 ], [ "ッチ", -10.124261856079102 ], [ "▁普通", -10.125060081481934 ], [ "アー", -10.125576972961426 ], [ "▁十", -10.125643730163574 ], [ "▁メリット", -10.126456260681152 ], [ "べ", -10.126784324645996 ], [ "▁入れる", -10.128057479858398 ], [ "▁芸能", -10.128106117248535 ], [ "▁言った", -10.12830638885498 ], [ "▁ファ", -10.128702163696289 ], [ "▁売却", -10.128732681274414 ], [ "▁本部", -10.128783226013184 ], [ "▁カフェ", -10.128854751586914 ], [ "▁トラブル", -10.12916374206543 ], [ "▁務める", -10.129315376281738 ], [ "○", -10.12962818145752 ], [ "▁セール", -10.129900932312012 ], [ "▁ロンドン", -10.130437850952148 ], [ "▁茨城", -10.131446838378906 ], [ "▁手続き", -10.131571769714355 ], [ "▁レイ", -10.13230037689209 ], [ "▁固定", -10.132400512695312 ], [ "▁用語", -10.132448196411133 ], [ "▁No", -10.132650375366211 ], [ "▁イラスト", -10.133376121520996 ], [ "▁過ぎ", -10.133461952209473 ], [ "▁普及", -10.13390064239502 ], [ "▁主人公", -10.134778022766113 ], [ "▁感覚", -10.134844779968262 ], [ "▁うえ", -10.136165618896484 ], [ "▁アート", -10.136492729187012 ], [ "▁活", -10.136899948120117 ], [ "スタ", -10.13744068145752 ], [ "▁コーチ", -10.137838363647461 ], [ "▁利", -10.138105392456055 ], [ "▁ヘア", -10.138705253601074 ], [ "▁共通", -10.139022827148438 ], [ "▁軍事", -10.139049530029297 ], [ "▁事項", -10.140003204345703 ], [ "▁職員", -10.14000415802002 ], [ "チャ", -10.140054702758789 ], [ "▁正規", -10.141352653503418 ], [ "▁充実", -10.14305591583252 ], [ "ある", -10.143348693847656 ], [ "母", -10.143455505371094 ], [ "▁書いた", -10.143980026245117 ], [ "▁レコード", -10.144062995910645 ], [ "ちなみに", -10.144242286682129 ], [ "▁さえ", -10.145636558532715 ], [ "▁ワールド", -10.146834373474121 ], [ "ッド", -10.1469087600708 ], [ "▁項目", -10.147281646728516 ], [ "▁防衛", -10.147761344909668 ], [ "ウス", -10.148383140563965 ], [ "▁チ", -10.14928150177002 ], [ "▁ム", -10.149859428405762 ], [ "▁37", -10.150376319885254 ], [ "▁アーティスト", -10.150586128234863 ], [ "▁内閣", -10.151777267456055 ], [ "▁直後", -10.151970863342285 ], [ "▁上記", -10.152312278747559 ], [ "世", -10.152620315551758 ], [ "▁シート", -10.15313720703125 ], [ "角", -10.153246879577637 ], [ "こう", -10.153270721435547 ], [ "▁比", -10.154783248901367 ], [ "こちら", -10.15495491027832 ], [ "▁徳島", -10.155017852783203 ], [ "▁スクール", -10.15542984008789 ], [ "▁削除", -10.155869483947754 ], [ "っと", -10.156556129455566 ], [ "▁2002", -10.15676212310791 ], [ "あなた", -10.157543182373047 ], [ "ia", -10.157910346984863 ], [ "倉", -10.158506393432617 ], [ "▁得て", -10.158733367919922 ], [ "▁司令", -10.159324645996094 ], [ "▁学び", -10.159610748291016 ], [ "▁くれて", -10.159777641296387 ], [ "▁歩", -10.159812927246094 ], [ "▁各種", -10.159881591796875 ], [ "▁実績", -10.160247802734375 ], [ "▁主演", -10.161070823669434 ], [ "▁ブロック", -10.16110610961914 ], [ "ar", -10.16129207611084 ], [ "▁低下", -10.161492347717285 ], [ "ーズ", -10.162286758422852 ], [ "▁わかる", -10.16247272491455 ], [ "▁新規", -10.162654876708984 ], [ "▁条約", -10.163368225097656 ], [ "▁民族", -10.163848876953125 ], [ "▁事態", -10.164390563964844 ], [ "▁角", -10.165027618408203 ], [ "▁ぐらい", -10.165179252624512 ], [ "式", -10.165266036987305 ], [ "勝", -10.166006088256836 ], [ "▁本格", -10.166057586669922 ], [ "▁復活", -10.166080474853516 ], [ "▁研修", -10.166254997253418 ], [ "▁マー", -10.166668891906738 ], [ "▁恋愛", -10.166831016540527 ], [ "各", -10.167850494384766 ], [ "▁動作", -10.168756484985352 ], [ "▁収集", -10.16929817199707 ], [ "香", -10.169703483581543 ], [ "▁銀", -10.170317649841309 ], [ "▁コミュニケーション", -10.170331001281738 ], [ "▁仙台", -10.170352935791016 ], [ "▁2001", -10.170476913452148 ], [ "▁暮らし", -10.170719146728516 ], [ "▁実は", -10.170921325683594 ], [ "▁ネ", -10.171064376831055 ], [ "ly", -10.171104431152344 ], [ "▁自転車", -10.171478271484375 ], [ "▁良かった", -10.171720504760742 ], [ "▁青森", -10.172158241271973 ], [ "▁か月", -10.172226905822754 ], [ "▁コスト", -10.173460006713867 ], [ "▁統一", -10.17435359954834 ], [ "産", -10.1752347946167 ], [ "世界", -10.175420761108398 ], [ "▁移転", -10.175716400146484 ], [ "▁なぁ", -10.175810813903809 ], [ "▁児童", -10.176252365112305 ], [ "アメリカ", -10.176490783691406 ], [ "▁最後", -10.176624298095703 ], [ "▁演出", -10.176933288574219 ], [ "▁OK", -10.177393913269043 ], [ "▁手段", -10.177395820617676 ], [ "▁本来", -10.177627563476562 ], [ "▁述べて", -10.177640914916992 ], [ "▁開設", -10.178108215332031 ], [ "▁買う", -10.178318977355957 ], [ "▁三重", -10.178378105163574 ], [ "チェ", -10.178425788879395 ], [ "▁求める", -10.17868709564209 ], [ "▁1990", -10.178801536560059 ], [ "▁名誉", -10.179173469543457 ], [ "▁ダイエット", -10.179242134094238 ], [ "▁一定", -10.17951488494873 ], [ "▁ゴール", -10.179759979248047 ], [ "▁このような", -10.179959297180176 ], [ "▁九", -10.180530548095703 ], [ "▁的で", -10.180636405944824 ], [ "▁立", -10.181344985961914 ], [ "浦", -10.181347846984863 ], [ "▁物質", -10.181495666503906 ], [ "▁ブ", -10.182380676269531 ], [ "▁用いて", -10.182509422302246 ], [ "▁空気", -10.183707237243652 ], [ "▁de", -10.18392276763916 ], [ "▁午後", -10.184065818786621 ], [ "▁事情", -10.18482780456543 ], [ "▁輸入", -10.185100555419922 ], [ "▁新宿", -10.18603515625 ], [ "▁39", -10.186256408691406 ], [ "▁交渉", -10.186765670776367 ], [ "▁仏", -10.186928749084473 ], [ "▁比べて", -10.186988830566406 ], [ "am", -10.187105178833008 ], [ "▁商業", -10.187145233154297 ], [ "▁生命", -10.187987327575684 ], [ "▁久", -10.188233375549316 ], [ "レイ", -10.188250541687012 ], [ "▁探して", -10.188350677490234 ], [ "▁ロード", -10.189229965209961 ], [ "14", -10.189322471618652 ], [ "▁長期", -10.189483642578125 ], [ "▁延長", -10.191094398498535 ], [ "▁押し", -10.19178581237793 ], [ "▁好き", -10.192069053649902 ], [ "▁案", -10.192094802856445 ], [ "▁手術", -10.192102432250977 ], [ "▁呼ぶ", -10.192741394042969 ], [ "つまり", -10.19351863861084 ], [ "▁博物", -10.193961143493652 ], [ "re", -10.195416450500488 ], [ "▁高齢", -10.19568920135498 ], [ "▁取る", -10.196154594421387 ], [ "▁留学", -10.196381568908691 ], [ "▁ワイン", -10.197135925292969 ], [ "▁胸", -10.197422981262207 ], [ "▁上昇", -10.197867393493652 ], [ "▁管", -10.198802947998047 ], [ "▁つける", -10.199614524841309 ], [ "▁〉", -10.19969367980957 ], [ "▁兼", -10.200396537780762 ], [ "▁学ぶ", -10.200592041015625 ], [ "▁400", -10.200950622558594 ], [ "アル", -10.201570510864258 ], [ "▁電力", -10.201576232910156 ], [ "▁周囲", -10.202235221862793 ], [ "▁現地", -10.202375411987305 ], [ "▁合計", -10.202400207519531 ], [ "▁加えて", -10.202675819396973 ], [ "しく", -10.202871322631836 ], [ "利", -10.20311164855957 ], [ "▁43", -10.204051971435547 ], [ "▁ゴ", -10.204180717468262 ], [ "保", -10.204325675964355 ], [ "▁みたいな", -10.204351425170898 ], [ "▁群馬", -10.204421043395996 ], [ "▁超える", -10.204585075378418 ], [ "▁陣", -10.204922676086426 ], [ "シン", -10.204987525939941 ], [ "▁うまく", -10.205254554748535 ], [ "▁首相", -10.205608367919922 ], [ "▁にくい", -10.205799102783203 ], [ "▁42", -10.206098556518555 ], [ "▁組み", -10.2063627243042 ], [ "▁ルーム", -10.206772804260254 ], [ "▁素", -10.206779479980469 ], [ "▁買って", -10.207152366638184 ], [ "▁油", -10.207260131835938 ], [ "▁列", -10.207415580749512 ], [ "▁所在", -10.208100318908691 ], [ "▁グリーン", -10.208717346191406 ], [ "▁コンピュータ", -10.208775520324707 ], [ "▁同意", -10.208819389343262 ], [ "字", -10.208826065063477 ], [ "▁CM", -10.20939826965332 ], [ "務", -10.209611892700195 ], [ "永", -10.209774017333984 ], [ "▁北部", -10.210318565368652 ], [ "▁言える", -10.210441589355469 ], [ "▁アー", -10.210592269897461 ], [ "春", -10.211310386657715 ], [ "▁除く", -10.21160888671875 ], [ "▁最初", -10.212051391601562 ], [ "▁太", -10.21212100982666 ], [ "▁論文", -10.212286949157715 ], [ "軍", -10.213054656982422 ], [ "▁勢力", -10.213224411010742 ], [ "バン", -10.213245391845703 ], [ "まず", -10.213578224182129 ], [ "真", -10.213987350463867 ], [ "▁レンタル", -10.214136123657227 ], [ "▁保育", -10.21428394317627 ], [ "トラ", -10.215141296386719 ], [ "▁原作", -10.215335845947266 ], [ "▁処分", -10.216004371643066 ], [ "▁多かった", -10.216009140014648 ], [ "▁ストレス", -10.216010093688965 ], [ "▁ストア", -10.216461181640625 ], [ "▁生まれる", -10.21728801727295 ], [ "死", -10.21760082244873 ], [ "▁すぎる", -10.217828750610352 ], [ "▁作った", -10.218454360961914 ], [ "▁林", -10.219106674194336 ], [ "▁初代", -10.21938705444336 ], [ "▁周", -10.219623565673828 ], [ "2005", -10.219664573669434 ], [ "▁古い", -10.219900131225586 ], [ "空", -10.220401763916016 ], [ "薬", -10.220454216003418 ], [ "▁どのように", -10.220763206481934 ], [ "▁モノ", -10.221078872680664 ], [ "▁答え", -10.221389770507812 ], [ "キロ", -10.22156810760498 ], [ "ネット", -10.222054481506348 ], [ "▁比較的", -10.222319602966309 ], [ "▁駐車", -10.222848892211914 ], [ "▁応じて", -10.22307014465332 ], [ "取", -10.22387981414795 ], [ "▁源", -10.224019050598145 ], [ "▁材料", -10.224226951599121 ], [ "\"", -10.224627494812012 ], [ "▁将軍", -10.224689483642578 ], [ "有", -10.224791526794434 ], [ "▁季節", -10.22515869140625 ], [ "▁財", -10.22670841217041 ], [ "▁供給", -10.22671890258789 ], [ "史", -10.227409362792969 ], [ "▁目指す", -10.228360176086426 ], [ "▁攻略", -10.228671073913574 ], [ "▁定", -10.229308128356934 ], [ "▁地上", -10.229634284973145 ], [ "▁徹底", -10.229820251464844 ], [ "▁ずつ", -10.230225563049316 ], [ "多", -10.231148719787598 ], [ "▁独自の", -10.231205940246582 ], [ "ジー", -10.231724739074707 ], [ "▁44", -10.232118606567383 ], [ "船", -10.232385635375977 ], [ "▁移行", -10.23312759399414 ], [ "▁同士", -10.233534812927246 ], [ "▁予算", -10.234079360961914 ], [ "▁関", -10.234198570251465 ], [ "▁佐賀", -10.23452091217041 ], [ "▁創設", -10.234539031982422 ], [ "▁弟", -10.235224723815918 ], [ "▁鏡", -10.235508918762207 ], [ "▁キッズ", -10.23554801940918 ], [ "▁艦隊", -10.235628128051758 ], [ "▁化粧", -10.235630989074707 ], [ "▁徒歩", -10.236654281616211 ], [ "▁探す", -10.236726760864258 ], [ "▁チャンネル", -10.237210273742676 ], [ "ント", -10.237351417541504 ], [ "▁ダンス", -10.238512992858887 ], [ "▁野菜", -10.238831520080566 ], [ "▁豊", -10.239356994628906 ], [ "める", -10.240373611450195 ], [ "▁育成", -10.241013526916504 ], [ "シア", -10.241768836975098 ], [ "▁クリスマス", -10.242165565490723 ], [ "▁技", -10.242307662963867 ], [ "▁ノースフェイス", -10.242383003234863 ], [ "▁ユニット", -10.242718696594238 ], [ "▁嬉しい", -10.242877960205078 ], [ "▁残り", -10.24290943145752 ], [ "▁閲覧", -10.24309253692627 ], [ "▁性格", -10.244415283203125 ], [ "▁トイレ", -10.24507999420166 ], [ "▁コーヒー", -10.245301246643066 ], [ "●", -10.245811462402344 ], [ "▁楽しむ", -10.245985984802246 ], [ "▁置いて", -10.246166229248047 ], [ "▁忠", -10.247074127197266 ], [ ",000", -10.247445106506348 ], [ "▁リー", -10.247515678405762 ], [ "▁打ち", -10.248457908630371 ], [ "▁む", -10.24931526184082 ], [ "父", -10.249855995178223 ], [ "蔵", -10.250210762023926 ], [ "▁取り組み", -10.25031566619873 ], [ "▁栃木", -10.250349998474121 ], [ "▁呼び", -10.250398635864258 ], [ "▁インタビュー", -10.250503540039062 ], [ "▁基地", -10.25117015838623 ], [ "意", -10.251445770263672 ], [ "▁持た", -10.251594543457031 ], [ "▁変", -10.25228214263916 ], [ "▁和歌山", -10.252452850341797 ], [ "▁岩手", -10.252676963806152 ], [ "▁同様", -10.25295639038086 ], [ "▁とおり", -10.253084182739258 ], [ "▁公共", -10.253095626831055 ], [ "▁つく", -10.253410339355469 ], [ "▁ホワイト", -10.253459930419922 ], [ "▁オール", -10.25449275970459 ], [ "▁材", -10.254768371582031 ], [ "▁平和", -10.254971504211426 ], [ "▁憲法", -10.255131721496582 ], [ "▁スキル", -10.255338668823242 ], [ "▁査定", -10.255417823791504 ], [ "▁最後に", -10.25562858581543 ], [ "▁程", -10.255643844604492 ], [ "▁継承", -10.256033897399902 ], [ "▁よろしく", -10.258008003234863 ], [ "▁傷", -10.258216857910156 ], [ "▁―", -10.258612632751465 ], [ "▁地下", -10.258716583251953 ], [ "▁藤", -10.258809089660645 ], [ "▁可能に", -10.259041786193848 ], [ "▁極", -10.259828567504883 ], [ "2000", -10.260284423828125 ], [ "▁聞いた", -10.260334014892578 ], [ "もし", -10.260987281799316 ], [ "駅", -10.261507987976074 ], [ "▁バイク", -10.261528968811035 ], [ "▁有名な", -10.261678695678711 ], [ "▁申し上げ", -10.261812210083008 ], [ "▁当日", -10.26229190826416 ], [ "▁特集", -10.26279354095459 ], [ "▁送信", -10.263455390930176 ], [ "▁観測", -10.263607025146484 ], [ "▁いれば", -10.264095306396484 ], [ "▁ほ", -10.264127731323242 ], [ "▁ネタ", -10.264459609985352 ], [ "▁込んだ", -10.265904426574707 ], [ "▁資産", -10.266158103942871 ], [ "▁進行", -10.26626968383789 ], [ "▁終わった", -10.266983985900879 ], [ "▁根", -10.267513275146484 ], [ "▁1980", -10.267542839050293 ], [ "▁目指して", -10.267694473266602 ], [ "ED", -10.268234252929688 ], [ "▁診療", -10.268455505371094 ], [ "今年", -10.268547058105469 ], [ "▁手法", -10.268799781799316 ], [ "▁脱", -10.2689790725708 ], [ "伝", -10.269187927246094 ], [ "▁置く", -10.269268989562988 ], [ "ッシュ", -10.269268989562988 ], [ "▁ロゴ", -10.269367218017578 ], [ "▁ゲスト", -10.269486427307129 ], [ "13", -10.26972484588623 ], [ "▁感情", -10.27202320098877 ], [ "▁文書", -10.27203369140625 ], [ "当初", -10.27252197265625 ], [ "▁湾", -10.272761344909668 ], [ "だが", -10.273442268371582 ], [ "▁最初に", -10.273465156555176 ], [ "▁扱い", -10.27420425415039 ], [ "▁エロ", -10.274316787719727 ], [ "▁箱", -10.27452278137207 ], [ "▁高知", -10.274967193603516 ], [ "セン", -10.275060653686523 ], [ "▁急", -10.275070190429688 ], [ "▁オフィス", -10.27512264251709 ], [ "▁進め", -10.275641441345215 ], [ "▁山梨", -10.27569580078125 ], [ "ゾ", -10.276543617248535 ], [ "ジュ", -10.27712345123291 ], [ "▁縁", -10.277307510375977 ], [ "▁スポット", -10.277511596679688 ], [ "歌", -10.277637481689453 ], [ "▁杯", -10.27868938446045 ], [ "陽", -10.278707504272461 ], [ "▁経由", -10.278886795043945 ], [ "▁いえば", -10.278934478759766 ], [ "▁始まった", -10.279053688049316 ], [ "言", -10.279109001159668 ], [ "▁単", -10.27911376953125 ], [ "▁堂", -10.27929401397705 ], [ "▁生きて", -10.279444694519043 ], [ "▁欧", -10.27973747253418 ], [ "▁書く", -10.279924392700195 ], [ "▁姿勢", -10.279987335205078 ], [ "▁事例", -10.280543327331543 ], [ "▁ルー", -10.280649185180664 ], [ "▁オーストラリア", -10.280738830566406 ], [ "▁IT", -10.28093147277832 ], [ "園", -10.281234741210938 ], [ "▁緑", -10.281266212463379 ], [ "▁否定", -10.281597137451172 ], [ "▁食べて", -10.281678199768066 ], [ "▁兄", -10.282051086425781 ], [ "約", -10.282184600830078 ], [ "▁疑問", -10.282252311706543 ], [ "▁江", -10.282488822937012 ], [ "▁無理", -10.28331470489502 ], [ "個人", -10.283439636230469 ], [ "at", -10.284222602844238 ], [ "▁formula", -10.2847900390625 ], [ "▁ゴルフ", -10.287172317504883 ], [ "▁有効", -10.287229537963867 ], [ "▁スマートフォン", -10.287385940551758 ], [ "▁決め", -10.287618637084961 ], [ "▁想像", -10.28805923461914 ], [ "▁政", -10.289105415344238 ], [ "▁伊", -10.289315223693848 ], [ "▁住んで", -10.289346694946289 ], [ "▁災害", -10.28990650177002 ], [ "▁路", -10.291058540344238 ], [ "▁像", -10.291245460510254 ], [ "▁王座", -10.291836738586426 ], [ "▁解消", -10.292037010192871 ], [ "▁史上", -10.292317390441895 ], [ "▁コミック", -10.292651176452637 ], [ "▁犯罪", -10.292767524719238 ], [ "▁¥", -10.293030738830566 ], [ "▁キッチン", -10.293268203735352 ], [ "▁タグ", -10.293280601501465 ], [ "▁41", -10.293612480163574 ], [ "来", -10.294169425964355 ], [ "▁伴う", -10.29469108581543 ], [ "ート", -10.294713973999023 ], [ "▁翻訳", -10.294779777526855 ], [ "▁逮捕", -10.294806480407715 ], [ "▁美しい", -10.294888496398926 ], [ "▁聞く", -10.296477317810059 ], [ "▁教師", -10.296792030334473 ], [ "▁若", -10.296987533569336 ], [ "▁上げる", -10.297057151794434 ], [ "▁いわゆる", -10.297213554382324 ], [ "リス", -10.297266006469727 ], [ "▁課", -10.298113822937012 ], [ "輪", -10.298396110534668 ], [ "県", -10.298681259155273 ], [ "▁くん", -10.299677848815918 ], [ "▁u", -10.299732208251953 ], [ "▁術", -10.30102825164795 ], [ "例", -10.30107307434082 ], [ "▁栄養", -10.30151653289795 ], [ "▁Amazon", -10.301549911499023 ], [ "▁相続", -10.302424430847168 ], [ "▁原子", -10.302757263183594 ], [ "▁当該", -10.302800178527832 ], [ "コー", -10.303447723388672 ], [ "▁全部", -10.303569793701172 ], [ "ひ", -10.304044723510742 ], [ "装", -10.304274559020996 ], [ "▁br", -10.305057525634766 ], [ "▁基づく", -10.306203842163086 ], [ "パン", -10.306390762329102 ], [ "▁カン", -10.306808471679688 ], [ "▁受付", -10.306927680969238 ], [ "骨", -10.306930541992188 ], [ "▁回答", -10.30696964263916 ], [ "▁吉", -10.307116508483887 ], [ "ティー", -10.307409286499023 ], [ "▁メダル", -10.30815315246582 ], [ "▁替え", -10.308550834655762 ], [ "▁優先", -10.308573722839355 ], [ "▁守る", -10.308721542358398 ], [ "人物", -10.308985710144043 ], [ "夜", -10.309078216552734 ], [ "品", -10.30964183807373 ], [ "▁パーク", -10.309723854064941 ], [ "▁展", -10.310312271118164 ], [ "一般", -10.310426712036133 ], [ "▁In", -10.310674667358398 ], [ "れた", -10.311141967773438 ], [ "▁出力", -10.311250686645508 ], [ "介", -10.311508178710938 ], [ "▁働いて", -10.311566352844238 ], [ "▁伝説", -10.312043190002441 ], [ "▁変換", -10.312213897705078 ], [ "▁中継", -10.3123140335083 ], [ "▁応募", -10.312585830688477 ], [ "店", -10.312658309936523 ], [ "▁イオン", -10.313222885131836 ], [ "21", -10.313742637634277 ], [ "il", -10.314043045043945 ], [ "このような", -10.31427001953125 ], [ "▁大手", -10.314430236816406 ], [ "▁考慮", -10.314496994018555 ], [ "▁そのもの", -10.314847946166992 ], [ "▁アフリカ", -10.315502166748047 ], [ "▁歌手", -10.31650161743164 ], [ "▁穴", -10.316633224487305 ], [ "任", -10.316742897033691 ], [ "▁保有", -10.3167724609375 ], [ "▁必要に", -10.316987991333008 ], [ "クラ", -10.31732177734375 ], [ "公", -10.317361831665039 ], [ "▁巻き", -10.31736946105957 ], [ "▁協議", -10.317549705505371 ], [ "▁st", -10.317668914794922 ], [ "▁刊行", -10.318114280700684 ], [ "▁レストラン", -10.319147109985352 ], [ "宗", -10.319180488586426 ], [ "樹", -10.319537162780762 ], [ "▁大切な", -10.319780349731445 ], [ "▁セキュリティ", -10.31999683380127 ], [ "▁合い", -10.320281982421875 ], [ "▁いえ", -10.320688247680664 ], [ "▁まとめて", -10.320998191833496 ], [ "▁かかり", -10.321187973022461 ], [ "▁立て", -10.321287155151367 ], [ "▁言えば", -10.32142448425293 ], [ "▁兄弟", -10.321900367736816 ], [ "|", -10.322455406188965 ], [ "▁気分", -10.322455406188965 ], [ "越", -10.322491645812988 ], [ "▁発信", -10.322968482971191 ], [ "▁再開", -10.323111534118652 ], [ "岡山", -10.323217391967773 ], [ "▁連盟", -10.323295593261719 ], [ "▁令和", -10.323410987854004 ], [ "▁廃", -10.323676109313965 ], [ "▁損害", -10.323831558227539 ], [ "▁場面", -10.323908805847168 ], [ "▁ガイド", -10.324475288391113 ], [ "▁転職", -10.324549674987793 ], [ "▁罪", -10.324551582336426 ], [ "▁予選", -10.324552536010742 ], [ "広", -10.324559211730957 ], [ "▁愛媛", -10.324742317199707 ], [ "▁サーバー", -10.324773788452148 ], [ "▁片", -10.325254440307617 ], [ "▁活性", -10.325481414794922 ], [ "▁拡張", -10.32558822631836 ], [ "▁〈", -10.32564640045166 ], [ "▁国道", -10.327262878417969 ], [ "▁窓", -10.327431678771973 ], [ "▁アカウント", -10.32778263092041 ], [ "澤", -10.328670501708984 ], [ "▁変わって", -10.328695297241211 ], [ "▁療法", -10.328722953796387 ], [ "▁小さい", -10.328736305236816 ], [ "▁プラス", -10.328839302062988 ], [ "▁承認", -10.329033851623535 ], [ "▁かかわら", -10.32906723022461 ], [ "▁ボール", -10.329224586486816 ], [ "▁筋", -10.329428672790527 ], [ "▁当選", -10.329472541809082 ], [ "▁知事", -10.329477310180664 ], [ "▁成果", -10.329695701599121 ], [ "▁すぎ", -10.329834938049316 ], [ "▁たくさんの", -10.329888343811035 ], [ "▁น", -10.329916000366211 ], [ "▁端末", -10.330236434936523 ], [ "▁素晴らしい", -10.330312728881836 ], [ "▁会話", -10.330910682678223 ], [ "▁カテゴリー", -10.33116340637207 ], [ "土", -10.33172607421875 ], [ "▁ならば", -10.331989288330078 ], [ "▁変わり", -10.332175254821777 ], [ "▁老", -10.332212448120117 ], [ "タイ", -10.332416534423828 ], [ "▁主要", -10.33281421661377 ], [ "役", -10.332989692687988 ], [ "▁肩", -10.333133697509766 ], [ "▁ころ", -10.333293914794922 ], [ "90", -10.33350944519043 ], [ "▁午前", -10.334228515625 ], [ "▁滋賀", -10.3348970413208 ], [ "▁悪く", -10.335927963256836 ], [ "▁秀", -10.336341857910156 ], [ "▁富士", -10.336898803710938 ], [ "▁余", -10.336955070495605 ], [ "ード", -10.33708381652832 ], [ "▁補助", -10.337424278259277 ], [ "▁概念", -10.337969779968262 ], [ "▁参戦", -10.33797836303711 ], [ "▁歯科", -10.338166236877441 ], [ "▁祝い", -10.338294982910156 ], [ "*", -10.338508605957031 ], [ "▁合", -10.338797569274902 ], [ "▁デュベティカ", -10.33934211730957 ], [ "▁命令", -10.339689254760742 ], [ "▁ギ", -10.340006828308105 ], [ "▁人材", -10.340754508972168 ], [ "▁つか", -10.341043472290039 ], [ "▁回転", -10.341477394104004 ], [ "▁考えた", -10.341629028320312 ], [ "▁百", -10.34170150756836 ], [ "▁なんか", -10.341763496398926 ], [ "奈", -10.342241287231445 ], [ "ヨ", -10.343354225158691 ], [ "▁以後", -10.343472480773926 ], [ "▁ギフト", -10.34399700164795 ], [ "▁エステ", -10.34416389465332 ], [ "▁我々", -10.344646453857422 ], [ "▁独", -10.3447904586792 ], [ "▁CBD", -10.345341682434082 ], [ "▁描いた", -10.34559440612793 ], [ "▁相場", -10.345691680908203 ], [ "um", -10.346540451049805 ], [ "かつて", -10.346600532531738 ], [ "▁系列", -10.346840858459473 ], [ "古", -10.347200393676758 ], [ "論", -10.347315788269043 ], [ "不", -10.347707748413086 ], [ "▁オフ", -10.347711563110352 ], [ "▁結局", -10.347859382629395 ], [ "▁キャ", -10.348244667053223 ], [ "オー", -10.348637580871582 ], [ "▁武器", -10.348737716674805 ], [ "▁1999", -10.348862648010254 ], [ "▁軸", -10.349011421203613 ], [ "▁スペシャル", -10.3490571975708 ], [ "▁証拠", -10.349150657653809 ], [ "▁THE", -10.349172592163086 ], [ "▁京", -10.349203109741211 ], [ "▁ボディ", -10.349509239196777 ], [ "▁ガラス", -10.349565505981445 ], [ "▁ハン", -10.349692344665527 ], [ "▁隻", -10.349742889404297 ], [ "▁著者", -10.349776268005371 ], [ "▁更に", -10.349796295166016 ], [ "トル", -10.349839210510254 ], [ "球", -10.350180625915527 ], [ "▁現象", -10.3507080078125 ], [ "▁ハー", -10.350826263427734 ], [ "▁64", -10.351364135742188 ], [ "▁執筆", -10.35138988494873 ], [ "▁同盟", -10.351421356201172 ], [ "▁欧州", -10.351430892944336 ], [ "ブラ", -10.351686477661133 ], [ "▁疾患", -10.3517427444458 ], [ "▁有する", -10.351768493652344 ], [ "▁詳しく", -10.351832389831543 ], [ "▁要望", -10.351848602294922 ], [ "▁披露", -10.351983070373535 ], [ "▁始まる", -10.35221004486084 ], [ "▁谷", -10.352385520935059 ], [ "▁マル", -10.352758407592773 ], [ "▁首都", -10.352895736694336 ], [ "ない", -10.3539400100708 ], [ "米", -10.35404109954834 ], [ "▁通過", -10.354351043701172 ], [ "▁危機", -10.354893684387207 ], [ "▁措置", -10.354979515075684 ], [ "▁ボックス", -10.35595417022705 ], [ "▁ブック", -10.356493949890137 ], [ "▁パーツ", -10.35720443725586 ], [ "▁鳥取", -10.357298851013184 ], [ "▁いろいろ", -10.358075141906738 ], [ "河", -10.358293533325195 ], [ "▁がん", -10.358309745788574 ], [ "藤", -10.358431816101074 ], [ "也", -10.358745574951172 ], [ "▁建", -10.359408378601074 ], [ "点", -10.359424591064453 ], [ "▁トン", -10.359647750854492 ], [ "▁セミナー", -10.35976791381836 ], [ "状", -10.360755920410156 ], [ "▁惑星", -10.360832214355469 ], [ "▁竹", -10.360955238342285 ], [ "▁オススメ", -10.361659049987793 ], [ "▁HP", -10.362462997436523 ], [ "▁弊社", -10.362558364868164 ], [ "▁市長", -10.362619400024414 ], [ "▁緊急", -10.362659454345703 ], [ "▁OS", -10.362911224365234 ], [ "▁ドライバー", -10.363279342651367 ], [ "▁経", -10.36337947845459 ], [ "▁結", -10.36474609375 ], [ "▁°", -10.364830017089844 ], [ "▁辞典", -10.3649263381958 ], [ "ルト", -10.36512279510498 ], [ "泉", -10.365804672241211 ], [ "八", -10.366159439086914 ], [ "▁シティ", -10.3662109375 ], [ "▁習慣", -10.36627197265625 ], [ "▁進学", -10.366511344909668 ], [ "▁深い", -10.367547988891602 ], [ "▁翌年", -10.367928504943848 ], [ "▁数字", -10.36801528930664 ], [ "▁チャ", -10.36807918548584 ], [ "▁忘れ", -10.368093490600586 ], [ "▁47", -10.368891716003418 ], [ "▁物理", -10.369668006896973 ], [ "チン", -10.369876861572266 ], [ "進", -10.369884490966797 ], [ "▁合う", -10.370368003845215 ], [ "▁レッスン", -10.370404243469238 ], [ "賀", -10.370760917663574 ], [ "▁文章", -10.3710355758667 ], [ "▁思想", -10.371237754821777 ], [ "▁ライ", -10.371244430541992 ], [ "▁楽しめる", -10.371539115905762 ], [ "▁生み", -10.372221946716309 ], [ "ation", -10.372426986694336 ], [ "▁メジャー", -10.3726224899292 ], [ "曲", -10.372980117797852 ], [ "▁判定", -10.37314224243164 ], [ "▁探偵", -10.3733491897583 ], [ "▁re", -10.37336540222168 ], [ "▁定め", -10.373544692993164 ], [ "▁発達", -10.373565673828125 ], [ "▁雇用", -10.373750686645508 ], [ "▁魔法", -10.374417304992676 ], [ "▁セックス", -10.375133514404297 ], [ "▁進んで", -10.375678062438965 ], [ "夏", -10.3758544921875 ], [ "▁エン", -10.375908851623535 ], [ "▁指名", -10.376277923583984 ], [ "ER", -10.37660026550293 ], [ "▁牛", -10.376936912536621 ], [ "▁志", -10.377666473388672 ], [ "25", -10.37808895111084 ], [ "▁限", -10.378119468688965 ], [ "▁主な", -10.379281044006348 ], [ "▁ティ", -10.379584312438965 ], [ "▁民間", -10.379637718200684 ], [ "▁入社", -10.379780769348145 ], [ "制", -10.379859924316406 ], [ "2004", -10.3800048828125 ], [ "▁詩", -10.380074501037598 ], [ "▁ぞ", -10.380115509033203 ], [ "▁やら", -10.38046932220459 ], [ "▁●", -10.380616188049316 ], [ "▁香川", -10.380911827087402 ], [ "▁在", -10.381392478942871 ], [ "▁生き", -10.381439208984375 ], [ "▁普段", -10.381511688232422 ], [ "都", -10.381539344787598 ], [ "▁あらゆる", -10.381929397583008 ], [ "▁あげ", -10.382040023803711 ], [ "▁始めて", -10.38241958618164 ], [ "▁スピード", -10.382558822631836 ], [ "▁刺激", -10.382650375366211 ], [ "▁概要", -10.382974624633789 ], [ "▁天然", -10.383219718933105 ], [ "▁冊", -10.384076118469238 ], [ "▁例えば", -10.384346008300781 ], [ "▁昇格", -10.384509086608887 ], [ "ウェイ", -10.384779930114746 ], [ "▁ジャンル", -10.384949684143066 ], [ "トリ", -10.385407447814941 ], [ "▁脚本", -10.386109352111816 ], [ "▁同一", -10.386436462402344 ], [ "▁乾燥", -10.386594772338867 ], [ "▁結ぶ", -10.386606216430664 ], [ "▁落ち", -10.386618614196777 ], [ "▁永", -10.386853218078613 ], [ "めて", -10.386921882629395 ], [ "▁タウン", -10.387154579162598 ], [ "▁半島", -10.387262344360352 ], [ "▁面積", -10.387463569641113 ], [ "▁戸", -10.387630462646484 ], [ "ざ", -10.387742042541504 ], [ "▁ID", -10.387887954711914 ], [ "▁パートナー", -10.388225555419922 ], [ "▁パック", -10.388298034667969 ], [ "▁男女", -10.388802528381348 ], [ "ぼ", -10.388839721679688 ], [ "▁雑貨", -10.388845443725586 ], [ "▁商標", -10.388978004455566 ], [ "▁分割", -10.38909912109375 ], [ "森", -10.390250205993652 ], [ "▁テーブル", -10.390382766723633 ], [ "ay", -10.390890121459961 ], [ "▁宿", -10.391096115112305 ], [ "▁サイド", -10.391164779663086 ], [ "▁記者", -10.391397476196289 ], [ "▁進めて", -10.39148998260498 ], [ "▁郵便", -10.391502380371094 ], [ "ヘ", -10.392293930053711 ], [ "▁外部", -10.392454147338867 ], [ "▁ロング", -10.392610549926758 ], [ "▁幸", -10.392681121826172 ], [ "▁いつ", -10.392873764038086 ], [ "▁福", -10.393143653869629 ], [ "▁コンサート", -10.393157005310059 ], [ "▁期限", -10.39369010925293 ], [ "▁語って", -10.39419174194336 ], [ "▁大陸", -10.394214630126953 ], [ "かい", -10.394264221191406 ], [ "19", -10.394939422607422 ], [ "▁開", -10.395060539245605 ], [ "▁取材", -10.395159721374512 ], [ "▁課程", -10.395255088806152 ], [ "▁施行", -10.395392417907715 ], [ "▁Re", -10.395400047302246 ], [ "▁金属", -10.395685195922852 ], [ "略歴", -10.395817756652832 ], [ "話", -10.395822525024414 ], [ "▁両方", -10.3958740234375 ], [ "▁ママ", -10.396178245544434 ], [ "愛", -10.397112846374512 ], [ "▁ジェ", -10.397401809692383 ], [ "▁顧客", -10.397616386413574 ], [ "旧", -10.39778995513916 ], [ "▁ミス", -10.398008346557617 ], [ "▁問わ", -10.398163795471191 ], [ "▁求めて", -10.398272514343262 ], [ "▁居", -10.398802757263184 ], [ "▁表面", -10.3989839553833 ], [ "▁1970", -10.399073600769043 ], [ "▁過程", -10.399077415466309 ], [ "▁統計", -10.399312019348145 ], [ "▁AV", -10.399459838867188 ], [ "まり", -10.399803161621094 ], [ "▁分離", -10.399940490722656 ], [ "▁上位", -10.39996337890625 ], [ "▁母親", -10.40032958984375 ], [ "▁カジノ", -10.400348663330078 ], [ "▁持った", -10.400863647460938 ], [ "▁変える", -10.400907516479492 ], [ "▁地図", -10.401063919067383 ], [ "▁上げて", -10.401177406311035 ], [ "▁基づいて", -10.401188850402832 ], [ "▁ようで", -10.401477813720703 ], [ "ジャー", -10.401653289794922 ], [ "▁指す", -10.402029991149902 ], [ "▁オランダ", -10.402191162109375 ], [ "▁関心", -10.40241527557373 ], [ "調", -10.402687072753906 ], [ "▁楽しく", -10.402807235717773 ], [ "]", -10.40290355682373 ], [ "員", -10.403618812561035 ], [ "▁向かう", -10.404180526733398 ], [ "▁クリア", -10.404272079467773 ], [ "▁同様の", -10.404342651367188 ], [ "▁じ", -10.404364585876465 ], [ "▁もし", -10.404585838317871 ], [ "▁知れ", -10.404641151428223 ], [ "▁安く", -10.40524673461914 ], [ "▁けれども", -10.405365943908691 ], [ "▁就職", -10.405367851257324 ], [ "▁太平洋", -10.405671119689941 ], [ "開", -10.406060218811035 ], [ "▁現状", -10.406076431274414 ], [ "▁51", -10.406150817871094 ], [ "▁鳥", -10.40654182434082 ], [ "▁用いる", -10.406722068786621 ], [ "▁54", -10.40701961517334 ], [ "▁ダム", -10.407090187072754 ], [ "▁いま", -10.408557891845703 ], [ "▁リアル", -10.408573150634766 ], [ "▁クリニック", -10.408661842346191 ], [ "▁ルート", -10.408803939819336 ], [ "連", -10.40881633758545 ], [ "▁球", -10.408885955810547 ], [ "▁発送", -10.408915519714355 ], [ "▁最高の", -10.40892219543457 ], [ "▁かける", -10.410067558288574 ], [ "▁体育", -10.410075187683105 ], [ "▁ブラ", -10.410375595092773 ], [ "▁軌道", -10.411060333251953 ], [ "60", -10.411382675170898 ], [ "▁哲学", -10.411991119384766 ], [ "▁宗", -10.41267204284668 ], [ "▁友", -10.412779808044434 ], [ "▁厚", -10.412906646728516 ], [ "▁把握", -10.413262367248535 ], [ "▁進む", -10.413434982299805 ], [ "だから", -10.413847923278809 ], [ "▁銃", -10.413938522338867 ], [ "ter", -10.414321899414062 ], [ "紀", -10.414596557617188 ], [ "▁(3)", -10.414834022521973 ], [ "大学", -10.41535758972168 ], [ "▁向かって", -10.415421485900879 ], [ "▁ツ", -10.41596794128418 ], [ "▁学院", -10.416036605834961 ], [ "▁現役", -10.416062355041504 ], [ "▁遠", -10.416236877441406 ], [ "24", -10.417057037353516 ], [ "▁聞か", -10.417810440063477 ], [ "▁父親", -10.417868614196777 ], [ "たら", -10.417909622192383 ], [ "▁シン", -10.41791820526123 ], [ "▁浮気", -10.418021202087402 ], [ "▁プレイヤー", -10.418825149536133 ], [ "▁香", -10.418827056884766 ], [ "▁ボード", -10.418862342834473 ], [ "初", -10.41972827911377 ], [ "▁改造", -10.419764518737793 ], [ "▁収納", -10.420071601867676 ], [ "▁逆に", -10.420195579528809 ], [ "▁んだろう", -10.420354843139648 ], [ "声", -10.420442581176758 ], [ "▁最低", -10.420510292053223 ], [ "▁ギター", -10.420561790466309 ], [ "▁解散", -10.420865058898926 ], [ "▁進化", -10.421073913574219 ], [ "▁入手", -10.42123794555664 ], [ "▁龍", -10.421448707580566 ], [ "テレビ", -10.421660423278809 ], [ "ったり", -10.421821594238281 ], [ "▁趣味", -10.4219388961792 ], [ "▁抵抗", -10.422475814819336 ], [ "▁j", -10.422775268554688 ], [ "▁ヴィ", -10.422904014587402 ], [ "j", -10.42332935333252 ], [ "▁取って", -10.423440933227539 ], [ "チャー", -10.424064636230469 ], [ "▁しかし", -10.42443561553955 ], [ "▁グローバル", -10.424629211425781 ], [ "▁いたら", -10.424633979797363 ], [ "▁自信", -10.424702644348145 ], [ "ング", -10.424796104431152 ], [ "表", -10.424872398376465 ], [ "▁日記", -10.424890518188477 ], [ "キン", -10.425881385803223 ], [ "▁発揮", -10.426017761230469 ], [ "▁遺産", -10.426451683044434 ], [ "えて", -10.427022933959961 ], [ "▁手数", -10.427421569824219 ], [ "▁続けた", -10.427456855773926 ], [ "バス", -10.427654266357422 ], [ "▁キャラ", -10.427778244018555 ], [ "▁認知", -10.429009437561035 ], [ "ッカー", -10.429706573486328 ], [ "▁レギュラー", -10.430030822753906 ], [ "大阪", -10.430656433105469 ], [ "▁初心", -10.430686950683594 ], [ "▁楽器", -10.43118667602539 ], [ "▁そ", -10.431268692016602 ], [ "▁指", -10.431403160095215 ], [ "彼女", -10.432101249694824 ], [ "▁確定", -10.432596206665039 ], [ "▁しばらく", -10.432938575744629 ], [ "▁免許", -10.433759689331055 ], [ "▁孫", -10.433796882629395 ], [ "▁Android", -10.434316635131836 ], [ "▁飛び", -10.434525489807129 ], [ "▁ก", -10.434849739074707 ], [ "▁ユ", -10.435091972351074 ], [ "▁1998", -10.435378074645996 ], [ "さて", -10.435420989990234 ], [ "▁渋谷", -10.435454368591309 ], [ "キー", -10.435776710510254 ], [ "▁機種", -10.436023712158203 ], [ "2022", -10.436248779296875 ], [ "▁羽", -10.436261177062988 ], [ "▁解放", -10.436602592468262 ], [ "▁近代", -10.436779022216797 ], [ "▁測定", -10.436847686767578 ], [ "▁乱", -10.437007904052734 ], [ "▁違反", -10.437294006347656 ], [ "▁150", -10.437515258789062 ], [ "▁従事", -10.437540054321289 ], [ "▁感じた", -10.437638282775879 ], [ "▁地位", -10.437732696533203 ], [ "多く", -10.438329696655273 ], [ "▁ドア", -10.439351081848145 ], [ "▁述べた", -10.439953804016113 ], [ "▁焼き", -10.440441131591797 ], [ "科", -10.44051456451416 ], [ "▁霊", -10.440533638000488 ], [ "▁─", -10.440621376037598 ], [ "▁拒否", -10.440677642822266 ], [ "▁深く", -10.44104290008545 ], [ "▁指示", -10.441056251525879 ], [ "▁インチ", -10.441125869750977 ], [ "▁ショッピング", -10.441317558288574 ], [ "▁規約", -10.441384315490723 ], [ "▁結構", -10.441636085510254 ], [ "▁未満", -10.44164752960205 ], [ "▁競走", -10.441686630249023 ], [ "to", -10.441798210144043 ], [ "▁チケット", -10.441951751708984 ], [ "リック", -10.442530632019043 ], [ "さん", -10.442891120910645 ], [ "▁テリー", -10.442906379699707 ], [ "▁笑い", -10.44308853149414 ], [ "▁フィ", -10.443546295166016 ], [ "せる", -10.443928718566895 ], [ "▁用いた", -10.444358825683594 ], [ "▁促進", -10.444682121276855 ], [ "▁相互", -10.444769859313965 ], [ "▁防御", -10.444964408874512 ], [ "▁特典", -10.445025444030762 ], [ "▁保", -10.445218086242676 ], [ "▁コー", -10.445477485656738 ], [ "▁マスター", -10.44552993774414 ], [ "▁正しい", -10.44602108001709 ], [ "▁アクション", -10.446952819824219 ], [ "▁しばしば", -10.447405815124512 ], [ "▁被", -10.447565078735352 ], [ "▁造", -10.447598457336426 ], [ "▁つまり", -10.448244094848633 ], [ "▁声優", -10.44851303100586 ], [ "ミン", -10.448626518249512 ], [ "▁掛け", -10.449970245361328 ], [ "▁コレクション", -10.450114250183105 ], [ "▁遊", -10.450190544128418 ], [ "▁こういう", -10.450335502624512 ], [ "▁開か", -10.450450897216797 ], [ "地理", -10.450501441955566 ], [ "▁まずは", -10.450749397277832 ], [ "▁海岸", -10.450986862182617 ], [ "▁風呂", -10.451064109802246 ], [ "▁弱", -10.451189994812012 ], [ "▁創業", -10.451395034790039 ], [ "バル", -10.451920509338379 ], [ "te", -10.452178955078125 ], [ "▁骨", -10.452258110046387 ], [ "▁St", -10.453333854675293 ], [ "▁’", -10.453709602355957 ], [ "▁理想", -10.453944206237793 ], [ "▁ゼロ", -10.454582214355469 ], [ "▁対立", -10.454639434814453 ], [ "情", -10.454852104187012 ], [ "▁伝える", -10.454919815063477 ], [ "▁面白い", -10.455239295959473 ], [ "ユ", -10.455470085144043 ], [ "▁自由に", -10.456164360046387 ], [ "▁含めて", -10.45644760131836 ], [ "マイ", -10.456533432006836 ], [ "▁通貨", -10.456686973571777 ], [ "草", -10.456823348999023 ], [ "▁仕組み", -10.45695972442627 ], [ "▁強制", -10.457134246826172 ], [ "▁録音", -10.457173347473145 ], [ "株式", -10.457317352294922 ], [ "ディング", -10.457429885864258 ], [ "造", -10.457488059997559 ], [ "リオ", -10.457799911499023 ], [ "▁高級", -10.457839965820312 ], [ "議", -10.458162307739258 ], [ "▁重視", -10.458274841308594 ], [ "▁クラ", -10.458277702331543 ], [ "相", -10.458537101745605 ], [ "▁残る", -10.458636283874512 ], [ "ミー", -10.45885944366455 ], [ "▁箇所", -10.459257125854492 ], [ "▁ブル", -10.459433555603027 ], [ "▁65", -10.460418701171875 ], [ "▁跡", -10.46047592163086 ], [ "アイ", -10.46049690246582 ], [ "▁経過", -10.460628509521484 ], [ "▁沖", -10.46131706237793 ], [ "▁治", -10.461347579956055 ], [ "▁はず", -10.461402893066406 ], [ "▁59", -10.461772918701172 ], [ "▁迎え", -10.462430000305176 ], [ "▁レッド", -10.462451934814453 ], [ "▁優秀", -10.463645935058594 ], [ "▁専攻", -10.463692665100098 ], [ "玉", -10.464188575744629 ], [ "▁マーケティング", -10.464713096618652 ], [ "中国", -10.465185165405273 ], [ "▁負け", -10.465825080871582 ], [ "守", -10.46628189086914 ], [ "▁バン", -10.466352462768555 ], [ "▁払い", -10.466496467590332 ], [ "▁リング", -10.466511726379395 ], [ "工", -10.466636657714844 ], [ "どう", -10.466691970825195 ], [ "▁帰国", -10.467049598693848 ], [ "▁転", -10.467390060424805 ], [ "▁投手", -10.467473030090332 ], [ "レット", -10.468132972717285 ], [ "▁1997", -10.468169212341309 ], [ "▁コミュニティ", -10.468795776367188 ], [ "オン", -10.469009399414062 ], [ "▁在籍", -10.469585418701172 ], [ "▁笑顔", -10.469808578491211 ], [ "▁52", -10.469841957092285 ], [ "ジン", -10.470102310180664 ], [ "▁サウンド", -10.470108032226562 ], [ "▁皮膚", -10.470166206359863 ], [ "▁流行", -10.470215797424316 ], [ "▁純", -10.470335006713867 ], [ "▁寝", -10.470391273498535 ], [ "ge", -10.470720291137695 ], [ "▁洋", -10.472484588623047 ], [ "▁ベッド", -10.472790718078613 ], [ "▁視点", -10.473199844360352 ], [ "▁リン", -10.4732666015625 ], [ "▁マシン", -10.473544120788574 ], [ "▁解釈", -10.473617553710938 ], [ "ion", -10.473678588867188 ], [ "▁パフォーマンス", -10.47401237487793 ], [ "▁代理", -10.474077224731445 ], [ "▁視", -10.475289344787598 ], [ "▁ピュー", -10.47544002532959 ], [ "▁砲", -10.475794792175293 ], [ "今後", -10.475794792175293 ], [ "▁加", -10.475903511047363 ], [ "▁ついた", -10.476033210754395 ], [ "▁リーダー", -10.476296424865723 ], [ "血", -10.476313591003418 ], [ "▁戻って", -10.47709846496582 ], [ "▁変わる", -10.477215766906738 ], [ "走", -10.477478981018066 ], [ "▁取り扱い", -10.477518081665039 ], [ "▁クリ", -10.478382110595703 ], [ "器", -10.478464126586914 ], [ "os", -10.47860050201416 ], [ "▁開幕", -10.478680610656738 ], [ "解", -10.478680610656738 ], [ "▁古代", -10.479103088378906 ], [ "▁アカデミー", -10.479461669921875 ], [ "▁常", -10.479778289794922 ], [ "▁講演", -10.480802536010742 ], [ "▁新幹線", -10.480935096740723 ], [ "▁よかった", -10.481436729431152 ], [ ">", -10.48215103149414 ], [ "熱", -10.482230186462402 ], [ "▁引き続き", -10.482282638549805 ], [ "▁香り", -10.482612609863281 ], [ "▁グ", -10.48310661315918 ], [ "華", -10.483307838439941 ], [ "▁財産", -10.48336410522461 ], [ "▁49", -10.483840942382812 ], [ "▁IC", -10.483899116516113 ], [ "id", -10.484437942504883 ], [ "▁グラ", -10.484756469726562 ], [ "▁栽培", -10.4848051071167 ], [ "▁宿泊", -10.485039710998535 ], [ "▁公表", -10.485075950622559 ], [ "▁プレミアム", -10.485156059265137 ], [ "▁75", -10.485177040100098 ], [ "▁該当", -10.485254287719727 ], [ "▁いけ", -10.48529052734375 ], [ "▁厳しい", -10.48569393157959 ], [ "▁特殊", -10.485925674438477 ], [ "▁モン", -10.486734390258789 ], [ "四", -10.486903190612793 ], [ "▁キャンプ", -10.486910820007324 ], [ "▁速", -10.48708724975586 ], [ "▁約束", -10.487266540527344 ], [ "▁一体", -10.487492561340332 ], [ "助", -10.487527847290039 ], [ "ゲーム", -10.487594604492188 ], [ "▁震災", -10.48786735534668 ], [ "▁皆", -10.487935066223145 ], [ "▁通って", -10.488229751586914 ], [ "ネス", -10.488350868225098 ], [ "▁卵", -10.48845100402832 ], [ "▁鈴木", -10.488458633422852 ], [ "▁朝日", -10.488466262817383 ], [ "▁依存", -10.488618850708008 ], [ "▁無く", -10.488658905029297 ], [ "ルド", -10.489663124084473 ], [ "▁職場", -10.489911079406738 ], [ "▁フォーム", -10.490093231201172 ], [ "居", -10.490172386169434 ], [ "清", -10.490262031555176 ], [ "▁by", -10.490970611572266 ], [ "▁一種", -10.491372108459473 ], [ "ro", -10.491476058959961 ], [ "▁決済", -10.491608619689941 ], [ "以前", -10.491668701171875 ], [ "▁パス", -10.491931915283203 ], [ "▁策", -10.492384910583496 ], [ "▁改良", -10.492807388305664 ], [ "ent", -10.493000984191895 ], [ "▁モバイル", -10.493106842041016 ], [ "▁吸収", -10.493185043334961 ], [ "▁もらえる", -10.493204116821289 ], [ "▁善", -10.49343204498291 ], [ "▁1996", -10.493520736694336 ], [ "▁パターン", -10.49364185333252 ], [ "郷", -10.494190216064453 ], [ "▁だって", -10.494237899780273 ], [ "なく", -10.495024681091309 ], [ "▁57", -10.495511054992676 ], [ "▁プロデューサー", -10.495625495910645 ], [ "▁申し込み", -10.49600601196289 ], [ "▁部品", -10.496329307556152 ], [ "▁直前", -10.496713638305664 ], [ "▁電", -10.496933937072754 ], [ "500", -10.497018814086914 ], [ "とう", -10.497456550598145 ], [ "▁後期", -10.49748706817627 ], [ "▁隣", -10.49764633178711 ], [ "▁菓子", -10.497699737548828 ], [ "▁瞬間", -10.4981050491333 ], [ "▁炎", -10.49817943572998 ], [ "▁ソロ", -10.498929023742676 ], [ "▁本体", -10.498967170715332 ], [ "▁アプリケーション", -10.499181747436523 ], [ "職", -10.499431610107422 ], [ "ファー", -10.499482154846191 ], [ "▁大切に", -10.499865531921387 ], [ "▁生成", -10.499884605407715 ], [ "▁マイル", -10.499968528747559 ], [ "▁オプション", -10.500041007995605 ], [ "▁1995", -10.500049591064453 ], [ "▁自社", -10.500080108642578 ], [ "経", -10.500192642211914 ], [ "▁素人", -10.500240325927734 ], [ "▁温度", -10.500269889831543 ], [ "ビル", -10.500395774841309 ], [ "▁執行", -10.500556945800781 ], [ "▁鬼", -10.500720977783203 ], [ "▁そうに", -10.501009941101074 ], [ "▁似て", -10.501116752624512 ], [ "▁わたし", -10.501299858093262 ], [ "▁夫婦", -10.501328468322754 ], [ "▁区域", -10.501420974731445 ], [ "集", -10.501749992370605 ], [ "▁試し", -10.501789093017578 ], [ "▁サー", -10.501919746398926 ], [ "▁雄", -10.502416610717773 ], [ "▁妹", -10.502914428710938 ], [ "▁長官", -10.502914428710938 ], [ "▁楽しんで", -10.503018379211426 ], [ "▁帰って", -10.503154754638672 ], [ "▁マスク", -10.50358772277832 ], [ "▁前半", -10.50387191772461 ], [ "▁ざる", -10.503875732421875 ], [ "▁属する", -10.504100799560547 ], [ "▁想定", -10.504129409790039 ], [ "▁○", -10.504786491394043 ], [ "▁保障", -10.504828453063965 ], [ "ate", -10.505040168762207 ], [ "ンズ", -10.505292892456055 ], [ "帝", -10.505805015563965 ], [ "僕", -10.505825996398926 ], [ "▁わたって", -10.505959510803223 ], [ "ゆ", -10.506048202514648 ], [ "当社", -10.506733894348145 ], [ "▁ロボット", -10.50677490234375 ], [ "▁建造", -10.506897926330566 ], [ "▁池", -10.50720500946045 ], [ "▁チャート", -10.507625579833984 ], [ "▁58", -10.5077543258667 ], [ "▁ง", -10.5079984664917 ], [ "▁集合", -10.50833797454834 ], [ "権", -10.509449005126953 ], [ "▁ようだ", -10.510111808776855 ], [ "▁やっぱり", -10.510293006896973 ], [ "▁田中", -10.51105785369873 ], [ "近", -10.51118278503418 ], [ "▁音声", -10.511432647705078 ], [ "ol", -10.5119047164917 ], [ "▁富", -10.512160301208496 ], [ "▁明日", -10.512517929077148 ], [ "▁タイミング", -10.512606620788574 ], [ "▁迷惑", -10.51266098022461 ], [ "▁半分", -10.512677192687988 ], [ "ティング", -10.512828826904297 ], [ "▁外科", -10.512837409973145 ], [ "▁調", -10.512894630432129 ], [ "▁ソ連", -10.513236045837402 ], [ "管", -10.513262748718262 ], [ "▁スキー", -10.513324737548828 ], [ "▁世帯", -10.514060020446777 ], [ "▁ゆっくり", -10.514233589172363 ], [ "▁すごく", -10.514322280883789 ], [ "▁YouTube", -10.51452350616455 ], [ "明治", -10.514820098876953 ], [ "▁床", -10.514954566955566 ], [ "▁悪化", -10.515046119689941 ], [ "▁サンプル", -10.515244483947754 ], [ "▁ノート", -10.515714645385742 ], [ "▁·", -10.515891075134277 ], [ "親", -10.515970230102539 ], [ "▁th", -10.515990257263184 ], [ "▁起用", -10.516020774841309 ], [ "▁すぎて", -10.516179084777832 ], [ "▁徐々に", -10.5167236328125 ], [ "ーク", -10.516725540161133 ], [ "▁乗って", -10.51679801940918 ], [ "▁テキスト", -10.51718807220459 ], [ "▁教科", -10.518324851989746 ], [ "▁エピソード", -10.518579483032227 ], [ "▁模様", -10.51868724822998 ], [ "▁任命", -10.518927574157715 ], [ "ける", -10.519067764282227 ], [ "沼", -10.519302368164062 ], [ "▁認証", -10.519386291503906 ], [ "ad", -10.519731521606445 ], [ "▁他人", -10.520163536071777 ], [ "官", -10.520537376403809 ], [ "▁都合", -10.520846366882324 ], [ "▁証", -10.52127456665039 ], [ "メント", -10.52145767211914 ], [ "板", -10.521571159362793 ], [ "▁いっぱい", -10.52171516418457 ], [ "▁可能である", -10.521912574768066 ], [ "▁世話", -10.522029876708984 ], [ "端", -10.522418022155762 ], [ "▁信号", -10.522561073303223 ], [ "▁不明", -10.522672653198242 ], [ "▁56", -10.522693634033203 ], [ "▁表明", -10.522911071777344 ], [ "▁矢", -10.522991180419922 ], [ "▁書類", -10.523468971252441 ], [ "▁里", -10.5238037109375 ], [ "▁ユダヤ", -10.524039268493652 ], [ "▁確立", -10.524553298950195 ], [ "▁陸上", -10.524770736694336 ], [ "▁形状", -10.525358200073242 ], [ "▁頑張って", -10.525382041931152 ], [ "▁描く", -10.525476455688477 ], [ "▁島根", -10.525552749633789 ], [ "▁マーケット", -10.525591850280762 ], [ "▁すら", -10.525641441345215 ], [ "鳥", -10.525818824768066 ], [ "22", -10.526357650756836 ], [ "▁健", -10.526498794555664 ], [ "ch", -10.52660846710205 ], [ "▁トレ", -10.527180671691895 ], [ "主な", -10.527520179748535 ], [ "▁西部", -10.527887344360352 ], [ "▁当然", -10.528342247009277 ], [ "▁加盟", -10.528627395629883 ], [ "▁ガンダム", -10.529075622558594 ], [ "▁゚", -10.529428482055664 ], [ "▁エア", -10.529458045959473 ], [ "▁発足", -10.529510498046875 ], [ "▁容量", -10.52964973449707 ], [ "界", -10.529934883117676 ], [ "メン", -10.53009033203125 ], [ "自", -10.530231475830078 ], [ "上げ", -10.53067684173584 ], [ "▁知", -10.531028747558594 ], [ "ir", -10.5311279296875 ], [ "2003", -10.53179931640625 ], [ "▁ナイト", -10.531908988952637 ], [ "▁コストコ", -10.532073020935059 ], [ "▁変わら", -10.53268051147461 ], [ "本塁", -10.532703399658203 ], [ "▁会計", -10.533059120178223 ], [ "▁含め", -10.533568382263184 ], [ "▁ヘッド", -10.533790588378906 ], [ "▁ジュニア", -10.534116744995117 ], [ "▁なお", -10.53455638885498 ], [ "ie", -10.534564971923828 ], [ "▁レシピ", -10.534653663635254 ], [ "▁共", -10.535125732421875 ], [ "▁新人", -10.535148620605469 ], [ "▁結び", -10.535223960876465 ], [ "▁制定", -10.535242080688477 ], [ "as", -10.535358428955078 ], [ "▁酸化", -10.535815238952637 ], [ "能", -10.536408424377441 ], [ "▁ペン", -10.536640167236328 ], [ "▁義務", -10.536652565002441 ], [ "▁特", -10.536839485168457 ], [ "▁イングランド", -10.53686809539795 ], [ "密", -10.536927223205566 ], [ "▁推定", -10.537759780883789 ], [ "▁沿い", -10.537775993347168 ], [ "▁合わせ", -10.537921905517578 ], [ "▁まったく", -10.53817081451416 ], [ "▁適切な", -10.538528442382812 ], [ "▁回数", -10.538846015930176 ], [ "的", -10.538866996765137 ], [ "▁−", -10.539522171020508 ], [ "▁需要", -10.539636611938477 ], [ "▁解", -10.539780616760254 ], [ "▁機体", -10.539833068847656 ], [ "▁使え", -10.539936065673828 ], [ "じゃ", -10.540026664733887 ], [ "▁幕府", -10.540477752685547 ], [ "▁早い", -10.540525436401367 ], [ "▁デバイス", -10.540824890136719 ], [ "▁塗装", -10.541227340698242 ], [ "▁コンセプト", -10.541257858276367 ], [ "▁済み", -10.541275978088379 ], [ "タル", -10.541396141052246 ], [ "▁河", -10.541488647460938 ], [ "▁べく", -10.541543960571289 ], [ "▁旨", -10.54171085357666 ], [ "▁連れて", -10.542189598083496 ], [ "▁教え", -10.542437553405762 ], [ "▁解析", -10.543166160583496 ], [ "▁崩壊", -10.543343544006348 ], [ "▁サイ", -10.544483184814453 ], [ "▁Pro", -10.544601440429688 ], [ "▁左右", -10.545303344726562 ], [ "ON", -10.545755386352539 ], [ "▁皇帝", -10.545920372009277 ], [ "▁輪", -10.545929908752441 ], [ "▁分け", -10.545965194702148 ], [ "▁家具", -10.546066284179688 ], [ "辺", -10.546396255493164 ], [ "▁やや", -10.54649829864502 ], [ "岩", -10.546558380126953 ], [ "▁レポート", -10.546915054321289 ], [ "▁クリーム", -10.546972274780273 ], [ "▁起こる", -10.547174453735352 ], [ "対", -10.547199249267578 ], [ "▁退職", -10.547263145446777 ], [ "▁初め", -10.547809600830078 ], [ "▁ど", -10.547882080078125 ], [ "▁腰", -10.548171997070312 ], [ "すべて", -10.548444747924805 ], [ "▁住む", -10.549030303955078 ], [ "演", -10.549086570739746 ], [ "観", -10.549123764038086 ], [ "▁•", -10.549249649047852 ], [ "▁麻", -10.549314498901367 ], [ "から", -10.54937744140625 ], [ "兵", -10.549515724182129 ], [ "映画", -10.549629211425781 ], [ "▁剣", -10.55005931854248 ], [ "▁配送", -10.550544738769531 ], [ "▁SP", -10.551517486572266 ], [ "▁諸島", -10.55174446105957 ], [ "▁バイ", -10.55216121673584 ], [ "▁劇", -10.552427291870117 ], [ "▁買い物", -10.5526123046875 ], [ "ダイ", -10.55285930633545 ], [ "▁改めて", -10.55402946472168 ], [ "▁袋", -10.554451942443848 ], [ "▁満", -10.554549217224121 ], [ "クト", -10.55467414855957 ], [ "▁見せ", -10.55472183227539 ], [ "▁東海", -10.554890632629395 ], [ "▁なれば", -10.555063247680664 ], [ "▁摂取", -10.555957794189453 ], [ "師", -10.556365966796875 ], [ "▁体重", -10.556449890136719 ], [ "▁換え", -10.556610107421875 ], [ "基本", -10.556936264038086 ], [ "詳細", -10.557188987731934 ], [ "▁筋肉", -10.557775497436523 ], [ "▁衆議院", -10.55783462524414 ], [ "▁マッサージ", -10.558528900146484 ], [ "勢", -10.558564186096191 ], [ "▁前年", -10.558675765991211 ], [ "▁振り", -10.558724403381348 ], [ "▁優れた", -10.558924674987793 ], [ "▁階級", -10.558975219726562 ], [ "▁民主", -10.5593900680542 ], [ "▁ch", -10.559639930725098 ], [ "▁もつ", -10.559649467468262 ], [ "備", -10.559749603271484 ], [ "ut", -10.559815406799316 ], [ "▁第三者", -10.560361862182617 ], [ "▁プロセス", -10.560379981994629 ], [ "▁ビッグ", -10.560503959655762 ], [ "▁移住", -10.560792922973633 ], [ "▁委託", -10.561125755310059 ], [ "▁証券", -10.561293601989746 ], [ "▁守", -10.56153392791748 ], [ "un", -10.561746597290039 ], [ "▁離婚", -10.562524795532227 ], [ "ハン", -10.562614440917969 ], [ "▁対処", -10.563167572021484 ], [ "▁プレ", -10.563279151916504 ], [ "▁そのような", -10.563922882080078 ], [ "ニング", -10.564064979553223 ], [ "▁であろう", -10.564095497131348 ], [ "▁在庫", -10.564375877380371 ], [ "▁120", -10.564413070678711 ], [ "▁きちんと", -10.564443588256836 ], [ "章", -10.564640998840332 ], [ "▁オート", -10.56477165222168 ], [ "ワン", -10.56511116027832 ], [ "ドル", -10.56520938873291 ], [ "▁徳", -10.565330505371094 ], [ "▁書店", -10.565359115600586 ], [ "#", -10.56538200378418 ], [ "▁パッケージ", -10.5657377243042 ], [ "70", -10.565741539001465 ], [ "▁ライター", -10.565743446350098 ], [ "▁誕生日", -10.566316604614258 ], [ "▁仲", -10.566390991210938 ], [ "▁ソース", -10.566514015197754 ], [ "▁提示", -10.566740989685059 ], [ "▁再度", -10.56678581237793 ], [ "▁判明", -10.56713581085205 ], [ "▁残さ", -10.567358016967773 ], [ "ジョ", -10.56737995147705 ], [ "▁職業", -10.567456245422363 ], [ "▁近年", -10.567686080932617 ], [ "こうした", -10.568107604980469 ], [ "▁検証", -10.568217277526855 ], [ "▁エイ", -10.568648338317871 ], [ "▁結合", -10.568918228149414 ], [ "▁数学", -10.568982124328613 ], [ "▁交差", -10.569039344787598 ], [ "▁区別", -10.56905746459961 ], [ "▁プリ", -10.569073677062988 ], [ "27", -10.569499015808105 ], [ "▁尾", -10.570080757141113 ], [ "é", -10.570541381835938 ], [ "▁難", -10.570733070373535 ], [ "▁助け", -10.570869445800781 ], [ "仁", -10.570876121520996 ], [ "▁昼", -10.5709867477417 ], [ "▁川崎", -10.571017265319824 ], [ "▁判決", -10.57159423828125 ], [ "▁人工", -10.5717134475708 ], [ "▁覚えて", -10.571783065795898 ], [ "▁予測", -10.571840286254883 ], [ "▁ケーキ", -10.571981430053711 ], [ "▁要因", -10.571983337402344 ], [ "▁色々", -10.572383880615234 ], [ "▁受講", -10.572539329528809 ], [ "サイ", -10.572700500488281 ], [ "▁たかった", -10.572758674621582 ], [ "IA", -10.572958946228027 ], [ "▁チャレンジ", -10.573175430297852 ], [ "▁有料", -10.573186874389648 ], [ "▁家電", -10.573331832885742 ], [ "▁痛", -10.573619842529297 ], [ "▁占領", -10.573822975158691 ], [ "羽", -10.574762344360352 ], [ "▁民主党", -10.575051307678223 ], [ "▁付属", -10.575066566467285 ], [ "▁トリ", -10.575173377990723 ], [ "▁背", -10.575396537780762 ], [ "雲", -10.575457572937012 ], [ "▁53", -10.575578689575195 ], [ "▁一致", -10.575647354125977 ], [ "▁クロ", -10.575692176818848 ], [ "ine", -10.575695991516113 ], [ "付け", -10.575743675231934 ], [ "▁香港", -10.575835227966309 ], [ "▁端", -10.576032638549805 ], [ "▁待って", -10.576395988464355 ], [ "▁通知", -10.57645034790039 ], [ "▁合成", -10.576895713806152 ], [ "▁wiki", -10.57724666595459 ], [ "▁秘密", -10.577787399291992 ], [ "▁ガン", -10.577814102172852 ], [ "生涯", -10.577973365783691 ], [ "▁衛生", -10.578251838684082 ], [ "妻", -10.578551292419434 ], [ "IC", -10.579459190368652 ], [ "▁有名", -10.579809188842773 ], [ "ヴェ", -10.579850196838379 ], [ "▁走行", -10.579970359802246 ], [ "▁フィルム", -10.580052375793457 ], [ "▁嫌", -10.580307006835938 ], [ "続き", -10.580391883850098 ], [ "▁ごろ", -10.58046817779541 ], [ "▁もらって", -10.580789566040039 ], [ "▁殺", -10.58079719543457 ], [ "臣", -10.58134937286377 ], [ "▁網", -10.58145809173584 ], [ "佐", -10.581507682800293 ], [ "▁泉", -10.582250595092773 ], [ "▁美味しい", -10.582939147949219 ], [ "▁地名", -10.583200454711914 ], [ "▁競争", -10.583226203918457 ], [ "▁ケーブル", -10.58351993560791 ], [ "▁戦後", -10.583548545837402 ], [ "▁素敵な", -10.583876609802246 ], [ "▁話して", -10.583879470825195 ], [ "ラス", -10.584029197692871 ], [ "▁ワーク", -10.584141731262207 ], [ "ディー", -10.584198951721191 ], [ "▁オーバー", -10.584382057189941 ], [ "▁短い", -10.584405899047852 ], [ "▁1994", -10.584415435791016 ], [ "▁保管", -10.584443092346191 ], [ "▁決めた", -10.58453369140625 ], [ "▁ノー", -10.584651947021484 ], [ " ", -10.584900856018066 ], [ "▁on", -10.585041046142578 ], [ "イル", -10.585562705993652 ], [ "▁関数", -10.586151123046875 ], [ "価", -10.58617877960205 ], [ "ピー", -10.586397171020508 ], [ "トロ", -10.586813926696777 ], [ "▁貴", -10.587382316589355 ], [ "▁グルメ", -10.587472915649414 ], [ "▁資本", -10.587594032287598 ], [ "▁黄", -10.587800979614258 ], [ "▁普通の", -10.588330268859863 ], [ "▁どんどん", -10.58836841583252 ], [ "▁果たす", -10.588475227355957 ], [ "▁後継", -10.588634490966797 ], [ "▁大使", -10.589052200317383 ], [ "▁ラーメン", -10.589088439941406 ], [ "ステ", -10.589125633239746 ], [ "EN", -10.589345932006836 ], [ "▁投げ", -10.589885711669922 ], [ "▁決して", -10.59030818939209 ], [ "▁保健", -10.590474128723145 ], [ "▁越し", -10.591001510620117 ], [ "▁いろいろな", -10.591121673583984 ], [ "▁自衛", -10.591279983520508 ], [ "▁表す", -10.591421127319336 ], [ "▁貿易", -10.5917329788208 ], [ "▁ソング", -10.591835975646973 ], [ "▁ショート", -10.592472076416016 ], [ "▁各国", -10.592511177062988 ], [ "▁規則", -10.592884063720703 ], [ "めた", -10.593396186828613 ], [ "せん", -10.593828201293945 ], [ "ンド", -10.593992233276367 ], [ "バイ", -10.594619750976562 ], [ "▁大半", -10.594970703125 ], [ "▁PS", -10.595251083374023 ], [ "号", -10.595405578613281 ], [ "▁もらった", -10.595519065856934 ], [ "服", -10.595538139343262 ], [ "▁冠", -10.595697402954102 ], [ "▁対抗", -10.595916748046875 ], [ "▁防", -10.59593677520752 ], [ "▁小型", -10.59601879119873 ], [ "条", -10.596096992492676 ], [ "▁変え", -10.596299171447754 ], [ "▁財団", -10.596566200256348 ], [ "▁Twitter", -10.597089767456055 ], [ "五", -10.598512649536133 ], [ "▁貴族", -10.598652839660645 ], [ "▁Apple", -10.599042892456055 ], [ "▁資源", -10.599228858947754 ], [ "▁1992", -10.599245071411133 ], [ "ナン", -10.59957218170166 ], [ "▁青年", -10.59961223602295 ], [ "▁貨物", -10.599722862243652 ], [ "▁機動", -10.599834442138672 ], [ "▁登板", -10.60049819946289 ], [ "▁頼", -10.60062026977539 ], [ "▁分布", -10.6009521484375 ], [ "▁甘", -10.60117244720459 ], [ "▁上げた", -10.60145092010498 ], [ "▁稼ぎ", -10.601629257202148 ], [ "▁ヨ", -10.601737976074219 ], [ "▁ウィ", -10.601821899414062 ], [ "説", -10.601866722106934 ], [ "読", -10.60220718383789 ], [ "▁上映", -10.602368354797363 ], [ "▁原則", -10.602415084838867 ], [ "▁先端", -10.602453231811523 ], [ "▁宝", -10.602934837341309 ], [ "▁単独", -10.603597640991211 ], [ "▁出来事", -10.603616714477539 ], [ "▁滞在", -10.603829383850098 ], [ "▁恐れ", -10.604592323303223 ], [ "▁署", -10.604592323303223 ], [ "http", -10.60476303100586 ], [ "▁レーベル", -10.604804992675781 ], [ "▁釣り", -10.605021476745605 ], [ "▁1993", -10.605817794799805 ], [ "ハイ", -10.606110572814941 ], [ "▁性質", -10.60622501373291 ], [ "▁ウールリッチ", -10.606371879577637 ], [ "起", -10.606873512268066 ], [ "IN", -10.606950759887695 ], [ "▁SNS", -10.60710334777832 ], [ "▁先輩", -10.607451438903809 ], [ "▁分かる", -10.608192443847656 ], [ "li", -10.609374046325684 ], [ "▁風俗", -10.60944938659668 ], [ "キャ", -10.609950065612793 ], [ "番", -10.610272407531738 ], [ "▁佐藤", -10.6105318069458 ], [ "▁調べて", -10.610678672790527 ], [ "▁可愛い", -10.610932350158691 ], [ "op", -10.611074447631836 ], [ "▁レンズ", -10.611294746398926 ], [ "LE", -10.611617088317871 ], [ "▁不倫", -10.611639022827148 ], [ "▁のであれば", -10.611771583557129 ], [ "マル", -10.611827850341797 ], [ "女性", -10.611860275268555 ], [ "▁別に", -10.612152099609375 ], [ "▁信用", -10.612218856811523 ], [ "▁コントロール", -10.612421989440918 ], [ "st", -10.612554550170898 ], [ "▁チャンス", -10.61292552947998 ], [ "▁観察", -10.612961769104004 ], [ "▁経緯", -10.613139152526855 ], [ "▁戻る", -10.613171577453613 ], [ "▁規格", -10.613327026367188 ], [ "▁減", -10.613452911376953 ], [ "▁取ら", -10.61364459991455 ], [ "▁任務", -10.613659858703613 ], [ "▁風景", -10.61367130279541 ], [ "▁圧倒", -10.61407470703125 ], [ "▁国会", -10.614187240600586 ], [ "▁主題", -10.61422348022461 ], [ "▁次元", -10.615046501159668 ], [ "翌", -10.61569881439209 ], [ "▁ブラジル", -10.615832328796387 ], [ "▁アンド", -10.616142272949219 ], [ "▁ドライブ", -10.616164207458496 ], [ "▁最新の", -10.616272926330566 ], [ "▁殺害", -10.616365432739258 ], [ "▁博", -10.616374969482422 ], [ "▁切れ", -10.616413116455078 ], [ "宝", -10.616637229919434 ], [ "▁歌詞", -10.617135047912598 ], [ "▁止め", -10.617502212524414 ], [ "▁わかって", -10.618289947509766 ], [ "隊", -10.618578910827637 ], [ "▁妊娠", -10.6188383102417 ], [ "▁要", -10.618898391723633 ], [ "▁脂肪", -10.618997573852539 ], [ "▁個別", -10.619119644165039 ], [ "▁塾", -10.619129180908203 ], [ "▁ログイン", -10.619389533996582 ], [ "▁卒", -10.619565963745117 ], [ "▁要請", -10.619709014892578 ], [ "▁燃料", -10.619897842407227 ], [ "▁ダン", -10.619965553283691 ], [ "▁ちゃんと", -10.620014190673828 ], [ "京", -10.62001895904541 ], [ "▁進み", -10.62021541595459 ], [ "グル", -10.620227813720703 ], [ "▁液", -10.620573043823242 ], [ "▁引", -10.620739936828613 ], [ "▁示して", -10.620859146118164 ], [ "▁上がり", -10.620955467224121 ], [ "▁住所", -10.621474266052246 ], [ "紙", -10.622063636779785 ], [ "▁インテリア", -10.62216854095459 ], [ "まる", -10.62254810333252 ], [ "2002", -10.622735977172852 ], [ "▁財政", -10.623008728027344 ], [ "▁地下鉄", -10.623178482055664 ], [ "▁カテゴリ", -10.623296737670898 ], [ "▁立つ", -10.623451232910156 ], [ "▁1960", -10.624146461486816 ], [ "ill", -10.624335289001465 ], [ "▁先発", -10.624603271484375 ], [ "▁プ", -10.624707221984863 ], [ "▁与えた", -10.62484359741211 ], [ "▁賃貸", -10.625142097473145 ], [ "▁解除", -10.625164031982422 ], [ "よく", -10.625188827514648 ], [ "塚", -10.625561714172363 ], [ "ぁ", -10.627054214477539 ], [ "▁シェア", -10.627095222473145 ], [ "▁氷", -10.627410888671875 ], [ "▁中村", -10.627572059631348 ], [ "▁はずです", -10.6276273727417 ], [ "ダン", -10.627696990966797 ], [ "▁あれ", -10.627836227416992 ], [ "けて", -10.62818431854248 ], [ "▁梅", -10.629030227661133 ], [ "▁1991", -10.629262924194336 ], [ "▁隣接", -10.629264831542969 ], [ "85", -10.629424095153809 ], [ "セル", -10.629737854003906 ], [ "▁ポーランド", -10.62981128692627 ], [ "▁納得", -10.630167961120605 ], [ "▁ゴールド", -10.630306243896484 ], [ "▁クロス", -10.630346298217773 ], [ "付", -10.630382537841797 ], [ "通常", -10.63072681427002 ], [ "▁意", -10.630902290344238 ], [ "▁わずか", -10.631807327270508 ], [ "▁合意", -10.631945610046387 ], [ "▁当たる", -10.631958961486816 ], [ "▁放射", -10.632353782653809 ], [ "▁漢", -10.632711410522461 ], [ "▁配布", -10.633065223693848 ], [ "ノー", -10.633269309997559 ], [ "ルー", -10.633328437805176 ], [ "▁感動", -10.633428573608398 ], [ "▁送って", -10.633527755737305 ], [ "▁アリ", -10.633627891540527 ], [ "▁十分", -10.633696556091309 ], [ "▁過", -10.633720397949219 ], [ "▁ゆ", -10.63477611541748 ], [ "▁アダルト", -10.636573791503906 ], [ "▁出産", -10.636759757995605 ], [ "校", -10.63697338104248 ], [ "▁前提", -10.637993812561035 ], [ "▁不可", -10.638615608215332 ], [ "▁アドバイス", -10.638640403747559 ], [ "▁ライセンス", -10.638670921325684 ], [ "▁サブ", -10.639055252075195 ], [ "▁ベビー", -10.639516830444336 ], [ "▁ポリシー", -10.639532089233398 ], [ "幸", -10.639786720275879 ], [ "▁康", -10.640162467956543 ], [ "▁合わせた", -10.640507698059082 ], [ "▁英国", -10.640867233276367 ], [ "▁施術", -10.64093017578125 ], [ "▁鼻", -10.641643524169922 ], [ "▁こうした", -10.642191886901855 ], [ "ri", -10.64236068725586 ], [ "クロ", -10.642477035522461 ], [ "▁起きた", -10.642826080322266 ], [ "▁パーティー", -10.64297103881836 ], [ "▁票", -10.642973899841309 ], [ "▁施工", -10.643680572509766 ], [ "▁迎えた", -10.643692970275879 ], [ "▁市街", -10.644038200378418 ], [ "▁東部", -10.64405632019043 ], [ "▁起動", -10.644109725952148 ], [ "▁ハード", -10.644306182861328 ], [ "▁諸国", -10.644641876220703 ], [ "▁開き", -10.644731521606445 ], [ "関", -10.645262718200684 ], [ "▁居住", -10.645434379577637 ], [ "co", -10.64546012878418 ], [ "▁欄", -10.645824432373047 ], [ "▁1989", -10.645875930786133 ], [ "▁李", -10.645977973937988 ], [ "23", -10.646096229553223 ], [ "▁豊富な", -10.646284103393555 ], [ "▁名義", -10.646286010742188 ], [ "80", -10.646575927734375 ], [ "圧", -10.646649360656738 ], [ "▁防ぐ", -10.646699905395508 ], [ "▁困難", -10.647612571716309 ], [ "▁雅", -10.647977828979492 ], [ "▁フォト", -10.648547172546387 ], [ "▁どうぞ", -10.648885726928711 ], [ "▁命名", -10.64920711517334 ], [ "▁アナ", -10.64926815032959 ], [ "▁兵器", -10.649847030639648 ], [ "▁学術", -10.650108337402344 ], [ "浜", -10.650506019592285 ], [ "▁後ろ", -10.650775909423828 ], [ "▁両親", -10.650813102722168 ], [ "▁ば", -10.650857925415039 ], [ "▁与えて", -10.651068687438965 ], [ "▁掃除", -10.65124225616455 ], [ "▁意図", -10.651289939880371 ], [ "▁{", -10.65147876739502 ], [ "▁トラ", -10.651638984680176 ], [ "▁基づき", -10.651810646057129 ], [ "▁わけ", -10.65185832977295 ], [ "▁削減", -10.652016639709473 ], [ "▁縦", -10.652219772338867 ], [ "OS", -10.652456283569336 ], [ "▁アナウンサー", -10.65251350402832 ], [ "▁話す", -10.65286922454834 ], [ "▁球団", -10.653066635131836 ], [ "▁臨床", -10.653249740600586 ], [ "▁思い出", -10.653548240661621 ], [ "▁放題", -10.653773307800293 ], [ "▁フィールド", -10.653843879699707 ], [ "▁具合", -10.654168128967285 ], [ "26", -10.654218673706055 ], [ "▁若者", -10.654234886169434 ], [ "▁飲食", -10.654251098632812 ], [ "▁分子", -10.654363632202148 ], [ "平成", -10.654529571533203 ], [ "▁手紙", -10.654577255249023 ], [ "▁本物", -10.654613494873047 ], [ "2001", -10.655438423156738 ], [ "▁ディスク", -10.655677795410156 ], [ "▁パンツ", -10.655719757080078 ], [ "▁長男", -10.655898094177246 ], [ "▁竜", -10.65591049194336 ], [ "ィ", -10.655988693237305 ], [ "▁選んで", -10.656149864196777 ], [ "▁まいり", -10.656558990478516 ], [ "▁実感", -10.656633377075195 ], [ "▁受信", -10.656886100769043 ], [ "節", -10.656898498535156 ], [ "▁提携", -10.657039642333984 ], [ "順", -10.657333374023438 ], [ "▁取り組んで", -10.65803337097168 ], [ "▁割引", -10.658052444458008 ], [ "▁増え", -10.658228874206543 ], [ "巻", -10.658323287963867 ], [ "友", -10.65871524810791 ], [ "io", -10.659010887145996 ], [ "▁配", -10.659646987915039 ], [ "▁無し", -10.65998649597168 ], [ "▁そうだ", -10.660008430480957 ], [ "▁靴", -10.660106658935547 ], [ "▁オル", -10.660253524780273 ], [ "柄", -10.661063194274902 ], [ "▁チャット", -10.661223411560059 ], [ "▁中学", -10.66123104095459 ], [ "▁転換", -10.661295890808105 ], [ "ところが", -10.661410331726074 ], [ "あと", -10.661547660827637 ], [ "▁特性", -10.661654472351074 ], [ "▁かね", -10.66187572479248 ], [ "▁囲", -10.662178039550781 ], [ "▁見つけ", -10.662419319152832 ], [ "▁着用", -10.662579536437988 ], [ "▁深夜", -10.662590026855469 ], [ "黒", -10.662744522094727 ], [ "▁腹", -10.663503646850586 ], [ "▁極めて", -10.66354751586914 ], [ "▁or", -10.663641929626465 ], [ "▁撤退", -10.664080619812012 ], [ "▁分解", -10.664419174194336 ], [ "▁関わる", -10.664423942565918 ], [ "all", -10.66447925567627 ], [ "▁あい", -10.664874076843262 ], [ "▁乗車", -10.664888381958008 ], [ "▁同時", -10.665441513061523 ], [ "▁商店", -10.665451049804688 ], [ "▁ビット", -10.665517807006836 ], [ "加", -10.665749549865723 ], [ "▁はっきり", -10.665983200073242 ], [ "▁ピンク", -10.666080474853516 ], [ "▁地点", -10.666500091552734 ], [ "ネル", -10.666592597961426 ], [ "▁近", -10.6666898727417 ], [ "▁保持", -10.666960716247559 ], [ "▁ウォーター", -10.667308807373047 ], [ "もの", -10.667551040649414 ], [ "味", -10.667752265930176 ], [ "▁意思", -10.667783737182617 ], [ "▁ゼミ", -10.667920112609863 ], [ "<", -10.668095588684082 ], [ "▁無視", -10.668235778808594 ], [ "▁即", -10.66830062866211 ], [ "▁幾", -10.668442726135254 ], [ "▁ランク", -10.668723106384277 ], [ "▁師団", -10.668892860412598 ], [ "▁華", -10.669175148010254 ], [ "▁似た", -10.669609069824219 ], [ "▁中間", -10.66963005065918 ], [ "具", -10.669775009155273 ], [ "売", -10.670099258422852 ], [ "▁毎週", -10.67020320892334 ], [ "▁毎", -10.670204162597656 ], [ "▁屋根", -10.670236587524414 ], [ "▁ティー", -10.67055892944336 ], [ "▁行か", -10.670868873596191 ], [ "▁メンテナンス", -10.671135902404785 ], [ "▁リフォーム", -10.671504020690918 ], [ "▁天気", -10.671528816223145 ], [ "▁改称", -10.672106742858887 ], [ "▁信仰", -10.672271728515625 ], [ "▁統治", -10.672943115234375 ], [ "▁歓迎", -10.672979354858398 ], [ "▁ラブ", -10.673094749450684 ], [ "▁先行", -10.673401832580566 ], [ "▁吉田", -10.673840522766113 ], [ "▁見せて", -10.674284934997559 ], [ "▁遺伝子", -10.674445152282715 ], [ "▁マップ", -10.67463493347168 ], [ "▁大幅に", -10.674697875976562 ], [ "▁創造", -10.674833297729492 ], [ "▁いえる", -10.674960136413574 ], [ "▁画家", -10.675365447998047 ], [ "ラム", -10.675662994384766 ], [ "近年", -10.675780296325684 ], [ "▁修", -10.675862312316895 ], [ "0", -10.676070213317871 ], [ "▁生きる", -10.676130294799805 ], [ "遠", -10.676259994506836 ], [ "▁昨年", -10.67640209197998 ], [ "▁菌", -10.676733016967773 ], [ "典", -10.676803588867188 ], [ "▁捜査", -10.677022933959961 ], [ "▁", -10.677600860595703 ], [ "▁紀元", -10.67774486541748 ], [ "▁関わら", -10.67777156829834 ], [ "▁出発", -10.677976608276367 ], [ "▁遺跡", -10.678329467773438 ], [ "トゥ", -10.678751945495605 ], [ "▁脚", -10.679109573364258 ], [ "▁激", -10.679110527038574 ], [ "▁集落", -10.679387092590332 ], [ "▁阪神", -10.68035888671875 ], [ "商品", -10.68060302734375 ], [ "lo", -10.680620193481445 ], [ "▁寄せ", -10.680861473083496 ], [ "▁ブラウザ", -10.680977821350098 ], [ "▁タレント", -10.681419372558594 ], [ "▁合った", -10.6819486618042 ], [ "▁見えて", -10.681988716125488 ], [ "▁入れた", -10.682061195373535 ], [ "▁隆", -10.682559967041016 ], [ "▁側面", -10.68258285522461 ], [ "▁キャンセル", -10.682631492614746 ], [ "▁チェンジ", -10.682719230651855 ], [ "十", -10.68310832977295 ], [ "▁みよう", -10.683241844177246 ], [ "▁借金", -10.683378219604492 ], [ "福", -10.683464050292969 ], [ "▁れたり", -10.683586120605469 ], [ "▁仁", -10.683978080749512 ], [ "▁用途", -10.684258460998535 ], [ "総", -10.684428215026855 ], [ "ハー", -10.684759140014648 ], [ "テル", -10.684826850891113 ], [ "まって", -10.685060501098633 ], [ "▁雲", -10.68521785736084 ], [ "▁爆発", -10.685356140136719 ], [ "▁銀座", -10.68541431427002 ], [ "▁割合", -10.685826301574707 ], [ "▁バル", -10.685835838317871 ], [ "いつも", -10.686234474182129 ], [ "感", -10.68653392791748 ], [ "▁アウト", -10.687507629394531 ], [ "▁想い", -10.687677383422852 ], [ "ag", -10.687862396240234 ], [ "▁管轄", -10.68789005279541 ], [ "▁いたり", -10.688348770141602 ], [ "党", -10.688633918762207 ], [ "▁協定", -10.689013481140137 ], [ "▁余裕", -10.689081192016602 ], [ "▁公立", -10.68935775756836 ], [ "▁なん", -10.689502716064453 ], [ "▁南北", -10.689728736877441 ], [ "運", -10.689977645874023 ], [ "▁基盤", -10.689995765686035 ], [ "▁入団", -10.690169334411621 ], [ "@", -10.690250396728516 ], [ "▁上がって", -10.690496444702148 ], [ "▁掲示板", -10.69051742553711 ], [ "▁ポスト", -10.690960884094238 ], [ "▁財布", -10.691305160522461 ], [ "▁外交", -10.6913423538208 ], [ "▁残して", -10.6913423538208 ], [ "▁AI", -10.691450119018555 ], [ "▁印", -10.69157886505127 ], [ "▁かかって", -10.691604614257812 ], [ "在", -10.691923141479492 ], [ "▁広い", -10.6920166015625 ], [ "▁当たり", -10.69225788116455 ], [ "▁LINE", -10.692301750183105 ], [ "極", -10.69247055053711 ], [ "づ", -10.6927490234375 ], [ "▁返済", -10.692989349365234 ], [ "▁文献", -10.693366050720215 ], [ "▁メイク", -10.69345760345459 ], [ "▁次第", -10.693553924560547 ], [ "▁繰り返し", -10.693568229675293 ], [ "算", -10.693727493286133 ], [ "▁駅前", -10.69383716583252 ], [ "▁姫", -10.69420051574707 ], [ "▁宣伝", -10.69420051574707 ], [ "ry", -10.694339752197266 ], [ "▁ベイ", -10.694341659545898 ], [ "ニン", -10.694510459899902 ], [ "シェ", -10.694759368896484 ], [ "▁集めて", -10.694802284240723 ], [ "▁陸", -10.694851875305176 ], [ "スク", -10.69485855102539 ], [ "▁様に", -10.695215225219727 ], [ "▁きっと", -10.695563316345215 ], [ "▁どうしても", -10.695597648620605 ], [ "▁ビール", -10.696128845214844 ], [ "and", -10.69620132446289 ], [ "▁フレーム", -10.696235656738281 ], [ "▁底", -10.696452140808105 ], [ "▁回収", -10.696488380432129 ], [ "興", -10.696905136108398 ], [ "▁臨時", -10.697068214416504 ], [ "カテゴリー", -10.697155952453613 ], [ "▁たび", -10.69729232788086 ], [ "岸", -10.697511672973633 ], [ "▁許さ", -10.697827339172363 ], [ "▁1988", -10.698448181152344 ], [ "▁もん", -10.698709487915039 ], [ "▁終わる", -10.698862075805664 ], [ "▁不満", -10.698989868164062 ], [ "▁CO", -10.699289321899414 ], [ "類", -10.699359893798828 ], [ "▁語り", -10.699482917785645 ], [ "▁得意", -10.699516296386719 ], [ "▁坂", -10.700058937072754 ], [ "▁カリフォルニア", -10.700129508972168 ], [ "▁バレ", -10.700430870056152 ], [ "乃", -10.701360702514648 ], [ "▁Ch", -10.701396942138672 ], [ "▁通算", -10.701435089111328 ], [ "▁ダイ", -10.701467514038086 ], [ "▁売", -10.701783180236816 ], [ "▁次々", -10.701801300048828 ], [ "▁買収", -10.70186710357666 ], [ "▁十分に", -10.70212173461914 ], [ "▁人類", -10.702156066894531 ], [ "▁z", -10.702608108520508 ], [ "ほ", -10.702630043029785 ], [ "▁プラ", -10.70311450958252 ], [ "デル", -10.703182220458984 ], [ "▁切", -10.703750610351562 ], [ "▁幅広い", -10.703866004943848 ], [ "▁庫", -10.703989028930664 ], [ "▁調理", -10.704361915588379 ], [ "利用", -10.704384803771973 ], [ "このように", -10.704418182373047 ], [ "▁反映", -10.704577445983887 ], [ "図", -10.704912185668945 ], [ "▁なあ", -10.704941749572754 ], [ "▁イー", -10.705008506774902 ], [ "▁占い", -10.705068588256836 ], [ "▁生じる", -10.705324172973633 ], [ "満", -10.705449104309082 ], [ "ション", -10.706048011779785 ], [ "▁フード", -10.706387519836426 ], [ "▁電動", -10.706525802612305 ], [ "好", -10.707021713256836 ], [ "▁締結", -10.707063674926758 ], [ "est", -10.707228660583496 ], [ "99", -10.707803726196289 ], [ "▁上がる", -10.708578109741211 ], [ "▁撮り", -10.708748817443848 ], [ "置", -10.709005355834961 ], [ "▁デザイナー", -10.70938491821289 ], [ "49", -10.709566116333008 ], [ "▁駆逐", -10.709647178649902 ], [ "トー", -10.709829330444336 ], [ "▁ベトナム", -10.7099609375 ], [ "▁開講", -10.710029602050781 ], [ "▁読者", -10.710100173950195 ], [ "▁初回", -10.710197448730469 ], [ "▁松本", -10.710376739501953 ], [ "▁ジャン", -10.71078872680664 ], [ "▁監視", -10.71123218536377 ], [ "百", -10.711564064025879 ], [ "ot", -10.711671829223633 ], [ "▁商", -10.712349891662598 ], [ "▁裕", -10.712491989135742 ], [ "▁PDF", -10.712738037109375 ], [ "▁いつでも", -10.714420318603516 ], [ "▁収容", -10.714472770690918 ], [ "▁表情", -10.714473724365234 ], [ "▁アクセサリー", -10.71512508392334 ], [ "▁決める", -10.715201377868652 ], [ "ボン", -10.715425491333008 ], [ "29", -10.715761184692383 ], [ "同じ", -10.71596622467041 ], [ "▁突然", -10.7160005569458 ], [ "▁採", -10.716123580932617 ], [ "▁姓", -10.716147422790527 ], [ "向", -10.71689224243164 ], [ "▁塔", -10.717092514038086 ], [ "▁作詞", -10.71718692779541 ], [ "団", -10.717340469360352 ], [ "ant", -10.717635154724121 ], [ "▁トンネル", -10.717796325683594 ], [ "▁グレー", -10.718750953674316 ], [ "▁600", -10.719345092773438 ], [ "視", -10.71964168548584 ], [ "▁流通", -10.719962120056152 ], [ "1990", -10.720258712768555 ], [ "▁栄", -10.720524787902832 ], [ "▁配慮", -10.72075366973877 ], [ "▁うる", -10.720885276794434 ], [ "▁is", -10.721294403076172 ], [ "▁扱う", -10.721309661865234 ], [ "▁差別", -10.72209644317627 ], [ "▁翌日", -10.722190856933594 ], [ "▁送る", -10.722200393676758 ], [ "▁無線", -10.722403526306152 ], [ "▁受け入れ", -10.722496032714844 ], [ "▁補", -10.722650527954102 ], [ "ければ", -10.722972869873047 ], [ "▁おかげ", -10.723441123962402 ], [ "▁戦車", -10.724544525146484 ], [ "▁━", -10.725343704223633 ], [ "交", -10.725500106811523 ], [ "▁従って", -10.725666046142578 ], [ "かん", -10.725988388061523 ], [ "急", -10.726025581359863 ], [ "▁率いる", -10.726204872131348 ], [ "▁バラ", -10.726448059082031 ], [ "ra", -10.72651195526123 ], [ "▁パート", -10.726529121398926 ], [ "御", -10.726615905761719 ], [ "ドン", -10.726641654968262 ], [ "▁出現", -10.726862907409668 ], [ "▁タン", -10.726863861083984 ], [ "歩", -10.726937294006348 ], [ "▁精", -10.72700309753418 ], [ "▁疲れ", -10.727191925048828 ], [ "ers", -10.727717399597168 ], [ "六", -10.727914810180664 ], [ "▁付いて", -10.728038787841797 ], [ "▁弘", -10.728067398071289 ], [ "▁新設", -10.728294372558594 ], [ "▁会い", -10.728347778320312 ], [ "▁逃げ", -10.728479385375977 ], [ "取り", -10.72877025604248 ], [ "▁歴任", -10.728885650634766 ], [ "▁ホイール", -10.729106903076172 ], [ "洋", -10.729284286499023 ], [ "ap", -10.72973918914795 ], [ "ケン", -10.729889869689941 ], [ "▁主体", -10.729907989501953 ], [ "▁暴力", -10.730273246765137 ], [ "▁吹き", -10.730552673339844 ], [ "留", -10.730786323547363 ], [ "実は", -10.731069564819336 ], [ "▁植民", -10.731371879577637 ], [ "▁1987", -10.732577323913574 ], [ "しかしながら", -10.732605934143066 ], [ "▁パネル", -10.732608795166016 ], [ "▁好み", -10.732817649841309 ], [ "▁帰り", -10.732895851135254 ], [ "▁工夫", -10.733030319213867 ], [ "▁接種", -10.733355522155762 ], [ "▁投入", -10.733445167541504 ], [ "▁マルチ", -10.733598709106445 ], [ "▁談", -10.733784675598145 ], [ "▁離れた", -10.733792304992676 ], [ "▁汚れ", -10.734173774719238 ], [ "▁気に入り", -10.734444618225098 ], [ "まだ", -10.734601974487305 ], [ "▁示した", -10.734881401062012 ], [ "▁理", -10.735295295715332 ], [ "筋", -10.735692977905273 ], [ "▁変動", -10.735965728759766 ], [ "▁豊かな", -10.735995292663574 ], [ "▁チェーン", -10.736213684082031 ], [ "one", -10.736610412597656 ], [ "▁伝", -10.73680305480957 ], [ "▁グランプリ", -10.737271308898926 ], [ "▁乳", -10.737570762634277 ], [ "▁アス", -10.737709999084473 ], [ "▁鎌倉", -10.73806381225586 ], [ "ee", -10.738065719604492 ], [ "▁変えて", -10.738358497619629 ], [ "▁ファミリー", -10.738367080688477 ], [ "▁学んだ", -10.738368034362793 ], [ "▁徳川", -10.738482475280762 ], [ "しかも", -10.738748550415039 ], [ "▁幸せ", -10.738773345947266 ], [ "▁日時", -10.7390718460083 ], [ "ドゥ", -10.739137649536133 ], [ "▁ダブル", -10.739543914794922 ], [ "▁スウェーデン", -10.739578247070312 ], [ "▁82", -10.739594459533691 ], [ "▁衛星", -10.739693641662598 ], [ "▁ランチ", -10.739830017089844 ], [ "▁カレー", -10.739934921264648 ], [ "▁フロント", -10.739957809448242 ], [ "▁戦士", -10.740230560302734 ], [ "▁めに", -10.740400314331055 ], [ "▁布", -10.740595817565918 ], [ "▁睡眠", -10.740818977355957 ], [ "▁オーストリア", -10.740860939025879 ], [ "▁スタジアム", -10.740934371948242 ], [ "47", -10.741072654724121 ], [ "▁スタンド", -10.741286277770996 ], [ "▁人数", -10.741925239562988 ], [ "▁謎", -10.7420072555542 ], [ "龍", -10.742512702941895 ], [ "▁重量", -10.742544174194336 ], [ "つき", -10.742650032043457 ], [ "35", -10.74278450012207 ], [ "28", -10.742947578430176 ], [ "▁クラシック", -10.743200302124023 ], [ "▁キング", -10.743509292602539 ], [ "▁衝撃", -10.743876457214355 ], [ "では", -10.743898391723633 ], [ "IS", -10.744841575622559 ], [ "▁マッチ", -10.744956970214844 ], [ "▁付けて", -10.745199203491211 ], [ "AL", -10.74521255493164 ], [ "▁砂", -10.745214462280273 ], [ "▁投", -10.745369911193848 ], [ "▁弁", -10.7454252243042 ], [ "▁優", -10.745903015136719 ], [ "過去", -10.746221542358398 ], [ "ッサ", -10.746478080749512 ], [ "▁広場", -10.747115135192871 ], [ "▁農", -10.7471342086792 ], [ "ig", -10.7474365234375 ], [ "▁図る", -10.747557640075684 ], [ "▁復興", -10.747750282287598 ], [ "▁通う", -10.747791290283203 ], [ "まずは", -10.74783706665039 ], [ "▁インター", -10.747848510742188 ], [ "▁試して", -10.748116493225098 ], [ "▁阿", -10.74820327758789 ], [ "北海道", -10.748265266418457 ], [ "▁TBS", -10.748269081115723 ], [ "▁突破", -10.74870777130127 ], [ "▁もらえ", -10.748785972595215 ], [ "▁浜", -10.749073028564453 ], [ "▁俊", -10.749162673950195 ], [ "▁在住", -10.749631881713867 ], [ "▁共産党", -10.749688148498535 ], [ "▁輸出", -10.75018310546875 ], [ "▁パパ", -10.750210762023926 ], [ "▁刑事", -10.750245094299316 ], [ "▁置き", -10.750259399414062 ], [ "▁フェ", -10.750304222106934 ], [ "▁出張", -10.750323295593262 ], [ "豊", -10.750361442565918 ], [ "▁思考", -10.750575065612793 ], [ "▁ナンバー", -10.750889778137207 ], [ "▁激しい", -10.75124740600586 ], [ "▁オン", -10.751447677612305 ], [ "▁恋人", -10.751620292663574 ], [ "収", -10.751784324645996 ], [ "▁稼ぐ", -10.751981735229492 ], [ "▁EX", -10.751996994018555 ], [ "▁オートバックス", -10.752192497253418 ], [ "府", -10.752724647521973 ], [ "100", -10.752809524536133 ], [ "▁特別な", -10.753090858459473 ], [ "▁違って", -10.753138542175293 ], [ "ั", -10.753378868103027 ], [ "衣", -10.753620147705078 ], [ "▁道具", -10.75365924835205 ], [ "称", -10.753668785095215 ], [ "▁だったり", -10.753694534301758 ], [ "型", -10.753713607788086 ], [ "▁ステーション", -10.7539644241333 ], [ "▁250", -10.754257202148438 ], [ "▁メキシコ", -10.754351615905762 ], [ "郡", -10.75451374053955 ], [ "▁取り付け", -10.754825592041016 ], [ "×", -10.755046844482422 ], [ "▁眼", -10.755205154418945 ], [ "▁不正", -10.755253791809082 ], [ "▁智", -10.755300521850586 ], [ "▁柄", -10.755454063415527 ], [ "▁キーワード", -10.755582809448242 ], [ "子供", -10.755758285522461 ], [ "▁緊張", -10.755980491638184 ], [ "▁パー", -10.756006240844727 ], [ "▁閉鎖", -10.75664234161377 ], [ "▁おか", -10.756956100463867 ], [ "▁厚生", -10.75699234008789 ], [ "▁沢山", -10.75706672668457 ], [ "▁デイ", -10.757244110107422 ], [ "▁アップデート", -10.757377624511719 ], [ "ース", -10.757486343383789 ], [ "▁医薬", -10.757721900939941 ], [ "01", -10.757879257202148 ], [ "▁model", -10.75843334197998 ], [ "様", -10.758508682250977 ], [ "▁合流", -10.758764266967773 ], [ "▁人民", -10.758831024169922 ], [ "▁天文", -10.759284973144531 ], [ "▁ございませ", -10.759328842163086 ], [ "▁体調", -10.759394645690918 ], [ "▁戦国", -10.75968074798584 ], [ "製", -10.760065078735352 ], [ "▁観点", -10.760107040405273 ], [ "報", -10.76013469696045 ], [ "ta", -10.760208129882812 ], [ "55", -10.760512351989746 ], [ "▁銅", -10.76057243347168 ], [ "ass", -10.760766983032227 ], [ "▁大和", -10.760872840881348 ], [ "▁雑", -10.761136054992676 ], [ "くて", -10.761143684387207 ], [ "高校", -10.76126766204834 ], [ "▁ビー", -10.761373519897461 ], [ "▁1985", -10.761563301086426 ], [ "▁セフレ", -10.76168441772461 ], [ "然", -10.762093544006348 ], [ "▁蔵", -10.762140274047852 ], [ "▁記さ", -10.762142181396484 ], [ "▁コル", -10.762563705444336 ], [ "▁履歴", -10.76258373260498 ], [ "▁振興", -10.76262092590332 ], [ "プラ", -10.76267147064209 ], [ "▁教員", -10.763262748718262 ], [ "▁伊藤", -10.76374626159668 ], [ "▁引用", -10.763988494873047 ], [ "切", -10.764281272888184 ], [ "▁彩", -10.764312744140625 ], [ "▁かわいい", -10.764335632324219 ], [ "▁渡り", -10.764396667480469 ], [ "▁短期", -10.764512062072754 ], [ "▁見学", -10.764540672302246 ], [ "▁混乱", -10.765107154846191 ], [ "貴", -10.765271186828613 ], [ "▁ホー", -10.765302658081055 ], [ "▁ゆう", -10.765351295471191 ], [ "殺", -10.76539421081543 ], [ "▁1986", -10.765628814697266 ], [ "▁殺人", -10.766005516052246 ], [ "▁ゲ", -10.766084671020508 ], [ "▁モーター", -10.766255378723145 ], [ "グラ", -10.766271591186523 ], [ "▁be", -10.766335487365723 ], [ "▁ニーズ", -10.766633033752441 ], [ "ッと", -10.766645431518555 ], [ "ite", -10.766961097717285 ], [ "▁糸", -10.76739501953125 ], [ "鉄", -10.767674446105957 ], [ "▁ジョージ", -10.767728805541992 ], [ "▁入院", -10.767756462097168 ], [ "▁郷", -10.767904281616211 ], [ "▁地帯", -10.767909049987793 ], [ "ロス", -10.768365859985352 ], [ "▁カラ", -10.768441200256348 ], [ "▁中部", -10.768596649169922 ], [ "▁保守", -10.768852233886719 ], [ "▁エス", -10.7688570022583 ], [ "▁断", -10.768927574157715 ], [ "転", -10.769081115722656 ], [ "納", -10.769204139709473 ], [ "▁ジャンプ", -10.769572257995605 ], [ "▁続いた", -10.769584655761719 ], [ "▁抜き", -10.769721031188965 ], [ "▁電源", -10.769990921020508 ], [ "▁いろんな", -10.77013874053955 ], [ "▁再現", -10.770313262939453 ], [ "▁ユー", -10.770479202270508 ], [ "▁本日", -10.770576477050781 ], [ "▁既存", -10.770631790161133 ], [ "▁張", -10.770856857299805 ], [ "▁組み合わせ", -10.771065711975098 ], [ "▁台風", -10.771232604980469 ], [ "▁WEB", -10.77126693725586 ], [ "▁ライダー", -10.771324157714844 ], [ "▁受", -10.771442413330078 ], [ "▁どういう", -10.772174835205078 ], [ "クル", -10.772211074829102 ], [ "▁乗", -10.772485733032227 ], [ "▁あたって", -10.773011207580566 ], [ "▁戻り", -10.773011207580566 ], [ "▁定める", -10.773107528686523 ], [ "▁順位", -10.77316665649414 ], [ "▁Cookie", -10.773225784301758 ], [ "▁800", -10.773232460021973 ], [ "▁態度", -10.773699760437012 ], [ "▁集め", -10.774336814880371 ], [ "席", -10.774398803710938 ], [ "段", -10.77443790435791 ], [ "▁予備", -10.774590492248535 ], [ "▁確率", -10.774798393249512 ], [ "▁能", -10.775267601013184 ], [ "▁山田", -10.77576732635498 ], [ "放送", -10.776034355163574 ], [ "▁涙", -10.776413917541504 ], [ "最終", -10.776598930358887 ], [ "洲", -10.776683807373047 ], [ "th", -10.776817321777344 ], [ "▁議長", -10.776972770690918 ], [ "▁融合", -10.776988983154297 ], [ "画", -10.777125358581543 ], [ "ゲン", -10.777262687683105 ], [ "▁すごい", -10.777837753295898 ], [ "▁ハワイ", -10.777915000915527 ], [ "ジョン", -10.778180122375488 ], [ "▁なに", -10.778225898742676 ], [ "ニック", -10.778369903564453 ], [ "▁示さ", -10.778698921203613 ], [ "▁62", -10.778779983520508 ], [ "▁なったり", -10.778813362121582 ], [ "▁魔", -10.779280662536621 ], [ "▁軒", -10.779706954956055 ], [ "▁小さく", -10.779977798461914 ], [ "▁児", -10.780074119567871 ], [ "▁仮想", -10.780279159545898 ], [ "▁柳", -10.780560493469238 ], [ "▁語る", -10.78058910369873 ], [ "▁債務", -10.780740737915039 ], [ "秋", -10.781007766723633 ], [ "▁デモ", -10.781322479248047 ], [ "乱", -10.781332969665527 ], [ "射", -10.781527519226074 ], [ "▁できれば", -10.7816743850708 ], [ "▁99", -10.781684875488281 ], [ "33", -10.78190803527832 ], [ "池", -10.781915664672852 ], [ "▁つもり", -10.782047271728516 ], [ "▁ピン", -10.782574653625488 ], [ "▁足り", -10.782734870910645 ], [ "昨日", -10.782748222351074 ], [ "▁流れる", -10.782894134521484 ], [ "▁比べ", -10.783468246459961 ], [ "▁およそ", -10.783714294433594 ], [ "▁そば", -10.783796310424805 ], [ "▁決めて", -10.783953666687012 ], [ "▁消滅", -10.784235954284668 ], [ "◆", -10.784285545349121 ], [ "▁頂いて", -10.784480094909668 ], [ "▁象徴", -10.7844877243042 ], [ "▁気温", -10.785170555114746 ], [ "▁向けた", -10.785361289978027 ], [ "▁構想", -10.785455703735352 ], [ "▁Sh", -10.785621643066406 ], [ "ell", -10.785684585571289 ], [ "▁全身", -10.785768508911133 ], [ "▁訴訟", -10.786338806152344 ], [ "▁ゼ", -10.78702449798584 ], [ "ES", -10.787266731262207 ], [ "MA", -10.787331581115723 ], [ "▁赤ちゃん", -10.787924766540527 ], [ "09", -10.787935256958008 ], [ "▁描き", -10.78796672821045 ], [ "▁単に", -10.788228988647461 ], [ "▁Co", -10.788381576538086 ], [ "▁平日", -10.788817405700684 ], [ "▁◆", -10.78945541381836 ], [ "▁泊", -10.789634704589844 ], [ "栄", -10.789788246154785 ], [ "▁生息", -10.789949417114258 ], [ "▁荒", -10.790071487426758 ], [ "▁所得", -10.790139198303223 ], [ "▁絵画", -10.79031753540039 ], [ "▁観客", -10.791157722473145 ], [ "▁避難", -10.791314125061035 ], [ "IT", -10.791377067565918 ], [ "▁けん", -10.79145622253418 ], [ "ソー", -10.791916847229004 ], [ "▁子育て", -10.792500495910645 ], [ "45", -10.792696952819824 ], [ "▁アニメーション", -10.792831420898438 ], [ "▁推奨", -10.793065071105957 ], [ "▁共演", -10.793068885803223 ], [ "最", -10.793084144592285 ], [ "▁区分", -10.793282508850098 ], [ "乗", -10.793521881103516 ], [ "▁つながる", -10.793953895568848 ], [ "▁忘れて", -10.794164657592773 ], [ "ペン", -10.794352531433105 ], [ "▁教材", -10.794719696044922 ], [ "▁高橋", -10.794736862182617 ], [ "▁複合", -10.794821739196777 ], [ "▁酵素", -10.794978141784668 ], [ "▁終", -10.795196533203125 ], [ "たとえば", -10.795251846313477 ], [ "▁楽し", -10.795260429382324 ], [ "▁実質", -10.795528411865234 ], [ "▁姉", -10.795628547668457 ], [ "▁コーデ", -10.795669555664062 ], [ "▁復習", -10.795804023742676 ], [ "▁改", -10.796074867248535 ], [ "▁デー", -10.796234130859375 ], [ "▁離れて", -10.796577453613281 ], [ "▁format", -10.797419548034668 ], [ "▁必須", -10.797565460205078 ], [ "ul", -10.797577857971191 ], [ "▁接触", -10.798535346984863 ], [ "回", -10.798542976379395 ], [ "▁ハンド", -10.799071311950684 ], [ "age", -10.799214363098145 ], [ "▁アレンジ", -10.79926586151123 ], [ "▁色々な", -10.799321174621582 ], [ "▁気候", -10.799463272094727 ], [ "32", -10.799541473388672 ], [ "▁ns", -10.799635887145996 ], [ "領", -10.799646377563477 ], [ "ッカ", -10.799870491027832 ], [ "▁亀", -10.800045013427734 ], [ "渡", -10.800149917602539 ], [ "▁ポール", -10.800448417663574 ], [ "▁週刊", -10.800708770751953 ], [ "▁多少", -10.80080795288086 ], [ "▁確実に", -10.8008394241333 ], [ "▁扉", -10.801047325134277 ], [ "▁年代", -10.801304817199707 ], [ "▁連隊", -10.801334381103516 ], [ "ive", -10.801403045654297 ], [ "▁ジュ", -10.80143928527832 ], [ "▁仮", -10.801597595214844 ], [ "OL", -10.801645278930664 ], [ "▁コイン", -10.801656723022461 ], [ "▁四国", -10.801823616027832 ], [ "▁後述", -10.801856994628906 ], [ "ッタ", -10.802078247070312 ], [ "▁鍵", -10.802079200744629 ], [ "▁旅客", -10.802305221557617 ], [ "36", -10.802318572998047 ], [ "TA", -10.802324295043945 ], [ "▁長年", -10.802534103393555 ], [ "絵", -10.80262565612793 ], [ "▁出席", -10.802642822265625 ], [ "▁ついに", -10.802724838256836 ], [ "▁歩いて", -10.802931785583496 ], [ "▁庭", -10.80301284790039 ], [ "▁分かって", -10.803607940673828 ], [ "▁白い", -10.804028511047363 ], [ "▁通称", -10.804475784301758 ], [ "髪", -10.804618835449219 ], [ "▁幕", -10.805013656616211 ], [ "▁行事", -10.805389404296875 ], [ "菜", -10.80550479888916 ], [ "▁格", -10.805623054504395 ], [ "31", -10.806045532226562 ], [ "▁潮", -10.806175231933594 ], [ "シス", -10.80622673034668 ], [ "常", -10.806344985961914 ], [ "▁故障", -10.806684494018555 ], [ "▁今度", -10.806721687316895 ], [ "▁1984", -10.80689525604248 ], [ "選", -10.806903839111328 ], [ "▁クラウド", -10.806916236877441 ], [ "組", -10.806939125061035 ], [ "▁応用", -10.80711841583252 ], [ "▁限界", -10.807272911071777 ], [ "▁走り", -10.807376861572266 ], [ "▁略", -10.808419227600098 ], [ "AN", -10.808430671691895 ], [ "酒", -10.808655738830566 ], [ "▁伊勢", -10.809086799621582 ], [ "▁キリスト教", -10.809090614318848 ], [ "材", -10.809109687805176 ], [ "▁プライバシー", -10.809134483337402 ], [ "▁だったら", -10.809202194213867 ], [ "37", -10.809682846069336 ], [ "▁あげる", -10.809926986694336 ], [ "フォ", -10.809948921203613 ], [ "▁スマート", -10.810383796691895 ], [ "▁散", -10.810428619384766 ], [ "▁簡単な", -10.810673713684082 ], [ "▁ワールドカップ", -10.811036109924316 ], [ "域", -10.812151908874512 ], [ "▁内外", -10.812254905700684 ], [ "im", -10.8123140335083 ], [ "▁丁寧に", -10.812349319458008 ], [ "39", -10.812593460083008 ], [ "▁ルイ", -10.812726020812988 ], [ "ブルク", -10.813285827636719 ], [ "50", -10.813522338867188 ], [ "▁ステ", -10.813758850097656 ], [ "▁セル", -10.813806533813477 ], [ "ヴァー", -10.81380844116211 ], [ "▁売上", -10.813891410827637 ], [ "らい", -10.814453125 ], [ "▁婚", -10.814495086669922 ], [ "上記", -10.81484603881836 ], [ "恵", -10.814936637878418 ], [ "▁呼称", -10.815424919128418 ], [ "▁いくら", -10.815544128417969 ], [ "▁関与", -10.815553665161133 ], [ "▁関節", -10.81557846069336 ], [ "▁ワクチン", -10.815677642822266 ], [ "張", -10.815704345703125 ], [ "▁正式に", -10.815871238708496 ], [ "▁走る", -10.816620826721191 ], [ "フランス", -10.817098617553711 ], [ "▁SC", -10.817144393920898 ], [ "▁数多く", -10.81795597076416 ], [ "▁少なくとも", -10.818013191223145 ], [ "▁寺院", -10.818359375 ], [ "▁進める", -10.818731307983398 ], [ "ce", -10.818768501281738 ], [ "▁古墳", -10.818899154663086 ], [ "▁異常", -10.819171905517578 ], [ "▁個性", -10.819464683532715 ], [ "▁様式", -10.819546699523926 ], [ "▁いや", -10.819726943969727 ], [ "▁誘導", -10.819780349731445 ], [ "▁広がり", -10.820183753967285 ], [ "▁迎える", -10.820320129394531 ], [ "格", -10.820511817932129 ], [ "▁呼吸", -10.82062816619873 ], [ "▁フォン", -10.82076358795166 ], [ "▁侵攻", -10.821016311645508 ], [ "昔", -10.821340560913086 ], [ "首", -10.821795463562012 ], [ "▁買った", -10.821860313415527 ], [ "▁63", -10.82215690612793 ], [ "▁アイルランド", -10.822314262390137 ], [ "▁速報", -10.822342872619629 ], [ "▁演劇", -10.822437286376953 ], [ "指", -10.822614669799805 ], [ "▁ファー", -10.82287883758545 ], [ "▁改修", -10.82295036315918 ], [ "▁ディズニー", -10.823001861572266 ], [ "▁´", -10.823089599609375 ], [ "▁権力", -10.823220252990723 ], [ "▁捨て", -10.82353687286377 ], [ "▁ましたら", -10.82443904876709 ], [ "▁棟", -10.82447338104248 ], [ "ーム", -10.824545860290527 ], [ "速", -10.824579238891602 ], [ "1999", -10.824584007263184 ], [ "智", -10.824638366699219 ], [ "▁照明", -10.824711799621582 ], [ "ラル", -10.824756622314453 ], [ "ビア", -10.82490062713623 ], [ "いずれ", -10.824922561645508 ], [ "▁合同", -10.825075149536133 ], [ "▁こだわり", -10.825103759765625 ], [ "病", -10.825328826904297 ], [ "▁過ごす", -10.825512886047363 ], [ "▁ミッション", -10.825634956359863 ], [ "▁抗", -10.825634956359863 ], [ "▁timestamp", -10.8259859085083 ], [ "▁ST", -10.826066970825195 ], [ "氏", -10.826300621032715 ], [ "▁スイス", -10.8269681930542 ], [ "▁祭り", -10.82728385925293 ], [ "▁contributor", -10.827411651611328 ], [ "▁プラットフォーム", -10.827425956726074 ], [ "▁県道", -10.827682495117188 ], [ "▁みなさん", -10.827780723571777 ], [ "▁低く", -10.827802658081055 ], [ "▁ようやく", -10.827879905700684 ], [ "▁姉妹", -10.827890396118164 ], [ "眼", -10.82791805267334 ], [ "▁問", -10.827959060668945 ], [ "▁け", -10.827972412109375 ], [ "▁リニューアル", -10.828022003173828 ], [ "▁61", -10.82828426361084 ], [ "術", -10.828350067138672 ], [ "▁発射", -10.82849407196045 ], [ "▁多様", -10.829227447509766 ], [ "▁不良", -10.829276084899902 ], [ "かし", -10.829373359680176 ], [ "▁報酬", -10.82961368560791 ], [ "▁根拠", -10.829750061035156 ], [ "▁負傷", -10.82979965209961 ], [ "▁残した", -10.829998016357422 ], [ "de", -10.83002758026123 ], [ "▁起きて", -10.830275535583496 ], [ "▁微", -10.830387115478516 ], [ "▁樹", -10.830570220947266 ], [ "こんな", -10.83072566986084 ], [ "▁しょう", -10.831138610839844 ], [ "ケット", -10.83121395111084 ], [ "▁ベルト", -10.831340789794922 ], [ "房", -10.831342697143555 ], [ "▁附属", -10.831404685974121 ], [ "寄", -10.831457138061523 ], [ "▁ジム", -10.831823348999023 ], [ "▁フジテレビ", -10.831872940063477 ], [ "▁譲渡", -10.832334518432617 ], [ "▁訪れた", -10.832381248474121 ], [ "★", -10.832632064819336 ], [ "▁車体", -10.83291244506836 ], [ "▁キャスト", -10.833102226257324 ], [ "像", -10.833291053771973 ], [ "▁タンパク", -10.833816528320312 ], [ "▁デスク", -10.834477424621582 ], [ "▁潜水", -10.834766387939453 ], [ "▁山本", -10.835043907165527 ], [ "▁ギリシャ", -10.835229873657227 ], [ "▁高度", -10.8352632522583 ], [ "▁超えて", -10.83571720123291 ], [ "▁知った", -10.835893630981445 ], [ "▁AC", -10.836145401000977 ], [ "分の", -10.836165428161621 ], [ "▁挙げた", -10.836207389831543 ], [ "04", -10.836593627929688 ], [ "一郎", -10.836653709411621 ], [ "▁援助", -10.836833000183105 ], [ "▁アイデア", -10.836995124816895 ], [ "▁争い", -10.83773422241211 ], [ "▁境", -10.837740898132324 ], [ "▁稲", -10.837783813476562 ], [ "▁過ぎて", -10.837991714477539 ], [ "▁モー", -10.838376998901367 ], [ "っちゃ", -10.838418006896973 ], [ "イト", -10.8385009765625 ], [ "▁グリ", -10.838544845581055 ], [ "▁テニス", -10.838590621948242 ], [ "▁主要な", -10.838613510131836 ], [ "▁初頭", -10.83899211883545 ], [ "▁中小", -10.839046478271484 ], [ "▁ブラウン", -10.839176177978516 ], [ "ティック", -10.839239120483398 ], [ "▁清水", -10.839578628540039 ], [ "▁敷地", -10.83966064453125 ], [ "▁亜", -10.839688301086426 ], [ "▁SS", -10.839731216430664 ], [ "▁動", -10.83985424041748 ], [ "75", -10.839998245239258 ], [ "▁弟子", -10.840091705322266 ], [ "PS", -10.840103149414062 ], [ "▁開通", -10.840418815612793 ], [ "弘", -10.840458869934082 ], [ "▁祝", -10.840487480163574 ], [ "▁Microsoft", -10.84054946899414 ], [ "▁何の", -10.840794563293457 ], [ "▁翼", -10.841475486755371 ], [ "▁85", -10.841525077819824 ], [ "▁อ", -10.841776847839355 ], [ "▁境界", -10.841863632202148 ], [ "▁実用", -10.842373847961426 ], [ "▁コラボ", -10.84250545501709 ], [ "▁甲", -10.842508316040039 ], [ "▁覆", -10.84304428100586 ], [ "▁回避", -10.843633651733398 ], [ "▁過ごし", -10.843873023986816 ], [ "▁編入", -10.84416675567627 ], [ "▁見つける", -10.844411849975586 ], [ "▁攻め", -10.844840049743652 ], [ "AT", -10.844941139221191 ], [ "▁静", -10.84505558013916 ], [ "布", -10.845056533813477 ], [ "スキー", -10.845314025878906 ], [ "▁プロデュース", -10.845340728759766 ], [ "▁クーポン", -10.845351219177246 ], [ "man", -10.845845222473145 ], [ "▁井", -10.846060752868652 ], [ "肉", -10.846098899841309 ], [ "▁ポケット", -10.846453666687012 ], [ "▁皮", -10.846659660339355 ], [ "族", -10.84666633605957 ], [ "▁コア", -10.847102165222168 ], [ "▁アメリカン", -10.847430229187012 ], [ "ーナ", -10.847577095031738 ], [ "▁らしく", -10.848380088806152 ], [ "▁役所", -10.848381042480469 ], [ "▁クリーニング", -10.848527908325195 ], [ "se", -10.848825454711914 ], [ "▁充電", -10.849115371704102 ], [ "1980", -10.849135398864746 ], [ "雨", -10.849185943603516 ], [ "ne", -10.849625587463379 ], [ "▁わたり", -10.84998607635498 ], [ "▁令", -10.850235939025879 ], [ "▁津", -10.850942611694336 ], [ "▁一環", -10.85106086730957 ], [ "▁佐", -10.851221084594727 ], [ "▁借り", -10.85136890411377 ], [ "▁兵士", -10.851425170898438 ], [ "▁リード", -10.851663589477539 ], [ "▁融資", -10.851808547973633 ], [ "▁荷物", -10.852049827575684 ], [ "▁人形", -10.852344512939453 ], [ "▁――", -10.852381706237793 ], [ "▁見解", -10.852519035339355 ], [ "皮", -10.852618217468262 ], [ "▁Me", -10.852788925170898 ], [ "細", -10.852855682373047 ], [ "ボー", -10.852913856506348 ], [ "▁フォー", -10.853102684020996 ], [ "クリ", -10.853184700012207 ], [ "▁興", -10.8533296585083 ], [ "▁ステップ", -10.85336685180664 ], [ "仕事", -10.854116439819336 ], [ "▁政党", -10.85440731048584 ], [ "若", -10.854902267456055 ], [ "▁おそらく", -10.855191230773926 ], [ "▁ミサイル", -10.855195999145508 ], [ "▁東洋", -10.85539436340332 ], [ "マス", -10.855630874633789 ], [ "たい", -10.855684280395508 ], [ "▁飯", -10.855759620666504 ], [ "▁漢字", -10.855849266052246 ], [ "77", -10.856367111206055 ], [ "▁つながり", -10.856627464294434 ], [ "▁全然", -10.856639862060547 ], [ "46", -10.857027053833008 ], [ "▁もっとも", -10.857086181640625 ], [ "88", -10.857219696044922 ], [ "▁むしろ", -10.857489585876465 ], [ "▁傘下", -10.85755443572998 ], [ "▁並んで", -10.857870101928711 ], [ "ワーク", -10.85792350769043 ], [ "▁ポジション", -10.857933044433594 ], [ "▁まさに", -10.858161926269531 ], [ "▁ヴェ", -10.858308792114258 ], [ "▁サイン", -10.85855770111084 ], [ "▁売る", -10.85859203338623 ], [ "英", -10.858636856079102 ], [ "▁便利な", -10.859158515930176 ], [ "34", -10.859264373779297 ], [ "▁定着", -10.859280586242676 ], [ "落", -10.859404563903809 ], [ "壁", -10.859678268432617 ], [ "▁ブレーキ", -10.859721183776855 ], [ "▁紀", -10.860040664672852 ], [ "パス", -10.860044479370117 ], [ "▁立って", -10.860254287719727 ], [ "トレ", -10.8602933883667 ], [ "▁薄", -10.860366821289062 ], [ "▁Mac", -10.860715866088867 ], [ "▁生涯", -10.860946655273438 ], [ "ak", -10.861135482788086 ], [ "▁仏教", -10.861235618591309 ], [ "▁スタッドレス", -10.861878395080566 ], [ "▁パラ", -10.861987113952637 ], [ "▁局長", -10.862184524536133 ], [ "▁マンガ", -10.862237930297852 ], [ "▁消防", -10.862260818481445 ], [ "TV", -10.86234188079834 ], [ "▁衝突", -10.862611770629883 ], [ "▁王者", -10.862715721130371 ], [ "▁トゥ", -10.86280632019043 ], [ "京都", -10.863123893737793 ], [ "86", -10.863222122192383 ], [ "▁生じた", -10.863591194152832 ], [ "▁カタログ", -10.863673210144043 ], [ "弟", -10.863836288452148 ], [ "▁お前", -10.863978385925293 ], [ "▁おお", -10.864136695861816 ], [ "GA", -10.864545822143555 ], [ "▁数値", -10.864629745483398 ], [ "▁飲む", -10.864645004272461 ], [ "▁洗濯", -10.864734649658203 ], [ "▁支部", -10.864771842956543 ], [ "▁ハメ", -10.86489486694336 ], [ "▁パスワード", -10.86491870880127 ], [ "▁循環", -10.865015029907227 ], [ "ノン", -10.865175247192383 ], [ "▁ne", -10.865182876586914 ], [ "▁南西", -10.865326881408691 ], [ "ベン", -10.865435600280762 ], [ "▁離", -10.865676879882812 ], [ "江戸", -10.865726470947266 ], [ "嶋", -10.865971565246582 ], [ "ぬ", -10.866026878356934 ], [ "▁タブレット", -10.866848945617676 ], [ "▁失わ", -10.866933822631836 ], [ "▁河川", -10.866994857788086 ], [ "▁再建", -10.867133140563965 ], [ "▁灯", -10.867159843444824 ], [ "▁茂", -10.867197036743164 ], [ "US", -10.86724853515625 ], [ "ment", -10.867571830749512 ], [ "▁メモ", -10.867574691772461 ], [ "▁フィリピン", -10.867624282836914 ], [ "▁試み", -10.867773056030273 ], [ "▁特許", -10.867806434631348 ], [ "持", -10.867871284484863 ], [ "▁1983", -10.867951393127441 ], [ "▁変わった", -10.868167877197266 ], [ "プレ", -10.868319511413574 ], [ "▁苦", -10.868467330932617 ], [ "歯", -10.868522644042969 ], [ "▁追", -10.868903160095215 ], [ "ub", -10.869268417358398 ], [ "▁陽", -10.869527816772461 ], [ "▁かけた", -10.86963176727295 ], [ "ーラ", -10.869709014892578 ], [ "▁スケジュール", -10.869715690612793 ], [ "▁急行", -10.8699312210083 ], [ "サイト", -10.870037078857422 ], [ "▁防災", -10.870318412780762 ], [ "▁含めた", -10.870340347290039 ], [ "▁演技", -10.870437622070312 ], [ "こんにちは", -10.870513916015625 ], [ "▁半年", -10.870737075805664 ], [ "48", -10.870755195617676 ], [ "リスト", -10.870811462402344 ], [ "▁驚き", -10.870872497558594 ], [ "ID", -10.87134838104248 ], [ "▁起こった", -10.871546745300293 ], [ "▁抑え", -10.871564865112305 ], [ "エイ", -10.871740341186523 ], [ "78", -10.872169494628906 ], [ "▁手伝い", -10.872354507446289 ], [ "▁ラテン", -10.872464179992676 ], [ "宿", -10.872557640075684 ], [ "▁由", -10.872576713562012 ], [ "▁年金", -10.872879028320312 ], [ "▁ジャック", -10.872980117797852 ], [ "▁手順", -10.872981071472168 ], [ "▁合って", -10.873331069946289 ], [ "▁国境", -10.873489379882812 ], [ "跡", -10.873665809631348 ], [ "主に", -10.874089241027832 ], [ "▁プロレス", -10.874284744262695 ], [ "▁まだまだ", -10.874490737915039 ], [ "先日", -10.874627113342285 ], [ "▁あら", -10.874648094177246 ], [ "▁グランド", -10.874650955200195 ], [ "護", -10.875105857849121 ], [ "▁冒険", -10.875123977661133 ], [ "▁楽しみに", -10.87546443939209 ], [ "▁終わって", -10.87546443939209 ], [ "▁喜び", -10.876097679138184 ], [ "▁向き", -10.876437187194824 ], [ "▁なれ", -10.876448631286621 ], [ "▁堀", -10.87702751159668 ], [ "▁孝", -10.877420425415039 ], [ "矢", -10.877500534057617 ], [ "▁1950", -10.877579689025879 ], [ "65", -10.877811431884766 ], [ "全国", -10.877900123596191 ], [ "▁んでしょう", -10.877958297729492 ], [ "▁伯", -10.878124237060547 ], [ "チュ", -10.878190040588379 ], [ "▁つけた", -10.878490447998047 ], [ "変", -10.878697395324707 ], [ "▁ストリート", -10.878839492797852 ], [ "▁マガジン", -10.878912925720215 ], [ "▁テープ", -10.878924369812012 ], [ "無料", -10.879100799560547 ], [ "▁アラ", -10.879172325134277 ], [ "▁来店", -10.879179000854492 ], [ "our", -10.879197120666504 ], [ "将", -10.879258155822754 ], [ "▁簡単", -10.879963874816895 ], [ "▁生地", -10.88005542755127 ], [ "▁まち", -10.880130767822266 ], [ "▁渡", -10.880749702453613 ], [ "▁72", -10.880783081054688 ], [ "代表", -10.880885124206543 ], [ "▁テレ", -10.881006240844727 ], [ "▁噂", -10.881402015686035 ], [ "▁ペース", -10.881463050842285 ], [ "酸", -10.88162899017334 ], [ "▁海上", -10.8817138671875 ], [ "05", -10.882214546203613 ], [ "▁東西", -10.882291793823242 ], [ "▁不要", -10.882367134094238 ], [ "▁エアコン", -10.882379531860352 ], [ "ウィ", -10.883003234863281 ], [ "▁藩主", -10.883223533630371 ], [ "▁実装", -10.883233070373535 ], [ "▁ビュー", -10.883420944213867 ], [ "▁決意", -10.883529663085938 ], [ "▁数々", -10.883766174316406 ], [ "▁修了", -10.883804321289062 ], [ "▁思え", -10.88386344909668 ], [ "84", -10.884475708007812 ], [ "艦", -10.88483715057373 ], [ "▁息", -10.88503360748291 ], [ "▁スキン", -10.885136604309082 ], [ "▁類似", -10.885190963745117 ], [ "▁挿入", -10.885714530944824 ], [ "▁しろ", -10.885893821716309 ], [ "▁描いて", -10.8865966796875 ], [ "▁ウクライナ", -10.886982917785645 ], [ "up", -10.887101173400879 ], [ "本日", -10.887109756469727 ], [ "▁180", -10.887373924255371 ], [ "▁鶴", -10.887730598449707 ], [ "▁`", -10.88797378540039 ], [ "▁クレ", -10.888189315795898 ], [ "▁伊勢丹", -10.888215065002441 ], [ "甲", -10.888479232788086 ], [ "▁1982", -10.888660430908203 ], [ "▁PR", -10.888731002807617 ], [ "▁折", -10.88880729675293 ], [ "▁開く", -10.888947486877441 ], [ "▁デメリット", -10.889228820800781 ], [ "給", -10.889327049255371 ], [ "▁言及", -10.889598846435547 ], [ "素", -10.88985538482666 ], [ "▁開示", -10.89022159576416 ], [ "▁高める", -10.890497207641602 ], [ "犬", -10.890711784362793 ], [ "▁北西", -10.890727043151855 ], [ "▁ウィリアム", -10.890804290771484 ], [ "片", -10.890810012817383 ], [ "▁95", -10.890863418579102 ], [ "▁チェ", -10.89088249206543 ], [ "イギリス", -10.89088249206543 ], [ "▁呼んで", -10.89091968536377 ], [ "▁3000", -10.89104175567627 ], [ "▁半ば", -10.891271591186523 ], [ "そういう", -10.891427040100098 ], [ "▁タッチ", -10.891545295715332 ], [ "▁准教授", -10.892192840576172 ], [ "06", -10.89240837097168 ], [ "▁大賞", -10.892534255981445 ], [ "64", -10.892694473266602 ], [ "▁よし", -10.892744064331055 ], [ "▁プレス", -10.893136024475098 ], [ "▁させて", -10.893285751342773 ], [ "▁次第に", -10.893506050109863 ], [ "配", -10.893511772155762 ], [ "休", -10.89358901977539 ], [ "▁オーナー", -10.893610000610352 ], [ "▁仕方", -10.893628120422363 ], [ "▁優しい", -10.893856048583984 ], [ "刊", -10.894163131713867 ], [ "▁露", -10.894722938537598 ], [ "▁サーバ", -10.894787788391113 ], [ "▁休日", -10.8948335647583 ], [ "ET", -10.894859313964844 ], [ "▁柱", -10.894939422607422 ], [ "青", -10.894969940185547 ], [ "▁アプローチ", -10.895113945007324 ], [ "▁埋め", -10.895456314086914 ], [ "▁ただし", -10.895459175109863 ], [ "▁スイッチ", -10.895560264587402 ], [ "▁明確に", -10.895963668823242 ], [ "▁個体", -10.896089553833008 ], [ "送ら", -10.896605491638184 ], [ "▁北朝鮮", -10.896717071533203 ], [ "ard", -10.896926879882812 ], [ "やま", -10.897140502929688 ], [ "▁べきだ", -10.897154808044434 ], [ "▁増える", -10.897178649902344 ], [ "▁頂く", -10.897305488586426 ], [ "44", -10.897472381591797 ], [ "▁めの", -10.8975191116333 ], [ "▁レディ", -10.898299217224121 ], [ "より", -10.89868450164795 ], [ "▁バラエティ", -10.899832725524902 ], [ "送", -10.899897575378418 ], [ "▁CR", -10.900067329406738 ], [ "▁若干", -10.900129318237305 ], [ "ビン", -10.900198936462402 ], [ "ケー", -10.900211334228516 ], [ "▁工", -10.900315284729004 ], [ "▁代行", -10.900318145751953 ], [ "▁都道府県", -10.900429725646973 ], [ "▁子会社", -10.900575637817383 ], [ "08", -10.90064525604248 ], [ "▁辞書", -10.900684356689453 ], [ "ai", -10.900707244873047 ], [ "ack", -10.900890350341797 ], [ "▁フラ", -10.9009428024292 ], [ "▁エレ", -10.900986671447754 ], [ "▁本拠", -10.901037216186523 ], [ "▁入荷", -10.901206970214844 ], [ "スティ", -10.901406288146973 ], [ "▁描写", -10.901653289794922 ], [ "▁ジャズ", -10.90184497833252 ], [ "▁帰", -10.902223587036133 ], [ "▁収め", -10.902702331542969 ], [ "フル", -10.902730941772461 ], [ "▁with", -10.903401374816895 ], [ "▁CORE", -10.903548240661621 ], [ "末", -10.903640747070312 ], [ "▁公認", -10.903825759887695 ], [ "▁密", -10.903865814208984 ], [ "全て", -10.904513359069824 ], [ "▁プリント", -10.904550552368164 ], [ "▁遺", -10.904727935791016 ], [ "em", -10.904818534851074 ], [ "▁♡", -10.904866218566895 ], [ "ワー", -10.905102729797363 ], [ "▁ダメージ", -10.905252456665039 ], [ "▁↓", -10.905340194702148 ], [ "▁汗", -10.90549087524414 ], [ "▁役員", -10.905628204345703 ], [ "▁小林", -10.905649185180664 ], [ "07", -10.90567684173584 ], [ "▁Al", -10.905692100524902 ], [ "▁チャンピオン", -10.90581226348877 ], [ "▁上野", -10.905845642089844 ], [ "▁退", -10.905912399291992 ], [ "▁実業", -10.90629768371582 ], [ "オス", -10.906305313110352 ], [ "▁キャンパス", -10.907663345336914 ], [ "▁とにかく", -10.907880783081055 ], [ "▁送", -10.908178329467773 ], [ "▁バトル", -10.908248901367188 ], [ "▁選定", -10.909293174743652 ], [ "▁北京", -10.909351348876953 ], [ "▁大切です", -10.909360885620117 ], [ "▁解体", -10.909403800964355 ], [ "▁次に", -10.90949535369873 ], [ "レーション", -10.909542083740234 ], [ "▁空軍", -10.90955924987793 ], [ "▁IP", -10.909643173217773 ], [ "▁審議", -10.909833908081055 ], [ "▁すなわち", -10.909945487976074 ], [ "69", -10.910168647766113 ], [ "▁現金", -10.910181045532227 ], [ "▁口座", -10.91080379486084 ], [ "▁ドレス", -10.910920143127441 ], [ "出す", -10.910983085632324 ], [ "▁貴重な", -10.911042213439941 ], [ "41", -10.911160469055176 ], [ "▁オーディオ", -10.911203384399414 ], [ "ヴォ", -10.911407470703125 ], [ "▁衣装", -10.911413192749023 ], [ "住", -10.911454200744629 ], [ "延", -10.911587715148926 ], [ "▁飲んで", -10.91175365447998 ], [ "03", -10.911887168884277 ], [ "▁カール", -10.912046432495117 ], [ "▁敗れた", -10.912087440490723 ], [ "出し", -10.912233352661133 ], [ "ส", -10.912367820739746 ], [ "▁マネジメント", -10.912367820739746 ], [ "ma", -10.91275405883789 ], [ "▁停車", -10.913187026977539 ], [ "交通", -10.913352966308594 ], [ "51", -10.914313316345215 ], [ "ou", -10.914480209350586 ], [ "RI", -10.91466236114502 ], [ "▁信じ", -10.914831161499023 ], [ "q", -10.914958000183105 ], [ "▁詰め", -10.914974212646484 ], [ "▁カ月", -10.915030479431152 ], [ "あらすじ", -10.9150972366333 ], [ "▁火災", -10.915226936340332 ], [ "▁び", -10.915623664855957 ], [ "▁職人", -10.91565990447998 ], [ "▁残念", -10.9159517288208 ], [ "▁仕", -10.916037559509277 ], [ "▁ガー", -10.916135787963867 ], [ "砲", -10.916177749633789 ], [ "▁会見", -10.91646671295166 ], [ "庭", -10.91647720336914 ], [ "写真", -10.917375564575195 ], [ "▁無かった", -10.917677879333496 ], [ "姫", -10.917706489562988 ], [ "▁申込", -10.918342590332031 ], [ "▁エジプト", -10.9187650680542 ], [ "53", -10.918862342834473 ], [ "ab", -10.919367790222168 ], [ "おう", -10.919395446777344 ], [ "▁西武", -10.919438362121582 ], [ "▁同期", -10.91978931427002 ], [ "▁悩んで", -10.919836044311523 ], [ "▁信じて", -10.920056343078613 ], [ "02", -10.920075416564941 ], [ "▁繊維", -10.920488357543945 ], [ "▁移り", -10.920580863952637 ], [ "▁張り", -10.920988082885742 ], [ "▁昇", -10.921756744384766 ], [ "▁ボランティア", -10.921969413757324 ], [ "▁遅く", -10.92224407196045 ], [ "▁オペラ", -10.92261028289795 ], [ "顔", -10.922727584838867 ], [ "次郎", -10.923234939575195 ], [ "▁苦労", -10.923256874084473 ], [ "▁ラグビー", -10.923744201660156 ], [ "pe", -10.92390251159668 ], [ "▁軽減", -10.924031257629395 ], [ "証", -10.92416000366211 ], [ "▁喜", -10.92431640625 ], [ "▁前回", -10.924522399902344 ], [ "ナイ", -10.924938201904297 ], [ "RO", -10.925053596496582 ], [ "昭和", -10.925239562988281 ], [ "▁サラ", -10.925392150878906 ], [ "▁交代", -10.925559043884277 ], [ "▁現れる", -10.92572021484375 ], [ "人口", -10.926432609558105 ], [ "▁取", -10.926569938659668 ], [ "▁ゲイ", -10.926887512207031 ], [ "▁出荷", -10.926931381225586 ], [ "▁選んだ", -10.927119255065918 ], [ "▁運", -10.927360534667969 ], [ "▁打率", -10.927536964416504 ], [ "関連", -10.927577018737793 ], [ "▁到達", -10.927590370178223 ], [ "▁トルコ", -10.92798137664795 ], [ "▁窓口", -10.928263664245605 ], [ "七", -10.928461074829102 ], [ "《", -10.92864990234375 ], [ "▁au", -10.929035186767578 ], [ "1998", -10.92908763885498 ], [ "▁奴隷", -10.929203987121582 ], [ "▁寒", -10.929234504699707 ], [ "▁ベルリン", -10.92923641204834 ], [ "▁ホルモン", -10.929259300231934 ], [ "▁ポルトガル", -10.929370880126953 ], [ "▁老人", -10.929443359375 ], [ "▁唐", -10.930023193359375 ], [ "▁除き", -10.930098533630371 ], [ "▁面接", -10.930109977722168 ], [ "望", -10.930587768554688 ], [ "▁1972", -10.930611610412598 ], [ "▁北東", -10.931269645690918 ], [ "43", -10.931435585021973 ], [ "▁弁当", -10.931638717651367 ], [ "▁フェア", -10.931658744812012 ], [ "▁奇", -10.931784629821777 ], [ "なので", -10.932402610778809 ], [ "od", -10.932404518127441 ], [ "▁休止", -10.932570457458496 ], [ "▁自殺", -10.932642936706543 ], [ "▁URL", -10.932646751403809 ], [ "67", -10.932713508605957 ], [ "▁大事な", -10.933155059814453 ], [ "▁予告", -10.933168411254883 ], [ "PC", -10.933265686035156 ], [ "わり", -10.933345794677734 ], [ "けん", -10.933478355407715 ], [ "▁積", -10.93364143371582 ], [ "▁末期", -10.934078216552734 ], [ "▁マリア", -10.93408489227295 ], [ "▁模擬", -10.934181213378906 ], [ "▁仮面", -10.934228897094727 ], [ "ide", -10.934432029724121 ], [ "ッター", -10.93446159362793 ], [ "▁ワシントン", -10.934839248657227 ], [ "虫", -10.934883117675781 ], [ "▁紅", -10.935072898864746 ], [ "▁ふた", -10.935213088989258 ], [ "使", -10.935391426086426 ], [ "▁人員", -10.935441970825195 ], [ "▁トー", -10.935468673706055 ], [ "▁法令", -10.935687065124512 ], [ "▁ハル", -10.935707092285156 ], [ "▁タワー", -10.935722351074219 ], [ "▁83", -10.936131477355957 ], [ "▁エンジニア", -10.936249732971191 ], [ "▁任せ", -10.936534881591797 ], [ "▁ブーム", -10.93661880493164 ], [ "CD", -10.936935424804688 ], [ "▁ビタミン", -10.93721866607666 ], [ "▁フレ", -10.93787670135498 ], [ "▁推薦", -10.937956809997559 ], [ "▁出来た", -10.937957763671875 ], [ "▁抑制", -10.938056945800781 ], [ "▁歴代", -10.938165664672852 ], [ "▁抱えて", -10.938321113586426 ], [ "祭", -10.938362121582031 ], [ "▁巨人", -10.938419342041016 ], [ "▁起こり", -10.938488006591797 ], [ "▁語った", -10.938647270202637 ], [ "雪", -10.938678741455078 ], [ "▁真実", -10.939223289489746 ], [ "▁十分な", -10.940074920654297 ], [ "▁81", -10.940132141113281 ], [ "▁手間", -10.940385818481445 ], [ "▁上演", -10.940589904785156 ], [ "▁言", -10.940631866455078 ], [ "ec", -10.940634727478027 ], [ "▁ソウル", -10.940681457519531 ], [ "局", -10.940847396850586 ], [ "▁あまりに", -10.940959930419922 ], [ "メール", -10.941201210021973 ], [ "▁秘", -10.94152545928955 ], [ "▁本当の", -10.941668510437012 ], [ "▁ワイド", -10.941725730895996 ], [ "▁電池", -10.941914558410645 ], [ "▁ゴー", -10.942625999450684 ], [ "茶", -10.942726135253906 ], [ "▁ケイ", -10.943137168884277 ], [ "▁1975", -10.9434814453125 ], [ "▁データベース", -10.943535804748535 ], [ "▁細", -10.943604469299316 ], [ "ブリ", -10.943766593933105 ], [ "▁1979", -10.943870544433594 ], [ "▁頻繁に", -10.944282531738281 ], [ "▁シューズ", -10.944306373596191 ], [ "▁軍人", -10.944655418395996 ], [ "▁みたいです", -10.944726943969727 ], [ "76", -10.944878578186035 ], [ "▁強調", -10.94497013092041 ], [ "症", -10.945006370544434 ], [ "▁リゾート", -10.945345878601074 ], [ "▁そもそも", -10.945408821105957 ], [ "87", -10.945456504821777 ], [ "▁ブリ", -10.945470809936523 ], [ "斎", -10.945621490478516 ], [ "▁反乱", -10.945813179016113 ], [ "▁1981", -10.946066856384277 ], [ "▁ハート", -10.946754455566406 ], [ "end", -10.946879386901855 ], [ "▁検出", -10.947149276733398 ], [ "▁双方", -10.94752025604248 ], [ "▁食べ物", -10.947649955749512 ], [ "MS", -10.947876930236816 ], [ "▁顧問", -10.948063850402832 ], [ "89", -10.948227882385254 ], [ "▁昇進", -10.948330879211426 ], [ "42", -10.948372840881348 ], [ "竹", -10.948408126831055 ], [ "AR", -10.948775291442871 ], [ "▁株主", -10.949057579040527 ], [ "フト", -10.949397087097168 ], [ "▁ゴールデン", -10.949511528015137 ], [ "▁comment", -10.94961166381836 ], [ "▁記入", -10.950042724609375 ], [ "▁売買", -10.950051307678223 ], [ "▁焼", -10.950251579284668 ], [ "▁少しずつ", -10.95050048828125 ], [ "▁最適", -10.950505256652832 ], [ "▁具", -10.951407432556152 ], [ "▁頂け", -10.951419830322266 ], [ "57", -10.951437950134277 ], [ "▁ボー", -10.951542854309082 ], [ "▁All", -10.951775550842285 ], [ "ポン", -10.951960563659668 ], [ "ストン", -10.952317237854004 ], [ "▁Bl", -10.952325820922852 ], [ "▁藤原", -10.952826499938965 ], [ "▁一気に", -10.95290756225586 ], [ "▁単語", -10.952932357788086 ], [ "▁タクシー", -10.953422546386719 ], [ "▁バッテリー", -10.953479766845703 ], [ "▁推測", -10.953546524047852 ], [ "▁見せる", -10.953763961791992 ], [ "クター", -10.954301834106445 ], [ "▁触れ", -10.954516410827637 ], [ "▁デート", -10.95498275756836 ], [ "▁おもちゃ", -10.955180168151855 ], [ "▁警備", -10.955230712890625 ], [ "▁カトリック", -10.955284118652344 ], [ "▁離脱", -10.955306053161621 ], [ "▁金利", -10.955815315246582 ], [ "▁目指し", -10.95623779296875 ], [ "トリー", -10.956411361694336 ], [ "▁ローカル", -10.9566011428833 ], [ "ぜひ", -10.956642150878906 ], [ "帯", -10.956690788269043 ], [ "▁ARMOR", -10.956986427307129 ], [ "▁選択肢", -10.957051277160645 ], [ "▁虫", -10.957140922546387 ], [ "▁調達", -10.957148551940918 ], [ "▁緩和", -10.957244873046875 ], [ "地域", -10.957402229309082 ], [ "湖", -10.957771301269531 ], [ "▁好評", -10.95823860168457 ], [ "▁得な", -10.95825481414795 ], [ "▁死後", -10.958440780639648 ], [ "▁MS", -10.958694458007812 ], [ "入れ", -10.958853721618652 ], [ "38", -10.958942413330078 ], [ "▁倉庫", -10.958958625793457 ], [ "つけ", -10.959266662597656 ], [ "▁選抜", -10.959342002868652 ], [ "▁日程", -10.959420204162598 ], [ "▁離れ", -10.95955753326416 ], [ "▁備えて", -10.959569931030273 ], [ "▁昨日", -10.959906578063965 ], [ "▁一族", -10.960021018981934 ], [ "▁体系", -10.960031509399414 ], [ "▁1945", -10.960221290588379 ], [ "グリ", -10.96023178100586 ], [ "▁金沢", -10.960897445678711 ], [ "▁合わ", -10.961522102355957 ], [ "キング", -10.96166706085205 ], [ "▁ベン", -10.962382316589355 ], [ "▁的である", -10.962456703186035 ], [ "▁侵入", -10.96290397644043 ], [ "織", -10.96314811706543 ], [ "▁前述", -10.96323013305664 ], [ "ドイツ", -10.963382720947266 ], [ "▁GP", -10.96345329284668 ], [ "▁しかも", -10.963517189025879 ], [ "▁ドン", -10.9635648727417 ], [ "▁取れ", -10.964313507080078 ], [ "むら", -10.96440601348877 ], [ "▁モンスター", -10.964436531066895 ], [ "麻", -10.96485424041748 ], [ "リエ", -10.965044975280762 ], [ "▁大部分", -10.96568489074707 ], [ "シング", -10.966004371643066 ], [ "ING", -10.966407775878906 ], [ "▁挙げて", -10.966598510742188 ], [ "▁上下", -10.966606140136719 ], [ "▁犯", -10.966917037963867 ], [ "▁演じる", -10.967142105102539 ], [ "▁ロレックス", -10.967362403869629 ], [ "▁コンビ", -10.967655181884766 ], [ "弁", -10.967996597290039 ], [ "▁それほど", -10.968774795532227 ], [ "聞", -10.969000816345215 ], [ "▁毎月", -10.96932601928711 ], [ "▁上陸", -10.969353675842285 ], [ "オフ", -10.969466209411621 ], [ "▁Inc", -10.969498634338379 ], [ "▁プール", -10.969584465026855 ], [ "81", -10.969635009765625 ], [ "▁影", -10.96989917755127 ], [ "クション", -10.970236778259277 ], [ "かり", -10.970298767089844 ], [ "羅", -10.970312118530273 ], [ "83", -10.970356941223145 ], [ "▁スタ", -10.970382690429688 ], [ "▁著書", -10.970399856567383 ], [ "▁はじめて", -10.970569610595703 ], [ "▁述べ", -10.970625877380371 ], [ "▁ボーナス", -10.970662117004395 ], [ "▁経歴", -10.970786094665527 ], [ "▁起", -10.970900535583496 ], [ "▁入口", -10.97104549407959 ], [ "▁創立", -10.971214294433594 ], [ "▁頂いた", -10.971372604370117 ], [ "温", -10.971375465393066 ], [ "撃", -10.97144889831543 ], [ "▁鹿", -10.971590995788574 ], [ "▁弱い", -10.971707344055176 ], [ "まった", -10.971903800964355 ], [ "盛", -10.971992492675781 ], [ "系", -10.972014427185059 ], [ "▁下り", -10.972067832946777 ], [ "AC", -10.972183227539062 ], [ "▁とり", -10.972280502319336 ], [ "▁歩兵", -10.972419738769531 ], [ "▁恐怖", -10.972704887390137 ], [ "▁寄付", -10.972734451293945 ], [ "▁持続", -10.973191261291504 ], [ "▁役立つ", -10.973219871520996 ], [ "スカ", -10.97332763671875 ], [ "▁キリスト", -10.973467826843262 ], [ "フリー", -10.973607063293457 ], [ "ho", -10.973830223083496 ], [ "▁ม", -10.973942756652832 ], [ "▁犠牲", -10.974493026733398 ], [ "▁耐久", -10.974596977233887 ], [ "▁ジョ", -10.974749565124512 ], [ "▁詐欺", -10.97480297088623 ], [ "賞", -10.974944114685059 ], [ "SE", -10.975196838378906 ], [ "得", -10.975549697875977 ], [ "▁向かい", -10.975857734680176 ], [ "▁1978", -10.975920677185059 ], [ "結果", -10.975970268249512 ], [ "ファン", -10.976008415222168 ], [ "▁連れ", -10.977215766906738 ], [ "▁免疫", -10.977527618408203 ], [ "▁伝えて", -10.97758960723877 ], [ "▁向", -10.977662086486816 ], [ "▁全般", -10.977724075317383 ], [ "ーブ", -10.977883338928223 ], [ "しょう", -10.977989196777344 ], [ "▁出来て", -10.978134155273438 ], [ "▁酸素", -10.978853225708008 ], [ "▁守備", -10.97901725769043 ], [ "▁勝負", -10.979056358337402 ], [ "▁勝手に", -10.979185104370117 ], [ "▁調べ", -10.97927188873291 ], [ "▁ショック", -10.979497909545898 ], [ "▁マイクロ", -10.98045825958252 ], [ "▁メイ", -10.980826377868652 ], [ "▁ピー", -10.981369972229004 ], [ "▁返品", -10.981528282165527 ], [ "▁確かに", -10.981677055358887 ], [ "▁評論", -10.981705665588379 ], [ "メル", -10.981789588928223 ], [ "ドラ", -10.981922149658203 ], [ "▁あらかじめ", -10.982044219970703 ], [ "▁そうで", -10.98207950592041 ], [ "▁・・・", -10.982455253601074 ], [ "▁街道", -10.982455253601074 ], [ "▁ラウンド", -10.9827241897583 ], [ "児", -10.982807159423828 ], [ "ナス", -10.983048439025879 ], [ "▁パーカー", -10.983146667480469 ], [ "▁De", -10.983182907104492 ], [ "らし", -10.9833345413208 ], [ "▁いかがでしょう", -10.983383178710938 ], [ "56", -10.983518600463867 ], [ "▁代替", -10.983677864074707 ], [ "幅", -10.98372745513916 ], [ "交響", -10.983981132507324 ], [ "▁1,000", -10.984042167663574 ], [ "遊", -10.984081268310547 ], [ "AD", -10.984349250793457 ], [ "▁トレード", -10.984416007995605 ], [ "▁尻", -10.984453201293945 ], [ "▁寛", -10.984729766845703 ], [ "▁紫", -10.985208511352539 ], [ "悪", -10.985234260559082 ], [ "ネー", -10.98532485961914 ], [ "▁決まって", -10.98563003540039 ], [ "▁講義", -10.985630989074707 ], [ "▁人事", -10.985710144042969 ], [ "▁早期", -10.985772132873535 ], [ "▁コマンド", -10.986066818237305 ], [ "、", -10.98630142211914 ], [ "▁全面", -10.986391067504883 ], [ "▁コンビニ", -10.986531257629395 ], [ "▁改名", -10.987541198730469 ], [ "赤", -10.987606048583984 ], [ "▁見直し", -10.987648010253906 ], [ "SC", -10.987717628479004 ], [ "建", -10.98797607421875 ], [ "▁テクノロジー", -10.988290786743164 ], [ "▁ドーム", -10.988332748413086 ], [ "▁ドラフト", -10.988337516784668 ], [ "▁魂", -10.988780975341797 ], [ "▁スト", -10.989167213439941 ], [ "▁通勤", -10.989505767822266 ], [ "▁比べる", -10.98966121673584 ], [ "▁赤い", -10.989717483520508 ], [ "1997", -10.989777565002441 ], [ "▁浜松", -10.989892959594727 ], [ "がい", -10.989982604980469 ], [ "▁1973", -10.990143775939941 ], [ "▁SF", -10.99021053314209 ], [ "▁To", -10.99024486541748 ], [ "▁ヒーロー", -10.990402221679688 ], [ "令", -10.990482330322266 ], [ "▁神話", -10.99071979522705 ], [ "▁大丈夫", -10.990873336791992 ], [ "尚", -10.991044998168945 ], [ "▁住まい", -10.991080284118652 ], [ "▁ターミナル", -10.991118431091309 ], [ "確", -10.991168975830078 ], [ "▁著", -10.991204261779785 ], [ "▁なったら", -10.991382598876953 ], [ "ーター", -10.991393089294434 ], [ "▁やす", -10.991477966308594 ], [ "らく", -10.991801261901855 ], [ "▁もともと", -10.991835594177246 ], [ "▁日曜日", -10.99194049835205 ], [ "▁興行", -10.9922513961792 ], [ "ショ", -10.992523193359375 ], [ "強", -10.9927339553833 ], [ "▁かい", -10.993118286132812 ], [ "人間", -10.993119239807129 ], [ "▁待", -10.99321174621582 ], [ "▁小学生", -10.993375778198242 ], [ "▁ガールズ", -10.993529319763184 ], [ "▁畑", -10.993637084960938 ], [ "▁課長", -10.994311332702637 ], [ "▁起源", -10.994736671447754 ], [ "礼", -10.994937896728516 ], [ "☆", -10.994943618774414 ], [ "▁才能", -10.995105743408203 ], [ "を", -10.99522876739502 ], [ "▁嫁", -10.995299339294434 ], [ "刀", -10.995415687561035 ], [ "海外", -10.995526313781738 ], [ "っこ", -10.995565414428711 ], [ "▁html", -10.995725631713867 ], [ "▁目の前", -10.995757102966309 ], [ "ぞ", -10.995766639709473 ], [ "1970", -10.9957914352417 ], [ "▁スク", -10.996283531188965 ], [ "▁怒り", -10.996524810791016 ], [ "男性", -10.996603965759277 ], [ "▁占める", -10.99722671508789 ], [ "▁トーナメント", -10.997509002685547 ], [ "▁滝", -10.997543334960938 ], [ "▁加藤", -10.997564315795898 ], [ "▁古典", -10.998063087463379 ], [ "題", -10.998260498046875 ], [ "▁飛行機", -10.998345375061035 ], [ "▁訪れる", -10.998424530029297 ], [ "ディア", -10.99852466583252 ], [ "▁特急", -10.998637199401855 ], [ "▁La", -10.998734474182129 ], [ "▁きょう", -10.998770713806152 ], [ "▁授与", -10.998847961425781 ], [ "リアン", -10.999383926391602 ], [ "▁養成", -10.999462127685547 ], [ "▁スケート", -10.999695777893066 ], [ "折", -10.999931335449219 ], [ "▁戻った", -10.999958038330078 ], [ "▁宇", -11.000102043151855 ], [ "▁三田", -11.000256538391113 ], [ "▁ちょうど", -11.000386238098145 ], [ "景", -11.0004301071167 ], [ "▁エコ", -11.000627517700195 ], [ "▁財務", -11.000835418701172 ], [ "▁進", -11.000940322875977 ], [ "▁最適な", -11.001424789428711 ], [ "▁失", -11.001564979553223 ], [ "▁なれる", -11.001623153686523 ], [ "▁集めた", -11.001662254333496 ], [ "▁登", -11.001964569091797 ], [ "▁こんなに", -11.002145767211914 ], [ "現", -11.002159118652344 ], [ "▁username", -11.00234603881836 ], [ "▁700", -11.002542495727539 ], [ "▁FM", -11.002579689025879 ], [ "▁偏", -11.002779006958008 ], [ "▁前身", -11.002901077270508 ], [ "▁ダイヤ", -11.00301456451416 ], [ "▁ロサンゼルス", -11.003028869628906 ], [ "フォー", -11.003610610961914 ], [ "ロウ", -11.003718376159668 ], [ "▁脱出", -11.003817558288574 ], [ "乳", -11.003939628601074 ], [ "▁権限", -11.004446029663086 ], [ "▁メトロ", -11.004499435424805 ], [ "▁収益", -11.005017280578613 ], [ "▁メモリ", -11.005403518676758 ], [ "▁加速", -11.005428314208984 ], [ "▁セント", -11.005657196044922 ], [ "▁国鉄", -11.00574016571045 ], [ "95", -11.005849838256836 ], [ "作品", -11.005950927734375 ], [ "▁石油", -11.005961418151855 ], [ "▁装着", -11.006033897399902 ], [ "▁正しく", -11.00625228881836 ], [ "▁1971", -11.006309509277344 ], [ "▁果たして", -11.006319999694824 ], [ "▁ブレ", -11.006396293640137 ], [ "隆", -11.006633758544922 ], [ "UN", -11.006731986999512 ], [ "▁業績", -11.007095336914062 ], [ "▁枝", -11.007149696350098 ], [ "▁新しく", -11.007491111755371 ], [ "▁作者", -11.007740020751953 ], [ "幕", -11.00778865814209 ], [ "詳しく", -11.007895469665527 ], [ "層", -11.007943153381348 ], [ "▁入会", -11.008013725280762 ], [ "フィー", -11.008218765258789 ], [ "創", -11.008503913879395 ], [ "▁避ける", -11.008626937866211 ], [ "▁絶", -11.009031295776367 ], [ "mo", -11.009072303771973 ], [ "▁挨拶", -11.009414672851562 ], [ "▁誤", -11.009798049926758 ], [ "▁人妻", -11.010337829589844 ], [ "NA", -11.010510444641113 ], [ "▁難しく", -11.010517120361328 ], [ "▁デュ", -11.010526657104492 ], [ "▁旦那", -11.01059341430664 ], [ "▁なんと", -11.010612487792969 ], [ "▁モチーフ", -11.010627746582031 ], [ "版", -11.010713577270508 ], [ "客", -11.010748863220215 ], [ "FC", -11.011324882507324 ], [ "73", -11.011357307434082 ], [ "▁世の中", -11.011737823486328 ], [ "▁MB", -11.011771202087402 ], [ "▁USB", -11.011882781982422 ], [ "スケ", -11.012299537658691 ], [ "▁アウトドア", -11.01235294342041 ], [ "▁ガーデン", -11.0125732421875 ], [ "▁pro", -11.012728691101074 ], [ "▁登山", -11.012937545776367 ], [ "▁旗", -11.013026237487793 ], [ "▁サル", -11.013113975524902 ], [ "▁コール", -11.013205528259277 ], [ "1996", -11.013359069824219 ], [ "ist", -11.013497352600098 ], [ "したがって", -11.013785362243652 ], [ "ゴン", -11.013937950134277 ], [ "則", -11.014019012451172 ], [ "▁バカ", -11.014399528503418 ], [ "▁避け", -11.01447582244873 ], [ "▁命じ", -11.014726638793945 ], [ "綱", -11.014962196350098 ], [ "▁推移", -11.015029907226562 ], [ "▁だい", -11.015303611755371 ], [ "▁110", -11.015586853027344 ], [ "▁成人", -11.015735626220703 ], [ "リュ", -11.015795707702637 ], [ "▁音源", -11.01583194732666 ], [ "▁フィギュア", -11.015913009643555 ], [ "▁アンケート", -11.016115188598633 ], [ "▁あげて", -11.016195297241211 ], [ "プル", -11.0164155960083 ], [ "▁まるで", -11.016429901123047 ], [ "▁豆", -11.016698837280273 ], [ "▁1976", -11.016719818115234 ], [ "国際", -11.016728401184082 ], [ "▁録", -11.016798973083496 ], [ "達", -11.016814231872559 ], [ "▁1969", -11.016940116882324 ], [ "両", -11.01697063446045 ], [ "商", -11.017129898071289 ], [ "▁取った", -11.017169952392578 ], [ "▁ご飯", -11.017295837402344 ], [ "▁プロフィール", -11.01774787902832 ], [ "喜", -11.017760276794434 ], [ "▁出品", -11.01777172088623 ], [ "▁ミュージシャン", -11.017827033996582 ], [ "▁池田", -11.017951011657715 ], [ "老", -11.018054962158203 ], [ "▁1974", -11.01805591583252 ], [ "▁嘘", -11.018352508544922 ], [ "▁開いて", -11.018688201904297 ], [ "▁桁", -11.018738746643066 ], [ "▁帝", -11.019346237182617 ], [ "想", -11.019686698913574 ], [ "▁一貫", -11.019779205322266 ], [ "▁軽く", -11.019843101501465 ], [ "返", -11.019909858703613 ], [ "▁通る", -11.019972801208496 ], [ "ear", -11.020231246948242 ], [ "200", -11.02052116394043 ], [ "▁発明", -11.020759582519531 ], [ "兵衛", -11.020994186401367 ], [ "▁ディレクター", -11.021284103393555 ], [ "▁注", -11.021523475646973 ], [ "番組", -11.021639823913574 ], [ "▁現れ", -11.021652221679688 ], [ "▁連結", -11.021718978881836 ], [ "▁沿岸", -11.02176284790039 ], [ "▁懸念", -11.02193832397461 ], [ "ix", -11.02196216583252 ], [ "▁mg", -11.021990776062012 ], [ "いだ", -11.022368431091309 ], [ "▁王子", -11.022505760192871 ], [ "▁地理", -11.022541999816895 ], [ "▁護衛", -11.022957801818848 ], [ "▁国王", -11.022970199584961 ], [ "▁騎士", -11.02353572845459 ], [ "▁86", -11.023581504821777 ], [ "右", -11.023962020874023 ], [ "▁サイクル", -11.0247163772583 ], [ "▁ロケット", -11.024788856506348 ], [ "弾", -11.024942398071289 ], [ "込", -11.024946212768555 ], [ "▁たる", -11.025118827819824 ], [ "▁女王", -11.025198936462402 ], [ "回り", -11.025246620178223 ], [ "▁濃度", -11.025537490844727 ], [ "▁アク", -11.025781631469727 ], [ "▁上部", -11.02612590789795 ], [ "▁膝", -11.026238441467285 ], [ "▁幼稚園", -11.02627944946289 ], [ "▁入門", -11.026464462280273 ], [ "▁元気", -11.026806831359863 ], [ "協", -11.026895523071289 ], [ "▁何らか", -11.026986122131348 ], [ "派", -11.027054786682129 ], [ "▁被災", -11.027205467224121 ], [ "▁込", -11.027356147766113 ], [ "▁イスラエル", -11.0274658203125 ], [ "▁要件", -11.027482986450195 ], [ "▁分けて", -11.027809143066406 ], [ "▁キット", -11.02786636352539 ], [ "▁暗号", -11.028038024902344 ], [ "▁階段", -11.028202056884766 ], [ "戦後", -11.028289794921875 ], [ "▁遠く", -11.02842903137207 ], [ "▁背中", -11.0285005569458 ], [ "忠", -11.028630256652832 ], [ "▁ย", -11.02885627746582 ], [ "フェン", -11.029019355773926 ], [ "▁水素", -11.029119491577148 ], [ "▁クイズ", -11.029582023620605 ], [ "▁題", -11.029593467712402 ], [ "魚", -11.029619216918945 ], [ "ッキー", -11.029726028442383 ], [ "▁思", -11.029780387878418 ], [ "▁近隣", -11.02982234954834 ], [ "決", -11.0299072265625 ], [ "▁自主", -11.029930114746094 ], [ "▁聖書", -11.030045509338379 ], [ "DA", -11.030837059020996 ], [ "ドロ", -11.03123950958252 ], [ "66", -11.031317710876465 ], [ "案", -11.031465530395508 ], [ "しゃ", -11.031608581542969 ], [ "誰", -11.032184600830078 ], [ "AS", -11.032197952270508 ], [ "74", -11.032272338867188 ], [ "▁実力", -11.032376289367676 ], [ "▁やがて", -11.032698631286621 ], [ "▁開放", -11.03274154663086 ], [ "▁ペア", -11.0327787399292 ], [ "▁モール", -11.032856941223145 ], [ "▁泰", -11.032998085021973 ], [ "▁盛り", -11.0330228805542 ], [ "▁1968", -11.033037185668945 ], [ "▁ポリ", -11.033135414123535 ], [ "▁環", -11.033196449279785 ], [ "▁珍しい", -11.033425331115723 ], [ "ゼル", -11.033438682556152 ], [ "▁広がる", -11.033510208129883 ], [ "▁創作", -11.033513069152832 ], [ "▁祖父", -11.033930778503418 ], [ "▁デッキ", -11.03409481048584 ], [ "EL", -11.034109115600586 ], [ "▁IN", -11.034506797790527 ], [ "ガス", -11.034515380859375 ], [ "本当に", -11.034661293029785 ], [ "ありがとう", -11.034798622131348 ], [ "▁放映", -11.0350923538208 ], [ "ホーム", -11.035476684570312 ], [ "兆", -11.035479545593262 ], [ "▁ハンガリー", -11.035734176635742 ], [ "特", -11.03584098815918 ], [ "▁読んだ", -11.035978317260742 ], [ "断", -11.03653621673584 ], [ "art", -11.036810874938965 ], [ "▁そんなに", -11.03714370727539 ], [ "▁クライアント", -11.037372589111328 ], [ "▁当店", -11.037553787231445 ], [ "▁アルコール", -11.037571907043457 ], [ "▁ゆく", -11.037657737731934 ], [ "▁原発", -11.037721633911133 ], [ "ty", -11.037798881530762 ], [ "▁帳", -11.037877082824707 ], [ "▁放", -11.038139343261719 ], [ "▁圧力", -11.038349151611328 ], [ "▁戦隊", -11.038619041442871 ], [ "▁母さん", -11.03874397277832 ], [ "▁国産", -11.038749694824219 ], [ "霊", -11.03885555267334 ], [ "▁元々", -11.038928031921387 ], [ "▁椅子", -11.039116859436035 ], [ "▁しん", -11.039182662963867 ], [ "▁桃", -11.039312362670898 ], [ "▁判", -11.039416313171387 ], [ "▁記号", -11.03945255279541 ], [ "▁住み", -11.03947639465332 ], [ "▁った", -11.039531707763672 ], [ "▁写", -11.039558410644531 ], [ "えた", -11.03977108001709 ], [ "TO", -11.039836883544922 ], [ "▁サークル", -11.039888381958008 ], [ "94", -11.04001235961914 ], [ "▁定番", -11.040018081665039 ], [ "▁一括", -11.040141105651855 ], [ "▁コムーネ", -11.040295600891113 ], [ "▁落", -11.040541648864746 ], [ "▁遠征", -11.040558815002441 ], [ "▁ごく", -11.040580749511719 ], [ "会社", -11.040711402893066 ], [ "82", -11.040792465209961 ], [ "▁マット", -11.040901184082031 ], [ "▁スカート", -11.041070938110352 ], [ "▁見た目", -11.041219711303711 ], [ "▁©", -11.041242599487305 ], [ "習", -11.041444778442383 ], [ "▁正式", -11.04173755645752 ], [ "▁$", -11.041820526123047 ], [ "79", -11.04189395904541 ], [ "▁申込み", -11.042526245117188 ], [ "基", -11.042533874511719 ], [ "ity", -11.043044090270996 ], [ "▁薬剤", -11.043230056762695 ], [ "ph", -11.043294906616211 ], [ "▁武装", -11.043777465820312 ], [ "▁両者", -11.043987274169922 ], [ "▁招待", -11.04401683807373 ], [ "▁近所", -11.044260025024414 ], [ "出さ", -11.044454574584961 ], [ "▁特化", -11.044527053833008 ], [ "▁つくる", -11.044824600219727 ], [ "▁整", -11.044915199279785 ], [ "▁呉", -11.04520034790039 ], [ "枝", -11.045330047607422 ], [ "SP", -11.04574203491211 ], [ "ドー", -11.045785903930664 ], [ "▁1977", -11.046102523803711 ], [ "傷", -11.0465669631958 ], [ "▁失った", -11.046601295471191 ], [ "▁本質", -11.046746253967285 ], [ "▁看板", -11.04746150970459 ], [ "1995", -11.047529220581055 ], [ "▁幹部", -11.048112869262695 ], [ "▁立候補", -11.048269271850586 ], [ "▁安倍", -11.048270225524902 ], [ "▁残す", -11.04843807220459 ], [ "▁賠償", -11.048562049865723 ], [ "▁Yahoo", -11.048731803894043 ], [ "ポジション", -11.048760414123535 ], [ "応", -11.048909187316895 ], [ "▁実家", -11.049017906188965 ], [ "▁血液", -11.049131393432617 ], [ "▁下部", -11.049291610717773 ], [ "▁BS", -11.049341201782227 ], [ "▁起こす", -11.049383163452148 ], [ "ルス", -11.050003051757812 ], [ "▁自民党", -11.050045013427734 ], [ "▁起業", -11.050055503845215 ], [ "結局", -11.050270080566406 ], [ "▁格安", -11.050293922424316 ], [ "ob", -11.050374984741211 ], [ "営", -11.050705909729004 ], [ "▁水準", -11.051170349121094 ], [ "フォード", -11.051292419433594 ], [ "SA", -11.051392555236816 ], [ "▁通行", -11.051548957824707 ], [ "▁ワイ", -11.05155086517334 ], [ "っか", -11.051786422729492 ], [ "っち", -11.05211353302002 ], [ "デス", -11.05220890045166 ], [ "▁戦う", -11.052796363830566 ], [ "▁稼げる", -11.053032875061035 ], [ "▁混", -11.05321979522705 ], [ "▁上手く", -11.053343772888184 ], [ "▁ジャスパー", -11.05335521697998 ], [ "▁美人", -11.05339527130127 ], [ "▁助手", -11.053520202636719 ], [ "▁スコア", -11.054044723510742 ], [ "▁普通に", -11.054186820983887 ], [ "覚", -11.054303169250488 ], [ "▁いただければ", -11.054401397705078 ], [ "▁ิ", -11.054474830627441 ], [ "▁学区", -11.054524421691895 ], [ "▁土曜日", -11.054828643798828 ], [ "▁最小", -11.055078506469727 ], [ "▁ラー", -11.055147171020508 ], [ "62", -11.055227279663086 ], [ "▁たか", -11.055335998535156 ], [ "コム", -11.055560111999512 ], [ "▁支給", -11.055642127990723 ], [ "湯", -11.055670738220215 ], [ "61", -11.055839538574219 ], [ "▁付ける", -11.05594253540039 ], [ "▁コラム", -11.056034088134766 ], [ "▁総理", -11.056771278381348 ], [ "▁気象", -11.057056427001953 ], [ "らん", -11.057075500488281 ], [ "CA", -11.057093620300293 ], [ "▁名付け", -11.057182312011719 ], [ "まあ", -11.05738353729248 ], [ "膜", -11.057406425476074 ], [ "▁紛争", -11.057573318481445 ], [ "陣", -11.057839393615723 ], [ "ープ", -11.057877540588379 ], [ "▁創", -11.057883262634277 ], [ "ガル", -11.058004379272461 ], [ "▁かん", -11.058189392089844 ], [ "▁ショット", -11.058384895324707 ], [ "慶", -11.058478355407715 ], [ "▁5000", -11.058525085449219 ], [ "▁Fi", -11.059002876281738 ], [ "音楽", -11.059033393859863 ], [ "▁教徒", -11.059074401855469 ], [ "▁クル", -11.059250831604004 ], [ "▁電鉄", -11.059295654296875 ], [ "▁軽量", -11.059388160705566 ], [ "72", -11.05953311920166 ], [ "ストーリー", -11.059825897216797 ], [ "▁ヨガ", -11.059889793395996 ], [ "▁おいしい", -11.060300827026367 ], [ "▁ユーロ", -11.060300827026367 ], [ "ow", -11.060455322265625 ], [ "▁くださった", -11.060616493225098 ], [ "▁排除", -11.060765266418457 ], [ "那", -11.060879707336426 ], [ "▁若手", -11.06100845336914 ], [ "チョ", -11.06100845336914 ], [ "▁申告", -11.061102867126465 ], [ "▁総会", -11.061232566833496 ], [ "▁負い", -11.061270713806152 ], [ "▁大変な", -11.06130599975586 ], [ "▁マク", -11.061416625976562 ], [ "▁主流", -11.06155776977539 ], [ "▁医者", -11.061595916748047 ], [ "富", -11.061710357666016 ], [ "▁尚", -11.061785697937012 ], [ "▁水道", -11.062195777893066 ], [ "▁ディスプレイ", -11.062450408935547 ], [ "▁ソビエト", -11.062519073486328 ], [ "願", -11.062830924987793 ], [ "▁落ちて", -11.062995910644531 ], [ "▁ガール", -11.063065528869629 ], [ "▁際して", -11.063130378723145 ], [ "放", -11.063551902770996 ], [ "ゲル", -11.063753128051758 ], [ "▁器具", -11.063821792602539 ], [ "▁Le", -11.064233779907227 ], [ "▁ファースト", -11.064295768737793 ], [ "立ち", -11.06443977355957 ], [ "スコ", -11.064447402954102 ], [ "▁当局", -11.064480781555176 ], [ "▁劉", -11.064496040344238 ], [ "底", -11.064529418945312 ], [ "▁メン", -11.064628601074219 ], [ "▁怖い", -11.06478500366211 ], [ "聖", -11.064851760864258 ], [ "▁88", -11.06493091583252 ], [ "▁スーツ", -11.065112113952637 ], [ "▁有して", -11.065841674804688 ], [ "タス", -11.06631851196289 ], [ "イス", -11.066521644592285 ], [ "▁司法", -11.066532135009766 ], [ "▁ドメイン", -11.066646575927734 ], [ "▁決まった", -11.066661834716797 ], [ "筆", -11.066668510437012 ], [ "▁オーディション", -11.066893577575684 ], [ "▁署名", -11.06690788269043 ], [ "ang", -11.066995620727539 ], [ "▁亡くなった", -11.067346572875977 ], [ "▁国勢", -11.067806243896484 ], [ "▁住", -11.068164825439453 ], [ "▁III", -11.0681734085083 ], [ "結婚", -11.068242073059082 ], [ "▁ポケモン", -11.068276405334473 ], [ "tu", -11.068326950073242 ], [ "▁必ずしも", -11.068461418151855 ], [ "▁ゴム", -11.068835258483887 ], [ "▁社団", -11.068880081176758 ], [ "▁けい", -11.068946838378906 ], [ "▁区画", -11.06925106048584 ], [ "▁เ", -11.069595336914062 ], [ "ock", -11.069612503051758 ], [ "▁矯正", -11.069653511047363 ], [ "▁終えた", -11.06967544555664 ], [ "鋭", -11.069698333740234 ], [ "▁降り", -11.06994915008545 ], [ "破", -11.070060729980469 ], [ "▁文学部", -11.07007122039795 ], [ "▁粉", -11.070101737976074 ], [ "▁別注", -11.070137977600098 ], [ "▁国土", -11.070302963256836 ], [ "ゾン", -11.070423126220703 ], [ "▁テロ", -11.07060432434082 ], [ "▁ゴミ", -11.070606231689453 ], [ "▁チャン", -11.070982933044434 ], [ "▁怪我", -11.071417808532715 ], [ "昨年", -11.071568489074707 ], [ "▁着て", -11.071708679199219 ], [ "毎日", -11.071955680847168 ], [ "▁煮", -11.071971893310547 ], [ "出演", -11.071975708007812 ], [ "▁巨大な", -11.072062492370605 ], [ "ウェ", -11.072150230407715 ], [ "▁戦線", -11.072433471679688 ], [ "98", -11.072790145874023 ], [ "▁ドラッグ", -11.072835922241211 ], [ "▁係", -11.07299518585205 ], [ "iz", -11.073140144348145 ], [ "▁夫人", -11.073291778564453 ], [ "ですが", -11.07333755493164 ], [ "▁青山", -11.073873519897461 ], [ "▁批評", -11.074097633361816 ], [ "▁法案", -11.074175834655762 ], [ "▁敬", -11.074440002441406 ], [ "キシ", -11.074522972106934 ], [ "半", -11.074543952941895 ], [ "▁ポップ", -11.074898719787598 ], [ "▁心臓", -11.075067520141602 ], [ "▁恵", -11.07523250579834 ], [ "▁マラソン", -11.075268745422363 ], [ "なぜ", -11.075358390808105 ], [ "91", -11.075691223144531 ], [ "▁AS", -11.075732231140137 ], [ "▁合戦", -11.075749397277832 ], [ "▁時刻", -11.075797080993652 ], [ "▁中野", -11.075864791870117 ], [ "▁及ぶ", -11.07597827911377 ], [ "▁エラー", -11.076040267944336 ], [ "▁鍋", -11.076089859008789 ], [ "▁助教", -11.076598167419434 ], [ "▁回り", -11.07663345336914 ], [ "ake", -11.076932907104492 ], [ "▁コンテスト", -11.077188491821289 ], [ "▁絵本", -11.077452659606934 ], [ "▁66", -11.077503204345703 ], [ "▁表彰", -11.077691078186035 ], [ "ユー", -11.077900886535645 ], [ "次に", -11.078507423400879 ], [ "▁温", -11.078642845153809 ], [ "ep", -11.078648567199707 ], [ "ンダー", -11.079046249389648 ], [ "▁死ぬ", -11.079181671142578 ], [ "▁韓", -11.079217910766602 ], [ "▁直営", -11.079387664794922 ], [ "▁残", -11.079469680786133 ], [ "na", -11.07961654663086 ], [ "▁読書", -11.07966423034668 ], [ "▁アレ", -11.080058097839355 ], [ "▁近鉄", -11.08007526397705 ], [ "▁芝", -11.080392837524414 ], [ "▁並行", -11.080413818359375 ], [ "▁楽団", -11.080446243286133 ], [ "▁好きで", -11.080591201782227 ], [ "ティア", -11.080599784851074 ], [ "▁消化", -11.080639839172363 ], [ "▁行なって", -11.080656051635742 ], [ "▁飾り", -11.080862998962402 ], [ "▁夕方", -11.080866813659668 ], [ "▁広がって", -11.080926895141602 ], [ "吾", -11.081127166748047 ], [ "▁プレート", -11.081202507019043 ], [ "差", -11.081226348876953 ], [ "▁内側", -11.08124828338623 ], [ "▁させ", -11.081542015075684 ], [ "▁イスラム", -11.081573486328125 ], [ "飯", -11.082005500793457 ], [ "▁市町村", -11.082060813903809 ], [ "▁盛", -11.082140922546387 ], [ "広島", -11.082172393798828 ], [ "▁込め", -11.082747459411621 ], [ "▁プライベート", -11.083014488220215 ], [ "検", -11.083104133605957 ], [ "54", -11.083202362060547 ], [ "59", -11.083314895629883 ], [ "OR", -11.083517074584961 ], [ "▁マリ", -11.08361530303955 ], [ "▁おしゃれ", -11.083810806274414 ], [ "▁オーダー", -11.083846092224121 ], [ "ライト", -11.083934783935547 ], [ "▁ビーチ", -11.084129333496094 ], [ "▁学長", -11.084161758422852 ], [ "▁動向", -11.084249496459961 ], [ "▁軍団", -11.08426570892334 ], [ "▁前日", -11.08434009552002 ], [ "▁複製", -11.084580421447754 ], [ "▁主導", -11.084660530090332 ], [ "▁iPad", -11.08468246459961 ], [ "68", -11.084763526916504 ], [ "▁渡って", -11.08498764038086 ], [ "▁とっても", -11.085142135620117 ], [ "ac", -11.085286140441895 ], [ "▁貞", -11.08529281616211 ], [ "▁フライ", -11.085450172424316 ], [ "▁並ぶ", -11.085760116577148 ], [ "▁テンプレート", -11.085835456848145 ], [ "▁1964", -11.08585262298584 ], [ "最初", -11.08652400970459 ], [ "▁毒", -11.086679458618164 ], [ "▁メル", -11.086722373962402 ], [ "▁水分", -11.086764335632324 ], [ "1994", -11.087038040161133 ], [ "油", -11.08729076385498 ], [ "▁ヘルス", -11.087697982788086 ], [ "▁上海", -11.087747573852539 ], [ "93", -11.087803840637207 ], [ "▁発症", -11.087879180908203 ], [ "▁還元", -11.088090896606445 ], [ "▁走って", -11.088350296020508 ], [ "▁セッション", -11.08863353729248 ], [ "▁理工", -11.088767051696777 ], [ "▁装甲", -11.089205741882324 ], [ "▁⇒", -11.08920955657959 ], [ "▁爪", -11.089214324951172 ], [ "少し", -11.089457511901855 ], [ "▁渡辺", -11.089751243591309 ], [ "▁運命", -11.0897798538208 ], [ "ice", -11.089838981628418 ], [ "ティス", -11.090261459350586 ], [ "▁放置", -11.090603828430176 ], [ "▁突き", -11.090736389160156 ], [ "▁プロダクション", -11.091106414794922 ], [ "▁有り", -11.091312408447266 ], [ "イア", -11.091367721557617 ], [ "ue", -11.091569900512695 ], [ "▁匹", -11.091644287109375 ], [ "▁短縮", -11.091761589050293 ], [ "技", -11.091959953308105 ], [ "尻", -11.092175483703613 ], [ "ニュ", -11.092461585998535 ], [ "▁かた", -11.093423843383789 ], [ "▁返し", -11.093610763549805 ], [ "けた", -11.093728065490723 ], [ "di", -11.0938138961792 ], [ "▁CA", -11.093859672546387 ], [ "▁®", -11.093890190124512 ], [ "▁我慢", -11.09403133392334 ], [ "舞", -11.094094276428223 ], [ "▁わたる", -11.094162940979004 ], [ "▁ロス", -11.094391822814941 ], [ "希", -11.09455394744873 ], [ "冷", -11.09464168548584 ], [ "▁給料", -11.09481143951416 ], [ "▁スクリーン", -11.094951629638672 ], [ "印", -11.095051765441895 ], [ "▁喜んで", -11.095187187194824 ], [ "97", -11.09547233581543 ], [ "▁ユース", -11.095870018005371 ], [ "セイ", -11.096272468566895 ], [ "▁複雑な", -11.096519470214844 ], [ "▁才", -11.096668243408203 ], [ "▁アパート", -11.09679126739502 ], [ "すると", -11.097010612487793 ], [ "ンス", -11.097041130065918 ], [ "▁98", -11.097092628479004 ], [ "▁必要である", -11.097124099731445 ], [ "▁散歩", -11.097358703613281 ], [ "▁人権", -11.097383499145508 ], [ "▁戦艦", -11.097410202026367 ], [ "▁鋼", -11.097624778747559 ], [ "▁笑", -11.097736358642578 ], [ "▁LED", -11.098053932189941 ], [ "/", -11.098065376281738 ], [ "カイ", -11.098109245300293 ], [ "▁筆", -11.098916053771973 ], [ "規", -11.099028587341309 ], [ "参加", -11.099181175231934 ], [ "▁主力", -11.099242210388184 ], [ "▁発掘", -11.099409103393555 ], [ "▁出走", -11.09941291809082 ], [ "打", -11.099457740783691 ], [ "だい", -11.099767684936523 ], [ "ian", -11.100058555603027 ], [ "▁秋冬", -11.100237846374512 ], [ "ance", -11.100399017333984 ], [ "アニメ", -11.100425720214844 ], [ "▁法的", -11.100502967834473 ], [ "▁集まって", -11.100707054138184 ], [ "▁透明", -11.100869178771973 ], [ "家族", -11.10089111328125 ], [ "▁周波", -11.10090160369873 ], [ "▁追求", -11.101000785827637 ], [ "▁違法", -11.101099967956543 ], [ "▁ならでは", -11.101102828979492 ], [ "96", -11.101173400878906 ], [ "▁付き合い", -11.101234436035156 ], [ "▁動く", -11.101234436035156 ], [ "▁陰", -11.101316452026367 ], [ "アウト", -11.101394653320312 ], [ "▁ボル", -11.101457595825195 ], [ "祖", -11.101478576660156 ], [ "▁きれ", -11.101545333862305 ], [ "▁親子", -11.101781845092773 ], [ "▁キス", -11.10184097290039 ], [ "▁折り", -11.102005958557129 ], [ "プリ", -11.102036476135254 ], [ "英語", -11.10217571258545 ], [ "腹", -11.102363586425781 ], [ "▁舞", -11.102389335632324 ], [ "▁アピール", -11.102832794189453 ], [ "▁調子", -11.103057861328125 ], [ "▁トロ", -11.103147506713867 ], [ "▁ガード", -11.103267669677734 ], [ "▁カイ", -11.103321075439453 ], [ "▁別れ", -11.103549003601074 ], [ "それぞれ", -11.1035737991333 ], [ "▁南東", -11.103690147399902 ], [ "示", -11.103784561157227 ], [ "▁ター", -11.103883743286133 ], [ "▁68", -11.103950500488281 ], [ "など", -11.10399055480957 ], [ "季", -11.104076385498047 ], [ "▁ソニー", -11.104219436645508 ], [ "▁大量", -11.104616165161133 ], [ "▁晴", -11.10486125946045 ], [ "▁彼氏", -11.104965209960938 ], [ "▁装飾", -11.105111122131348 ], [ "▁»", -11.105134963989258 ], [ "▁中学生", -11.105257034301758 ], [ "▁上がった", -11.105278015136719 ], [ "▁条例", -11.105340957641602 ], [ "▁容易に", -11.105552673339844 ], [ "▁GB", -11.10558032989502 ], [ "800", -11.105694770812988 ], [ "資", -11.105831146240234 ], [ "▁例外", -11.105833053588867 ], [ "陵", -11.105915069580078 ], [ "▁NO", -11.10591983795166 ], [ "辞", -11.106090545654297 ], [ "▁沿って", -11.106330871582031 ], [ "ほど", -11.106423377990723 ], [ "▁FA", -11.10644245147705 ], [ "▁フジ", -11.10655403137207 ], [ "be", -11.106629371643066 ], [ "▁勢", -11.106663703918457 ], [ "いや", -11.10671329498291 ], [ "▁とる", -11.106752395629883 ], [ "▁正確に", -11.106781005859375 ], [ "TS", -11.106858253479004 ], [ "▁net", -11.106927871704102 ], [ "ba", -11.106964111328125 ], [ "▁歩き", -11.106999397277832 ], [ "▁アレルギー", -11.107053756713867 ], [ "▁幅広く", -11.107107162475586 ], [ "▁入場", -11.107123374938965 ], [ "▁浅", -11.107258796691895 ], [ "▁持", -11.107319831848145 ], [ "柳", -11.107858657836914 ], [ "AP", -11.108444213867188 ], [ "▁冷", -11.108602523803711 ], [ "▁フロー", -11.109350204467773 ], [ "▁武田", -11.109797477722168 ], [ "▁ネイル", -11.10994815826416 ], [ "盤", -11.10995101928711 ], [ "▁流れて", -11.110055923461914 ], [ "▁プログラミング", -11.110408782958984 ], [ "▁少数", -11.11042308807373 ], [ "▁起こした", -11.110550880432129 ], [ "ame", -11.110610961914062 ], [ "▁1967", -11.11070728302002 ], [ "▁そういった", -11.110983848571777 ], [ "▁さくら", -11.111163139343262 ], [ "フォン", -11.111273765563965 ], [ "▁中期", -11.111297607421875 ], [ "▁棒", -11.111425399780273 ], [ "なり", -11.111522674560547 ], [ "息", -11.111542701721191 ], [ "▁会館", -11.11163330078125 ], [ "▁三菱", -11.111983299255371 ], [ "▁強力な", -11.11213493347168 ], [ "▁フリ", -11.112309455871582 ], [ "▁別途", -11.112464904785156 ], [ "▁主婦", -11.112834930419922 ], [ "▁総務", -11.113561630249023 ], [ "▁的です", -11.11374282836914 ], [ "▁廃棄", -11.113779067993164 ], [ "▁井上", -11.1138334274292 ], [ "象", -11.113846778869629 ], [ "っぱ", -11.113995552062988 ], [ "初めて", -11.114242553710938 ], [ "▁ズ", -11.114282608032227 ], [ "▁抗議", -11.114562034606934 ], [ "▁塗り", -11.114569664001465 ], [ "▁勢い", -11.114603042602539 ], [ "▁主人", -11.115410804748535 ], [ "秀", -11.115706443786621 ], [ "リュー", -11.115970611572266 ], [ "▁品種", -11.11623764038086 ], [ "▁リア", -11.116376876831055 ], [ "▁エントリー", -11.116423606872559 ], [ "BC", -11.116703033447266 ], [ "▁補給", -11.117128372192383 ], [ "▁栗", -11.117151260375977 ], [ "▁示唆", -11.117219924926758 ], [ "▁昌", -11.11746883392334 ], [ "▁麺", -11.117591857910156 ], [ "▁イエス", -11.117795944213867 ], [ "MO", -11.117866516113281 ], [ "合い", -11.11809253692627 ], [ "▁詳しい", -11.118178367614746 ], [ "具体", -11.118199348449707 ], [ "▁売れ", -11.118352890014648 ], [ "止め", -11.118419647216797 ], [ "三郎", -11.119007110595703 ], [ "列", -11.1190824508667 ], [ "ome", -11.119110107421875 ], [ "▁森林", -11.119172096252441 ], [ "しょ", -11.119257926940918 ], [ "71", -11.119617462158203 ], [ "左", -11.12015438079834 ], [ "ha", -11.120207786560059 ], [ "▁有機", -11.120430946350098 ], [ "▁チーズ", -11.1205472946167 ], [ "▁報じ", -11.120573997497559 ], [ "▁web", -11.120657920837402 ], [ "▁剛", -11.121115684509277 ], [ "▁与", -11.121211051940918 ], [ "▁ラスト", -11.121752738952637 ], [ "▁this", -11.122048377990723 ], [ "ana", -11.122050285339355 ], [ "飛", -11.122076988220215 ], [ "▁FX", -11.12213134765625 ], [ "▁させる", -11.122133255004883 ], [ "難", -11.122166633605957 ], [ "ッコ", -11.122610092163086 ], [ "▁なんとか", -11.122729301452637 ], [ "カラ", -11.122769355773926 ], [ "畑", -11.123275756835938 ], [ "▁├", -11.123286247253418 ], [ "▁照", -11.123311996459961 ], [ "▁見せた", -11.123435974121094 ], [ "▁襲撃", -11.123513221740723 ], [ "▁子孫", -11.12381362915039 ], [ "▁経路", -11.123929023742676 ], [ "▁助", -11.123934745788574 ], [ "▁ドラゴン", -11.124420166015625 ], [ "ッパー", -11.124515533447266 ], [ "▁収", -11.124543190002441 ], [ "念", -11.12457275390625 ], [ "沿革", -11.124707221984863 ], [ "▁ジョー", -11.1251802444458 ], [ "▁一連の", -11.125266075134277 ], [ "me", -11.125434875488281 ], [ "▁やま", -11.12545108795166 ], [ "▁申し訳", -11.125783920288086 ], [ "▁大学生", -11.125893592834473 ], [ "兄", -11.12593936920166 ], [ "▁学年", -11.12606143951416 ], [ "▁どうして", -11.126618385314941 ], [ "攻", -11.126638412475586 ], [ "▁バスケットボール", -11.126713752746582 ], [ "▁駒", -11.126848220825195 ], [ "ゼン", -11.126927375793457 ], [ "▁ブラン", -11.127158164978027 ], [ "▁大麻", -11.127251625061035 ], [ "札", -11.127427101135254 ], [ "▁評", -11.127462387084961 ], [ "▁軟", -11.127577781677246 ], [ "▁71", -11.127711296081543 ], [ "▁五輪", -11.127972602844238 ], [ "▁阪急", -11.128043174743652 ], [ "九", -11.1286039352417 ], [ "識", -11.128772735595703 ], [ "▁正確", -11.128798484802246 ], [ "der", -11.128870964050293 ], [ "ミング", -11.128959655761719 ], [ "セット", -11.129008293151855 ], [ "▁月刊", -11.129340171813965 ], [ "▁パイロット", -11.12950611114502 ], [ "▁賃金", -11.12956428527832 ], [ "衛", -11.129830360412598 ], [ "▁現れた", -11.129837989807129 ], [ "▁守り", -11.130082130432129 ], [ "▁中世", -11.130219459533691 ], [ "ーション", -11.130364418029785 ], [ "▁76", -11.130546569824219 ], [ "▁養子", -11.131001472473145 ], [ "TE", -11.1310396194458 ], [ "▁東急", -11.131348609924316 ], [ "チーム", -11.131885528564453 ], [ "▁豪", -11.132061958312988 ], [ "▁マネージャー", -11.132302284240723 ], [ "▁SH", -11.132471084594727 ], [ "▁移民", -11.133110046386719 ], [ "養", -11.133111000061035 ], [ "新しい", -11.133145332336426 ], [ "いま", -11.133363723754883 ], [ "敵", -11.133604049682617 ], [ "▁Mar", -11.133733749389648 ], [ "▁輝", -11.133793830871582 ], [ "▁73", -11.13403606414795 ], [ "▁損傷", -11.134132385253906 ], [ "▁発音", -11.134176254272461 ], [ "社会", -11.134422302246094 ], [ "▁非難", -11.134469985961914 ], [ "▁合唱", -11.13458251953125 ], [ "BA", -11.135089874267578 ], [ "▁税込", -11.1351900100708 ], [ "▁問合せ", -11.13541030883789 ], [ "之助", -11.135482788085938 ], [ "▁結んだ", -11.135632514953613 ], [ "▁工作", -11.135705947875977 ], [ "58", -11.13603401184082 ], [ "人気", -11.136146545410156 ], [ "▁グラン", -11.136216163635254 ], [ "デイ", -11.136244773864746 ], [ "▁小物", -11.136758804321289 ], [ "▁礼", -11.136992454528809 ], [ "▁アシスタント", -11.137032508850098 ], [ "殿", -11.137405395507812 ], [ "▁DS", -11.137604713439941 ], [ "▁劇団", -11.13780689239502 ], [ "▁モル", -11.137829780578613 ], [ "専門", -11.138031005859375 ], [ "▁容疑", -11.138167381286621 ], [ "▁放棄", -11.138410568237305 ], [ "▁96", -11.138447761535645 ], [ "▁司会", -11.138575553894043 ], [ "▁暗", -11.13859748840332 ], [ "寿", -11.138731956481934 ], [ "▁69", -11.138778686523438 ], [ "▁1965", -11.139036178588867 ], [ "▁ドラ", -11.139079093933105 ], [ "▁生理", -11.139296531677246 ], [ "▁奴", -11.139358520507812 ], [ "▁いち", -11.140044212341309 ], [ "▁北陸", -11.14028263092041 ], [ "▁炭素", -11.140326499938965 ], [ "▁巡", -11.140335083007812 ], [ "刑", -11.140398979187012 ], [ "▁スポンサー", -11.140519142150879 ], [ "▁回線", -11.140546798706055 ], [ "▁毎回", -11.140637397766113 ], [ "▁月額", -11.140704154968262 ], [ "▁オリ", -11.14111614227295 ], [ "受", -11.141190528869629 ], [ "▁MC", -11.141395568847656 ], [ "糸", -11.141425132751465 ], [ "▁Ma", -11.14148998260498 ], [ "▁排出", -11.141571998596191 ], [ "ちょっと", -11.141683578491211 ], [ "▁ケン", -11.141769409179688 ], [ "普段", -11.142183303833008 ], [ "▁嵐", -11.14239501953125 ], [ "▁大量の", -11.142732620239258 ], [ "▁レコーディング", -11.142781257629395 ], [ "▁ヴァ", -11.142878532409668 ], [ "▁鑑定", -11.143060684204102 ], [ "▁ノウハウ", -11.143081665039062 ], [ "▁神宮", -11.1432523727417 ], [ "▁立地", -11.143402099609375 ], [ "▁you", -11.143715858459473 ], [ "▁支払", -11.14380931854248 ], [ "▁amp", -11.143832206726074 ], [ "▁科目", -11.143845558166504 ], [ "▁黒い", -11.144144058227539 ], [ "芸", -11.144231796264648 ], [ "ポート", -11.144296646118164 ], [ "▁棚", -11.144603729248047 ], [ "▁積み", -11.144722938537598 ], [ "▁小学", -11.14513111114502 ], [ "引", -11.145294189453125 ], [ "da", -11.14548397064209 ], [ "▁縮小", -11.14553451538086 ], [ "▁ホット", -11.145614624023438 ], [ "▁明るい", -11.146562576293945 ], [ "▁辛", -11.146714210510254 ], [ "▁ストーン", -11.14672565460205 ], [ "天皇", -11.146933555603027 ], [ "港", -11.147161483764648 ], [ "▁護", -11.147305488586426 ], [ "ci", -11.147397994995117 ], [ "▁広報", -11.147400856018066 ], [ "▁やった", -11.147429466247559 ], [ "ですから", -11.147440910339355 ], [ "影", -11.147502899169922 ], [ "▁認める", -11.147582054138184 ], [ "▁損失", -11.147869110107422 ], [ "▁夜間", -11.148197174072266 ], [ "▁遅れ", -11.148233413696289 ], [ "▁コンパクト", -11.149072647094727 ], [ "▁ポート", -11.149174690246582 ], [ "▁没", -11.149200439453125 ], [ "▁熟", -11.149261474609375 ], [ "▁順に", -11.149365425109863 ], [ "▁リラックス", -11.149900436401367 ], [ "▁抑える", -11.150152206420898 ], [ "▁伴って", -11.150172233581543 ], [ "切り", -11.15022087097168 ], [ "▁○○", -11.150519371032715 ], [ "▁指輪", -11.150593757629395 ], [ "財", -11.150599479675293 ], [ "▁精度", -11.150673866271973 ], [ "▁ネーム", -11.150786399841309 ], [ "▁カウンター", -11.150914192199707 ], [ "▁Facebook", -11.151005744934082 ], [ "▁過ごして", -11.151074409484863 ], [ "63", -11.151118278503418 ], [ "▁もたらす", -11.151350975036621 ], [ "▁称さ", -11.151597023010254 ], [ "▁創刊", -11.151901245117188 ], [ "▁上司", -11.152026176452637 ], [ "▁講習", -11.152177810668945 ], [ "▁敗北", -11.152234077453613 ], [ "脚", -11.152958869934082 ], [ "▁บ", -11.153033256530762 ], [ "▁論理", -11.153125762939453 ], [ "▁回路", -11.153398513793945 ], [ "▁除去", -11.15340518951416 ], [ "▁エッチ", -11.153813362121582 ], [ "▁ヌ", -11.153860092163086 ], [ "▁取り組む", -11.153923034667969 ], [ "▁脇", -11.154170036315918 ], [ "キュ", -11.154333114624023 ], [ "▁進んだ", -11.154475212097168 ], [ "▁結論", -11.154512405395508 ], [ "▁実態", -11.154820442199707 ], [ "塩", -11.15517807006836 ], [ "コス", -11.155219078063965 ], [ "▁玄関", -11.155641555786133 ], [ "ドリ", -11.155645370483398 ], [ "▁標高", -11.155689239501953 ], [ "以上", -11.155959129333496 ], [ "▁ポン", -11.156088829040527 ], [ "▁マニュアル", -11.156411170959473 ], [ "もと", -11.15673828125 ], [ "君", -11.156925201416016 ], [ "育", -11.156928062438965 ], [ "▁交際", -11.157575607299805 ], [ "▁集まり", -11.157659530639648 ], [ "▁立ち上げ", -11.157981872558594 ], [ "▁JAPAN", -11.158000946044922 ], [ "▁中身", -11.15807056427002 ], [ "▁前期", -11.158327102661133 ], [ "▁楽しめ", -11.158341407775879 ], [ "▁開いた", -11.158370018005371 ], [ "CE", -11.15842342376709 ], [ "ud", -11.158432960510254 ], [ "ヌス", -11.1586275100708 ], [ "▁法務", -11.158629417419434 ], [ "ウル", -11.158744812011719 ], [ "▁綿", -11.158841133117676 ], [ "▁心地", -11.158891677856445 ], [ "▁お互い", -11.158988952636719 ], [ "▁HD", -11.159071922302246 ], [ "1992", -11.159252166748047 ], [ "▁エリ", -11.159369468688965 ], [ "峰", -11.159462928771973 ], [ "▁ウルトラ", -11.159528732299805 ], [ "▁西洋", -11.159661293029785 ], [ "▁侵害", -11.15968132019043 ], [ "▁‚", -11.159724235534668 ], [ "床", -11.159926414489746 ], [ "300", -11.159939765930176 ], [ "ase", -11.159961700439453 ], [ "▁出馬", -11.160138130187988 ], [ "比", -11.16025447845459 ], [ "▁略称", -11.160445213317871 ], [ "▁延期", -11.16071891784668 ], [ "▁それなり", -11.161246299743652 ], [ "▁激しく", -11.161355018615723 ], [ "▁クッキー", -11.161578178405762 ], [ "告", -11.161748886108398 ], [ "▁ハム", -11.161771774291992 ], [ "▁来場", -11.161781311035156 ], [ "▁証言", -11.161859512329102 ], [ "▁殿", -11.161876678466797 ], [ "▁チップ", -11.161930084228516 ], [ "炎", -11.161980628967285 ], [ "▁土産", -11.162507057189941 ], [ "▁ヒル", -11.162551879882812 ], [ "▁即位", -11.162883758544922 ], [ "▁起きる", -11.162946701049805 ], [ "▁トヨタ", -11.163063049316406 ], [ "▁提唱", -11.163455963134766 ], [ "更に", -11.163748741149902 ], [ "▁返信", -11.16376781463623 ], [ "▁扱わ", -11.16378116607666 ], [ "▁フェイス", -11.163896560668945 ], [ "▁最中", -11.163958549499512 ], [ "▁いこう", -11.164285659790039 ], [ "▁タンク", -11.164800643920898 ], [ "▁前作", -11.164837837219238 ], [ "最初の", -11.165199279785156 ], [ "便", -11.165217399597168 ], [ "▁挙げる", -11.16525936126709 ], [ "たる", -11.165267944335938 ], [ "▁誠", -11.165288925170898 ], [ "▁往復", -11.165369987487793 ], [ "▁ステークス", -11.165371894836426 ], [ "▁001", -11.165592193603516 ], [ "per", -11.166014671325684 ], [ "ェ", -11.166340827941895 ], [ "バラ", -11.166842460632324 ], [ "▁シンガポール", -11.167031288146973 ], [ "▁育て", -11.16710376739502 ], [ "リカ", -11.167280197143555 ], [ "▁編曲", -11.167304992675781 ], [ "▁セブン", -11.167372703552246 ], [ "▁頻度", -11.167413711547852 ], [ "ex", -11.167454719543457 ], [ "▁知的", -11.167464256286621 ], [ "収録", -11.167593955993652 ], [ "カリ", -11.167817115783691 ], [ "ーニ", -11.167837142944336 ], [ "▁増えた", -11.167881965637207 ], [ "▁AD", -11.167928695678711 ], [ "▁向いて", -11.168006896972656 ], [ "▁OFF", -11.168107986450195 ], [ "▁異なって", -11.16812515258789 ], [ "▁恵ま", -11.168168067932129 ], [ "▁マイク", -11.168325424194336 ], [ "▁面倒", -11.16850471496582 ], [ "▁エンド", -11.168529510498047 ], [ "▁誇る", -11.168784141540527 ], [ "400", -11.168827056884766 ], [ "▁ギャラリー", -11.168951988220215 ], [ "▁いらっしゃる", -11.1690092086792 ], [ "▁ボーカル", -11.169267654418945 ], [ "▁ヒト", -11.169368743896484 ], [ "▁暗殺", -11.169442176818848 ], [ "▁領土", -11.169553756713867 ], [ "▁ダメ", -11.169644355773926 ], [ "▁見つけて", -11.16970157623291 ], [ "▁腸", -11.16972541809082 ], [ "▁ドリンク", -11.169740676879883 ], [ "ッティ", -11.16980266571045 ], [ "学校", -11.169866561889648 ], [ "▁parenti", -11.170047760009766 ], [ "縁", -11.170379638671875 ], [ "シーズン", -11.17052936553955 ], [ "舎", -11.170757293701172 ], [ "▁寮", -11.170844078063965 ], [ "▁闇", -11.170909881591797 ], [ "▁スパイ", -11.171137809753418 ], [ "▁開拓", -11.171435356140137 ], [ "1993", -11.171619415283203 ], [ "修", -11.171769142150879 ], [ "未", -11.171880722045898 ], [ "▁逆転", -11.171996116638184 ], [ "▁モニター", -11.17211627960205 ], [ "▁習得", -11.172202110290527 ], [ "▁カラオケ", -11.172212600708008 ], [ "▁売って", -11.17227554321289 ], [ "▁分かれて", -11.172292709350586 ], [ "▁内科", -11.172699928283691 ], [ "▁理念", -11.172710418701172 ], [ "▁入居", -11.172730445861816 ], [ "積", -11.173418998718262 ], [ "▁もち", -11.173659324645996 ], [ "▁予", -11.174084663391113 ], [ "▁国連", -11.174090385437012 ], [ "▁フォロー", -11.174162864685059 ], [ "バーグ", -11.174300193786621 ], [ "▁割り", -11.174359321594238 ], [ "▁コマ", -11.17453384399414 ], [ "ヴァン", -11.17460823059082 ], [ "っぽ", -11.174657821655273 ], [ "づけ", -11.174695014953613 ], [ "▁習", -11.174846649169922 ], [ "▁160", -11.175012588500977 ], [ "レル", -11.175114631652832 ], [ "福岡", -11.175183296203613 ], [ "▁出会う", -11.175212860107422 ], [ "▁エース", -11.175410270690918 ], [ "▁トランス", -11.17553424835205 ], [ "訳", -11.176227569580078 ], [ "退", -11.176260948181152 ], [ "ザン", -11.176604270935059 ], [ "▁本当", -11.176633834838867 ], [ "IM", -11.176642417907715 ], [ "益", -11.17667293548584 ], [ "▁根本", -11.176709175109863 ], [ "▁ビジョン", -11.176787376403809 ], [ "▁銀河", -11.176854133605957 ], [ "銀", -11.177013397216797 ], [ "緒", -11.17747974395752 ], [ "▁追放", -11.177504539489746 ], [ "▁分裂", -11.177695274353027 ], [ "PA", -11.177823066711426 ], [ "▁世間", -11.17786979675293 ], [ "▁アイコン", -11.177946090698242 ], [ "▁クール", -11.177960395812988 ], [ "結", -11.178236961364746 ], [ "▁任", -11.178281784057617 ], [ "▁暦", -11.178520202636719 ], [ "▁双", -11.17859172821045 ], [ "▁一般に", -11.178689002990723 ], [ "▁密度", -11.178766250610352 ], [ "▁支店", -11.17885684967041 ], [ "▁菊", -11.178945541381836 ], [ "▁伸び", -11.179327011108398 ], [ "税", -11.179327011108398 ], [ "シャー", -11.1793851852417 ], [ "▁寝て", -11.179398536682129 ], [ "子ども", -11.179431915283203 ], [ "▁禁じ", -11.179495811462402 ], [ "▁休業", -11.17971134185791 ], [ "▁代謝", -11.179896354675293 ], [ "▁1966", -11.180038452148438 ], [ "▁彫刻", -11.180233001708984 ], [ "▁Tr", -11.180266380310059 ], [ "▁多様な", -11.18028450012207 ], [ "▁同僚", -11.180371284484863 ], [ "▁欠かせ", -11.18038558959961 ], [ "▁101", -11.1806058883667 ], [ "▁独占", -11.180792808532715 ], [ "▁勇", -11.180814743041992 ], [ "▁オープニング", -11.180863380432129 ], [ "魔", -11.181120872497559 ], [ "▁教える", -11.181143760681152 ], [ "▁疑い", -11.181478500366211 ], [ "▁果たし", -11.181641578674316 ], [ "▁悩ま", -11.181647300720215 ], [ "共", -11.181796073913574 ], [ "▁350", -11.182013511657715 ], [ "▁ベルギー", -11.18209457397461 ], [ "om", -11.182267189025879 ], [ "▁比率", -11.182297706604004 ], [ "▁モンゴル", -11.182564735412598 ], [ "▁現存", -11.182600975036621 ], [ "▁破", -11.18280029296875 ], [ "▁屋敷", -11.182907104492188 ], [ "▁飼育", -11.182942390441895 ], [ "▁フォ", -11.182976722717285 ], [ "▁中華人民共和国", -11.183018684387207 ], [ "▁題材", -11.183428764343262 ], [ "▁本名", -11.1835298538208 ], [ "▁修復", -11.184103012084961 ], [ "▁説得", -11.18416690826416 ], [ "▁働ける", -11.184188842773438 ], [ "▁嘉", -11.184316635131836 ], [ "▁起き", -11.184513092041016 ], [ "▁汚染", -11.184640884399414 ], [ "▁夕", -11.184725761413574 ], [ "▁バイオ", -11.184893608093262 ], [ "▁出店", -11.184952735900879 ], [ "▁カリ", -11.184967994689941 ], [ "▁慶", -11.185022354125977 ], [ "▁見方", -11.185129165649414 ], [ "▁芸人", -11.185478210449219 ], [ "▁いかなる", -11.185693740844727 ], [ "▁戦死", -11.185722351074219 ], [ "▁検定", -11.185839653015137 ], [ "▁シナリオ", -11.185930252075195 ], [ "▁シフト", -11.186119079589844 ], [ "▁演じた", -11.186344146728516 ], [ "▁短編", -11.186500549316406 ], [ "▁発着", -11.18667221069336 ], [ "▁にくく", -11.186734199523926 ], [ "▁そのうち", -11.18686294555664 ], [ "▁近郊", -11.18740463256836 ], [ "▁ω", -11.187483787536621 ], [ "▁辞任", -11.187500953674316 ], [ "▁原理", -11.187870025634766 ], [ "▁分岐", -11.18794059753418 ], [ "▁差し", -11.187965393066406 ], [ "▁求めた", -11.188152313232422 ], [ "▁完全な", -11.18833065032959 ], [ "▁トレンド", -11.188982963562012 ], [ "▁辛い", -11.189040184020996 ], [ "設", -11.189064025878906 ], [ "▁US", -11.189116477966309 ], [ "▁浩", -11.189573287963867 ], [ "▁DE", -11.189831733703613 ], [ "ストラ", -11.189837455749512 ], [ "▁92", -11.189860343933105 ], [ "円", -11.189926147460938 ], [ "▁英雄", -11.190080642700195 ], [ "▁刻", -11.190104484558105 ], [ "韓国", -11.190227508544922 ], [ "son", -11.19031047821045 ], [ "奥", -11.190366744995117 ], [ "堀", -11.190507888793945 ], [ "▁コスメ", -11.190641403198242 ], [ "▁皆さま", -11.19083023071289 ], [ "▁郊外", -11.191027641296387 ], [ "▁耐え", -11.191130638122559 ], [ "▁便利です", -11.191193580627441 ], [ "▁プロモーション", -11.191213607788086 ], [ "▁関わり", -11.191244125366211 ], [ "▁反発", -11.191386222839355 ], [ "▁お腹", -11.19150447845459 ], [ "1991", -11.191524505615234 ], [ "ーゼ", -11.191598892211914 ], [ "▁検", -11.191773414611816 ], [ "▁クラフト", -11.191802024841309 ], [ ":", -11.19196605682373 ], [ "▁超えた", -11.192171096801758 ], [ "▁モスクワ", -11.192272186279297 ], [ "▁更", -11.192636489868164 ], [ "▁すずかけ", -11.19270133972168 ], [ "ゃ", -11.192959785461426 ], [ "▁テン", -11.193077087402344 ], [ "▁マイナー", -11.19308090209961 ], [ "▁合理", -11.193203926086426 ], [ "ワイ", -11.193534851074219 ], [ "▁配合", -11.193808555603027 ], [ "ダル", -11.193887710571289 ], [ "▁覚え", -11.193995475769043 ], [ "▁損", -11.19400405883789 ], [ "▁無効", -11.194177627563477 ], [ "▁柔道", -11.194196701049805 ], [ "時間", -11.1942138671875 ], [ "▁生まれて", -11.194589614868164 ], [ "▁ด", -11.194689750671387 ], [ "▁係る", -11.194785118103027 ], [ "▁日曜", -11.194862365722656 ], [ "AI", -11.194865226745605 ], [ "▁仲介", -11.194987297058105 ], [ "注", -11.195239067077637 ], [ "▁ソーシャル", -11.195320129394531 ], [ "▁身長", -11.195496559143066 ], [ "▁マウス", -11.195672035217285 ], [ "▁行なわ", -11.195698738098145 ], [ "▁シェ", -11.195731163024902 ], [ "ブログ", -11.196207046508789 ], [ "▁禁", -11.19627857208252 ], [ "特徴", -11.196404457092285 ], [ "▁踏み", -11.196565628051758 ], [ "いち", -11.196579933166504 ], [ "ウェア", -11.1965970993042 ], [ "▁打撃", -11.197020530700684 ], [ "▁鳴", -11.197056770324707 ], [ "こうして", -11.197328567504883 ], [ "▁独特の", -11.197381019592285 ], [ "▁伯爵", -11.197382926940918 ], [ "▁浦", -11.19739818572998 ], [ "▁ロバート", -11.197425842285156 ], [ "▁ボン", -11.197456359863281 ], [ "▁延", -11.19747543334961 ], [ "▁コンピューター", -11.197554588317871 ], [ "以後", -11.197802543640137 ], [ "トップ", -11.198040008544922 ], [ "▁そうした", -11.198110580444336 ], [ "複数", -11.198209762573242 ], [ "▁称号", -11.198751449584961 ], [ "▁築", -11.198899269104004 ], [ "▁北九州", -11.19892406463623 ], [ "アス", -11.198967933654785 ], [ "つく", -11.199387550354004 ], [ "▁ƒ", -11.199543952941895 ], [ "▁スー", -11.200328826904297 ], [ "▁コメディ", -11.20036792755127 ], [ "カス", -11.200494766235352 ], [ "▁丘", -11.200531959533691 ], [ "▁オレンジ", -11.20058536529541 ], [ "▁77", -11.200611114501953 ], [ "▁有効に", -11.200738906860352 ], [ "一部", -11.201127052307129 ], [ "IX", -11.201128005981445 ], [ "▁大字", -11.201635360717773 ], [ "▁中山", -11.201746940612793 ], [ "_", -11.201926231384277 ], [ "▁ドラム", -11.201957702636719 ], [ "▁スイーツ", -11.20251750946045 ], [ "▁アド", -11.202539443969727 ], [ "▁駆動", -11.202783584594727 ], [ "▁寄り", -11.203055381774902 ], [ "1960", -11.203094482421875 ], [ "▁医科", -11.203174591064453 ], [ "▁残った", -11.203251838684082 ], [ "▁訪れ", -11.203529357910156 ], [ "▁いかに", -11.203561782836914 ], [ "▁後方", -11.203773498535156 ], [ "▁悪魔", -11.203858375549316 ], [ "▁予め", -11.20390796661377 ], [ "▁カレンダー", -11.2039155960083 ], [ "▁原料", -11.20406723022461 ], [ "フィン", -11.204084396362305 ], [ "ファイ", -11.20411491394043 ], [ "▁67", -11.204312324523926 ], [ "▁まさ", -11.204334259033203 ], [ "are", -11.204570770263672 ], [ "▁同日", -11.204879760742188 ], [ "▁こども", -11.205089569091797 ], [ "▁景", -11.205164909362793 ], [ "▁公務", -11.205227851867676 ], [ "当たり", -11.205292701721191 ], [ "ti", -11.20530891418457 ], [ "冬", -11.205323219299316 ], [ "▁日経", -11.20544147491455 ], [ "▁直線", -11.205628395080566 ], [ "柱", -11.205765724182129 ], [ "▁突", -11.205798149108887 ], [ "▁革", -11.205862045288086 ], [ "▁84", -11.205920219421387 ], [ "▁装", -11.206134796142578 ], [ "▁ばかりの", -11.206146240234375 ], [ "▁部位", -11.206292152404785 ], [ "▁手続", -11.206348419189453 ], [ "CH", -11.206485748291016 ], [ "▁妙", -11.206552505493164 ], [ "▁稼働", -11.206623077392578 ], [ "周", -11.207000732421875 ], [ "▁在学", -11.207255363464355 ], [ "600", -11.20737361907959 ], [ "▁正月", -11.207691192626953 ], [ "▁出会った", -11.207839012145996 ], [ "▁会う", -11.20788860321045 ], [ "▁満たす", -11.207967758178711 ], [ "▁あわせて", -11.208076477050781 ], [ "▁熟女", -11.208452224731445 ], [ "▁せよ", -11.208707809448242 ], [ "▁付与", -11.208971977233887 ], [ "▁黄色", -11.209065437316895 ], [ "▁上級", -11.209426879882812 ], [ "▁爆撃", -11.20968246459961 ], [ "▁奪わ", -11.20999526977539 ], [ "▁マス", -11.210065841674805 ], [ "焼", -11.210171699523926 ], [ "▁偽", -11.210179328918457 ], [ "ウム", -11.210210800170898 ], [ "▁金曜日", -11.210319519042969 ], [ "▁SM", -11.210561752319336 ], [ "▁分間", -11.210888862609863 ], [ "▁アイス", -11.211010932922363 ], [ "▁上限", -11.211106300354004 ], [ "▁報", -11.211133003234863 ], [ "▁フェスティバル", -11.211409568786621 ], [ "▁着物", -11.211430549621582 ], [ "▁ナビ", -11.211495399475098 ], [ "内容", -11.21160888671875 ], [ "▁正面", -11.211615562438965 ], [ "鹿", -11.21182918548584 ], [ "液", -11.211929321289062 ], [ "▁バレエ", -11.212075233459473 ], [ "▁なさい", -11.2120943069458 ], [ "▁見積もり", -11.2121000289917 ], [ "▁不思議な", -11.212179183959961 ], [ "ea", -11.212262153625488 ], [ "▁功績", -11.212418556213379 ], [ "現代", -11.212424278259277 ], [ "▁参", -11.212726593017578 ], [ "▁狂", -11.212760925292969 ], [ "ton", -11.212775230407715 ], [ "▁一員", -11.212797164916992 ], [ "ァ", -11.212809562683105 ], [ "ast", -11.212967872619629 ], [ "▁一家", -11.213105201721191 ], [ "▁示し", -11.2131986618042 ], [ "▁電波", -11.213287353515625 ], [ "▁出資", -11.213458061218262 ], [ "▁重要です", -11.213509559631348 ], [ "ウン", -11.213539123535156 ], [ "▁SA", -11.213555335998535 ], [ "▁抽出", -11.21360969543457 ], [ "▁見つけた", -11.213801383972168 ], [ "▁海洋", -11.213980674743652 ], [ "モー", -11.214181900024414 ], [ "▁1963", -11.214247703552246 ], [ "ネン", -11.21495532989502 ], [ "▁運び", -11.21500301361084 ], [ "▁増やす", -11.215011596679688 ], [ "▁先頭", -11.215456008911133 ], [ "▁Vol", -11.215618133544922 ], [ "がら", -11.215831756591797 ], [ "ink", -11.215975761413574 ], [ "▁一旦", -11.216080665588379 ], [ "書き", -11.216251373291016 ], [ "▁休", -11.216267585754395 ], [ "】", -11.216268539428711 ], [ "▁次男", -11.216370582580566 ], [ "ツァ", -11.216644287109375 ], [ "▁text", -11.2166748046875 ], [ "▁ぼ", -11.216713905334473 ], [ "▁移", -11.21690845489502 ], [ "ムス", -11.217013359069824 ], [ "▁me", -11.217039108276367 ], [ "ok", -11.217190742492676 ], [ "og", -11.217573165893555 ], [ "au", -11.21762466430664 ], [ "▁フロ", -11.217656135559082 ], [ "徒", -11.217942237854004 ], [ "▁選考", -11.217957496643066 ], [ "▁リズム", -11.21813678741455 ], [ "▁住居", -11.21821117401123 ], [ "漢", -11.218411445617676 ], [ "▁横断", -11.218633651733398 ], [ "▁法則", -11.218692779541016 ], [ "▁問い", -11.218805313110352 ], [ "▁フィルタ", -11.219124794006348 ], [ "▁工具", -11.219237327575684 ], [ "▁議席", -11.219292640686035 ], [ "▁給与", -11.219608306884766 ], [ "▁フー", -11.219627380371094 ], [ "初期", -11.219770431518555 ], [ "▁三井", -11.21984577178955 ], [ "▁包囲", -11.220176696777344 ], [ "gi", -11.220251083374023 ], [ "▁ml", -11.220259666442871 ], [ "▁松山", -11.220343589782715 ], [ "しん", -11.220752716064453 ], [ "▁八幡", -11.22105884552002 ], [ "▁ゾーン", -11.221070289611816 ], [ "暦", -11.221115112304688 ], [ "▁満載", -11.221386909484863 ], [ "▁何でも", -11.221582412719727 ], [ "獄", -11.221647262573242 ], [ "la", -11.222034454345703 ], [ "農", -11.222223281860352 ], [ "▁特任", -11.222309112548828 ], [ "ひと", -11.222819328308105 ], [ "▁〕", -11.222848892211914 ], [ "▁CS", -11.222954750061035 ], [ "▁胃", -11.223010063171387 ], [ "▁懐", -11.223217010498047 ], [ "▁至った", -11.22325611114502 ], [ "早", -11.223502159118652 ], [ "▁ボート", -11.223770141601562 ], [ "▁撤去", -11.223875999450684 ], [ "▁天使", -11.224125862121582 ], [ "▁猛", -11.22416877746582 ], [ "▁美し", -11.224244117736816 ], [ "▁本店", -11.224471092224121 ], [ "▁ポンド", -11.224569320678711 ], [ "▁とりあえず", -11.22480297088623 ], [ "▁たて", -11.224831581115723 ], [ "散", -11.22500991821289 ], [ "▁本館", -11.225018501281738 ], [ "▁誠に", -11.22510051727295 ], [ "等", -11.225411415100098 ], [ "▁退団", -11.225586891174316 ], [ "▁勇気", -11.2256498336792 ], [ "▁帰還", -11.225695610046387 ], [ "▁なきゃ", -11.225712776184082 ], [ "須", -11.225713729858398 ], [ "▁制服", -11.225786209106445 ], [ "▁ログ", -11.225963592529297 ], [ "▁相撲", -11.22646713256836 ], [ "▁手帳", -11.22648811340332 ], [ "▁なかったり", -11.226493835449219 ], [ "▁EC", -11.226553916931152 ], [ "▁集める", -11.226598739624023 ], [ "▁策定", -11.226823806762695 ], [ "▁Go", -11.227035522460938 ], [ "ish", -11.227214813232422 ], [ "▁巨大", -11.227228164672852 ], [ "▁おいた", -11.227672576904297 ], [ "▁畳", -11.22768783569336 ], [ "do", -11.227696418762207 ], [ "せば", -11.227723121643066 ], [ "▁思ったら", -11.227728843688965 ], [ "▁ノン", -11.227776527404785 ], [ "▁血管", -11.22780990600586 ], [ "リウス", -11.227967262268066 ], [ "▁幻", -11.228130340576172 ], [ "▁池袋", -11.228519439697266 ], [ "▁仕掛け", -11.22854232788086 ], [ "▁ミラー", -11.22866153717041 ], [ "▁ポスター", -11.228771209716797 ], [ "▁ダイヤモンド", -11.228797912597656 ], [ "▁SE", -11.228976249694824 ], [ "▁参謀", -11.229023933410645 ], [ "MP", -11.229247093200684 ], [ "▁監査", -11.22945785522461 ], [ "▁みたら", -11.229522705078125 ], [ "エー", -11.22955322265625 ], [ "▁杉", -11.229666709899902 ], [ "▁マッチング", -11.22990894317627 ], [ "プス", -11.230198860168457 ], [ "率", -11.230542182922363 ], [ "▁74", -11.230666160583496 ], [ "▁エンディング", -11.230681419372559 ], [ "▁桂", -11.231000900268555 ], [ "▁キャッシュ", -11.231082916259766 ], [ "▁家臣", -11.231096267700195 ], [ "▁苦手", -11.231209754943848 ], [ "▁130", -11.23137092590332 ], [ "▁先日", -11.231552124023438 ], [ "▁解約", -11.231616020202637 ], [ "▁早稲田", -11.231773376464844 ], [ "封", -11.232115745544434 ], [ "▁倶楽部", -11.232126235961914 ], [ "▁ギリシア", -11.232259750366211 ], [ "▁個々", -11.232283592224121 ], [ "▁取れる", -11.232376098632812 ], [ "改", -11.232882499694824 ], [ "▁将", -11.23306941986084 ], [ "▁ヘル", -11.233222961425781 ], [ "▁歩く", -11.23326587677002 ], [ "lu", -11.23328971862793 ], [ "でしょう", -11.233379364013672 ], [ "述", -11.23355484008789 ], [ "▁全力", -11.233559608459473 ], [ "昌", -11.233674049377441 ], [ "▁警戒", -11.233686447143555 ], [ "▁ぶ", -11.234336853027344 ], [ "▁コツ", -11.234634399414062 ], [ "▁たった", -11.234636306762695 ], [ "▁天井", -11.235045433044434 ], [ "▁不可能", -11.23505973815918 ], [ "活", -11.235250473022461 ], [ "▁帰る", -11.23530387878418 ], [ "NO", -11.235361099243164 ], [ "▁抜け", -11.235487937927246 ], [ "確かに", -11.235490798950195 ], [ "▁体力", -11.235560417175293 ], [ "さい", -11.235630989074707 ], [ "▁◎", -11.235743522644043 ], [ "ンダ", -11.235747337341309 ], [ "▁バンク", -11.23588752746582 ], [ "▁コンクリート", -11.236221313476562 ], [ "潮", -11.236342430114746 ], [ "▁まあ", -11.236371994018555 ], [ "▁守護", -11.23653793334961 ], [ "前回", -11.236562728881836 ], [ "▁レーザー", -11.236647605895996 ], [ "ミル", -11.236659049987793 ], [ "▁Cloud", -11.236994743347168 ], [ "▁文明", -11.237068176269531 ], [ "▁向かった", -11.237112998962402 ], [ "ST", -11.237277030944824 ], [ "ヘン", -11.237327575683594 ], [ "▁各社", -11.237600326538086 ], [ "no", -11.238073348999023 ], [ "▁育児", -11.238214492797852 ], [ "▁エー", -11.238280296325684 ], [ "▁行列", -11.238319396972656 ], [ "▁中断", -11.238435745239258 ], [ "▁1930", -11.238449096679688 ], [ "経済", -11.23845100402832 ], [ "▁狭い", -11.23851203918457 ], [ "▁安打", -11.238861083984375 ], [ "▁貸し", -11.238959312438965 ], [ "▁Japan", -11.239032745361328 ], [ "▁フットボール", -11.239059448242188 ], [ "▁シルバー", -11.23917293548584 ], [ "▁入店", -11.239304542541504 ], [ "ッグ", -11.239697456359863 ], [ "▁ぐ", -11.239899635314941 ], [ "▁絞り", -11.240012168884277 ], [ "▁鑑賞", -11.240092277526855 ], [ "▁インドネシア", -11.240131378173828 ], [ "▁歌う", -11.240140914916992 ], [ "▁オレ", -11.240174293518066 ], [ "スタン", -11.240320205688477 ], [ "▁多摩", -11.240367889404297 ], [ "▁しちゃ", -11.240691184997559 ], [ "▁犯人", -11.241055488586426 ], [ "桜", -11.241060256958008 ], [ "打ち", -11.24126148223877 ], [ "▁at", -11.241436004638672 ], [ "逆に", -11.241822242736816 ], [ "▁KO", -11.241862297058105 ], [ "参", -11.242090225219727 ], [ "程", -11.242210388183594 ], [ "研究", -11.24228572845459 ], [ "▁備え", -11.242288589477539 ], [ "▁備えた", -11.242377281188965 ], [ "絶", -11.242466926574707 ], [ "▁乗る", -11.242714881896973 ], [ "単", -11.242754936218262 ], [ "▁ゆる", -11.242931365966797 ], [ "▁艇", -11.24294662475586 ], [ "▁オス", -11.243124961853027 ], [ "▁あくまで", -11.243182182312012 ], [ "▁革新", -11.243363380432129 ], [ "EC", -11.243454933166504 ], [ "ナル", -11.243977546691895 ], [ "ギー", -11.24406909942627 ], [ "▁乾", -11.244237899780273 ], [ "IL", -11.244477272033691 ], [ "イヤー", -11.244477272033691 ], [ "▁1940", -11.244491577148438 ], [ "▁伝わる", -11.244529724121094 ], [ "名前", -11.244568824768066 ], [ "▁1962", -11.244820594787598 ], [ "▁佐野", -11.244834899902344 ], [ "▁デンマーク", -11.244900703430176 ], [ "純", -11.244982719421387 ], [ "▁在宅", -11.245399475097656 ], [ "限", -11.245400428771973 ], [ "▁上場", -11.245686531066895 ], [ "▁急に", -11.245704650878906 ], [ "▁操縦", -11.245715141296387 ], [ "ik", -11.245816230773926 ], [ "がって", -11.245918273925781 ], [ "▁短く", -11.246016502380371 ], [ "▁次回", -11.246051788330078 ], [ "垣", -11.246227264404297 ], [ "▁仙", -11.246236801147461 ], [ "デー", -11.246309280395508 ], [ "▁重い", -11.246440887451172 ], [ "CO", -11.246448516845703 ], [ "▁担う", -11.246684074401855 ], [ "▁有限", -11.247037887573242 ], [ "▁難易", -11.247217178344727 ], [ "▁接", -11.247334480285645 ], [ "▁ヘンリー", -11.247335433959961 ], [ "▁ミュージカル", -11.247382164001465 ], [ "aw", -11.247476577758789 ], [ "▁900", -11.247579574584961 ], [ "ko", -11.247763633728027 ], [ "籍", -11.247976303100586 ], [ "▁セイ", -11.248002052307129 ], [ "▁急速に", -11.248037338256836 ], [ "▁フィンペシア", -11.248135566711426 ], [ "▁伝承", -11.248485565185547 ], [ "▁接する", -11.248791694641113 ], [ "oc", -11.249051094055176 ], [ "せて", -11.249105453491211 ], [ "▁高額", -11.249112129211426 ], [ "ロイド", -11.249114036560059 ], [ "▁たら", -11.249322891235352 ], [ "1989", -11.249374389648438 ], [ "▁コスプレ", -11.249948501586914 ], [ "ケル", -11.250091552734375 ], [ "▁ランド", -11.250596046447754 ], [ "善", -11.250617027282715 ], [ "▁ว", -11.250669479370117 ], [ "▁意外", -11.250680923461914 ], [ "▁全域", -11.250824928283691 ], [ "▁愛称", -11.251016616821289 ], [ "▁プレミア", -11.251076698303223 ], [ "▁収穫", -11.25110149383545 ], [ "▁有力", -11.251140594482422 ], [ "竜", -11.2511625289917 ], [ "▁梅田", -11.251296997070312 ], [ "▁進歩", -11.251446723937988 ], [ "▁適応", -11.251476287841797 ], [ "▁フロア", -11.251943588256836 ], [ "区", -11.252069473266602 ], [ "▁行こう", -11.252338409423828 ], [ "▁続編", -11.252455711364746 ], [ "BS", -11.2524995803833 ], [ "▁平野", -11.25258731842041 ], [ "▁ふく", -11.252616882324219 ], [ "▁誘", -11.252748489379883 ], [ "▁法学部", -11.252803802490234 ], [ "週", -11.252894401550293 ], [ "▁ども", -11.25333309173584 ], [ "▁cc", -11.253402709960938 ], [ "▁アマチュア", -11.253475189208984 ], [ "▁暮らして", -11.253478050231934 ], [ "最後に", -11.253661155700684 ], [ "▁天狼", -11.253742218017578 ], [ "▁加えた", -11.253935813903809 ], [ "ind", -11.254014015197754 ], [ "▁目安", -11.254447937011719 ], [ "▁78", -11.254745483398438 ], [ "▁支え", -11.254773139953613 ], [ "▁切り替え", -11.254932403564453 ], [ "▁座席", -11.254966735839844 ], [ "▁除いて", -11.255037307739258 ], [ "深", -11.255048751831055 ], [ "せい", -11.255049705505371 ], [ "ゴー", -11.255139350891113 ], [ "ほか", -11.255217552185059 ], [ "▁エキス", -11.255247116088867 ], [ "ip", -11.255331993103027 ], [ "皆さん", -11.25544261932373 ], [ "▁重ね", -11.255448341369629 ], [ "博", -11.255576133728027 ], [ "源", -11.255914688110352 ], [ "そのような", -11.256083488464355 ], [ "▁修士", -11.25613784790039 ], [ "払", -11.257147789001465 ], [ "▁Do", -11.257286071777344 ], [ "▁来年", -11.25741958618164 ], [ "▁ロイヤル", -11.258052825927734 ], [ "▁浸透", -11.258254051208496 ], [ "▁手作り", -11.258710861206055 ], [ "▁みな", -11.258792877197266 ], [ "▁やつ", -11.258828163146973 ], [ "▁やめ", -11.258941650390625 ], [ "▁接近", -11.258966445922852 ], [ "▁移植", -11.259222030639648 ], [ "▁87", -11.259382247924805 ], [ "▁肝", -11.259420394897461 ], [ "要", -11.259456634521484 ], [ "▁居る", -11.259811401367188 ], [ "発売", -11.259900093078613 ], [ "▁ならびに", -11.260130882263184 ], [ "メイ", -11.260397911071777 ], [ "▁祐", -11.260808944702148 ], [ "▁ドゥ", -11.260902404785156 ], [ "ค", -11.261274337768555 ], [ "▁載せて", -11.26130485534668 ], [ "▁スコットランド", -11.261385917663574 ], [ "▁死んだ", -11.261457443237305 ], [ "▁巨乳", -11.261474609375 ], [ "▁まい", -11.261727333068848 ], [ "モア", -11.261749267578125 ], [ "▁下位", -11.261821746826172 ], [ "▁シャー", -11.261859893798828 ], [ "▁中華", -11.262081146240234 ], [ "▁殆ど", -11.262604713439941 ], [ "▁巨", -11.262617111206055 ], [ "▁工程", -11.26262378692627 ], [ "▁FIFA", -11.262657165527344 ], [ "▁あったり", -11.262701034545898 ], [ "軽", -11.262955665588379 ], [ "▁豚", -11.262988090515137 ], [ "▁打点", -11.263078689575195 ], [ "ax", -11.263195037841797 ], [ "▁91", -11.263448715209961 ], [ "oo", -11.263533592224121 ], [ "監", -11.263717651367188 ], [ "▁思える", -11.263888359069824 ], [ "▁タオル", -11.263899803161621 ], [ "act", -11.263998985290527 ], [ "▁NTT", -11.264097213745117 ], [ "▁実務", -11.264100074768066 ], [ "▁山脈", -11.264420509338379 ], [ "▁特殊な", -11.264425277709961 ], [ "▁twitter", -11.264473915100098 ], [ "▁ますます", -11.264618873596191 ], [ "▁私立", -11.264720916748047 ], [ "▁収めた", -11.26483154296875 ], [ "カナダ", -11.26485538482666 ], [ "▁届く", -11.265081405639648 ], [ "▁ドキュメンタリー", -11.26514720916748 ], [ "額", -11.265345573425293 ], [ "▁御殿場", -11.265351295471191 ], [ "▁大量に", -11.265464782714844 ], [ "▁1944", -11.265643119812012 ], [ "▁連覇", -11.26579475402832 ], [ "▁GT", -11.265849113464355 ], [ "▁食べた", -11.265873908996582 ], [ "評", -11.26598834991455 ], [ "毎年", -11.266079902648926 ], [ "EM", -11.266161918640137 ], [ "▁ライバル", -11.266172409057617 ], [ "穂", -11.266519546508789 ], [ "▁代金", -11.266678810119629 ], [ "▁適合", -11.266899108886719 ], [ "▁破産", -11.26701831817627 ], [ "OT", -11.267744064331055 ], [ "▁2105", -11.267763137817383 ], [ "照", -11.267827033996582 ], [ "▁工房", -11.268389701843262 ], [ "▁不思議", -11.268714904785156 ], [ "▁位置づけ", -11.26874828338623 ], [ "▁スカイ", -11.268959999084473 ], [ "ニス", -11.268978118896484 ], [ "静", -11.268986701965332 ], [ "▁飲料", -11.269424438476562 ], [ "TC", -11.269737243652344 ], [ "▁キャップ", -11.269845008850098 ], [ "▁肉体", -11.270078659057617 ], [ "▁グラス", -11.270241737365723 ], [ "▁興奮", -11.270402908325195 ], [ "▁ヒロイン", -11.270572662353516 ], [ "▁ワークショップ", -11.271191596984863 ], [ "ブロ", -11.271398544311523 ], [ "▁どころ", -11.271469116210938 ], [ "▁α", -11.271585464477539 ], [ "▁シャンプー", -11.271614074707031 ], [ "▁決まり", -11.27176570892334 ], [ "わら", -11.27195930480957 ], [ "そもそも", -11.272123336791992 ], [ "▁ジー", -11.272140502929688 ], [ "▁平安", -11.272259712219238 ], [ "▁岸", -11.272381782531738 ], [ "練", -11.272435188293457 ], [ "掛け", -11.272520065307617 ], [ "▁ターゲット", -11.272575378417969 ], [ "朗", -11.272650718688965 ], [ "▁マイナス", -11.272732734680176 ], [ "IP", -11.272847175598145 ], [ "▁細菌", -11.27291488647461 ], [ "▁困って", -11.273083686828613 ], [ "▁蒸気", -11.273523330688477 ], [ "▁合わせる", -11.27354907989502 ], [ "▁案件", -11.273616790771484 ], [ "▁シカゴ", -11.273687362670898 ], [ "▁刀", -11.273740768432617 ], [ "▁救急", -11.27379035949707 ], [ "▁順次", -11.273843765258789 ], [ "▁DC", -11.273872375488281 ], [ "▁キーボード", -11.274683952331543 ], [ "▁ユニフォーム", -11.274991035461426 ], [ "▁マッ", -11.275094032287598 ], [ "ラント", -11.27512264251709 ], [ "▁スープ", -11.275162696838379 ], [ "▁手入れ", -11.275177955627441 ], [ "ライブ", -11.275201797485352 ], [ "▁食料", -11.275623321533203 ], [ "▁景色", -11.275762557983398 ], [ "▁認可", -11.275777816772461 ], [ "▁1961", -11.275794982910156 ], [ "▁重複", -11.275826454162598 ], [ "▁やっと", -11.275858879089355 ], [ "▁耐", -11.275898933410645 ], [ "▁いらっしゃい", -11.27592945098877 ], [ "▁幸いです", -11.2762451171875 ], [ "▁爆", -11.276602745056152 ], [ "▁大好きな", -11.276663780212402 ], [ "▁飛", -11.276810646057129 ], [ "▁JavaScript", -11.276909828186035 ], [ "▁体操", -11.277043342590332 ], [ "▁余り", -11.277127265930176 ], [ "▁ナショナル", -11.277338027954102 ], [ "▁渡る", -11.277543067932129 ], [ "▁大切", -11.27762508392334 ], [ "▁打ち上げ", -11.277668952941895 ], [ "▁国防", -11.277881622314453 ], [ "▁抽選", -11.27797794342041 ], [ "▁丈", -11.278057098388672 ], [ "▁射", -11.278114318847656 ], [ "▁次いで", -11.278565406799316 ], [ "▁補佐", -11.278757095336914 ], [ "▁店頭", -11.279202461242676 ], [ "▁外務", -11.27959156036377 ], [ "ヨン", -11.279623985290527 ], [ "▁好きに", -11.279654502868652 ], [ "▁青春", -11.279888153076172 ], [ "▁Con", -11.279980659484863 ], [ "▁ッ", -11.280354499816895 ], [ "▁ミックス", -11.280548095703125 ], [ "▁宝塚", -11.280661582946777 ], [ "▁ボクシング", -11.280920028686523 ], [ "▁ユーザ", -11.28122615814209 ], [ "▁待つ", -11.281233787536621 ], [ "▁違った", -11.281254768371582 ], [ "▁繋がり", -11.281336784362793 ], [ "▁総督", -11.281474113464355 ], [ "▁en", -11.281479835510254 ], [ "▁マイケル", -11.28150463104248 ], [ "ick", -11.281606674194336 ], [ "▁芸", -11.281659126281738 ], [ "▁意向", -11.281700134277344 ], [ "▁嬢", -11.281729698181152 ], [ "▁申し", -11.281790733337402 ], [ "裏", -11.281928062438965 ], [ "▁New", -11.281965255737305 ], [ "もっと", -11.282133102416992 ], [ "▁書記", -11.282193183898926 ], [ "▁舌", -11.282842636108398 ], [ "▁爆弾", -11.28307819366455 ], [ "EE", -11.283158302307129 ], [ "▁ロン", -11.283211708068848 ], [ "▁まとめた", -11.283272743225098 ], [ "▁高松", -11.283331871032715 ], [ "ore", -11.283463478088379 ], [ "▁上り", -11.283501625061035 ], [ "解説", -11.28369140625 ], [ "▁つくり", -11.283721923828125 ], [ "▁ぎ", -11.283731460571289 ], [ "▁焦点", -11.28388500213623 ], [ "▁IS", -11.283968925476074 ], [ "▁ダー", -11.284089088439941 ], [ "eb", -11.284568786621094 ], [ "▁がっこう", -11.284932136535645 ], [ "ノール", -11.285111427307129 ], [ "PO", -11.285292625427246 ], [ "▁圧縮", -11.285412788391113 ], [ "リル", -11.285451889038086 ], [ "▁ハリ", -11.285489082336426 ], [ "▁米軍", -11.285542488098145 ], [ "▁カレッジ", -11.285561561584473 ], [ "▁数十", -11.285627365112305 ], [ "▁繁殖", -11.285639762878418 ], [ "▁支える", -11.285662651062012 ], [ "▁徹", -11.285795211791992 ], [ "▁植え", -11.285859107971191 ], [ "▁いら", -11.285993576049805 ], [ "▁1500", -11.286091804504395 ], [ "▁英和", -11.2862548828125 ], [ "▁死刑", -11.286296844482422 ], [ "計", -11.286333084106445 ], [ "▁ファイナル", -11.286640167236328 ], [ "離", -11.286742210388184 ], [ "▁サクラ", -11.286763191223145 ], [ "ダム", -11.28679370880127 ], [ "port", -11.286931037902832 ], [ "▁厳選", -11.287022590637207 ], [ "ミリ", -11.287076950073242 ], [ "▁ソリューション", -11.287224769592285 ], [ "▁いける", -11.287371635437012 ], [ "▁かかった", -11.287436485290527 ], [ "グロ", -11.287613868713379 ], [ "同時に", -11.287853240966797 ], [ "緑", -11.287870407104492 ], [ "弥", -11.288129806518555 ], [ "ドール", -11.288151741027832 ], [ "▁ガソリン", -11.288230895996094 ], [ "▁直し", -11.288379669189453 ], [ "▁正確な", -11.288471221923828 ], [ "▁味方", -11.288495063781738 ], [ "Windows", -11.288564682006836 ], [ "刻", -11.288748741149902 ], [ "▁レー", -11.288933753967285 ], [ "FA", -11.289209365844727 ], [ "▁告白", -11.289220809936523 ], [ "▁承", -11.28924560546875 ], [ "▁任意", -11.289246559143066 ], [ "菌", -11.289517402648926 ], [ "ボール", -11.28984546661377 ], [ "▁1947", -11.290120124816895 ], [ "▁同人", -11.29040241241455 ], [ "▁単行本", -11.290416717529297 ], [ "載", -11.290417671203613 ], [ "我", -11.29042911529541 ], [ "▁生じ", -11.290626525878906 ], [ "▁テクニック", -11.290882110595703 ], [ "▁起こし", -11.291028022766113 ], [ "▁庭園", -11.29121208190918 ], [ "▁ひろ", -11.291349411010742 ], [ "▁我", -11.291487693786621 ], [ "フラ", -11.29153060913086 ], [ "アップ", -11.291593551635742 ], [ "▁ブロ", -11.291765213012695 ], [ "ニュー", -11.292007446289062 ], [ "mon", -11.292061805725098 ], [ "▁知り合い", -11.292067527770996 ], [ "ビス", -11.29208755493164 ], [ "▁わかった", -11.292509078979492 ], [ "▁寿命", -11.292519569396973 ], [ "▁インディアン", -11.2927827835083 ], [ "▁済", -11.292967796325684 ], [ "録", -11.293025016784668 ], [ "▁快", -11.293118476867676 ], [ "▁角度", -11.293231964111328 ], [ "合わせ", -11.29355239868164 ], [ "▁トム", -11.293598175048828 ], [ "▁下旬", -11.293724060058594 ], [ "▁勝手", -11.29378890991211 ], [ "▁っぽい", -11.293951034545898 ], [ "▁360", -11.294014930725098 ], [ "▁TO", -11.294288635253906 ], [ "▁ワンピース", -11.294392585754395 ], [ "▁調べる", -11.29446029663086 ], [ "JR", -11.294605255126953 ], [ "▁ねぇ", -11.294770240783691 ], [ "▁祈り", -11.294943809509277 ], [ "▁最多", -11.2949857711792 ], [ "ディン", -11.294997215270996 ], [ "鉄道", -11.29521369934082 ], [ "陸", -11.295223236083984 ], [ "▁決断", -11.295476913452148 ], [ "▁LIVE", -11.29582691192627 ], [ "情報", -11.296005249023438 ], [ "費", -11.296088218688965 ], [ "▁仕上げ", -11.296207427978516 ], [ "弊社", -11.29634952545166 ], [ "▁婦", -11.296360969543457 ], [ "▁97", -11.296770095825195 ], [ "ッキ", -11.296857833862305 ], [ "▁分散", -11.296947479248047 ], [ "▁粒子", -11.297127723693848 ], [ "▁アブ", -11.297157287597656 ], [ "除", -11.297207832336426 ], [ "▁総額", -11.29725170135498 ], [ "▁堅", -11.29730224609375 ], [ "▁ネコ", -11.297503471374512 ], [ "▁技能", -11.297677993774414 ], [ "ぜ", -11.297921180725098 ], [ "▁89", -11.297971725463867 ], [ "▁イラン", -11.298125267028809 ], [ "▁カップル", -11.298150062561035 ], [ "牧", -11.298233985900879 ], [ "▁士官", -11.29824447631836 ], [ "▁Li", -11.29825496673584 ], [ "壇", -11.298280715942383 ], [ "▁ユナイテッド", -11.29831600189209 ], [ "▁線路", -11.298318862915039 ], [ "▁暮らす", -11.298410415649414 ], [ "▁考察", -11.29841423034668 ], [ "CC", -11.298589706420898 ], [ "▁食い", -11.298762321472168 ], [ "▁vol", -11.298856735229492 ], [ "朽", -11.298887252807617 ], [ "▁再編", -11.298913955688477 ], [ "▁突入", -11.299188613891602 ], [ "▁国籍", -11.299202919006348 ], [ "▁高原", -11.299298286437988 ], [ "▁みたいに", -11.299325942993164 ], [ "▁学位", -11.299346923828125 ], [ "ピン", -11.2994384765625 ], [ "▁玩具", -11.299887657165527 ], [ "▁有無", -11.299917221069336 ], [ "▁だから", -11.299946784973145 ], [ "身長", -11.300012588500977 ], [ "▁木村", -11.300768852233887 ], [ "▁東映", -11.30079460144043 ], [ "IG", -11.300891876220703 ], [ "▁外観", -11.301066398620605 ], [ "▁タッグ", -11.301154136657715 ], [ "▁SAP", -11.301335334777832 ], [ "▁センチ", -11.301375389099121 ], [ "学生", -11.301417350769043 ], [ "▁官僚", -11.301420211791992 ], [ "▁ぼく", -11.301631927490234 ], [ "次の", -11.301726341247559 ], [ "▁al", -11.301850318908691 ], [ "▁芳", -11.301894187927246 ], [ "▁洗浄", -11.301990509033203 ], [ "▁総称", -11.302053451538086 ], [ "▁玄", -11.302461624145508 ], [ "▁page", -11.302515983581543 ], [ "▁行方", -11.303047180175781 ], [ "▁敗退", -11.303085327148438 ], [ "▁岡", -11.303178787231445 ], [ "▁保つ", -11.303236961364746 ], [ "▁なるべく", -11.303563117980957 ], [ "▁Part", -11.303777694702148 ], [ "ru", -11.304069519042969 ], [ "▁行け", -11.304222106933594 ], [ "▁故郷", -11.304357528686523 ], [ "▁いきなり", -11.30491828918457 ], [ "▁愛さ", -11.30508041381836 ], [ "航", -11.305302619934082 ], [ "儀", -11.305495262145996 ], [ "シティ", -11.305512428283691 ], [ "▁終戦", -11.305622100830078 ], [ "▁所蔵", -11.305856704711914 ], [ "▁JA", -11.305899620056152 ], [ "医", -11.305985450744629 ], [ "▁自立", -11.306144714355469 ], [ "▁堺", -11.306192398071289 ], [ "AND", -11.306414604187012 ], [ "▁何とか", -11.306486129760742 ], [ "▁レジ", -11.306621551513672 ], [ "▁グラフィック", -11.306836128234863 ], [ "IO", -11.307095527648926 ], [ "▁放出", -11.307404518127441 ], [ "▁うた", -11.307448387145996 ], [ "▁トライ", -11.307499885559082 ], [ "▁インターナショナル", -11.30754566192627 ], [ "夢", -11.307846069335938 ], [ "▁葬儀", -11.308137893676758 ], [ "▁アンテナ", -11.308441162109375 ], [ "しま", -11.308603286743164 ], [ "▁DJ", -11.308707237243652 ], [ "▁既", -11.308737754821777 ], [ "▁応え", -11.30875301361084 ], [ "▁アメ", -11.309354782104492 ], [ "▁安全な", -11.309407234191895 ], [ "▁医学部", -11.309588432312012 ], [ "▁陳", -11.30986499786377 ], [ "▁アカ", -11.310028076171875 ], [ "但し", -11.310086250305176 ], [ "▁当主", -11.31013298034668 ], [ "▁かな", -11.310138702392578 ], [ "▁ご存知", -11.310379981994629 ], [ "▁先進", -11.310418128967285 ], [ "▁帽子", -11.310962677001953 ], [ "戻", -11.311052322387695 ], [ "行政", -11.311589241027832 ], [ "▁主任", -11.311767578125 ], [ "▁欠", -11.311864852905273 ], [ "▁蓄積", -11.311922073364258 ], [ "じょう", -11.311980247497559 ], [ "▁アム", -11.312039375305176 ], [ "▁なされて", -11.312122344970703 ], [ "とも", -11.312238693237305 ], [ "▁碑", -11.312407493591309 ], [ "▁故", -11.31273365020752 ], [ "▁文部", -11.31301212310791 ], [ "肌", -11.313202857971191 ], [ "▁書庫", -11.313239097595215 ], [ "▁ヴァン", -11.313272476196289 ], [ "襲", -11.313379287719727 ], [ "▁何より", -11.313382148742676 ], [ "▁集まる", -11.313563346862793 ], [ "▁スロット", -11.314101219177246 ], [ "処", -11.31472396850586 ], [ "剤", -11.315237998962402 ], [ "少", -11.315398216247559 ], [ "▁頭部", -11.315695762634277 ], [ "▁昭", -11.315751075744629 ], [ "▁細かい", -11.315861701965332 ], [ "▁花火", -11.316194534301758 ], [ "▁探", -11.316282272338867 ], [ "▁SIM", -11.316341400146484 ], [ "▁宅配", -11.316400527954102 ], [ "ベルク", -11.316495895385742 ], [ "▁併用", -11.316551208496094 ], [ "▁疲労", -11.316612243652344 ], [ "帰", -11.316834449768066 ], [ "猫", -11.31686019897461 ], [ "▁成田", -11.31719970703125 ], [ "支", -11.317277908325195 ], [ "▁アロマ", -11.317320823669434 ], [ "su", -11.317543983459473 ], [ "▁並び", -11.317753791809082 ], [ "以降", -11.317882537841797 ], [ "▁博多", -11.317896842956543 ], [ "輔", -11.317995071411133 ], [ "▁意志", -11.31810188293457 ], [ "ジャン", -11.318110466003418 ], [ "▁フォーラム", -11.31820297241211 ], [ "▁パイ", -11.318342208862305 ], [ "▁調節", -11.318655014038086 ], [ "▁フィンランド", -11.318816184997559 ], [ "▁決議", -11.318818092346191 ], [ "ka", -11.318833351135254 ], [ "▁水産", -11.31889533996582 ], [ "▁頂ける", -11.318912506103516 ], [ "▁ヶ", -11.319084167480469 ], [ "▁節約", -11.31908893585205 ], [ "▁農家", -11.31924819946289 ], [ "▁便利", -11.319329261779785 ], [ "▁ボス", -11.319360733032227 ], [ "▁生存", -11.319422721862793 ], [ "▁勃発", -11.319476127624512 ], [ "▁三浦", -11.319478988647461 ], [ "▁潜", -11.319513320922852 ], [ "▁フォーク", -11.319624900817871 ], [ "ank", -11.319929122924805 ], [ "▁過ぎる", -11.32000732421875 ], [ "▁冷蔵", -11.320249557495117 ], [ "▁降", -11.320304870605469 ], [ "▁93", -11.320372581481934 ], [ "▁軍隊", -11.32071304321289 ], [ "ホン", -11.320754051208496 ], [ "▁拘束", -11.321037292480469 ], [ "▁信長", -11.321213722229004 ], [ "▁動員", -11.321520805358887 ], [ "反", -11.321623802185059 ], [ "ain", -11.321639060974121 ], [ "▁属して", -11.321866989135742 ], [ "本名", -11.321883201599121 ], [ "▁込めて", -11.322010040283203 ], [ "▁次ぐ", -11.322237014770508 ], [ "▁コント", -11.322306632995605 ], [ "クラブ", -11.322640419006348 ], [ "▁叙", -11.32275104522705 ], [ "▁authorHTMLs", -11.322979927062988 ], [ "▁入ら", -11.322979927062988 ], [ "短", -11.323067665100098 ], [ "あの", -11.323079109191895 ], [ "WA", -11.323182106018066 ], [ "ハイム", -11.323321342468262 ], [ "▁連勝", -11.323417663574219 ], [ "▁継いだ", -11.323527336120605 ], [ "タウン", -11.32354736328125 ], [ "1988", -11.323575973510742 ], [ "詞", -11.323689460754395 ], [ "▁休憩", -11.323814392089844 ], [ "▁互いに", -11.324016571044922 ], [ "やか", -11.324422836303711 ], [ "▁大名", -11.32446002960205 ], [ "ぃ", -11.324494361877441 ], [ "▁MP", -11.324695587158203 ], [ "▁スタンダード", -11.324750900268555 ], [ "▁味わい", -11.324915885925293 ], [ "キュー", -11.324922561645508 ], [ "イド", -11.324983596801758 ], [ "▁遊ぶ", -11.325037002563477 ], [ "▁新築", -11.325129508972168 ], [ "▁交付", -11.325149536132812 ], [ "able", -11.325203895568848 ], [ "ox", -11.325486183166504 ], [ "▁百貨店", -11.325570106506348 ], [ "▁キン", -11.325583457946777 ], [ "▁除", -11.325689315795898 ], [ "ッフル", -11.3258056640625 ], [ "▁拝", -11.325831413269043 ], [ "▁配列", -11.326038360595703 ], [ "▁ウェア", -11.326160430908203 ], [ "▁MA", -11.326275825500488 ], [ "背", -11.326314926147461 ], [ "とはいえ", -11.326410293579102 ], [ "▁存続", -11.326502799987793 ], [ "▁寿司", -11.32674503326416 ], [ "▁試作", -11.327055931091309 ], [ "▁危険な", -11.327293395996094 ], [ "▁1948", -11.327387809753418 ], [ "▁破り", -11.32739543914795 ], [ "▁あん", -11.327529907226562 ], [ "▁ムー", -11.327543258666992 ], [ "▁1920", -11.327582359313965 ], [ "アメリカ合衆国", -11.327858924865723 ], [ "▁緩", -11.32808780670166 ], [ "▁黄金", -11.32812213897705 ], [ "▁錦", -11.328158378601074 ], [ "▁近畿", -11.328286170959473 ], [ "▁ロール", -11.328404426574707 ], [ "▁スパ", -11.32848834991455 ], [ "▁町村", -11.32853889465332 ], [ "▁残し", -11.328838348388672 ], [ "牛", -11.328849792480469 ], [ "▁忙しい", -11.328902244567871 ], [ "引き", -11.328910827636719 ], [ "▁添加", -11.328949928283691 ], [ "シル", -11.329257011413574 ], [ "ary", -11.329421043395996 ], [ "▁DNA", -11.329533576965332 ], [ "▁認めて", -11.329578399658203 ], [ "▁とう", -11.329686164855957 ], [ "▁鎮", -11.329758644104004 ], [ "▁人種", -11.329920768737793 ], [ "問", -11.32992935180664 ], [ "▁BOX", -11.330159187316895 ], [ "▁球場", -11.3302001953125 ], [ "▁至って", -11.330440521240234 ], [ "▁立体", -11.330622673034668 ], [ "▁告知", -11.331110954284668 ], [ "▁ジェイ", -11.331257820129395 ], [ "▁奉", -11.331339836120605 ], [ "策", -11.331355094909668 ], [ "▁ねば", -11.331840515136719 ], [ "▁語ら", -11.332123756408691 ], [ "▁UP", -11.332139015197754 ], [ "▁グレード", -11.33217716217041 ], [ "▁脱退", -11.332234382629395 ], [ "▁相性", -11.332528114318848 ], [ "▁ゾ", -11.332658767700195 ], [ "▁たっぷり", -11.33279037475586 ], [ "▁施さ", -11.332793235778809 ], [ "滅", -11.3330717086792 ], [ "ウッド", -11.333094596862793 ], [ "▁修行", -11.333176612854004 ], [ "▁ジェームズ", -11.33334732055664 ], [ "▁支払う", -11.333456993103027 ], [ "ヘル", -11.333547592163086 ], [ "▁⌒", -11.333578109741211 ], [ "▁つい", -11.333673477172852 ], [ "▁地形", -11.333802223205566 ], [ "▁明るく", -11.334163665771484 ], [ "鶴", -11.334168434143066 ], [ "▁辺", -11.3341703414917 ], [ "インターネット", -11.334217071533203 ], [ "▁常識", -11.334247589111328 ], [ "▁部下", -11.334378242492676 ], [ "▁宅", -11.334542274475098 ], [ "▁オーケストラ", -11.33460807800293 ], [ "▁々", -11.334628105163574 ], [ "研", -11.334662437438965 ], [ "▁補償", -11.33471393585205 ], [ "▁刑", -11.334797859191895 ], [ "▁後悔", -11.334817886352539 ], [ "リズム", -11.334906578063965 ], [ "▁ダーク", -11.33495807647705 ], [ "▁雷", -11.335000991821289 ], [ "▁必要だ", -11.335108757019043 ], [ "▁組んで", -11.335290908813477 ], [ "▁強度", -11.335309982299805 ], [ "▁即日", -11.335700988769531 ], [ "責", -11.335832595825195 ], [ "彩", -11.33587646484375 ], [ "▁周期", -11.33598804473877 ], [ "▁おけば", -11.336408615112305 ], [ "▁カウンセリング", -11.336487770080566 ], [ "▁ヤング", -11.336663246154785 ], [ "▁降伏", -11.336690902709961 ], [ "▁1959", -11.336730003356934 ], [ "▁切って", -11.336753845214844 ], [ "▁アナログ", -11.33679485321045 ], [ "▁講談", -11.337383270263672 ], [ "▁出勤", -11.337565422058105 ], [ "▁ねん", -11.337756156921387 ], [ "かさ", -11.338033676147461 ], [ "▁岳", -11.338044166564941 ], [ "▁大いに", -11.338086128234863 ], [ "▁応じた", -11.338287353515625 ], [ "▁参議院", -11.338577270507812 ], [ "▁王朝", -11.338894844055176 ], [ "まら", -11.338943481445312 ], [ "▁増大", -11.338996887207031 ], [ "▁iOS", -11.339112281799316 ], [ "▁減らす", -11.339767456054688 ], [ "▁ロケ", -11.339889526367188 ], [ "シャン", -11.340130805969238 ], [ "▁1958", -11.340242385864258 ], [ "▁運輸", -11.340256690979004 ], [ "文字", -11.340328216552734 ], [ "かわ", -11.340685844421387 ], [ "▁後者", -11.34079360961914 ], [ "▁望む", -11.3408784866333 ], [ "▁振動", -11.340943336486816 ], [ "▁たくて", -11.34118938446045 ], [ "▁混合", -11.341242790222168 ], [ "▁一帯", -11.34124755859375 ], [ "▁イラク", -11.341700553894043 ], [ "▁びっくり", -11.341850280761719 ], [ "▁キック", -11.341869354248047 ], [ "▁甘い", -11.3423490524292 ], [ "OD", -11.342363357543945 ], [ "▁火山", -11.342516899108887 ], [ "▁詩人", -11.34262466430664 ], [ "外部", -11.342817306518555 ], [ "▁コレ", -11.342824935913086 ], [ "▁マラ", -11.342828750610352 ], [ "隣接", -11.342851638793945 ], [ "▁ソー", -11.343031883239746 ], [ "▁超え", -11.343215942382812 ], [ "境", -11.343518257141113 ], [ "▁変形", -11.34424114227295 ], [ "▁オリジナルの", -11.344524383544922 ], [ "▁1949", -11.344529151916504 ], [ "▁年収", -11.344820976257324 ], [ "▁裸", -11.34487247467041 ], [ "▁神様", -11.344989776611328 ], [ "▁税金", -11.344990730285645 ], [ "▁前線", -11.345267295837402 ], [ "▁RE", -11.345398902893066 ], [ "▁時々", -11.345398902893066 ], [ "▁方言", -11.345568656921387 ], [ "▁大宮", -11.345573425292969 ], [ "▁振る", -11.345877647399902 ], [ "▁1946", -11.3458833694458 ], [ "▁援", -11.346023559570312 ], [ "▁食材", -11.346176147460938 ], [ "▁賢", -11.346182823181152 ], [ "▁参入", -11.346189498901367 ], [ "▁師事", -11.346353530883789 ], [ "▁自然に", -11.346444129943848 ], [ "▁さいたま", -11.346555709838867 ], [ "輝", -11.346749305725098 ], [ "なし", -11.346778869628906 ], [ "▁通学", -11.346781730651855 ], [ "▁処刑", -11.346783638000488 ], [ "▁ごう", -11.347029685974121 ], [ "神奈川", -11.34721851348877 ], [ "▁ストップ", -11.34731388092041 ], [ "▁配備", -11.347322463989258 ], [ "元々", -11.347428321838379 ], [ "▁デル", -11.347893714904785 ], [ "▁朱", -11.348068237304688 ], [ "イー", -11.348094940185547 ], [ "米国", -11.348116874694824 ], [ "▁チョコレート", -11.348447799682617 ], [ "ロック", -11.348575592041016 ], [ "▁ウル", -11.348711967468262 ], [ "▁炉", -11.348762512207031 ], [ "▁ウィーン", -11.348930358886719 ], [ "▁マネー", -11.349210739135742 ], [ "▁一時的に", -11.349344253540039 ], [ "▁原題", -11.349353790283203 ], [ "茂", -11.349411010742188 ], [ "▁十字", -11.349639892578125 ], [ "▁荘", -11.349878311157227 ], [ "とても", -11.350150108337402 ], [ "▁Be", -11.350240707397461 ], [ "厚", -11.350362777709961 ], [ "ey", -11.350406646728516 ], [ "▁織田", -11.350552558898926 ], [ "▁​", -11.350791931152344 ], [ "▁An", -11.350905418395996 ], [ "▁太田", -11.351000785827637 ], [ "脇", -11.351354598999023 ], [ "▁糖", -11.351433753967285 ], [ "▁ドクター", -11.351466178894043 ], [ "▁厳しく", -11.351561546325684 ], [ "うち", -11.351628303527832 ], [ "ペット", -11.351853370666504 ], [ "▁薬物", -11.351940155029297 ], [ "▁mi", -11.351956367492676 ], [ "▁表紙", -11.352012634277344 ], [ "▁回って", -11.35215950012207 ], [ "▁施策", -11.352235794067383 ], [ "椎", -11.352279663085938 ], [ "▁140", -11.35239315032959 ], [ "▁CG", -11.35241413116455 ], [ "▁触れる", -11.3524751663208 ], [ "袋", -11.352651596069336 ], [ "▁エージェント", -11.353012084960938 ], [ "▁置き換え", -11.35302734375 ], [ "▁宣", -11.353174209594727 ], [ "ーヌ", -11.353299140930176 ], [ "▁派生", -11.353357315063477 ], [ "俺", -11.353384017944336 ], [ "異", -11.353407859802246 ], [ "イベント", -11.353802680969238 ], [ "超", -11.353889465332031 ], [ "▁工芸", -11.353912353515625 ], [ "▁禍", -11.353997230529785 ], [ "▁日付", -11.354031562805176 ], [ "▁減って", -11.354117393493652 ], [ "▁BL", -11.354287147521973 ], [ "いい", -11.354822158813477 ], [ "▁質量", -11.355236053466797 ], [ "▁航海", -11.355384826660156 ], [ "ug", -11.355619430541992 ], [ "娘", -11.355775833129883 ], [ "皆様", -11.355876922607422 ], [ "▁戦力", -11.356178283691406 ], [ "使用", -11.356258392333984 ], [ "過", -11.356328010559082 ], [ "▁TR", -11.35645580291748 ], [ "AM", -11.356547355651855 ], [ "ぼう", -11.356629371643066 ], [ "▁踊り", -11.356727600097656 ], [ "700", -11.356792449951172 ], [ "▁東海道", -11.356890678405762 ], [ "強い", -11.356956481933594 ], [ "▁アウター", -11.357093811035156 ], [ "中央", -11.357128143310547 ], [ "▁1955", -11.357226371765137 ], [ "▁併設", -11.357275009155273 ], [ "▁集会", -11.357596397399902 ], [ "▁脅威", -11.357720375061035 ], [ "▁ちゅう", -11.358174324035645 ], [ "▁シンプルな", -11.358179092407227 ], [ "▁漁", -11.35832691192627 ], [ "▁武将", -11.358410835266113 ], [ "▁代わって", -11.358453750610352 ], [ "▁見れば", -11.358464241027832 ], [ "▁寿", -11.3588228225708 ], [ "▁ray", -11.359000205993652 ], [ "右衛門", -11.359084129333496 ], [ "態", -11.359150886535645 ], [ "▁アクティブ", -11.359396934509277 ], [ "▁要する", -11.359589576721191 ], [ "添", -11.359638214111328 ], [ "▁ぜ", -11.359756469726562 ], [ "テス", -11.359969139099121 ], [ "▁予報", -11.360020637512207 ], [ "▁外側", -11.360222816467285 ], [ "▁完結", -11.360563278198242 ], [ "▁スピーカー", -11.36075496673584 ], [ "ys", -11.36102294921875 ], [ "▁維新", -11.361058235168457 ], [ "▁ニー", -11.361201286315918 ], [ "▁痛い", -11.36130428314209 ], [ "▁土曜", -11.361458778381348 ], [ "▁大好き", -11.361858367919922 ], [ "▁正義", -11.361873626708984 ], [ "出して", -11.361889839172363 ], [ "▁保全", -11.362051963806152 ], [ "▁否", -11.362258911132812 ], [ "▁ウェイ", -11.362319946289062 ], [ "▁重ねて", -11.362327575683594 ], [ "警", -11.362360954284668 ], [ "なる", -11.362467765808105 ], [ "▁頑張り", -11.362488746643066 ], [ "▁衆", -11.362492561340332 ], [ "アナ", -11.362637519836426 ], [ "ぇ", -11.362712860107422 ], [ "▁バックアップ", -11.362859725952148 ], [ "評議", -11.362960815429688 ], [ "▁アンダー", -11.363035202026367 ], [ "▁復元", -11.363086700439453 ], [ "▁峠", -11.363121032714844 ], [ "▁教養", -11.363147735595703 ], [ "▁独自", -11.36318302154541 ], [ "▁展望", -11.363189697265625 ], [ "果", -11.363245010375977 ], [ "功", -11.36369800567627 ], [ "句", -11.363713264465332 ], [ "▁1956", -11.363763809204102 ], [ "▁隠し", -11.36382007598877 ], [ "▁給", -11.363970756530762 ], [ "杉", -11.36409854888916 ], [ "▁蓮", -11.364133834838867 ], [ "IE", -11.364386558532715 ], [ "▁コミックス", -11.364822387695312 ], [ "▁死んで", -11.364840507507324 ], [ "▁やり取り", -11.364850997924805 ], [ "▁パーセント", -11.364934921264648 ], [ "▁ドライ", -11.365094184875488 ], [ "▁たま", -11.365121841430664 ], [ "▁Th", -11.365242958068848 ], [ "▁達した", -11.365259170532227 ], [ "▁錠", -11.365274429321289 ], [ "▁読売", -11.365394592285156 ], [ "投稿", -11.365428924560547 ], [ "▁身分", -11.365547180175781 ], [ "タイトル", -11.365589141845703 ], [ "▁ジェット", -11.365608215332031 ], [ "▁関わって", -11.365958213806152 ], [ "▁間違って", -11.366086959838867 ], [ "▁VR", -11.36613655090332 ], [ "▁送った", -11.36618423461914 ], [ "1987", -11.366327285766602 ], [ "坊", -11.366374969482422 ], [ "▁パーソナリティ", -11.366392135620117 ], [ "▁指数", -11.366482734680176 ], [ "タリ", -11.366554260253906 ], [ "▁歌い", -11.366826057434082 ], [ "▁復", -11.366987228393555 ], [ "▁綾", -11.367074966430664 ], [ "▁発注", -11.367340087890625 ], [ "監督", -11.367361068725586 ], [ "▁驚く", -11.367505073547363 ], [ "▁スカ", -11.367520332336426 ], [ ";", -11.367546081542969 ], [ "▁サム", -11.367730140686035 ], [ "▁癌", -11.367758750915527 ], [ "翌年", -11.368062973022461 ], [ "教育", -11.368088722229004 ], [ "▁安全に", -11.368107795715332 ], [ "▁造り", -11.368128776550293 ], [ "ng", -11.368326187133789 ], [ "▁リクエスト", -11.36856746673584 ], [ "▁薄い", -11.36866569519043 ], [ "千葉", -11.36867618560791 ], [ "▁メタ", -11.368746757507324 ], [ "▁コラボレーション", -11.369024276733398 ], [ "▁軽い", -11.369091033935547 ], [ "▁無人", -11.369128227233887 ], [ "▁ランプ", -11.36913013458252 ], [ "RA", -11.36916446685791 ], [ "▁続", -11.369226455688477 ], [ "▁ヒント", -11.369351387023926 ], [ "▁面白", -11.369452476501465 ], [ "▁ファンタジー", -11.369495391845703 ], [ "▁敏", -11.36989688873291 ], [ "再", -11.369994163513184 ], [ "▁遊んで", -11.370100975036621 ], [ "▁走", -11.370369911193848 ], [ "▁休暇", -11.37048053741455 ], [ "▁岡田", -11.370655059814453 ], [ "▁一生", -11.370814323425293 ], [ "▁正直", -11.370885848999023 ], [ "▁相対", -11.370927810668945 ], [ "▁キャッチ", -11.371609687805176 ], [ "▁サプリメント", -11.37176513671875 ], [ "存", -11.37182903289795 ], [ "▁高まり", -11.371981620788574 ], [ "▁sh", -11.372234344482422 ], [ "▁旅館", -11.372458457946777 ], [ "▁食堂", -11.37263298034668 ], [ "▁カロリー", -11.372726440429688 ], [ "▁小児", -11.372759819030762 ], [ "▁発想", -11.372878074645996 ], [ "▁ノルウェー", -11.372900009155273 ], [ "▁大事に", -11.373027801513672 ], [ "▁簡易", -11.373116493225098 ], [ "▁明け", -11.373148918151855 ], [ "ロール", -11.373161315917969 ], [ "康", -11.373333930969238 ], [ "▁スムーズに", -11.373434066772461 ], [ "sh", -11.373534202575684 ], [ "▁利点", -11.373557090759277 ], [ "▁社名", -11.373580932617188 ], [ "▁通話", -11.373645782470703 ], [ "▁インフラ", -11.373826026916504 ], [ "▁たとえば", -11.374016761779785 ], [ "▁タバコ", -11.374128341674805 ], [ "▁1943", -11.374295234680176 ], [ "▁なんで", -11.374680519104004 ], [ "▁登記", -11.374687194824219 ], [ "▁含み", -11.37474250793457 ], [ "アラ", -11.37476921081543 ], [ "▁優しく", -11.374796867370605 ], [ "▁コンクール", -11.374865531921387 ], [ "▁市販", -11.374872207641602 ], [ "▁店員", -11.374967575073242 ], [ "▁転送", -11.374981880187988 ], [ "▁一層", -11.375066757202148 ], [ "[[", -11.375114440917969 ], [ "UR", -11.375125885009766 ], [ "復", -11.375174522399902 ], [ "▁フランク", -11.375175476074219 ], [ "▁辺り", -11.375176429748535 ], [ "▁僧", -11.3751859664917 ], [ "▁捉え", -11.375356674194336 ], [ "ure", -11.375386238098145 ], [ "名古屋", -11.375422477722168 ], [ "かな", -11.375495910644531 ], [ "▁当たって", -11.375606536865234 ], [ "▁任じ", -11.375614166259766 ], [ "▁no", -11.375897407531738 ], [ "どんな", -11.375904083251953 ], [ "▁順番", -11.375988960266113 ], [ "▁拓", -11.376008033752441 ], [ "ージ", -11.37602710723877 ], [ "▁立てて", -11.37603759765625 ], [ "▁営", -11.376338958740234 ], [ "カード", -11.37636947631836 ], [ "もり", -11.376874923706055 ], [ "▁CH", -11.376956939697266 ], [ "ong", -11.377039909362793 ], [ "ピア", -11.37723159790039 ], [ "▁1941", -11.377279281616211 ], [ "▁79", -11.377466201782227 ], [ "▁法学", -11.377822875976562 ], [ "▁教皇", -11.377859115600586 ], [ "群", -11.377963066101074 ], [ "▁快適な", -11.378113746643066 ], [ "▁金銭", -11.378114700317383 ], [ "仙", -11.37812328338623 ], [ "防", -11.378327369689941 ], [ "▁THR", -11.378715515136719 ], [ "▁大橋", -11.378751754760742 ], [ "▁チャールズ", -11.378766059875488 ], [ "ib", -11.379109382629395 ], [ "▁フィナステリ", -11.379110336303711 ], [ "▁歌って", -11.379213333129883 ], [ "▁ないし", -11.379425048828125 ], [ "シカ", -11.379566192626953 ], [ "▁キャッシング", -11.379781723022461 ], [ "豆", -11.379894256591797 ], [ "しかった", -11.3799467086792 ], [ "▁シミュレーション", -11.380035400390625 ], [ "ペル", -11.380061149597168 ], [ "ウィン", -11.380120277404785 ], [ "▁地獄", -11.380319595336914 ], [ "▁まつり", -11.380362510681152 ], [ "▁外出", -11.38058853149414 ], [ "▁分かった", -11.380825996398926 ], [ "▁大隊", -11.380863189697266 ], [ "ビット", -11.38097858428955 ], [ "▁腐", -11.381110191345215 ], [ "▁実習", -11.381326675415039 ], [ "▁変遷", -11.38154411315918 ], [ "▁死者", -11.381573677062988 ], [ "ga", -11.381750106811523 ], [ "▁ドコモ", -11.381848335266113 ], [ "▁センサー", -11.381864547729492 ], [ "▁ブー", -11.381866455078125 ], [ "▁泣き", -11.381948471069336 ], [ "従来", -11.381952285766602 ], [ "▁引っ越し", -11.38197135925293 ], [ "iv", -11.382162094116211 ], [ "▁Music", -11.38217830657959 ], [ "▁ディー", -11.382359504699707 ], [ "▁応", -11.382466316223145 ], [ "文化", -11.382533073425293 ], [ "ツィ", -11.382761001586914 ], [ "▁破損", -11.38283634185791 ], [ "▁動かす", -11.382902145385742 ], [ "▁アルミ", -11.382905006408691 ], [ "オール", -11.382916450500488 ], [ "▁ワークス", -11.383146286010742 ], [ "ke", -11.383462905883789 ], [ "▁1942", -11.383649826049805 ], [ "▁跡地", -11.38370418548584 ], [ "▁本番", -11.383882522583008 ], [ "▁一言", -11.383973121643066 ], [ "どこ", -11.384206771850586 ], [ "▁当地", -11.384252548217773 ], [ "▁改め", -11.384307861328125 ], [ "▁リサーチ", -11.384371757507324 ], [ "斗", -11.384398460388184 ], [ "オリ", -11.384517669677734 ], [ "▁従い", -11.384676933288574 ], [ "▁幸せに", -11.384804725646973 ], [ "▁保安", -11.384843826293945 ], [ "▁付いた", -11.384897232055664 ], [ "▁ハーフ", -11.385117530822754 ], [ "ヶ", -11.385180473327637 ], [ "▁〔", -11.385435104370117 ], [ "▁マックス", -11.385468482971191 ], [ "▁血圧", -11.385557174682617 ], [ "▁負荷", -11.385584831237793 ], [ "▁反射", -11.385669708251953 ], [ "▁フラワー", -11.385709762573242 ], [ "▁AT", -11.385724067687988 ], [ "▁宜しく", -11.385740280151367 ], [ "▁少将", -11.385747909545898 ], [ "どちら", -11.385842323303223 ], [ "▁北米", -11.385897636413574 ], [ "▁Store", -11.386024475097656 ], [ "▁ゆき", -11.386122703552246 ], [ "▁余儀な", -11.386151313781738 ], [ "▁審", -11.386201858520508 ], [ "▁切る", -11.386321067810059 ], [ "▁功", -11.386373519897461 ], [ "ミュ", -11.38637924194336 ], [ "▁SD", -11.386445999145508 ], [ "趣味", -11.386474609375 ], [ "テック", -11.386545181274414 ], [ "ケイ", -11.386573791503906 ], [ "▁For", -11.3866605758667 ], [ "▁動か", -11.38677978515625 ], [ "▁コンサルティング", -11.386935234069824 ], [ "▁GO", -11.387088775634766 ], [ "▁あて", -11.3871431350708 ], [ "▁パル", -11.387340545654297 ], [ "▁車種", -11.387614250183105 ], [ "▁学問", -11.387870788574219 ], [ "▁退任", -11.387969017028809 ], [ "▁1952", -11.388185501098633 ], [ "▁症候", -11.388313293457031 ], [ "▁団地", -11.388446807861328 ], [ "▁ストレート", -11.388608932495117 ], [ "裁", -11.388666152954102 ], [ "▁メタル", -11.38874340057373 ], [ "▁優れて", -11.388877868652344 ], [ "▁テキサス", -11.389604568481445 ], [ "▁浮", -11.389726638793945 ], [ "▁数え", -11.389790534973145 ], [ "ウェル", -11.389854431152344 ], [ "試合", -11.389942169189453 ], [ "▁そちら", -11.390044212341309 ], [ "▁思わず", -11.390047073364258 ], [ "▁セルフ", -11.390227317810059 ], [ "粉", -11.390572547912598 ], [ "▁ウェ", -11.390772819519043 ], [ "エス", -11.390857696533203 ], [ "▁義塾", -11.39102840423584 ], [ "▁たまに", -11.391061782836914 ], [ "▁巣", -11.39116382598877 ], [ "LO", -11.391298294067383 ], [ "▁覚悟", -11.391361236572266 ], [ "▁構え", -11.391495704650879 ], [ "▁着手", -11.391719818115234 ], [ "ポー", -11.391880989074707 ], [ "まい", -11.392142295837402 ], [ "公式", -11.392251968383789 ], [ "横", -11.392486572265625 ], [ "▁高山", -11.392518997192383 ], [ "▁計測", -11.392745971679688 ], [ "▁ごはん", -11.392804145812988 ], [ "▁調教", -11.392866134643555 ], [ "▁佳", -11.392877578735352 ], [ "▁シリア", -11.392888069152832 ], [ "テーション", -11.392898559570312 ], [ "▁騒動", -11.392924308776855 ], [ "▁糖尿", -11.392956733703613 ], [ "▁幸福", -11.39303970336914 ], [ "▁取り入れ", -11.39321231842041 ], [ "▁グレイ", -11.39331340789795 ], [ "▁許諾", -11.393343925476074 ], [ "▁神学", -11.393364906311035 ], [ "▁さすが", -11.393399238586426 ], [ "もともと", -11.39380168914795 ], [ "▁指標", -11.39383316040039 ], [ "▁全長", -11.394052505493164 ], [ "▁狙い", -11.39407730102539 ], [ "▁対決", -11.394083976745605 ], [ "▁直径", -11.394116401672363 ], [ "bo", -11.39417552947998 ], [ "▁獣", -11.394224166870117 ], [ "▁班", -11.394392967224121 ], [ "▁助成", -11.394437789916992 ], [ "▁騎乗", -11.394556045532227 ], [ "▁ニュージーランド", -11.394590377807617 ], [ "▁自然の", -11.3945951461792 ], [ "▁使", -11.39501953125 ], [ "▁前方", -11.395659446716309 ], [ "ロード", -11.396112442016602 ], [ "▁うどん", -11.396172523498535 ], [ "向き", -11.396605491638184 ], [ "▁カナダグース", -11.396750450134277 ], [ "▁ニッポン", -11.39693832397461 ], [ "ner", -11.397146224975586 ], [ "サル", -11.397250175476074 ], [ "ten", -11.39733600616455 ], [ "▁制覇", -11.397369384765625 ], [ "RP", -11.397405624389648 ], [ "庫", -11.397489547729492 ], [ "▁ねえ", -11.397672653198242 ], [ "▁株価", -11.397697448730469 ], [ "KO", -11.39783763885498 ], [ "塔", -11.3978853225708 ], [ "トス", -11.397918701171875 ], [ "▁所長", -11.398212432861328 ], [ "▁話した", -11.398279190063477 ], [ "▁市営", -11.398282051086426 ], [ "▁宇都宮", -11.398306846618652 ], [ "▁返事", -11.398462295532227 ], [ "▁いつか", -11.398660659790039 ], [ "▁年始", -11.398733139038086 ], [ "▁結んで", -11.398909568786621 ], [ "リオン", -11.398958206176758 ], [ "▁bit", -11.399029731750488 ], [ "ca", -11.399153709411621 ], [ "▁あげた", -11.399530410766602 ], [ "▁起こして", -11.399611473083496 ], [ "▁商人", -11.399667739868164 ], [ "▁変身", -11.399801254272461 ], [ "貞", -11.40023422241211 ], [ "▁瀬戸", -11.400350570678711 ], [ "みんな", -11.400351524353027 ], [ "なか", -11.400411605834961 ], [ "▁SO", -11.40064525604248 ], [ "▁慣れて", -11.400846481323242 ], [ "▁始まって", -11.400975227355957 ], [ "▁Wi", -11.401020050048828 ], [ "▁遭遇", -11.4010648727417 ], [ "▁グル", -11.401191711425781 ], [ "tor", -11.401289939880371 ], [ "▁東方", -11.401378631591797 ], [ "▁流出", -11.401449203491211 ], [ "▁訴え", -11.401565551757812 ], [ "day", -11.401707649230957 ], [ "▁アルゼンチン", -11.40173625946045 ], [ "1986", -11.401762008666992 ], [ "▁水着", -11.401846885681152 ], [ "▁ローズ", -11.401937484741211 ], [ "▁硬", -11.401998519897461 ], [ "▁竣工", -11.40201473236084 ], [ "▁校長", -11.402057647705078 ], [ "▁ニット", -11.402103424072266 ], [ "▁マジ", -11.402178764343262 ], [ "▁秘書", -11.402276992797852 ], [ "パラ", -11.402348518371582 ], [ "いで", -11.402623176574707 ], [ "▁校舎", -11.402649879455566 ], [ "▁弓", -11.402664184570312 ], [ "▁意欲", -11.402665138244629 ], [ "▁マスコミ", -11.40276050567627 ], [ "ノス", -11.402934074401855 ], [ "▁マリー", -11.402961730957031 ], [ "▁田舎", -11.403072357177734 ], [ "ヨー", -11.403209686279297 ], [ "▁行使", -11.403544425964355 ], [ "値", -11.40357494354248 ], [ "すなわち", -11.403916358947754 ], [ "▁小倉", -11.404197692871094 ], [ "丘", -11.404438972473145 ], [ "▁識別", -11.404500007629395 ], [ "▁将棋", -11.404692649841309 ], [ "▁本土", -11.404706001281738 ], [ "▁信託", -11.404953002929688 ], [ "▁じょう", -11.405210494995117 ], [ "▁NA", -11.405220985412598 ], [ "当日", -11.405266761779785 ], [ "▁上流", -11.40537166595459 ], [ "▁シェル", -11.405394554138184 ], [ "▁建立", -11.405462265014648 ], [ "▁元気に", -11.405537605285645 ], [ "▁こなし", -11.405577659606934 ], [ "▁太郎", -11.406081199645996 ], [ "▁困難な", -11.406103134155273 ], [ "ni", -11.40626049041748 ], [ "▁運航", -11.406319618225098 ], [ "▁ラベル", -11.40637493133545 ], [ "▁ハンドル", -11.406388282775879 ], [ "ホー", -11.406521797180176 ], [ "▁助教授", -11.40673542022705 ], [ "ロシア", -11.406820297241211 ], [ "▁投与", -11.406901359558105 ], [ "▁エクスプレス", -11.407047271728516 ], [ "▁古くから", -11.407060623168945 ], [ "あい", -11.40736198425293 ], [ "▁プレーヤー", -11.407722473144531 ], [ "▁載って", -11.40794849395752 ], [ "▁カンパニー", -11.408126831054688 ], [ "シオ", -11.408188819885254 ], [ "▁クー", -11.408294677734375 ], [ "▁困り", -11.408424377441406 ], [ "ブン", -11.408482551574707 ], [ "▁シール", -11.408538818359375 ], [ "▁ラップ", -11.408620834350586 ], [ "▁清掃", -11.408727645874023 ], [ "▁内蔵", -11.408771514892578 ], [ "ミア", -11.408785820007324 ], [ "▁うれしい", -11.408795356750488 ], [ "さま", -11.40926456451416 ], [ "▁村上", -11.409411430358887 ], [ "▁がちな", -11.40942096710205 ], [ "▁マグ", -11.40942668914795 ], [ "ヤー", -11.409429550170898 ], [ "オンライン", -11.409444808959961 ], [ "▁1954", -11.409529685974121 ], [ "LS", -11.409579277038574 ], [ "▁んで", -11.41018009185791 ], [ "んじ", -11.41019058227539 ], [ "vi", -11.410204887390137 ], [ "▁憧れ", -11.410218238830566 ], [ "▁動いて", -11.410261154174805 ], [ "▁主役", -11.41037368774414 ], [ "▁互換", -11.410659790039062 ], [ "キア", -11.410689353942871 ], [ "央", -11.410744667053223 ], [ "地元", -11.410895347595215 ], [ "▁Mo", -11.411443710327148 ], [ "▁失点", -11.411662101745605 ], [ "つか", -11.411676406860352 ], [ "▁敏感", -11.41174602508545 ], [ "▁足利", -11.411750793457031 ], [ "街", -11.411890983581543 ], [ "▁Ver", -11.411928176879883 ], [ "▁翔", -11.41198444366455 ], [ "▁甲斐", -11.41209888458252 ], [ "▁熊", -11.412135124206543 ], [ "▁さらなる", -11.41220474243164 ], [ "▁過ごした", -11.412378311157227 ], [ "▁商工", -11.41249942779541 ], [ "▁冒頭", -11.412616729736328 ], [ "▁付けた", -11.412681579589844 ], [ "ail", -11.4127197265625 ], [ "▁ハッピー", -11.412813186645508 ], [ "▁平方", -11.412860870361328 ], [ "NN", -11.4130220413208 ], [ "▁ああ", -11.413052558898926 ], [ "頼", -11.413110733032227 ], [ "登場", -11.413420677185059 ], [ "統", -11.413704872131348 ], [ "ran", -11.41370964050293 ], [ "▁甲子園", -11.413908958435059 ], [ "▁ファイ", -11.414006233215332 ], [ "▁ベンチ", -11.414016723632812 ], [ "▁処方", -11.414082527160645 ], [ "▁誤解", -11.414111137390137 ], [ "料", -11.414300918579102 ], [ "▁橋本", -11.414326667785645 ], [ "▁CPU", -11.41440486907959 ], [ "▁黒人", -11.4144926071167 ], [ "▁分泌", -11.414684295654297 ], [ "伊", -11.414831161499023 ], [ "▁聖堂", -11.414849281311035 ], [ "▁念", -11.414867401123047 ], [ "▁コンサルタント", -11.414924621582031 ], [ "▁家事", -11.415096282958984 ], [ "割", -11.415202140808105 ], [ "泊", -11.41528606414795 ], [ "▁発覚", -11.415397644042969 ], [ "▁美しく", -11.41555404663086 ], [ "▁ホールディングス", -11.415566444396973 ], [ "ジア", -11.415828704833984 ], [ "価格", -11.415919303894043 ], [ "▁射撃", -11.41617488861084 ], [ "▁カスタム", -11.4163236618042 ], [ "参考", -11.41636848449707 ], [ "▁旭", -11.416481971740723 ], [ "▁Car", -11.416759490966797 ], [ "gu", -11.417009353637695 ], [ "本書", -11.417030334472656 ], [ "企業", -11.417064666748047 ], [ "▁落語", -11.417299270629883 ], [ "判", -11.417342185974121 ], [ "▁返す", -11.417496681213379 ], [ "▁大気", -11.417645454406738 ], [ "▁修道院", -11.41768741607666 ], [ "容", -11.417750358581543 ], [ "▁保湿", -11.417784690856934 ], [ "剣", -11.417859077453613 ], [ "▁学んで", -11.418168067932129 ], [ "▁ワード", -11.418313026428223 ], [ "▁課税", -11.41839599609375 ], [ "▁単なる", -11.41882038116455 ], [ "▁やってきた", -11.418837547302246 ], [ "SS", -11.418901443481445 ], [ "▁—", -11.419100761413574 ], [ "▁1957", -11.419105529785156 ], [ "1985", -11.419282913208008 ], [ "▁司教", -11.41952133178711 ], [ "孝", -11.419660568237305 ], [ "▁ホル", -11.419896125793457 ], [ "やはり", -11.420040130615234 ], [ "▁謝罪", -11.42007827758789 ], [ "概", -11.420127868652344 ], [ "自然", -11.420376777648926 ], [ "▁覚", -11.420547485351562 ], [ "▁ペーパー", -11.420555114746094 ], [ "▁考案", -11.420562744140625 ], [ "まぁ", -11.420564651489258 ], [ "▁配達", -11.420698165893555 ], [ "▁抱き", -11.420763969421387 ], [ "▁滑", -11.420876502990723 ], [ "▁捕虜", -11.420933723449707 ], [ "増", -11.420968055725098 ], [ "▁皿", -11.420990943908691 ], [ "▁news", -11.42126178741455 ], [ "▁債権", -11.421361923217773 ], [ "ーバー", -11.421370506286621 ], [ "Copyright", -11.421630859375 ], [ "▁警告", -11.421899795532227 ], [ "▁Mi", -11.421966552734375 ], [ "▁ブース", -11.421993255615234 ], [ "▁尽力", -11.422223091125488 ], [ "▁経費", -11.422259330749512 ], [ "相手", -11.42244815826416 ], [ "▁珍しく", -11.422464370727539 ], [ "▁任期", -11.422500610351562 ], [ "▁届か", -11.422502517700195 ], [ "▁改訂", -11.422605514526367 ], [ "▁虎", -11.422914505004883 ], [ "▁an", -11.422989845275879 ], [ "▁空き", -11.423002243041992 ], [ "▁ウェブサイト", -11.423276901245117 ], [ "▁ノース", -11.423323631286621 ], [ "▁綱", -11.423823356628418 ], [ "痛", -11.42383098602295 ], [ "▁決算", -11.423860549926758 ], [ "▁媒体", -11.424056053161621 ], [ "シップ", -11.424215316772461 ], [ "▁バレーボール", -11.424388885498047 ], [ "▁借りて", -11.424407005310059 ], [ "ムシ", -11.424615859985352 ], [ "▁篇", -11.424661636352539 ], [ "▁美女", -11.424755096435547 ], [ "▁JP", -11.424763679504395 ], [ "▁TOP", -11.424906730651855 ], [ "パル", -11.424994468688965 ], [ "▁満た", -11.42509651184082 ], [ "DI", -11.425337791442871 ], [ "残", -11.425359725952148 ], [ "▁嫌い", -11.425457000732422 ], [ "▁猿", -11.425786018371582 ], [ "▁菅", -11.425838470458984 ], [ "▁天候", -11.425918579101562 ], [ "遺", -11.425969123840332 ], [ "▁賞金", -11.426149368286133 ], [ "▁一瞬", -11.426199913024902 ], [ "▁受け付けて", -11.426210403442383 ], [ "▁紅葉", -11.426407814025879 ], [ "▁グロ", -11.426443099975586 ], [ "▁化合", -11.426451683044434 ], [ "▁届き", -11.426674842834473 ], [ "かく", -11.42678451538086 ], [ "▁遺体", -11.42680835723877 ], [ "チー", -11.426889419555664 ], [ "▁試", -11.427038192749023 ], [ "▁EU", -11.427284240722656 ], [ "▁ライティング", -11.427324295043945 ], [ "▁露出", -11.427332878112793 ], [ "▁養", -11.427504539489746 ], [ "▁ドリーム", -11.427597999572754 ], [ "宇", -11.427606582641602 ], [ "HO", -11.427706718444824 ], [ "▁管理人", -11.42780590057373 ], [ "やかな", -11.427858352661133 ], [ "▁哲", -11.428213119506836 ], [ "▁ちょう", -11.428243637084961 ], [ "▁せん", -11.428533554077148 ], [ "かけ", -11.428570747375488 ], [ "▁寄", -11.428680419921875 ], [ "為", -11.428802490234375 ], [ "ちゃん", -11.42880630493164 ], [ "ron", -11.428850173950195 ], [ "▁トランプ", -11.428956031799316 ], [ "▁祖", -11.428980827331543 ], [ "▁駆け", -11.429244041442871 ], [ "ロイ", -11.429426193237305 ], [ "際", -11.43009090423584 ], [ "止", -11.430196762084961 ], [ "▁針", -11.430215835571289 ], [ "▁手当", -11.430243492126465 ], [ "▁反省", -11.430634498596191 ], [ "▁あき", -11.43064022064209 ], [ "▁入賞", -11.43065357208252 ], [ "eg", -11.431154251098633 ], [ "肢", -11.431157112121582 ], [ "▁敗れ", -11.431477546691895 ], [ "▁盗", -11.431571960449219 ], [ "ごと", -11.431624412536621 ], [ "▁給付", -11.431774139404297 ], [ "チュー", -11.43195915222168 ], [ "▁一緒", -11.431960105895996 ], [ "▁十二", -11.432129859924316 ], [ "bi", -11.43230152130127 ], [ "▁重点", -11.432514190673828 ], [ "▁意義", -11.432515144348145 ], [ "訴", -11.43276309967041 ], [ "▁寄与", -11.432791709899902 ], [ "▁キュー", -11.432984352111816 ], [ "ジング", -11.433313369750977 ], [ "▁か所", -11.433780670166016 ], [ "▁▽", -11.433856964111328 ], [ "開発", -11.43387222290039 ], [ "▁琉球", -11.434035301208496 ], [ "▁AM", -11.434144020080566 ], [ "▁遅い", -11.434365272521973 ], [ "▁沢", -11.434431076049805 ], [ "▁述べる", -11.434621810913086 ], [ "CM", -11.434635162353516 ], [ "▁シアター", -11.43475341796875 ], [ "▁マジック", -11.434804916381836 ], [ "▁機材", -11.435257911682129 ], [ "▁宮殿", -11.435345649719238 ], [ "▁立った", -11.435406684875488 ], [ "▁水戸", -11.435466766357422 ], [ "▁カジュアル", -11.435511589050293 ], [ "劇", -11.435565948486328 ], [ "▁キム", -11.435860633850098 ], [ "▁国語", -11.436031341552734 ], [ "▁演説", -11.436077117919922 ], [ "▁1953", -11.43608283996582 ], [ "▁優秀な", -11.436412811279297 ], [ "▁ラインナップ", -11.436626434326172 ], [ "▁่", -11.43703842163086 ], [ "▁DM", -11.437117576599121 ], [ "▁れたら", -11.437348365783691 ], [ "▁はずだ", -11.437518119812012 ], [ "▁占めて", -11.437616348266602 ], [ "ブレ", -11.43772029876709 ], [ "▁フラン", -11.437865257263184 ], [ "▁nd", -11.43795108795166 ], [ "▁アクア", -11.438090324401855 ], [ "紅", -11.43809986114502 ], [ "▁癒し", -11.438152313232422 ], [ "▁北条", -11.438213348388672 ], [ "▁達する", -11.438379287719727 ], [ "▁笠", -11.438909530639648 ], [ "▁模型", -11.439062118530273 ], [ "▁MO", -11.439079284667969 ], [ "クタ", -11.439090728759766 ], [ "鬼", -11.439191818237305 ], [ "ージュ", -11.439208984375 ], [ "▁ウッド", -11.439270973205566 ], [ "ヤン", -11.439602851867676 ], [ "▁供", -11.43962574005127 ], [ "▁なき", -11.439651489257812 ], [ "▁1951", -11.439674377441406 ], [ "▁品川", -11.439762115478516 ], [ "SD", -11.439799308776855 ], [ "▁バリ", -11.439959526062012 ], [ "▁パーティ", -11.44002628326416 ], [ "chi", -11.440102577209473 ], [ "▁締め", -11.4401216506958 ], [ "▁比例", -11.440225601196289 ], [ "サイド", -11.440265655517578 ], [ "▁すっかり", -11.440350532531738 ], [ "▁都心", -11.44054126739502 ], [ "▁ウォッチ", -11.440665245056152 ], [ "▁司", -11.440696716308594 ], [ "イラ", -11.440711975097656 ], [ "入り", -11.440834999084473 ], [ "▁造船", -11.44091510772705 ], [ "▁あや", -11.440948486328125 ], [ "診", -11.441038131713867 ], [ "▁安値", -11.441104888916016 ], [ "▁並びに", -11.441181182861328 ], [ "▁天体", -11.441197395324707 ], [ "▁医院", -11.44131851196289 ], [ "▁気づき", -11.441596031188965 ], [ "▁倫理", -11.44163990020752 ], [ "▁ココ", -11.441650390625 ], [ "▁押", -11.44190788269043 ], [ "text", -11.442010879516602 ], [ "▁函館", -11.442079544067383 ], [ "愛知", -11.442183494567871 ], [ "▁ゲー", -11.442276000976562 ], [ "▁駅舎", -11.442293167114258 ], [ "▁豊田", -11.44231128692627 ], [ "▁沈", -11.442403793334961 ], [ "▁通い", -11.442472457885742 ], [ "▁返金", -11.442887306213379 ], [ "前作", -11.442916870117188 ], [ "なぜなら", -11.442956924438477 ], [ "▁佐々木", -11.443012237548828 ], [ "▁申し出", -11.443160057067871 ], [ "▁療養", -11.4431791305542 ], [ "▁液晶", -11.443519592285156 ], [ "バック", -11.443760871887207 ], [ "迫", -11.444022178649902 ], [ "おい", -11.444300651550293 ], [ "▁上回る", -11.444390296936035 ], [ "ロフ", -11.44440746307373 ], [ "▁服用", -11.444425582885742 ], [ "▁則", -11.44460678100586 ], [ "ニカ", -11.444851875305176 ], [ "▁東南", -11.445070266723633 ], [ "▁無事", -11.445085525512695 ], [ "▁牧", -11.445094108581543 ], [ "▁พ", -11.445107460021973 ], [ "らす", -11.445133209228516 ], [ "▁ナチュラル", -11.445391654968262 ], [ "▁乗客", -11.445413589477539 ], [ "▁中旬", -11.445494651794434 ], [ "▁こういった", -11.445549964904785 ], [ "▁賛成", -11.445822715759277 ], [ "▁参り", -11.446430206298828 ], [ "▁液体", -11.446699142456055 ], [ "▁長編", -11.446784019470215 ], [ "チョウ", -11.446939468383789 ], [ "▁役立ち", -11.446961402893066 ], [ "かに", -11.446975708007812 ], [ "▁リサイクル", -11.446981430053711 ], [ "▁協同", -11.447006225585938 ], [ "ータ", -11.44720458984375 ], [ "丁", -11.4472074508667 ], [ "▁‐", -11.447208404541016 ], [ "▁停", -11.447216987609863 ], [ "▁漏れ", -11.447308540344238 ], [ "▁コーポレーション", -11.447415351867676 ], [ "▁受け取る", -11.447484970092773 ], [ "▁メイド", -11.447514533996582 ], [ "▁庁舎", -11.447668075561523 ], [ "▁審判", -11.44820785522461 ], [ "▁もはや", -11.44833755493164 ], [ "▁大衆", -11.448416709899902 ], [ "▁様な", -11.448420524597168 ], [ "▁ex", -11.448577880859375 ], [ "▁起こって", -11.448860168457031 ], [ "▁ウエスト", -11.448873519897461 ], [ "▁土木", -11.448884010314941 ], [ "▁肺", -11.448892593383789 ], [ "▁山陽", -11.448934555053711 ], [ "▁モジュール", -11.44899845123291 ], [ "▁膜", -11.449227333068848 ], [ "▁サンタ", -11.449287414550781 ], [ "▁Chrome", -11.44943904876709 ], [ "▁ニキビ", -11.449625968933105 ], [ "▁違和感", -11.44963550567627 ], [ "略", -11.449637413024902 ], [ "獣", -11.4496431350708 ], [ "▁立てる", -11.449738502502441 ], [ "▁移管", -11.449780464172363 ], [ "ME", -11.4498291015625 ], [ "ニャ", -11.449831008911133 ], [ "▁直通", -11.45028018951416 ], [ "▁視覚", -11.450508117675781 ], [ "▁見つかり", -11.45064640045166 ], [ "害", -11.4507417678833 ], [ "著", -11.450758934020996 ], [ "▁プラスチック", -11.451098442077637 ], [ "▁ガル", -11.451252937316895 ], [ "▁侍", -11.451258659362793 ], [ "▁確信", -11.451297760009766 ], [ "▁冷凍", -11.451411247253418 ], [ "▁ダービー", -11.451414108276367 ], [ "▁当事", -11.451472282409668 ], [ "1950", -11.451741218566895 ], [ "▁ギャル", -11.451803207397461 ], [ "汗", -11.451813697814941 ], [ "ave", -11.452014923095703 ], [ "▁ピーク", -11.45220947265625 ], [ "孫", -11.452329635620117 ], [ "▁シネマ", -11.453264236450195 ], [ "▁菜", -11.453361511230469 ], [ "í", -11.453373908996582 ], [ "▁ミル", -11.45347785949707 ], [ "▁ざ", -11.453484535217285 ], [ "▁入試", -11.45351791381836 ], [ "▁知人", -11.453642845153809 ], [ "▁php", -11.453686714172363 ], [ "▁リチャード", -11.453810691833496 ], [ "ood", -11.454063415527344 ], [ "▁しゃ", -11.454265594482422 ], [ "▁ポー", -11.454301834106445 ], [ "ya", -11.454330444335938 ], [ "▁船団", -11.454333305358887 ], [ "▁ボストン", -11.45440673828125 ], [ "がる", -11.454422950744629 ], [ "▁94", -11.454550743103027 ], [ "▁業種", -11.454789161682129 ], [ "▁家康", -11.45483684539795 ], [ "ial", -11.454984664916992 ], [ "▁スカウト", -11.455307960510254 ], [ "▁DIY", -11.455398559570312 ], [ "LA", -11.455414772033691 ], [ "ヒル", -11.455448150634766 ], [ "▁スケール", -11.455466270446777 ], [ "▁ゲート", -11.455656051635742 ], [ "▁アフィリエイト", -11.455798149108887 ], [ "▁史料", -11.455809593200684 ], [ "▁トレーナー", -11.455867767333984 ], [ "シャル", -11.456049919128418 ], [ "リンク", -11.456182479858398 ], [ "往", -11.456298828125 ], [ "▁淳", -11.45647144317627 ], [ "淵", -11.456689834594727 ], [ "▁巡洋艦", -11.456969261169434 ], [ "レート", -11.457054138183594 ], [ "▁サプリ", -11.457119941711426 ], [ "あれ", -11.457216262817383 ], [ "▁My", -11.457260131835938 ], [ "▁瀬", -11.45732307434082 ], [ "▁詳細な", -11.457378387451172 ], [ "▁上京", -11.457599639892578 ], [ "▁迎えて", -11.45761489868164 ], [ "▁制約", -11.457680702209473 ], [ "▁なんだか", -11.457730293273926 ], [ "▁零", -11.457731246948242 ], [ "▁目撃", -11.457771301269531 ], [ "▁混雑", -11.45815658569336 ], [ "▁キャスター", -11.458158493041992 ], [ "▁終盤", -11.458169937133789 ], [ "TI", -11.45844554901123 ], [ "臭", -11.45846176147461 ], [ "▁グラウンド", -11.458486557006836 ], [ "▁ED", -11.458505630493164 ], [ "▁奇跡", -11.458564758300781 ], [ "▁You", -11.458586692810059 ], [ "ローズ", -11.458626747131348 ], [ "▁実況", -11.458650588989258 ], [ "▁楽に", -11.458725929260254 ], [ "▁アマ", -11.458745002746582 ], [ "▁墓地", -11.45888614654541 ], [ "▁所持", -11.45889949798584 ], [ "▁奏者", -11.458915710449219 ], [ "▁ペイ", -11.458982467651367 ], [ "▁出展", -11.459233283996582 ], [ "▁邦", -11.459407806396484 ], [ "▁越", -11.45947265625 ], [ "DS", -11.459754943847656 ], [ "優", -11.45977783203125 ], [ "▁三島", -11.459870338439941 ], [ "闘", -11.459988594055176 ], [ "▁せよう", -11.460412979125977 ], [ "▁割り当て", -11.460441589355469 ], [ "▁奈", -11.46078872680664 ], [ "▁このまま", -11.460790634155273 ], [ "▁知能", -11.460836410522461 ], [ "▁グラフ", -11.460893630981445 ], [ "▁繰り返す", -11.460953712463379 ], [ "じん", -11.46104907989502 ], [ "思", -11.461212158203125 ], [ "▁降格", -11.461296081542969 ], [ "▁千代田", -11.46136474609375 ], [ "タナ", -11.461578369140625 ], [ "▁整形", -11.461579322814941 ], [ "▁ウィーク", -11.461581230163574 ], [ "▁天国", -11.461612701416016 ], [ "▁種目", -11.461699485778809 ], [ "▁呼んだ", -11.461830139160156 ], [ "▁ボトル", -11.461868286132812 ], [ "▁q", -11.461981773376465 ], [ "▁ゲット", -11.462117195129395 ], [ "▁任意の", -11.462244033813477 ], [ "ef", -11.462371826171875 ], [ "▁歩行", -11.462430000305176 ], [ "▁打者", -11.462525367736816 ], [ "▁Live", -11.462661743164062 ], [ "air", -11.462756156921387 ], [ "ッパ", -11.462839126586914 ], [ "▁セミ", -11.463003158569336 ], [ "▁ノミネート", -11.463067054748535 ], [ "▁尿", -11.4631986618042 ], [ "穴", -11.463567733764648 ], [ "▁権威", -11.463578224182129 ], [ "▁量産", -11.463608741760254 ], [ "▁尊", -11.4636869430542 ], [ "藩", -11.463729858398438 ], [ "ラク", -11.464103698730469 ], [ "▁大島", -11.464130401611328 ], [ "▁累計", -11.464133262634277 ], [ "謀", -11.464160919189453 ], [ "▁中島", -11.464249610900879 ], [ "▁じっくり", -11.464323043823242 ], [ "▁One", -11.464350700378418 ], [ "ブス", -11.46439266204834 ], [ "▁狭", -11.464537620544434 ], [ "▁終結", -11.464553833007812 ], [ "▁市川", -11.464561462402344 ], [ "▁二十", -11.464842796325684 ], [ "▁フルーツ", -11.465165138244629 ], [ "▁AR", -11.465228080749512 ], [ "▁クリス", -11.465394020080566 ], [ "ティン", -11.465470314025879 ], [ "▁柏", -11.465490341186523 ], [ "1984", -11.465599060058594 ], [ "▁改定", -11.465816497802734 ], [ "▁閉", -11.465902328491211 ], [ "▁フィード", -11.46605396270752 ], [ "ence", -11.466092109680176 ], [ "▁堪能", -11.466439247131348 ], [ "バンド", -11.466501235961914 ], [ "▁可能で", -11.466618537902832 ], [ "▁ムービー", -11.466890335083008 ], [ "▁情勢", -11.467082977294922 ], [ "コール", -11.467276573181152 ], [ "ガイ", -11.467399597167969 ], [ "▁シミ", -11.467421531677246 ], [ "1945", -11.46764850616455 ], [ "▁不詳", -11.467669486999512 ], [ "▁添付", -11.467734336853027 ], [ "▁阻止", -11.467851638793945 ], [ "▁農民", -11.467941284179688 ], [ "▁関し", -11.468282699584961 ], [ "▁併せて", -11.468292236328125 ], [ "▁チラシ", -11.468317985534668 ], [ "リーナ", -11.46835708618164 ], [ "▁パイプ", -11.468361854553223 ], [ "▁ニコニコ", -11.468416213989258 ], [ "▁崩れ", -11.469244003295898 ], [ "やがて", -11.469470977783203 ], [ "▁みなさ", -11.46951961517334 ], [ "▁ガラ", -11.470105171203613 ], [ "▁メガ", -11.470157623291016 ], [ "▁暫定", -11.470161437988281 ], [ "好きな", -11.470191955566406 ], [ "▁柔軟", -11.47024154663086 ], [ "▁スタンプ", -11.470470428466797 ], [ "▁架空", -11.470500946044922 ], [ "▁帰宅", -11.470519065856934 ], [ "▁ヴァル", -11.470697402954102 ], [ "▁新品", -11.470747947692871 ], [ "▁適", -11.47080135345459 ], [ "爆", -11.470983505249023 ], [ "がり", -11.471024513244629 ], [ "▁Certified", -11.47106647491455 ], [ "沖縄", -11.47169017791748 ], [ "▁タップ", -11.471949577331543 ], [ "▁コロンビア", -11.472163200378418 ], [ "▁みれば", -11.472254753112793 ], [ "▁共感", -11.47242546081543 ], [ "▁臭い", -11.472522735595703 ], [ "▁願って", -11.472553253173828 ], [ "ost", -11.472565650939941 ], [ "ハウス", -11.472916603088379 ], [ "ens", -11.473211288452148 ], [ "購入", -11.47329330444336 ], [ "▁タイル", -11.473367691040039 ], [ "▁仰", -11.473402976989746 ], [ "▁間隔", -11.473611831665039 ], [ "▁洋服", -11.47368335723877 ], [ "医療", -11.4736909866333 ], [ "▁隊員", -11.473724365234375 ], [ "▁貧困", -11.473841667175293 ], [ "▁復旧", -11.474045753479004 ], [ "▁べ", -11.47431755065918 ], [ "▁期生", -11.474517822265625 ], [ "コック", -11.474666595458984 ], [ "du", -11.475152015686035 ], [ "投", -11.475371360778809 ], [ "低", -11.47545337677002 ], [ "▁共産", -11.475732803344727 ], [ "▁レンジ", -11.475865364074707 ], [ "曜", -11.476044654846191 ], [ "▁伝達", -11.476546287536621 ], [ "SI", -11.476606369018555 ], [ "▁グレ", -11.476688385009766 ], [ "インド", -11.476792335510254 ], [ "▁取扱い", -11.477203369140625 ], [ "▁メガネ", -11.477378845214844 ], [ "▁あさ", -11.47740364074707 ], [ "▁con", -11.477578163146973 ], [ "データ", -11.47779655456543 ], [ "ヴェン", -11.477855682373047 ], [ "▁総裁", -11.478009223937988 ], [ "レース", -11.478068351745605 ], [ "▁闘争", -11.478221893310547 ], [ "ve", -11.478261947631836 ], [ "▁転載", -11.478480339050293 ], [ "▁診察", -11.478503227233887 ], [ "CS", -11.478791236877441 ], [ "▁偽物", -11.479058265686035 ], [ "▁カ国", -11.479063034057617 ], [ "▁ミルク", -11.47907829284668 ], [ "▁置いた", -11.47911262512207 ], [ "▁つながって", -11.479130744934082 ], [ "▁薬局", -11.479218482971191 ], [ "▁南海", -11.479378700256348 ], [ "▁無償", -11.479581832885742 ], [ "したり", -11.480059623718262 ], [ "童", -11.480059623718262 ], [ "▁努めて", -11.480165481567383 ], [ "▁点検", -11.480207443237305 ], [ "▁守って", -11.480239868164062 ], [ "▁レス", -11.480240821838379 ], [ "▁衰退", -11.480271339416504 ], [ "▁解答", -11.480290412902832 ], [ "▁エクス", -11.480306625366211 ], [ "ヴィン", -11.48052978515625 ], [ "▁遠い", -11.481033325195312 ], [ "尊", -11.481078147888184 ], [ "▁前田", -11.481324195861816 ], [ "▁ぽ", -11.48138427734375 ], [ "▁共通の", -11.481447219848633 ], [ "▁綺麗な", -11.481457710266113 ], [ "梨", -11.481464385986328 ], [ "旗", -11.481518745422363 ], [ "腫", -11.48160457611084 ], [ "▁リビング", -11.481660842895508 ], [ "▁現行", -11.482017517089844 ], [ "▁伝えた", -11.482028007507324 ], [ "▁船舶", -11.482056617736816 ], [ "覧", -11.482129096984863 ], [ "▁colspa", -11.482279777526855 ], [ "▁僅か", -11.482285499572754 ], [ "▁断り", -11.482483863830566 ], [ "▁インク", -11.482489585876465 ], [ "▁返還", -11.482617378234863 ], [ "稿", -11.482710838317871 ], [ "▁伝わって", -11.483076095581055 ], [ "▁横須賀", -11.483160972595215 ], [ "▁視野", -11.483186721801758 ], [ "ies", -11.483219146728516 ], [ "▁なくなり", -11.483315467834473 ], [ "談", -11.48334789276123 ], [ "イング", -11.48349380493164 ], [ "▁大将", -11.483663558959961 ], [ "▁云", -11.48367691040039 ], [ "▁炎症", -11.483692169189453 ], [ "ki", -11.48383903503418 ], [ "▁撮", -11.483891487121582 ], [ "脳", -11.48390007019043 ], [ "▁DAY", -11.483925819396973 ], [ "▁悠", -11.484456062316895 ], [ "▁三振", -11.484466552734375 ], [ "▁苦手な", -11.484557151794434 ], [ "▁家督", -11.484755516052246 ], [ "▁フォント", -11.484807968139648 ], [ "▁観音", -11.485495567321777 ], [ "新型", -11.485552787780762 ], [ "▁大佐", -11.485576629638672 ], [ "▁渡し", -11.485630989074707 ], [ "▁後任", -11.485651016235352 ], [ "▁武士", -11.485671043395996 ], [ "▁風邪", -11.485941886901855 ], [ "▁観て", -11.486027717590332 ], [ "拠", -11.486174583435059 ], [ "▁配属", -11.486248016357422 ], [ "ワール", -11.486307144165039 ], [ "▁副業", -11.486492156982422 ], [ "ナイト", -11.486586570739746 ], [ "トロン", -11.486597061157227 ], [ "イタリア", -11.486602783203125 ], [ "▁ウォー", -11.486795425415039 ], [ "ei", -11.486860275268555 ], [ "ぶり", -11.486964225769043 ], [ "▁加える", -11.487502098083496 ], [ "非", -11.487549781799316 ], [ "▁景観", -11.487639427185059 ], [ "▁ネオ", -11.487810134887695 ], [ "▁対話", -11.487839698791504 ], [ "享年", -11.488120079040527 ], [ "▁会談", -11.488165855407715 ], [ "明日", -11.48826789855957 ], [ "▁ミラノ", -11.488316535949707 ], [ "▁インデックス", -11.488697052001953 ], [ "▁実証", -11.489055633544922 ], [ "▁落ちる", -11.489289283752441 ], [ "持ち", -11.489357948303223 ], [ "▁アリーナ", -11.489428520202637 ], [ "階", -11.489495277404785 ], [ "▁定員", -11.489553451538086 ], [ "▁伊豆", -11.489577293395996 ], [ "▁押す", -11.489845275878906 ], [ "▁日光", -11.4898681640625 ], [ "▁沙", -11.489912033081055 ], [ "▁アラブ", -11.490135192871094 ], [ "婚", -11.490299224853516 ], [ "▁アドバイザー", -11.490367889404297 ], [ "▁芝居", -11.49046802520752 ], [ "なん", -11.490561485290527 ], [ "▁典型", -11.490589141845703 ], [ "▁国務", -11.491047859191895 ], [ "▁当て", -11.491326332092285 ], [ "リヤ", -11.491527557373047 ], [ "ちょう", -11.491802215576172 ], [ "▁勘", -11.491880416870117 ], [ "▁ボリューム", -11.491984367370605 ], [ "▁小野", -11.49262523651123 ], [ "▁バイパス", -11.49272632598877 ], [ "fe", -11.49284839630127 ], [ "皇", -11.492979049682617 ], [ "▁銭", -11.493147850036621 ], [ "▁属性", -11.493273735046387 ], [ "1983", -11.493413925170898 ], [ "▁レーダー", -11.493571281433105 ], [ "▁消えて", -11.493758201599121 ], [ "▁有効な", -11.4938325881958 ], [ "▁出典", -11.494004249572754 ], [ "▁蘭", -11.49400806427002 ], [ "ポイント", -11.494121551513672 ], [ "▁メイト", -11.49436092376709 ], [ "▁介入", -11.494404792785645 ], [ "ヴェル", -11.49445629119873 ], [ "▁シャワー", -11.494697570800781 ], [ "出した", -11.494721412658691 ], [ "えん", -11.494854927062988 ], [ "▁付加", -11.49496841430664 ], [ "▁ユニ", -11.494991302490234 ], [ "▁メー", -11.495055198669434 ], [ "宅", -11.495085716247559 ], [ "吹", -11.495285034179688 ], [ "▁聴いて", -11.49545955657959 ], [ "▁運賃", -11.495465278625488 ], [ "キャスト", -11.495552062988281 ], [ "▁なされた", -11.495631217956543 ], [ "▁岡崎", -11.495656967163086 ], [ "yn", -11.495689392089844 ], [ "MI", -11.495716094970703 ], [ "▁出口", -11.49575138092041 ], [ "▁敗戦", -11.495770454406738 ], [ "▁吉野", -11.49606704711914 ], [ "哉", -11.496081352233887 ], [ "▁大勢", -11.496500015258789 ], [ "審", -11.496522903442383 ], [ "land", -11.496573448181152 ], [ "ord", -11.49658203125 ], [ "▁密着", -11.496692657470703 ], [ "▁塁", -11.496767044067383 ], [ "仲", -11.496803283691406 ], [ "▁引く", -11.496807098388672 ], [ "▁中川", -11.4970121383667 ], [ "ov", -11.497051239013672 ], [ "▁ラリー", -11.497076034545898 ], [ "▁セン", -11.497106552124023 ], [ "▁デス", -11.497183799743652 ], [ "▁介して", -11.4974946975708 ], [ "▁戦術", -11.497584342956543 ], [ "▁見えた", -11.497678756713867 ], [ "糖", -11.49769401550293 ], [ "▁ピーター", -11.497828483581543 ], [ "▁ウィンドウ", -11.497928619384766 ], [ "箱", -11.497980117797852 ], [ "▁手元", -11.498202323913574 ], [ "▁容器", -11.49820327758789 ], [ "おり", -11.49832534790039 ], [ "▁呼びかけ", -11.498434066772461 ], [ "▁ล", -11.498531341552734 ], [ "▁アリス", -11.498641014099121 ], [ "▁จ", -11.498677253723145 ], [ "陰", -11.498687744140625 ], [ "▁ヘビー", -11.498696327209473 ], [ "▁ナン", -11.498711585998535 ], [ "tic", -11.499102592468262 ], [ "▁空襲", -11.49936580657959 ], [ "▁君主", -11.499385833740234 ], [ "▁ヘイ", -11.499399185180664 ], [ "▁体型", -11.499505043029785 ], [ "▁誤り", -11.499509811401367 ], [ "▁っ", -11.499588012695312 ], [ "▁鉱山", -11.499661445617676 ], [ "精", -11.499702453613281 ], [ "▁演", -11.499871253967285 ], [ "▁納税", -11.499937057495117 ], [ "▁大野", -11.50009536743164 ], [ "▁フォード", -11.500123977661133 ], [ "▁ちょっとした", -11.500279426574707 ], [ "▁連動", -11.500300407409668 ], [ "▁自覚", -11.500326156616211 ], [ "登", -11.500509262084961 ], [ "▁RPG", -11.500545501708984 ], [ "▁偶然", -11.500731468200684 ], [ "▁物資", -11.500919342041016 ], [ "▁ヘルプ", -11.501097679138184 ], [ "▁ヤード", -11.50147819519043 ], [ "▁隠", -11.501652717590332 ], [ "▁白人", -11.501699447631836 ], [ "はじめ", -11.50170612335205 ], [ "▁閉店", -11.501709938049316 ], [ "ber", -11.501736640930176 ], [ "ラブ", -11.50179386138916 ], [ "▁フォルダ", -11.502446174621582 ], [ "▁埋葬", -11.502496719360352 ], [ "▁解雇", -11.502616882324219 ], [ "免", -11.502649307250977 ], [ "▁尊重", -11.502655982971191 ], [ "▁フォーマット", -11.502673149108887 ], [ "▁喪失", -11.502730369567871 ], [ "▁技法", -11.503057479858398 ], [ "▁経って", -11.503079414367676 ], [ "▁図鑑", -11.503606796264648 ], [ "すぐ", -11.503633499145508 ], [ "▁卿", -11.503634452819824 ], [ "▁ラム", -11.503689765930176 ], [ "▁座って", -11.503877639770508 ], [ "▁含んで", -11.503984451293945 ], [ "▁ドー", -11.504005432128906 ], [ "▁歌劇", -11.504059791564941 ], [ "▁スミス", -11.504076957702637 ], [ "扱って", -11.504130363464355 ], [ "▁高め", -11.504143714904785 ], [ "▁はずの", -11.504301071166992 ], [ "bl", -11.504463195800781 ], [ "▁かわ", -11.504656791687012 ], [ "▁まつ", -11.50483226776123 ], [ "属", -11.504870414733887 ], [ "▁落とし", -11.504887580871582 ], [ "▁OF", -11.504904747009277 ], [ "▁ハンター", -11.504961013793945 ], [ "▁負", -11.504977226257324 ], [ "▁ターン", -11.505025863647461 ], [ "▁認めた", -11.50502872467041 ], [ "▁北方", -11.50521469116211 ], [ "▁接して", -11.505226135253906 ], [ "▁高度な", -11.505352020263672 ], [ "▁缶", -11.505404472351074 ], [ "▁首位", -11.5056734085083 ], [ "災", -11.505751609802246 ], [ "▁ツイン", -11.505813598632812 ], [ "▁最強", -11.505826950073242 ], [ "トレー", -11.505943298339844 ], [ "▁厳", -11.506060600280762 ], [ "FF", -11.506107330322266 ], [ "▁試しに", -11.506125450134277 ], [ "じて", -11.506433486938477 ], [ "従", -11.506464004516602 ], [ "▁入金", -11.506699562072754 ], [ "▁飽き", -11.506880760192871 ], [ "ズム", -11.506932258605957 ], [ "砂", -11.507036209106445 ], [ "▁銘柄", -11.507072448730469 ], [ "▁繰り返して", -11.507253646850586 ], [ "▁奉仕", -11.507593154907227 ], [ "▁焦", -11.507759094238281 ], [ "▁GR", -11.507903099060059 ], [ "▁要塞", -11.507950782775879 ], [ "▁MI", -11.50800895690918 ], [ "▁Play", -11.508352279663086 ], [ "▁でしょ", -11.508479118347168 ], [ "通り", -11.508501052856445 ], [ "腕", -11.508988380432129 ], [ "▁阻害", -11.509172439575195 ], [ "▁Ad", -11.50930118560791 ], [ "▁受容", -11.509661674499512 ], [ "▁サマー", -11.50969123840332 ], [ "▁ラッシュ", -11.509803771972656 ], [ "▁坪", -11.509835243225098 ], [ "▁省略", -11.509923934936523 ], [ "▁記念日", -11.510469436645508 ], [ "ust", -11.510659217834473 ], [ "▁スタン", -11.51078987121582 ], [ "▁笑って", -11.5109281539917 ], [ "▁170", -11.511195182800293 ], [ "▁亮", -11.511321067810059 ], [ "▁伸", -11.511388778686523 ], [ "事業", -11.511474609375 ], [ "▁ソフトバンク", -11.51154613494873 ], [ "▁初日", -11.511724472045898 ], [ "▁祝日", -11.511725425720215 ], [ "ina", -11.512048721313477 ], [ "▁このように", -11.512269020080566 ], [ "▁︎", -11.512386322021484 ], [ "▁荷", -11.512503623962402 ], [ "▁こんにちは", -11.512657165527344 ], [ "廃", -11.512738227844238 ], [ "▁荒れ", -11.512880325317383 ], [ "▁騎兵", -11.512948036193848 ], [ "▁実に", -11.512980461120605 ], [ "mi", -11.513055801391602 ], [ "▁益", -11.513261795043945 ], [ "▁インスタ", -11.51341438293457 ], [ "チャン", -11.513460159301758 ], [ "▁revision", -11.513535499572754 ], [ "▁1939", -11.513721466064453 ], [ "▁Ar", -11.513758659362793 ], [ "▁小売", -11.513937950134277 ], [ "候", -11.514021873474121 ], [ "▁庄", -11.51413631439209 ], [ "ッジ", -11.514163970947266 ], [ "リウム", -11.514749526977539 ], [ "▁キャバ", -11.514764785766602 ], [ "▁撮って", -11.515030860900879 ], [ "立た", -11.515159606933594 ], [ "▁果て", -11.51516342163086 ], [ "▁粗", -11.515830993652344 ], [ "▁奏", -11.515836715698242 ], [ "▁マナー", -11.516169548034668 ], [ "▁広域", -11.516225814819336 ], [ "▁空母", -11.516263961791992 ], [ "▁ほんの", -11.516271591186523 ], [ "▁情熱", -11.516389846801758 ], [ "▁処", -11.516435623168945 ], [ "烈", -11.516469955444336 ], [ "▁失い", -11.516655921936035 ], [ "net", -11.516688346862793 ], [ "磁", -11.51704216003418 ], [ "荷", -11.517106056213379 ], [ "▁今では", -11.51777458190918 ], [ "▁振", -11.51781940460205 ], [ "▁句", -11.517874717712402 ], [ "哀", -11.517900466918945 ], [ "▁砂糖", -11.518102645874023 ], [ "pa", -11.518278121948242 ], [ "姓", -11.518324851989746 ], [ "▁基金", -11.518567085266113 ], [ "▁1200", -11.518847465515137 ], [ "▁上田", -11.518889427185059 ], [ "▁海賊", -11.518915176391602 ], [ "si", -11.519067764282227 ], [ "エロ", -11.519244194030762 ], [ "▁イノベーション", -11.519267082214355 ], [ "▁不能", -11.519529342651367 ], [ "▁台車", -11.519549369812012 ], [ "▁押して", -11.519669532775879 ], [ "▁小川", -11.51969051361084 ], [ "▁ジャーナリスト", -11.519742012023926 ], [ "▁詳細に", -11.519784927368164 ], [ "▁手軽に", -11.519861221313477 ], [ "レク", -11.520003318786621 ], [ "横浜", -11.520184516906738 ], [ "RE", -11.520360946655273 ], [ "震", -11.520512580871582 ], [ "▁交", -11.520538330078125 ], [ "架", -11.520777702331543 ], [ "▁夫妻", -11.520879745483398 ], [ "▁ノベル", -11.521023750305176 ], [ "労", -11.521047592163086 ], [ "▁ミー", -11.521065711975098 ], [ "▁NPO", -11.521130561828613 ], [ "オル", -11.521225929260254 ], [ "^", -11.521415710449219 ], [ "▁▼", -11.521488189697266 ], [ "様々な", -11.522185325622559 ], [ "▁あえて", -11.522257804870605 ], [ "▁ヵ月", -11.522357940673828 ], [ "▁レン", -11.522859573364258 ], [ "▁皇", -11.523118019104004 ], [ "▁青い", -11.523214340209961 ], [ "▁変数", -11.52328109741211 ], [ "▁スリー", -11.523397445678711 ], [ "グレ", -11.52340030670166 ], [ "▁天才", -11.523494720458984 ], [ "▁永久", -11.523499488830566 ], [ "ルン", -11.523547172546387 ], [ "▁べきで", -11.52377986907959 ], [ "▁何故", -11.523786544799805 ], [ "▁App", -11.523823738098145 ], [ "眠", -11.523935317993164 ], [ "▁排", -11.52418327331543 ], [ "▁戦場", -11.524581909179688 ], [ "可", -11.524584770202637 ], [ "▁屋外", -11.524787902832031 ], [ "▁牽引", -11.524861335754395 ], [ "▁随時", -11.525100708007812 ], [ "▁競輪", -11.525365829467773 ], [ "▁目立つ", -11.525591850280762 ], [ "雑", -11.525697708129883 ], [ "▁揃って", -11.5256986618042 ], [ "▁フィルター", -11.525870323181152 ], [ "齢", -11.525877952575684 ], [ "▁方程式", -11.525936126708984 ], [ "▁喫煙", -11.525996208190918 ], [ "▁ようである", -11.526054382324219 ], [ "▁防水", -11.526139259338379 ], [ "▁薄く", -11.526161193847656 ], [ "▁居酒屋", -11.526473999023438 ], [ "▁非常", -11.526585578918457 ], [ "埼玉", -11.526708602905273 ], [ "▁尋ね", -11.526886940002441 ], [ "▁TOKYO", -11.526897430419922 ], [ "▁全額", -11.526933670043945 ], [ "バーン", -11.527088165283203 ], [ "▁年次", -11.527206420898438 ], [ "▁ございましたら", -11.527339935302734 ], [ "▁商売", -11.527783393859863 ], [ "▁ディーゼル", -11.527809143066406 ], [ "▁Ro", -11.528017044067383 ], [ "▁扇", -11.528024673461914 ], [ "▁指し", -11.528312683105469 ], [ "▁シニア", -11.52834701538086 ], [ "ual", -11.52840518951416 ], [ "á", -11.528609275817871 ], [ "▁訂正", -11.528748512268066 ], [ "▁冷え", -11.528870582580566 ], [ "▁マリオ", -11.52890682220459 ], [ "▁誇り", -11.528926849365234 ], [ "▁コンテナ", -11.529008865356445 ], [ "評価", -11.529083251953125 ], [ "▁ป", -11.52934455871582 ], [ "▁妨害", -11.529348373413086 ], [ "▁シル", -11.529417991638184 ], [ "▁たとえ", -11.53002643585205 ], [ "▁△", -11.530097007751465 ], [ "▁職務", -11.530147552490234 ], [ "▁山岳", -11.530197143554688 ], [ "▁検察", -11.530319213867188 ], [ "黄", -11.5304594039917 ], [ "▁小松", -11.53066349029541 ], [ "▁亡命", -11.530688285827637 ], [ "▁受注", -11.5306978225708 ], [ "▁月曜日", -11.530721664428711 ], [ "▁客員", -11.530769348144531 ], [ "▁レール", -11.530786514282227 ], [ "▁木材", -11.531097412109375 ], [ "▁粒", -11.53114128112793 ], [ "▁臨", -11.531335830688477 ], [ "亭", -11.531404495239258 ], [ "▁営利", -11.531732559204102 ], [ "ah", -11.531778335571289 ], [ "▁ホンダ", -11.531821250915527 ], [ "▁搭乗", -11.531868934631348 ], [ "バッハ", -11.5319242477417 ], [ "換", -11.53197193145752 ], [ "▁視線", -11.53201961517334 ], [ "▁げ", -11.53203010559082 ], [ "▁ラク", -11.532071113586426 ], [ "寒", -11.532150268554688 ], [ "▁繋がる", -11.532289505004883 ], [ "▁東大", -11.532371520996094 ], [ "▁フェラ", -11.532586097717285 ], [ "▁決", -11.532779693603516 ], [ "▁並", -11.53281021118164 ], [ "▁競合", -11.532831192016602 ], [ "▁ミドル", -11.532892227172852 ], [ "▁ウィン", -11.533068656921387 ], [ "▁化石", -11.533198356628418 ], [ "▁クライ", -11.533312797546387 ], [ "▁枕", -11.533651351928711 ], [ "▁ヤン", -11.533812522888184 ], [ "レオ", -11.53397274017334 ], [ "▁福音", -11.534271240234375 ], [ "ながら", -11.534271240234375 ], [ "▁帰属", -11.534295082092285 ], [ "▁無断", -11.53432846069336 ], [ "▁キュ", -11.534372329711914 ], [ "ath", -11.534440040588379 ], [ "脈", -11.534574508666992 ], [ "こういう", -11.534626960754395 ], [ "▁ルイス", -11.53482723236084 ], [ "▁幸せな", -11.534914016723633 ], [ "幹", -11.534940719604492 ], [ "ポリス", -11.535076141357422 ], [ "▁借りる", -11.535205841064453 ], [ "臼", -11.535602569580078 ], [ "ight", -11.53561782836914 ], [ "クレ", -11.535758972167969 ], [ "▁征服", -11.536404609680176 ], [ "ari", -11.536468505859375 ], [ "▁寒い", -11.536624908447266 ], [ "▁海水", -11.53664493560791 ], [ "▁嫌な", -11.536652565002441 ], [ "▁引き起こす", -11.536674499511719 ], [ "サム", -11.536972999572754 ], [ "▁男の子", -11.537053108215332 ], [ "II", -11.537186622619629 ], [ "▁ME", -11.537556648254395 ], [ "ピュ", -11.537750244140625 ], [ "▁再会", -11.53787612915039 ], [ "▁125", -11.538320541381836 ], [ "1982", -11.538400650024414 ], [ "▁本気で", -11.538468360900879 ], [ "▁適した", -11.538553237915039 ], [ "▁ツー", -11.538615226745605 ], [ "▁生態", -11.53887939453125 ], [ "▁通じ", -11.538923263549805 ], [ "go", -11.53895092010498 ], [ "ts", -11.539010047912598 ], [ "ストロ", -11.539131164550781 ], [ "▁ギア", -11.539398193359375 ], [ "▁Cl", -11.539471626281738 ], [ "▁シンボル", -11.539501190185547 ], [ "▁山崎", -11.539619445800781 ], [ "グループ", -11.539734840393066 ], [ "ヤマ", -11.539894104003906 ], [ "▁遠慮", -11.539907455444336 ], [ "▁中将", -11.540020942687988 ], [ "▁ha", -11.540223121643066 ], [ "がた", -11.540266036987305 ], [ "▁慢性", -11.540319442749023 ], [ "▁MF", -11.540613174438477 ], [ "▁須", -11.540787696838379 ], [ "▁育", -11.540902137756348 ], [ "▁転向", -11.540990829467773 ], [ "BO", -11.541297912597656 ], [ "▁煙", -11.541495323181152 ], [ "▁炭", -11.541499137878418 ], [ "▁見つか", -11.541543006896973 ], [ "▁訪れて", -11.541550636291504 ], [ "▁担って", -11.541637420654297 ], [ "▁エンタテインメント", -11.541714668273926 ], [ "ビング", -11.541733741760254 ], [ "▁from", -11.54184341430664 ], [ "ほとんど", -11.54188346862793 ], [ "▁腫瘍", -11.542017936706543 ], [ "▁語学", -11.542044639587402 ], [ "▁レザー", -11.542129516601562 ], [ "▁漁業", -11.542232513427734 ], [ "認", -11.542322158813477 ], [ "▁染め", -11.542414665222168 ], [ "▁Su", -11.542444229125977 ], [ "▁責め", -11.542562484741211 ], [ "▁なくなって", -11.542707443237305 ], [ "▁丁", -11.542737007141113 ], [ "▁体質", -11.54275894165039 ], [ "▁抱いて", -11.542869567871094 ], [ "GO", -11.542879104614258 ], [ "▁シンプル", -11.54300308227539 ], [ "現役", -11.543410301208496 ], [ "▁奪", -11.543670654296875 ], [ "▁論争", -11.54376220703125 ], [ "▁招き", -11.54385757446289 ], [ "▁儀式", -11.543864250183105 ], [ "▁ホスト", -11.54387092590332 ], [ "▁補正", -11.543872833251953 ], [ "hi", -11.543951034545898 ], [ "▁読ま", -11.544011116027832 ], [ "▁1937", -11.54419994354248 ], [ "▁圧", -11.544358253479004 ], [ "▁配給", -11.54449462890625 ], [ "ボル", -11.544677734375 ], [ "▁原稿", -11.544694900512695 ], [ "▁いじめ", -11.54478645324707 ], [ "っきり", -11.545027732849121 ], [ "余", -11.545058250427246 ], [ "▁行える", -11.545069694519043 ], [ "▁受け取り", -11.545154571533203 ], [ "ーレ", -11.545161247253418 ], [ "講", -11.545281410217285 ], [ "▁劣", -11.545616149902344 ], [ "▁深刻な", -11.545848846435547 ], [ "ハラ", -11.54586124420166 ], [ "▁ISO", -11.546037673950195 ], [ "▁天神", -11.546126365661621 ], [ "▁承諾", -11.546219825744629 ], [ "▁シャン", -11.546418190002441 ], [ "〇", -11.546483993530273 ], [ "▁UEFA", -11.54650592803955 ], [ "▁氏名", -11.546714782714844 ], [ "▁電圧", -11.547322273254395 ], [ "over", -11.547503471374512 ], [ "宣", -11.547539710998535 ], [ "アリ", -11.547703742980957 ], [ "OO", -11.5477876663208 ], [ "テー", -11.547795295715332 ], [ "▁知恵", -11.547859191894531 ], [ "▁マレーシア", -11.547948837280273 ], [ "▁特有の", -11.548108100891113 ], [ "!", -11.548381805419922 ], [ "OC", -11.548510551452637 ], [ "奏", -11.548550605773926 ], [ "▁セカンド", -11.54858112335205 ], [ "▁公益", -11.54861831665039 ], [ "▁勲章", -11.548792839050293 ], [ "▁処置", -11.54904842376709 ], [ "▁情", -11.54915714263916 ], [ "▁弥", -11.549205780029297 ], [ "▁鎖", -11.549327850341797 ], [ "▁ツイッター", -11.54953670501709 ], [ "▁割れ", -11.54969310760498 ], [ "▁追跡", -11.549796104431152 ], [ "▁動機", -11.549909591674805 ], [ "▁拘", -11.549922943115234 ], [ "岐", -11.549934387207031 ], [ "▁万全", -11.549962997436523 ], [ "▁入浴", -11.549978256225586 ], [ "セント", -11.550076484680176 ], [ "▁se", -11.550126075744629 ], [ "途", -11.550166130065918 ], [ "▁開館", -11.550322532653809 ], [ "炭", -11.550369262695312 ], [ "▁ゆえ", -11.55056095123291 ], [ "検索", -11.550562858581543 ], [ "▁取り扱う", -11.550677299499512 ], [ "立て", -11.550714492797852 ], [ "▁完備", -11.550764083862305 ], [ "▁あったら", -11.550867080688477 ], [ "▁Sa", -11.551190376281738 ], [ "▁洗面", -11.55128002166748 ], [ "だん", -11.55152702331543 ], [ "こと", -11.551536560058594 ], [ "▁ことだ", -11.551679611206055 ], [ "▁綺麗に", -11.551692008972168 ], [ "ニコ", -11.55179500579834 ], [ "▁絶滅", -11.551801681518555 ], [ "就", -11.551892280578613 ], [ "わる", -11.55194091796875 ], [ "▁自作", -11.551994323730469 ], [ "▁貫", -11.552048683166504 ], [ "▁宏", -11.552136421203613 ], [ "OM", -11.552311897277832 ], [ "デュ", -11.552470207214355 ], [ "▁くださる", -11.552491188049316 ], [ "▁駆使", -11.55252456665039 ], [ "▁センス", -11.552730560302734 ], [ "刺", -11.552825927734375 ], [ "▁1936", -11.552940368652344 ], [ "呂", -11.552943229675293 ], [ "▁読", -11.553034782409668 ], [ "▁ヴェル", -11.553435325622559 ], [ "▁外壁", -11.553540229797363 ], [ "ごろ", -11.553841590881348 ], [ "厳", -11.553910255432129 ], [ "▁ギャ", -11.553942680358887 ], [ "▁騎手", -11.554055213928223 ], [ "▁Di", -11.554186820983887 ], [ "▁気づいた", -11.55423641204834 ], [ "▁2,000", -11.554327964782715 ], [ "動画", -11.554511070251465 ], [ "腸", -11.55480670928955 ], [ "▁主宰", -11.554828643798828 ], [ "▁服装", -11.554876327514648 ], [ "▁住友", -11.554951667785645 ], [ "▁改装", -11.555045127868652 ], [ "障", -11.555219650268555 ], [ "▁出土", -11.555362701416016 ], [ "核", -11.555381774902344 ], [ "▁研", -11.555407524108887 ], [ "挙", -11.555560111999512 ], [ "みなさん", -11.555630683898926 ], [ "▁コーディネート", -11.55565071105957 ], [ "沙", -11.555861473083496 ], [ "▁明確な", -11.556219100952148 ], [ "▁World", -11.556333541870117 ], [ "▁高まって", -11.556527137756348 ], [ "▁喫茶", -11.556574821472168 ], [ "▁完", -11.556774139404297 ], [ "ルク", -11.556790351867676 ], [ "▁対照", -11.556865692138672 ], [ "▁仕上がり", -11.556896209716797 ], [ "▁拳", -11.557093620300293 ], [ "固", -11.557123184204102 ], [ "▁頭痛", -11.557260513305664 ], [ "▁町名", -11.557506561279297 ], [ "軸", -11.557526588439941 ], [ "阿", -11.557558059692383 ], [ "▁不調", -11.557581901550293 ], [ "▁支", -11.557791709899902 ], [ "ボウ", -11.557847023010254 ], [ "▁湘南", -11.557868957519531 ], [ "▁レア", -11.558034896850586 ], [ "▁答えて", -11.55804443359375 ], [ "▁魔女", -11.55809211730957 ], [ "▁中毒", -11.558412551879883 ], [ "メンバー", -11.558427810668945 ], [ "▁受診", -11.558448791503906 ], [ "▁不明である", -11.558582305908203 ], [ "▁魚雷", -11.558640480041504 ], [ "▁晩", -11.55876636505127 ], [ "▁1938", -11.558841705322266 ], [ "▁又", -11.558841705322266 ], [ "モス", -11.559161186218262 ], [ "▁矛盾", -11.559165954589844 ], [ "▁育てる", -11.55916976928711 ], [ "▁巡り", -11.559405326843262 ], [ "是非", -11.559425354003906 ], [ "▁圭", -11.559439659118652 ], [ "▁役者", -11.559490203857422 ], [ "▁レオ", -11.55959415435791 ], [ "▁時給", -11.559657096862793 ], [ "ポリ", -11.559671401977539 ], [ "▁少", -11.559736251831055 ], [ "替え", -11.559747695922852 ], [ "▁イエロー", -11.559782981872559 ], [ "▁ヤマ", -11.559840202331543 ], [ "▁インパクト", -11.559844970703125 ], [ "▁結晶", -11.56010627746582 ], [ "▁Com", -11.560153007507324 ], [ "▁ジン", -11.560352325439453 ], [ "▁快適に", -11.560362815856934 ], [ "憲", -11.560385704040527 ], [ "犯", -11.560454368591309 ], [ "補", -11.560554504394531 ], [ "▁定年", -11.560721397399902 ], [ "▁流域", -11.560895919799805 ], [ "本来", -11.561036109924316 ], [ "▁貸", -11.561302185058594 ], [ "初回", -11.561418533325195 ], [ "ort", -11.561542510986328 ], [ "▁希", -11.56159782409668 ], [ "▁成年", -11.561631202697754 ], [ "▁山地", -11.561671257019043 ], [ "▁不安に", -11.561849594116211 ], [ "▁変えた", -11.561914443969727 ], [ "ew", -11.562054634094238 ], [ "▁シュー", -11.56208324432373 ], [ "▁寄附", -11.562138557434082 ], [ "▁虚", -11.562272071838379 ], [ "▁5,000", -11.562386512756348 ], [ "▁みつ", -11.562727928161621 ], [ "準", -11.56277084350586 ], [ "失", -11.563116073608398 ], [ "▁追わ", -11.563188552856445 ], [ "▁愛情", -11.563214302062988 ], [ "▁メス", -11.56343936920166 ], [ "ny", -11.56363296508789 ], [ "▁勘違い", -11.56369400024414 ], [ "▁溝", -11.564163208007812 ], [ "▁婦人", -11.564228057861328 ], [ "テール", -11.564266204833984 ], [ "▁歌舞伎", -11.564608573913574 ], [ "▁涼", -11.564642906188965 ], [ "▁酔", -11.564774513244629 ], [ "▁暑い", -11.564875602722168 ], [ "▁誘い", -11.565125465393066 ], [ "▁do", -11.565268516540527 ], [ "▁セルビア", -11.565314292907715 ], [ "▁文芸", -11.565388679504395 ], [ "▁チョ", -11.56601619720459 ], [ "▁救助", -11.566064834594727 ], [ "▁正解", -11.566121101379395 ], [ "没", -11.5662841796875 ], [ "編", -11.56634521484375 ], [ "ネイ", -11.566422462463379 ], [ "▁諦め", -11.566437721252441 ], [ "▁3,000", -11.566505432128906 ], [ "▁集密", -11.566506385803223 ], [ "ベー", -11.56655216217041 ], [ "▁乗り入れ", -11.566644668579102 ], [ "▁原則として", -11.566715240478516 ], [ "▁おっぱい", -11.566970825195312 ], [ "▁Lo", -11.567032814025879 ], [ "▁趣旨", -11.56741714477539 ], [ "ium", -11.567506790161133 ], [ "▁洗い", -11.567662239074707 ], [ "▁聴く", -11.567803382873535 ], [ "▁歌唱", -11.567948341369629 ], [ "▁牡馬", -11.567975044250488 ], [ "▁ホラー", -11.568001747131348 ], [ "▁複", -11.568106651306152 ], [ "za", -11.568130493164062 ], [ "▁直面", -11.568251609802246 ], [ "▁ガイドライン", -11.568258285522461 ], [ "▁やめて", -11.568379402160645 ], [ "▁適切に", -11.568633079528809 ], [ "▁チョコ", -11.569042205810547 ], [ "▁醤油", -11.569222450256348 ], [ "▁陥落", -11.569222450256348 ], [ "▁組み立て", -11.569510459899902 ], [ "勤", -11.569581031799316 ], [ "ヒー", -11.56961441040039 ], [ "▁外来", -11.569644927978516 ], [ "1979", -11.569684028625488 ], [ "▁使えば", -11.569869995117188 ], [ "▁まる", -11.570510864257812 ], [ "▁越えて", -11.570560455322266 ], [ "▁細かく", -11.570809364318848 ], [ "▁名乗る", -11.571096420288086 ], [ "▁がちです", -11.571125030517578 ], [ "1972", -11.571202278137207 ], [ "▁エンターテインメント", -11.571346282958984 ], [ "テリア", -11.571630477905273 ], [ "▁オスマン", -11.5717134475708 ], [ "▁入札", -11.571821212768555 ], [ "▁愛用", -11.57199478149414 ], [ "dy", -11.572011947631836 ], [ "▁戻す", -11.572025299072266 ], [ "▁排水", -11.57229232788086 ], [ "▁幼児", -11.572421073913574 ], [ "ルズ", -11.572540283203125 ], [ "▁種子", -11.572575569152832 ], [ "▁ゆったり", -11.572985649108887 ], [ "▁カム", -11.573020935058594 ], [ "メイン", -11.573119163513184 ], [ "▁出せ", -11.573238372802734 ], [ "▁食器", -11.573366165161133 ], [ "▁アマゾン", -11.57353401184082 ], [ "苑", -11.573599815368652 ], [ "▁恩", -11.573614120483398 ], [ "▁グラム", -11.573660850524902 ], [ "▁終わら", -11.573784828186035 ], [ "HA", -11.5737943649292 ], [ "▁克", -11.574190139770508 ], [ "▁縮", -11.574241638183594 ], [ "▁スプリング", -11.574352264404297 ], [ "スパ", -11.57451343536377 ], [ "▁見通し", -11.574616432189941 ], [ "▁行ったり", -11.574620246887207 ], [ "▁倉", -11.57478141784668 ], [ "▁四季", -11.574896812438965 ], [ "▁松平", -11.575023651123047 ], [ "▁わざわざ", -11.575102806091309 ], [ "▁伊達", -11.575163841247559 ], [ "▁タスク", -11.575169563293457 ], [ "▁ヴァイ", -11.575169563293457 ], [ "▁赤字", -11.575226783752441 ], [ "▁旅団", -11.575323104858398 ], [ "当店", -11.575345039367676 ], [ "すけ", -11.575379371643066 ], [ "▁目黒", -11.575485229492188 ], [ "バリ", -11.575528144836426 ], [ "▁トル", -11.57565975189209 ], [ "▁失う", -11.57568359375 ], [ "▁はるかに", -11.575811386108398 ], [ "▁オブジェクト", -11.575927734375 ], [ "▁砦", -11.576189994812012 ], [ "▁プロペシア", -11.576212882995605 ], [ "然と", -11.576263427734375 ], [ "▁名所", -11.576374053955078 ], [ "続いて", -11.576461791992188 ], [ "ライン", -11.576507568359375 ], [ "▁ミュー", -11.576713562011719 ], [ "与", -11.57701587677002 ], [ "▁カウント", -11.57707405090332 ], [ "▁部族", -11.577223777770996 ], [ "▁ふうに", -11.577259063720703 ], [ "▁至ら", -11.577476501464844 ], [ "▁対面", -11.577526092529297 ], [ "▁加熱", -11.577576637268066 ], [ "▁測", -11.577601432800293 ], [ "スタッフ", -11.577781677246094 ], [ "▁演習", -11.578076362609863 ], [ "▁ショ", -11.578207015991211 ], [ "▁撃", -11.578226089477539 ], [ "▁控え", -11.578418731689453 ], [ "ギン", -11.578436851501465 ], [ "▁女神", -11.57854175567627 ], [ "▁NEWS", -11.578622817993164 ], [ "▁答えた", -11.578639030456543 ], [ "▁父さん", -11.578715324401855 ], [ "▁加算", -11.579071998596191 ], [ "▁送付", -11.579302787780762 ], [ "▁引越", -11.5794038772583 ], [ "ple", -11.579546928405762 ], [ "▁プル", -11.579778671264648 ], [ "施設", -11.579876899719238 ], [ "1981", -11.579887390136719 ], [ "展覧", -11.5799560546875 ], [ "ドルフ", -11.579972267150879 ], [ "▁過剰", -11.58004093170166 ], [ "▁カスタマイズ", -11.580327033996582 ], [ "▁付く", -11.580347061157227 ], [ "▁無限", -11.580353736877441 ], [ "sc", -11.580512046813965 ], [ "▁旬", -11.581007957458496 ], [ "▁ホビー", -11.581050872802734 ], [ "▁ふるさと", -11.58105754852295 ], [ "いつ", -11.581058502197266 ], [ "わたし", -11.581155776977539 ], [ "▁海峡", -11.581384658813477 ], [ "どの", -11.581411361694336 ], [ "▁愛する", -11.581536293029785 ], [ "▁カス", -11.581689834594727 ], [ "Google", -11.581818580627441 ], [ "▁落選", -11.582067489624023 ], [ "▁画質", -11.582341194152832 ], [ "▁暑", -11.582357406616211 ], [ "▁抱える", -11.58236312866211 ], [ "▁運搬", -11.582478523254395 ], [ "▁レーシング", -11.582688331604004 ], [ "▁見かけ", -11.582715034484863 ], [ "▁常時", -11.582738876342773 ], [ "」", -11.582863807678223 ], [ "▁録画", -11.583144187927246 ], [ "sp", -11.58326530456543 ], [ "▁前面", -11.5833158493042 ], [ "券", -11.58335018157959 ], [ "▁勇者", -11.583436965942383 ], [ "▁ラウンジ", -11.583494186401367 ], [ "▁コンタクト", -11.583820343017578 ], [ "サラ", -11.584065437316895 ], [ "▁回る", -11.584142684936523 ], [ "▁昆虫", -11.584309577941895 ], [ "露", -11.58471393585205 ], [ "スポーツ", -11.584715843200684 ], [ "▁斎藤", -11.584869384765625 ], [ "▁リース", -11.5849027633667 ], [ "▁津波", -11.58497142791748 ], [ "▁NG", -11.585017204284668 ], [ "▁バリエーション", -11.585076332092285 ], [ "コメント", -11.585161209106445 ], [ "▁声明", -11.585165023803711 ], [ "▁奉行", -11.585264205932617 ], [ "▁PV", -11.58543586730957 ], [ "▁べきである", -11.585627555847168 ], [ "▁ドッグ", -11.585638046264648 ], [ "▁温暖", -11.585711479187012 ], [ "▁真っ", -11.585835456848145 ], [ "▁内装", -11.585895538330078 ], [ "▁LAN", -11.58592700958252 ], [ "▁ノイズ", -11.586008071899414 ], [ "▁地面", -11.586389541625977 ], [ "貧", -11.58640193939209 ], [ "▁典", -11.586405754089355 ], [ "RC", -11.586463928222656 ], [ "▁失って", -11.586564064025879 ], [ "フレ", -11.586583137512207 ], [ "▁スラ", -11.586676597595215 ], [ "▁as", -11.586771011352539 ], [ "▁Vi", -11.586929321289062 ], [ "▁運ぶ", -11.58709716796875 ], [ "▁レイアウト", -11.587228775024414 ], [ "▁遅れて", -11.58743953704834 ], [ "▁羊", -11.587566375732422 ], [ "▁ローラー", -11.587627410888672 ], [ "▁Qu", -11.587657928466797 ], [ "▁心から", -11.587693214416504 ], [ "▁フィット", -11.587725639343262 ], [ "▁無事に", -11.587794303894043 ], [ "▁過ぎた", -11.588093757629395 ], [ "▁餌", -11.588205337524414 ], [ "▁表して", -11.588295936584473 ], [ "▁統制", -11.588393211364746 ], [ "▁英会話", -11.588393211364746 ], [ "▁Life", -11.588444709777832 ], [ "▁スペック", -11.588470458984375 ], [ "▁ジェル", -11.5887451171875 ], [ "▁進展", -11.588831901550293 ], [ "▁運送", -11.588980674743652 ], [ "コフ", -11.589017868041992 ], [ "▁求", -11.589406967163086 ], [ "▁遺伝", -11.589544296264648 ], [ "▁Love", -11.58974838256836 ], [ "ull", -11.589756965637207 ], [ "弱", -11.589827537536621 ], [ "▁いけば", -11.589845657348633 ], [ "▁路面", -11.589845657348633 ], [ "僚", -11.589845657348633 ], [ "▁格闘", -11.589970588684082 ], [ "▁エク", -11.590082168579102 ], [ "▁遣", -11.590106010437012 ], [ "▁目線", -11.590171813964844 ], [ "▁野生", -11.590180397033691 ], [ "▁男爵", -11.59030818939209 ], [ "▁閉じ", -11.590472221374512 ], [ "ブー", -11.590961456298828 ], [ "▁待機", -11.591633796691895 ], [ "▁工学部", -11.591641426086426 ], [ "▁好きです", -11.592142105102539 ], [ "▁アラビア", -11.592329978942871 ], [ "▁浸", -11.592561721801758 ], [ "▁灰", -11.592596054077148 ], [ "カム", -11.592772483825684 ], [ "▁土壌", -11.592784881591797 ], [ "▁優位", -11.592839241027832 ], [ "唱", -11.593040466308594 ], [ "▁トロント", -11.593091011047363 ], [ "▁ウィル", -11.593119621276855 ], [ "紋", -11.593307495117188 ], [ "▁王位", -11.593378067016602 ], [ "▁専", -11.593771934509277 ], [ "ソウ", -11.593823432922363 ], [ "▁加わった", -11.593907356262207 ], [ "▁支障", -11.594058990478516 ], [ "試", -11.59416675567627 ], [ "▁廃車", -11.594374656677246 ], [ "he", -11.594916343688965 ], [ "ator", -11.594944953918457 ], [ "5000", -11.595099449157715 ], [ "以", -11.59521198272705 ], [ "▁肖像", -11.595328330993652 ], [ "pan", -11.595443725585938 ], [ "邦", -11.595616340637207 ], [ "TER", -11.595792770385742 ], [ "▁触れて", -11.595938682556152 ], [ "ッテ", -11.596099853515625 ], [ "▁著名な", -11.596456527709961 ], [ "uc", -11.596552848815918 ], [ "▁後輩", -11.596638679504395 ], [ "▁クエスト", -11.596673011779785 ], [ "▁燃焼", -11.596811294555664 ], [ "▁田村", -11.596988677978516 ], [ "▁だろ", -11.597010612487793 ], [ "▁デカ", -11.597184181213379 ], [ "▁ヤマト", -11.597250938415527 ], [ "▁スレ", -11.597257614135742 ], [ "下記", -11.59749698638916 ], [ "▁奨励", -11.597572326660156 ], [ "▁チェコ", -11.597757339477539 ], [ "▁無駄", -11.597962379455566 ], [ "ロット", -11.598231315612793 ], [ "カラー", -11.598313331604004 ], [ "▁産地", -11.598404884338379 ], [ "▁繰り広げ", -11.598530769348145 ], [ "▁國", -11.598575592041016 ], [ "▁セーブ", -11.598638534545898 ], [ "▁クリエイティブ", -11.59872817993164 ], [ "RT", -11.599089622497559 ], [ "▁カナ", -11.599321365356445 ], [ "▁小屋", -11.599323272705078 ], [ "▁vs", -11.599716186523438 ], [ "▁沿線", -11.599825859069824 ], [ "▁惜し", -11.59986686706543 ], [ "▁買", -11.599933624267578 ], [ "▁かから", -11.600000381469727 ], [ "▁物流", -11.600076675415039 ], [ "▁角形", -11.600375175476074 ], [ "old", -11.60042667388916 ], [ "洗", -11.600589752197266 ], [ "▁木造", -11.600717544555664 ], [ "リーグ", -11.601142883300781 ], [ "引退", -11.601163864135742 ], [ "▁なくなった", -11.601166725158691 ], [ "OP", -11.601225852966309 ], [ "▁薩摩", -11.601238250732422 ], [ "sa", -11.601289749145508 ], [ "▁寝る", -11.60151481628418 ], [ "▁馬鹿", -11.60155963897705 ], [ "▁構内", -11.601689338684082 ], [ "▁技師", -11.601725578308105 ], [ "▁まさか", -11.601844787597656 ], [ "▁ビジュアル", -11.601884841918945 ], [ "▁客観", -11.60193157196045 ], [ "▁克服", -11.601972579956055 ], [ "▁やろう", -11.602822303771973 ], [ "▁快速", -11.602877616882324 ], [ "▁磯", -11.602906227111816 ], [ "▁妖怪", -11.602916717529297 ], [ "▁つれて", -11.603096961975098 ], [ "▁正体", -11.603216171264648 ], [ "▁断念", -11.60352897644043 ], [ "▁聴き", -11.603869438171387 ], [ "所属", -11.603875160217285 ], [ "ミス", -11.603896141052246 ], [ "▁性別", -11.603907585144043 ], [ "▁食物", -11.603957176208496 ], [ "▁レート", -11.604058265686035 ], [ "▁専属", -11.604215621948242 ], [ "▁山下", -11.604316711425781 ], [ "記事", -11.604403495788574 ], [ "▁専念", -11.604414939880371 ], [ "ずる", -11.604642868041992 ], [ "▁防犯", -11.604748725891113 ], [ "▁オナニー", -11.605206489562988 ], [ "かる", -11.605267524719238 ], [ "ベルト", -11.60543441772461 ], [ "▁育ち", -11.605673789978027 ], [ "それでは", -11.605711936950684 ], [ "▁我が", -11.605754852294922 ], [ "▁葬", -11.60579776763916 ], [ "▁妄想", -11.605887413024902 ], [ "▁瞳", -11.606099128723145 ], [ "窓", -11.606138229370117 ], [ "▁舟", -11.606207847595215 ], [ "会員", -11.606226921081543 ], [ "▁潤", -11.60636043548584 ], [ "▁困る", -11.606472969055176 ], [ "▁アシスト", -11.606602668762207 ], [ "ったら", -11.607001304626465 ], [ "▁初期に", -11.607379913330078 ], [ "▁溶け", -11.60739517211914 ], [ "EA", -11.607659339904785 ], [ "\\", -11.607918739318848 ], [ "ose", -11.608015060424805 ], [ "▁汚", -11.608076095581055 ], [ "▁幼", -11.608345031738281 ], [ "出典", -11.608540534973145 ], [ "▁潜在", -11.60863971710205 ], [ "りつ", -11.608688354492188 ], [ "▁大丈夫です", -11.60892391204834 ], [ "▁害", -11.608997344970703 ], [ "▁ハイブリッド", -11.60899829864502 ], [ "▁見込み", -11.609015464782715 ], [ "接", -11.60901927947998 ], [ "閉", -11.609079360961914 ], [ "lin", -11.609274864196777 ], [ "麗", -11.609503746032715 ], [ "いく", -11.609583854675293 ], [ "▁手前", -11.60958480834961 ], [ "▁利便", -11.609644889831543 ], [ "▁資材", -11.609724044799805 ], [ "▁用紙", -11.609745025634766 ], [ "況", -11.609819412231445 ], [ "▁365", -11.609914779663086 ], [ "ヴィル", -11.609990119934082 ], [ "▁釣", -11.610042572021484 ], [ "▁執", -11.61020565032959 ], [ "ナム", -11.610608100891113 ], [ "▁authorTXTs", -11.610623359680176 ], [ "▁こっち", -11.610846519470215 ], [ "▁シュート", -11.610926628112793 ], [ "切れ", -11.61095905303955 ], [ "っく", -11.611175537109375 ], [ "1975", -11.611188888549805 ], [ "▁AP", -11.611224174499512 ], [ "▁武道", -11.611261367797852 ], [ "トリア", -11.611307144165039 ], [ "1978", -11.611333847045898 ], [ "▁邸", -11.61135482788086 ], [ "▁職種", -11.61136245727539 ], [ "▁支えて", -11.611371040344238 ], [ "▁その場で", -11.61166763305664 ], [ "▁トマト", -11.61192512512207 ], [ "▁熱い", -11.612165451049805 ], [ "▁おめでとう", -11.61228084564209 ], [ "ade", -11.61233139038086 ], [ "▁ディーラー", -11.612371444702148 ], [ "リャ", -11.612378120422363 ], [ "▁カート", -11.612462043762207 ], [ "Web", -11.61270809173584 ], [ "▁劣化", -11.612751960754395 ], [ "▁源氏", -11.6128511428833 ], [ "消", -11.612909317016602 ], [ "ign", -11.612924575805664 ], [ "ich", -11.613052368164062 ], [ "メディア", -11.61316204071045 ], [ "▁ハロウィン", -11.613227844238281 ], [ "テイ", -11.613422393798828 ], [ "タール", -11.613430976867676 ], [ "諸", -11.613775253295898 ], [ "▁sp", -11.613795280456543 ], [ "尼", -11.613814353942871 ], [ "▁クルー", -11.613917350769043 ], [ "ウォー", -11.613986015319824 ], [ "▁気圧", -11.613998413085938 ], [ "エフ", -11.614108085632324 ], [ "シック", -11.614330291748047 ], [ "▁東武", -11.61447811126709 ], [ "ウト", -11.614480972290039 ], [ "卒業", -11.614484786987305 ], [ "RM", -11.614537239074707 ], [ "▁倒産", -11.614622116088867 ], [ "ツェ", -11.614795684814453 ], [ "▁件数", -11.61488151550293 ], [ "登録", -11.614887237548828 ], [ "▁邪魔", -11.614934921264648 ], [ "▁てい", -11.615018844604492 ], [ "▁花粉", -11.61508560180664 ], [ "▁掲げる", -11.615267753601074 ], [ "▁舎", -11.61536979675293 ], [ "▁立た", -11.615442276000977 ], [ "釈", -11.615585327148438 ], [ "▁上院", -11.615764617919922 ], [ "▁セールス", -11.615821838378906 ], [ "▁応じ", -11.615944862365723 ], [ "▁Se", -11.61599063873291 ], [ "▁ボーイ", -11.615996360778809 ], [ "▁行なう", -11.616036415100098 ], [ "▁渋", -11.616225242614746 ], [ "▁編纂", -11.616304397583008 ], [ "▁おかしい", -11.616338729858398 ], [ "貨", -11.616361618041992 ], [ "▁鶏", -11.616459846496582 ], [ "▁正式な", -11.616493225097656 ], [ "▁ツイート", -11.616720199584961 ], [ "▁ウェスト", -11.617181777954102 ], [ "▁蘇", -11.617551803588867 ], [ "飲", -11.617613792419434 ], [ "▁あくまでも", -11.61772346496582 ], [ "▁レジャー", -11.617733001708984 ], [ "▁樹脂", -11.617745399475098 ], [ "▁講", -11.61777114868164 ], [ "▁わが", -11.617907524108887 ], [ "▁上手に", -11.61792278289795 ], [ "模", -11.617939949035645 ], [ "▁どうも", -11.618009567260742 ], [ "スマホ", -11.618021965026855 ], [ "az", -11.618042945861816 ], [ "株", -11.618328094482422 ], [ "▁止める", -11.618340492248535 ], [ "▁TE", -11.618600845336914 ], [ "旅", -11.618803024291992 ], [ "▁及ぼす", -11.619375228881836 ], [ "▁セレクト", -11.619396209716797 ], [ "▁駐", -11.61945629119873 ], [ "ヴィー", -11.619596481323242 ], [ "▁因子", -11.61961841583252 ], [ "▁キル", -11.619680404663086 ], [ "▁中核", -11.61999225616455 ], [ "指定", -11.620144844055176 ], [ "▁治安", -11.62015438079834 ], [ "▁助言", -11.620285987854004 ], [ "▁郷土", -11.620306015014648 ], [ "▁スペ", -11.620356559753418 ], [ "OW", -11.62044906616211 ], [ "閣", -11.620536804199219 ], [ "▁ギャンブル", -11.620599746704102 ], [ "▁発動", -11.620601654052734 ], [ "▁酒造", -11.620654106140137 ], [ "▁日中", -11.620800018310547 ], [ "因", -11.620806694030762 ], [ "▁置", -11.620888710021973 ], [ "▁力学", -11.620967864990234 ], [ "腰", -11.62109088897705 ], [ "▁うつ", -11.621321678161621 ], [ "▁払って", -11.621350288391113 ], [ "▁きれいに", -11.621493339538574 ], [ "フィールド", -11.621532440185547 ], [ "リク", -11.621807098388672 ], [ "▁逃亡", -11.621808052062988 ], [ "▁転用", -11.621981620788574 ], [ "▁サンド", -11.621987342834473 ], [ "▁めぐる", -11.62207317352295 ], [ "長野", -11.622116088867188 ], [ "▁カーテン", -11.62219524383545 ], [ "▁PA", -11.622456550598145 ], [ "▁ピット", -11.622642517089844 ], [ "▁220", -11.623035430908203 ], [ "嶺", -11.623252868652344 ], [ "クー", -11.62389087677002 ], [ "▁ベリー", -11.623895645141602 ], [ "EX", -11.624113082885742 ], [ "▁プラグイン", -11.624149322509766 ], [ "丹", -11.624153137207031 ], [ "▁通路", -11.624451637268066 ], [ "▁ニコ", -11.624584197998047 ], [ "▁フェス", -11.624919891357422 ], [ "くり", -11.624919891357422 ], [ "しき", -11.62492847442627 ], [ "▁引き上げ", -11.625086784362793 ], [ "▁知名度", -11.625099182128906 ], [ "▁常勤", -11.625326156616211 ], [ "900", -11.625426292419434 ], [ "▁HTML", -11.62551498413086 ], [ "▁かわい", -11.62564468383789 ], [ "▁しょ", -11.625658988952637 ], [ "1973", -11.625661849975586 ], [ "▁エド", -11.625666618347168 ], [ "▁自慢", -11.625733375549316 ], [ "ica", -11.62576675415039 ], [ "▁シナ", -11.625853538513184 ], [ "▁乙", -11.625893592834473 ], [ "▁ブレイク", -11.625944137573242 ], [ "▁べきです", -11.62613296508789 ], [ "自身", -11.626147270202637 ], [ "bu", -11.626152038574219 ], [ "▁パブ", -11.626222610473633 ], [ "ぐる", -11.626273155212402 ], [ "▁流し", -11.626283645629883 ], [ "▁新田", -11.626365661621094 ], [ "▁Instagram", -11.626897811889648 ], [ "ワールド", -11.626937866210938 ], [ "▁閣", -11.627145767211914 ], [ "▁入り口", -11.62732982635498 ], [ "たく", -11.627406120300293 ], [ "▁金曜", -11.627425193786621 ], [ "▁浅草", -11.627459526062012 ], [ "▁先ほど", -11.627791404724121 ], [ "▁加わ", -11.628179550170898 ], [ "▁飾った", -11.628262519836426 ], [ "▁ウー", -11.628278732299805 ], [ "刈", -11.628463745117188 ], [ "BI", -11.628744125366211 ], [ "▁航路", -11.6290922164917 ], [ "げる", -11.629170417785645 ], [ "▁会って", -11.629319190979004 ], [ "▁古く", -11.629475593566895 ], [ "▁探検", -11.629549980163574 ], [ "▁浦和", -11.629853248596191 ], [ "▁取り扱って", -11.629887580871582 ], [ "▁継が", -11.630146026611328 ], [ "レッド", -11.63079833984375 ], [ "▁Na", -11.630888938903809 ], [ "▁泥", -11.631368637084961 ], [ "▁DX", -11.631815910339355 ], [ "▁桐", -11.631893157958984 ], [ "▁サイバー", -11.63206672668457 ], [ "どり", -11.632163047790527 ], [ "▁殺し", -11.632181167602539 ], [ "▁なろう", -11.632187843322754 ], [ "▁朝食", -11.63249397277832 ], [ "▁戦時", -11.632501602172852 ], [ "▁実在", -11.632502555847168 ], [ "NK", -11.63256549835205 ], [ "▁クッション", -11.632619857788086 ], [ "▁せっかく", -11.632644653320312 ], [ "ーノ", -11.632649421691895 ], [ "ッソ", -11.632655143737793 ], [ "▁空中", -11.63265609741211 ], [ "▁ウェル", -11.63270092010498 ], [ "▁豊富に", -11.632713317871094 ], [ "▁Pr", -11.632742881774902 ], [ "▁済む", -11.632783889770508 ], [ "▁サンフランシスコ", -11.632829666137695 ], [ "MC", -11.632863998413086 ], [ "ほん", -11.632983207702637 ], [ "▁国有", -11.632993698120117 ], [ "考", -11.63304615020752 ], [ "️", -11.633244514465332 ], [ "ker", -11.633352279663086 ], [ "▁幹事", -11.633706092834473 ], [ "▁匂い", -11.633780479431152 ], [ "國", -11.633871078491211 ], [ "携帯", -11.634023666381836 ], [ "▁曲線", -11.634029388427734 ], [ "販", -11.634214401245117 ], [ "九州", -11.634286880493164 ], [ "▁フッド", -11.634481430053711 ], [ "▁敷", -11.634536743164062 ], [ "▁片付け", -11.634565353393555 ], [ "級", -11.634587287902832 ], [ "▁ハリウッド", -11.63459587097168 ], [ "毒", -11.63471794128418 ], [ "▁スライド", -11.634856224060059 ], [ "リコ", -11.634963035583496 ], [ "▁吸", -11.634969711303711 ], [ "▁泡", -11.635416984558105 ], [ "▁採択", -11.635453224182129 ], [ "▁最古", -11.635472297668457 ], [ "▁Fr", -11.63577651977539 ], [ "倒", -11.635905265808105 ], [ "▁筆頭", -11.635953903198242 ], [ "▁運んで", -11.63597297668457 ], [ "▁ブーツ", -11.636110305786133 ], [ "システム", -11.636308670043945 ], [ "▁宮廷", -11.636333465576172 ], [ "ッシ", -11.636470794677734 ], [ "仏", -11.636687278747559 ], [ "條", -11.637179374694824 ], [ "▁後退", -11.637369155883789 ], [ "▁絞", -11.637555122375488 ], [ "▁Adobe", -11.63770866394043 ], [ "▁包括", -11.637985229492188 ], [ "▁果", -11.638140678405762 ], [ "▁南アフリカ", -11.638157844543457 ], [ "らしい", -11.638289451599121 ], [ "▁預け", -11.639055252075195 ], [ "ニエ", -11.639167785644531 ], [ "――", -11.639203071594238 ], [ "ps", -11.639389991760254 ], [ "なら", -11.63941764831543 ], [ "▁開け", -11.63951301574707 ], [ "▁多々", -11.639514923095703 ], [ "int", -11.639562606811523 ], [ "ッセ", -11.639640808105469 ], [ "葬", -11.639938354492188 ], [ "▁ブルース", -11.639999389648438 ], [ "OE", -11.64003849029541 ], [ "ベラ", -11.640188217163086 ], [ "▁1933", -11.640388488769531 ], [ "▁この頃", -11.640400886535645 ], [ "▁メソッド", -11.640658378601074 ], [ "岳", -11.640802383422852 ], [ "▁たた", -11.640910148620605 ], [ "▁カタ", -11.640913009643555 ], [ "▁気づか", -11.640921592712402 ], [ "▁洪水", -11.6410493850708 ], [ "▁小山", -11.641073226928711 ], [ "▁晴れ", -11.641242980957031 ], [ "St", -11.641642570495605 ], [ "左衛門", -11.641864776611328 ], [ "デザイン", -11.642037391662598 ], [ "▁わか", -11.642361640930176 ], [ "禄", -11.64236831665039 ], [ "▁単純な", -11.642376899719238 ], [ "▁限度", -11.642491340637207 ], [ "▁開けて", -11.64252758026123 ], [ "▁クロー", -11.64268684387207 ], [ "▁ジュエリー", -11.64273738861084 ], [ "▁モーニング", -11.642788887023926 ], [ "▁作れる", -11.642850875854492 ], [ "▁道徳", -11.642995834350586 ], [ "▁Gu", -11.643203735351562 ], [ "分け", -11.643401145935059 ], [ "▁初演", -11.643404960632324 ], [ "▁盛んに", -11.643476486206055 ], [ "▁濃い", -11.643725395202637 ], [ "通称", -11.643800735473633 ], [ "shi", -11.643810272216797 ], [ "▁トレー", -11.643904685974121 ], [ "違い", -11.643940925598145 ], [ "▁演じて", -11.644256591796875 ], [ "▁侵略", -11.644355773925781 ], [ "▁ナチス", -11.64437198638916 ], [ "▁崇", -11.644424438476562 ], [ "健康", -11.644549369812012 ], [ "付か", -11.644645690917969 ], [ "最高", -11.644665718078613 ], [ "▁ダル", -11.64537239074707 ], [ "▁和田", -11.64542293548584 ], [ "寧", -11.645605087280273 ], [ "▁パチンコ", -11.645720481872559 ], [ "歴", -11.645768165588379 ], [ "▁シロ", -11.645967483520508 ], [ "▁番地", -11.645986557006836 ], [ "▁ストレッチ", -11.646193504333496 ], [ "0000", -11.646230697631836 ], [ "冠", -11.646320343017578 ], [ "▁真剣に", -11.646437644958496 ], [ "パイ", -11.646590232849121 ], [ "▁毛利", -11.646720886230469 ], [ "▁Linux", -11.646759033203125 ], [ "▁ポンプ", -11.646831512451172 ], [ "1971", -11.647040367126465 ], [ "pi", -11.647136688232422 ], [ "▁吸い", -11.647177696228027 ], [ "ポル", -11.647258758544922 ], [ "▁1934", -11.647375106811523 ], [ "▁SEX", -11.647404670715332 ], [ "▁隔", -11.64752197265625 ], [ "▁重大な", -11.647645950317383 ], [ "▁難民", -11.647650718688965 ], [ "▁109", -11.647753715515137 ], [ "ire", -11.647757530212402 ], [ "▁預金", -11.647854804992676 ], [ "▁蛇", -11.647961616516113 ], [ "▁風味", -11.647964477539062 ], [ "▁袖", -11.648265838623047 ], [ "▁詰", -11.64869499206543 ], [ "▁ハマ", -11.648776054382324 ], [ "▁股", -11.648911476135254 ], [ "▁一面", -11.64893913269043 ], [ "んこ", -11.64930534362793 ], [ "ger", -11.649312973022461 ], [ "▁リモート", -11.649321556091309 ], [ "▁——", -11.64952278137207 ], [ "宴", -11.649542808532715 ], [ "▁エドワード", -11.649617195129395 ], [ "▁偉", -11.649670600891113 ], [ "▁車線", -11.649951934814453 ], [ "シマ", -11.649993896484375 ], [ "蓮", -11.650125503540039 ], [ "▁生じて", -11.650128364562988 ], [ "▁響", -11.650152206420898 ], [ "えば", -11.650388717651367 ], [ "▁成し", -11.650419235229492 ], [ "がわ", -11.650668144226074 ], [ "▁スタイリスト", -11.650700569152832 ], [ "▁us", -11.650821685791016 ], [ "▁Br", -11.650871276855469 ], [ "▁オフィシャル", -11.65109920501709 ], [ "▁ワクワク", -11.651111602783203 ], [ "▁1935", -11.651288986206055 ], [ "▁BO", -11.651420593261719 ], [ "▁オメガ", -11.651508331298828 ], [ "1976", -11.651809692382812 ], [ "NE", -11.652166366577148 ], [ "トゥー", -11.652442932128906 ], [ "▁ユニバーサル", -11.652478218078613 ], [ "もっとも", -11.652570724487305 ], [ "耳", -11.652785301208496 ], [ "▁電化", -11.652863502502441 ], [ "▁インナー", -11.652959823608398 ], [ "▁兼任", -11.653206825256348 ], [ "▁慶應", -11.653336524963379 ], [ "▁農林", -11.653369903564453 ], [ "▁水平", -11.653371810913086 ], [ "▁贈ら", -11.653511047363281 ], [ "▁牧場", -11.653716087341309 ], [ "シュー", -11.653820991516113 ], [ "▁物事", -11.654051780700684 ], [ "▁背後", -11.654123306274414 ], [ "▁早朝", -11.654312133789062 ], [ "UM", -11.65434455871582 ], [ "▁痩せ", -11.654397964477539 ], [ "▁イェ", -11.654656410217285 ], [ "▁pdf", -11.654683113098145 ], [ "▁外見", -11.654803276062012 ], [ "▁触", -11.655025482177734 ], [ "▁バリア", -11.655099868774414 ], [ "ばし", -11.655285835266113 ], [ "PI", -11.655294418334961 ], [ "▁1932", -11.655311584472656 ], [ "▁師範", -11.6554536819458 ], [ "▁踏まえ", -11.656288146972656 ], [ "▁楽譜", -11.656295776367188 ], [ "▁GI", -11.656323432922363 ], [ "▁開店", -11.656377792358398 ], [ "▁Air", -11.656618118286133 ], [ "EP", -11.656838417053223 ], [ "ビック", -11.656853675842285 ], [ "Amazon", -11.65689754486084 ], [ "▁オークション", -11.65699291229248 ], [ "タム", -11.65703010559082 ], [ "▁ファンド", -11.657444953918457 ], [ "▁改札", -11.65776252746582 ], [ "のち", -11.657984733581543 ], [ "▁PlayStation", -11.657995223999023 ], [ "▁従う", -11.658028602600098 ], [ "▁人格", -11.658303260803223 ], [ "紀元", -11.658553123474121 ], [ "▁近江", -11.658592224121094 ], [ "▁長女", -11.658644676208496 ], [ "中華民国", -11.658714294433594 ], [ "▁臭", -11.658732414245605 ], [ "腺", -11.658848762512207 ], [ "▁野村", -11.658927917480469 ], [ "▁ありがたい", -11.658987045288086 ], [ "▁残留", -11.659025192260742 ], [ "終", -11.659027099609375 ], [ "▁ガイ", -11.659079551696777 ], [ "▁独自に", -11.659191131591797 ], [ "亜", -11.65932559967041 ], [ "▁BR", -11.65936279296875 ], [ "▁稼いで", -11.659468650817871 ], [ "▁濃", -11.6595458984375 ], [ "▁いよいよ", -11.659564018249512 ], [ "▁ラック", -11.659570693969727 ], [ "▁気筒", -11.65968132019043 ], [ "▁可愛", -11.659956932067871 ], [ "▁エレベーター", -11.659957885742188 ], [ "▁みや", -11.660174369812012 ], [ "▁出血", -11.660178184509277 ], [ "▁会合", -11.660199165344238 ], [ "▁ON", -11.660276412963867 ], [ "▁プリンス", -11.660305976867676 ], [ "▁催", -11.660451889038086 ], [ "▁晋", -11.66075325012207 ], [ "▁冷却", -11.660770416259766 ], [ "▁VS", -11.660778045654297 ], [ "ミール", -11.66081428527832 ], [ "▁パーソナル", -11.660919189453125 ], [ "▁継ぎ", -11.661062240600586 ], [ "▁変異", -11.661288261413574 ], [ "▁開校", -11.661805152893066 ], [ "スーパー", -11.661993026733398 ], [ "ぽ", -11.66207504272461 ], [ "▁五十", -11.66243839263916 ], [ "▁広げて", -11.662590026855469 ], [ "▁まん", -11.662642478942871 ], [ "▁格好", -11.662799835205078 ], [ "であれば", -11.662949562072754 ], [ "▁210", -11.663190841674805 ], [ "▁快適", -11.663298606872559 ], [ "▁京王", -11.663333892822266 ], [ "▁ふと", -11.663397789001465 ], [ "▁System", -11.663444519042969 ], [ "▁落下", -11.663481712341309 ], [ "▁どっち", -11.663521766662598 ], [ "▁公社", -11.663553237915039 ], [ "イロ", -11.663615226745605 ], [ "ONE", -11.663640022277832 ], [ "▁札", -11.663945198059082 ], [ "▁石井", -11.663999557495117 ], [ "▁are", -11.664102554321289 ], [ "▁フロリダ", -11.664185523986816 ], [ "ヨーロッパ", -11.66434097290039 ], [ "ess", -11.66441535949707 ], [ "▁綴", -11.664454460144043 ], [ "鳳", -11.664461135864258 ], [ "▁忍", -11.664615631103516 ], [ "下げ", -11.664728164672852 ], [ "植", -11.664795875549316 ], [ "1974", -11.664860725402832 ], [ "咲", -11.664922714233398 ], [ "ult", -11.66502857208252 ], [ "梅", -11.665101051330566 ], [ "▁道場", -11.665132522583008 ], [ "▁光景", -11.665193557739258 ], [ "▁起点", -11.665279388427734 ], [ "りん", -11.665366172790527 ], [ "▁インフルエンザ", -11.665419578552246 ], [ "▁キャプテン", -11.665422439575195 ], [ "▁院長", -11.665584564208984 ], [ "▁神田", -11.665599822998047 ], [ "▁為替", -11.66585636138916 ], [ "ical", -11.66598129272461 ], [ "サービス", -11.665987968444824 ], [ "TP", -11.666155815124512 ], [ "▁ラッセル", -11.666418075561523 ], [ "づく", -11.666481971740723 ], [ "▁貝", -11.666486740112305 ], [ "▁ネック", -11.666496276855469 ], [ "▁公的", -11.666536331176758 ], [ "▁答える", -11.666654586791992 ], [ "▁武蔵", -11.66700267791748 ], [ "ピング", -11.667009353637695 ], [ "▁応答", -11.667014122009277 ], [ "▁通報", -11.667070388793945 ], [ "ケース", -11.667240142822266 ], [ "▁絆", -11.667651176452637 ], [ "▁落とす", -11.667691230773926 ], [ "▁リボン", -11.667729377746582 ], [ "▁据え", -11.667791366577148 ], [ "▁味噌", -11.667829513549805 ], [ "AY", -11.668023109436035 ], [ "ノフ", -11.668185234069824 ], [ "▁礼拝", -11.668248176574707 ], [ "▁内戦", -11.668299674987793 ], [ "疑", -11.668420791625977 ], [ "▁癖", -11.668645858764648 ], [ "▁起訴", -11.668815612792969 ], [ "晴", -11.668927192687988 ], [ "▁トータル", -11.669055938720703 ], [ "▁ボブ", -11.669058799743652 ], [ "▁八王子", -11.669201850891113 ], [ "▁総長", -11.66930103302002 ], [ "リティ", -11.669303894042969 ], [ "嗣", -11.669344902038574 ], [ "▁伸びて", -11.669438362121582 ], [ "▁基づいた", -11.669690132141113 ], [ "▁排気", -11.670069694519043 ], [ "▁捜索", -11.670104026794434 ], [ "ヒト", -11.670127868652344 ], [ "▁果実", -11.670231819152832 ], [ "yo", -11.670352935791016 ], [ "▁LP", -11.670378684997559 ], [ "▁トーマス", -11.670442581176758 ], [ "▁アウ", -11.67052173614502 ], [ "▁幹", -11.670527458190918 ], [ "ビュ", -11.670538902282715 ], [ "▁瑞", -11.670610427856445 ], [ "▁唇", -11.670620918273926 ], [ "▁進路", -11.670744895935059 ], [ "払い", -11.670910835266113 ], [ "▁落ち着いた", -11.671097755432129 ], [ "▁掛", -11.671236038208008 ], [ "▁プロイセン", -11.671302795410156 ], [ "▁スピ", -11.671353340148926 ], [ "▁税理士", -11.671551704406738 ], [ "最も", -11.671560287475586 ], [ "ユーザー", -11.671656608581543 ], [ "パリ", -11.67173957824707 ], [ "▁疎", -11.671781539916992 ], [ "▁暴", -11.671783447265625 ], [ "▁拡散", -11.671831130981445 ], [ "ans", -11.672109603881836 ], [ "がき", -11.672195434570312 ], [ "▁介", -11.6723051071167 ], [ "▁瓦", -11.672451972961426 ], [ "▁監修", -11.672452926635742 ], [ "CP", -11.67250919342041 ], [ "ホテル", -11.672554016113281 ], [ "卒", -11.672605514526367 ], [ "if", -11.672647476196289 ], [ "▁サンデー", -11.6728515625 ], [ "▁ABC", -11.672871589660645 ], [ "▁救済", -11.672874450683594 ], [ "▁辻", -11.67293643951416 ], [ "富士", -11.672961235046387 ], [ "▁低迷", -11.67301082611084 ], [ "▁ミッド", -11.673091888427734 ], [ "▁なくなる", -11.673443794250488 ], [ "▁取り入れて", -11.673479080200195 ], [ "▁木製", -11.67365550994873 ], [ "ビュー", -11.674084663391113 ], [ "惑", -11.674145698547363 ], [ "▁フェル", -11.674229621887207 ], [ "▁掲げ", -11.674328804016113 ], [ "▁福山", -11.674753189086914 ], [ "...", -11.674910545349121 ], [ "▁アサ", -11.674965858459473 ], [ "dd", -11.675037384033203 ], [ "▁孤独", -11.67508602142334 ], [ "▁切断", -11.675267219543457 ], [ "ッキング", -11.675286293029785 ], [ "プト", -11.675375938415527 ], [ "ash", -11.675518035888672 ], [ "リーズ", -11.675564765930176 ], [ "▁紐", -11.675617218017578 ], [ "にも", -11.675642967224121 ], [ "▁北区", -11.67566967010498 ], [ "がった", -11.675910949707031 ], [ "▁考古", -11.676007270812988 ], [ "迷", -11.676115036010742 ], [ "ゲー", -11.676398277282715 ], [ "▁植", -11.676405906677246 ], [ "▁CC", -11.67650318145752 ], [ "▁明記", -11.676734924316406 ], [ "▁BGM", -11.676750183105469 ], [ "テラ", -11.676774978637695 ], [ "▁ac", -11.676836967468262 ], [ "▁最強の", -11.67725944519043 ], [ "▁づらい", -11.677308082580566 ], [ "RS", -11.677526473999023 ], [ "▁解明", -11.677632331848145 ], [ "サウルス", -11.677658081054688 ], [ "▁当たり前", -11.677749633789062 ], [ "▁箱根", -11.677827835083008 ], [ "▁序", -11.677896499633789 ], [ "▁あつ", -11.677948951721191 ], [ "▁遺言", -11.678077697753906 ], [ "▁フィート", -11.678094863891602 ], [ "▁講じ", -11.678308486938477 ], [ "漫画", -11.67835807800293 ], [ "▁大坂", -11.67836856842041 ], [ "▁譲", -11.678462982177734 ], [ "AST", -11.678815841674805 ], [ "適", -11.678823471069336 ], [ "▁記して", -11.679001808166504 ], [ "▁文句", -11.67904281616211 ], [ "▁刑務所", -11.679255485534668 ], [ "▁会った", -11.67927360534668 ], [ "衝", -11.679300308227539 ], [ "▁なんとなく", -11.679320335388184 ], [ "VA", -11.679616928100586 ], [ "▁携わる", -11.67995834350586 ], [ "虎", -11.679963111877441 ], [ "▁後日", -11.680011749267578 ], [ "▁肯定", -11.680091857910156 ], [ "だろう", -11.680291175842285 ], [ "▁クオリティ", -11.680302619934082 ], [ "▁グラビア", -11.680619239807129 ], [ "?", -11.68066120147705 ], [ "▁景気", -11.680795669555664 ], [ "俊", -11.680798530578613 ], [ "とにかく", -11.681086540222168 ], [ "静岡", -11.681305885314941 ], [ "▁ちゃ", -11.681601524353027 ], [ "そのほか", -11.68166446685791 ], [ "▁定数", -11.681741714477539 ], [ "▁di", -11.681828498840332 ], [ "ディス", -11.681939125061035 ], [ "▁管区", -11.682242393493652 ], [ "1968", -11.682353973388672 ], [ "よって", -11.682376861572266 ], [ "iPhone", -11.682421684265137 ], [ "▁固有", -11.682433128356934 ], [ "エール", -11.682490348815918 ], [ "▁至", -11.682497024536133 ], [ "嘉", -11.682650566101074 ], [ "▁下着", -11.682662010192871 ], [ "レム", -11.683034896850586 ], [ "▁巡る", -11.683064460754395 ], [ "▁野田", -11.683431625366211 ], [ "▁大地", -11.683574676513672 ], [ "▁一応", -11.68371295928955 ], [ "▁アフター", -11.683734893798828 ], [ "▁ベー", -11.683744430541992 ], [ "▁模索", -11.683793067932129 ], [ "モノ", -11.684267044067383 ], [ "▁プレーオフ", -11.68429946899414 ], [ "▁ランニング", -11.684350967407227 ], [ "罪", -11.684369087219238 ], [ "▁Art", -11.6845064163208 ], [ "▁OL", -11.684615135192871 ], [ "▁適して", -11.684673309326172 ], [ "▁水上", -11.684798240661621 ], [ "▁上杉", -11.684879302978516 ], [ "問題", -11.684983253479004 ], [ "▁番手", -11.685160636901855 ], [ "▁聴", -11.685245513916016 ], [ "タグ", -11.685308456420898 ], [ "耶", -11.685332298278809 ], [ "故", -11.685343742370605 ], [ "mer", -11.685399055480957 ], [ "▁房", -11.685402870178223 ], [ "▁骨折", -11.68546199798584 ], [ "ヌー", -11.685465812683105 ], [ "▁机", -11.685572624206543 ], [ "▁残業", -11.685616493225098 ], [ "▁衣", -11.685746192932129 ], [ "▁AKB", -11.685829162597656 ], [ "▁見なさ", -11.685837745666504 ], [ "ino", -11.68593978881836 ], [ "政治", -11.686055183410645 ], [ "▁チベット", -11.686134338378906 ], [ "▁坂本", -11.686188697814941 ], [ "▁アニ", -11.686455726623535 ], [ "▁自然な", -11.68654727935791 ], [ "▁手配", -11.686573028564453 ], [ "承", -11.686579704284668 ], [ "兵庫", -11.68662166595459 ], [ "▁単純", -11.686666488647461 ], [ "▁組み合わせた", -11.686983108520508 ], [ "▁鈴", -11.68699836730957 ], [ "1977", -11.687061309814453 ], [ "▁山頂", -11.687104225158691 ], [ "▁乱れ", -11.68712329864502 ], [ "▁ハードウェア", -11.687126159667969 ], [ "バート", -11.687174797058105 ], [ "av", -11.687291145324707 ], [ "▁出生", -11.68748664855957 ], [ "▁もたらした", -11.68751049041748 ], [ "▁幼少", -11.687539100646973 ], [ "▁it", -11.687544822692871 ], [ "lus", -11.687843322753906 ], [ "po", -11.687895774841309 ], [ "▁沢山の", -11.687957763671875 ], [ "▁空手", -11.687980651855469 ], [ "▁親友", -11.688066482543945 ], [ "▁好きだ", -11.688079833984375 ], [ "副", -11.688143730163574 ], [ "初代", -11.688164710998535 ], [ "▁なー", -11.688212394714355 ], [ "sy", -11.68862247467041 ], [ "▁調和", -11.688679695129395 ], [ "レックス", -11.688923835754395 ], [ "▁ブラシ", -11.689298629760742 ], [ "▁クイーン", -11.689315795898438 ], [ "han", -11.689509391784668 ], [ "▁届いた", -11.689532279968262 ], [ "当然", -11.68954849243164 ], [ "▁ふる", -11.689569473266602 ], [ "▁楽しかった", -11.689620971679688 ], [ "鎮", -11.689641952514648 ], [ "洞", -11.689648628234863 ], [ "▁切った", -11.68986701965332 ], [ "▁土佐", -11.689896583557129 ], [ "ブルー", -11.689912796020508 ], [ "Book", -11.690123558044434 ], [ "湿", -11.690131187438965 ], [ "▁出向", -11.690168380737305 ], [ "▁ヒュー", -11.69023323059082 ], [ "▁組み合わせて", -11.690293312072754 ], [ "▁幼い", -11.690566062927246 ], [ "▁app", -11.690775871276855 ], [ "▁姉さん", -11.690815925598145 ], [ "▁450", -11.690824508666992 ], [ "一番", -11.690832138061523 ], [ "▁DF", -11.690999984741211 ], [ "電子", -11.691019058227539 ], [ "▁海戦", -11.691023826599121 ], [ "▁やりとり", -11.691027641296387 ], [ "▁一生懸命", -11.691094398498535 ], [ "▁清潔", -11.69112491607666 ], [ "▁グッド", -11.691128730773926 ], [ "庁", -11.69115161895752 ], [ "▁ソル", -11.69120979309082 ], [ "構", -11.691367149353027 ], [ "▁プラザ", -11.691624641418457 ], [ "▁ベクトル", -11.69166088104248 ], [ "▁宛", -11.691804885864258 ], [ "きょう", -11.692086219787598 ], [ "▁領主", -11.69212818145752 ], [ "伯", -11.692243576049805 ], [ "▁満了", -11.69224739074707 ], [ "▁イカ", -11.692255020141602 ], [ "by", -11.692306518554688 ], [ "▁シード", -11.692375183105469 ], [ "▁オリコン", -11.692434310913086 ], [ "▁整え", -11.692535400390625 ], [ "加えて", -11.692558288574219 ], [ "▁多分", -11.692612648010254 ], [ "log", -11.692626953125 ], [ "▁動脈", -11.692672729492188 ], [ "▁▲", -11.692869186401367 ], [ "胞", -11.693111419677734 ], [ "▁IBM", -11.693166732788086 ], [ "▁ボク", -11.693465232849121 ], [ "▁傍", -11.6935396194458 ], [ "▁達し", -11.693866729736328 ], [ "▁ワイルド", -11.694183349609375 ], [ "own", -11.69426441192627 ], [ "▁ナンパ", -11.694565773010254 ], [ "▁ブリッジ", -11.694693565368652 ], [ "マール", -11.694744110107422 ], [ "▁ドロップ", -11.694921493530273 ], [ "▁腰痛", -11.695014953613281 ], [ "ata", -11.695295333862305 ], [ "▁バス停", -11.695422172546387 ], [ "▁仲良く", -11.695700645446777 ], [ "背景", -11.695706367492676 ], [ "▁体感", -11.695718765258789 ], [ "SH", -11.695819854736328 ], [ "▁芽", -11.695917129516602 ], [ "ZA", -11.696003913879395 ], [ "▁屈", -11.696188926696777 ], [ "▁効", -11.69650650024414 ], [ "ous", -11.69662857055664 ], [ "▁なんでも", -11.696721076965332 ], [ "▁集まった", -11.696792602539062 ], [ "写", -11.696795463562012 ], [ "世帯", -11.6968355178833 ], [ "▁心身", -11.696952819824219 ], [ "▁斉", -11.696986198425293 ], [ "▁遂行", -11.69703483581543 ], [ "▁なかったら", -11.697129249572754 ], [ "▁終えて", -11.6972074508667 ], [ "1969", -11.697269439697266 ], [ "▁摂", -11.697278022766113 ], [ "▁店長", -11.69728946685791 ], [ "抜け", -11.697698593139648 ], [ "▁襲わ", -11.697888374328613 ], [ "▁熱帯", -11.698073387145996 ], [ "ama", -11.698112487792969 ], [ "▁台詞", -11.698168754577637 ], [ "▁稽古", -11.698311805725098 ], [ "AB", -11.698479652404785 ], [ "▁望んで", -11.698500633239746 ], [ "▁明らか", -11.69876766204834 ], [ "▁固め", -11.6988525390625 ], [ "▁英文", -11.698954582214355 ], [ "エラ", -11.698987007141113 ], [ "▁1928", -11.699042320251465 ], [ "ほう", -11.699563980102539 ], [ "▁シェー", -11.699862480163574 ], [ "▁世田谷", -11.699875831604004 ], [ "▁ひどい", -11.700326919555664 ], [ "▁同じで", -11.700453758239746 ], [ "▁ドキュメント", -11.700728416442871 ], [ "▁担保", -11.700825691223145 ], [ "▁なっちゃ", -11.700843811035156 ], [ "▁尺", -11.700995445251465 ], [ "▁CEO", -11.701087951660156 ], [ "▁しま", -11.70115852355957 ], [ "▁我が家", -11.701247215270996 ], [ "▁税務", -11.701311111450195 ], [ "▁間接", -11.701443672180176 ], [ "チェン", -11.701655387878418 ], [ "▁甲板", -11.701717376708984 ], [ "▁◇", -11.701735496520996 ], [ "▁異性", -11.701750755310059 ], [ "▁ベンチャー", -11.702077865600586 ], [ "▁ビン", -11.702123641967773 ], [ "▁鷹", -11.70213508605957 ], [ "▁音響", -11.702343940734863 ], [ "▁MLB", -11.702350616455078 ], [ "▁定めた", -11.702475547790527 ], [ "キス", -11.70254898071289 ], [ "栗", -11.702696800231934 ], [ "▁勝つ", -11.702779769897461 ], [ "▁徴収", -11.70323371887207 ], [ "ホル", -11.703314781188965 ], [ "▁だらけ", -11.703316688537598 ], [ "▁立川", -11.703354835510254 ], [ "▁庶民", -11.703935623168945 ], [ "EG", -11.704042434692383 ], [ "▁LOVE", -11.704145431518555 ], [ "▁三角", -11.704338073730469 ], [ "▁謝", -11.70444393157959 ], [ "▁叩き", -11.704506874084473 ], [ "▁1931", -11.70451545715332 ], [ "恋", -11.704560279846191 ], [ "▁直す", -11.704607963562012 ], [ "▁ステンレス", -11.704721450805664 ], [ "▁数量", -11.704977035522461 ], [ "▁眼鏡", -11.70502758026123 ], [ "▁傍ら", -11.70507526397705 ], [ "yl", -11.705225944519043 ], [ "▁レグノ", -11.7055082321167 ], [ "▁中隊", -11.70563793182373 ], [ "tr", -11.705667495727539 ], [ "YO", -11.705697059631348 ], [ "▁仮説", -11.705711364746094 ], [ "▁ろ", -11.705979347229004 ], [ "▁宝石", -11.706052780151367 ], [ "▁史跡", -11.706083297729492 ], [ "▁参画", -11.706185340881348 ], [ "▁民俗", -11.706257820129395 ], [ "▁借入", -11.706306457519531 ], [ "シリ", -11.70633316040039 ], [ "▁お伺い", -11.706365585327148 ], [ "▁再発", -11.706414222717285 ], [ "導", -11.706526756286621 ], [ "撮影", -11.706669807434082 ], [ "電話", -11.706718444824219 ], [ "In", -11.706801414489746 ], [ "▁観戦", -11.70700740814209 ], [ "▁戦前", -11.707096099853516 ], [ "▁称して", -11.707158088684082 ], [ "▁不便", -11.707183837890625 ], [ "view", -11.707202911376953 ], [ "▁タイムズ", -11.707262992858887 ], [ "▁育毛", -11.70728588104248 ], [ "▁Rayong", -11.707296371459961 ], [ "仕", -11.707380294799805 ], [ "▁近づいて", -11.707557678222656 ], [ "VE", -11.707588195800781 ], [ "▁固", -11.707588195800781 ], [ "ii", -11.70760726928711 ], [ "▁アーカイブ", -11.7076416015625 ], [ "▁β", -11.70767593383789 ], [ "▁魔術", -11.70784854888916 ], [ "▁プライム", -11.707855224609375 ], [ "▁働", -11.707866668701172 ], [ "▁POP", -11.707937240600586 ], [ "▁..", -11.708242416381836 ], [ "▁ルーマニア", -11.708246231079102 ], [ "▁鹿島", -11.708272933959961 ], [ "GE", -11.70848274230957 ], [ "▁アフ", -11.708547592163086 ], [ "SU", -11.708649635314941 ], [ "▁統括", -11.708733558654785 ], [ "▁加賀", -11.708765029907227 ], [ "▁慣れ", -11.708795547485352 ], [ "柔", -11.708800315856934 ], [ "査", -11.708873748779297 ], [ "アド", -11.708930015563965 ], [ "▁エリザベス", -11.708930969238281 ], [ "▁得に", -11.709107398986816 ], [ "▁Sp", -11.709161758422852 ], [ "ike", -11.70920181274414 ], [ "▁目覚め", -11.709623336791992 ], [ "スキ", -11.709625244140625 ], [ "▁映", -11.70979118347168 ], [ "▁公衆", -11.709911346435547 ], [ "▁複雑", -11.70997142791748 ], [ "激", -11.710136413574219 ], [ "▁まわり", -11.710307121276855 ], [ "浪", -11.710359573364258 ], [ "最初に", -11.710518836975098 ], [ "▁雇", -11.710564613342285 ], [ "▁狙って", -11.710590362548828 ], [ "▁境内", -11.710638046264648 ], [ "さく", -11.710859298706055 ], [ "ドリー", -11.711077690124512 ], [ "▁ヨー", -11.711112022399902 ], [ "▁アイランド", -11.711162567138672 ], [ "▁リソース", -11.71143627166748 ], [ "主人公", -11.71158504486084 ], [ "▁志望", -11.71174430847168 ], [ "▁人文", -11.711922645568848 ], [ "コイ", -11.711965560913086 ], [ "▁後藤", -11.71203899383545 ], [ "振", -11.712455749511719 ], [ "EI", -11.712604522705078 ], [ "▁公爵", -11.712631225585938 ], [ "奇", -11.712873458862305 ], [ "▁ベージュ", -11.71291732788086 ], [ "▁FF", -11.712991714477539 ], [ "ディオ", -11.712997436523438 ], [ "ギャ", -11.713068962097168 ], [ "▁WiFi", -11.713187217712402 ], [ "▁斬", -11.7132568359375 ], [ "▁しまえば", -11.713269233703613 ], [ "▁1929", -11.713310241699219 ], [ "▁所定", -11.713508605957031 ], [ "▁返して", -11.713508605957031 ], [ "▁驚いた", -11.713528633117676 ], [ "ound", -11.713656425476074 ], [ "▁あんな", -11.713666915893555 ], [ "RU", -11.713750839233398 ], [ "築", -11.713788986206055 ], [ "▁注射", -11.71387767791748 ], [ "▁愛して", -11.713883399963379 ], [ "▁官房", -11.714021682739258 ], [ "▁ぱ", -11.714070320129395 ], [ "▁クルマ", -11.714138984680176 ], [ "▁秦", -11.71425724029541 ], [ "▁蓋", -11.714286804199219 ], [ "▁東宝", -11.714588165283203 ], [ "▁ちなんで", -11.714774131774902 ], [ "父親", -11.714859962463379 ], [ "▁停留所", -11.71491813659668 ], [ "▁SL", -11.714987754821777 ], [ "▁虐待", -11.714990615844727 ], [ "▁アキ", -11.715079307556152 ], [ "▁乗った", -11.715577125549316 ], [ "▁少々", -11.715636253356934 ], [ "▁内務", -11.715678215026855 ], [ "前述", -11.715744972229004 ], [ "々しい", -11.7162504196167 ], [ "扱", -11.71630859375 ], [ "▁CL", -11.716325759887695 ], [ "▁討", -11.716395378112793 ], [ "▁遅延", -11.716449737548828 ], [ "ミニ", -11.716535568237305 ], [ "整", -11.716586112976074 ], [ "▁親王", -11.716638565063477 ], [ "▁東芝", -11.716700553894043 ], [ "▁公募", -11.716750144958496 ], [ "▁製薬", -11.716878890991211 ], [ "^)", -11.717002868652344 ], [ "とり", -11.717048645019531 ], [ "▁平面", -11.717294692993164 ], [ "▁セイコー", -11.717429161071777 ], [ "シリーズ", -11.717513084411621 ], [ "ニュース", -11.717820167541504 ], [ "▁着陸", -11.717907905578613 ], [ "店舗", -11.717947006225586 ], [ "原作", -11.718125343322754 ], [ "▁合法", -11.718267440795898 ], [ "▁リレー", -11.718341827392578 ], [ "▁フィン", -11.718354225158691 ], [ "すでに", -11.718360900878906 ], [ "ベイ", -11.7184419631958 ], [ "▁喜ば", -11.718478202819824 ], [ "▁NBA", -11.71848201751709 ], [ "▁壁紙", -11.718588829040527 ], [ "▁下流", -11.718902587890625 ], [ "▁命じた", -11.718990325927734 ], [ "▁消", -11.719006538391113 ], [ "▁mo", -11.719491004943848 ], [ "吐", -11.71954345703125 ], [ "▁タル", -11.719558715820312 ], [ "а", -11.719764709472656 ], [ "▁重要である", -11.719765663146973 ], [ "えき", -11.719789505004883 ], [ "▁簿", -11.719958305358887 ], [ "さき", -11.720001220703125 ], [ "▁重力", -11.72021198272705 ], [ "▁育った", -11.720368385314941 ], [ "▁なす", -11.720377922058105 ], [ "▁標的", -11.720518112182617 ], [ "▁フィリップ", -11.720560073852539 ], [ "▁契機", -11.720563888549805 ], [ "▁フラッシュ", -11.720569610595703 ], [ "▁捕らえ", -11.720715522766113 ], [ "思い", -11.72075080871582 ], [ "▁出雲", -11.720778465270996 ], [ "▁Jo", -11.720845222473145 ], [ "▁満州", -11.720932960510254 ], [ "▁繋がって", -11.721006393432617 ], [ "▁目指した", -11.721162796020508 ], [ "▁日野", -11.721473693847656 ], [ "▁緑色", -11.721595764160156 ], [ "▁標", -11.721674919128418 ], [ "▁バルセロナ", -11.72174072265625 ], [ "しばらく", -11.72179126739502 ], [ "▁身近な", -11.721943855285645 ], [ "血液型", -11.722023010253906 ], [ "荘", -11.722064971923828 ], [ "▁叔父", -11.722162246704102 ], [ "▁ポーズ", -11.72226619720459 ], [ "舞台", -11.72234058380127 ], [ "サス", -11.722393035888672 ], [ "ぶん", -11.722575187683105 ], [ "▁適正", -11.722589492797852 ], [ "▁弦", -11.722631454467773 ], [ "▁流さ", -11.722908020019531 ], [ "▁ライブラリ", -11.722930908203125 ], [ "▁電磁", -11.722996711730957 ], [ "▁PukiWiki", -11.723034858703613 ], [ "この際", -11.723122596740723 ], [ "▁間もなく", -11.723161697387695 ], [ "▁ミン", -11.723344802856445 ], [ "▁贈り物", -11.723367691040039 ], [ "債", -11.723579406738281 ], [ "▁逸", -11.72367000579834 ], [ "sion", -11.723748207092285 ], [ "▁クリエイター", -11.723804473876953 ], [ "泰", -11.723919868469238 ], [ "▁探索", -11.724064826965332 ], [ "▁運河", -11.72463607788086 ], [ "▁他者", -11.724640846252441 ], [ "斑", -11.724928855895996 ], [ "滝", -11.72509479522705 ], [ "▁賭け", -11.725259780883789 ], [ "熊", -11.725275993347168 ], [ "▁環状", -11.7252836227417 ], [ "▁褐色", -11.725366592407227 ], [ "▁ストック", -11.72538948059082 ], [ "▁働いた", -11.72539234161377 ], [ "▁公正", -11.725408554077148 ], [ "▁飛んで", -11.725442886352539 ], [ "▁リトル", -11.725457191467285 ], [ "▁狩り", -11.725890159606934 ], [ "▁浮上", -11.725957870483398 ], [ "▁豪華", -11.726005554199219 ], [ "五郎", -11.726152420043945 ], [ "▁スナック", -11.726163864135742 ], [ "バード", -11.726451873779297 ], [ "▁ONE", -11.726455688476562 ], [ "▁Man", -11.726683616638184 ], [ "▁We", -11.72671127319336 ], [ "▁ロッテ", -11.726943969726562 ], [ "▁迷って", -11.726975440979004 ], [ "ale", -11.727029800415039 ], [ "▁SI", -11.727240562438965 ], [ "▁きり", -11.727275848388672 ], [ "▁ヘン", -11.727588653564453 ], [ "▁前進", -11.727588653564453 ], [ "▁抜いて", -11.727696418762207 ], [ "▼", -11.727821350097656 ], [ "▁退社", -11.72787094116211 ], [ "テッド", -11.727959632873535 ], [ "巣", -11.728020668029785 ], [ "▁救援", -11.728073120117188 ], [ "▁衛", -11.728263854980469 ], [ "けい", -11.728461265563965 ], [ "TR", -11.728641510009766 ], [ "▁バイエルン", -11.728731155395508 ], [ "tion", -11.728893280029297 ], [ "▁別名", -11.728925704956055 ], [ "▁艶", -11.729008674621582 ], [ "熟", -11.729016304016113 ], [ "▁暇", -11.72921085357666 ], [ "古代", -11.729259490966797 ], [ "▁ウィルス", -11.729290962219238 ], [ "▁石炭", -11.729668617248535 ], [ "サイズ", -11.729679107666016 ], [ "笠", -11.729736328125 ], [ "▁ヴァイオリン", -11.729799270629883 ], [ "^_^", -11.72989559173584 ], [ "▁控除", -11.729971885681152 ], [ "▁たん", -11.730027198791504 ], [ "▁飯田", -11.730182647705078 ], [ "▁スロー", -11.7304105758667 ], [ "▁爵位", -11.730411529541016 ], [ "▁稀", -11.730714797973633 ], [ "▁ちょ", -11.730838775634766 ], [ "▁っと", -11.731120109558105 ], [ "ソル", -11.73114013671875 ], [ "▁天正", -11.731173515319824 ], [ "▁暗い", -11.731406211853027 ], [ "▁買わ", -11.731466293334961 ], [ "5,000", -11.731467247009277 ], [ "キャン", -11.731549263000488 ], [ "▁使命", -11.731645584106445 ], [ "▁大西洋", -11.731993675231934 ], [ "▁包ま", -11.731999397277832 ], [ "▁電流", -11.732177734375 ], [ "賢", -11.732528686523438 ], [ "▁県民", -11.732532501220703 ], [ "▁支払わ", -11.732641220092773 ], [ "▁不十分", -11.732686996459961 ], [ "▁喧嘩", -11.732686996459961 ], [ "▁ヶ所", -11.732854843139648 ], [ "▁不在", -11.733016967773438 ], [ "敬", -11.73302936553955 ], [ "グマ", -11.733113288879395 ], [ "違", -11.733123779296875 ], [ "dr", -11.733206748962402 ], [ "尿", -11.73330020904541 ], [ "▁イス", -11.73343276977539 ], [ "▁昼間", -11.733516693115234 ], [ "ALL", -11.733556747436523 ], [ "▁備える", -11.73377799987793 ], [ "▁諏訪", -11.733938217163086 ], [ "選択", -11.733962059020996 ], [ "▁褒め", -11.733975410461426 ], [ "▁凄い", -11.733981132507324 ], [ "ach", -11.734086036682129 ], [ "▁耕", -11.73410701751709 ], [ "▁ふり", -11.734138488769531 ], [ "tro", -11.734325408935547 ], [ "▁初戦", -11.73434829711914 ], [ "▁吹", -11.734349250793457 ], [ "▁水泳", -11.734376907348633 ], [ "แ", -11.73437786102295 ], [ "▁引き出し", -11.734580993652344 ], [ "▁長岡", -11.734737396240234 ], [ "▁著しく", -11.734823226928711 ], [ "▁称する", -11.734894752502441 ], [ "▁しまったり", -11.734981536865234 ], [ "▁受け止め", -11.734981536865234 ], [ "▁不幸", -11.735098838806152 ], [ "▁ライヴ", -11.735371589660645 ], [ "way", -11.73547077178955 ], [ "▁たまたま", -11.735763549804688 ], [ "aka", -11.735857963562012 ], [ "▁ターボ", -11.735944747924805 ], [ "▁浪", -11.736114501953125 ], [ "卵", -11.736272811889648 ], [ "▁Office", -11.736371994018555 ], [ "▁AAA", -11.736401557922363 ], [ "▁チリ", -11.736592292785645 ], [ "▁尊敬", -11.73659896850586 ], [ "▁途上", -11.736738204956055 ], [ "les", -11.73681640625 ], [ "▁カーブ", -11.736832618713379 ], [ "▁幻想", -11.736837387084961 ], [ "▁野外", -11.736881256103516 ], [ "▁定理", -11.736970901489258 ], [ "ティブ", -11.737058639526367 ], [ "継", -11.737067222595215 ], [ "▁去", -11.737160682678223 ], [ "af", -11.737479209899902 ], [ "▁受け入れる", -11.737519264221191 ], [ "察", -11.738001823425293 ], [ "スティック", -11.73814582824707 ], [ "▁図り", -11.738149642944336 ], [ "▁わけだ", -11.738207817077637 ], [ "▁親族", -11.73824405670166 ], [ "アム", -11.738402366638184 ], [ "▁嬉しく", -11.738418579101562 ], [ "▁茎", -11.739232063293457 ], [ "▁究極", -11.739469528198242 ], [ "展", -11.739604949951172 ], [ "▁課金", -11.739778518676758 ], [ "▁バレンタイン", -11.739795684814453 ], [ "貫", -11.7400484085083 ], [ "▁取り寄せ", -11.740239143371582 ], [ "▁リメイク", -11.740409851074219 ], [ "▁アンチ", -11.74042797088623 ], [ "▁和解", -11.740459442138672 ], [ "▁そろそろ", -11.740673065185547 ], [ "替", -11.740882873535156 ], [ "SM", -11.74130630493164 ], [ "▁麦", -11.741390228271484 ], [ "▁促す", -11.741394996643066 ], [ "CL", -11.741753578186035 ], [ "ターズ", -11.741771697998047 ], [ "ics", -11.741926193237305 ], [ "=", -11.74205493927002 ], [ "▁アルゴリズム", -11.742283821105957 ], [ "▁覚える", -11.74239730834961 ], [ "幡", -11.742405891418457 ], [ "▁105", -11.742510795593262 ], [ "▁ジョンソン", -11.74281120300293 ], [ "▁変な", -11.742835998535156 ], [ "▁覚醒", -11.742879867553711 ], [ "▁降順", -11.742988586425781 ], [ "▁勧誘", -11.743026733398438 ], [ "▁スクリプト", -11.7431001663208 ], [ "▁度々", -11.743169784545898 ], [ "▁偵察", -11.74339771270752 ], [ "▁春日", -11.743427276611328 ], [ "ja", -11.743483543395996 ], [ "▁渋滞", -11.743621826171875 ], [ "▁振込", -11.743638038635254 ], [ "▁のだった", -11.743684768676758 ], [ "▁決戦", -11.743772506713867 ], [ "▁(^^)", -11.743846893310547 ], [ "▁艦長", -11.743931770324707 ], [ "▁演じ", -11.744094848632812 ], [ "PE", -11.744344711303711 ], [ "▁揚げ", -11.744453430175781 ], [ "▁精力", -11.744539260864258 ], [ "▁汁", -11.744715690612793 ], [ "由", -11.74472427368164 ], [ "ダウン", -11.744874000549316 ], [ "▁いざ", -11.744918823242188 ], [ "▁文法", -11.745475769042969 ], [ "▁ピッタリ", -11.745478630065918 ], [ "▁日産", -11.745552062988281 ], [ "▁デイリー", -11.74558162689209 ], [ "ier", -11.745681762695312 ], [ "▁盛期", -11.745720863342285 ], [ "▁丘陵", -11.745877265930176 ], [ "済", -11.745930671691895 ], [ "鏡", -11.746027946472168 ], [ "授", -11.746261596679688 ], [ "▁大田", -11.746354103088379 ], [ "▁新曲", -11.746381759643555 ], [ "▁姫路", -11.746426582336426 ], [ "→", -11.74664306640625 ], [ "gen", -11.746726036071777 ], [ "▁真理", -11.74679946899414 ], [ "▁欲", -11.746869087219238 ], [ "フェル", -11.746971130371094 ], [ "▁欠点", -11.74716567993164 ], [ "▁てん", -11.747479438781738 ], [ "デビュー", -11.747513771057129 ], [ "鑑", -11.747547149658203 ], [ "掲載", -11.7476224899292 ], [ "▁リンパ", -11.748025894165039 ], [ "ero", -11.74804973602295 ], [ "▁馬場", -11.748147964477539 ], [ "快", -11.748183250427246 ], [ "独", -11.74821662902832 ], [ "▁永遠", -11.748363494873047 ], [ "▁蒼", -11.748458862304688 ], [ "▁小田原", -11.748639106750488 ], [ "氷", -11.748727798461914 ], [ "▁スキ", -11.748779296875 ], [ "▁不安定", -11.748807907104492 ], [ "▁でしたら", -11.748924255371094 ], [ "▁種別", -11.749025344848633 ], [ "▁上旬", -11.749098777770996 ], [ "о", -11.749131202697754 ], [ "▁含める", -11.749157905578613 ], [ "たん", -11.749160766601562 ], [ "▁飲ま", -11.749432563781738 ], [ "▁ドリ", -11.749449729919434 ], [ "aku", -11.74975299835205 ], [ "▁μ", -11.749861717224121 ], [ "スリー", -11.750073432922363 ], [ "▁冬季", -11.750139236450195 ], [ "▁ハーブ", -11.750420570373535 ], [ "▁梁", -11.7508544921875 ], [ "▁両立", -11.750855445861816 ], [ "▁月曜", -11.750923156738281 ], [ "▁京成", -11.750934600830078 ], [ "そうした", -11.751009941101074 ], [ "▁2108", -11.751032829284668 ], [ "昭", -11.75109577178955 ], [ "▁輝く", -11.751104354858398 ], [ "欲", -11.751274108886719 ], [ "▁滅亡", -11.751379013061523 ], [ "ara", -11.751513481140137 ], [ "▁接客", -11.751551628112793 ], [ "▁水中", -11.751635551452637 ], [ "▁補強", -11.751797676086426 ], [ "▁MAX", -11.751832962036133 ], [ "かす", -11.752156257629395 ], [ "付き", -11.752176284790039 ], [ "薄", -11.752264022827148 ], [ "▁紫外線", -11.752266883850098 ], [ "▁セリフ", -11.75246810913086 ], [ "大人", -11.752496719360352 ], [ "▁フェリー", -11.752547264099121 ], [ "▁バグ", -11.752569198608398 ], [ "▁沼", -11.752715110778809 ], [ "▁白色", -11.75302505493164 ], [ "▁従軍", -11.753263473510742 ], [ "ペラ", -11.753339767456055 ], [ "▁自由な", -11.753347396850586 ], [ "we", -11.753570556640625 ], [ "▁信者", -11.753583908081055 ], [ "▁アナル", -11.753866195678711 ], [ "▁膨ら", -11.753999710083008 ], [ "▁ห", -11.754110336303711 ], [ "PH", -11.754146575927734 ], [ "▁撮る", -11.754252433776855 ], [ "▁Mon", -11.754316329956055 ], [ "▁移った", -11.754411697387695 ], [ "▁早速", -11.754427909851074 ], [ "▁ダンサー", -11.754691123962402 ], [ "▁ガリ", -11.754800796508789 ], [ "▁繁栄", -11.754842758178711 ], [ "▁平等", -11.754875183105469 ], [ "▁〒", -11.755023002624512 ], [ "ところで", -11.755069732666016 ], [ "▁之", -11.755107879638672 ], [ "tal", -11.755127906799316 ], [ "▁建国", -11.755192756652832 ], [ "▁天下", -11.75526237487793 ], [ "▁マルクス", -11.75532341003418 ], [ "▁うん", -11.755475044250488 ], [ "▁学名", -11.755483627319336 ], [ "▁Un", -11.755550384521484 ], [ "胎", -11.755576133728027 ], [ "▁EP", -11.755581855773926 ], [ "▁トリートメント", -11.755651473999023 ], [ "▁だんだん", -11.755727767944336 ], [ "▁山中", -11.755765914916992 ], [ "丈", -11.755767822265625 ], [ "▁決まる", -11.755880355834961 ], [ "衆", -11.755884170532227 ], [ "▁競", -11.755949974060059 ], [ "▁色んな", -11.75602912902832 ], [ "▁CP", -11.756040573120117 ], [ "ウイ", -11.756155967712402 ], [ "▁ぷ", -11.756254196166992 ], [ "▁救う", -11.756301879882812 ], [ "▁直ちに", -11.756404876708984 ], [ "▁ジャーナル", -11.756492614746094 ], [ "▁オファー", -11.756651878356934 ], [ "▁藤井", -11.756766319274902 ], [ "lan", -11.756778717041016 ], [ "▁本文", -11.756787300109863 ], [ "▁コットン", -11.756818771362305 ], [ "煙", -11.757068634033203 ], [ "蒲", -11.757157325744629 ], [ "▁協", -11.757187843322754 ], [ "▁果物", -11.757216453552246 ], [ "▁ぽっちゃり", -11.757430076599121 ], [ "▁個室", -11.757589340209961 ], [ "▁概ね", -11.757609367370605 ], [ "▁cbd", -11.757759094238281 ], [ "▁ジャクソン", -11.75836181640625 ], [ "▁ブドウ", -11.758400917053223 ], [ "▁テル", -11.75845718383789 ], [ "▁併", -11.758683204650879 ], [ "▁LA", -11.75877571105957 ], [ "▁サラダ", -11.758780479431152 ], [ "1964", -11.758810043334961 ], [ "▁教職", -11.758830070495605 ], [ "アク", -11.759032249450684 ], [ "プラス", -11.759088516235352 ], [ "▁琴", -11.759211540222168 ], [ "▁自律", -11.759410858154297 ], [ "▁だし", -11.759471893310547 ], [ "名称", -11.75955867767334 ], [ "▁盗塁", -11.759578704833984 ], [ "途中", -11.759827613830566 ], [ "str", -11.759903907775879 ], [ "珠", -11.760151863098145 ], [ "▁1900", -11.760233879089355 ], [ "▁眺め", -11.760272979736328 ], [ "▁南方", -11.760395050048828 ], [ "▁附", -11.760415077209473 ], [ "寝", -11.760597229003906 ], [ "▁標本", -11.760673522949219 ], [ "▁打つ", -11.760761260986328 ], [ "律", -11.76085376739502 ], [ "▁伺い", -11.760854721069336 ], [ "▁高崎", -11.760903358459473 ], [ "▁反論", -11.760986328125 ], [ "▁ウォ", -11.761102676391602 ], [ "▁レスラー", -11.761220932006836 ], [ "▁秀吉", -11.76123332977295 ], [ "▁久しぶりに", -11.761408805847168 ], [ "ニューヨーク", -11.761551856994629 ], [ "▁駐屯", -11.761611938476562 ], [ "▁去った", -11.761722564697266 ], [ "ひろ", -11.761727333068848 ], [ "▁Core", -11.76188850402832 ], [ "▁プロローグ", -11.761895179748535 ], [ "▁梱", -11.761980056762695 ], [ "▁ゲル", -11.76203727722168 ], [ "▁出入り", -11.76207447052002 ], [ "sk", -11.762261390686035 ], [ "▁エッセイ", -11.762297630310059 ], [ "▁引き継", -11.76234245300293 ], [ "抱", -11.76235294342041 ], [ "▁今月", -11.76236343383789 ], [ "貢", -11.76244068145752 ], [ "▁不全", -11.76248836517334 ], [ "▁BE", -11.762507438659668 ], [ "▁引き受け", -11.762697219848633 ], [ "▁わけに", -11.762702941894531 ], [ "ヴィア", -11.762927055358887 ], [ "Lock", -11.763002395629883 ], [ "▁あっ", -11.76301383972168 ], [ "幌", -11.763023376464844 ], [ "▁隙間", -11.763093948364258 ], [ "専", -11.763203620910645 ], [ "DO", -11.763283729553223 ], [ "▁那覇", -11.76342487335205 ], [ "▁発酵", -11.763513565063477 ], [ "ise", -11.763586044311523 ], [ "▁ランダム", -11.763800621032715 ], [ "AV", -11.763832092285156 ], [ "▁カルチャー", -11.763910293579102 ], [ "モンド", -11.763959884643555 ], [ "▁最短", -11.763986587524414 ], [ "▁可能だ", -11.764059066772461 ], [ "▁再婚", -11.764241218566895 ], [ "▁高層", -11.764253616333008 ], [ "▁望遠", -11.764423370361328 ], [ "▁∀", -11.764450073242188 ], [ "▁怖", -11.764469146728516 ], [ "▁羅", -11.764516830444336 ], [ "▁迫", -11.764564514160156 ], [ "1944", -11.764601707458496 ], [ "▁喉", -11.764649391174316 ], [ "▁長島", -11.764745712280273 ], [ "▁其", -11.765095710754395 ], [ "▁一同", -11.765481948852539 ], [ "▁荒川", -11.765546798706055 ], [ "▁4000", -11.765645980834961 ], [ "セス", -11.765654563903809 ], [ "▁ネイビー", -11.765746116638184 ], [ "▁運ば", -11.76587200164795 ], [ "▁マッケンジー", -11.765928268432617 ], [ "CI", -11.765992164611816 ], [ "▁動力", -11.766168594360352 ], [ "▁並べ", -11.766240119934082 ], [ "▁重ねる", -11.766280174255371 ], [ "▁辞職", -11.766559600830078 ], [ "▁見つかる", -11.766668319702148 ], [ "▁ヒトラー", -11.766743659973145 ], [ "duct", -11.766828536987305 ], [ "▁盛岡", -11.766947746276855 ], [ "自由", -11.767178535461426 ], [ "▁バター", -11.767243385314941 ], [ "▁遂げた", -11.767440795898438 ], [ "▁戻", -11.76744270324707 ], [ "▁ラグ", -11.767579078674316 ], [ "▁大蔵", -11.767748832702637 ], [ "わって", -11.767777442932129 ], [ "▁モチベーション", -11.76798152923584 ], [ "▁モリ", -11.76805305480957 ], [ "ぞう", -11.768186569213867 ], [ "▁死に", -11.768221855163574 ], [ "▁最上", -11.768372535705566 ], [ "▁抜く", -11.768484115600586 ], [ "っき", -11.76854419708252 ], [ "だからこそ", -11.768590927124023 ], [ "▁在位", -11.76859188079834 ], [ "ds", -11.768613815307617 ], [ "▁パッド", -11.768754959106445 ], [ "売り", -11.768765449523926 ], [ "▁アーム", -11.768853187561035 ], [ "ท", -11.76897144317627 ], [ "▁調べた", -11.768983840942383 ], [ "▁著名", -11.769278526306152 ], [ "▁アクセント", -11.769370079040527 ], [ "GI", -11.769384384155273 ], [ "▁挙", -11.76942253112793 ], [ "▁雌", -11.769423484802246 ], [ "▁1924", -11.769500732421875 ], [ "不動産", -11.769513130187988 ], [ "ビリティ", -11.769598007202148 ], [ "▁満点", -11.769612312316895 ], [ "アプリ", -11.769686698913574 ], [ "▁戦った", -11.769718170166016 ], [ "▁ヘンプ", -11.76972770690918 ], [ "ベリ", -11.769814491271973 ], [ "▁中東", -11.769816398620605 ], [ "宏", -11.769824981689453 ], [ "▁同行", -11.769993782043457 ], [ "▁あか", -11.770069122314453 ], [ "▁信濃", -11.770160675048828 ], [ "▁西区", -11.770185470581055 ], [ "▁恒星", -11.770230293273926 ], [ "新潟", -11.770337104797363 ], [ "▁ボルト", -11.770340919494629 ], [ "郵便", -11.770362854003906 ], [ "▁PL", -11.770462989807129 ], [ "▁ジョーンズ", -11.770546913146973 ], [ "hu", -11.770590782165527 ], [ "▁低減", -11.770635604858398 ], [ "クサ", -11.770641326904297 ], [ "▁1925", -11.770661354064941 ], [ "▁阿部", -11.770930290222168 ], [ "りゃ", -11.770992279052734 ], [ "▁船橋", -11.771215438842773 ], [ "▁Bo", -11.771462440490723 ], [ "しか", -11.771546363830566 ], [ "▁リッチ", -11.771682739257812 ], [ "▁鞍", -11.771928787231445 ], [ "▁BA", -11.771953582763672 ], [ "▁梨", -11.772132873535156 ], [ "▁落ちた", -11.772148132324219 ], [ "▁指して", -11.77226734161377 ], [ "▁率い", -11.772342681884766 ], [ "▁改編", -11.772431373596191 ], [ "▁GM", -11.772541999816895 ], [ "▁ループ", -11.772552490234375 ], [ "▁避けて", -11.772683143615723 ], [ "生活", -11.772871971130371 ], [ "▁未経験", -11.773155212402344 ], [ "けば", -11.77315616607666 ], [ "▁出撃", -11.773348808288574 ], [ "怒", -11.773412704467773 ], [ "ami", -11.773598670959473 ], [ "▁止", -11.773614883422852 ], [ "▁Rights", -11.773706436157227 ], [ "▁啓", -11.773792266845703 ], [ "▁刃", -11.773894309997559 ], [ "▁あらすじ", -11.774068832397461 ], [ "▁増強", -11.77410888671875 ], [ "▁ヘリコプター", -11.774166107177734 ], [ "▁丹", -11.774206161499023 ], [ "▁虹", -11.774274826049805 ], [ "▁バブル", -11.774320602416992 ], [ "▁操", -11.774397850036621 ], [ "提", -11.774408340454102 ], [ "▁今週", -11.774500846862793 ], [ "▁樹立", -11.77454948425293 ], [ "▁取り入れた", -11.774645805358887 ], [ "▁とくに", -11.774662971496582 ], [ "▁混ぜ", -11.77471923828125 ], [ "▁破綻", -11.774856567382812 ], [ "かって", -11.774856567382812 ], [ "威", -11.774979591369629 ], [ "▁警視", -11.77508544921875 ], [ "▁悩む", -11.775086402893066 ], [ "従って", -11.775164604187012 ], [ "▁役職", -11.775252342224121 ], [ "妙", -11.775311470031738 ], [ "ぐり", -11.77540397644043 ], [ "譜", -11.775456428527832 ], [ "▁異動", -11.77563190460205 ], [ "use", -11.775744438171387 ], [ "チル", -11.775829315185547 ], [ "▁友好", -11.77593994140625 ], [ "▁イケメン", -11.776183128356934 ], [ "ARD", -11.776240348815918 ], [ "▁婚約", -11.776248931884766 ], [ "▁メロディ", -11.776310920715332 ], [ "oy", -11.776400566101074 ], [ "▁相違", -11.776447296142578 ], [ "▁継ぐ", -11.776514053344727 ], [ "▁民衆", -11.776515007019043 ], [ "▁悲劇", -11.776552200317383 ], [ "プレイ", -11.776605606079102 ], [ "1967", -11.776618957519531 ], [ "▁慎重に", -11.776725769042969 ], [ "アルバム", -11.776738166809082 ], [ "▁渡さ", -11.777012825012207 ], [ "ドウ", -11.777175903320312 ], [ "▁川口", -11.777289390563965 ], [ "▁サイエンス", -11.777323722839355 ], [ "▁ムーン", -11.777331352233887 ], [ "▁日頃", -11.777460098266602 ], [ "▁アドベンチャー", -11.777463912963867 ], [ "▁バレー", -11.777559280395508 ], [ "ラマ", -11.777624130249023 ], [ "▁考えれば", -11.777691841125488 ], [ "軌", -11.777708053588867 ], [ "ต", -11.777848243713379 ], [ "▁フリードリヒ", -11.777859687805176 ], [ "パソコン", -11.778079986572266 ], [ "ver", -11.778347969055176 ], [ "▁どおり", -11.778575897216797 ], [ "▁受章", -11.778688430786133 ], [ "▁数百", -11.778841018676758 ], [ "コロナ", -11.779012680053711 ], [ "▁API", -11.77904987335205 ], [ "▁木更津", -11.77907943725586 ], [ "塁", -11.77918815612793 ], [ "▁神聖", -11.779226303100586 ], [ "▁石垣", -11.77927303314209 ], [ "rea", -11.779332160949707 ], [ "▁充分", -11.779873847961426 ], [ "▁ジャー", -11.779953956604004 ], [ "▁勅", -11.779958724975586 ], [ "▁フェイ", -11.780125617980957 ], [ "▁中退", -11.780146598815918 ], [ "▁ディア", -11.780153274536133 ], [ "様な", -11.780698776245117 ], [ "▁マウント", -11.780713081359863 ], [ "▁タブ", -11.780808448791504 ], [ "クシ", -11.780815124511719 ], [ "▁守ら", -11.780837059020996 ], [ "▁アダム", -11.780867576599121 ], [ "▁細川", -11.780921936035156 ], [ "▁テラス", -11.78105640411377 ], [ "ミヤ", -11.781092643737793 ], [ "▁トライアル", -11.78114128112793 ], [ "▁含有", -11.78125286102295 ], [ "▁ほん", -11.781367301940918 ], [ "▁敷設", -11.78140640258789 ], [ "ウエア", -11.781656265258789 ], [ "▁名作", -11.781895637512207 ], [ "件", -11.782062530517578 ], [ "▁不振", -11.782392501831055 ], [ "▁部署", -11.782966613769531 ], [ "AG", -11.783052444458008 ], [ "▁挟んで", -11.783166885375977 ], [ "▁ja", -11.78317642211914 ], [ "掛", -11.783275604248047 ], [ "▁201", -11.783341407775879 ], [ "ita", -11.783604621887207 ], [ "ere", -11.783638954162598 ], [ "▁師匠", -11.784013748168945 ], [ "営業", -11.784148216247559 ], [ "▁高温", -11.784271240234375 ], [ "荒", -11.7843599319458 ], [ "▁朝廷", -11.784476280212402 ], [ "ベスト", -11.784525871276855 ], [ "▁アッ", -11.784774780273438 ], [ "▁頂点", -11.784814834594727 ], [ "▁リュック", -11.78482723236084 ], [ "▁ad", -11.785024642944336 ], [ "▁交易", -11.785030364990234 ], [ "モント", -11.78508472442627 ], [ "▁1923", -11.785120964050293 ], [ "▁漂", -11.785224914550781 ], [ "福島", -11.785478591918945 ], [ "▁パズル", -11.78554630279541 ], [ "▁イースト", -11.785747528076172 ], [ "▁農村", -11.785833358764648 ], [ "▁対称", -11.785863876342773 ], [ "▁左翼", -11.785871505737305 ], [ "▁整体", -11.785917282104492 ], [ "▁プロセッサ", -11.78603744506836 ], [ "NI", -11.786109924316406 ], [ "イザー", -11.786112785339355 ], [ "▁サポーター", -11.786147117614746 ], [ "▁多彩な", -11.786184310913086 ], [ "バリー", -11.786198616027832 ], [ "▁イル", -11.786213874816895 ], [ "▁奪い", -11.786446571350098 ], [ "va", -11.786505699157715 ], [ "▁孔", -11.786620140075684 ], [ "▁プロフェッショナル", -11.786649703979492 ], [ "1940", -11.786657333374023 ], [ "▁角川", -11.786809921264648 ], [ "ドア", -11.786821365356445 ], [ "▁輩出", -11.787116050720215 ], [ "▁高かった", -11.787174224853516 ], [ "▁おじさん", -11.787271499633789 ], [ "▁コト", -11.787278175354004 ], [ "ボス", -11.787393569946289 ], [ "鮮", -11.78757381439209 ], [ "モンクレール", -11.787737846374512 ], [ "▁多大な", -11.787741661071777 ], [ "▁掛けて", -11.787857055664062 ], [ "vo", -11.787972450256348 ], [ "▁闘", -11.7880220413208 ], [ "▁間違え", -11.788057327270508 ], [ "女子", -11.788080215454102 ], [ "▁藤田", -11.788195610046387 ], [ "▁導", -11.788445472717285 ], [ "▁単一", -11.789499282836914 ], [ "▁水曜日", -11.78974437713623 ], [ "▁恐竜", -11.789999961853027 ], [ "▁如", -11.79002857208252 ], [ "▁算出", -11.790225982666016 ], [ "▁大体", -11.790291786193848 ], [ "▁某", -11.790337562561035 ], [ "▁赴任", -11.790379524230957 ], [ "▁On", -11.790449142456055 ], [ "▁フレーズ", -11.79046630859375 ], [ "ミック", -11.790594100952148 ], [ "▁行ける", -11.790600776672363 ], [ "▁怠", -11.790847778320312 ], [ "▁FAX", -11.791279792785645 ], [ "▁発祥", -11.791288375854492 ], [ "▁視察", -11.791577339172363 ], [ "▁牝馬", -11.791703224182129 ], [ "▁持参", -11.791884422302246 ], [ "▁支出", -11.792160987854004 ], [ "▁有し", -11.79256534576416 ], [ "▁珍", -11.792587280273438 ], [ "▁膨大な", -11.792619705200195 ], [ "▁Free", -11.792694091796875 ], [ "▁And", -11.792724609375 ], [ "▁助ける", -11.792767524719238 ], [ "▁面白く", -11.79280948638916 ], [ "騎", -11.793021202087402 ], [ "▁奥さん", -11.793205261230469 ], [ "▁ジュース", -11.79322624206543 ], [ "▁ジェネリック", -11.793341636657715 ], [ "▁ボイス", -11.793469429016113 ], [ "▁できたら", -11.793562889099121 ], [ "あまり", -11.793604850769043 ], [ "▁エピローグ", -11.793733596801758 ], [ "▁アール", -11.793734550476074 ], [ "▁昇順", -11.793787956237793 ], [ "ツキ", -11.793869972229004 ], [ "▁サラリーマン", -11.793927192687988 ], [ "ACE", -11.794029235839844 ], [ "▁驚", -11.794059753417969 ], [ "▁豊かに", -11.79418659210205 ], [ "▁アルファ", -11.794320106506348 ], [ "▁おそれ", -11.794321060180664 ], [ "▁狙う", -11.794525146484375 ], [ "▁つくば", -11.794665336608887 ], [ "▁1919", -11.794716835021973 ], [ "▁野党", -11.794822692871094 ], [ "よし", -11.794878005981445 ], [ "▁終点", -11.794912338256836 ], [ "囲", -11.795012474060059 ], [ "▁患", -11.795199394226074 ], [ "ホール", -11.795251846313477 ], [ "ji", -11.795472145080566 ], [ "fl", -11.795539855957031 ], [ "▁聞け", -11.795586585998535 ], [ "▁禅", -11.795621871948242 ], [ "▁レイン", -11.795671463012695 ], [ "ーダ", -11.795823097229004 ], [ "▁実写", -11.79592227935791 ], [ "澄", -11.796156883239746 ], [ "▁乃木坂", -11.796167373657227 ], [ "▁あっという間", -11.796222686767578 ], [ "▁招", -11.79640007019043 ], [ "▁向こう", -11.79647159576416 ], [ "▁入国", -11.796615600585938 ], [ "hat", -11.796670913696289 ], [ "▁正当", -11.796716690063477 ], [ "ッサー", -11.796743392944336 ], [ "▁広大な", -11.796939849853516 ], [ "雀", -11.797069549560547 ], [ "▁隅", -11.797130584716797 ], [ "NS", -11.797203063964844 ], [ "▁港湾", -11.797204971313477 ], [ "▁DO", -11.797240257263184 ], [ "▁干渉", -11.797256469726562 ], [ "▁虐殺", -11.797330856323242 ], [ "▁乗降", -11.797351837158203 ], [ "▁買える", -11.797370910644531 ], [ "健", -11.797391891479492 ], [ "▁調味料", -11.79780101776123 ], [ "▁ヶ月間", -11.797894477844238 ], [ "▁解任", -11.798232078552246 ], [ "▁気に入って", -11.798338890075684 ], [ "▁選べる", -11.798355102539062 ], [ "▁高架", -11.798377990722656 ], [ "▁砂漠", -11.798434257507324 ], [ "▁番線", -11.798521041870117 ], [ "▁増やして", -11.798705101013184 ], [ "▁多岐", -11.798778533935547 ], [ "▁揺れ", -11.798927307128906 ], [ "▁ピック", -11.799068450927734 ], [ "▁自家", -11.799177169799805 ], [ "YA", -11.799249649047852 ], [ "UT", -11.799651145935059 ], [ "▁1918", -11.79974365234375 ], [ "▁招集", -11.79979133605957 ], [ "▁1927", -11.79979419708252 ], [ "▁単純に", -11.799861907958984 ], [ "化学", -11.799861907958984 ], [ "ベリー", -11.799898147583008 ], [ "▁威", -11.799956321716309 ], [ "ネーション", -11.800095558166504 ], [ "抜", -11.800116539001465 ], [ "事務", -11.800216674804688 ], [ "曹", -11.800374984741211 ], [ "▁ロマン", -11.800434112548828 ], [ "▁デニム", -11.800592422485352 ], [ "ムズ", -11.800697326660156 ], [ "▁裁", -11.800711631774902 ], [ "敷", -11.800838470458984 ], [ "もん", -11.80111312866211 ], [ "▁優良", -11.801255226135254 ], [ "▁リュ", -11.80125617980957 ], [ "LI", -11.801265716552734 ], [ "▁告げ", -11.801294326782227 ], [ "▁セントラル", -11.801301956176758 ], [ "den", -11.801316261291504 ], [ "ぷ", -11.801785469055176 ], [ "▁きれいな", -11.801824569702148 ], [ "自動車", -11.801858901977539 ], [ "▁布団", -11.801891326904297 ], [ "▁セレ", -11.802106857299805 ], [ "▁✨", -11.802186012268066 ], [ "大きな", -11.802312850952148 ], [ "▁Dr", -11.802351951599121 ], [ "▁近藤", -11.802464485168457 ], [ "▁併合", -11.80251693725586 ], [ "▁属し", -11.802556037902832 ], [ "▁揚", -11.802563667297363 ], [ "▁He", -11.802593231201172 ], [ "▁募", -11.802599906921387 ], [ "答", -11.80269718170166 ], [ "▁美味しく", -11.802735328674316 ], [ "▁クリスチャン", -11.802767753601074 ], [ "▁起因", -11.80285358428955 ], [ "▁岬", -11.8031587600708 ], [ "▁舐め", -11.803231239318848 ], [ "▁真似", -11.803323745727539 ], [ "▁まとめる", -11.803420066833496 ], [ "画像", -11.803810119628906 ], [ "▁Power", -11.803852081298828 ], [ "▁ベア", -11.803953170776367 ], [ "▁デン", -11.803974151611328 ], [ "oll", -11.804204940795898 ], [ "▁MV", -11.80435562133789 ], [ "com", -11.804438591003418 ], [ "▁仕方ない", -11.804490089416504 ], [ "▁漬け", -11.804583549499512 ], [ "▁ひら", -11.804659843444824 ], [ "欠", -11.804680824279785 ], [ "▁スキャン", -11.804694175720215 ], [ "▁負う", -11.804769515991211 ], [ "婦", -11.804888725280762 ], [ "▁州立", -11.8049955368042 ], [ "デリ", -11.8050537109375 ], [ "魂", -11.805070877075195 ], [ "LC", -11.8051176071167 ], [ "▁会津", -11.80521297454834 ], [ "row", -11.805380821228027 ], [ "▁ミク", -11.805412292480469 ], [ "かれ", -11.805595397949219 ], [ "▁笹", -11.805764198303223 ], [ "会場", -11.805822372436523 ], [ "▁顕", -11.805879592895508 ], [ "▁115", -11.80592155456543 ], [ "▁ピア", -11.805974960327148 ], [ "▁アース", -11.806144714355469 ], [ "おそらく", -11.806145668029785 ], [ "▁つれ", -11.806434631347656 ], [ "▁すぎた", -11.806530952453613 ], [ "とりあえず", -11.806625366210938 ], [ "▁除外", -11.80663776397705 ], [ "フィル", -11.806676864624023 ], [ "▁相次いで", -11.806720733642578 ], [ "▁勧告", -11.806939125061035 ], [ "▁様々", -11.806990623474121 ], [ "▁嬉しかった", -11.807028770446777 ], [ "▁ハリケーン", -11.80717658996582 ], [ "伸", -11.807282447814941 ], [ "▁Si", -11.807377815246582 ], [ "▁傘", -11.807387351989746 ], [ "NC", -11.807503700256348 ], [ "▁オーガニック", -11.807595252990723 ], [ "▁海域", -11.807609558105469 ], [ "▁祀", -11.80763053894043 ], [ "▁ライオン", -11.807851791381836 ], [ "▁あお", -11.807941436767578 ], [ "▁遠隔", -11.807979583740234 ], [ "ext", -11.808052062988281 ], [ "▁1911", -11.80809497833252 ], [ "▁Black", -11.8081693649292 ], [ "▁ブルガリア", -11.808198928833008 ], [ "▁007", -11.808215141296387 ], [ "▁在任", -11.80826473236084 ], [ "ラジオ", -11.808387756347656 ], [ "▁アンサンブル", -11.808523178100586 ], [ "▁シルエット", -11.808530807495117 ], [ "地方", -11.808636665344238 ], [ "▁町田", -11.808828353881836 ], [ "ä", -11.808918952941895 ], [ "▁就", -11.809012413024902 ], [ "▁こなす", -11.809159278869629 ], [ "▁志向", -11.809171676635742 ], [ "▁高まる", -11.80925178527832 ], [ "▁集計", -11.809280395507812 ], [ "▁ストラ", -11.809391021728516 ], [ "▁チュ", -11.809439659118652 ], [ "▁大谷", -11.80961799621582 ], [ "▁頼り", -11.809699058532715 ], [ "コル", -11.809797286987305 ], [ "▁後部", -11.809922218322754 ], [ "▁だいたい", -11.809932708740234 ], [ "キョ", -11.810154914855957 ], [ "BB", -11.810458183288574 ], [ "▁導き", -11.810532569885254 ], [ "▁殿堂", -11.810821533203125 ], [ "へ", -11.810929298400879 ], [ "▁ビームス", -11.810970306396484 ], [ "▁慎", -11.810972213745117 ], [ "▁河口", -11.811018943786621 ], [ "▁いつまでも", -11.811339378356934 ], [ "▁列島", -11.811454772949219 ], [ "▁この世", -11.811609268188477 ], [ "▁朝日新聞", -11.811683654785156 ], [ "▁馴染み", -11.811697959899902 ], [ "狼", -11.811720848083496 ], [ "▁府中", -11.81178092956543 ], [ "▁テー", -11.811908721923828 ], [ "▁頭皮", -11.811919212341309 ], [ "▁現れて", -11.811942100524902 ], [ "▁はずな", -11.8120756149292 ], [ "▁Internet", -11.812348365783691 ], [ "▁ロイ", -11.81241512298584 ], [ "▁沈没", -11.812507629394531 ], [ "DR", -11.812524795532227 ], [ "▁縛り", -11.812860488891602 ], [ "▁your", -11.812919616699219 ], [ "min", -11.813063621520996 ], [ "▁空いて", -11.813156127929688 ], [ "クロス", -11.813222885131836 ], [ "▁支流", -11.813294410705566 ], [ "▁テント", -11.813586235046387 ], [ "▁独身", -11.813589096069336 ], [ "販売", -11.814094543457031 ], [ "降", -11.814148902893066 ], [ "▁染色", -11.8143892288208 ], [ "だけど", -11.814471244812012 ], [ "▁白石", -11.814915657043457 ], [ "▁アミノ酸", -11.81496810913086 ], [ "伏", -11.815048217773438 ], [ "▁Inter", -11.81506061553955 ], [ "▁マリン", -11.815193176269531 ], [ "▁焼失", -11.815625190734863 ], [ "▁力士", -11.815637588500977 ], [ "▁格納", -11.81566047668457 ], [ "▁月間", -11.815818786621094 ], [ "ぐら", -11.815876960754395 ], [ "ンガ", -11.815969467163086 ], [ "▁将校", -11.816044807434082 ], [ "▁大型の", -11.816184043884277 ], [ "▁パンク", -11.816368103027344 ], [ "▁的だ", -11.816628456115723 ], [ "▁絶望", -11.816679954528809 ], [ "コード", -11.816734313964844 ], [ "▁スポ", -11.816800117492676 ], [ "ler", -11.816818237304688 ], [ "翼", -11.816835403442383 ], [ "頂", -11.816970825195312 ], [ "▁離島", -11.817052841186523 ], [ "▁迅速に", -11.817286491394043 ], [ "▁導く", -11.817349433898926 ], [ "ble", -11.81735897064209 ], [ "▁新書", -11.817439079284668 ], [ "so", -11.817521095275879 ], [ "ICE", -11.817553520202637 ], [ "▁換気", -11.817680358886719 ], [ "了", -11.81774616241455 ], [ "チカ", -11.817811965942383 ], [ "▁飲んだ", -11.817859649658203 ], [ "▁甲府", -11.817896842956543 ], [ "▁抜擢", -11.818160057067871 ], [ "▁ラボ", -11.818262100219727 ], [ "▁だれ", -11.818313598632812 ], [ "▁大山", -11.81864070892334 ], [ "ゥ", -11.81866455078125 ], [ "▁武蔵野", -11.818754196166992 ], [ "▁Reserved", -11.819040298461914 ], [ "▁遵守", -11.819120407104492 ], [ "▁ハウ", -11.819129943847656 ], [ "▁マドリード", -11.819280624389648 ], [ "UD", -11.819347381591797 ], [ "▁解禁", -11.819387435913086 ], [ "▁グロー", -11.819398880004883 ], [ "ev", -11.819404602050781 ], [ "下院", -11.819554328918457 ], [ "▁ミネラル", -11.819601058959961 ], [ "▁立法", -11.819601058959961 ], [ "box", -11.819785118103027 ], [ "レンス", -11.819787979125977 ], [ "▁春夏", -11.819948196411133 ], [ "ung", -11.819995880126953 ], [ "▁読め", -11.820040702819824 ], [ "▁セクシー", -11.820045471191406 ], [ "▁演算", -11.820115089416504 ], [ "許", -11.820158004760742 ], [ "▁気味", -11.820528030395508 ], [ "ris", -11.820544242858887 ], [ "ナード", -11.820597648620605 ], [ "さら", -11.820643424987793 ], [ "▁祖母", -11.82070255279541 ], [ "▁フラット", -11.820985794067383 ], [ "染", -11.82101058959961 ], [ "▁季", -11.821064949035645 ], [ "1965", -11.821072578430176 ], [ "▁心がけて", -11.821403503417969 ], [ "ぉ", -11.821526527404785 ], [ "▁始", -11.821930885314941 ], [ "▁イヤー", -11.822021484375 ], [ "▁多発", -11.822141647338867 ], [ "禁", -11.822149276733398 ], [ "▁噴火", -11.822272300720215 ], [ "▁クリップ", -11.82239055633545 ], [ "戒", -11.822591781616211 ], [ "▁三十", -11.822673797607422 ], [ "▁ススメ", -11.822732925415039 ], [ "でん", -11.822859764099121 ], [ "最大", -11.82294750213623 ], [ "▁日立", -11.823042869567871 ], [ "▁毛穴", -11.823125839233398 ], [ "▁急増", -11.823185920715332 ], [ "待", -11.823537826538086 ], [ "太字", -11.823843002319336 ], [ "▁福田", -11.823911666870117 ], [ "▁松田", -11.823993682861328 ], [ "oot", -11.824102401733398 ], [ "▁少なかった", -11.824180603027344 ], [ "先生", -11.824243545532227 ], [ "▁けっこう", -11.824273109436035 ], [ "▁おう", -11.824341773986816 ], [ "form", -11.824386596679688 ], [ "路線", -11.82448959350586 ], [ "▁困難に", -11.824551582336426 ], [ "▁メカニズム", -11.824586868286133 ], [ "▁コーティング", -11.824934959411621 ], [ "▁org", -11.824956893920898 ], [ "▁始動", -11.825043678283691 ], [ "▁預かり", -11.825065612792969 ], [ "▁ジョージア", -11.825178146362305 ], [ "▁飛ぶ", -11.82525634765625 ], [ "▁ポルノ", -11.825411796569824 ], [ "▁格差", -11.825511932373047 ], [ "aki", -11.825592041015625 ], [ "▁IV", -11.82563591003418 ], [ "▁熊野", -11.825641632080078 ], [ "out", -11.825654029846191 ], [ "▁減り", -11.82582950592041 ], [ "▁アナウンス", -11.825952529907227 ], [ "▁薄毛", -11.826006889343262 ], [ "ギア", -11.8261137008667 ], [ "▁格闘技", -11.826133728027344 ], [ "▁買え", -11.826169967651367 ], [ "▁Ta", -11.826192855834961 ], [ "チック", -11.826363563537598 ], [ "▁回し", -11.826400756835938 ], [ "▁that", -11.826458930969238 ], [ "▁待遇", -11.826530456542969 ], [ "生育", -11.826571464538574 ], [ "▁理学", -11.826672554016113 ], [ "▁美濃", -11.826789855957031 ], [ "▁ストレージ", -11.8268404006958 ], [ "▁急ぎ", -11.826894760131836 ], [ "▁城主", -11.826930046081543 ], [ "▁速い", -11.827032089233398 ], [ "▁瓶", -11.8270902633667 ], [ "ぎょう", -11.82723331451416 ], [ "▁王立", -11.827404975891113 ], [ "▁トラベル", -11.82742691040039 ], [ "ond", -11.827545166015625 ], [ "▁ミュンヘン", -11.827570915222168 ], [ "▁首脳", -11.827631950378418 ], [ "▁PPV", -11.827706336975098 ], [ "この後", -11.82784652709961 ], [ "▁山城", -11.827853202819824 ], [ "▁怪獣", -11.82797908782959 ], [ "グラム", -11.828145027160645 ], [ "CON", -11.82826042175293 ], [ "▁遮", -11.82833194732666 ], [ "▁誇", -11.82834529876709 ], [ "▁1926", -11.82838249206543 ], [ "▁砲撃", -11.828442573547363 ], [ "1966", -11.828654289245605 ], [ "▁甥", -11.828768730163574 ], [ "なんと", -11.828813552856445 ], [ "ポール", -11.82884693145752 ], [ "▁地中海", -11.82894229888916 ], [ "▁プリンター", -11.829018592834473 ], [ "▁ひな", -11.829020500183105 ], [ "才", -11.82904052734375 ], [ "▁匿名", -11.829103469848633 ], [ "▁大韓民国", -11.82917594909668 ], [ "▁コチラ", -11.829266548156738 ], [ "▁醸造", -11.829345703125 ], [ "▁通訳", -11.829371452331543 ], [ "▁奇妙な", -11.829426765441895 ], [ "▁塚", -11.829668998718262 ], [ "プライ", -11.829773902893066 ], [ "▁サーキット", -11.829913139343262 ], [ "▁牧師", -11.830032348632812 ], [ "▁NEXT", -11.830080032348633 ], [ "▁仮に", -11.830116271972656 ], [ "▁撃破", -11.830175399780273 ], [ "▁FW", -11.83024787902832 ], [ "上がり", -11.830333709716797 ], [ "ガール", -11.830360412597656 ], [ "▁たびたび", -11.830479621887207 ], [ "ディーン", -11.830533981323242 ], [ "▁れれば", -11.83065414428711 ], [ "隠", -11.830916404724121 ], [ "▁いふ", -11.830965995788574 ], [ "▁モダン", -11.830988883972168 ], [ "銀行", -11.831035614013672 ], [ "▁ダンジョン", -11.831037521362305 ], [ "▁推理", -11.831258773803711 ], [ "良い", -11.831303596496582 ], [ "▁リハビリ", -11.831521987915039 ], [ "銭", -11.831600189208984 ], [ "▁死体", -11.831887245178223 ], [ "▁苦しみ", -11.831939697265625 ], [ "vel", -11.831982612609863 ], [ "▁ナポレオン", -11.83201789855957 ], [ "スピ", -11.832048416137695 ], [ "▁垂直", -11.832212448120117 ], [ "▁素晴らし", -11.8324556350708 ], [ "▁哨戒", -11.832507133483887 ], [ "▁落として", -11.832534790039062 ], [ "DC", -11.832581520080566 ], [ "▁トイ", -11.832828521728516 ], [ "んど", -11.832836151123047 ], [ "▁大事", -11.83309555053711 ], [ "▁不明な", -11.833110809326172 ], [ "▁欲求", -11.833244323730469 ], [ "▁順調に", -11.833337783813477 ], [ "索", -11.833440780639648 ], [ "▁クロアチア", -11.83346939086914 ], [ "▁討ち", -11.83363151550293 ], [ "▁秩序", -11.83364486694336 ], [ "▁1922", -11.833671569824219 ], [ "特別", -11.833755493164062 ], [ "FT", -11.833876609802246 ], [ "▁スムーズ", -11.83407211303711 ], [ "▁平行", -11.834181785583496 ], [ "▁高田", -11.834193229675293 ], [ "▁農場", -11.834228515625 ], [ "▁立憲", -11.834263801574707 ], [ "▁修道", -11.834485054016113 ], [ "▁撮った", -11.834495544433594 ], [ "序", -11.834659576416016 ], [ "▁カントリー", -11.834782600402832 ], [ "▁CIA", -11.834795951843262 ], [ "1941", -11.835076332092285 ], [ "▁ねー", -11.835139274597168 ], [ "▁マニア", -11.835150718688965 ], [ "▁Ex", -11.835250854492188 ], [ "こういった", -11.8352689743042 ], [ "▁リップ", -11.83539867401123 ], [ "▁篠", -11.835463523864746 ], [ "▁楽章", -11.835824012756348 ], [ "▁室町", -11.83582878112793 ], [ "▁くら", -11.835917472839355 ], [ "▁童貞", -11.835923194885254 ], [ "ギュ", -11.836081504821777 ], [ "ω", -11.836169242858887 ], [ "sta", -11.836235046386719 ], [ "包", -11.836243629455566 ], [ "ree", -11.836296081542969 ], [ "▁ar", -11.83636474609375 ], [ "▁老舗", -11.836419105529785 ], [ "▁共和党", -11.836488723754883 ], [ "著者", -11.8364896774292 ], [ "▁窯", -11.836664199829102 ], [ "▁申", -11.836804389953613 ], [ "▁多用", -11.836848258972168 ], [ "フラン", -11.836977005004883 ], [ "▁水域", -11.836982727050781 ], [ "肥", -11.836996078491211 ], [ "自宅", -11.837026596069336 ], [ "▁確か", -11.837044715881348 ], [ "▁Ca", -11.837096214294434 ], [ "▁添え", -11.837226867675781 ], [ "▁アラン", -11.837363243103027 ], [ "▁常務", -11.837370872497559 ], [ "▁歩道", -11.837576866149902 ], [ "▁牛乳", -11.837626457214355 ], [ "▁良好", -11.837628364562988 ], [ "ater", -11.83763599395752 ], [ "▁物体", -11.837682723999023 ], [ "▁正常", -11.837784767150879 ], [ "▁チン", -11.83791446685791 ], [ "ライズ", -11.83798885345459 ], [ "本人", -11.838147163391113 ], [ "まれ", -11.838647842407227 ], [ "▁日焼け", -11.83869743347168 ], [ "BL", -11.838846206665039 ], [ "▁レモン", -11.838903427124023 ], [ "▁レトロ", -11.838973045349121 ], [ "▁したがって", -11.839088439941406 ], [ "▁尾張", -11.839422225952148 ], [ "▁困った", -11.83944034576416 ], [ "▁獲", -11.839454650878906 ], [ "▁熱心", -11.839605331420898 ], [ "MG", -11.83977222442627 ], [ "▁もも", -11.839924812316895 ], [ "ノキ", -11.839930534362793 ], [ "▁抗争", -11.83993911743164 ], [ "▁明石", -11.840078353881836 ], [ "ッチャー", -11.840270042419434 ], [ "▁TM", -11.840557098388672 ], [ "▁量子", -11.840576171875 ], [ "▁好意", -11.840630531311035 ], [ "▁払う", -11.840743064880371 ], [ "▁かみ", -11.84083366394043 ], [ "▁フィル", -11.840895652770996 ], [ "▁依然", -11.841062545776367 ], [ "▁ミステリー", -11.841187477111816 ], [ "側", -11.841337203979492 ], [ "▁CF", -11.841349601745605 ], [ "▁クリスタル", -11.841353416442871 ], [ "▁増して", -11.841357231140137 ], [ "▁不定期", -11.841431617736816 ], [ "ダウンロード", -11.841450691223145 ], [ "ct", -11.84155559539795 ], [ "▁Xbox", -11.841594696044922 ], [ "Categor", -11.841609001159668 ], [ "ize", -11.841611862182617 ], [ "楽天", -11.841632843017578 ], [ "▁啓発", -11.841859817504883 ], [ "▁大塚", -11.842293739318848 ], [ "▁クリーン", -11.842458724975586 ], [ "▁壊滅", -11.842469215393066 ], [ "ニョ", -11.842520713806152 ], [ "づき", -11.842586517333984 ], [ "浄", -11.842632293701172 ], [ "▁槍", -11.84278678894043 ], [ "▁グレート", -11.842796325683594 ], [ "▁思い出し", -11.842950820922852 ], [ "ower", -11.842968940734863 ], [ "がん", -11.843133926391602 ], [ "LD", -11.843138694763184 ], [ "▁かき", -11.843220710754395 ], [ "ブラン", -11.84323787689209 ], [ "▁濡れ", -11.843326568603516 ], [ "戯", -11.843363761901855 ], [ "▁都立", -11.843371391296387 ], [ "凶", -11.843855857849121 ], [ "▁サンダー", -11.843976020812988 ], [ "▁復讐", -11.844267845153809 ], [ "▁禁煙", -11.844364166259766 ], [ "▁カプセル", -11.844595909118652 ], [ "▁付き合って", -11.844817161560059 ], [ "▁名詞", -11.84500789642334 ], [ "▁銘", -11.845030784606934 ], [ "ッケ", -11.845040321350098 ], [ "▁終え", -11.845108032226562 ], [ "▁どんなに", -11.845182418823242 ], [ "▁親しま", -11.845216751098633 ], [ "▁流入", -11.845232963562012 ], [ "▁スマ", -11.845235824584961 ], [ "▁口径", -11.845358848571777 ], [ "ブランド", -11.845430374145508 ], [ "▁お互いに", -11.845682144165039 ], [ "▁ver", -11.845800399780273 ], [ "地球", -11.845833778381348 ], [ "▁つなぐ", -11.845915794372559 ], [ "1930", -11.846270561218262 ], [ "▁積み重ね", -11.846405029296875 ], [ "▁ドミ", -11.846471786499023 ], [ "若い", -11.846532821655273 ], [ "狭", -11.846609115600586 ], [ "NHK", -11.8466796875 ], [ "▁興味深い", -11.846684455871582 ], [ "▁敗れて", -11.846816062927246 ], [ "▁メディカル", -11.846850395202637 ], [ "VI", -11.846942901611328 ], [ "▁キューバ", -11.847012519836426 ], [ "▁健康に", -11.847124099731445 ], [ "テク", -11.847155570983887 ], [ "スペイン", -11.847282409667969 ], [ "訓", -11.847439765930176 ], [ "cr", -11.847563743591309 ], [ "▁疑惑", -11.847566604614258 ], [ "予", -11.847651481628418 ], [ "▁迫る", -11.847681999206543 ], [ "▁抜", -11.84769058227539 ], [ "随", -11.847738265991211 ], [ "▁Studio", -11.84782886505127 ], [ "ショー", -11.847837448120117 ], [ "▁火力", -11.847882270812988 ], [ "▁オーク", -11.84790325164795 ], [ "▁容", -11.848011016845703 ], [ "▁包装", -11.84808349609375 ], [ "▁精密", -11.848134994506836 ], [ "モリ", -11.848278999328613 ], [ "人生", -11.848457336425781 ], [ "抜き", -11.84852123260498 ], [ "阪", -11.848593711853027 ], [ "▁my", -11.848861694335938 ], [ "▁創建", -11.848869323730469 ], [ "▁恭", -11.848955154418945 ], [ "▁指針", -11.849068641662598 ], [ "▁大井", -11.849117279052734 ], [ "▁免除", -11.849136352539062 ], [ "網", -11.849316596984863 ], [ "▁葵", -11.849345207214355 ], [ "▁傾斜", -11.849457740783691 ], [ "▁峰", -11.849492073059082 ], [ "政府", -11.849555015563965 ], [ "▁ミュ", -11.849564552307129 ], [ "▁ウン", -11.84958267211914 ], [ "▁労", -11.849605560302734 ], [ "▁ロリ", -11.849855422973633 ], [ "▁納め", -11.849963188171387 ], [ "チア", -11.849963188171387 ], [ "▁記した", -11.849992752075195 ], [ "▁先住", -11.850056648254395 ], [ "▁キャン", -11.850076675415039 ], [ "▁ゆかり", -11.850079536437988 ], [ "▁たって", -11.850127220153809 ], [ "▁狼", -11.850332260131836 ], [ "▁救出", -11.850468635559082 ], [ "所在", -11.850594520568848 ], [ "▁作動", -11.850954055786133 ], [ "▁ショウ", -11.8510160446167 ], [ "▁たぶん", -11.851097106933594 ], [ "▁家屋", -11.851381301879883 ], [ "pl", -11.851462364196777 ], [ "▁青木", -11.851619720458984 ], [ "▁冷たい", -11.851644515991211 ], [ "そういった", -11.851819038391113 ], [ "▁住人", -11.851851463317871 ], [ "▁スニーカー", -11.851853370666504 ], [ "▁119", -11.852239608764648 ], [ "▁輝き", -11.852543830871582 ], [ "▁CI", -11.852566719055176 ], [ "▁和泉", -11.853087425231934 ], [ "生き", -11.853124618530273 ], [ "新聞", -11.853172302246094 ], [ "▁ヘリ", -11.85330581665039 ], [ "っくり", -11.85344409942627 ], [ "ning", -11.85356616973877 ], [ "▁新生", -11.853598594665527 ], [ "▁仕入れ", -11.853641510009766 ], [ "ff", -11.85383415222168 ], [ "▁頁", -11.853952407836914 ], [ "製作", -11.85395336151123 ], [ "▁素直に", -11.854007720947266 ], [ "▁オリーブ", -11.854043960571289 ], [ "▁抽", -11.85413646697998 ], [ "▁重く", -11.854185104370117 ], [ "▁ベテラン", -11.854339599609375 ], [ "▁書房", -11.854381561279297 ], [ "▁延伸", -11.854436874389648 ], [ "映", -11.854593276977539 ], [ "ちょ", -11.854595184326172 ], [ "すみ", -11.854806900024414 ], [ "アント", -11.854842185974121 ], [ "Read", -11.854952812194824 ], [ "生い立ち", -11.855009078979492 ], [ "▁フィー", -11.855034828186035 ], [ "▁パーマ", -11.85531234741211 ], [ "▁カメラマン", -11.855368614196777 ], [ "▁編み", -11.855429649353027 ], [ "▁嘆", -11.855449676513672 ], [ "▁とらえ", -11.85550308227539 ], [ "標", -11.855602264404297 ], [ "▁パンフレット", -11.855668067932129 ], [ "▁羽田", -11.855917930603027 ], [ "▁ca", -11.855987548828125 ], [ "▁ダイレクト", -11.856082916259766 ], [ "rin", -11.856143951416016 ], [ "自己", -11.85635757446289 ], [ "ori", -11.856404304504395 ], [ "▁鐘", -11.856743812561035 ], [ "▁大事です", -11.856804847717285 ], [ "▁入れ替え", -11.856868743896484 ], [ "pt", -11.856927871704102 ], [ "▁貯金", -11.857378959655762 ], [ "▁降下", -11.857418060302734 ], [ "▁郵送", -11.857580184936523 ], [ "▁AA", -11.857867240905762 ], [ "セー", -11.857980728149414 ], [ "▁速やかに", -11.858022689819336 ], [ "▁阪", -11.858270645141602 ], [ "▁消え", -11.85832691192627 ], [ "▁Or", -11.85854434967041 ], [ "▁ウイ", -11.858610153198242 ], [ "▁客室", -11.858755111694336 ], [ "▁思えば", -11.858882904052734 ], [ "▁おかしく", -11.8589506149292 ], [ "▁神殿", -11.858965873718262 ], [ "▁なつ", -11.859100341796875 ], [ "▁la", -11.859245300292969 ], [ "▁ダブルス", -11.859336853027344 ], [ "▁洗練", -11.859509468078613 ], [ "▁推", -11.859779357910156 ], [ "▁差異", -11.85987663269043 ], [ "リアス", -11.859879493713379 ], [ "やっぱり", -11.860028266906738 ], [ "績", -11.860052108764648 ], [ "▁去年", -11.860111236572266 ], [ "ern", -11.860161781311035 ], [ "塵", -11.860331535339355 ], [ "▁沿った", -11.860607147216797 ], [ "▁111", -11.860740661621094 ], [ "▁育てて", -11.860880851745605 ], [ "▁かく", -11.860901832580566 ], [ "賛", -11.860955238342285 ], [ "朝鮮", -11.860980987548828 ], [ "▁天保", -11.861031532287598 ], [ "オリジナル", -11.861136436462402 ], [ "レア", -11.861449241638184 ], [ "年齢", -11.861661911010742 ], [ "▁手掛けた", -11.861751556396484 ], [ "▁多額", -11.86182975769043 ], [ "▁貨幣", -11.861835479736328 ], [ "始", -11.861879348754883 ], [ "充", -11.862038612365723 ], [ "▁籠", -11.862261772155762 ], [ "ช", -11.862504005432129 ], [ "▁運転手", -11.862527847290039 ], [ "敏", -11.86263656616211 ], [ "▁家賃", -11.862813949584961 ], [ "▁だいぶ", -11.862831115722656 ], [ "▁どん", -11.862906455993652 ], [ "▁くま", -11.862920761108398 ], [ "▁ヤンキース", -11.862945556640625 ], [ "▁黙", -11.86297607421875 ], [ "▁つる", -11.863100051879883 ], [ "▁オイ", -11.863401412963867 ], [ "NP", -11.863551139831543 ], [ "ole", -11.863603591918945 ], [ "▁抜群", -11.863703727722168 ], [ "マリ", -11.863771438598633 ], [ "▁燃え", -11.8638277053833 ], [ "Re", -11.863922119140625 ], [ "▁安田", -11.863993644714355 ], [ "▁色彩", -11.864121437072754 ], [ "ラート", -11.864152908325195 ], [ "▁パッ", -11.864160537719727 ], [ "選手", -11.864202499389648 ], [ "▁掘り", -11.864411354064941 ], [ "chan", -11.864506721496582 ], [ "▁奨学", -11.86451530456543 ], [ "▁飲み物", -11.864666938781738 ], [ "▁出願", -11.86468505859375 ], [ "▁飾る", -11.864693641662598 ], [ "僧", -11.864770889282227 ], [ "中学", -11.864836692810059 ], [ "筑", -11.864840507507324 ], [ "▁安心です", -11.864863395690918 ], [ "▁巡って", -11.864864349365234 ], [ "▁半数", -11.864871978759766 ], [ "▁楊", -11.865070343017578 ], [ "▁宋", -11.865135192871094 ], [ "ジェン", -11.865300178527832 ], [ "▁PRO", -11.865331649780273 ], [ "カール", -11.865338325500488 ], [ "▁SEO", -11.865711212158203 ], [ "▁旭川", -11.86571216583252 ], [ "ルカ", -11.86598014831543 ], [ "▁まし", -11.865998268127441 ], [ "豪", -11.866018295288086 ], [ "▁まつわる", -11.86603832244873 ], [ "LL", -11.866262435913086 ], [ "▁ナイフ", -11.866353034973145 ], [ "▁倒れ", -11.866433143615723 ], [ "▁西宮", -11.866451263427734 ], [ "▁継", -11.866572380065918 ], [ "▁価", -11.866602897644043 ], [ "焼き", -11.866610527038574 ], [ "▁中盤", -11.866671562194824 ], [ "▁カニ", -11.866683959960938 ], [ "イチ", -11.86673355102539 ], [ "▁香水", -11.866989135742188 ], [ "げん", -11.867009162902832 ], [ "▁みち", -11.867109298706055 ], [ "▁採取", -11.867146492004395 ], [ "▁光学", -11.867252349853516 ], [ "突", -11.867444038391113 ], [ "濃", -11.867481231689453 ], [ "▁くださって", -11.867566108703613 ], [ "ELL", -11.86760139465332 ], [ "▁クマ", -11.867660522460938 ], [ "ュ", -11.867753982543945 ], [ "ローン", -11.867799758911133 ], [ "なみ", -11.868011474609375 ], [ "笛", -11.868124961853027 ], [ "▁ツリー", -11.868302345275879 ], [ "▁ドット", -11.868305206298828 ], [ "▁ソックス", -11.868355751037598 ], [ "▁留", -11.868395805358887 ], [ "▁捕手", -11.868398666381836 ], [ "▁下ろし", -11.86841869354248 ], [ "▁あま", -11.868426322937012 ], [ "々と", -11.868581771850586 ], [ "▁捨てて", -11.868644714355469 ], [ "▁象", -11.868672370910645 ], [ "ハム", -11.868739128112793 ], [ "ミズ", -11.869120597839355 ], [ "損", -11.869132995605469 ], [ "位置", -11.86925220489502 ], [ "▁命中", -11.869281768798828 ], [ "▁おも", -11.869379997253418 ], [ "ペー", -11.869483947753906 ], [ "▁165", -11.86963176727295 ], [ "まし", -11.869653701782227 ], [ "▁見つかった", -11.86976146697998 ], [ "▁タイガース", -11.869824409484863 ], [ "▁TA", -11.870083808898926 ], [ "▁おもしろ", -11.870379447937012 ], [ "▁生き物", -11.870423316955566 ], [ "▁引越し", -11.870866775512695 ], [ "▁見出し", -11.870869636535645 ], [ "▁レコーダー", -11.870904922485352 ], [ "▁チャンピオンズ", -11.870925903320312 ], [ "▁取り戻す", -11.870989799499512 ], [ "▁WA", -11.871004104614258 ], [ "▁Designer", -11.871220588684082 ], [ "雷", -11.871407508850098 ], [ "▁パスポート", -11.871469497680664 ], [ "▁ギタリスト", -11.871496200561523 ], [ "▁RO", -11.871759414672852 ], [ "▁とった", -11.871858596801758 ], [ "▁依", -11.87211799621582 ], [ "▁懲役", -11.872171401977539 ], [ "▁大幅な", -11.872177124023438 ], [ "▁ピッチ", -11.872514724731445 ], [ "▁紋章", -11.872532844543457 ], [ "▁博覧", -11.872798919677734 ], [ "▁霧", -11.87295150756836 ], [ "▁ウール", -11.873130798339844 ], [ "▁□", -11.87317180633545 ], [ "▁干", -11.8735933303833 ], [ "▁マクロ", -11.873652458190918 ], [ "▁海兵", -11.873679161071777 ], [ "ぼり", -11.873682975769043 ], [ "▁地質", -11.87377643585205 ], [ "▁みなさま", -11.873811721801758 ], [ "レディ", -11.873849868774414 ], [ "又", -11.874011039733887 ], [ "▁発現", -11.87411117553711 ], [ "十九", -11.874119758605957 ], [ "sch", -11.87421703338623 ], [ "▁努め", -11.874292373657227 ], [ "ベール", -11.874337196350098 ], [ "▁伴", -11.874480247497559 ], [ "▁ネイ", -11.874496459960938 ], [ "きり", -11.87453556060791 ], [ "▁枚数", -11.874685287475586 ], [ "▁条項", -11.874762535095215 ], [ "公園", -11.87476634979248 ], [ "HE", -11.875300407409668 ], [ "最後の", -11.875375747680664 ], [ "▁あちこち", -11.875386238098145 ], [ "▁チャージ", -11.87552261352539 ], [ "▁オオ", -11.875598907470703 ], [ "負", -11.875628471374512 ], [ "▁大津", -11.875692367553711 ], [ "駄", -11.875753402709961 ], [ "治療", -11.875905990600586 ], [ "被", -11.875921249389648 ], [ "▁反撃", -11.875936508178711 ], [ "▁1600", -11.876042366027832 ], [ "▁Gr", -11.87624454498291 ], [ "奈良", -11.876432418823242 ], [ "ACK", -11.876474380493164 ], [ "▁太鼓", -11.87660026550293 ], [ "▁河内", -11.876646995544434 ], [ "稲", -11.876692771911621 ], [ "▁シドニー", -11.876744270324707 ], [ "▁名簿", -11.876980781555176 ], [ "▁速く", -11.877004623413086 ], [ "▁バーチャル", -11.877082824707031 ], [ "▁転生", -11.877119064331055 ], [ "▁サウス", -11.877248764038086 ], [ "▁クレイ", -11.877419471740723 ], [ "▁乙女", -11.877459526062012 ], [ "▁ラッピング", -11.877500534057617 ], [ "プリン", -11.877544403076172 ], [ "▁解像度", -11.877931594848633 ], [ "▁750", -11.877948760986328 ], [ "▁Open", -11.878021240234375 ], [ "▁持て", -11.878059387207031 ], [ "▁集約", -11.87809944152832 ], [ "▁通し", -11.878161430358887 ], [ "ハルト", -11.878189086914062 ], [ "ドラマ", -11.87831974029541 ], [ "測", -11.87833309173584 ], [ "▁Win", -11.878399848937988 ], [ "▁位置付け", -11.878419876098633 ], [ "レーター", -11.878482818603516 ], [ "▁凄く", -11.878555297851562 ], [ "▁響き", -11.878594398498535 ], [ "おか", -11.878843307495117 ], [ "▁川越", -11.87928581237793 ], [ "1963", -11.879375457763672 ], [ "▁痛く", -11.879491806030273 ], [ "▁無関係", -11.87978458404541 ], [ "▁エアロ", -11.87983226776123 ], [ "▁アーツ", -11.879964828491211 ], [ "▁エンターテイメント", -11.879973411560059 ], [ "▁倒す", -11.879984855651855 ], [ "▁築いた", -11.880029678344727 ], [ "▁淡路", -11.880266189575195 ], [ "▁ラウ", -11.880290031433105 ], [ "▁up", -11.880446434020996 ], [ "▁有数", -11.880516052246094 ], [ "▁皇后", -11.88054370880127 ], [ "▁難波", -11.880556106567383 ], [ "▁航行", -11.880560874938965 ], [ "ついて", -11.88060188293457 ], [ "▁律", -11.880657196044922 ], [ "▁符号", -11.880667686462402 ], [ "▁イキ", -11.880799293518066 ], [ "リナ", -11.880875587463379 ], [ "▁Java", -11.880928993225098 ], [ "▁詠", -11.880935668945312 ], [ "1942", -11.881093978881836 ], [ "▁真珠", -11.881121635437012 ], [ "酷", -11.881125450134277 ], [ "ロジー", -11.88129997253418 ], [ "事故", -11.881482124328613 ], [ "▁ジョブ", -11.881508827209473 ], [ "オラ", -11.881608963012695 ], [ "革", -11.881669044494629 ], [ "▁特色", -11.88178539276123 ], [ "▁ハリー", -11.881803512573242 ], [ "▁汎用", -11.882018089294434 ], [ "▁くじ", -11.882122039794922 ], [ "▁日報", -11.88232707977295 ], [ "▁法廷", -11.8823881149292 ], [ "▁咲", -11.88265609741211 ], [ "邸", -11.88278579711914 ], [ "レント", -11.882802963256836 ], [ "▁シャープ", -11.882827758789062 ], [ "▁悲", -11.882852554321289 ], [ "てい", -11.883112907409668 ], [ "▁贈る", -11.883258819580078 ], [ "▁Project", -11.8834810256958 ], [ "▁妃", -11.883503913879395 ], [ "▁掲げて", -11.88365650177002 ], [ "▁当然の", -11.883735656738281 ], [ "▁Star", -11.883793830871582 ], [ "続", -11.883796691894531 ], [ "ッズ", -11.883879661560059 ], [ "ッポ", -11.883959770202637 ], [ "トゥス", -11.883966445922852 ], [ "▁新興", -11.88397216796875 ], [ "次回", -11.884008407592773 ], [ "▁SU", -11.884034156799316 ], [ "oto", -11.884110450744629 ], [ "▁献", -11.884145736694336 ], [ "▁魔王", -11.884265899658203 ], [ "爵", -11.884385108947754 ], [ "▁司馬", -11.884407043457031 ], [ "▁栄養素", -11.8845853805542 ], [ "▁1921", -11.884597778320312 ], [ "きっと", -11.884788513183594 ], [ "▁スル", -11.884855270385742 ], [ "▁グローブ", -11.884963035583496 ], [ "▁有る", -11.884973526000977 ], [ "▁隠さ", -11.885049819946289 ], [ "マーク", -11.885074615478516 ], [ "▁日数", -11.885225296020508 ], [ "▁新鮮な", -11.885273933410645 ], [ "tra", -11.88542652130127 ], [ "▁勤", -11.88554859161377 ], [ "プレー", -11.885555267333984 ], [ "amp", -11.885809898376465 ], [ "▁スッキリ", -11.885950088500977 ], [ "▁釈放", -11.886035919189453 ], [ "▁サッ", -11.886127471923828 ], [ "▁世論", -11.886231422424316 ], [ "mail", -11.8862886428833 ], [ "▁眉", -11.886290550231934 ], [ "▁手掛ける", -11.886378288269043 ], [ "▁恒例", -11.886495590209961 ], [ "▁好ま", -11.886628150939941 ], [ "踏", -11.886777877807617 ], [ "▁DI", -11.886859893798828 ], [ "▁見逃し", -11.886895179748535 ], [ "▁促し", -11.887024879455566 ], [ "ザル", -11.887025833129883 ], [ "寛", -11.8871431350708 ], [ "▁あふれる", -11.88714599609375 ], [ "▁必要で", -11.887310028076172 ], [ "ms", -11.887459754943848 ], [ "ワル", -11.887533187866211 ], [ "▁不動", -11.887701988220215 ], [ "▁ひどく", -11.887773513793945 ], [ "▁望ましい", -11.887789726257324 ], [ "▁みたり", -11.88780403137207 ], [ "▁芦", -11.887836456298828 ], [ "▁遺族", -11.887974739074707 ], [ "▁ピザ", -11.888007164001465 ], [ "▁助けて", -11.888121604919434 ], [ "▁特例", -11.888137817382812 ], [ "▁大豆", -11.888221740722656 ], [ "ダス", -11.888349533081055 ], [ "▁偉大な", -11.888608932495117 ], [ "▁落ち着いて", -11.88878059387207 ], [ "▁洗", -11.888810157775879 ], [ "▁ケー", -11.888884544372559 ], [ "▁親戚", -11.889071464538574 ], [ "▁Pa", -11.889204978942871 ], [ "ぅ", -11.889209747314453 ], [ "▁飼い主", -11.889591217041016 ], [ "▁三河", -11.88963794708252 ], [ "飾", -11.889857292175293 ], [ "▁紅白", -11.88985824584961 ], [ "▁本数", -11.88997745513916 ], [ "込み", -11.889978408813477 ], [ "ARA", -11.889988899230957 ], [ "▁アパレル", -11.890250205993652 ], [ "▁取組", -11.890253067016602 ], [ "▁豊橋", -11.890279769897461 ], [ "が丘", -11.890429496765137 ], [ "▁チャンピオンシップ", -11.890615463256836 ], [ "享", -11.890707015991211 ], [ "▁ポータル", -11.89071273803711 ], [ "▁静かに", -11.890788078308105 ], [ "並み", -11.89086627960205 ], [ "▁シャトル", -11.890960693359375 ], [ "▁可決", -11.891046524047852 ], [ "▁コム", -11.89113712310791 ], [ "▁薫", -11.89133358001709 ], [ "RY", -11.891345024108887 ], [ "▁El", -11.891556739807129 ], [ "▁セラ", -11.891876220703125 ], [ "▁1910", -11.891918182373047 ], [ "シングル", -11.891924858093262 ], [ "red", -11.891947746276855 ], [ "▁刺", -11.891997337341309 ], [ "▁藤沢", -11.892026901245117 ], [ "▁晩年", -11.892036437988281 ], [ "▁吹奏", -11.892060279846191 ], [ "▁楽しみです", -11.892091751098633 ], [ "ワード", -11.892218589782715 ], [ "溝", -11.892417907714844 ], [ "▁当たり前の", -11.892460823059082 ], [ "▁打ち合わせ", -11.892803192138672 ], [ "▁ブルガリ", -11.892949104309082 ], [ "完全", -11.893092155456543 ], [ "▁右手", -11.893223762512207 ], [ "▁擁護", -11.893342971801758 ], [ "▁開ける", -11.893348693847656 ], [ "▁少な", -11.89340591430664 ], [ "▁自国", -11.893502235412598 ], [ "▁疑", -11.893514633178711 ], [ "▁一見", -11.893536567687988 ], [ "▁半導体", -11.893601417541504 ], [ "▁sm", -11.894152641296387 ], [ "▁抑えて", -11.894289016723633 ], [ "ランス", -11.894319534301758 ], [ "IB", -11.894525527954102 ], [ "▁とある", -11.894554138183594 ], [ "芽", -11.894632339477539 ], [ "シブ", -11.8947172164917 ], [ "▁らし", -11.894737243652344 ], [ "航空", -11.894850730895996 ], [ "▁入植", -11.894891738891602 ], [ "追", -11.89493465423584 ], [ "▁滑走", -11.894942283630371 ], [ "▁抱え", -11.894966125488281 ], [ "▁試行", -11.894972801208496 ], [ "▁流用", -11.895281791687012 ], [ "1943", -11.895370483398438 ], [ "詩", -11.895493507385254 ], [ "▁答弁", -11.895502090454102 ], [ "▁絶賛", -11.895605087280273 ], [ "ッシング", -11.895615577697754 ], [ "病院", -11.895623207092285 ], [ "トウ", -11.895744323730469 ], [ "▁骨格", -11.895760536193848 ], [ "届", -11.895797729492188 ], [ "▁not", -11.896004676818848 ], [ "残念", -11.89601993560791 ], [ "▁あけ", -11.896020889282227 ], [ "CK", -11.896034240722656 ], [ "党員", -11.896163940429688 ], [ "▁見分け", -11.89619255065918 ], [ "▁悟", -11.896337509155273 ], [ "▁コロ", -11.896478652954102 ], [ "秋田", -11.896479606628418 ], [ "ERS", -11.89665699005127 ], [ "▁憲", -11.896809577941895 ], [ "▁レター", -11.8968505859375 ], [ "▁台頭", -11.896929740905762 ], [ "己", -11.89696216583252 ], [ "▁こうして", -11.89700698852539 ], [ "▁妥当", -11.897140502929688 ], [ "▁キリ", -11.897181510925293 ], [ "▁織", -11.897287368774414 ], [ "▁仮定", -11.897313117980957 ], [ "▁辰", -11.89731502532959 ], [ "▁直結", -11.897636413574219 ], [ "▁慶長", -11.897658348083496 ], [ "▁作れ", -11.897796630859375 ], [ "礁", -11.897823333740234 ], [ "▁ふさわしい", -11.897839546203613 ], [ "ツォ", -11.897852897644043 ], [ "上述", -11.897867202758789 ], [ "▁単体", -11.897964477539062 ], [ "▁藍", -11.898058891296387 ], [ "▁気づいて", -11.898384094238281 ], [ "▁字幕", -11.898650169372559 ], [ "▁造形", -11.898681640625 ], [ "▁止めて", -11.8988618850708 ], [ "▁商用", -11.89906120300293 ], [ "▁公民", -11.899177551269531 ], [ "▁Ne", -11.899336814880371 ], [ "ヴァル", -11.899406433105469 ], [ "▁ボウル", -11.899417877197266 ], [ "ico", -11.89957332611084 ], [ "▁チュー", -11.899761199951172 ], [ "試験", -11.89993953704834 ], [ "▁カワ", -11.899945259094238 ], [ "▁集積", -11.900083541870117 ], [ "▁乗務", -11.90012264251709 ], [ "▁盗撮", -11.900187492370605 ], [ "▁ブロー", -11.90047836303711 ], [ "▁家系", -11.900484085083008 ], [ "ダラ", -11.900489807128906 ], [ "▁じゅう", -11.9005765914917 ], [ "050", -11.90066146850586 ], [ "▁チェア", -11.901004791259766 ], [ "台湾", -11.901022911071777 ], [ "▁追って", -11.901054382324219 ], [ "qu", -11.9011812210083 ], [ "▁家計", -11.901288986206055 ], [ "her", -11.901326179504395 ], [ "▁整える", -11.90151596069336 ], [ "▁スクエア", -11.901588439941406 ], [ "▁凝", -11.901695251464844 ], [ "www", -11.901849746704102 ], [ "ガラ", -11.901856422424316 ], [ "▁越え", -11.901926040649414 ], [ "ile", -11.902092933654785 ], [ "▁作画", -11.902121543884277 ], [ "ゴス", -11.902169227600098 ], [ "▁純正", -11.90237808227539 ], [ "外国", -11.902423858642578 ], [ "▁あいだ", -11.902578353881836 ], [ "▁通った", -11.90295124053955 ], [ "▁納", -11.903011322021484 ], [ "▁離れる", -11.903292655944824 ], [ "▁乳首", -11.903465270996094 ], [ "▁美味し", -11.903558731079102 ], [ "▁剥", -11.903575897216797 ], [ "▁踏まえて", -11.90369701385498 ], [ "れん", -11.903937339782715 ], [ "▁金庫", -11.903952598571777 ], [ "PR", -11.904041290283203 ], [ "JI", -11.904220581054688 ], [ "じゅ", -11.904335021972656 ], [ "▁木曜日", -11.90444278717041 ], [ "立つ", -11.904596328735352 ], [ "▁折れ", -11.904745101928711 ], [ "▁農学", -11.904830932617188 ], [ "脱", -11.905036926269531 ], [ "掃", -11.905157089233398 ], [ "▁ハナ", -11.905303001403809 ], [ "▁本国", -11.905312538146973 ], [ "▁焼肉", -11.905458450317383 ], [ "カメラ", -11.905552864074707 ], [ "▁ぴったり", -11.905632019042969 ], [ "▁惹か", -11.90564250946045 ], [ "全体", -11.905661582946777 ], [ "▁農地", -11.90579605102539 ], [ "▁抜ける", -11.905957221984863 ], [ "ビオ", -11.906026840209961 ], [ "▁園芸", -11.906054496765137 ], [ "▁孤立", -11.906106948852539 ], [ "▁図って", -11.906139373779297 ], [ "ings", -11.906285285949707 ], [ "▁民事", -11.90654468536377 ], [ "ッセル", -11.906548500061035 ], [ "▁ピース", -11.906574249267578 ], [ "▁相模原", -11.906610488891602 ], [ "▁妥", -11.906641960144043 ], [ "胸", -11.906789779663086 ], [ "▁OP", -11.906939506530762 ], [ "▁部員", -11.907051086425781 ], [ "▁社会党", -11.907052040100098 ], [ "▁1914", -11.907380104064941 ], [ "警察", -11.90742015838623 ], [ "▁貴方", -11.907439231872559 ], [ "▁市議", -11.907705307006836 ], [ "▁えき", -11.907803535461426 ], [ "ミナ", -11.907817840576172 ], [ "▁筆者", -11.90802001953125 ], [ "▁小さ", -11.90804386138916 ], [ "▁多くて", -11.908332824707031 ], [ "▁240", -11.908380508422852 ], [ "▁筑波", -11.908468246459961 ], [ "▁まぁ", -11.908479690551758 ], [ "▁去る", -11.908793449401855 ], [ "▁iTunes", -11.908817291259766 ], [ "ster", -11.909052848815918 ], [ "▁104", -11.909075736999512 ], [ "ボリ", -11.909097671508789 ], [ "▁(^", -11.909110069274902 ], [ "躍", -11.909292221069336 ], [ "▁1909", -11.909402847290039 ], [ "▁コメ", -11.909451484680176 ], [ "▁特撮", -11.909533500671387 ], [ "▁ATM", -11.909581184387207 ], [ "▁加わる", -11.909830093383789 ], [ "▁快感", -11.909914016723633 ], [ "▁変態", -11.909932136535645 ], [ "▁分ける", -11.909993171691895 ], [ "▁ref", -11.910035133361816 ], [ "▁明示", -11.910168647766113 ], [ "DVD", -11.910297393798828 ], [ "▁ユニークな", -11.910357475280762 ], [ "▁長谷川", -11.910492897033691 ], [ "▁細い", -11.91054630279541 ], [ "▁アップル", -11.910689353942871 ], [ "契約", -11.91086196899414 ], [ "▁ごみ", -11.910931587219238 ], [ "▁圧迫", -11.911116600036621 ], [ "▁安芸", -11.911242485046387 ], [ "続く", -11.911247253417969 ], [ "▁打って", -11.911346435546875 ], [ "▁10,000", -11.911456108093262 ], [ "▁生きた", -11.911559104919434 ], [ "▁眠", -11.91156005859375 ], [ "▁たけ", -11.911650657653809 ], [ "ガリ", -11.911674499511719 ], [ "▁リバー", -11.911971092224121 ], [ "▁福袋", -11.912120819091797 ], [ "▁PM", -11.91250991821289 ], [ "fa", -11.912638664245605 ], [ "託", -11.912663459777832 ], [ "▁ma", -11.912700653076172 ], [ "イヤ", -11.912755012512207 ], [ "▁奪取", -11.912910461425781 ], [ "▁ドラえもん", -11.912945747375488 ], [ "▁作ろう", -11.913007736206055 ], [ "ピオ", -11.913337707519531 ], [ "▁点数", -11.913516998291016 ], [ "▁VI", -11.913695335388184 ], [ "ゾー", -11.913737297058105 ], [ "▁ひたすら", -11.913738250732422 ], [ "観光", -11.91388988494873 ], [ "1962", -11.913909912109375 ], [ "▁就労", -11.913926124572754 ], [ "▁沿", -11.914148330688477 ], [ "▁指令", -11.914164543151855 ], [ "テア", -11.914203643798828 ], [ "▁スプレー", -11.914234161376953 ], [ "▁教区", -11.914271354675293 ], [ "▁ステッカー", -11.914353370666504 ], [ "▁標識", -11.914637565612793 ], [ "▁中立", -11.914695739746094 ], [ "▁日本橋", -11.914695739746094 ], [ "よろしく", -11.914756774902344 ], [ "プトン", -11.914803504943848 ], [ "▁シャル", -11.914824485778809 ], [ "▁数千", -11.914883613586426 ], [ "ミオ", -11.914897918701172 ], [ "ライフ", -11.914973258972168 ], [ "それにしても", -11.91514778137207 ], [ "▁配偶", -11.915255546569824 ], [ "▁ジャニーズ", -11.915299415588379 ], [ "▁ゴジラ", -11.915325164794922 ], [ "▁繁", -11.915343284606934 ], [ "▁リトアニア", -11.915380477905273 ], [ "▁傑作", -11.91550064086914 ], [ "▁コク", -11.915724754333496 ], [ "予約", -11.91585922241211 ], [ "亀", -11.916269302368164 ], [ "GS", -11.916316986083984 ], [ "▁討伐", -11.916387557983398 ], [ "▁BD", -11.916393280029297 ], [ "ボード", -11.916406631469727 ], [ "▁ES", -11.916481971740723 ], [ "▁ビックリ", -11.916516304016113 ], [ "▁越える", -11.916563987731934 ], [ "▁的中", -11.916587829589844 ], [ "▁騙", -11.916604042053223 ], [ "1920", -11.916844367980957 ], [ "モト", -11.916864395141602 ], [ "▁PD", -11.916877746582031 ], [ "▁高めて", -11.916905403137207 ], [ "▁去って", -11.917095184326172 ], [ "▁つらい", -11.917234420776367 ], [ "▁救い", -11.917289733886719 ], [ "▁読める", -11.917309761047363 ], [ "ルイ", -11.917315483093262 ], [ "▁広げる", -11.91738510131836 ], [ "▁処女", -11.917511940002441 ], [ "▁陣営", -11.917531967163086 ], [ "▁同じです", -11.917571067810059 ], [ "▁パール", -11.917691230773926 ], [ "▁せたり", -11.917728424072266 ], [ "▁大尉", -11.917787551879883 ], [ "▁年賀", -11.9177885055542 ], [ "庄", -11.91779613494873 ], [ "▁飾", -11.91793441772461 ], [ "▁ふじ", -11.918191909790039 ], [ "▁着る", -11.91843318939209 ], [ "▁判事", -11.918475151062012 ], [ "コレ", -11.918492317199707 ], [ "▁イスラーム", -11.918681144714355 ], [ "▁篤", -11.918863296508789 ], [ "▁投じ", -11.918919563293457 ], [ "▁新年", -11.919120788574219 ], [ "▁1912", -11.919193267822266 ], [ "▁プロダクト", -11.919212341308594 ], [ "▁火曜日", -11.919282913208008 ], [ "▁ダッシュ", -11.91930103302002 ], [ "▁急遽", -11.919302940368652 ], [ "▁成熟", -11.919351577758789 ], [ "▁逃れ", -11.919363021850586 ], [ "っぴ", -11.919365882873535 ], [ "婆", -11.919478416442871 ], [ "▁捕獲", -11.91948127746582 ], [ "▁民営", -11.91950511932373 ], [ "舟", -11.919570922851562 ], [ "ild", -11.919621467590332 ], [ "山口", -11.919657707214355 ], [ "▁バスト", -11.919713020324707 ], [ "助かり", -11.91981315612793 ], [ "DE", -11.919819831848145 ], [ "▁伊東", -11.919867515563965 ], [ "▁前者", -11.920058250427246 ], [ "▁名刺", -11.920275688171387 ], [ "▁京阪", -11.920319557189941 ], [ "▁赤色", -11.92033576965332 ], [ "▁娯楽", -11.920541763305664 ], [ "▁顎", -11.92073917388916 ], [ "▁進撃", -11.92076301574707 ], [ "▁分配", -11.920974731445312 ], [ "暮", -11.92104721069336 ], [ "▁一郎", -11.921248435974121 ], [ "Android", -11.921265602111816 ], [ "▁ライナー", -11.92173957824707 ], [ "▁Ju", -11.921921730041504 ], [ "奨", -11.921953201293945 ], [ "▁AL", -11.92210578918457 ], [ "略称", -11.922106742858887 ], [ "▁筆記", -11.92214298248291 ], [ "▁炭酸", -11.922432899475098 ], [ "▁プチ", -11.922483444213867 ], [ "▁ラジ", -11.922507286071777 ], [ "▁ラフ", -11.922595977783203 ], [ "▁倉敷", -11.922602653503418 ], [ "まえ", -11.92269229888916 ], [ "▁基調", -11.922707557678223 ], [ "▁領地", -11.92283821105957 ], [ "返し", -11.922884941101074 ], [ "▁杏", -11.922887802124023 ], [ "▁取付", -11.922913551330566 ], [ "▁フリーランス", -11.923018455505371 ], [ "▁願", -11.92304515838623 ], [ "あん", -11.923063278198242 ], [ "▁次官", -11.923163414001465 ], [ "▁固く", -11.923202514648438 ], [ "▁わずかに", -11.92321491241455 ], [ "▁レスリング", -11.923425674438477 ], [ "▁熱中", -11.923550605773926 ], [ "res", -11.923689842224121 ], [ "ヴェー", -11.923722267150879 ], [ "▁利息", -11.923738479614258 ], [ "▁後世", -11.923798561096191 ], [ "▁解剖", -11.923830032348633 ], [ "▁プリンセス", -11.923834800720215 ], [ "▁壮", -11.923957824707031 ], [ "▁NEW", -11.92414665222168 ], [ "▁辞め", -11.924375534057617 ], [ "▁梱包", -11.924458503723145 ], [ "▁斜面", -11.924602508544922 ], [ "▁噛み", -11.924661636352539 ], [ "▁夕食", -11.924748420715332 ], [ "▁三男", -11.92478084564209 ], [ "980", -11.92485237121582 ], [ "熊本", -11.924899101257324 ], [ "▁NI", -11.925008773803711 ], [ "▁ビューティー", -11.925287246704102 ], [ "▁賛同", -11.925431251525879 ], [ "▁やさしい", -11.925436019897461 ], [ "▁松竹", -11.925454139709473 ], [ "▁反響", -11.925491333007812 ], [ "▁まり", -11.925585746765137 ], [ "▁すっきり", -11.925618171691895 ], [ "唐", -11.9256591796875 ], [ "▁ゲージ", -11.925753593444824 ], [ "大会", -11.925768852233887 ], [ "減", -11.925795555114746 ], [ "▁進ま", -11.925924301147461 ], [ "▁洞窟", -11.926054954528809 ], [ "CHI", -11.926125526428223 ], [ "▁Day", -11.926247596740723 ], [ "▁洗顔", -11.926313400268555 ], [ "ジョー", -11.926465034484863 ], [ "▁blog", -11.92662239074707 ], [ "ラウ", -11.92662525177002 ], [ "ora", -11.92667007446289 ], [ "キャラクター", -11.92674732208252 ], [ "ーネ", -11.926751136779785 ], [ "ney", -11.92678451538086 ], [ "▁メーター", -11.926839828491211 ], [ "▁定めて", -11.92685317993164 ], [ "▁パナソニック", -11.9268798828125 ], [ "▁悲しい", -11.926883697509766 ], [ "▁じゃあ", -11.926974296569824 ], [ "▁引いて", -11.927225112915039 ], [ "▁増殖", -11.92741870880127 ], [ "▁so", -11.927427291870117 ], [ "。", -11.927454948425293 ], [ "AGE", -11.927563667297363 ], [ "▁品揃え", -11.927570343017578 ], [ "▁順序", -11.927661895751953 ], [ "▁同居", -11.927669525146484 ], [ "htt", -11.92769718170166 ], [ "▁AB", -11.927720069885254 ], [ "▁Str", -11.927774429321289 ], [ "IF", -11.927785873413086 ], [ "▁消し", -11.927800178527832 ], [ "▁下がって", -11.927844047546387 ], [ "▁アズ", -11.927922248840332 ], [ "▁眠り", -11.927968978881836 ], [ "▁障がい", -11.928016662597656 ], [ "▁封じ", -11.928112983703613 ], [ "▁探査", -11.928210258483887 ], [ "hy", -11.928211212158203 ], [ "ベック", -11.928372383117676 ], [ "ting", -11.928399085998535 ], [ "▁見舞わ", -11.928462982177734 ], [ "▁ニンテンドー", -11.928511619567871 ], [ "愛称", -11.928546905517578 ], [ "塾", -11.92856216430664 ], [ "▁近づく", -11.928757667541504 ], [ "▁気配", -11.928894996643066 ], [ "▁幕末", -11.928987503051758 ], [ "und", -11.929101943969727 ], [ "▁島津", -11.9295015335083 ], [ "▁フック", -11.929540634155273 ], [ "▁goo", -11.929583549499512 ], [ "摩", -11.929601669311523 ], [ "▁ギャップ", -11.929605484008789 ], [ "▁一人ひとり", -11.929643630981445 ], [ "▁PK", -11.929658889770508 ], [ "▁はじめた", -11.929664611816406 ], [ "▁アバ", -11.929758071899414 ], [ "▁LO", -11.929841041564941 ], [ "まん", -11.929848670959473 ], [ "▁豊富", -11.929862022399902 ], [ "▁しゅ", -11.929936408996582 ], [ "▁包", -11.929937362670898 ], [ "▁胡", -11.929973602294922 ], [ "▁簡単で", -11.930002212524414 ], [ "▁AN", -11.930086135864258 ], [ "▁立てた", -11.93014907836914 ], [ "▁インターフェイス", -11.930174827575684 ], [ "▁リーガ", -11.930407524108887 ], [ "KU", -11.930431365966797 ], [ "▁保ち", -11.930529594421387 ], [ "▁のんびり", -11.930609703063965 ], [ "せっかく", -11.930615425109863 ], [ "▁ブライ", -11.93072509765625 ], [ "頃", -11.930767059326172 ], [ "nu", -11.93082332611084 ], [ "ッラ", -11.930859565734863 ], [ "▁達して", -11.930904388427734 ], [ "▁卓球", -11.931087493896484 ], [ "マラ", -11.931124687194824 ], [ "▁お礼", -11.93115234375 ], [ "▁ヲ", -11.93117904663086 ], [ "▁OB", -11.931299209594727 ], [ "che", -11.931374549865723 ], [ "ook", -11.931952476501465 ], [ "▁変革", -11.931991577148438 ], [ "代わり", -11.932100296020508 ], [ "▁高値", -11.9323148727417 ], [ "▁食糧", -11.932372093200684 ], [ "▁103", -11.932451248168945 ], [ "▁くり", -11.932515144348145 ], [ "anc", -11.932737350463867 ], [ "▁ハット", -11.932756423950195 ], [ "墓", -11.932768821716309 ], [ "ペイ", -11.932825088500977 ], [ "籠", -11.933112144470215 ], [ "▁ファーム", -11.933258056640625 ], [ "▁征", -11.933281898498535 ], [ "一般に", -11.93331241607666 ], [ "ハル", -11.933314323425293 ], [ "▁仕立て", -11.933326721191406 ], [ "▁滑り", -11.933343887329102 ], [ "▁降板", -11.933439254760742 ], [ "▁似", -11.933455467224121 ], [ "1961", -11.93356704711914 ], [ "▁小泉", -11.933574676513672 ], [ "▁脆弱", -11.933659553527832 ], [ "ゆう", -11.933795928955078 ], [ "▁終える", -11.933956146240234 ], [ "落ち", -11.934065818786621 ], [ "▁John", -11.934112548828125 ], [ "▁必見", -11.934440612792969 ], [ "▁貼り", -11.934442520141602 ], [ "▁トゥー", -11.93455696105957 ], [ "▁デリヘル", -11.934557914733887 ], [ "▁便秘", -11.93460750579834 ], [ "▁参拝", -11.93465518951416 ], [ "▁髪型", -11.93468952178955 ], [ "▁1917", -11.934691429138184 ], [ "▁マイクロソフト", -11.93478775024414 ], [ "▁切手", -11.934840202331543 ], [ "▁ムダ", -11.934864044189453 ], [ "▁承知", -11.93490982055664 ], [ "▁鉱物", -11.93502140045166 ], [ "LP", -11.935210227966309 ], [ "ek", -11.935307502746582 ], [ "▁疲れて", -11.935354232788086 ], [ "▁本田", -11.935479164123535 ], [ "DK", -11.935503005981445 ], [ "▁子宮", -11.935593605041504 ], [ "▁追う", -11.935620307922363 ], [ "來", -11.935637474060059 ], [ "▁都会", -11.935708045959473 ], [ "移", -11.935734748840332 ], [ "▁衰え", -11.935747146606445 ], [ "▁教諭", -11.935750007629395 ], [ "▁ディープ", -11.935821533203125 ], [ "ory", -11.935999870300293 ], [ "▁ビート", -11.936004638671875 ], [ "じる", -11.936140060424805 ], [ "▁退会", -11.936169624328613 ], [ "コウ", -11.936324119567871 ], [ "径", -11.936529159545898 ], [ "▁創出", -11.936545372009277 ], [ "▁エム", -11.936603546142578 ], [ "▁苦しい", -11.936646461486816 ], [ "パウ", -11.936891555786133 ], [ "▁dis", -11.936902046203613 ], [ "泣", -11.936992645263672 ], [ "▁抱く", -11.937081336975098 ], [ "▁シングルス", -11.937095642089844 ], [ "▁小田急", -11.937366485595703 ], [ "▁交わ", -11.937378883361816 ], [ "serv", -11.937414169311523 ], [ "ツー", -11.93743896484375 ], [ "都市", -11.937565803527832 ], [ "膳", -11.937620162963867 ], [ "束", -11.937655448913574 ], [ "▁染", -11.9376802444458 ], [ "建築", -11.937731742858887 ], [ "スル", -11.93779468536377 ], [ "▁元素", -11.937845230102539 ], [ "▁LI", -11.937910079956055 ], [ "▁悲しみ", -11.938079833984375 ], [ "▁支社", -11.93813419342041 ], [ "▁配当", -11.938185691833496 ], [ "▁謳", -11.938294410705566 ], [ "▁曲目", -11.938447952270508 ], [ "そのうち", -11.938526153564453 ], [ "▁ディナー", -11.938647270202637 ], [ "▁un", -11.938691139221191 ], [ "▁Switch", -11.938796997070312 ], [ "ンツ", -11.938898086547852 ], [ "ツァー", -11.938966751098633 ], [ "▁ハードル", -11.938971519470215 ], [ "▁松井", -11.938972473144531 ], [ "抄", -11.938973426818848 ], [ "▁告発", -11.939064979553223 ], [ "▁深刻", -11.939148902893066 ], [ "カレ", -11.939297676086426 ], [ "▁moncler", -11.939515113830566 ], [ "▁フレンチ", -11.939606666564941 ], [ "▁頬", -11.939702987670898 ], [ "ロア", -11.939775466918945 ], [ "ESS", -11.939857482910156 ], [ "▁ロボ", -11.939878463745117 ], [ "▁寄生", -11.940011024475098 ], [ "▁提言", -11.940057754516602 ], [ "▁エビ", -11.940176010131836 ], [ "▁バージニア", -11.940217018127441 ], [ "▁まもなく", -11.940333366394043 ], [ "▁ダイニング", -11.940600395202637 ], [ "ニル", -11.94063663482666 ], [ "▁分かれ", -11.940644264221191 ], [ "▁改変", -11.940659523010254 ], [ "▁ワー", -11.940884590148926 ], [ "▁受け入れて", -11.940959930419922 ], [ "▁ナトリウム", -11.940961837768555 ], [ "▁ヴォ", -11.940999984741211 ], [ "▁集英社", -11.941052436828613 ], [ "▁耐震", -11.941071510314941 ], [ "▁ぴ", -11.941084861755371 ], [ "eed", -11.941174507141113 ], [ "▁登校", -11.941205024719238 ], [ "ren", -11.941229820251465 ], [ "▁組む", -11.941238403320312 ], [ "▁戦って", -11.941304206848145 ], [ "タキ", -11.941481590270996 ], [ "食べ", -11.941546440124512 ], [ "▁受け取った", -11.941673278808594 ], [ "▁歌った", -11.94178295135498 ], [ "▁伸びる", -11.941944122314453 ], [ "ろい", -11.942047119140625 ], [ "▁式典", -11.9420747756958 ], [ "周辺", -11.942106246948242 ], [ "▁好調", -11.942255973815918 ], [ "▁かたち", -11.942317008972168 ], [ "ENT", -11.94243335723877 ], [ "▁明る", -11.942557334899902 ], [ "エンド", -11.942639350891113 ], [ "ser", -11.942766189575195 ], [ "▁振り返って", -11.942774772644043 ], [ "▁触媒", -11.942778587341309 ], [ "▁苗", -11.942839622497559 ], [ "じま", -11.943013191223145 ], [ "辛", -11.9432954788208 ], [ "呼", -11.943326950073242 ], [ "同日", -11.94334888458252 ], [ "▁カスタマー", -11.943498611450195 ], [ "製品", -11.943692207336426 ], [ "▁紛失", -11.943771362304688 ], [ "落とさ", -11.943801879882812 ], [ "▁磁気", -11.943862915039062 ], [ "当て", -11.944086074829102 ], [ "小学校", -11.94413948059082 ], [ "▁終日", -11.944191932678223 ], [ "特定", -11.944201469421387 ], [ "▁手がけた", -11.944320678710938 ], [ "AZ", -11.944341659545898 ], [ "▁邪", -11.944353103637695 ], [ "▁Ka", -11.944485664367676 ], [ "ついた", -11.944514274597168 ], [ "逆", -11.94457721710205 ], [ "▁夏季", -11.944693565368652 ], [ "▁ワンマン", -11.944840431213379 ], [ "▁測量", -11.945021629333496 ], [ "暗", -11.945225715637207 ], [ "チュア", -11.945262908935547 ], [ "▁拒絶", -11.94531536102295 ], [ "▁TKO", -11.945352554321289 ], [ "▁とりわけ", -11.945375442504883 ], [ "出会い", -11.9456205368042 ], [ "▁補修", -11.94572639465332 ], [ "▁tr", -11.945740699768066 ], [ "▁鎮圧", -11.945813179016113 ], [ "▁司法書士", -11.945843696594238 ], [ "▁好む", -11.945880889892578 ], [ "▁いったん", -11.945958137512207 ], [ "▁インディ", -11.945972442626953 ], [ "道路", -11.946024894714355 ], [ "▁ソープ", -11.946296691894531 ], [ "▁kW", -11.946345329284668 ], [ "▁出題", -11.946428298950195 ], [ "▁リフト", -11.946430206298828 ], [ "▁増やし", -11.946464538574219 ], [ "▁救", -11.946900367736816 ], [ "▁石原", -11.946982383728027 ], [ "▁紋", -11.947028160095215 ], [ "▁108", -11.947136878967285 ], [ "▁メモリー", -11.947251319885254 ], [ "▁EV", -11.947458267211914 ], [ "▁一流", -11.947511672973633 ], [ "▁きゅう", -11.94753646850586 ], [ "▁凍結", -11.947602272033691 ], [ "巨", -11.94775390625 ], [ "セロ", -11.94782543182373 ], [ "公開", -11.947884559631348 ], [ "似", -11.947991371154785 ], [ "lic", -11.94814395904541 ], [ "▁必然", -11.948149681091309 ], [ "▁高価", -11.948383331298828 ], [ "遣", -11.948522567749023 ], [ "梁", -11.948704719543457 ], [ "▁ダニエル", -11.948715209960938 ], [ "▁カルティエ", -11.94880485534668 ], [ "蓋", -11.948830604553223 ], [ "▁集結", -11.948851585388184 ], [ "▁鈍", -11.948892593383789 ], [ "▁一人一人", -11.949048042297363 ], [ "なんて", -11.949102401733398 ], [ "がく", -11.949248313903809 ], [ "▁Ra", -11.949254989624023 ], [ "▁麻酔", -11.949338912963867 ], [ "どころ", -11.949641227722168 ], [ "▁UC", -11.950033187866211 ], [ "▁マザー", -11.9501314163208 ], [ "▁手がける", -11.950215339660645 ], [ "▁放つ", -11.950220108032227 ], [ "▁つくら", -11.950315475463867 ], [ "住宅", -11.950334548950195 ], [ "▁消毒", -11.95042896270752 ], [ "▁準拠", -11.95050048828125 ], [ "▁クルーズ", -11.950607299804688 ], [ "▁ジオ", -11.950677871704102 ], [ "▁パスタ", -11.950730323791504 ], [ "ムラ", -11.950740814208984 ], [ "浅", -11.950898170471191 ], [ "▁ガチャ", -11.950945854187012 ], [ "▁発作", -11.951101303100586 ], [ "▁恒", -11.951118469238281 ], [ "▁Bluetooth", -11.951313018798828 ], [ "▁占", -11.951329231262207 ], [ "▁観る", -11.951377868652344 ], [ "磨", -11.951460838317871 ], [ "▁活かし", -11.951590538024902 ], [ "▁携わって", -11.95161247253418 ], [ "▁教官", -11.951622009277344 ], [ "▁被った", -11.951781272888184 ], [ "▁内陸", -11.951817512512207 ], [ "即", -11.95185661315918 ], [ "蘭", -11.952012062072754 ], [ "▁両手", -11.952033996582031 ], [ "▁磨き", -11.952054977416992 ], [ "▁乗せて", -11.952101707458496 ], [ "▁農薬", -11.952184677124023 ], [ "▁柴", -11.952216148376465 ], [ "玄", -11.952251434326172 ], [ "▁急性", -11.952388763427734 ], [ "▁叶", -11.952408790588379 ], [ "フー", -11.95248031616211 ], [ "あり", -11.95251750946045 ], [ "ace", -11.952738761901855 ], [ "▁キャバクラ", -11.952754020690918 ], [ "▁ナノ", -11.952827453613281 ], [ "▁麗", -11.952914237976074 ], [ "▁辞退", -11.95299243927002 ], [ "佳", -11.95315170288086 ], [ "塞", -11.953239440917969 ], [ "▁消耗", -11.953346252441406 ], [ "▁プラチナ", -11.953351020812988 ], [ "百万", -11.953392028808594 ], [ "▁近衛", -11.953397750854492 ], [ "▁あきらめ", -11.953542709350586 ], [ "ste", -11.953584671020508 ], [ "ゼー", -11.953662872314453 ], [ "▁合宿", -11.953716278076172 ], [ "▁盛り上がり", -11.953912734985352 ], [ "▁一角", -11.953923225402832 ], [ "ナミ", -11.953930854797363 ], [ "▁パンチ", -11.954017639160156 ], [ "▁寄贈", -11.954174041748047 ], [ "Pro", -11.954268455505371 ], [ "▁ろう", -11.954270362854004 ], [ "▁幾何", -11.954521179199219 ], [ "ae", -11.95458984375 ], [ "▁スコット", -11.954862594604492 ], [ "▁墜落", -11.954995155334473 ], [ "▁漢方", -11.955093383789062 ], [ "▁坊", -11.955245018005371 ], [ "▁å", -11.955336570739746 ], [ "low", -11.955535888671875 ], [ "▁DA", -11.955588340759277 ], [ "▁その分", -11.95560073852539 ], [ "▁見かける", -11.9557523727417 ], [ "▁ラブラドール", -11.95582103729248 ], [ "▁危惧", -11.95582103729248 ], [ "▁用地", -11.955829620361328 ], [ "▁杜", -11.955878257751465 ], [ "▁端子", -11.955982208251953 ], [ "▁行なった", -11.95620346069336 ], [ "▁こま", -11.956287384033203 ], [ "長年", -11.956308364868164 ], [ "干", -11.95638656616211 ], [ "事件", -11.956392288208008 ], [ "▁na", -11.956741333007812 ], [ "▁ドライバ", -11.956827163696289 ], [ "▁下げる", -11.95688533782959 ], [ "▁浴室", -11.957059860229492 ], [ "ならば", -11.957066535949707 ], [ "▁暖かい", -11.957178115844727 ], [ "▁動詞", -11.957329750061035 ], [ "eo", -11.957331657409668 ], [ "▁MT", -11.95736026763916 ], [ "▁上手", -11.957467079162598 ], [ "神戸", -11.957478523254395 ], [ "▁記す", -11.957778930664062 ], [ "▁樹木", -11.957789421081543 ], [ "ンゲン", -11.957871437072754 ], [ "▁階層", -11.957886695861816 ], [ "▁落とした", -11.957930564880371 ], [ "▁つくって", -11.958069801330566 ], [ "▁XP", -11.958155632019043 ], [ "▁幹線", -11.95852279663086 ], [ "誉", -11.958528518676758 ], [ "cu", -11.958534240722656 ], [ "▁網羅", -11.958741188049316 ], [ "やかに", -11.958783149719238 ], [ "▁絶え", -11.958793640136719 ], [ "▁弱く", -11.958797454833984 ], [ "▁衣類", -11.958887100219727 ], [ "▁Sc", -11.959085464477539 ], [ "▁相模", -11.959141731262207 ], [ "play", -11.959217071533203 ], [ "▁蛍光", -11.959317207336426 ], [ "如", -11.959345817565918 ], [ "▁ねこ", -11.959592819213867 ], [ "▁陰謀", -11.95961856842041 ], [ "▁ヤマハ", -11.959731101989746 ], [ "▁称した", -11.9597806930542 ], [ "▁マイン", -11.959972381591797 ], [ "▁烏", -11.96003532409668 ], [ "▁メアリー", -11.960062026977539 ], [ "まち", -11.960088729858398 ], [ "▁車検", -11.960212707519531 ], [ "渓", -11.960237503051758 ], [ "▁バナナ", -11.960245132446289 ], [ "▁いったい", -11.960480690002441 ], [ "▁欠け", -11.960492134094238 ], [ "▁止まら", -11.960530281066895 ], [ "▁ファクトリー", -11.96060848236084 ], [ "まつ", -11.960654258728027 ], [ "テロ", -11.960790634155273 ], [ "▁イイ", -11.96085262298584 ], [ "▁生体", -11.960886001586914 ], [ "▁萩", -11.96097469329834 ], [ "▁ノーベル", -11.961026191711426 ], [ "Microsoft", -11.961047172546387 ], [ "▁le", -11.961078643798828 ], [ "▁理科", -11.96117115020752 ], [ "▁失業", -11.96117877960205 ], [ "▁苦痛", -11.96119499206543 ], [ "ッシャー", -11.961217880249023 ], [ "▁ドローン", -11.961406707763672 ], [ "▁メンタル", -11.961465835571289 ], [ "HOME", -11.961475372314453 ], [ "▁あんまり", -11.961496353149414 ], [ "描", -11.961589813232422 ], [ "▁すず", -11.961702346801758 ], [ "▁体温", -11.961796760559082 ], [ "▁CB", -11.961886405944824 ], [ "▁廻", -11.96200942993164 ], [ "▁成り", -11.96201229095459 ], [ "▁ユニオン", -11.962064743041992 ], [ "▁仕え", -11.962066650390625 ], [ "▁餅", -11.962089538574219 ], [ "▁ウォール", -11.962128639221191 ], [ "シェル", -11.962374687194824 ], [ "▁補充", -11.962573051452637 ], [ "▁柴田", -11.962575912475586 ], [ "▁聡", -11.962628364562988 ], [ "▁先祖", -11.962657928466797 ], [ "▁肝臓", -11.962743759155273 ], [ "bs", -11.962943077087402 ], [ "組織", -11.962963104248047 ], [ "▁フォース", -11.96304988861084 ], [ "▁府立", -11.963101387023926 ], [ "▁アーケード", -11.963224411010742 ], [ "ベス", -11.96335220336914 ], [ "年度", -11.963441848754883 ], [ "1959", -11.963444709777832 ], [ "ポス", -11.96360969543457 ], [ "正直", -11.963713645935059 ], [ "и", -11.963842391967773 ], [ "▁違いない", -11.96389102935791 ], [ "▁凛", -11.96391487121582 ], [ "▁藩士", -11.964062690734863 ], [ "▁同じである", -11.964143753051758 ], [ "▁ヴァー", -11.964212417602539 ], [ "▁ピアニスト", -11.964313507080078 ], [ "PG", -11.96440315246582 ], [ "▁UN", -11.96442985534668 ], [ "▁Am", -11.964437484741211 ], [ "▁フット", -11.964512825012207 ], [ "▁穂", -11.964537620544434 ], [ "uk", -11.964570999145508 ], [ "▁曜日", -11.964677810668945 ], [ "▁電機", -11.964863777160645 ], [ "▁センチメートル", -11.965047836303711 ], [ "グラフィ", -11.965293884277344 ], [ "ジオ", -11.96530818939209 ], [ "▁出入", -11.96534538269043 ], [ "占", -11.965352058410645 ], [ "▁麻雀", -11.965450286865234 ], [ "祐", -11.96552562713623 ], [ "▁糖質", -11.965597152709961 ], [ "▁俗", -11.96560001373291 ], [ "▁タカ", -11.965763092041016 ], [ "▁未だ", -11.96589183807373 ], [ "OG", -11.965924263000488 ], [ "▁プレゼン", -11.966096878051758 ], [ "むしろ", -11.966176986694336 ], [ "▁SK", -11.966268539428711 ], [ "▁モザイク", -11.96634578704834 ], [ "▁飛躍", -11.96635913848877 ], [ "▁DL", -11.966559410095215 ], [ "hen", -11.96657657623291 ], [ "▁出せる", -11.966633796691895 ], [ "▁被告", -11.96665096282959 ], [ "関西", -11.966670036315918 ], [ "▁海底", -11.96676254272461 ], [ "▁最長", -11.966768264770508 ], [ "▁ヨハン", -11.96682071685791 ], [ "yp", -11.966873168945312 ], [ "▁肘", -11.967226028442383 ], [ "▁趙", -11.967233657836914 ], [ "HI", -11.967307090759277 ], [ "▁豆腐", -11.967327117919922 ], [ "▁溢れる", -11.967398643493652 ], [ "▁撃墜", -11.967649459838867 ], [ "▁三木", -11.96788501739502 ], [ "UI", -11.96803092956543 ], [ "▁内定", -11.968042373657227 ], [ "きゅう", -11.968111991882324 ], [ "ele", -11.968170166015625 ], [ "▁見たら", -11.96823501586914 ], [ "▁Wiki", -11.968303680419922 ], [ "▁負わ", -11.968457221984863 ], [ "▁プー", -11.968683242797852 ], [ "FL", -11.968757629394531 ], [ "▁ヤクルト", -11.968762397766113 ], [ "▁エディ", -11.968819618225098 ], [ "▁専任", -11.968903541564941 ], [ "メー", -11.968965530395508 ], [ "Twitter", -11.968989372253418 ], [ "のう", -11.969013214111328 ], [ "off", -11.969033241271973 ], [ "rit", -11.969096183776855 ], [ "▁夜中", -11.96910285949707 ], [ "▁モテ", -11.969183921813965 ], [ "▁神々", -11.969522476196289 ], [ "▁設ける", -11.969703674316406 ], [ "▁ノル", -11.969805717468262 ], [ "▁ステータス", -11.969879150390625 ], [ "経営", -11.969902038574219 ], [ "▁バルブ", -11.970044136047363 ], [ "▁持ち主", -11.970054626464844 ], [ "▁きん", -11.97005558013916 ], [ "▁反面", -11.970175743103027 ], [ "妹", -11.970242500305176 ], [ "言葉", -11.970301628112793 ], [ "▁退役", -11.970345497131348 ], [ "▁1800", -11.97037124633789 ], [ "▁ミーティング", -11.970389366149902 ], [ "▁確実", -11.970664024353027 ], [ "▁amazon", -11.970734596252441 ], [ "ずみ", -11.970739364624023 ], [ "▁いかが", -11.97077751159668 ], [ "wa", -11.970818519592285 ], [ "1947", -11.970916748046875 ], [ "機嫌", -11.970951080322266 ], [ "▁右翼", -11.97099494934082 ], [ "コロ", -11.971144676208496 ], [ "▁生えて", -11.971181869506836 ], [ "▁実戦", -11.9712553024292 ], [ "▁塗料", -11.971287727355957 ], [ "旨", -11.971366882324219 ], [ "ヴィチ", -11.971574783325195 ], [ "ビジネス", -11.971619606018066 ], [ "セックス", -11.971684455871582 ], [ "ux", -11.972042083740234 ], [ "▁):", -11.972168922424316 ], [ "rac", -11.972229957580566 ], [ "▁番台", -11.972240447998047 ], [ "リヒ", -11.97243881225586 ], [ "▁か国", -11.972475051879883 ], [ "▁more", -11.972650527954102 ], [ "▁陥った", -11.97277545928955 ], [ "▁Manual", -11.972783088684082 ], [ "▁練", -11.972792625427246 ], [ "▁あす", -11.972907066345215 ], [ "▁日向", -11.973170280456543 ], [ "ざい", -11.973207473754883 ], [ "▁北上", -11.973237991333008 ], [ "▁アフガニスタン", -11.97329330444336 ], [ "▁エミ", -11.973539352416992 ], [ "▁繰り返", -11.973633766174316 ], [ "▁下がる", -11.973689079284668 ], [ "▁コキ", -11.973828315734863 ], [ "▁訴える", -11.973845481872559 ], [ "▁Red", -11.974014282226562 ], [ "▁JK", -11.974543571472168 ], [ "▁フライト", -11.974733352661133 ], [ "rist", -11.97487735748291 ], [ "▁Comp", -11.974903106689453 ], [ "▁ビザ", -11.975202560424805 ], [ "環境", -11.975211143493652 ], [ "ヶ丘", -11.975221633911133 ], [ "▁LE", -11.975325584411621 ], [ "▁開花", -11.97576904296875 ], [ "ll", -11.975787162780762 ], [ "初め", -11.975912094116211 ], [ "▁カ所", -11.975996017456055 ], [ "ニスト", -11.97611141204834 ], [ "粒", -11.976147651672363 ], [ "▁コーン", -11.976645469665527 ], [ "▁豊島", -11.976665496826172 ], [ "庵", -11.976717948913574 ], [ "クレジット", -11.976720809936523 ], [ "▁きたら", -11.976722717285156 ], [ "▁免", -11.976771354675293 ], [ "▁スピン", -11.976784706115723 ], [ "しゅ", -11.976840019226074 ], [ "ニウム", -11.976947784423828 ], [ "▁捨てる", -11.9769868850708 ], [ "▁ニッ", -11.977023124694824 ], [ "灯", -11.977108001708984 ], [ "▁パッチ", -11.977112770080566 ], [ "▁ディス", -11.977232933044434 ], [ "きん", -11.97725772857666 ], [ "▁WBC", -11.977270126342773 ], [ "▁許容", -11.977272033691406 ], [ "敗", -11.977285385131836 ], [ "▁正常に", -11.977324485778809 ], [ "▁アーサー", -11.977334976196289 ], [ "PU", -11.977398872375488 ], [ "▁上空", -11.97746753692627 ], [ "▁脈", -11.9774751663208 ], [ "▁広げ", -11.97749137878418 ], [ "▁ブライアン", -11.977503776550293 ], [ "▁連休", -11.977585792541504 ], [ "▁図った", -11.977635383605957 ], [ "▁歩み", -11.977652549743652 ], [ "ode", -11.97766399383545 ], [ "対象", -11.97790813446045 ], [ "▁DV", -11.977950096130371 ], [ "▁未知", -11.978086471557617 ], [ "▁占め", -11.978118896484375 ], [ "▁ドキドキ", -11.978297233581543 ], [ "▁ダイビング", -11.97833251953125 ], [ "att", -11.978472709655762 ], [ "▁であったり", -11.978482246398926 ], [ "▁劇中", -11.978588104248047 ], [ "▁辞", -11.978617668151855 ], [ "徹", -11.978713989257812 ], [ "▁フォル", -11.978754997253418 ], [ "▁強力", -11.978755950927734 ], [ "nel", -11.978774070739746 ], [ "▁左手", -11.978796005249023 ], [ "セラ", -11.97881031036377 ], [ "わい", -11.978918075561523 ], [ "車両", -11.978938102722168 ], [ "▁急激に", -11.978955268859863 ], [ "▁通用", -11.979063034057617 ], [ "▁大きかった", -11.979103088378906 ], [ "▁ガチ", -11.979406356811523 ], [ "▁高島", -11.97946548461914 ], [ "▁何と", -11.97972297668457 ], [ "▁最寄り", -11.979769706726074 ], [ "▁継いで", -11.979813575744629 ], [ "ばら", -11.979974746704102 ], [ "かつ", -11.980002403259277 ], [ "▁中等", -11.980110168457031 ], [ "▁お出かけ", -11.980178833007812 ], [ "▁与党", -11.980325698852539 ], [ "▁ローラ", -11.980478286743164 ], [ "▁適切", -11.980563163757324 ], [ "▁働きかけ", -11.980587005615234 ], [ "滑", -11.980606079101562 ], [ "ky", -11.980674743652344 ], [ "▁客車", -11.980844497680664 ], [ "▁バット", -11.980917930603027 ], [ "AU", -11.980928421020508 ], [ "▁キープ", -11.981184959411621 ], [ "學", -11.981215476989746 ], [ "1958", -11.981477737426758 ], [ "▁デブ", -11.98148250579834 ], [ "▁殺す", -11.981618881225586 ], [ "裕", -11.981661796569824 ], [ "▁Time", -11.981762886047363 ], [ "▁聞こえて", -11.981783866882324 ], [ "▁ソファ", -11.981821060180664 ], [ "▁175", -11.982128143310547 ], [ "▁伏見", -11.982151985168457 ], [ "▁打席", -11.98236083984375 ], [ "▁失礼", -11.982577323913574 ], [ "張り", -11.982577323913574 ], [ "▁けんどう", -11.982634544372559 ], [ "動物", -11.982636451721191 ], [ "▁丁寧な", -11.982779502868652 ], [ "めき", -11.982918739318848 ], [ "▁興業", -11.983339309692383 ], [ "なに", -11.983346939086914 ], [ "▁彗星", -11.98357105255127 ], [ "▁進めた", -11.983613014221191 ], [ "イク", -11.983695983886719 ], [ "ザイ", -11.983696937561035 ], [ "芝", -11.983759880065918 ], [ "▁パレード", -11.98404312133789 ], [ "▁SAC", -11.984146118164062 ], [ "調査", -11.984152793884277 ], [ "▁序盤", -11.984346389770508 ], [ "▁下落", -11.984368324279785 ], [ "FI", -11.984670639038086 ], [ "▁評して", -11.984670639038086 ], [ "▁Video", -11.984894752502441 ], [ "▁貼り付け", -11.985016822814941 ], [ "▁看", -11.985107421875 ], [ "▁蝶", -11.98520565032959 ], [ "▁兼ねて", -11.985276222229004 ], [ "▁ハリス", -11.985346794128418 ], [ "▁部会", -11.985408782958984 ], [ "▁就業", -11.98546028137207 ], [ "▁眼科", -11.985483169555664 ], [ "▁102", -11.985618591308594 ], [ "立って", -11.985692024230957 ], [ "▁下げ", -11.98576831817627 ], [ "▁パウダー", -11.985840797424316 ], [ "▁550", -11.985847473144531 ], [ "脚注", -11.985883712768555 ], [ "ICA", -11.985989570617676 ], [ "▁ハミルトン", -11.986028671264648 ], [ "▁購読", -11.986028671264648 ], [ "高い", -11.98631477355957 ], [ "▁あわせ", -11.986409187316895 ], [ "▁世に", -11.986421585083008 ], [ "▁フィラデルフィア", -11.986502647399902 ], [ "ます", -11.986531257629395 ], [ "クン", -11.986538887023926 ], [ "▁パラメータ", -11.986600875854492 ], [ "▁NET", -11.986711502075195 ], [ "ated", -11.986781120300293 ], [ "SL", -11.987138748168945 ], [ "▁卸", -11.987157821655273 ], [ "▁儲け", -11.987194061279297 ], [ "▁眠れ", -11.987234115600586 ], [ "▁暖", -11.987286567687988 ], [ "▁全線", -11.987316131591797 ], [ "▁こころ", -11.987561225891113 ], [ "▁留意", -11.98758602142334 ], [ "▁Jr", -11.987788200378418 ], [ "辱", -11.988302230834961 ], [ "▁バーン", -11.988381385803223 ], [ "はら", -11.988410949707031 ], [ "▁アンプ", -11.988597869873047 ], [ "▁商事", -11.988713264465332 ], [ "INE", -11.98876953125 ], [ "抗", -11.988777160644531 ], [ "▁勝て", -11.988778114318848 ], [ "▁6000", -11.989171028137207 ], [ "HD", -11.98930549621582 ], [ "▁ヤフオク", -11.989347457885742 ], [ "▁佐世保", -11.989347457885742 ], [ "決勝", -11.989370346069336 ], [ "開催", -11.989371299743652 ], [ "▁国々", -11.989426612854004 ], [ "縫", -11.989534378051758 ], [ "▁威力", -11.989614486694336 ], [ "侯", -11.989700317382812 ], [ "▁ノリ", -11.989808082580566 ], [ "リーン", -11.989830017089844 ], [ "▁見受け", -11.989847183227539 ], [ "▁COM", -11.989986419677734 ], [ "▁無駄に", -11.990019798278809 ], [ "LU", -11.990071296691895 ], [ "book", -11.99007511138916 ], [ "▁Ti", -11.990147590637207 ], [ "▁織り", -11.990172386169434 ], [ "QU", -11.990324020385742 ], [ "▁原産", -11.990557670593262 ], [ "がみ", -11.990667343139648 ], [ "リッジ", -11.990742683410645 ], [ "▁踏襲", -11.99086856842041 ], [ "▁めぐり", -11.991084098815918 ], [ "▁遠藤", -11.99111557006836 ], [ "尉", -11.991135597229004 ], [ "▁陽性", -11.99124813079834 ], [ "▁転じ", -11.991264343261719 ], [ "今週", -11.991327285766602 ], [ "▁ブラッド", -11.991348266601562 ], [ "▁越前", -11.991424560546875 ], [ "▁みどり", -11.991701126098633 ], [ "rop", -11.991710662841797 ], [ "▁ゆり", -11.991719245910645 ], [ "▁直して", -11.991881370544434 ], [ "▁定価", -11.991968154907227 ], [ "▁流す", -11.992027282714844 ], [ "▁恥", -11.99209213256836 ], [ "申", -11.992124557495117 ], [ "▁台北", -11.992165565490723 ], [ "渕", -11.99220085144043 ], [ "▁MR", -11.992262840270996 ], [ "▁統", -11.99252700805664 ], [ "▁マウンテン", -11.992581367492676 ], [ "▁着工", -11.992666244506836 ], [ "▁立案", -11.992681503295898 ], [ "TH", -11.992823600769043 ], [ "▁なされ", -11.992855072021484 ], [ "クイ", -11.992934226989746 ], [ "かなり", -11.993124008178711 ], [ "▁留め", -11.993128776550293 ], [ "▁座り", -11.993228912353516 ], [ "▁スコ", -11.993697166442871 ], [ "▁破って", -11.993897438049316 ], [ "殻", -11.99397087097168 ], [ "▁シリコン", -11.994203567504883 ], [ "立った", -11.994256019592285 ], [ "嚢", -11.994680404663086 ], [ "SON", -11.99477767944336 ], [ "聴", -11.9948148727417 ], [ "▁供養", -11.99489688873291 ], [ "▁食用", -11.994908332824707 ], [ "▁咲く", -11.99492073059082 ], [ "▁言動", -11.994943618774414 ], [ "▁傾け", -11.994963645935059 ], [ "▁Server", -11.994967460632324 ], [ "んぽ", -11.995014190673828 ], [ "▁抜けて", -11.995031356811523 ], [ "▁過言", -11.995100975036621 ], [ "▁満たして", -11.995126724243164 ], [ "▁小笠原", -11.995243072509766 ], [ "帖", -11.995253562927246 ], [ "バナ", -11.995280265808105 ], [ "戦闘", -11.995330810546875 ], [ "▁重奏", -11.99533462524414 ], [ "しろ", -11.995478630065918 ], [ "▁同等の", -11.995710372924805 ], [ "▁回想", -11.995731353759766 ], [ "▁高木", -11.99579906463623 ], [ "▁洒落", -11.995922088623047 ], [ "▁弾薬", -11.995962142944336 ], [ "▁プリン", -11.995965003967285 ], [ "▁あわ", -11.996320724487305 ], [ "メス", -11.99635124206543 ], [ "▁盾", -11.99639892578125 ], [ "cle", -11.996414184570312 ], [ "▁橘", -11.996440887451172 ], [ "▁桑", -11.996453285217285 ], [ "▁RA", -11.996659278869629 ], [ "▁まかせ", -11.99674129486084 ], [ "電気", -11.99675464630127 ], [ "▁カミ", -11.996938705444336 ], [ "▁パチスロ", -11.996973991394043 ], [ "▁id", -11.996990203857422 ], [ "▁名づけ", -11.99724292755127 ], [ "供", -11.997435569763184 ], [ "NG", -11.997491836547852 ], [ "▁受託", -11.997762680053711 ], [ "TF", -11.997811317443848 ], [ "▁だめ", -11.99783706665039 ], [ "▁学士", -11.997875213623047 ], [ "▁デッド", -11.997993469238281 ], [ "ress", -11.997994422912598 ], [ "アーズ", -11.998150825500488 ], [ "▁六本木", -11.99831485748291 ], [ "▁各々", -11.998377799987793 ], [ "息子", -11.998404502868652 ], [ "▁遅", -11.99846076965332 ], [ "▁透", -11.998464584350586 ], [ "▁部活", -11.99867057800293 ], [ "▁麻薬", -11.998757362365723 ], [ "qui", -11.998780250549316 ], [ "最後", -11.998839378356934 ], [ "▁接着", -11.998883247375488 ], [ "hr", -11.998917579650879 ], [ "千万", -11.999165534973145 ], [ "▁築き", -11.999175071716309 ], [ "▁黒田", -11.999279022216797 ], [ "▁ドロ", -11.99930477142334 ], [ "▁微分", -11.999430656433105 ], [ "▁恐ろしい", -11.99952220916748 ], [ "▁秩父", -11.99965763092041 ], [ "▁モハ", -11.999674797058105 ], [ "フュー", -11.999724388122559 ], [ "依", -11.99988079071045 ], [ "針", -11.999916076660156 ], [ "▁マーティン", -11.999958038330078 ], [ "▁信じる", -12.000093460083008 ], [ "▁難し", -12.000136375427246 ], [ "▁アジ", -12.000214576721191 ], [ "▁赤坂", -12.00021743774414 ], [ "▁わけじゃ", -12.000239372253418 ], [ "アーカイブ", -12.000443458557129 ], [ "市立", -12.000469207763672 ], [ "▁警報", -12.000521659851074 ], [ "▁ボーイズ", -12.000527381896973 ], [ "▁名目", -12.000597953796387 ], [ "ベット", -12.00067138671875 ], [ "1955", -12.000699043273926 ], [ "yu", -12.000726699829102 ], [ "▁掘", -12.000828742980957 ], [ "料金", -12.000860214233398 ], [ "じゅう", -12.000896453857422 ], [ "▁ウマ", -12.0009765625 ], [ "はい", -12.001053810119629 ], [ "▁ケル", -12.001198768615723 ], [ "残り", -12.001368522644043 ], [ "SR", -12.00139331817627 ], [ "▁紅茶", -12.001533508300781 ], [ "con", -12.001544952392578 ], [ "▁原型", -12.001585960388184 ], [ "▁むら", -12.001639366149902 ], [ "▁ぜん", -12.001694679260254 ], [ "▁活かして", -12.00184440612793 ], [ "OTO", -12.001875877380371 ], [ "▁IR", -12.001997947692871 ], [ "ヨウ", -12.002128601074219 ], [ "▁迷い", -12.00216007232666 ], [ "▁抗体", -12.00217056274414 ], [ "▁It", -12.002175331115723 ], [ "▁減らし", -12.002179145812988 ], [ "▁バンダイ", -12.002182006835938 ], [ "切って", -12.002214431762695 ], [ "▁聞こえ", -12.00224781036377 ], [ "頸", -12.002251625061035 ], [ "▁ムラ", -12.002327919006348 ], [ "▁売れる", -12.002349853515625 ], [ "The", -12.00259017944336 ], [ "▁頂ければ", -12.002720832824707 ], [ "▁マタニティ", -12.002734184265137 ], [ "▁西方", -12.002779960632324 ], [ "▁得票", -12.002788543701172 ], [ "ins", -12.00290584564209 ], [ "▁リアルな", -12.003046035766602 ], [ "栓", -12.003077507019043 ], [ "▁楕円", -12.003599166870117 ], [ "1946", -12.003623008728027 ], [ "HC", -12.003674507141113 ], [ "卑", -12.003695487976074 ], [ "事前", -12.003764152526855 ], [ "▁水系", -12.00395393371582 ], [ "ローマ", -12.003969192504883 ], [ "ショウ", -12.00403881072998 ], [ "▁気づく", -12.004080772399902 ], [ "ばん", -12.004083633422852 ], [ "▁親交", -12.004250526428223 ], [ "▁カルシウム", -12.004563331604004 ], [ "list", -12.004622459411621 ], [ "▁訪ね", -12.004715919494629 ], [ "▁クチコミ", -12.004755973815918 ], [ "▁音質", -12.004925727844238 ], [ "▁↑", -12.004973411560059 ], [ "app", -12.005083084106445 ], [ "▁恥ずかしい", -12.005107879638672 ], [ "▁寸法", -12.005215644836426 ], [ "▁主として", -12.005239486694336 ], [ "▁領事", -12.0054292678833 ], [ "▁南極", -12.00558090209961 ], [ "ンデ", -12.005583763122559 ], [ "範", -12.005670547485352 ], [ "▁柔らかい", -12.005698204040527 ], [ "▁マルコ", -12.00584602355957 ], [ "yth", -12.005935668945312 ], [ "▁岡本", -12.0059814453125 ], [ "ごう", -12.006022453308105 ], [ "HS", -12.006088256835938 ], [ "サキ", -12.006160736083984 ], [ "メラ", -12.006234169006348 ], [ "デラ", -12.006516456604004 ], [ "▁敦", -12.006598472595215 ], [ "▁墨", -12.00667953491211 ], [ "▁用水", -12.006728172302246 ], [ "飼", -12.006791114807129 ], [ "▁菊池", -12.006927490234375 ], [ "▁アスリート", -12.006977081298828 ], [ "▁径", -12.007085800170898 ], [ "▁卓", -12.00710678100586 ], [ "中でも", -12.007112503051758 ], [ "▁託", -12.007379531860352 ], [ "▁範", -12.007390022277832 ], [ "エンジン", -12.007499694824219 ], [ "▁クーデター", -12.007556915283203 ], [ "工科", -12.0077486038208 ], [ "▁1913", -12.007807731628418 ], [ "▁豪雨", -12.007893562316895 ], [ "▁本屋", -12.00795841217041 ], [ "▁117", -12.008166313171387 ], [ "▁売上高", -12.00834846496582 ], [ "▁青少年", -12.008371353149414 ], [ "▁振り返る", -12.008720397949219 ], [ "トラック", -12.008728981018066 ], [ "リット", -12.00877571105957 ], [ "▁試みた", -12.008788108825684 ], [ "▁名物", -12.008800506591797 ], [ "潰", -12.008854866027832 ], [ "▁マスターズ", -12.008872032165527 ], [ "本当", -12.008883476257324 ], [ "カート", -12.00894832611084 ], [ "▁イヤ", -12.009222984313965 ], [ "▁狭く", -12.009349822998047 ], [ "1956", -12.009448051452637 ], [ "久保", -12.009651184082031 ], [ "▁ヴィルヘルム", -12.009686470031738 ], [ "▁罰", -12.009758949279785 ], [ "ボーイ", -12.00999641418457 ], [ "▁ブレンド", -12.01001262664795 ], [ "atch", -12.01003646850586 ], [ "▁滅ぼ", -12.010125160217285 ], [ "▁宇治", -12.01013469696045 ], [ "ブロン", -12.010236740112305 ], [ "1948", -12.010250091552734 ], [ "騒", -12.010327339172363 ], [ "▁渓谷", -12.01046371459961 ], [ "▁広瀬", -12.010550498962402 ], [ "▁係数", -12.010749816894531 ], [ "▁ペル", -12.01108169555664 ], [ "▁双子", -12.011098861694336 ], [ "易", -12.011205673217773 ], [ "晩", -12.011324882507324 ], [ "▁セー", -12.011359214782715 ], [ "▁素敵", -12.011360168457031 ], [ "▁後援", -12.01140022277832 ], [ "ギリ", -12.011577606201172 ], [ "戦争", -12.011988639831543 ], [ "札幌", -12.012046813964844 ], [ "▁川上", -12.012097358703613 ], [ "▁サバ", -12.012321472167969 ], [ "▁カメ", -12.012685775756836 ], [ "最新", -12.012757301330566 ], [ "DM", -12.012762069702148 ], [ "暴", -12.012768745422363 ], [ "▁連ね", -12.012948989868164 ], [ "▁満喫", -12.013096809387207 ], [ "▁足立", -12.013227462768555 ], [ "▁疑わ", -12.013482093811035 ], [ "▁ロジャー", -12.013626098632812 ], [ "▁庵", -12.013651847839355 ], [ "まだまだ", -12.013773918151855 ], [ "▁鶴見", -12.013781547546387 ], [ "やり", -12.014057159423828 ], [ "▁ホイ", -12.014169692993164 ], [ "other", -12.014283180236816 ], [ "ert", -12.014385223388672 ], [ "ニク", -12.014440536499023 ], [ "どき", -12.014817237854004 ], [ "▁ブレイ", -12.014994621276855 ], [ "▁SUPER", -12.015037536621094 ], [ "胤", -12.015129089355469 ], [ "▁下手", -12.01537799835205 ], [ "▁Auto", -12.015384674072266 ], [ "▁罰金", -12.015788078308105 ], [ "▁図ら", -12.015816688537598 ], [ "IST", -12.016030311584473 ], [ "▁ストラップ", -12.01616382598877 ], [ "▁隊長", -12.016426086425781 ], [ "▁撃退", -12.016613960266113 ], [ "▁りゅう", -12.016678810119629 ], [ "▁兵力", -12.016757011413574 ], [ "制作", -12.016845703125 ], [ "▁代々", -12.016990661621094 ], [ "▁立ち上げた", -12.017095565795898 ], [ "▁見積り", -12.017119407653809 ], [ "▁燃", -12.01728343963623 ], [ "▁きれい", -12.017302513122559 ], [ "▁しゅう", -12.017508506774902 ], [ "▁シャルル", -12.017531394958496 ], [ "天正", -12.017690658569336 ], [ "倫", -12.017979621887207 ], [ "▁主権", -12.018132209777832 ], [ "▁招く", -12.018135070800781 ], [ "ょ", -12.018392562866211 ], [ "▁因", -12.018524169921875 ], [ "▁128", -12.018637657165527 ], [ "▁ポーチ", -12.018819808959961 ], [ "▁年少", -12.018819808959961 ], [ "▁ポル", -12.018850326538086 ], [ "メト", -12.018877983093262 ], [ "ーヴ", -12.018942832946777 ], [ "幼少", -12.01911735534668 ], [ "▁訪", -12.019168853759766 ], [ "▁ナル", -12.019237518310547 ], [ "▁ワイヤー", -12.019256591796875 ], [ "▁工法", -12.01927375793457 ], [ "▁大輔", -12.019375801086426 ], [ "´", -12.019506454467773 ], [ "▁浄化", -12.019524574279785 ], [ "▁sa", -12.01967716217041 ], [ "▁レバー", -12.019707679748535 ], [ "▁デフォルト", -12.019966125488281 ], [ "▁113", -12.02003288269043 ], [ "PP", -12.020052909851074 ], [ "▁極端に", -12.020307540893555 ], [ "▁水路", -12.020309448242188 ], [ "▁解く", -12.020448684692383 ], [ "ヴァイ", -12.020626068115234 ], [ "▁至り", -12.020708084106445 ], [ "夷", -12.020797729492188 ], [ "«", -12.020988464355469 ], [ "撫", -12.020990371704102 ], [ "避", -12.021100997924805 ], [ "▁So", -12.02112102508545 ], [ "1939", -12.021154403686523 ], [ "▁po", -12.021231651306152 ], [ "▁ハッ", -12.021286010742188 ], [ "▁捧げ", -12.021364212036133 ], [ "▁薦め", -12.021398544311523 ], [ "▁114", -12.02172565460205 ], [ "▁決着", -12.021748542785645 ], [ "▁東山", -12.021761894226074 ], [ "▁頼む", -12.022078514099121 ], [ "▁屋内", -12.02208423614502 ], [ "▁和歌", -12.022149085998535 ], [ "▁籍", -12.02225112915039 ], [ "くる", -12.022414207458496 ], [ "▁パキスタン", -12.022562980651855 ], [ "合う", -12.022812843322754 ], [ "▁整えて", -12.022831916809082 ], [ "▁詞", -12.022875785827637 ], [ "▁コロン", -12.022994995117188 ], [ "▁AW", -12.023035049438477 ], [ "▁NEC", -12.023256301879883 ], [ "▁受け付け", -12.023270606994629 ], [ "▁賜", -12.02342414855957 ], [ "▁gray", -12.023439407348633 ], [ "▁ぬいぐるみ", -12.023447036743164 ], [ "▁有名である", -12.023499488830566 ], [ "▁投下", -12.02351188659668 ], [ "▁母体", -12.023577690124512 ], [ "▁BC", -12.023634910583496 ], [ "▁all", -12.023706436157227 ], [ "杯", -12.0238618850708 ], [ "▁渡す", -12.024124145507812 ], [ "テレ", -12.024582862854004 ], [ "▁セガ", -12.02458667755127 ], [ "鳴", -12.024700164794922 ], [ "▁自称", -12.024772644042969 ], [ "我々", -12.02479076385498 ], [ "▁バンコク", -12.024824142456055 ], [ "▁血糖", -12.024892807006836 ], [ "迎", -12.024895668029785 ], [ "▁配分", -12.025033950805664 ], [ "ョ", -12.025169372558594 ], [ "▁貫通", -12.025209426879883 ], [ "▁原点", -12.025227546691895 ], [ "ーフ", -12.025289535522461 ], [ "▁均", -12.025335311889648 ], [ "▁コミ", -12.02536392211914 ], [ "▁艦艇", -12.025463104248047 ], [ "▁〇", -12.025522232055664 ], [ "都道府県", -12.025538444519043 ], [ "▁リベラル", -12.025625228881836 ], [ "▁丼", -12.02624797821045 ], [ "ISS", -12.026358604431152 ], [ "▁おしゃれな", -12.026592254638672 ], [ "▁問う", -12.026599884033203 ], [ "たらさ", -12.026674270629883 ], [ "▁さらさ", -12.026843070983887 ], [ "cial", -12.026846885681152 ], [ "▁会費", -12.026870727539062 ], [ "キッ", -12.02689266204834 ], [ "▁暴走", -12.027030944824219 ], [ "▁車庫", -12.02705192565918 ], [ "▁ミュージアム", -12.027286529541016 ], [ "LT", -12.02773380279541 ], [ "ture", -12.027746200561523 ], [ "ime", -12.027884483337402 ], [ "▁渡った", -12.02813720703125 ], [ "スプ", -12.028292655944824 ], [ "▁ドール", -12.028424263000488 ], [ "▁きら", -12.028453826904297 ], [ "早く", -12.02859115600586 ], [ "▁勝った", -12.028727531433105 ], [ "top", -12.028738021850586 ], [ "WS", -12.028796195983887 ], [ "▁信念", -12.028894424438477 ], [ "zu", -12.028950691223145 ], [ "▁アイヌ", -12.028985977172852 ], [ "▁練馬", -12.029120445251465 ], [ "è", -12.029163360595703 ], [ "マシーン", -12.029186248779297 ], [ "MM", -12.029335021972656 ], [ "▁みなし", -12.029571533203125 ], [ "▁代理人", -12.029828071594238 ], [ "鍋", -12.0299072265625 ], [ "▁着目", -12.029927253723145 ], [ "ンジ", -12.029927253723145 ], [ "▁すり", -12.030180931091309 ], [ "▁大久保", -12.03022575378418 ], [ "▁猪", -12.03026294708252 ], [ "je", -12.030506134033203 ], [ "▁推し", -12.03055191040039 ], [ "はな", -12.030569076538086 ], [ "1954", -12.03061294555664 ], [ "que", -12.03061294555664 ], [ "▁使い分け", -12.030792236328125 ], [ "▁望み", -12.030793190002441 ], [ "デジタル", -12.030813217163086 ], [ "▁スリム", -12.030922889709473 ], [ "▁生前", -12.030929565429688 ], [ "▁イライラ", -12.030953407287598 ], [ "▁ヴォル", -12.031042098999023 ], [ "亘", -12.031339645385742 ], [ "アジア", -12.03135871887207 ], [ "▁パニック", -12.031383514404297 ], [ "▁紗", -12.031455039978027 ], [ "▁隠れて", -12.031514167785645 ], [ "建物", -12.031661033630371 ], [ "省", -12.031776428222656 ], [ "▁氏族", -12.031834602355957 ], [ "▁アンティーク", -12.031854629516602 ], [ "忙し", -12.031900405883789 ], [ "縮", -12.031970024108887 ], [ "▁志願", -12.032115936279297 ], [ "▁叫び", -12.032132148742676 ], [ "▁的だった", -12.032208442687988 ], [ "▁Pi", -12.03221321105957 ], [ "▁吉川", -12.032342910766602 ], [ "遇", -12.032361030578613 ], [ "▁巡回", -12.032380104064941 ], [ "李", -12.0324125289917 ], [ "美容", -12.032763481140137 ], [ "get", -12.032772064208984 ], [ "▁112", -12.03278636932373 ], [ "1949", -12.0328950881958 ], [ "かえ", -12.032928466796875 ], [ "▁通じる", -12.032963752746582 ], [ "しゅう", -12.033111572265625 ], [ "定期", -12.033157348632812 ], [ "▁祝福", -12.033199310302734 ], [ "▁ラッキー", -12.033387184143066 ], [ "▁中性", -12.033401489257812 ], [ "▁降って", -12.033587455749512 ], [ "逸", -12.033649444580078 ], [ "誌", -12.033653259277344 ], [ "俗", -12.033815383911133 ], [ "▁皇子", -12.033828735351562 ], [ "▁作風", -12.034064292907715 ], [ "▁引き継いだ", -12.034137725830078 ], [ "▁役目", -12.034173011779785 ], [ "▁願望", -12.034235954284668 ], [ "▁Fe", -12.034327507019043 ], [ "▁迷彩", -12.034414291381836 ], [ "▁mini", -12.034528732299805 ], [ "エア", -12.034544944763184 ], [ "▁ペルー", -12.034628868103027 ], [ "宇宙", -12.034714698791504 ], [ "▁八重", -12.034839630126953 ], [ "▁International", -12.035011291503906 ], [ "▁CV", -12.035077095031738 ], [ "▁ROM", -12.035185813903809 ], [ "▁眞", -12.03519058227539 ], [ "▁目録", -12.035242080688477 ], [ "▁珠", -12.03528881072998 ], [ "▁カリキュラム", -12.035308837890625 ], [ "▁テク", -12.035386085510254 ], [ "▁ブリー", -12.035438537597656 ], [ "▁もてなし", -12.035526275634766 ], [ "ラグ", -12.035529136657715 ], [ "▁凍", -12.03566837310791 ], [ "▁フォーミュラ", -12.035707473754883 ], [ "▁開局", -12.035898208618164 ], [ "▁駅伝", -12.036035537719727 ], [ "鼻", -12.036112785339355 ], [ "▁温かい", -12.036213874816895 ], [ "▁活発に", -12.036369323730469 ], [ "ソリ", -12.036397933959961 ], [ "▁押さえ", -12.036410331726074 ], [ "▁事象", -12.036550521850586 ], [ "▁妖", -12.036674499511719 ], [ "▁浴場", -12.036985397338867 ], [ "▁NSE", -12.037089347839355 ], [ "スキン", -12.03711986541748 ], [ "▁立派な", -12.037461280822754 ], [ "▁大国", -12.037626266479492 ], [ "場所", -12.037690162658691 ], [ "▁採掘", -12.037711143493652 ], [ "▁真ん中", -12.03797435760498 ], [ "▁ギャグ", -12.038028717041016 ], [ "▁おこう", -12.038174629211426 ], [ "▁特権", -12.038220405578613 ], [ "BE", -12.038248062133789 ], [ "▁移る", -12.038324356079102 ], [ "▁担", -12.038328170776367 ], [ "環", -12.038461685180664 ], [ "`", -12.03852653503418 ], [ "▁ラス", -12.038734436035156 ], [ "最新の", -12.03892707824707 ], [ "▁なが", -12.038965225219727 ], [ "中世", -12.03899097442627 ], [ "▁跨", -12.0390043258667 ], [ "▁斜", -12.039046287536621 ], [ "rid", -12.039083480834961 ], [ "▁帰った", -12.039090156555176 ], [ "▁カビ", -12.039155960083008 ], [ "ビリ", -12.03933048248291 ], [ "uch", -12.039373397827148 ], [ "▁男優", -12.039412498474121 ], [ "▁関わった", -12.039795875549316 ], [ "関東", -12.039809226989746 ], [ "▁及ば", -12.039814949035645 ], [ "既に", -12.039826393127441 ], [ "▁ヴェネツィア", -12.039993286132812 ], [ "ステル", -12.040040016174316 ], [ "▁掛かる", -12.040106773376465 ], [ "▁Explorer", -12.040393829345703 ], [ "▁突撃", -12.040433883666992 ], [ "▁淡", -12.040450096130371 ], [ "▁トレント", -12.040796279907227 ], [ "▁名乗り", -12.040950775146484 ], [ "▁成る", -12.041208267211914 ], [ "▁オルガン", -12.041210174560547 ], [ "001", -12.041279792785645 ], [ "分布", -12.041505813598633 ], [ "▁Pe", -12.041516304016113 ], [ "ces", -12.041542053222656 ], [ "▁婚姻", -12.041698455810547 ], [ "▁万が一", -12.04173469543457 ], [ "▁りん", -12.041741371154785 ], [ "▁続々", -12.04202651977539 ], [ "▁代数", -12.0420503616333 ], [ "ブレー", -12.042218208312988 ], [ "▁通商", -12.04234790802002 ], [ "▁希少", -12.04251480102539 ], [ "▁本件", -12.042716026306152 ], [ "れい", -12.042730331420898 ], [ "▁使者", -12.042794227600098 ], [ "▁含んだ", -12.04285717010498 ], [ "▁中日", -12.042987823486328 ], [ "▁踊る", -12.042998313903809 ], [ "テスト", -12.043190956115723 ], [ "har", -12.043210983276367 ], [ "▁付着", -12.043264389038086 ], [ "▁投球", -12.043313980102539 ], [ "▁やってくる", -12.043339729309082 ], [ "▁治世", -12.043387413024902 ], [ "▁盆地", -12.043396949768066 ], [ "概説", -12.043442726135254 ], [ "▁田園", -12.04344654083252 ], [ "▁タラ", -12.043513298034668 ], [ "▁鍛え", -12.043607711791992 ], [ "▁特設", -12.043660163879395 ], [ "穀", -12.043696403503418 ], [ "帳", -12.0437650680542 ], [ "▁役立て", -12.04378604888916 ], [ "▁カレ", -12.043805122375488 ], [ "RAM", -12.043880462646484 ], [ "▁増設", -12.043901443481445 ], [ "テキスト", -12.043905258178711 ], [ "▁ゴン", -12.043912887573242 ], [ "▁神秘", -12.044041633605957 ], [ "▁発する", -12.044163703918457 ], [ "▁役場", -12.044179916381836 ], [ "炊", -12.044397354125977 ], [ "▁十三", -12.04446792602539 ], [ "▁ベースボール", -12.044524192810059 ], [ "▁セクション", -12.0446138381958 ], [ "こく", -12.044666290283203 ], [ "いわゆる", -12.044682502746582 ], [ "▁政務", -12.044715881347656 ], [ "▁げん", -12.044918060302734 ], [ "1952", -12.04494571685791 ], [ "▁創り", -12.045021057128906 ], [ "▁ピストン", -12.04505443572998 ], [ "買", -12.045061111450195 ], [ "▁DP", -12.045063018798828 ], [ "▁際し", -12.045077323913574 ], [ "▁曰く", -12.045103073120117 ], [ "つい", -12.045242309570312 ], [ "▁両面", -12.045289993286133 ], [ "▁濃厚", -12.045292854309082 ], [ "▁営む", -12.045392036437988 ], [ "▁go", -12.045470237731934 ], [ "▁取り入れる", -12.045665740966797 ], [ "▁規範", -12.04570484161377 ], [ "維", -12.045707702636719 ], [ "▁アト", -12.045748710632324 ], [ "▁ヨーク", -12.046090126037598 ], [ "▁秋葉原", -12.046106338500977 ], [ "▁暴行", -12.046555519104004 ], [ "▁皇太子", -12.046608924865723 ], [ "▁専業", -12.046730995178223 ], [ "エム", -12.046754837036133 ], [ "▁Can", -12.04677677154541 ], [ "口コミ", -12.046905517578125 ], [ "▁分かれる", -12.047000885009766 ], [ "▁及ぼし", -12.047015190124512 ], [ "▁原材料", -12.047037124633789 ], [ "▁生かして", -12.047057151794434 ], [ "▁優し", -12.047069549560547 ], [ "▁前橋", -12.047094345092773 ], [ "▁吊り", -12.047165870666504 ], [ "▁おやつ", -12.04721736907959 ], [ "▁燕", -12.047380447387695 ], [ "▁漆", -12.047422409057617 ], [ "▁真相", -12.047459602355957 ], [ "差し", -12.047477722167969 ], [ "並", -12.047487258911133 ], [ "▁都営", -12.04749870300293 ], [ "▁尼崎", -12.047616004943848 ], [ "▁バウ", -12.047722816467285 ], [ "▁届いて", -12.047789573669434 ], [ "▁リーディング", -12.04789924621582 ], [ "▁Ho", -12.04804515838623 ], [ "▁民法", -12.048050880432129 ], [ "▁縛", -12.04807186126709 ], [ "INT", -12.048162460327148 ], [ "ビッチ", -12.048335075378418 ], [ "▁入所", -12.048492431640625 ], [ "▁MediaWiki", -12.0485258102417 ], [ "▁誠実", -12.0488862991333 ], [ "将来", -12.049050331115723 ], [ "SO", -12.04908561706543 ], [ "ool", -12.049124717712402 ], [ "▁Po", -12.049128532409668 ], [ "▁ライオンズ", -12.049223899841309 ], [ "小説", -12.049243927001953 ], [ "▁iphone", -12.049263954162598 ], [ "▁湿度", -12.049368858337402 ], [ "▁BB", -12.049421310424805 ], [ "現行", -12.04943561553955 ], [ "▁誤った", -12.04954719543457 ], [ "ILL", -12.049615859985352 ], [ "▁べし", -12.049661636352539 ], [ "汁", -12.049675941467285 ], [ "▁デザート", -12.049732208251953 ], [ "▁洋画", -12.049732208251953 ], [ "▁お家", -12.049784660339355 ], [ "もない", -12.049860954284668 ], [ "▁1915", -12.049866676330566 ], [ "▁マサチューセッツ", -12.049932479858398 ], [ "まとめ", -12.050128936767578 ], [ "援", -12.050172805786133 ], [ "▁症例", -12.050288200378418 ], [ "▁ウィリアムズ", -12.050382614135742 ], [ "▁固有の", -12.05063533782959 ], [ "只", -12.050637245178223 ], [ "▁祖先", -12.050649642944336 ], [ "讃", -12.05070972442627 ], [ "▁カーボン", -12.050724029541016 ], [ "tan", -12.05094051361084 ], [ "ぱ", -12.050959587097168 ], [ "▁青葉", -12.051074028015137 ], [ "▁硬化", -12.051226615905762 ], [ "▁武力", -12.051239967346191 ], [ "▁アーチ", -12.051376342773438 ], [ "▁ビス", -12.051403999328613 ], [ "BU", -12.051523208618164 ], [ "▁尖", -12.051616668701172 ], [ "▁rd", -12.051806449890137 ], [ "レフ", -12.052119255065918 ], [ "▁掲示", -12.052128791809082 ], [ "е", -12.052255630493164 ], [ "▁不明の", -12.052277565002441 ], [ "▁ロビー", -12.052383422851562 ], [ "DY", -12.052427291870117 ], [ "どれ", -12.052620887756348 ], [ "▁協奏曲", -12.052661895751953 ], [ "▁餃子", -12.052661895751953 ], [ "▁怒ら", -12.052667617797852 ], [ "▁法定", -12.052678108215332 ], [ "▁Wii", -12.052783012390137 ], [ "▁定住", -12.052877426147461 ], [ "▁金持ち", -12.052935600280762 ], [ "mp", -12.05294418334961 ], [ "▁搬送", -12.05296516418457 ], [ "▁エリート", -12.053023338317871 ], [ "漫", -12.053045272827148 ], [ "▁減る", -12.053442001342773 ], [ "▁べきな", -12.053443908691406 ], [ "tin", -12.053498268127441 ], [ "UE", -12.053522109985352 ], [ "▁拉致", -12.053572654724121 ], [ "▁youtube", -12.053573608398438 ], [ "▁フォワード", -12.053689956665039 ], [ "▁ぐん", -12.053738594055176 ], [ "▁000", -12.053741455078125 ], [ "▁付随", -12.053754806518555 ], [ "▁名人", -12.053781509399414 ], [ "▁手軽", -12.053840637207031 ], [ "▁倒", -12.053893089294434 ], [ "▁シャトー", -12.053958892822266 ], [ "▁独学", -12.054040908813477 ], [ "▁石田", -12.054153442382812 ], [ "藝", -12.054383277893066 ], [ "▁憎", -12.054597854614258 ], [ "▁絶頂", -12.054606437683105 ], [ "▁南米", -12.054643630981445 ], [ "UB", -12.054655075073242 ], [ "orn", -12.054666519165039 ], [ "▁下関", -12.054682731628418 ], [ "▁勾配", -12.0546875 ], [ "▁眠って", -12.054716110229492 ], [ "▁ヘー", -12.054814338684082 ], [ "▁寸", -12.054985046386719 ], [ "▁リスナー", -12.05511474609375 ], [ "▁MUSIC", -12.055194854736328 ], [ "構造", -12.055200576782227 ], [ "トラン", -12.055413246154785 ], [ "▁トーン", -12.055432319641113 ], [ "▁感度", -12.055575370788574 ], [ "ifi", -12.055601119995117 ], [ "▁逃げる", -12.055655479431152 ], [ "▁行え", -12.056012153625488 ], [ "かみ", -12.05609130859375 ], [ "▁ランス", -12.056175231933594 ], [ "▁母音", -12.056244850158691 ], [ "▁スルー", -12.05630874633789 ], [ "コース", -12.056312561035156 ], [ "CR", -12.056323051452637 ], [ "▁人体", -12.056342124938965 ], [ "狐", -12.056513786315918 ], [ "▁ウェディング", -12.056772232055664 ], [ "▁あう", -12.056877136230469 ], [ "▁クリクラ", -12.05710220336914 ], [ "▁苦戦", -12.057229995727539 ], [ "ジル", -12.057331085205078 ], [ "▁就航", -12.057342529296875 ], [ "▁ウェールズ", -12.057432174682617 ], [ "▁EA", -12.057578086853027 ], [ "▁塗", -12.057665824890137 ], [ "▁カツ", -12.057743072509766 ], [ "▁ひき", -12.057830810546875 ], [ "がけ", -12.057923316955566 ], [ "▁望ま", -12.057960510253906 ], [ "▁ライス", -12.057981491088867 ], [ "▁降りて", -12.057984352111816 ], [ "HT", -12.057990074157715 ], [ "盟", -12.058003425598145 ], [ "▁同等", -12.058222770690918 ], [ "▁基幹", -12.058252334594727 ], [ "▁色素", -12.058259963989258 ], [ "1953", -12.058283805847168 ], [ "▁唱え", -12.0582857131958 ], [ "▁もしかしたら", -12.058307647705078 ], [ "播", -12.058320999145508 ], [ "▁柿", -12.058359146118164 ], [ "▁錯誤", -12.058445930480957 ], [ "▁落札", -12.058486938476562 ], [ "▁Bar", -12.058564186096191 ], [ "▁NS", -12.058684349060059 ], [ "アンド", -12.058878898620605 ], [ "▁伊予", -12.058895111083984 ], [ "▁大学校", -12.058961868286133 ], [ "▁小島", -12.059021949768066 ], [ "▁混同", -12.059048652648926 ], [ "▁vodafone", -12.059056282043457 ], [ "ウォ", -12.059073448181152 ], [ "十七", -12.059097290039062 ], [ "▁風土", -12.05920696258545 ], [ "▁挑む", -12.059261322021484 ], [ "悩", -12.05936336517334 ], [ "▁たり", -12.059469223022461 ], [ "Co", -12.059666633605957 ], [ "▁流して", -12.059671401977539 ], [ "1957", -12.059691429138184 ], [ "ウェン", -12.059694290161133 ], [ "何度", -12.05981731414795 ], [ "▁こん", -12.059906005859375 ], [ "▁さまざま", -12.059985160827637 ], [ "▁届出", -12.059995651245117 ], [ "▁首長", -12.060133934020996 ], [ "▁Per", -12.060277938842773 ], [ "▁レイプ", -12.060371398925781 ], [ "ナウ", -12.060397148132324 ], [ "私生活", -12.06042194366455 ], [ "star", -12.060503005981445 ], [ "テージ", -12.060556411743164 ], [ "▁News", -12.060651779174805 ], [ "▁最速", -12.06068229675293 ], [ "ft", -12.060686111450195 ], [ "裂", -12.06074333190918 ], [ "▁有罪", -12.060783386230469 ], [ "▁訓", -12.060830116271973 ], [ "昼", -12.060925483703613 ], [ "▁メルカリ", -12.060929298400879 ], [ "▁包み", -12.060933113098145 ], [ "ION", -12.060970306396484 ], [ "▁獅子", -12.060994148254395 ], [ "使い", -12.061037063598633 ], [ "リッツ", -12.06108570098877 ], [ "カップ", -12.061100006103516 ], [ "▁躊躇", -12.061197280883789 ], [ "▁ショルダー", -12.061299324035645 ], [ "▁滅", -12.061565399169922 ], [ "▁換算", -12.061605453491211 ], [ "▁ヴィン", -12.061606407165527 ], [ "▁えい", -12.061616897583008 ], [ "▁コナン", -12.061701774597168 ], [ "秘", -12.061789512634277 ], [ "更", -12.06191635131836 ], [ "▁全集", -12.061929702758789 ], [ "▁バク", -12.06194019317627 ], [ "寄せ", -12.061956405639648 ], [ "▁突如", -12.062028884887695 ], [ "▁弾圧", -12.06203842163086 ], [ "▁着いた", -12.06207275390625 ], [ "▁ブラウザー", -12.062185287475586 ], [ "▁学級", -12.062196731567383 ], [ "▁かっこいい", -12.0623197555542 ], [ "雅", -12.062426567077637 ], [ "てん", -12.062552452087402 ], [ "▁シェフ", -12.062603950500488 ], [ "▁熊谷", -12.06261157989502 ], [ "鉱", -12.06277084350586 ], [ "▁古着", -12.062804222106934 ], [ "サッカー", -12.062822341918945 ], [ "▁見つめ", -12.062826156616211 ], [ "▁みたいで", -12.062846183776855 ], [ "▁西村", -12.063023567199707 ], [ "▁can", -12.063179969787598 ], [ "▁農園", -12.06326675415039 ], [ "活動", -12.063299179077148 ], [ "▁AF", -12.063326835632324 ], [ "▁重要に", -12.063370704650879 ], [ "▁次郎", -12.063566207885742 ], [ "四郎", -12.063569068908691 ], [ "▁アポ", -12.06357479095459 ], [ "▁伸ばして", -12.063702583312988 ], [ "ley", -12.063704490661621 ], [ "祥", -12.063725471496582 ], [ "▁地盤", -12.063788414001465 ], [ "ころ", -12.063807487487793 ], [ "▁乗員", -12.063861846923828 ], [ "▁うま", -12.063924789428711 ], [ "▁謙", -12.063995361328125 ], [ "ティーン", -12.064075469970703 ], [ "棒", -12.06408405303955 ], [ "▁パーフェクト", -12.064160346984863 ], [ "▁習い", -12.06418514251709 ], [ "茨城", -12.064325332641602 ], [ "▁狩猟", -12.064366340637207 ], [ "主要", -12.064453125 ], [ "せた", -12.064537048339844 ], [ "▁パブリック", -12.064552307128906 ], [ "▁しき", -12.06464672088623 ], [ "注意", -12.064671516418457 ], [ "俣", -12.064715385437012 ], [ "▁都度", -12.06472110748291 ], [ "▁騒音", -12.064776420593262 ], [ "▁書簡", -12.064848899841309 ], [ "▁半径", -12.064969062805176 ], [ "きょ", -12.065115928649902 ], [ "▁恐らく", -12.06515884399414 ], [ "プレス", -12.065165519714355 ], [ "争", -12.065165519714355 ], [ "▁蹴", -12.065183639526367 ], [ "▁ねじ", -12.06525707244873 ], [ "▁悲し", -12.065285682678223 ], [ "ym", -12.065299987792969 ], [ "▁リハビリテーション", -12.065301895141602 ], [ "kin", -12.065314292907715 ], [ "▁カシ", -12.065317153930664 ], [ "レッジ", -12.065360069274902 ], [ "ean", -12.065397262573242 ], [ "▁めぐって", -12.065410614013672 ], [ "▁183", -12.065425872802734 ], [ "▁皮切", -12.065618515014648 ], [ "▁住吉", -12.065642356872559 ], [ "▁後年", -12.06569766998291 ], [ "否", -12.065720558166504 ], [ "▁元禄", -12.065762519836426 ], [ "隣", -12.06579303741455 ], [ "ute", -12.06590461730957 ], [ "▁リンゴ", -12.065939903259277 ], [ "▁宅地", -12.065950393676758 ], [ "つぶ", -12.066058158874512 ], [ "▁寝具", -12.066119194030762 ], [ "VC", -12.06624984741211 ], [ "▁アイディア", -12.06640625 ], [ "▁バズ", -12.066452980041504 ], [ "芳", -12.066463470458984 ], [ "▁船体", -12.066574096679688 ], [ "効果", -12.066585540771484 ], [ "▁つて", -12.066699028015137 ], [ "じり", -12.066843032836914 ], [ "ゴール", -12.066896438598633 ], [ "tory", -12.067008018493652 ], [ "ャ", -12.067129135131836 ], [ "▁プリキュア", -12.06734848022461 ], [ "fer", -12.067378997802734 ], [ "▁Firefox", -12.067410469055176 ], [ "▁対談", -12.067480087280273 ], [ "ez", -12.06753921508789 ], [ "▁素早く", -12.068096160888672 ], [ "▁書面", -12.068367958068848 ], [ "ヴィス", -12.06843376159668 ], [ "建設", -12.068483352661133 ], [ "▁経理", -12.068547248840332 ], [ "▁ぶん", -12.068550109863281 ], [ "石川", -12.068608283996582 ], [ "駒", -12.06865406036377 ], [ "▁シンポジウム", -12.068674087524414 ], [ "AX", -12.06869125366211 ], [ "▁有用", -12.0687837600708 ], [ "▁不審", -12.068824768066406 ], [ "▁Youtube", -12.06894302368164 ], [ "設計", -12.068985939025879 ], [ "▁オト", -12.069037437438965 ], [ "到", -12.069058418273926 ], [ "▁抜か", -12.069154739379883 ], [ "▁背負", -12.069156646728516 ], [ "▁悪かった", -12.069268226623535 ], [ "▁殴", -12.069340705871582 ], [ "▁遥", -12.069388389587402 ], [ "▁削", -12.069623947143555 ], [ "▁好きだった", -12.069894790649414 ], [ "忍", -12.069896697998047 ], [ "▁ともかく", -12.06991195678711 ], [ "▁ケータイ", -12.069953918457031 ], [ "グラフ", -12.070067405700684 ], [ "グラン", -12.07007122039795 ], [ "やす", -12.07011890411377 ], [ "▁刺さ", -12.070128440856934 ], [ "▁一行", -12.07020378112793 ], [ "▁パラリンピック", -12.070218086242676 ], [ "▁所管", -12.07023811340332 ], [ "▁Reader", -12.070340156555176 ], [ "至", -12.070403099060059 ], [ "▁ストリーミング", -12.070423126220703 ], [ "▁UV", -12.070427894592285 ], [ "早々", -12.070446014404297 ], [ "▁教団", -12.07060718536377 ], [ "▁那須", -12.070629119873047 ], [ "▁例年", -12.070708274841309 ], [ "▁横山", -12.070796012878418 ], [ "▁ヒロ", -12.070808410644531 ], [ "ぐれ", -12.07083511352539 ], [ "◎", -12.070932388305664 ], [ "落とし", -12.071026802062988 ], [ "ばり", -12.071087837219238 ], [ "▁伸ばす", -12.071145057678223 ], [ "所要", -12.071146011352539 ], [ "期間", -12.071181297302246 ], [ "▁出会って", -12.071422576904297 ], [ "っぷ", -12.071435928344727 ], [ "rom", -12.071601867675781 ], [ "▁願う", -12.071836471557617 ], [ "ッスル", -12.071863174438477 ], [ "▁現職", -12.071907043457031 ], [ "▁市区", -12.072066307067871 ], [ "▁近世", -12.072073936462402 ], [ "▁per", -12.072127342224121 ], [ "リッシュ", -12.072169303894043 ], [ "▁ビーム", -12.072331428527832 ], [ "鋼", -12.07235050201416 ], [ "▁眺めて", -12.07251262664795 ], [ "アクセス", -12.072604179382324 ], [ "▁he", -12.072762489318848 ], [ "▁常連", -12.072840690612793 ], [ "▁特異", -12.072958946228027 ], [ "食事", -12.072996139526367 ], [ "▁星野", -12.0730562210083 ], [ "▁芸名", -12.073079109191895 ], [ "▁歪", -12.073152542114258 ], [ "▁cl", -12.07320785522461 ], [ "COM", -12.073259353637695 ], [ "▁鉢", -12.073352813720703 ], [ "▁澄", -12.073413848876953 ], [ "▁食欲", -12.073538780212402 ], [ "燃", -12.073685646057129 ], [ "リフ", -12.073697090148926 ], [ "▁必殺", -12.073740005493164 ], [ "▁馬力", -12.073760032653809 ], [ "▁もしも", -12.073762893676758 ], [ "▁土器", -12.073963165283203 ], [ "▁アタック", -12.074055671691895 ], [ "▁MVP", -12.074174880981445 ], [ "癌", -12.074262619018555 ], [ "▁最悪の", -12.074501991271973 ], [ "▁暁", -12.074514389038086 ], [ "姉", -12.074563026428223 ], [ "▁警官", -12.074655532836914 ], [ "▁Hot", -12.074728965759277 ], [ "▁河原", -12.074796676635742 ], [ "▁1908", -12.074840545654297 ], [ "▁面会", -12.074885368347168 ], [ "サカ", -12.074941635131836 ], [ "▁堆積", -12.074965476989746 ], [ "▁マヤ", -12.074999809265137 ], [ "▁ナイ", -12.075016021728516 ], [ "▁管弦", -12.075055122375488 ], [ "▁キレイ", -12.0751371383667 ], [ "▁配下", -12.075169563293457 ], [ "▁晃", -12.075272560119629 ], [ "堤", -12.075441360473633 ], [ "▁手動", -12.075461387634277 ], [ "Mac", -12.07553482055664 ], [ "▁専務", -12.075543403625488 ], [ "▁われわれ", -12.075690269470215 ], [ "小路", -12.075949668884277 ], [ "▁伏", -12.076041221618652 ], [ "▁Excel", -12.076159477233887 ], [ "杵", -12.076208114624023 ], [ "▁モンテ", -12.07623291015625 ], [ "▁ロープ", -12.076295852661133 ], [ "▁うけ", -12.076391220092773 ], [ "▁枠組み", -12.076457023620605 ], [ "▁柔らかく", -12.076504707336426 ], [ "▁ピク", -12.076530456542969 ], [ "来年", -12.076611518859863 ], [ "▁揺", -12.076674461364746 ], [ "▁確かな", -12.076700210571289 ], [ "▁恐", -12.076732635498047 ], [ "▁メリ", -12.077054023742676 ], [ "▁降る", -12.077108383178711 ], [ "▁すみ", -12.077113151550293 ], [ "▁自粛", -12.07719898223877 ], [ "▁意味合い", -12.077232360839844 ], [ "微", -12.077278137207031 ], [ "▁充", -12.077282905578613 ], [ "コミ", -12.077347755432129 ], [ "▁Ba", -12.07748031616211 ], [ "▁義務付け", -12.077608108520508 ], [ "琴", -12.077710151672363 ], [ "▁陥って", -12.07786750793457 ], [ "▁シルク", -12.07800579071045 ], [ "▁パク", -12.078041076660156 ], [ "▁たまら", -12.07809829711914 ], [ "著作", -12.078156471252441 ], [ "▁横綱", -12.078391075134277 ], [ "▁三好", -12.07847785949707 ], [ "▁:)", -12.078489303588867 ], [ "▁斜め", -12.078513145446777 ], [ "▁異なった", -12.07853889465332 ], [ "men", -12.078675270080566 ], [ "▁南京", -12.07870864868164 ], [ "▁犯行", -12.078797340393066 ], [ "FE", -12.07880687713623 ], [ "▁ホリ", -12.079154014587402 ], [ "▁円形", -12.07923698425293 ], [ "▁十一", -12.079251289367676 ], [ "▁ムスリム", -12.07973575592041 ], [ "▁請負", -12.079739570617676 ], [ "イカ", -12.079747200012207 ], [ "▁チェン", -12.079771041870117 ], [ "▁要領", -12.07982349395752 ], [ "モデル", -12.07984733581543 ], [ "岐阜", -12.080012321472168 ], [ "▁余地", -12.080117225646973 ], [ "▁心がけ", -12.080144882202148 ], [ "▁欲しく", -12.080337524414062 ], [ "▁Sch", -12.080368041992188 ], [ "▁向か", -12.08040714263916 ], [ "▁りょう", -12.080440521240234 ], [ "▁オリックス", -12.0805025100708 ], [ "▁静かな", -12.080524444580078 ], [ "▁実物", -12.080643653869629 ], [ "▁木曽", -12.080933570861816 ], [ "▁少佐", -12.081027030944824 ], [ "ウェブ", -12.08126449584961 ], [ "▁限って", -12.081265449523926 ], [ "▁転写", -12.081338882446289 ], [ "ling", -12.081352233886719 ], [ "▁man", -12.081457138061523 ], [ "オーストラリア", -12.0814790725708 ], [ "繁", -12.08149242401123 ], [ "▁アルファベット", -12.081721305847168 ], [ "▁ブルーレイ", -12.08187484741211 ], [ "▁丹波", -12.081875801086426 ], [ "▁深め", -12.081901550292969 ], [ "▁己", -12.081924438476562 ], [ "生徒", -12.0822114944458 ], [ "▁ルーツ", -12.082234382629395 ], [ "Sh", -12.082277297973633 ], [ "▁トップス", -12.082322120666504 ], [ "▁党首", -12.082398414611816 ], [ "▁朝倉", -12.082536697387695 ], [ "正式", -12.082564353942871 ], [ "▁コウ", -12.08265495300293 ], [ "みん", -12.082671165466309 ], [ "ボーン", -12.082677841186523 ], [ "▁いちばん", -12.082771301269531 ], [ "▁中京", -12.082850456237793 ], [ "長い", -12.08292007446289 ], [ "瓶", -12.082954406738281 ], [ "▁照射", -12.08301830291748 ], [ "▁鈴鹿", -12.083296775817871 ], [ "▁トク", -12.083325386047363 ], [ "▁親切", -12.083366394042969 ], [ "las", -12.083442687988281 ], [ "▁浴", -12.083539009094238 ], [ "▁育つ", -12.083561897277832 ], [ "長崎", -12.083587646484375 ], [ "ぶし", -12.083786010742188 ], [ "▁club", -12.083817481994629 ], [ "▁下がり", -12.08387279510498 ], [ "▁アワード", -12.083914756774902 ], [ "mark", -12.0841064453125 ], [ "▁オートバイ", -12.084184646606445 ], [ "▁月日", -12.084485054016113 ], [ "▁普遍", -12.084532737731934 ], [ "▁肥料", -12.084539413452148 ], [ "UL", -12.084562301635742 ], [ "山田", -12.084583282470703 ], [ "▁両側", -12.084708213806152 ], [ "▁ベストセラー", -12.084726333618164 ], [ "▁くださり", -12.08474349975586 ], [ "▁アルバ", -12.084749221801758 ], [ "▁青色", -12.084762573242188 ], [ "▁スズキ", -12.084851264953613 ], [ "▁再選", -12.084892272949219 ], [ "▁ドレ", -12.084897994995117 ], [ "▁祈願", -12.08494758605957 ], [ "カワ", -12.084972381591797 ], [ "▁充て", -12.085023880004883 ], [ "▁遼", -12.085062026977539 ], [ "▁アビ", -12.085119247436523 ], [ "穏", -12.085186958312988 ], [ "iss", -12.085235595703125 ], [ "▁妊婦", -12.085261344909668 ], [ "▁1907", -12.0852632522583 ], [ "▁履", -12.085271835327148 ], [ "▁理学部", -12.085322380065918 ], [ "▁ワイヤレス", -12.085365295410156 ], [ "▁軽井沢", -12.08557415008545 ], [ "▁スノー", -12.08558464050293 ], [ "淀川", -12.085634231567383 ], [ "オーバー", -12.085714340209961 ], [ "▁観念", -12.085824966430664 ], [ "▁かず", -12.08585262298584 ], [ "▁一目", -12.08592700958252 ], [ "▁Dis", -12.086169242858887 ], [ "▁放った", -12.086431503295898 ], [ "▁ワゴン", -12.086540222167969 ], [ "▁鉛筆", -12.08663272857666 ], [ "ンドラ", -12.086798667907715 ], [ "▁合金", -12.086840629577637 ], [ "▁射精", -12.08685302734375 ], [ "▁戸田", -12.086921691894531 ], [ "▁チキン", -12.087179183959961 ], [ "▁愛し", -12.087291717529297 ], [ "▁鉱", -12.08734130859375 ], [ "▁IoT", -12.087563514709473 ], [ "▁定額", -12.087646484375 ], [ "WE", -12.08765983581543 ], [ "翌日", -12.087724685668945 ], [ "1937", -12.087868690490723 ], [ "▁225", -12.08788013458252 ], [ "▁惨", -12.088119506835938 ], [ "さつ", -12.088189125061035 ], [ "シート", -12.08833122253418 ], [ "技術", -12.08837890625 ], [ "▁吉本", -12.088407516479492 ], [ "▁┃", -12.088601112365723 ], [ "▁棋士", -12.088611602783203 ], [ "▁ステイ", -12.088761329650879 ], [ "ーニャ", -12.088842391967773 ], [ "▁路上", -12.08886432647705 ], [ "ゐ", -12.089007377624512 ], [ "▁花嫁", -12.089019775390625 ], [ "▁本能", -12.089156150817871 ], [ "ano", -12.089159965515137 ], [ "▁厳密に", -12.089178085327148 ], [ "加害", -12.089727401733398 ], [ "尽", -12.089865684509277 ], [ "▁退学", -12.089876174926758 ], [ "▁沸", -12.089906692504883 ], [ "▁blue", -12.089934349060059 ], [ "ニオン", -12.089934349060059 ], [ "▁王妃", -12.089980125427246 ], [ "▁カロ", -12.090007781982422 ], [ "▁誘致", -12.09009075164795 ], [ "ぶら", -12.090156555175781 ], [ "藻", -12.09015941619873 ], [ "▁HPE", -12.090213775634766 ], [ "▁一宮", -12.090311050415039 ], [ "▁西口", -12.09032917022705 ], [ "隈", -12.090344429016113 ], [ "▁是", -12.090397834777832 ], [ "▁RS", -12.090413093566895 ], [ "▁we", -12.090433120727539 ], [ "▁招聘", -12.090500831604004 ], [ "▁口腔", -12.090608596801758 ], [ "▁ブス", -12.09067440032959 ], [ "▁欠場", -12.090686798095703 ], [ "▁花見", -12.090790748596191 ], [ "ドス", -12.090808868408203 ], [ "▁西川", -12.090887069702148 ], [ "▁ウラ", -12.090947151184082 ], [ "▁届", -12.090964317321777 ], [ "▁うまい", -12.091055870056152 ], [ "ハウゼン", -12.091094970703125 ], [ "line", -12.091160774230957 ], [ "▁特長", -12.091193199157715 ], [ "▁主観", -12.091194152832031 ], [ "▁代官", -12.091241836547852 ], [ "▁応える", -12.091524124145508 ], [ "▁頂", -12.091559410095215 ], [ "▁下水", -12.091660499572754 ], [ "▁135", -12.091803550720215 ], [ "LINE", -12.091848373413086 ], [ "婿", -12.09186840057373 ], [ "振り", -12.091883659362793 ], [ "▁ばかりで", -12.09190559387207 ], [ "▁歌謡", -12.092000961303711 ], [ "▁喫し", -12.092022895812988 ], [ "▁大社", -12.092062950134277 ], [ "▁検診", -12.09221076965332 ], [ "▁ワッペン", -12.092214584350586 ], [ "▁大変です", -12.092302322387695 ], [ "▁ツーリング", -12.092427253723145 ], [ "▁ジェフ", -12.092482566833496 ], [ "▁本気", -12.09253215789795 ], [ "▁儀", -12.092540740966797 ], [ "▁WordPress", -12.09254264831543 ], [ "▁裏切", -12.09254264831543 ], [ "孔", -12.092750549316406 ], [ "家庭", -12.092750549316406 ], [ "タニ", -12.092801094055176 ], [ "▁破棄", -12.092823028564453 ], [ "ノミ", -12.092859268188477 ], [ "▁勤め", -12.092985153198242 ], [ "▁それとも", -12.093066215515137 ], [ "ets", -12.093121528625488 ], [ "▁王室", -12.093131065368652 ], [ "▁厩舎", -12.09355354309082 ], [ "▁シールド", -12.093725204467773 ], [ "▁", -12.093757629394531 ], [ "▁控えて", -12.093796730041504 ], [ "▁当てて", -12.093830108642578 ], [ "▁食卓", -12.093830108642578 ], [ "▁BEST", -12.09386157989502 ], [ "▁管制", -12.094076156616211 ], [ "大正", -12.094176292419434 ], [ "レンジ", -12.0942964553833 ], [ "AKA", -12.094367980957031 ], [ "苗", -12.094382286071777 ], [ "他方", -12.094511985778809 ], [ "▁寄稿", -12.094522476196289 ], [ "▁GK", -12.094551086425781 ], [ "個別", -12.094830513000488 ], [ "▁ネックレス", -12.094907760620117 ], [ "▁三郎", -12.094971656799316 ], [ "賃", -12.095020294189453 ], [ "▁語源", -12.095117568969727 ], [ "xy", -12.09548282623291 ], [ "▁菩薩", -12.095558166503906 ], [ "シナ", -12.095792770385742 ], [ "▁ドラゴンボール", -12.095802307128906 ], [ "tt", -12.095808029174805 ], [ "舷", -12.095874786376953 ], [ "▁政令", -12.095978736877441 ], [ "ze", -12.096040725708008 ], [ "▁あた", -12.096078872680664 ], [ "棺", -12.096086502075195 ], [ "▁安藤", -12.096144676208496 ], [ "ルム", -12.096208572387695 ], [ "創業", -12.096301078796387 ], [ "精神", -12.096352577209473 ], [ "函", -12.096380233764648 ], [ "ページ", -12.096571922302246 ], [ "衡", -12.096640586853027 ], [ "いん", -12.096670150756836 ], [ "ani", -12.096816062927246 ], [ "▁ウブロ", -12.09686279296875 ], [ "▁選べ", -12.096899032592773 ], [ "ü", -12.097064018249512 ], [ "▁ランナー", -12.097248077392578 ], [ "ナール", -12.097387313842773 ], [ "綿", -12.0975923538208 ], [ "ベース", -12.09760856628418 ], [ "▁猟", -12.097676277160645 ], [ "▁ファイバー", -12.097784042358398 ], [ "消費", -12.097799301147461 ], [ "▁陶", -12.098066329956055 ], [ "▁原田", -12.098132133483887 ], [ "▁リム", -12.098231315612793 ], [ "▁行進", -12.098246574401855 ], [ "▁ちゃんねる", -12.098414421081543 ], [ "マッチ", -12.098490715026855 ], [ "▁撤回", -12.098519325256348 ], [ "▁塊", -12.098546981811523 ], [ "▁傷つけ", -12.098560333251953 ], [ "▁邸宅", -12.098641395568848 ], [ "▁紙幣", -12.098686218261719 ], [ "▁国軍", -12.09900951385498 ], [ "▁癒さ", -12.099051475524902 ], [ "▁魅了", -12.099056243896484 ], [ "▁マインド", -12.09907054901123 ], [ "▁FI", -12.099135398864746 ], [ "▁320", -12.099197387695312 ], [ "▁スリ", -12.099241256713867 ], [ "ユニ", -12.099352836608887 ], [ "▁ソン", -12.099472045898438 ], [ "cy", -12.099624633789062 ], [ "▁動かして", -12.09965705871582 ], [ "▁日用", -12.099736213684082 ], [ "▁周知", -12.099858283996582 ], [ "▁バルト", -12.099878311157227 ], [ "▁かしら", -12.099912643432617 ], [ "▁楠", -12.100241661071777 ], [ "▁切ら", -12.100242614746094 ], [ "鷹", -12.10024642944336 ], [ "▁魏", -12.100446701049805 ], [ "▁上越", -12.100468635559082 ], [ "AF", -12.100818634033203 ], [ "▁ばあちゃん", -12.100852966308594 ], [ "▁ボクサー", -12.100933074951172 ], [ "宋", -12.101235389709473 ], [ "▁コンスタン", -12.101238250732422 ], [ "▁消えた", -12.101401329040527 ], [ "▁配線", -12.101462364196777 ], [ "▁コーラス", -12.101736068725586 ], [ "▁納品", -12.101956367492676 ], [ "▁フレッシュ", -12.102128982543945 ], [ "▁小型の", -12.102408409118652 ], [ "▁電撃", -12.102426528930664 ], [ "スペ", -12.102460861206055 ], [ "セラー", -12.102709770202637 ], [ "▁空白", -12.102723121643066 ], [ "▁Kindle", -12.102765083312988 ], [ "▁越後", -12.10282039642334 ], [ "▁いち早く", -12.102994918823242 ], [ "▁←", -12.103053092956543 ], [ "▁合間", -12.103249549865723 ], [ "oku", -12.103253364562988 ], [ "ื", -12.103297233581543 ], [ "▁シンガー", -12.103456497192383 ], [ "▁本音", -12.103697776794434 ], [ "pic", -12.10374641418457 ], [ "▁ノイ", -12.10374927520752 ], [ "▁欲望", -12.10374927520752 ], [ "Translate", -12.103890419006348 ], [ "ニシ", -12.104015350341797 ], [ "▁登り", -12.104571342468262 ], [ "eep", -12.10458755493164 ], [ "▁重症", -12.104615211486816 ], [ "▁慰安", -12.10489559173584 ], [ "▁繰り", -12.10492992401123 ], [ "▁春秋", -12.105203628540039 ], [ "▁セリエ", -12.105273246765137 ], [ "▁ナレーション", -12.105340003967285 ], [ "▁アンリ", -12.105342864990234 ], [ "▁不法", -12.105386734008789 ], [ "▁市南", -12.10539436340332 ], [ "▁承って", -12.105422019958496 ], [ "▁喫した", -12.105565071105957 ], [ "のり", -12.105903625488281 ], [ "▁送迎", -12.105981826782227 ], [ "エット", -12.106012344360352 ], [ "東北", -12.106289863586426 ], [ "ABJ", -12.106356620788574 ], [ "ボット", -12.106549263000488 ], [ "▁ファイト", -12.106698989868164 ], [ "▁うさぎ", -12.106709480285645 ], [ "▁筒", -12.107053756713867 ], [ "▁学期", -12.107057571411133 ], [ "▁リセット", -12.107086181640625 ], [ "▁苦情", -12.10713005065918 ], [ "▁En", -12.107182502746582 ], [ "▁彰", -12.107452392578125 ], [ "▁知り合った", -12.107457160949707 ], [ "マツ", -12.107491493225098 ], [ "▁ビビ", -12.107502937316895 ], [ "▁腎臓", -12.107675552368164 ], [ "▁効能", -12.107817649841309 ], [ "濱", -12.107882499694824 ], [ "ザール", -12.108014106750488 ], [ "ric", -12.108077049255371 ], [ "▁モットー", -12.108101844787598 ], [ "▁シャッター", -12.108238220214844 ], [ "▁7000", -12.108298301696777 ], [ "▁私的", -12.10831356048584 ], [ "▁活発", -12.108335494995117 ], [ "oshi", -12.108354568481445 ], [ "爾", -12.108419418334961 ], [ "バチ", -12.10843276977539 ], [ "▁駄目", -12.108527183532715 ], [ "▁誤って", -12.108682632446289 ], [ "▁家老", -12.108715057373047 ], [ "▁PE", -12.108819007873535 ], [ "▁たつ", -12.108856201171875 ], [ "▁えん", -12.108931541442871 ], [ "▁崖", -12.109217643737793 ], [ "▁アミ", -12.109271049499512 ], [ "ユキ", -12.109309196472168 ], [ "だったら", -12.109521865844727 ], [ "▁コリン", -12.1096830368042 ], [ "▁GPS", -12.109792709350586 ], [ "▁書物", -12.110057830810547 ], [ "沙汰", -12.110077857971191 ], [ "▁リオ", -12.110078811645508 ], [ "レール", -12.110222816467285 ], [ "▁ずれ", -12.11035442352295 ], [ "▁CLUB", -12.110355377197266 ], [ "▁こく", -12.110397338867188 ], [ "乗り", -12.110505104064941 ], [ "▁アロ", -12.11058235168457 ], [ "▁駿", -12.110602378845215 ], [ "▁ジョイ", -12.110627174377441 ], [ "▁怪", -12.110644340515137 ], [ "▁唄", -12.110648155212402 ], [ "複", -12.110807418823242 ], [ "▁かえって", -12.111015319824219 ], [ "▁崩", -12.111152648925781 ], [ "cer", -12.111194610595703 ], [ "▁フィットネス", -12.111358642578125 ], [ "▁クラーク", -12.111377716064453 ], [ "▁文房具", -12.111419677734375 ], [ "▁CT", -12.111461639404297 ], [ "壊", -12.111505508422852 ], [ "ワース", -12.111600875854492 ], [ "▁甚", -12.11168384552002 ], [ "▁鳥類", -12.111759185791016 ], [ "▁燃費", -12.111862182617188 ], [ "▁if", -12.112042427062988 ], [ "▁プロテスタン", -12.112171173095703 ], [ "▁高野", -12.112298011779785 ], [ "▁キャリー", -12.112318992614746 ], [ "偶", -12.11257553100586 ], [ "安全", -12.112592697143555 ], [ "▁隠して", -12.112787246704102 ], [ "1000", -12.112869262695312 ], [ "▁開けた", -12.113194465637207 ], [ "▁行けば", -12.113323211669922 ], [ "▁うつ病", -12.113373756408691 ], [ "レスト", -12.11337947845459 ], [ "1951", -12.11344051361084 ], [ "▁鍼灸", -12.113460540771484 ], [ "▁感性", -12.113624572753906 ], [ "▁任ぜ", -12.113707542419434 ], [ "ンベルク", -12.113751411437988 ], [ "▁任天堂", -12.113774299621582 ], [ "▁Plugin", -12.113890647888184 ], [ "▁提起", -12.113890647888184 ], [ "推", -12.114012718200684 ], [ "▁タマ", -12.114052772521973 ], [ "▁っけ", -12.114062309265137 ], [ "▁消失", -12.114119529724121 ], [ "gr", -12.114250183105469 ], [ "鹿児島", -12.114351272583008 ], [ "▁太夫", -12.114409446716309 ], [ "チャイ", -12.114449501037598 ], [ "テナ", -12.11445426940918 ], [ "拡", -12.114481925964355 ], [ "▁ブッシュ", -12.11452865600586 ], [ "理由", -12.114533424377441 ], [ "▁負けて", -12.114628791809082 ], [ "▁南端", -12.114744186401367 ], [ "▁於いて", -12.114795684814453 ], [ "▁僧侶", -12.114861488342285 ], [ "筒", -12.114933013916016 ], [ "駆", -12.114947319030762 ], [ "AA", -12.114995002746582 ], [ "枠", -12.115017890930176 ], [ "IV", -12.115123748779297 ], [ "van", -12.115132331848145 ], [ "っしゃ", -12.115169525146484 ], [ "▁ペルシア", -12.115354537963867 ], [ "▁摩擦", -12.115509033203125 ], [ "▁特攻", -12.11557674407959 ], [ "▁細か", -12.115578651428223 ], [ "▁慶応", -12.11568546295166 ], [ "▁返", -12.115686416625977 ], [ "▁断熱", -12.115937232971191 ], [ "▁工賃", -12.115955352783203 ], [ "双", -12.116034507751465 ], [ "▁強盗", -12.116191864013672 ], [ "住所", -12.116294860839844 ], [ "▁リバウンド", -12.11636734008789 ], [ "▁綺麗", -12.116415977478027 ], [ "▁家畜", -12.11650276184082 ], [ "▁別荘", -12.116652488708496 ], [ "▁おる", -12.117237091064453 ], [ "▁年数", -12.11741828918457 ], [ "▁DD", -12.117509841918945 ], [ "▁殻", -12.117589950561523 ], [ "▁Hi", -12.11763858795166 ], [ "▁1916", -12.117668151855469 ], [ "▁インストラクター", -12.117986679077148 ], [ "▁同じだ", -12.118046760559082 ], [ "▁拡充", -12.11830997467041 ], [ "▁ナポリ", -12.118361473083496 ], [ "▁迫って", -12.118413925170898 ], [ "▁換える", -12.118460655212402 ], [ "▁Is", -12.118463516235352 ], [ "タケ", -12.11852741241455 ], [ "▁調停", -12.118551254272461 ], [ "▁ピエール", -12.11860179901123 ], [ "▁テクノ", -12.11865520477295 ], [ "▁凄", -12.118712425231934 ], [ "▁単価", -12.118792533874512 ], [ "午後", -12.118871688842773 ], [ "帆", -12.119102478027344 ], [ "▁見事に", -12.119148254394531 ], [ "▁ネイティブ", -12.119185447692871 ], [ "撰", -12.119283676147461 ], [ "▁片手", -12.119333267211914 ], [ "Wiki", -12.119342803955078 ], [ "▁連発", -12.119376182556152 ], [ "▁カンボジア", -12.1194429397583 ], [ "▁増す", -12.119620323181152 ], [ "▁プロトコル", -12.119721412658691 ], [ "チオ", -12.11972427368164 ], [ "▁最善", -12.119887351989746 ], [ "同じく", -12.119909286499023 ], [ "`)", -12.120060920715332 ], [ "運動", -12.120138168334961 ], [ "ブラウザ", -12.120209693908691 ], [ "▁背番号", -12.120309829711914 ], [ "であろう", -12.1204252243042 ], [ "MAN", -12.120537757873535 ], [ "▁すみません", -12.120566368103027 ], [ "▁バナー", -12.120580673217773 ], [ "▁寄せて", -12.120744705200195 ], [ "oss", -12.120748519897461 ], [ "WC", -12.120800971984863 ], [ "▁水力", -12.120838165283203 ], [ "▁解き", -12.120861053466797 ], [ "▁一度に", -12.121021270751953 ], [ "住民", -12.121054649353027 ], [ "LY", -12.12108325958252 ], [ "▁色合い", -12.121136665344238 ], [ "py", -12.1212158203125 ], [ "国民", -12.121285438537598 ], [ "▁天王", -12.121333122253418 ], [ "▁ウォーズ", -12.121384620666504 ], [ "▁梅雨", -12.12186336517334 ], [ "TY", -12.12199592590332 ], [ "胆", -12.122089385986328 ], [ "ブラー", -12.122106552124023 ], [ "▁遮断", -12.12212085723877 ], [ "br", -12.12230110168457 ], [ "レコ", -12.122349739074707 ], [ "▁移し", -12.122596740722656 ], [ "祝", -12.12260913848877 ], [ "▁もったいない", -12.122641563415527 ], [ "太陽", -12.122840881347656 ], [ "▁水面", -12.122842788696289 ], [ "▁GL", -12.122952461242676 ], [ "▁貼って", -12.122967720031738 ], [ "▁追悼", -12.12297534942627 ], [ "▁完璧な", -12.123064041137695 ], [ "Tech", -12.123224258422852 ], [ "▁アンナ", -12.123358726501465 ], [ "▁減った", -12.123537063598633 ], [ "▁ルーファ", -12.123615264892578 ], [ "垂", -12.123678207397461 ], [ "▁賜り", -12.123703002929688 ], [ "▁到来", -12.123726844787598 ], [ "ANA", -12.123770713806152 ], [ "▁いちご", -12.123991966247559 ], [ "▁梶", -12.124005317687988 ], [ "▁蒸し", -12.124102592468262 ], [ "ロンドン", -12.124200820922852 ], [ "キル", -12.124242782592773 ], [ "▁浅野", -12.124296188354492 ], [ "▁SR", -12.12433910369873 ], [ "▁残存", -12.124412536621094 ], [ "vent", -12.124561309814453 ], [ "▁間に合わ", -12.124567985534668 ], [ "▁MHz", -12.12470531463623 ], [ "▁RC", -12.124762535095215 ], [ "▁すき", -12.124809265136719 ], [ "▁良好な", -12.124809265136719 ], [ "▁若く", -12.12484073638916 ], [ "nes", -12.12486743927002 ], [ "▁我が国", -12.124919891357422 ], [ "部屋", -12.124943733215332 ], [ "▁軍勢", -12.124953269958496 ], [ "あるいは", -12.125041007995605 ], [ "▁新刊", -12.125068664550781 ], [ "▁Data", -12.12513256072998 ], [ "▁ジャム", -12.125378608703613 ], [ "▁養護", -12.125395774841309 ], [ "▁在り", -12.125442504882812 ], [ "▁Word", -12.125455856323242 ], [ "▁店主", -12.125456809997559 ], [ "▁宮本", -12.125544548034668 ], [ "勉", -12.125667572021484 ], [ "▁館長", -12.125702857971191 ], [ "▁ウォーキング", -12.125718116760254 ], [ "▁湿", -12.126065254211426 ], [ "▁咲き", -12.12612247467041 ], [ "ぞく", -12.126130104064941 ], [ "▁まくり", -12.126152992248535 ], [ "▁誤差", -12.126167297363281 ], [ "▁耐性", -12.126261711120605 ], [ "非常に", -12.126364707946777 ], [ "鈴", -12.126452445983887 ], [ "▁連敗", -12.12649917602539 ], [ "▁和食", -12.126547813415527 ], [ "▁出会える", -12.12664794921875 ], [ "▁逢", -12.126664161682129 ], [ "郭", -12.12668228149414 ], [ "▁火星", -12.12686824798584 ], [ "誠", -12.12705135345459 ], [ "くも", -12.127269744873047 ], [ "▁若しくは", -12.127318382263184 ], [ "▁強め", -12.127425193786621 ], [ "▁訴えた", -12.127574920654297 ], [ "TM", -12.127639770507812 ], [ "▁アトリエ", -12.127886772155762 ], [ "▁擁立", -12.127972602844238 ], [ "知ら", -12.128107070922852 ], [ "▁出会え", -12.128193855285645 ], [ "物語", -12.128203392028809 ], [ "▁消去", -12.128307342529297 ], [ "▁引き出す", -12.12860107421875 ], [ "▁クラン", -12.128631591796875 ], [ "▁ザン", -12.128692626953125 ], [ "▁重要だ", -12.128908157348633 ], [ "ざわ", -12.128935813903809 ], [ "グー", -12.12903881072998 ], [ "▁製菓", -12.129043579101562 ], [ "▁原爆", -12.129066467285156 ], [ "権者", -12.12911319732666 ], [ "▁TOUR", -12.129196166992188 ], [ "▁唯", -12.129301071166992 ], [ "▁転落", -12.129384994506836 ], [ "▁井戸", -12.129470825195312 ], [ "ママ", -12.129495620727539 ], [ "▁煽", -12.129501342773438 ], [ "夕", -12.129509925842285 ], [ "▁マツダ", -12.129622459411621 ], [ "▁貴重", -12.129657745361328 ], [ "▁走ら", -12.129715919494629 ], [ "▁召", -12.129721641540527 ], [ "▁握り", -12.12983226776123 ], [ "▁トート", -12.129851341247559 ], [ "▁Fate", -12.129860877990723 ], [ "▁肺炎", -12.130075454711914 ], [ "▁検知", -12.130157470703125 ], [ "▁留ま", -12.130306243896484 ], [ "▁内田", -12.130342483520508 ], [ "▁施した", -12.130583763122559 ], [ "▁連想", -12.130841255187988 ], [ "▁爆破", -12.130959510803223 ], [ "▁全土", -12.130975723266602 ], [ "▁撃沈", -12.131148338317871 ], [ "▁8000", -12.13129997253418 ], [ "▁HA", -12.13159465789795 ], [ "▁Blue", -12.131611824035645 ], [ "▁ステレオ", -12.13161563873291 ], [ "▁エール", -12.131632804870605 ], [ "▁pr", -12.131698608398438 ], [ "ini", -12.131821632385254 ], [ "▁給食", -12.13203239440918 ], [ "BM", -12.132132530212402 ], [ "▁鎌", -12.13219928741455 ], [ "▁UFC", -12.132317543029785 ], [ "ors", -12.132582664489746 ], [ "▁おおむね", -12.133004188537598 ], [ "▁友情", -12.133056640625 ], [ "オブ", -12.133129119873047 ], [ "+", -12.13318920135498 ], [ "▁優れ", -12.133411407470703 ], [ "ブラック", -12.133447647094727 ], [ "ょう", -12.133591651916504 ], [ "▁æ", -12.133720397949219 ], [ "▁培", -12.133747100830078 ], [ "▁創始", -12.133792877197266 ], [ "▁テンポ", -12.133822441101074 ], [ "▁カラダ", -12.133829116821289 ], [ "▁収束", -12.133899688720703 ], [ "▁骨盤", -12.133962631225586 ], [ "▁隠れ", -12.134186744689941 ], [ "▁交戦", -12.134218215942383 ], [ "▁2500", -12.13426399230957 ], [ "▁レアル", -12.134295463562012 ], [ "▁ひろし", -12.13432788848877 ], [ "▁弥生", -12.1343412399292 ], [ "▁バンクーバー", -12.134346008300781 ], [ "▁大切だ", -12.134364128112793 ], [ "▁曽", -12.134414672851562 ], [ "▁経ち", -12.13448715209961 ], [ "▁炎上", -12.134495735168457 ], [ "▁感心", -12.134511947631836 ], [ "▁アーキテクチャ", -12.134539604187012 ], [ "たくさんの", -12.134584426879883 ], [ "▁捕", -12.134593963623047 ], [ "ケーション", -12.134685516357422 ], [ "▁Out", -12.134751319885254 ], [ "▁カウンセラー", -12.134869575500488 ], [ "フード", -12.134987831115723 ], [ "▁純粋な", -12.135003089904785 ], [ "▁ばら", -12.135160446166992 ], [ "▁リモコン", -12.135198593139648 ], [ "▁exe", -12.135202407836914 ], [ "▁新卒", -12.135223388671875 ], [ "▁BBC", -12.135320663452148 ], [ "▁欠陥", -12.13542366027832 ], [ "▁功労", -12.1354398727417 ], [ "▁品番", -12.135618209838867 ], [ "揚", -12.135652542114258 ], [ "▁労務", -12.135687828063965 ], [ "▁芯", -12.13583755493164 ], [ "タリー", -12.135909080505371 ], [ "ye", -12.135936737060547 ], [ "▁動態", -12.136452674865723 ], [ "▁結城", -12.136552810668945 ], [ "▁大抵", -12.136557579040527 ], [ "▁彫", -12.1366548538208 ], [ "▁トニー", -12.13668441772461 ], [ "▁酢", -12.13669204711914 ], [ "▁無くて", -12.136701583862305 ], [ "▁ホルダー", -12.13670539855957 ], [ "普通", -12.136774063110352 ], [ "▁長寿", -12.136883735656738 ], [ "先週", -12.136993408203125 ], [ "読み", -12.137117385864258 ], [ "▁桜井", -12.13720989227295 ], [ "▁イク", -12.137223243713379 ], [ "著書", -12.137271881103516 ], [ "▁土砂", -12.137277603149414 ], [ "gin", -12.137343406677246 ], [ "▁殺した", -12.137406349182129 ], [ "▁ヌー", -12.137430191040039 ], [ "身体", -12.137499809265137 ], [ "▁一例", -12.137713432312012 ], [ "げて", -12.13773250579834 ], [ "MB", -12.13785457611084 ], [ "コア", -12.137906074523926 ], [ "▁島田", -12.13796329498291 ], [ "▁NC", -12.137991905212402 ], [ "ぎり", -12.13800048828125 ], [ "DU", -12.138040542602539 ], [ "▁チーフ", -12.138063430786133 ], [ "cho", -12.138191223144531 ], [ "▁細部", -12.138266563415527 ], [ "▁PHP", -12.138294219970703 ], [ "リリース", -12.138405799865723 ], [ "▁イルミネーション", -12.138501167297363 ], [ "EF", -12.138517379760742 ], [ "▁パケット", -12.138605117797852 ], [ "▁์", -12.13872241973877 ], [ "▁臓器", -12.138832092285156 ], [ "▁カウ", -12.138859748840332 ], [ "ィー", -12.138919830322266 ], [ "▁屋上", -12.139094352722168 ], [ "▁リットル", -12.139165878295898 ], [ "▁垂れ", -12.139211654663086 ], [ "ナルド", -12.139227867126465 ], [ "求", -12.13924503326416 ], [ "▁寂しい", -12.139403343200684 ], [ "▁受取", -12.139557838439941 ], [ "▁パロディ", -12.139641761779785 ], [ "▁手掛けて", -12.139825820922852 ], [ "ever", -12.140000343322754 ], [ "斉", -12.14001178741455 ], [ "▁慣習", -12.140045166015625 ], [ "▁EN", -12.140241622924805 ], [ "▁片方", -12.140398025512695 ], [ "▁しりつ", -12.140450477600098 ], [ "▁アイアン", -12.140460014343262 ], [ "▁八戸", -12.140469551086426 ], [ "▁鬼滅の刃", -12.14059829711914 ], [ "▁経った", -12.140599250793457 ], [ "▁改築", -12.140629768371582 ], [ "▁帆", -12.14067268371582 ], [ "▁江戸川", -12.140685081481934 ], [ "▁絹", -12.140799522399902 ], [ "SB", -12.140802383422852 ], [ "▁粘", -12.140979766845703 ], [ "▁縄文", -12.140992164611816 ], [ "▁サプライズ", -12.141104698181152 ], [ "▁探せ", -12.141120910644531 ], [ "映像", -12.141207695007324 ], [ "▁略奪", -12.141271591186523 ], [ "患者", -12.141310691833496 ], [ "▁ブルック", -12.141340255737305 ], [ "▁考", -12.14149284362793 ], [ "▁1905", -12.14179801940918 ], [ "トール", -12.141828536987305 ], [ "▁const", -12.141853332519531 ], [ "▁駿河", -12.141956329345703 ], [ "ガニ", -12.142008781433105 ], [ "▁刺繍", -12.142036437988281 ], [ "DAM", -12.142074584960938 ], [ "タラ", -12.14230728149414 ], [ "▁勃起", -12.142367362976074 ], [ "▁ダメな", -12.1423921585083 ], [ "▁マフラー", -12.142699241638184 ], [ "▁イラ", -12.142709732055664 ], [ "▁凌", -12.142870903015137 ], [ "▁ギル", -12.142878532409668 ], [ "クリスマス", -12.1428804397583 ], [ "AE", -12.142936706542969 ], [ "▁出港", -12.143119812011719 ], [ "よい", -12.143159866333008 ], [ "こんばんは", -12.143253326416016 ], [ "▁同窓", -12.143281936645508 ], [ "官位", -12.143319129943848 ], [ "▁YOU", -12.143430709838867 ], [ "垢", -12.143444061279297 ], [ "▁どうやら", -12.143476486206055 ], [ "▁わずかな", -12.143819808959961 ], [ "▁であれ", -12.143843650817871 ], [ "▁お祭り", -12.143880844116211 ], [ "▁ヤリ", -12.143908500671387 ], [ "帰国", -12.143927574157715 ], [ "▁長袖", -12.143930435180664 ], [ "▁ようでした", -12.144379615783691 ], [ "▁スタイリング", -12.144414901733398 ], [ "▁共生", -12.14458179473877 ], [ "▁学芸", -12.14460563659668 ], [ "▁イチ", -12.144611358642578 ], [ "削", -12.144654273986816 ], [ "ML", -12.144757270812988 ], [ "▁宴会", -12.144805908203125 ], [ "っちり", -12.144806861877441 ], [ "▁ホース", -12.14488410949707 ], [ "シャツ", -12.144911766052246 ], [ "▁こなして", -12.145100593566895 ], [ "▁親善", -12.145208358764648 ], [ "メーカー", -12.145281791687012 ], [ "▁思い出して", -12.14543342590332 ], [ "メガ", -12.145540237426758 ], [ "小さな", -12.14554214477539 ], [ "ヲ", -12.145654678344727 ], [ "pedia", -12.145759582519531 ], [ "▁刺し", -12.145822525024414 ], [ "単行本", -12.145875930786133 ], [ "▁スチール", -12.146137237548828 ], [ "▁メカ", -12.146194458007812 ], [ "▁逃", -12.146207809448242 ], [ "▁建てた", -12.146256446838379 ], [ "▁危", -12.146257400512695 ], [ "▁遂に", -12.1463623046875 ], [ "峯", -12.146470069885254 ], [ "当該", -12.14647102355957 ], [ "▁1,500", -12.146472930908203 ], [ "▁当院", -12.146574020385742 ], [ "OWN", -12.146796226501465 ], [ "▁シャネル", -12.146883010864258 ], [ "ナビ", -12.146913528442383 ], [ "▁不可能な", -12.146944999694824 ], [ "▁テイラー", -12.146968841552734 ], [ "▁ヴィー", -12.147130012512207 ], [ "菊", -12.14730167388916 ], [ "▁公布", -12.147319793701172 ], [ "▁ウォル", -12.147416114807129 ], [ "▁薬品", -12.147449493408203 ], [ "▁正統", -12.14774227142334 ], [ "▁駆除", -12.147815704345703 ], [ "▁誘惑", -12.147826194763184 ], [ "enn", -12.148323059082031 ], [ "▁ヴィトン", -12.148341178894043 ], [ "靴", -12.148341178894043 ], [ "▁西暦", -12.148370742797852 ], [ "ショナル", -12.148395538330078 ], [ "主演", -12.148398399353027 ], [ "▁106", -12.14842700958252 ], [ "▁AWS", -12.14852237701416 ], [ "羊", -12.148548126220703 ], [ "傘", -12.148591995239258 ], [ "VER", -12.148700714111328 ], [ "ヂ", -12.14880657196045 ], [ "▁誘拐", -12.148807525634766 ], [ "▁優待", -12.148836135864258 ], [ "▁蜂起", -12.148940086364746 ], [ "妊娠", -12.149014472961426 ], [ "▁2201", -12.149121284484863 ], [ "▁受給", -12.149215698242188 ], [ "▁宮内", -12.149375915527344 ], [ "▁知見", -12.149425506591797 ], [ "▁蕎麦", -12.14947509765625 ], [ "▁ビートルズ", -12.149598121643066 ], [ "柴", -12.149701118469238 ], [ "督", -12.149896621704102 ], [ "▁木曜", -12.149944305419922 ], [ "慢", -12.149950981140137 ], [ "▁過度", -12.150123596191406 ], [ "▁見つかって", -12.150158882141113 ], [ "ボディ", -12.150235176086426 ], [ "欧", -12.150405883789062 ], [ "▁独り", -12.150455474853516 ], [ "▁650", -12.150481224060059 ], [ "▁クリスティ", -12.150589942932129 ], [ "avi", -12.150629043579102 ], [ "▁束", -12.150768280029297 ], [ "▁駐在", -12.150853157043457 ], [ "ASS", -12.15097713470459 ], [ "▁駆けつけ", -12.151288032531738 ], [ "ぶつ", -12.15138053894043 ], [ "board", -12.151412963867188 ], [ "▁156", -12.151434898376465 ], [ "▁再興", -12.151609420776367 ], [ "▁水族", -12.151782035827637 ], [ "韻", -12.151786804199219 ], [ "ヤシ", -12.151957511901855 ], [ "▁地裁", -12.151971817016602 ], [ "巡", -12.152050971984863 ], [ "▁委ね", -12.152092933654785 ], [ "▁切れて", -12.152132034301758 ], [ "▁有馬", -12.15213394165039 ], [ "▁ホン", -12.152229309082031 ], [ "▁ゆめ", -12.152255058288574 ], [ "▁緑地", -12.15227222442627 ], [ "焚", -12.152377128601074 ], [ "tel", -12.152405738830566 ], [ "▁貯蔵", -12.152520179748535 ], [ "▁マート", -12.152742385864258 ], [ "であって", -12.152778625488281 ], [ "浴", -12.15278148651123 ], [ "▁宣告", -12.152856826782227 ], [ "▁直樹", -12.15292739868164 ], [ "▁先駆", -12.152935028076172 ], [ "▁新車", -12.152942657470703 ], [ "▁賞賛", -12.152958869934082 ], [ "▁申し訳ない", -12.153027534484863 ], [ "▁動かし", -12.153141021728516 ], [ "▁アトランタ", -12.15327262878418 ], [ "▁させた", -12.153304100036621 ], [ "▁補完", -12.153400421142578 ], [ "レーン", -12.153472900390625 ], [ "▁cat", -12.153542518615723 ], [ "トゥル", -12.153594970703125 ], [ "▁さほど", -12.153669357299805 ], [ "▁称賛", -12.153719902038574 ], [ "▁就いた", -12.153779029846191 ], [ "▁スレッド", -12.153922080993652 ], [ "ナリ", -12.153928756713867 ], [ "ピース", -12.153975486755371 ], [ "▁テンション", -12.15400505065918 ], [ "▁上方", -12.15412712097168 ], [ "潟", -12.154278755187988 ], [ "▁瞑想", -12.154279708862305 ], [ "KK", -12.1544828414917 ], [ "▁小樽", -12.154483795166016 ], [ "▁回す", -12.15458869934082 ], [ "▁制圧", -12.15461540222168 ], [ "▁取り出し", -12.154812812805176 ], [ "▁つながった", -12.154953002929688 ], [ "幣", -12.155112266540527 ], [ "安心", -12.15514087677002 ], [ "ハリ", -12.155216217041016 ], [ "ons", -12.155608177185059 ], [ "▁冷房", -12.155681610107422 ], [ "▁もらえた", -12.15571117401123 ], [ "▁京浜", -12.155769348144531 ], [ "▁泣いて", -12.155850410461426 ], [ "1936", -12.155937194824219 ], [ "▁櫻井", -12.156074523925781 ], [ "▁有名に", -12.156146049499512 ], [ "▁隠居", -12.15623950958252 ], [ "itch", -12.156294822692871 ], [ "▁見舞い", -12.15629768371582 ], [ "▁ベネ", -12.156351089477539 ], [ "▁ミャンマー", -12.156445503234863 ], [ "▁上達", -12.156484603881836 ], [ "メンズ", -12.156487464904785 ], [ "ボラ", -12.15662956237793 ], [ "▁久保", -12.156712532043457 ], [ "ther", -12.156726837158203 ], [ "▁釧路", -12.156746864318848 ], [ "▁本町", -12.156810760498047 ], [ "アーノ", -12.156843185424805 ], [ "▁大事だ", -12.15684986114502 ], [ "▁近辺", -12.156976699829102 ], [ "р", -12.157081604003906 ], [ "▁大変だ", -12.157159805297852 ], [ "▁参事", -12.157241821289062 ], [ "跳", -12.157307624816895 ], [ "▁倭", -12.157312393188477 ], [ "light", -12.157320022583008 ], [ "ーゲン", -12.157413482666016 ], [ "LK", -12.157584190368652 ], [ "▁デュー", -12.157598495483398 ], [ "▁溢れ", -12.157657623291016 ], [ "rain", -12.15777587890625 ], [ "▁置換", -12.15788745880127 ], [ "予め", -12.157983779907227 ], [ "隅", -12.158011436462402 ], [ "▁ロウ", -12.158080101013184 ], [ "▁面倒な", -12.158241271972656 ], [ "▁水野", -12.158246994018555 ], [ "▁中枢", -12.158312797546387 ], [ "▁っぱなし", -12.158320426940918 ], [ "▁アシ", -12.158346176147461 ], [ "▁懸", -12.158348083496094 ], [ "▁修繕", -12.158552169799805 ], [ "▁石器", -12.15870475769043 ], [ "▁mod", -12.158842086791992 ], [ "▁AGA", -12.158856391906738 ], [ "▁振り返り", -12.15888500213623 ], [ "ぺ", -12.159140586853027 ], [ "▁諦めて", -12.159271240234375 ], [ "請", -12.159282684326172 ], [ "ism", -12.159299850463867 ], [ "1938", -12.159309387207031 ], [ "▁time", -12.159335136413574 ], [ "明け", -12.15938949584961 ], [ "▁開封", -12.15941047668457 ], [ "▁ことば", -12.159467697143555 ], [ "▁すい", -12.15960693359375 ], [ "▁テナント", -12.159711837768555 ], [ "▁散策", -12.159717559814453 ], [ "▁マスコット", -12.159754753112793 ], [ "ont", -12.15981388092041 ], [ "▁ ̄", -12.160063743591309 ], [ "▁急いで", -12.160083770751953 ], [ "▁どうでも", -12.160116195678711 ], [ "▁当たった", -12.160148620605469 ], [ "▁戦記", -12.160237312316895 ], [ "▁辞めて", -12.160237312316895 ], [ "▁固ま", -12.160239219665527 ], [ "▁座標", -12.160534858703613 ], [ "求人", -12.160651206970215 ], [ "▁マンチェスター", -12.160797119140625 ], [ "▁絡み", -12.160799026489258 ], [ "FO", -12.160809516906738 ], [ "▁点在", -12.160873413085938 ], [ "▁移す", -12.161124229431152 ], [ "▁日刊", -12.161269187927246 ], [ "トム", -12.161279678344727 ], [ "伊那", -12.161355972290039 ], [ "▁航", -12.161394119262695 ], [ "▁当駅", -12.16144847869873 ], [ "▁肥満", -12.161494255065918 ], [ "▁位相", -12.161626815795898 ], [ "▁焼酎", -12.161813735961914 ], [ "▁適正な", -12.161849021911621 ], [ "いろ", -12.161918640136719 ], [ "▁アルメニア", -12.161925315856934 ], [ "薩", -12.162151336669922 ], [ "▁JN", -12.16215705871582 ], [ "▁強豪", -12.162243843078613 ], [ "霧", -12.162589073181152 ], [ "▁裏付け", -12.162632942199707 ], [ "▁召喚", -12.162830352783203 ], [ "ries", -12.162934303283691 ], [ "▁カンファレンス", -12.163166999816895 ], [ "▁馬車", -12.163189888000488 ], [ "▁稲荷", -12.163204193115234 ], [ "▁ハイパー", -12.163214683532715 ], [ "▁起こさ", -12.163311958312988 ], [ "▁マカ", -12.163594245910645 ], [ "н", -12.163844108581543 ], [ "▁迄", -12.164067268371582 ], [ "▁ヒート", -12.164068222045898 ], [ "辰", -12.1641845703125 ], [ "▁葛飾", -12.164190292358398 ], [ "▁隔離", -12.164205551147461 ], [ "▁人質", -12.16423225402832 ], [ "リアル", -12.164261817932129 ], [ "▁硫黄", -12.164298057556152 ], [ "▁漏洩", -12.164299011230469 ], [ "▁王女", -12.164320945739746 ], [ "▁完売", -12.16434097290039 ], [ "楼", -12.164448738098145 ], [ "▁岩田", -12.16454029083252 ], [ "▁奪う", -12.164575576782227 ], [ "▁意外に", -12.164604187011719 ], [ "iko", -12.164607048034668 ], [ "大変", -12.164658546447754 ], [ "▁ファル", -12.164731979370117 ], [ "▁Cr", -12.164835929870605 ], [ "▁対空", -12.164850234985352 ], [ "ニズム", -12.164891242980957 ], [ "▁隠す", -12.164941787719727 ], [ "▁やん", -12.164956092834473 ], [ "▁便宜", -12.165010452270508 ], [ "▁ā", -12.16512680053711 ], [ "▁きわめて", -12.165203094482422 ], [ "箕", -12.165203094482422 ], [ "▁いっぱいに", -12.16525650024414 ], [ "▁垂", -12.165261268615723 ], [ "▁ピックアップ", -12.16556167602539 ], [ "▁水槽", -12.165672302246094 ], [ "▁整数", -12.165886878967285 ], [ "▁発熱", -12.165912628173828 ], [ "▁地味", -12.16600227355957 ], [ "▁納期", -12.166285514831543 ], [ "グン", -12.166329383850098 ], [ "日々", -12.166555404663086 ], [ "▁作物", -12.166655540466309 ], [ "▁贅沢", -12.166891098022461 ], [ "▁制裁", -12.167006492614746 ], [ "リブ", -12.167040824890137 ], [ "兼", -12.167122840881348 ], [ "▁封印", -12.167145729064941 ], [ "▁鑑", -12.167163848876953 ], [ "グラー", -12.167292594909668 ], [ "アート", -12.167304992675781 ], [ "▁稼げ", -12.167319297790527 ], [ "▁ピアス", -12.167363166809082 ], [ "▁Ph", -12.1676664352417 ], [ "▁真空", -12.16768741607666 ], [ "▁中高", -12.167716979980469 ], [ "▁飲酒", -12.167811393737793 ], [ "なかなか", -12.167860984802246 ], [ "▁伝記", -12.16787052154541 ], [ "▁麓", -12.16787338256836 ], [ "▁抹消", -12.167924880981445 ], [ "フロ", -12.167947769165039 ], [ "そのまま", -12.16795539855957 ], [ "▁リターン", -12.168011665344238 ], [ "▁今井", -12.168023109436035 ], [ "クール", -12.168024063110352 ], [ "▁チア", -12.168197631835938 ], [ "▁安政", -12.168340682983398 ], [ "ゲイン", -12.168437957763672 ], [ "▁執政", -12.168638229370117 ], [ "▁捕食", -12.168780326843262 ], [ "▁重宝", -12.168912887573242 ], [ "パート", -12.169159889221191 ], [ "腔", -12.169172286987305 ], [ "▁論じ", -12.169384002685547 ], [ "▁ゴル", -12.169391632080078 ], [ "OK", -12.169417381286621 ], [ "▁相関", -12.169432640075684 ], [ "独立", -12.169530868530273 ], [ "▁就役", -12.169563293457031 ], [ "▁155", -12.16960620880127 ], [ "▁抜いた", -12.169686317443848 ], [ "▁ひかり", -12.169795989990234 ], [ "▁迫力", -12.169838905334473 ], [ "▁浅い", -12.169840812683105 ], [ "▁アグ", -12.169920921325684 ], [ "ぜん", -12.16999626159668 ], [ "▁中傷", -12.170069694519043 ], [ "▁微妙な", -12.170076370239258 ], [ "▁濃く", -12.170294761657715 ], [ "▁今や", -12.170299530029297 ], [ "▁ファミ", -12.170320510864258 ], [ "▁高騰", -12.170361518859863 ], [ "麺", -12.170382499694824 ], [ "▁侯", -12.17038345336914 ], [ "原因", -12.17041015625 ], [ "▁チョイス", -12.170567512512207 ], [ "▁ダイナミック", -12.170772552490234 ], [ "▁123", -12.170891761779785 ], [ "旅行", -12.170991897583008 ], [ "formul", -12.171051025390625 ], [ "▁新鮮", -12.17105770111084 ], [ "EAR", -12.171157836914062 ], [ "▁Intel", -12.171371459960938 ], [ "▁括弧", -12.17152214050293 ], [ "▁遊べる", -12.171819686889648 ], [ "頻", -12.172019958496094 ], [ "▁ふう", -12.172067642211914 ], [ "▁メディ", -12.172134399414062 ], [ "▁ぺ", -12.172138214111328 ], [ "▁千代", -12.1721773147583 ], [ "▁大河", -12.172224044799805 ], [ "▁俳句", -12.172248840332031 ], [ "▁身近に", -12.172362327575684 ], [ "▁ヌード", -12.172392845153809 ], [ "KE", -12.172403335571289 ], [ "8,000", -12.172446250915527 ], [ "▁ワット", -12.17248821258545 ], [ "妃", -12.172539710998535 ], [ "▁AFC", -12.172576904296875 ], [ "▁グー", -12.172598838806152 ], [ "▁トリック", -12.1726713180542 ], [ "壺", -12.172704696655273 ], [ "▁授け", -12.172739028930664 ], [ "曾", -12.172819137573242 ], [ "▁常磐", -12.172948837280273 ], [ "▁和平", -12.172985076904297 ], [ "▁みなみ", -12.172999382019043 ], [ "遠方", -12.17327880859375 ], [ "臓", -12.17343521118164 ], [ "遅", -12.173460006713867 ], [ "▁秘密の", -12.173503875732422 ], [ "▁Ab", -12.173523902893066 ], [ "▁面白かった", -12.173643112182617 ], [ "▁役人", -12.173674583435059 ], [ "棚", -12.173819541931152 ], [ "▁Ha", -12.173830032348633 ], [ "▁TEL", -12.173992156982422 ], [ "▁ジャイアンツ", -12.174005508422852 ], [ "▁後押し", -12.174188613891602 ], [ "粋", -12.174267768859863 ], [ "▁下車", -12.174325942993164 ], [ "▁生かした", -12.174338340759277 ], [ "今度", -12.174405097961426 ], [ "work", -12.17445182800293 ], [ "初心", -12.174471855163574 ], [ "▁去り", -12.174493789672852 ], [ "oon", -12.174511909484863 ], [ "めい", -12.174552917480469 ], [ "▁捉える", -12.174628257751465 ], [ "▁結末", -12.174644470214844 ], [ "▁日高", -12.174752235412598 ], [ "▁最適です", -12.174875259399414 ], [ "▁開戦", -12.174906730651855 ], [ "▁特別に", -12.175036430358887 ], [ "▁イタリアン", -12.175079345703125 ], [ "▁互い", -12.175079345703125 ], [ "▁安保", -12.17512035369873 ], [ "▁コンポーネント", -12.175332069396973 ], [ "▁何事", -12.175366401672363 ], [ "read", -12.175413131713867 ], [ "勧", -12.175511360168457 ], [ "▁豊富で", -12.175516128540039 ], [ "▁RT", -12.175691604614258 ], [ "▁転じた", -12.175812721252441 ], [ "▁砲兵", -12.175933837890625 ], [ "▁言ったら", -12.17594051361084 ], [ "▁及", -12.175997734069824 ], [ "ッケン", -12.176050186157227 ], [ "▁構わ", -12.176136016845703 ], [ "▁洗剤", -12.176149368286133 ], [ "▁残高", -12.176183700561523 ], [ "▁ごとく", -12.176451683044434 ], [ "▁若年", -12.176565170288086 ], [ "▁法制", -12.176665306091309 ], [ "やく", -12.1766996383667 ], [ "ove", -12.176728248596191 ], [ "髄", -12.176791191101074 ], [ "▁デルタ", -12.176831245422363 ], [ "▁活かした", -12.176939010620117 ], [ "ましい", -12.176968574523926 ], [ "▁だす", -12.176985740661621 ], [ "▁未だに", -12.177356719970703 ], [ "▁携", -12.177436828613281 ], [ "▁トラン", -12.177550315856934 ], [ "yama", -12.177949905395508 ], [ "▁新報", -12.177968978881836 ], [ "▁関税", -12.178064346313477 ], [ "シオン", -12.178072929382324 ], [ "▁エディフィス", -12.178081512451172 ], [ "▁尽き", -12.178082466125488 ], [ "▁交互", -12.17808723449707 ], [ "▁エディション", -12.178224563598633 ], [ "崩", -12.178245544433594 ], [ "▁年々", -12.1782808303833 ], [ "▁拳銃", -12.178319931030273 ], [ "▁熱く", -12.178427696228027 ], [ "盆", -12.178592681884766 ], [ "▁Home", -12.178607940673828 ], [ "▁触れた", -12.178616523742676 ], [ "TT", -12.178749084472656 ], [ "▁合体", -12.17879867553711 ], [ "▁不要な", -12.178829193115234 ], [ "▁Plus", -12.178918838500977 ], [ "骸", -12.178983688354492 ], [ "▁首席", -12.179070472717285 ], [ "▁1906", -12.179072380065918 ], [ "▁亡くなる", -12.179117202758789 ], [ "▁健康な", -12.179128646850586 ], [ "現地", -12.179162979125977 ], [ "▁ボディー", -12.179272651672363 ], [ "▁寸前", -12.1796875 ], [ "▁均一", -12.179713249206543 ], [ "ヶ谷", -12.179905891418457 ], [ "▁二度と", -12.179919242858887 ], [ "video", -12.179924964904785 ], [ "エーション", -12.180018424987793 ], [ "▁掌握", -12.180150032043457 ], [ "▁納入", -12.18022632598877 ], [ "▁就く", -12.1802396774292 ], [ "▁気に入った", -12.180316925048828 ], [ "▁STAR", -12.1804838180542 ], [ "ジット", -12.180488586425781 ], [ "アール", -12.180590629577637 ], [ "▁検事", -12.180658340454102 ], [ "▁効力", -12.180710792541504 ], [ "▁穏やかな", -12.180723190307617 ], [ "▁借り入れ", -12.180791854858398 ], [ "nc", -12.181026458740234 ], [ "▁御礼", -12.181066513061523 ], [ "ギス", -12.181100845336914 ], [ "▁じん", -12.181180953979492 ], [ "▁みたい", -12.18120002746582 ], [ "▁製法", -12.181295394897461 ], [ "鶏", -12.18132209777832 ], [ "▁阿波", -12.181361198425293 ], [ "友人", -12.181413650512695 ], [ "▁スペクトル", -12.181414604187012 ], [ "▁笑う", -12.181524276733398 ], [ "oi", -12.181562423706055 ], [ "田中", -12.181642532348633 ], [ "▁クビ", -12.18165111541748 ], [ "▁グレン", -12.181830406188965 ], [ "ムー", -12.18186092376709 ], [ "ッテン", -12.181891441345215 ], [ "▁tag", -12.181950569152832 ], [ "この頃", -12.182174682617188 ], [ "▁マットレス", -12.18228530883789 ], [ "▁浴衣", -12.182357788085938 ], [ "▁紀伊", -12.182491302490234 ], [ "ZE", -12.182502746582031 ], [ "▁めい", -12.182513236999512 ], [ "▁ケガ", -12.182586669921875 ], [ "▁大腸", -12.182587623596191 ], [ "▁脂質", -12.182609558105469 ], [ "鈴木", -12.182616233825684 ], [ "▁スピーチ", -12.182680130004883 ], [ "▁つなぎ", -12.182817459106445 ], [ "▁出世", -12.18285846710205 ], [ "▁おれ", -12.182953834533691 ], [ "たま", -12.18315315246582 ], [ "ATION", -12.18330192565918 ], [ "▁≫", -12.183317184448242 ], [ "▁背面", -12.183382034301758 ], [ "▁逸話", -12.183420181274414 ], [ "▁控訴", -12.183486938476562 ], [ "▁ヘルメット", -12.183497428894043 ], [ "▁2107", -12.183725357055664 ], [ "総合", -12.18374252319336 ], [ "▁GS", -12.183782577514648 ], [ "▁毎日新聞", -12.183821678161621 ], [ "~", -12.183881759643555 ], [ "ブール", -12.183923721313477 ], [ "article", -12.183924674987793 ], [ "▁シンガーソング", -12.183947563171387 ], [ "▁攻勢", -12.183948516845703 ], [ "▁られたり", -12.18395709991455 ], [ "シュタット", -12.184067726135254 ], [ "ane", -12.184221267700195 ], [ "▁リス", -12.184232711791992 ], [ "▁船長", -12.184236526489258 ], [ "▁オタク", -12.18438720703125 ], [ "▁残念な", -12.184396743774414 ], [ "ダイエット", -12.184718132019043 ], [ "▁友だち", -12.1847562789917 ], [ "セク", -12.18482494354248 ], [ "▁山陰", -12.184829711914062 ], [ "▁コイル", -12.184887886047363 ], [ "▁平方メートル", -12.18498706817627 ], [ "鰭", -12.18498706817627 ], [ "▁囲碁", -12.185107231140137 ], [ "フスキー", -12.185311317443848 ], [ "▁押さ", -12.18565559387207 ], [ "▁封", -12.185657501220703 ], [ "びと", -12.185840606689453 ], [ "king", -12.185879707336426 ], [ "▁国旗", -12.1859130859375 ], [ "▁アップグレード", -12.185965538024902 ], [ "▁vi", -12.186001777648926 ], [ "▁ا", -12.186063766479492 ], [ "▁4017", -12.186090469360352 ], [ "▁そら", -12.186100959777832 ], [ "▁味わう", -12.186142921447754 ], [ "▁エンジェル", -12.186285972595215 ], [ "let", -12.186297416687012 ], [ "▁エキ", -12.186511039733887 ], [ "▁生え", -12.186530113220215 ], [ "課", -12.186545372009277 ], [ "▁導いた", -12.186569213867188 ], [ "ッシー", -12.186579704284668 ], [ "▁公示", -12.186583518981934 ], [ "▁コラーゲン", -12.186720848083496 ], [ "▁致", -12.186722755432129 ], [ "▁遺構", -12.186751365661621 ], [ "降水", -12.186796188354492 ], [ "台風", -12.186832427978516 ], [ "GM", -12.186881065368652 ], [ "▁違", -12.186944961547852 ], [ "▁梗塞", -12.186952590942383 ], [ "▁マツ", -12.187125205993652 ], [ "▁窒素", -12.187183380126953 ], [ "▁カマ", -12.187225341796875 ], [ "▁普", -12.187228202819824 ], [ "▁どうにか", -12.187307357788086 ], [ "▁転倒", -12.187349319458008 ], [ "val", -12.187504768371582 ], [ "▁311", -12.187641143798828 ], [ "▁怪物", -12.187660217285156 ], [ "▁ゾンビ", -12.187689781188965 ], [ "▁津軽", -12.187837600708008 ], [ "▁おろし", -12.18783950805664 ], [ "tsu", -12.187843322753906 ], [ "▁滞", -12.18785285949707 ], [ "▁拾", -12.18791389465332 ], [ "PL", -12.187945365905762 ], [ "▁パープル", -12.187948226928711 ], [ "▁鬱", -12.187952995300293 ], [ "▁しゃべ", -12.187982559204102 ], [ "甘", -12.188024520874023 ], [ "▁107", -12.188089370727539 ], [ "▁シンデレラ", -12.18811321258545 ], [ "▁深める", -12.188170433044434 ], [ "▁ツイ", -12.188396453857422 ], [ "ちゅ", -12.188549041748047 ], [ "▁ギュ", -12.188566207885742 ], [ "▁有害", -12.188596725463867 ], [ "KY", -12.18870735168457 ], [ "▁河野", -12.188748359680176 ], [ "▁資", -12.189149856567383 ], [ "▁NY", -12.18915843963623 ], [ "▁交え", -12.189204216003418 ], [ "▁紳士", -12.189269065856934 ], [ "▁行ったら", -12.189371109008789 ], [ "▁返答", -12.189393997192383 ], [ "▁亭", -12.189412117004395 ], [ "NT", -12.189516067504883 ], [ "▁リフレッシュ", -12.189520835876465 ], [ "ema", -12.189587593078613 ], [ "▁芋", -12.189667701721191 ], [ "▁オハイオ", -12.189733505249023 ], [ "▁切り離", -12.18986701965332 ], [ "▁有楽町", -12.18996524810791 ], [ "▁群れ", -12.189998626708984 ], [ "▁胆", -12.190207481384277 ], [ "▁エリック", -12.190214157104492 ], [ "▁便利に", -12.190271377563477 ], [ "▁題名", -12.190376281738281 ], [ "▁Nintendo", -12.190443992614746 ], [ "恩", -12.190511703491211 ], [ "ark", -12.190584182739258 ], [ "▁Super", -12.190690994262695 ], [ "楽曲", -12.190800666809082 ], [ "▁老化", -12.190937042236328 ], [ "▁震え", -12.191014289855957 ], [ "▁HDD", -12.191047668457031 ], [ "▁トマス", -12.191078186035156 ], [ "▁へん", -12.191125869750977 ], [ "▁Game", -12.191168785095215 ], [ "銃", -12.191228866577148 ], [ "▁ウエ", -12.191266059875488 ], [ "pr", -12.191279411315918 ], [ "▁退官", -12.191340446472168 ], [ "▁カネ", -12.191390037536621 ], [ "▁公平", -12.19139575958252 ], [ "▁1903", -12.191439628601074 ], [ "▁在来", -12.191567420959473 ], [ "▁深化", -12.19160270690918 ], [ "▁モノレール", -12.191632270812988 ], [ "▁必死に", -12.191654205322266 ], [ "▁ヨシ", -12.191688537597656 ], [ "▁経つ", -12.191892623901367 ], [ "▁引き分け", -12.191929817199707 ], [ "▁舞踊", -12.191944122314453 ], [ "▁逃した", -12.19201946258545 ], [ "▁はじめる", -12.192055702209473 ], [ "▁みたいだ", -12.19206428527832 ], [ "十郎", -12.192187309265137 ], [ "▁明か", -12.192201614379883 ], [ "▁少量", -12.192264556884766 ], [ "さまざまな", -12.19228458404541 ], [ "▁Type", -12.192398071289062 ], [ "▁載せ", -12.19240951538086 ], [ "▁収支", -12.1924409866333 ], [ "というのも", -12.192638397216797 ], [ "▁困難である", -12.192641258239746 ], [ "ding", -12.192745208740234 ], [ "▁携わった", -12.192755699157715 ], [ "▁手がけて", -12.19275951385498 ], [ "▁呼", -12.192821502685547 ], [ "クロン", -12.19290828704834 ], [ "▁酒井", -12.193053245544434 ], [ "▁ファミコン", -12.193169593811035 ], [ "ATA", -12.19318675994873 ], [ "▁不況", -12.193243026733398 ], [ "ISA", -12.193547248840332 ], [ "▁インプラント", -12.19359302520752 ], [ "▁拍手", -12.193803787231445 ], [ "▁曹", -12.193924903869629 ], [ "▁メロ", -12.194063186645508 ], [ "▁バッ", -12.194151878356934 ], [ "▁トミー", -12.194253921508789 ], [ "▁馬身", -12.194319725036621 ], [ "ゴリ", -12.19435977935791 ], [ "▁有利", -12.194375038146973 ], [ "癖", -12.19451904296875 ], [ "▁パシフィック", -12.194619178771973 ], [ "さすが", -12.194754600524902 ], [ "▁Sky", -12.19491958618164 ], [ "こなわ", -12.194961547851562 ], [ "▁オシャレ", -12.195018768310547 ], [ "▁増し", -12.19507884979248 ], [ "▁EL", -12.195178985595703 ], [ "▁チャネル", -12.195231437683105 ], [ "▁松原", -12.195290565490723 ], [ "太平洋", -12.19533920288086 ], [ "浩", -12.195342063903809 ], [ "▁As", -12.195456504821777 ], [ "匠", -12.195579528808594 ], [ "▁インフレ", -12.195659637451172 ], [ "▁◯", -12.195706367492676 ], [ "▁セラピスト", -12.195902824401855 ], [ "▁激減", -12.19593334197998 ], [ "雑誌", -12.195938110351562 ], [ "払わ", -12.195977210998535 ], [ "▁ダイエー", -12.196196556091309 ], [ "反対", -12.196248054504395 ], [ "▁穀物", -12.196371078491211 ], [ "▁等しい", -12.196407318115234 ], [ "ーーーー", -12.196521759033203 ], [ "ざん", -12.196534156799316 ], [ "▁アーク", -12.196560859680176 ], [ "▁小麦", -12.196581840515137 ], [ "▁エンタメ", -12.196603775024414 ], [ "運営", -12.196704864501953 ], [ "▁陥る", -12.196722030639648 ], [ "▁土台", -12.19686222076416 ], [ "日常", -12.196934700012207 ], [ "▁民家", -12.197007179260254 ], [ "しも", -12.197010040283203 ], [ "ada", -12.197014808654785 ], [ "▁橋梁", -12.197039604187012 ], [ "▁事柄", -12.197073936462402 ], [ "▁視界", -12.197104454040527 ], [ "▁キハ", -12.197128295898438 ], [ "楚", -12.197355270385742 ], [ "近く", -12.19737720489502 ], [ "っつ", -12.197449684143066 ], [ "▁徐", -12.197513580322266 ], [ "▁間近", -12.19772720336914 ], [ "▁生殖", -12.197744369506836 ], [ "オキシ", -12.197795867919922 ], [ "▁敬意", -12.197881698608398 ], [ "1933", -12.197980880737305 ], [ "▁町長", -12.198041915893555 ], [ "▁ぴったりの", -12.19807243347168 ], [ "▁映し", -12.19808292388916 ], [ "▁輝いた", -12.198105812072754 ], [ "ッション", -12.198164939880371 ], [ "sen", -12.198261260986328 ], [ "rus", -12.19829273223877 ], [ "▁ホークス", -12.19831371307373 ], [ "▁一杯", -12.198325157165527 ], [ "▁まんが", -12.198378562927246 ], [ "今月", -12.198519706726074 ], [ "▁聞こえる", -12.198521614074707 ], [ "▁届ける", -12.198678016662598 ], [ "▁ボイ", -12.198801040649414 ], [ "▁赤く", -12.198875427246094 ], [ "▁アトラクション", -12.198943138122559 ], [ "▁暖房", -12.199085235595703 ], [ "▁アクセ", -12.199088096618652 ], [ "▁Ac", -12.199258804321289 ], [ "▁広がった", -12.199262619018555 ], [ "▁主席", -12.199372291564941 ], [ "▁Ge", -12.19944953918457 ], [ "▁スターリン", -12.199469566345215 ], [ "晩年", -12.199569702148438 ], [ "▁等々", -12.199593544006348 ], [ "▁計上", -12.199594497680664 ], [ "十四", -12.199618339538574 ], [ "▁ルパン", -12.199634552001953 ], [ "▁ふれあい", -12.199654579162598 ], [ "歴代", -12.199699401855469 ], [ "mor", -12.19986343383789 ], [ "▁日帰り", -12.199865341186523 ], [ "▁妨げ", -12.199872016906738 ], [ "▁文脈", -12.199955940246582 ], [ "▁コーラ", -12.199978828430176 ], [ "▁着た", -12.200285911560059 ], [ "▁兼務", -12.200387001037598 ], [ "タカ", -12.200395584106445 ], [ "▁組成", -12.200677871704102 ], [ "▁告げる", -12.200706481933594 ], [ "▁仕えた", -12.200709342956543 ], [ "キッド", -12.200898170471191 ], [ "▁War", -12.20112133026123 ], [ "▁不自由", -12.201156616210938 ], [ "▁指向", -12.201301574707031 ], [ "▁ウォーク", -12.201451301574707 ], [ "だって", -12.201462745666504 ], [ "▁共用", -12.20146369934082 ], [ "▁胴", -12.201766967773438 ], [ "▁拝見", -12.201996803283691 ], [ "▁叱", -12.202232360839844 ], [ "▁保って", -12.202291488647461 ], [ "▁積分", -12.202507972717285 ], [ "▁大雨", -12.202666282653809 ], [ "▁デジ", -12.202777862548828 ], [ "シェン", -12.202795028686523 ], [ "▁造成", -12.202900886535645 ], [ "▁腎", -12.202903747558594 ], [ "▁エッジ", -12.202911376953125 ], [ "▁フェラーリ", -12.202934265136719 ], [ "二郎", -12.2029390335083 ], [ "▁生かし", -12.203011512756348 ], [ "らう", -12.203080177307129 ], [ "▁串", -12.203102111816406 ], [ "▁Associate", -12.203167915344238 ], [ "▁勿論", -12.203186988830566 ], [ "▁シャイ", -12.203227996826172 ], [ "▁愛人", -12.203295707702637 ], [ "ジェット", -12.203299522399902 ], [ "▁昼食", -12.203343391418457 ], [ "▁ハインリヒ", -12.20340347290039 ], [ "▁Te", -12.203775405883789 ], [ "▁恩恵", -12.203794479370117 ], [ "ゅ", -12.20386791229248 ], [ "ral", -12.203868865966797 ], [ "▁良くて", -12.204134941101074 ], [ "▁通院", -12.204179763793945 ], [ "髙", -12.204227447509766 ], [ "▁松尾", -12.204270362854004 ], [ "▁名門", -12.204424858093262 ], [ "▁よー", -12.20448112487793 ], [ "▁たばこ", -12.20470142364502 ], [ "▁負った", -12.204824447631836 ], [ "eam", -12.204843521118164 ], [ "▁溶", -12.204975128173828 ], [ "▁組んだ", -12.205167770385742 ], [ "▁まな", -12.205216407775879 ], [ "▁尋常", -12.20528793334961 ], [ "jo", -12.20544147491455 ], [ "▁強かった", -12.20560359954834 ], [ "ゼット", -12.205663681030273 ], [ "▁内海", -12.205801963806152 ], [ "▁挟ま", -12.205901145935059 ], [ "ランチ", -12.206098556518555 ], [ "▁経た", -12.206123352050781 ], [ "▁カッ", -12.20621109008789 ], [ "▁静止", -12.206274032592773 ], [ "ニクス", -12.206286430358887 ], [ "ターン", -12.20630931854248 ], [ "▁宛て", -12.206465721130371 ], [ "▁昨今", -12.206503868103027 ], [ "▁減ら", -12.206526756286621 ], [ "▁パレスチナ", -12.206703186035156 ], [ "停", -12.206714630126953 ], [ "SHI", -12.206759452819824 ], [ "▁116", -12.206790924072266 ], [ "▁焼け", -12.206812858581543 ], [ "▁司祭", -12.206859588623047 ], [ "▁消す", -12.20693588256836 ], [ "▁容赦", -12.20694351196289 ], [ "▁FOR", -12.206954956054688 ], [ "メア", -12.20695972442627 ], [ "▁組み合わせる", -12.206978797912598 ], [ "▁冗談", -12.207056999206543 ], [ "▁大森", -12.207070350646973 ], [ "▁特番", -12.207188606262207 ], [ "KA", -12.207261085510254 ], [ "▁トルク", -12.207274436950684 ], [ "▁騒ぎ", -12.207293510437012 ], [ "▁面談", -12.207318305969238 ], [ "▁キズ", -12.207342147827148 ], [ "ラード", -12.207375526428223 ], [ "END", -12.20740795135498 ], [ "▁佐伯", -12.207561492919922 ], [ "▁グリル", -12.207852363586426 ], [ "FX", -12.207982063293457 ], [ "▁電灯", -12.208037376403809 ], [ "▁有志", -12.208312034606934 ], [ "▁っぽく", -12.208431243896484 ], [ "press", -12.208504676818848 ], [ "がし", -12.208572387695312 ], [ "びき", -12.208605766296387 ], [ "▁Bi", -12.208650588989258 ], [ "▁最高峰", -12.208684921264648 ], [ "▁ファイナルファンタジー", -12.208715438842773 ], [ "▁貴族院", -12.20895767211914 ], [ "股", -12.208990097045898 ], [ "牌", -12.209066390991211 ], [ "▁板橋", -12.209121704101562 ], [ "誤", -12.209217071533203 ], [ "盛り", -12.209344863891602 ], [ "ジョージ", -12.209471702575684 ], [ "▁即座に", -12.209657669067383 ], [ "▁次期", -12.209738731384277 ], [ "機能", -12.209901809692383 ], [ "▁捉えて", -12.209903717041016 ], [ "シエ", -12.210014343261719 ], [ "▁曖昧", -12.210027694702148 ], [ "▁町立", -12.210076332092285 ], [ "▁思い出す", -12.210088729858398 ], [ "▁新入", -12.210088729858398 ], [ "▁伝道", -12.210095405578613 ], [ "栖", -12.210219383239746 ], [ "▁踊", -12.210458755493164 ], [ "▁仕方がない", -12.21048641204834 ], [ "▁外野手", -12.210487365722656 ], [ "▁返却", -12.210492134094238 ], [ "ズル", -12.210517883300781 ], [ "トゥール", -12.210561752319336 ], [ "▁猶予", -12.21060562133789 ], [ "▁スパイス", -12.210640907287598 ], [ "▁通告", -12.210643768310547 ], [ "▁いつの間にか", -12.210681915283203 ], [ "mu", -12.210713386535645 ], [ "▁つまみ", -12.210731506347656 ], [ "▁写本", -12.21074390411377 ], [ "▁愛顧", -12.21076774597168 ], [ "そうして", -12.210790634155273 ], [ "▁討論", -12.210894584655762 ], [ "ken", -12.210917472839355 ], [ "選挙", -12.211030006408691 ], [ "鋳", -12.211079597473145 ], [ "▁遡", -12.211482048034668 ], [ "▁強烈な", -12.211503028869629 ], [ "吉田", -12.211578369140625 ], [ "▁丈夫", -12.211599349975586 ], [ "▁LIFE", -12.211801528930664 ], [ "▁KA", -12.211943626403809 ], [ "鼓", -12.211990356445312 ], [ "だか", -12.21214771270752 ], [ "▁神道", -12.212182998657227 ], [ "▁返した", -12.212320327758789 ], [ "▁通じた", -12.2123384475708 ], [ "括", -12.21250057220459 ], [ "▁追及", -12.212512969970703 ], [ "▁意匠", -12.212528228759766 ], [ "▁跳ね", -12.212530136108398 ], [ "▁留まり", -12.212567329406738 ], [ "▁止まり", -12.212669372558594 ], [ "▁実情", -12.212687492370605 ], [ "▁築いて", -12.212713241577148 ], [ "▁適度", -12.212714195251465 ], [ "肩", -12.21279239654541 ], [ "▁予言", -12.212956428527832 ], [ "▁Pay", -12.21299934387207 ], [ "▁病理", -12.213067054748535 ], [ "▁注入", -12.213171005249023 ], [ "▁当番", -12.213261604309082 ], [ "▁精子", -12.213268280029297 ], [ "▁朗読", -12.213335037231445 ], [ "▁以て", -12.213345527648926 ], [ "▁貸出", -12.213435173034668 ], [ "▁ジャージ", -12.213623046875 ], [ "▁弱点", -12.213638305664062 ], [ "▁遊戯", -12.213732719421387 ], [ "▁公安", -12.213798522949219 ], [ "▁優遇", -12.213835716247559 ], [ "宮城", -12.213855743408203 ], [ "▁入隊", -12.213886260986328 ], [ "▁加わって", -12.213946342468262 ], [ "▁モス", -12.213959693908691 ], [ "▁水雷", -12.214062690734863 ], [ "▁アルト", -12.214102745056152 ], [ "奮", -12.214146614074707 ], [ "▁小田", -12.214242935180664 ], [ "▁伸ばし", -12.214262008666992 ], [ "▁奮闘", -12.214284896850586 ], [ "▁コンプレックス", -12.214404106140137 ], [ "▁賞味", -12.214434623718262 ], [ "広告", -12.214436531066895 ], [ "▁転移", -12.214442253112793 ], [ "▁鷲", -12.214469909667969 ], [ "▁et", -12.21449089050293 ], [ "PER", -12.214492797851562 ], [ "▁合衆", -12.21469497680664 ], [ "▁奪還", -12.21476936340332 ], [ "ient", -12.214899063110352 ], [ "▁こい", -12.214984893798828 ], [ "▁Edition", -12.214999198913574 ], [ "▁雑草", -12.21500301361084 ], [ "▁続行", -12.215116500854492 ], [ "オレ", -12.21523380279541 ], [ "桶", -12.21535587310791 ], [ "▁HO", -12.215373039245605 ], [ "アフリカ", -12.215604782104492 ], [ "舌", -12.215913772583008 ], [ "EST", -12.216012954711914 ], [ "ゲイ", -12.216078758239746 ], [ "▁ヴィクトリア", -12.216196060180664 ], [ "▁産出", -12.2162446975708 ], [ "▁陸地", -12.21627140045166 ], [ "慣", -12.21628189086914 ], [ "イザ", -12.21634578704834 ], [ "▁返って", -12.216376304626465 ], [ "製造", -12.216385841369629 ], [ "uki", -12.216654777526855 ], [ "▁ヴィンテージ", -12.217150688171387 ], [ "▁NFL", -12.21724796295166 ], [ "疹", -12.217257499694824 ], [ "▁函数", -12.217264175415039 ], [ "▁高価な", -12.217368125915527 ], [ "ene", -12.217585563659668 ], [ "▁学歴", -12.217592239379883 ], [ "▁施", -12.21761417388916 ], [ "▁info", -12.217619895935059 ], [ "管理", -12.217641830444336 ], [ "▁皇族", -12.217659950256348 ], [ "ars", -12.217706680297852 ], [ "ドキ", -12.217761993408203 ], [ "そく", -12.217873573303223 ], [ "▁等級", -12.218024253845215 ], [ "ku", -12.218055725097656 ], [ "AMP", -12.218086242675781 ], [ "▁見据え", -12.218101501464844 ], [ "▁此", -12.218210220336914 ], [ "弁護", -12.218250274658203 ], [ "▁百合", -12.218297958374023 ], [ "▁陥り", -12.218338966369629 ], [ "ところ", -12.218355178833008 ], [ "▁1889", -12.218461990356445 ], [ "▁源泉", -12.218568801879883 ], [ "▁やりがい", -12.218585968017578 ], [ "▁ビニール", -12.218620300292969 ], [ "▁BMW", -12.218697547912598 ], [ "▁清楚", -12.21876335144043 ], [ "大手", -12.218765258789062 ], [ "▁ノア", -12.218766212463379 ], [ "▁原宿", -12.218916893005371 ], [ "▁かかわる", -12.219058990478516 ], [ "午前", -12.219114303588867 ], [ "▁建てる", -12.219115257263184 ], [ "▁pre", -12.21915340423584 ], [ "▁郡山", -12.219164848327637 ], [ "▁休養", -12.219213485717773 ], [ "どうも", -12.219245910644531 ], [ "▁エルメス", -12.219345092773438 ], [ "ミュー", -12.219382286071777 ], [ "▁おばさん", -12.219533920288086 ], [ "▁ジェン", -12.21957778930664 ], [ "▁ルーキー", -12.219621658325195 ], [ "▁材質", -12.219625473022461 ], [ "▁胴体", -12.219627380371094 ], [ "▁ディレクトリ", -12.219651222229004 ], [ "▁なるほど", -12.219658851623535 ], [ "▁1890", -12.219720840454102 ], [ "▁一つ一つ", -12.219771385192871 ], [ "▁1904", -12.21978759765625 ], [ "▁引き起こし", -12.219796180725098 ], [ "▁まっ", -12.219841003417969 ], [ "カット", -12.219890594482422 ], [ "▁ステーキ", -12.219895362854004 ], [ "▁回帰", -12.219905853271484 ], [ "▁ケンタッキー", -12.220009803771973 ], [ "▁襲い", -12.220017433166504 ], [ "▁妖精", -12.220022201538086 ], [ "レッ", -12.22022533416748 ], [ "言語", -12.220454216003418 ], [ "▁軍用", -12.220527648925781 ], [ "陳", -12.2205810546875 ], [ "▁おこなって", -12.220608711242676 ], [ "▁溶接", -12.22061824798584 ], [ "▁ビルド", -12.220645904541016 ], [ "▁乗り越え", -12.22067928314209 ], [ "▁種族", -12.220754623413086 ], [ "▁南区", -12.220765113830566 ], [ "出来", -12.220792770385742 ], [ "欧州", -12.220793724060059 ], [ "▁性欲", -12.221287727355957 ], [ "ひょ", -12.221635818481445 ], [ "lor", -12.221806526184082 ], [ "ぴ", -12.221879005432129 ], [ "▁発令", -12.22192096710205 ], [ "▁容姿", -12.221931457519531 ], [ "づか", -12.221997261047363 ], [ "▁聖地", -12.222379684448242 ], [ "▁足元", -12.222380638122559 ], [ "貝", -12.222413063049316 ], [ "▁ip", -12.222515106201172 ], [ "プレイヤー", -12.222628593444824 ], [ "▁器官", -12.222776412963867 ], [ "▁脂", -12.222848892211914 ], [ "▁超人", -12.223217964172363 ], [ "▁Professional", -12.223244667053223 ], [ "▁クレー", -12.223284721374512 ], [ "▁カムループス", -12.223484992980957 ], [ "▁総数", -12.223530769348145 ], [ "▁自由民主党", -12.223535537719727 ], [ "ウィー", -12.223567008972168 ], [ "▁線形", -12.223577499389648 ], [ "▁御殿", -12.223589897155762 ], [ "▁準じ", -12.223649978637695 ], [ "舘", -12.223725318908691 ], [ "▁千歳", -12.223771095275879 ], [ "▁School", -12.223797798156738 ], [ "▁ファイター", -12.224020957946777 ], [ "必要", -12.224081993103027 ], [ "▁支線", -12.224148750305176 ], [ "▁Fl", -12.224220275878906 ], [ "▁持てる", -12.224493980407715 ], [ "rn", -12.224542617797852 ], [ "▁可視", -12.224909782409668 ], [ "▁夜景", -12.2249174118042 ], [ "▁付か", -12.224991798400879 ], [ "▁名声", -12.225010871887207 ], [ "▁メルマガ", -12.225046157836914 ], [ "▁小遣い", -12.225166320800781 ], [ "スパイ", -12.225201606750488 ], [ "▁乗組員", -12.225286483764648 ], [ "▁飼って", -12.225319862365723 ], [ "▁本山", -12.225347518920898 ], [ "▁codic", -12.225509643554688 ], [ "▁お迎え", -12.2255277633667 ], [ "っとり", -12.225590705871582 ], [ "▁中佐", -12.225597381591797 ], [ "▁ウォン", -12.225662231445312 ], [ "▁白く", -12.225698471069336 ], [ "ense", -12.225992202758789 ], [ "デール", -12.226115226745605 ], [ "堅", -12.226225852966309 ], [ "ヅ", -12.226245880126953 ], [ "ドック", -12.226303100585938 ], [ "▁新井", -12.226435661315918 ], [ "▁sim", -12.226828575134277 ], [ "▁ナイキ", -12.226846694946289 ], [ "▁就活", -12.226871490478516 ], [ "▁お好み", -12.226966857910156 ], [ "▁キレイに", -12.22707748413086 ], [ "▁工務", -12.227231979370117 ], [ "▁陶器", -12.227245330810547 ], [ "▁音波", -12.227453231811523 ], [ "▁転が", -12.227547645568848 ], [ "▁車輪", -12.22756576538086 ], [ "▁直轄", -12.227640151977539 ], [ "▁並べて", -12.227718353271484 ], [ "▁天王寺", -12.227794647216797 ], [ "▁Tokyo", -12.227823257446289 ], [ "▁連帯", -12.22785472869873 ], [ "▁負債", -12.22795295715332 ], [ "▁治癒", -12.227956771850586 ], [ "PM", -12.228090286254883 ], [ "rt", -12.228130340576172 ], [ "▁協調", -12.228225708007812 ], [ "▁TH", -12.228248596191406 ], [ "▁院生", -12.228288650512695 ], [ "▁忍者", -12.228387832641602 ], [ "1932", -12.22845458984375 ], [ "▁巡礼", -12.22846794128418 ], [ "▁反する", -12.228565216064453 ], [ "▁pic", -12.228653907775879 ], [ "hon", -12.228656768798828 ], [ "▁衣服", -12.2288236618042 ], [ "料理", -12.228829383850098 ], [ "eck", -12.228867530822754 ], [ "▁Mozilla", -12.228900909423828 ], [ "ッピー", -12.22893238067627 ], [ "▁消える", -12.229165077209473 ], [ "▁最大で", -12.2291898727417 ], [ "▁買い取り", -12.229253768920898 ], [ "徒然", -12.229321479797363 ], [ "働", -12.229430198669434 ], [ "▁石鹸", -12.229515075683594 ], [ "▁低温", -12.229521751403809 ], [ "▁山手", -12.229623794555664 ], [ "▁Management", -12.22962474822998 ], [ "▁アルミニウム", -12.229639053344727 ], [ "▁要約", -12.22967529296875 ], [ "▁ええ", -12.229707717895508 ], [ "▁松下", -12.229769706726074 ], [ "▁版画", -12.229819297790527 ], [ "▁殺到", -12.229897499084473 ], [ "▁レオン", -12.229927062988281 ], [ "がれ", -12.230128288269043 ], [ "▁中型", -12.23013687133789 ], [ "ctor", -12.230185508728027 ], [ "▁fi", -12.230194091796875 ], [ "▁接し", -12.230340957641602 ], [ "▁小沢", -12.230395317077637 ], [ "こし", -12.230402946472168 ], [ "▁質感", -12.230437278747559 ], [ "ネオ", -12.230450630187988 ], [ "TU", -12.230706214904785 ], [ "▁サーチ", -12.23081111907959 ], [ "▁ハラ", -12.230817794799805 ], [ "▁Mark", -12.231293678283691 ], [ "蔑", -12.231317520141602 ], [ "▁330", -12.231403350830078 ], [ "▁哺乳", -12.231437683105469 ], [ "▁スケッチ", -12.231520652770996 ], [ "ロース", -12.231554985046387 ], [ "カテゴリ", -12.231595993041992 ], [ "RF", -12.231857299804688 ], [ "▁代わる", -12.23192024230957 ], [ "シロ", -12.232075691223145 ], [ "ホーク", -12.232239723205566 ], [ "▁石橋", -12.232276916503906 ], [ "▁譜", -12.232439041137695 ], [ "効", -12.232492446899414 ], [ "▁インテル", -12.232695579528809 ], [ "OSS", -12.232712745666504 ], [ "▁県庁", -12.23299503326416 ], [ "err", -12.233136177062988 ], [ "kan", -12.233160018920898 ], [ "麻呂", -12.233214378356934 ], [ "▁税制", -12.233317375183105 ], [ "▁大崎", -12.233414649963379 ], [ "ニウス", -12.23343563079834 ], [ "瞬", -12.233489036560059 ], [ "▁向ける", -12.233548164367676 ], [ "▁門下", -12.233656883239746 ], [ "▁引き取", -12.233726501464844 ], [ "▁Work", -12.233797073364258 ], [ "▁センサ", -12.23379898071289 ], [ "▁124", -12.233813285827637 ], [ "▁詫び", -12.233860969543457 ], [ "なんか", -12.233895301818848 ], [ "▁ドック", -12.233973503112793 ], [ "▁壊", -12.234020233154297 ], [ "▁キラキラ", -12.234103202819824 ], [ "▁称え", -12.234158515930176 ], [ "▁ミリオン", -12.234163284301758 ], [ "▁碧", -12.234336853027344 ], [ "▁珈琲", -12.234346389770508 ], [ "▁下野", -12.234365463256836 ], [ "▁蜜", -12.234394073486328 ], [ "▁各種の", -12.234458923339844 ], [ "▁アルプス", -12.234615325927734 ], [ "▁重傷", -12.23471736907959 ], [ "▁高麗", -12.234819412231445 ], [ "介護", -12.234823226928711 ], [ "▁旗艦", -12.234895706176758 ], [ "UP", -12.234957695007324 ], [ "▁寂し", -12.235027313232422 ], [ "awa", -12.235167503356934 ], [ "▁Bu", -12.235227584838867 ], [ "戦国", -12.235244750976562 ], [ "▁戯曲", -12.235560417175293 ], [ "▁コリ", -12.235577583312988 ], [ "帰り", -12.235594749450684 ], [ "▁簡単です", -12.235645294189453 ], [ "▁突起", -12.235873222351074 ], [ "んだり", -12.235879898071289 ], [ "廟", -12.23592472076416 ], [ "▁麻痺", -12.23592758178711 ], [ "▁招いて", -12.236041069030762 ], [ "▁アンドレ", -12.236099243164062 ], [ "▁痛め", -12.236124992370605 ], [ "▁争う", -12.236166954040527 ], [ "▁タコ", -12.236289024353027 ], [ "▁歌声", -12.236294746398926 ], [ "サック", -12.236432075500488 ], [ "ミド", -12.23646354675293 ], [ "ッティング", -12.236471176147461 ], [ "▁内臓", -12.236753463745117 ], [ "▁少なからず", -12.236775398254395 ], [ "▁line", -12.236910820007324 ], [ "▁410", -12.236947059631348 ], [ "RR", -12.237013816833496 ], [ "▁セレブ", -12.237058639526367 ], [ "▁寛永", -12.23709774017334 ], [ "▁チェロ", -12.237228393554688 ], [ "ith", -12.237255096435547 ], [ "mal", -12.237686157226562 ], [ "粛", -12.237802505493164 ], [ "▁ジュリア", -12.237854957580566 ], [ "んぼ", -12.238058090209961 ], [ "▁灰色", -12.238130569458008 ], [ "▁チューブ", -12.238165855407715 ], [ "リョ", -12.238184928894043 ], [ "YouTube", -12.238249778747559 ], [ "ket", -12.238292694091797 ], [ "▁松戸", -12.238308906555176 ], [ "▁KB", -12.238337516784668 ], [ "LF", -12.238365173339844 ], [ "▁Pre", -12.238511085510254 ], [ "▁重ねた", -12.238519668579102 ], [ "ザック", -12.23861312866211 ], [ "▁貸して", -12.238801956176758 ], [ "▁ダート", -12.238866806030273 ], [ "テリ", -12.238873481750488 ], [ "▁封鎖", -12.239092826843262 ], [ "▁分担", -12.239121437072754 ], [ "▁ライフル", -12.239189147949219 ], [ "モール", -12.239195823669434 ], [ "▁因んで", -12.23920726776123 ], [ "▁イヤホン", -12.239226341247559 ], [ "プロフィール", -12.239233016967773 ], [ "年間", -12.239273071289062 ], [ "▁りんご", -12.239339828491211 ], [ "少年", -12.239389419555664 ], [ "UC", -12.239432334899902 ], [ "茎", -12.239570617675781 ], [ "▁承継", -12.239598274230957 ], [ "メロ", -12.239752769470215 ], [ "▁グリー", -12.239776611328125 ], [ "▁生誕", -12.239787101745605 ], [ "▁来院", -12.239845275878906 ], [ "▁移設", -12.239859580993652 ], [ "▁どういった", -12.240192413330078 ], [ "▁ナイロン", -12.240384101867676 ], [ "▁細く", -12.240554809570312 ], [ "▁箸", -12.240555763244629 ], [ "▁遅れた", -12.240593910217285 ], [ "平日", -12.240612983703613 ], [ "▁いわば", -12.240789413452148 ], [ "▁こみ", -12.24083423614502 ], [ "▁鳥居", -12.240851402282715 ], [ "▁氷河", -12.241079330444336 ], [ "▁脅迫", -12.241164207458496 ], [ "時代", -12.241320610046387 ], [ "fu", -12.241323471069336 ], [ "cl", -12.241440773010254 ], [ "ウオ", -12.241543769836426 ], [ "▁すご", -12.241559028625488 ], [ "▁軍艦", -12.241569519042969 ], [ "緯", -12.241593360900879 ], [ "▁des", -12.241722106933594 ], [ "▁収める", -12.24191665649414 ], [ "擬", -12.242016792297363 ], [ "IR", -12.24205207824707 ], [ "▁MOD", -12.242210388183594 ], [ "▁Up", -12.242348670959473 ], [ "▁移って", -12.242447853088379 ], [ "▁見込ま", -12.242508888244629 ], [ "▁最多の", -12.24254035949707 ], [ "▁募金", -12.242622375488281 ], [ "eu", -12.24262523651123 ], [ "拍", -12.242685317993164 ], [ "▁アルカ", -12.242706298828125 ], [ "▁萬", -12.242737770080566 ], [ "zo", -12.242740631103516 ], [ "▁いっ", -12.242776870727539 ], [ "キャリア", -12.242892265319824 ], [ "▁冷静に", -12.242910385131836 ], [ "▁王様", -12.242912292480469 ], [ "▁一律", -12.242984771728516 ], [ "▁自力", -12.2430419921875 ], [ "▁サスペンション", -12.243120193481445 ], [ "▁寒く", -12.243151664733887 ], [ "シアン", -12.243326187133789 ], [ "▁スマイル", -12.243402481079102 ], [ "賊", -12.243468284606934 ], [ "▁スイ", -12.243517875671387 ], [ "分類", -12.243539810180664 ], [ "合って", -12.243555068969727 ], [ "▁やむ", -12.243558883666992 ], [ "▁代用", -12.243592262268066 ], [ "▁高圧", -12.2437105178833 ], [ "▁気付いた", -12.243917465209961 ], [ "▁設けた", -12.243925094604492 ], [ "▁微笑", -12.244036674499512 ], [ "十五", -12.24406909942627 ], [ "▁ダイヤル", -12.244084358215332 ], [ "▁質疑", -12.24410343170166 ], [ "韓", -12.244154930114746 ], [ "菓", -12.244242668151855 ], [ "▁停滞", -12.24435043334961 ], [ "▁コス", -12.244366645812988 ], [ "どうぞ", -12.244399070739746 ], [ "▁原始", -12.244430541992188 ], [ "貌", -12.244439125061035 ], [ "▁くれたり", -12.244502067565918 ], [ "▁引き起こ", -12.244543075561523 ], [ "▁Watch", -12.24467658996582 ], [ "▁漫才", -12.244712829589844 ], [ "葺", -12.244712829589844 ], [ "涼", -12.24494457244873 ], [ "▁高岡", -12.244973182678223 ], [ "ラボ", -12.24500846862793 ], [ "▁pp", -12.245095252990723 ], [ "パワー", -12.245165824890137 ], [ "▁OR", -12.245182037353516 ], [ "脱毛", -12.245345115661621 ], [ "▁コンディション", -12.245572090148926 ], [ "ラーズ", -12.245704650878906 ], [ "拳", -12.245755195617676 ], [ "▁雛", -12.246228218078613 ], [ "▁惚れ", -12.246353149414062 ], [ "マート", -12.246528625488281 ], [ "▁屈指", -12.246588706970215 ], [ "bor", -12.246681213378906 ], [ "▁洗う", -12.246768951416016 ], [ "ホームページ", -12.24677848815918 ], [ "▁ペンシルベニア", -12.246854782104492 ], [ "▁絵師", -12.24701976776123 ], [ "▁不安な", -12.247185707092285 ], [ "▁雑談", -12.247214317321777 ], [ "▁ウサギ", -12.247326850891113 ], [ "▁Direct", -12.247332572937012 ], [ "▁SW", -12.247483253479004 ], [ "佐藤", -12.247483253479004 ], [ "▁顔面", -12.247489929199219 ], [ "▁外れ", -12.247564315795898 ], [ "▁政界", -12.247729301452637 ], [ "^^", -12.24775505065918 ], [ "▁復刻", -12.24781322479248 ], [ "▁プレッシャー", -12.248063087463379 ], [ "▁茶色", -12.24813461303711 ], [ "▁ユーゴスラビア", -12.24819564819336 ], [ "ery", -12.248230934143066 ], [ "操", -12.248249053955078 ], [ "▁痕跡", -12.248274803161621 ], [ "▁カルロス", -12.248333930969238 ], [ "テュ", -12.248403549194336 ], [ "いき", -12.248404502868652 ], [ "▁的であった", -12.248476028442383 ], [ "▁喋", -12.248481750488281 ], [ "▁嫌だ", -12.248557090759277 ], [ "ティエ", -12.24856948852539 ], [ "まさ", -12.248838424682617 ], [ "▁吾", -12.248940467834473 ], [ "▁一門", -12.248955726623535 ], [ "労働", -12.249001502990723 ], [ "▁インスタグラム", -12.249029159545898 ], [ "ジュール", -12.249089241027832 ], [ "作詞", -12.249098777770996 ], [ "▁ワーナー", -12.249136924743652 ], [ "▁学力", -12.24915885925293 ], [ "oh", -12.24935531616211 ], [ "▁Opera", -12.249369621276855 ], [ "▁聖人", -12.249373435974121 ], [ "ジュー", -12.249380111694336 ], [ "▁砕", -12.249396324157715 ], [ "▁トピック", -12.249402046203613 ], [ "▁アテネ", -12.249510765075684 ], [ "▁中尉", -12.249529838562012 ], [ "mes", -12.249726295471191 ], [ "えい", -12.250041961669922 ], [ "▁アレン", -12.250107765197754 ], [ "ゲスト", -12.250153541564941 ], [ "▁没後", -12.250248908996582 ], [ "▁大工", -12.250267028808594 ], [ "▁フォックス", -12.250285148620605 ], [ "▁後楽園", -12.250492095947266 ], [ "▁真田", -12.250593185424805 ], [ "▁ムハンマド", -12.250866889953613 ], [ "▁恵比寿", -12.250985145568848 ], [ "▁Network", -12.251004219055176 ], [ "▁っ子", -12.251077651977539 ], [ "ARS", -12.251100540161133 ], [ "▁喜ぶ", -12.251100540161133 ], [ "▁マナ", -12.251103401184082 ], [ "アニ", -12.251142501831055 ], [ "▁伊賀", -12.251455307006836 ], [ "↓", -12.25147819519043 ], [ "▁局所", -12.251673698425293 ], [ "▁Ltd", -12.251728057861328 ], [ "▁下さった", -12.252103805541992 ], [ "▁好奇心", -12.252220153808594 ], [ "群馬", -12.25222396850586 ], [ "▁美味しかった", -12.252227783203125 ], [ "▁相変わらず", -12.25231647491455 ], [ "▁外して", -12.252497673034668 ], [ "▁分館", -12.25284481048584 ], [ "スマートフォン", -12.252846717834473 ], [ "特記", -12.252856254577637 ], [ "▁てつ", -12.252889633178711 ], [ "仙台", -12.252989768981934 ], [ "▁トリオ", -12.253083229064941 ], [ "▁亡くなって", -12.253087043762207 ], [ "▁一新", -12.253100395202637 ], [ "▁mp", -12.253127098083496 ], [ "▁今夜", -12.253267288208008 ], [ "これほど", -12.253291130065918 ], [ "▁美白", -12.253334045410156 ], [ "▁堤", -12.25337028503418 ], [ "槽", -12.253433227539062 ], [ "▁ついで", -12.253463745117188 ], [ "ドゥー", -12.253470420837402 ], [ "▁破った", -12.253645896911621 ], [ "▁レイヤー", -12.253691673278809 ], [ "▁一戸建て", -12.253703117370605 ], [ "▁TS", -12.253750801086426 ], [ "▁キーパー", -12.25390625 ], [ "▁懐かしい", -12.25395393371582 ], [ "▁良し", -12.253957748413086 ], [ "▁過失", -12.253999710083008 ], [ "▁半額", -12.254167556762695 ], [ "▁特産", -12.254287719726562 ], [ "▁おまえ", -12.25433349609375 ], [ "▁注ぐ", -12.25438117980957 ], [ "▁主将", -12.254483222961426 ], [ "連邦", -12.254535675048828 ], [ "▁大丈夫な", -12.254590034484863 ], [ "▁マレー", -12.254647254943848 ], [ "画面", -12.254653930664062 ], [ "▁留まった", -12.254778861999512 ], [ "vers", -12.254904747009277 ], [ "▁台地", -12.254939079284668 ], [ "▁逃走", -12.254972457885742 ], [ "ッリ", -12.255030632019043 ], [ "▁ズレ", -12.25505256652832 ], [ "▁うな", -12.25507926940918 ], [ "同様に", -12.255094528198242 ], [ "▁Fire", -12.25512409210205 ], [ "▁近づけ", -12.255218505859375 ], [ "▁麻生", -12.255302429199219 ], [ "▁村田", -12.255305290222168 ], [ "▁取り巻く", -12.2553129196167 ], [ "▁本願寺", -12.2553129196167 ], [ "▁的であり", -12.255313873291016 ], [ "▁信州", -12.255317687988281 ], [ "lex", -12.255348205566406 ], [ "▁近接", -12.25535774230957 ], [ "▁直接の", -12.25544548034668 ], [ "▁幸運", -12.255459785461426 ], [ "フィア", -12.255636215209961 ], [ "▁親しみ", -12.255685806274414 ], [ "▁太子", -12.255768775939941 ], [ "▁弘前", -12.255778312683105 ], [ "ven", -12.255842208862305 ], [ "▁忙しく", -12.255904197692871 ], [ "却", -12.255941390991211 ], [ "▁周回", -12.255965232849121 ], [ "▁撃ち", -12.25601577758789 ], [ "▁浮き", -12.256046295166016 ], [ "▁USS", -12.256196975708008 ], [ "▁不妊", -12.256285667419434 ], [ "my", -12.256355285644531 ], [ "▁マニ", -12.256449699401855 ], [ "▁高額な", -12.256523132324219 ], [ "ラック", -12.256525993347168 ], [ "▁ウッ", -12.256529808044434 ], [ "▁模倣", -12.256552696228027 ], [ "付いて", -12.256613731384277 ], [ "▁購買", -12.256800651550293 ], [ "▁ハーバード", -12.256834030151367 ], [ "▁単品", -12.256916999816895 ], [ "捕", -12.256954193115234 ], [ "▁吊", -12.256957054138184 ], [ "せつ", -12.256963729858398 ], [ "▁年月", -12.256982803344727 ], [ "まさに", -12.257193565368652 ], [ "right", -12.25725269317627 ], [ "▁ギリギリ", -12.25729751586914 ], [ "▁引いた", -12.257370948791504 ], [ "エレ", -12.25742244720459 ], [ "▁online", -12.257454872131348 ], [ "TRA", -12.257514953613281 ], [ "▁水曜", -12.257645606994629 ], [ "rs", -12.257671356201172 ], [ "▁亡くなり", -12.257673263549805 ], [ "▁張って", -12.257840156555176 ], [ "▁大丸", -12.257963180541992 ], [ "▁豪華な", -12.258033752441406 ], [ "pon", -12.258171081542969 ], [ "▁FR", -12.258177757263184 ], [ "スン", -12.258232116699219 ], [ "▁物価", -12.258430480957031 ], [ "▁ネパール", -12.258455276489258 ], [ "▁摩", -12.258463859558105 ], [ "AKE", -12.258522987365723 ], [ "▁遅れる", -12.258530616760254 ], [ "パール", -12.258551597595215 ], [ "▁伊丹", -12.25872802734375 ], [ "ect", -12.258854866027832 ], [ "▁卸売", -12.258912086486816 ], [ "▁硬貨", -12.25955581665039 ], [ "▁€", -12.259661674499512 ], [ "▁ぶっ", -12.259748458862305 ], [ "aga", -12.2598237991333 ], [ "▁ビリー", -12.25982666015625 ], [ "▁聴覚", -12.26006031036377 ], [ "ロワ", -12.260143280029297 ], [ "▁メルセデス", -12.260156631469727 ], [ "▁レンガ", -12.260177612304688 ], [ "▁淫", -12.260272026062012 ], [ "▁ベッ", -12.260428428649902 ], [ "▁補う", -12.260478973388672 ], [ "▁厳重", -12.260485649108887 ], [ "▁手袋", -12.260541915893555 ], [ "▁頼朝", -12.260632514953613 ], [ "ND", -12.260724067687988 ], [ "▁ティン", -12.260787963867188 ], [ "▁帯び", -12.261004447937012 ], [ "▁プロバイダー", -12.26112174987793 ], [ "arch", -12.261162757873535 ], [ "暑", -12.261207580566406 ], [ "▁見合い", -12.261305809020996 ], [ "▁出かける", -12.261429786682129 ], [ "シド", -12.261476516723633 ], [ "▁歪み", -12.261536598205566 ], [ "ns", -12.261618614196777 ], [ "▁貯め", -12.261618614196777 ], [ "▁元帥", -12.261808395385742 ], [ "▁薪", -12.26182746887207 ], [ "ato", -12.261855125427246 ], [ "▁書道", -12.261866569519043 ], [ "▁かねて", -12.2618989944458 ], [ "▁取り戻し", -12.262018203735352 ], [ "▁森田", -12.262125015258789 ], [ "ディアン", -12.262141227722168 ], [ "蛮", -12.262275695800781 ], [ "閑", -12.26252555847168 ], [ "▁Ga", -12.262535095214844 ], [ "国立", -12.262578964233398 ], [ "▁冊子", -12.262761116027832 ], [ "ATE", -12.262972831726074 ], [ "シェア", -12.26305866241455 ], [ "▁Team", -12.263144493103027 ], [ "▁MAN", -12.263219833374023 ], [ "▁Ko", -12.263364791870117 ], [ "裁判", -12.263396263122559 ], [ "▁湧", -12.263442039489746 ], [ "ダール", -12.263649940490723 ], [ "▁緊", -12.263655662536621 ], [ "▁ダメだ", -12.263882637023926 ], [ "▁面して", -12.263910293579102 ], [ "▁キミ", -12.263992309570312 ], [ "▁ブロンテ", -12.264131546020508 ], [ "とくに", -12.264148712158203 ], [ "▁クラウン", -12.264165878295898 ], [ "▁祥", -12.264222145080566 ], [ "曇", -12.264394760131836 ], [ "▁ビキニ", -12.264524459838867 ], [ "▁敗れる", -12.264625549316406 ], [ "▁嫉妬", -12.264649391174316 ], [ "▁終始", -12.264679908752441 ], [ "弦", -12.264721870422363 ], [ "▁空調", -12.264817237854004 ], [ "▁品物", -12.264856338500977 ], [ "▁居た", -12.264891624450684 ], [ "less", -12.265054702758789 ], [ "▁Mobile", -12.26508617401123 ], [ "こない", -12.265116691589355 ], [ "▁富田", -12.265164375305176 ], [ "ふう", -12.265179634094238 ], [ "▁廣", -12.265242576599121 ], [ "覇", -12.265254974365234 ], [ "▁戸籍", -12.265360832214355 ], [ "▁没した", -12.26537036895752 ], [ "▁190", -12.265388488769531 ], [ "▁虫歯", -12.265471458435059 ], [ "こす", -12.265498161315918 ], [ "ift", -12.265509605407715 ], [ "条件", -12.265552520751953 ], [ "▁ローダー", -12.26560115814209 ], [ "担当", -12.265670776367188 ], [ "▁Dream", -12.265789031982422 ], [ "▁常任", -12.265849113464355 ], [ "▁qu", -12.266084671020508 ], [ "▁よば", -12.26617431640625 ], [ "▁サミット", -12.266368865966797 ], [ "—", -12.266378402709961 ], [ "▁ずいぶん", -12.26652717590332 ], [ "▁単身", -12.266770362854004 ], [ "▁洞", -12.266844749450684 ], [ "▁クラッシュ", -12.266863822937012 ], [ "mas", -12.266867637634277 ], [ "▁牙", -12.266935348510742 ], [ "uck", -12.266940116882324 ], [ "ule", -12.266948699951172 ], [ "▁靖", -12.267006874084473 ], [ "菅", -12.267016410827637 ], [ "1934", -12.267059326171875 ], [ "▁サングラス", -12.267098426818848 ], [ "一緒に", -12.267281532287598 ], [ "バッグ", -12.267298698425293 ], [ "▁元気な", -12.267315864562988 ], [ "mm", -12.267361640930176 ], [ "▁特命", -12.2673921585083 ], [ "▁貰って", -12.267531394958496 ], [ "▁めで", -12.267790794372559 ], [ "▁まえ", -12.267830848693848 ], [ "▁斗", -12.268009185791016 ], [ "▁002", -12.268080711364746 ], [ "▁物産", -12.268193244934082 ], [ "▁タービン", -12.268220901489258 ], [ "去", -12.26839542388916 ], [ "▁ウエア", -12.26856803894043 ], [ "瀧", -12.268659591674805 ], [ "バンク", -12.268865585327148 ], [ "▁いつまで", -12.26907730102539 ], [ "▁手助け", -12.269288063049316 ], [ "▁進軍", -12.269294738769531 ], [ "フス", -12.269319534301758 ], [ "▁やめる", -12.269351959228516 ], [ "▁彦", -12.269465446472168 ], [ "セブン", -12.269501686096191 ], [ "▁確実な", -12.269535064697266 ], [ "▁ミラ", -12.269536972045898 ], [ "国道", -12.269554138183594 ], [ "ORI", -12.269660949707031 ], [ "プティ", -12.269820213317871 ], [ "▁御所", -12.269919395446777 ], [ "▁先週", -12.26996898651123 ], [ "奉", -12.270041465759277 ], [ "▁ポータブル", -12.270042419433594 ], [ "▁各駅", -12.270094871520996 ], [ "▁すばらしい", -12.270153045654297 ], [ "▁外食", -12.270153999328613 ], [ "▁ハーン", -12.270242691040039 ], [ "べる", -12.270270347595215 ], [ "しっかり", -12.270320892333984 ], [ "▁その先", -12.27047061920166 ], [ "▁特技", -12.270683288574219 ], [ "ッセン", -12.270768165588379 ], [ "▁寝室", -12.271096229553223 ], [ "▁マネ", -12.271164894104004 ], [ "▁超過", -12.271164894104004 ], [ "▁怪しい", -12.27132511138916 ], [ "MON", -12.271347045898438 ], [ "▁融", -12.271428108215332 ], [ "▁健全な", -12.27143669128418 ], [ "禅", -12.27153205871582 ], [ "▁表し", -12.271551132202148 ], [ "ネコ", -12.271564483642578 ], [ "▁子爵", -12.271588325500488 ], [ "鞭", -12.271597862243652 ], [ "塗", -12.27161693572998 ], [ "▁激怒", -12.271716117858887 ], [ "ちょうど", -12.271722793579102 ], [ "oth", -12.2717866897583 ], [ "▁取り除く", -12.271803855895996 ], [ "▁酷い", -12.271808624267578 ], [ "べつ", -12.27188491821289 ], [ "▁直感", -12.272018432617188 ], [ "▁混在", -12.272132873535156 ], [ "cent", -12.272261619567871 ], [ "RB", -12.272313117980957 ], [ "▁PP", -12.272329330444336 ], [ "バース", -12.272333145141602 ], [ "▁赤本", -12.272335052490234 ], [ "▁何者", -12.27236557006836 ], [ "▁HC", -12.272394180297852 ], [ "▁頼み", -12.272443771362305 ], [ "▁鱗", -12.272501945495605 ], [ "▁云う", -12.272509574890137 ], [ "▁行政書士", -12.272560119628906 ], [ "▁報じた", -12.272686958312988 ], [ "▁魅", -12.272706031799316 ], [ "▁ギャング", -12.272915840148926 ], [ "畠", -12.273188591003418 ], [ "嶽", -12.273316383361816 ], [ "ö", -12.273442268371582 ], [ "翁", -12.273443222045898 ], [ "▁取引先", -12.2735013961792 ], [ "▁飛鳥", -12.273642539978027 ], [ "▁カモ", -12.273665428161621 ], [ "▁At", -12.273724555969238 ], [ "▁金剛", -12.273748397827148 ], [ "▁動け", -12.27389144897461 ], [ "▁積んで", -12.273932456970215 ], [ "▁ディオ", -12.274223327636719 ], [ "▁揃え", -12.274418830871582 ], [ "ction", -12.274491310119629 ], [ "▁USA", -12.274508476257324 ], [ "顎", -12.274550437927246 ], [ "▁くろ", -12.274557113647461 ], [ "▁暴動", -12.274558067321777 ], [ "こい", -12.274592399597168 ], [ "▁聖職", -12.274635314941406 ], [ "▁IWC", -12.274639129638672 ], [ "陀", -12.27470588684082 ], [ "DOM", -12.274815559387207 ], [ "▁総集編", -12.275084495544434 ], [ "ミット", -12.27517318725586 ], [ "ott", -12.275288581848145 ], [ "▁釜", -12.275510787963867 ], [ "だし", -12.275552749633789 ], [ "ゆき", -12.275565147399902 ], [ "▁過激", -12.275567054748535 ], [ "▁アクリル", -12.275633811950684 ], [ "▁分譲", -12.275660514831543 ], [ "▁とんでもない", -12.275718688964844 ], [ "▁頂上", -12.275786399841309 ], [ "nn", -12.275839805603027 ], [ "▁原告", -12.275893211364746 ], [ "ネタ", -12.275915145874023 ], [ "▁バイブ", -12.275993347167969 ], [ "ITA", -12.276098251342773 ], [ "ダック", -12.276185989379883 ], [ "▁ペイント", -12.276267051696777 ], [ "わざ", -12.276334762573242 ], [ "▁着実に", -12.276350021362305 ], [ "▁JS", -12.276424407958984 ], [ "els", -12.27642822265625 ], [ "▁YouTuber", -12.276487350463867 ], [ "▁鮮やかな", -12.276511192321777 ], [ "▁マシ", -12.276639938354492 ], [ "▁ミカ", -12.276698112487793 ], [ "▁アリゾナ", -12.276728630065918 ], [ "▁TD", -12.276732444763184 ], [ "▁閉め", -12.276912689208984 ], [ "旭", -12.276938438415527 ], [ "▁表題", -12.27694034576416 ], [ "▁供用", -12.276983261108398 ], [ "リントン", -12.277057647705078 ], [ "▁水田", -12.277200698852539 ], [ "生産", -12.27724838256836 ], [ "カフェ", -12.277284622192383 ], [ "継ぎ", -12.277300834655762 ], [ "▁音色", -12.277313232421875 ], [ "▁対峙", -12.277363777160645 ], [ "▁Har", -12.277417182922363 ], [ "▁北口", -12.27742862701416 ], [ "いちゃ", -12.277454376220703 ], [ "▁東工", -12.27757453918457 ], [ "▁浮かぶ", -12.277674674987793 ], [ "出版", -12.277979850769043 ], [ "▁ぶつけ", -12.278024673461914 ], [ "▁手頃", -12.278046607971191 ], [ "対応", -12.278047561645508 ], [ "▁カップリング", -12.278217315673828 ], [ "▁手持ち", -12.278288841247559 ], [ "”", -12.278341293334961 ], [ "▁入間", -12.278348922729492 ], [ "▁苛", -12.27837085723877 ], [ "▁青空", -12.278520584106445 ], [ "▁白鳥", -12.278609275817871 ], [ "▁サンダル", -12.27861213684082 ], [ "▁Res", -12.278743743896484 ], [ "▁可動", -12.278989791870117 ], [ "▁アタ", -12.27900218963623 ], [ "▁あっさり", -12.279009819030762 ], [ "エリア", -12.27901840209961 ], [ "▁もたらし", -12.279029846191406 ], [ "センス", -12.279125213623047 ], [ "▁築く", -12.279128074645996 ], [ "▁履行", -12.279132843017578 ], [ "▁奉納", -12.279191017150879 ], [ "▁幕張", -12.27922534942627 ], [ "越し", -12.279393196105957 ], [ "ステージ", -12.27939510345459 ], [ "▁もらおう", -12.27940559387207 ], [ "▁ジェリー", -12.279458045959473 ], [ "▁フォート", -12.279542922973633 ], [ "▁皇室", -12.279623985290527 ], [ "mit", -12.279777526855469 ], [ "▁確かめ", -12.280029296875 ], [ "1935", -12.28003978729248 ], [ "▁何かと", -12.280157089233398 ], [ "▁下さ", -12.280244827270508 ], [ "▁ヒューマン", -12.280254364013672 ], [ "▁ロッド", -12.280364990234375 ], [ "▁失調", -12.28064250946045 ], [ "▁議事", -12.28066349029541 ], [ "ウロ", -12.280673027038574 ], [ "目的", -12.28072452545166 ], [ "To", -12.280738830566406 ], [ "大型", -12.280774116516113 ], [ "▁無駄な", -12.280855178833008 ], [ "▁ノード", -12.28093147277832 ], [ "曽根", -12.280932426452637 ], [ "▁Mod", -12.281020164489746 ], [ "▁奄美", -12.281042098999023 ], [ "▁側近", -12.281140327453613 ], [ "▁京急", -12.281194686889648 ], [ "▁貧しい", -12.28129768371582 ], [ "▁ベール", -12.281302452087402 ], [ "▁満ちた", -12.281475067138672 ], [ "▁部数", -12.281575202941895 ], [ "歩き", -12.281593322753906 ], [ "▁当てる", -12.2816162109375 ], [ "HP", -12.281636238098145 ], [ "▁カセット", -12.281673431396484 ], [ "emo", -12.281758308410645 ], [ "▁高地", -12.281842231750488 ], [ "▁伴奏", -12.281947135925293 ], [ "▁ミリ", -12.281951904296875 ], [ "▁はじまり", -12.281966209411621 ], [ "碑", -12.28219985961914 ], [ "▁系譜", -12.282207489013672 ], [ "▁並み", -12.28221607208252 ], [ "投資", -12.282217025756836 ], [ "▁おおよそ", -12.282232284545898 ], [ "▁培養", -12.282459259033203 ], [ "▁しまったら", -12.2825288772583 ], [ "OU", -12.282537460327148 ], [ "フィラ", -12.282682418823242 ], [ "▁咲いて", -12.28281021118164 ], [ "▁オバマ", -12.282824516296387 ], [ "▁res", -12.28285026550293 ], [ "tle", -12.282951354980469 ], [ "▁夢中に", -12.282953262329102 ], [ "▁朴", -12.28308391571045 ], [ "▁1902", -12.283285140991211 ], [ "▁勤めて", -12.28329849243164 ], [ "uz", -12.283495903015137 ], [ "▁発刊", -12.283608436584473 ], [ "▁効く", -12.283615112304688 ], [ "▁伝わり", -12.283759117126465 ], [ "我が家", -12.283857345581055 ], [ "▁西郷", -12.283907890319824 ], [ "▁蜂", -12.28406047821045 ], [ "▁過酷な", -12.284098625183105 ], [ "▁点灯", -12.284128189086914 ], [ "unt", -12.284194946289062 ], [ "近代", -12.284238815307617 ], [ "▁貰う", -12.284353256225586 ], [ "ニャン", -12.284354209899902 ], [ "▁屋台", -12.284358978271484 ], [ "▁眠る", -12.284378051757812 ], [ "ルディ", -12.284448623657227 ], [ "CU", -12.284512519836426 ], [ "挿", -12.284529685974121 ], [ "ポキル", -12.284536361694336 ], [ "▁アポロ", -12.28467082977295 ], [ "▁萌え", -12.2850341796875 ], [ "銘", -12.285099983215332 ], [ "▁重なり", -12.285114288330078 ], [ "炉", -12.285141944885254 ], [ "▁津田", -12.285272598266602 ], [ "▁何十", -12.285294532775879 ], [ "▁富士見", -12.285307884216309 ], [ "》", -12.28539752960205 ], [ "▁ウィルソン", -12.285435676574707 ], [ "▁図面", -12.285454750061035 ], [ "▁デパート", -12.285486221313477 ], [ "▁有力な", -12.28565502166748 ], [ "▁リリー", -12.28565788269043 ], [ "▁Records", -12.285764694213867 ], [ "▁見積", -12.285829544067383 ], [ "▁すす", -12.285859107971191 ], [ "▁気付き", -12.285959243774414 ], [ "▁産駒", -12.286067008972168 ], [ "▁盛り込ま", -12.286140441894531 ], [ "▁green", -12.286145210266113 ], [ "▁うかが", -12.28619384765625 ], [ "縄", -12.286275863647461 ], [ "ection", -12.286444664001465 ], [ "▁デコ", -12.28646469116211 ], [ "▁隙", -12.286510467529297 ], [ "清水", -12.286548614501953 ], [ "▁文京", -12.286665916442871 ], [ "▁ジュー", -12.286723136901855 ], [ "まじ", -12.286725044250488 ], [ "▁奥様", -12.286734580993652 ], [ "▁ウチ", -12.286943435668945 ], [ "絡", -12.287077903747559 ], [ "▁トレーディング", -12.287091255187988 ], [ "轄", -12.287311553955078 ], [ "▁封入", -12.287357330322266 ], [ "シュタイン", -12.287393569946289 ], [ "▁貯", -12.28748607635498 ], [ "ゴル", -12.287588119506836 ], [ "▁なされる", -12.287611961364746 ], [ "LM", -12.287631034851074 ], [ "▁懐かし", -12.28775691986084 ], [ "▁コミューン", -12.287847518920898 ], [ "▁頼んで", -12.287931442260742 ], [ "▁有名です", -12.287933349609375 ], [ "AO", -12.288150787353516 ], [ "▁無罪", -12.288189888000488 ], [ "クライ", -12.288403511047363 ], [ "河内", -12.288409233093262 ], [ "▁factory", -12.288443565368652 ], [ "emp", -12.288564682006836 ], [ "▁«", -12.288578033447266 ], [ "▁MBS", -12.288671493530273 ], [ "屈", -12.288712501525879 ], [ "▁突っ込", -12.288867950439453 ], [ "omi", -12.28888988494873 ], [ "苦", -12.28895378112793 ], [ "▁格子", -12.28901481628418 ], [ "▁処罰", -12.289093017578125 ], [ "ava", -12.289121627807617 ], [ "伝統", -12.289220809936523 ], [ "▁引か", -12.289237976074219 ], [ "▁ヒン", -12.289444923400879 ], [ "▁止まって", -12.289506912231445 ], [ "TB", -12.289560317993164 ], [ "▁構図", -12.289596557617188 ], [ "▁創生", -12.289670944213867 ], [ "▁シューティング", -12.28978157043457 ], [ "▁フェチ", -12.28982162475586 ], [ "▁摂津", -12.289863586425781 ], [ "廷", -12.289905548095703 ], [ "▁久米", -12.28998851776123 ], [ "編集", -12.290099143981934 ], [ "▁だが", -12.290117263793945 ], [ "ミノ", -12.290143966674805 ], [ "▁開閉", -12.290170669555664 ], [ "▁姦", -12.290231704711914 ], [ "感染", -12.290337562561035 ], [ "▁Mr", -12.290514945983887 ], [ "揚げ", -12.290553092956543 ], [ "▁本舗", -12.290576934814453 ], [ "▁Ni", -12.290593147277832 ], [ "▁不問", -12.290611267089844 ], [ "亡", -12.29063892364502 ], [ "▁吾妻", -12.290651321411133 ], [ "▁まこと", -12.29076099395752 ], [ "▁狙", -12.29081916809082 ], [ "▁映え", -12.290857315063477 ], [ "▁幽", -12.290863037109375 ], [ "▁制した", -12.291057586669922 ], [ "▁内面", -12.291091918945312 ], [ "▁High", -12.291119575500488 ], [ "▁廊下", -12.2911376953125 ], [ "▁シベリア", -12.29127025604248 ], [ "▁肥", -12.291337013244629 ], [ "ちゅう", -12.29134750366211 ], [ "クリス", -12.291377067565918 ], [ "▁XL", -12.2913818359375 ], [ "▁舗装", -12.291394233703613 ], [ "cc", -12.291465759277344 ], [ "▁履き", -12.291476249694824 ], [ "▁反転", -12.291500091552734 ], [ "▁クレーム", -12.291717529296875 ], [ "▁越えた", -12.291837692260742 ], [ "▁貸切", -12.292227745056152 ], [ "▁ゲリラ", -12.292293548583984 ], [ "1928", -12.292384147644043 ], [ "ゅう", -12.292447090148926 ], [ "三重", -12.292481422424316 ], [ "▁投影", -12.292746543884277 ], [ "▁商社", -12.293010711669922 ], [ "▁GE", -12.293051719665527 ], [ "▁Disc", -12.293137550354004 ], [ "還", -12.293192863464355 ], [ "SQL", -12.293207168579102 ], [ "▁エンジニアリング", -12.293244361877441 ], [ "▁厚く", -12.29325008392334 ], [ "▁亡", -12.293330192565918 ], [ "▁分断", -12.293339729309082 ], [ "▁慰謝料", -12.293451309204102 ], [ "▁洗礼", -12.293734550476074 ], [ "温泉", -12.29378890991211 ], [ "▁木下", -12.293900489807129 ], [ "▁サウ", -12.294113159179688 ], [ "ono", -12.294219970703125 ], [ "now", -12.294281005859375 ], [ "▁カラフル", -12.294310569763184 ], [ "▁間違った", -12.294353485107422 ], [ "▁密かに", -12.29439640045166 ], [ "▁ヒーター", -12.29448127746582 ], [ "pro", -12.294529914855957 ], [ "▁ウイング", -12.2946138381958 ], [ "弓", -12.294700622558594 ], [ "▁310", -12.294754028320312 ], [ "送料", -12.294754028320312 ], [ "▁郵政", -12.294868469238281 ], [ "▁プレゼンテーション", -12.294883728027344 ], [ "▁Ant", -12.295036315917969 ], [ "▁容易", -12.29510498046875 ], [ "▁名乗って", -12.295255661010742 ], [ "▁諸説", -12.295690536499023 ], [ "かったり", -12.295763969421387 ], [ "▁嫌いな", -12.295780181884766 ], [ "▁flower", -12.296029090881348 ], [ "PDF", -12.296075820922852 ], [ "▁紺", -12.2962064743042 ], [ "砕", -12.296257019042969 ], [ "▁大川", -12.296378135681152 ], [ "▁必要不可欠", -12.296416282653809 ], [ "▁Da", -12.29642105102539 ], [ "エステ", -12.296459197998047 ], [ "シード", -12.296723365783691 ], [ "▁DR", -12.296788215637207 ], [ "▁var", -12.296796798706055 ], [ "▁獣医", -12.296806335449219 ], [ "▁電球", -12.296871185302734 ], [ "▁申し立て", -12.29695987701416 ], [ "▁じゅん", -12.297037124633789 ], [ "▁渡航", -12.297243118286133 ], [ "漁", -12.297304153442383 ], [ "▁脅か", -12.297435760498047 ], [ "▁浜田", -12.29745101928711 ], [ "▁乗り物", -12.297459602355957 ], [ "▁聴取", -12.297516822814941 ], [ "りょう", -12.297571182250977 ], [ "▁断言", -12.297609329223633 ], [ "▁SSL", -12.297630310058594 ], [ "▁余計な", -12.297708511352539 ], [ "IVE", -12.297745704650879 ], [ "借", -12.297898292541504 ], [ "▁台東", -12.297981262207031 ], [ "ショップ", -12.297981262207031 ], [ "▁騎", -12.298088073730469 ], [ "▁Application", -12.298095703125 ], [ "▁とらわれ", -12.298105239868164 ], [ "自動", -12.298114776611328 ], [ "▁金子", -12.298127174377441 ], [ "▁もとより", -12.298148155212402 ], [ "▁葛", -12.298179626464844 ], [ "▁リノベーション", -12.298613548278809 ], [ "征", -12.298711776733398 ], [ "▁アイデンティティ", -12.29874324798584 ], [ "▁スレンダー", -12.298772811889648 ], [ "▁引き継ぎ", -12.298807144165039 ], [ "the", -12.298842430114746 ], [ "▁何処", -12.298879623413086 ], [ "▁暮れ", -12.29891300201416 ], [ "DL", -12.298933029174805 ], [ "友達", -12.298962593078613 ], [ "▁WORLD", -12.299001693725586 ], [ "▁オーラ", -12.299055099487305 ], [ "▁親衛隊", -12.299261093139648 ], [ "era", -12.29928207397461 ], [ "▁301", -12.299285888671875 ], [ "▁サーフィン", -12.299345016479492 ], [ "▁着く", -12.299386978149414 ], [ "▁アリバイ", -12.299395561218262 ], [ "チコ", -12.299604415893555 ], [ "▁Sw", -12.299605369567871 ], [ "▁国体", -12.299622535705566 ], [ "▁延び", -12.299633979797363 ], [ "▁つとめ", -12.2997465133667 ], [ "▁断片", -12.29986572265625 ], [ "▁NT", -12.300063133239746 ], [ "▁聖母", -12.300103187561035 ], [ "App", -12.300126075744629 ], [ "▁ナイター", -12.300182342529297 ], [ "EAT", -12.300209045410156 ], [ "▁射程", -12.300463676452637 ], [ "▁頭文字", -12.300467491149902 ], [ "クマ", -12.300514221191406 ], [ "▁Exp", -12.300668716430664 ], [ "クラス", -12.300734519958496 ], [ "▁コンロ", -12.300816535949707 ], [ "▁苦しんで", -12.300816535949707 ], [ "▁共存", -12.300883293151855 ], [ "▁><", -12.300908088684082 ], [ "▁地蔵", -12.300920486450195 ], [ "▁互", -12.300984382629395 ], [ "テーマ", -12.301006317138672 ], [ "▁椿", -12.301024436950684 ], [ "▁国営", -12.301128387451172 ], [ "▁ユリ", -12.301305770874023 ], [ "エリ", -12.301309585571289 ], [ "▁スラム", -12.3013277053833 ], [ "▁産物", -12.3015718460083 ], [ "▁本家", -12.30158519744873 ], [ "付ける", -12.301621437072754 ], [ "悟", -12.30176067352295 ], [ "▁住んだ", -12.301793098449707 ], [ "▁Ag", -12.302131652832031 ], [ "▁退院", -12.302440643310547 ], [ "ノコ", -12.30251693725586 ], [ "狂", -12.302732467651367 ], [ "▁タイガー", -12.302743911743164 ], [ "▁おこなう", -12.302762985229492 ], [ "▁松江", -12.302769660949707 ], [ "▁ホッ", -12.30282211303711 ], [ "▁枯れ", -12.30282974243164 ], [ "質問", -12.302922248840332 ], [ "峠", -12.303194999694824 ], [ "▁のうた", -12.303400039672852 ], [ "▁Col", -12.30345630645752 ], [ "DER", -12.30354118347168 ], [ "▁どなた", -12.303827285766602 ], [ "小学生", -12.303884506225586 ], [ "▁レイク", -12.30391788482666 ], [ "ピス", -12.303921699523926 ], [ "巾", -12.303932189941406 ], [ "▁ローソン", -12.303987503051758 ], [ "▁乗せ", -12.303987503051758 ], [ "瑠", -12.304062843322754 ], [ "▁Club", -12.30423641204834 ], [ "ログ", -12.304287910461426 ], [ "▁マクドナルド", -12.304323196411133 ], [ "ワーズ", -12.304340362548828 ], [ "BR", -12.304365158081055 ], [ "▁浴びて", -12.304413795471191 ], [ "▁ワンダー", -12.304461479187012 ], [ "車体", -12.30447006225586 ], [ "▁レンタカー", -12.304500579833984 ], [ "▁恐れて", -12.304574012756348 ], [ "▁フォール", -12.304717063903809 ], [ "▁居場所", -12.304753303527832 ], [ "▁致命", -12.304760932922363 ], [ "▁旗本", -12.30476188659668 ], [ "▁最高裁", -12.304767608642578 ], [ "▁住職", -12.305068969726562 ], [ "▁母子", -12.305163383483887 ], [ "▁襲名", -12.30523681640625 ], [ "ヘイ", -12.305272102355957 ], [ "ビアン", -12.305468559265137 ], [ "可能", -12.305486679077148 ], [ "ブリー", -12.305558204650879 ], [ "▁定時", -12.3056001663208 ], [ "▁罠", -12.305601119995117 ], [ "▁田原", -12.305606842041016 ], [ "▁御用", -12.305865287780762 ], [ "▁観た", -12.305865287780762 ], [ "▁堤防", -12.305898666381836 ], [ "▁養育", -12.305920600891113 ], [ "▁ブラザーズ", -12.306015968322754 ], [ "▁書け", -12.306109428405762 ], [ "▁思い出した", -12.306138038635254 ], [ "仮名", -12.306190490722656 ], [ "▁架け", -12.306239128112793 ], [ "▁沼津", -12.306282997131348 ], [ "劇場", -12.306286811828613 ], [ "▁告示", -12.30640697479248 ], [ "▁茅", -12.306426048278809 ], [ "▁気に入", -12.30647087097168 ], [ "¥", -12.306474685668945 ], [ "必ず", -12.30652141571045 ], [ "▁学べる", -12.306551933288574 ], [ "討", -12.30662727355957 ], [ "▁ようこそ", -12.306668281555176 ], [ "▁苦しむ", -12.306669235229492 ], [ "▁か月間", -12.306965827941895 ], [ "DP", -12.307012557983398 ], [ "▁神楽", -12.307046890258789 ], [ "eng", -12.307055473327637 ], [ "簡", -12.307074546813965 ], [ "▁先代", -12.307137489318848 ], [ "拒", -12.3071870803833 ], [ "RNA", -12.30718994140625 ], [ "▁中堅", -12.307767868041992 ], [ "▁年俸", -12.307777404785156 ], [ "▁注力", -12.307812690734863 ], [ "▁事由", -12.307856559753418 ], [ "▁制し", -12.307859420776367 ], [ "▁過ごせる", -12.307868003845215 ], [ "▁特価", -12.307991981506348 ], [ "▁モーション", -12.308006286621094 ], [ "▁エディタ", -12.30801773071289 ], [ "▁裏切り", -12.308233261108398 ], [ "ham", -12.308354377746582 ], [ "▁着色", -12.308415412902832 ], [ "▁ケネディ", -12.308499336242676 ], [ "地名", -12.30855941772461 ], [ "▁会える", -12.308571815490723 ], [ "▁ソナタ", -12.30862808227539 ], [ "▁単発", -12.308751106262207 ], [ "▁抜粋", -12.30876636505127 ], [ "▁鴨", -12.308876037597656 ], [ "▁撤廃", -12.30888843536377 ], [ "ノア", -12.308966636657715 ], [ "▁1300", -12.309028625488281 ], [ "1929", -12.30916690826416 ], [ "ーん", -12.309292793273926 ], [ "▁フットサル", -12.309296607971191 ], [ "▁暴露", -12.309298515319824 ], [ "▁230", -12.309377670288086 ], [ "▁ダイア", -12.30950927734375 ], [ "▁済ませ", -12.309599876403809 ], [ "▁飼い", -12.309663772583008 ], [ "▁マック", -12.309723854064941 ], [ "富山", -12.309745788574219 ], [ "▁激化", -12.309760093688965 ], [ "▁嬉し", -12.30983829498291 ], [ "AIR", -12.309941291809082 ], [ "▁合致", -12.309964179992676 ], [ "IDE", -12.310047149658203 ], [ "▁毒性", -12.310272216796875 ], [ "▁寄って", -12.310323715209961 ], [ "▁総括", -12.31032943725586 ], [ "▁フォーカス", -12.310388565063477 ], [ "▁幸い", -12.31039047241211 ], [ "▁ヤフー", -12.310428619384766 ], [ "▁虚偽", -12.310462951660156 ], [ "要するに", -12.310462951660156 ], [ "▁シアリス", -12.310523986816406 ], [ "▁海老", -12.310546875 ], [ "▁がんばって", -12.31071949005127 ], [ "▁挫折", -12.310851097106934 ], [ "▁安価な", -12.3108549118042 ], [ "▁火曜", -12.311047554016113 ], [ "晋", -12.311090469360352 ], [ "▁シグナル", -12.311113357543945 ], [ "▁本多", -12.311131477355957 ], [ "▁ボーイング", -12.311214447021484 ], [ "▁使節", -12.31130313873291 ], [ "▁ベーシック", -12.3115234375 ], [ "ファイル", -12.311582565307617 ], [ "▁過半数", -12.311636924743652 ], [ "傑", -12.311636924743652 ], [ "▁CAD", -12.311663627624512 ], [ "▁招いた", -12.311834335327148 ], [ "▁480", -12.311845779418945 ], [ "▁引っ張", -12.311882972717285 ], [ "▁テクニカル", -12.311899185180664 ], [ "▁江東", -12.311963081359863 ], [ "▁SHOW", -12.312068939208984 ], [ "▁10000", -12.312187194824219 ], [ "▁忘れた", -12.312283515930176 ], [ "▁甘く", -12.312376022338867 ], [ "▁受領", -12.31238842010498 ], [ "釜", -12.31254768371582 ], [ "▁製鉄", -12.312627792358398 ], [ "▁剣道", -12.312633514404297 ], [ "▁white", -12.312686920166016 ], [ "▁ミスター", -12.312737464904785 ], [ "▁Sun", -12.312752723693848 ], [ "▁iPod", -12.312817573547363 ], [ "▁薬学", -12.312893867492676 ], [ "▁WBA", -12.312950134277344 ], [ "PD", -12.312973022460938 ], [ "▁魔法使い", -12.312989234924316 ], [ "▁バード", -12.313251495361328 ], [ "▁ロマ", -12.313254356384277 ], [ "▁火事", -12.313295364379883 ], [ "▁鎮守", -12.313419342041016 ], [ "寮", -12.313468933105469 ], [ "▁波長", -12.313529968261719 ], [ "▁当面", -12.31376838684082 ], [ "STA", -12.313824653625488 ], [ "▁熟成", -12.313847541809082 ], [ "▁没収", -12.313937187194824 ], [ "▁解凍", -12.31401252746582 ], [ "▁狙った", -12.314050674438477 ], [ "▁得意な", -12.314136505126953 ], [ "▁三原", -12.314140319824219 ], [ "ANG", -12.314254760742188 ], [ "ダンス", -12.314337730407715 ], [ "スタイン", -12.31434154510498 ], [ "ノイ", -12.314517974853516 ], [ "▁COVI", -12.314599990844727 ], [ "▁めちゃくちゃ", -12.314656257629395 ], [ "TAL", -12.31477165222168 ], [ "▁プライ", -12.314803123474121 ], [ "ギター", -12.31481647491455 ], [ "ring", -12.314884185791016 ], [ "▁ブッ", -12.314887046813965 ], [ "▁停電", -12.314915657043457 ], [ "back", -12.314952850341797 ], [ "▁シリアル", -12.315028190612793 ], [ "▁グリップ", -12.315288543701172 ], [ "▁チラ", -12.315337181091309 ], [ "▁im", -12.3154878616333 ], [ "キリ", -12.315507888793945 ], [ "▁やってき", -12.315532684326172 ], [ "▁アンティ", -12.315638542175293 ], [ "▁外装", -12.315657615661621 ], [ "▁通す", -12.315847396850586 ], [ "▁そのように", -12.315857887268066 ], [ "▁ソーダ", -12.31592082977295 ], [ "▁ノット", -12.316032409667969 ], [ "▁人柄", -12.316178321838379 ], [ "▁庇", -12.316201210021973 ], [ "▁ストライク", -12.316510200500488 ], [ "▁慎重", -12.316511154174805 ], [ "廉", -12.316630363464355 ], [ "▁1901", -12.31664752960205 ], [ "▁着替え", -12.316719055175781 ], [ "▁マケドニア", -12.31689453125 ], [ "▁スパイク", -12.316916465759277 ], [ "いたり", -12.316938400268555 ], [ "1927", -12.316962242126465 ], [ "▁個展", -12.317059516906738 ], [ "▁パンダ", -12.317105293273926 ], [ "▁テラ", -12.317163467407227 ], [ "gar", -12.317243576049805 ], [ "▁まく", -12.317245483398438 ], [ "▁もうけた", -12.317266464233398 ], [ "▁抜群の", -12.317527770996094 ], [ "▁忘れる", -12.317543029785156 ], [ "知らず", -12.31764030456543 ], [ "▁走った", -12.317668914794922 ], [ "▁振る舞い", -12.317825317382812 ], [ "レコード", -12.318039894104004 ], [ "▁content", -12.31808090209961 ], [ "▁構い", -12.318086624145508 ], [ "▁ばん", -12.318106651306152 ], [ "暖", -12.318367958068848 ], [ "▁アレクサ", -12.318448066711426 ], [ "▁黙って", -12.318536758422852 ], [ "▁常陸", -12.31855583190918 ], [ "lip", -12.318588256835938 ], [ "哲", -12.31865119934082 ], [ "▁Best", -12.318670272827148 ], [ "▁立ち寄り", -12.318740844726562 ], [ "▁極限", -12.318843841552734 ], [ "▁仮名", -12.318875312805176 ], [ "▁こだわって", -12.31893253326416 ], [ "レータ", -12.31911849975586 ], [ "奴", -12.319193840026855 ], [ "ルート", -12.319272994995117 ], [ "▁道中", -12.319280624389648 ], [ "閃", -12.319401741027832 ], [ "▁ボーダー", -12.319442749023438 ], [ "▁整列", -12.31945514678955 ], [ "▁茶屋", -12.319615364074707 ], [ "▁オックスフォード", -12.319665908813477 ], [ "▁公式の", -12.319708824157715 ], [ "▁ロマンス", -12.319828987121582 ], [ "エナ", -12.319929122924805 ], [ "▁目立ち", -12.320030212402344 ], [ "▁ローション", -12.320047378540039 ], [ "▁づけ", -12.320052146911621 ], [ "公職", -12.320100784301758 ], [ "▁別府", -12.32010555267334 ], [ "▁ドリル", -12.320252418518066 ], [ "形態", -12.320252418518066 ], [ "パーツ", -12.320255279541016 ], [ "▁明細", -12.320314407348633 ], [ "あき", -12.320341110229492 ], [ "葛", -12.320355415344238 ], [ "▁南口", -12.32042121887207 ], [ "▁インテ", -12.320611953735352 ], [ "▁シチュエーション", -12.320723533630371 ], [ "▁切り替える", -12.320804595947266 ], [ "▁澤", -12.320942878723145 ], [ "まかな", -12.320967674255371 ], [ "じめ", -12.320969581604004 ], [ "▁English", -12.320987701416016 ], [ "▁乗用車", -12.320987701416016 ], [ "サブ", -12.321207046508789 ], [ "ピタ", -12.321220397949219 ], [ "毎月", -12.321489334106445 ], [ "東海", -12.321549415588379 ], [ "セール", -12.321600914001465 ], [ "▁亜科", -12.32164478302002 ], [ "▁大王", -12.321694374084473 ], [ "▁貨車", -12.321915626525879 ], [ "▁‘", -12.321969985961914 ], [ "日頃", -12.322138786315918 ], [ "学長", -12.322198867797852 ], [ "▁語彙", -12.32224178314209 ], [ "▁多重", -12.322415351867676 ], [ "受賞", -12.322433471679688 ], [ "oma", -12.322491645812988 ], [ "▁救わ", -12.322495460510254 ], [ "男子", -12.322532653808594 ], [ "エント", -12.322664260864258 ], [ "タイヤ", -12.322686195373535 ], [ "YS", -12.322736740112305 ], [ "須賀", -12.32276439666748 ], [ "キャラ", -12.322806358337402 ], [ "宗教", -12.3228120803833 ], [ "▁未明", -12.32284164428711 ], [ "▁属した", -12.322956085205078 ], [ "サール", -12.323036193847656 ], [ "▁憂", -12.323042869567871 ], [ "▁ポロシャツ", -12.32324504852295 ], [ "▁feat", -12.323259353637695 ], [ "銅", -12.323261260986328 ], [ "▁扱った", -12.323271751403809 ], [ "▁カクテル", -12.323372840881348 ], [ "▁封筒", -12.323379516601562 ], [ "地震", -12.323583602905273 ], [ "ピナ", -12.32363510131836 ], [ "▁エリー", -12.323655128479004 ], [ "▁相応", -12.323662757873535 ], [ "▁ミサ", -12.323749542236328 ], [ "▁フィクション", -12.323752403259277 ], [ "コート", -12.323836326599121 ], [ "鎌倉", -12.323862075805664 ], [ "▁丸山", -12.3239107131958 ], [ "▁室長", -12.323936462402344 ], [ "▁シワ", -12.323993682861328 ], [ "▁斉藤", -12.324095726013184 ], [ "マリー", -12.324104309082031 ], [ "▁ハブ", -12.324165344238281 ], [ "煎", -12.32416820526123 ], [ "▁š", -12.324169158935547 ], [ "ui", -12.324189186096191 ], [ "ジェイ", -12.324252128601074 ], [ "ベロ", -12.324405670166016 ], [ "▁自由党", -12.324437141418457 ], [ "▁ネズミ", -12.3245267868042 ], [ "une", -12.324628829956055 ], [ "▁委", -12.324661254882812 ], [ "▁メチル", -12.324719429016113 ], [ "▁長調", -12.324746131896973 ], [ "▁挿絵", -12.324832916259766 ], [ "面積", -12.324908256530762 ], [ "んじゃ", -12.324999809265137 ], [ "▁回して", -12.325050354003906 ], [ "擦", -12.325087547302246 ], [ "▁エルフ", -12.325197219848633 ], [ "稚", -12.325221061706543 ], [ "▁下げて", -12.325268745422363 ], [ "フォル", -12.325336456298828 ], [ "▁驚いて", -12.325361251831055 ], [ "▁殺して", -12.325362205505371 ], [ "▁伝授", -12.325403213500977 ], [ "▁寧", -12.325525283813477 ], [ "▁見たり", -12.325544357299805 ], [ "▁触り", -12.325544357299805 ], [ "くれ", -12.325613975524902 ], [ "▁炒め", -12.325662612915039 ], [ "win", -12.32575798034668 ], [ "▁LDK", -12.325858116149902 ], [ "それとも", -12.325878143310547 ], [ "▁und", -12.325943946838379 ], [ "▁放課後", -12.326028823852539 ], [ "▁フィルハーモニ", -12.32616138458252 ], [ "▁不可欠", -12.326189041137695 ], [ "▁VIP", -12.32619857788086 ], [ "晶", -12.326212882995605 ], [ "▁Tour", -12.326238632202148 ], [ "▁練り", -12.326313018798828 ], [ "謝", -12.326454162597656 ], [ "コット", -12.32650375366211 ], [ "▁緩やか", -12.326542854309082 ], [ "▁北斗", -12.326543807983398 ], [ "NY", -12.326582908630371 ], [ "置き", -12.326591491699219 ], [ "▁手伝って", -12.326828002929688 ], [ "▁防ぎ", -12.326869010925293 ], [ "チェル", -12.326899528503418 ], [ "▁VERDICT", -12.326959609985352 ], [ "▁勲", -12.327018737792969 ], [ "▁竹内", -12.32707405090332 ], [ "▁メダリスト", -12.327093124389648 ], [ "▁山内", -12.327183723449707 ], [ "おん", -12.327240943908691 ], [ "▁マニラ", -12.327357292175293 ], [ "▁手書き", -12.327357292175293 ], [ "リム", -12.32741641998291 ], [ "▁下地", -12.327585220336914 ], [ "▁寛政", -12.327699661254883 ], [ "▁腫れ", -12.327713012695312 ], [ "牟", -12.32789134979248 ], [ "▁クモ", -12.328038215637207 ], [ "GU", -12.328104972839355 ], [ "IRE", -12.32819938659668 ], [ "ゲージ", -12.328210830688477 ], [ "▁red", -12.328465461730957 ], [ "▁実体", -12.328493118286133 ], [ "▁意外な", -12.328550338745117 ], [ "bb", -12.328557014465332 ], [ "▁松浦", -12.328657150268555 ], [ "▁没年", -12.32869815826416 ], [ "▁並木", -12.328713417053223 ], [ "▁ソフトウエア", -12.328849792480469 ], [ "▁委任", -12.328858375549316 ], [ "▁行ない", -12.32903003692627 ], [ "早稲田", -12.329081535339355 ], [ "▁視力", -12.329099655151367 ], [ "ban", -12.329146385192871 ], [ "▁異常な", -12.329194068908691 ], [ "▁巻き起こ", -12.329230308532715 ], [ "▁行き来", -12.329243659973145 ], [ "▁三宅", -12.329278945922852 ], [ "▁アシュ", -12.329487800598145 ], [ "▁Online", -12.32950210571289 ], [ "▁有形", -12.329508781433105 ], [ "▁秋山", -12.329618453979492 ], [ "▁ザクセン", -12.32975959777832 ], [ "▁有吉", -12.329779624938965 ], [ "▁取り組んだ", -12.32980728149414 ], [ "▁襟", -12.330024719238281 ], [ "▁異議", -12.330035209655762 ], [ "▁ロータリー", -12.330082893371582 ], [ "vis", -12.330324172973633 ], [ "bin", -12.330348014831543 ], [ "▁白山", -12.330373764038086 ], [ "▁1868", -12.330559730529785 ], [ "▁踏切", -12.330696105957031 ], [ "▁溢れて", -12.33081340789795 ], [ "▁暴れ", -12.330850601196289 ], [ "▁ビクター", -12.331096649169922 ], [ "大切な", -12.331101417541504 ], [ "ashi", -12.331106185913086 ], [ "nal", -12.33115291595459 ], [ "▁巧", -12.331207275390625 ], [ "▁向き合う", -12.331254005432129 ], [ "▁リーダーシップ", -12.331432342529297 ], [ "▁内藤", -12.33146858215332 ], [ "▁クロム", -12.331527709960938 ], [ "▁グルー", -12.33163070678711 ], [ "▁惹", -12.331639289855957 ], [ "賜", -12.33169174194336 ], [ "▁受け取って", -12.331714630126953 ], [ "▁ヘクタール", -12.33176326751709 ], [ "▁鋭い", -12.331774711608887 ], [ "▁勝って", -12.331831932067871 ], [ "▁許", -12.331838607788086 ], [ "▁マキ", -12.331857681274414 ], [ "▁カルテ", -12.331892013549805 ], [ "▁^^", -12.33198356628418 ], [ "痕", -12.33203125 ], [ "▁棲", -12.332100868225098 ], [ "▁JST", -12.332133293151855 ], [ "▁不利", -12.332134246826172 ], [ "▁Lab", -12.33217716217041 ], [ "▁スパー", -12.332273483276367 ], [ "▁遺物", -12.3323974609375 ], [ "▁ブレスレット", -12.3324556350708 ], [ "▁肩こり", -12.33256721496582 ], [ "▁1898", -12.332659721374512 ], [ "▁Group", -12.332700729370117 ], [ "▁深めて", -12.332804679870605 ], [ "▁終焉", -12.33297061920166 ], [ "▁追撃", -12.33304214477539 ], [ "▁平坦", -12.333122253417969 ], [ "綬", -12.333370208740234 ], [ "桐", -12.333420753479004 ], [ "▁一方的に", -12.333503723144531 ], [ "▁ノルマ", -12.333548545837402 ], [ "棋", -12.333738327026367 ], [ "»", -12.333800315856934 ], [ "▁中原", -12.333881378173828 ], [ "普通の", -12.333986282348633 ], [ "ノル", -12.334000587463379 ], [ "▁割に", -12.334105491638184 ], [ "▁ゴシック", -12.33425235748291 ], [ "▁杉並", -12.334325790405273 ], [ "歳", -12.334434509277344 ], [ "▁拷問", -12.334442138671875 ], [ "▁愛国", -12.334449768066406 ], [ "簡単に", -12.334503173828125 ], [ "▁市電", -12.334547996520996 ], [ "▁カッコ", -12.33458423614502 ], [ "っこう", -12.334635734558105 ], [ "1931", -12.334650039672852 ], [ "マニア", -12.334830284118652 ], [ "慶長", -12.334918975830078 ], [ "▁リュー", -12.33512020111084 ], [ "▁下痢", -12.33518123626709 ], [ "すごい", -12.33532428741455 ], [ "▁ストローク", -12.335421562194824 ], [ "▁フェザー", -12.335432052612305 ], [ "▁押し付け", -12.335477828979492 ], [ "溜", -12.33551025390625 ], [ "植物", -12.335634231567383 ], [ "▁占拠", -12.335665702819824 ], [ "▁イズ", -12.33566951751709 ], [ "▁留守", -12.335672378540039 ], [ "▁事案", -12.335709571838379 ], [ "リップ", -12.335775375366211 ], [ "旦", -12.335789680480957 ], [ "▁抗菌", -12.335840225219727 ], [ "▁4,000", -12.335907936096191 ], [ "くじ", -12.335984230041504 ], [ "▁粟", -12.336055755615234 ], [ "▁念頭", -12.336077690124512 ], [ "オープン", -12.336097717285156 ], [ "▁本郷", -12.33635425567627 ], [ "▁転勤", -12.336383819580078 ], [ "ブイ", -12.336419105529785 ], [ "▁テイスト", -12.336440086364746 ], [ "▁クレンジング", -12.336456298828125 ], [ "▁フェスタ", -12.336487770080566 ], [ "ノート", -12.336539268493652 ], [ "▁捕ま", -12.33654499053955 ], [ "UG", -12.33666706085205 ], [ "オート", -12.336771011352539 ], [ "イユ", -12.336806297302246 ], [ "▁除いた", -12.336954116821289 ], [ "宮崎", -12.337017059326172 ], [ "▁進捗", -12.337130546569824 ], [ "▁用具", -12.337242126464844 ], [ "自治", -12.337259292602539 ], [ "lk", -12.337275505065918 ], [ "フィンペシア", -12.337319374084473 ], [ "﨑", -12.337396621704102 ], [ "▁未定", -12.337601661682129 ], [ "▁きや", -12.33760929107666 ], [ "▁暗く", -12.337701797485352 ], [ "あらかじめ", -12.337725639343262 ], [ "国家", -12.337786674499512 ], [ "▁遂げ", -12.337806701660156 ], [ "▁高くて", -12.337833404541016 ], [ "▁積水ハウス", -12.337935447692871 ], [ "▁ジュリエット", -12.338069915771484 ], [ "1923", -12.338095664978027 ], [ "▁テック", -12.338190078735352 ], [ "aya", -12.33823013305664 ], [ "▁ヒューストン", -12.338237762451172 ], [ "▁テオ", -12.338249206542969 ], [ "▁モロッコ", -12.338485717773438 ], [ "▁無形", -12.33848762512207 ], [ "▁適当な", -12.338571548461914 ], [ "タイム", -12.338574409484863 ], [ "▁労力", -12.338578224182129 ], [ "▁TB", -12.338621139526367 ], [ "逃", -12.338651657104492 ], [ "キュラ", -12.338791847229004 ], [ "▁まじ", -12.338799476623535 ], [ "▁スイング", -12.338984489440918 ], [ "▁ズボン", -12.339107513427734 ], [ "ブリン", -12.339234352111816 ], [ "oid", -12.339241027832031 ], [ "▁田辺", -12.339540481567383 ], [ "あげ", -12.339542388916016 ], [ "小さい", -12.339570999145508 ], [ "▁座る", -12.339584350585938 ], [ "1924", -12.339594841003418 ], [ "▁頼って", -12.339654922485352 ], [ "▁随分", -12.33968734741211 ], [ "▁サックス", -12.339694023132324 ], [ "▁磨", -12.339728355407715 ], [ "MD", -12.339778900146484 ], [ "base", -12.33980655670166 ], [ "atsu", -12.33989143371582 ], [ "▁おもしろい", -12.339900016784668 ], [ "▁Mk", -12.339914321899414 ], [ "(_", -12.339937210083008 ], [ "▁安全で", -12.339967727661133 ], [ "▁music", -12.340017318725586 ], [ "▁消して", -12.340048789978027 ], [ "▁ドナルド", -12.340068817138672 ], [ "▁イマ", -12.340130805969238 ], [ "▁陸奥", -12.340163230895996 ], [ "▁対訳", -12.340209007263184 ], [ "erry", -12.340458869934082 ], [ "▁大師", -12.340502738952637 ], [ "▁可愛く", -12.340561866760254 ], [ "▁シュタイン", -12.340620040893555 ], [ "▁フランクフルト", -12.340630531311035 ], [ "▁拍子", -12.340903282165527 ], [ "気候", -12.340919494628906 ], [ "▁北極", -12.3410005569458 ], [ "▁ナッツ", -12.341033935546875 ], [ "▁Cre", -12.341044425964355 ], [ "ソロ", -12.341185569763184 ], [ "マニ", -12.341241836547852 ], [ "▁フィッシュ", -12.341269493103027 ], [ "▁なんとも", -12.341290473937988 ], [ "▁浮か", -12.341297149658203 ], [ "▁繋げ", -12.34135913848877 ], [ "▁たいてい", -12.341399192810059 ], [ "▁共著", -12.341550827026367 ], [ "▁享保", -12.341573715209961 ], [ "▁下した", -12.34168529510498 ], [ "両親", -12.341769218444824 ], [ "▁おかず", -12.34190559387207 ], [ "地上", -12.341913223266602 ], [ "▁JRA", -12.341915130615234 ], [ "看護", -12.341954231262207 ], [ "セキュリティ", -12.342070579528809 ], [ "ala", -12.342090606689453 ], [ "▁ヒラ", -12.342108726501465 ], [ "▁エンタープライズ", -12.34225082397461 ], [ "マク", -12.342392921447754 ], [ "ドラー", -12.342428207397461 ], [ "峡", -12.342448234558105 ], [ "▁臨む", -12.342602729797363 ], [ "▁武家", -12.342666625976562 ], [ "▁クセ", -12.34278392791748 ], [ "▁計量", -12.342796325683594 ], [ "▁ラヴ", -12.342823028564453 ], [ "▁ストーブ", -12.342887878417969 ], [ "去年", -12.342986106872559 ], [ "▁きみ", -12.343064308166504 ], [ "▁NASA", -12.343111038208008 ], [ "▁闘い", -12.343205451965332 ], [ "高速", -12.343585014343262 ], [ "▁水源", -12.343710899353027 ], [ "墨", -12.343732833862305 ], [ "▁疲れた", -12.34394645690918 ], [ "設定", -12.344024658203125 ], [ "▁志摩", -12.344192504882812 ], [ "Cookie", -12.344221115112305 ], [ "▁狩", -12.344351768493652 ], [ "▁時事", -12.344362258911133 ], [ "its", -12.344488143920898 ], [ "▁420", -12.344560623168945 ], [ "▁高まった", -12.344758033752441 ], [ "▁ジョニー", -12.34476089477539 ], [ "▁石灰", -12.344764709472656 ], [ "▁トレイン", -12.344766616821289 ], [ "▁キラ", -12.34477424621582 ], [ "▁東口", -12.344802856445312 ], [ "累", -12.34495735168457 ], [ "OCA", -12.345134735107422 ], [ "fin", -12.345147132873535 ], [ "▁ベンツ", -12.345264434814453 ], [ "▁愛犬", -12.345297813415527 ], [ "刃", -12.34536075592041 ], [ "▁何かしら", -12.345365524291992 ], [ "▁南朝", -12.34538459777832 ], [ "▁撮れ", -12.345431327819824 ], [ "▁三越", -12.345561027526855 ], [ "慰", -12.345603942871094 ], [ "ann", -12.345608711242676 ], [ "▁桃山", -12.345621109008789 ], [ "▁スタンス", -12.345622062683105 ], [ "▁ゆとり", -12.345682144165039 ], [ "▁優勢", -12.34576416015625 ], [ "▁有利な", -12.345789909362793 ], [ "▁KI", -12.345818519592285 ], [ "▁西鉄", -12.345907211303711 ], [ "糧", -12.345952987670898 ], [ "▁Par", -12.346050262451172 ], [ "▁出家", -12.346123695373535 ], [ "▁UK", -12.346142768859863 ], [ "code", -12.346263885498047 ], [ "▁スイート", -12.346354484558105 ], [ "ě", -12.346449851989746 ], [ "フォーム", -12.346467018127441 ], [ "▁メッシュ", -12.34650707244873 ], [ "▁オールド", -12.346545219421387 ], [ "▁エロい", -12.346550941467285 ], [ "▁ユネスコ", -12.346857070922852 ], [ "審査", -12.346874237060547 ], [ "OUND", -12.346915245056152 ], [ "▁名曲", -12.346979141235352 ], [ "▁フリーの", -12.346988677978516 ], [ "▁杭", -12.34702205657959 ], [ "▁ダニ", -12.347074508666992 ], [ "▁疾病", -12.347128868103027 ], [ "▁とどまった", -12.347132682800293 ], [ "▁ヒルズ", -12.347352981567383 ], [ "▁減額", -12.34747314453125 ], [ "インター", -12.347504615783691 ], [ "レック", -12.347618103027344 ], [ "巳", -12.347663879394531 ], [ "▁コロラド", -12.347672462463379 ], [ "▁出かけて", -12.34776496887207 ], [ "大分", -12.347783088684082 ], [ "▁アドバンス", -12.34781265258789 ], [ "▁オナクラ", -12.347832679748535 ], [ "デュー", -12.347886085510254 ], [ "▁ヒーリング", -12.347946166992188 ], [ "▁ジミー", -12.3480224609375 ], [ "輩", -12.348029136657715 ], [ "▁自発", -12.348062515258789 ], [ "▁アントニオ", -12.348079681396484 ], [ "▁目次", -12.348088264465332 ], [ "▁無理な", -12.34814739227295 ], [ "▁ウィキペディア", -12.34821605682373 ], [ "▁1871", -12.348217010498047 ], [ "ビデオ", -12.348237991333008 ], [ "▁蟹", -12.348484992980957 ], [ "▁引換", -12.348543167114258 ], [ "▁太守", -12.348596572875977 ], [ "▁アオ", -12.348620414733887 ], [ "▁探知", -12.348743438720703 ], [ "▁買い求め", -12.348760604858398 ], [ "▁末端", -12.348788261413574 ], [ "▁キロ", -12.348801612854004 ], [ "▁成り立つ", -12.349091529846191 ], [ "user", -12.349132537841797 ], [ "▁登壇", -12.34935188293457 ], [ "▁あれこれ", -12.349397659301758 ], [ "▁遡る", -12.349441528320312 ], [ "▁商船", -12.349626541137695 ], [ "▁エチオピア", -12.349712371826172 ], [ "▁有難う", -12.349712371826172 ], [ "仮", -12.349740028381348 ], [ "ニアン", -12.349769592285156 ], [ "▁存", -12.349812507629395 ], [ "▁レーン", -12.349818229675293 ], [ "▁大村", -12.349997520446777 ], [ "▁フルート", -12.35001277923584 ], [ "イオン", -12.35014820098877 ], [ "▁目玉", -12.350203514099121 ], [ "▁だした", -12.35024356842041 ], [ "▁誓い", -12.350397109985352 ], [ "ハロ", -12.35040283203125 ], [ "▁チョン", -12.350748062133789 ], [ "▁晒", -12.350757598876953 ], [ "▁打った", -12.350912094116211 ], [ "▁対比", -12.350926399230957 ], [ "▁気動車", -12.35093879699707 ], [ "▁あたし", -12.350992202758789 ], [ "▁光沢", -12.35127067565918 ], [ "帽", -12.351277351379395 ], [ "▁原案", -12.35129165649414 ], [ "▁和風", -12.351346969604492 ], [ "▁近親", -12.351359367370605 ], [ "▁片側", -12.351402282714844 ], [ "十八", -12.351436614990234 ], [ "▁お盆", -12.351557731628418 ], [ "▁工藤", -12.351621627807617 ], [ "▁徴", -12.351682662963867 ], [ "▁理性", -12.351798057556152 ], [ "▁出かけ", -12.351800918579102 ], [ "輸", -12.35184097290039 ], [ "秦", -12.351916313171387 ], [ "▁ファイン", -12.351978302001953 ], [ "FU", -12.3519926071167 ], [ "▁くす", -12.352171897888184 ], [ "レジ", -12.35272216796875 ], [ "▁広東", -12.35283088684082 ], [ "圓", -12.352849960327148 ], [ "▁断絶", -12.352913856506348 ], [ "ウィッチ", -12.352946281433105 ], [ "▁ものすごく", -12.3529634475708 ], [ "▁動揺", -12.352991104125977 ], [ "▁増進", -12.353035926818848 ], [ "ヘア", -12.353215217590332 ], [ "▁さっき", -12.353389739990234 ], [ "ギョ", -12.35339069366455 ], [ "ros", -12.353407859802246 ], [ "ゼーション", -12.353484153747559 ], [ "▁鎧", -12.353690147399902 ], [ "tom", -12.35374927520752 ], [ "▁バーベキュー", -12.353806495666504 ], [ "▁ブライダル", -12.353827476501465 ], [ "▁例え", -12.353913307189941 ], [ "多摩", -12.354080200195312 ], [ "▁講和", -12.354108810424805 ], [ "▁粉末", -12.354146957397461 ], [ "oom", -12.35421085357666 ], [ "▁握る", -12.354357719421387 ], [ "▁フォロワー", -12.354490280151367 ], [ "▁割と", -12.354545593261719 ], [ "▁召し", -12.354560852050781 ], [ "▁モントリオール", -12.354901313781738 ], [ "▁正当な", -12.355170249938965 ], [ "ろく", -12.355287551879883 ], [ "今では", -12.355384826660156 ], [ "▁支払って", -12.355464935302734 ], [ "伴", -12.355561256408691 ], [ "ッテル", -12.355703353881836 ], [ "▁コカ", -12.355728149414062 ], [ "▁領有", -12.35579776763916 ], [ "▁訊", -12.356009483337402 ], [ "▁ハゲ", -12.356107711791992 ], [ "ロジ", -12.356164932250977 ], [ "▁取り外し", -12.35622501373291 ], [ "仮に", -12.356228828430176 ], [ "▁Max", -12.35633659362793 ], [ "amb", -12.356350898742676 ], [ "▁無職", -12.356351852416992 ], [ "▁グッチ", -12.356374740600586 ], [ "桓", -12.35640811920166 ], [ "▁Em", -12.356525421142578 ], [ "▁対馬", -12.35654067993164 ], [ "▁鄭", -12.35661792755127 ], [ "▁ソーラー", -12.35666275024414 ], [ "▁浸水", -12.356679916381836 ], [ "▁カープ", -12.356756210327148 ], [ "▁鉛", -12.356785774230957 ], [ "▁本堂", -12.356833457946777 ], [ "▁シンセ", -12.356873512268066 ], [ "▁あたった", -12.357105255126953 ], [ "▁慈恵", -12.357111930847168 ], [ "▁陣地", -12.357179641723633 ], [ "▁既婚", -12.357213020324707 ], [ "▁却下", -12.357231140136719 ], [ "▁トウ", -12.357420921325684 ], [ "STER", -12.357421875 ], [ "▁_)", -12.357441902160645 ], [ "▁新羅", -12.357443809509277 ], [ "▁0408", -12.357550621032715 ], [ "▁判別", -12.357686996459961 ], [ "▁ホロ", -12.35776138305664 ], [ "酔", -12.357804298400879 ], [ "▁任せて", -12.357876777648926 ], [ "▁健全", -12.35795783996582 ], [ "▁大内", -12.358034133911133 ], [ "▁わき", -12.358047485351562 ], [ "▁GDP", -12.358048439025879 ], [ "▁サビ", -12.35806655883789 ], [ "▁艦船", -12.358095169067383 ], [ "デント", -12.358098030090332 ], [ "▁砲塔", -12.358128547668457 ], [ "▁理系", -12.358142852783203 ], [ "▁おはよう", -12.35833740234375 ], [ "▁高槻", -12.358475685119629 ], [ "▁エルサレム", -12.358603477478027 ], [ "▁古来", -12.358716011047363 ], [ "幼", -12.358721733093262 ], [ "▁釘", -12.358805656433105 ], [ "▁SDGs", -12.358878135681152 ], [ "▁牧野", -12.359020233154297 ], [ "▁インディーズ", -12.359134674072266 ], [ "姦", -12.359171867370605 ], [ "別の", -12.359183311462402 ], [ "▁一線", -12.359230041503906 ], [ "▁豊か", -12.359232902526855 ], [ "life", -12.359383583068848 ], [ "荒廃", -12.359469413757324 ], [ "▁多目的", -12.359524726867676 ], [ "▁1896", -12.359599113464355 ], [ "勇", -12.359697341918945 ], [ "▁匹敵", -12.35975456237793 ], [ "▁文具", -12.359827041625977 ], [ "季節", -12.360028266906738 ], [ "ガメ", -12.360140800476074 ], [ "GR", -12.360162734985352 ], [ "▁呈し", -12.360225677490234 ], [ "▁教訓", -12.360332489013672 ], [ "▁ホームズ", -12.360347747802734 ], [ "▁大敗", -12.360389709472656 ], [ "▁ナムコ", -12.3604097366333 ], [ "▁揃えて", -12.360686302185059 ], [ "▁断層", -12.360748291015625 ], [ "▁基板", -12.360808372497559 ], [ "▁各所", -12.36082649230957 ], [ "▁最期", -12.360857963562012 ], [ "▁性感", -12.36093521118164 ], [ "▁収縮", -12.360962867736816 ], [ "▁会派", -12.360995292663574 ], [ "▁シタデル", -12.361079216003418 ], [ "▁Light", -12.361109733581543 ], [ "▁エラ", -12.361164093017578 ], [ "かせ", -12.361196517944336 ], [ "▁ポテンシャル", -12.361217498779297 ], [ "▁ジル", -12.361248016357422 ], [ "▁浮かび", -12.361428260803223 ], [ "できる", -12.361495971679688 ], [ "▁おいしく", -12.361566543579102 ], [ "д", -12.3616304397583 ], [ "bar", -12.361716270446777 ], [ "▁造営", -12.361739158630371 ], [ "孤", -12.36176586151123 ], [ "▁金山", -12.361787796020508 ], [ "預", -12.361894607543945 ], [ "▁擁する", -12.361906051635742 ], [ "▁対岸", -12.361908912658691 ], [ "▁親会社", -12.362046241760254 ], [ "tech", -12.362092971801758 ], [ "下半身", -12.362464904785156 ], [ "▁著しい", -12.362492561340332 ], [ "▁送金", -12.362497329711914 ], [ "▁えり", -12.362906455993652 ], [ "まき", -12.36291790008545 ], [ "▁Gen", -12.362937927246094 ], [ "▁極力", -12.362979888916016 ], [ "▁オカ", -12.362998008728027 ], [ "ข", -12.363009452819824 ], [ "▁収蔵", -12.36313247680664 ], [ "▁1897", -12.363152503967285 ], [ "▁ポット", -12.363207817077637 ], [ "現実", -12.363404273986816 ], [ "▁連日", -12.363419532775879 ], [ "gan", -12.363494873046875 ], [ "▁ルノー", -12.363503456115723 ], [ "▁怖く", -12.363984107971191 ], [ "▁飛ば", -12.364068031311035 ], [ "南北", -12.364124298095703 ], [ "pen", -12.364127159118652 ], [ "▁pos", -12.364156723022461 ], [ "ニオ", -12.364215850830078 ], [ "▁out", -12.364249229431152 ], [ "IKE", -12.364272117614746 ], [ "麦", -12.364410400390625 ], [ "▁大丈夫だ", -12.364447593688965 ], [ "▁画期的な", -12.364470481872559 ], [ "▁鋳造", -12.36452865600586 ], [ "▁信徒", -12.364551544189453 ], [ "▁創る", -12.3645601272583 ], [ "産業", -12.36466121673584 ], [ "▁生む", -12.364672660827637 ], [ "ピット", -12.364700317382812 ], [ "▁失踪", -12.364945411682129 ], [ "▁関連付け", -12.365163803100586 ], [ "▁見直す", -12.365221977233887 ], [ "恋愛", -12.365290641784668 ], [ "1925", -12.365340232849121 ], [ "▁Her", -12.365341186523438 ], [ "tail", -12.365346908569336 ], [ "▁壊れ", -12.365407943725586 ], [ "▁Corporation", -12.365496635437012 ], [ "▁亜鉛", -12.36550521850586 ], [ "寂", -12.365525245666504 ], [ "叉", -12.36563491821289 ], [ "▁エクセル", -12.365689277648926 ], [ "クチ", -12.365768432617188 ], [ "▁さっぱり", -12.365784645080566 ], [ "▁埋", -12.365859031677246 ], [ "▁キャット", -12.365863800048828 ], [ "▁118", -12.365883827209473 ], [ "▁大小", -12.3659029006958 ], [ "▁無効に", -12.365991592407227 ], [ "ざき", -12.365996360778809 ], [ "▁1899", -12.366332054138184 ], [ "プロジェクト", -12.366486549377441 ], [ "どろ", -12.366491317749023 ], [ "▁最悪", -12.366862297058105 ], [ "▁ドラマー", -12.366899490356445 ], [ "▁ROCK", -12.3670654296875 ], [ "▁アルマ", -12.367074012756348 ], [ "▁アデ", -12.367143630981445 ], [ "▁瑞穂", -12.36732292175293 ], [ "調べ", -12.367341995239258 ], [ "戴", -12.367568016052246 ], [ "▁おとな", -12.367713928222656 ], [ "▁落ち着き", -12.367851257324219 ], [ "▁リンカーン", -12.367990493774414 ], [ "▁ナナ", -12.368429183959961 ], [ "レギュラー", -12.368444442749023 ], [ "紫", -12.368444442749023 ], [ "▁寅", -12.368449211120605 ], [ "▁傾", -12.36864948272705 ], [ "▁一斉に", -12.36866283416748 ], [ "▁フランツ", -12.368681907653809 ], [ "live", -12.368849754333496 ], [ "レベル", -12.368878364562988 ], [ "▁慣れた", -12.369125366210938 ], [ "rm", -12.36916732788086 ], [ "青森", -12.369277954101562 ], [ "▁エクササイズ", -12.369378089904785 ], [ "▁弾き", -12.369388580322266 ], [ "錬", -12.369444847106934 ], [ "▁布告", -12.369451522827148 ], [ "▁プラグ", -12.369458198547363 ], [ "ART", -12.369527816772461 ], [ "▁連立", -12.369771957397461 ], [ "Heydouga", -12.369808197021484 ], [ "▁スワ", -12.369844436645508 ], [ "▁朝日放送", -12.369932174682617 ], [ "もち", -12.36998462677002 ], [ "▁出会", -12.369997024536133 ], [ "▁ダグラス", -12.369999885559082 ], [ "▁郁", -12.370046615600586 ], [ "ถ", -12.370072364807129 ], [ "蔣", -12.370072364807129 ], [ "▁下し", -12.370118141174316 ], [ "墓所", -12.370317459106445 ], [ "プー", -12.370352745056152 ], [ "▁熱狂", -12.370410919189453 ], [ "ケア", -12.370485305786133 ], [ "▁要員", -12.370524406433105 ], [ "▁駆", -12.370619773864746 ], [ "▁叶え", -12.370674133300781 ], [ "▁ビーズ", -12.370810508728027 ], [ "▁ニュージャージー", -12.370906829833984 ], [ "▁尾崎", -12.371047973632812 ], [ "▁ノーマル", -12.371054649353027 ], [ "ミッション", -12.371077537536621 ], [ "ACT", -12.371187210083008 ], [ "ビジョン", -12.371235847473145 ], [ "▁スタメン", -12.371574401855469 ], [ "▁連鎖", -12.371636390686035 ], [ "▁ヒール", -12.371695518493652 ], [ "par", -12.371853828430176 ], [ "▁怒って", -12.372025489807129 ], [ "レンジャー", -12.372163772583008 ], [ "▁吹田", -12.372315406799316 ], [ "クロー", -12.37233829498291 ], [ "▁1870", -12.372356414794922 ], [ "侍", -12.37251091003418 ], [ "紛", -12.372557640075684 ], [ "皿", -12.37256145477295 ], [ "▁文政", -12.372576713562012 ], [ "▁執り行", -12.372577667236328 ], [ "▁リール", -12.372583389282227 ], [ "KS", -12.372640609741211 ], [ "▁was", -12.372668266296387 ], [ "▁きたり", -12.372708320617676 ], [ "▁バルコニー", -12.372716903686523 ], [ "続け", -12.372849464416504 ], [ "▁フェニックス", -12.372871398925781 ], [ "▁炭鉱", -12.373008728027344 ], [ "ago", -12.373041152954102 ], [ "lect", -12.373266220092773 ], [ "tre", -12.373359680175781 ], [ "▁民放", -12.373453140258789 ], [ "▁プレイス", -12.373490333557129 ], [ "▁スローガン", -12.373917579650879 ], [ "はる", -12.374091148376465 ], [ "▁UNI", -12.37410831451416 ], [ "▁MX", -12.374276161193848 ], [ "ジェル", -12.374320030212402 ], [ "▁付録", -12.374444007873535 ], [ "▁広まった", -12.374532699584961 ], [ "▁日比谷", -12.374670028686523 ], [ "▁相当な", -12.374680519104004 ], [ "▁そっくり", -12.37471866607666 ], [ "▁予感", -12.37474536895752 ], [ "▁催眠", -12.374829292297363 ], [ "▁part", -12.374835968017578 ], [ "▁キングダム", -12.374874114990234 ], [ "▁仔", -12.37506103515625 ], [ "▁デジモン", -12.375138282775879 ], [ "姿", -12.375173568725586 ], [ "▁頑張る", -12.375307083129883 ], [ "▁まどか", -12.375367164611816 ], [ "▁担任", -12.375412940979004 ], [ "▁戻し", -12.375459671020508 ], [ "▁GW", -12.37551212310791 ], [ "▁許して", -12.375590324401855 ], [ "ヴィッチ", -12.375596046447754 ], [ "▁やれば", -12.375636100769043 ], [ "script", -12.375662803649902 ], [ "ファイア", -12.375712394714355 ], [ "っぱい", -12.375726699829102 ], [ "▁型式", -12.375821113586426 ], [ "▁模した", -12.37592887878418 ], [ "▁沈黙", -12.375931739807129 ], [ "▁シアトル", -12.376068115234375 ], [ "▁ヒップホップ", -12.376206398010254 ], [ "ばた", -12.376255989074707 ], [ "▁東区", -12.376277923583984 ], [ "▁CAS", -12.376331329345703 ], [ "▁厚い", -12.376450538635254 ], [ "▁プラント", -12.376561164855957 ], [ "▁迅速", -12.376761436462402 ], [ "▁ベラ", -12.376803398132324 ], [ "IME", -12.376852035522461 ], [ "ニール", -12.376914978027344 ], [ "▁FS", -12.377008438110352 ], [ "▁時空", -12.377132415771484 ], [ "▁快楽", -12.377178192138672 ], [ "▁採集", -12.377609252929688 ], [ "rc", -12.377677917480469 ], [ "▁途絶え", -12.377745628356934 ], [ "▁教習", -12.377787590026855 ], [ "▁こだわった", -12.377800941467285 ], [ "▁まき", -12.377866744995117 ], [ "▁取り揃えて", -12.377880096435547 ], [ "真面目", -12.377881050109863 ], [ "▁リーフ", -12.378016471862793 ], [ "rp", -12.378077507019043 ], [ "▁ジョセフ", -12.3782377243042 ], [ "▁了解", -12.378305435180664 ], [ "▁許す", -12.378535270690918 ], [ "▁協賛", -12.378599166870117 ], [ "トラー", -12.378697395324707 ], [ "▁吉祥寺", -12.378866195678711 ], [ "▁遷移", -12.378872871398926 ], [ "高齢", -12.379066467285156 ], [ "すい", -12.379095077514648 ], [ "▁壊れて", -12.379131317138672 ], [ "▁マンハッタン", -12.379146575927734 ], [ "▁AG", -12.379232406616211 ], [ "▁忠実", -12.379426956176758 ], [ "▁紡", -12.379539489746094 ], [ "▁公明党", -12.379568099975586 ], [ "▁追記", -12.37961196899414 ], [ "▁一夜", -12.379626274108887 ], [ "▁松岡", -12.379694938659668 ], [ "▁中々", -12.379705429077148 ], [ "▁平田", -12.37975788116455 ], [ "かして", -12.379800796508789 ], [ "▁少人数", -12.37985610961914 ], [ "保険", -12.379857063293457 ], [ "▁post", -12.38007640838623 ], [ "ッツァ", -12.380125045776367 ], [ "▁Design", -12.380172729492188 ], [ "▁次長", -12.380210876464844 ], [ "▁揃い", -12.38027286529541 ], [ "▁ART", -12.380291938781738 ], [ "KI", -12.380294799804688 ], [ "▁生駒", -12.38033390045166 ], [ "▁やめた", -12.380374908447266 ], [ "中古", -12.380385398864746 ], [ "ika", -12.380391120910645 ], [ "▁リクルート", -12.380410194396973 ], [ "競", -12.380417823791504 ], [ "▁ARP", -12.380459785461426 ], [ "▁ポピュラー", -12.380550384521484 ], [ "ほぼ", -12.380594253540039 ], [ "▁異例の", -12.380636215209961 ], [ "aj", -12.380645751953125 ], [ "デンス", -12.380819320678711 ], [ "▁凡", -12.380839347839355 ], [ "カバー", -12.380846977233887 ], [ "ura", -12.380895614624023 ], [ "▁ICT", -12.380914688110352 ], [ "▁280", -12.381092071533203 ], [ "▁大友", -12.381098747253418 ], [ "▁かわり", -12.381143569946289 ], [ "▁縁起", -12.38117504119873 ], [ "▁ルカ", -12.38122272491455 ], [ "▁立花", -12.381224632263184 ], [ "會", -12.38125228881836 ], [ "▁凝縮", -12.38126277923584 ], [ "▁焼く", -12.381375312805176 ], [ "作者", -12.381380081176758 ], [ "ロボ", -12.381393432617188 ], [ "▁転居", -12.38144302368164 ], [ "国勢", -12.381479263305664 ], [ "▁履いて", -12.381494522094727 ], [ "菱", -12.38155460357666 ], [ "▁うら", -12.38155746459961 ], [ "▁面した", -12.381573677062988 ], [ "▁パイオニア", -12.381674766540527 ], [ "▁OVA", -12.3817138671875 ], [ "▁州都", -12.381782531738281 ], [ "▁竜王", -12.381903648376465 ], [ "REA", -12.381916046142578 ], [ "▁常設", -12.382049560546875 ], [ "▁サムソナイト", -12.382096290588379 ], [ "サンシャイン", -12.382102012634277 ], [ "▁魚介", -12.382147789001465 ], [ "▁ナース", -12.38219165802002 ], [ "▁潜入", -12.382265090942383 ], [ "▁鳥羽", -12.382423400878906 ], [ "▁借", -12.38244342803955 ], [ "▁デトロイト", -12.382518768310547 ], [ "▁頼る", -12.382540702819824 ], [ "寸", -12.382561683654785 ], [ "赤ちゃん", -12.382580757141113 ], [ "▁key", -12.382591247558594 ], [ "ランキング", -12.382628440856934 ], [ "▁つもりです", -12.382695198059082 ], [ "▁サイコ", -12.382776260375977 ], [ "▁刑法", -12.382881164550781 ], [ "▁レガ", -12.382895469665527 ], [ "GH", -12.383003234863281 ], [ "▁有利に", -12.383095741271973 ], [ "ぐち", -12.383326530456543 ], [ "▁開口", -12.383381843566895 ], [ "▁スターズ", -12.383386611938477 ], [ "▁タケ", -12.383416175842285 ], [ "別名", -12.383440971374512 ], [ "с", -12.383502960205078 ], [ "▁おいし", -12.383623123168945 ], [ "わか", -12.383639335632324 ], [ "桃", -12.383657455444336 ], [ "De", -12.383689880371094 ], [ "▁細工", -12.383766174316406 ], [ "▁祭典", -12.38377857208252 ], [ "▁157", -12.383872032165527 ], [ "▁DB", -12.38388442993164 ], [ "▁覆う", -12.383916854858398 ], [ "▁五郎", -12.383943557739258 ], [ "テイン", -12.383990287780762 ], [ "▁播磨", -12.38406753540039 ], [ "ful", -12.384167671203613 ], [ "▁喜多", -12.38436508178711 ], [ "▁inc", -12.384387016296387 ], [ "▁放ち", -12.3848876953125 ], [ "ゲート", -12.384960174560547 ], [ "▁許し", -12.384970664978027 ], [ "▁幽霊", -12.385072708129883 ], [ "▁推計", -12.385075569152832 ], [ "十六", -12.385144233703613 ], [ "▁登る", -12.385223388671875 ], [ "▁Post", -12.385232925415039 ], [ "▁問屋", -12.385359764099121 ], [ "▁黒色", -12.385416984558105 ], [ "No", -12.385534286499023 ], [ "VO", -12.385558128356934 ], [ "▁佐渡", -12.385574340820312 ], [ "桂", -12.385658264160156 ], [ "▁過ごせ", -12.385664939880371 ], [ "▁外伝", -12.38576602935791 ], [ "TL", -12.3858003616333 ], [ "▁突然の", -12.385805130004883 ], [ "ッハ", -12.385844230651855 ], [ "▁del", -12.38591480255127 ], [ "ああ", -12.385969161987305 ], [ "▁反して", -12.385981559753418 ], [ "▁ユン", -12.38603401184082 ], [ "ヘッド", -12.386226654052734 ], [ "▁侯爵", -12.386333465576172 ], [ "▁車輌", -12.386478424072266 ], [ "▁ちん", -12.386637687683105 ], [ "▁目論", -12.386648178100586 ], [ "▁CAM", -12.386650085449219 ], [ "畜", -12.386825561523438 ], [ "苦笑", -12.386961936950684 ], [ "ピカ", -12.387030601501465 ], [ "▁ファンデーション", -12.387031555175781 ], [ "▁ブロードウェイ", -12.38719367980957 ], [ "▁ゴースト", -12.387356758117676 ], [ "ANCE", -12.38755989074707 ], [ "▁退け", -12.38756275177002 ], [ "▁買い得", -12.387669563293457 ], [ "顕微", -12.387773513793945 ], [ "▁返さ", -12.387825012207031 ], [ "▁フランシス", -12.387853622436523 ], [ "▁Sony", -12.388154983520508 ], [ "ature", -12.388198852539062 ], [ "先ほど", -12.388293266296387 ], [ "タマ", -12.388306617736816 ], [ "▁結核", -12.388518333435059 ], [ "▁シノ", -12.388633728027344 ], [ "常に", -12.38866901397705 ], [ "▁斡旋", -12.388871192932129 ], [ "▁組立", -12.388886451721191 ], [ "▁転売", -12.388888359069824 ], [ "▁物品", -12.389062881469727 ], [ "▁インディアナ", -12.389171600341797 ], [ "▁豊臣", -12.389371871948242 ], [ "ations", -12.389395713806152 ], [ "▁MD", -12.389433860778809 ], [ "▁独特な", -12.389437675476074 ], [ "▁フェロー", -12.389721870422363 ], [ "▁シンプルで", -12.389863967895508 ], [ "ストレス", -12.389900207519531 ], [ "ead", -12.390003204345703 ], [ "BF", -12.390030860900879 ], [ "クィ", -12.390031814575195 ], [ "▁ラーニング", -12.390107154846191 ], [ "▁明らかで", -12.39037036895752 ], [ "怪", -12.390495300292969 ], [ "特技", -12.390572547912598 ], [ "▁サマ", -12.390643119812012 ], [ "▁干し", -12.390727996826172 ], [ "▁観覧", -12.390851974487305 ], [ "▁コスチューム", -12.39085578918457 ], [ "▁話せる", -12.39085578918457 ], [ "▁ライアン", -12.390924453735352 ], [ "▁財源", -12.390968322753906 ], [ "ソフト", -12.391080856323242 ], [ "▁繊細な", -12.391128540039062 ], [ "▁ピュア", -12.391196250915527 ], [ "▁起工", -12.391400337219238 ], [ "▁ドットコム", -12.391449928283691 ], [ "自ら", -12.3915433883667 ], [ "設立", -12.391563415527344 ], [ "▁不安定な", -12.391685485839844 ], [ "檀", -12.391707420349121 ], [ "▁あろう", -12.391716957092285 ], [ "そこそこ", -12.391801834106445 ], [ "▁アーネスト", -12.391875267028809 ], [ "▁名乗った", -12.39199447631836 ], [ "▁左派", -12.392005920410156 ], [ "▁じっと", -12.392048835754395 ], [ "▁遷", -12.392068862915039 ], [ "▁如何", -12.392072677612305 ], [ "▁つもりで", -12.39215087890625 ], [ "▁浴びる", -12.392178535461426 ], [ "▁咳", -12.392395973205566 ], [ "マーン", -12.392411231994629 ], [ "顕", -12.3925142288208 ], [ "world", -12.392560005187988 ], [ "▁カートリッジ", -12.392715454101562 ], [ "▁ネクタイ", -12.392844200134277 ], [ "▁育って", -12.39316177368164 ], [ "ADE", -12.393280029296875 ], [ "リスク", -12.393391609191895 ], [ "▁玉川", -12.393423080444336 ], [ "▁一橋", -12.39342975616455 ], [ "▁QR", -12.393479347229004 ], [ "▁暗黒", -12.393494606018066 ], [ "▁稀に", -12.393513679504395 ], [ "▁対外", -12.393516540527344 ], [ "▁飛騨", -12.393556594848633 ], [ "▁270", -12.393597602844238 ], [ "▁みず", -12.393624305725098 ], [ "▁くせ", -12.39362621307373 ], [ "▁草津", -12.393662452697754 ], [ "▁救命", -12.393763542175293 ], [ "lat", -12.393811225891113 ], [ "▁コンセント", -12.39400577545166 ], [ "▁かんたん", -12.394020080566406 ], [ "▁売り場", -12.39405345916748 ], [ "▁リオデジャネイロ", -12.394256591796875 ], [ "▁ペダル", -12.394286155700684 ], [ "ition", -12.394338607788086 ], [ "▁あしら", -12.394371032714844 ], [ "▁ほっと", -12.394449234008789 ], [ "トリス", -12.394574165344238 ], [ "▁河北", -12.394634246826172 ], [ "ずっと", -12.39464282989502 ], [ "▁急な", -12.394659042358398 ], [ "ology", -12.394659996032715 ], [ "▁裾", -12.394726753234863 ], [ "▁たまご", -12.394776344299316 ], [ "▁不明だ", -12.394803047180176 ], [ "▁Act", -12.39495849609375 ], [ "ーっと", -12.395095825195312 ], [ "▁ゲン", -12.395145416259766 ], [ "ャー", -12.395268440246582 ], [ "▁ウルフ", -12.395337104797363 ], [ "▁杖", -12.395354270935059 ], [ "▁裏面", -12.395403861999512 ], [ "グリーン", -12.395411491394043 ], [ "▁織物", -12.395464897155762 ], [ "毎回", -12.395540237426758 ], [ "組み", -12.395565032958984 ], [ "▁残念です", -12.395570755004883 ], [ "業務", -12.395589828491211 ], [ "▁ヒュ", -12.395617485046387 ], [ "▁墳", -12.395685195922852 ], [ "▁ルブタン", -12.395691871643066 ], [ "▁牛肉", -12.395695686340332 ], [ "▁アイスランド", -12.395719528198242 ], [ "イェ", -12.395912170410156 ], [ "▁Mc", -12.396031379699707 ], [ "1918", -12.396120071411133 ], [ "▁期日", -12.396161079406738 ], [ "スロー", -12.396276473999023 ], [ "▁写像", -12.396339416503906 ], [ "▁AK", -12.396366119384766 ], [ "▁ばっかり", -12.396404266357422 ], [ "▁fals", -12.396462440490723 ], [ "▁先着", -12.396470069885254 ], [ "▁ポリエステル", -12.396547317504883 ], [ "▁不備", -12.396586418151855 ], [ "▁伏せ", -12.396651268005371 ], [ "▁表参道", -12.396690368652344 ], [ "▁迎撃", -12.396690368652344 ], [ "▁エピ", -12.39669418334961 ], [ "▁抱か", -12.396979331970215 ], [ "▁勝者", -12.39702033996582 ], [ "めん", -12.397360801696777 ], [ "▁サント", -12.397422790527344 ], [ "▁タイト", -12.39749526977539 ], [ "▁任官", -12.397497177124023 ], [ "ヒロ", -12.39755916595459 ], [ "▁婚活", -12.397754669189453 ], [ "旦那", -12.397846221923828 ], [ "慮", -12.397991180419922 ], [ "▁女学校", -12.398037910461426 ], [ "SK", -12.39805793762207 ], [ "▁貧乏", -12.398118019104004 ], [ "▁極東", -12.39834213256836 ], [ "▁波動", -12.398383140563965 ], [ "▁能登", -12.3984956741333 ], [ "▁探求", -12.39856243133545 ], [ "▁共鳴", -12.39858627319336 ], [ "▁膣", -12.398618698120117 ], [ "▁ヶ国", -12.398640632629395 ], [ "げた", -12.398860931396484 ], [ "▁ANA", -12.399004936218262 ], [ "▁できたり", -12.3990478515625 ], [ "▁赤外線", -12.39911937713623 ], [ "▁Tw", -12.39923095703125 ], [ "▁決心", -12.399299621582031 ], [ "篠", -12.399374008178711 ], [ "▁簡素", -12.399405479431152 ], [ "▁少子", -12.399676322937012 ], [ "▁中年", -12.39970588684082 ], [ "周囲", -12.399727821350098 ], [ "▁喜劇", -12.399739265441895 ], [ "▁ジーンズ", -12.399748802185059 ], [ "殖", -12.399944305419922 ], [ "作曲", -12.400110244750977 ], [ "ツク", -12.400113105773926 ], [ "ý", -12.400121688842773 ], [ "前年", -12.400136947631836 ], [ "▁プロト", -12.400165557861328 ], [ "▁サスペンス", -12.400264739990234 ], [ "ゝ", -12.400264739990234 ], [ "磯", -12.400426864624023 ], [ "ッペ", -12.4004545211792 ], [ "▁Chan", -12.400465965270996 ], [ "▁ラスベガス", -12.400694847106934 ], [ "▁込めた", -12.400718688964844 ], [ "MT", -12.400853157043457 ], [ "▁固体", -12.400882720947266 ], [ "▁射殺", -12.400903701782227 ], [ "▁サボ", -12.400914192199707 ], [ "▁移した", -12.400967597961426 ], [ "▁省令", -12.401341438293457 ], [ "▁貰える", -12.40134334564209 ], [ "tions", -12.401424407958984 ], [ "ウラ", -12.401433944702148 ], [ "▁往来", -12.401555061340332 ], [ "▁FL", -12.40156078338623 ], [ "▁いまだに", -12.401567459106445 ], [ "▁最安", -12.401787757873535 ], [ "▁フン", -12.401825904846191 ], [ "午", -12.401958465576172 ], [ "▁所沢", -12.402073860168457 ], [ "▁くれたら", -12.402077674865723 ], [ "▁マイアミ", -12.402416229248047 ], [ "▁算定", -12.40241813659668 ], [ "▁ジェンダー", -12.4024658203125 ], [ "▁ソープランド", -12.402497291564941 ], [ "▁定かで", -12.40256118774414 ], [ "▁村山", -12.402673721313477 ], [ "▁兼ねた", -12.402708053588867 ], [ "▁ウォーカー", -12.402718544006348 ], [ "ナント", -12.402728080749512 ], [ "▁粘土", -12.40274429321289 ], [ "▁av", -12.402746200561523 ], [ "▁ジョーダン", -12.402790069580078 ], [ "祖父", -12.402798652648926 ], [ "▁ギャラ", -12.402854919433594 ], [ "開業", -12.40286922454834 ], [ "▁どれほど", -12.403008460998535 ], [ "▁不信", -12.403121948242188 ], [ "▁生年月日", -12.403133392333984 ], [ "▁題して", -12.403135299682617 ], [ "▁1100", -12.403267860412598 ], [ "▁テイ", -12.403282165527344 ], [ "▁品目", -12.403326034545898 ], [ "グラス", -12.403390884399414 ], [ "▁デヴィッド", -12.403564453125 ], [ "▁エフ", -12.403600692749023 ], [ "▁ビア", -12.403613090515137 ], [ "▁土俵", -12.403639793395996 ], [ "▁西尾", -12.403693199157715 ], [ "鵬", -12.403708457946777 ], [ "▁続出", -12.403743743896484 ], [ "▁駐留", -12.403899192810059 ], [ "トーク", -12.40396785736084 ], [ "ヨシ", -12.40396785736084 ], [ "けど", -12.403972625732422 ], [ "通信", -12.404043197631836 ], [ "▁フロリネ", -12.404109954833984 ], [ "▁濁", -12.404223442077637 ], [ "▁莫大な", -12.40428352355957 ], [ "后", -12.404379844665527 ], [ "1919", -12.404460906982422 ], [ "▁ヴィル", -12.40451431274414 ], [ "▁ローゼン", -12.40474796295166 ], [ "ジロ", -12.404865264892578 ], [ "▁マルタ", -12.404874801635742 ], [ "▁尽くす", -12.404882431030273 ], [ "▁セクター", -12.404886245727539 ], [ "ital", -12.404916763305664 ], [ "▁はるか", -12.404994010925293 ], [ "駐車", -12.405088424682617 ], [ "突然", -12.405094146728516 ], [ "ida", -12.405190467834473 ], [ "▁湾岸", -12.405192375183105 ], [ "▁Pol", -12.405197143554688 ], [ "▁源流", -12.405287742614746 ], [ "▁シャフト", -12.40533447265625 ], [ "▁何ら", -12.405352592468262 ], [ "▁旋回", -12.405434608459473 ], [ "▁バッハ", -12.40544605255127 ], [ "詰", -12.405475616455078 ], [ "▁コマーシャル", -12.405722618103027 ], [ "▁コーディネーター", -12.406010627746582 ], [ "叡", -12.406010627746582 ], [ "▁知性", -12.406122207641602 ], [ "▁途端", -12.406155586242676 ], [ "▁転身", -12.406363487243652 ], [ "▁砲弾", -12.406411170959473 ], [ "т", -12.406440734863281 ], [ "▁王家", -12.406635284423828 ], [ "ポロ", -12.406647682189941 ], [ "▁そのほか", -12.40667724609375 ], [ "▁鉄筋", -12.406702995300293 ], [ "▁欲し", -12.406867027282715 ], [ "▁振替", -12.40692138671875 ], [ "▁訴えて", -12.406975746154785 ], [ "▁│", -12.40700626373291 ], [ "▁尽くして", -12.40714168548584 ], [ "ぢ", -12.407163619995117 ], [ "▁タク", -12.407365798950195 ], [ "▁富裕", -12.407493591308594 ], [ "▁売春", -12.407508850097656 ], [ "▁LG", -12.407780647277832 ], [ "▁中でも", -12.407811164855957 ], [ "ビール", -12.407917976379395 ], [ "▁代々木", -12.407933235168457 ], [ "ソール", -12.407981872558594 ], [ "ドゥル", -12.407995223999023 ], [ "ピラ", -12.408011436462402 ], [ "▁レンジャー", -12.408238410949707 ], [ "必要な", -12.40828800201416 ], [ "鉢", -12.408404350280762 ], [ "▁驚異", -12.40848445892334 ], [ "▁プロテイン", -12.408492088317871 ], [ "▁偽装", -12.408573150634766 ], [ "慧", -12.408751487731934 ], [ "潤", -12.408772468566895 ], [ "卓", -12.408868789672852 ], [ "行き", -12.408872604370117 ], [ "eve", -12.408940315246582 ], [ "コーン", -12.409070014953613 ], [ "LOG", -12.409269332885742 ], [ "▁盲", -12.409296035766602 ], [ "ks", -12.409348487854004 ], [ "▁証書", -12.40947437286377 ], [ "▁フランソワ", -12.409476280212402 ], [ "臨", -12.40948486328125 ], [ "▁何となく", -12.409517288208008 ], [ "▁パーキング", -12.409566879272461 ], [ "▁握手", -12.409619331359863 ], [ "▁増税", -12.409626007080078 ], [ "▁電信", -12.409696578979492 ], [ "毎週", -12.409720420837402 ], [ "CT", -12.409743309020996 ], [ "▁伝送", -12.409862518310547 ], [ "▁シラ", -12.410107612609863 ], [ "▁ISBN", -12.410197257995605 ], [ "▁戦績", -12.410322189331055 ], [ "▁駅名", -12.4103364944458 ], [ "▁デリバリー", -12.410486221313477 ], [ "▁エッ", -12.410577774047852 ], [ "▁スン", -12.41073989868164 ], [ "▁髭", -12.410770416259766 ], [ "干し", -12.410816192626953 ], [ "ッピング", -12.41086196899414 ], [ "塊", -12.410882949829102 ], [ "ミラ", -12.410888671875 ], [ "▁バラバラ", -12.41099739074707 ], [ "▁サンディエゴ", -12.411065101623535 ], [ "▁勝率", -12.411124229431152 ], [ "▁ヨーグルト", -12.411210060119629 ], [ "▁ポロ", -12.411355018615723 ], [ "▁コパ", -12.411372184753418 ], [ "▁リミックス", -12.411499977111816 ], [ "▁崇拝", -12.411507606506348 ], [ "ena", -12.411543846130371 ], [ "▁土日祝", -12.411660194396973 ], [ "▁取り壊", -12.411690711975098 ], [ "▁樽", -12.411844253540039 ], [ "▁古川", -12.411904335021973 ], [ "潜", -12.412002563476562 ], [ "良く", -12.41219711303711 ], [ "▁授乳", -12.412224769592285 ], [ "▁塩化", -12.41222858428955 ], [ "OME", -12.412413597106934 ], [ "▁セリ", -12.4124174118042 ], [ "▁ムード", -12.412564277648926 ], [ "▁山麓", -12.412618637084961 ], [ "▁Media", -12.412681579589844 ], [ "▁召集", -12.41269588470459 ], [ "colspa", -12.412779808044434 ], [ "嫁", -12.413082122802734 ], [ "▁試みる", -12.413239479064941 ], [ "蔭", -12.413239479064941 ], [ "▁メドレー", -12.413240432739258 ], [ "▁ヤー", -12.413313865661621 ], [ "▁ゴッド", -12.413458824157715 ], [ "坐", -12.413529396057129 ], [ "▁色味", -12.413596153259277 ], [ "080", -12.413631439208984 ], [ "▁見極め", -12.413718223571777 ], [ "bc", -12.41386890411377 ], [ "ネットワーク", -12.414017677307129 ], [ "▁用法", -12.414057731628418 ], [ "困", -12.41407585144043 ], [ "少なくとも", -12.414095878601074 ], [ "▁社交", -12.414183616638184 ], [ "MR", -12.414201736450195 ], [ "▁清浄", -12.414227485656738 ], [ "テオ", -12.414244651794434 ], [ "▁広め", -12.414275169372559 ], [ "致", -12.414295196533203 ], [ "▁魚類", -12.414633750915527 ], [ "▁プラハ", -12.414706230163574 ], [ "▁まくって", -12.414809226989746 ], [ "▁SALE", -12.414923667907715 ], [ "▁ウイスキー", -12.415162086486816 ], [ "▁必", -12.415251731872559 ], [ "▁改めた", -12.415260314941406 ], [ "▁ノック", -12.415266990661621 ], [ "▁北端", -12.41543960571289 ], [ "▁弾道", -12.41554069519043 ], [ "▁コミュ", -12.415550231933594 ], [ "ted", -12.415745735168457 ], [ "cal", -12.415919303894043 ], [ "ハード", -12.415996551513672 ], [ "▁ヴォーカル", -12.416047096252441 ], [ "▁呪い", -12.416084289550781 ], [ "▁Uni", -12.416096687316895 ], [ "▁起こら", -12.416146278381348 ], [ "ハンド", -12.416214942932129 ], [ "▁釈迦", -12.416291236877441 ], [ "▁振付", -12.416380882263184 ], [ "▁慕", -12.416419982910156 ], [ "▁遊園地", -12.416437149047852 ], [ "その頃", -12.416536331176758 ], [ "▁国宝", -12.416556358337402 ], [ "▁開会", -12.416613578796387 ], [ "松本", -12.416631698608398 ], [ "▁Trans", -12.416662216186523 ], [ "umi", -12.416753768920898 ], [ "胡", -12.41688346862793 ], [ "▁尽くした", -12.417048454284668 ], [ "▁渡した", -12.41706371307373 ], [ "▁ブラウス", -12.417140007019043 ], [ "湾", -12.417202949523926 ], [ "▁San", -12.417226791381836 ], [ "サワ", -12.417304992675781 ], [ "諱", -12.41731071472168 ], [ "凄", -12.417362213134766 ], [ "▁大垣", -12.417549133300781 ], [ "▁太平", -12.417556762695312 ], [ "▁まっすぐ", -12.417613983154297 ], [ "▁ダイアリー", -12.41765308380127 ], [ "▁シチリア", -12.41774845123291 ], [ "▁大砲", -12.417763710021973 ], [ "▁吹替", -12.417764663696289 ], [ "▁フレンド", -12.417922973632812 ], [ "▁トランク", -12.417999267578125 ], [ "▁嗜好", -12.418039321899414 ], [ "ピル", -12.418167114257812 ], [ "▁握って", -12.418187141418457 ], [ "▁脱落", -12.418204307556152 ], [ "興味", -12.418334007263184 ], [ "ブリア", -12.418353080749512 ], [ "▁ウイン", -12.418360710144043 ], [ "▁台本", -12.41845989227295 ], [ "▁クソ", -12.418501853942871 ], [ "▁捕まえ", -12.418519973754883 ], [ "▁水質", -12.418587684631348 ], [ "▁ZERO", -12.41868782043457 ], [ "▁今川", -12.418720245361328 ], [ "▁Grand", -12.418747901916504 ], [ "▁万能", -12.418793678283691 ], [ "▁暖かく", -12.418850898742676 ], [ "オランダ", -12.418864250183105 ], [ "▁ムーア", -12.418924331665039 ], [ "表示", -12.419048309326172 ], [ "▁専修", -12.419093132019043 ], [ "▁十字架", -12.419235229492188 ], [ "▁写し", -12.419244766235352 ], [ "▁ベータ", -12.419270515441895 ], [ "ソス", -12.419368743896484 ], [ "▁ルミ", -12.419594764709473 ], [ "▁キューブ", -12.419600486755371 ], [ "▁少尉", -12.419806480407715 ], [ "是", -12.419812202453613 ], [ "▁バース", -12.419909477233887 ], [ "ジュラ", -12.419925689697266 ], [ "アカ", -12.419971466064453 ], [ "▁ガガ", -12.420015335083008 ], [ "▁大神", -12.420527458190918 ], [ "▁カバン", -12.420560836791992 ], [ "▁矢野", -12.420611381530762 ], [ "摂", -12.420705795288086 ], [ "ush", -12.420849800109863 ], [ "ョー", -12.420857429504395 ], [ "asa", -12.420873641967773 ], [ "淀", -12.421024322509766 ], [ "山形", -12.421058654785156 ], [ "ative", -12.421146392822266 ], [ "ホワイト", -12.421148300170898 ], [ "▁恥ずかし", -12.421330451965332 ], [ "▁新橋", -12.42136001586914 ], [ "▁ハチ", -12.421379089355469 ], [ "▁教わ", -12.421381950378418 ], [ "▁内祝い", -12.421399116516113 ], [ "▁バート", -12.421418190002441 ], [ "罰", -12.42142391204834 ], [ "▁スピンオフ", -12.421425819396973 ], [ "▁ブルゾン", -12.421510696411133 ], [ "▁出番", -12.421512603759766 ], [ "天然", -12.421635627746582 ], [ "▁145", -12.421765327453613 ], [ "紹", -12.421804428100586 ], [ "▁コスモ", -12.421844482421875 ], [ "ボロ", -12.42190933227539 ], [ "▁母国", -12.421961784362793 ], [ "企画", -12.42203426361084 ], [ "▁協働", -12.422140121459961 ], [ "スペル", -12.422201156616211 ], [ "▁手足", -12.42221736907959 ], [ "▁酵母", -12.422276496887207 ], [ "▁あんた", -12.422350883483887 ], [ "周り", -12.422451972961426 ], [ "▁四十", -12.422471046447754 ], [ "プラン", -12.422552108764648 ], [ "▁凱旋", -12.42257022857666 ], [ "▁安置", -12.422937393188477 ], [ "乾", -12.422940254211426 ], [ "▁前向きに", -12.423009872436523 ], [ "▁排泄", -12.423009872436523 ], [ "▁極端な", -12.423155784606934 ], [ "▁若き", -12.423254013061523 ], [ "ノイド", -12.423320770263672 ], [ "▁仮設", -12.423373222351074 ], [ "▁有田", -12.423519134521484 ], [ "▁外さ", -12.4235258102417 ], [ "▁平塚", -12.423601150512695 ], [ "▁メラ", -12.423620223999023 ], [ "▁間取り", -12.423673629760742 ], [ "▁及んだ", -12.423768997192383 ], [ "書籍", -12.423868179321289 ], [ "母親", -12.42392349243164 ], [ "▁蹴り", -12.423962593078613 ], [ "▁Download", -12.424036026000977 ], [ "▁報復", -12.42422103881836 ], [ "コンピュータ", -12.424251556396484 ], [ "▁江南", -12.424311637878418 ], [ "▁May", -12.424359321594238 ], [ "▁MU", -12.42440128326416 ], [ "▁肉棒", -12.424402236938477 ], [ "▁恵み", -12.424430847167969 ], [ "▁詰めて", -12.42453384399414 ], [ "▁ルルーシュ", -12.424622535705566 ], [ "▁Du", -12.424640655517578 ], [ "ピック", -12.424748420715332 ], [ "▁産後", -12.424785614013672 ], [ "▁プライド", -12.42506217956543 ], [ "▁クロック", -12.425067901611328 ], [ "▁ss", -12.425349235534668 ], [ "▁譲り", -12.425515174865723 ], [ "ICO", -12.4255952835083 ], [ "▁密接", -12.42559814453125 ], [ "▁しょうがっこう", -12.425821304321289 ], [ "▁商会", -12.425993919372559 ], [ "誕", -12.426131248474121 ], [ "▁原画", -12.4263916015625 ], [ "▁グア", -12.42654037475586 ], [ "▁音量", -12.426544189453125 ], [ "まるで", -12.42656421661377 ], [ "▁デラックス", -12.426613807678223 ], [ "▁フロンティア", -12.426679611206055 ], [ "▁断面", -12.426705360412598 ], [ "▁白河", -12.426787376403809 ], [ "1926", -12.426912307739258 ], [ "▁カンザス", -12.426973342895508 ], [ "▁ついつい", -12.426992416381836 ], [ "▁クリー", -12.427011489868164 ], [ "▁北川", -12.427091598510742 ], [ "▁精通", -12.427133560180664 ], [ "▁目立った", -12.427225112915039 ], [ "OCK", -12.427265167236328 ], [ "▁ひまわり", -12.427268028259277 ], [ "▁Of", -12.427377700805664 ], [ "ipp", -12.427390098571777 ], [ "▁144", -12.427441596984863 ], [ "▁ヴォー", -12.427530288696289 ], [ "tar", -12.427617073059082 ], [ "▁アパ", -12.427637100219727 ], [ "▁デュエル", -12.427756309509277 ], [ "フォース", -12.427837371826172 ], [ "▁銃撃", -12.427838325500488 ], [ "▁塩基", -12.427876472473145 ], [ "▁明白", -12.427961349487305 ], [ "▁Safari", -12.428004264831543 ], [ "▁イケ", -12.428182601928711 ], [ "エク", -12.428230285644531 ], [ "▁〇〇", -12.428295135498047 ], [ "▁渦", -12.428709030151367 ], [ "パレ", -12.428723335266113 ], [ "dia", -12.42890453338623 ], [ "▁白髪", -12.428985595703125 ], [ "▁女児", -12.429024696350098 ], [ "▁アトピー", -12.429073333740234 ], [ "押", -12.429153442382812 ], [ "▁容認", -12.429200172424316 ], [ "▁醸し", -12.429211616516113 ], [ "KYO", -12.42933177947998 ], [ "▁コーチング", -12.42935562133789 ], [ "▁進入", -12.42943000793457 ], [ "▁爆乳", -12.42953109741211 ], [ "自転車", -12.429737091064453 ], [ "▁公使", -12.42982006072998 ], [ "生態", -12.429827690124512 ], [ "パック", -12.429888725280762 ], [ "▁bu", -12.43004322052002 ], [ "hot", -12.430133819580078 ], [ "▁催し", -12.430146217346191 ], [ "▁1880", -12.430156707763672 ], [ "構成", -12.430191040039062 ], [ "▁侵", -12.430193901062012 ], [ "なかった", -12.43024730682373 ], [ "▁スクロール", -12.430264472961426 ], [ "▁素子", -12.430305480957031 ], [ "令和", -12.430365562438965 ], [ "▁取り組", -12.430469512939453 ], [ "▁破れ", -12.430620193481445 ], [ "▁糞", -12.430777549743652 ], [ "▁外れた", -12.43081283569336 ], [ "▁生後", -12.431142807006836 ], [ "おかげ", -12.43117618560791 ], [ "翔", -12.431333541870117 ], [ "陶", -12.431377410888672 ], [ "▁ロッカー", -12.431438446044922 ], [ "ンガム", -12.431468963623047 ], [ "▁陽子", -12.43151569366455 ], [ "ロップ", -12.43161678314209 ], [ "▁北野", -12.431621551513672 ], [ "▁クイーンズ", -12.431632995605469 ], [ "▁閉じた", -12.431886672973633 ], [ "▁こむ", -12.431931495666504 ], [ "▁東亜", -12.431940078735352 ], [ "▁きって", -12.43198299407959 ], [ "▁スリーブ", -12.43199348449707 ], [ "OB", -12.4320707321167 ], [ "▁リブ", -12.432289123535156 ], [ "▁台所", -12.432326316833496 ], [ "▁傷害", -12.432377815246582 ], [ "▁FP", -12.432384490966797 ], [ "▁car", -12.432394981384277 ], [ "▁調布", -12.432416915893555 ], [ "▁辿り着", -12.432432174682617 ], [ "▁宣教師", -12.432448387145996 ], [ "おお", -12.432514190673828 ], [ "▁春季", -12.432592391967773 ], [ "▁いったら", -12.432612419128418 ], [ "パーク", -12.432699203491211 ], [ "▁省エネ", -12.43272876739502 ], [ "マックス", -12.432750701904297 ], [ "▁JIS", -12.432760238647461 ], [ "▁直撃", -12.432879447937012 ], [ "▁実効", -12.432964324951172 ], [ "スポンサー", -12.433015823364258 ], [ "▁ミシガン", -12.433023452758789 ], [ "IND", -12.4331693649292 ], [ "Apple", -12.43319034576416 ], [ "▁アルフ", -12.433197975158691 ], [ "▁込める", -12.43325138092041 ], [ "ヴァルト", -12.433269500732422 ], [ "▁新党", -12.433313369750977 ], [ "クラウド", -12.433313369750977 ], [ "▁茨木", -12.433319091796875 ], [ "▁薔薇", -12.433467864990234 ], [ "熙", -12.433467864990234 ], [ "文学", -12.433479309082031 ], [ "▁一時的な", -12.43355655670166 ], [ "ォ", -12.433601379394531 ], [ "gl", -12.433613777160645 ], [ "▁成り立って", -12.433673858642578 ], [ "らしく", -12.433673858642578 ], [ "▁ご存じ", -12.433911323547363 ], [ "▁宙", -12.433920860290527 ], [ "っぺ", -12.434012413024902 ], [ "レビュー", -12.434040069580078 ], [ "▁注釈", -12.434088706970215 ], [ "▁裂", -12.434103012084961 ], [ "▁クローン", -12.434184074401855 ], [ "扇", -12.434221267700195 ], [ "▁廃業", -12.43425178527832 ], [ "▁分化", -12.434281349182129 ], [ "▁倒れて", -12.434297561645508 ], [ "qua", -12.434370994567871 ], [ "いくら", -12.434391021728516 ], [ "▁各自", -12.434463500976562 ], [ "モル", -12.434469223022461 ], [ "▁補足", -12.434609413146973 ], [ "▁PT", -12.434619903564453 ], [ "金融", -12.434621810913086 ], [ "▁任用", -12.43470287322998 ], [ "沈", -12.434713363647461 ], [ "each", -12.434819221496582 ], [ "▁連中", -12.434826850891113 ], [ "▁旋律", -12.434948921203613 ], [ "▁白川", -12.434986114501953 ], [ "▁慌てて", -12.435192108154297 ], [ "tes", -12.435248374938965 ], [ "転職", -12.435251235961914 ], [ "▁天地", -12.435253143310547 ], [ "▁気持ちよく", -12.435319900512695 ], [ "▁改組", -12.43535041809082 ], [ "▁盛り上がって", -12.435394287109375 ], [ "▁隆盛", -12.435494422912598 ], [ "伺", -12.435511589050293 ], [ "▁くに", -12.435546875 ], [ "コミック", -12.435548782348633 ], [ "ichi", -12.435574531555176 ], [ "▁刺史", -12.435604095458984 ], [ "▁タイアップ", -12.435733795166016 ], [ "▁噴", -12.435872077941895 ], [ "▁モニタリング", -12.435892105102539 ], [ "考え", -12.435962677001953 ], [ "▁柵", -12.435970306396484 ], [ "▁十六", -12.436079025268555 ], [ "▁大根", -12.436126708984375 ], [ "▁腹部", -12.436153411865234 ], [ "▁長所", -12.436180114746094 ], [ "ラウンド", -12.436217308044434 ], [ "▁苦悩", -12.436312675476074 ], [ "▁逃げて", -12.436413764953613 ], [ "勲", -12.43647575378418 ], [ "バレー", -12.436537742614746 ], [ "▁印鑑", -12.436627388000488 ], [ "▁病棟", -12.4366455078125 ], [ "lock", -12.436675071716309 ], [ "▁イリノイ", -12.43687915802002 ], [ "CBD", -12.436955451965332 ], [ "樋", -12.437026977539062 ], [ "▁MAR", -12.437110900878906 ], [ "何故", -12.437151908874512 ], [ "ola", -12.43718147277832 ], [ "▁どうぶつ", -12.437337875366211 ], [ "▁オフライン", -12.437402725219727 ], [ "▁持ち帰り", -12.437647819519043 ], [ "▁小池", -12.437703132629395 ], [ "▁dark", -12.437756538391113 ], [ "ump", -12.437949180603027 ], [ "離れ", -12.438024520874023 ], [ "▁浮世", -12.438031196594238 ], [ "▁皮肉", -12.438163757324219 ], [ "合わ", -12.438302040100098 ], [ "▁コンボ", -12.438337326049805 ], [ "▁強要", -12.43844223022461 ], [ "櫻", -12.43851375579834 ], [ "▁レインボー", -12.438566207885742 ], [ "ワシ", -12.438593864440918 ], [ "もしも", -12.438604354858398 ], [ "▁国分寺", -12.438813209533691 ], [ "▁忠誠", -12.438895225524902 ], [ "▁見どころ", -12.43896198272705 ], [ "of", -12.439019203186035 ], [ "通算", -12.439022064208984 ], [ "▁おせち", -12.439115524291992 ], [ "▁スウェット", -12.439258575439453 ], [ "▁大好きで", -12.439260482788086 ], [ "早速", -12.439371109008789 ], [ "▁赤十字", -12.439408302307129 ], [ "▁1400", -12.439484596252441 ], [ "ender", -12.439493179321289 ], [ "▁デュオ", -12.43960189819336 ], [ "▁facebook", -12.439705848693848 ], [ "▁イラストレーター", -12.439775466918945 ], [ "▁Ki", -12.439862251281738 ], [ "▁団員", -12.440045356750488 ], [ "า", -12.44005298614502 ], [ "▁小牧", -12.440086364746094 ], [ "▁パートナーシップ", -12.440089225769043 ], [ "▁古河", -12.440239906311035 ], [ "▁OCN", -12.440305709838867 ], [ "▁159", -12.440430641174316 ], [ "▁Architecture", -12.440512657165527 ], [ "▁発車", -12.440519332885742 ], [ "▁子役", -12.440563201904297 ], [ "▁Mobil", -12.440678596496582 ], [ "距離", -12.440750122070312 ], [ "▁盗難", -12.440790176391602 ], [ "▁プライス", -12.4408540725708 ], [ "▁教えた", -12.440963745117188 ], [ "GP", -12.44096565246582 ], [ "溶", -12.441006660461426 ], [ "3000", -12.441088676452637 ], [ "▁ベランダ", -12.441113471984863 ], [ "arm", -12.44113826751709 ], [ "▁121", -12.44116497039795 ], [ "▁ほんと", -12.44119930267334 ], [ "▁規程", -12.441346168518066 ], [ "或いは", -12.441349983215332 ], [ "▁プランナー", -12.441360473632812 ], [ "▁モデ", -12.441366195678711 ], [ "▁歯周病", -12.441495895385742 ], [ "▁閣議", -12.441561698913574 ], [ "▁満員", -12.441696166992188 ], [ "▁ニコラ", -12.441794395446777 ], [ "シュタ", -12.442032814025879 ], [ "▁バーガー", -12.442193984985352 ], [ "出て", -12.442255973815918 ], [ "▁どうか", -12.442435264587402 ], [ "▁エウ", -12.44248104095459 ], [ "完", -12.442549705505371 ], [ "▁構える", -12.442635536193848 ], [ "リッチ", -12.442678451538086 ], [ "▁リーマン", -12.442697525024414 ], [ "cul", -12.442774772644043 ], [ "英国", -12.44293212890625 ], [ "▁ガレージ", -12.44312858581543 ], [ "めく", -12.443254470825195 ], [ "▁麹", -12.443285942077637 ], [ "ラール", -12.443367958068848 ], [ "▁嫌悪", -12.44339656829834 ], [ "▁ヨン", -12.443436622619629 ], [ "▁被告人", -12.443499565124512 ], [ "後日", -12.443517684936523 ], [ "買い", -12.443526268005371 ], [ "▁流星", -12.44353199005127 ], [ "▁ブランディング", -12.4435453414917 ], [ "▁ぼう", -12.44357681274414 ], [ "▁贈呈", -12.443589210510254 ], [ "▁Service", -12.443644523620605 ], [ "▁バスク", -12.443839073181152 ], [ "山本", -12.443852424621582 ], [ "▁甘味", -12.444032669067383 ], [ "▁ホモ", -12.444252014160156 ], [ "たとえ", -12.444321632385254 ], [ "▁メロン", -12.444487571716309 ], [ "▁1895", -12.44459342956543 ], [ "体験", -12.444637298583984 ], [ "リィ", -12.444661140441895 ], [ "▁掲げた", -12.444704055786133 ], [ "▁鎮座", -12.444769859313965 ], [ "▁慈", -12.444862365722656 ], [ "▁千里", -12.444917678833008 ], [ "▁Halloween", -12.444934844970703 ], [ "▁ワックス", -12.444954872131348 ], [ "▁上層", -12.44505500793457 ], [ "▁如く", -12.445061683654785 ], [ "▁ノエル", -12.445243835449219 ], [ "メット", -12.445511817932129 ], [ "づいて", -12.445537567138672 ], [ "▁づつ", -12.445550918579102 ], [ "▁易", -12.44555950164795 ], [ "嫌", -12.44558048248291 ], [ "モニ", -12.445610046386719 ], [ "▁出動", -12.445855140686035 ], [ "▁詰まった", -12.446022033691406 ], [ "▁168", -12.446123123168945 ], [ "▁星座", -12.44615650177002 ], [ "▁別冊", -12.446231842041016 ], [ "このまま", -12.446395874023438 ], [ "▁民謡", -12.446452140808105 ], [ "IZ", -12.446456909179688 ], [ "▁逃れた", -12.446596145629883 ], [ "▁浄土", -12.446701049804688 ], [ "被害", -12.44670581817627 ], [ "▁愚", -12.446784973144531 ], [ "▁Level", -12.44691276550293 ], [ "▁眺める", -12.44694709777832 ], [ "▁Answer", -12.447033882141113 ], [ "▁和菓子", -12.447183609008789 ], [ "▁生んだ", -12.447196960449219 ], [ "▁養殖", -12.447344779968262 ], [ "ライド", -12.447415351867676 ], [ "淡", -12.447446823120117 ], [ "▁明確", -12.447466850280762 ], [ "▁聴いた", -12.447680473327637 ], [ "更新", -12.447713851928711 ], [ "▁量販", -12.447787284851074 ], [ "▁Netflix", -12.447834014892578 ], [ "痴", -12.447930335998535 ], [ "oz", -12.447999000549316 ], [ "▁表れ", -12.448049545288086 ], [ "▁悪役", -12.44806957244873 ], [ "▁無名", -12.448171615600586 ], [ "▁ふみ", -12.448455810546875 ], [ "▁クレーン", -12.44849967956543 ], [ "睡", -12.448525428771973 ], [ "▁サザン", -12.448570251464844 ], [ "脂", -12.448596000671387 ], [ "ガウ", -12.448596954345703 ], [ "▁防空", -12.448616981506348 ], [ "▁金色", -12.448866844177246 ], [ "▁└", -12.448882102966309 ], [ "▁見事", -12.448930740356445 ], [ "▁有意", -12.44897747039795 ], [ "計画", -12.44902515411377 ], [ "▁ペリ", -12.449097633361816 ], [ "▁呪", -12.449187278747559 ], [ "▁派閥", -12.449525833129883 ], [ "▁帯域", -12.449592590332031 ], [ "ジウム", -12.449668884277344 ], [ "▁逆の", -12.449687004089355 ], [ "▁出航", -12.449797630310059 ], [ "count", -12.449838638305664 ], [ "魯", -12.450039863586426 ], [ "ビッド", -12.45007610321045 ], [ "んと", -12.45008373260498 ], [ "訪", -12.450108528137207 ], [ "lon", -12.450128555297852 ], [ "▁溜め", -12.4501953125 ], [ "科学", -12.450340270996094 ], [ "▁ルーター", -12.450420379638672 ], [ "ピアノ", -12.450493812561035 ], [ "▁カリウム", -12.450547218322754 ], [ "▁蔵書", -12.450549125671387 ], [ "経験", -12.45055103302002 ], [ "▁1872", -12.450713157653809 ], [ "▁偏見", -12.450764656066895 ], [ "運転", -12.450889587402344 ], [ "▁破る", -12.450919151306152 ], [ "捨", -12.450937271118164 ], [ "▁膨張", -12.450943946838379 ], [ "シモ", -12.451013565063477 ], [ "蛇", -12.451085090637207 ], [ "苦しい", -12.451374053955078 ], [ "▁ごめん", -12.451414108276367 ], [ "▁誘って", -12.451423645019531 ], [ "1917", -12.451508522033691 ], [ "メタ", -12.451542854309082 ], [ "治郎", -12.451552391052246 ], [ "▁望", -12.451574325561523 ], [ "▁クレア", -12.451642990112305 ], [ "▁硬式", -12.451656341552734 ], [ "▁アナリスト", -12.45166301727295 ], [ "▁踏まえた", -12.451725006103516 ], [ "▁せき", -12.451752662658691 ], [ "▁Blog", -12.451991081237793 ], [ "わす", -12.45201301574707 ], [ "▁米沢", -12.452013969421387 ], [ "▁リアリティ", -12.452061653137207 ], [ "▁湧き", -12.452157020568848 ], [ "▁飾って", -12.452188491821289 ], [ "天文", -12.452240943908691 ], [ "▁鉱業", -12.452260971069336 ], [ "▁カノ", -12.452281951904297 ], [ "プール", -12.4523344039917 ], [ "FS", -12.45236873626709 ], [ "ひこ", -12.452397346496582 ], [ "レイン", -12.452438354492188 ], [ "▁コンビニエンス", -12.452467918395996 ], [ "▁Wh", -12.452533721923828 ], [ "▁pink", -12.452539443969727 ], [ "▁納付", -12.452645301818848 ], [ "▁めん", -12.452754020690918 ], [ "▁女流", -12.452776908874512 ], [ "▁レズ", -12.452865600585938 ], [ "▁備考", -12.452917098999023 ], [ "▁閉塞", -12.452921867370605 ], [ "ines", -12.45302963256836 ], [ "▁危ない", -12.453099250793457 ], [ "riv", -12.453121185302734 ], [ "▁バッジ", -12.453125953674316 ], [ "々しく", -12.45315933227539 ], [ "唄", -12.453234672546387 ], [ "徳島", -12.453372955322266 ], [ "生まれ", -12.453378677368164 ], [ "▁辺境", -12.453394889831543 ], [ "vie", -12.453471183776855 ], [ "▁オペレーティング", -12.453810691833496 ], [ "▁無垢", -12.453852653503418 ], [ "SF", -12.45389461517334 ], [ "ジャック", -12.453962326049805 ], [ "iro", -12.45400333404541 ], [ "Ch", -12.454030990600586 ], [ "▁南下", -12.454116821289062 ], [ "▁Exam", -12.454117774963379 ], [ "▁保証人", -12.454137802124023 ], [ "▁徴兵", -12.454142570495605 ], [ "▁呂", -12.454183578491211 ], [ "▁コレステロール", -12.454263687133789 ], [ "RG", -12.454329490661621 ], [ "伊藤", -12.454364776611328 ], [ "▁セレクション", -12.454447746276855 ], [ "▁shop", -12.454488754272461 ], [ "▁争", -12.454602241516113 ], [ "1921", -12.454629898071289 ], [ "▁探る", -12.454659461975098 ], [ "▁霞", -12.454659461975098 ], [ "▁敢行", -12.454717636108398 ], [ "▁萌", -12.454741477966309 ], [ "▁ルネサンス", -12.4550199508667 ], [ "▁大相撲", -12.45503044128418 ], [ "▁モラ", -12.455036163330078 ], [ "▁選任", -12.45521068572998 ], [ "▁アット", -12.45530891418457 ], [ "緊急", -12.45535659790039 ], [ "トイレ", -12.45552921295166 ], [ "▁著した", -12.455543518066406 ], [ "▁永遠に", -12.455554008483887 ], [ "演奏", -12.45556354522705 ], [ "▁203", -12.455607414245605 ], [ "▁日清", -12.455728530883789 ], [ "ワイン", -12.455745697021484 ], [ "▁やってきて", -12.455768585205078 ], [ "言い", -12.455830574035645 ], [ "▁Rock", -12.455917358398438 ], [ "▁覚えた", -12.456010818481445 ], [ "note", -12.456194877624512 ], [ "▁レジェンド", -12.456231117248535 ], [ "▁可能であり", -12.456262588500977 ], [ "rum", -12.456321716308594 ], [ "▁中略", -12.45633316040039 ], [ "蕭", -12.456382751464844 ], [ "▁奥州", -12.456441879272461 ], [ "▁グッ", -12.456531524658203 ], [ "▁どうせ", -12.456653594970703 ], [ "ration", -12.456707954406738 ], [ "▁260", -12.45673656463623 ], [ "▁ウラン", -12.456743240356445 ], [ "▁直近", -12.456871032714844 ], [ "▁シャドウ", -12.456942558288574 ], [ "▁ベネズエラ", -12.456989288330078 ], [ "▁申し込む", -12.457091331481934 ], [ "ニヤ", -12.457110404968262 ], [ "▁っこ", -12.457136154174805 ], [ "▁十数", -12.457159996032715 ], [ "▁団長", -12.457219123840332 ], [ "EV", -12.457240104675293 ], [ "福井", -12.457369804382324 ], [ "▁有人", -12.457447052001953 ], [ "▁マグロ", -12.457536697387695 ], [ "▁味わって", -12.457564353942871 ], [ "Facebook", -12.457639694213867 ], [ "▁義理", -12.457690238952637 ], [ "III", -12.45772647857666 ], [ "▁富士通", -12.457759857177734 ], [ "ves", -12.457770347595215 ], [ "▁サントリー", -12.4578275680542 ], [ "▁退場", -12.45785140991211 ], [ "▁豊川", -12.457883834838867 ], [ "▁Security", -12.45789909362793 ], [ "▁愚か", -12.458003044128418 ], [ "▁DMM", -12.458049774169922 ], [ "アマゾン", -12.458104133605957 ], [ "▁石巻", -12.458281517028809 ], [ "ほく", -12.458324432373047 ], [ "▁NPB", -12.458358764648438 ], [ "▁コネクタ", -12.458377838134766 ], [ "▁差し替え", -12.458388328552246 ], [ "▁etc", -12.458459854125977 ], [ "▁名残", -12.458523750305176 ], [ "河原", -12.458619117736816 ], [ "▁brown", -12.45872974395752 ], [ "▁古賀", -12.458739280700684 ], [ "▁痴漢", -12.458809852600098 ], [ "光寺", -12.458820343017578 ], [ "忌", -12.458852767944336 ], [ "GN", -12.458929061889648 ], [ "gs", -12.45902156829834 ], [ "▁ソニック", -12.459086418151855 ], [ "▁引き下げ", -12.459091186523438 ], [ "▁蝦夷", -12.459114074707031 ], [ "▁地価", -12.459132194519043 ], [ "▁朱印", -12.459160804748535 ], [ "▁デュアル", -12.459272384643555 ], [ "Name", -12.459327697753906 ], [ "▁バンタム", -12.459327697753906 ], [ "コシ", -12.459339141845703 ], [ "8000", -12.459376335144043 ], [ "ごく", -12.45946979522705 ], [ "モバイル", -12.45947551727295 ], [ "▁先駆け", -12.459506034851074 ], [ "▁迫害", -12.45959186553955 ], [ "▁議決", -12.459722518920898 ], [ "たまに", -12.459836959838867 ], [ "慣れ", -12.459900856018066 ], [ "▁free", -12.460097312927246 ], [ "標準", -12.460105895996094 ], [ "▁ハイライト", -12.460203170776367 ], [ "ーー", -12.460219383239746 ], [ "▁OUT", -12.460357666015625 ], [ "もしかしたら", -12.460705757141113 ], [ "誠に", -12.460737228393555 ], [ "▁演歌", -12.460877418518066 ], [ "▁格段に", -12.460938453674316 ], [ "キャップ", -12.461004257202148 ], [ "1922", -12.46113395690918 ], [ "▁イグ", -12.461196899414062 ], [ "詰め", -12.46125316619873 ], [ "▁ww", -12.461426734924316 ], [ "運行", -12.461445808410645 ], [ "▁トレイ", -12.461559295654297 ], [ "▁つくった", -12.461711883544922 ], [ "▁請願", -12.461712837219238 ], [ "▁プードル", -12.461753845214844 ], [ "▁評した", -12.46177864074707 ], [ "▁ディズニーランド", -12.461814880371094 ], [ "個", -12.46190071105957 ], [ "▁着せ", -12.46190357208252 ], [ "▁冷や", -12.461935043334961 ], [ "▁本尊", -12.461935043334961 ], [ "▁切れる", -12.461956977844238 ], [ "▁服部", -12.462021827697754 ], [ "▁打ち切り", -12.462027549743652 ], [ "▁ハロー", -12.462117195129395 ], [ "▁洪", -12.462362289428711 ], [ "▁衆院", -12.462457656860352 ], [ "グレー", -12.462593078613281 ], [ "▁儀礼", -12.462638854980469 ], [ "▁双葉", -12.462641716003418 ], [ "▁日活", -12.462660789489746 ], [ "曽", -12.462688446044922 ], [ "▁小平", -12.462831497192383 ], [ "▁磐田", -12.462886810302734 ], [ "和田", -12.462912559509277 ], [ "ッペン", -12.462916374206543 ], [ "▁手芸", -12.463149070739746 ], [ "般", -12.463217735290527 ], [ "rad", -12.463218688964844 ], [ "ARK", -12.463266372680664 ], [ "▁トリプル", -12.463334083557129 ], [ "oph", -12.463550567626953 ], [ "▁キャンディ", -12.463570594787598 ], [ "▁発光", -12.463772773742676 ], [ "▁媒介", -12.463834762573242 ], [ "▁FINAL", -12.463988304138184 ], [ "▁歓", -12.46420955657959 ], [ "▁倍率", -12.464221000671387 ], [ "庸", -12.4642915725708 ], [ "ナップ", -12.464312553405762 ], [ "漏", -12.464422225952148 ], [ "▁パット", -12.464433670043945 ], [ "▁Solutions", -12.464599609375 ], [ "▁四方", -12.46481704711914 ], [ "恒", -12.464855194091797 ], [ "▁覆い", -12.464874267578125 ], [ "▁モーツァルト", -12.464903831481934 ], [ "•", -12.465006828308105 ], [ "▁領収", -12.465069770812988 ], [ "▁凸", -12.46512508392334 ], [ "▁Architect", -12.465187072753906 ], [ "▁Version", -12.465231895446777 ], [ "▁シャーロット", -12.465240478515625 ], [ "▁証人", -12.465254783630371 ], [ "梓", -12.465361595153809 ], [ "▁マーシャル", -12.465468406677246 ], [ "к", -12.465514183044434 ], [ "メリ", -12.465522766113281 ], [ "▁サード", -12.46560287475586 ], [ "▁ネギ", -12.465603828430176 ], [ "▁回った", -12.465853691101074 ], [ "▁ランドナー", -12.465950965881348 ], [ "スペクト", -12.466092109680176 ], [ "伐", -12.466264724731445 ], [ "801", -12.466329574584961 ], [ "▁あらためて", -12.466432571411133 ], [ "▁とどまら", -12.466435432434082 ], [ "マグ", -12.466575622558594 ], [ "▁減らして", -12.4666166305542 ], [ "ope", -12.46672248840332 ], [ "▁似合う", -12.46687126159668 ], [ "▁体格", -12.466913223266602 ], [ "▁母艦", -12.466962814331055 ], [ "素材", -12.467108726501465 ], [ "Play", -12.467145919799805 ], [ "農業", -12.467278480529785 ], [ "新規", -12.467323303222656 ], [ "zi", -12.467366218566895 ], [ "▁亡くし", -12.46739673614502 ], [ "▁アリア", -12.467453002929688 ], [ "▁米子", -12.4674711227417 ], [ "▁円盤", -12.467527389526367 ], [ "▁明かした", -12.467785835266113 ], [ "▁舞鶴", -12.46785831451416 ], [ "▁多忙", -12.467988967895508 ], [ "事実", -12.468076705932617 ], [ "▁八幡宮", -12.468079566955566 ], [ "▁Mor", -12.468125343322754 ], [ "先制", -12.468177795410156 ], [ "▁詰まって", -12.468321800231934 ], [ "▁バスケット", -12.468499183654785 ], [ "ツェル", -12.468520164489746 ], [ "▁チェス", -12.468554496765137 ], [ "▁引き継ぐ", -12.468685150146484 ], [ "▁母乳", -12.46876049041748 ], [ "▁特筆", -12.469144821166992 ], [ "▁プリンタ", -12.469179153442383 ], [ "▁シリンダー", -12.46919059753418 ], [ "▁テネシー", -12.469344139099121 ], [ "▁楽園", -12.469403266906738 ], [ "▁繰り返した", -12.469422340393066 ], [ "▁葛藤", -12.469535827636719 ], [ "狩", -12.469696998596191 ], [ "昇", -12.469740867614746 ], [ "▁埋める", -12.46975326538086 ], [ "▁百済", -12.469871520996094 ], [ "▁ライド", -12.469919204711914 ], [ "ポラ", -12.469961166381836 ], [ "▁万博", -12.469970703125 ], [ "▁〝", -12.469992637634277 ], [ "▁近づ", -12.470025062561035 ], [ "▁国税", -12.470046997070312 ], [ "各種", -12.47011947631836 ], [ "▁have", -12.470163345336914 ], [ "▁局面", -12.470197677612305 ], [ "▁奪った", -12.470227241516113 ], [ "▁乏しい", -12.47026538848877 ], [ "▁消火", -12.470356941223145 ], [ "▁ロードレース", -12.470520973205566 ], [ "ett", -12.470568656921387 ], [ "▁ロケーション", -12.470582962036133 ], [ "▁崩し", -12.470619201660156 ], [ "くち", -12.470742225646973 ], [ "▁pc", -12.470858573913574 ], [ "▁ジュン", -12.47103500366211 ], [ "▁並列", -12.47107219696045 ], [ "▁サウジアラビア", -12.471091270446777 ], [ "ima", -12.471111297607422 ], [ "▁借りた", -12.47115421295166 ], [ "▁白書", -12.47115421295166 ], [ "繋", -12.471169471740723 ], [ "▁精霊", -12.471280097961426 ], [ "▁引き換え", -12.471342086791992 ], [ "新たな", -12.471356391906738 ], [ "▁TT", -12.471428871154785 ], [ "▁中頃", -12.47148609161377 ], [ "▁喚起", -12.471495628356934 ], [ "くん", -12.471911430358887 ], [ "ビエ", -12.47192668914795 ], [ "▁衝動", -12.47195816040039 ], [ "ITY", -12.471980094909668 ], [ "変わり", -12.471983909606934 ], [ "▁進水", -12.472057342529297 ], [ "▁126", -12.472156524658203 ], [ "▁洗って", -12.472168922424316 ], [ "▁ネジ", -12.472199440002441 ], [ "▁臨んだ", -12.47230052947998 ], [ "▁血液型", -12.472338676452637 ], [ "▁トロイ", -12.472405433654785 ], [ "▁内視鏡", -12.472418785095215 ], [ "▁換装", -12.472419738769531 ], [ "首都", -12.472434997558594 ], [ "▁負けた", -12.47243595123291 ], [ "▁靴下", -12.472566604614258 ], [ "▁プラダ", -12.472631454467773 ], [ "▁20,000", -12.47263240814209 ], [ "▁引き寄せ", -12.472664833068848 ], [ "▁浮かべ", -12.472687721252441 ], [ "▁称し", -12.47274112701416 ], [ "▁言い訳", -12.472757339477539 ], [ "EW", -12.472795486450195 ], [ "▁エレクトリック", -12.473034858703613 ], [ "▶", -12.473034858703613 ], [ "▁無地", -12.473036766052246 ], [ "隷", -12.473173141479492 ], [ "▁興信所", -12.473188400268555 ], [ "▁King", -12.47337532043457 ], [ "ret", -12.473419189453125 ], [ "▁永井", -12.473470687866211 ], [ "抵", -12.47347640991211 ], [ "愁", -12.47349739074707 ], [ "▁どうした", -12.473553657531738 ], [ "バイク", -12.473580360412598 ], [ "槻", -12.473590850830078 ], [ "Tweet", -12.473894119262695 ], [ "yr", -12.473965644836426 ], [ "RAN", -12.474020004272461 ], [ "▁フランチャイズ", -12.474113464355469 ], [ "▁ゼン", -12.474272727966309 ], [ "たぶん", -12.47429084777832 ], [ "▁取り消し", -12.474331855773926 ], [ "説明", -12.474352836608887 ], [ "▁亜種", -12.474361419677734 ], [ "古い", -12.474419593811035 ], [ "▁適当に", -12.474589347839355 ], [ "▁国政", -12.474679946899414 ], [ "▁ç", -12.474742889404297 ], [ "十二", -12.474762916564941 ], [ "衰", -12.474825859069824 ], [ "LV", -12.47485065460205 ], [ "媒", -12.474869728088379 ], [ "▁ルートヴィヒ", -12.474884986877441 ], [ "▁熱海", -12.474932670593262 ], [ "▁フェリ", -12.474996566772461 ], [ "▁惣", -12.475178718566895 ], [ "竿", -12.475193977355957 ], [ "▁127", -12.475202560424805 ], [ "▁ございまして", -12.475348472595215 ], [ "ウマ", -12.475486755371094 ], [ "▁浄水", -12.475504875183105 ], [ "▁ラング", -12.47558307647705 ], [ "▁ミッキー", -12.475626945495605 ], [ "埼", -12.475628852844238 ], [ "▁エレクトロニクス", -12.475811004638672 ], [ "▁ピラミッド", -12.475811004638672 ], [ "楽器", -12.476018905639648 ], [ "▁匠", -12.476040840148926 ], [ "▁フィニッシュ", -12.4761381149292 ], [ "▁ヨハネ", -12.476273536682129 ], [ "▁ケリー", -12.476446151733398 ], [ "▁出来れば", -12.476490020751953 ], [ "チケット", -12.476570129394531 ], [ "▁ONLINE", -12.476597785949707 ], [ "col", -12.476737022399902 ], [ "▁代名詞", -12.476738929748535 ], [ "償", -12.476865768432617 ], [ "クラー", -12.476888656616211 ], [ "▁纏", -12.476943016052246 ], [ "単式", -12.477096557617188 ], [ "ira", -12.477099418640137 ], [ "何も", -12.477179527282715 ], [ "▁伐採", -12.477202415466309 ], [ "▁SV", -12.47723388671875 ], [ "▁硬い", -12.477252006530762 ], [ "▁華やかな", -12.477286338806152 ], [ "▁ポルシェ", -12.47739315032959 ], [ "メド", -12.47758674621582 ], [ "▁風習", -12.477852821350098 ], [ "▁説教", -12.477917671203613 ], [ "▁イタ", -12.477957725524902 ], [ "一つ", -12.47797679901123 ], [ "▁未遂", -12.478029251098633 ], [ "▁積載", -12.478035926818848 ], [ "▁加齢", -12.478049278259277 ], [ "後半", -12.478055953979492 ], [ "燈", -12.478130340576172 ], [ "▁FE", -12.478193283081055 ], [ "▁autumn", -12.478285789489746 ], [ "▁事変", -12.478365898132324 ], [ "働き", -12.478382110595703 ], [ "aff", -12.478385925292969 ], [ "じょ", -12.478544235229492 ], [ "▁式場", -12.478626251220703 ], [ "▁380", -12.478689193725586 ], [ "▁エストニア", -12.47880744934082 ], [ "▁活発な", -12.478835105895996 ], [ "▁存分に", -12.47890567779541 ], [ "▁久々に", -12.478906631469727 ], [ "▁Il", -12.47917366027832 ], [ "ness", -12.47918701171875 ], [ "▁褒美", -12.479215621948242 ], [ "▁入選", -12.479246139526367 ], [ "▁半減", -12.479355812072754 ], [ "▁剥奪", -12.479375839233398 ], [ "▁劣る", -12.479482650756836 ], [ "MACHINE", -12.479525566101074 ], [ "▁祇園", -12.479525566101074 ], [ "▁めっちゃ", -12.479635238647461 ], [ "▁Japanese", -12.479835510253906 ], [ "中村", -12.480096817016602 ], [ "▁イソ", -12.480193138122559 ], [ "現状", -12.480202674865723 ], [ "▁噛", -12.480205535888672 ], [ "▁お返し", -12.480230331420898 ], [ "▁且つ", -12.480300903320312 ], [ "GC", -12.480683326721191 ], [ "search", -12.480794906616211 ], [ "▁Д", -12.48087215423584 ], [ "虐", -12.48090648651123 ], [ "▁1⁄4", -12.480921745300293 ], [ "los", -12.480934143066406 ], [ "▁阿蘇", -12.480965614318848 ], [ "▁当てはまる", -12.481101036071777 ], [ "▁値上げ", -12.481202125549316 ], [ "現場", -12.481226921081543 ], [ "▁試す", -12.481229782104492 ], [ "▁感銘", -12.481284141540527 ], [ "▁教義", -12.48139476776123 ], [ "▁買い取っ", -12.481473922729492 ], [ "▁誘発", -12.481560707092285 ], [ "▁尾根", -12.481680870056152 ], [ "洛", -12.481840133666992 ], [ "▁阻", -12.481873512268066 ], [ "▁mar", -12.481954574584961 ], [ "▁ボケ", -12.482000350952148 ], [ "▁ウソ", -12.482024192810059 ], [ "▁如来", -12.482077598571777 ], [ "▁Real", -12.482215881347656 ], [ "▁損な", -12.482245445251465 ], [ "▁ダイナ", -12.48232364654541 ], [ "栃木", -12.482333183288574 ], [ "▁欲しかった", -12.482339859008789 ], [ "▁省庁", -12.482357025146484 ], [ "▁不自然", -12.482421875 ], [ "ローム", -12.482442855834961 ], [ "▁存じ", -12.482513427734375 ], [ "▁スティック", -12.48257064819336 ], [ "tern", -12.48260498046875 ], [ "チェック", -12.48272705078125 ], [ "布施", -12.482754707336426 ], [ "▁重なる", -12.482763290405273 ], [ "▁ふれ", -12.482940673828125 ], [ "▁残せ", -12.483062744140625 ], [ "▁ゲノム", -12.483409881591797 ], [ "▁イノ", -12.483444213867188 ], [ "NU", -12.483617782592773 ], [ "▁NATO", -12.483715057373047 ], [ "▁ゼネラル", -12.483720779418945 ], [ "ファス", -12.483839988708496 ], [ "ハヤ", -12.483902931213379 ], [ "ABA", -12.483977317810059 ], [ "▁MY", -12.483980178833008 ], [ "▁恐慌", -12.484189987182617 ], [ "▁ステロイド", -12.484254837036133 ], [ "▁サヨナラ", -12.484343528747559 ], [ "汎", -12.484343528747559 ], [ "▁TIME", -12.484403610229492 ], [ "▁ケンブリッジ", -12.484509468078613 ], [ "▁退去", -12.484522819519043 ], [ "レグ", -12.484528541564941 ], [ "セリ", -12.484548568725586 ], [ "フレー", -12.484587669372559 ], [ "▁繋ぐ", -12.484655380249023 ], [ "▁まくる", -12.484663963317871 ], [ "▁良心", -12.484698295593262 ], [ "作業", -12.484833717346191 ], [ "▁大関", -12.48486042022705 ], [ "▁美容院", -12.48493480682373 ], [ "▁菅原", -12.484970092773438 ], [ "窮", -12.48512077331543 ], [ "琉", -12.485122680664062 ], [ "▁解け", -12.485123634338379 ], [ "▁振って", -12.485328674316406 ], [ "▁檜", -12.485369682312012 ], [ "見た目", -12.485398292541504 ], [ "▁おしゃべり", -12.48546314239502 ], [ "▁光線", -12.485530853271484 ], [ "▁スピリチュアル", -12.485590934753418 ], [ "ナック", -12.485603332519531 ], [ "▁和英", -12.485747337341309 ], [ "どうしても", -12.485782623291016 ], [ "▁接合", -12.485846519470215 ], [ "しりつ", -12.485973358154297 ], [ "Ruby", -12.486011505126953 ], [ "▁アレックス", -12.486112594604492 ], [ "ASH", -12.486187934875488 ], [ "▁スナップ", -12.486207008361816 ], [ "kai", -12.486234664916992 ], [ "▁来週", -12.486364364624023 ], [ "▁コミュニケーションズ", -12.486456871032715 ], [ "▁腐敗", -12.486546516418457 ], [ "日経", -12.486593246459961 ], [ "▁完璧", -12.486618041992188 ], [ "カツ", -12.486620903015137 ], [ "▁一揆", -12.486631393432617 ], [ "タイプ", -12.486654281616211 ], [ "囚", -12.486681938171387 ], [ "▁じょ", -12.486751556396484 ], [ "▁ユーモア", -12.48675537109375 ], [ "頑", -12.486777305603027 ], [ "▁仮称", -12.486799240112305 ], [ "▁ニュータウン", -12.486837387084961 ], [ "▁居心地", -12.48684024810791 ], [ "250", -12.487006187438965 ], [ "▁アベニュー", -12.487168312072754 ], [ "んぱ", -12.487184524536133 ], [ "▁一色", -12.487194061279297 ], [ "AKI", -12.487215042114258 ], [ "iver", -12.487239837646484 ], [ "▁お陰", -12.48724365234375 ], [ "なぎ", -12.487385749816895 ], [ "▁1873", -12.4874267578125 ], [ "▁ディフェンス", -12.487621307373047 ], [ "MAX", -12.487676620483398 ], [ "▁保留", -12.487791061401367 ], [ "▁党派", -12.488104820251465 ], [ "▁すく", -12.4881591796875 ], [ "▁着任", -12.488195419311523 ], [ "▁嫡男", -12.48824691772461 ], [ "タク", -12.488369941711426 ], [ "▁取り付ける", -12.488377571105957 ], [ "▁古巣", -12.488389015197754 ], [ "▁{{", -12.488397598266602 ], [ "▁贅沢な", -12.488420486450195 ], [ "シク", -12.48861312866211 ], [ "▁不当", -12.488638877868652 ], [ "▁反対の", -12.48867416381836 ], [ "嵐", -12.48868465423584 ], [ "▁出費", -12.489092826843262 ], [ "蓄", -12.489133834838867 ], [ "▁ラビ", -12.489290237426758 ], [ "▁玲", -12.489317893981934 ], [ "▁シグネチャ", -12.489341735839844 ], [ "▁軌跡", -12.489358901977539 ], [ "▁アレクサンドル", -12.48942756652832 ], [ "錦", -12.489471435546875 ], [ "▁こんで", -12.489500999450684 ], [ "▁マスト", -12.489596366882324 ], [ "▁そっち", -12.489622116088867 ], [ "▁book", -12.489907264709473 ], [ "THE", -12.48993968963623 ], [ "▁フレンズ", -12.490090370178223 ], [ "▁クランク", -12.490105628967285 ], [ "カリフォルニア", -12.490283012390137 ], [ "▁転校", -12.490307807922363 ], [ "絶対", -12.490372657775879 ], [ "▁Minecraft", -12.490438461303711 ], [ "または", -12.490449905395508 ], [ "▁じゃん", -12.490452766418457 ], [ "▁げな", -12.490554809570312 ], [ "▁メロディー", -12.490687370300293 ], [ "▁文字通り", -12.490692138671875 ], [ "▁ブリティッシュ", -12.490752220153809 ], [ "▁フェンス", -12.490764617919922 ], [ "▁淡水", -12.490952491760254 ], [ "隋", -12.491222381591797 ], [ "▁突出", -12.491348266601562 ], [ "クリー", -12.491442680358887 ], [ "▁何とも", -12.491509437561035 ], [ "▁パナマ", -12.491545677185059 ], [ "▁平地", -12.491555213928223 ], [ "▁控えめ", -12.491684913635254 ], [ "▁More", -12.491820335388184 ], [ "▁バックス", -12.4918212890625 ], [ "▁秘訣", -12.491853713989258 ], [ "▁栄誉", -12.491888046264648 ], [ "▁バスケ", -12.49206829071045 ], [ "ANT", -12.492071151733398 ], [ "1914", -12.492077827453613 ], [ "ツール", -12.492094039916992 ], [ "▁Translate", -12.49223518371582 ], [ "▁四日市", -12.492321968078613 ], [ "▁ナチ", -12.492369651794434 ], [ "▁止まる", -12.492371559143066 ], [ "▁導か", -12.492391586303711 ], [ "▁テレワーク", -12.492417335510254 ], [ "▁クラッチ", -12.49243450164795 ], [ "▁1869", -12.492457389831543 ], [ "▁税率", -12.492558479309082 ], [ "cur", -12.492565155029297 ], [ "▁RNA", -12.492631912231445 ], [ "rie", -12.492673873901367 ], [ "▁イヌ", -12.492712020874023 ], [ "▁スカル", -12.492727279663086 ], [ "▁留置", -12.493053436279297 ], [ "之介", -12.493115425109863 ], [ "▁親しく", -12.49335765838623 ], [ "▁モロ", -12.493377685546875 ], [ "▁整骨", -12.493407249450684 ], [ "バージョン", -12.493444442749023 ], [ "▁グーグル", -12.49345588684082 ], [ "don", -12.493470191955566 ], [ "▁水晶", -12.493577003479004 ], [ "汐", -12.49357795715332 ], [ "▁次女", -12.4935884475708 ], [ "桑", -12.493729591369629 ], [ "▁クラウ", -12.493732452392578 ], [ "ジム", -12.493824005126953 ], [ "▁配色", -12.49403190612793 ], [ "▁Macintosh", -12.494050025939941 ], [ "▁コンソール", -12.494128227233887 ], [ "▁露天", -12.49422836303711 ], [ "▁同点", -12.494244575500488 ], [ "▁豊後", -12.494295120239258 ], [ "▁貰え", -12.49431037902832 ], [ "▁平凡", -12.494409561157227 ], [ "▁Es", -12.494458198547363 ], [ "tional", -12.49448013305664 ], [ "憤", -12.494522094726562 ], [ "土地", -12.494657516479492 ], [ "▁賄", -12.494660377502441 ], [ "▁付け加え", -12.49466609954834 ], [ "フェルト", -12.49484634399414 ], [ "フレンド", -12.49484634399414 ], [ "▁アンドリュー", -12.4949369430542 ], [ "▁アクティビティ", -12.495152473449707 ], [ "フェイス", -12.495187759399414 ], [ "素人", -12.495195388793945 ], [ "▁若狭", -12.495217323303223 ], [ "▁冷戦", -12.495246887207031 ], [ "▁人称", -12.495262145996094 ], [ "▁薬師", -12.495428085327148 ], [ "▁inter", -12.495431900024414 ], [ "▁手塚", -12.49572467803955 ], [ "▁名言", -12.495843887329102 ], [ "ユニット", -12.49584674835205 ], [ "▁大作", -12.495885848999023 ], [ "▁無くなって", -12.495942115783691 ], [ "▁頂戴", -12.495946884155273 ], [ "▁姪", -12.495952606201172 ], [ "▁感激", -12.49599838256836 ], [ "▁築城", -12.496304512023926 ], [ "▁香料", -12.496343612670898 ], [ "▁無制限", -12.496413230895996 ], [ "▁邑", -12.496440887451172 ], [ "▁ラブライブ", -12.496492385864258 ], [ "uf", -12.496519088745117 ], [ "款", -12.49653434753418 ], [ "淑", -12.496570587158203 ], [ "▁消した", -12.496596336364746 ], [ "香港", -12.496612548828125 ], [ "▁武術", -12.49665641784668 ], [ "▁趣", -12.496688842773438 ], [ "▁あがり", -12.496918678283691 ], [ "▁やすかった", -12.49696159362793 ], [ "トイ", -12.496987342834473 ], [ "▁全曲", -12.497036933898926 ], [ "▁抱えた", -12.497044563293457 ], [ "多分", -12.497062683105469 ], [ "▁リタ", -12.497127532958984 ], [ "ヒョン", -12.497178077697754 ], [ "▁途切れ", -12.497201919555664 ], [ "膏", -12.497201919555664 ], [ "伊豆", -12.497454643249512 ], [ "▁163", -12.497687339782715 ], [ "▁楽しんだ", -12.49770736694336 ], [ "▁リベ", -12.497719764709473 ], [ "▁河合", -12.497735023498535 ], [ "スラフ", -12.497857093811035 ], [ "競走", -12.497928619384766 ], [ "style", -12.49796199798584 ], [ "ねん", -12.497966766357422 ], [ "▁出陣", -12.49799919128418 ], [ "▁多種多様な", -12.498031616210938 ], [ "▁産経", -12.498154640197754 ], [ "鷲", -12.49821949005127 ], [ "▁無理だ", -12.498270034790039 ], [ "▁公営", -12.498300552368164 ], [ "お互い", -12.498534202575684 ], [ "▁逆襲", -12.498602867126465 ], [ "▁アコースティック", -12.498781204223633 ], [ "▁ダイバー", -12.498891830444336 ], [ "マリア", -12.49890422821045 ], [ "▁林業", -12.498908996582031 ], [ "▁言論", -12.498936653137207 ], [ "▁サイクリング", -12.49909782409668 ], [ "▁ファブリック", -12.49909782409668 ], [ "翠", -12.49909782409668 ], [ "▁贈", -12.499114990234375 ], [ "▁煙突", -12.499115943908691 ], [ "⇒", -12.49917221069336 ], [ "渉", -12.499238014221191 ], [ "▁暖か", -12.499238967895508 ], [ "▁大日", -12.499272346496582 ], [ "▁ピル", -12.499459266662598 ], [ "▁人件", -12.499532699584961 ], [ "▁のりば", -12.499686241149902 ], [ "小林", -12.499946594238281 ], [ "▁清算", -12.499975204467773 ], [ "▁その頃", -12.49998664855957 ], [ "触", -12.500039100646973 ], [ "▁海運", -12.500054359436035 ], [ "▁退屈", -12.500069618225098 ], [ "▁渡して", -12.50007152557373 ], [ "▁長老", -12.50011157989502 ], [ "▁漏", -12.500312805175781 ], [ "ヴン", -12.500364303588867 ], [ "▁セラミック", -12.500382423400879 ], [ "▁プッシュ", -12.500598907470703 ], [ "▁精製", -12.500646591186523 ], [ "▁貸与", -12.500703811645508 ], [ "▁むか", -12.500739097595215 ], [ "▁替える", -12.500781059265137 ], [ "▁即時", -12.500804901123047 ], [ "▁シップ", -12.500969886779785 ], [ "▁内緒", -12.501065254211426 ], [ "ハート", -12.501193046569824 ], [ "▁稼動", -12.501211166381836 ], [ "▁なんの", -12.50122356414795 ], [ "冒", -12.501250267028809 ], [ "▁遭い", -12.501313209533691 ], [ "悶", -12.501313209533691 ], [ "▁堂々と", -12.501537322998047 ], [ "▁硬く", -12.501542091369629 ], [ "▁入園", -12.501585006713867 ], [ "▁やたら", -12.501667022705078 ], [ "▁大差", -12.501753807067871 ], [ "寵", -12.501789093017578 ], [ "ITE", -12.501816749572754 ], [ "ique", -12.501970291137695 ], [ "▁真宗", -12.501989364624023 ], [ "▁太い", -12.50200080871582 ], [ "▁ピンサロ", -12.502105712890625 ], [ "▁備わって", -12.502105712890625 ], [ "▁県警", -12.502123832702637 ], [ "ソク", -12.502211570739746 ], [ "▁パルコ", -12.502232551574707 ], [ "▁宝物", -12.502275466918945 ], [ "▁玲奈", -12.502455711364746 ], [ "▁刷新", -12.502500534057617 ], [ "▁WWE", -12.502511024475098 ], [ "空港", -12.502514839172363 ], [ "▁ローリング", -12.5026216506958 ], [ "▁削り", -12.502659797668457 ], [ "めば", -12.50271224975586 ], [ "ぐん", -12.502787590026855 ], [ "▁パーカ", -12.502799987792969 ], [ "▁締切", -12.502910614013672 ], [ "▁ひで", -12.502951622009277 ], [ "剃", -12.503211975097656 ], [ "▁インスト", -12.503267288208008 ], [ "▁1894", -12.503499031066895 ], [ "ZZ", -12.503562927246094 ], [ "りゅう", -12.50361156463623 ], [ "JavaScript", -12.503645896911621 ], [ "▁純粋に", -12.503694534301758 ], [ "▁度合い", -12.50375747680664 ], [ "ついでに", -12.50377368927002 ], [ "▁十五", -12.50381088256836 ], [ "▁期して", -12.503888130187988 ], [ "▁テイク", -12.503971099853516 ], [ "なかでも", -12.504019737243652 ], [ "▁エクステリア", -12.50407886505127 ], [ "▁発散", -12.504098892211914 ], [ "↑", -12.504129409790039 ], [ "▁注いで", -12.504220008850098 ], [ "▁完璧に", -12.504257202148438 ], [ "ドッグ", -12.504273414611816 ], [ "▁修学", -12.504584312438965 ], [ "響", -12.504831314086914 ], [ "ハウ", -12.504928588867188 ], [ "▁長門", -12.504944801330566 ], [ "▁コモンズ", -12.504986763000488 ], [ "市場", -12.505206108093262 ], [ "▁爆笑", -12.505219459533691 ], [ "▁ペンダント", -12.505230903625488 ], [ "▁故意", -12.505399703979492 ], [ "▁テイクアウト", -12.505456924438477 ], [ "袖", -12.505459785461426 ], [ "▁改宗", -12.50546646118164 ], [ "▁ヒゲ", -12.50550651550293 ], [ "▁テレビジョン", -12.505598068237305 ], [ "▁釜山", -12.505603790283203 ], [ "HY", -12.506072044372559 ], [ "旋", -12.506077766418457 ], [ "▁トランペット", -12.506094932556152 ], [ "bot", -12.506101608276367 ], [ "▁除けば", -12.506103515625 ], [ "place", -12.506148338317871 ], [ "▁漂う", -12.5062255859375 ], [ "虜", -12.506231307983398 ], [ "▁スバル", -12.506248474121094 ], [ "▁ラバー", -12.50639533996582 ], [ "異名", -12.506720542907715 ], [ "▁WD", -12.506840705871582 ], [ "▁震度", -12.506875991821289 ], [ "▁日誌", -12.506942749023438 ], [ "▁数える", -12.50710391998291 ], [ "▁松島", -12.507107734680176 ], [ "▁筋力", -12.507119178771973 ], [ "ジェネ", -12.507242202758789 ], [ "▁ハーバー", -12.507292747497559 ], [ "美子", -12.507325172424316 ], [ "▁不正な", -12.507416725158691 ], [ "YU", -12.507418632507324 ], [ "▁min", -12.507523536682129 ], [ "night", -12.507572174072266 ], [ "という", -12.50760555267334 ], [ "▁こっそり", -12.507672309875488 ], [ "▁初音", -12.507725715637207 ], [ "医師", -12.507776260375977 ], [ "even", -12.507830619812012 ], [ "▁高句麗", -12.507831573486328 ], [ "▁発した", -12.507865905761719 ], [ "譲", -12.507980346679688 ], [ "▁団結", -12.507988929748535 ], [ "▁Fa", -12.507993698120117 ], [ "▁総統", -12.508193016052246 ], [ "▁敷き", -12.50828742980957 ], [ "▁セメント", -12.508368492126465 ], [ "▁歩いた", -12.508402824401855 ], [ "ログイン", -12.508405685424805 ], [ "世の中", -12.508462905883789 ], [ "▁三味線", -12.508469581604004 ], [ "▁帯広", -12.508519172668457 ], [ "CNSA", -12.508520126342773 ], [ "▁いかがです", -12.508541107177734 ], [ "▁応えて", -12.508580207824707 ], [ "▁return", -12.50862979888916 ], [ "▁ソラ", -12.508631706237793 ], [ "▁BLACK", -12.508971214294434 ], [ "▁ジャガー", -12.508995056152344 ], [ "▁部落", -12.509048461914062 ], [ "▁コンゴ", -12.509113311767578 ], [ "▁UI", -12.509202003479004 ], [ "フロー", -12.50930404663086 ], [ "▁取れた", -12.509332656860352 ], [ "test", -12.509366989135742 ], [ "▁ミシシッピ", -12.509428024291992 ], [ "▁ミネソタ", -12.509428024291992 ], [ "▁年寄り", -12.50960922241211 ], [ "▁大幅", -12.509744644165039 ], [ "▁サリ", -12.50975227355957 ], [ "▁未熟", -12.50976276397705 ], [ "▁Vista", -12.509770393371582 ], [ "▁本校", -12.509861946105957 ], [ "うん", -12.509907722473145 ], [ "▁高雄", -12.509960174560547 ], [ "▁荒木", -12.509988784790039 ], [ "▁ホセ", -12.510025024414062 ], [ "▁貯蓄", -12.510071754455566 ], [ "▁申立", -12.510151863098145 ], [ "▁くれれば", -12.510270118713379 ], [ "▁強引に", -12.510387420654297 ], [ "▁地主", -12.510409355163574 ], [ "平安", -12.51041030883789 ], [ "込む", -12.510551452636719 ], [ "▁おこし", -12.51064682006836 ], [ "▁定評", -12.510833740234375 ], [ "▁City", -12.510900497436523 ], [ "▁クロウ", -12.5109224319458 ], [ "▁符", -12.51099681854248 ], [ "▁繰", -12.511034965515137 ], [ "同期", -12.511125564575195 ], [ "剛", -12.511134147644043 ], [ "▁配管", -12.511200904846191 ], [ "▁University", -12.511346817016602 ], [ "▁潤い", -12.511505126953125 ], [ "▁ps", -12.51164436340332 ], [ "▁sub", -12.511707305908203 ], [ "▁容易で", -12.511740684509277 ], [ "oko", -12.512118339538574 ], [ "▁スロバキア", -12.51211929321289 ], [ "▁積んだ", -12.512228012084961 ], [ "▁苦しめ", -12.51235294342041 ], [ "▁マカオ", -12.512433052062988 ], [ "INS", -12.512495040893555 ], [ "lit", -12.512514114379883 ], [ "ピエ", -12.51257038116455 ], [ "▁接点", -12.512579917907715 ], [ "▁掘削", -12.512797355651855 ], [ "COLOR", -12.512866973876953 ], [ "▁ズーム", -12.512871742248535 ], [ "▁景品", -12.513072967529297 ], [ "▁溜まって", -12.51310920715332 ], [ "▁縫い", -12.513114929199219 ], [ "▁ショーツ", -12.51318645477295 ], [ "mic", -12.513219833374023 ], [ "クソ", -12.513225555419922 ], [ "▁リラクゼーション", -12.513269424438477 ], [ "キャッチ", -12.513301849365234 ], [ "▁クイック", -12.51333236694336 ], [ "▁調印", -12.513382911682129 ], [ "新宿", -12.513392448425293 ], [ "▁迂回", -12.513429641723633 ], [ "▁ガム", -12.513533592224121 ], [ "▁買おう", -12.513636589050293 ], [ "ティウス", -12.51364517211914 ], [ "▁太刀", -12.513760566711426 ], [ "▁大物", -12.513762474060059 ], [ "エンス", -12.513805389404297 ], [ "▁賛否", -12.514071464538574 ], [ "豚", -12.514110565185547 ], [ "疫", -12.514211654663086 ], [ "武蔵", -12.514318466186523 ], [ "カーズ", -12.514521598815918 ], [ "ベア", -12.514545440673828 ], [ "▁製紙", -12.514570236206055 ], [ "▁当たら", -12.514711380004883 ], [ "▁Flash", -12.514738082885742 ], [ "▁あらわれ", -12.514763832092285 ], [ "キンス", -12.514769554138184 ], [ "プラー", -12.514922142028809 ], [ "▁205", -12.51492691040039 ], [ "▁連行", -12.514989852905273 ], [ "soft", -12.515042304992676 ], [ "▁マーチ", -12.515189170837402 ], [ "ember", -12.515336990356445 ], [ "▁成す", -12.515373229980469 ], [ "▁申し込", -12.515469551086426 ], [ "▁スクウェア", -12.515742301940918 ], [ "▁家政", -12.515751838684082 ], [ "media", -12.515853881835938 ], [ "湊", -12.515896797180176 ], [ "▁本種", -12.515935897827148 ], [ "高田", -12.516000747680664 ], [ "▁カギ", -12.51613712310791 ], [ "▁平原", -12.516203880310059 ], [ "カタ", -12.516246795654297 ], [ "▁名付けた", -12.516281127929688 ], [ "▁無意識", -12.516342163085938 ], [ "▁川島", -12.51646614074707 ], [ "▁スティーブン", -12.516510963439941 ], [ "ダブル", -12.516534805297852 ], [ "▁Master", -12.5165376663208 ], [ "▁以南", -12.516645431518555 ], [ "▁塗る", -12.51665210723877 ], [ "▁目前", -12.516674995422363 ], [ "▁皆無", -12.516797065734863 ], [ "高橋", -12.51683521270752 ], [ "▁祝う", -12.51695728302002 ], [ "▁ハンス", -12.517066955566406 ], [ "▁ファイターズ", -12.517193794250488 ], [ "▁豚肉", -12.517194747924805 ], [ "ヴォー", -12.517239570617676 ], [ "▁訪ねて", -12.517292022705078 ], [ "▁National", -12.51729965209961 ], [ "亮", -12.517352104187012 ], [ "▁掛ける", -12.517358779907227 ], [ "DB", -12.517369270324707 ], [ "▁柔軟に", -12.517380714416504 ], [ "▁並んだ", -12.517472267150879 ], [ "▁岩崎", -12.517561912536621 ], [ "▁出かけた", -12.517620086669922 ], [ "1912", -12.517925262451172 ], [ "▁農産物", -12.51793098449707 ], [ "▁ひょう", -12.518017768859863 ], [ "宰", -12.518113136291504 ], [ "▁被爆", -12.518174171447754 ], [ "▁朧", -12.518309593200684 ], [ "▁部材", -12.518453598022461 ], [ "▁SOFT", -12.518540382385254 ], [ "▁惣菜", -12.518596649169922 ], [ "▁キノコ", -12.51865291595459 ], [ "ゞ", -12.518736839294434 ], [ "▁対局", -12.518796920776367 ], [ "▁東端", -12.518805503845215 ], [ "core", -12.518835067749023 ], [ "▁稼", -12.518853187561035 ], [ "▁見守って", -12.518898963928223 ], [ "▁ボスニア", -12.518954277038574 ], [ "▁羽生", -12.519000053405762 ], [ "▁締", -12.51923656463623 ], [ "ward", -12.519577026367188 ], [ "密集", -12.519608497619629 ], [ "▁キリン", -12.519647598266602 ], [ "▁タール", -12.51970100402832 ], [ "▁ばね", -12.519950866699219 ], [ "▁アムステルダム", -12.520028114318848 ], [ "頓", -12.520173072814941 ], [ "▁因果", -12.520208358764648 ], [ "▁育てた", -12.520312309265137 ], [ "▁大好きです", -12.520366668701172 ], [ "▁見かけた", -12.520408630371094 ], [ "ウィック", -12.520537376403809 ], [ "▁焼いて", -12.520553588867188 ], [ "▁トヨタ自動車", -12.520703315734863 ], [ "▁チタン", -12.52071762084961 ], [ "▁早川", -12.520718574523926 ], [ "▁わざと", -12.52083969116211 ], [ "▁サテライト", -12.520997047424316 ], [ "▁Cap", -12.521020889282227 ], [ "貸", -12.521062850952148 ], [ "正しい", -12.521080017089844 ], [ "▁塗って", -12.521108627319336 ], [ "▁キャピタル", -12.521159172058105 ], [ "▁表した", -12.521191596984863 ], [ "▁エニックス", -12.521242141723633 ], [ "▁国交", -12.521378517150879 ], [ "▁コッ", -12.521389961242676 ], [ "▁アンダーソン", -12.521459579467773 ], [ "▁硫酸", -12.521482467651367 ], [ "▁いっしょに", -12.521491050720215 ], [ "Cl", -12.521577835083008 ], [ "▁一因", -12.52165412902832 ], [ "▁勤める", -12.521673202514648 ], [ "▁一躍", -12.521804809570312 ], [ "▁痴女", -12.521805763244629 ], [ "ミラー", -12.521954536437988 ], [ "▁城下町", -12.521966934204102 ], [ "斯", -12.521966934204102 ], [ "▁養老", -12.522017478942871 ], [ "▁1893", -12.522032737731934 ], [ "ろん", -12.52204704284668 ], [ "ハワイ", -12.522163391113281 ], [ "▁1・2", -12.522192001342773 ], [ "▁同伴", -12.522199630737305 ], [ "▁祖国", -12.522354125976562 ], [ "▁シェイ", -12.522355079650879 ], [ "▁撫で", -12.52245807647705 ], [ "▁童話", -12.522615432739258 ], [ "▁ALL", -12.522639274597168 ], [ "▁閉じる", -12.522660255432129 ], [ "▁信越", -12.522753715515137 ], [ "▁直した", -12.5227689743042 ], [ "▁法政", -12.522787094116211 ], [ "▁芦屋", -12.522953987121582 ], [ "枯", -12.523016929626465 ], [ "美術", -12.523168563842773 ], [ "好き", -12.523226737976074 ], [ "▁響く", -12.523327827453613 ], [ "▁おもい", -12.523422241210938 ], [ "暮れ", -12.52342700958252 ], [ "▁遥かに", -12.523603439331055 ], [ "▁ホウ", -12.5236177444458 ], [ "▁正常な", -12.523900985717773 ], [ "▁1886", -12.524154663085938 ], [ "▁昨", -12.52418041229248 ], [ "▁支所", -12.524236679077148 ], [ "共和", -12.524330139160156 ], [ "▁投げる", -12.524345397949219 ], [ "▁エフェクト", -12.524396896362305 ], [ "▁もっぱら", -12.52441120147705 ], [ "ular", -12.524435997009277 ], [ "omo", -12.524489402770996 ], [ "▁病死", -12.524526596069336 ], [ "▁身の", -12.524537086486816 ], [ "腐", -12.524543762207031 ], [ "▁文言", -12.524682998657227 ], [ "▁献上", -12.524704933166504 ], [ "▁冨", -12.52479076385498 ], [ "▁開場", -12.52480697631836 ], [ "▁今季", -12.524866104125977 ], [ "▁包丁", -12.52490234375 ], [ "ume", -12.524937629699707 ], [ "▁喪", -12.52495002746582 ], [ "▁築地", -12.525017738342285 ], [ "いろいろ", -12.525031089782715 ], [ "ぽん", -12.525113105773926 ], [ "▁Val", -12.525443077087402 ], [ "衆議院", -12.525507926940918 ], [ "▁提督", -12.525532722473145 ], [ "▁栄光", -12.525821685791016 ], [ "▁トーヨー", -12.52591323852539 ], [ "▁BIG", -12.52608871459961 ], [ "▁登って", -12.52610969543457 ], [ "▁採り", -12.526371002197266 ], [ "▁みかん", -12.526503562927246 ], [ "▁打診", -12.526527404785156 ], [ "▁吸引", -12.526542663574219 ], [ "▁舞い", -12.526572227478027 ], [ "▁羽根", -12.526690483093262 ], [ "ASA", -12.526834487915039 ], [ "▁嘉永", -12.52697467803955 ], [ "▁操業", -12.526996612548828 ], [ "▁なにも", -12.527066230773926 ], [ "▁エイジング", -12.527071952819824 ], [ "▁多賀", -12.527115821838379 ], [ "▁延べ", -12.52714729309082 ], [ "▁飽和", -12.5271577835083 ], [ "▁手首", -12.527214050292969 ], [ "▁図形", -12.527223587036133 ], [ "▁活かす", -12.52724552154541 ], [ "フィナステリ", -12.527304649353027 ], [ "クリストファー", -12.527325630187988 ], [ "▁解読", -12.52734088897705 ], [ "▁当てた", -12.527568817138672 ], [ "ボク", -12.527582168579102 ], [ "▁1884", -12.527667045593262 ], [ "ソ連", -12.527684211730957 ], [ "UST", -12.527703285217285 ], [ "▁いただけたら", -12.527809143066406 ], [ "▁後続", -12.52784538269043 ], [ "▁ハック", -12.527923583984375 ], [ "javascript", -12.527971267700195 ], [ "站", -12.527971267700195 ], [ "▁sec", -12.528040885925293 ], [ "人権", -12.52816390991211 ], [ "▁吸血", -12.528202056884766 ], [ "▁水深", -12.528264999389648 ], [ "tain", -12.528302192687988 ], [ "▁節目", -12.528388023376465 ], [ "▁カブ", -12.528398513793945 ], [ "▁セグメント", -12.528459548950195 ], [ "▁佑", -12.528477668762207 ], [ "エピソード", -12.528615951538086 ], [ "▁プラズマ", -12.528724670410156 ], [ "▁灘", -12.528749465942383 ], [ "▁256", -12.528904914855957 ], [ "▁オーブン", -12.528942108154297 ], [ "▁重臣", -12.529088973999023 ], [ "▁公言", -12.5291748046875 ], [ "▁マクロス", -12.529237747192383 ], [ "▁左岸", -12.52925968170166 ], [ "uit", -12.529294967651367 ], [ "▁英訳", -12.529430389404297 ], [ "▁Norton", -12.529437065124512 ], [ "▁代役", -12.529583930969238 ], [ "▁エネルギッシュ", -12.529600143432617 ], [ "ついに", -12.529643058776855 ], [ "▁ビルマ", -12.529682159423828 ], [ "▁替", -12.529690742492676 ], [ "メイド", -12.529691696166992 ], [ "▁ダウ", -12.52969741821289 ], [ "▁トキ", -12.52974796295166 ], [ "▁急激な", -12.529764175415039 ], [ "蒙", -12.529915809631348 ], [ "▁庄内", -12.529961585998535 ], [ "TOP", -12.530007362365723 ], [ "電力", -12.530102729797363 ], [ "▁王族", -12.530238151550293 ], [ "▁ヘッセン", -12.530311584472656 ], [ "▁宇佐", -12.530369758605957 ], [ "運用", -12.530439376831055 ], [ "掌", -12.530460357666016 ], [ "▁擁し", -12.530471801757812 ], [ "▁移送", -12.530484199523926 ], [ "▁反抗", -12.530503273010254 ], [ "▁諸侯", -12.530511856079102 ], [ "優勝", -12.530534744262695 ], [ "どい", -12.530553817749023 ], [ "▁胃腸", -12.530776977539062 ], [ "ious", -12.530839920043945 ], [ "▁扇風機", -12.530904769897461 ], [ "▁熱心な", -12.530909538269043 ], [ "レーヌ", -12.530917167663574 ], [ "▁買取り", -12.531103134155273 ], [ "RON", -12.531146049499512 ], [ "▁様相", -12.531177520751953 ], [ "久しぶりの", -12.531432151794434 ], [ "▁半期", -12.531472206115723 ], [ "▁レッズ", -12.531744956970215 ], [ "eta", -12.531770706176758 ], [ "▁浴びた", -12.531830787658691 ], [ "▁CSS", -12.531851768493652 ], [ "▁乗馬", -12.531861305236816 ], [ "▁同調", -12.53190803527832 ], [ "互", -12.532081604003906 ], [ "▁夜明け", -12.532198905944824 ], [ "▁アレクサンダー", -12.53222942352295 ], [ "川崎", -12.532341003417969 ], [ "▁キエフ", -12.532364845275879 ], [ "ein", -12.532529830932617 ], [ "▁キャスティング", -12.532683372497559 ], [ "fc", -12.53274154663086 ], [ "▁外す", -12.532768249511719 ], [ "ゼロッテ", -12.532773971557617 ], [ "▁灯台", -12.532853126525879 ], [ "荻", -12.53286361694336 ], [ "受け", -12.532903671264648 ], [ "ギル", -12.533021926879883 ], [ "誹謗", -12.533028602600098 ], [ "▁Export", -12.533065795898438 ], [ "▁真面目に", -12.533199310302734 ], [ "▁財閥", -12.533384323120117 ], [ "▁八木", -12.533388137817383 ], [ "▁GHz", -12.533520698547363 ], [ "▁ふら", -12.533537864685059 ], [ "▁四郎", -12.533547401428223 ], [ "▁弦楽", -12.53359317779541 ], [ "▁Gl", -12.533839225769043 ], [ "▁胞子", -12.533853530883789 ], [ "ングス", -12.533927917480469 ], [ "▁逃れる", -12.533936500549316 ], [ "▁判例", -12.533997535705566 ], [ "▁マクミラン", -12.534174919128418 ], [ "▁黄色い", -12.534318923950195 ], [ "ペプチド", -12.534341812133789 ], [ "じつ", -12.534393310546875 ], [ "▁マーカー", -12.534520149230957 ], [ "▁js", -12.534539222717285 ], [ "▁忌", -12.53459644317627 ], [ "750", -12.534662246704102 ], [ "▁イニング", -12.535040855407715 ], [ "▁狙撃", -12.535179138183594 ], [ "▁Top", -12.535233497619629 ], [ "▁風力", -12.535255432128906 ], [ "▁田川", -12.535269737243652 ], [ "▁フレグランス", -12.535321235656738 ], [ "▁元老", -12.535404205322266 ], [ "▁湊", -12.535426139831543 ], [ "▁門司", -12.535441398620605 ], [ "179", -12.535622596740723 ], [ "工業", -12.535630226135254 ], [ "愛媛", -12.535712242126465 ], [ "▁販促", -12.535977363586426 ], [ "▁貝塚", -12.536199569702148 ], [ "症状", -12.536351203918457 ], [ "uji", -12.536385536193848 ], [ "AK", -12.536473274230957 ], [ "爪", -12.536529541015625 ], [ "▁無難", -12.536722183227539 ], [ "▁湿地", -12.536819458007812 ], [ "des", -12.536913871765137 ], [ "▁滴", -12.537114143371582 ], [ "▁陛下", -12.537126541137695 ], [ "▁翌月", -12.537156105041504 ], [ "▁足跡", -12.537346839904785 ], [ "560", -12.537355422973633 ], [ "▁二輪", -12.537487983703613 ], [ "▁血統", -12.537578582763672 ], [ "苦し", -12.537737846374512 ], [ "▁ハンマー", -12.537775039672852 ], [ "▁STORE", -12.537809371948242 ], [ "択", -12.53786563873291 ], [ "▁138", -12.537915229797363 ], [ "丞", -12.537947654724121 ], [ "▁活気", -12.538116455078125 ], [ "▁博した", -12.538128852844238 ], [ "▁Good", -12.538175582885742 ], [ "▁厄介", -12.538276672363281 ], [ "▁機銃", -12.53838062286377 ], [ "▁朔", -12.538424491882324 ], [ "挑", -12.538435935974121 ], [ "實", -12.53844165802002 ], [ "▁両端", -12.53850269317627 ], [ "▁アルバニア", -12.538555145263672 ], [ "▁基底", -12.538565635681152 ], [ "▁態勢", -12.538771629333496 ], [ "エビ", -12.538784980773926 ], [ "▁若松", -12.538800239562988 ], [ "▁勅令", -12.538806915283203 ], [ "▁臨海", -12.538817405700684 ], [ "カウ", -12.538891792297363 ], [ "▁添えて", -12.539022445678711 ], [ "san", -12.539050102233887 ], [ "神経", -12.539201736450195 ], [ "アイドル", -12.53922176361084 ], [ "当院", -12.539477348327637 ], [ "▁メリー", -12.539783477783203 ], [ "▁415", -12.539835929870605 ], [ "▁顕著な", -12.539875984191895 ], [ "▁出掛け", -12.540002822875977 ], [ "▁フローリング", -12.54025650024414 ], [ "▁抜け毛", -12.540277481079102 ], [ "▁浴び", -12.540318489074707 ], [ "▁胚", -12.5403413772583 ], [ "んしゃ", -12.540384292602539 ], [ "ファッション", -12.540413856506348 ], [ "▁抜け出し", -12.540416717529297 ], [ "▁最良の", -12.540417671203613 ], [ "▁ハワード", -12.540434837341309 ], [ "▁スタイ", -12.540515899658203 ], [ "ocal", -12.540553092956543 ], [ "▁Night", -12.540556907653809 ], [ "▁任せる", -12.540611267089844 ], [ "▁HR", -12.540756225585938 ], [ "▁作ったり", -12.540761947631836 ], [ "▁悪意", -12.540770530700684 ], [ "▁改ざん", -12.540775299072266 ], [ "▁大原", -12.540797233581543 ], [ "ゼロ", -12.540865898132324 ], [ "▁可変", -12.541008949279785 ], [ "ノース", -12.5412015914917 ], [ "平均", -12.541382789611816 ], [ "▁重なって", -12.541415214538574 ], [ "▁頼んだ", -12.541426658630371 ], [ "▁坑", -12.541428565979004 ], [ "ili", -12.541479110717773 ], [ "▁チェル", -12.541492462158203 ], [ "スタート", -12.541559219360352 ], [ "▁ろく", -12.5415620803833 ], [ "▁インフォメーション", -12.541735649108887 ], [ "▁リキッド", -12.541763305664062 ], [ "潔", -12.541777610778809 ], [ "珍", -12.541840553283691 ], [ "▁区切り", -12.541940689086914 ], [ "▁ミステリ", -12.541960716247559 ], [ "▁谷川", -12.542023658752441 ], [ "▁温め", -12.542047500610352 ], [ "▁鳴らし", -12.542058944702148 ], [ "▁ヴィラ", -12.542119026184082 ], [ "ヴィエ", -12.542179107666016 ], [ "▁キャベツ", -12.542231559753418 ], [ "150", -12.54234504699707 ], [ "▁定休日", -12.542427062988281 ], [ "本社", -12.54245376586914 ], [ "WR", -12.542533874511719 ], [ "▁メッセ", -12.5425443649292 ], [ "▁cd", -12.542582511901855 ], [ "▁プロペラ", -12.542631149291992 ], [ "ote", -12.54275894165039 ], [ "▁コスパ", -12.542877197265625 ], [ "dom", -12.542913436889648 ], [ "▁クハ", -12.542975425720215 ], [ "▁治す", -12.542984962463379 ], [ "保護", -12.543198585510254 ], [ "▁ペトロ", -12.543274879455566 ], [ "混", -12.543314933776855 ], [ "▁キタ", -12.543427467346191 ], [ "▁失脚", -12.543785095214844 ], [ "▁古事", -12.543865203857422 ], [ "▁脊椎", -12.543883323669434 ], [ "▁華やか", -12.543917655944824 ], [ "▁貸付", -12.544038772583008 ], [ "▁ファイブ", -12.544045448303223 ], [ "▁監禁", -12.544048309326172 ], [ "▁エアー", -12.544087409973145 ], [ "劣", -12.544182777404785 ], [ "▁寺社", -12.54422378540039 ], [ "▁反対に", -12.544301986694336 ], [ "附", -12.544310569763184 ], [ "▁青梅", -12.544502258300781 ], [ "▁ヘルシー", -12.544512748718262 ], [ "▁券売機", -12.54454517364502 ], [ "アゼルバイジャン", -12.54454517364502 ], [ "翅", -12.54454517364502 ], [ "▁常駐", -12.544563293457031 ], [ "▁あいさつ", -12.54458236694336 ], [ "▁大東", -12.544771194458008 ], [ "▁芝生", -12.544788360595703 ], [ "▁反動", -12.54487419128418 ], [ "▁近似", -12.54491901397705 ], [ "▁コープ", -12.544920921325684 ], [ "▁曲げ", -12.545005798339844 ], [ "▁山間", -12.545058250427246 ], [ "ロング", -12.545318603515625 ], [ "▁鶴岡", -12.545326232910156 ], [ "そろ", -12.545448303222656 ], [ "▁ソード", -12.545465469360352 ], [ "チュウ", -12.545466423034668 ], [ "▁はずだった", -12.5454740524292 ], [ "▁チリワック", -12.545537948608398 ], [ "▁Steam", -12.54557991027832 ], [ "▁易い", -12.54564094543457 ], [ "紗", -12.545843124389648 ], [ "▁空いた", -12.545845985412598 ], [ "▁発端", -12.545889854431152 ], [ "▁1885", -12.54595947265625 ], [ "▁シークレット", -12.546035766601562 ], [ "▁カレン", -12.54608154296875 ], [ "芸能", -12.546113967895508 ], [ "餅", -12.546195983886719 ], [ "▁諮問", -12.5462007522583 ], [ "▁支局", -12.546248435974121 ], [ "▁ギネス", -12.546290397644043 ], [ "▁みそ", -12.54642105102539 ], [ "▁ストリーム", -12.546577453613281 ], [ "それゆえ", -12.546586036682129 ], [ "▁日テレ", -12.546630859375 ], [ "▁刷", -12.54666805267334 ], [ "▁rights", -12.54670524597168 ], [ "▁味付け", -12.546795845031738 ], [ "▁美味", -12.54682445526123 ], [ "▁番付", -12.546903610229492 ], [ "▁クローバー", -12.546981811523438 ], [ "▁アリー", -12.547069549560547 ], [ "▁直流", -12.547139167785645 ], [ "▁浪人", -12.547204971313477 ], [ "▁ソール", -12.547245025634766 ], [ "▁スピーディ", -12.54729175567627 ], [ "図書", -12.547423362731934 ], [ "▁ディビシオン", -12.547528266906738 ], [ "▁だくさん", -12.547530174255371 ], [ "▁グリッド", -12.54776668548584 ], [ "▁タダ", -12.547941207885742 ], [ "▁エヌ", -12.547990798950195 ], [ "▁安土", -12.548134803771973 ], [ "▁蔓延", -12.548192024230957 ], [ "▁あいつ", -12.548285484313965 ], [ "▁うっかり", -12.548357963562012 ], [ "▁カタルーニャ", -12.548357963562012 ], [ "昨夜", -12.548420906066895 ], [ "スタジオ", -12.548421859741211 ], [ "▁つとめた", -12.548428535461426 ], [ "▁グラフィックス", -12.548449516296387 ], [ "▁偽造", -12.548467636108398 ], [ "▁宗家", -12.548468589782715 ], [ "tive", -12.548562049865723 ], [ "▁みずほ", -12.54872989654541 ], [ "▁文理", -12.548794746398926 ], [ "▁脱走", -12.548800468444824 ], [ "鴻", -12.548856735229492 ], [ "▁直送", -12.5488862991333 ], [ "深い", -12.548890113830566 ], [ "SNS", -12.548975944519043 ], [ "rim", -12.548991203308105 ], [ "illa", -12.549001693725586 ], [ "▁Technology", -12.549022674560547 ], [ "▁貼ら", -12.54902458190918 ], [ "ルール", -12.549031257629395 ], [ "ジャンル", -12.549090385437012 ], [ "▁冷静", -12.549196243286133 ], [ "▁飼", -12.549225807189941 ], [ "▁名鉄", -12.549256324768066 ], [ "バランス", -12.549287796020508 ], [ "▁スキャンダル", -12.549384117126465 ], [ "▁らしき", -12.549420356750488 ], [ "▁刈谷", -12.54952335357666 ], [ "辻", -12.549858093261719 ], [ "▁死傷", -12.549871444702148 ], [ "ella", -12.550039291381836 ], [ "▁光る", -12.550046920776367 ], [ "▁めざし", -12.550240516662598 ], [ "▁さよなら", -12.55035400390625 ], [ "MIT", -12.550429344177246 ], [ "▁画素", -12.550448417663574 ], [ "AMI", -12.55050277709961 ], [ "▁003", -12.55050277709961 ], [ "▁ストライプ", -12.550520896911621 ], [ "▁心地よい", -12.55070686340332 ], [ "▁晶", -12.55072021484375 ], [ "マウス", -12.550795555114746 ], [ "bit", -12.550909042358398 ], [ "▁触って", -12.550933837890625 ], [ "▁中途", -12.550938606262207 ], [ "▁えび", -12.55097484588623 ], [ "切ら", -12.550996780395508 ], [ "▁就いて", -12.551013946533203 ], [ "▁啓蒙", -12.551027297973633 ], [ "▁火器", -12.551104545593262 ], [ "▁殺菌", -12.551109313964844 ], [ "▁過剰な", -12.551117897033691 ], [ "ーーー", -12.551139831542969 ], [ "▁今治", -12.551167488098145 ], [ "HL", -12.55126953125 ], [ "▁スリランカ", -12.551352500915527 ], [ "▁貼る", -12.551355361938477 ], [ "▁仕上げて", -12.551406860351562 ], [ "▁甘え", -12.551460266113281 ], [ "▁退治", -12.551480293273926 ], [ "▁ブルックリン", -12.55164623260498 ], [ "▁宗派", -12.551657676696777 ], [ "▁タフ", -12.55172061920166 ], [ "霞", -12.551749229431152 ], [ "▁同様である", -12.551847457885742 ], [ "▁取組み", -12.551955223083496 ], [ "▁フィーチャー", -12.552085876464844 ], [ "▁水害", -12.55214786529541 ], [ "▁大仏", -12.552227973937988 ], [ "▁リチウム", -12.552351951599121 ], [ "▁陶芸", -12.552374839782715 ], [ "▁消極", -12.552571296691895 ], [ "▁ピンチ", -12.552587509155273 ], [ "▁カエル", -12.552593231201172 ], [ "▁引き起こした", -12.5526762008667 ], [ "▁官職", -12.55274772644043 ], [ "▁BG", -12.552937507629395 ], [ "Point", -12.552990913391113 ], [ "▁入部", -12.553004264831543 ], [ "▁反復", -12.553019523620605 ], [ "大き", -12.55302906036377 ], [ "▁ワーキング", -12.55305290222168 ], [ "▁上皇", -12.55309009552002 ], [ "▁注ぎ", -12.553221702575684 ], [ "▁野口", -12.553268432617188 ], [ "▁知多", -12.55329418182373 ], [ "▁ペットボトル", -12.553353309631348 ], [ "▁取り消", -12.553478240966797 ], [ "Bl", -12.553494453430176 ], [ "▁エッセンス", -12.553525924682617 ], [ "乾燥", -12.553553581237793 ], [ "▁サウナ", -12.553618431091309 ], [ "▁ナビゲーション", -12.55368709564209 ], [ "▁Net", -12.553727149963379 ], [ "メタル", -12.553744316101074 ], [ "▁ベタ", -12.55374526977539 ], [ "▁1891", -12.553752899169922 ], [ "▁minor", -12.55375862121582 ], [ "▁コミュニティー", -12.553862571716309 ], [ "▁Tu", -12.553956985473633 ], [ "▁くっつ", -12.55408763885498 ], [ "wi", -12.55417537689209 ], [ "ペア", -12.554214477539062 ], [ "▁いわき", -12.55422592163086 ], [ "▁右岸", -12.554350852966309 ], [ "▁dvd", -12.55435562133789 ], [ "全長", -12.554370880126953 ], [ "トヨタ", -12.554438591003418 ], [ "▁レプリカ", -12.554551124572754 ], [ "▁発効", -12.554616928100586 ], [ "連続", -12.554621696472168 ], [ "▁貰い", -12.55469036102295 ], [ "▁カバ", -12.55478572845459 ], [ "▁免責", -12.554879188537598 ], [ "恨み", -12.554895401000977 ], [ "Pa", -12.554899215698242 ], [ "▁ぶどう", -12.554967880249023 ], [ "くろ", -12.555001258850098 ], [ "▁題した", -12.555014610290527 ], [ "▁ローター", -12.555032730102539 ], [ "▁縄", -12.55504035949707 ], [ "▁川西", -12.555045127868652 ], [ "▁佐倉", -12.555072784423828 ], [ "▁給湯", -12.555076599121094 ], [ "▁ソロモン", -12.555191040039062 ], [ "▁クライマックス", -12.55520248413086 ], [ "▁少なくて", -12.555243492126465 ], [ "クォ", -12.555282592773438 ], [ "▁自伝", -12.555362701416016 ], [ "▁ケルン", -12.555364608764648 ], [ "サギ", -12.555511474609375 ], [ "▁2023", -12.555534362792969 ], [ "和歌山", -12.555575370788574 ], [ "▁思ったり", -12.555630683898926 ], [ "▁あー", -12.555670738220215 ], [ "DH", -12.555764198303223 ], [ "▁絶景", -12.555939674377441 ], [ "▁交えて", -12.556063652038574 ], [ "▁JC", -12.556090354919434 ], [ "JA", -12.556169509887695 ], [ "в", -12.556194305419922 ], [ "▁生まれ変わ", -12.556641578674316 ], [ "腿", -12.556697845458984 ], [ "▁ノートン", -12.556741714477539 ], [ "▁あし", -12.556829452514648 ], [ "▁くだ", -12.556912422180176 ], [ "曳", -12.557031631469727 ], [ " ", -12.557032585144043 ], [ "▁逝去", -12.557032585144043 ], [ "コーヒー", -12.557072639465332 ], [ "▁隔て", -12.557119369506836 ], [ "▁兄ちゃん", -12.557138442993164 ], [ "▁秋季", -12.55716323852539 ], [ "▁タックル", -12.55720043182373 ], [ "▁アルカリ", -12.55721664428711 ], [ "ウィリアム", -12.55743408203125 ], [ "▁∞", -12.557474136352539 ], [ "▁マーガレット", -12.557535171508789 ], [ "uku", -12.557547569274902 ], [ "▁ボーン", -12.557650566101074 ], [ "デオ", -12.557689666748047 ], [ "▁この先", -12.557698249816895 ], [ "▁仕上がって", -12.557703018188477 ], [ "▁コンサル", -12.55774211883545 ], [ "▁ごめんなさい", -12.557744026184082 ], [ "▁挟み", -12.55787181854248 ], [ "▁520", -12.55799674987793 ], [ "▁イルカ", -12.558099746704102 ], [ "▁通達", -12.558128356933594 ], [ "ぼく", -12.558131217956543 ], [ "▁おっしゃって", -12.558207511901855 ], [ "▁城壁", -12.55832576751709 ], [ "▁しょうがない", -12.558374404907227 ], [ "▁インターフェース", -12.558374404907227 ], [ "▁時効", -12.558426856994629 ], [ "▁しっとり", -12.558709144592285 ], [ "▁前夜", -12.558774948120117 ], [ "飲み", -12.558823585510254 ], [ "▁フレデリック", -12.558877944946289 ], [ "▁永禄", -12.558911323547363 ], [ "▁咲か", -12.559159278869629 ], [ "1900", -12.559189796447754 ], [ "▁商法", -12.559200286865234 ], [ "みや", -12.559226036071777 ], [ "ツィオ", -12.55924129486084 ], [ "兄弟", -12.559342384338379 ], [ "▁減速", -12.55935287475586 ], [ "▁全文", -12.55950927734375 ], [ "太田", -12.55953598022461 ], [ "▁AZ", -12.559618949890137 ], [ "項", -12.55963134765625 ], [ "▁満たない", -12.559649467468262 ], [ "▁絶好", -12.559656143188477 ], [ "▁永田", -12.559685707092285 ], [ "▁輝いて", -12.559696197509766 ], [ "▁チャイルド", -12.559885025024414 ], [ "▁Get", -12.559986114501953 ], [ "一応", -12.560111045837402 ], [ "▁半球", -12.56011962890625 ], [ "▁クラリネット", -12.560220718383789 ], [ "いよいよ", -12.560311317443848 ], [ "graph", -12.560380935668945 ], [ "応募", -12.560486793518066 ], [ "▁トレイル", -12.560493469238281 ], [ "▁リタイア", -12.560574531555176 ], [ "▁防護", -12.56069278717041 ], [ "富良野", -12.560729026794434 ], [ "▁室蘭", -12.560813903808594 ], [ "1910", -12.560907363891602 ], [ "ぼん", -12.560933113098145 ], [ "▁兄さん", -12.56101131439209 ], [ "mar", -12.56103515625 ], [ "▁windows", -12.561058044433594 ], [ "▁パワフル", -12.561229705810547 ], [ "ヨコハマタイヤ", -12.561325073242188 ], [ "小学", -12.561344146728516 ], [ "▁ブン", -12.561380386352539 ], [ "▁一転", -12.561477661132812 ], [ "▁ビューティ", -12.561554908752441 ], [ "▁なくちゃ", -12.561700820922852 ], [ "▁まともに", -12.561735153198242 ], [ "▁オットー", -12.561747550964355 ], [ "▁衣料", -12.561761856079102 ], [ "▁セダン", -12.562078475952148 ], [ "劉", -12.562336921691895 ], [ "▁果たせ", -12.562418937683105 ], [ "▁Sound", -12.562446594238281 ], [ "▁1888", -12.562503814697266 ], [ "スティン", -12.562694549560547 ], [ "yc", -12.562857627868652 ], [ "▁留まる", -12.562888145446777 ], [ "誓", -12.56289291381836 ], [ "▁返送", -12.562943458557129 ], [ "▁重要で", -12.562980651855469 ], [ "いろんな", -12.56302547454834 ], [ "▁気付いて", -12.563042640686035 ], [ "▁交配", -12.563136100769043 ], [ "▁カイロ", -12.563149452209473 ], [ "▁公司", -12.56316089630127 ], [ "▁おまけ", -12.563166618347168 ], [ "ria", -12.56318187713623 ], [ "ible", -12.563331604003906 ], [ "▁磐", -12.563346862792969 ], [ "▁大石", -12.563458442687988 ], [ "▁没頭", -12.56351089477539 ], [ "▁Award", -12.563667297363281 ], [ "▁流れた", -12.563685417175293 ], [ "▁励まし", -12.563775062561035 ], [ "▁供与", -12.563785552978516 ], [ "▁ハッチ", -12.563820838928223 ], [ "▁アーマード", -12.564530372619629 ], [ "▁木星", -12.564541816711426 ], [ "▁摂政", -12.564574241638184 ], [ "▁パウロ", -12.564769744873047 ], [ "▁悩んだ", -12.564793586730957 ], [ "▁GC", -12.564961433410645 ], [ "▁列挙", -12.56503963470459 ], [ "▁絶大な", -12.565109252929688 ], [ "▁オレゴン", -12.565170288085938 ], [ "▁ツボ", -12.565177917480469 ], [ "▁歌人", -12.565258026123047 ], [ "▁イオンモール", -12.565321922302246 ], [ "▁寄進", -12.565375328063965 ], [ "▁おなじみ", -12.565444946289062 ], [ "撒", -12.565444946289062 ], [ "▁母校", -12.565472602844238 ], [ "▁着信", -12.565476417541504 ], [ "▁よそ", -12.565484046936035 ], [ "▁冠した", -12.565510749816895 ], [ "▁丸の内", -12.5656156539917 ], [ "野球", -12.565733909606934 ], [ "駅舎", -12.565808296203613 ], [ "USE", -12.565876007080078 ], [ "▁悦", -12.565882682800293 ], [ "▁コロムビア", -12.56595230102539 ], [ "▁百科事典", -12.566121101379395 ], [ "前者", -12.566205024719238 ], [ "マック", -12.566283226013184 ], [ "ブレイ", -12.566428184509277 ], [ "▁抑えた", -12.566548347473145 ], [ "▁二郎", -12.56676197052002 ], [ "食品", -12.566802024841309 ], [ "▁遂げる", -12.56684684753418 ], [ "惟", -12.56696605682373 ], [ "▁ニュアンス", -12.566967010498047 ], [ "▁アイスクリーム", -12.566975593566895 ], [ "▁シックス", -12.567084312438965 ], [ "▁モノクロ", -12.567122459411621 ], [ "▁洋楽", -12.56716251373291 ], [ "▁かゆ", -12.567183494567871 ], [ "赦", -12.567458152770996 ], [ "相談", -12.567537307739258 ], [ "妊", -12.567670822143555 ], [ "遷", -12.56781005859375 ], [ "▁使徒", -12.56785774230957 ], [ "▁噴出", -12.567863464355469 ], [ "▁弔", -12.56786823272705 ], [ "▁失望", -12.567899703979492 ], [ "欽", -12.56798267364502 ], [ "▁有線", -12.568231582641602 ], [ "▁椎名", -12.568325996398926 ], [ "iP", -12.568367004394531 ], [ "▁贈与", -12.568501472473145 ], [ "▁コンパニオン", -12.568660736083984 ], [ "car", -12.568704605102539 ], [ "▁ヤツ", -12.568792343139648 ], [ "▁窪", -12.568869590759277 ], [ "ブラジル", -12.568872451782227 ], [ "▁平定", -12.568916320800781 ], [ "▁祭神", -12.568933486938477 ], [ "喰", -12.568951606750488 ], [ "癒", -12.569039344787598 ], [ "▁アダプター", -12.569087028503418 ], [ "▁産卵", -12.569100379943848 ], [ "▁バイマ", -12.569120407104492 ], [ "โ", -12.569169044494629 ], [ "▁直ぐに", -12.569169998168945 ], [ "爺", -12.569169998168945 ], [ "▁6,000", -12.56932544708252 ], [ "ニチ", -12.569440841674805 ], [ "▁tv", -12.569552421569824 ], [ "▁幼虫", -12.569555282592773 ], [ "▁ナカ", -12.56955623626709 ], [ "▁ミドリ", -12.569599151611328 ], [ "▁始発", -12.569616317749023 ], [ "▁始末", -12.569717407226562 ], [ "▁拾い", -12.56973648071289 ], [ "▁置き換える", -12.569873809814453 ], [ "▁複雑に", -12.569999694824219 ], [ "看", -12.570040702819824 ], [ "▁ひいて", -12.570085525512695 ], [ "▁演目", -12.57037353515625 ], [ "▁シンク", -12.57044506072998 ], [ "厚生", -12.570635795593262 ], [ "▁ニール", -12.570758819580078 ], [ "▁ハイキング", -12.570762634277344 ], [ "▁待望", -12.570783615112305 ], [ "人数", -12.571003913879395 ], [ "▁KING", -12.571023941040039 ], [ "▁真言宗", -12.571036338806152 ], [ "▁ウォルト", -12.57113265991211 ], [ "詳", -12.571133613586426 ], [ "クリーブランド", -12.571138381958008 ], [ "▁Player", -12.571176528930664 ], [ "▁信任", -12.571184158325195 ], [ "▁活力", -12.571250915527344 ], [ "▁限る", -12.571487426757812 ], [ "▁要注意", -12.571587562561035 ], [ "▁味わえる", -12.571637153625488 ], [ "▁Development", -12.57171630859375 ], [ "SCO", -12.571745872497559 ], [ "▁MIN", -12.571752548217773 ], [ "▁トロフィー", -12.571789741516113 ], [ "けれども", -12.571808815002441 ], [ "▁裕福な", -12.571890830993652 ], [ "完成", -12.571905136108398 ], [ "▁蒸留", -12.571907997131348 ], [ "はん", -12.571920394897461 ], [ "ベトナム", -12.57207202911377 ], [ "▁吉岡", -12.572073936462402 ], [ "▁コンプリート", -12.572226524353027 ], [ "後者", -12.572266578674316 ], [ "▁健診", -12.572309494018555 ], [ "▁難い", -12.572378158569336 ], [ "于", -12.572392463684082 ], [ "▁岡村", -12.572576522827148 ], [ "▁急死", -12.572591781616211 ], [ "▁温か", -12.572656631469727 ], [ "▁ベット", -12.572662353515625 ], [ "▁Plan", -12.572681427001953 ], [ "厄", -12.572736740112305 ], [ "鯉", -12.572736740112305 ], [ "▁大江", -12.57284927368164 ], [ "DAY", -12.572869300842285 ], [ "っちゃん", -12.572891235351562 ], [ "▁末日", -12.572920799255371 ], [ "電車", -12.5729341506958 ], [ "ジカ", -12.57295036315918 ], [ "ior", -12.572969436645508 ], [ "▁倒れた", -12.573044776916504 ], [ "▁攻防", -12.573077201843262 ], [ "▁潔", -12.573137283325195 ], [ "賓", -12.573247909545898 ], [ "▁あゆみ", -12.573418617248535 ], [ "▁reserved", -12.573588371276855 ], [ "▁全権", -12.573603630065918 ], [ "▁研磨", -12.573777198791504 ], [ "トーン", -12.573819160461426 ], [ "借金", -12.573884010314941 ], [ "▁待ち合わせ", -12.573933601379395 ], [ "▁Au", -12.574009895324707 ], [ "漬", -12.57406234741211 ], [ "▁健一", -12.574068069458008 ], [ "NH", -12.574080467224121 ], [ "保育", -12.57411003112793 ], [ "▁オーシャン", -12.574112892150879 ], [ "ZO", -12.574117660522461 ], [ "▁金具", -12.574302673339844 ], [ "▁1892", -12.57433795928955 ], [ "▁就学", -12.57441520690918 ], [ "▁目の当たり", -12.57461166381836 ], [ "▁飛び出し", -12.574633598327637 ], [ "ジャケット", -12.57475471496582 ], [ "滋", -12.574920654296875 ], [ "樫", -12.574952125549316 ], [ "▁OH", -12.575109481811523 ], [ "▁伝導", -12.575175285339355 ], [ "オット", -12.575233459472656 ], [ "伊勢", -12.575246810913086 ], [ "単に", -12.57526683807373 ], [ "▁抑圧", -12.57529354095459 ], [ "▁共済", -12.57535457611084 ], [ "NET", -12.575416564941406 ], [ "▁値引き", -12.575416564941406 ], [ "▁トバ", -12.575470924377441 ], [ "▁プロバイダ", -12.575509071350098 ], [ "▁エスト", -12.575630187988281 ], [ "▁ウィー", -12.575658798217773 ], [ "▁アトリ", -12.575695991516113 ], [ "▁いらっしゃ", -12.575753211975098 ], [ "▁アンカー", -12.575876235961914 ], [ "▁ラグーン", -12.575918197631836 ], [ "阪神", -12.576014518737793 ], [ "ホス", -12.576019287109375 ], [ "▁離陸", -12.576045036315918 ], [ "▁BT", -12.576112747192383 ], [ "▁SG", -12.57614517211914 ], [ "ゴルフ", -12.576257705688477 ], [ "ガード", -12.576274871826172 ], [ "▁筈", -12.57632827758789 ], [ "▁建材", -12.576333045959473 ], [ "▁蓄え", -12.57636833190918 ], [ "悲", -12.576438903808594 ], [ "▁フィレンツェ", -12.576488494873047 ], [ "▁外資", -12.576523780822754 ], [ "▁締めくく", -12.576836585998535 ], [ "▁忠実に", -12.576841354370117 ], [ "耐", -12.576841354370117 ], [ "ニキ", -12.576944351196289 ], [ "▁心境", -12.576953887939453 ], [ "▁賢い", -12.57713508605957 ], [ "▁筑後", -12.577173233032227 ], [ "▁非公式", -12.577188491821289 ], [ "▁アイロン", -12.577315330505371 ], [ "冥", -12.57734203338623 ], [ "▁暑く", -12.577360153198242 ], [ "▁ムン", -12.577465057373047 ], [ "▁私鉄", -12.577466011047363 ], [ "クルー", -12.577508926391602 ], [ "〒", -12.577576637268066 ], [ "ショッピング", -12.577594757080078 ], [ "▁打ち切", -12.577706336975098 ], [ "▁天草", -12.577733039855957 ], [ "山梨", -12.577739715576172 ], [ "▁そっと", -12.577858924865723 ], [ "▁誘う", -12.577902793884277 ], [ "▁放射能", -12.578042030334473 ], [ "▁八尾", -12.578042984008789 ], [ "▁採点", -12.578060150146484 ], [ "yahoo", -12.57806396484375 ], [ "開幕", -12.57806396484375 ], [ "▁従属", -12.578177452087402 ], [ "▁祭祀", -12.578234672546387 ], [ "▁相棒", -12.578292846679688 ], [ "▁属す", -12.578385353088379 ], [ "ISH", -12.578486442565918 ], [ "乞", -12.578537940979004 ], [ "詮", -12.578540802001953 ], [ "WI", -12.57857608795166 ], [ "▁その方", -12.57862377166748 ], [ "ッチャ", -12.578643798828125 ], [ "▁従った", -12.578715324401855 ], [ "▁新庄", -12.578728675842285 ], [ "▁兎", -12.578865051269531 ], [ "掛かり", -12.578871726989746 ], [ "time", -12.579156875610352 ], [ "ius", -12.579202651977539 ], [ "▁ベロ", -12.579292297363281 ], [ "▁三鷹", -12.579388618469238 ], [ "▁宜", -12.579465866088867 ], [ "ORY", -12.57949447631836 ], [ "▁或", -12.579619407653809 ], [ "▁内訳", -12.579812049865723 ], [ "▁同志", -12.579855918884277 ], [ "▁土屋", -12.579858779907227 ], [ "フロント", -12.579890251159668 ], [ "箇", -12.579910278320312 ], [ "▁痙攣", -12.579911231994629 ], [ "アルコール", -12.579933166503906 ], [ "イラスト", -12.580338478088379 ], [ "▁郭", -12.580348014831543 ], [ "瓜", -12.580425262451172 ], [ "禰", -12.580425262451172 ], [ "獲", -12.580495834350586 ], [ "▁西岸", -12.580519676208496 ], [ "▁なれた", -12.58056640625 ], [ "▁除菌", -12.58064079284668 ], [ "▁漁港", -12.580645561218262 ], [ "▁戦果", -12.5807466506958 ], [ "▁痛感", -12.580767631530762 ], [ "▁ストライキ", -12.580770492553711 ], [ "▁優雅", -12.580977439880371 ], [ "▁急便", -12.581083297729492 ], [ "▁移して", -12.58153247833252 ], [ "▁絞って", -12.581544876098633 ], [ "▁ディスカッション", -12.581626892089844 ], [ "▁預言", -12.581626892089844 ], [ "▁抱いた", -12.581806182861328 ], [ "▁鍛える", -12.581815719604492 ], [ "布団", -12.581881523132324 ], [ "▁産婦人科", -12.58197021484375 ], [ "▁辛く", -12.58203125 ], [ "伽", -12.58214282989502 ], [ "▁home", -12.582170486450195 ], [ "▁ミキ", -12.582387924194336 ], [ "▁帰れ", -12.582533836364746 ], [ "▁Char", -12.582541465759277 ], [ "福祉", -12.582611083984375 ], [ "▁大家", -12.58270263671875 ], [ "らかな", -12.582831382751465 ], [ "▁深川", -12.582929611206055 ], [ "ツイート", -12.58297061920166 ], [ "歌詞", -12.58305549621582 ], [ "▁事典", -12.58312702178955 ], [ "▁相馬", -12.58316707611084 ], [ "▁派手な", -12.58317756652832 ], [ "▁たいへん", -12.5831937789917 ], [ "▁鳴り", -12.583194732666016 ], [ "▁止めた", -12.583234786987305 ], [ "以来", -12.58354377746582 ], [ "そん", -12.583633422851562 ], [ "00", -12.583702087402344 ], [ "バトル", -12.583776473999023 ], [ "▁哲也", -12.58379077911377 ], [ "▁バドミントン", -12.583861351013184 ], [ "▁酸味", -12.583990097045898 ], [ "タッチ", -12.584146499633789 ], [ "▁夜行", -12.584157943725586 ], [ "▁出そう", -12.58418083190918 ], [ "▁UFJ", -12.584205627441406 ], [ "▁改行", -12.584296226501465 ], [ "▁染み", -12.584488868713379 ], [ "膿", -12.584550857543945 ], [ "▁カラス", -12.584551811218262 ], [ "▁チャーリー", -12.584633827209473 ], [ "温水", -12.58464241027832 ], [ "▁強行", -12.584710121154785 ], [ "▁遊んだ", -12.584739685058594 ], [ "上品な", -12.584753036499023 ], [ "ウー", -12.584809303283691 ], [ "▁見事な", -12.58481216430664 ], [ "メニュー", -12.584833145141602 ], [ "DD", -12.58499813079834 ], [ "▁バラエティー", -12.585058212280273 ], [ "探", -12.585076332092285 ], [ "ega", -12.585131645202637 ], [ "▁利害", -12.585190773010254 ], [ "あまりに", -12.585198402404785 ], [ "鞘", -12.58523941040039 ], [ "mac", -12.585251808166504 ], [ "▁欠如", -12.585434913635254 ], [ "▁フランシスコ", -12.585508346557617 ], [ "拭", -12.585570335388184 ], [ "▁反逆", -12.585681915283203 ], [ "▁微妙に", -12.585854530334473 ], [ "▁心筋", -12.58590030670166 ], [ "煮", -12.585901260375977 ], [ "▁±", -12.586081504821777 ], [ "▁業態", -12.586174011230469 ], [ "ゅー", -12.586175918579102 ], [ "▁好感", -12.586225509643555 ], [ "▁フレームワーク", -12.586228370666504 ], [ "基礎", -12.586235046386719 ], [ "▁降りる", -12.586237907409668 ], [ "▁パラダイス", -12.586446762084961 ], [ "ノウ", -12.586520195007324 ], [ "▁末裔", -12.586523056030273 ], [ "▁さっそく", -12.586630821228027 ], [ "shin", -12.586655616760254 ], [ "俳優", -12.586763381958008 ], [ "▁Gra", -12.586782455444336 ], [ "▁声楽", -12.586819648742676 ], [ "せき", -12.586874961853027 ], [ "▁終末", -12.587075233459473 ], [ "▁枚方", -12.587096214294434 ], [ "▁1860", -12.587190628051758 ], [ "▁ศ", -12.587214469909668 ], [ "▁松坂", -12.587334632873535 ], [ "境内", -12.58735179901123 ], [ "▁書き下ろし", -12.58736801147461 ], [ "驚", -12.58745288848877 ], [ "▁樺太", -12.587482452392578 ], [ "▁明言", -12.587512016296387 ], [ "▁引き継いで", -12.58768081665039 ], [ "▁社殿", -12.587700843811035 ], [ "◇", -12.587801933288574 ], [ "詔", -12.587827682495117 ], [ "▁American", -12.588001251220703 ], [ "▁十八", -12.588098526000977 ], [ "▁Off", -12.588125228881836 ], [ "▁壮大な", -12.588178634643555 ], [ "泳ぎ", -12.588194847106934 ], [ "▁アルル", -12.58820915222168 ], [ "畳", -12.588323593139648 ], [ "erson", -12.588440895080566 ], [ "▁難しかった", -12.588493347167969 ], [ "▁召し上がり", -12.588528633117676 ], [ "▁担い", -12.588582992553711 ], [ "▁CHA", -12.588664054870605 ], [ "▁競う", -12.588689804077148 ], [ "▁替わり", -12.588711738586426 ], [ "錠", -12.588860511779785 ], [ "脚本", -12.58889389038086 ], [ "▁詩集", -12.588942527770996 ], [ "▁クリーナー", -12.588973045349121 ], [ "男女", -12.589118003845215 ], [ "廊", -12.589138984680176 ], [ "▁スパルタ", -12.589229583740234 ], [ "MF", -12.589380264282227 ], [ "▁当然です", -12.58940601348877 ], [ "献", -12.589461326599121 ], [ "触り", -12.58946418762207 ], [ "▁正直に", -12.58955192565918 ], [ "▁セラピー", -12.589609146118164 ], [ "tage", -12.589635848999023 ], [ "NF", -12.589695930480957 ], [ "▁越谷", -12.589695930480957 ], [ "▁辞める", -12.58979606628418 ], [ "拙", -12.589903831481934 ], [ "▁ハッキリ", -12.589912414550781 ], [ "uni", -12.58993148803711 ], [ "▁アラスカ", -12.589943885803223 ], [ "rand", -12.589982986450195 ], [ "▁法規", -12.590018272399902 ], [ "▁確かめる", -12.590086936950684 ], [ "ener", -12.590145111083984 ], [ "▁下降", -12.590252876281738 ], [ "Me", -12.590354919433594 ], [ "▁描画", -12.590422630310059 ], [ "▁満洲", -12.590583801269531 ], [ "ヽ", -12.590596199035645 ], [ "▁愚痴", -12.590600967407227 ], [ "▁壁面", -12.590621948242188 ], [ "ju", -12.59069538116455 ], [ "▁ウィズ", -12.590726852416992 ], [ "鐵", -12.590768814086914 ], [ "▁囚人", -12.590771675109863 ], [ "▁支えた", -12.590827941894531 ], [ "▁東郷", -12.590903282165527 ], [ "▁短歌", -12.590958595275879 ], [ "▁的でした", -12.591047286987305 ], [ "▁霜", -12.591079711914062 ], [ "ライザー", -12.591146469116211 ], [ "▁あきら", -12.59115219116211 ], [ "▁ミラン", -12.59119987487793 ], [ "▁トークン", -12.591230392456055 ], [ "▁ペレ", -12.5912504196167 ], [ "▁グアム", -12.591275215148926 ], [ "▁血行", -12.591277122497559 ], [ "▁乗せた", -12.591370582580566 ], [ "▁高めた", -12.591593742370605 ], [ "▁月給", -12.591779708862305 ], [ "▁弄", -12.59191608428955 ], [ "lia", -12.591939926147461 ], [ "▁EMI", -12.591985702514648 ], [ "▁んだろ", -12.592061042785645 ], [ "藤原", -12.59209156036377 ], [ "load", -12.592092514038086 ], [ "まさか", -12.592151641845703 ], [ "TION", -12.59232234954834 ], [ "GF", -12.592323303222656 ], [ "▁引っかか", -12.59233570098877 ], [ "▁立ち上げる", -12.592364311218262 ], [ "▁准", -12.592402458190918 ], [ "▁フェルト", -12.59244441986084 ], [ "睦", -12.59268569946289 ], [ "iff", -12.592690467834473 ], [ "▁アドルフ", -12.592694282531738 ], [ "▁サムライ", -12.593045234680176 ], [ "vid", -12.593096733093262 ], [ "▁つもりだった", -12.59313678741455 ], [ "究", -12.593164443969727 ], [ "肝", -12.593207359313965 ], [ "▁公判", -12.593208312988281 ], [ "▁一変", -12.593308448791504 ], [ "▁温室", -12.593426704406738 ], [ "▁ロビン", -12.593490600585938 ], [ "▁ザガーロ", -12.59361457824707 ], [ "(__)", -12.593720436096191 ], [ "▁佐久", -12.593774795532227 ], [ "▁大洋", -12.5938720703125 ], [ "▁感触", -12.593907356262207 ], [ "▁リリーフ", -12.593994140625 ], [ "▁スロベニア", -12.594067573547363 ], [ "奢", -12.594067573547363 ], [ "▁帽", -12.594141006469727 ], [ "▁刀剣", -12.594283103942871 ], [ "▁気付く", -12.594407081604004 ], [ "▁とことん", -12.594422340393066 ], [ "▁先物", -12.594422340393066 ], [ "▁良質な", -12.594590187072754 ], [ "▁呼び名", -12.594701766967773 ], [ "▁鉄鋼", -12.594846725463867 ], [ "▁発案", -12.595090866088867 ], [ "▁鞭", -12.595222473144531 ], [ "▁たかし", -12.595243453979492 ], [ "▁352", -12.595386505126953 ], [ "▁改題", -12.595386505126953 ], [ "聯", -12.595459938049316 ], [ "へい", -12.595532417297363 ], [ "▁ミクロ", -12.595638275146484 ], [ "暇", -12.595687866210938 ], [ "▁加茂", -12.595731735229492 ], [ "face", -12.595747947692871 ], [ "ments", -12.595787048339844 ], [ "終戦", -12.595830917358398 ], [ "▁ジャングル", -12.595968246459961 ], [ "―", -12.595978736877441 ], [ "▁思い切って", -12.595980644226074 ], [ "▁精進", -12.596012115478516 ], [ "▁SSD", -12.596115112304688 ], [ "▁たまり", -12.596141815185547 ], [ "袁", -12.596156120300293 ], [ "▁mail", -12.596171379089355 ], [ "EGA", -12.59618091583252 ], [ "▁192", -12.596206665039062 ], [ "▁Update", -12.596318244934082 ], [ "▁仏像", -12.596375465393066 ], [ "▁負って", -12.596400260925293 ], [ "▁Business", -12.596505165100098 ], [ "▁サバイバル", -12.596505165100098 ], [ "▁四角", -12.596846580505371 ], [ "▁脊髄", -12.596853256225586 ], [ "▁遺品", -12.5968599319458 ], [ "▁造語", -12.596928596496582 ], [ "▁リダイレクト", -12.597027778625488 ], [ "救", -12.597084045410156 ], [ "LAN", -12.59715461730957 ], [ "▁バイキング", -12.597163200378418 ], [ "▁掛かり", -12.597179412841797 ], [ "▁給油", -12.59725570678711 ], [ "▁強姦", -12.5972900390625 ], [ "丼", -12.597294807434082 ], [ "恨", -12.597333908081055 ], [ "▁ブレード", -12.59737491607666 ], [ "呟", -12.597375869750977 ], [ "▁汽船", -12.597376823425293 ], [ "▁ウィング", -12.597396850585938 ], [ "▁完走", -12.597456932067871 ], [ "OX", -12.597468376159668 ], [ "▁1887", -12.597500801086426 ], [ "cha", -12.597511291503906 ], [ "▁こだわる", -12.597513198852539 ], [ "▁豊中", -12.597532272338867 ], [ "▁含", -12.597667694091797 ], [ "▁fo", -12.5977144241333 ], [ "皆", -12.597715377807617 ], [ "▁引き渡", -12.597784996032715 ], [ "牢", -12.597887992858887 ], [ "▁colo", -12.597901344299316 ], [ "諜報", -12.597904205322266 ], [ "▁貰った", -12.597923278808594 ], [ "ふく", -12.598007202148438 ], [ "直接", -12.598063468933105 ], [ "▁廻り", -12.598094940185547 ], [ "▁授賞", -12.598249435424805 ], [ "▁透過", -12.598270416259766 ], [ "▁CBS", -12.598541259765625 ], [ "▁炭水化物", -12.59859848022461 ], [ "▁広州", -12.598747253417969 ], [ "LR", -12.598779678344727 ], [ "▁参列", -12.598833084106445 ], [ "艇", -12.598915100097656 ], [ "▁担った", -12.598953247070312 ], [ "▁民兵", -12.59897518157959 ], [ "mura", -12.599016189575195 ], [ "ライダー", -12.59913444519043 ], [ "▁掌", -12.599278450012207 ], [ "▁整合", -12.599303245544434 ], [ "bra", -12.599329948425293 ], [ "▁ポッド", -12.599390983581543 ], [ "ミィ", -12.599466323852539 ], [ "▁主砲", -12.599503517150879 ], [ "uri", -12.599578857421875 ], [ "ッピ", -12.599625587463379 ], [ "▁安堵", -12.60000228881836 ], [ "▁ニュートン", -12.600013732910156 ], [ "▁思いやり", -12.600027084350586 ], [ "▁ディビジョン", -12.600056648254395 ], [ "▁掘り下げ", -12.600190162658691 ], [ "▁寝た", -12.60022258758545 ], [ "can", -12.600269317626953 ], [ "▁Special", -12.600318908691406 ], [ "▁モスク", -12.600323677062988 ], [ "▁宿題", -12.600499153137207 ], [ "▁尋ねる", -12.600500106811523 ], [ "▁休む", -12.600557327270508 ], [ "▁クック", -12.600573539733887 ], [ "▁ベンダー", -12.60063648223877 ], [ "▁皮脂", -12.600719451904297 ], [ "▁広義", -12.60073471069336 ], [ "▁イーグルス", -12.600749015808105 ], [ "▁Color", -12.60085678100586 ], [ "▁ウーマン", -12.60086441040039 ], [ "▁オペレーション", -12.600872039794922 ], [ "▁Salesforce", -12.601046562194824 ], [ "IMA", -12.601120948791504 ], [ "▁トール", -12.601143836975098 ], [ "▁フィッシング", -12.601282119750977 ], [ "▁GAME", -12.601755142211914 ], [ "OY", -12.601879119873047 ], [ "▁Acrobat", -12.601922035217285 ], [ "▁頭脳", -12.601924896240234 ], [ "未来", -12.601951599121094 ], [ "瑞", -12.602005958557129 ], [ "▁棘", -12.602025032043457 ], [ "▁ポートフォリオ", -12.602097511291504 ], [ "▁スティーブ", -12.602243423461914 ], [ "▁アークティック", -12.602302551269531 ], [ "岩手", -12.602346420288086 ], [ "松山", -12.602435111999512 ], [ "▁ディフェンダー", -12.602448463439941 ], [ "詣", -12.602581024169922 ], [ "▁倣", -12.602684020996094 ], [ "▁親指", -12.602710723876953 ], [ "▁近縁", -12.60272216796875 ], [ "TSU", -12.602747917175293 ], [ "▁つまらない", -12.602799415588379 ], [ "▁筑紫", -12.602799415588379 ], [ "ガラス", -12.602813720703125 ], [ "▁わら", -12.602895736694336 ], [ "lab", -12.602961540222168 ], [ "尹", -12.602974891662598 ], [ "▁複素", -12.60302734375 ], [ "なんだか", -12.603092193603516 ], [ "▁Foundation", -12.603150367736816 ], [ "▁磨く", -12.603365898132324 ], [ "こん", -12.603484153747559 ], [ "▁有益な", -12.603537559509277 ], [ "BT", -12.60356616973877 ], [ "▁結集", -12.603759765625 ], [ "ゃく", -12.603842735290527 ], [ "▁間違えて", -12.60384750366211 ], [ "▁征伐", -12.603859901428223 ], [ "▁小銃", -12.60407543182373 ], [ "▁WHO", -12.604081153869629 ], [ "▁増刊", -12.604096412658691 ], [ "▁倒さ", -12.604156494140625 ], [ "▁レバノン", -12.604203224182129 ], [ "▁躍進", -12.604204177856445 ], [ "▁在留", -12.604230880737305 ], [ "施", -12.604244232177734 ], [ "▁パトリック", -12.604379653930664 ], [ "▁ご挨拶", -12.604554176330566 ], [ "▁ストー", -12.604584693908691 ], [ "▁漁師", -12.604644775390625 ], [ "▁崩御", -12.604766845703125 ], [ "▁BAR", -12.604780197143555 ], [ "▁投げて", -12.604949951171875 ], [ "▁暗示", -12.604971885681152 ], [ "▁丸い", -12.605047225952148 ], [ "▁コップ", -12.605161666870117 ], [ "▁開架", -12.605172157287598 ], [ "マリン", -12.60533618927002 ], [ "▁従わ", -12.605403900146484 ], [ "▁ベートーヴェン", -12.605433464050293 ], [ "▁ホイヤー", -12.605477333068848 ], [ "▁くすり", -12.605485916137695 ], [ "▁オロ", -12.605517387390137 ], [ "▁差し上げ", -12.60554313659668 ], [ "遍", -12.60560417175293 ], [ "▁選帝侯", -12.605608940124512 ], [ "▁BP", -12.605626106262207 ], [ "▁set", -12.605693817138672 ], [ "▁踏み込", -12.60583782196045 ], [ "▁欠席", -12.605860710144043 ], [ "▁ポップス", -12.605931282043457 ], [ "▁指先", -12.605952262878418 ], [ "▁製剤", -12.605969429016113 ], [ "ヒュー", -12.606086730957031 ], [ "▁伸縮", -12.606155395507812 ], [ "▁動的", -12.606648445129395 ], [ "▁祀る", -12.606842041015625 ], [ "put", -12.606952667236328 ], [ "▁ツヤ", -12.607000350952148 ], [ "▁Global", -12.607129096984863 ], [ "大和", -12.607179641723633 ], [ "錯", -12.607182502746582 ], [ "▁たけし", -12.60722541809082 ], [ "▁作法", -12.607366561889648 ], [ "付く", -12.607632637023926 ], [ "▁宇部", -12.607660293579102 ], [ "涙", -12.607680320739746 ], [ "▁施し", -12.607686996459961 ], [ "▁ブックス", -12.607755661010742 ], [ "▁書体", -12.607990264892578 ], [ "スカイ", -12.608007431030273 ], [ "▁マルク", -12.608085632324219 ], [ "▁兼用", -12.608158111572266 ], [ "ship", -12.608193397521973 ], [ "▁Shi", -12.608278274536133 ], [ "▁ナシ", -12.608281135559082 ], [ "▁サロ", -12.608291625976562 ], [ "▁William", -12.608427047729492 ], [ "゜", -12.608427047729492 ], [ "▁キレ", -12.608464241027832 ], [ "▁天津", -12.608485221862793 ], [ "▁大西", -12.608664512634277 ], [ "拝", -12.608671188354492 ], [ "勉強", -12.608774185180664 ], [ "▁譚", -12.609001159667969 ], [ "▁刻印", -12.60901927947998 ], [ "Ma", -12.609084129333496 ], [ "▁及んで", -12.609102249145508 ], [ "▁加減", -12.609188079833984 ], [ "▁いまだ", -12.609206199645996 ], [ "gy", -12.609214782714844 ], [ "▁ゆず", -12.609214782714844 ], [ "▁Cisco", -12.609310150146484 ], [ "▁どうにも", -12.609370231628418 ], [ "▁オウ", -12.609426498413086 ], [ "▁細長い", -12.609517097473145 ], [ "掘", -12.609548568725586 ], [ "▁休刊", -12.609561920166016 ], [ "佑", -12.60964298248291 ], [ "DEN", -12.60981559753418 ], [ "▁前部", -12.609825134277344 ], [ "▁瀬戸内", -12.609903335571289 ], [ "VR", -12.609920501708984 ], [ "▁宰相", -12.610015869140625 ], [ "▁落ち着か", -12.610015869140625 ], [ "▁チューニング", -12.610069274902344 ], [ "▁飲め", -12.61008358001709 ], [ "▁リーチ", -12.610105514526367 ], [ "▁同情", -12.610175132751465 ], [ "▁積む", -12.61017894744873 ], [ "ray", -12.610289573669434 ], [ "▁発進", -12.610483169555664 ], [ "▁Developer", -12.610546112060547 ], [ "テュー", -12.61056900024414 ], [ "▁産学", -12.61070728302002 ], [ "▁折りたたみ", -12.610723495483398 ], [ "▁ホールド", -12.61074447631836 ], [ "勤務", -12.610809326171875 ], [ "▁火葬", -12.610917091369629 ], [ "▁励み", -12.611078262329102 ], [ "▁的確に", -12.611078262329102 ], [ "▁抜けた", -12.611223220825195 ], [ "▁アスレチック", -12.61125373840332 ], [ "▁ハンドボール", -12.61133098602295 ], [ "▁放って", -12.611454963684082 ], [ "▁ハーレム", -12.611509323120117 ], [ "▁商学", -12.611570358276367 ], [ "ORE", -12.611631393432617 ], [ "▁BLUE", -12.611639976501465 ], [ "▁風潮", -12.611717224121094 ], [ "▁マウ", -12.611777305603027 ], [ "▁畜産", -12.611784934997559 ], [ "▁泣く", -12.611788749694824 ], [ "▁Xperia", -12.611961364746094 ], [ "ガガミラノ", -12.611961364746094 ], [ "▁ポジティブ", -12.612038612365723 ], [ "ough", -12.612255096435547 ], [ "▁閉館", -12.612447738647461 ], [ "ダーズ", -12.612521171569824 ], [ "▁インタフェース", -12.612669944763184 ], [ "▁鳩", -12.612685203552246 ], [ "ula", -12.612687110900879 ], [ "GL", -12.612703323364258 ], [ "▁捨てた", -12.612923622131348 ], [ "▁仇", -12.6129789352417 ], [ "▁きつい", -12.613078117370605 ], [ "▁最高に", -12.613080024719238 ], [ "撮", -12.613089561462402 ], [ "▁戴冠", -12.613201141357422 ], [ "TON", -12.613225936889648 ], [ "▁明和", -12.613249778747559 ], [ "▁一味", -12.613302230834961 ], [ "▁シュル", -12.613325119018555 ], [ "鮎", -12.613378524780273 ], [ "▁摂る", -12.613571166992188 ], [ "▁迅速な", -12.613723754882812 ], [ "▁小麦粉", -12.613750457763672 ], [ "莉", -12.613950729370117 ], [ "ona", -12.614060401916504 ], [ "色々", -12.614063262939453 ], [ "恐", -12.614102363586426 ], [ "cre", -12.614105224609375 ], [ "▁♥", -12.614120483398438 ], [ "▁純粋", -12.614269256591797 ], [ "▁晋三", -12.614317893981934 ], [ "▁均等", -12.614465713500977 ], [ "▁資質", -12.614516258239746 ], [ "▁カーネル", -12.614619255065918 ], [ "▁佐竹", -12.614724159240723 ], [ "▁思惑", -12.614839553833008 ], [ "ナーズ", -12.614952087402344 ], [ "▁出羽", -12.614968299865723 ], [ "▁有名で", -12.61501407623291 ], [ "▁調剤", -12.61507511138916 ], [ "▁老後", -12.615253448486328 ], [ "▁プロパティ", -12.61534595489502 ], [ "▁キングス", -12.615352630615234 ], [ "▁けども", -12.6154146194458 ], [ "gn", -12.61545467376709 ], [ "▁コースト", -12.615503311157227 ], [ "▁簡潔", -12.615508079528809 ], [ "▁土浦", -12.615533828735352 ], [ "▁勝ち越し", -12.615609169006348 ], [ "ファル", -12.615884780883789 ], [ "▁実例", -12.615887641906738 ], [ "▁携わり", -12.616068840026855 ], [ "bon", -12.616227149963379 ], [ "▁生計", -12.616280555725098 ], [ "▁押さえて", -12.616579055786133 ], [ "▁レイバン", -12.616662979125977 ], [ "盧", -12.616752624511719 ], [ "▁オールナイト", -12.616861343383789 ], [ "▁ブリュ", -12.616910934448242 ], [ "ツェン", -12.616938591003418 ], [ "灘", -12.616969108581543 ], [ "▁たっぷりの", -12.617085456848145 ], [ "▁国債", -12.617263793945312 ], [ "▁拭き", -12.617287635803223 ], [ "▁うわ", -12.617365837097168 ], [ "▁アンドロイド", -12.61738109588623 ], [ "▁内包", -12.617385864257812 ], [ "亚", -12.617819786071777 ], [ "▁エヴァン", -12.617835998535156 ], [ "▁代打", -12.617938041687012 ], [ "▁商学部", -12.617948532104492 ], [ "迅", -12.617997169494629 ], [ "▁下がった", -12.61800765991211 ], [ "lum", -12.618173599243164 ], [ "▁治水", -12.618221282958984 ], [ "素敵な", -12.618221282958984 ], [ "▁楼", -12.618294715881348 ], [ "▁抹茶", -12.618353843688965 ], [ "▁曇り", -12.61836051940918 ], [ "ホイ", -12.618496894836426 ], [ "iel", -12.618561744689941 ], [ "▁戻して", -12.618617057800293 ], [ "▁繋が", -12.618645668029785 ], [ "▁繋がった", -12.618680000305176 ], [ "▁定食", -12.618807792663574 ], [ "▁悪質な", -12.618844985961914 ], [ "▁結びつき", -12.618885040283203 ], [ "▁きっちり", -12.61889362335205 ], [ "近頃", -12.618988990783691 ], [ "サイン", -12.619036674499512 ], [ "▁よろしい", -12.619109153747559 ], [ "ストーン", -12.619129180908203 ], [ "▁別れて", -12.619172096252441 ], [ "▁藤本", -12.619366645812988 ], [ "▁ボイラー", -12.619393348693848 ], [ "▁ジェラール", -12.619460105895996 ], [ "▁壁画", -12.6196928024292 ], [ "▁放火", -12.61981201171875 ], [ "▁尾道", -12.619884490966797 ], [ "▁スティーヴン", -12.619904518127441 ], [ "▁UFO", -12.619940757751465 ], [ "▁ボヘミア", -12.619958877563477 ], [ "▁ブレス", -12.620011329650879 ], [ "法律", -12.620018005371094 ], [ "6000", -12.620052337646484 ], [ "▁火薬", -12.620057106018066 ], [ "▁引き渡し", -12.620074272155762 ], [ "▁売店", -12.620129585266113 ], [ "EK", -12.620279312133789 ], [ "▁まれに", -12.620331764221191 ], [ "▁八代", -12.620443344116211 ], [ "ado", -12.620484352111816 ], [ "祓", -12.62049388885498 ], [ "マスク", -12.620519638061523 ], [ "aut", -12.620637893676758 ], [ "不安", -12.620676040649414 ], [ "▁丹後", -12.620688438415527 ], [ "▁良品", -12.620810508728027 ], [ "▁インスリン", -12.621030807495117 ], [ "▁サイモン", -12.621052742004395 ], [ "揃", -12.621100425720215 ], [ "▁不快", -12.621101379394531 ], [ "▁本業", -12.62118148803711 ], [ "▁ローテーション", -12.621188163757324 ], [ "▁帰省", -12.621241569519043 ], [ "全身", -12.621354103088379 ], [ "▁ボロ", -12.621460914611816 ], [ "▁美学", -12.621575355529785 ], [ "バト", -12.621597290039062 ], [ "▁残酷", -12.621598243713379 ], [ "▁身體", -12.621642112731934 ], [ "崔", -12.621744155883789 ], [ "ures", -12.621763229370117 ], [ "▁シーリング", -12.621769905090332 ], [ "▁ブリテン", -12.621814727783203 ], [ "▁べきでしょう", -12.621842384338379 ], [ "パパ", -12.621867179870605 ], [ "ジュン", -12.621912956237793 ], [ "▁ハガキ", -12.62192440032959 ], [ "▁静脈", -12.621981620788574 ], [ "▁Cor", -12.622015953063965 ], [ "▁迷う", -12.62210464477539 ], [ "▁エクストラ", -12.622125625610352 ], [ "▁のび太", -12.622325897216797 ], [ "▁1876", -12.622403144836426 ], [ "▁弾き語り", -12.622459411621094 ], [ "▁850", -12.622474670410156 ], [ "▁翻", -12.622537612915039 ], [ "▁顕著", -12.622538566589355 ], [ "RL", -12.622546195983887 ], [ "▁ちなみ", -12.622607231140137 ], [ "▁備前", -12.622645378112793 ], [ "▁Wikipedia", -12.622649192810059 ], [ "バイン", -12.622709274291992 ], [ "▁ミニチュア", -12.622726440429688 ], [ "▁登用", -12.6227388381958 ], [ "▁ハンバーグ", -12.622954368591309 ], [ "▁困窮", -12.62299633026123 ], [ "▁舵", -12.62310791015625 ], [ "▁朋", -12.623132705688477 ], [ "▁栗原", -12.623194694519043 ], [ "ジェネクリ", -12.62337875366211 ], [ "▁退却", -12.623380661010742 ], [ "幼い", -12.623406410217285 ], [ "▁スタディ", -12.62358570098877 ], [ "▁届け出", -12.623588562011719 ], [ "▁ダラス", -12.623896598815918 ], [ "▁全滅", -12.623948097229004 ], [ "マンション", -12.623952865600586 ], [ "ming", -12.623967170715332 ], [ "▁スライダー", -12.624039649963379 ], [ "▁傭兵", -12.62407112121582 ], [ "▁OEM", -12.624126434326172 ], [ "▁原油", -12.624160766601562 ], [ "化粧", -12.62416934967041 ], [ "ツキー", -12.624212265014648 ], [ "▁むくみ", -12.624251365661621 ], [ "▁ニコライ", -12.624251365661621 ], [ "▁磁場", -12.624252319335938 ], [ "▁同志社", -12.624255180358887 ], [ "▁軌", -12.624344825744629 ], [ "▁ドゥー", -12.624448776245117 ], [ "▁風船", -12.624456405639648 ], [ "▁千住", -12.624711990356445 ], [ "▁請", -12.624740600585938 ], [ "摺", -12.624787330627441 ], [ "▁フッ", -12.624909400939941 ], [ "▁photo", -12.624911308288574 ], [ "▁産む", -12.624984741210938 ], [ "▁消臭", -12.624992370605469 ], [ "▁will", -12.625031471252441 ], [ "▁着けて", -12.625221252441406 ], [ "▁持株", -12.625367164611816 ], [ "▁発し", -12.625372886657715 ], [ "▁旧制", -12.625486373901367 ], [ "WEB", -12.625574111938477 ], [ "▁あふれ", -12.625657081604004 ], [ "▁ブックマーク", -12.625751495361328 ], [ "▁明らかな", -12.625755310058594 ], [ "▁短調", -12.625815391540527 ], [ "▁仕える", -12.625913619995117 ], [ "▁倒し", -12.62601375579834 ], [ "▁720", -12.626144409179688 ], [ "▁厚木", -12.626152992248535 ], [ "ディナ", -12.626155853271484 ], [ "ボルト", -12.626175880432129 ], [ "幸い", -12.626221656799316 ], [ "▁筐体", -12.626222610473633 ], [ "▁堰", -12.626423835754395 ], [ "▁フォア", -12.62646198272705 ], [ "▁倒して", -12.62653923034668 ], [ "▁まれ", -12.626590728759766 ], [ "▁努める", -12.626656532287598 ], [ "cast", -12.626812934875488 ], [ "▁黒川", -12.626879692077637 ], [ "▁取れて", -12.626947402954102 ], [ "▁支那", -12.626988410949707 ], [ "▁産生", -12.62708568572998 ], [ "▁公家", -12.627107620239258 ], [ "得意", -12.627233505249023 ], [ "▁インスピレーション", -12.627301216125488 ], [ "▁出自", -12.62751579284668 ], [ "武天皇", -12.627530097961426 ], [ "Ex", -12.627639770507812 ], [ "▁久留米", -12.627644538879395 ], [ "▁kHz", -12.628020286560059 ], [ "▁ぐるみ", -12.628029823303223 ], [ "▁アオイ", -12.628060340881348 ], [ "声優", -12.628060340881348 ], [ "▁鉄板", -12.628063201904297 ], [ "▁VTR", -12.628097534179688 ], [ "▁疑う", -12.628153800964355 ], [ "▁優等", -12.628288269042969 ], [ "融", -12.62834358215332 ], [ "▁万一", -12.628355026245117 ], [ "▁なおかつ", -12.628434181213379 ], [ "▁先月", -12.628584861755371 ], [ "▁前記", -12.62868881225586 ], [ "─", -12.629054069519043 ], [ "職場", -12.62905502319336 ], [ "▁モモ", -12.629127502441406 ], [ "met", -12.629158973693848 ], [ "ERA", -12.629573822021484 ], [ "▁知覚", -12.62959098815918 ], [ "標高", -12.629617691040039 ], [ "▁イオ", -12.629626274108887 ], [ "▁合弁", -12.629634857177734 ], [ "篇", -12.62975025177002 ], [ "▁やさしく", -12.62983226776123 ], [ "▁Reg", -12.630005836486816 ], [ "shop", -12.630067825317383 ], [ "▁重大", -12.630303382873535 ], [ "▁オナ", -12.630363464355469 ], [ "▁閉じて", -12.630420684814453 ], [ "▁┈", -12.630427360534668 ], [ "▁Vo", -12.630433082580566 ], [ "▁酸性", -12.630459785461426 ], [ "1911", -12.630476951599121 ], [ "魏", -12.630489349365234 ], [ "▁香取", -12.630516052246094 ], [ "mobile", -12.630545616149902 ], [ "▁繰り広げる", -12.630555152893066 ], [ "▁エコー", -12.630568504333496 ], [ "▁毅", -12.63058090209961 ], [ "▁リベンジ", -12.630583763122559 ], [ "▁スプリント", -12.630722045898438 ], [ "▁免れ", -12.630837440490723 ], [ "▁掛かって", -12.630922317504883 ], [ "ポーター", -12.630958557128906 ], [ "▁長尾", -12.630992889404297 ], [ "▁ダイジェスト", -12.631082534790039 ], [ "▁ヘブライ", -12.631082534790039 ], [ "必", -12.631159782409668 ], [ "▁迫った", -12.63117790222168 ], [ "議院", -12.63129997253418 ], [ "▁遠野", -12.631339073181152 ], [ "▁エサ", -12.631440162658691 ], [ "▁シュン", -12.631443977355957 ], [ "▁ノンフィクション", -12.631443977355957 ], [ "▁胎児", -12.631443977355957 ], [ "▁笑った", -12.631525993347168 ], [ "▁file", -12.6315279006958 ], [ "▁戻ら", -12.631535530090332 ], [ "▲", -12.631600379943848 ], [ "▁待合室", -12.631624221801758 ], [ "RIS", -12.631778717041016 ], [ "▁ノースカロライ", -12.631804466247559 ], [ "▁居城", -12.631831169128418 ], [ "▁帰郷", -12.63196086883545 ], [ "▁黒字", -12.631969451904297 ], [ "ien", -12.632049560546875 ], [ "▁配役", -12.632220268249512 ], [ "ota", -12.632407188415527 ], [ "ドロス", -12.632433891296387 ], [ "アキ", -12.63243579864502 ], [ "▁セッティング", -12.632450103759766 ], [ "圏", -12.632508277893066 ], [ "▁見つめて", -12.632633209228516 ], [ "礫", -12.632707595825195 ], [ "▁均衡", -12.632718086242676 ], [ "▁書ける", -12.632823944091797 ], [ "▁伊勢崎", -12.633129119873047 ], [ "iki", -12.633180618286133 ], [ "関係", -12.633289337158203 ], [ "ペリ", -12.633328437805176 ], [ "▁愛着", -12.633413314819336 ], [ "▁商号", -12.6336030960083 ], [ "おはよう", -12.633607864379883 ], [ "アヌス", -12.633665084838867 ], [ "▁後進", -12.633702278137207 ], [ "▁シンプルに", -12.633740425109863 ], [ "▁斬り", -12.633758544921875 ], [ "▁Billboard", -12.633792877197266 ], [ "▁This", -12.633951187133789 ], [ "▁多項式", -12.633974075317383 ], [ "だれ", -12.633978843688965 ], [ "▁漸", -12.634028434753418 ], [ "▁ケープ", -12.63413143157959 ], [ "▁厨房", -12.634154319763184 ], [ "つける", -12.63416862487793 ], [ "ball", -12.634246826171875 ], [ "▁絵柄", -12.634248733520508 ], [ "▁外れて", -12.634289741516113 ], [ "▁ボア", -12.63439655303955 ], [ "▁­", -12.634407997131348 ], [ "▁満ち", -12.634492874145508 ], [ "▁ダイハツ", -12.634516716003418 ], [ "どうやら", -12.634519577026367 ], [ "▁履修", -12.634541511535645 ], [ "▁コンパイル", -12.634697914123535 ], [ "▁ヤクザ", -12.634697914123535 ], [ "▁祈祷", -12.634697914123535 ], [ "チング", -12.634742736816406 ], [ "▁キャンドル", -12.63475513458252 ], [ "UMA", -12.634766578674316 ], [ "ソニー", -12.634781837463379 ], [ "ats", -12.634819030761719 ], [ "▁於", -12.635065078735352 ], [ "▁混ぜて", -12.635079383850098 ], [ "▁向き合い", -12.635147094726562 ], [ "棟", -12.635167121887207 ], [ "▁やったら", -12.635225296020508 ], [ "AGA", -12.635356903076172 ], [ "▁精算", -12.635395050048828 ], [ "▁カタカナ", -12.635422706604004 ], [ "クルス", -12.635549545288086 ], [ "鎖", -12.635550498962402 ], [ "▁スノーボード", -12.635615348815918 ], [ "どのような", -12.635793685913086 ], [ "▁サハ", -12.635804176330566 ], [ "▁北村", -12.635818481445312 ], [ "▁親方", -12.635858535766602 ], [ "OI", -12.635931015014648 ], [ "▁切符", -12.635988235473633 ], [ "▁肝炎", -12.636022567749023 ], [ "icon", -12.636055946350098 ], [ "無理", -12.636076927185059 ], [ "▁ハンガー", -12.63618278503418 ], [ "ーデ", -12.636351585388184 ], [ "▁鳴門", -12.636390686035156 ], [ "▁蒸", -12.636561393737793 ], [ "▁星人", -12.636564254760742 ], [ "既", -12.636661529541016 ], [ "▁乗り出し", -12.63668155670166 ], [ "▁分校", -12.636796951293945 ], [ "▁負ける", -12.63684368133545 ], [ "▁数理", -12.636868476867676 ], [ "▁覗いて", -12.636873245239258 ], [ "▁Prime", -12.6370849609375 ], [ "書誌", -12.637248039245605 ], [ "泥", -12.637258529663086 ], [ "▁セントルイス", -12.637417793273926 ], [ "▁上回って", -12.637419700622559 ], [ "▁志村", -12.63760757446289 ], [ "▁淫乱", -12.637629508972168 ], [ "house", -12.637655258178711 ], [ "▁ほし", -12.637757301330566 ], [ "▁街並み", -12.637810707092285 ], [ "▁父子", -12.637835502624512 ], [ "▁良き", -12.637835502624512 ], [ "▁PART", -12.637883186340332 ], [ "▁マキシ", -12.638007164001465 ], [ "▁蚊", -12.638175010681152 ], [ "ムーン", -12.638197898864746 ], [ "安倍", -12.63822078704834 ], [ "1913", -12.638254165649414 ], [ "▁受理", -12.63829517364502 ], [ "障害", -12.638386726379395 ], [ "▁遂げて", -12.638463973999023 ], [ "▁ヒアルロン", -12.638507843017578 ], [ "▁マルティ", -12.638651847839355 ], [ "eth", -12.638704299926758 ], [ "Drive", -12.638708114624023 ], [ "▁終わったら", -12.638715744018555 ], [ "▁気体", -12.638748168945312 ], [ "▁塀", -12.63887882232666 ], [ "obo", -12.63888931274414 ], [ "▁BOOK", -12.639007568359375 ], [ "学区", -12.639131546020508 ], [ "▁きょく", -12.639423370361328 ], [ "他人", -12.639471054077148 ], [ "▁高台", -12.639598846435547 ], [ "幻", -12.639630317687988 ], [ "▁トラスト", -12.639897346496582 ], [ "▁スコープ", -12.64000129699707 ], [ "がかり", -12.64004135131836 ], [ "▁陰陽", -12.640124320983887 ], [ "ICS", -12.640142440795898 ], [ "▁ウクレレ", -12.640145301818848 ], [ "▁安城", -12.640159606933594 ], [ "▁オクタ", -12.64023494720459 ], [ "ッキン", -12.640251159667969 ], [ "冊", -12.640252113342285 ], [ "▁低かった", -12.640259742736816 ], [ "▁直列", -12.64028263092041 ], [ "▁心情", -12.640335083007812 ], [ "▁伯父", -12.640351295471191 ], [ "▁仮装", -12.640356063842773 ], [ "Mo", -12.640620231628418 ], [ "▁醜", -12.640663146972656 ], [ "lot", -12.640666007995605 ], [ "▁きよ", -12.640719413757324 ], [ "▁メモリアル", -12.640730857849121 ], [ "▁山々", -12.640778541564941 ], [ "▁いただけた", -12.640917778015137 ], [ "▁変貌", -12.640925407409668 ], [ "▁親しい", -12.640957832336426 ], [ "len", -12.641090393066406 ], [ "中野", -12.641106605529785 ], [ "オウ", -12.641196250915527 ], [ "▁インタラクティブ", -12.64123821258545 ], [ "▁ュ", -12.641284942626953 ], [ "縞", -12.641420364379883 ], [ "卓越", -12.641423225402832 ], [ "mat", -12.64146900177002 ], [ "Cont", -12.641742706298828 ], [ "疲れ", -12.641793251037598 ], [ "ould", -12.641830444335938 ], [ "zer", -12.641871452331543 ], [ "▁ちょい", -12.641912460327148 ], [ "▁劇的に", -12.641966819763184 ], [ "▁FG", -12.642069816589355 ], [ "▁不要で", -12.642072677612305 ], [ "cro", -12.642107963562012 ], [ "▁元来", -12.642229080200195 ], [ "にもかかわらず", -12.642332077026367 ], [ "▁円滑に", -12.642333030700684 ], [ "始め", -12.642409324645996 ], [ "▁鍵盤", -12.642426490783691 ], [ "▁建つ", -12.642439842224121 ], [ "▁ホログラム", -12.642523765563965 ], [ "'", -12.642578125 ], [ "ram", -12.642722129821777 ], [ "▁差し出", -12.642736434936523 ], [ "▁寛容", -12.642755508422852 ], [ "たけ", -12.642837524414062 ], [ "煌", -12.642879486083984 ], [ "▁営み", -12.642919540405273 ], [ "嵩", -12.643062591552734 ], [ "ving", -12.643173217773438 ], [ "vin", -12.643176078796387 ], [ "cept", -12.643304824829102 ], [ "▁済ませて", -12.643425941467285 ], [ "▁鯨", -12.6434326171875 ], [ "▁クローゼット", -12.643441200256348 ], [ "▁スーダン", -12.64353084564209 ], [ "▁信玄", -12.643712043762207 ], [ "▁叶える", -12.643718719482422 ], [ "▁ふつう", -12.643793106079102 ], [ "▁語族", -12.643892288208008 ], [ "柚", -12.643972396850586 ], [ "ガタ", -12.644085884094238 ], [ "▁ヒッツ", -12.644100189208984 ], [ "▁1,200", -12.644161224365234 ], [ "▁幕下", -12.644240379333496 ], [ "▁愛車", -12.644242286682129 ], [ "▁アヤ", -12.644330024719238 ], [ "▁スペシャリスト", -12.644341468811035 ], [ "▁武者", -12.644341468811035 ], [ "ニム", -12.644440650939941 ], [ "本体", -12.644440650939941 ], [ "▁施して", -12.644454956054688 ], [ "▁ユウ", -12.64445686340332 ], [ "▁ペイン", -12.644464492797852 ], [ "▁ファスナー", -12.644525527954102 ], [ "▁バーデン", -12.644584655761719 ], [ "▁付き合う", -12.644681930541992 ], [ "▁ウェイト", -12.64470100402832 ], [ "л", -12.644705772399902 ], [ "▁見立て", -12.6447114944458 ], [ "▁時短", -12.644725799560547 ], [ "▁桐生", -12.644889831542969 ], [ "▁ヨーゼフ", -12.644919395446777 ], [ "▁止まった", -12.644933700561523 ], [ "▁令嬢", -12.645075798034668 ], [ "いろいろな", -12.645142555236816 ], [ "▁アップロード", -12.645354270935059 ], [ "▁ハドソン", -12.645440101623535 ], [ "▁ニックネーム", -12.645458221435547 ], [ "▁アホ", -12.645463943481445 ], [ "▁トラウマ", -12.645467758178711 ], [ "▁日の出", -12.645491600036621 ], [ "▁草原", -12.645492553710938 ], [ "壮", -12.645529747009277 ], [ "ours", -12.645648002624512 ], [ "▁ガジェット", -12.645703315734863 ], [ "▁受け入れた", -12.645790100097656 ], [ "▁執事", -12.645793914794922 ], [ "ather", -12.64589786529541 ], [ "▁那珂", -12.645988464355469 ], [ "docomo", -12.645989418029785 ], [ "▁悔し", -12.646014213562012 ], [ "自社", -12.646056175231934 ], [ "▁着け", -12.646069526672363 ], [ "▁シメオ", -12.646123886108398 ], [ "▁甲状腺", -12.646354675292969 ], [ "▁尽く", -12.646390914916992 ], [ "▁巴", -12.646434783935547 ], [ "▁こいつ", -12.646472930908203 ], [ "▁児玉", -12.646539688110352 ], [ "▁義勇", -12.646806716918945 ], [ "▁憂鬱", -12.646905899047852 ], [ "配信", -12.647128105163574 ], [ "▁ネクス", -12.64719295501709 ], [ "▁タウ", -12.647217750549316 ], [ "▁荷重", -12.64722728729248 ], [ "▁じいちゃん", -12.647271156311035 ], [ "▁中級", -12.647416114807129 ], [ "▁知らせる", -12.64745044708252 ], [ "▁カッコいい", -12.647470474243164 ], [ "万が一", -12.647565841674805 ], [ "▁空き家", -12.64758014678955 ], [ "▁のぞき", -12.64769172668457 ], [ "鍼", -12.647820472717285 ], [ "▁スリップ", -12.647920608520508 ], [ "▁荘園", -12.64794635772705 ], [ "壱", -12.648004531860352 ], [ "麿", -12.648004531860352 ], [ "▁立山", -12.6480712890625 ], [ "▁系図", -12.648176193237305 ], [ "▁PROJECT", -12.648187637329102 ], [ "▁脫", -12.648412704467773 ], [ "▁乗船", -12.648608207702637 ], [ "▁過激な", -12.648651123046875 ], [ "オリンピック", -12.648669242858887 ], [ "▁ピクチャーズ", -12.648738861083984 ], [ "▁話せ", -12.648981094360352 ], [ "▁メッキ", -12.649007797241211 ], [ "細胞", -12.649066925048828 ], [ "▁ミズーリ", -12.6491060256958 ], [ "▁乳酸菌", -12.649290084838867 ], [ "▁とどめ", -12.649304389953613 ], [ "▁鞄", -12.649317741394043 ], [ "▁とうとう", -12.649421691894531 ], [ "カミ", -12.64950180053711 ], [ "▁タイツ", -12.649506568908691 ], [ "▁文久", -12.649673461914062 ], [ "▁飯塚", -12.64980411529541 ], [ "絢", -12.64984130859375 ], [ "▁ョ", -12.649863243103027 ], [ "igh", -12.649918556213379 ], [ "HTML", -12.649978637695312 ], [ "▁ベニ", -12.65005111694336 ], [ "▁締め切り", -12.650074005126953 ], [ "▁是正", -12.65014362335205 ], [ "▁カンナビジオール", -12.650209426879883 ], [ "ウォール", -12.650279998779297 ], [ "彫", -12.650303840637207 ], [ "side", -12.650333404541016 ], [ "▁水溶", -12.650535583496094 ], [ "▁エキスパート", -12.65059757232666 ], [ "▁増田", -12.650670051574707 ], [ "▁讃岐", -12.650760650634766 ], [ "AKU", -12.650806427001953 ], [ "プチ", -12.650834083557129 ], [ "キサン", -12.650835990905762 ], [ "▁魔力", -12.65099048614502 ], [ "▁もらったり", -12.651137351989746 ], [ "▁ハンドメイド", -12.651151657104492 ], [ "uro", -12.651322364807129 ], [ "▁MAP", -12.651347160339355 ], [ "▁内野手", -12.65150260925293 ], [ "メキシコ", -12.651588439941406 ], [ "▁ウィンター", -12.651654243469238 ], [ "▁アクセル", -12.651664733886719 ], [ "▁生き延び", -12.651681900024414 ], [ "▁治る", -12.651691436767578 ], [ "TOR", -12.651716232299805 ], [ "▁1864", -12.651739120483398 ], [ "▁落合", -12.651782035827637 ], [ "▁炊き", -12.65186882019043 ], [ "▁公団", -12.651888847351074 ], [ "▁申し上げる", -12.651888847351074 ], [ "▁1881", -12.651970863342285 ], [ "▁フランクリン", -12.652195930480957 ], [ "▁控える", -12.652290344238281 ], [ "▁犯した", -12.652363777160645 ], [ "〈", -12.652379035949707 ], [ "▁頻発", -12.652419090270996 ], [ "▁熱意", -12.652667045593262 ], [ "▁Hol", -12.652795791625977 ], [ "SION", -12.652802467346191 ], [ "▁紛れ", -12.652811050415039 ], [ "▁ジェイムズ", -12.652814865112305 ], [ "▁浮かんで", -12.652915954589844 ], [ "▁Center", -12.652974128723145 ], [ "▁校区", -12.653132438659668 ], [ "謂", -12.653154373168945 ], [ "▁扶養", -12.653156280517578 ], [ "▁日本書紀", -12.653157234191895 ], [ "▁ゲーミング", -12.653205871582031 ], [ "▁大館", -12.653220176696777 ], [ "▁不利益", -12.653286933898926 ], [ "▁1882", -12.653481483459473 ], [ "▁要ら", -12.653497695922852 ], [ "▁ランドリー", -12.65369701385498 ], [ "▁挑発", -12.653709411621094 ], [ "▁カズ", -12.653711318969727 ], [ "▁ネガティブな", -12.653740882873535 ], [ "▁休んで", -12.653924942016602 ], [ "▁残ら", -12.654046058654785 ], [ "カジノ", -12.654056549072266 ], [ "▁クロノ", -12.654088020324707 ], [ "▁オーダーメイド", -12.654095649719238 ], [ "▁豪族", -12.654167175292969 ], [ "公共", -12.654196739196777 ], [ "▁1700", -12.6542329788208 ], [ "▁ブリーダー", -12.654281616210938 ], [ "詳しい", -12.654287338256836 ], [ "▁土岐", -12.654415130615234 ], [ "▁エプロン", -12.654448509216309 ], [ "▁混入", -12.654552459716797 ], [ "▁その辺", -12.654586791992188 ], [ "▁以って", -12.654641151428223 ], [ "▁exp", -12.65466022491455 ], [ "プリー", -12.654725074768066 ], [ "▁笑み", -12.654764175415039 ], [ "TIC", -12.65477180480957 ], [ "▁ペンギン", -12.65489673614502 ], [ "▁漏らし", -12.655094146728516 ], [ "滋賀", -12.655204772949219 ], [ "▁Weblio", -12.65522289276123 ], [ "▁先駆けて", -12.655245780944824 ], [ "記録", -12.655327796936035 ], [ "▁氾濫", -12.65537166595459 ], [ "▁罰則", -12.655403137207031 ], [ "▁激突", -12.65542221069336 ], [ "一見", -12.65544319152832 ], [ "▁一斉", -12.655498504638672 ], [ "▁ロスト", -12.655503273010254 ], [ "授業", -12.655547142028809 ], [ "團", -12.655556678771973 ], [ "▁一式", -12.65561580657959 ], [ "ちん", -12.655673027038574 ], [ "▁莉", -12.655698776245117 ], [ "▁寝台", -12.655714988708496 ], [ "▁碑文", -12.655733108520508 ], [ "▁繁華街", -12.655741691589355 ], [ "閏", -12.655741691589355 ], [ "▁Jun", -12.65588665008545 ], [ "▁ようだった", -12.655942916870117 ], [ "▁UTC", -12.655963897705078 ], [ "▁破片", -12.656007766723633 ], [ "猿", -12.656103134155273 ], [ "▁そろって", -12.656115531921387 ], [ "▁四川", -12.65627384185791 ], [ "啓", -12.656291007995605 ], [ "▁以北", -12.656298637390137 ], [ "▁竹田", -12.65632152557373 ], [ "▁乗り越えて", -12.656384468078613 ], [ "▁サガ", -12.656394958496094 ], [ "▁ハンディ", -12.656396865844727 ], [ "▁福利", -12.65647029876709 ], [ "蹄", -12.656481742858887 ], [ "▁塩分", -12.656584739685059 ], [ "▁初版", -12.65676212310791 ], [ "ガシ", -12.656795501708984 ], [ "▁エイリアン", -12.656810760498047 ], [ "▁ニオイ", -12.656853675842285 ], [ "▁JAL", -12.656970024108887 ], [ "▁栄えた", -12.656994819641113 ], [ "▁憲章", -12.657093048095703 ], [ "▁パルス", -12.657170295715332 ], [ "符", -12.657278060913086 ], [ "▁ニート", -12.657288551330566 ], [ "▁大別", -12.65731143951416 ], [ "▁シモン", -12.65733528137207 ], [ "戦前", -12.65733528137207 ], [ "キャッチフレーズ", -12.6574068069458 ], [ "浮気", -12.657483100891113 ], [ "ジマ", -12.657489776611328 ], [ "メリーランド", -12.657588958740234 ], [ "▁ロッキー", -12.657748222351074 ], [ "▁麻衣", -12.657769203186035 ], [ "▁厳格な", -12.65778636932373 ], [ "YAMA", -12.65778923034668 ], [ "▁無縁", -12.65784740447998 ], [ "意外", -12.657856941223145 ], [ "▁来訪", -12.657883644104004 ], [ "▁チャリティー", -12.657906532287598 ], [ "▁素肌", -12.657919883728027 ], [ "▁ホッと", -12.658036231994629 ], [ "uth", -12.658085823059082 ], [ "▁控えた", -12.658097267150879 ], [ "▁おこなった", -12.658333778381348 ], [ "olo", -12.658378601074219 ], [ "alt", -12.658392906188965 ], [ "▁リラックマ", -12.65851879119873 ], [ "▁在職", -12.65860366821289 ], [ "▁1878", -12.658649444580078 ], [ "▁白井", -12.658689498901367 ], [ "▁抑止", -12.65870475769043 ], [ "▁停車場", -12.658830642700195 ], [ "▁見込め", -12.65893840789795 ], [ "▁スパン", -12.659027099609375 ], [ "▁文科", -12.65905475616455 ], [ "▁祈る", -12.659080505371094 ], [ "アダルト", -12.659090995788574 ], [ "▁成形", -12.659235000610352 ], [ "▁水没", -12.65930461883545 ], [ "升", -12.65944766998291 ], [ "▁カッター", -12.659466743469238 ], [ "▁伝来", -12.659496307373047 ], [ "モット", -12.659584999084473 ], [ "んせん", -12.659661293029785 ], [ "▁批准", -12.659818649291992 ], [ "▁相まって", -12.660035133361816 ], [ "▁味覚", -12.660116195678711 ], [ "▁復縁", -12.66024112701416 ], [ "4000", -12.660324096679688 ], [ "▁溶解", -12.660420417785645 ], [ "けれど", -12.660502433776855 ], [ "▁勘定", -12.660740852355957 ], [ "▁偏差値", -12.660747528076172 ], [ "▁別々の", -12.660749435424805 ], [ "リンゲン", -12.660865783691406 ], [ "▁達人", -12.661005020141602 ], [ "TX", -12.661028861999512 ], [ "▁造園", -12.661063194274902 ], [ "▁油圧", -12.661211013793945 ], [ "▁Song", -12.661219596862793 ], [ "▁海面", -12.661642074584961 ], [ "MU", -12.661742210388184 ], [ "▁奥行き", -12.66178035736084 ], [ "eas", -12.661782264709473 ], [ "▁集い", -12.661797523498535 ], [ "憩", -12.661849021911621 ], [ "▁歩んで", -12.661907196044922 ], [ "▁七夕", -12.661953926086426 ], [ "▁弾丸", -12.662039756774902 ], [ "▁赴き", -12.662049293518066 ], [ "▁強硬", -12.66209888458252 ], [ "ヘレ", -12.662164688110352 ], [ "高知", -12.66220474243164 ], [ "▁穿", -12.662381172180176 ], [ "▁チャーム", -12.662454605102539 ], [ "1915", -12.662459373474121 ], [ "▁異常に", -12.662498474121094 ], [ "LOW", -12.662535667419434 ], [ "▁プロット", -12.662822723388672 ], [ "▁シュガー", -12.662851333618164 ], [ "▁初級", -12.662983894348145 ], [ "▁給水", -12.663080215454102 ], [ "児童", -12.663082122802734 ], [ "▁Solution", -12.663164138793945 ], [ "AH", -12.663311004638672 ], [ "▁改札口", -12.663434982299805 ], [ "盗", -12.663891792297363 ], [ "▁カーディガン", -12.663911819458008 ], [ "▁いたずら", -12.66392993927002 ], [ "▁image", -12.663947105407715 ], [ "▁アニマル", -12.663979530334473 ], [ "▁官邸", -12.664023399353027 ], [ "▁今朝", -12.66421127319336 ], [ "▁セレモニー", -12.664284706115723 ], [ "▁リハーサル", -12.664284706115723 ], [ "▁泥棒", -12.664300918579102 ], [ "▁可愛らしい", -12.664308547973633 ], [ "▁広範囲に", -12.66435432434082 ], [ "▁生かす", -12.664360046386719 ], [ "▁主軸", -12.664409637451172 ], [ "▁施す", -12.664435386657715 ], [ "▁伸ばした", -12.66443920135498 ], [ "▁即興", -12.664637565612793 ], [ "手のひら", -12.664657592773438 ], [ "飴", -12.664657592773438 ], [ "▁ストーカー", -12.664820671081543 ], [ "▁多角", -12.664823532104492 ], [ "▁有用な", -12.664862632751465 ], [ "▁心配に", -12.66489315032959 ], [ "▁平家", -12.66490364074707 ], [ "ージェント", -12.665019989013672 ], [ "▁conf", -12.66518783569336 ], [ "病気", -12.66528034210205 ], [ "▁上品", -12.665350914001465 ], [ "▁探した", -12.66538143157959 ], [ "住居", -12.665395736694336 ], [ "▁点差", -12.665403366088867 ], [ "▁ガーデニング", -12.665404319763184 ], [ "▁早急に", -12.665404319763184 ], [ "メート", -12.665546417236328 ], [ "▁爽やかな", -12.665558815002441 ], [ "▁風水", -12.665640830993652 ], [ "▁急速な", -12.66573715209961 ], [ "工事", -12.66574478149414 ], [ "ハナ", -12.665789604187012 ], [ "出場", -12.665963172912598 ], [ "▁精一杯", -12.66596508026123 ], [ "▁引っ張り", -12.66601848602295 ], [ "abi", -12.666106224060059 ], [ "寡", -12.66615104675293 ], [ "▁岸田", -12.666261672973633 ], [ "▁西端", -12.666375160217285 ], [ "民主党", -12.666375160217285 ], [ "▁地表", -12.666452407836914 ], [ "▁機雷", -12.666452407836914 ], [ "▁クローズ", -12.666454315185547 ], [ "▁チェリー", -12.666497230529785 ], [ "這", -12.666522026062012 ], [ "▁ポートランド", -12.666577339172363 ], [ "▁まゆ", -12.666687965393066 ], [ "▁重心", -12.666793823242188 ], [ "LAND", -12.66684627532959 ], [ "▁手腕", -12.666937828063965 ], [ "▁ブランク", -12.667145729064941 ], [ "▁紀要", -12.66719913482666 ], [ "戊", -12.66727352142334 ], [ "柏", -12.667357444763184 ], [ "▁頭取", -12.667479515075684 ], [ "▁岩石", -12.66749095916748 ], [ "▁ャ", -12.667583465576172 ], [ "▁1874", -12.667603492736816 ], [ "▁向き合って", -12.667675971984863 ], [ "▁兵役", -12.667914390563965 ], [ "棄", -12.667917251586914 ], [ "▁サーカス", -12.668145179748535 ], [ "董", -12.668179512023926 ], [ "▁ドバイ", -12.668251991271973 ], [ "▁和らげ", -12.668349266052246 ], [ "▁たしかに", -12.668400764465332 ], [ "▁体積", -12.668478012084961 ], [ "ister", -12.668739318847656 ], [ "▁フライデー", -12.668835639953613 ], [ "直し", -12.668874740600586 ], [ "フォール", -12.668905258178711 ], [ "▁三宮", -12.668930053710938 ], [ "▁!!", -12.668977737426758 ], [ "berg", -12.669086456298828 ], [ "▁安価で", -12.669116973876953 ], [ "▁工廠", -12.669160842895508 ], [ "lick", -12.669208526611328 ], [ "▁努めた", -12.669211387634277 ], [ "▁クッキング", -12.669325828552246 ], [ "▁利き", -12.669379234313965 ], [ "▁長者", -12.669394493103027 ], [ "▁ゐる", -12.669425964355469 ], [ "▁最寄", -12.669506072998047 ], [ "▁消息", -12.669559478759766 ], [ "徽", -12.669708251953125 ], [ "▁墨田", -12.669731140136719 ], [ "▁厳し", -12.669732093811035 ], [ "▁重度", -12.669795989990234 ], [ "▁Photo", -12.669885635375977 ], [ "▁ベーシスト", -12.669896125793457 ], [ "▁停留場", -12.669896125793457 ], [ "▁デイサービス", -12.669954299926758 ], [ "▁公卿", -12.669986724853516 ], [ "rv", -12.670012474060059 ], [ "▁鳥栖", -12.67013168334961 ], [ "マルク", -12.67017936706543 ], [ "魁", -12.670270919799805 ], [ "▁Chi", -12.670315742492676 ], [ "チョー", -12.670320510864258 ], [ "スウェーデン", -12.670379638671875 ], [ "欺", -12.670458793640137 ], [ "▁潰し", -12.670653343200684 ], [ "▁zip", -12.670744895935059 ], [ "ミノキシジル", -12.670833587646484 ], [ "▁上質な", -12.670841217041016 ], [ "▁池上", -12.67093563079834 ], [ "▁クイン", -12.671050071716309 ], [ "瞬時", -12.67109203338623 ], [ "▁足首", -12.671119689941406 ], [ "▁中途半端", -12.671209335327148 ], [ "レッタ", -12.671269416809082 ], [ "フォト", -12.67128849029541 ], [ "▁歯磨き", -12.67139720916748 ], [ "租", -12.671399116516113 ], [ "▁挙動", -12.671540260314941 ], [ "▁似合", -12.671570777893066 ], [ "▁世襲", -12.671615600585938 ], [ "概略", -12.671623229980469 ], [ "▁オンエア", -12.671822547912598 ], [ "陸軍", -12.67184829711914 ], [ "イメージ", -12.671902656555176 ], [ "クラフト", -12.671914100646973 ], [ "▁冷め", -12.671928405761719 ], [ "▁商材", -12.672104835510254 ], [ "▁恋活", -12.672140121459961 ], [ "▁揃った", -12.67215633392334 ], [ "▁不可欠な", -12.672165870666504 ], [ "▁加湿", -12.672224998474121 ], [ "厩", -12.67233657836914 ], [ "喬", -12.672337532043457 ], [ "▁リュウ", -12.672613143920898 ], [ "セレ", -12.672642707824707 ], [ "▁唱える", -12.672713279724121 ], [ "▁減量", -12.672714233398438 ], [ "▁動いた", -12.672952651977539 ], [ "▁そごう", -12.672959327697754 ], [ "▁手洗い", -12.673001289367676 ], [ "▁trans", -12.673016548156738 ], [ "▁対人", -12.67308235168457 ], [ "▁自生", -12.6731595993042 ], [ "戚", -12.673392295837402 ], [ "▁Your", -12.673456192016602 ], [ "yan", -12.673476219177246 ], [ "▁Leg", -12.673572540283203 ], [ "▁突き出", -12.673741340637207 ], [ "▁ナマ", -12.67387580871582 ], [ "色々な", -12.6738862991333 ], [ "▁和名", -12.674012184143066 ], [ "▁済ませる", -12.674142837524414 ], [ "▁用事", -12.674186706542969 ], [ "FM", -12.674545288085938 ], [ "▁驚愕", -12.674596786499023 ], [ "ドーム", -12.674616813659668 ], [ "▁コレクター", -12.674671173095703 ], [ "徴", -12.674883842468262 ], [ "▁レーサー", -12.675005912780762 ], [ "▁案外", -12.67509937286377 ], [ "▁004", -12.67516040802002 ], [ "▁TSUTAYA", -12.675161361694336 ], [ "イングランド", -12.6751708984375 ], [ "▁1875", -12.675175666809082 ], [ "っしり", -12.675176620483398 ], [ "▁Consultant", -12.675350189208984 ], [ "▁セクキャバ", -12.675350189208984 ], [ "▁錬金術", -12.675350189208984 ], [ "▁噴射", -12.675376892089844 ], [ "どうして", -12.675393104553223 ], [ "表題", -12.675472259521484 ], [ "佐賀", -12.675577163696289 ], [ "▁居て", -12.675599098205566 ], [ "unk", -12.675677299499512 ], [ "▁打倒", -12.675713539123535 ], [ "zen", -12.675870895385742 ], [ "▁ティム", -12.675891876220703 ], [ "▁拠れば", -12.675918579101562 ], [ "▁ナザレ", -12.675926208496094 ], [ "▁オークランド", -12.67603588104248 ], [ "▁パイパン", -12.676048278808594 ], [ "▁西野", -12.67609691619873 ], [ "▁進言", -12.676101684570312 ], [ "▁ハンブルク", -12.676122665405273 ], [ "▁打ち明け", -12.67618465423584 ], [ "ぼろ", -12.676226615905762 ], [ "oli", -12.67626953125 ], [ "▁よろ", -12.676276206970215 ], [ "▁直行", -12.676288604736328 ], [ "昆", -12.67629337310791 ], [ "ua", -12.676298141479492 ], [ "pin", -12.67644214630127 ], [ "▁出迎え", -12.676486015319824 ], [ "▁Ass", -12.676582336425781 ], [ "▁1867", -12.67658519744873 ], [ "▁下さる", -12.676627159118652 ], [ "▁Imp", -12.676725387573242 ], [ "eat", -12.676762580871582 ], [ "▁いかにも", -12.67678451538086 ], [ "▁性交", -12.676850318908691 ], [ "▁顕彰", -12.67686653137207 ], [ "▁忍び", -12.676870346069336 ], [ "An", -12.676974296569824 ], [ "▁まとまった", -12.677014350891113 ], [ "負け", -12.67717170715332 ], [ "ベント", -12.677202224731445 ], [ "窟", -12.67723274230957 ], [ "▁小坂", -12.677314758300781 ], [ "粕", -12.6774263381958 ], [ "ラックス", -12.677434921264648 ], [ "▁同定", -12.677471160888672 ], [ "房総", -12.677504539489746 ], [ "アウ", -12.677559852600098 ], [ "▁通した", -12.677695274353027 ], [ "▁チャイナ", -12.677810668945312 ], [ "lim", -12.677875518798828 ], [ "▁貯水", -12.677992820739746 ], [ "▁ケニア", -12.678009986877441 ], [ "▁アナタ", -12.678275108337402 ], [ "▁培った", -12.678306579589844 ], [ "キャンペーン", -12.678357124328613 ], [ "▁White", -12.678400039672852 ], [ "▁星空", -12.678423881530762 ], [ "▁弱体", -12.678483963012695 ], [ "▁近海", -12.67857551574707 ], [ "▁ナウ", -12.678638458251953 ], [ "▁ボトム", -12.678693771362305 ], [ "▁察知", -12.678750991821289 ], [ "▁松前", -12.678799629211426 ], [ "▁アワー", -12.67881965637207 ], [ "▁霧島", -12.67891788482666 ], [ "加藤", -12.678976058959961 ], [ "▁異母", -12.679097175598145 ], [ "▁除籍", -12.679179191589355 ], [ "▁懇談", -12.67931842803955 ], [ "▁激戦", -12.679405212402344 ], [ "海軍", -12.67947006225586 ], [ "屯", -12.679498672485352 ], [ "▁バトン", -12.679633140563965 ], [ "ツィア", -12.679670333862305 ], [ "▁闇金", -12.6798095703125 ], [ "任意", -12.679875373840332 ], [ "▁嵯峨", -12.679886817932129 ], [ "フライ", -12.679948806762695 ], [ "▁1877", -12.679986000061035 ], [ "▁デイヴィッド", -12.680075645446777 ], [ "▁唾液", -12.680075645446777 ], [ "▁マグネット", -12.680206298828125 ], [ "抗うつ薬", -12.680265426635742 ], [ "▁泳", -12.680266380310059 ], [ "oco", -12.680290222167969 ], [ "ケラ", -12.680364608764648 ], [ "ライナー", -12.68037223815918 ], [ "ISE", -12.68052864074707 ], [ "▁ウォレット", -12.680717468261719 ], [ "▁羽毛", -12.68075180053711 ], [ "▁悪用", -12.680819511413574 ], [ "九郎", -12.680839538574219 ], [ "▁Big", -12.6808500289917 ], [ "▁嘔吐", -12.681023597717285 ], [ "▁当たり前に", -12.681059837341309 ], [ "▁ばかりです", -12.681108474731445 ], [ "▁BBQ", -12.681146621704102 ], [ "▁不眠", -12.68128776550293 ], [ "▁WH", -12.681307792663574 ], [ "▁轟", -12.681355476379395 ], [ "▁けが", -12.681380271911621 ], [ "▁もたらして", -12.681432723999023 ], [ "内部", -12.681486129760742 ], [ "▁古今", -12.681489944458008 ], [ "▁レクリエーション", -12.681782722473145 ], [ "▁ブロガー", -12.68181324005127 ], [ "▁ロブ", -12.68193244934082 ], [ "▁沸騰", -12.681977272033691 ], [ "予選", -12.68203353881836 ], [ "巧", -12.682146072387695 ], [ "▁ウェルター", -12.682241439819336 ], [ "楓", -12.682352066040039 ], [ "▁分科", -12.682367324829102 ], [ "▁右派", -12.682378768920898 ], [ "sky", -12.682433128356934 ], [ "▁儲か", -12.682433128356934 ], [ "▁のぼる", -12.68244743347168 ], [ "通販", -12.682528495788574 ], [ "▁鶏肉", -12.682599067687988 ], [ "▁SOUL", -12.682604789733887 ], [ "▁根底", -12.682719230651855 ], [ "▁盗み", -12.682723045349121 ], [ "▁フォレスト", -12.682758331298828 ], [ "▁Society", -12.68292236328125 ], [ "慈", -12.682926177978516 ], [ "姉妹", -12.68295669555664 ], [ "摘", -12.683079719543457 ], [ "▁ワニ", -12.68310832977295 ], [ "機械", -12.68315315246582 ], [ "▁不要です", -12.683199882507324 ], [ "▁休ま", -12.683231353759766 ], [ "玩", -12.683300971984863 ], [ "▁断った", -12.683333396911621 ], [ "目標", -12.683470726013184 ], [ "▁密接な", -12.683613777160645 ], [ "▁ハンバーガー", -12.683682441711426 ], [ "競技", -12.683732032775879 ], [ "▁迷った", -12.683852195739746 ], [ "▁流体", -12.683918952941895 ], [ "Com", -12.683948516845703 ], [ "▁まんこ", -12.683950424194336 ], [ "▁憧れて", -12.683980941772461 ], [ "▁大通り", -12.68403148651123 ], [ "大野", -12.684242248535156 ], [ "隼", -12.68425178527832 ], [ "▁弾いて", -12.684274673461914 ], [ "©", -12.684287071228027 ], [ "▁佐川", -12.684370994567871 ], [ "▁北見", -12.684419631958008 ], [ "▁Galaxy", -12.684443473815918 ], [ "▁Min", -12.68450927734375 ], [ "▁笑わ", -12.684779167175293 ], [ "昂", -12.684823989868164 ], [ "nan", -12.684956550598145 ], [ "壕", -12.685014724731445 ], [ "▁無くなった", -12.685036659240723 ], [ "▁囲む", -12.685171127319336 ], [ "▁官報", -12.685190200805664 ], [ "▁Comments", -12.685215950012207 ], [ "ARE", -12.685294151306152 ], [ "▁刻み", -12.685405731201172 ], [ "ips", -12.685440063476562 ], [ "rew", -12.685571670532227 ], [ "▁孤児", -12.685585975646973 ], [ "▁えっ", -12.685604095458984 ], [ "▁洋書", -12.685614585876465 ], [ "ッロ", -12.685638427734375 ], [ "議会", -12.685713768005371 ], [ "▁Cu", -12.685746192932129 ], [ "▁ハンデ", -12.685839653015137 ], [ "hiro", -12.685900688171387 ], [ "▁出兵", -12.68598461151123 ], [ "mus", -12.685985565185547 ], [ "キヤ", -12.686036109924316 ], [ "揮", -12.68605899810791 ], [ "rip", -12.686129570007324 ], [ "▁マスメディア", -12.686199188232422 ], [ "フラワー", -12.686199188232422 ], [ "びた", -12.686283111572266 ], [ "▁バラード", -12.686333656311035 ], [ "▁指南", -12.686384201049805 ], [ "ポップ", -12.686453819274902 ], [ "▁カンヌ", -12.686467170715332 ], [ "別に", -12.686530113220215 ], [ "鯛", -12.686538696289062 ], [ "懇", -12.686728477478027 ], [ "▁ツッコミ", -12.686729431152344 ], [ "場合", -12.686753273010254 ], [ "手術", -12.68686580657959 ], [ "▁Games", -12.686893463134766 ], [ "▁Tri", -12.687010765075684 ], [ "▁イワ", -12.687151908874512 ], [ "▁マンコ", -12.687219619750977 ], [ "▁尽くし", -12.687226295471191 ], [ "▁前衛", -12.687244415283203 ], [ "▁ジャマイカ", -12.687302589416504 ], [ "▁倒壊", -12.687313079833984 ], [ "▁欠か", -12.68738842010498 ], [ "▁男児", -12.687399864196777 ], [ "▁病床", -12.687469482421875 ], [ "▁モナコ", -12.687494277954102 ], [ "▁宝暦", -12.687792778015137 ], [ "▁耐える", -12.687814712524414 ], [ "既存", -12.68795108795166 ], [ "▁Del", -12.68802547454834 ], [ "▁フィオナ", -12.688066482543945 ], [ "▁ベラルーシ", -12.688066482543945 ], [ "▁クリーク", -12.688089370727539 ], [ "▁史実", -12.68812084197998 ], [ "▁クロニクル", -12.688257217407227 ], [ "▁メルボルン", -12.688257217407227 ], [ "槌", -12.688257217407227 ], [ "ピロ", -12.688318252563477 ], [ "olf", -12.688360214233398 ], [ "▁ミシェル", -12.688393592834473 ], [ "▁View", -12.688459396362305 ], [ "ステップ", -12.68860149383545 ], [ "宜", -12.688610076904297 ], [ "▁元気で", -12.688688278198242 ], [ "▁時速", -12.688802719116211 ], [ "▁翌朝", -12.688822746276855 ], [ "▁Sal", -12.68883228302002 ], [ "▁坂井", -12.688884735107422 ], [ "▁張る", -12.688941955566406 ], [ "▁後払い", -12.688955307006836 ], [ "▁バレンシア", -12.689021110534668 ], [ "▁スプーン", -12.689213752746582 ], [ "▁コールド", -12.689240455627441 ], [ "魔法", -12.689249038696289 ], [ "法人", -12.68925666809082 ], [ "ヴォル", -12.6892671585083 ], [ "▁万葉", -12.689273834228516 ], [ "▁ナイン", -12.689301490783691 ], [ "▁倒した", -12.689458847045898 ], [ "▁還", -12.689573287963867 ], [ "▁1879", -12.689701080322266 ], [ "▁礼儀", -12.689844131469727 ], [ "▁極上", -12.690099716186523 ], [ "フェア", -12.69013500213623 ], [ "▁騒が", -12.69017505645752 ], [ "▁SHOP", -12.69021987915039 ], [ "うーん", -12.690317153930664 ], [ "ald", -12.690322875976562 ], [ "▁推し進め", -12.690362930297852 ], [ "▁アッシュ", -12.690557479858398 ], [ "ゾル", -12.690608978271484 ], [ "兼ね", -12.690622329711914 ], [ "▁発砲", -12.690765380859375 ], [ "筆者", -12.690898895263672 ], [ "専用", -12.690969467163086 ], [ "▁クリントン", -12.691035270690918 ], [ "ales", -12.691095352172852 ], [ "▁平ら", -12.691120147705078 ], [ "▁ウルグアイ", -12.691126823425293 ], [ "▁心得", -12.69119930267334 ], [ "▁〟", -12.691263198852539 ], [ "▁当方", -12.691302299499512 ], [ "▁index", -12.691319465637207 ], [ "ティクス", -12.691433906555176 ], [ "▁ミント", -12.691459655761719 ], [ "▁たるみ", -12.691533088684082 ], [ "▁川内", -12.691587448120117 ], [ "▁フレア", -12.691612243652344 ], [ "▁加古川", -12.691701889038086 ], [ "▁昆布", -12.691701889038086 ], [ "▁おっさん", -12.691704750061035 ], [ "▁一途", -12.691742897033691 ], [ "▁多量", -12.691757202148438 ], [ "▁就寝", -12.691912651062012 ], [ "ヴェイ", -12.691920280456543 ], [ "▁ステート", -12.691924095153809 ], [ "rec", -12.691947937011719 ], [ "▁ビーフ", -12.692009925842285 ], [ "▁来たら", -12.692066192626953 ], [ "▁久しぶり", -12.692083358764648 ], [ "ツアー", -12.692137718200684 ], [ "▁公約", -12.692157745361328 ], [ "▁ゼリー", -12.692187309265137 ], [ "▁棄却", -12.692276954650879 ], [ "1889", -12.692378044128418 ], [ "▁スロ", -12.692460060119629 ], [ "▁トリノ", -12.692461013793945 ], [ "▁つぶやき", -12.692468643188477 ], [ "▁ž", -12.692469596862793 ], [ "▁オペレーター", -12.692660331726074 ], [ "▁疎開", -12.692744255065918 ], [ "cus", -12.692764282226562 ], [ "▁リピート", -12.692852973937988 ], [ "ao", -12.69294261932373 ], [ "▁引き締め", -12.693094253540039 ], [ "▁応急", -12.693126678466797 ], [ "▁分家", -12.693181037902832 ], [ "▁ムーブメント", -12.693236351013184 ], [ "▁アーバン", -12.693272590637207 ], [ "吻", -12.693428039550781 ], [ "▁ルドルフ", -12.693428993225098 ], [ "稜", -12.693619728088379 ], [ "▁めぐみ", -12.693764686584473 ], [ "▁正午", -12.693795204162598 ], [ "▁許せ", -12.693848609924316 ], [ "▁End", -12.69388484954834 ], [ "青山", -12.693900108337402 ], [ "▁刺身", -12.69392204284668 ], [ "▁絶えず", -12.693947792053223 ], [ "時計", -12.693949699401855 ], [ "▁ソフトボール", -12.693990707397461 ], [ "▁官庁", -12.693991661071777 ], [ "▁別々に", -12.694007873535156 ], [ "ova", -12.694120407104492 ], [ "▁フラグ", -12.69417667388916 ], [ "DF", -12.694330215454102 ], [ "▁魔導", -12.694445610046387 ], [ "▁鑑み", -12.694562911987305 ], [ "▁界隈", -12.69467544555664 ], [ "▁流行って", -12.694753646850586 ], [ "▁download", -12.694966316223145 ], [ "▁ユーティリティ", -12.694966316223145 ], [ "▁ガンガン", -12.69515323638916 ], [ "湘", -12.695158004760742 ], [ "視聴", -12.695323944091797 ], [ "▁2,500", -12.695355415344238 ], [ "成長", -12.695388793945312 ], [ "▁保温", -12.695515632629395 ], [ "▁篠原", -12.695542335510254 ], [ "ผ", -12.69554328918457 ], [ "▁キャロル", -12.695544242858887 ], [ "▁1863", -12.695562362670898 ], [ "▁納豆", -12.695569038391113 ], [ "aru", -12.695707321166992 ], [ "庶", -12.695731163024902 ], [ "▁カウンタ", -12.69587230682373 ], [ "▁奔走", -12.695927619934082 ], [ "lie", -12.695985794067383 ], [ "​", -12.696059226989746 ], [ "匿", -12.696102142333984 ], [ "▁Op", -12.696189880371094 ], [ "▁サイレント", -12.696195602416992 ], [ "▁占有", -12.696197509765625 ], [ "▁思春期", -12.696398735046387 ], [ "▁クルーゼ", -12.696429252624512 ], [ "▁国府", -12.696455955505371 ], [ "▁書式", -12.696808815002441 ], [ "ヒン", -12.696964263916016 ], [ "▁企", -12.696966171264648 ], [ "ウィル", -12.696975708007812 ], [ "▁洋食", -12.697037696838379 ], [ "▁飛車", -12.697123527526855 ], [ "バニ", -12.697187423706055 ], [ "特殊", -12.697237968444824 ], [ "▁元祖", -12.697253227233887 ], [ "陪", -12.69727611541748 ], [ "▁グラミー", -12.697347640991211 ], [ "▁セーラー", -12.697440147399902 ], [ "▁物足りな", -12.697468757629395 ], [ "▁困惑", -12.697469711303711 ], [ "▁福知山", -12.697469711303711 ], [ "▁害虫", -12.69752311706543 ], [ "▁天野", -12.697611808776855 ], [ "朱", -12.697613716125488 ], [ "窪", -12.697617530822754 ], [ "▁杉山", -12.697653770446777 ], [ "▁スパイダー", -12.697752952575684 ], [ "▁ポテト", -12.697855949401855 ], [ "栄養", -12.697904586791992 ], [ "需", -12.697911262512207 ], [ "嘆", -12.69797420501709 ], [ "▁御前", -12.698027610778809 ], [ "▁デリケート", -12.698047637939453 ], [ "▁余計に", -12.698047637939453 ], [ "▁替えて", -12.698263168334961 ], [ "ニェ", -12.698278427124023 ], [ "数学", -12.69827938079834 ], [ "▁嘱託", -12.698433876037598 ], [ "▁要した", -12.69844913482666 ], [ "▁通気", -12.698505401611328 ], [ "▁love", -12.69865608215332 ], [ "▁春日井", -12.698721885681152 ], [ "▁ライブラリー", -12.698728561401367 ], [ "▁駐輪場", -12.698820114135742 ], [ "▁ぶち", -12.698945045471191 ], [ "▁ヒップ", -12.69914436340332 ], [ "▁レポ", -12.699164390563965 ], [ "▁Link", -12.699183464050293 ], [ "▁覗き", -12.699207305908203 ], [ "▁マーベル", -12.699214935302734 ], [ "▁ペナルティ", -12.699315071105957 ], [ "kt", -12.699345588684082 ], [ "▁紀行", -12.699464797973633 ], [ "中学生", -12.69968032836914 ], [ "▁Express", -12.699807167053223 ], [ "▁歌曲", -12.699841499328613 ], [ "▁カルト", -12.6998872756958 ], [ "▁失格", -12.699894905090332 ], [ "▁ドロー", -12.700071334838867 ], [ "▁目立って", -12.700116157531738 ], [ "▁バロック", -12.70012378692627 ], [ "▁湿気", -12.700139999389648 ], [ "REAL", -12.700174331665039 ], [ "業界", -12.700191497802734 ], [ "入って", -12.700386047363281 ], [ "▁接収", -12.700456619262695 ], [ "▁THC", -12.700540542602539 ], [ "▁アベ", -12.700554847717285 ], [ "▁正直な", -12.70057487487793 ], [ "ディッシュ", -12.700586318969727 ], [ "▁外傷", -12.700663566589355 ], [ "▁描け", -12.70080280303955 ], [ "カブト", -12.700843811035156 ], [ "▁石碑", -12.70092487335205 ], [ "こんなに", -12.701054573059082 ], [ "▁道のり", -12.70110034942627 ], [ "▁GUI", -12.701146125793457 ], [ "▁ひげ", -12.701168060302734 ], [ "▁クーラー", -12.701172828674316 ], [ "備考", -12.701197624206543 ], [ "ウエ", -12.701215744018555 ], [ "Alexa", -12.701269149780273 ], [ "カビ", -12.701448440551758 ], [ "▁稲葉", -12.701459884643555 ], [ "実家", -12.701556205749512 ], [ "PT", -12.701594352722168 ], [ "▁メシ", -12.701605796813965 ], [ "▁粘り", -12.701739311218262 ], [ "▁苦しく", -12.701822280883789 ], [ "▁またがる", -12.701896667480469 ], [ "鷺", -12.702107429504395 ], [ "生物", -12.702180862426758 ], [ "▁リポーター", -12.702260971069336 ], [ "控", -12.702298164367676 ], [ "▁とどまり", -12.702309608459473 ], [ "在学", -12.702392578125 ], [ "▁値する", -12.702491760253906 ], [ "▁太く", -12.70261287689209 ], [ "▁WIN", -12.702646255493164 ], [ "▁柔術", -12.702688217163086 ], [ "▁満開", -12.70275592803955 ], [ "▁ヨット", -12.702781677246094 ], [ "ali", -12.702939987182617 ], [ "▁増減", -12.70297908782959 ], [ "γ", -12.703076362609863 ], [ "▁おっしゃる", -12.703079223632812 ], [ "小金井", -12.703146934509277 ], [ "TEC", -12.703189849853516 ], [ "▁盛んで", -12.703368186950684 ], [ "目次", -12.70343017578125 ], [ "▁SUV", -12.703454971313477 ], [ "▁1862", -12.703459739685059 ], [ "氣", -12.70346450805664 ], [ "▁アサヒ", -12.703511238098145 ], [ "▁ビットコイン", -12.703658103942871 ], [ "▁無用", -12.703697204589844 ], [ "るべき", -12.7037992477417 ], [ "▁キース", -12.703848838806152 ], [ "▁しまわ", -12.704129219055176 ], [ "▁富んだ", -12.70423412322998 ], [ "▁掴み", -12.704241752624512 ], [ "晃", -12.70424747467041 ], [ "発表", -12.704344749450684 ], [ "北朝鮮", -12.704428672790527 ], [ "▁まちづくり", -12.704434394836426 ], [ "▁むすめ", -12.704434394836426 ], [ "▁合作", -12.704648971557617 ], [ "ヒャ", -12.704751968383789 ], [ "屋根", -12.704766273498535 ], [ "エース", -12.70482063293457 ], [ "▁Hz", -12.704850196838379 ], [ "▁透け", -12.704861640930176 ], [ "▁降った", -12.704891204833984 ], [ "気持ち", -12.704936027526855 ], [ "▁志賀", -12.70495319366455 ], [ "▁仕上げる", -12.705015182495117 ], [ "▁相次いだ", -12.70501708984375 ], [ "膠", -12.70501708984375 ], [ "▁甲州", -12.705080032348633 ], [ "▁アルバート", -12.705100059509277 ], [ "ette", -12.705169677734375 ], [ "▁勝敗", -12.705238342285156 ], [ "▁規律", -12.705599784851074 ], [ "▁RED", -12.705610275268555 ], [ "▁エックス", -12.705620765686035 ], [ "▁棄権", -12.705794334411621 ], [ "▁学費", -12.70585823059082 ], [ "▁廃墟", -12.705992698669434 ], [ "▁嬲", -12.706192970275879 ], [ "ミュージック", -12.70620346069336 ], [ "▁PSP", -12.706221580505371 ], [ "web", -12.706239700317383 ], [ "▁望月", -12.706284523010254 ], [ "▁勝てる", -12.706303596496582 ], [ "▁壊れた", -12.706315040588379 ], [ "市民", -12.706405639648438 ], [ "▁いのち", -12.706510543823242 ], [ "▁見なし", -12.706657409667969 ], [ "▁古本", -12.706686019897461 ], [ "▁赤穂", -12.70671272277832 ], [ "▁ちか", -12.706742286682129 ], [ "onic", -12.706801414489746 ], [ "▁頑張れ", -12.706844329833984 ], [ "▁もらわ", -12.707025527954102 ], [ "▁羽織", -12.707130432128906 ], [ "ally", -12.707237243652344 ], [ "▁入党", -12.70724868774414 ], [ "▁Suica", -12.707380294799805 ], [ "▁唐津", -12.707412719726562 ], [ "▁値下げ", -12.707586288452148 ], [ "▁綺麗で", -12.70766544342041 ], [ "IBA", -12.707671165466309 ], [ "▁キラー", -12.707845687866211 ], [ "▁順で", -12.707889556884766 ], [ "▁オンデマンド", -12.707935333251953 ], [ "▁亡き", -12.707937240600586 ], [ "▁気楽に", -12.707939147949219 ], [ "▁太り", -12.708013534545898 ], [ "▁戦法", -12.708024978637695 ], [ "▁アルジェリア", -12.708130836486816 ], [ "▁便利で", -12.708352088928223 ], [ "ร", -12.708362579345703 ], [ "展示", -12.708402633666992 ], [ "諭", -12.708471298217773 ], [ "▁≪", -12.708477020263672 ], [ "▁ちなんだ", -12.708520889282227 ], [ "▁サンクトペテルブルク", -12.708587646484375 ], [ "▁アダプタ", -12.708614349365234 ], [ "ドライバー", -12.708667755126953 ], [ "▁アッパー", -12.708752632141113 ], [ "▁伝播", -12.708757400512695 ], [ "休日", -12.708767890930176 ], [ "oni", -12.7087984085083 ], [ "▁ひし", -12.708822250366211 ], [ "▁スギ", -12.708901405334473 ], [ "雇", -12.708937644958496 ], [ "▁交わし", -12.709074974060059 ], [ "▁番外", -12.709084510803223 ], [ "eek", -12.709122657775879 ], [ "▁水銀", -12.709157943725586 ], [ "Life", -12.709205627441406 ], [ "ディーズ", -12.709219932556152 ], [ "▁故人", -12.709234237670898 ], [ "▁産み", -12.709271430969238 ], [ "▁マフィア", -12.709318161010742 ], [ "定義", -12.709367752075195 ], [ "▁頒布", -12.709495544433594 ], [ "▁引数", -12.709515571594238 ], [ "励", -12.709527015686035 ], [ "▁カーン", -12.709534645080566 ], [ "▁ペドロ", -12.709611892700195 ], [ "▁キャサリン", -12.70969009399414 ], [ "▁別れた", -12.709722518920898 ], [ "注文", -12.709773063659668 ], [ "▁インターホン", -12.709776878356934 ], [ "▁かぐや", -12.709898948669434 ], [ "▁活字", -12.709979057312012 ], [ "相続", -12.710001945495605 ], [ "▁論者", -12.710140228271484 ], [ "▁Lv", -12.710165977478027 ], [ "lb", -12.710175514221191 ], [ "▁流派", -12.710393905639648 ], [ "体重", -12.710519790649414 ], [ "▁1883", -12.710556983947754 ], [ "▁支配人", -12.710598945617676 ], [ "渇", -12.71066665649414 ], [ "uff", -12.710784912109375 ], [ "▁肛門", -12.710862159729004 ], [ "▁粘膜", -12.71088981628418 ], [ "▁神父", -12.711019515991211 ], [ "▁オタ", -12.7110595703125 ], [ "▁フライング", -12.711078643798828 ], [ "▁積雪", -12.711163520812988 ], [ "▁ジェーン", -12.711182594299316 ], [ "墳丘", -12.711216926574707 ], [ "▁偽り", -12.711238861083984 ], [ "▁楽な", -12.711256980895996 ], [ "1916", -12.71166706085205 ], [ "▁ペルシャ", -12.7117338180542 ], [ "▁肥後", -12.711771965026855 ], [ "▁耕作", -12.711838722229004 ], [ "▁GHQ", -12.711840629577637 ], [ "中島", -12.711860656738281 ], [ "elle", -12.71194076538086 ], [ "▁始めよう", -12.711997032165527 ], [ "▁毛皮", -12.712164878845215 ], [ "▁Pan", -12.712272644042969 ], [ "▁ゆい", -12.712318420410156 ], [ "nit", -12.712702751159668 ], [ "▁明かして", -12.712748527526855 ], [ "吏", -12.71287727355957 ], [ "▁異端", -12.713001251220703 ], [ "▁リフレ", -12.713092803955078 ], [ "櫛", -12.713210105895996 ], [ "蹟", -12.713210105895996 ], [ "▁飼料", -12.713223457336426 ], [ "シタ", -12.713233947753906 ], [ "▁あがって", -12.71330451965332 ], [ "▁貸金", -12.713401794433594 ], [ "▁ヒアリング", -12.71340560913086 ], [ "▁いくらか", -12.713562965393066 ], [ "▁ジャワ", -12.713563919067383 ], [ "泡", -12.713616371154785 ], [ "▁クジラ", -12.713640213012695 ], [ "well", -12.713656425476074 ], [ "▁西南", -12.713705062866211 ], [ "▁9000", -12.713708877563477 ], [ "MENT", -12.713724136352539 ], [ "2,000", -12.713800430297852 ], [ "▁nm", -12.713850021362305 ], [ "▁不祥事", -12.71385669708252 ], [ "▁ルビー", -12.713946342468262 ], [ "▁直下", -12.713951110839844 ], [ "▁万国", -12.713957786560059 ], [ "▁たんぱく", -12.713994026184082 ], [ "▁祭壇", -12.71410846710205 ], [ "▁キュア", -12.714146614074707 ], [ "vision", -12.714238166809082 ], [ "工場", -12.714303016662598 ], [ "▁ネリー", -12.714445114135742 ], [ "▁基質", -12.71462345123291 ], [ "▁ラオス", -12.71462631225586 ], [ "下限", -12.71463680267334 ], [ "word", -12.714752197265625 ], [ "▁宿主", -12.714778900146484 ], [ "▁企て", -12.714783668518066 ], [ "▁BY", -12.714805603027344 ], [ "モク", -12.7149076461792 ], [ "▁レパートリー", -12.714974403381348 ], [ "▁無力", -12.715008735656738 ], [ "▁凹", -12.71501636505127 ], [ "排", -12.715452194213867 ], [ "▁開山", -12.715597152709961 ], [ "▁ウェーブ", -12.71561336517334 ], [ "ドラゴン", -12.715683937072754 ], [ "▁有効である", -12.715715408325195 ], [ "▁透析", -12.715764999389648 ], [ "▁エステル", -12.715829849243164 ], [ "重なる", -12.7159423828125 ], [ "▁完封", -12.715997695922852 ], [ "▁弾力", -12.716146469116211 ], [ "sor", -12.716181755065918 ], [ "▁稔", -12.716198921203613 ], [ "結論", -12.716207504272461 ], [ "尺", -12.716273307800293 ], [ "▁真っ白", -12.716310501098633 ], [ "▁津山", -12.716341972351074 ], [ "▁グラント", -12.716348648071289 ], [ "▁慈善", -12.716365814208984 ], [ "▁赤羽", -12.71643352508545 ], [ "表面", -12.71656608581543 ], [ "▁切除", -12.716638565063477 ], [ "▁ベンガル", -12.716642379760742 ], [ "▁考えたら", -12.71666145324707 ], [ "芋", -12.716852188110352 ], [ "▁平衡", -12.716878890991211 ], [ "▁カオス", -12.716894149780273 ], [ "▁公害", -12.716936111450195 ], [ "▁前立腺", -12.716938018798828 ], [ "▁なぞ", -12.716986656188965 ], [ "履", -12.717005729675293 ], [ "鼠", -12.717135429382324 ], [ "スーツ", -12.717151641845703 ], [ "殺し", -12.717341423034668 ], [ "▁ホームラン", -12.717536926269531 ], [ "▁フォルム", -12.717543601989746 ], [ "▁伸びた", -12.717595100402832 ], [ "山号", -12.71774673461914 ], [ "フィリピン", -12.717841148376465 ], [ "▁賭博", -12.71792221069336 ], [ "利根川", -12.717935562133789 ], [ "▁ハマって", -12.718026161193848 ], [ "▁後編", -12.718132019042969 ], [ "▁鵜", -12.718223571777344 ], [ "▁アンディ", -12.718235969543457 ], [ "といって", -12.718238830566406 ], [ "▁開票", -12.718344688415527 ], [ "駅名", -12.71838665008545 ], [ "▁到底", -12.718512535095215 ], [ "▁ヴェルディ", -12.718567848205566 ], [ "チュール", -12.71865463256836 ], [ "▁余剰", -12.718720436096191 ], [ "▁平穏", -12.718849182128906 ], [ "▁軟骨", -12.718873023986816 ], [ "▁お邪魔", -12.71890640258789 ], [ "ティーノ", -12.718968391418457 ], [ "▁不明に", -12.71919059753418 ], [ "aa", -12.719292640686035 ], [ "▁ENU", -12.719295501708984 ], [ "▁クリミア", -12.719405174255371 ], [ "▁観賞", -12.719423294067383 ], [ "錫", -12.719497680664062 ], [ "灰", -12.719502449035645 ], [ "OUR", -12.71955394744873 ], [ "▁書院", -12.71962833404541 ], [ "▁Association", -12.719694137573242 ], [ "百合", -12.719741821289062 ], [ "長期", -12.719780921936035 ], [ "▁こうとう", -12.719878196716309 ], [ "▁塗布", -12.719929695129395 ], [ "▁取消", -12.71994686126709 ], [ "▁超越", -12.719971656799316 ], [ "rap", -12.719983100891113 ], [ "▁悪性", -12.720170974731445 ], [ "▁グノ", -12.720200538635254 ], [ "▁特製", -12.720475196838379 ], [ "▁コロニー", -12.720487594604492 ], [ "▁天明", -12.720505714416504 ], [ "▁法華", -12.720520973205566 ], [ "1908", -12.72072696685791 ], [ "▁久保田", -12.720818519592285 ], [ "叫", -12.720854759216309 ], [ "▁沼田", -12.720903396606445 ], [ "畔", -12.721033096313477 ], [ "咸", -12.721076011657715 ], [ "▁殴り", -12.721168518066406 ], [ "▁胸部", -12.721294403076172 ], [ "▁あそこ", -12.721303939819336 ], [ "▁色気", -12.721431732177734 ], [ "▁カテ", -12.721525192260742 ], [ "ó", -12.721538543701172 ], [ "地下", -12.721632957458496 ], [ "攻撃", -12.721701622009277 ], [ "▁助産", -12.721858978271484 ], [ "▁ピクセル", -12.721912384033203 ], [ "iga", -12.721940040588379 ], [ "学習", -12.721972465515137 ], [ "あらゆる", -12.722015380859375 ], [ "朴", -12.72205638885498 ], [ "▁上手い", -12.72231388092041 ], [ "▁優良な", -12.722389221191406 ], [ "▁下級", -12.722419738769531 ], [ "▁可能であった", -12.722479820251465 ], [ "▁宮中", -12.722586631774902 ], [ "▁バルーン", -12.722649574279785 ], [ "▁太もも", -12.72265625 ], [ "扶", -12.72265625 ], [ "pu", -12.722686767578125 ], [ "▁ミケ", -12.722779273986816 ], [ "マネー", -12.722797393798828 ], [ "▁未亡人", -12.722853660583496 ], [ "radi", -12.72288990020752 ], [ "▁軽快", -12.722965240478516 ], [ "▁母方", -12.723031044006348 ], [ "▁責務", -12.723052978515625 ], [ "▁ペースト", -12.723068237304688 ], [ "▁放浪", -12.72309684753418 ], [ "▁開港", -12.723398208618164 ], [ "▁ブリュッセル", -12.723454475402832 ], [ "▁学業", -12.723647117614746 ], [ "▁とどまる", -12.723651885986328 ], [ "▁WORK", -12.723836898803711 ], [ "▁呪術", -12.723869323730469 ], [ "ドライ", -12.724137306213379 ], [ "今朝", -12.724205017089844 ], [ "▁父母", -12.724226951599121 ], [ "怨", -12.724239349365234 ], [ "▁銭湯", -12.72429370880127 ], [ "~~~", -12.724384307861328 ], [ "▁幼馴染", -12.72443675994873 ], [ "▁延ばし", -12.724515914916992 ], [ "彰", -12.72454833984375 ], [ "握", -12.724593162536621 ], [ "矩", -12.724635124206543 ], [ "▁ジャンボ", -12.72485637664795 ], [ "▁フェー", -12.725043296813965 ], [ "▁奈々", -12.725065231323242 ], [ "▁口頭", -12.72509765625 ], [ "▁カーペット", -12.725129127502441 ], [ "▁無くなり", -12.725177764892578 ], [ "▁大変だった", -12.72522258758545 ], [ "▁吹く", -12.7256441116333 ], [ "▁802", -12.725820541381836 ], [ "▁サンドイッチ", -12.725824356079102 ], [ "▁茶道", -12.726066589355469 ], [ "▁反則", -12.726107597351074 ], [ "八幡", -12.726119041442871 ], [ "1907", -12.72616195678711 ], [ "▁阿弥陀", -12.726420402526855 ], [ "▁置き場", -12.726451873779297 ], [ "▁煙草", -12.72651481628418 ], [ "暑い", -12.726624488830566 ], [ "▁ヴァージョン", -12.726862907409668 ], [ "渋谷", -12.726893424987793 ], [ "オミ", -12.72714614868164 ], [ "▁有効です", -12.727170944213867 ], [ "▁車載", -12.727270126342773 ], [ "ject", -12.727293968200684 ], [ "▁子音", -12.727302551269531 ], [ "▁飢え", -12.727472305297852 ], [ "nce", -12.72754192352295 ], [ "▁馳せ", -12.727664947509766 ], [ "350", -12.727679252624512 ], [ "▁バイナリ", -12.727768898010254 ], [ "▁不可能に", -12.727788925170898 ], [ "鮭", -12.72780990600586 ], [ "▁ルーフ", -12.727867126464844 ], [ "屋敷", -12.72808837890625 ], [ "▁申し入れ", -12.728090286254883 ], [ "▁マニアック", -12.728103637695312 ], [ "▁宇多", -12.7282133102417 ], [ "▁蒲田", -12.728214263916016 ], [ "民間", -12.72823715209961 ], [ "▁悲鳴", -12.728421211242676 ], [ "▁桑名", -12.728473663330078 ], [ "▁見守る", -12.728608131408691 ], [ "ement", -12.728620529174805 ], [ "road", -12.728662490844727 ], [ "▁選べば", -12.728666305541992 ], [ "▁生年", -12.728713989257812 ], [ "随所", -12.728754043579102 ], [ "▁済ま", -12.728926658630371 ], [ "▁導いて", -12.729000091552734 ], [ "▁LGBT", -12.729008674621582 ], [ "▁情緒", -12.729049682617188 ], [ "▁総監", -12.729129791259766 ], [ "▁朝鮮民主主義人民共和国", -12.729169845581055 ], [ "APP", -12.729244232177734 ], [ "モンゴル", -12.72928237915039 ], [ "ギング", -12.729329109191895 ], [ "▁みなす", -12.729618072509766 ], [ "挺", -12.729734420776367 ], [ "▁フェルディナン", -12.729802131652832 ], [ "▁全編", -12.729842185974121 ], [ "墳", -12.729857444763184 ], [ "▁痩せる", -12.72989559173584 ], [ "range", -12.729928970336914 ], [ "▁Anniversary", -12.729998588562012 ], [ "▁適性", -12.730013847351074 ], [ "▁ロータス", -12.730046272277832 ], [ "▁インターン", -12.730056762695312 ], [ "▁戸塚", -12.730056762695312 ], [ "reat", -12.730057716369629 ], [ "▁金星", -12.730132102966309 ], [ "メイク", -12.730252265930176 ], [ "▁堀江", -12.73035717010498 ], [ "▁そろえ", -12.73038101196289 ], [ "▁パンデミック", -12.73039722442627 ], [ "▁嫌がらせ", -12.73039722442627 ], [ "▁時系列", -12.73039722442627 ], [ "コンビニ", -12.730419158935547 ], [ "gle", -12.730488777160645 ], [ "まして", -12.730550765991211 ], [ "▁イチゴ", -12.730637550354004 ], [ "▁主翼", -12.7306547164917 ], [ "▁ゴードン", -12.730731010437012 ], [ "▁山東", -12.730857849121094 ], [ "魚沼", -12.73095417022705 ], [ "▁信条", -12.731029510498047 ], [ "▁有明", -12.731033325195312 ], [ "▁滝川", -12.731098175048828 ], [ "▁黒く", -12.7311372756958 ], [ "▁ホント", -12.731234550476074 ], [ "ヶ崎", -12.73125171661377 ], [ "オフィス", -12.73143482208252 ], [ "▁č", -12.731598854064941 ], [ "▁走れ", -12.731626510620117 ], [ "▁デビル", -12.731729507446289 ], [ "▁様々です", -12.731935501098633 ], [ "▁吉村", -12.732078552246094 ], [ "▁Gold", -12.73215103149414 ], [ "本格", -12.732186317443848 ], [ "懐", -12.732234001159668 ], [ "トリン", -12.7324800491333 ], [ "▁シンクロ", -12.732492446899414 ], [ "作家", -12.732625007629395 ], [ "▁半田", -12.732787132263184 ], [ "▁五島", -12.732844352722168 ], [ "▁必要だった", -12.732879638671875 ], [ "▁下回る", -12.732993125915527 ], [ "▁休息", -12.73305892944336 ], [ "▁野望", -12.733098983764648 ], [ "▁葬式", -12.733110427856445 ], [ "▁ミツ", -12.733183860778809 ], [ "▁敢えて", -12.733190536499023 ], [ "牡", -12.733190536499023 ], [ "▁HOUSE", -12.733196258544922 ], [ "OVER", -12.73321533203125 ], [ "ARI", -12.733220100402832 ], [ "▁放り", -12.73327922821045 ], [ "▁返上", -12.73330020904541 ], [ "▁あたかも", -12.733390808105469 ], [ "▁細分", -12.733465194702148 ], [ "汚", -12.733471870422363 ], [ "▁第一人者", -12.733590126037598 ], [ "▁パイズリ", -12.733591079711914 ], [ "▁オールインワン", -12.733990669250488 ], [ "▁海浜", -12.73404312133789 ], [ "嬉", -12.734161376953125 ], [ "†", -12.734189987182617 ], [ "▁船員", -12.73419189453125 ], [ "種類", -12.734206199645996 ], [ "▁美脚", -12.734553337097168 ], [ "アリス", -12.734556198120117 ], [ "▁旺盛", -12.734590530395508 ], [ "▁黎明", -12.734591484069824 ], [ "▁架かる", -12.734790802001953 ], [ "▁騙し", -12.734888076782227 ], [ "▁運休", -12.734905242919922 ], [ "▁知行", -12.734914779663086 ], [ "▁フューチャー", -12.734992027282715 ], [ "▁伝染", -12.73504638671875 ], [ "ソフ", -12.735115051269531 ], [ "hor", -12.735133171081543 ], [ "隔", -12.735212326049805 ], [ "洗い", -12.73533821105957 ], [ "♂", -12.735391616821289 ], [ "▁載せる", -12.735416412353516 ], [ "▁前項", -12.735495567321777 ], [ "Go", -12.735511779785156 ], [ "▁マサ", -12.735514640808105 ], [ "最寄り", -12.735658645629883 ], [ "んぷ", -12.735828399658203 ], [ "nim", -12.73582935333252 ], [ "▁フレーバー", -12.735857009887695 ], [ "とりわけ", -12.735859870910645 ], [ "▁築造", -12.735926628112793 ], [ "▁泊まり", -12.736005783081055 ], [ "軒", -12.736055374145508 ], [ "▁素数", -12.736133575439453 ], [ "▁対等", -12.736149787902832 ], [ "▁シェイクスピア", -12.73619270324707 ], [ "▁ワルシャワ", -12.736392974853516 ], [ "▁碁", -12.736455917358398 ], [ "▁ポチ", -12.736565589904785 ], [ "▁ホステス", -12.736593246459961 ], [ "天気", -12.736684799194336 ], [ "fect", -12.736825942993164 ], [ "▁モレ", -12.73684024810791 ], [ "果たして", -12.736879348754883 ], [ "NEX", -12.736888885498047 ], [ "▁悪徳", -12.737138748168945 ], [ "▁ミリタリー", -12.737404823303223 ], [ "濁", -12.737479209899902 ], [ "▁礎", -12.737536430358887 ], [ "TBS", -12.737554550170898 ], [ "▁銘打", -12.737642288208008 ], [ "▁山村", -12.737789154052734 ], [ "▁アルテ", -12.738203048706055 ], [ "デレ", -12.738283157348633 ], [ "すごく", -12.738411903381348 ], [ "▁エーカー", -12.738436698913574 ], [ "PORT", -12.73846435546875 ], [ "▁マネージメント", -12.738600730895996 ], [ "▁修業", -12.738604545593262 ], [ "オカ", -12.738656044006348 ], [ "▁門前", -12.738676071166992 ], [ "ウズベキスタン", -12.738801956176758 ], [ "▁鳩山", -12.738889694213867 ], [ "▁村長", -12.739165306091309 ], [ "▁コーポレート", -12.739203453063965 ], [ "▁バルカン", -12.73933219909668 ], [ "▁欠く", -12.73941421508789 ], [ "巌", -12.739605903625488 ], [ "▁景勝", -12.739786148071289 ], [ "▁琵琶湖", -12.739816665649414 ], [ "▁戻れ", -12.739896774291992 ], [ "▁電荷", -12.73990249633789 ], [ "▁直人", -12.740309715270996 ], [ "▁曲がり", -12.74039077758789 ], [ "▁FREE", -12.74046802520752 ], [ "▁ヴュルテンベルク", -12.740813255310059 ], [ "▁ガンバ", -12.740880966186523 ], [ "ware", -12.741053581237793 ], [ "▁管弦楽", -12.741302490234375 ], [ "Qu", -12.741320610046387 ], [ "▁ひがし", -12.741375923156738 ], [ "▁味わえ", -12.741528511047363 ], [ "▁呑", -12.741584777832031 ], [ "▁アンソニー", -12.741704940795898 ], [ "叔", -12.7418212890625 ], [ "ポスト", -12.742098808288574 ], [ "▁ヒンドゥー", -12.742231369018555 ], [ "ぱん", -12.74232006072998 ], [ "dai", -12.742369651794434 ], [ "▁オシ", -12.742587089538574 ], [ "ヴィッツ", -12.742598533630371 ], [ "磐", -12.742724418640137 ], [ "▁二重", -12.742796897888184 ], [ "▁アングル", -12.742886543273926 ], [ "精品", -12.742900848388672 ], [ "▁カリスマ", -12.74303150177002 ], [ "デモ", -12.74310302734375 ], [ "▁酒場", -12.743135452270508 ], [ "▁コナミ", -12.743237495422363 ], [ "eld", -12.74330997467041 ], [ "alo", -12.743349075317383 ], [ "子育て", -12.743361473083496 ], [ "▁ひとつひとつ", -12.74350357055664 ], [ "MX", -12.743528366088867 ], [ "▁薄れ", -12.74365234375 ], [ "▁尚書", -12.743990898132324 ], [ "uma", -12.744013786315918 ], [ "▁帰化", -12.744308471679688 ], [ "▁メイキング", -12.744343757629395 ], [ "ij", -12.744389533996582 ], [ "移動", -12.744505882263184 ], [ "▁天平", -12.744607925415039 ], [ "▁要項", -12.744675636291504 ], [ "ito", -12.744705200195312 ], [ "▁せめて", -12.744739532470703 ], [ "▁ヘルパー", -12.744840621948242 ], [ "lc", -12.7449312210083 ], [ "▁ネクスト", -12.744978904724121 ], [ "For", -12.745173454284668 ], [ "▁クーパー", -12.745206832885742 ], [ "キーワード", -12.74526309967041 ], [ "▁本庄", -12.745322227478027 ], [ "▁小浜", -12.745370864868164 ], [ "チョン", -12.745372772216797 ], [ "▁違え", -12.745386123657227 ], [ "▁荒野", -12.745413780212402 ], [ "ゾーン", -12.745506286621094 ], [ "▁過ご", -12.745560646057129 ], [ "▁アライメント", -12.745656967163086 ], [ "買取", -12.745661735534668 ], [ "▁ひざ", -12.745762825012207 ], [ "▁つなげる", -12.745819091796875 ], [ "▁1850", -12.745902061462402 ], [ "▁Count", -12.745935440063477 ], [ "積み", -12.746228218078613 ], [ "襄", -12.746264457702637 ], [ "▁われ", -12.746280670166016 ], [ "EO", -12.74632453918457 ], [ "おまけに", -12.746384620666504 ], [ "幾", -12.74640941619873 ], [ "▁カヴァー", -12.746541023254395 ], [ "▁繰り出", -12.746614456176758 ], [ "▁遠距離", -12.746708869934082 ], [ "▁自走", -12.746726989746094 ], [ "▁ケージ", -12.746787071228027 ], [ "▁松永", -12.746803283691406 ], [ "▁争奪", -12.746875762939453 ], [ "▁コモ", -12.747082710266113 ], [ "▁湖南", -12.747082710266113 ], [ "▁IIA", -12.747140884399414 ], [ "▁NBC", -12.747152328491211 ], [ "una", -12.747365951538086 ], [ "▁半袖", -12.747380256652832 ], [ "▁平井", -12.74743366241455 ], [ "▁エレガント", -12.747479438781738 ], [ "▁片岡", -12.747482299804688 ], [ "▁天狗", -12.747528076171875 ], [ "▁明神", -12.747559547424316 ], [ "▁綾瀬", -12.747662544250488 ], [ "祠", -12.747682571411133 ], [ "▁足場", -12.747748374938965 ], [ "▁世俗", -12.747791290283203 ], [ "リッヒ", -12.74787712097168 ], [ "▁テロリスト", -12.747986793518066 ], [ "▁入れ替える", -12.74799919128418 ], [ "▁書評", -12.74805736541748 ], [ "▁搬入", -12.748087882995605 ], [ "▁踏んで", -12.748089790344238 ], [ "▁生き残り", -12.748153686523438 ], [ "ski", -12.748220443725586 ], [ "▁些細な", -12.748291015625 ], [ "本稿", -12.748398780822754 ], [ "用途", -12.748438835144043 ], [ "▁ワーカー", -12.748441696166992 ], [ "▁川端", -12.748552322387695 ], [ "▁メカニック", -12.749009132385254 ], [ "▁ほんとに", -12.749053955078125 ], [ "▁愉し", -12.7491455078125 ], [ "寒い", -12.749152183532715 ], [ "▁逸品", -12.74919605255127 ], [ "▁詰める", -12.749204635620117 ], [ "▁戸建", -12.749284744262695 ], [ "▁パレット", -12.749381065368652 ], [ "▁布教", -12.749407768249512 ], [ "▁円墳", -12.749428749084473 ], [ "▁大黒", -12.749460220336914 ], [ "▁逃げた", -12.749462127685547 ], [ "▁SUN", -12.749485969543457 ], [ "離婚", -12.749527931213379 ], [ "▁リウマチ", -12.749711990356445 ], [ "▁不規則", -12.749711990356445 ], [ "▁久久", -12.749732971191406 ], [ "▁思えて", -12.749800682067871 ], [ "▁問い合せ", -12.74991512298584 ], [ "▁賢明", -12.75024700164795 ], [ "▁地雷", -12.750303268432617 ], [ "ッツォ", -12.750391960144043 ], [ "▁開園", -12.750481605529785 ], [ "▁支払った", -12.750486373901367 ], [ "▁地層", -12.750580787658691 ], [ "▁1865", -12.750629425048828 ], [ "篤", -12.750711441040039 ], [ "▁JD", -12.75080394744873 ], [ "▁KR", -12.750890731811523 ], [ "▁強風", -12.751047134399414 ], [ "▁701", -12.75104808807373 ], [ "▁部局", -12.751059532165527 ], [ "▁避けた", -12.751127243041992 ], [ "▁出逢い", -12.751134872436523 ], [ "▁銚子", -12.751338005065918 ], [ "▁談話", -12.751365661621094 ], [ "▁ウルス", -12.751482963562012 ], [ "▁紙面", -12.75149154663086 ], [ "▁流行り", -12.75155258178711 ], [ "ニックス", -12.7515869140625 ], [ "▁天守", -12.751794815063477 ], [ "一線", -12.751805305480957 ], [ "カスティーリャ", -12.751949310302734 ], [ "▁譲って", -12.752022743225098 ], [ "▁円筒", -12.752115249633789 ], [ "析", -12.752119064331055 ], [ "ディズニー", -12.752150535583496 ], [ "▁塩素", -12.752218246459961 ], [ "▁巫女", -12.75235652923584 ], [ "▁GIRL", -12.752388000488281 ], [ "SY", -12.752442359924316 ], [ "▁ブタ", -12.752464294433594 ], [ "▁ブレーブス", -12.752763748168945 ], [ "▁十分で", -12.752897262573242 ], [ "▁Paul", -12.753022193908691 ], [ "▁アナリティクス", -12.75317096710205 ], [ "▁コンプライアンス", -12.75317096710205 ], [ "▁口臭", -12.753186225891113 ], [ "▁コンペ", -12.753205299377441 ], [ "▁あく", -12.75329303741455 ], [ "▁ギルド", -12.753314971923828 ], [ "▁着想", -12.753337860107422 ], [ "§", -12.753375053405762 ], [ "再び", -12.753464698791504 ], [ "▁野郎", -12.753495216369629 ], [ "怖", -12.753581047058105 ], [ "▁美乳", -12.753636360168457 ], [ "▁リビア", -12.753702163696289 ], [ "ふた", -12.753713607788086 ], [ "▁段落", -12.753719329833984 ], [ "▁映る", -12.753775596618652 ], [ "諡", -12.753783226013184 ], [ "▁綴り", -12.754026412963867 ], [ "680", -12.754149436950684 ], [ "▁袴", -12.754190444946289 ], [ "▁垣間見", -12.75439453125 ], [ "▁ボンド", -12.754497528076172 ], [ "げき", -12.75460433959961 ], [ "▁ジャンクション", -12.754732131958008 ], [ "▁査読", -12.754804611206055 ], [ "イック", -12.75487232208252 ], [ "db", -12.754944801330566 ], [ "▁報知", -12.7550048828125 ], [ "▁EXILE", -12.75500774383545 ], [ "▁KDDI", -12.75500774383545 ], [ "▁遊撃手", -12.75500774383545 ], [ "etter", -12.755084991455078 ], [ "促", -12.755091667175293 ], [ "▁Port", -12.755141258239746 ], [ "▁Edge", -12.755215644836426 ], [ "▁なにより", -12.75555419921875 ], [ "▁充当", -12.755578994750977 ], [ "妓", -12.755620956420898 ], [ "堺", -12.755646705627441 ], [ "▁いずみ", -12.755712509155273 ], [ "▁ガッ", -12.75588607788086 ], [ "▁相手方", -12.755951881408691 ], [ "▁仕切", -12.755996704101562 ], [ "ゴールド", -12.755999565124512 ], [ "▁汚い", -12.756025314331055 ], [ "太后", -12.756097793579102 ], [ "▁自営", -12.75620174407959 ], [ "蒔", -12.756438255310059 ], [ "肺", -12.756471633911133 ], [ "▁明瞭", -12.756647109985352 ], [ "▁満席", -12.756834030151367 ], [ "hl", -12.756837844848633 ], [ "▁叔母", -12.756847381591797 ], [ "渚", -12.756847381591797 ], [ "▁暫く", -12.75684928894043 ], [ "IK", -12.756892204284668 ], [ "▁高砂", -12.756935119628906 ], [ "▁カタール", -12.75700569152832 ], [ "▁新造", -12.757177352905273 ], [ "▁借用", -12.75733757019043 ], [ "▁離党", -12.757408142089844 ], [ "長男", -12.757413864135742 ], [ "anta", -12.757455825805664 ], [ "▁鳴き声", -12.757461547851562 ], [ "▁免税", -12.757493019104004 ], [ "呉", -12.757502555847168 ], [ "因み", -12.757513046264648 ], [ "▁data", -12.757594108581543 ], [ "▁トレンチ", -12.757600784301758 ], [ "▁カンパ", -12.75765323638916 ], [ "▁開運", -12.75770378112793 ], [ "票", -12.757709503173828 ], [ "ウイルス", -12.757843971252441 ], [ "▁ヘルマン", -12.757844924926758 ], [ "▁初等", -12.757882118225098 ], [ "▁引け", -12.75797176361084 ], [ "冒頭", -12.757996559143066 ], [ "沿", -12.758118629455566 ], [ "▁破滅", -12.758133888244629 ], [ "委員", -12.758146286010742 ], [ "moto", -12.758185386657715 ], [ "▁栄え", -12.758288383483887 ], [ "▁間際", -12.75833511352539 ], [ "▁丁度", -12.758431434631348 ], [ "TEL", -12.758501052856445 ], [ "UKI", -12.758644104003906 ], [ "らぬ", -12.758668899536133 ], [ "▁イデオロギー", -12.75869083404541 ], [ "▁コロコロ", -12.758706092834473 ], [ "ビタミン", -12.758792877197266 ], [ "▁裁量", -12.758816719055176 ], [ "▁歯車", -12.758825302124023 ], [ "ECT", -12.75882625579834 ], [ "▁カーター", -12.758835792541504 ], [ "▁Key", -12.758880615234375 ], [ "▁窃盗", -12.758895874023438 ], [ "▁供述", -12.75894546508789 ], [ "▁ストール", -12.759092330932617 ], [ "▁大胆な", -12.759101867675781 ], [ "▁NGO", -12.759150505065918 ], [ "▁禁断", -12.759178161621094 ], [ "▁フタ", -12.759256362915039 ], [ "▁鉱石", -12.759678840637207 ], [ "茜", -12.759716033935547 ], [ "鉾", -12.759716033935547 ], [ "▁油断", -12.75971794128418 ], [ "▁欠ける", -12.759803771972656 ], [ "コスト", -12.759810447692871 ], [ "念のため", -12.759921073913574 ], [ "▁茹で", -12.75992202758789 ], [ "猛", -12.759976387023926 ], [ "▁ゆか", -12.759988784790039 ], [ "▁坂道", -12.760102272033691 ], [ "▁必要であり", -12.760193824768066 ], [ "ダメ", -12.76025104522705 ], [ "クレイ", -12.760276794433594 ], [ "▁グルジア", -12.760376930236816 ], [ "▁紀州", -12.760392189025879 ], [ "▁何だか", -12.760437965393066 ], [ "ony", -12.760451316833496 ], [ "▁浅井", -12.760704040527344 ], [ "▁漠然と", -12.7607421875 ], [ "▁警部", -12.760746002197266 ], [ "▁座敷", -12.760890007019043 ], [ "▁見積も", -12.760934829711914 ], [ "人工", -12.760951042175293 ], [ "OH", -12.761075973510742 ], [ "▁まともな", -12.761157989501953 ], [ "マヌエル", -12.761165618896484 ], [ "last", -12.761177062988281 ], [ "▁フアン", -12.761262893676758 ], [ "▁定量", -12.761354446411133 ], [ "括弧", -12.761438369750977 ], [ "▁1866", -12.761443138122559 ], [ "ask", -12.761484146118164 ], [ "昨今", -12.761507034301758 ], [ "▁出所", -12.76155948638916 ], [ "▁新婚", -12.761619567871094 ], [ "結構", -12.761879920959473 ], [ "▁青汁", -12.762079238891602 ], [ "ブロー", -12.762173652648926 ], [ "▁長持ち", -12.76235580444336 ], [ "▁Research", -12.76242733001709 ], [ "▁ムル", -12.762505531311035 ], [ "▁狭山", -12.762506484985352 ], [ "▁トレーラー", -12.762675285339355 ], [ "▁シティー", -12.76275634765625 ], [ "▁ストレーター", -12.762842178344727 ], [ "斐", -12.762985229492188 ], [ "悔", -12.763189315795898 ], [ "▁風合い", -12.763200759887695 ], [ "▁廉価", -12.763212203979492 ], [ "▁敦賀", -12.763277053833008 ], [ "▁オンリー", -12.763405799865723 ], [ "▁顕著に", -12.763411521911621 ], [ "兜", -12.763622283935547 ], [ "▁告げた", -12.763778686523438 ], [ "Category", -12.763910293579102 ], [ "▁試聴", -12.764058113098145 ], [ "▁代引", -12.764079093933105 ], [ "注目", -12.76431655883789 ], [ "▁ウォルター", -12.764357566833496 ], [ "逐", -12.76444149017334 ], [ "▁小室", -12.76446533203125 ], [ "▁DeNA", -12.764542579650879 ], [ "▁プロポーズ", -12.764859199523926 ], [ "殊", -12.765022277832031 ], [ "▁奪って", -12.765091896057129 ], [ "▁水位", -12.765161514282227 ], [ "▁沈め", -12.76541805267334 ], [ "▁おでかけ", -12.765481948852539 ], [ "▁切れた", -12.765671730041504 ], [ "樺", -12.765684127807617 ], [ "▁遭難", -12.765891075134277 ], [ "▁ペニス", -12.765908241271973 ], [ "前半", -12.76591968536377 ], [ "▁増毛", -12.766067504882812 ], [ "▁売れた", -12.76608657836914 ], [ "▁呪文", -12.766226768493652 ], [ "ˆ", -12.766510009765625 ], [ "▁カザフスタン", -12.766510009765625 ], [ "▁悟り", -12.766623497009277 ], [ "▁奥行", -12.766633987426758 ], [ "▁岩国", -12.766868591308594 ], [ "渾", -12.766923904418945 ], [ "▁山林", -12.767035484313965 ], [ "ARC", -12.767070770263672 ], [ "▁困ら", -12.767136573791504 ], [ "▁終身", -12.767287254333496 ], [ "▁ロベルト", -12.767373085021973 ], [ "▁デイヴィス", -12.767379760742188 ], [ "▁スーツケース", -12.767383575439453 ], [ "憑", -12.767541885375977 ], [ "▁Robert", -12.76755428314209 ], [ "▁ブースター", -12.767616271972656 ], [ "▁MEN", -12.767657279968262 ], [ "▁ふさ", -12.767720222473145 ], [ "▁爬虫類", -12.76775074005127 ], [ "▁‹", -12.767777442932129 ], [ "▁無理やり", -12.767824172973633 ], [ "AVE", -12.767904281616211 ], [ "و", -12.76795768737793 ], [ "僅", -12.768113136291504 ], [ "tics", -12.768148422241211 ], [ "▁試練", -12.768213272094727 ], [ "AMA", -12.768317222595215 ], [ "▁VMware", -12.76837158203125 ], [ "▁乱交", -12.768391609191895 ], [ "▁深海", -12.768491744995117 ], [ "▁毎朝", -12.768514633178711 ], [ "▁ソフィア", -12.768664360046387 ], [ "タリア", -12.768705368041992 ], [ "▁丸く", -12.76885986328125 ], [ "▁海鮮", -12.768928527832031 ], [ "▁提訴", -12.76899242401123 ], [ "▁づらく", -12.768993377685547 ], [ "▁陽気", -12.769186019897461 ], [ "ピコ", -12.769207954406738 ], [ "▁がちだ", -12.769335746765137 ], [ "▁スティーヴ", -12.769412994384766 ], [ "▁Green", -12.769418716430664 ], [ "apa", -12.769453048706055 ], [ "▁選別", -12.769471168518066 ], [ "▁宮古", -12.769515991210938 ], [ "▁Huawei", -12.769821166992188 ], [ "▁気力", -12.769989013671875 ], [ "▁ドラゴンクエスト", -12.770041465759277 ], [ "▁変容", -12.770166397094727 ], [ "シネマ", -12.770381927490234 ], [ "▁下北沢", -12.7704439163208 ], [ "▁結社", -12.770491600036621 ], [ "▁空腹", -12.77057933807373 ], [ "仮想", -12.77061653137207 ], [ "▁換金", -12.770652770996094 ], [ "public", -12.770658493041992 ], [ "▁角質", -12.770661354064941 ], [ "及", -12.770706176757812 ], [ "▁権現", -12.770805358886719 ], [ "▁関ヶ原", -12.770885467529297 ], [ "▁潮流", -12.770906448364258 ], [ "みず", -12.770916938781738 ], [ "▁公用", -12.770917892456055 ], [ "ソフトウェア", -12.770956993103027 ], [ "▁トリミング", -12.770991325378418 ], [ "▁本棚", -12.771044731140137 ], [ "็", -12.771065711975098 ], [ "▁トラフィック", -12.771065711975098 ], [ "▁岩倉", -12.771117210388184 ], [ "▁相姦", -12.771150588989258 ], [ "▁rpm", -12.77127456665039 ], [ "▁装填", -12.771276473999023 ], [ "▁変速", -12.771313667297363 ], [ "ガミ", -12.771434783935547 ], [ "▁若林", -12.7715482711792 ], [ "毅", -12.771642684936523 ], [ "▁花園", -12.77178955078125 ], [ "影響", -12.771865844726562 ], [ "▁いちいち", -12.771967887878418 ], [ "▁パトロール", -12.772104263305664 ], [ "▁ドジャース", -12.77210521697998 ], [ "▁点火", -12.772109985351562 ], [ "▁擦り", -12.772112846374512 ], [ "▁分かれた", -12.772239685058594 ], [ "▁but", -12.772350311279297 ], [ "▁アザ", -12.772436141967773 ], [ "セミ", -12.772502899169922 ], [ "▁曹操", -12.772527694702148 ], [ "▁his", -12.772537231445312 ], [ "▁低地", -12.772541999816895 ], [ "賦", -12.772727012634277 ], [ "▁島々", -12.772741317749023 ], [ "やっと", -12.772876739501953 ], [ "▁払え", -12.772892951965332 ], [ "▁末尾", -12.77292251586914 ], [ "ぶき", -12.772997856140137 ], [ "▁ジョイント", -12.773421287536621 ], [ "パッケージ", -12.773524284362793 ], [ "▁充填", -12.773560523986816 ], [ "ほんと", -12.773591995239258 ], [ "▁立教", -12.773691177368164 ], [ "会津", -12.77371597290039 ], [ "鳥取", -12.773866653442383 ], [ "▁芳香", -12.773935317993164 ], [ "▁守山", -12.774249076843262 ], [ "▁触手", -12.774385452270508 ], [ "両者", -12.774452209472656 ], [ "▁変色", -12.774459838867188 ], [ "oka", -12.7746000289917 ], [ "▁オアシス", -12.7746000289917 ], [ "▁フレイ", -12.774658203125 ], [ "印刷", -12.774789810180664 ], [ "ソース", -12.77481746673584 ], [ "▁リポート", -12.774906158447266 ], [ "▁テトラ", -12.774916648864746 ], [ "▁拠出", -12.775020599365234 ], [ "▁交点", -12.775128364562988 ], [ "福寺", -12.775195121765137 ], [ "櫓", -12.775224685668945 ], [ "社員", -12.775224685668945 ], [ "▁構文", -12.775226593017578 ], [ "斬新な", -12.775246620178223 ], [ "鍵", -12.775413513183594 ], [ "▁望んだ", -12.775423049926758 ], [ "▁Education", -12.775433540344238 ], [ "▁ツル", -12.775739669799805 ], [ "▁類型", -12.775810241699219 ], [ "▁進級", -12.775903701782227 ], [ "▁フェーズ", -12.775943756103516 ], [ "▁弾く", -12.776049613952637 ], [ "▁サミュエル", -12.7760591506958 ], [ "▁慰霊", -12.7760591506958 ], [ "費用", -12.776074409484863 ], [ "▁タレ", -12.776076316833496 ], [ "▁¤", -12.776193618774414 ], [ "ANS", -12.77621841430664 ], [ "▁書こう", -12.776226997375488 ], [ "▁ピッツバーグ", -12.77647590637207 ], [ "雁", -12.77647590637207 ], [ "▁美里", -12.776504516601562 ], [ "▁忙しくて", -12.776529312133789 ], [ "▁ミラクル", -12.776937484741211 ], [ "▁about", -12.77710247039795 ], [ "▁頑丈", -12.77710247039795 ], [ "▁根岸", -12.77717399597168 ], [ "オオ", -12.777250289916992 ], [ "▁散乱", -12.777251243591309 ], [ "▁着いて", -12.777303695678711 ], [ "缶", -12.777307510375977 ], [ "ベク", -12.777369499206543 ], [ "▁カラーリング", -12.777397155761719 ], [ "▁Ru", -12.77747917175293 ], [ "▁水色", -12.777573585510254 ], [ "資料", -12.77757453918457 ], [ "女優", -12.77768611907959 ], [ "▁防具", -12.777725219726562 ], [ "デュタステリド", -12.777729034423828 ], [ "▁File", -12.777851104736328 ], [ "▁ローレンス", -12.777853012084961 ], [ "あたたか", -12.77785587310791 ], [ "▁樋口", -12.777938842773438 ], [ "▁google", -12.777945518493652 ], [ "▁ハングル", -12.77800464630127 ], [ "▁絶縁", -12.778020858764648 ], [ "▁照会", -12.77805233001709 ], [ "▁talk", -12.77808952331543 ], [ "▁コンテ", -12.778139114379883 ], [ "盾", -12.778151512145996 ], [ "rat", -12.77819538116455 ], [ "▁乳房", -12.778299331665039 ], [ "公立", -12.778422355651855 ], [ "▁操る", -12.778425216674805 ], [ "名鉄", -12.779035568237305 ], [ "▁おさめ", -12.77907657623291 ], [ "▁みゆき", -12.779088973999023 ], [ "▁大映", -12.779401779174805 ], [ "▁WAVE", -12.779532432556152 ], [ "▁Ann", -12.779589653015137 ], [ "▁参詣", -12.779626846313477 ], [ "▁フリゲート", -12.779632568359375 ], [ "閥", -12.779662132263184 ], [ "▁翻弄", -12.779821395874023 ], [ "▁前向きな", -12.77982234954834 ], [ "▁繊細", -12.77983570098877 ], [ "▁ひか", -12.780081748962402 ], [ "run", -12.78011417388916 ], [ "▁転じて", -12.780150413513184 ], [ "▁上半身", -12.78023910522461 ], [ "▁無数の", -12.780241012573242 ], [ "▁多摩川", -12.780261993408203 ], [ "街道", -12.780328750610352 ], [ "▁東京電力", -12.780380249023438 ], [ "VM", -12.780401229858398 ], [ "▁涼子", -12.780410766601562 ], [ "▁スプラ", -12.78061294555664 ], [ "▁スパーク", -12.780670166015625 ], [ "▁久留", -12.780712127685547 ], [ "▁SEA", -12.780817985534668 ], [ "痛み", -12.780876159667969 ], [ "鐘", -12.780879974365234 ], [ "bn", -12.780952453613281 ], [ "▁バッファロー", -12.78096866607666 ], [ "縦", -12.781096458435059 ], [ "スコット", -12.7811918258667 ], [ "▁ノーザン", -12.781205177307129 ], [ "▁ラブコメ", -12.78128719329834 ], [ "▁王権", -12.781392097473145 ], [ "▁揶揄", -12.78149700164795 ], [ "▁あがる", -12.781542778015137 ], [ "▁盛況", -12.781546592712402 ], [ "▁捧げる", -12.781551361083984 ], [ "mun", -12.781750679016113 ], [ "▁ブロード", -12.7818603515625 ], [ "▁インポート", -12.781956672668457 ], [ "▁並べる", -12.78200912475586 ], [ "mix", -12.782039642333984 ], [ "▁尋ねた", -12.782173156738281 ], [ "▁キャンバス", -12.782201766967773 ], [ "だいがく", -12.782201766967773 ], [ "▁エフエム", -12.782343864440918 ], [ "▁賑わい", -12.782546043395996 ], [ "▁迷宮", -12.782547950744629 ], [ "▁ボールペン", -12.782573699951172 ], [ "▁突き止め", -12.78262710571289 ], [ "▁無意味", -12.782649993896484 ], [ "▁初旬", -12.7827730178833 ], [ "スコア", -12.782918930053711 ], [ "▁ユリウス", -12.782958984375 ], [ "▁fr", -12.783040046691895 ], [ "▁背負って", -12.783095359802246 ], [ "毘", -12.783174514770508 ], [ "▁比べれば", -12.783207893371582 ], [ "▁アンコール", -12.783257484436035 ], [ "▁そうだった", -12.783281326293945 ], [ "クレア", -12.783489227294922 ], [ "▁ソファー", -12.783602714538574 ], [ "当たり前です", -12.783674240112305 ], [ "▁測る", -12.78367805480957 ], [ "▁成就", -12.783738136291504 ], [ "▁サンプリング", -12.783805847167969 ], [ "▁広範な", -12.783805847167969 ], [ "▁優駿", -12.784034729003906 ], [ "▁ウエディング", -12.784070014953613 ], [ "▁ハイウェイ", -12.784071922302246 ], [ "▁ゴミ箱", -12.784072875976562 ], [ "OBI", -12.7841796875 ], [ "▁上手な", -12.784200668334961 ], [ "箔", -12.784226417541504 ], [ "▁オーロラ", -12.784228324890137 ], [ "テーブル", -12.784232139587402 ], [ "▁Cha", -12.784279823303223 ], [ "▁class", -12.784481048583984 ], [ "ZU", -12.78465461730957 ], [ "▁回顧", -12.784817695617676 ], [ "ヴォイ", -12.784834861755371 ], [ "▁フュージョン", -12.784857749938965 ], [ "iano", -12.784971237182617 ], [ "▁特異な", -12.785054206848145 ], [ "▁洗脳", -12.785093307495117 ], [ "▁FUJI", -12.7852783203125 ], [ "▁岸和田", -12.785296440124512 ], [ "mann", -12.785307884216309 ], [ "ゲラ", -12.785320281982422 ], [ "▁不可能である", -12.785327911376953 ], [ "▁見せつけ", -12.78555679321289 ], [ "古く", -12.78568172454834 ], [ "▁亀山", -12.785730361938477 ], [ "▁広げた", -12.785801887512207 ], [ "▁苫小牧", -12.785910606384277 ], [ "▁挑んだ", -12.78591251373291 ], [ "っかい", -12.785930633544922 ], [ "(3)", -12.785978317260742 ], [ "▁サーフ", -12.786028861999512 ], [ "▁広範囲", -12.786042213439941 ], [ "▁馬券", -12.786199569702148 ], [ "▁イヴ", -12.786296844482422 ], [ "rou", -12.786338806152344 ], [ "▁旗揚げ", -12.786357879638672 ], [ "650", -12.78646183013916 ], [ "▁ゲルマン", -12.786482810974121 ], [ "▁彼方", -12.78654956817627 ], [ "面接", -12.786633491516113 ], [ "▁goose", -12.786693572998047 ], [ "俳", -12.78674030303955 ], [ "▁ナイジェリア", -12.786752700805664 ], [ "▁セーフティ", -12.786773681640625 ], [ "▁Phil", -12.786796569824219 ], [ "▁サンパウロ", -12.786964416503906 ], [ "▁贈り", -12.786966323852539 ], [ "▁カナディアン", -12.786979675292969 ], [ "1906", -12.786992073059082 ], [ "▁聞いたら", -12.787028312683105 ], [ "▁アレク", -12.787124633789062 ], [ "▁鍛冶", -12.787175178527832 ], [ "non", -12.787181854248047 ], [ "▁豊かで", -12.78722095489502 ], [ "併", -12.787354469299316 ], [ "▁迎え入れ", -12.78737735748291 ], [ "▁日替わり", -12.787385940551758 ], [ "▁濃縮", -12.78740406036377 ], [ "shima", -12.787430763244629 ], [ "▁別人", -12.787447929382324 ], [ "▁厳格", -12.78765869140625 ], [ "ポーランド", -12.787675857543945 ], [ "▁佐久間", -12.78769588470459 ], [ "▁KADOKAWA", -12.78780746459961 ], [ "▁検閲", -12.78781795501709 ], [ "悦", -12.787894248962402 ], [ "▁乗せる", -12.78791618347168 ], [ "▁軍需", -12.787952423095703 ], [ "▁実地", -12.788007736206055 ], [ "▁リマスター", -12.788020133972168 ], [ "▁ネルソン", -12.788025856018066 ], [ "craft", -12.788154602050781 ], [ "▁不適", -12.788241386413574 ], [ "ハシ", -12.788241386413574 ], [ "▁スポンジ", -12.788248062133789 ], [ "▁要し", -12.788318634033203 ], [ "▁簡略", -12.788440704345703 ], [ "ヶ岳", -12.788476943969727 ], [ "久しぶりに", -12.788531303405762 ], [ "▁ショーン", -12.788708686828613 ], [ "�", -12.788741111755371 ], [ "tis", -12.788808822631836 ], [ "▁勤めた", -12.788866996765137 ], [ "▁魔物", -12.788912773132324 ], [ "bert", -12.788965225219727 ], [ "▁富岡", -12.788969039916992 ], [ "メンタル", -12.78900146484375 ], [ "▁打線", -12.789024353027344 ], [ "▁隣人", -12.789177894592285 ], [ "▁Prince", -12.789290428161621 ], [ "サロン", -12.789444923400879 ], [ "▁George", -12.789497375488281 ], [ "外題", -12.789497375488281 ], [ "▁隷下", -12.789498329162598 ], [ "▁イレブン", -12.789709091186523 ], [ "▁ソーセージ", -12.789709091186523 ], [ "▁ハーモニー", -12.789709091186523 ], [ "▁ルクセンブルク", -12.789709091186523 ], [ "▁ウェスタン", -12.789761543273926 ], [ "▁坂上", -12.78976821899414 ], [ "▁フォーマル", -12.789880752563477 ], [ "卯", -12.78991985321045 ], [ "▁悲惨な", -12.789920806884766 ], [ "▁有望", -12.789920806884766 ], [ "▁応じる", -12.789924621582031 ], [ "スタンフォード", -12.790138244628906 ], [ "▁Hello", -12.790166854858398 ], [ "マット", -12.79026985168457 ], [ "▁インターンシップ", -12.79035472869873 ], [ "▁脱却", -12.79040241241455 ], [ "▁IEC", -12.790436744689941 ], [ "ゆり", -12.790449142456055 ], [ "▁城跡", -12.790483474731445 ], [ "凪", -12.790555000305176 ], [ "▁SAN", -12.790596008300781 ], [ "1905", -12.790672302246094 ], [ "ヌイ", -12.790691375732422 ], [ "▁David", -12.790775299072266 ], [ "分離", -12.790794372558594 ], [ "▁避妊", -12.791190147399902 ], [ "▁吸う", -12.791240692138672 ], [ "▁思い浮かべ", -12.791274070739746 ], [ "希望", -12.791397094726562 ], [ "▁クズ", -12.791399955749512 ], [ "▁紫色", -12.791418075561523 ], [ "▁マッシュ", -12.79145622253418 ], [ "▁マシュー", -12.791484832763672 ], [ "▁逸脱", -12.791633605957031 ], [ "国土", -12.791753768920898 ], [ "俵", -12.791925430297852 ], [ "▁マテリアル", -12.792037963867188 ], [ "奪", -12.792052268981934 ], [ "NB", -12.792243957519531 ], [ "ape", -12.792261123657227 ], [ "ワナ", -12.792440414428711 ], [ "主題", -12.792498588562012 ], [ "Al", -12.792533874511719 ], [ "▁GOOD", -12.792533874511719 ], [ "▁方策", -12.792651176452637 ], [ "▁踏む", -12.792675018310547 ], [ "▁すぐさま", -12.792859077453613 ], [ "▁署長", -12.792925834655762 ], [ "▁常備", -12.792936325073242 ], [ "テックス", -12.793087005615234 ], [ "▁片山", -12.793120384216309 ], [ "▁浦安", -12.793182373046875 ], [ "孟", -12.793310165405273 ], [ "▁ビク", -12.793432235717773 ], [ "▁交わした", -12.793437004089355 ], [ "てゐる", -12.793466567993164 ], [ "▁松阪", -12.793631553649902 ], [ "厨", -12.793734550476074 ], [ "▁寄せる", -12.793802261352539 ], [ "▁争わ", -12.793829917907715 ], [ "▁女装", -12.79389762878418 ], [ "▁Back", -12.793925285339355 ], [ "▁薬用", -12.793936729431152 ], [ "▁伝わ", -12.794063568115234 ], [ "偉", -12.794185638427734 ], [ "▁横田", -12.79419994354248 ], [ "▁共闘", -12.794260025024414 ], [ "▁ホワイトニング", -12.79427433013916 ], [ "▁溶液", -12.79439640045166 ], [ "hn", -12.794453620910645 ], [ "▁望め", -12.794490814208984 ], [ "ベッド", -12.794517517089844 ], [ "▁怒る", -12.794600486755371 ], [ "▁Heart", -12.794861793518066 ], [ "キャンプ", -12.794900894165039 ], [ "▁箕面", -12.79500961303711 ], [ "▁Angel", -12.795022010803223 ], [ "AVI", -12.795042037963867 ], [ "▁レンタ", -12.795249938964844 ], [ "モイ", -12.795309066772461 ], [ "▁見直", -12.795374870300293 ], [ "eno", -12.795421600341797 ], [ "▁ブンデスリーガ", -12.79543399810791 ], [ "伍", -12.79543399810791 ], [ "▁緯度", -12.795434951782227 ], [ "▁OPEN", -12.795502662658691 ], [ "▁チェルシー", -12.795538902282715 ], [ "▁無機", -12.795680046081543 ], [ "phone", -12.7959566116333 ], [ "▁高官", -12.795976638793945 ], [ "▁オウム", -12.79603385925293 ], [ "モーター", -12.79605770111084 ], [ "▁原文", -12.796117782592773 ], [ "▁濃厚な", -12.796130180358887 ], [ "▁木々", -12.796154022216797 ], [ "▁試算", -12.796161651611328 ], [ "▁Pat", -12.79620361328125 ], [ "▁テロップ", -12.796204566955566 ], [ "▁思わぬ", -12.796263694763184 ], [ "▁農耕", -12.796304702758789 ], [ "▁How", -12.796311378479004 ], [ "▁選曲", -12.796314239501953 ], [ "▁まみれ", -12.796351432800293 ], [ "gram", -12.796408653259277 ], [ "▁叙任", -12.796428680419922 ], [ "〔", -12.796439170837402 ], [ "▁ルーズベルト", -12.79649829864502 ], [ "▁共催", -12.796509742736816 ], [ "▁外貨", -12.796526908874512 ], [ "770", -12.796588897705078 ], [ "abel", -12.796675682067871 ], [ "▁真面目な", -12.796720504760742 ], [ "▁対価", -12.79679012298584 ], [ "▁伴わ", -12.796830177307129 ], [ "▁和室", -12.79686164855957 ], [ "▁エヴァ", -12.796921730041504 ], [ "イエス", -12.797059059143066 ], [ "▁エルミンヌ", -12.797136306762695 ], [ "傳", -12.797136306762695 ], [ "▁讃え", -12.797202110290527 ], [ "▁慌て", -12.797215461730957 ], [ "▁エナジー", -12.797350883483887 ], [ "開き", -12.797404289245605 ], [ "確か", -12.797406196594238 ], [ "▁ワケ", -12.797516822814941 ], [ "▁レスポンス", -12.797562599182129 ], [ "▁根元", -12.797563552856445 ], [ "▁プランニング", -12.797661781311035 ], [ "▁あおい", -12.797769546508789 ], [ "スキル", -12.797782897949219 ], [ "▁正規の", -12.797879219055176 ], [ "▁VHS", -12.797944068908691 ], [ "ネスト", -12.797947883605957 ], [ "▁クア", -12.798011779785156 ], [ "▁接待", -12.798236846923828 ], [ "▁カーキ", -12.798296928405762 ], [ "▁抗原", -12.798306465148926 ], [ "Cloud", -12.798410415649414 ], [ "▁つないで", -12.798421859741211 ], [ "喝", -12.798628807067871 ], [ "▁譲り受け", -12.79863452911377 ], [ "▁0120", -12.798770904541016 ], [ "▁持ちかけ", -12.798788070678711 ], [ "▁ペルソナ", -12.798842430114746 ], [ "ガモ", -12.798843383789062 ], [ "▁割って", -12.798853874206543 ], [ "▁旅人", -12.798858642578125 ], [ "ホット", -12.79903793334961 ], [ "▁Beat", -12.799286842346191 ], [ "ison", -12.799312591552734 ], [ "▁野心", -12.7993745803833 ], [ "▁見直して", -12.799463272094727 ], [ "勿論", -12.799463272094727 ], [ "REN", -12.799484252929688 ], [ "▁巡航", -12.79954719543457 ], [ "▁上洛", -12.799715042114258 ], [ "ERO", -12.79975414276123 ], [ "▁富豪", -12.799765586853027 ], [ "▁旅客機", -12.79979419708252 ], [ "▁大々的", -12.799909591674805 ], [ "▁課せ", -12.799912452697754 ], [ "▁かぎり", -12.79992389678955 ], [ "待ち", -12.799932479858398 ], [ "汝", -12.800097465515137 ], [ "▁隕石", -12.80012321472168 ], [ "▁余分な", -12.800124168395996 ], [ "▁掴む", -12.800124168395996 ], [ "▁cente", -12.800186157226562 ], [ "▁ルアー", -12.800209999084473 ], [ "▁無印", -12.800261497497559 ], [ "▁格付け", -12.800312042236328 ], [ "▁ZIP", -12.800335884094238 ], [ "▁新春", -12.80044174194336 ], [ "▁お守り", -12.80056381225586 ], [ "▁踊って", -12.800581932067871 ], [ "▁遊歩道", -12.800765037536621 ], [ "▁取り決め", -12.80077075958252 ], [ "▁プラモデル", -12.800811767578125 ], [ "▁実数", -12.80081558227539 ], [ "▁イサ", -12.800976753234863 ], [ "▁CBC", -12.801143646240234 ], [ "違う", -12.801191329956055 ], [ "▁ヘビ", -12.801273345947266 ], [ "▁新星", -12.801337242126465 ], [ "▁キネマ", -12.801408767700195 ], [ "▁例文", -12.801444053649902 ], [ "▁溺れ", -12.801501274108887 ], [ "▁譲る", -12.801676750183105 ], [ "▁CENTE", -12.80186653137207 ], [ "▁1861", -12.801876068115234 ], [ "▁座った", -12.802130699157715 ], [ "▁作製", -12.802141189575195 ], [ "ゴット", -12.802251815795898 ], [ "就職", -12.80234432220459 ], [ "潜伏", -12.802361488342285 ], [ "▁ちび", -12.802370071411133 ], [ "▁見極める", -12.80245590209961 ], [ "▁バーク", -12.802645683288574 ], [ "▁高揚", -12.802671432495117 ], [ "▁スライム", -12.802691459655762 ], [ "▁宇野", -12.802846908569336 ], [ "▁河南", -12.80285358428955 ], [ "φ", -12.802905082702637 ], [ "▁算数", -12.802909851074219 ], [ "▁挙式", -12.803013801574707 ], [ "連載", -12.803033828735352 ], [ "香川", -12.803047180175781 ], [ "▁散布", -12.803048133850098 ], [ "▁監察", -12.803118705749512 ], [ "▁詰めた", -12.803119659423828 ], [ "▁ジョル", -12.803247451782227 ], [ "▁部類", -12.803298950195312 ], [ "▁ペンネーム", -12.803333282470703 ], [ "▁叩く", -12.803548812866211 ], [ "▁30,000", -12.803722381591797 ], [ "gra", -12.803750991821289 ], [ "▁ホントに", -12.804099082946777 ], [ "▁NEO", -12.8041353225708 ], [ "▁生き残る", -12.804190635681152 ], [ "▁検挙", -12.804239273071289 ], [ "▁居宅", -12.804304122924805 ], [ "センター", -12.804327964782715 ], [ "▁***", -12.804405212402344 ], [ "▁あだ名", -12.80440616607666 ], [ "▁即ち", -12.804415702819824 ], [ "慶應", -12.804418563842773 ], [ "帥", -12.804780006408691 ], [ "▁天然ガス", -12.804801940917969 ], [ "Search", -12.804811477661133 ], [ "祈", -12.804819107055664 ], [ "チャート", -12.804884910583496 ], [ "ナージャ", -12.804905891418457 ], [ "IPS", -12.804966926574707 ], [ "▁Audi", -12.80496883392334 ], [ "▁わくわく", -12.805049896240234 ], [ "▁West", -12.805071830749512 ], [ "▁完治", -12.805464744567871 ], [ "▁罹患", -12.805479049682617 ], [ "RV", -12.80563735961914 ], [ "ゆえに", -12.805717468261719 ], [ "もしかすると", -12.805930137634277 ], [ "▁死因", -12.805949211120605 ], [ "▁税抜", -12.806092262268066 ], [ "▁ルター", -12.806262016296387 ], [ "▁無限の", -12.806276321411133 ], [ "ショア", -12.806278228759766 ], [ "▁慕容", -12.806354522705078 ], [ "▁相応しい", -12.806408882141113 ], [ "メジャー", -12.806443214416504 ], [ "rag", -12.806596755981445 ], [ "▁掛けた", -12.806596755981445 ], [ "練習", -12.806650161743164 ], [ "ní", -12.806679725646973 ], [ "▁チェコスロバキア", -12.806770324707031 ], [ "透明", -12.806928634643555 ], [ "▁コンピューティング", -12.806983947753906 ], [ "▁加水", -12.80699634552002 ], [ "敷地", -12.807104110717773 ], [ "靖", -12.807229042053223 ], [ "▁不変", -12.807534217834473 ], [ "井上", -12.80762767791748 ], [ "▁発して", -12.807657241821289 ], [ "▁ひね", -12.807686805725098 ], [ "▁青銅", -12.80771255493164 ], [ "▁照準", -12.80789566040039 ], [ "▁洋子", -12.807924270629883 ], [ "▁いまいち", -12.807999610900879 ], [ "ONG", -12.808090209960938 ], [ "▁白馬", -12.80814266204834 ], [ "point", -12.808171272277832 ], [ "▁ふんだんに", -12.808490753173828 ], [ "▁宝くじ", -12.808530807495117 ], [ "▁クワ", -12.808639526367188 ], [ "▁あざ", -12.808666229248047 ], [ "▁難航", -12.808822631835938 ], [ "祇", -12.808921813964844 ], [ "▁旧暦", -12.809133529663086 ], [ "▁遅らせ", -12.809168815612793 ], [ "▁防寒", -12.809226989746094 ], [ "▁玄米", -12.809281349182129 ], [ "▁砂浜", -12.809324264526367 ], [ "▁ハンセン", -12.809757232666016 ], [ "▁ダブリン", -12.809915542602539 ], [ "▁雲南", -12.81005573272705 ], [ "▁健在", -12.810222625732422 ], [ "廣", -12.810271263122559 ], [ "lation", -12.810296058654785 ], [ "地区", -12.810481071472168 ], [ "▁ケイト", -12.810505867004395 ], [ "瑛", -12.810863494873047 ], [ "腱", -12.810863494873047 ], [ "▁ノーフォーク", -12.810885429382324 ], [ "受験", -12.810935020446777 ], [ "▁ふわふわ", -12.811079025268555 ], [ "▁従兄弟", -12.811145782470703 ], [ "▁雇い", -12.811164855957031 ], [ "贈", -12.811326026916504 ], [ "▁ディスコ", -12.811381340026855 ], [ "DV", -12.811437606811523 ], [ "▁華艶", -12.811527252197266 ], [ "▁書写", -12.811546325683594 ], [ "α", -12.811576843261719 ], [ "▁コツコツ", -12.811727523803711 ], [ "▁カカオ", -12.811729431152344 ], [ "ソーム", -12.811742782592773 ], [ "▁向く", -12.811874389648438 ], [ "在线", -12.812012672424316 ], [ "▁空想", -12.812334060668945 ], [ "劣等", -12.812417030334473 ], [ "▁谷口", -12.812482833862305 ], [ "▁霊園", -12.812528610229492 ], [ "峻", -12.812592506408691 ], [ "▁ウケ", -12.812617301940918 ], [ "▁取り出す", -12.812655448913574 ], [ "有名な", -12.812666893005371 ], [ "▁Tur", -12.812702178955078 ], [ "▁アットホーム", -12.81283187866211 ], [ "▁こぼれ", -12.812833786010742 ], [ "ループ", -12.812843322753906 ], [ "▁あつた", -12.812957763671875 ], [ "▁EURO", -12.812976837158203 ], [ "▁積立", -12.812982559204102 ], [ "どく", -12.813011169433594 ], [ "▁ロジック", -12.813029289245605 ], [ "▁電報", -12.813243865966797 ], [ "meth", -12.813455581665039 ], [ "渠", -12.813458442687988 ], [ "そば", -12.813472747802734 ], [ "▁hp", -12.81357479095459 ], [ "惨", -12.81359577178955 ], [ "▁若葉", -12.813643455505371 ], [ "▁不二", -12.813652038574219 ], [ "▁クレーター", -12.813815116882324 ], [ "▁von", -12.8139066696167 ], [ "▁闘士", -12.81401252746582 ], [ "ホフ", -12.814051628112793 ], [ "▁安易に", -12.814107894897461 ], [ "▁セブ", -12.814139366149902 ], [ "召", -12.814140319824219 ], [ "全く", -12.814199447631836 ], [ "▁コスモス", -12.814273834228516 ], [ "劇中", -12.814336776733398 ], [ "ネーター", -12.814393997192383 ], [ "▁異物", -12.814452171325684 ], [ "寛永", -12.814507484436035 ], [ "ete", -12.814554214477539 ], [ "▁怪人", -12.814562797546387 ], [ "▁ペリー", -12.814657211303711 ], [ "指導", -12.814689636230469 ], [ "▁囚われ", -12.814974784851074 ], [ "▁ユタ", -12.815102577209473 ], [ "▁北海", -12.815109252929688 ], [ "La", -12.815122604370117 ], [ "▁甚大な", -12.815192222595215 ], [ "▁東村山", -12.815194129943848 ], [ "▁Syll", -12.815206527709961 ], [ "▁増築", -12.815325736999512 ], [ "▁易く", -12.815376281738281 ], [ "▁日日新聞", -12.815409660339355 ], [ "▁電極", -12.81542682647705 ], [ "▁奥羽", -12.815622329711914 ], [ "▁Science", -12.81562614440918 ], [ "▁コンピレーション", -12.81562614440918 ], [ "▁左京", -12.815661430358887 ], [ "osa", -12.815725326538086 ], [ "▁Season", -12.815849304199219 ], [ "▁経口", -12.815909385681152 ], [ "▁貫く", -12.816248893737793 ], [ "リーニ", -12.816268920898438 ], [ "▁インスタント", -12.816413879394531 ], [ "nov", -12.816452026367188 ], [ "1909", -12.816513061523438 ], [ "亡くな", -12.816579818725586 ], [ "▁志す", -12.816591262817383 ], [ "▁街路", -12.816635131835938 ], [ "▁レーニン", -12.816655158996582 ], [ "▁集う", -12.816781044006348 ], [ "–", -12.816818237304688 ], [ "▁ビクトリア", -12.816939353942871 ], [ "▁乗り場", -12.817001342773438 ], [ "7000", -12.817078590393066 ], [ "アイス", -12.817144393920898 ], [ "网", -12.817146301269531 ], [ "▁運んだ", -12.817148208618164 ], [ "▁ジキル", -12.817463874816895 ], [ "金属", -12.817501068115234 ], [ "ガイド", -12.817602157592773 ], [ "INA", -12.817645072937012 ], [ "▁なんば", -12.817710876464844 ], [ "▁直子", -12.817710876464844 ], [ "▁シードル", -12.817763328552246 ], [ "▁手話", -12.817763328552246 ], [ "▁canada", -12.817809104919434 ], [ "▁コネ", -12.817827224731445 ], [ "▁倍増", -12.817856788635254 ], [ "近隣", -12.817971229553223 ], [ "▁ビルディング", -12.818049430847168 ], [ "巴", -12.818138122558594 ], [ "▁落成", -12.81824779510498 ], [ "▁心配です", -12.81843090057373 ], [ "咬", -12.818450927734375 ], [ "▁Code", -12.818511009216309 ], [ "體", -12.818574905395508 ], [ "▁怪し", -12.818628311157227 ], [ "▁オカマ", -12.818804740905762 ], [ "眩", -12.818885803222656 ], [ "中心", -12.818888664245605 ], [ "GG", -12.818899154663086 ], [ "▁参院", -12.818915367126465 ], [ "▁断る", -12.81900691986084 ], [ "▁極度", -12.819024085998535 ], [ "幼名", -12.819134712219238 ], [ "▁真実の", -12.819242477416992 ], [ "▁トリップ", -12.819250106811523 ], [ "教会", -12.819270133972168 ], [ "▁粛清", -12.819321632385254 ], [ "▁おにぎり", -12.819324493408203 ], [ "▁田畑", -12.819337844848633 ], [ "野菜", -12.819376945495605 ], [ "CTFL", -12.819443702697754 ], [ "スイス", -12.819536209106445 ], [ "▁ジーン", -12.819578170776367 ], [ "▁モダンな", -12.819740295410156 ], [ "▁天竜", -12.819743156433105 ], [ "各国", -12.819940567016602 ], [ "eh", -12.819948196411133 ], [ "▁年月日", -12.819963455200195 ], [ "▁マグネシウム", -12.819974899291992 ], [ "▁乗っ取", -12.819988250732422 ], [ "▁邦画", -12.820056915283203 ], [ "ORD", -12.820155143737793 ], [ "▁松村", -12.820159912109375 ], [ "▁パコパコ", -12.82019329071045 ], [ "▁心掛けて", -12.820194244384766 ], [ "▁Program", -12.820219993591309 ], [ "sho", -12.820490837097168 ], [ "▁王道", -12.820499420166016 ], [ "本貫", -12.820524215698242 ], [ "▁長浜", -12.820528984069824 ], [ "かろう", -12.820578575134277 ], [ "▁論点", -12.820606231689453 ], [ "MV", -12.820725440979004 ], [ "▁HOT", -12.821078300476074 ], [ "▁察し", -12.821091651916504 ], [ "▁的確な", -12.82132339477539 ], [ "▁立ち会", -12.82137393951416 ], [ "▁先立って", -12.821537017822266 ], [ "相対", -12.821707725524902 ], [ "▁走者", -12.821720123291016 ], [ "▁ヴォルフ", -12.821880340576172 ], [ "▁Des", -12.821903228759766 ], [ "▁ハンカチ", -12.821938514709473 ], [ "▁レーフ", -12.821941375732422 ], [ "▁千種", -12.82197380065918 ], [ "▁酒類", -12.822098731994629 ], [ "▁理屈", -12.822195053100586 ], [ "▁柔らか", -12.822306632995605 ], [ "▁RECORDS", -12.822375297546387 ], [ "▁移入", -12.822447776794434 ], [ "マルチ", -12.822498321533203 ], [ "▁ルイジアナ", -12.822593688964844 ], [ "▁遭った", -12.822598457336426 ], [ "▁受精", -12.822672843933105 ], [ "▁ゼウス", -12.82268238067627 ], [ "なんといっても", -12.8228120803833 ], [ "▁ひととき", -12.822815895080566 ], [ "▁DREAM", -12.822824478149414 ], [ "▁ヘッドホン", -12.822931289672852 ], [ "for", -12.823053359985352 ], [ "レンツ", -12.823084831237793 ], [ "Net", -12.823100090026855 ], [ "▁満月", -12.82310676574707 ], [ "▁スパム", -12.823138236999512 ], [ "▁濡れた", -12.823330879211426 ], [ "▁Run", -12.823342323303223 ], [ "▁救世", -12.823343276977539 ], [ "▁求職", -12.823345184326172 ], [ "▁公文書", -12.823468208312988 ], [ "素晴らしい", -12.823631286621094 ], [ "西洋", -12.823654174804688 ], [ "嫡", -12.82368278503418 ], [ "▁item", -12.82369327545166 ], [ "▁襲った", -12.823737144470215 ], [ "▁悔しい", -12.823929786682129 ], [ "内閣", -12.824089050292969 ], [ "爽", -12.824106216430664 ], [ "崇", -12.824280738830566 ], [ "▁ポニーキャニオン", -12.82434368133545 ], [ "▁花束", -12.824437141418457 ], [ "▁条文", -12.824542045593262 ], [ "中学校", -12.824678421020508 ], [ "探り", -12.824695587158203 ], [ "頷", -12.824780464172363 ], [ "▁灌漑", -12.82478141784668 ], [ "▁議案", -12.82500171661377 ], [ "▁容積", -12.825037956237793 ], [ "▁組曲", -12.825196266174316 ], [ "頚", -12.82521915435791 ], [ "蔡", -12.825438499450684 ], [ "▁吐き気", -12.825511932373047 ], [ "▁晴れて", -12.82555866241455 ], [ "▁パイレーツ", -12.825657844543457 ], [ "▁商談", -12.825743675231934 ], [ "▁急進", -12.82584285736084 ], [ "▁チンポ", -12.825888633728027 ], [ "▁資する", -12.826190948486328 ], [ "▁動植物", -12.826348304748535 ], [ "▁ATP", -12.826502799987793 ], [ "替わって", -12.826526641845703 ], [ "▁ハプスブルク", -12.826534271240234 ], [ "▁悲報", -12.826589584350586 ], [ "▁生き残った", -12.826776504516602 ], [ "▁エコノミー", -12.826973915100098 ], [ "リーダー", -12.827018737792969 ], [ "▁ビーコン", -12.827049255371094 ], [ "▁型番", -12.82720947265625 ], [ "upp", -12.827217102050781 ], [ "▁タイマー", -12.827234268188477 ], [ "▁手形", -12.827272415161133 ], [ "▁エネ", -12.827338218688965 ], [ "▁スキップ", -12.827554702758789 ], [ "ental", -12.827570915222168 ], [ "▁カヌー", -12.8275728225708 ], [ "▁Park", -12.827595710754395 ], [ "▁身内", -12.827699661254883 ], [ "▁脱ぎ", -12.827779769897461 ], [ "儒", -12.827851295471191 ], [ "▁長方形", -12.827853202819824 ], [ "▁スワン", -12.827863693237305 ], [ "▁懸賞", -12.827885627746582 ], [ "▁隠岐", -12.827888488769531 ], [ "▁溶岩", -12.827900886535645 ], [ "▁集客", -12.827930450439453 ], [ "▁Report", -12.827993392944336 ], [ "▁義父", -12.828043937683105 ], [ "1890", -12.828105926513672 ], [ "▁不快な", -12.828184127807617 ], [ "▁慣例", -12.828291893005371 ], [ "▁慣れる", -12.828505516052246 ], [ "発見", -12.828593254089355 ], [ "▁勤労", -12.828756332397461 ], [ "▁051", -12.82895278930664 ], [ "▁バリュー", -12.828990936279297 ], [ "▁利子", -12.82901382446289 ], [ "何より", -12.8290376663208 ], [ "▁床下", -12.829081535339355 ], [ "▁微細", -12.829092979431152 ], [ "▁タカラ", -12.82910442352295 ], [ "▁竹本", -12.829313278198242 ], [ "▁天理", -12.829529762268066 ], [ "▁代償", -12.829543113708496 ], [ "▁兼ね備えた", -12.829573631286621 ], [ "叙", -12.829604148864746 ], [ "信頼", -12.830044746398926 ], [ "オープニング", -12.830047607421875 ], [ "▁通わ", -12.830098152160645 ], [ "▁諦める", -12.830367088317871 ], [ "弊", -12.830450057983398 ], [ "▁順調", -12.83050537109375 ], [ "▁有給", -12.830509185791016 ], [ "▁切り替えて", -12.83071231842041 ], [ "在庫", -12.83080768585205 ], [ "▁和紙", -12.830887794494629 ], [ "▁ティッシュ", -12.83090591430664 ], [ "嵌", -12.830931663513184 ], [ "睡眠", -12.830949783325195 ], [ "▁免れた", -12.830977439880371 ], [ "▁フィッシャー", -12.831002235412598 ], [ "▁LEAGUE", -12.831151962280273 ], [ "グモ", -12.831258773803711 ], [ "▁高浜", -12.831321716308594 ], [ "▁一晩", -12.831559181213379 ], [ "▁鎮痛", -12.831643104553223 ], [ "注釈", -12.831652641296387 ], [ "有難い", -12.831826210021973 ], [ "▁片隅", -12.831878662109375 ], [ "▁昼寝", -12.831889152526855 ], [ "▁達也", -12.832005500793457 ], [ "▁舞踏", -12.832073211669922 ], [ "▁始祖", -12.832296371459961 ], [ "▁彦根", -12.832554817199707 ], [ "▁浮遊", -12.832768440246582 ], [ "ل", -12.832917213439941 ], [ "▁クンニ", -12.832929611206055 ], [ "▁桔梗", -12.833137512207031 ], [ "繁殖", -12.833168983459473 ], [ "▁増額", -12.833349227905273 ], [ "▁一眼レフ", -12.833358764648438 ], [ "▁ピンと", -12.833426475524902 ], [ "瀬戸", -12.833588600158691 ], [ "▁・・)", -12.833629608154297 ], [ "▁Software", -12.833800315856934 ], [ "▁いろは", -12.833806991577148 ], [ "▁公的な", -12.833964347839355 ], [ "▁With", -12.833976745605469 ], [ "▁フラメッテ", -12.83402156829834 ], [ "▁被写体", -12.83424186706543 ], [ "▁実演", -12.834293365478516 ], [ "▁誤認", -12.83430290222168 ], [ "天保", -12.834315299987793 ], [ "▁交友", -12.834330558776855 ], [ "omb", -12.834339141845703 ], [ "▁帯びた", -12.834421157836914 ], [ "んこう", -12.834451675415039 ], [ "決して", -12.834479331970215 ], [ "之内", -12.834599494934082 ], [ "ちゃんと", -12.834731101989746 ], [ "▁重んじ", -12.83474349975586 ], [ "侠", -12.834905624389648 ], [ "▁障壁", -12.834906578063965 ], [ "ずく", -12.834999084472656 ], [ "▁気持", -12.835041046142578 ], [ "▁いっぱいの", -12.835171699523926 ], [ "▁What", -12.83522891998291 ], [ "▁CAU", -12.835312843322754 ], [ "▁オリオン", -12.83536434173584 ], [ "▁回廊", -12.835375785827637 ], [ "ノ内", -12.83553409576416 ], [ "▁義母", -12.835638999938965 ], [ "そそ", -12.835670471191406 ], [ "▁入省", -12.835712432861328 ], [ "▁コンペティション", -12.835790634155273 ], [ "▁アドニス", -12.835855484008789 ], [ "▁あさひ", -12.835890769958496 ], [ "😊", -12.836012840270996 ], [ "▁植木", -12.836200714111328 ], [ "▁見破る", -12.836236000061035 ], [ "朋", -12.836286544799805 ], [ "フランク", -12.836434364318848 ], [ "▁聴衆", -12.836480140686035 ], [ "▁夏目", -12.836481094360352 ], [ "▁ただいま", -12.836522102355957 ], [ "サポート", -12.836658477783203 ], [ "▁いすゞ", -12.836677551269531 ], [ "▁明かり", -12.836763381958008 ], [ "▁デビッド", -12.836820602416992 ], [ "▁欠乏", -12.836908340454102 ], [ "▁伝わった", -12.837027549743652 ], [ "▁東大阪", -12.837047576904297 ], [ "▁裁定", -12.837057113647461 ], [ "▁再戦", -12.837119102478027 ], [ "▁親父", -12.837215423583984 ], [ "▁宮古島", -12.837289810180664 ], [ "強者", -12.83730697631836 ], [ "▁ファイナンシャル", -12.837342262268066 ], [ "楯", -12.837342262268066 ], [ "砥", -12.837342262268066 ], [ "▁快挙", -12.837387084960938 ], [ "浮", -12.837533950805664 ], [ "▁ロースター", -12.837535858154297 ], [ "▁ニンニク", -12.837563514709473 ], [ "acy", -12.837567329406738 ], [ "▁State", -12.83775520324707 ], [ "斧", -12.837785720825195 ], [ "▁都督", -12.838143348693848 ], [ "▁涼しい", -12.838163375854492 ], [ "渡辺", -12.838271141052246 ], [ "←", -12.838295936584473 ], [ "▁兄妹", -12.838311195373535 ], [ "▁ヴェーチェ", -12.838422775268555 ], [ "▁うなぎ", -12.83849048614502 ], [ "巷", -12.83867359161377 ], [ "▁草案", -12.838723182678223 ], [ "▁トラップ", -12.838876724243164 ], [ "▁おおい", -12.838929176330566 ], [ "▁上告", -12.838963508605957 ], [ "▁エグゼクティブ", -12.839118003845215 ], [ "▁ETC", -12.839154243469238 ], [ "▁苗字", -12.839208602905273 ], [ "▁収まる", -12.8394775390625 ], [ "▁ネタバレ", -12.83956241607666 ], [ "▁文春", -12.839601516723633 ], [ "シリア", -12.839609146118164 ], [ "▁かかわり", -12.839795112609863 ], [ "捻", -12.840004920959473 ], [ "▁有害な", -12.840005874633789 ], [ "▁崩れて", -12.840024948120117 ], [ "入社", -12.840097427368164 ], [ "▁ウィッグ", -12.840130805969238 ], [ "杏", -12.840132713317871 ], [ "IRA", -12.840144157409668 ], [ "▁フィリ", -12.840187072753906 ], [ "▁CAN", -12.840222358703613 ], [ "▁カリブ海", -12.840229034423828 ], [ "▁ガッツ", -12.840254783630371 ], [ "ーヴル", -12.840314865112305 ], [ "祭り", -12.84031867980957 ], [ "▁尋問", -12.84045124053955 ], [ "▁得です", -12.840523719787598 ], [ "▁延喜", -12.840537071228027 ], [ "リッド", -12.840566635131836 ], [ "▁キレイな", -12.840853691101074 ], [ "近い", -12.840899467468262 ], [ "volution", -12.841118812561035 ], [ "喫", -12.841146469116211 ], [ "▁こめて", -12.841193199157715 ], [ "材料", -12.841232299804688 ], [ "▁整った", -12.841338157653809 ], [ "騰", -12.841462135314941 ], [ "1904", -12.841489791870117 ], [ "▁肩書き", -12.841729164123535 ], [ "▁Over", -12.841760635375977 ], [ "▁フライパン", -12.84197998046875 ], [ "▁ジャガイモ", -12.842009544372559 ], [ "▁生没", -12.842018127441406 ], [ "▁スタック", -12.842039108276367 ], [ "late", -12.842074394226074 ], [ "記念", -12.8421049118042 ], [ "▁平方キロメートル", -12.842232704162598 ], [ "▁足らず", -12.842233657836914 ], [ "毎", -12.84223747253418 ], [ "ブック", -12.84238052368164 ], [ "▁ぴったりな", -12.842497825622559 ], [ "▁滅び", -12.842631340026855 ], [ "▁ひも", -12.842679023742676 ], [ "▁一本化", -12.842682838439941 ], [ "拓", -12.84271240234375 ], [ "▁スイカ", -12.842732429504395 ], [ "▁帰投", -12.842750549316406 ], [ "▁後遺症", -12.842901229858398 ], [ "▁毀損", -12.842901229858398 ], [ "前日", -12.842902183532715 ], [ "▁隠蔽", -12.84290885925293 ], [ "黎", -12.843123435974121 ], [ "▁赴く", -12.843125343322754 ], [ "▁ユーナ", -12.84313678741455 ], [ "オーストリア", -12.843229293823242 ], [ "▁とどまって", -12.843355178833008 ], [ "▁マッド", -12.843449592590332 ], [ "▁漁船", -12.843506813049316 ], [ "▁良ければ", -12.843534469604492 ], [ "▁Digital", -12.843570709228516 ], [ "▁盛り上がる", -12.843570709228516 ], [ "囁", -12.843570709228516 ], [ "▁マグカップ", -12.843595504760742 ], [ "▁シラバス", -12.84361743927002 ], [ "▁ユニクロ", -12.843732833862305 ], [ "全部", -12.844137191772461 ], [ "▁探究", -12.844255447387695 ], [ "▁賞品", -12.844316482543945 ], [ "▁客船", -12.844359397888184 ], [ "down", -12.844364166259766 ], [ "▁涼しく", -12.844374656677246 ], [ "▁飛来", -12.844404220581055 ], [ "▁強固な", -12.844463348388672 ], [ "▁畠山", -12.844467163085938 ], [ "war", -12.844478607177734 ], [ "廻", -12.844620704650879 ], [ "▁Collection", -12.844686508178711 ], [ "▁エタノール", -12.844686508178711 ], [ "亨", -12.844686508178711 ], [ "▁BOOKS", -12.844955444335938 ], [ "廃止", -12.845069885253906 ], [ "▁肉食", -12.845132827758789 ], [ "▁INTERFACE", -12.845133781433105 ], [ "▁モンキー", -12.845263481140137 ], [ "▁FBI", -12.845288276672363 ], [ "▁VOL", -12.845290184020996 ], [ "▁泌尿器", -12.845356941223145 ], [ "▁紡績", -12.845368385314941 ], [ "地図", -12.845379829406738 ], [ "インストール", -12.845402717590332 ], [ "機体", -12.845402717590332 ], [ "▁自負", -12.845537185668945 ], [ "▁FAQ", -12.845540046691895 ], [ "ローグ", -12.845664024353027 ], [ "▁津島", -12.845666885375977 ], [ "クリーン", -12.84569263458252 ], [ "邪", -12.845719337463379 ], [ "ウォン", -12.845803260803223 ], [ "▁Little", -12.845804214477539 ], [ "▁ケベック", -12.845914840698242 ], [ "▁東横", -12.845945358276367 ], [ "▁根源", -12.845976829528809 ], [ "▁スラヴ", -12.845993041992188 ], [ "▁役柄", -12.846020698547363 ], [ "▁ちなむ", -12.846029281616211 ], [ "▁焼いた", -12.846142768859863 ], [ "▁大雪", -12.846159934997559 ], [ "▁執着", -12.846172332763672 ], [ "訂", -12.846230506896973 ], [ "▁VPN", -12.846253395080566 ], [ "anna", -12.846346855163574 ], [ "▁君臨", -12.846358299255371 ], [ "トルコ", -12.846610069274902 ], [ "▁圧勝", -12.846619606018066 ], [ "▁千鳥", -12.846993446350098 ], [ "bal", -12.8471097946167 ], [ "▁こわ", -12.847186088562012 ], [ "機関", -12.84721565246582 ], [ "▁SMAP", -12.847262382507324 ], [ "▁藤枝", -12.847360610961914 ], [ "倍", -12.847386360168457 ], [ "▁ジェイソン", -12.847578048706055 ], [ "▁リコチェット", -12.84759521484375 ], [ "▁見当たら", -12.84759521484375 ], [ "▁チェスター", -12.847780227661133 ], [ "▁トレーリング", -12.847861289978027 ], [ "▁クラウス", -12.847870826721191 ], [ "▁返り", -12.847906112670898 ], [ "▁解か", -12.847926139831543 ], [ "▁錯覚", -12.848043441772461 ], [ "千代", -12.84805965423584 ], [ "答え", -12.848098754882812 ], [ "HAN", -12.848121643066406 ], [ "▁セーター", -12.848265647888184 ], [ "▁お披露目", -12.848267555236816 ], [ "▁ソマリア", -12.848340034484863 ], [ "坪", -12.848416328430176 ], [ "▁芥川", -12.848492622375488 ], [ "Soft", -12.848519325256348 ], [ "▁終わ", -12.848590850830078 ], [ "バイオ", -12.848610877990723 ], [ "▁三郷", -12.848647117614746 ], [ "▁トウモロコシ", -12.848715782165527 ], [ "ULL", -12.848881721496582 ], [ "▁親和", -12.848906517028809 ], [ "▁細心の", -12.848939895629883 ], [ "▁率いた", -12.848943710327148 ], [ "▁複線", -12.849279403686523 ], [ "▁明智", -12.849353790283203 ], [ "HIRO", -12.849425315856934 ], [ "▁うるさい", -12.84950065612793 ], [ "▁Line", -12.849597930908203 ], [ "▁ヨルダン", -12.849613189697266 ], [ "▁不服", -12.84962272644043 ], [ "ody", -12.849663734436035 ], [ "▁マイホーム", -12.849693298339844 ], [ "▁知育", -12.84975814819336 ], [ "▁ユニバース", -12.84985637664795 ], [ "▁あかり", -12.849982261657715 ], [ "▁STYLE", -12.850062370300293 ], [ "▁吟味", -12.850062370300293 ], [ "電動車", -12.850074768066406 ], [ "▁演芸", -12.850119590759277 ], [ "▁HIV", -12.850143432617188 ], [ "▁ちく", -12.850200653076172 ], [ "医学", -12.850247383117676 ], [ "▁喘息", -12.850287437438965 ], [ "▁野戦", -12.850379943847656 ], [ "卷", -12.85051155090332 ], [ "オム", -12.850536346435547 ], [ "▁賑わっ", -12.850549697875977 ], [ "▁ソレ", -12.850586891174316 ], [ "REP", -12.85058879852295 ], [ "▁GPU", -12.850759506225586 ], [ "▁真っ赤", -12.850796699523926 ], [ "▁隠れ家", -12.850923538208008 ], [ "濠", -12.850961685180664 ], [ "▁クラウドファンディング", -12.85118579864502 ], [ "▁光秀", -12.851247787475586 ], [ "▁争った", -12.85128116607666 ], [ "▁萩原", -12.851358413696289 ], [ "仰", -12.851522445678711 ], [ "▁肥大", -12.851533889770508 ], [ "▁簿記", -12.851536750793457 ], [ "▁光源", -12.851602554321289 ], [ "▁画題", -12.851726531982422 ], [ "▁西条", -12.851744651794434 ], [ "▁ウォーム", -12.851791381835938 ], [ "▁ドラクエ", -12.851861000061035 ], [ "▁およぶ", -12.851863861083984 ], [ "▁ラッパー", -12.851941108703613 ], [ "プログラム", -12.851971626281738 ], [ "憶", -12.851995468139648 ], [ "烏", -12.852028846740723 ], [ "ニョン", -12.85203742980957 ], [ "▁淡い", -12.85206127166748 ], [ "▁Enterprise", -12.852086067199707 ], [ "▁Sub", -12.852289199829102 ], [ "▁秒間", -12.852302551269531 ], [ "▁迷わ", -12.852316856384277 ], [ "▁スモール", -12.852350234985352 ], [ "▁税法", -12.852483749389648 ], [ "粗", -12.852533340454102 ], [ "▁イングリッシュ", -12.85253620147705 ], [ "▁ネーミング", -12.852537155151367 ], [ "▁処遇", -12.852559089660645 ], [ "艦名", -12.85274887084961 ], [ "▁ひっ", -12.852790832519531 ], [ "▁ニッケル", -12.852791786193848 ], [ "法科", -12.85289192199707 ], [ "▁呼び掛け", -12.852934837341309 ], [ "▁ウィンブルドン", -12.852986335754395 ], [ "▁バイデン", -12.852996826171875 ], [ "arr", -12.853036880493164 ], [ "テープ", -12.853148460388184 ], [ "ヨガ", -12.853279113769531 ], [ "▁ふしぎ", -12.853437423706055 ], [ "▁架橋", -12.853439331054688 ], [ "ã", -12.853628158569336 ], [ "▁民生", -12.853636741638184 ], [ "▁貧血", -12.853663444519043 ], [ "▁思いっきり", -12.853809356689453 ], [ "▁絶品", -12.853874206542969 ], [ "不思議", -12.854044914245605 ], [ "▁名跡", -12.854045867919922 ], [ "din", -12.854236602783203 ], [ "▁仕切り", -12.854389190673828 ], [ "▁行程", -12.854435920715332 ], [ "どんなに", -12.854476928710938 ], [ "▁Girls", -12.854575157165527 ], [ "▁トリガー", -12.854701042175293 ], [ "▁チューナー", -12.854782104492188 ], [ "▁抗生物質", -12.855015754699707 ], [ "▁タロット", -12.855036735534668 ], [ "URA", -12.855097770690918 ], [ "▁川村", -12.855164527893066 ], [ "呼応", -12.855196952819824 ], [ "▁賃料", -12.855241775512695 ], [ "▁ストックホルム", -12.855249404907227 ], [ "出産", -12.855284690856934 ], [ "▁あふれて", -12.855313301086426 ], [ "▁ウニ", -12.855340957641602 ], [ "▁鉄砲", -12.855356216430664 ], [ "▁歳暮", -12.855374336242676 ], [ "▁アトランティック", -12.855467796325684 ], [ "▁分かち", -12.85547161102295 ], [ "ais", -12.855737686157227 ], [ "▁慰め", -12.855745315551758 ], [ "▁うめ", -12.855819702148438 ], [ "▁隠れた", -12.85605525970459 ], [ "▁龍馬", -12.856064796447754 ], [ "▁アグリ", -12.856204986572266 ], [ "▁グリコ", -12.856212615966797 ], [ "▁ナレーター", -12.856330871582031 ], [ "▁当てはま", -12.856350898742676 ], [ "▁京橋", -12.856391906738281 ], [ "GY", -12.856424331665039 ], [ "▁常用", -12.856514930725098 ], [ "▁園児", -12.85651683807373 ], [ "保存", -12.856520652770996 ], [ "トランス", -12.856542587280273 ], [ "▁エンブレム", -12.856596946716309 ], [ "▁藤岡", -12.856648445129395 ], [ "▁モニタ", -12.856668472290039 ], [ "iya", -12.85672664642334 ], [ "▁金髪", -12.856890678405762 ], [ "レーティス", -12.856905937194824 ], [ "▁心斎橋", -12.85727596282959 ], [ "▁有意義な", -12.85727596282959 ], [ "▁ふか", -12.857415199279785 ], [ "▁手がかり", -12.857431411743164 ], [ "裸", -12.8574800491333 ], [ "▁亀裂", -12.85754680633545 ], [ "▁骨髄", -12.857560157775879 ], [ "逢", -12.857726097106934 ], [ "▁ギャラクシー", -12.857728004455566 ], [ "疇", -12.857728004455566 ], [ "苔", -12.857823371887207 ], [ "▁立派", -12.857827186584473 ], [ "▁ひらがな", -12.857954025268555 ], [ "lar", -12.858022689819336 ], [ "▁Arm", -12.858070373535156 ], [ "クエスト", -12.85816764831543 ], [ "▁貯まって", -12.858221054077148 ], [ "▁くず", -12.858266830444336 ], [ "▁仕上げた", -12.85837173461914 ], [ "廠", -12.858388900756836 ], [ "▁PayPay", -12.858407020568848 ], [ "扉", -12.85841178894043 ], [ "▁たのし", -12.858448028564453 ], [ "給与", -12.858478546142578 ], [ "girl", -12.858646392822266 ], [ "▁根幹", -12.858765602111816 ], [ "▁カルタゴ", -12.85886001586914 ], [ "▁丸ごと", -12.858875274658203 ], [ "▁いっぱいです", -12.858895301818848 ], [ "▁法要", -12.858968734741211 ], [ "▁カワイイ", -12.859086990356445 ], [ "▁引き抜", -12.859101295471191 ], [ "エクス", -12.859244346618652 ], [ "▁DOS", -12.859301567077637 ], [ "▁享受", -12.85931396484375 ], [ "▁ユニーク", -12.85952091217041 ], [ "▁歩け", -12.859631538391113 ], [ "▁罪悪", -12.85975456237793 ], [ "▁改める", -12.859760284423828 ], [ "▁下層", -12.85976505279541 ], [ "▁マッピング", -12.860017776489258 ], [ "▁ガイドブック", -12.860027313232422 ], [ "▁熱田", -12.860086441040039 ], [ "▁kcal", -12.86009693145752 ], [ "ベート", -12.860157012939453 ], [ "▁主治医", -12.860220909118652 ], [ "▁懇願", -12.860220909118652 ], [ "▁競艇", -12.860458374023438 ], [ "▁ぶっかけ", -12.860469818115234 ], [ "▁ときどき", -12.86050796508789 ], [ "▁視認", -12.860553741455078 ], [ "▁MOVIE", -12.860674858093262 ], [ "▁ラグジュアリー", -12.860674858093262 ], [ "▁流した", -12.860803604125977 ], [ "▁近傍", -12.86091423034668 ], [ "▁帰ら", -12.861248970031738 ], [ "▁御座います", -12.861355781555176 ], [ "▁デジカメ", -12.861366271972656 ], [ "▁不利な", -12.861376762390137 ], [ "rem", -12.861466407775879 ], [ "GER", -12.8615083694458 ], [ "▁両替", -12.861557006835938 ], [ "▁Mbps", -12.86158275604248 ], [ "▁ショコラ", -12.861583709716797 ], [ "▁Che", -12.861624717712402 ], [ "▁仕込", -12.861708641052246 ], [ "▁増やした", -12.861781120300293 ], [ "有限", -12.861796379089355 ], [ "▁ジェームス", -12.861809730529785 ], [ "▁わたくし", -12.862037658691406 ], [ "▁ロフト", -12.862040519714355 ], [ "▁義経", -12.862041473388672 ], [ "▁漁獲", -12.862052917480469 ], [ "▁健太", -12.862120628356934 ], [ "▁XML", -12.862197875976562 ], [ "締め", -12.862399101257324 ], [ "▁必須です", -12.862417221069336 ], [ "▁全裸", -12.862527847290039 ], [ "▁サウロ", -12.86257553100586 ], [ "无码", -12.862947463989258 ], [ "橙", -12.862947463989258 ], [ "▁握った", -12.862969398498535 ], [ "▁埋まっ", -12.86301326751709 ], [ "▁Entertainment", -12.863174438476562 ], [ "rade", -12.863316535949707 ], [ "▁エージェンシー", -12.863402366638184 ], [ "▁妨げる", -12.863419532775879 ], [ "▁頑張った", -12.863428115844727 ], [ "▁ブレン", -12.863482475280762 ], [ "▁見送ら", -12.863526344299316 ], [ "カク", -12.863777160644531 ], [ "aaS", -12.863877296447754 ], [ "VAL", -12.864118576049805 ], [ "▁キヤノン", -12.864313125610352 ], [ "▁無差別", -12.864314079284668 ], [ "3,000", -12.864316940307617 ], [ "▁version", -12.864336013793945 ], [ "▁直訳", -12.864462852478027 ], [ "夕方", -12.864522933959961 ], [ "歓", -12.864584922790527 ], [ "論文", -12.864606857299805 ], [ "▁柏木", -12.864609718322754 ], [ "▁メタリック", -12.86467170715332 ], [ "▁憲政", -12.864699363708496 ], [ "ping", -12.864741325378418 ], [ "轢", -12.864768981933594 ], [ "▁親身", -12.864840507507324 ], [ "乙女", -12.86486530303955 ], [ "設置", -12.865174293518066 ], [ "メディ", -12.865206718444824 ], [ "▁ガーディアン", -12.86526107788086 ], [ "▁テクスチャ", -12.865306854248047 ], [ "▁ドロン", -12.865338325500488 ], [ "▁チャーター", -12.865448951721191 ], [ "▁受け取", -12.865457534790039 ], [ "▁赤松", -12.865487098693848 ], [ "▁左右する", -12.86549186706543 ], [ "▁缶詰", -12.865499496459961 ], [ "▁現物", -12.865541458129883 ], [ "▁広まり", -12.865581512451172 ], [ "▁リーズナブルな", -12.865652084350586 ], [ "▁オシャレな", -12.865655899047852 ], [ "▁ヘルニア", -12.865680694580078 ], [ "▁湧いて", -12.865818977355957 ], [ "▁スリッパ", -12.865866661071777 ], [ "EU", -12.86589527130127 ], [ "▁アッシリア", -12.865917205810547 ], [ "▁食道", -12.865935325622559 ], [ "▁アクト", -12.865957260131836 ], [ "▁パース", -12.866033554077148 ], [ "弐", -12.866137504577637 ], [ "リオス", -12.8662109375 ], [ "▁引き上げる", -12.866318702697754 ], [ "▁子女", -12.866378784179688 ], [ "Д", -12.866438865661621 ], [ "▁Def", -12.866490364074707 ], [ "▁モテる", -12.866517066955566 ], [ "▁レノン", -12.866605758666992 ], [ "▁軍曹", -12.866621971130371 ], [ "綺", -12.8668212890625 ], [ "▁ヒマラヤ", -12.866822242736816 ], [ "▁上回った", -12.86682415008545 ], [ "azz", -12.866850852966309 ], [ "いつか", -12.8668851852417 ], [ "鴨", -12.866887092590332 ], [ "▁守った", -12.866987228393555 ], [ "皮膚", -12.8671293258667 ], [ "▁由紀", -12.867207527160645 ], [ "プロペシア", -12.86735725402832 ], [ "成功", -12.867462158203125 ], [ "▁Photoshop", -12.867511749267578 ], [ "▁ホリデー", -12.867537498474121 ], [ "gent", -12.86754035949707 ], [ "580", -12.867635726928711 ], [ "▁初恋", -12.86767864227295 ], [ "▁云々", -12.867751121520996 ], [ "▁田口", -12.867779731750488 ], [ "▁皇女", -12.867912292480469 ], [ "▁懇親", -12.867964744567871 ], [ "ごたえ", -12.867995262145996 ], [ "▁制式", -12.868067741394043 ], [ "▁揺れる", -12.868102073669434 ], [ "▁幼年", -12.868258476257324 ], [ "▁インターハイ", -12.868400573730469 ], [ "▁James", -12.868429183959961 ], [ "▁Radio", -12.868485450744629 ], [ "▁爽快", -12.868650436401367 ], [ "詐", -12.868879318237305 ], [ "鯖", -12.868879318237305 ], [ "▁競泳", -12.868886947631836 ], [ "▁見出す", -12.868921279907227 ], [ "▁命題", -12.86895751953125 ], [ "emi", -12.868988990783691 ], [ "▁便座", -12.869145393371582 ], [ "付いた", -12.869145393371582 ], [ "▁蒸発", -12.869173049926758 ], [ "ident", -12.869182586669922 ], [ "▁念仏", -12.869376182556152 ], [ "クシャ", -12.86951732635498 ], [ "▁同好", -12.869532585144043 ], [ "▁思えた", -12.869576454162598 ], [ "▁インド洋", -12.869772911071777 ], [ "▁汽車", -12.869795799255371 ], [ "▁飛び出して", -12.869812965393066 ], [ "ブロック", -12.869917869567871 ], [ "▁Mag", -12.869956016540527 ], [ "繊", -12.870024681091309 ], [ "▁ギョウ", -12.870028495788574 ], [ "▁ムック", -12.870104789733887 ], [ "輿", -12.87010669708252 ], [ "tus", -12.870193481445312 ], [ "卿", -12.870245933532715 ], [ "▁通例", -12.870514869689941 ], [ "クティブ", -12.870514869689941 ], [ "▁ダニー", -12.870573043823242 ], [ "▁ギミック", -12.870579719543457 ], [ "▁取りやめ", -12.870621681213379 ], [ "ボイス", -12.870641708374023 ], [ "▁プレーン", -12.870667457580566 ], [ "▁豊臣秀吉", -12.870712280273438 ], [ "▁遺骨", -12.870722770690918 ], [ "三菱", -12.870962142944336 ], [ "じゃあ", -12.870975494384766 ], [ "achi", -12.871025085449219 ], [ "▁囲い", -12.871031761169434 ], [ "▁寒冷", -12.871047973632812 ], [ "▁飛ばし", -12.87106704711914 ], [ "▁四半期", -12.871170997619629 ], [ "▁白黒", -12.871222496032715 ], [ "▁Jack", -12.871304512023926 ], [ "引き続き", -12.87139892578125 ], [ "▁取り戻した", -12.871456146240234 ], [ "▁くさ", -12.871476173400879 ], [ "講師", -12.87160873413086 ], [ "race", -12.871614456176758 ], [ "▁ニューオーリンズ", -12.87162971496582 ], [ "▁フェラチオ", -12.871650695800781 ], [ "▁遊具", -12.871663093566895 ], [ "Do", -12.871673583984375 ], [ "背番号", -12.871746063232422 ], [ "▁講堂", -12.871771812438965 ], [ "▁由美", -12.871810913085938 ], [ "▁三輪", -12.871829986572266 ], [ "vert", -12.87186336517334 ], [ "▁触る", -12.871976852416992 ], [ "WBO", -12.872097969055176 ], [ "▁LTD", -12.872100830078125 ], [ "▁エミー", -12.872150421142578 ], [ "▁つかむ", -12.872153282165527 ], [ "BD", -12.872197151184082 ], [ "▁ガンマ", -12.872299194335938 ], [ "och", -12.872318267822266 ], [ "▁大破", -12.872504234313965 ], [ "▁工兵", -12.8727388381958 ], [ "▁乳幼児", -12.872793197631836 ], [ "▁はずである", -12.872807502746582 ], [ "6,000", -12.87282657623291 ], [ "▁立ち向かう", -12.87289047241211 ], [ "▁オレンジ色", -12.872931480407715 ], [ "▁Pop", -12.873003959655762 ], [ "話題", -12.873099327087402 ], [ "▁スコー", -12.873218536376953 ], [ "▁画策", -12.873239517211914 ], [ "池田", -12.87340259552002 ], [ "宵", -12.873467445373535 ], [ "▁挟んだ", -12.873469352722168 ], [ "▁Series", -12.873485565185547 ], [ "NR", -12.873571395874023 ], [ "▁じんじゃ", -12.873574256896973 ], [ "▁宣教", -12.873628616333008 ], [ "新たに", -12.87384033203125 ], [ "▁買い時", -12.87392520904541 ], [ "▁Advanced", -12.873927116394043 ], [ "▁侮辱", -12.873927116394043 ], [ "▁備蓄", -12.873927116394043 ], [ "▁面影", -12.87394905090332 ], [ "漢和", -12.873997688293457 ], [ "▁陰性", -12.874056816101074 ], [ "沖資", -12.874113082885742 ], [ "▁エスカレーター", -12.874387741088867 ], [ "ヴュ", -12.874509811401367 ], [ "▁形質", -12.874524116516113 ], [ "▁default", -12.874617576599121 ], [ "彌", -12.874617576599121 ], [ "▁適宜", -12.874629974365234 ], [ "▁Boy", -12.874768257141113 ], [ "▁温かく", -12.87476921081543 ], [ "汲", -12.874845504760742 ], [ "▁洞察", -12.874863624572754 ], [ "▁欠損", -12.874879837036133 ], [ "▁キャプチャ", -12.874902725219727 ], [ "▁ロビンソン", -12.874974250793457 ], [ "▁狂気", -12.875090599060059 ], [ "験", -12.875090599060059 ], [ "きゃ", -12.875444412231445 ], [ "▁SPECIAL", -12.87553882598877 ], [ "▁飢饉", -12.87553882598877 ], [ "紘", -12.87553882598877 ], [ "▁埋もれ", -12.875545501708984 ], [ "資格", -12.875568389892578 ], [ "▁被って", -12.875609397888184 ], [ "▁差し引", -12.875616073608398 ], [ "商業", -12.875713348388672 ], [ "you", -12.875760078430176 ], [ "薙", -12.87576961517334 ], [ "▁オスカー", -12.875782012939453 ], [ "▁道筋", -12.875930786132812 ], [ "▁張った", -12.875967025756836 ], [ "▁つかみ", -12.87612247467041 ], [ "▁あがった", -12.876229286193848 ], [ "▁Happy", -12.876230239868164 ], [ "▁備品", -12.876233100891113 ], [ "▁おしっこ", -12.876235008239746 ], [ "▁永続", -12.876314163208008 ], [ "▁固めた", -12.876348495483398 ], [ "▁個数", -12.8764009475708 ], [ "▁落ち着く", -12.876461029052734 ], [ "▁准将", -12.876485824584961 ], [ "ras", -12.876565933227539 ], [ "▁ファームウェア", -12.876727104187012 ], [ "▁フレンドリー", -12.876754760742188 ], [ "▁適当", -12.876840591430664 ], [ "160", -12.876914024353027 ], [ "▁外れる", -12.876927375793457 ], [ "出仕", -12.877135276794434 ], [ "▁頓挫", -12.877152442932129 ], [ "▁ミート", -12.877230644226074 ], [ "rep", -12.877394676208496 ], [ "▁メッツ", -12.877397537231445 ], [ "▁競い", -12.877419471740723 ], [ "▁JCT", -12.877592086791992 ], [ "▁汲み", -12.877615928649902 ], [ "クロリス", -12.877705574035645 ], [ "▁脅し", -12.877872467041016 ], [ "▁居留", -12.877877235412598 ], [ "▁Show", -12.878079414367676 ], [ "▁モーリス", -12.878108024597168 ], [ "▁見失", -12.878289222717285 ], [ "▁IBF", -12.878305435180664 ], [ "牙", -12.878472328186035 ], [ "そろそろ", -12.878482818603516 ], [ "▁聖なる", -12.878557205200195 ], [ "渋", -12.87856674194336 ], [ "▁低速", -12.878649711608887 ], [ "mil", -12.87869930267334 ], [ "▁監獄", -12.87877082824707 ], [ "▁1848", -12.878804206848145 ], [ "CHE", -12.878815650939941 ], [ "▁耐熱", -12.878908157348633 ], [ "▁働け", -12.878915786743164 ], [ "▁曖昧な", -12.878971099853516 ], [ "二手房", -12.87900161743164 ], [ "療", -12.879072189331055 ], [ "▁only", -12.879159927368164 ], [ "高級", -12.879168510437012 ], [ "▁Manager", -12.879231452941895 ], [ "▁債券", -12.879231452941895 ], [ "俗に", -12.879283905029297 ], [ "▁アカデミア", -12.879463195800781 ], [ "允", -12.879463195800781 ], [ "▁退いた", -12.879520416259766 ], [ "▁目印", -12.879530906677246 ], [ "▁なかろう", -12.879533767700195 ], [ "耕", -12.879603385925293 ], [ "▁坂口", -12.879654884338379 ], [ "▁滑らかな", -12.879709243774414 ], [ "tric", -12.879753112792969 ], [ "▁姉ちゃん", -12.879782676696777 ], [ "変更", -12.879918098449707 ], [ "▁House", -12.880022048950195 ], [ "▁Summer", -12.880157470703125 ], [ "▁コースター", -12.880202293395996 ], [ "▁サニー", -12.880260467529297 ], [ "▁あみ", -12.880277633666992 ], [ "room", -12.88028335571289 ], [ "▁春日部", -12.880326271057129 ], [ "▁門人", -12.880497932434082 ], [ "▁潰れ", -12.880516052246094 ], [ "雫", -12.880620002746582 ], [ "▁すこし", -12.880660057067871 ], [ "▁点滴", -12.880690574645996 ], [ "▁マギカ", -12.880852699279785 ], [ "▁思ひ", -12.881065368652344 ], [ "▁過敏", -12.881150245666504 ], [ "OOK", -12.881158828735352 ], [ "▁武藤", -12.881193161010742 ], [ "禎", -12.881315231323242 ], [ "▁塁打", -12.881376266479492 ], [ "┗", -12.881546974182129 ], [ "▁ミシュラン", -12.881546974182129 ], [ "▁税関", -12.881711959838867 ], [ "▁見つめる", -12.8817720413208 ], [ "▁叫ぶ", -12.881779670715332 ], [ "▁立証", -12.881817817687988 ], [ "▁ゴルファー", -12.881834983825684 ], [ "LIN", -12.882183074951172 ], [ "梵", -12.882242202758789 ], [ "视频", -12.882242202758789 ], [ "▁キプロス", -12.882244110107422 ], [ "検査", -12.8822603225708 ], [ "▁like", -12.882506370544434 ], [ "▁無言", -12.882522583007812 ], [ "▁元首", -12.882728576660156 ], [ "▁律令", -12.882753372192383 ], [ "▁バッド", -12.882843017578125 ], [ "▁いっしょ", -12.882869720458984 ], [ "▁満たした", -12.883191108703613 ], [ "喧", -12.883402824401855 ], [ "▁掴んで", -12.883403778076172 ], [ "▁巨額", -12.883467674255371 ], [ "▁恒久", -12.883758544921875 ], [ "pat", -12.883777618408203 ], [ "▁ヘッドライト", -12.88379955291748 ], [ "OLO", -12.884072303771973 ], [ "asp", -12.884125709533691 ], [ "▁小売店", -12.884230613708496 ], [ "▁ドーナツ", -12.884331703186035 ], [ "▁ウエスタン", -12.884358406066895 ], [ "▁皮革", -12.884385108947754 ], [ "▁説いた", -12.884507179260254 ], [ "▁疲弊", -12.884564399719238 ], [ "▁スピリッツ", -12.884584426879883 ], [ "▁没落", -12.884674072265625 ], [ "NEW", -12.8847074508667 ], [ "沖", -12.88476848602295 ], [ "▁グラフィー", -12.884778022766113 ], [ "フジテレビ", -12.884786605834961 ], [ "▁information", -12.884797096252441 ], [ "▁種々の", -12.88479995727539 ], [ "▁政宗", -12.885014533996582 ], [ "民主", -12.885079383850098 ], [ "▁宝永", -12.885160446166992 ], [ "▁赤道", -12.885232925415039 ], [ "▁ハピ", -12.885250091552734 ], [ "▁取り立て", -12.885334968566895 ], [ "uka", -12.88538932800293 ], [ "▁コントラ", -12.88545036315918 ], [ "南部", -12.885455131530762 ], [ "▁仲良し", -12.88549518585205 ], [ "▁叩いて", -12.88549518585205 ], [ "▁LLC", -12.885499954223633 ], [ "▁学べ", -12.885510444641113 ], [ "▁決闘", -12.885536193847656 ], [ "▁ハードコア", -12.885546684265137 ], [ "▁吉備", -12.886075019836426 ], [ "▁ウルトラマン", -12.886208534240723 ], [ "▁キャブ", -12.886421203613281 ], [ "▁如何に", -12.886663436889648 ], [ "▁葛西", -12.886807441711426 ], [ "ř", -12.886892318725586 ], [ "主催", -12.886926651000977 ], [ "▁とうきょう", -12.886941909790039 ], [ "▁マルウェア", -12.887067794799805 ], [ "▁配電", -12.887160301208496 ], [ "▁おかしな", -12.887537002563477 ], [ "滴", -12.887771606445312 ], [ "▁ユーリ", -12.887797355651855 ], [ "▁大牟田", -12.887825012207031 ], [ "導入", -12.888026237487793 ], [ "▁感受性", -12.888057708740234 ], [ "▁盛り上げて", -12.8881196975708 ], [ "▁NWA", -12.888175964355469 ], [ "悼", -12.888272285461426 ], [ "aint", -12.888293266296387 ], [ "ORA", -12.888638496398926 ], [ "▁極楽", -12.888679504394531 ], [ "夫婦", -12.88873291015625 ], [ "▁ジャッキー", -12.889018058776855 ], [ "▁試料", -12.889039039611816 ], [ "▁神事", -12.889039993286133 ], [ "▁ヨハネス", -12.889156341552734 ], [ "▁近道", -12.889228820800781 ], [ "kyo", -12.889291763305664 ], [ "▁MAC", -12.889305114746094 ], [ "▁朝刊", -12.88940715789795 ], [ "▁Company", -12.889458656311035 ], [ "alig", -12.889530181884766 ], [ "▁仲裁", -12.889575004577637 ], [ "▁急流", -12.889643669128418 ], [ "▁ウラジーミ", -12.88969612121582 ], [ "▁HMV", -12.889699935913086 ], [ "▁本殿", -12.889873504638672 ], [ "file", -12.889910697937012 ], [ "▁ガンダルフ", -12.889925956726074 ], [ "阪急", -12.890019416809082 ], [ "▁怯え", -12.890108108520508 ], [ "ジョウ", -12.890114784240723 ], [ "▁謡曲", -12.890159606933594 ], [ "会議", -12.89018440246582 ], [ "▁吉原", -12.890235900878906 ], [ "▁ウェー", -12.890268325805664 ], [ "▁推力", -12.890337944030762 ], [ "▁なじみ", -12.890400886535645 ], [ "割り", -12.890521049499512 ], [ "▁モカ", -12.890603065490723 ], [ "▁縮め", -12.890705108642578 ], [ "▁ジョーク", -12.891128540039062 ], [ "▁イブン", -12.891156196594238 ], [ "▁リヴァプール", -12.891328811645508 ], [ "▁サリー", -12.891419410705566 ], [ "▁モンスターズ", -12.891457557678223 ], [ "▁アウディ", -12.891472816467285 ], [ "▁試した", -12.89150333404541 ], [ "▁ホノルル", -12.891563415527344 ], [ "▁見守り", -12.891565322875977 ], [ "▁jpg", -12.891566276550293 ], [ "▁尊厳", -12.891603469848633 ], [ "▁吐き出", -12.89166259765625 ], [ "次いで", -12.891764640808105 ], [ "▁休館", -12.891789436340332 ], [ "ī", -12.891797065734863 ], [ "▁荒らし", -12.891853332519531 ], [ "採用", -12.89189338684082 ], [ "乱闘", -12.891924858093262 ], [ "head", -12.891946792602539 ], [ "▁石狩", -12.89197063446045 ], [ "▁マッカーサー", -12.8920316696167 ], [ "isa", -12.892158508300781 ], [ "スミス", -12.892306327819824 ], [ "美しい", -12.892324447631836 ], [ "あくまで", -12.892467498779297 ], [ "▁ガイア", -12.892488479614258 ], [ "▁宗像", -12.892502784729004 ], [ "▁祈って", -12.892502784729004 ], [ "▁ヒロシ", -12.892587661743164 ], [ "▁手放し", -12.89267349243164 ], [ "▁複雑で", -12.892685890197754 ], [ "▁輪郭", -12.892791748046875 ], [ "ities", -12.892792701721191 ], [ "▁乱暴", -12.892806053161621 ], [ "▁テレフォン", -12.89284610748291 ], [ "▁福原", -12.892849922180176 ], [ "▁媚薬", -12.892969131469727 ], [ "▁政友", -12.893057823181152 ], [ "▁ジョギング", -12.893223762512207 ], [ "▁滞納", -12.8932466506958 ], [ "▁宮田", -12.89328670501709 ], [ "▁崩して", -12.893314361572266 ], [ "▁イーグル", -12.893315315246582 ], [ "透", -12.893402099609375 ], [ "▁生協", -12.89343547821045 ], [ "▁タトゥー", -12.893446922302246 ], [ "▁has", -12.893575668334961 ], [ "チャク", -12.893630981445312 ], [ "▁パルマ", -12.893718719482422 ], [ "▁歩む", -12.893749237060547 ], [ "▁ローマ字", -12.893750190734863 ], [ "利益", -12.893797874450684 ], [ "▁破裂", -12.893939971923828 ], [ "▁ポルト", -12.894014358520508 ], [ "GEN", -12.89406681060791 ], [ "▁シム", -12.894316673278809 ], [ "▁全勝", -12.894387245178223 ], [ "同様の", -12.89444637298584 ], [ "▁すべ", -12.894529342651367 ], [ "▁連なる", -12.8945951461792 ], [ "▁立ち入り", -12.894599914550781 ], [ "▁biz", -12.894632339477539 ], [ "▁久慈", -12.894658088684082 ], [ "ネズミ", -12.894693374633789 ], [ "▁ジャイアント", -12.894845962524414 ], [ "▁奥深", -12.894948959350586 ], [ "▁パンチラ", -12.89498519897461 ], [ "▁適時", -12.895034790039062 ], [ "ソウル", -12.895074844360352 ], [ "▁滅多に", -12.895081520080566 ], [ "▁診て", -12.895108222961426 ], [ "ホルム", -12.895149230957031 ], [ "▁離さ", -12.895280838012695 ], [ "たわら", -12.895284652709961 ], [ "悪い", -12.895389556884766 ], [ "▁霊場", -12.895391464233398 ], [ "▁充分な", -12.895419120788574 ], [ "▁神輿", -12.895466804504395 ], [ "▁浅く", -12.895482063293457 ], [ "▁ボルチモア", -12.895550727844238 ], [ "▁蛋白", -12.895550727844238 ], [ "▁優子", -12.895602226257324 ], [ "RES", -12.895697593688965 ], [ "▁トラックバック", -12.89573860168457 ], [ "▁燃える", -12.895785331726074 ], [ "▁ぐるなび", -12.89578628540039 ], [ "▁ジョジョ", -12.895829200744629 ], [ "大統領", -12.895866394042969 ], [ "〇〇", -12.896087646484375 ], [ "▁定ま", -12.896105766296387 ], [ "▁防火", -12.89621353149414 ], [ "気なく", -12.896321296691895 ], [ "▁Hu", -12.896332740783691 ], [ "▁プロミス", -12.89645004272461 ], [ "へん", -12.896450996398926 ], [ "▁阿南", -12.896500587463379 ], [ "▁オオカミ", -12.896501541137695 ], [ "▁筒井", -12.896501541137695 ], [ "▁ケンカ", -12.89663028717041 ], [ "▁コネチカット", -12.896726608276367 ], [ "ロイヤル", -12.896818161010742 ], [ "▁座長", -12.896923065185547 ], [ "▁いい加減", -12.89696216583252 ], [ "宍", -12.89696216583252 ], [ "▁唱えた", -12.897021293640137 ], [ "▁無双", -12.8970365524292 ], [ "(^^;", -12.897211074829102 ], [ "グレイ", -12.89749526977539 ], [ "▁空挺", -12.897510528564453 ], [ "▁ソリューションズ", -12.897518157958984 ], [ "▁堕ち", -12.897669792175293 ], [ "▁捕鯨", -12.897671699523926 ], [ "▁マネジャー", -12.897726058959961 ], [ "▁伺って", -12.897909164428711 ], [ "例年", -12.898168563842773 ], [ "飲食", -12.898207664489746 ], [ "asi", -12.898353576660156 ], [ "▁震源", -12.898375511169434 ], [ "緋", -12.898375511169434 ], [ "▁右下", -12.898637771606445 ], [ "▁介した", -12.898674964904785 ], [ "ロバート", -12.898717880249023 ], [ "空気", -12.898825645446777 ], [ "unch", -12.898892402648926 ], [ "▁馬主", -12.898955345153809 ], [ "Li", -12.898993492126465 ], [ "▁ココロ", -12.899202346801758 ], [ "▁バファローズ", -12.89931869506836 ], [ "▁PCR", -12.89934253692627 ], [ "鳩", -12.899432182312012 ], [ "棲", -12.899433135986328 ], [ "▁貧乳", -12.899556159973145 ], [ "▁王政", -12.899559020996094 ], [ "▁吠え", -12.899615287780762 ], [ "sha", -12.899687767028809 ], [ "▁watch", -12.899723052978516 ], [ "▁セクハラ", -12.89979076385498 ], [ "OKU", -12.89983081817627 ], [ "▁待ち受け", -12.899868965148926 ], [ "ウナギ", -12.89993953704834 ], [ "▁存命", -12.900338172912598 ], [ "蜀", -12.90049934387207 ], [ "▁京セラ", -12.900580406188965 ], [ "▁著述", -12.900588989257812 ], [ "▁付帯", -12.900721549987793 ], [ "▁仏壇", -12.900923728942871 ], [ "▁入線", -12.901008605957031 ], [ "▁集配", -12.90116024017334 ], [ "▁兆候", -12.901208877563477 ], [ "金沢", -12.901263236999512 ], [ "▁たちまち", -12.901301383972168 ], [ "早い", -12.90145206451416 ], [ "▁結びついて", -12.901518821716309 ], [ "▁転出", -12.90157413482666 ], [ "▁採決", -12.901588439941406 ], [ "▁乗合", -12.901603698730469 ], [ "1902", -12.901673316955566 ], [ "▁四球", -12.901854515075684 ], [ "辿", -12.901908874511719 ], [ "ヘルツェゴビナ", -12.901917457580566 ], [ "▁済んだ", -12.90194320678711 ], [ "▁損益", -12.901994705200195 ], [ "▁イースタン", -12.902036666870117 ], [ "匂", -12.902151107788086 ], [ "▁真剣", -12.902312278747559 ], [ "▁ディタ", -12.902379035949707 ], [ "à", -12.902390480041504 ], [ "▁Vita", -12.902412414550781 ], [ "▁断って", -12.90247631072998 ], [ "▁動かさ", -12.902560234069824 ], [ "移籍", -12.902560234069824 ], [ "sport", -12.902640342712402 ], [ "遂", -12.902776718139648 ], [ "▁打ち破", -12.902849197387695 ], [ "▁触ら", -12.902934074401855 ], [ "▁パノラマ", -12.903100967407227 ], [ "▁力強く", -12.90310287475586 ], [ "▁見送り", -12.90310287475586 ], [ "ゲット", -12.90314769744873 ], [ "▁フランコ", -12.903522491455078 ], [ "▁相乗", -12.903597831726074 ], [ "▁ブレイン", -12.903804779052734 ], [ "▁幼なじみ", -12.90381145477295 ], [ "▁賑やか", -12.903853416442871 ], [ "後述", -12.90391731262207 ], [ "▁焦り", -12.903950691223145 ], [ "▁絡め", -12.904003143310547 ], [ "▁共作", -12.90402889251709 ], [ "連合", -12.904033660888672 ], [ "値段", -12.904051780700684 ], [ "▁修得", -12.904208183288574 ], [ "leg", -12.904417037963867 ], [ "▁字体", -12.904434204101562 ], [ "佛", -12.904522895812988 ], [ "▁シミュレータ", -12.904528617858887 ], [ "虚", -12.90466022491455 ], [ "™", -12.904760360717773 ], [ "▁元号", -12.904850959777832 ], [ "▁準ずる", -12.904952049255371 ], [ "▁ポイ", -12.90495491027832 ], [ "works", -12.904985427856445 ], [ "▁カーニバル", -12.904997825622559 ], [ "▁邦題", -12.905069351196289 ], [ "FR", -12.905163764953613 ], [ "▁スカパー", -12.90518569946289 ], [ "▁宮川", -12.90554428100586 ], [ "姑", -12.905709266662598 ], [ "▁ヤンキー", -12.90576457977295 ], [ "社長", -12.905769348144531 ], [ "▁陶磁器", -12.905946731567383 ], [ "imi", -12.906010627746582 ], [ "▁アーモンド", -12.906063079833984 ], [ "▁引っ張って", -12.906145095825195 ], [ "濡", -12.906203269958496 ], [ "▁たどり", -12.906238555908203 ], [ "追加", -12.906414985656738 ], [ "▁七五三", -12.906421661376953 ], [ "▁習志野", -12.906421661376953 ], [ "▁シスター", -12.906454086303711 ], [ "▁天空", -12.906522750854492 ], [ "▁盛り上げ", -12.906534194946289 ], [ "▁果樹", -12.906539916992188 ], [ "▁百姓", -12.9065523147583 ], [ "北京", -12.90665054321289 ], [ "做", -12.906660079956055 ], [ "▁絡んで", -12.906661987304688 ], [ "▁暗闇", -12.906673431396484 ], [ "▁形容", -12.906749725341797 ], [ "▁混み", -12.906839370727539 ], [ "▁上乗せ", -12.90689754486084 ], [ "▁抱っこ", -12.90689754486084 ], [ "▁冴え", -12.906928062438965 ], [ "▁ポーカー", -12.907114028930664 ], [ "1903", -12.907227516174316 ], [ "ating", -12.907317161560059 ], [ "▁キツい", -12.907374382019043 ], [ "▁安永", -12.907402038574219 ], [ "余談", -12.90743350982666 ], [ "主要な", -12.907499313354492 ], [ "ニャー", -12.907560348510742 ], [ "▁標榜", -12.907611846923828 ], [ "唯一", -12.907655715942383 ], [ "▁水彩", -12.907692909240723 ], [ "グランド", -12.907936096191406 ], [ "▁Journal", -12.908086776733398 ], [ "パートナー", -12.908146858215332 ], [ "性格", -12.908517837524414 ], [ "劇団", -12.90860652923584 ], [ "近所", -12.908705711364746 ], [ "▁金魚", -12.908949851989746 ], [ "▁RGB", -12.909075736999512 ], [ "▁凝ら", -12.90914249420166 ], [ "▁身元", -12.909263610839844 ], [ "▁親権", -12.909375190734863 ], [ "▁指紋", -12.909388542175293 ], [ "▁精油", -12.909414291381836 ], [ "▁名護", -12.909453392028809 ], [ "▁ゴリラ", -12.909517288208008 ], [ "kei", -12.9096097946167 ], [ "▁鳴る", -12.909660339355469 ], [ "デスク", -12.909685134887695 ], [ "▁王冠", -12.909700393676758 ], [ "▁ふたたび", -12.909753799438477 ], [ "ネック", -12.909822463989258 ], [ "▁丸亀", -12.909910202026367 ], [ "出張", -12.909913063049316 ], [ "按", -12.909992218017578 ], [ "▁PTA", -12.909995079040527 ], [ "要は", -12.910324096679688 ], [ "軍事", -12.910374641418457 ], [ "▁答申", -12.910470008850098 ], [ "そうそう", -12.91051959991455 ], [ "債務", -12.910552024841309 ], [ "WF", -12.910587310791016 ], [ "坑", -12.910676956176758 ], [ "▁ウインド", -12.910687446594238 ], [ "噺", -12.9107084274292 ], [ "遜", -12.9107084274292 ], [ "▁一塁", -12.910780906677246 ], [ "▁きっぷ", -12.910989761352539 ], [ "前身", -12.911027908325195 ], [ "▁無くなる", -12.911084175109863 ], [ "▁アイオワ", -12.911186218261719 ], [ "▁酢酸", -12.911465644836426 ], [ "▁閉ざ", -12.911555290222168 ], [ "▁休戦", -12.911768913269043 ], [ "▁聴け", -12.911832809448242 ], [ "キッチン", -12.911988258361816 ], [ "グローバル", -12.912113189697266 ], [ "遼", -12.912117958068848 ], [ "▁乗り越える", -12.912128448486328 ], [ "ates", -12.912139892578125 ], [ "▁怒鳴", -12.912140846252441 ], [ "▁残虐", -12.912165641784668 ], [ "▁QB", -12.91229248046875 ], [ "▁幕僚", -12.912457466125488 ], [ "▁2563", -12.912572860717773 ], [ "arc", -12.912692070007324 ], [ "▁能代", -12.912702560424805 ], [ "▁秋元", -12.912845611572266 ], [ "▁緻密", -12.912858009338379 ], [ "▁湖畔", -12.912910461425781 ], [ "▁八十", -12.912940979003906 ], [ "添え", -12.913137435913086 ], [ "ワット", -12.913228988647461 ], [ "スクール", -12.91327953338623 ], [ "▁リプレイ", -12.913302421569824 ], [ "搾", -12.913331985473633 ], [ "縣", -12.913336753845215 ], [ "▁ボルドー", -12.91336727142334 ], [ "gh", -12.913437843322754 ], [ "▁決め手", -12.913506507873535 ], [ "ピンク", -12.913776397705078 ], [ "▁留めて", -12.913939476013184 ], [ "▁STUDIO", -12.914054870605469 ], [ "▁悪し", -12.914097785949707 ], [ "▁インスタンス", -12.914114952087402 ], [ "▁GET", -12.914121627807617 ], [ "▁掛川", -12.91413402557373 ], [ "▁チャック", -12.914188385009766 ], [ "エアコン", -12.914203643798828 ], [ "▁費やす", -12.91422176361084 ], [ "▁食べたり", -12.9142484664917 ], [ "拾", -12.914255142211914 ], [ "▁低音", -12.914281845092773 ], [ "▁ボリビア", -12.914295196533203 ], [ "▁挙がっ", -12.914348602294922 ], [ "▁デハ", -12.914401054382324 ], [ "VEL", -12.91445255279541 ], [ "▁矢印", -12.914461135864258 ], [ "▁正室", -12.914754867553711 ], [ "ブリッジ", -12.914770126342773 ], [ "アイルランド", -12.91477108001709 ], [ "▁八千代", -12.914847373962402 ], [ "▁学童", -12.914877891540527 ], [ "▁六角", -12.915060043334961 ], [ "▁50,000", -12.91537857055664 ], [ "▁不透明", -12.915411949157715 ], [ "▁辞めた", -12.915428161621094 ], [ "▁雑記", -12.915604591369629 ], [ "▁可否", -12.915608406066895 ], [ "▁譜面", -12.915635108947754 ], [ "▁懲戒", -12.915732383728027 ], [ "▁SPORTS", -12.91573429107666 ], [ "▁ケント", -12.915770530700684 ], [ "▁Great", -12.915804862976074 ], [ "▁電解", -12.915812492370605 ], [ "▁華族", -12.91591739654541 ], [ "▁焙煎", -12.915971755981445 ], [ "▁ルックス", -12.916533470153809 ], [ "ハール", -12.916604042053223 ], [ "▁清朝", -12.916647911071777 ], [ "ねこ", -12.91688346862793 ], [ "▁きのこ", -12.916949272155762 ], [ "とっても", -12.916953086853027 ], [ "▁柏崎", -12.916982650756836 ], [ "▁Pack", -12.917106628417969 ], [ "▁民報", -12.91711139678955 ], [ "パーソナリティ", -12.917177200317383 ], [ "▁電線", -12.917281150817871 ], [ "▁宇和島", -12.917412757873535 ], [ "▁右京", -12.917705535888672 ], [ "彼氏", -12.917732238769531 ], [ "▁炊飯", -12.917893409729004 ], [ "eur", -12.917976379394531 ], [ "▁確かめて", -12.918013572692871 ], [ "▁パレス", -12.918062210083008 ], [ "▁片道", -12.918137550354004 ], [ "▁オムニバス", -12.918148040771484 ], [ "アカウント", -12.918401718139648 ], [ "▁常滑", -12.91844654083252 ], [ "▁発芽", -12.918564796447754 ], [ "▁車掌", -12.918570518493652 ], [ "760", -12.91857624053955 ], [ "▁病状", -12.918652534484863 ], [ "▁音節", -12.918720245361328 ], [ "▁あぁ", -12.918797492980957 ], [ "▁数百万", -12.91882610321045 ], [ "レーザー", -12.918927192687988 ], [ "▁割譲", -12.918950080871582 ], [ "▁チューン", -12.918997764587402 ], [ "▁官吏", -12.919022560119629 ], [ "▁同棲", -12.919093132019043 ], [ "比較的", -12.91915225982666 ], [ "▁微小", -12.919193267822266 ], [ "▁三部作", -12.919337272644043 ], [ "▁逗子", -12.919337272644043 ], [ "▁無意識に", -12.919437408447266 ], [ "▁モデリング", -12.919464111328125 ], [ "▁大理石", -12.919577598571777 ], [ "恭", -12.919591903686523 ], [ "イスラエル", -12.919614791870117 ], [ "委", -12.919617652893066 ], [ "▁偶然に", -12.919625282287598 ], [ "▁ゲッ", -12.91964340209961 ], [ "▁吉良", -12.919707298278809 ], [ "▁ガバナンス", -12.919817924499512 ], [ "▁アトラス", -12.919886589050293 ], [ "Rotten", -12.920062065124512 ], [ "▁有償", -12.920161247253418 ], [ "人類", -12.920211791992188 ], [ "▁風速", -12.920289039611816 ], [ "▁汚職", -12.920401573181152 ], [ "ザメ", -12.92040729522705 ], [ "施術", -12.920612335205078 ], [ "借り", -12.920652389526367 ], [ "▁フェルナンド", -12.920781135559082 ], [ "▁サイレン", -12.92080307006836 ], [ "▁静電気", -12.920830726623535 ], [ "▁サメ", -12.92087173461914 ], [ "芸術", -12.920944213867188 ], [ "▁最高です", -12.9209623336792 ], [ "▁コペンハーゲン", -12.921022415161133 ], [ "▁ハラスメント", -12.921022415161133 ], [ "蜂", -12.92104434967041 ], [ "▁官能", -12.921059608459473 ], [ "▁抱きしめ", -12.92129898071289 ], [ "▁三塁", -12.92149829864502 ], [ "蝋", -12.921504974365234 ], [ "▁宮島", -12.921573638916016 ], [ "扱わ", -12.921656608581543 ], [ "▁狭義", -12.921720504760742 ], [ "▁住ま", -12.921723365783691 ], [ "▁ぼんやり", -12.921746253967285 ], [ "▁至近", -12.92184066772461 ], [ "▁ルーク", -12.921884536743164 ], [ "include", -12.921993255615234 ], [ "克", -12.92203140258789 ], [ "KEY", -12.922111511230469 ], [ "▁正則", -12.922141075134277 ], [ "セルフ", -12.922200202941895 ], [ "酢", -12.922289848327637 ], [ "▁がんばり", -12.922311782836914 ], [ "▁三昧", -12.922319412231445 ], [ "ben", -12.922369003295898 ], [ "▁引き取り", -12.922415733337402 ], [ "永禄", -12.92242431640625 ], [ "▁縫製", -12.922470092773438 ], [ "▁警護", -12.922471046447754 ], [ "▁アウグスト", -12.922712326049805 ], [ "掻", -12.922951698303223 ], [ "NER", -12.923171043395996 ], [ "SDP", -12.923367500305176 ], [ "¦", -12.923436164855957 ], [ "▁マイナビ", -12.923543930053711 ], [ "▁乳液", -12.923798561096191 ], [ "実験", -12.923819541931152 ], [ "▁macOS", -12.923919677734375 ], [ "▁パジャマ", -12.923920631408691 ], [ "▁試用", -12.923925399780273 ], [ "▁チカラ", -12.923966407775879 ], [ "▁ベイビー", -12.924152374267578 ], [ "▁白金", -12.92420768737793 ], [ "▁転入", -12.924362182617188 ], [ "▁アイスホッケー", -12.92440414428711 ], [ "▁盛んな", -12.924421310424805 ], [ "▁ハーツ", -12.924541473388672 ], [ "▁メッセンジャー", -12.92464542388916 ], [ "▁結束", -12.92473030090332 ], [ "▁堀川", -12.924731254577637 ], [ "▁刃物", -12.92502498626709 ], [ "▁大學", -12.92512321472168 ], [ "▁租税", -12.925129890441895 ], [ "stand", -12.925222396850586 ], [ "▁竹中", -12.925280570983887 ], [ "ステッド", -12.925374031066895 ], [ "▁イマイチ", -12.925385475158691 ], [ "▁焼却", -12.925406455993652 ], [ "▁まとまり", -12.925537109375 ], [ "元禄", -12.925578117370605 ], [ "▁弊害", -12.925614356994629 ], [ "▁城郭", -12.925625801086426 ], [ "▁隣国", -12.925854682922363 ], [ "杜", -12.925947189331055 ], [ "▁トピックス", -12.925948143005371 ], [ "≦", -12.926098823547363 ], [ "▁呆れ", -12.926108360290527 ], [ "▁失速", -12.926477432250977 ], [ "▁ワープ", -12.926513671875 ], [ "▁木工", -12.926549911499023 ], [ "▁代議員", -12.926583290100098 ], [ "▁解いて", -12.926684379577637 ], [ "陸上", -12.926764488220215 ], [ "▁ステラ", -12.926791191101074 ], [ "▁這い", -12.926830291748047 ], [ "▁累積", -12.927068710327148 ], [ "▁無敵", -12.927190780639648 ], [ "uel", -12.927200317382812 ], [ "山頂", -12.927248001098633 ], [ "▁プログラマ", -12.927297592163086 ], [ "キリスト教", -12.927412986755371 ], [ "▁試食", -12.927568435668945 ], [ "▁LTE", -12.927638053894043 ], [ "嗅", -12.927796363830566 ], [ "1898", -12.92781925201416 ], [ "ラーゼ", -12.927919387817383 ], [ "▁宮沢", -12.92795467376709 ], [ "よろしければ", -12.928040504455566 ], [ "▁無知", -12.928086280822754 ], [ "▁Arc", -12.928146362304688 ], [ "メッセージ", -12.928146362304688 ], [ "▁くらべ", -12.92814826965332 ], [ "▁カルドナ", -12.928285598754883 ], [ "▁バニラ", -12.928291320800781 ], [ "▁Mini", -12.928349494934082 ], [ "゚", -12.928388595581055 ], [ "ako", -12.928434371948242 ], [ "▁混沌", -12.92852783203125 ], [ "▁キャンベル", -12.928669929504395 ], [ "▁相次ぎ", -12.928768157958984 ], [ "▁修飾", -12.9288330078125 ], [ "▁なめらか", -12.92885684967041 ], [ "ザキ", -12.92888355255127 ], [ "▁フィリップス", -12.928905487060547 ], [ "▁模範", -12.929011344909668 ], [ "▁名高い", -12.929059028625488 ], [ "▁ポッター", -12.929158210754395 ], [ "▁美咲", -12.929179191589355 ], [ "認定", -12.929348945617676 ], [ "▁スペクトラム", -12.929692268371582 ], [ "▁ハイエンド", -12.929716110229492 ], [ "▁マルチメディア", -12.929821968078613 ], [ "▁プーチン", -12.92982292175293 ], [ "唇", -12.929862976074219 ], [ "マシン", -12.92998218536377 ], [ "▁眺望", -12.929984092712402 ], [ "▁春樹", -12.930126190185547 ], [ "▁青島", -12.930144309997559 ], [ "▁ボンバー", -12.930158615112305 ], [ "▁半角", -12.930306434631348 ], [ "▁マッカートニー", -12.93047046661377 ], [ "▁大晦日", -12.93047046661377 ], [ "▁クーペ", -12.930620193481445 ], [ "▁切開", -12.930621147155762 ], [ "回答", -12.93066120147705 ], [ "斜", -12.930838584899902 ], [ "覚え", -12.930902481079102 ], [ "▁石材", -12.930930137634277 ], [ "▁スティール", -12.930963516235352 ], [ "▁快く", -12.931032180786133 ], [ "▁意気", -12.931124687194824 ], [ "▁シャーマン", -12.931154251098633 ], [ "oci", -12.931219100952148 ], [ "▁埋蔵", -12.931262969970703 ], [ "▁恐ろし", -12.931313514709473 ], [ "ブルグ", -12.931448936462402 ], [ "▁断食", -12.93145751953125 ], [ "▁SONY", -12.93146800994873 ], [ "▁支柱", -12.931498527526855 ], [ "kura", -12.931519508361816 ], [ "▁延暦", -12.931520462036133 ], [ "▁アバター", -12.931572914123535 ], [ "▁広める", -12.931662559509277 ], [ "▁カルア", -12.931679725646973 ], [ "▁冷たく", -12.931756973266602 ], [ "▁フランケン", -12.931798934936523 ], [ "プラザ", -12.931957244873047 ], [ "エンヌ", -12.931962013244629 ], [ "弾頭", -12.932045936584473 ], [ "▁説話", -12.932046890258789 ], [ "派遣", -12.932114601135254 ], [ "▁実名", -12.93211555480957 ], [ "▁サタデー", -12.932175636291504 ], [ "▁賢者", -12.932183265686035 ], [ "navi", -12.932245254516602 ], [ "▁産んだ", -12.932268142700195 ], [ "憲法", -12.932374000549316 ], [ "▁推察", -12.932443618774414 ], [ "▁序列", -12.932472229003906 ], [ "▁蜘蛛", -12.932662963867188 ], [ "▁花柄", -12.932692527770996 ], [ "該", -12.932723999023438 ], [ "賭", -12.933018684387207 ], [ "▁片づけ", -12.933101654052734 ], [ "▁エベレスト", -12.933151245117188 ], [ "討ち", -12.933238983154297 ], [ "▁フラグメント", -12.933429718017578 ], [ "▁コントラスト", -12.933759689331055 ], [ "▁里見", -12.933792114257812 ], [ "▁結構です", -12.933802604675293 ], [ "▁ジェネレーション", -12.933883666992188 ], [ "▁空室", -12.933992385864258 ], [ "兵員", -12.934083938598633 ], [ "▁Zoom", -12.934377670288086 ], [ "▁岩波", -12.934507369995117 ], [ "▁七尾", -12.934733390808105 ], [ "東洋", -12.9347505569458 ], [ "▁ライプツィヒ", -12.934861183166504 ], [ "理想", -12.934880256652832 ], [ "▁ロースト", -12.935014724731445 ], [ "▁アロール", -12.935086250305176 ], [ "▁野良", -12.935792922973633 ], [ "▁android", -12.935839653015137 ], [ "▁隼人", -12.93584156036377 ], [ "先月", -12.935868263244629 ], [ "シンプル", -12.93594741821289 ], [ "▁脇役", -12.936034202575684 ], [ "▁なさって", -12.936141014099121 ], [ "rick", -12.936169624328613 ], [ "▁怪談", -12.93659782409668 ], [ "▁タンカー", -12.936622619628906 ], [ "▁コラーダ", -12.936820030212402 ], [ "▁路地", -12.936833381652832 ], [ "▁愛宕", -12.936842918395996 ], [ "udo", -12.936931610107422 ], [ "▁和美", -12.937030792236328 ], [ "簡単な", -12.937116622924805 ], [ "▁田んぼ", -12.937152862548828 ], [ "ウクライナ", -12.93724536895752 ], [ "▁ギムレット", -12.937309265136719 ], [ "苺", -12.937309265136719 ], [ "ヶ島", -12.937317848205566 ], [ "▁粘着", -12.937402725219727 ], [ "▁白紙", -12.937405586242676 ], [ "▁レンジャーズ", -12.937493324279785 ], [ "▁ラトビア", -12.937554359436035 ], [ "報道", -12.937613487243652 ], [ "▁便利だ", -12.937615394592285 ], [ "国鉄", -12.937623977661133 ], [ "メリット", -12.937676429748535 ], [ "▁奉公", -12.937719345092773 ], [ "▁盛り込んだ", -12.937799453735352 ], [ "列車", -12.937833786010742 ], [ "▁GRE", -12.937848091125488 ], [ "▁菜園", -12.937952995300293 ], [ "▁アルフレッド", -12.93805980682373 ], [ "▁こまめに", -12.938289642333984 ], [ "▁寄港", -12.938356399536133 ], [ "▁段差", -12.938379287719727 ], [ "▁周防", -12.938464164733887 ], [ "ATSU", -12.938608169555664 ], [ "▁NMB", -12.938679695129395 ], [ "ようやく", -12.938705444335938 ], [ "▁Miss", -12.93874740600586 ], [ "ç", -12.938761711120605 ], [ "蛍", -12.938779830932617 ], [ "▁ダイアログ", -12.938789367675781 ], [ "エチレン", -12.938881874084473 ], [ "▁楽しもう", -12.938908576965332 ], [ "▁Style", -12.938921928405762 ], [ "▁ダンプ", -12.938946723937988 ], [ "▁アウェー", -12.93902587890625 ], [ "▁合図", -12.93908977508545 ], [ "▁あすか", -12.939102172851562 ], [ "▁木目", -12.939239501953125 ], [ "▁コメンテーター", -12.939270973205566 ], [ "▁粉砕", -12.939300537109375 ], [ "▁帝王", -12.939480781555176 ], [ "¨", -12.9395170211792 ], [ "▁齋藤", -12.9395170211792 ], [ "Script", -12.939518928527832 ], [ "▁傾倒", -12.939533233642578 ], [ "世間", -12.939544677734375 ], [ "▁壊して", -12.939592361450195 ], [ "多数", -12.939602851867676 ], [ "インスタ", -12.939711570739746 ], [ "olar", -12.939746856689453 ], [ "▁審理", -12.939760208129883 ], [ "▁満期", -12.939787864685059 ], [ "▁MacBook", -12.939827919006348 ], [ "▁右腕", -12.939842224121094 ], [ "▁クリエイト", -12.940008163452148 ], [ "▁利回り", -12.940032005310059 ], [ "BLE", -12.940169334411621 ], [ "▁DARK", -12.940230369567871 ], [ "ADA", -12.940289497375488 ], [ "▁映って", -12.94030475616455 ], [ "▁将兵", -12.940400123596191 ], [ "▁あべ", -12.940425872802734 ], [ "縛", -12.940449714660645 ], [ "▁体現", -12.940651893615723 ], [ "批評", -12.940715789794922 ], [ "570", -12.940802574157715 ], [ "▁バリュ", -12.940875053405762 ], [ "▁仕草", -12.940961837768555 ], [ "▁広々", -12.940984725952148 ], [ "▁両論", -12.941137313842773 ], [ "stra", -12.941161155700684 ], [ "▁乱用", -12.941177368164062 ], [ "σ", -12.941238403320312 ], [ "▁味噌汁", -12.941258430480957 ], [ "ml", -12.941550254821777 ], [ "▁寝返", -12.94167423248291 ], [ "▁ギガ", -12.941732406616211 ], [ "▁羽目", -12.942007064819336 ], [ "不倫", -12.942032814025879 ], [ "勝手な", -12.942160606384277 ], [ "瘤", -12.942222595214844 ], [ "なるほど", -12.942278861999512 ], [ "全員", -12.942359924316406 ], [ "▁冷やし", -12.942464828491211 ], [ "溺", -12.942605018615723 ], [ "美味しい", -12.942641258239746 ], [ "▁血縁", -12.942706108093262 ], [ "▁グラデーション", -12.94271469116211 ], [ "▁Dance", -12.942730903625488 ], [ "▁絶妙な", -12.942780494689941 ], [ "▁浅間", -12.942977905273438 ], [ "▁See", -12.94300365447998 ], [ "▁食い込", -12.943038940429688 ], [ "▁趣向", -12.943242073059082 ], [ "▁少額", -12.943259239196777 ], [ "TURE", -12.943324089050293 ], [ "▁まんま", -12.943402290344238 ], [ "▁銃弾", -12.943411827087402 ], [ "罵", -12.94345474243164 ], [ "▁呑み", -12.94347095489502 ], [ "ザンヌ", -12.943471908569336 ], [ "▁サムスン", -12.943479537963867 ], [ "▁財界", -12.943613052368164 ], [ "▁ドラゴンズ", -12.94366455078125 ], [ "たしかに", -12.943696975708008 ], [ "投票", -12.943703651428223 ], [ "ization", -12.943790435791016 ], [ "登山", -12.943831443786621 ], [ "▁取って代わ", -12.943893432617188 ], [ "▁参与", -12.944001197814941 ], [ "aster", -12.944072723388672 ], [ "ela", -12.94432258605957 ], [ "▁砲台", -12.944404602050781 ], [ "▁ウィンダム", -12.944493293762207 ], [ "それなのに", -12.944828987121582 ], [ "▁買物", -12.944901466369629 ], [ "▁あそび", -12.944934844970703 ], [ "▁ブルゴーニュ", -12.944934844970703 ], [ "▁オセアニア", -12.945181846618652 ], [ "ラツィオーネ", -12.945189476013184 ], [ "顧客", -12.945197105407715 ], [ "≧", -12.945428848266602 ], [ "▁クロスオーバー", -12.945486068725586 ], [ "逝", -12.94564151763916 ], [ "▁煉瓦", -12.94567584991455 ], [ "なんでも", -12.945706367492676 ], [ "▁KBS", -12.945775032043457 ], [ "▁街頭", -12.945852279663086 ], [ "▁気仙沼", -12.9459228515625 ], [ "芹", -12.9459228515625 ], [ "▁偶数", -12.945923805236816 ], [ "▁Michael", -12.946170806884766 ], [ "▁リヨン", -12.946182250976562 ], [ "海岸", -12.946306228637695 ], [ "▁釜石", -12.946338653564453 ], [ "▁増した", -12.946495056152344 ], [ "▁COMIC", -12.946560859680176 ], [ "hin", -12.946581840515137 ], [ "甫", -12.946664810180664 ], [ "▁売った", -12.946749687194824 ], [ "▁moon", -12.946769714355469 ], [ "▁Cons", -12.946869850158691 ], [ "▁茅ヶ崎", -12.946918487548828 ], [ "▁引き立て", -12.94714641571045 ], [ "▁定型", -12.947239875793457 ], [ "▁Engine", -12.947408676147461 ], [ "▁プレイステーション", -12.947427749633789 ], [ "ワシントン", -12.947428703308105 ], [ "▁顔写真", -12.947524070739746 ], [ "▁軽視", -12.947554588317871 ], [ "▁稚内", -12.94765567779541 ], [ "▁経典", -12.947714805603027 ], [ "ッツィ", -12.947770118713379 ], [ "▁生姜", -12.947855949401855 ], [ "四国", -12.947920799255371 ], [ "▁ルック", -12.947927474975586 ], [ "ヘキサ", -12.948041915893555 ], [ "▁百科", -12.948051452636719 ], [ "▁License", -12.948150634765625 ], [ "▁闘病", -12.948214530944824 ], [ "▁返せ", -12.948342323303223 ], [ "itz", -12.948410987854004 ], [ "胴", -12.948429107666016 ], [ "▁極秘", -12.948484420776367 ], [ "▁アヘル", -12.948511123657227 ], [ "▁洛陽", -12.94864559173584 ], [ "▁Luc", -12.948747634887695 ], [ "▁脳卒中", -12.948893547058105 ], [ "▁ベリニ", -12.948919296264648 ], [ "▁ほのか", -12.948949813842773 ], [ "▁アミューズメント", -12.949141502380371 ], [ "▁捏造", -12.949141502380371 ], [ "▁委嘱", -12.949143409729004 ], [ "▁Smart", -12.949219703674316 ], [ "▁比重", -12.949380874633789 ], [ "FOR", -12.949430465698242 ], [ "▁まるごと", -12.949434280395508 ], [ "aid", -12.949437141418457 ], [ "▁ハルゲル", -12.949506759643555 ], [ "▁弱者", -12.949518203735352 ], [ "▁Tomatoes", -12.949886322021484 ], [ "藪", -12.949886322021484 ], [ "▁ただちに", -12.949888229370117 ], [ "楽しみ", -12.949928283691406 ], [ "550", -12.950056076049805 ], [ "▁鉄骨", -12.95007610321045 ], [ "鋒", -12.95013427734375 ], [ "▁交替", -12.950167655944824 ], [ "いきなり", -12.950461387634277 ], [ "▁サプライ", -12.95051383972168 ], [ "▁General", -12.950634956359863 ], [ "QUE", -12.950654029846191 ], [ "▁常温", -12.950835227966309 ], [ "▁覇権", -12.950879096984863 ], [ "▁散々", -12.950896263122559 ], [ "▁薄型", -12.951050758361816 ], [ "方法", -12.951099395751953 ], [ "▁Just", -12.951107025146484 ], [ "麟", -12.951126098632812 ], [ "▁後見人", -12.951136589050293 ], [ "▁ボビー", -12.951155662536621 ], [ "旬", -12.951187133789062 ], [ "▁雷撃", -12.951214790344238 ], [ "lio", -12.951299667358398 ], [ "▁芽生え", -12.951387405395508 ], [ "▁抗がん", -12.951436996459961 ], [ "▁占めた", -12.95154857635498 ], [ "▁旭日", -12.95161247253418 ], [ "▁かなって", -12.951628684997559 ], [ "現存", -12.951761245727539 ], [ "▁プルー", -12.951837539672852 ], [ "▁日立製作所", -12.951873779296875 ], [ "▁深層", -12.951923370361328 ], [ "▁坊主", -12.952032089233398 ], [ "▁白血病", -12.95212173461914 ], [ "▁一掃", -12.95213508605957 ], [ "▁もらえれば", -12.952187538146973 ], [ "▁さわやか", -12.952213287353516 ], [ "▁ナオ", -12.952360153198242 ], [ "▁打ち出し", -12.95252799987793 ], [ "▁ばい", -12.952567100524902 ], [ "▁オンタリオ", -12.952619552612305 ], [ "▁華麗な", -12.952620506286621 ], [ "萩", -12.95268440246582 ], [ "もに", -12.952828407287598 ], [ "フスキ", -12.95284652709961 ], [ "公益", -12.952879905700684 ], [ "▁ヴェストファーレン", -12.953117370605469 ], [ "シテ", -12.95313835144043 ], [ "▁大納言", -12.95336627960205 ], [ "ディスク", -12.953506469726562 ], [ "▁ジョゼフ", -12.95362663269043 ], [ "▁彫り", -12.953648567199707 ], [ "▁横切", -12.953680992126465 ], [ "▁ゴマ", -12.953750610351562 ], [ "▁つなげて", -12.953875541687012 ], [ "▁由紀夫", -12.953934669494629 ], [ "▁Long", -12.953981399536133 ], [ "▁隆起", -12.954106330871582 ], [ "レンタル", -12.954116821289062 ], [ "▁尊氏", -12.954202651977539 ], [ "▁アルベルト", -12.95433235168457 ], [ "▁ベーコン", -12.954347610473633 ], [ "▁和也", -12.954350471496582 ], [ "▁満ちて", -12.954434394836426 ], [ "▁カタチ", -12.954562187194824 ], [ "▁文系", -12.954584121704102 ], [ "▁グスタフ", -12.954614639282227 ], [ "▁湧水", -12.95461654663086 ], [ "市販", -12.954642295837402 ], [ "▁搾取", -12.954861640930176 ], [ "▁潤滑", -12.954885482788086 ], [ "▁桑田", -12.954896926879883 ], [ "マイケル", -12.95510482788086 ], [ "▁プロパガンダ", -12.955111503601074 ], [ "▁撥水", -12.95511245727539 ], [ "▁感知", -12.955183029174805 ], [ "▁掻き", -12.955362319946289 ], [ "賃貸", -12.955451965332031 ], [ "▁POS", -12.95569133758545 ], [ "▁スキーム", -12.95571517944336 ], [ "正在播放", -12.955860137939453 ], [ "▁祭礼", -12.955896377563477 ], [ "楊", -12.955951690673828 ], [ "▁軽度", -12.956155776977539 ], [ "フォーク", -12.956184387207031 ], [ "▁まわし", -12.956215858459473 ], [ "▁振り分け", -12.956463813781738 ], [ "▁武蔵国", -12.956576347351074 ], [ "外観", -12.956589698791504 ], [ "ーニョ", -12.956665992736816 ], [ "応援", -12.956745147705078 ], [ "▁バンパー", -12.956850051879883 ], [ "▁明朝", -12.956851959228516 ], [ "▁集大成", -12.956859588623047 ], [ "▁PLAY", -12.956971168518066 ], [ "高等", -12.956974029541016 ], [ "▁めまい", -12.957099914550781 ], [ "▁悪夢", -12.957132339477539 ], [ "禅寺", -12.957351684570312 ], [ "▁戸惑い", -12.957359313964844 ], [ "▁漏えい", -12.957366943359375 ], [ "▁飛ばす", -12.957498550415039 ], [ "▁Land", -12.957902908325195 ], [ "▁使おう", -12.95794677734375 ], [ "Yahoo", -12.957966804504395 ], [ "▁休め", -12.957968711853027 ], [ "▁インフォ", -12.957971572875977 ], [ "ニッシュ", -12.95812702178955 ], [ "▁レオナルド", -12.958131790161133 ], [ "▁効いた", -12.958227157592773 ], [ "▁有識", -12.958270072937012 ], [ "▁ボーカリスト", -12.958359718322754 ], [ "▁遭って", -12.95836067199707 ], [ "BOY", -12.958415031433105 ], [ "▁JUN", -12.958420753479004 ], [ "▁RSS", -12.958454132080078 ], [ "oop", -12.958585739135742 ], [ "IRT", -12.958601951599121 ], [ "▁天ぷら", -12.958609580993652 ], [ "▁下さって", -12.958612442016602 ], [ "▁純度", -12.958643913269043 ], [ "▁自害", -12.958669662475586 ], [ "imp", -12.959264755249023 ], [ "▁林道", -12.95932388305664 ], [ "▁ゲーマー", -12.959407806396484 ], [ "DX", -12.959431648254395 ], [ "▁献身", -12.95950984954834 ], [ "▁わいせつ", -12.959611892700195 ], [ "▁真剣な", -12.959716796875 ], [ "銀座", -12.959741592407227 ], [ "ify", -12.960125923156738 ], [ "▁散見", -12.96021842956543 ], [ "吸", -12.960227012634277 ], [ "▁オヤジ", -12.960365295410156 ], [ "▁なんらか", -12.960616111755371 ], [ "▁鮮やか", -12.960665702819824 ], [ "▁温める", -12.96090316772461 ], [ "有効", -12.961071014404297 ], [ "▁魔界", -12.96135425567627 ], [ "近世", -12.961448669433594 ], [ "▁ラミナー", -12.961620330810547 ], [ "ハノーファー", -12.96162223815918 ], [ "▁欠落", -12.961716651916504 ], [ "▁学説", -12.961780548095703 ], [ "▁WEST", -12.961819648742676 ], [ "▁キュン", -12.961883544921875 ], [ "▁載せた", -12.961921691894531 ], [ "無線", -12.96213436126709 ], [ "▁秀樹", -12.962327003479004 ], [ "▁蒲生", -12.96237564086914 ], [ "カタログ", -12.9625244140625 ], [ "▁(*^^*)", -12.962623596191406 ], [ "▁神仏", -12.962674140930176 ], [ "迫り", -12.962746620178223 ], [ "ヴァール", -12.962803840637207 ], [ "▁流布", -12.962855339050293 ], [ "host", -12.963064193725586 ], [ "▁巻いて", -12.963082313537598 ], [ "▁過大", -12.963135719299316 ], [ "▁電装", -12.963274955749512 ], [ "グラード", -12.963294982910156 ], [ "有料", -12.963446617126465 ], [ "ウォル", -12.963491439819336 ], [ "▁実技", -12.96359920501709 ], [ "▁柏原", -12.963603019714355 ], [ "▁みなとみらい", -12.963629722595215 ], [ "▁呼べる", -12.963640213012695 ], [ "▁浴びせ", -12.963790893554688 ], [ "▁電位", -12.964058876037598 ], [ "▁呼びかけた", -12.964526176452637 ], [ "フルーツ", -12.96454906463623 ], [ "▁明確で", -12.964566230773926 ], [ "▁ジャンヌ", -12.964599609375 ], [ "OMO", -12.964615821838379 ], [ "▁デニス", -12.964675903320312 ], [ "▁ウェイン", -12.965009689331055 ], [ "▁しなやか", -12.965028762817383 ], [ "▁はじまる", -12.965209007263184 ], [ "▁尾翼", -12.96522331237793 ], [ "▁WOWOW", -12.965392112731934 ], [ "▁甲賀", -12.965404510498047 ], [ "▁ETF", -12.965494155883789 ], [ "読者", -12.965597152709961 ], [ "▁飲める", -12.965653419494629 ], [ "▁繰り上げ", -12.965707778930664 ], [ "▁のぞみ", -12.965743064880371 ], [ "▁サーモン", -12.965822219848633 ], [ "▁退位", -12.965836524963379 ], [ "▁嫡子", -12.965900421142578 ], [ "下ろし", -12.965983390808105 ], [ "高度", -12.966036796569824 ], [ "▁台帳", -12.966263771057129 ], [ "▁献立", -12.966323852539062 ], [ "▁チューリップ", -12.966414451599121 ], [ "▁吸って", -12.966550827026367 ], [ "▁ナイス", -12.966644287109375 ], [ "▁海苔", -12.96679973602295 ], [ "▁ベーカリー", -12.96690559387207 ], [ "▁Specialist", -12.966930389404297 ], [ "▁柳川", -12.966933250427246 ], [ "▁黒澤", -12.966965675354004 ], [ "▁自費", -12.96701717376709 ], [ "▁平氏", -12.96702766418457 ], [ "▁カンタン", -12.967083930969238 ], [ "▁ウィメンズ", -12.967214584350586 ], [ "▁クレストン", -12.967297554016113 ], [ "▁金貨", -12.967389106750488 ], [ "竈", -12.96741008758545 ], [ "body", -12.967595100402832 ], [ "捷", -12.967662811279297 ], [ "▁忘年", -12.967663764953613 ], [ "榎", -12.967913627624512 ], [ "▁磁石", -12.967918395996094 ], [ "▁ブロンズ", -12.96792221069336 ], [ "▁奇数", -12.967986106872559 ], [ "ワイド", -12.968199729919434 ], [ "▁モヤモヤ", -12.96842098236084 ], [ "▁起こせる", -12.96842098236084 ], [ "▁防げ", -12.968448638916016 ], [ "▁下さり", -12.968562126159668 ], [ "▁格別", -12.968684196472168 ], [ "窺", -12.968926429748535 ], [ "▁素顔", -12.968961715698242 ], [ "▁乳児", -12.969085693359375 ], [ "ر", -12.9691801071167 ], [ "▁振り込み", -12.969199180603027 ], [ "▁ジオン", -12.969362258911133 ], [ "▁鬼太郎", -12.969413757324219 ], [ "▁童謡", -12.969432830810547 ], [ "▁光栄", -12.969571113586426 ], [ "闇", -12.969622611999512 ], [ "邑", -12.969640731811523 ], [ "灌", -12.969686508178711 ], [ "▁巨匠", -12.969966888427734 ], [ "▁占星術", -12.970192909240723 ], [ "▁touch", -12.970312118530273 ], [ "▁入港", -12.970335960388184 ], [ "ミントン", -12.970417022705078 ], [ "▁GOLD", -12.970476150512695 ], [ "▁無ければ", -12.9705171585083 ], [ "分の一", -12.97053050994873 ], [ "▁繋ぎ", -12.97070026397705 ], [ "arri", -12.970837593078613 ], [ "▁農作", -12.970871925354004 ], [ "喉", -12.970914840698242 ], [ "▁波及", -12.971014022827148 ], [ "▁桜木", -12.971386909484863 ], [ "tim", -12.971439361572266 ], [ "▁1854", -12.971574783325195 ], [ "▁石室", -12.97159481048584 ], [ "Poste", -12.971732139587402 ], [ "▁乗じて", -12.971802711486816 ], [ "▁水温", -12.971891403198242 ], [ "会話", -12.971891403198242 ], [ "‎", -12.971966743469238 ], [ "▁1858", -12.972063064575195 ], [ "▁大変でした", -12.972090721130371 ], [ "▁植栽", -12.972222328186035 ], [ "▁フーズ", -12.97272777557373 ], [ "▁穏やかに", -12.972728729248047 ], [ "痘", -12.972728729248047 ], [ "aven", -12.972743034362793 ], [ "▁先導", -12.972938537597656 ], [ "▁生ずる", -12.97296142578125 ], [ "▁ケルト", -12.972986221313477 ], [ "▁攻城", -12.972987174987793 ], [ "共通", -12.973039627075195 ], [ "▁成虫", -12.973047256469727 ], [ "▁バイアス", -12.973149299621582 ], [ "▁遠ざか", -12.973187446594238 ], [ "▁スワローズ", -12.973254203796387 ], [ "▁ベイスターズ", -12.973490715026855 ], [ "▁ラファエル", -12.973490715026855 ], [ "▁ミシン", -12.973514556884766 ], [ "▁フラッグ", -12.973583221435547 ], [ "▁フィナンシャル", -12.97374439239502 ], [ "▁服従", -12.973752975463867 ], [ "▁骨董", -12.973784446716309 ], [ "▁未婚", -12.973841667175293 ], [ "飽", -12.97399616241455 ], [ "▁激励", -12.974029541015625 ], [ "▁デュエット", -12.974039077758789 ], [ "デッド", -12.974150657653809 ], [ "戦時", -12.974185943603516 ], [ "▁以西", -12.974255561828613 ], [ "▁違憲", -12.974273681640625 ], [ "▁降臨", -12.974273681640625 ], [ "▁脱線", -12.974382400512695 ], [ "▁埠頭", -12.974507331848145 ], [ "吟", -12.974507331848145 ], [ "▁異変", -12.974597930908203 ], [ "▁トッピング", -12.974644660949707 ], [ "此", -12.974749565124512 ], [ "枢", -12.974777221679688 ], [ "▁ネガティブ", -12.97497272491455 ], [ "▁マクラーレン", -12.975016593933105 ], [ "勒", -12.975016593933105 ], [ "▁襲来", -12.975018501281738 ], [ "▁壊し", -12.975044250488281 ], [ "▁ものまね", -12.975278854370117 ], [ "▁渡来", -12.975293159484863 ], [ "編成", -12.97531795501709 ], [ "▁ほぐし", -12.975336074829102 ], [ "▁新婦", -12.97541332244873 ], [ "1901", -12.975472450256348 ], [ "▁スプレッド", -12.97552490234375 ], [ "▁藝術", -12.97552490234375 ], [ "▁エッグ", -12.975683212280273 ], [ "▁無理です", -12.97573184967041 ], [ "死後", -12.975793838500977 ], [ "携", -12.976014137268066 ], [ "暢", -12.976034164428711 ], [ "▁マイヤー", -12.976058959960938 ], [ "▁滝沢", -12.976099967956543 ], [ "ATH", -12.976127624511719 ], [ "博士", -12.976276397705078 ], [ "▁わがまま", -12.976292610168457 ], [ "普通に", -12.976400375366211 ], [ "hap", -12.97641658782959 ], [ "▁美浜", -12.976457595825195 ], [ "恐縮", -12.976510047912598 ], [ "▁傾き", -12.976513862609863 ], [ "▁体裁", -12.976594924926758 ], [ "▁要衝", -12.97663402557373 ], [ "チュラ", -12.976666450500488 ], [ "後年", -12.976702690124512 ], [ "▁坂田", -12.976704597473145 ], [ "▁ズー", -12.97671127319336 ], [ "Apache", -12.976801872253418 ], [ "▁ストライカー", -12.976801872253418 ], [ "▁ルーカス", -12.977005004882812 ], [ "偏", -12.977046012878418 ], [ "▁学研", -12.977084159851074 ], [ "▁延岡", -12.977121353149414 ], [ "▁複写", -12.977343559265137 ], [ "▁発泡", -12.977398872375488 ], [ "▁ドライヤー", -12.977447509765625 ], [ "AME", -12.977555274963379 ], [ "▁1859", -12.977688789367676 ], [ "▁つなげ", -12.977790832519531 ], [ "▁玉ねぎ", -12.977819442749023 ], [ "struct", -12.977887153625488 ], [ "▁随筆", -12.97807502746582 ], [ "raz", -12.978165626525879 ], [ "近距離", -12.978169441223145 ], [ "▁Micro", -12.97817611694336 ], [ "▁CAP", -12.978269577026367 ], [ "▁ヒューズ", -12.978296279907227 ], [ "▁手がけ", -12.978363990783691 ], [ "▁装い", -12.978364944458008 ], [ "シィ", -12.97840404510498 ], [ "▁幕内", -12.978452682495117 ], [ "▁摂り", -12.97857666015625 ], [ "▁筑前", -12.978588104248047 ], [ "メンタ", -12.978601455688477 ], [ "経緯", -12.978666305541992 ], [ "▁海抜", -12.978757858276367 ], [ "▁マツコ", -12.978833198547363 ], [ "▁ゲオルク", -12.978840827941895 ], [ "▁ヘルシンキ", -12.978840827941895 ], [ "▁ビギナー", -12.978846549987793 ], [ "凍", -12.978862762451172 ], [ "▁ヤギ", -12.979016304016113 ], [ "▁恥じ", -12.979100227355957 ], [ "▁結衣", -12.979133605957031 ], [ "4,000", -12.979297637939453 ], [ "▁切替", -12.979307174682617 ], [ "ogo", -12.979382514953613 ], [ "▁SBI", -12.979506492614746 ], [ "▁打楽器", -12.979708671569824 ], [ "▁飛ばして", -12.979713439941406 ], [ "▁マネージャ", -12.979754447937012 ], [ "▁こだわ", -12.979809761047363 ], [ "▁Information", -12.979863166809082 ], [ "▁励んで", -12.979864120483398 ], [ "▁襲う", -12.979869842529297 ], [ "▁エントランス", -12.979899406433105 ], [ "▁縦断", -12.98002815246582 ], [ "▁労組", -12.980182647705078 ], [ "シンプルな", -12.980222702026367 ], [ "▁チョーク", -12.98026180267334 ], [ "じけん", -12.98029899597168 ], [ "▁リニア", -12.980408668518066 ], [ "▁プチプラ", -12.98044490814209 ], [ "PAR", -12.980552673339844 ], [ "▁待った", -12.980613708496094 ], [ "▁刈り", -12.9806489944458 ], [ "▁羨まし", -12.980673789978027 ], [ "▁物販", -12.98077392578125 ], [ "▁三陸", -12.980775833129883 ], [ "▁担い手", -12.980830192565918 ], [ "▁ブート", -12.9808349609375 ], [ "▁クロード", -12.980905532836914 ], [ "▁里親", -12.980953216552734 ], [ "▁Image", -12.980972290039062 ], [ "▁嫌う", -12.980984687805176 ], [ "▁堕落", -12.9811429977417 ], [ "女の子", -12.981191635131836 ], [ "予想", -12.981237411499023 ], [ "風俗", -12.981353759765625 ], [ "▁洋風", -12.981422424316406 ], [ "▁シンシナティ", -12.98165512084961 ], [ "サウスカロライナ", -12.98165512084961 ], [ "腎", -12.981706619262695 ], [ "▁オルガ", -12.981842041015625 ], [ "▁疫病", -12.981910705566406 ], [ "▁ハイテク", -12.981911659240723 ], [ "▁現像", -12.982132911682129 ], [ "▁効き", -12.98226547241211 ], [ "▁技士", -12.982321739196777 ], [ "til", -12.982416152954102 ], [ "▁アウトプット", -12.982423782348633 ], [ "▁賀茂", -12.98242473602295 ], [ "vil", -12.982438087463379 ], [ "▁踏み入れ", -12.982545852661133 ], [ "意識", -12.982561111450195 ], [ "▁喋り", -12.982569694519043 ], [ "▁義務づけ", -12.982587814331055 ], [ "喩", -12.982641220092773 ], [ "EVER", -12.982813835144043 ], [ "▁特約", -12.982820510864258 ], [ "UMI", -12.98310375213623 ], [ "▁ジーニアス", -12.983193397521973 ], [ "▁混成", -12.983455657958984 ], [ "▁まとまって", -12.983478546142578 ], [ "▁深谷", -12.983481407165527 ], [ "450", -12.983527183532715 ], [ "▁しあわせ", -12.9837064743042 ], [ "nh", -12.983785629272461 ], [ "篭", -12.983963012695312 ], [ "▁持ち味", -12.984126091003418 ], [ "▁スターター", -12.984143257141113 ], [ "▁ブラインド", -12.984169960021973 ], [ "▁フェンダー", -12.984620094299316 ], [ "▁score", -12.984655380249023 ], [ "Torrent", -12.984733581542969 ], [ "▁アンソロジー", -12.984733581542969 ], [ "wood", -12.98473834991455 ], [ "▁ゾイド", -12.9847993850708 ], [ "ランジェ", -12.98481559753418 ], [ "▁難点", -12.984832763671875 ], [ "▁離職", -12.984963417053223 ], [ "▁心霊", -12.985004425048828 ], [ "▁山荘", -12.985225677490234 ], [ "釣り", -12.985443115234375 ], [ "▁扶桑", -12.985505104064941 ], [ "▁Note", -12.985522270202637 ], [ "▁情景", -12.985577583312988 ], [ "Edit", -12.985647201538086 ], [ "▁卓上", -12.98568058013916 ], [ "级", -12.985762596130371 ], [ "▁必需", -12.985767364501953 ], [ "▁Ever", -12.985877990722656 ], [ "大きく", -12.985883712768555 ], [ "▁摘発", -12.9860200881958 ], [ "uo", -12.986181259155273 ], [ "▁告訴", -12.98627758026123 ], [ "▁売場", -12.986355781555176 ], [ "▁揃える", -12.986956596374512 ], [ "▁(^-^)", -12.987049102783203 ], [ "▁わりと", -12.98707389831543 ], [ "▁ハープ", -12.987091064453125 ], [ "競馬", -12.987237930297852 ], [ "▁溶かし", -12.987298011779785 ], [ "▁取り下げ", -12.987334251403809 ], [ "▁高裁", -12.987340927124023 ], [ "▁平壌", -12.987347602844238 ], [ "蒸", -12.987401008605957 ], [ "——", -12.98741340637207 ], [ "lac", -12.987458229064941 ], [ "▁救った", -12.987548828125 ], [ "▁カウボーイ", -12.987579345703125 ], [ "irt", -12.987593650817871 ], [ "▁Azure", -12.987822532653809 ], [ "▁真摯に", -12.987822532653809 ], [ "楽しい", -12.987991333007812 ], [ "▁ダクト", -12.98808765411377 ], [ "ハタ", -12.988375663757324 ], [ "駿", -12.988398551940918 ], [ "▁スライス", -12.988399505615234 ], [ "▁養う", -12.98853874206543 ], [ "基督教", -12.988595962524414 ], [ "▁ブランチ", -12.988801002502441 ], [ "▁夜勤", -12.98902416229248 ], [ "cat", -12.989089012145996 ], [ "▁二階堂", -12.98911190032959 ], [ "認知", -12.98940372467041 ], [ "▁ひかる", -12.989456176757812 ], [ "ヒェン", -12.989481925964355 ], [ "▁追いや", -12.989532470703125 ], [ "▁取りまとめ", -12.989729881286621 ], [ "ユダヤ", -12.98974323272705 ], [ "▁ばか", -12.989855766296387 ], [ "▁網走", -12.98994255065918 ], [ "▁研鑽", -12.99040412902832 ], [ "▁異国", -12.990455627441406 ], [ "従前", -12.990530014038086 ], [ "▁運勢", -12.990610122680664 ], [ "滲", -12.99066162109375 ], [ "▁見習い", -12.990662574768066 ], [ "▁狩野", -12.990981101989746 ], [ "▁本誌", -12.99108600616455 ], [ "▁武雄", -12.991127967834473 ], [ "▁移築", -12.991227149963379 ], [ "▁悪口", -12.99138355255127 ], [ "▁浩二", -12.9913911819458 ], [ "OV", -12.991476058959961 ], [ "▁打開", -12.991477012634277 ], [ "▁原価", -12.991558074951172 ], [ "▁おおさか", -12.991701126098633 ], [ "▁専売", -12.991790771484375 ], [ "▁憲兵", -12.992033958435059 ], [ "ヴィクト", -12.992218017578125 ], [ "▁レジスタ", -12.99232292175293 ], [ "▁アンドレア", -12.992379188537598 ], [ "▁淡々と", -12.992490768432617 ], [ "▁ディック", -12.992574691772461 ], [ "速力", -12.992704391479492 ], [ "▁押し上げ", -12.992924690246582 ], [ "▁難病", -12.99295711517334 ], [ "▁HTTP", -12.993001937866211 ], [ "▁傷つける", -12.993228912353516 ], [ "▁空洞", -12.993229866027832 ], [ "▁巧みに", -12.993249893188477 ], [ "▁試乗", -12.993349075317383 ], [ "▁成約", -12.993355751037598 ], [ "▁養父", -12.993420600891113 ], [ "▁アディダス", -12.993509292602539 ], [ "▁子連れ", -12.993509292602539 ], [ "ピーター", -12.993657112121582 ], [ "スロット", -12.99371337890625 ], [ "ODE", -12.993766784667969 ], [ "▁VII", -12.993829727172852 ], [ "▁不当な", -12.993849754333496 ], [ "▁ガリア", -12.993959426879883 ], [ "諾", -12.993988990783691 ], [ "▁たどり着いた", -12.994028091430664 ], [ "▁混じって", -12.994028091430664 ], [ "▁Sports", -12.994032859802246 ], [ "▁マルシェ", -12.994096755981445 ], [ "▁網膜", -12.9942045211792 ], [ "(*^", -12.994248390197754 ], [ "トゥン", -12.994449615478516 ], [ "▁漬物", -12.994548797607422 ], [ "▁放ってお", -12.994566917419434 ], [ "▁おむつ", -12.994733810424805 ], [ "▁思い浮か", -12.994784355163574 ], [ "▁ルイヴィトン", -12.994806289672852 ], [ "▁ボウリング", -12.9948091506958 ], [ "▁スケベ", -12.994823455810547 ], [ "▁さかのぼる", -12.994842529296875 ], [ "ぜんぜん", -12.994893074035645 ], [ "▁参議", -12.994929313659668 ], [ "ORN", -12.99494457244873 ], [ "596", -12.995020866394043 ], [ "畏", -12.995063781738281 ], [ "▁監事", -12.995068550109863 ], [ "▁GIF", -12.995165824890137 ], [ "餌", -12.995227813720703 ], [ "print", -12.995445251464844 ], [ "▁便器", -12.995498657226562 ], [ "ไ", -12.995585441589355 ], [ "▁レクチャー", -12.995586395263672 ], [ "▁論じた", -12.995765686035156 ], [ "▁断然", -12.995782852172852 ], [ "忘れ", -12.995782852172852 ], [ "物理", -12.995784759521484 ], [ "北米", -12.995810508728027 ], [ "スワフ", -12.995841026306152 ], [ "▁しゅん", -12.99588680267334 ], [ "▁形容詞", -12.996118545532227 ], [ "▁特捜", -12.996648788452148 ], [ "▁夕刊", -12.99673843383789 ], [ "matic", -12.996758460998535 ], [ "▁杉本", -12.996868133544922 ], [ "▁桃太郎", -12.996915817260742 ], [ "▁天堂", -12.997142791748047 ], [ "アルデヒド", -12.99714469909668 ], [ "クリーム", -12.997444152832031 ], [ "マイクロ", -12.997517585754395 ], [ "歯科", -12.997567176818848 ], [ "▁オブジェ", -12.997705459594727 ], [ "蘇", -12.997763633728027 ], [ "hol", -12.997865676879883 ], [ "▁萎縮", -12.997925758361816 ], [ "vy", -12.997964859008789 ], [ "▁問答", -12.997991561889648 ], [ "小型", -12.997992515563965 ], [ "▁行えば", -12.998010635375977 ], [ "▁段々", -12.998026847839355 ], [ "▁バースデー", -12.998209953308105 ], [ "▁パーソン", -12.99832534790039 ], [ "▁さっさと", -12.998446464538574 ], [ "▁ボロボロ", -12.998452186584473 ], [ "▁襲って", -12.998462677001953 ], [ "ゾール", -12.9986572265625 ], [ "scape", -12.998772621154785 ], [ "譚", -12.998902320861816 ], [ "▁つばさ", -12.99898624420166 ], [ "デット", -12.999051094055176 ], [ "▁真偽", -12.999078750610352 ], [ "▁正方形", -12.999228477478027 ], [ "▁着心地", -12.999228477478027 ], [ "叢", -12.999228477478027 ], [ "▁イエズ", -12.999232292175293 ], [ "AIL", -12.999234199523926 ], [ "▁辰巳", -12.999241828918457 ], [ "尋", -12.99943733215332 ], [ "褐", -12.999488830566406 ], [ "▁Kids", -12.999505043029785 ], [ "▁summer", -12.999750137329102 ], [ "▁疑似", -12.999770164489746 ], [ "▁廃校", -12.999837875366211 ], [ "着陸", -12.999917030334473 ], [ "珪", -13.00001049041748 ], [ "▁暗記", -13.000012397766113 ], [ "ific", -13.000075340270996 ], [ "▁十和田", -13.000082015991211 ], [ "▁会津若松", -13.000271797180176 ], [ "んどう", -13.00029182434082 ], [ "宿泊", -13.00030517578125 ], [ "▁Order", -13.000316619873047 ], [ "▁過ち", -13.000323295593262 ], [ "▁通年", -13.00047492980957 ], [ "▁チャーチル", -13.000534057617188 ], [ "▁フリル", -13.000677108764648 ], [ "靭", -13.000794410705566 ], [ "▁オースティン", -13.00087833404541 ], [ "ズィー", -13.000996589660645 ], [ "混血", -13.001035690307617 ], [ "ฏ", -13.001055717468262 ], [ "▁sca", -13.001129150390625 ], [ "▁リピーター", -13.001199722290039 ], [ "▁東岸", -13.001205444335938 ], [ "▁ソムリエ", -13.00131607055664 ], [ "▁カーナビ", -13.001521110534668 ], [ "▁ニーチェ", -13.001548767089844 ], [ "▁North", -13.00158405303955 ], [ "▁今更", -13.001585006713867 ], [ "▁SKE", -13.001694679260254 ], [ "▁エキストラ", -13.001818656921387 ], [ "▁現われ", -13.002047538757324 ], [ "▁アクセサリ", -13.002076148986816 ], [ "▁ヴァリ", -13.002114295959473 ], [ "▁遅刻", -13.002135276794434 ], [ "▁イントロ", -13.002175331115723 ], [ "▁絡む", -13.002364158630371 ], [ "rian", -13.002370834350586 ], [ "▁密教", -13.002435684204102 ], [ "▁怒った", -13.00243854522705 ], [ "▁モーガン", -13.002492904663086 ], [ "▁ありのまま", -13.002623558044434 ], [ "▁アンバサダー", -13.002885818481445 ], [ "♬", -13.002885818481445 ], [ "▁TPP", -13.002888679504395 ], [ "▁AMD", -13.003000259399414 ], [ "▁更年期", -13.00314712524414 ], [ "芙", -13.00314712524414 ], [ "▁自民", -13.003190040588379 ], [ "ピーク", -13.003244400024414 ], [ "▁果汁", -13.00343132019043 ], [ "紹介", -13.003434181213379 ], [ "▁吐き", -13.003478050231934 ], [ "▁叶う", -13.003575325012207 ], [ "凡", -13.003581047058105 ], [ "▁Year", -13.00365924835205 ], [ "壽", -13.003669738769531 ], [ "▁がっかり", -13.003768920898438 ], [ "▁税額", -13.003790855407715 ], [ "▁アラバマ", -13.004194259643555 ], [ "古典", -13.004231452941895 ], [ "ギリシャ", -13.00429630279541 ], [ "▁固い", -13.004301071166992 ], [ "▁厳密な", -13.004456520080566 ], [ "▁有り難", -13.004555702209473 ], [ "▁論議", -13.004594802856445 ], [ "hal", -13.00475025177002 ], [ "▁醍醐", -13.00495719909668 ], [ "▁謎解き", -13.00498104095459 ], [ "罷免", -13.004982948303223 ], [ "▁バッチリ", -13.005041122436523 ], [ "NBA", -13.005081176757812 ], [ "OTH", -13.005130767822266 ], [ "▁根強い", -13.00516414642334 ], [ "▁吹いて", -13.005253791809082 ], [ "▁酷く", -13.005309104919434 ], [ "採", -13.005424499511719 ], [ "シャール", -13.005637168884277 ], [ "栃", -13.00563907623291 ], [ "部活", -13.005712509155273 ], [ "▁いっそう", -13.005716323852539 ], [ "▁メトロポリタン", -13.005767822265625 ], [ "▁酷似", -13.005767822265625 ], [ "當", -13.005767822265625 ], [ "▁モリス", -13.005768775939941 ], [ "▁Check", -13.005813598632812 ], [ "wiki", -13.005864143371582 ], [ "▁ポジティブな", -13.005916595458984 ], [ "ICHI", -13.006024360656738 ], [ "馴", -13.006204605102539 ], [ "トランプ", -13.006243705749512 ], [ "acc", -13.006285667419434 ], [ "▁spring", -13.00631046295166 ], [ "其", -13.006537437438965 ], [ "▁目覚まし", -13.006573677062988 ], [ "EIT", -13.006641387939453 ], [ "▁謙虚", -13.00682544708252 ], [ "▁強大な", -13.007086753845215 ], [ "▁MASTER", -13.007107734680176 ], [ "▁ワースト", -13.007173538208008 ], [ "▁埴輪", -13.007344245910645 ], [ "▁project", -13.007366180419922 ], [ "▁こなせる", -13.007630348205566 ], [ "アンドロ", -13.007704734802246 ], [ "享保", -13.007723808288574 ], [ "▁東邦", -13.007850646972656 ], [ "逃げ", -13.007946014404297 ], [ "▁不意", -13.008007049560547 ], [ "▁アーマー", -13.008025169372559 ], [ "▁勇敢", -13.00814437866211 ], [ "MOS", -13.008173942565918 ], [ "char", -13.008261680603027 ], [ "▁桃花", -13.008289337158203 ], [ "▁sex", -13.00836181640625 ], [ "楢", -13.00839614868164 ], [ "▁由利", -13.00844669342041 ], [ "▁Kiss", -13.008661270141602 ], [ "▁Control", -13.008666038513184 ], [ "OSHI", -13.008715629577637 ], [ "▁吹雪", -13.008723258972168 ], [ "kh", -13.008914947509766 ], [ "▁因む", -13.008919715881348 ], [ "瓦", -13.008925437927246 ], [ "而", -13.008962631225586 ], [ "▁リネン", -13.00899600982666 ], [ "硬", -13.009072303771973 ], [ "▁文様", -13.009073257446289 ], [ "予定", -13.009111404418945 ], [ "▁執拗", -13.00918960571289 ], [ "▁カフェイン", -13.009382247924805 ], [ "▁負け越し", -13.009543418884277 ], [ "▁償却", -13.009712219238281 ], [ "▁水漏れ", -13.009712219238281 ], [ "▁繋いで", -13.009712219238281 ], [ "mission", -13.009714126586914 ], [ "▁合算", -13.010047912597656 ], [ "確認", -13.010068893432617 ], [ "▁目隠し", -13.01024055480957 ], [ "▁健太郎", -13.01025390625 ], [ "兎", -13.010265350341797 ], [ "んかん", -13.010302543640137 ], [ "IAN", -13.010333061218262 ], [ "▁戻した", -13.010429382324219 ], [ "国連", -13.010488510131836 ], [ "▁フォルクスワーゲン", -13.010502815246582 ], [ "▁エルンスト", -13.010503768920898 ], [ "▁別表", -13.010506629943848 ], [ "▁労使", -13.010560035705566 ], [ "cher", -13.010621070861816 ], [ "モーニング", -13.0106840133667 ], [ "▁むつ", -13.010736465454102 ], [ "室町", -13.01081657409668 ], [ "▁カットソー", -13.010884284973145 ], [ "みなさま", -13.011062622070312 ], [ "偽", -13.01120376586914 ], [ "ないしは", -13.011321067810059 ], [ "▁すみれ", -13.011371612548828 ], [ "状態", -13.011489868164062 ], [ "▁新編", -13.011507987976074 ], [ "▁海老名", -13.011551856994629 ], [ "▁ハッシュタグ", -13.011567115783691 ], [ "▁お好み焼き", -13.011573791503906 ], [ "▁para", -13.011587142944336 ], [ "▁賢治", -13.011690139770508 ], [ "▁めざす", -13.011821746826172 ], [ "▁組み合わさ", -13.011821746826172 ], [ "▁猛暑", -13.011850357055664 ], [ "▁扮し", -13.011886596679688 ], [ "▁section", -13.01193618774414 ], [ "キュウ", -13.01209545135498 ], [ "皆さま", -13.012142181396484 ], [ "▁異論", -13.012166976928711 ], [ "▁減税", -13.012239456176758 ], [ "▁銀貨", -13.012242317199707 ], [ "而上", -13.012247085571289 ], [ "table", -13.012324333190918 ], [ "▁相鉄", -13.01235294342041 ], [ "将軍", -13.012415885925293 ], [ "▁放電", -13.012476921081543 ], [ "▁励ま", -13.012508392333984 ], [ "▁ニュルンベルク", -13.012614250183105 ], [ "city", -13.012743949890137 ], [ "▁好物", -13.0128755569458 ], [ "λ", -13.012882232666016 ], [ "▁二十四", -13.013072967529297 ], [ "▁ハプニング", -13.013407707214355 ], [ "▁靖国", -13.01341438293457 ], [ "駐", -13.013623237609863 ], [ "▁author", -13.013668060302734 ], [ "▁劇作家", -13.01370620727539 ], [ "ロボット", -13.013724327087402 ], [ "▁聞こえた", -13.01382827758789 ], [ "▁実話", -13.013875007629395 ], [ "É", -13.013936042785645 ], [ "▁三菱電機", -13.013936996459961 ], [ "▁不都合", -13.013936996459961 ], [ "▁色紙", -13.014135360717773 ], [ "▁揖斐", -13.014201164245605 ], [ "▁菅野", -13.014223098754883 ], [ "太夫", -13.014378547668457 ], [ "▁嫌気", -13.014423370361328 ], [ "謹慎", -13.0144681930542 ], [ "▁鋭く", -13.014505386352539 ], [ "翻訳", -13.0145263671875 ], [ "於", -13.014548301696777 ], [ "RING", -13.014647483825684 ], [ "▁キャビネット", -13.014730453491211 ], [ "どういう", -13.014792442321777 ], [ "▁発せ", -13.014795303344727 ], [ "▁てんかん", -13.014887809753418 ], [ "▁溜まり", -13.014996528625488 ], [ "▁容易な", -13.015092849731445 ], [ "▁眠気", -13.015268325805664 ], [ "▁難関", -13.015271186828613 ], [ "免费", -13.015310287475586 ], [ "▁JCB", -13.015380859375 ], [ "▁夕張", -13.015385627746582 ], [ "▁中高年", -13.015459060668945 ], [ "▁円錐", -13.015460014343262 ], [ "▁Para", -13.01546859741211 ], [ "災害", -13.015640258789062 ], [ "▁言い回し", -13.0160551071167 ], [ "蓬", -13.0160551071167 ], [ "▁フライヤー", -13.016261100769043 ], [ "▁バーコード", -13.016324996948242 ], [ "▁京極", -13.01638412475586 ], [ "▁別居", -13.016487121582031 ], [ "▁マダム", -13.01655101776123 ], [ "▁潰瘍", -13.016586303710938 ], [ "▁Street", -13.016587257385254 ], [ "chen", -13.016697883605957 ], [ "map", -13.016763687133789 ], [ "音声", -13.016871452331543 ], [ "▁着付け", -13.016873359680176 ], [ "▁Wind", -13.01710033416748 ], [ "▁プエルトリコ", -13.017382621765137 ], [ "▁吸着", -13.017550468444824 ], [ "▁平気で", -13.017858505249023 ], [ "▁便所", -13.017877578735352 ], [ "▁タブー", -13.017900466918945 ], [ "▁出汁", -13.017949104309082 ], [ "▁バークレー", -13.01796817779541 ], [ "▁臨み", -13.018067359924316 ], [ "▁列強", -13.018193244934082 ], [ "▁レディー", -13.018462181091309 ], [ "▁早世", -13.01870059967041 ], [ "梯", -13.018707275390625 ], [ "▁不可欠です", -13.01871395111084 ], [ "Ω", -13.018976211547852 ], [ "▁HDMI", -13.01904296875 ], [ "杖", -13.019074440002441 ], [ "提供", -13.019092559814453 ], [ "▁腹筋", -13.019207000732422 ], [ "▁Institute", -13.019242286682129 ], [ "▁ブダペスト", -13.019242286682129 ], [ "采", -13.019242286682129 ], [ "格安", -13.019329071044922 ], [ "最低", -13.01943588256836 ], [ "皇帝", -13.019465446472168 ], [ "▁レンダリング", -13.019508361816406 ], [ "▁節句", -13.019516944885254 ], [ "ader", -13.019554138183594 ], [ "▁境遇", -13.019561767578125 ], [ "▁ブラザース", -13.019774436950684 ], [ "▁疼痛", -13.019774436950684 ], [ "媚", -13.019774436950684 ], [ "▁不可能です", -13.01977825164795 ], [ "合併", -13.01999568939209 ], [ "ケ丘", -13.020000457763672 ], [ "跋", -13.020040512084961 ], [ "▁食塩", -13.020088195800781 ], [ "▁タモリ", -13.020271301269531 ], [ "▁マルセイユ", -13.020306587219238 ], [ "▁飼う", -13.020548820495605 ], [ "▁封建", -13.020613670349121 ], [ "▁脱水", -13.02070140838623 ], [ "▁加担", -13.020862579345703 ], [ "▁桜花", -13.020944595336914 ], [ "▁持ち出し", -13.020999908447266 ], [ "▁ソケット", -13.021289825439453 ], [ "▁SEED", -13.021329879760742 ], [ "▁アラート", -13.021586418151855 ], [ "駅前", -13.021617889404297 ], [ "▁拡幅", -13.021638870239258 ], [ "▁託児", -13.021686553955078 ], [ "▁具現", -13.022039413452148 ], [ "▁ストーム", -13.022141456604004 ], [ "▁民政", -13.022377014160156 ], [ "▁上半期", -13.022439002990723 ], [ "▁歓喜", -13.022467613220215 ], [ "▁パラレル", -13.022562026977539 ], [ "▁傾い", -13.02260971069336 ], [ "▁靭帯", -13.022706031799316 ], [ "▁Basic", -13.022746086120605 ], [ "▁リスニング", -13.022770881652832 ], [ "できれば", -13.022838592529297 ], [ "▁六甲", -13.022849082946777 ], [ "▁ニコラス", -13.023061752319336 ], [ "oun", -13.023340225219727 ], [ "▁緑化", -13.023369789123535 ], [ "プライベート", -13.023369789123535 ], [ "▁スムージー", -13.023507118225098 ], [ "▁天満", -13.023521423339844 ], [ "▁チンギス", -13.02352523803711 ], [ "探偵", -13.023642539978027 ], [ "いつでも", -13.023763656616211 ], [ "秤", -13.023774147033691 ], [ "▁スタイリッシュな", -13.024042129516602 ], [ "OVA", -13.024150848388672 ], [ "▁コミット", -13.024264335632324 ], [ "▁マリファナ", -13.024309158325195 ], [ "▁うれしく", -13.024606704711914 ], [ "▁未完成", -13.024759292602539 ], [ "▁どこまでも", -13.024845123291016 ], [ "▁由緒", -13.024965286254883 ], [ "JAPAN", -13.024989128112793 ], [ "▁スピリット", -13.02513599395752 ], [ "▁ハローワーク", -13.025145530700684 ], [ "串", -13.025259971618652 ], [ "▁料亭", -13.025513648986816 ], [ "怜", -13.025646209716797 ], [ "茸", -13.025646209716797 ], [ "▁First", -13.025647163391113 ], [ "ネックス", -13.025677680969238 ], [ "▁クロマ", -13.025694847106934 ], [ "▁うず", -13.025739669799805 ], [ "▁線維", -13.025901794433594 ], [ "▁壱岐", -13.025914192199707 ], [ "ency", -13.026098251342773 ], [ "por", -13.026203155517578 ], [ "inal", -13.026274681091309 ], [ "▁着ける", -13.026329040527344 ], [ "▁フォルダー", -13.026357650756836 ], [ "弧", -13.026445388793945 ], [ "▁推論", -13.0265531539917 ], [ "▁長久手", -13.026719093322754 ], [ "▁刑罰", -13.027008056640625 ], [ "▁セイバー", -13.027135848999023 ], [ "▁邦楽", -13.027307510375977 ], [ "▁野鳥", -13.027337074279785 ], [ "▁べから", -13.027383804321289 ], [ "オリコン", -13.027485847473145 ], [ "▁五反田", -13.027522087097168 ], [ "▁剥がれ", -13.027544975280762 ], [ "クイーン", -13.027589797973633 ], [ "一覧", -13.02762508392334 ], [ "▁惨敗", -13.027807235717773 ], [ "▁食パン", -13.02780818939209 ], [ "▁禁書", -13.027931213378906 ], [ "▁宿舎", -13.0282564163208 ], [ "▁放流", -13.028266906738281 ], [ "field", -13.028404235839844 ], [ "▁近視", -13.02883243560791 ], [ "▁FOX", -13.028844833374023 ], [ "▁根室", -13.028849601745605 ], [ "▁なでしこ", -13.028863906860352 ], [ "▁ファイナリスト", -13.028863906860352 ], [ "泳", -13.028975486755371 ], [ "▁面倒だ", -13.028993606567383 ], [ "▁谷間", -13.029003143310547 ], [ "▁ダンボール", -13.029004096984863 ], [ "軟", -13.029035568237305 ], [ "emb", -13.029058456420898 ], [ "クライアント", -13.029059410095215 ], [ "文章", -13.029060363769531 ], [ "莫", -13.029132843017578 ], [ "▁悔い", -13.029298782348633 ], [ "▁ティル", -13.029465675354004 ], [ "▁電通", -13.029579162597656 ], [ "▁ラルフ", -13.02961254119873 ], [ "▁たどり着く", -13.029670715332031 ], [ "ヘッダー", -13.029858589172363 ], [ "nor", -13.029923439025879 ], [ "ペリパトス", -13.029938697814941 ], [ "▁ベクター", -13.03000259399414 ], [ "綾", -13.030126571655273 ], [ "kk", -13.03020191192627 ], [ "▁費やして", -13.030208587646484 ], [ "▁見返り", -13.0302095413208 ], [ "▁揺さぶ", -13.0302152633667 ], [ "慶応", -13.030241966247559 ], [ "もかも", -13.030325889587402 ], [ "▁健闘", -13.030336380004883 ], [ "uv", -13.030448913574219 ], [ "暮らし", -13.030448913574219 ], [ "▁盛り上げる", -13.030476570129395 ], [ "▁サンリオ", -13.030723571777344 ], [ "▁rose", -13.030844688415527 ], [ "エチル", -13.03084945678711 ], [ "▁削って", -13.030915260314941 ], [ "プライバシー", -13.030940055847168 ], [ "▁但馬", -13.031015396118164 ], [ "▁サーブ", -13.0311279296875 ], [ "改めて", -13.031128883361816 ], [ "▁枢機卿", -13.03128433227539 ], [ "▁兼ねる", -13.031292915344238 ], [ "▁キャノン", -13.031296730041504 ], [ "OSE", -13.031367301940918 ], [ "緩", -13.031468391418457 ], [ "失敗", -13.031510353088379 ], [ "▁ジョナサン", -13.031553268432617 ], [ "▁揃う", -13.03155517578125 ], [ "▁一向に", -13.031560897827148 ], [ "▁豊前", -13.03157901763916 ], [ "▁ジッパー", -13.031615257263184 ], [ "臨床", -13.031781196594238 ], [ "▁ボトムス", -13.031783103942871 ], [ "IKA", -13.031805038452148 ], [ "▁囃子", -13.032093048095703 ], [ "▁割り振", -13.032149314880371 ], [ "▁クライミング", -13.032158851623535 ], [ "▁メイクアップ", -13.032222747802734 ], [ "▁ヴァレ", -13.032246589660645 ], [ "ヴェール", -13.032257080078125 ], [ "▁柔らかな", -13.032275199890137 ], [ "重要な", -13.03229808807373 ], [ "▁ユーラシア", -13.03236198425293 ], [ "訛", -13.03236198425293 ], [ "ちっと", -13.032384872436523 ], [ "学位", -13.032388687133789 ], [ "幕末", -13.032437324523926 ], [ "▁ターナー", -13.032465934753418 ], [ "▁イスタンブール", -13.032630920410156 ], [ "▁ジャニ", -13.032919883728027 ], [ "goo", -13.032984733581543 ], [ "▁エネミー", -13.033206939697266 ], [ "▁辛口", -13.033280372619629 ], [ "文庫", -13.033329963684082 ], [ "▁決行", -13.033356666564941 ], [ "植生", -13.033422470092773 ], [ "▁永住", -13.033430099487305 ], [ "▁希薄", -13.033474922180176 ], [ "▁降車", -13.033479690551758 ], [ "▁エクステ", -13.033493041992188 ], [ "▁向いた", -13.033513069152832 ], [ "▁艦首", -13.033693313598633 ], [ "▁吸気", -13.033803939819336 ], [ "▁毒素", -13.033842086791992 ], [ "目の前", -13.033929824829102 ], [ "▁Hey", -13.034111976623535 ], [ "▁モニュメント", -13.034250259399414 ], [ "▁五十嵐", -13.034265518188477 ], [ "▁アニメーター", -13.034341812133789 ], [ "ヶ原", -13.034517288208008 ], [ "葦", -13.034520149230957 ], [ "釉", -13.0347900390625 ], [ "480", -13.034951210021973 ], [ "rig", -13.034961700439453 ], [ "▁マヨネーズ", -13.03506088256836 ], [ "嘲", -13.03506088256836 ], [ "▁慣行", -13.035062789916992 ], [ "▁銅像", -13.035252571105957 ], [ "▁Hulu", -13.035346031188965 ], [ "▁直属", -13.035383224487305 ], [ "▁葉酸", -13.035459518432617 ], [ "共同", -13.03564453125 ], [ "綜", -13.035871505737305 ], [ "▁叫んだ", -13.03587818145752 ], [ "▁渦巻", -13.035914421081543 ], [ "▁術後", -13.0360689163208 ], [ "▁各務原", -13.03614330291748 ], [ "▁二塁", -13.03618049621582 ], [ "▁コミカル", -13.03626823425293 ], [ "▁口説", -13.036382675170898 ], [ "▁creat", -13.036416053771973 ], [ "▁ことごとく", -13.036418914794922 ], [ "春日", -13.036498069763184 ], [ "▁シロップ", -13.036520004272461 ], [ "▁IOC", -13.036595344543457 ], [ "▁出征", -13.0369234085083 ], [ "▁送受信", -13.037495613098145 ], [ "▁流量", -13.037697792053223 ], [ "BEAMS", -13.037769317626953 ], [ "系譜", -13.037809371948242 ], [ "ぶっちゃけ", -13.037839889526367 ], [ "▁豊岡", -13.037842750549316 ], [ "▁コソボ", -13.038037300109863 ], [ "▁糾弾", -13.038037300109863 ], [ "▁ストロー", -13.0382080078125 ], [ "▁引き金", -13.03834056854248 ], [ "ن", -13.038579940795898 ], [ "▁ブラケット", -13.038581848144531 ], [ "▁くらし", -13.038589477539062 ], [ "掴", -13.038670539855957 ], [ "ゴールデン", -13.03868293762207 ], [ "▁自我", -13.038702011108398 ], [ "▁溶媒", -13.038859367370605 ], [ "▁必勝", -13.038923263549805 ], [ "▁割当", -13.038928985595703 ], [ "bj", -13.038930892944336 ], [ "▁明かす", -13.0390043258667 ], [ "▁着衣", -13.039033889770508 ], [ "▁加筆", -13.039052963256836 ], [ "▁パステル", -13.039112091064453 ], [ "▁トーキョー", -13.039121627807617 ], [ "感謝", -13.039158821105957 ], [ "▁佐々", -13.039249420166016 ], [ "▁パルプ", -13.039323806762695 ], [ "諏訪", -13.039387702941895 ], [ "▁素朴な", -13.039393424987793 ], [ "匡", -13.039393424987793 ], [ "抜本", -13.03957748413086 ], [ "膝", -13.039660453796387 ], [ "▁昇降", -13.039726257324219 ], [ "▁ナイツ", -13.039921760559082 ], [ "インドネシア", -13.039934158325195 ], [ "▁振込み", -13.039937019348145 ], [ "▁此の", -13.039960861206055 ], [ "▁ばれ", -13.040000915527344 ], [ "▁丹羽", -13.040027618408203 ], [ "▁立ち去", -13.040048599243164 ], [ "▁殿下", -13.040050506591797 ], [ "▁削ら", -13.040337562561035 ], [ "▁井原", -13.040373802185059 ], [ "テヘル", -13.040413856506348 ], [ "▁オーボエ", -13.04047966003418 ], [ "▁みせた", -13.040557861328125 ], [ "▁尻尾", -13.04068374633789 ], [ "罹", -13.040751457214355 ], [ "左腕", -13.040945053100586 ], [ "▁暴風", -13.041004180908203 ], [ "▁備中", -13.041013717651367 ], [ "▁花巻", -13.041056632995605 ], [ "▁主君", -13.041158676147461 ], [ "vol", -13.041260719299316 ], [ "▁ガブリエル", -13.041295051574707 ], [ "なるべく", -13.041304588317871 ], [ "▁益田", -13.04133129119873 ], [ "▁Room", -13.041333198547363 ], [ "▁車輛", -13.041343688964844 ], [ "▁スレイヤー", -13.041621208190918 ], [ "▁遅滞", -13.041845321655273 ], [ "危険", -13.041850090026855 ], [ "ジャパン", -13.041863441467285 ], [ "古くから", -13.041887283325195 ], [ "▁ひっくり返", -13.042384147644043 ], [ "lam", -13.042431831359863 ], [ "▁シャンパン", -13.042533874511719 ], [ "▁ランタン", -13.04254150390625 ], [ "▁六十", -13.042558670043945 ], [ "▁鴨川", -13.04258918762207 ], [ "比較", -13.042657852172852 ], [ "▁劇的な", -13.042927742004395 ], [ "▁レクサス", -13.043200492858887 ], [ "▁群衆", -13.043246269226074 ], [ "ヴィング", -13.043292999267578 ], [ "▁有益", -13.04329776763916 ], [ "▁ヤバい", -13.043475151062012 ], [ "▁スカイツリー", -13.043745994567871 ], [ "▁コンバータ", -13.043753623962402 ], [ "▁下げた", -13.0437593460083 ], [ "▁英検", -13.04378604888916 ], [ "▁にんにく", -13.044017791748047 ], [ "▁足柄", -13.04405403137207 ], [ "▁残骸", -13.044054985046387 ], [ "▁Audio", -13.044164657592773 ], [ "▁ナイル", -13.044210433959961 ], [ "▁沈着", -13.044224739074707 ], [ "PAC", -13.04430103302002 ], [ "▁ガーニッシュ", -13.0443115234375 ], [ "▁貯める", -13.044561386108398 ], [ "▁ケミカル", -13.044563293457031 ], [ "▁コネクト", -13.044595718383789 ], [ "▁加増", -13.044706344604492 ], [ "▁サラブレッド", -13.044836044311523 ], [ "▁因縁", -13.044875144958496 ], [ "lay", -13.045013427734375 ], [ "1896", -13.045096397399902 ], [ "シンガポール", -13.045149803161621 ], [ "▁Camp", -13.045356750488281 ], [ "輌", -13.045358657836914 ], [ "茉", -13.045382499694824 ], [ "クワガタ", -13.045431137084961 ], [ "署", -13.045583724975586 ], [ "▁肥前", -13.04587173461914 ], [ "▁ふんわり", -13.045928955078125 ], [ "▁裏腹に", -13.045928955078125 ], [ "studio", -13.045931816101074 ], [ "▁マキノ", -13.045945167541504 ], [ "▁剥離", -13.045968055725098 ], [ "予算", -13.046051025390625 ], [ "UNE", -13.046119689941406 ], [ "▁和牛", -13.046167373657227 ], [ "uis", -13.046228408813477 ], [ "かといって", -13.046241760253906 ], [ "評判", -13.04631519317627 ], [ "▁ハムスター", -13.046334266662598 ], [ "増援", -13.046371459960938 ], [ "▁潜んで", -13.046460151672363 ], [ "▁レントゲン", -13.046476364135742 ], [ "▁ロペス", -13.046476364135742 ], [ "LIVE", -13.04676342010498 ], [ "▁サブタイトル", -13.047150611877441 ], [ "▁フリークス", -13.047179222106934 ], [ "▁カブス", -13.047264099121094 ], [ "▁競売", -13.047380447387695 ], [ "▁カウンティ", -13.04739761352539 ], [ "▁ウェッ", -13.047409057617188 ], [ "逃して", -13.047540664672852 ], [ "▁頑固", -13.047569274902344 ], [ "昼間", -13.047572135925293 ], [ "▁急逝", -13.047607421875 ], [ "▁ハッシュ", -13.047698020935059 ], [ "▁リモワ", -13.047843933105469 ], [ "▁ショッパー", -13.047908782958984 ], [ "本尊", -13.048059463500977 ], [ "▁弁論", -13.048165321350098 ], [ "▁治験", -13.04842472076416 ], [ "▁拾って", -13.048450469970703 ], [ "▁苦難", -13.048521995544434 ], [ "▁図案", -13.04871654510498 ], [ "小野田", -13.04874324798584 ], [ "motion", -13.048748970031738 ], [ "▁ジャッジ", -13.048891067504883 ], [ "乙", -13.048966407775879 ], [ "▁Shin", -13.049031257629395 ], [ "▁覚書", -13.049195289611816 ], [ "❤", -13.049212455749512 ], [ "▁失効", -13.049250602722168 ], [ "▁ストッキング", -13.049284934997559 ], [ "豊富な", -13.049286842346191 ], [ "▁支度", -13.049409866333008 ], [ "▁渡部", -13.049519538879395 ], [ "▁雨天", -13.049598693847656 ], [ "▁ささやか", -13.049607276916504 ], [ "▁シャーシ", -13.049668312072754 ], [ "▁弾性", -13.049683570861816 ], [ "▁ベンジャミン", -13.049760818481445 ], [ "▁不気味", -13.049760818481445 ], [ "▁過疎", -13.04976749420166 ], [ "キャッシング", -13.049918174743652 ], [ "Works", -13.049995422363281 ], [ "┣", -13.050034523010254 ], [ "洗顔", -13.05019474029541 ], [ "▁せんしゅ", -13.050261497497559 ], [ "▁ブエノスアイレス", -13.050309181213379 ], [ "▁support", -13.050310134887695 ], [ "▁挑み", -13.050312042236328 ], [ "▁意気込み", -13.05031681060791 ], [ "▁守ろう", -13.050407409667969 ], [ "▁ホープ", -13.05068302154541 ], [ "フィンランド", -13.050722122192383 ], [ "▁バタバタ", -13.050858497619629 ], [ "▁払拭", -13.050858497619629 ], [ "▁洋菓子", -13.050858497619629 ], [ "iva", -13.05087947845459 ], [ "▁(*´", -13.050909042358398 ], [ "至上", -13.051008224487305 ], [ "スカヤ", -13.051072120666504 ], [ "ディオン", -13.051115036010742 ], [ "淮", -13.051132202148438 ], [ "▁ジェイコブ", -13.051139831542969 ], [ "▁登頂", -13.051190376281738 ], [ "▁合奏", -13.051281929016113 ], [ "受付", -13.051323890686035 ], [ "¸", -13.051406860351562 ], [ "鄧", -13.051411628723145 ], [ "▁ストリップ", -13.051445960998535 ], [ "▁環礁", -13.051458358764648 ], [ "▁気遣い", -13.051682472229004 ], [ "▁絡ま", -13.051751136779785 ], [ "褒", -13.05180835723877 ], [ "射砲", -13.051855087280273 ], [ "輸入", -13.05189323425293 ], [ "▁生まれ変わり", -13.051918983459473 ], [ "▁恥ずかしく", -13.051949501037598 ], [ "勃", -13.051956176757812 ], [ "▁呼び寄せ", -13.052057266235352 ], [ "▁ワイワイ", -13.052062034606934 ], [ "すべり", -13.0520658493042 ], [ "▁ブラウ", -13.052179336547852 ], [ "▁edit", -13.05218505859375 ], [ "▁漂流", -13.052186012268066 ], [ "1897", -13.052240371704102 ], [ "▁リッチモンド", -13.052260398864746 ], [ "グラフィック", -13.052331924438477 ], [ "▁VISA", -13.052436828613281 ], [ "アリストテレス", -13.052506446838379 ], [ "▁大将軍", -13.052640914916992 ], [ "▁育む", -13.05267333984375 ], [ "ε", -13.05278205871582 ], [ "▁漱石", -13.05278205871582 ], [ "▁補聴器", -13.05278205871582 ], [ "▁譲った", -13.052802085876465 ], [ "マーケティング", -13.052886009216309 ], [ "—", -13.053056716918945 ], [ "⭐", -13.053056716918945 ], [ "親王", -13.053132057189941 ], [ "ROOM", -13.053167343139648 ], [ "カトリック", -13.053736686706543 ], [ "恐らく", -13.05374526977539 ], [ "▁ブックレット", -13.053768157958984 ], [ "▁屋久島", -13.053882598876953 ], [ "蝕", -13.053882598876953 ], [ "堪", -13.05423641204834 ], [ "▁くださ", -13.05429458618164 ], [ "要所", -13.054430961608887 ], [ "▁受動", -13.054448127746582 ], [ "▁持ち上が", -13.054654121398926 ], [ "亥", -13.054709434509277 ], [ "趙", -13.054830551147461 ], [ "▁イヤリング", -13.05521297454834 ], [ "ZEN", -13.055277824401855 ], [ "▁乾杯", -13.0552978515625 ], [ "▁否決", -13.055349349975586 ], [ "▁近況", -13.055360794067383 ], [ "ビッグ", -13.055397033691406 ], [ "臥", -13.055536270141602 ], [ "鮫", -13.055536270141602 ], [ "▁松崎", -13.056066513061523 ], [ "▁うんざり", -13.056087493896484 ], [ "半年", -13.056129455566406 ], [ "▁特務", -13.05627155303955 ], [ "売上", -13.056278228759766 ], [ "類似", -13.056288719177246 ], [ "▁セーラームーン", -13.056368827819824 ], [ "▁災い", -13.056379318237305 ], [ "▁労災", -13.056398391723633 ], [ "▁平戸", -13.05642032623291 ], [ "▁治虫", -13.05660629272461 ], [ "▁抵触", -13.056639671325684 ], [ "▁星雲", -13.056639671325684 ], [ "▁アニソン", -13.056742668151855 ], [ "懸", -13.056766510009766 ], [ "▁Spotify", -13.056916236877441 ], [ "▁女房", -13.05703067779541 ], [ "▁楽天ブックス", -13.0571928024292 ], [ "▁転機", -13.057208061218262 ], [ "▁許した", -13.057251930236816 ], [ "▁羞恥", -13.05746841430664 ], [ "OLD", -13.057519912719727 ], [ "▁アイドラッグ", -13.057519912719727 ], [ "▁美穂", -13.057611465454102 ], [ "▁受諾", -13.057767868041992 ], [ "▁老眼", -13.057771682739258 ], [ "ザクラ", -13.057887077331543 ], [ "新しく", -13.057891845703125 ], [ "1880", -13.057994842529297 ], [ "懲", -13.05802059173584 ], [ "▁乗換", -13.05811882019043 ], [ "▁歌集", -13.058199882507324 ], [ "▁ディテール", -13.058233261108398 ], [ "oke", -13.05856990814209 ], [ "▁敗走", -13.058574676513672 ], [ "▁直系", -13.058584213256836 ], [ "▁編制", -13.058670997619629 ], [ "▁ウィンド", -13.058794975280762 ], [ "▁曹洞宗", -13.05885124206543 ], [ "店頭", -13.058867454528809 ], [ "atio", -13.05896282196045 ], [ "▁ミュン", -13.059185981750488 ], [ "近畿", -13.059297561645508 ], [ "▁イメクラ", -13.059405326843262 ], [ "▁寄り添い", -13.059405326843262 ], [ "▁again", -13.059408187866211 ], [ "▁精鋭", -13.059566497802734 ], [ "View", -13.059568405151367 ], [ "▁遅かった", -13.059608459472656 ], [ "▁微妙", -13.059615135192871 ], [ "▁打球", -13.059776306152344 ], [ "▁砂利", -13.059782028198242 ], [ "▁設営", -13.05996036529541 ], [ "▁夢見て", -13.059962272644043 ], [ "▁ホワイトハウス", -13.060132026672363 ], [ "▁Face", -13.060243606567383 ], [ "▁常盤", -13.060434341430664 ], [ "▁好投", -13.060453414916992 ], [ "▁マディソン", -13.060514450073242 ], [ "▁tokyo", -13.060572624206543 ], [ "▁毛布", -13.060700416564941 ], [ "チーノ", -13.060729026794434 ], [ "▁牡蠣", -13.060791015625 ], [ "▁ヘレン", -13.060871124267578 ], [ "iu", -13.0609769821167 ], [ "▁賞与", -13.061044692993164 ], [ "▁反感", -13.061062812805176 ], [ "シルバー", -13.06112003326416 ], [ "挽", -13.0613431930542 ], [ "๑", -13.061345100402832 ], [ "▁チルドレン", -13.061345100402832 ], [ "メチル", -13.061422348022461 ], [ "▁参道", -13.06159782409668 ], [ "▁税込み", -13.061644554138184 ], [ "▁赴いた", -13.061909675598145 ], [ "▁振り込", -13.062027931213379 ], [ "コンテンツ", -13.062359809875488 ], [ "rel", -13.062397003173828 ], [ "▁安達", -13.062410354614258 ], [ "▁議題", -13.062457084655762 ], [ "▁振袖", -13.062472343444824 ], [ "▁頑張", -13.062503814697266 ], [ "„", -13.06273365020752 ], [ "▁ダメです", -13.062798500061035 ], [ "管理人", -13.062888145446777 ], [ "▁ニコル", -13.06292724609375 ], [ "▁創成", -13.063020706176758 ], [ "▁ボギー", -13.063033103942871 ], [ "▁追贈", -13.06303596496582 ], [ "▁Space", -13.063037872314453 ], [ "▁要綱", -13.063200950622559 ], [ "▁パッと", -13.06325626373291 ], [ "▁バイアグラ", -13.063289642333984 ], [ "スペース", -13.063433647155762 ], [ "▁見込んで", -13.063567161560059 ], [ "鍾", -13.063567161560059 ], [ "▁ストロング", -13.063599586486816 ], [ "▁航続", -13.063862800598145 ], [ "▁HERO", -13.063875198364258 ], [ "lite", -13.063897132873535 ], [ "ロサンゼルス", -13.064042091369629 ], [ "▁桟橋", -13.064123153686523 ], [ "▁定款", -13.064188003540039 ], [ "▁Soul", -13.064334869384766 ], [ "▁スクラップ", -13.064401626586914 ], [ "アイテム", -13.064602851867676 ], [ "▁杉浦", -13.064640045166016 ], [ "▁ファントム", -13.064663887023926 ], [ "▁想起", -13.064682006835938 ], [ "申し訳", -13.064884185791016 ], [ "▁甲信越", -13.064958572387695 ], [ "▁孵化", -13.065237045288086 ], [ "殷", -13.065237045288086 ], [ "▁限りなく", -13.065494537353516 ], [ "م", -13.065515518188477 ], [ "宅配", -13.065815925598145 ], [ "▁スペクトラ", -13.065896987915039 ], [ "▁付け根", -13.066061973571777 ], [ "じゅつ", -13.066084861755371 ], [ "iri", -13.066204071044922 ], [ "▁WWF", -13.066267013549805 ], [ "レッスン", -13.066300392150879 ], [ "▁入れ替わり", -13.066351890563965 ], [ "佐久", -13.06655216217041 ], [ "▁飛んだ", -13.066823959350586 ], [ "牝", -13.066908836364746 ], [ "▁安楽", -13.066910743713379 ], [ "▁企図", -13.06694221496582 ], [ "▁オカルト", -13.066969871520996 ], [ "▁兆し", -13.066975593566895 ], [ "▁小道具", -13.06746768951416 ], [ "▁民進党", -13.06746768951416 ], [ "▁親切に", -13.067691802978516 ], [ "▁泣か", -13.067752838134766 ], [ "▁呉服", -13.067935943603516 ], [ "セフレ", -13.06796932220459 ], [ "▁未解決", -13.068025588989258 ], [ "▁越中", -13.068188667297363 ], [ "▁暴落", -13.06838321685791 ], [ "▁絞め", -13.068581581115723 ], [ "▁アインシュタイン", -13.068584442138672 ], [ "▁ほしく", -13.068695068359375 ], [ "▁必死", -13.068708419799805 ], [ "▁読み書き", -13.06883716583252 ], [ "▁丁寧で", -13.068915367126465 ], [ "▁泳ぐ", -13.068942070007324 ], [ "▁ともなう", -13.069143295288086 ], [ "▁信憑性", -13.069143295288086 ], [ "▁捕え", -13.069236755371094 ], [ "▁離反", -13.069253921508789 ], [ "▁似顔絵", -13.06942367553711 ], [ "verse", -13.069558143615723 ], [ "▁ブーケ", -13.06958293914795 ], [ "▁マルティン", -13.069674491882324 ], [ "▁リーズナブル", -13.069738388061523 ], [ "▁昼夜", -13.069828987121582 ], [ "▁韓流", -13.069897651672363 ], [ "▁プラットホーム", -13.069982528686523 ], [ "連絡", -13.070013999938965 ], [ "▁閉校", -13.070101737976074 ], [ "PRESS", -13.070120811462402 ], [ "▁リコール", -13.070137977600098 ], [ "ANK", -13.070144653320312 ], [ "▁NCS", -13.070204734802246 ], [ "▁Cyber", -13.070266723632812 ], [ "tribut", -13.07030963897705 ], [ "漕", -13.070542335510254 ], [ "ホーフ", -13.070600509643555 ], [ "▁決ま", -13.07071304321289 ], [ "▁真っ直ぐ", -13.070822715759277 ], [ "▁United", -13.070830345153809 ], [ "▁夕日", -13.070952415466309 ], [ "▁吐く", -13.071112632751465 ], [ "▁乳製品", -13.071170806884766 ], [ "▁あぶ", -13.071224212646484 ], [ "▁折々", -13.071603775024414 ], [ "▁スペンサー", -13.071662902832031 ], [ "▁伸長", -13.071695327758789 ], [ "要職", -13.07170295715332 ], [ "▁ブレイブ", -13.071775436401367 ], [ "▁成り立", -13.071942329406738 ], [ "▁長州藩", -13.071943283081055 ], [ "まもなく", -13.072210311889648 ], [ "KAI", -13.072257041931152 ], [ "呆", -13.072266578674316 ], [ "▁バッチ", -13.07227897644043 ], [ "▁GNU", -13.072328567504883 ], [ "▁損ね", -13.072339057922363 ], [ "kawa", -13.072410583496094 ], [ "▁サンライズ", -13.072495460510254 ], [ "鸞", -13.072504997253418 ], [ "ヒョウ", -13.072518348693848 ], [ "∇", -13.072784423828125 ], [ "▁プラセンタ", -13.072785377502441 ], [ "▁闘う", -13.073050498962402 ], [ "▁久喜", -13.07308292388916 ], [ "いなる", -13.073123931884766 ], [ "▁Last", -13.073153495788574 ], [ "▁茶会", -13.073348999023438 ], [ "▁稲垣", -13.073468208312988 ], [ "▁チワワ", -13.074189186096191 ], [ "▁叫んで", -13.074190139770508 ], [ "▁侍従", -13.074240684509277 ], [ "▁素敵です", -13.074297904968262 ], [ "▁UNIX", -13.074393272399902 ], [ "▁Virtual", -13.074470520019531 ], [ "▁呈する", -13.074470520019531 ], [ "妾", -13.074470520019531 ], [ "▁断続", -13.074540138244629 ], [ "▁電器", -13.074563980102539 ], [ "▁奪回", -13.074564933776855 ], [ "▁さらけ", -13.074660301208496 ], [ "▁皐月", -13.074751853942871 ], [ "敷金", -13.074814796447754 ], [ "kit", -13.0748291015625 ], [ "▁ファイアー", -13.074956893920898 ], [ "▁食肉", -13.07502269744873 ], [ "▁広まっ", -13.075045585632324 ], [ "▁飯島", -13.075091361999512 ], [ "絞", -13.07517147064209 ], [ "▁シクロ", -13.075200080871582 ], [ "▁ロドリゲス", -13.075313568115234 ], [ "▁鮮明に", -13.07534408569336 ], [ "▁ダーツ", -13.075349807739258 ], [ "日暮里", -13.075361251831055 ], [ "▁シュミット", -13.075432777404785 ], [ "▁たたき", -13.07553768157959 ], [ "USB", -13.07556438446045 ], [ "▁デベロッパー", -13.075594902038574 ], [ "▁ミュウミュウ", -13.075594902038574 ], [ "誅", -13.075594902038574 ], [ "クチン", -13.075620651245117 ], [ "▁仕込み", -13.075641632080078 ], [ "iwa", -13.07579517364502 ], [ "850", -13.07588005065918 ], [ "chem", -13.075949668884277 ], [ "ひゃく", -13.075970649719238 ], [ "▁カンナビノイド", -13.07615852355957 ], [ "雌", -13.076176643371582 ], [ "傾", -13.076301574707031 ], [ "▁ヒカル", -13.076315879821777 ], [ "▁保養", -13.076363563537598 ], [ "▁ジャンパー", -13.076407432556152 ], [ "▁誇った", -13.07658863067627 ], [ "▁トリニティ", -13.077019691467285 ], [ "▁唐揚げ", -13.077042579650879 ], [ "本営", -13.077187538146973 ], [ "▁矢先", -13.07719612121582 ], [ "閲", -13.077260971069336 ], [ "▁浪費", -13.077332496643066 ], [ "pla", -13.077448844909668 ], [ "1899", -13.077458381652832 ], [ "▁アライアンス", -13.077567100524902 ], [ "址", -13.077567100524902 ], [ "▁Girl", -13.077840805053711 ], [ "ソビエト", -13.078165054321289 ], [ "自民党", -13.078165054321289 ], [ "▁贈答", -13.078426361083984 ], [ "▁生還", -13.078682899475098 ], [ "蚕", -13.07868480682373 ], [ "曙", -13.078695297241211 ], [ "▁油脂", -13.078764915466309 ], [ "彷", -13.07897663116455 ], [ "▁遭う", -13.078977584838867 ], [ "blog", -13.079069137573242 ], [ "▁コンシェルジュ", -13.07926082611084 ], [ "▁トンプソン", -13.07926082611084 ], [ "▁モンテネグロ", -13.07926082611084 ], [ "▁満塁", -13.079354286193848 ], [ "およそ", -13.079490661621094 ], [ "▁PCMAX", -13.079676628112793 ], [ "▁不向き", -13.079747200012207 ], [ "▁カツオ", -13.080307960510254 ], [ "▁っぷり", -13.080403327941895 ], [ "▁交感神経", -13.080673217773438 ], [ "▁三十三", -13.080709457397461 ], [ "少女", -13.080738067626953 ], [ "▁リサイタル", -13.08095645904541 ], [ "▁パウンド", -13.080957412719727 ], [ "▁JFL", -13.081225395202637 ], [ "▁鳴らす", -13.081311225891113 ], [ "hem", -13.081321716308594 ], [ "▁追随", -13.081588745117188 ], [ "▁マスキング", -13.081639289855957 ], [ "▁DNS", -13.081729888916016 ], [ "£", -13.081805229187012 ], [ "▁ドッキング", -13.081900596618652 ], [ "OUT", -13.082037925720215 ], [ "▁ドナウ", -13.082075119018555 ], [ "▁ラバウル", -13.082088470458984 ], [ "▁深度", -13.082146644592285 ], [ "クラシック", -13.082300186157227 ], [ "▁身延", -13.082342147827148 ], [ "rich", -13.082344055175781 ], [ "酌", -13.082372665405273 ], [ "▁窮地", -13.08237361907959 ], [ "▁百選", -13.082404136657715 ], [ "▁中日ドラゴンズ", -13.082655906677246 ], [ "▁板垣", -13.082663536071777 ], [ "9,000", -13.082695007324219 ], [ "▁オッズ", -13.082754135131836 ], [ "▁挿し", -13.082829475402832 ], [ "bat", -13.082883834838867 ], [ "▁クルーザー", -13.0828857421875 ], [ "皇后", -13.083016395568848 ], [ "▁精査", -13.083025932312012 ], [ "なのに", -13.083270072937012 ], [ "▁騎馬", -13.083337783813477 ], [ "晴らし", -13.083490371704102 ], [ "▁プリペイド", -13.083505630493164 ], [ "エネルギー", -13.083582878112793 ], [ "▁おさえ", -13.083585739135742 ], [ "▁無休", -13.083634376525879 ], [ "▁ガリシア", -13.083656311035156 ], [ "Unicode", -13.083658218383789 ], [ "▁聞き入れ", -13.08366584777832 ], [ "▁みやげ", -13.083674430847168 ], [ "▁Snow", -13.083765983581543 ], [ "▁せいぜい", -13.083789825439453 ], [ "グレード", -13.08391284942627 ], [ "▁Services", -13.083932876586914 ], [ "▁瑕疵", -13.084074020385742 ], [ "▁守れ", -13.08411979675293 ], [ "▁銃器", -13.084195137023926 ], [ "▁日産自動車", -13.084385871887207 ], [ "▁Arch", -13.0845947265625 ], [ "▁拍車", -13.08464241027832 ], [ "レストラン", -13.084856986999512 ], [ "▁1,100", -13.084931373596191 ], [ "▁疑念", -13.08497428894043 ], [ "force", -13.085034370422363 ], [ "▁降雨", -13.085039138793945 ], [ "▁壊す", -13.08514404296875 ], [ "▁賛美", -13.085211753845215 ], [ "▁郷里", -13.085222244262695 ], [ "宝塚", -13.085301399230957 ], [ "サウンド", -13.085302352905273 ], [ "たまたま", -13.085320472717285 ], [ "▁発声", -13.08534049987793 ], [ "▁ガルシア", -13.085803031921387 ], [ "震災", -13.085922241210938 ], [ "偲", -13.08606243133545 ], [ "▁ヴァレン", -13.086074829101562 ], [ "▁ハウジング", -13.086101531982422 ], [ "▁アルツハイマー", -13.086346626281738 ], [ "▁助長", -13.086386680603027 ], [ "▁イージー", -13.086458206176758 ], [ "ウェスト", -13.08651065826416 ], [ "▁近づいた", -13.08715534210205 ], [ "アレクサンドリア", -13.087485313415527 ], [ "▁取り掛か", -13.087713241577148 ], [ "▁インテリジェント", -13.087769508361816 ], [ "ATO", -13.087841033935547 ], [ "▁爽やか", -13.087843894958496 ], [ "▁密閉", -13.087850570678711 ], [ "壬", -13.088053703308105 ], [ "▁チュートリアル", -13.088054656982422 ], [ "窩", -13.088054656982422 ], [ "▁design", -13.088075637817383 ], [ "筋肉", -13.08808708190918 ], [ "▁膀胱", -13.088339805603027 ], [ "長生き", -13.088519096374512 ], [ "▁寝屋川", -13.088624954223633 ], [ "▁段ボール", -13.088652610778809 ], [ "意味", -13.08871078491211 ], [ "ウォーター", -13.088841438293457 ], [ "▁color", -13.088871955871582 ], [ "▁加圧", -13.088948249816895 ], [ "▁スルタン", -13.089070320129395 ], [ "▁カージナルス", -13.089195251464844 ], [ "▁空爆", -13.08923625946045 ], [ "不慮", -13.089322090148926 ], [ "▁よしもと", -13.089325904846191 ], [ "▁自決", -13.089447021484375 ], [ "▁応対", -13.089911460876465 ], [ "▁処方箋", -13.09006118774414 ], [ "`*)", -13.090073585510254 ], [ "謹", -13.09033489227295 ], [ "▁入れ歯", -13.090335845947266 ], [ "引越", -13.0904541015625 ], [ "REE", -13.090532302856445 ], [ "▁連打", -13.090666770935059 ], [ "▁スマッシュ", -13.090740203857422 ], [ "架線", -13.090786933898926 ], [ "気象", -13.090828895568848 ], [ "▁読めば", -13.09084701538086 ], [ "メモリ", -13.090922355651855 ], [ "▁稼いだ", -13.090935707092285 ], [ "▁別個", -13.091132164001465 ], [ "▁献金", -13.091153144836426 ], [ "▁河岸", -13.091198921203613 ], [ "▁ドレスデン", -13.091264724731445 ], [ "▁割り切り", -13.091292381286621 ], [ "佐々木", -13.091336250305176 ], [ "▁洗濯物", -13.091442108154297 ], [ "▁乱入", -13.091453552246094 ], [ "▁コピペ", -13.091480255126953 ], [ "▁鯖江", -13.09148120880127 ], [ "オプション", -13.091623306274414 ], [ "▁進駐", -13.091784477233887 ], [ "▁申し付け", -13.091800689697266 ], [ "▁和装", -13.091825485229492 ], [ "オイル", -13.091845512390137 ], [ "▁カエサル", -13.09205150604248 ], [ "▁抗酸化", -13.09205150604248 ], [ "▁頑張ろう", -13.092106819152832 ], [ "土曜日", -13.092201232910156 ], [ "▁Asia", -13.092286109924316 ], [ "陥", -13.092411994934082 ], [ "体調", -13.092706680297852 ], [ "▁銃身", -13.09278678894043 ], [ "苦労", -13.09280014038086 ], [ "留学", -13.092901229858398 ], [ "▁ソプラノ", -13.092910766601562 ], [ "▁盗賊", -13.092936515808105 ], [ "▁落葉", -13.093015670776367 ], [ "▁打ち出した", -13.093165397644043 ], [ "ival", -13.093210220336914 ], [ "▁正恩", -13.093232154846191 ], [ "▁ポリマー", -13.093280792236328 ], [ "▁病変", -13.093335151672363 ], [ "▁平民", -13.09338092803955 ], [ "▁飢餓", -13.093482971191406 ], [ "▁キツネ", -13.093484878540039 ], [ "▁推挙", -13.09351634979248 ], [ "▁崇敬", -13.093517303466797 ], [ "畝", -13.093770027160645 ], [ "▁肝心の", -13.094056129455566 ], [ "▁赤ん坊", -13.094056129455566 ], [ "▁Tool", -13.094098091125488 ], [ "▁定格", -13.094124794006348 ], [ "▁立て直し", -13.09414291381836 ], [ "▁沈む", -13.094267845153809 ], [ "ISO", -13.0942964553833 ], [ "▁Road", -13.094331741333008 ], [ "▁ぎん", -13.094407081604004 ], [ "▁プラネット", -13.094658851623535 ], [ "ür", -13.094847679138184 ], [ "▁併せ", -13.094888687133789 ], [ "▁予知", -13.094921112060547 ], [ "pre", -13.094926834106445 ], [ "▁聖歌", -13.094934463500977 ], [ "berry", -13.095130920410156 ], [ "▁枯渇", -13.095203399658203 ], [ "▁生まれ育った", -13.095203399658203 ], [ "▁オーラル", -13.09521198272705 ], [ "▁取り替え", -13.095293998718262 ], [ "▁縁組", -13.095338821411133 ], [ "ello", -13.095362663269043 ], [ "乏", -13.095479011535645 ], [ "▁ウレタン", -13.095490455627441 ], [ "▁こたつ", -13.09549331665039 ], [ "▁放牧", -13.095588684082031 ], [ "´∀`", -13.095707893371582 ], [ "▁York", -13.095783233642578 ], [ "▁ファイヤー", -13.095800399780273 ], [ "RIN", -13.096014022827148 ], [ "▁結論付け", -13.096028327941895 ], [ "▁暮らせる", -13.096065521240234 ], [ "▁改易", -13.096126556396484 ], [ "疾", -13.096351623535156 ], [ "Sourc", -13.09653377532959 ], [ "▁特選", -13.0966157913208 ], [ "▁送れる", -13.096824645996094 ], [ "▁取り除き", -13.096927642822266 ], [ "▁グラハム", -13.097023010253906 ], [ "可愛い", -13.09711742401123 ], [ "▁草加", -13.097146987915039 ], [ "スタイル", -13.097171783447266 ], [ "▁トロンボーン", -13.097214698791504 ], [ "嗜", -13.097214698791504 ], [ "退き", -13.097421646118164 ], [ "▁博文", -13.097480773925781 ], [ "▁PARCO", -13.097790718078613 ], [ "寅", -13.097989082336426 ], [ "▁菊花", -13.098189353942871 ], [ "▁RAW", -13.098241806030273 ], [ "▁コンパイラ", -13.098368644714355 ], [ "▁お参り", -13.098374366760254 ], [ "▁デンバー", -13.098465919494629 ], [ "▁声援", -13.098748207092285 ], [ "▁沈んで", -13.098857879638672 ], [ "プレミアム", -13.098857879638672 ], [ "▁御家人", -13.098942756652832 ], [ "▁筑豊", -13.098942756652832 ], [ "▁於ける", -13.098984718322754 ], [ "▁中津川", -13.09924030303955 ], [ "▁Movie", -13.099258422851562 ], [ "▁水俣", -13.099685668945312 ], [ "▁差額", -13.09971809387207 ], [ "▁落とし穴", -13.099858283996582 ], [ "▁ハワイアン", -13.099881172180176 ], [ "暉", -13.10009479522705 ], [ "▁腹痛", -13.100220680236816 ], [ "▁関門", -13.100531578063965 ], [ "▁効き目", -13.10074234008789 ], [ "蕃", -13.100959777832031 ], [ "▁しんどい", -13.100995063781738 ], [ "▁磨いて", -13.101123809814453 ], [ "▁摂食", -13.10119342803955 ], [ "▁脚色", -13.101197242736816 ], [ "▁みずから", -13.101303100585938 ], [ "▁スパイラル", -13.101675987243652 ], [ "難しい", -13.101788520812988 ], [ "NTT", -13.102203369140625 ], [ "▁寄席", -13.102229118347168 ], [ "▁ランドセル", -13.102276802062988 ], [ "▁インバータ", -13.102310180664062 ], [ "▁直進", -13.102322578430176 ], [ "▁落城", -13.102322578430176 ], [ "寇", -13.10240364074707 ], [ "▁北魏", -13.102437973022461 ], [ "nik", -13.10268783569336 ], [ "反応", -13.102733612060547 ], [ "▁切腹", -13.102860450744629 ], [ "▁福建", -13.102949142456055 ], [ "▁被疑者", -13.102982521057129 ], [ "▁亜目", -13.103006362915039 ], [ "▁錦糸", -13.103068351745605 ], [ "▁クエリ", -13.103069305419922 ], [ "▁試着", -13.1032075881958 ], [ "紳", -13.103269577026367 ], [ "▁コンベンション", -13.103271484375 ], [ "▁相次ぐ", -13.103271484375 ], [ "▁酪農", -13.103271484375 ], [ "配送", -13.10339069366455 ], [ "ized", -13.10340404510498 ], [ "park", -13.103509902954102 ], [ "▁被験者", -13.103561401367188 ], [ "▁見なす", -13.103592872619629 ], [ "uh", -13.103608131408691 ], [ "サンシア", -13.103631019592285 ], [ "▁まつ毛", -13.103816032409668 ], [ "▁ウィスコンシ", -13.103850364685059 ], [ "▁レフェリー", -13.103850364685059 ], [ "▁オリエンタル", -13.104140281677246 ], [ "▁引き締ま", -13.104143142700195 ], [ "固定", -13.104209899902344 ], [ "▁裂け", -13.104288101196289 ], [ "アマチュア", -13.104391098022461 ], [ "▁札所", -13.104405403137207 ], [ "▁ラベンダー", -13.104430198669434 ], [ "▁祝賀", -13.10444164276123 ], [ "▁巡査", -13.10448932647705 ], [ "▁TEE", -13.10453987121582 ], [ "青年", -13.104562759399414 ], [ "▁リテラ", -13.10484790802002 ], [ "捜", -13.104955673217773 ], [ "м", -13.105008125305176 ], [ "▁アクシデント", -13.105009078979492 ], [ "▁高千穂", -13.105009078979492 ], [ "躯", -13.105009078979492 ], [ "▁帳簿", -13.105016708374023 ], [ "錆", -13.105290412902832 ], [ "▁ケンコー", -13.105292320251465 ], [ "▁模試", -13.10529899597168 ], [ "▁立ち寄った", -13.105299949645996 ], [ "▁ジョルジュ", -13.105345726013184 ], [ "全曲", -13.105488777160645 ], [ "ポルトガル", -13.105559349060059 ], [ "▁好ましい", -13.105850219726562 ], [ "Europe", -13.106175422668457 ], [ "▁覚まし", -13.106293678283691 ], [ "▁さとみ", -13.106411933898926 ], [ "訪問", -13.106459617614746 ], [ "商科", -13.106544494628906 ], [ "▁パウル", -13.106654167175293 ], [ "来週", -13.10665512084961 ], [ "オーネ", -13.10672378540039 ], [ "淳", -13.106730461120605 ], [ "締", -13.106794357299805 ], [ "職業", -13.106889724731445 ], [ "▁ノズル", -13.10690975189209 ], [ "普", -13.10692024230957 ], [ "MAS", -13.10693359375 ], [ "mine", -13.10697078704834 ], [ "日曜日", -13.107022285461426 ], [ "▁function", -13.107040405273438 ], [ "▁ジャーナリズム", -13.107040405273438 ], [ "▁続投", -13.107099533081055 ], [ "険", -13.107230186462402 ], [ "▁叩か", -13.107331275939941 ], [ "▁おろか", -13.107401847839355 ], [ "幼稚園", -13.1076078414917 ], [ "▁ぶつかり", -13.107621192932129 ], [ "▁恵那", -13.107743263244629 ], [ "▁Health", -13.107911109924316 ], [ "▁passwor", -13.107915878295898 ], [ "▁ジェネレータ", -13.108149528503418 ], [ "忘", -13.108431816101074 ], [ "▁榎本", -13.108495712280273 ], [ "▁チューリッヒ", -13.108502388000488 ], [ "▁試写", -13.108537673950195 ], [ "pad", -13.108650207519531 ], [ "▁秀忠", -13.108753204345703 ], [ "▁交わす", -13.108915328979492 ], [ "▁込もう", -13.109137535095215 ], [ "卜", -13.109365463256836 ], [ "▁比企", -13.10937213897705 ], [ "▁加重", -13.109405517578125 ], [ "880", -13.109665870666504 ], [ "▁執った", -13.109901428222656 ], [ "▁故事", -13.110318183898926 ], [ "報告", -13.110396385192871 ], [ "▁対向", -13.110522270202637 ], [ "▁チュニジア", -13.110530853271484 ], [ "▁テイルズ", -13.110845565795898 ], [ "▁高野山", -13.110933303833008 ], [ "▁釣れ", -13.110990524291992 ], [ "取水", -13.111083984375 ], [ "Ζ", -13.111113548278809 ], [ "呼吸", -13.111137390136719 ], [ "▁振った", -13.111254692077637 ], [ "LEX", -13.111260414123535 ], [ "▁JAM", -13.111263275146484 ], [ "▁居室", -13.11128044128418 ], [ "EACH", -13.111374855041504 ], [ "▁併記", -13.111562728881836 ], [ "▁イヴァン", -13.111661911010742 ], [ "▁弾劾", -13.111991882324219 ], [ "oki", -13.11209487915039 ], [ "▁ジョシュ", -13.11221694946289 ], [ "▁擬似", -13.11228084564209 ], [ "▁winter", -13.112281799316406 ], [ "▁踏んだ", -13.112313270568848 ], [ "▁デコレーション", -13.112322807312012 ], [ "▁Model", -13.112434387207031 ], [ "▁渤海", -13.11257266998291 ], [ "▁外構", -13.113130569458008 ], [ "▁飛び降り", -13.113157272338867 ], [ "▁貯まる", -13.113212585449219 ], [ "▁唐辛子", -13.113449096679688 ], [ "▁応力", -13.113519668579102 ], [ "▁急速", -13.113727569580078 ], [ "List", -13.11373519897461 ], [ "クウェート", -13.113743782043457 ], [ "妖", -13.11407470703125 ], [ "▁劣勢", -13.11415958404541 ], [ "コーポレーション", -13.11436939239502 ], [ "▁バッファ", -13.114459991455078 ], [ "▁好転", -13.114497184753418 ], [ "ちょっとした", -13.114521980285645 ], [ "▁変調", -13.1145658493042 ], [ "▁CHANNEL", -13.114912033081055 ], [ "▁ケビン", -13.114968299865723 ], [ "▁チート", -13.115082740783691 ], [ "▁彩色", -13.11508560180664 ], [ "蔽", -13.115194320678711 ], [ "▁癒や", -13.115256309509277 ], [ "▁花序", -13.115375518798828 ], [ "▁マーキュリー", -13.115497589111328 ], [ "▁浮いて", -13.115630149841309 ], [ "藁", -13.115790367126465 ], [ "▁随一", -13.11579704284668 ], [ "▁ピストル", -13.115802764892578 ], [ "▁安佐", -13.116036415100098 ], [ "▁座談", -13.116079330444336 ], [ "▁ブランデンブルク", -13.116083145141602 ], [ "▁須磨", -13.116114616394043 ], [ "▁Walk", -13.1163330078125 ], [ "▁技量", -13.116351127624512 ], [ "▁屏風", -13.116375923156738 ], [ "▁確執", -13.116375923156738 ], [ "mart", -13.116461753845215 ], [ "▁モーメント", -13.116933822631836 ], [ "▁染料", -13.116998672485352 ], [ "▁必死で", -13.117042541503906 ], [ "▁恩師", -13.117084503173828 ], [ "厭", -13.117256164550781 ], [ "▁参政", -13.117365837097168 ], [ "▁脱いで", -13.117453575134277 ], [ "▁幽閉", -13.117570877075195 ], [ "▁音符", -13.11772632598877 ], [ "▁アントワー", -13.117851257324219 ], [ "▁カーソル", -13.117851257324219 ], [ "ッツェ", -13.11793327331543 ], [ "▁細身", -13.117997169494629 ], [ "涌", -13.118136405944824 ], [ "▁切ない", -13.118206977844238 ], [ "▁スラング", -13.118280410766602 ], [ "▁浸か", -13.11851692199707 ], [ "▁がちに", -13.11857795715332 ], [ "oda", -13.11868953704834 ], [ "▁凶悪", -13.118724822998047 ], [ "▽", -13.118803024291992 ], [ "▁div", -13.118828773498535 ], [ "▁NTR", -13.118898391723633 ], [ "▁岡部", -13.1189546585083 ], [ "¯", -13.119017601013184 ], [ "▁向こう側", -13.119044303894043 ], [ "▁Make", -13.11916732788086 ], [ "▁謙信", -13.119171142578125 ], [ ",000,000", -13.119308471679688 ], [ "キホーテ", -13.119312286376953 ], [ "▁突っ込んで", -13.119528770446777 ], [ "▁蒲郡", -13.119606971740723 ], [ "シズム", -13.11962890625 ], [ "1895", -13.119723320007324 ], [ "▁敬老", -13.119733810424805 ], [ "▁手渡し", -13.119877815246582 ], [ "▁議定書", -13.11989974975586 ], [ "▁Victor", -13.12024211883545 ], [ "▁取り締まり", -13.120268821716309 ], [ "枚", -13.120284080505371 ], [ "▁いつしか", -13.12031078338623 ], [ "▁デフレ", -13.120360374450684 ], [ "▁instagram", -13.120488166809082 ], [ "▁悪質", -13.120601654052734 ], [ "▁ほんとうに", -13.120782852172852 ], [ "▁オマージュ", -13.120782852172852 ], [ "▁トライアングル", -13.120782852172852 ], [ "▁行き詰ま", -13.120792388916016 ], [ "iber", -13.120890617370605 ], [ "▁ランジェリー", -13.121082305908203 ], [ "ぎょ", -13.121089935302734 ], [ "▁泣いた", -13.121129035949707 ], [ "▁取ろう", -13.121559143066406 ], [ "辣", -13.12166690826416 ], [ "▁ロープウェイ", -13.121755599975586 ], [ "▁降雪", -13.121774673461914 ], [ "▁リアクション", -13.121800422668457 ], [ "▁言い伝え", -13.121962547302246 ], [ "▁陳情", -13.122138023376465 ], [ "¡", -13.1222562789917 ], [ "▁マドンナ", -13.1222562789917 ], [ "▁間に合", -13.122488975524902 ], [ "掟", -13.122550964355469 ], [ "▁落書き", -13.122659683227539 ], [ "▁懸命に", -13.122845649719238 ], [ "▁幻覚", -13.122950553894043 ], [ "▁Film", -13.123043060302734 ], [ "▁スタント", -13.123051643371582 ], [ "▁リポジトリ", -13.123141288757324 ], [ "ウァ", -13.123188018798828 ], [ "▁皇居", -13.123279571533203 ], [ "▁早起き", -13.123435974121094 ], [ "▁ボカロ", -13.12343978881836 ], [ "▁商務", -13.123554229736328 ], [ "冬期", -13.123822212219238 ], [ "án", -13.123825073242188 ], [ "胃", -13.123851776123047 ], [ "仲間", -13.1239652633667 ], [ "oca", -13.124109268188477 ], [ "▁イチロー", -13.124218940734863 ], [ "枕", -13.12443733215332 ], [ "▁デイトナ", -13.124619483947754 ], [ "パスワード", -13.124811172485352 ], [ "▁武漢", -13.124927520751953 ], [ "▁振り返った", -13.124940872192383 ], [ "ヘイト", -13.124954223632812 ], [ "▁ランドマーク", -13.124959945678711 ], [ "▁振り付け", -13.125349998474121 ], [ "▁原付", -13.12541389465332 ], [ "麓", -13.125428199768066 ], [ "❗", -13.125504493713379 ], [ "諫", -13.125504493713379 ], [ "鱗", -13.125641822814941 ], [ "状況", -13.12578296661377 ], [ "▁牽制", -13.125800132751465 ], [ "侮", -13.125800132751465 ], [ "space", -13.125986099243164 ], [ "▁停め", -13.126082420349121 ], [ "奔", -13.126093864440918 ], [ "▁伽藍", -13.126096725463867 ], [ "榮", -13.126096725463867 ], [ "▁ミッドフィールダー", -13.126392364501953 ], [ "▁傲慢", -13.126392364501953 ], [ "▁サイパン", -13.126542091369629 ], [ "▁至福", -13.126786231994629 ], [ "▁ウィザード", -13.126843452453613 ], [ "▁オークリー", -13.126862525939941 ], [ "▁払い戻し", -13.126985549926758 ], [ "▁ぐるぐる", -13.127281188964844 ], [ "▁捻出", -13.127283096313477 ], [ "▁茶碗", -13.127297401428223 ], [ "▁干支", -13.127324104309082 ], [ "▁弦楽器", -13.127346992492676 ], [ "アルプス", -13.127381324768066 ], [ "▁true", -13.127684593200684 ], [ "操作", -13.12790584564209 ], [ "▁葉っぱ", -13.127923965454102 ], [ "▁納言", -13.1279935836792 ], [ "▁ウインドウ", -13.128016471862793 ], [ "脅", -13.128165245056152 ], [ "聚", -13.12817096710205 ], [ "形式", -13.128182411193848 ], [ "▁アンゴラ", -13.128186225891113 ], [ "ヶ浜", -13.128305435180664 ], [ "▁エディンバラ", -13.128467559814453 ], [ "▁見捨て", -13.12846851348877 ], [ "Metacritic", -13.128764152526855 ], [ "▁Friend", -13.128764152526855 ], [ "▁ドーピング", -13.128808975219727 ], [ "▁琴平", -13.12883472442627 ], [ "▁久美子", -13.128836631774902 ], [ "▁リバティ", -13.128878593444824 ], [ "▁セグンダ", -13.129060745239258 ], [ "▁who", -13.129172325134277 ], [ "掲", -13.12934398651123 ], [ "▁エメラルド", -13.12935733795166 ], [ "▁儒学", -13.129358291625977 ], [ "錐", -13.129430770874023 ], [ "▁鬼灯", -13.12944507598877 ], [ "▁presents", -13.129523277282715 ], [ "消防", -13.12957763671875 ], [ "▁昇華", -13.12961196899414 ], [ "cell", -13.129629135131836 ], [ "▁ひっそり", -13.129654884338379 ], [ "▁Championship", -13.129655838012695 ], [ "ッチョ", -13.129666328430176 ], [ "▁降ろし", -13.129705429077148 ], [ "▁ナンバーワン", -13.12993335723877 ], [ "▁請け", -13.129997253417969 ], [ "▁キャラバン", -13.130009651184082 ], [ "▁スタミナ", -13.130011558532715 ], [ "地下鉄", -13.130155563354492 ], [ "▁ハノイ", -13.130169868469238 ], [ "▁葡萄", -13.1302490234375 ], [ "LIGHT", -13.130263328552246 ], [ "▁GATE", -13.130465507507324 ], [ "▁ヤバイ", -13.13049030303955 ], [ "▁折りたたむ", -13.130546569824219 ], [ "▁飛翔", -13.130572319030762 ], [ "▁顔料", -13.13057804107666 ], [ "▁逃す", -13.130821228027344 ], [ "Time", -13.13087272644043 ], [ "取引", -13.131308555603027 ], [ "▁観衆", -13.131361961364746 ], [ "About", -13.131607055664062 ], [ "▁プラトン", -13.13170051574707 ], [ "▁謀反", -13.131736755371094 ], [ "ビョ", -13.131970405578613 ], [ "▁リペア", -13.132002830505371 ], [ "▁クライスラー", -13.132034301757812 ], [ "マインドフルネス", -13.132034301757812 ], [ "▁理容", -13.132158279418945 ], [ "▁キャラメル", -13.13228988647461 ], [ "▁篠山", -13.132591247558594 ], [ "郊", -13.13260555267334 ], [ "▁ミディアム", -13.13262939453125 ], [ "▁争点", -13.132692337036133 ], [ "▁除名", -13.132820129394531 ], [ "▁Platform", -13.132927894592285 ], [ "▁うれしかった", -13.132927894592285 ], [ "▁スイミング", -13.132964134216309 ], [ "プロモーション", -13.133125305175781 ], [ "Build", -13.1332426071167 ], [ "▁投降", -13.133306503295898 ], [ "ellow", -13.133355140686035 ], [ "貯", -13.133382797241211 ], [ "▁鮮度", -13.133524894714355 ], [ "▁クエン酸", -13.133822441101074 ], [ "劫", -13.133822441101074 ], [ "狸", -13.133822441101074 ], [ "▁ミハイル", -13.134119987487793 ], [ "▁浙江", -13.134119987487793 ], [ "▁香辛料", -13.134119987487793 ], [ "▁たどる", -13.134122848510742 ], [ "▁カシオ", -13.13416576385498 ], [ "疱", -13.134418487548828 ], [ "ヴィット", -13.1344633102417 ], [ "▁エイター", -13.134692192077637 ], [ "▁パンタグラフ", -13.134716987609863 ], [ "▁ダウンベスト", -13.134817123413086 ], [ "▁ソリッド", -13.135085105895996 ], [ "未経験", -13.135258674621582 ], [ "▁Final", -13.135401725769043 ], [ "▁スチュワート", -13.13591194152832 ], [ "▁合祀", -13.135939598083496 ], [ "開始", -13.135940551757812 ], [ "OKI", -13.13613224029541 ], [ "▁交野", -13.136157035827637 ], [ "復古", -13.136186599731445 ], [ "▁浮き彫り", -13.136211395263672 ], [ "顧", -13.13643741607666 ], [ "▁ゆうちょ", -13.136480331420898 ], [ "▁開墾", -13.136518478393555 ], [ "▁open", -13.13652515411377 ], [ "交換", -13.136544227600098 ], [ "▁ロマンティック", -13.136585235595703 ], [ "▁義昭", -13.136768341064453 ], [ "▁Album", -13.136809349060059 ], [ "▁絨毯", -13.136809349060059 ], [ "▁引きずり", -13.136810302734375 ], [ "▁TYPE", -13.136811256408691 ], [ "▁侵食", -13.13692569732666 ], [ "▁印字", -13.13693618774414 ], [ "iOS", -13.137396812438965 ], [ "▁ワーグナー", -13.137408256530762 ], [ "▁雨漏り", -13.137408256530762 ], [ "璃", -13.137408256530762 ], [ "▁天台宗", -13.138007164001465 ], [ "▁泳いで", -13.138025283813477 ], [ "▁即効", -13.13806438446045 ], [ "▁joi", -13.138110160827637 ], [ "ault", -13.138184547424316 ], [ "▁歓声", -13.138365745544434 ], [ "▁重なった", -13.13843822479248 ], [ "▁Earth", -13.138607025146484 ], [ "講演", -13.138676643371582 ], [ "▁キャッシュレス", -13.13869571685791 ], [ "再生", -13.138720512390137 ], [ "▁清涼", -13.138768196105957 ], [ "▁変則", -13.138901710510254 ], [ "▁伺う", -13.138908386230469 ], [ "▁衣裳", -13.138909339904785 ], [ "與", -13.139205932617188 ], [ "滞", -13.13941764831543 ], [ "▁浴槽", -13.139518737792969 ], [ "楠", -13.13973331451416 ], [ "▁叢書", -13.139806747436523 ], [ "自在に", -13.140032768249512 ], [ "エジプト", -13.140061378479004 ], [ "遊び", -13.140376091003418 ], [ "ú", -13.140405654907227 ], [ "▁トランジスタ", -13.140406608581543 ], [ "▁ショパン", -13.140567779541016 ], [ "▁発起人", -13.140706062316895 ], [ "▁スロープ", -13.140759468078613 ], [ "ゆっくり", -13.140765190124512 ], [ "▁引き揚げ", -13.140841484069824 ], [ "▁ステキな", -13.141008377075195 ], [ "▁難解", -13.141075134277344 ], [ "▁防いで", -13.141151428222656 ], [ "退職", -13.141165733337402 ], [ "▁時計回り", -13.141277313232422 ], [ "▁サハラ", -13.1412992477417 ], [ "▁きめ細か", -13.14130687713623 ], [ "▁ハーモニカ", -13.14130687713623 ], [ "▁途方", -13.14130973815918 ], [ "たくさん", -13.141531944274902 ], [ "▁SHIN", -13.141777992248535 ], [ "▁エクスペリエンス", -13.141908645629883 ], [ "poli", -13.1420259475708 ], [ "▁読み聞かせ", -13.14220905303955 ], [ "頭角", -13.142330169677734 ], [ "▁塗った", -13.142388343811035 ], [ "▁朝日新聞社", -13.14296817779541 ], [ "▁曳航", -13.143112182617188 ], [ "▁義兄", -13.143258094787598 ], [ "▁Form", -13.143293380737305 ], [ "▁ヤコブ", -13.143420219421387 ], [ "▁ハザード", -13.143714904785156 ], [ "呈", -13.14372730255127 ], [ "ベルギー", -13.14376163482666 ], [ "▁置け", -13.143800735473633 ], [ "伝説", -13.143832206726074 ], [ "▁パラグアイ", -13.144015312194824 ], [ "▁減衰", -13.144062995910645 ], [ "▁ファクター", -13.144373893737793 ], [ "▁係員", -13.144556045532227 ], [ "▁四万十", -13.14461898803711 ], [ "▁length", -13.144927024841309 ], [ "▁アミノ", -13.145299911499023 ], [ "▁ワイナリー", -13.145523071289062 ], [ "▁細やかな", -13.145623207092285 ], [ "▁IEEE", -13.14582633972168 ], [ "▁ミキサー", -13.145917892456055 ], [ "▁要点", -13.145918846130371 ], [ "嘗", -13.146126747131348 ], [ "瞬く間に", -13.146126747131348 ], [ "膵", -13.146127700805664 ], [ "▁癒す", -13.146431922912598 ], [ "漠", -13.146709442138672 ], [ "▁Standard", -13.14673137664795 ], [ "▁ステーショナリー", -13.14673137664795 ], [ "▁ホッケー", -13.146774291992188 ], [ "▁ダーウィン", -13.146808624267578 ], [ "XY", -13.14696979522705 ], [ "▁ブルターニュ", -13.14703369140625 ], [ "▁ルージュ", -13.147056579589844 ], [ "▁ネイチャー", -13.147141456604004 ], [ "♫", -13.14733600616455 ], [ "▁サプライヤー", -13.147652626037598 ], [ "", -13.147656440734863 ], [ "盃", -13.148242950439453 ], [ "▁img", -13.14836311340332 ], [ "Adobe", -13.148571014404297 ], [ "▁異例", -13.149093627929688 ], [ "▁起草", -13.149105072021484 ], [ "▁Limited", -13.149151802062988 ], [ "▁アテナイ", -13.149151802062988 ], [ "デンマーク", -13.149324417114258 ], [ "▁シェイプ", -13.14965534210205 ], [ "▁chocolate", -13.149757385253906 ], [ "▁マンツーマン", -13.149757385253906 ], [ "▁アラゴン", -13.149919509887695 ], [ "▁加味", -13.150094032287598 ], [ "▁豊洲", -13.150142669677734 ], [ "▁防音", -13.15017032623291 ], [ "▁しくみ", -13.150222778320312 ], [ "脚部", -13.150259971618652 ], [ "娼", -13.15036392211914 ], [ "▁フィアット", -13.15036678314209 ], [ "もしくは", -13.15040397644043 ], [ "▁乏しく", -13.150667190551758 ], [ "▁関白", -13.150701522827148 ], [ "修理", -13.150761604309082 ], [ "▁聖霊", -13.150797843933105 ], [ "▁繁盛", -13.151029586791992 ], [ "▁ウェット", -13.15103530883789 ], [ "▁コンビネーション", -13.151037216186523 ], [ "武器", -13.151152610778809 ], [ "▁立ち向か", -13.151165008544922 ], [ "▁寄り添う", -13.151273727416992 ], [ "▁硝子", -13.151276588439941 ], [ "□", -13.151322364807129 ], [ "国产", -13.151327133178711 ], [ "▁介助", -13.151399612426758 ], [ "果実", -13.15141773223877 ], [ "▁バトラー", -13.151479721069336 ], [ "▁アイゼン", -13.151493072509766 ], [ "▁ロイター", -13.151727676391602 ], [ "▁エントリ", -13.151836395263672 ], [ "▁エクアドル", -13.151881217956543 ], [ "▁にっぽん", -13.15202522277832 ], [ "▁販路", -13.15218734741211 ], [ "コロンビア", -13.152239799499512 ], [ "▁助監督", -13.152578353881836 ], [ "▁真鍮", -13.152806282043457 ], [ "▁凝固", -13.152826309204102 ], [ "▁テンプル", -13.152913093566895 ], [ "丙", -13.153097152709961 ], [ "▁ランディング", -13.153148651123047 ], [ "ナショナル", -13.15328598022461 ], [ "▁経常", -13.15342903137207 ], [ "語源", -13.153486251831055 ], [ "▁病態", -13.153564453125 ], [ "ification", -13.15368366241455 ], [ "灸", -13.153705596923828 ], [ "▁振り向", -13.153753280639648 ], [ "▁主計", -13.153763771057129 ], [ "スミレ", -13.153966903686523 ], [ "テイル", -13.154021263122559 ], [ "久留米", -13.154082298278809 ], [ "▁転覆", -13.154324531555176 ], [ "バージニア", -13.154388427734375 ], [ "lad", -13.15458869934082 ], [ "結成", -13.154620170593262 ], [ "▁当てはめ", -13.154635429382324 ], [ "ブラウン", -13.154681205749512 ], [ "支払い", -13.154746055603027 ], [ "▁雑音", -13.154926300048828 ], [ "▁翔太", -13.155044555664062 ], [ "系統", -13.155097007751465 ], [ "▁撲滅", -13.155227661132812 ], [ "賠", -13.155227661132812 ], [ "▁行き届い", -13.155259132385254 ], [ "フェニル", -13.15545654296875 ], [ "▁中南米", -13.155534744262695 ], [ "▁忠告", -13.155794143676758 ], [ "tract", -13.155941009521484 ], [ "▁くすみ", -13.15597152709961 ], [ "▁助かっ", -13.156192779541016 ], [ "▁2・3", -13.156315803527832 ], [ "▁any", -13.156355857849121 ], [ "▁ジョアン", -13.15639591217041 ], [ "â", -13.156447410583496 ], [ "診療", -13.156551361083984 ], [ "▁親睦", -13.156577110290527 ], [ "▁かっこよ", -13.156648635864258 ], [ "▁宣誓", -13.156773567199707 ], [ "▁そびえ", -13.156786918640137 ], [ "▁復員", -13.15693473815918 ], [ "▁おやじ", -13.15707015991211 ], [ "▁食育", -13.15710163116455 ], [ "▁阿久", -13.157154083251953 ], [ "▁盗んだ", -13.157157897949219 ], [ "ソフトバンク", -13.157163619995117 ], [ "彭", -13.157362937927246 ], [ "燕", -13.157462120056152 ], [ "▁殺傷", -13.157573699951172 ], [ "仏教", -13.157646179199219 ], [ "▁Public", -13.157669067382812 ], [ "ネーデルラント", -13.157669067382812 ], [ "CTION", -13.157713890075684 ], [ "▁屈折", -13.15774154663086 ], [ "▁空席", -13.157760620117188 ], [ "▁カフカ", -13.157803535461426 ], [ "▁古文書", -13.157974243164062 ], [ "▁砂丘", -13.158099174499512 ], [ "▁照れ", -13.158269882202148 ], [ "▁千秋楽", -13.158279418945312 ], [ "▁めざまし", -13.158281326293945 ], [ "▁ゲッター", -13.158437728881836 ], [ "▁洗車", -13.158478736877441 ], [ "▁利権", -13.158535957336426 ], [ "▁カトラリー", -13.158585548400879 ], [ "▁官公庁", -13.158585548400879 ], [ "▁ぐっ", -13.158918380737305 ], [ "▁ビジター", -13.159198760986328 ], [ "▁フェイシャル", -13.159238815307617 ], [ "▁アタシ", -13.159364700317383 ], [ "▁ウエイト", -13.159553527832031 ], [ "▁リスボン", -13.159567832946777 ], [ "▁キャッスル", -13.159597396850586 ], [ "▁Magic", -13.159627914428711 ], [ "▁アドリア", -13.159712791442871 ], [ "▁ノルマンディー", -13.159809112548828 ], [ "▁多方面", -13.159809112548828 ], [ "▁進呈", -13.159826278686523 ], [ "▁菩提寺", -13.159878730773926 ], [ "宇都宮", -13.159927368164062 ], [ "▁儒教", -13.160115242004395 ], [ "▁August", -13.160116195678711 ], [ "▁貴金属", -13.160151481628418 ], [ "lash", -13.160212516784668 ], [ "lg", -13.160469055175781 ], [ "▁千尋", -13.160481452941895 ], [ "▁卵巣", -13.160538673400879 ], [ "Select", -13.160650253295898 ], [ "▁Creative", -13.160737991333008 ], [ "▁猪木", -13.160823822021484 ], [ "勅", -13.160839080810547 ], [ "▁帰ろう", -13.160931587219238 ], [ "堕", -13.161033630371094 ], [ "▁Community", -13.16103458404541 ], [ "▁無関心", -13.16103458404541 ], [ "▁誓約", -13.161035537719727 ], [ "▁陳列", -13.161128997802734 ], [ "▁噛む", -13.161224365234375 ], [ "ロビン", -13.161290168762207 ], [ "▁レジスタンス", -13.161357879638672 ], [ "▁木蓮", -13.161585807800293 ], [ "▁!!️", -13.161662101745605 ], [ "▁江ノ島", -13.161955833435059 ], [ "▁井伊", -13.16207218170166 ], [ "▁モラル", -13.162075996398926 ], [ "▁ジブリ", -13.162463188171387 ], [ "▁万年筆", -13.162568092346191 ], [ "▁アドセンス", -13.162601470947266 ], [ "▁焼きそば", -13.162610054016113 ], [ "▁武勇", -13.162671089172363 ], [ "わずか", -13.162742614746094 ], [ "▁アベンジャーズ", -13.162875175476074 ], [ "▁兼ね備え", -13.162927627563477 ], [ "ré", -13.162975311279297 ], [ "▁Motor", -13.163018226623535 ], [ "▁除草", -13.163057327270508 ], [ "▁贈った", -13.163122177124023 ], [ "▁太宰府", -13.163201332092285 ], [ "▁心拍", -13.163341522216797 ], [ "▁噴水", -13.163445472717285 ], [ "ester", -13.163787841796875 ], [ "▁誰しも", -13.163792610168457 ], [ "abe", -13.164285659790039 ], [ "▁coach", -13.164299964904785 ], [ "▁恵美", -13.164385795593262 ], [ "▁ユニコーン", -13.164434432983398 ], [ "誘", -13.164557456970215 ], [ "▁沈んだ", -13.16456413269043 ], [ "独自の", -13.164567947387695 ], [ "SKA", -13.164572715759277 ], [ "▁ロッシ", -13.164624214172363 ], [ "▁吹き飛ば", -13.16472053527832 ], [ "▁温帯", -13.164861679077148 ], [ "iku", -13.164868354797363 ], [ "統計", -13.164949417114258 ], [ "▁助かる", -13.165099143981934 ], [ "▁豆乳", -13.16517162322998 ], [ "墜", -13.165325164794922 ], [ "▁敷いて", -13.165377616882324 ], [ "▁節税", -13.165410995483398 ], [ "▁mixi", -13.165627479553223 ], [ "タクシー", -13.165639877319336 ], [ "▁固執", -13.165651321411133 ], [ "▁残党", -13.165827751159668 ], [ "STEP", -13.16617488861084 ], [ "cade", -13.166184425354004 ], [ "▁ブサイク", -13.166258811950684 ], [ "灼", -13.166258811950684 ], [ "電源", -13.166482925415039 ], [ "▁グアテマラ", -13.166566848754883 ], [ "▁蓄電池", -13.166566848754883 ], [ "▁俳人", -13.166569709777832 ], [ "▁干拓", -13.166576385498047 ], [ "▁やむなく", -13.166641235351562 ], [ "自爆", -13.166677474975586 ], [ "危害", -13.166743278503418 ], [ "ů", -13.166875839233398 ], [ "▁心構え", -13.166875839233398 ], [ "嘴", -13.166875839233398 ], [ "▁After", -13.166900634765625 ], [ "もはや", -13.16705322265625 ], [ "御門", -13.167059898376465 ], [ "dict", -13.16708755493164 ], [ "▁イニシャル", -13.167183876037598 ], [ "▁絶叫", -13.16720962524414 ], [ "▁振舞", -13.16726303100586 ], [ "▁サイコロ", -13.167556762695312 ], [ "rab", -13.167593002319336 ], [ "机", -13.167675018310547 ], [ "▁緑茶", -13.16780948638916 ], [ "裔", -13.167973518371582 ], [ "セミナー", -13.168105125427246 ], [ "▁チャップリン", -13.168108940124512 ], [ "▁丁寧", -13.16812515258789 ], [ "▁Peter", -13.16834545135498 ], [ "▁妙高", -13.168461799621582 ], [ "▁駆け抜け", -13.168465614318848 ], [ "▁毛髪", -13.168648719787598 ], [ "▁蛇口", -13.168869972229004 ], [ "▁ペンシル", -13.168895721435547 ], [ "のりば", -13.16905689239502 ], [ "▁こもった", -13.169347763061523 ], [ "▁朝夕", -13.169376373291016 ], [ "aba", -13.169414520263672 ], [ "ペディア", -13.169540405273438 ], [ "▁吸入", -13.16992473602295 ], [ "馮", -13.169962882995605 ], [ "真っ暗", -13.169978141784668 ], [ "▁ぴあ", -13.170066833496094 ], [ "▁挟む", -13.170273780822754 ], [ "▁膨れ", -13.1703462600708 ], [ "▁トゥルー", -13.170394897460938 ], [ "敢", -13.170557022094727 ], [ "敦", -13.170763969421387 ], [ "▁リザーブ", -13.170892715454102 ], [ "▁実弟", -13.171001434326172 ], [ "▁湿原", -13.171049118041992 ], [ "▁被弾", -13.17113971710205 ], [ "▁スカイライン", -13.171265602111816 ], [ "▁know", -13.171420097351074 ], [ "屑", -13.171510696411133 ], [ "▁天童", -13.171677589416504 ], [ "限定", -13.171793937683105 ], [ "Map", -13.172157287597656 ], [ "▁垂水", -13.17216968536377 ], [ "▁バイヤー", -13.172258377075195 ], [ "▁誓う", -13.172442436218262 ], [ "▁フッ素", -13.172472953796387 ], [ "▁Eye", -13.172672271728516 ], [ "▁借地", -13.17302131652832 ], [ "▁ミルウォーキー", -13.173060417175293 ], [ "▁バチカン", -13.17306137084961 ], [ "▁Quick", -13.173121452331543 ], [ "▁独奏", -13.173224449157715 ], [ "▁バイオリン", -13.173295021057129 ], [ "湛", -13.173371315002441 ], [ "募", -13.173416137695312 ], [ "▁右折", -13.173431396484375 ], [ "ディスコグラフィ", -13.173603057861328 ], [ "▁延々と", -13.17373275756836 ], [ "姜", -13.173738479614258 ], [ "▁否認", -13.173741340637207 ], [ "xxx", -13.17388916015625 ], [ "▁叙事詩", -13.173992156982422 ], [ "雍", -13.173992156982422 ], [ "▁摘出", -13.173994064331055 ], [ "▁暗黙", -13.174006462097168 ], [ "▁近寄", -13.174236297607422 ], [ "煕", -13.174302101135254 ], [ "▁思い通りに", -13.174925804138184 ], [ "▁ウォーレン", -13.175100326538086 ], [ "▁巡業", -13.175203323364258 ], [ "anda", -13.175225257873535 ], [ "津軽", -13.175370216369629 ], [ "▁暴言", -13.175389289855957 ], [ "▁太政官", -13.175545692443848 ], [ "▁遠ざけ", -13.175556182861328 ], [ "▁マリーンズ", -13.175702095031738 ], [ "▁武豊", -13.175755500793457 ], [ "あわせて", -13.175796508789062 ], [ "洪", -13.175797462463379 ], [ "▁出没", -13.175804138183594 ], [ "▁休職", -13.176053047180176 ], [ "▁ルーレット", -13.176074981689453 ], [ "▁season", -13.176177024841309 ], [ "だいたい", -13.17626667022705 ], [ "▁ロックンロール", -13.17647933959961 ], [ "▁アーノルド", -13.176480293273926 ], [ "▁ファシズム", -13.176522254943848 ], [ "▁埋立", -13.1765775680542 ], [ "▁スポーク", -13.176651954650879 ], [ "璧", -13.176780700683594 ], [ "▁峡谷", -13.17679214477539 ], [ "▁毎時", -13.176933288574219 ], [ "▁終息", -13.17695140838623 ], [ "アーティスト", -13.177050590515137 ], [ " ", -13.177102088928223 ], [ "▁レコーズ", -13.177103996276855 ], [ "dig", -13.17717456817627 ], [ "▁ワンセグ", -13.177412986755371 ], [ "▁猛烈な", -13.177412986755371 ], [ "なんとなく", -13.177473068237305 ], [ "▁橿原", -13.177724838256836 ], [ "〆", -13.177724838256836 ], [ "▁慎太郎", -13.177886009216309 ], [ "▁レイカーズ", -13.178115844726562 ], [ "yuki", -13.17821216583252 ], [ "▁エドガー", -13.178449630737305 ], [ "▁ハイドロ", -13.178494453430176 ], [ "颯", -13.178972244262695 ], [ "▁ワルツ", -13.178979873657227 ], [ "▁黒ずみ", -13.178979873657227 ], [ "▁緩め", -13.179106712341309 ], [ "▁フィリーズ", -13.179161071777344 ], [ "昨", -13.179252624511719 ], [ "▁リユース", -13.179285049438477 ], [ "▁擬人", -13.179288864135742 ], [ "AKB", -13.179591178894043 ], [ "苅", -13.179908752441406 ], [ "▁ネバダ", -13.179909706115723 ], [ "▁ヴィーナス", -13.17995834350586 ], [ "放射", -13.1800537109375 ], [ "諦", -13.180157661437988 ], [ "hydro", -13.18022346496582 ], [ "▁めぐ", -13.1803560256958 ], [ "▁強烈", -13.18040943145752 ], [ "糠", -13.180534362792969 ], [ "▁TEAM", -13.180594444274902 ], [ "▁瑠璃", -13.180846214294434 ], [ "▁スクリュー", -13.180981636047363 ], [ "▁敷居", -13.181289672851562 ], [ "▁尺度", -13.181353569030762 ], [ "▁従四位", -13.181471824645996 ], [ "▁イベリア", -13.181472778320312 ], [ "粟", -13.182089805603027 ], [ "▁交尾", -13.18210506439209 ], [ "設備", -13.18227767944336 ], [ "▁ファルコン", -13.182286262512207 ], [ "▁フレッド", -13.183042526245117 ], [ "▁乱舞", -13.18327522277832 ], [ "▁乖離", -13.183350563049316 ], [ "▁レズビアン", -13.18336009979248 ], [ "▁South", -13.183371543884277 ], [ "▁険し", -13.183380126953125 ], [ "▁樹林", -13.183469772338867 ], [ "▁見せかけ", -13.183574676513672 ], [ "▁葛城", -13.183592796325684 ], [ "▁多治見", -13.183664321899414 ], [ "▁Charles", -13.183679580688477 ], [ "▁立ち読み", -13.183812141418457 ], [ "▁転任", -13.183853149414062 ], [ "▁泊まる", -13.18393325805664 ], [ "hir", -13.184053421020508 ], [ "黙", -13.18423843383789 ], [ "▁マイノリティ", -13.18429183959961 ], [ "▁気管支", -13.18429183959961 ], [ "在外", -13.184537887573242 ], [ "▁示談", -13.184606552124023 ], [ "槍", -13.184617042541504 ], [ "著名な", -13.18461799621582 ], [ "▁改番", -13.18487548828125 ], [ "▁Thomas", -13.184919357299805 ], [ "▁協業", -13.184928894042969 ], [ "▁遷都", -13.184988021850586 ], [ "▁装束", -13.185281753540039 ], [ "▁ロッジ", -13.185632705688477 ], [ "▁いけたら", -13.185676574707031 ], [ "▁帝都", -13.185821533203125 ], [ "謙", -13.185883522033691 ], [ "▁ナショナリズム", -13.186175346374512 ], [ "娩", -13.186175346374512 ], [ "汽", -13.186175346374512 ], [ "▁マリノス", -13.186271667480469 ], [ "▁ブレーメン", -13.186491012573242 ], [ "(^^)", -13.186503410339355 ], [ "▁様々である", -13.186574935913086 ], [ "▁不確実", -13.186650276184082 ], [ "▁休校", -13.186662673950195 ], [ "▁Richard", -13.18680477142334 ], [ "▁総じて", -13.18681526184082 ], [ "▁交番", -13.186936378479004 ], [ "▁疑わしい", -13.186944961547852 ], [ "更改", -13.186968803405762 ], [ "▁サクセス", -13.187118530273438 ], [ "▁Classic", -13.18712043762207 ], [ "▁プログラマー", -13.18713665008545 ], [ "▁御覧", -13.187383651733398 ], [ "把", -13.187434196472168 ], [ "プロデューサー", -13.187467575073242 ], [ "期待", -13.187651634216309 ], [ "由来", -13.187681198120117 ], [ "▁新発田", -13.187750816345215 ], [ "▁誇張", -13.187827110290527 ], [ "▁オードリー", -13.187978744506836 ], [ "▁コサック", -13.187992095947266 ], [ "▁Cafe", -13.188036918640137 ], [ "覗", -13.188057899475098 ], [ "あくまでも", -13.18821907043457 ], [ "▁帝京", -13.188281059265137 ], [ "▁マジカル", -13.188333511352539 ], [ "799", -13.188488960266113 ], [ "ウエスト", -13.188804626464844 ], [ "▁威嚇", -13.189008712768555 ], [ "玄関", -13.189455032348633 ], [ "▁プリメーラ", -13.1896390914917 ], [ "視点", -13.189746856689453 ], [ "▁廃絶", -13.189868927001953 ], [ "▁鶴橋", -13.189891815185547 ], [ "▁フランチェスコ", -13.18995475769043 ], [ "▁有能な", -13.18997859954834 ], [ "▁持病", -13.190115928649902 ], [ "▁Touch", -13.190326690673828 ], [ "action", -13.190457344055176 ], [ "RAD", -13.190499305725098 ], [ "▁接骨", -13.19050121307373 ], [ "▁払った", -13.190545082092285 ], [ "▁はちみつ", -13.19058609008789 ], [ "蟻", -13.19058609008789 ], [ "▁Sweet", -13.19058895111084 ], [ "▁取り調べ", -13.190590858459473 ], [ "斎藤", -13.190627098083496 ], [ "恐れ入り", -13.190694808959961 ], [ "▁退避", -13.190960884094238 ], [ "▁海藻", -13.190980911254883 ], [ "起源", -13.191134452819824 ], [ "▁撤収", -13.191217422485352 ], [ "▁揉み", -13.191219329833984 ], [ "ford", -13.191372871398926 ], [ "▁Marketing", -13.191533088684082 ], [ "▁ピラティス", -13.191533088684082 ], [ "▁暇つぶし", -13.191849708557129 ], [ "info", -13.191902160644531 ], [ "▁浜辺", -13.192153930664062 ], [ "▁妊活", -13.19216537475586 ], [ "グラスゴー", -13.192238807678223 ], [ "▁発布", -13.192248344421387 ], [ "MLB", -13.192386627197266 ], [ "執", -13.192428588867188 ], [ "ū", -13.192481994628906 ], [ "▁サブスクリプション", -13.192481994628906 ], [ "鞍", -13.192558288574219 ], [ "▁シュトラウス", -13.192797660827637 ], [ "▁招致", -13.192813873291016 ], [ "▁感慨", -13.192822456359863 ], [ "▁貫いて", -13.19287395477295 ], [ "▁フランドル", -13.192949295043945 ], [ "▁アルティメット", -13.193114280700684 ], [ "▁勧請", -13.193114280700684 ], [ "▁スクーター", -13.193267822265625 ], [ "サンプル", -13.193290710449219 ], [ "All", -13.193552017211914 ], [ "▁服飾", -13.193652153015137 ], [ "▁見下ろす", -13.193747520446777 ], [ "▁乾いた", -13.19375228881836 ], [ "計算", -13.193985939025879 ], [ "▁ディレクション", -13.194064140319824 ], [ "箋", -13.194304466247559 ], [ "▁ニホン", -13.194685935974121 ], [ "him", -13.19473648071289 ], [ "悲観", -13.194900512695312 ], [ "ï", -13.195014953613281 ], [ "コンスタンティノープル", -13.195014953613281 ], [ "▁宿命", -13.195079803466797 ], [ "▁活かせる", -13.195332527160645 ], [ "筑摩", -13.195357322692871 ], [ "▁悟空", -13.195466995239258 ], [ "▁発育", -13.195535659790039 ], [ "▁菌類", -13.195613861083984 ], [ " ", -13.195650100708008 ], [ "抑", -13.195940971374512 ], [ "▁大騒ぎ", -13.195966720581055 ], [ "▁密輸", -13.19601058959961 ], [ "蓋骨", -13.196011543273926 ], [ "▁施主", -13.196121215820312 ], [ "▁裾野", -13.196338653564453 ], [ "▁チャペル", -13.196478843688965 ], [ "▁ボイコット", -13.196614265441895 ], [ "▁訃報", -13.196919441223145 ], [ "▁逓信", -13.197237968444824 ], [ "▁^^;", -13.197265625 ], [ "▁血栓", -13.197371482849121 ], [ "▁効用", -13.19748592376709 ], [ "▁バウンド", -13.1976318359375 ], [ "▁デモンストレーション", -13.19787311553955 ], [ "▁円滑な", -13.197874069213867 ], [ "▁前もって", -13.197883605957031 ], [ "憧", -13.198079109191895 ], [ "▁損なう", -13.1981782913208 ], [ "▁新疆", -13.198274612426758 ], [ "▁ステファン", -13.198375701904297 ], [ "うれし", -13.198823928833008 ], [ "▁慶喜", -13.198951721191406 ], [ "▁野獣", -13.199119567871094 ], [ "▁サターン", -13.199403762817383 ], [ "▁メンフィス", -13.199464797973633 ], [ "▁親御さん", -13.199464797973633 ], [ "堡", -13.199464797973633 ], [ "▁難聴", -13.19955062866211 ], [ "▁ミセス", -13.199746131896973 ], [ "努", -13.19978141784668 ], [ "▁すばやく", -13.199783325195312 ], [ "▁蒙古", -13.199784278869629 ], [ "きちんと", -13.199919700622559 ], [ "憂", -13.199921607971191 ], [ "▁農協", -13.199974060058594 ], [ "▁ザーメン", -13.200429916381836 ], [ "▁浄土宗", -13.20048999786377 ], [ "▁花びら", -13.201061248779297 ], [ "▁喰ら", -13.201131820678711 ], [ "風邪", -13.201297760009766 ], [ "▁政変", -13.201411247253418 ], [ "▁ツーリズム", -13.201440811157227 ], [ "▁開演", -13.201494216918945 ], [ "隙", -13.201529502868652 ], [ "耗", -13.20168399810791 ], [ "amadana", -13.201698303222656 ], [ "▁スリラー", -13.201895713806152 ], [ "▁酷評", -13.202335357666016 ], [ "▁サファイア", -13.202550888061523 ], [ "▁Week", -13.20263671875 ], [ "脆", -13.202654838562012 ], [ "▁spli", -13.202729225158691 ], [ "埋め", -13.202740669250488 ], [ "▁キャビン", -13.20283317565918 ], [ "▁ふとん", -13.20290756225586 ], [ "述懐", -13.203315734863281 ], [ "▁淹れ", -13.203326225280762 ], [ "深夜", -13.203371047973633 ], [ "▁クレイジー", -13.203431129455566 ], [ "▁成り立ち", -13.203465461730957 ], [ "▁☆☆☆", -13.203614234924316 ], [ "りょく", -13.203700065612793 ], [ "某", -13.20378303527832 ], [ "批判", -13.20378589630127 ], [ "▁スタッド", -13.203934669494629 ], [ "▁バビロニア", -13.204254150390625 ], [ "▁知り合う", -13.204408645629883 ], [ "part", -13.204427719116211 ], [ "▁突きつけ", -13.204510688781738 ], [ "▁PIECE", -13.204574584960938 ], [ "▁ワトソン", -13.204575538635254 ], [ "▁イブニング", -13.204894065856934 ], [ "▁和睦", -13.205063819885254 ], [ "▁Festival", -13.205214500427246 ], [ "▁費やした", -13.205217361450195 ], [ "▁貝殻", -13.205243110656738 ], [ "▁Under", -13.205276489257812 ], [ "▁1,300", -13.205538749694824 ], [ "‰", -13.205855369567871 ], [ "SIDE", -13.205951690673828 ], [ "申込", -13.206075668334961 ], [ "▁TCG", -13.206199645996094 ], [ "▁啓示", -13.206238746643066 ], [ "▁SoftBank", -13.206497192382812 ], [ "赤血球", -13.206500053405762 ], [ "▁醍醐味", -13.206525802612305 ], [ "▁言おう", -13.206674575805664 ], [ "ジャイアンツ", -13.206690788269043 ], [ "研修", -13.206780433654785 ], [ "spir", -13.206805229187012 ], [ "▁忌避", -13.206829071044922 ], [ "▁ジークヴァル", -13.206846237182617 ], [ "▁codice", -13.206864356994629 ], [ "▁ベオグラード", -13.207139015197754 ], [ "▁画廊", -13.207231521606445 ], [ "▁トラッキング", -13.207249641418457 ], [ "ason", -13.207369804382324 ], [ "樽", -13.207396507263184 ], [ "▁デトックス", -13.207460403442383 ], [ "査定", -13.207584381103516 ], [ "▁衰弱", -13.207780838012695 ], [ "▁前倒し", -13.207781791687012 ], [ "▁キャンピング", -13.20781421661377 ], [ "roll", -13.208257675170898 ], [ "返品", -13.208273887634277 ], [ "▁島嶼", -13.208474159240723 ], [ "▁メラニン", -13.208475112915039 ], [ "▁必至", -13.208757400512695 ], [ "▁おいしかった", -13.2089204788208 ], [ "burg", -13.209037780761719 ], [ "池袋", -13.209089279174805 ], [ "▁ハッキング", -13.209249496459961 ], [ "▁Architectur", -13.209300994873047 ], [ "▁榴弾", -13.20938777923584 ], [ "▁辞し", -13.209518432617188 ], [ "コミュニケーション", -13.209604263305664 ], [ "▁ブリストル", -13.209710121154785 ], [ "▁林檎", -13.209712028503418 ], [ "▁束縛", -13.209716796875 ], [ "▁トランジット", -13.209724426269531 ], [ "▁ミッドナイト", -13.209757804870605 ], [ "▁パーティション", -13.209843635559082 ], [ "トーマス", -13.209850311279297 ], [ "▁穏健", -13.210031509399414 ], [ "靱", -13.210031509399414 ], [ "gress", -13.210298538208008 ], [ "▁アロマテラピー", -13.21035385131836 ], [ "蝶", -13.210573196411133 ], [ "▁引渡し", -13.210677146911621 ], [ "▁懸け", -13.210678100585938 ], [ "後醍醐天皇", -13.210997581481934 ], [ "1892", -13.211151123046875 ], [ "おしゃれ", -13.211227416992188 ], [ "▁WiMAX", -13.211343765258789 ], [ "耀", -13.211642265319824 ], [ "▁究明", -13.21164321899414 ], [ "萼", -13.21196460723877 ], [ "郵", -13.212918281555176 ], [ "💦", -13.212932586669922 ], [ "ญ", -13.213255882263184 ], [ "叛", -13.214224815368652 ], [ "愚", -13.214530944824219 ], [ "嬌", -13.214548110961914 ], [ "掠", -13.214872360229492 ], [ "煉", -13.215195655822754 ], [ "抽", -13.215462684631348 ], [ "", -13.215843200683594 ], [ "虔", -13.216166496276855 ], [ "迦", -13.216166496276855 ], [ "惠", -13.21778678894043 ], [ "稼", -13.218404769897461 ], [ "у", -13.21876049041748 ], [ "担", -13.220108032226562 ], [ "班", -13.220368385314941 ], [ "猟", -13.22102165222168 ], [ "弼", -13.221362113952637 ], [ "贄", -13.221362113952637 ], [ "蕨", -13.224949836730957 ], [ "庚", -13.225276947021484 ], [ "ゑ", -13.225930213928223 ], [ "侵", -13.226950645446777 ], [ "鉛", -13.227590560913086 ], [ "艸", -13.228550910949707 ], [ "艶", -13.22857666015625 ], [ "秩", -13.229534149169922 ], [ "霜", -13.230586051940918 ], [ "暫", -13.2315034866333 ], [ "俸", -13.233648300170898 ], [ "π", -13.235461235046387 ], [ "豫", -13.235461235046387 ], [ "穣", -13.236452102661133 ], [ "俯", -13.236780166625977 ], [ "鼎", -13.238435745239258 ], [ "冶", -13.239762306213379 ], [ "鴉", -13.239762306213379 ], [ "矛", -13.242419242858887 ], [ "เ", -13.243926048278809 ], [ "欣", -13.24608325958252 ], [ "汪", -13.24608325958252 ], [ "爛", -13.24608325958252 ], [ "埋", -13.247064590454102 ], [ "患", -13.247221946716309 ], [ "佃", -13.247419357299805 ], [ "莢", -13.248756408691406 ], [ "痒", -13.250094413757324 ], [ "瞼", -13.25110149383545 ], [ "肇", -13.25580883026123 ], [ "羨", -13.256423950195312 ], [ "笹", -13.257447242736816 ], [ "苫", -13.257832527160645 ], [ "邱", -13.258170127868652 ], [ "衙", -13.25986099243164 ], [ "弛", -13.260198593139648 ], [ "憐", -13.263200759887695 ], [ "糊", -13.265289306640625 ], [ "酬", -13.26629638671875 ], [ "埃", -13.26630973815918 ], [ "塑", -13.26699161529541 ], [ "痩", -13.267292976379395 ], [ "餓", -13.267332077026367 ], [ "ヱ", -13.268013954162598 ], [ "魅", -13.268109321594238 ], [ "舗", -13.268165588378906 ], [ "搬", -13.268335342407227 ], [ "浸", -13.268342018127441 ], [ "賄", -13.26839828491211 ], [ "粥", -13.270404815673828 ], [ "仔", -13.271499633789062 ], [ "≪", -13.272191047668457 ], [ "什", -13.27280044555664 ], [ "餡", -13.272801399230957 ], [ "ν", -13.273833274841309 ], [ "噴", -13.273897171020508 ], [ "堯", -13.274859428405762 ], [ "鋸", -13.275203704833984 ], [ "饗", -13.275891304016113 ], [ "逼", -13.277267456054688 ], [ "祢", -13.278645515441895 ], [ "喚", -13.278984069824219 ], [ "僑", -13.279335021972656 ], [ "均", -13.27964973449707 ], [ "係", -13.280773162841797 ], [ "緊", -13.280898094177246 ], [ "桝", -13.28417682647705 ], [ "揉", -13.286059379577637 ], [ "玖", -13.286606788635254 ], [ "ي", -13.287997245788574 ], [ "挟", -13.288616180419922 ], [ "桁", -13.290661811828613 ], [ "彬", -13.291483879089355 ], [ "β", -13.29312801361084 ], [ "危", -13.294157028198242 ], [ "韋", -13.295682907104492 ], [ "💕", -13.29603385925293 ], [ "妄", -13.297086715698242 ], [ "柿", -13.299497604370117 ], [ "煩", -13.30024242401123 ], [ "鰻", -13.300604820251465 ], [ "靡", -13.302369117736816 ], [ "怯", -13.302800178527832 ], [ "苻", -13.303428649902344 ], [ "焦", -13.305157661437988 ], [ "勾", -13.305196762084961 ], [ "膨", -13.306523323059082 ], [ "∴", -13.30661392211914 ], [ "й", -13.308743476867676 ], [ "挫", -13.309453964233398 ], [ "孕", -13.309454917907715 ], [ "蘆", -13.310166358947754 ], [ "硫", -13.311945915222168 ], [ "傅", -13.31230354309082 ], [ "蕩", -13.313015937805176 ], [ "Δ", -13.313373565673828 ], [ "淋", -13.313373565673828 ], [ "槇", -13.314087867736816 ], [ "契", -13.314767837524414 ], [ "醤", -13.317307472229004 ], [ "耽", -13.317666053771973 ], [ "鉤", -13.318024635314941 ], [ "含", -13.319204330444336 ], [ "祀", -13.319442749023438 ], [ "硝", -13.320175170898438 ], [ "蛙", -13.320537567138672 ], [ "━", -13.321383476257324 ], [ "暁", -13.321747779846191 ], [ "蕾", -13.32450008392334 ], [ "濤", -13.324861526489258 ], [ "畷", -13.324861526489258 ], [ "冪", -13.32630729675293 ], [ "邊", -13.32664966583252 ], [ "据", -13.326857566833496 ], [ "△", -13.328301429748535 ], [ "〞", -13.328478813171387 ], [ "橘", -13.330862045288086 ], [ "虹", -13.331594467163086 ], [ "軋", -13.331746101379395 ], [ "距", -13.332097053527832 ], [ "Â", -13.332472801208496 ], [ "ฟ", -13.333929061889648 ], [ "遁", -13.333929061889648 ], [ "鋏", -13.334294319152832 ], [ "粘", -13.335981369018555 ], [ "榊", -13.336482048034668 ], [ "鰐", -13.336483001708984 ], [ "勘", -13.337096214294434 ], [ "舜", -13.337214469909668 ], [ "ñ", -13.337944984436035 ], [ "唸", -13.338311195373535 ], [ "賤", -13.339044570922852 ], [ "殆", -13.339776992797852 ], [ "賈", -13.340143203735352 ], [ "但", -13.340906143188477 ], [ "樂", -13.341243743896484 ], [ "狗", -13.343361854553223 ], [ "悠", -13.343391418457031 ], [ "關", -13.343448638916016 ], [ "臀", -13.347502708435059 ], [ "玲", -13.347853660583496 ], [ "虞", -13.348980903625488 ], [ "践", -13.351130485534668 ], [ "廓", -13.353057861328125 ], [ "欄", -13.353079795837402 ], [ "吃", -13.353429794311523 ], [ "簾", -13.354172706604004 ], [ "卸", -13.354207038879395 ], [ "繕", -13.355265617370605 ], [ "腋", -13.355289459228516 ], [ "萬", -13.356081008911133 ], [ "箏", -13.357897758483887 ], [ "紆", -13.358644485473633 ], [ "疏", -13.359018325805664 ], [ "糞", -13.359090805053711 ], [ "眞", -13.359467506408691 ], [ "套", -13.360139846801758 ], [ "稀", -13.360198974609375 ], [ "睨", -13.360512733459473 ], [ "丑", -13.362011909484863 ], [ "謡", -13.362987518310547 ], [ "脊", -13.363136291503906 ], [ "宥", -13.36351203918457 ], [ "柊", -13.3665189743042 ], [ "别", -13.36689567565918 ], [ "醒", -13.36801528930664 ], [ "苞", -13.37104606628418 ], [ "藍", -13.371981620788574 ], [ "註", -13.37218189239502 ], [ "貪", -13.372939109802246 ], [ "貼", -13.372957229614258 ], [ "惜", -13.373045921325684 ], [ "嚥", -13.373697280883789 ], [ "线", -13.375094413757324 ], [ "屠", -13.376354217529297 ], [ "漿", -13.377495765686035 ], [ "ฒ", -13.377876281738281 ], [ "酉", -13.380927085876465 ], [ "砦", -13.383109092712402 ], [ "鰹", -13.383220672607422 ], [ "犠", -13.385519981384277 ], [ "惰", -13.386287689208984 ], [ "緻", -13.386287689208984 ], [ "ب", -13.386672019958496 ], [ "謬", -13.387439727783203 ], [ "脩", -13.387825012207031 ], [ "犀", -13.388209342956543 ], [ "盲", -13.388901710510254 ], [ "岬", -13.39046859741211 ], [ "釣", -13.391789436340332 ], [ "捲", -13.394383430480957 ], [ "甕", -13.395933151245117 ], [ "慕", -13.398666381835938 ], [ "呑", -13.398686408996582 ], [ "鰓", -13.399039268493652 ], [ "∵", -13.400595664978027 ], [ "琳", -13.401374816894531 ], [ "瘡", -13.401764869689941 ], [ "ß", -13.402154922485352 ], [ "檻", -13.402935028076172 ], [ "竺", -13.402935028076172 ], [ "“", -13.403716087341309 ], [ "馨", -13.405281066894531 ], [ "屍", -13.405672073364258 ], [ "姚", -13.4060640335083 ], [ "諒", -13.4080228805542 ], [ "賑", -13.409065246582031 ], [ "穢", -13.409594535827637 ], [ "猶", -13.409987449645996 ], [ "禿", -13.409987449645996 ], [ "扁", -13.410773277282715 ], [ "捌", -13.410773277282715 ], [ "蝉", -13.411954879760742 ], [ "ใ", -13.412348747253418 ], [ "紐", -13.412477493286133 ], [ "醸", -13.412662506103516 ], [ "葵", -13.413272857666016 ], [ "鬱", -13.413662910461426 ], [ "壷", -13.415111541748047 ], [ "贖", -13.415902137756348 ], [ "♀", -13.416297912597656 ], [ "ت", -13.418277740478516 ], [ "謁", -13.419466972351074 ], [ "凧", -13.419864654541016 ], [ "猪", -13.42406940460205 ], [ "舶", -13.424543380737305 ], [ "捺", -13.425838470458984 ], [ "叩", -13.427013397216797 ], [ "閻", -13.428237915039062 ], [ "拿", -13.428638458251953 ], [ "佇", -13.431446075439453 ], [ "殉", -13.431446075439453 ], [ "巽", -13.434664726257324 ], [ "捉", -13.435419082641602 ], [ "惚", -13.4357271194458 ], [ "繭", -13.436278343200684 ], [ "招", -13.437827110290527 ], [ "紬", -13.437893867492676 ], [ "誇", -13.438628196716309 ], [ "•", -13.439107894897461 ], [ "擁", -13.442209243774414 ], [ "芥", -13.445196151733398 ], [ "卍", -13.445198059082031 ], [ "椒", -13.445598602294922 ], [ "綴", -13.44637393951416 ], [ "ê", -13.446420669555664 ], [ "萱", -13.44682788848877 ], [ "爲", -13.447234153747559 ], [ "謄", -13.448869705200195 ], [ "閤", -13.448869705200195 ], [ "眉", -13.449286460876465 ], [ "唾", -13.449687957763672 ], [ "猥", -13.450508117675781 ], [ "蔦", -13.45214557647705 ], [ "紡", -13.45302677154541 ], [ "倹", -13.453786849975586 ], [ "矯", -13.455018997192383 ], [ "襖", -13.455431938171387 ], [ "徐", -13.455924034118652 ], [ "燭", -13.456665992736816 ], [ "璋", -13.45707893371582 ], [ "撥", -13.459553718566895 ], [ "獅", -13.46079158782959 ], [ "凱", -13.4620361328125 ], [ "旛", -13.4620361328125 ], [ "娶", -13.464523315429688 ], [ "〓", -13.465770721435547 ], [ "謎", -13.46845531463623 ], [ "螺", -13.469518661499023 ], [ "喘", -13.472862243652344 ], [ "¿", -13.474119186401367 ], [ "忽", -13.474119186401367 ], [ "裾", -13.47605037689209 ], [ "沸", -13.477320671081543 ], [ "范", -13.47916316986084 ], [ "δ", -13.480006217956543 ], [ "鍛", -13.48033618927002 ], [ "姻", -13.480405807495117 ], [ "贋", -13.481271743774414 ], [ "埴", -13.482115745544434 ], [ "斤", -13.482538223266602 ], [ "踊", -13.482827186584473 ], [ "詠", -13.484106063842773 ], [ "ธ", -13.485926628112793 ], [ "穆", -13.485926628112793 ], [ "賽", -13.488049507141113 ], [ "酵", -13.489664077758789 ], [ "蹊", -13.489751815795898 ], [ "Σ", -13.491029739379883 ], [ "癬", -13.491029739379883 ], [ "芦", -13.491411209106445 ], [ "侑", -13.491456031799316 ], [ "侶", -13.491870880126953 ], [ "榛", -13.491881370544434 ], [ "淫", -13.492271423339844 ], [ "哨", -13.49359130859375 ], [ "椀", -13.4940185546875 ], [ "肴", -13.4940185546875 ], [ "柑", -13.49573040008545 ], [ "怠", -13.496575355529785 ], [ "}", -13.496583938598633 ], [ "ы", -13.497445106506348 ], [ "я", -13.49787425994873 ], [ "竣", -13.49787425994873 ], [ "鞠", -13.49787425994873 ], [ "п", -13.498732566833496 ], [ "髭", -13.498749732971191 ], [ "鎌", -13.499116897583008 ], [ "瀋", -13.504334449768066 ], [ "彡", -13.506497383117676 ], [ "甦", -13.507363319396973 ], [ "圃", -13.508665084838867 ], [ "圳", -13.513885498046875 ], [ "錘", -13.513885498046875 ], [ "嘘", -13.516668319702148 ], [ "游", -13.517380714416504 ], [ "焔", -13.51781940460205 ], [ "禽", -13.518257141113281 ], [ "κ", -13.518694877624512 ], [ "竄", -13.519133567810059 ], [ "繰", -13.51976203918457 ], [ "發", -13.5204496383667 ], [ "█", -13.520889282226562 ], [ "б", -13.521327018737793 ], [ "璽", -13.521768569946289 ], [ "貶", -13.523088455200195 ], [ "脛", -13.523528099060059 ], [ "鶯", -13.523528099060059 ], [ "萌", -13.525510787963867 ], [ "慌", -13.52571964263916 ], [ "甑", -13.526174545288086 ], [ "葱", -13.526174545288086 ], [ "圭", -13.526863098144531 ], [ "د", -13.527057647705078 ], [ "ь", -13.527941703796387 ], [ "›", -13.528827667236328 ], [ "凹", -13.531390190124512 ], [ "刷", -13.534429550170898 ], [ "傍", -13.534430503845215 ], [ "ι", -13.5346040725708 ], [ "竪", -13.535490989685059 ], [ "س", -13.536382675170898 ], [ "曰", -13.536808013916016 ], [ "掾", -13.538616180419922 ], [ "拉", -13.541302680969238 ], [ "г", -13.541749954223633 ], [ "撲", -13.542563438415527 ], [ "禍", -13.542577743530273 ], [ "窯", -13.546207427978516 ], [ "茅", -13.546623229980469 ], [ "趣", -13.546639442443848 ], [ "襟", -13.551673889160156 ], [ "蒼", -13.552127838134766 ], [ "欅", -13.553481101989746 ], [ "观", -13.557121276855469 ], [ "−", -13.557168006896973 ], [ "刹", -13.562599182128906 ], [ "稽", -13.565339088439941 ], [ "媛", -13.567508697509766 ], [ "薫", -13.568251609802246 ], [ "壌", -13.572540283203125 ], [ "坦", -13.575431823730469 ], [ "趾", -13.575505256652832 ], [ "ก", -13.581809043884277 ], [ "冨", -13.583224296569824 ], [ "蜜", -13.585105895996094 ], [ "甚", -13.58554458618164 ], [ "撤", -13.586701393127441 ], [ "寓", -13.586702346801758 ], [ "訟", -13.58811092376709 ], [ "較", -13.593238830566406 ], [ "咽", -13.594709396362305 ], [ "炒", -13.595538139343262 ], [ "砺", -13.596129417419434 ], [ "堰", -13.601298332214355 ], [ "齋", -13.601828575134277 ], [ "茨", -13.602682113647461 ], [ "械", -13.602911949157715 ], [ "豹", -13.60373592376709 ], [ "幽", -13.604182243347168 ], [ "催", -13.604828834533691 ], [ "遥", -13.605144500732422 ], [ "肋", -13.605168342590332 ], [ "⁄", -13.605645179748535 ], [ "倭", -13.606600761413574 ], [ "馳", -13.607430458068848 ], [ "♪", -13.608038902282715 ], [ "諮", -13.608039855957031 ], [ "妬", -13.608040809631348 ], [ "駕", -13.609474182128906 ], [ "萎", -13.61043930053711 ], [ "旺", -13.610919952392578 ], [ "桟", -13.610919952392578 ], [ "裟", -13.611882209777832 ], [ "朔", -13.61434268951416 ], [ "产", -13.615174293518066 ], [ "慎", -13.618219375610352 ], [ "唯", -13.619485855102539 ], [ "貿", -13.619609832763672 ], [ "凛", -13.621662139892578 ], [ "å", -13.622654914855957 ], [ "呪", -13.627556800842285 ], [ "汰", -13.627646446228027 ], [ "∞", -13.630024909973145 ], [ "蹴", -13.638455390930176 ], [ "釧", -13.641173362731934 ], [ "祷", -13.641664505004883 ], [ "斥", -13.645134925842285 ], [ "些", -13.645145416259766 ], [ "溢", -13.645968437194824 ], [ "瞑", -13.647136688232422 ], [ "貰", -13.65246868133545 ], [ "憎", -13.655001640319824 ], [ "薦", -13.66061019897461 ], [ "窒", -13.661174774169922 ], [ "鯨", -13.666743278503418 ], [ "梱", -13.668286323547363 ], [ "麹", -13.669828414916992 ], [ "′", -13.674417495727539 ], [ "碧", -13.677538871765137 ], [ "恥", -13.677557945251465 ], [ "穫", -13.679537773132324 ], [ "絹", -13.679641723632812 ], [ "勿", -13.681062698364258 ], [ "贅", -13.682645797729492 ], [ "☺", -13.684196472167969 ], [ "曝", -13.686238288879395 ], [ "肖", -13.697210311889648 ], [ "鄭", -13.698505401611328 ], [ "准", -13.699034690856934 ], [ "梶", -13.700590133666992 ], [ "’", -13.702214241027832 ], [ "喪", -13.702214241027832 ], [ "燻", -13.70246410369873 ], [ "峨", -13.705101013183594 ], [ "且", -13.706146240234375 ], [ "披", -13.707216262817383 ], [ "紺", -13.70914077758789 ], [ "冴", -13.717787742614746 ], [ "葡", -13.718391418457031 ], [ "餐", -13.722136497497559 ], [ "忙", -13.722527503967285 ], [ "應", -13.731832504272461 ], [ "倶", -13.734574317932129 ], [ "湧", -13.735126495361328 ], [ "儲", -13.737449645996094 ], [ "偵", -13.740564346313477 ], [ "毀", -13.741674423217773 ], [ "聡", -13.742295265197754 ], [ "芯", -13.746171951293945 ], [ "‍", -13.74661922454834 ], [ "阜", -13.747708320617676 ], [ "抹", -13.74771785736084 ], [ "剰", -13.748212814331055 ], [ "逗", -13.751026153564453 ], [ "疲", -13.75217342376709 ], [ "晦", -13.75324535369873 ], [ "狛", -13.75601863861084 ], [ "零", -13.758440017700195 ], [ "蕉", -13.763830184936523 ], [ "崖", -13.769726753234863 ], [ "遵", -13.77000904083252 ], [ "无", -13.770009994506836 ], [ "碁", -13.78000259399414 ], [ "揖", -13.783056259155273 ], [ "费", -13.786953926086426 ], [ "菩", -13.78763484954834 ], [ "堆", -13.791656494140625 ], [ "挨", -13.795696258544922 ], [ "揺", -13.796154975891113 ], [ "漆", -13.799100875854492 ], [ "巫", -13.79917049407959 ], [ "箸", -13.800902366638184 ], [ "ป", -13.806778907775879 ], [ "蟹", -13.807341575622559 ], [ "琢", -13.807906150817871 ], [ "匹", -13.808547019958496 ], [ "購", -13.813136100769043 ], [ "拶", -13.813194274902344 ], [ "斬", -13.815032005310059 ], [ "吊", -13.816255569458008 ], [ "郁", -13.816255569458008 ], [ "擲", -13.820873260498047 ], [ "搭", -13.82800006866455 ], [ "畿", -13.829755783081055 ], [ "椿", -13.830639839172363 ], [ "捧", -13.844849586486816 ], [ "蔓", -13.849746704101562 ], [ "◯", -13.851994514465332 ], [ "雛", -13.85319709777832 ], [ "循", -13.853416442871094 ], [ "遙", -13.853951454162598 ], [ "袈", -13.854028701782227 ], [ "荊", -13.857097625732422 ], [ "牲", -13.857712745666504 ], [ "洒", -13.858943939208984 ], [ "簿", -13.85953426361084 ], [ "狙", -13.866278648376465 ], [ "屏", -13.873836517333984 ], [ "牽", -13.873836517333984 ], [ "痢", -13.877902030944824 ], [ "沃", -13.878223419189453 ], [ "凝", -13.884501457214355 ], [ "瘍", -13.886420249938965 ], [ "梢", -13.890725135803223 ], [ "曼", -13.891497611999512 ], [ "飢", -13.891938209533691 ], [ "熾", -13.898521423339844 ], [ "糾", -13.911420822143555 ], [ "$", -13.914992332458496 ], [ "洩", -13.918583869934082 ], [ "珂", -13.921205520629883 ], [ "廿", -13.92186164855957 ], [ "酪", -13.92580509185791 ], [ "逓", -13.929763793945312 ], [ "臆", -13.949124336242676 ], [ "宙", -13.95175838470459 ], [ "%", -13.95246696472168 ], [ "柵", -13.96619987487793 ], [ "榴", -13.967491149902344 ], [ "甥", -13.967582702636719 ], [ "噂", -13.973135948181152 ], [ "措", -13.978537559509277 ], [ "囃", -13.982708930969238 ], [ "·", -13.985745429992676 ], [ "矮", -13.98620319366455 ], [ "尖", -13.986437797546387 ], [ "愉", -13.98815631866455 ], [ "疼", -13.99251937866211 ], [ "裳", -13.996036529541016 ], [ " ̄", -13.999945640563965 ], [ "纂", -14.013781547546387 ], [ "或", -14.014342308044434 ], [ "沫", -14.016733169555664 ], [ "ヵ", -14.016743659973145 ], [ "杭", -14.027464866638184 ], [ "韮", -14.028351783752441 ], [ "迄", -14.04677963256836 ], [ "咄", -14.048250198364258 ], [ "桔", -14.05123233795166 ], [ "奄", -14.054221153259277 ], [ "傭", -14.057220458984375 ], [ "窃", -14.058725357055664 ], [ "炸", -14.059477806091309 ], [ "拗", -14.073873519897461 ], [ "嘱", -14.078471183776855 ], [ "唆", -14.078474998474121 ], [ "彿", -14.080779075622559 ], [ "伎", -14.085403442382812 ], [ "噌", -14.08689022064209 ], [ "崗", -14.086950302124023 ], [ "≫", -14.08731460571289 ], [ "椅", -14.08927059173584 ], [ "茹", -14.08927059173584 ], [ "冗", -14.090825080871582 ], [ "肘", -14.092007637023926 ], [ "ศ", -14.095149040222168 ], [ "哺", -14.100190162658691 ], [ "∀", -14.101542472839355 ], [ "朧", -14.104631423950195 ], [ "剖", -14.108034133911133 ], [ "瞳", -14.112602233886719 ], [ "騨", -14.120772361755371 ], [ "咎", -14.131956100463867 ], [ "吠", -14.135086059570312 ], [ "惣", -14.13526725769043 ], [ "泌", -14.13651180267334 ], [ "涯", -14.143689155578613 ], [ "焉", -14.154128074645996 ], [ "咳", -14.154274940490723 ], [ "μ", -14.161813735961914 ], [ "覆", -14.164271354675293 ], [ "昧", -14.166324615478516 ], [ "〕", -14.166869163513184 ], [ "蝦", -14.170836448669434 ], [ "嵯", -14.17251968383789 ], [ "燥", -14.174190521240234 ], [ "證", -14.17420768737793 ], [ "昏", -14.18265151977539 ], [ "培", -14.183053016662598 ], [ "捗", -14.184372901916504 ], [ "纏", -14.189062118530273 ], [ "蠣", -14.200727462768555 ], [ "噛", -14.202127456665039 ], [ "梗", -14.215575218200684 ], [ "稔", -14.218008041381836 ], [ "云", -14.220608711242676 ], [ "彙", -14.22134017944336 ], [ "肛", -14.221753120422363 ], [ "碗", -14.227921485900879 ], [ "浙", -14.228860855102539 ], [ "赴", -14.22984790802002 ], [ "迂", -14.247762680053711 ], [ "批", -14.260542869567871 ], [ "琶", -14.265179634094238 ], [ "拘", -14.270949363708496 ], [ "疎", -14.274696350097656 ], [ "濾", -14.27820873260498 ], [ "醐", -14.281023025512695 ], [ "醍", -14.285731315612793 ], [ "邉", -14.29044246673584 ], [ "檜", -14.291808128356934 ], [ "濫", -14.293310165405273 ], [ "æ", -14.297568321228027 ], [ "琵", -14.298076629638672 ], [ "耆", -14.301888465881348 ], [ "釘", -14.30433177947998 ], [ "凸", -14.310140609741211 ], [ "‘", -14.311141014099121 ], [ "视", -14.320301055908203 ], [ "筐", -14.32716178894043 ], [ "♡", -14.334845542907715 ], [ "肯", -14.338043212890625 ], [ "爬", -14.342029571533203 ], [ "蛋", -14.346031188964844 ], [ "嶼", -14.352913856506348 ], [ "填", -14.357078552246094 ], [ "栽", -14.360157012939453 ], [ "扮", -14.36037826538086 ], [ "菖", -14.363221168518066 ], [ "騙", -14.367328643798828 ], [ "皐", -14.375534057617188 ], [ "荼", -14.390095710754395 ], [ "惹", -14.39244270324707 ], [ "墾", -14.394264221191406 ], [ "孵", -14.39851188659668 ], [ "綻", -14.40273380279541 ], [ "遮", -14.407364845275879 ], [ "遭", -14.41016674041748 ], [ "弄", -14.411677360534668 ], [ "嬢", -14.421427726745605 ], [ "鵜", -14.421448707580566 ], [ "薪", -14.439041137695312 ], [ "叶", -14.443531036376953 ], [ "攣", -14.446114540100098 ], [ "弔", -14.4501953125 ], [ "絨", -14.458377838134766 ], [ "訣", -14.46173095703125 ], [ "諜", -14.46285343170166 ], [ "〝", -14.464884757995605 ], [ "腑", -14.469658851623535 ], [ "蚊", -14.471738815307617 ], [ "宕", -14.476377487182617 ], [ "焙", -14.478775024414062 ], [ "姪", -14.48442554473877 ], [ "筈", -14.486750602722168 ], [ "塀", -14.489079475402832 ], [ "ม", -14.492584228515625 ], [ "凰", -14.494933128356934 ], [ "痺", -14.5029296875 ], [ "渦", -14.503172874450684 ], [ "摯", -14.504283905029297 ], [ "│", -14.509103775024414 ], [ "冑", -14.524429321289062 ], [ "傲", -14.526850700378418 ], [ "諧", -14.529255867004395 ], [ "荏", -14.534080505371094 ], [ "翻", -14.552862167358398 ], [ "芭", -14.554866790771484 ], [ "棘", -14.556615829467773 ], [ "嗟", -14.561062812805176 ], [ "胚", -14.562873840332031 ], [ "讐", -14.568536758422852 ], [ "婁", -14.57608699798584 ], [ "鹸", -14.578503608703613 ], [ "弩", -14.579883575439453 ], [ "珊", -14.586236953735352 ], [ "邁", -14.587512016296387 ], [ "瀕", -14.596328735351562 ], [ "鈍", -14.601265907287598 ], [ "繍", -14.60423755645752 ], [ "阻", -14.606498718261719 ], [ "銚", -14.608141899108887 ], [ "膚", -14.63183879852295 ], [ "頬", -14.635775566101074 ], [ "娯", -14.635887145996094 ], [ "嘩", -14.63588809967041 ], [ "薇", -14.638570785522461 ], [ "剪", -14.639914512634277 ], [ "妥", -14.641191482543945 ], [ "疆", -14.643594741821289 ], [ "宛", -14.643898010253906 ], [ "袴", -14.650741577148438 ], [ "遽", -14.664387702941895 ], [ "┃", -14.665935516357422 ], [ "醜", -14.674321174621582 ], [ "彗", -14.676904678344727 ], [ "攘", -14.690959930419922 ], [ "秒", -14.691283226013184 ], [ "陝", -14.692376136779785 ], [ "轟", -14.69273567199707 ], [ "夭", -14.7138671875 ], [ "舵", -14.714404106140137 ], [ "蕎", -14.719676971435547 ], [ "酎", -14.724039077758789 ], [ "眺", -14.726947784423828 ], [ "凌", -14.732050895690918 ], [ "歪", -14.733570098876953 ], [ "膣", -14.73656940460205 ], [ "隕", -14.738795280456543 ], [ "码", -14.74924373626709 ], [ "踪", -14.75524616241455 ], [ "漂", -14.766850471496582 ], [ "糟", -14.770471572875977 ], [ "漸", -14.773075103759766 ], [ "隘", -14.775070190429688 ], [ "捏", -14.778164863586426 ], [ "剥", -14.782401084899902 ], [ "痙", -14.782808303833008 ], [ "嘔", -14.789034843444824 ], [ "麒", -14.79216194152832 ], [ "拐", -14.796858787536621 ], [ "揆", -14.800548553466797 ], [ "鎧", -14.80295181274414 ], [ "餃", -14.809536933898926 ], [ "訊", -14.814188003540039 ], [ "°", -14.814188957214355 ], [ "企", -14.825390815734863 ], [ "嫉", -14.835368156433105 ], [ "瑚", -14.845229148864746 ], [ "輛", -14.85322380065918 ], [ "✨", -14.874055862426758 ], [ "仇", -14.884391784667969 ], [ "舐", -14.889005661010742 ], [ "楕", -14.89257526397705 ], [ "礎", -14.89300537109375 ], [ "愕", -14.899518013000488 ], [ "薔", -14.903018951416016 ], [ "粧", -14.916532516479492 ], [ "漱", -14.918891906738281 ], [ "墟", -14.924206733703613 ], [ "渥", -14.938640594482422 ], [ "絆", -14.956169128417969 ], [ "ا", -14.978750228881836 ], [ "衷", -14.990981101989746 ], [ "罷", -14.99648380279541 ], [ "瞰", -15.002273559570312 ], [ "琥", -15.01003360748291 ], [ "堵", -15.011916160583496 ], [ "薨", -15.023758888244629 ], [ "橿", -15.04168701171875 ], [ "詫", -15.055856704711914 ], [ "妨", -15.057886123657227 ], [ "訃", -15.064044952392578 ], [ "殴", -15.068272590637207 ], [ "珈", -15.08062744140625 ], [ "瑕", -15.084815979003906 ], [ "顆", -15.089021682739258 ], [ "疵", -15.110321998596191 ], [ "謗", -15.116801261901855 ], [ "慨", -15.1209716796875 ], [ "瞭", -15.129806518554688 ], [ "聘", -15.140911102294922 ], [ "埠", -15.145374298095703 ], [ "隻", -15.150660514831543 ], [ "ง", -15.175832748413086 ], [ "频", -15.17708683013916 ], [ "羞", -15.181700706481934 ], [ "ว", -15.182809829711914 ], [ "渤", -15.184015274047852 ], [ "จ", -15.18514633178711 ], [ "ด", -15.187488555908203 ], [ "ห", -15.192188262939453 ], [ "沌", -15.212203979492188 ], [ "〉", -15.223291397094727 ], [ "泄", -15.229039192199707 ], [ "頁", -15.235516548156738 ], [ "├", -15.240448951721191 ], [ "榜", -15.24615478515625 ], [ "冤", -15.248601913452148 ], [ "曖", -15.248631477355957 ], [ "琲", -15.256075859069824 ], [ "膀", -15.261069297790527 ], [ "淘", -15.278746604919434 ], [ "♥", -15.283384323120117 ], [ "鞄", -15.293760299682617 ], [ "叱", -15.296371459960938 ], [ "鍮", -15.296629905700684 ], [ "‐", -15.309530258178711 ], [ "跨", -15.312182426452637 ], [ "蜘", -15.31242847442627 ], [ "胱", -15.325691223144531 ], [ "罠", -15.406828880310059 ], [ "漑", -15.41209602355957 ], [ "姶", -15.415011405944824 ], [ "穿", -15.415626525878906 ], [ "拷", -15.420867919921875 ], [ "頒", -15.426758766174316 ], [ "庇", -15.433457374572754 ], [ "誹", -15.43864631652832 ], [ "倦", -15.456745147705078 ], [ "窄", -15.46284294128418 ], [ "¤", -15.470102310180664 ], [ "迭", -15.478272438049316 ], [ "殲", -15.516324996948242 ], [ "淹", -15.519238471984863 ], [ "顛", -15.529333114624023 ], [ "珀", -15.542512893676758 ], [ "匈", -15.545835494995117 ], [ "酋", -15.562613487243652 ], [ "遡", -15.564634323120117 ], [ "斡", -15.569405555725098 ], [ "蛛", -15.569405555725098 ], [ "倣", -15.588857650756836 ], [ "鹵", -15.600549697875977 ], [ "└", -15.606526374816895 ], [ "喋", -15.631767272949219 ], [ "濯", -15.665892601013184 ], [ "陛", -15.700262069702148 ], [ "雰", -15.73583984375 ], [ "煽", -15.752070426940918 ], [ "苛", -15.768730163574219 ], [ "亢", -15.798100471496582 ], [ "萄", -15.819746971130371 ], [ "諏", -15.897053718566895 ], [ "饉", -15.920982360839844 ], [ "晒", -15.927383422851562 ], [ "峙", -15.930635452270508 ], [ "氾", -15.93071460723877 ], [ "戮", -15.94051742553711 ], [ "鑽", -15.970610618591309 ], [ "饅", -16.044530868530273 ], [ "劾", -16.049970626831055 ], [ "躇", -16.089357376098633 ], [ "­", -16.1043643951416 ], [ "祉", -16.11249351501465 ], [ "恣", -16.11842918395996 ], [ "艤", -16.130298614501953 ], [ "擢", -16.142303466796875 ], [ "ā", -16.164804458618164 ], [ "毯", -16.211088180541992 ], [ "咥", -16.270925521850586 ], [ "蒐", -16.29193878173828 ], [ "賂", -16.29897689819336 ], [ "⌒", -16.348995208740234 ], [ "揄", -16.38759994506836 ], [ "檎", -16.395315170288086 ], [ "惧", -16.395347595214844 ], [ "憾", -16.403146743774414 ], [ "嚇", -16.41103172302246 ], [ "乖", -16.426977157592773 ], [ "肪", -16.4596004486084 ], [ "逮", -16.459627151489258 ], [ "傀", -16.476367950439453 ], [ "揶", -16.555355072021484 ], [ "±", -16.56560516357422 ], [ " ", -16.705135345458984 ], [ "徊", -16.71331214904785 ], [ "〟", -16.782949447631836 ], [ "︎", -16.818248748779297 ], [ "儡", -16.85067367553711 ], [ "゙", -16.905803680419922 ], [ "®", -17.140445709228516 ], [ "謳", -17.15711212158203 ], [ "ƒ", -17.382352828979492 ], [ "拮", -17.433551788330078 ], [ "┈", -17.447589874267578 ], [ "娠", -17.45577049255371 ], [ "综", -17.525489807128906 ], [ "脫", -17.928848266601562 ], [ "徘", -18.18313980102539 ], [ "‹", -18.50208854675293 ], [ "", -18.568756103515625 ], [ "ย", -18.568756103515625 ], [ "‚", -18.80044174194336 ], [ "嬲", -19.370323181152344 ], [ "น", -19.53699493408203 ], [ "บ", -19.53699493408203 ], [ "พ", -19.73699951171875 ], [ "č", -19.987009048461914 ], [ "ิ", -19.987009048461914 ], [ "€", -20.32036590576172 ], [ "อ", -20.820444107055664 ], [ "่", -20.820444107055664 ], [ "Š", -21.820039749145508 ], [ "ณ", -21.820140838623047 ], [ "Œ", -21.820240020751953 ], [ "ํ", -21.82033920288086 ], [ "ู", -21.8204402923584 ], [ "躊", -21.820539474487305 ], [ "ุ", -21.820640563964844 ], [ "ี", -21.82073974609375 ], [ "้", -21.82084083557129 ], [ "š", -21.820940017700195 ], [ "ž", -21.820940017700195 ], [ "ล", -21.820940017700195 ], [ "ะ", -21.820940017700195 ], [ "์", -21.820940017700195 ] ] } ================================================ FILE: BertVits.md ================================================ # BertVits及Vits使用指南 - 1、按照要求安装模型 - 2、安装Cleaner([下载地址](https://github.com/NaruseMioShirakana/TextCleaner/releases),将文件夹“G2P”解压到Exe路径) - 3、将Bert文件夹复制到Exe路径,其中的子文件夹可以放置我发布的Bert模型,也可以啥都不放(如果不放模型就不能用Bert模型,但是不影响正常推理,就是效果可能会大打折扣) - 4、按照自己的需要配置字典(Dict)文件 - 5、编写输入,载入程序推理 ## BasicDict.json 字典的作用就是将软件自动处理出来的文本替换为你使用的模型的Symbol,而字典文件的作用就是规定这个替换规则,字典文件是如同BasicDict.json的文件,其中由非常多的键值对组成,其中的Key就是待替换文本,而Value就是替换后的文本。 ## VitsInputTemplate.json ```jsonc //Json需要是数组类型 [ { "Tokens": "私は誰?",//必填,进入Bert的文本 "Seq": ["w","a","t","a","s","h","i","w","a","d","a","r","e","?"],//选填,音素组成的序列,如果不填会根据Tokens自动生成 "Tones": [0,0,0,0,0,0,0,0,0,0,0,0,0],//选填,音调序列,必须与音素序列等长 "Durations": [2,5,2,5,2,2,5,2,5,2,5,2,5],//选填,音素时长序列,必须与音素序列等长 "Language": [0,0,0,0,0,0,0,0,0,0,0,0,0],//选填,语言序列,必须与音素序列等长 "SpeakerMix": [1,0,0],//选填,角色混合比例,决定对应下标角色音色的混合比例 "EmotionPrompt": ["sad", "happy"],//选填,情感参数,有情感模型的情况下可用 "NoiseScale": 0.666,//选填,噪声修正因子 "LengthScale": 1.1,//选填,时长修正因子 "DurationPredictorNoiseScale": 0.333,//选填,随机时长预测器噪声修正因子 "FactorDpSdp": 0.6,//选填,时长预测器和随机时长预测器的混合比例 "GateThreshold": 0.777,//选填,Tacotron2 EOS阈值 "MaxDecodeStep": 114514,//选填,Tacotron2 最大解码步数 "Seed": 1919810,//选填,种子 "SpeakerId": 2,//选填,角色ID(若SpeakerMix为空则使用) "RestTime": 1.0,//选填,决定与上一个片段的时间间隔(单位为秒),若为负数则表示切断音频并输出一个新的 "PlaceHolderSymbol": "|",//选填,当Seq为String时,隔开两个音素的记号 "LanguageID": "JP",//选填,语言(ZH,JP或EN) "G2PAdditionalInfo": "/[Japanese2]"//选填,Cleaner额外参数 }, ] ``` ================================================ FILE: CMakeLists.txt ================================================ # CMakeList.txt: 顶层 CMake 项目文件,在此处执行全局配置 # 并包含子项目。 # cmake_minimum_required (VERSION 3.8) # 如果支持,请为 MSVC 编译器启用热重载。 if (POLICY CMP0141) cmake_policy(SET CMP0141 NEW) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") endif() project ("DragonianSpeech") set(FISHSPEECHCPP_BUILD_DEMO ON) add_subdirectory ("fish-speech.cpp") ================================================ FILE: CMakePresets.json ================================================ { "version": 3, "configurePresets": [ { "name": "windows-base", "hidden": true, "generator": "Ninja", "binaryDir": "${sourceDir}/out/build/${presetName}", "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe" }, "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" } }, { "name": "x64-debug", "displayName": "x64 Debug", "inherits": "windows-base", "architecture": { "value": "x64", "strategy": "external" }, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } }, { "name": "x64-release", "displayName": "x64 Release", "inherits": "x64-debug", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } }, { "name": "x86-debug", "displayName": "x86 Debug", "inherits": "windows-base", "architecture": { "value": "x86", "strategy": "external" }, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } }, { "name": "x86-release", "displayName": "x86 Release", "inherits": "x86-debug", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } } ] } ================================================ FILE: CSharpDemo/CSharpDemo.csproj ================================================  Exe net8.0 enable enable True Debug;Release True True Resources.resx ResXFileCodeGenerator Resources.Designer.cs ================================================ FILE: CSharpDemo/Program.cs ================================================ using LibSvcApi; LibSvc.LibSvcHparams Config = new(); Config.TensorExtractor = "DiffusionSvc"; Config.SamplingRate = 44100; Config.HopSize = 512; Config.HubertPath = "D:\\VSGIT\\MoeVoiceStudioSvc - Core - Cmd\\x64\\Debug\\hubert\\vec-768-layer-12.onnx"; Config.SpeakerCount = 2; Config.HiddenUnitKDims = 768; Config.EnableCharaMix = 1; Config.EnableVolume = 1; Config.MelBins = 128; Config.DiffusionSvc.After = "D:\\VSGIT\\MoeVoiceStudioSvc - Core - Cmd\\x64\\Debug\\Models\\ShallowDiffusion\\ShallowDiffusion_after.onnx"; Config.DiffusionSvc.Alpha = "D:\\VSGIT\\MoeVoiceStudioSvc - Core - Cmd\\x64\\Debug\\Models\\ShallowDiffusion\\ShallowDiffusion_alpha.onnx"; Config.DiffusionSvc.Encoder = "D:\\VSGIT\\MoeVoiceStudioSvc - Core - Cmd\\x64\\Debug\\Models\\ShallowDiffusion\\ShallowDiffusion_encoder.onnx"; Config.DiffusionSvc.Denoise = "D:\\VSGIT\\MoeVoiceStudioSvc - Core - Cmd\\x64\\Debug\\Models\\ShallowDiffusion\\ShallowDiffusion_denoise.onnx"; Config.DiffusionSvc.Naive = "D:\\VSGIT\\MoeVoiceStudioSvc - Core - Cmd\\x64\\Debug\\Models\\ShallowDiffusion\\ShallowDiffusion_naive.onnx"; Config.DiffusionSvc.Pred = "D:\\VSGIT\\MoeVoiceStudioSvc - Core - Cmd\\x64\\Debug\\Models\\ShallowDiffusion\\ShallowDiffusion_pred.onnx"; void PrintProgress(ulong arg1, ulong arg2) { Console.WriteLine(arg1 * 100.0 / 10); } LibSvc.CallbackProgress Callback = new LibSvc.CallbackProgress(PrintProgress); UnionModel Model = LibSvc.Factory.LoadUnionSvcModel( ref Config, ref Callback, 0, 0, 8 ); string AudioPath = "input.wav"; Int16Vector Audio = LibSvc.Factory.ReadAudio(ref AudioPath, 48000); Console.WriteLine(Audio.Size()); LibSvc.SlicerSettings slicerSettings = new(); UInt64Vector SlicePos = LibSvc.Factory.SliceAudio(ref Audio, ref slicerSettings); SlicePos.Resize(3); Console.WriteLine(SlicePos.Size()); Slices slices = LibSvc.Factory.Preprocess(ref Audio, ref SlicePos); Console.WriteLine(slices.Size()); string VocoderPath = "D:\\VSGIT\\MoeVoiceStudioSvc - Core - Cmd\\x64\\Debug\\hifigan\\nsf_hifigan.onnx"; VocoderModel Vocoder = LibSvc.Factory.LoadVocoderModel(ref VocoderPath); LibSvc.Params _params = new(); _params.Step = 100; _params.Pndm = 10; _params.SetVocoder(ref Vocoder); ulong Proc = 0; Slice slice = slices[1]; Audio = Model.Inference(slice, ref _params, ref Proc); Console.WriteLine((double)slice.SrcLength() * Config.SamplingRate / slicerSettings.SamplingRate); Console.WriteLine(Audio.Size()); Callback(1, 2); GC.KeepAlive(Callback); GC.KeepAlive(Vocoder); LibSvc.Factory.WriteAudio(Audio, "Out1.wav", Config.SamplingRate); Audio.Insert(ref Audio); LibSvc.Factory.WriteAudio(Audio, "Out2.wav", Config.SamplingRate); ================================================ FILE: CSharpDemo/Properties/Resources.Designer.cs ================================================ //------------------------------------------------------------------------------ // // 此代码由工具生成。 // 运行时版本:4.0.30319.42000 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ namespace CSharpDemo.Properties { using System; /// /// 一个强类型的资源类,用于查找本地化的字符串等。 /// // 此类是由 StronglyTypedResourceBuilder // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen // (以 /str 作为命令选项),或重新生成 VS 项目。 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CSharpDemo.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// 重写当前线程的 CurrentUICulture 属性,对 /// 使用此强类型资源类的所有资源查找执行重写。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } } } ================================================ FILE: CSharpDemo/Properties/Resources.resx ================================================  text/microsoft-resx 1.3 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: CSharpDemo/Properties/launchSettings.json ================================================ { "profiles": { "CSharpDemo": { "commandName": "Project", "nativeDebugging": true } } } ================================================ FILE: CSharpDemo/README.md ================================================
![image](logo/logo256(AIGen).png) # DragonianVoice [中文](README.md) | [English](README_en.md)
> 本仓库已经暂时停止了UI项目的维护,以后可能会成为一个纯Lib项目。 > 本仓库为:1、TTS(Tacotron2、Vits、EmotionalVits、BERTVits2、GPtSoVits);2、SVC(SoVitsSvc、RVC、DiffusionSvc、FishDiffusion、ReflowSvc);3、SVS(DiffSinger) 的Onnx框架推理仓库,目前支持C/Cpp/C#调用。 > 本仓库的最新版本已经与 [fish-speech](https://github.com/fishaudio/fish-speech) 联动,使用ggml框架重写fish-speech,组成fish-speech.cpp子项目 > 注意:支持SVS的分支:[MoeVoiceStudio](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudio) [MoeVoiceStudioCore](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore) > 关于Cuda支持的相关问题可以前往 [OnnxRuntime官方仓库](https://github.com/microsoft/onnxruntime/releases) 查看 > 经过实验,Dml会导致Onnx中一些不支持的算子在使用时并不会报错,而是会返回一个不可预料的结果,所以会导致SoVits3.0和SoVits4.0在DmlEP上的推理结果错误。不过最新的SoVits仓库中的Onnx导出已经替换了这些算子,故SoVits3.0和SoVits4.0恢复支持Dml使用,但是要使用最新(2023/7/17)版本的SoVitsOnnx导出重新导出Onnx模型 > 由于Diffusion和Reflow模型的特性,如果你推理的总步数大于模型训练时最大的步数(实际步数=总步数/加速倍率,这个总步数不是推理时实际走过的步数,而是K_Step),会导致输出音频炸掉或者出现非常大的噪声,所以建议在推理前请仔细观察自己模型配置文件中的MaxStep(或K_Step_Max)
支持的Net: - [DeepLearningExamples](https://github.com/NVIDIA/DeepLearningExamples) - [Vits](https://github.com/jaywalnut310/vits) - [EmotionalVits](https://github.com/innnky/emotional-vits) - [BertVits2](https://github.com/fishaudio/Bert-VITS2) - [SoVitsSvc (v2/v3/v4)](https://github.com/svc-develop-team/so-vits-svc) - [RVC](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) - [DiffSvc](https://github.com/prophesier/diff-SVC) - [DiffusionSvc (v1/v2)](https://github.com/CNChTu/Diffusion-SVC) - [FishDiffusion](https://github.com/fishaudio/fish-diffusion) - [ReflowSvc](https://github.com/prophesier/diff-SVC) - [DiffSinger](https://github.com/openvpi/DiffSinger) - [FCPE](https://github.com/CNChTu/MelPE) - [RMVPE](https://github.com/yxlllc/RMVPE)
## 目录 - [协议](#用户协议) - [免责声明](#免责声明) - [说明](#说明) - [分支说明](#分支) - [FAQ问答](#faq) - Q: [项目名的来历是什么?](#q-项目名的来历) - Q: [这个项目到底有什么作用?](#q-这个项目到底有什么作用) - Q: [该项目以后会收费吗?](#q-该项目以后会收费吗) - Q: [是否提供有偿模型代训练?](#q-是否提供有偿模型代训练) - Q: [电子垃圾评判标准是什么?](#q-电子垃圾评判标准是什么) - Q: [技术支持?](#q-技术支持) - [注意事项](#注意事项) - [使用方法](#使用方法) - [模型配置](#模型配置) - [前置模型](#前置模型) - [配置文件](#配置文件) - [支持的项目](#支持的项目) - [其他设置](#其他设置) - [Symbol](#symbol) - [Cleaner](#cleaner) - [本地编译](#本地编译) - [依赖列表](#依赖列表) - [相关法规](#-相关法规) ## 用户协议: ### 使用该项目你必须同意以下条款,若不同意则禁止使用该项目: 1. 你必须自行承担由于使用该项目而造成的一切后果。 2. 禁止出售该程序。 3. 使用该项目时,你必须自觉遵守当地的法律法规,禁止使用该项目从事违法活动。 4. 禁止用于任何商业游戏、低创游戏[^1]以及Galgame制作,不反对无偿的精品游戏制作以及Mod制作。 5. 禁止使用该项目及该项目衍生物以及发布模型等制作各种电子垃圾[^2] (例如AIGalgame,AI游戏制作等)。 6. 禁止一切政治相关内容。 7. 你使用该项目生成的一切内容均与该项目开发者无关。 8. 本项目开发者主张使用者不具有其所生成“音频本身”的版权,应当划归公共领域;而音频背后涉及到的歌词、乐曲的版权所有者均为该歌词、乐曲的版权所有方。 [^1]: 低创的评判标准为: 大量使用AI生成的任何内容,原创内容较低,意义不明,内容质量低下等。 [^2]: 电子垃圾评判标准: 1、原创度。自己的东西在整个项目中的比例(对于AI来说,使用完全由你独立训练模型的创作属于你自己;使用他人模型的创作属于别人)。涵盖的方面包括但不限于程序、美工、音频、策划等等。例如,套用Unity等引擎模板换皮属于电子垃圾。 ## 免责声明 本项目为**开源、离线的项目,本项目的所有开发者以及维护者(以下简称贡献者)对本项目没有控制力**。本项目的贡献者从未向任何组织或个人提供包括但不限于数据集提取、数据集加工、算力支持、训练支持、推理等一切形式的帮助;本项目的贡献者不知晓也无法知晓使用者使用该项目的用途。故一切基于本项目合成的音频都与本项目贡献者无关。**一切由此造成的问题由使用者自行承担**。 本项目本身不具备任何语音合成的功能,只是用于启动使用者自行训练并自行制作为Onnx模型的模型,且模型的训练与Onnx模型的制作均与本项目的贡献者无关,均为使用者自己的行为,本项目贡献者未参与一切使用者的模型训练与制作。 本项目为完全离线状态下运行,无法采集任何用户信息,也无法获取用户的输入数据,故本项目贡献者对用户的一切输入以及模型不知情,因此不对任何用户输入负责。 **本项目也没有附带任何模型,任何二次发布所附带的模型以及用于此项目的模型均与此项目开发者无关。** ## 说明 本项目目前已完全支持自行调用其中方法来实现命令行推理或其他软件,欢迎大家向本项目提PR 作者的其他项目:[AiToolKits](https://github.com/NaruseMioShirakana/ShirakanaNoAiToolKits) 如果想要参加开发,可以加入QQ群:263805400或直接提PR **模型需要转换为ONNX模型,详情见你选择的项目的源仓库,PTH模型不能直接使用!!!!!!!!!!!!!** ## 分支 本项目的各分支: - [MoeVoiceStudioCore(主分支)](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore) 项目核心 - [MoeVoiceStudio](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudio) 本项目的简单GUI实现 基于qt - [MoeSSV2](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/V2) 旧版MoeSSV2版本存档 - [MoeSSV1](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/V2) 旧版MoeSSV1版本存档 ## FAQ ### Q: 项目名的来历?
A: > XP至上主义者狂喜,有谁不喜欢龙娘呢
### Q: 这个项目到底有什么作用?
A: > 这个项目的开发初衷主要是实现无需环境部属各个语音合成项目,而现在打算制作为一个SVC的辅助编辑器。 > > 由于这个项目毕竟是一个"个人的" "不专业"的项目,所以在您拥有更专业的软件,或者您是Python Cli爱好者,又或者您是相关领域大佬。我自知本软件不够专业且很大可能无法满足您的需求甚至对您没有用处。 > > 本项目并不是不可替代的项目,相反的本项目的功能您可以使用各种工具替代,我没有奢望本项目成为相关领域的领军项目,我只是怀着一腔热情继续着该项目的开发。但是热情总有消散的一天,但是该项目承诺在我的开 > 发热情完全消散之前会一直保持维护(不管有没有人使用,就算用户数目为0) > > 本项目在设计上可能存在着各种各样的问题,所以也是需要大家积极的点炒饭来帮助我完善功能的,大部分对于功能和体验的优化我都会接受。
### Q: 该项目以后会收费吗?
A: > 该项目永久开源免费,如果在其他地方存在本项目的收费版本,请立即举报且不要购买,本项目永久免费。如果想用疯狂星期四塞满白叶,可以前往爱发癫 https://afdian.net/a/NaruseMioShirakana >
### Q: 是否提供有偿模型代训练?
A: > 不提供,训练模型比较简单,没必要花冤枉钱,按照网上教程一步一步走就可以了。
### Q: 电子垃圾评判标准是什么?
A: > 1. 原创度。自己的东西在整个项目中的比例(对于AI来说,使用完全由你独立训练模型的创作属于你自己;使用他人模型的创作属于别人)。涵盖的方面包括但不限于程序、美工、音频、策划等等。举个例子,套用Unity等引擎模板换皮属于电子垃圾。 > 2. 开发者态度。作者开发的态度是不是捞一波流量和钱走人或单纯虚荣。比方说打了无数的tag,像什么“国产”“首个”“最强”“自制”这种引流宣传,结果是非常烂或是平庸的东西,且作者明显没有好好制作该项目的想法,属于电子垃圾。 > 3. 反对一切使用未授权的数据集训练出来的AI模型商用的行为。
### Q: 技术支持?
A: > 如果能够确定你做的不是电子垃圾,同时合法合规,没有严重的政治错误,我会提供一些力所能及的技术支持。
## 注意事项 ### 由于OnnxRuntime引发的问题 不支持中文路径?实际上项目本体是支持中文路径的,不过2023年3月前版本的OnnxRuntime是不支持中文路径的,因为这些版本的OnnxRuntime使用了Win32Api的A系列函数,A系列函数都是不支持非ANSI编码的路径的。这个问题并不是我能够解决的也不是我应该解决的,只有微软官方才可以修复这个BUG,不过好在最新的OnnxRuntime使用了W系列函数,解决了中文路径问题。 ### Cuda版本问题 由于Cuda有着极差的兼容性,导致一个基于Cuda的程序在使用时,必须安装和编译该程序时相同或是未修改Api最近版本的Cuda。这个问题只能等英伟达公司重视兼容性了。 ## 使用方法 MoeVoiceStudioCore以Lib的形式提供 使用C++语言调用 按需引用以下对应的类 ```cpp #include #include #include #include #include InferClass::Tacotron2; InferClass::Vits; InferClass::VitsSvc; InferClass::DiffusionSvc; InferClass::DiffusionSinger; /* 构造函数第一个是配置文件json 第二个是进度条回调 第三个是参数回调 (若为TTS 此参数为空即可) 第四个参数为设备 使用调用Inference函数即可 */ ``` 模型配置请参见[#模型配置](#模型配置) demo: [RVC命令行示例](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore/CMD-RVC-Onnx-Inference) ## 模型配置 ### 前置模型 #### 与所支持的几个项目无关 为深度学习领域的通用模型 停止更新(由于下载和上传速度): [Vocoder & HiddenUnitBert](https://github.com/NaruseMioShirakana/RequireMent-Model-For-MoeSS) 停止更新(由于HuggingFace被墙) : [HuggingFace](https://huggingface.co/NaruseMioShirakana/MoeSS-SUBModel) 最新仓库:[Openi](https://openi.pcl.ac.cn/Shirakana/SubModel) 自己导出前置: - HuBert:`input_names`应该为`["source"]`,`output_names`应该为`["embed"]`,`dynamic_axes`应当为`{"source":[0,2],}` - Diffusion模型使用的hifigan:`input_names`应该为`["c","f0"]`,`output_names`应该为`["audio"]`,`dynamic_axes`应当为`{"c":[0,1],"f0":[0,1],}` - Tacotron2使用的hifigan:`input_names`应该为`["x"]`,`output_names`应该为`["audio"]`,`dynamic_axes`应当为`{"x":[0,1],}` Vec模型和Hubert模型放在Hubert文件夹下,Hifigan模型放在Hifigan文件夹下 如需使用FCPE或RMVPE这两个F0预测器,则需要在根目录创建F0Predictor文件夹并将onnx模型放置在其中 ## 配置文件 - 本项目标准化了模型读取模块,模型保存在Mods文件夹下的子文件夹中。`xxx.json` 为模型的配置文件,需要自行按照模板编写,同时需要自行将模型转换为Onnx。 #### 通用参数(不管是啥模型都必须填的,不填就不识别): - `Folder`:保存模型的文件夹名 - `Name`:模型在UI中的显示名称 - `Type`:模型类别 - `Rate`:采样率(必须和你训练时候的一模一样,不明白原因建议去学计算机音频相关的知识) ### 配置示例
Tacotron2: ```jsonc { "Folder" : "Atri", "Name" : "亚托莉-Tacotron2", "Type" : "Tacotron2", "Rate" : 22050, "Symbol" : "_-!'(),.:;? ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "Cleaner" : "", "AddBlank": false, "Hifigan": "hifigan" } //Symbol:模型的Symbol,不知道Symbol是啥的建议多看几个视频了解了解TTS的基础知识,这一项在Tacotron2中必须填。 //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hifigan:Hifigan模型名,必须填且必须将在前置模型中下载到的hifigan放置到hifigan文件夹 //AddBlank:是否在音素之间插0作为分隔 ```
Vits: ```jsonc { "Folder" : "SummerPockets", "Name" : "SummerPocketsReflectionBlue", "Type" : "Vits", "Rate" : 22050, "Symbol" : "_,.!?-~…AEINOQUabdefghijkmnoprstuvwyzʃʧʦ↓↑ ", "Cleaner" : "", "AddBlank": true, "Emotional" : true, "EmotionalPath" : "all_emotions", "Characters" : ["鳴瀬しろは","空門蒼","鷹原うみ","紬ヴェンダース","神山識","水織静久","野村美希","久島鴎","岬鏡子"] } //Symbol:模型的Symbol,不知道Symbol是啥的建议多看几个视频了解了解TTS的基础知识,这一项在Vits中必须填。 //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //AddBlank:是否在音素之间插0作为分隔(大多数Vits模型必须为true) //Emotional:是否加入情感向量 //EmotionalPath:情感向量npy文件名 ```
Pits: ```jsonc { "Folder" : "SummerPockets", "Name" : "SummerPocketsReflectionBlue", "Type" : "Pits", "Rate" : 22050, "Symbol" : "_,.!?-~…AEINOQUabdefghijkmnoprstuvwyzʃʧʦ↓↑ ", "Cleaner" : "", "AddBlank": true, "Emotional" : true, "EmotionalPath" : "all_emotions", "Characters" : ["鳴瀬しろは","空門蒼","鷹原うみ","紬ヴェンダース","神山識","水織静久","野村美希","久島鴎","岬鏡子"] } //Symbol:模型的Symbol,不知道Symbol是啥的建议多看几个视频了解了解TTS的基础知识,这一项在Vits中必须填。 //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //AddBlank:是否在音素之间插0作为分隔(大多数Pits模型必须为true) //Emotional:是否加入情感向量 //EmotionalPath:情感向量npy文件名 ```
RVC: ```jsonc { "Folder" : "NyaruTaffy", "Name" : "NyaruTaffy", "Type" : "RVC", "Rate" : 40000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert4.0", "Diffusion": false, "CharaMix": true, "Volume": false, "SoVits2": true, "ShallowDiffusion" : "NyaruTaffy" "HiddenSize": 256, "Cluster": "Index" "Characters" : ["Taffy","Nyaru"] } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Diffusion:是否为DDSP仓库下的扩散模型 //CharaMix:是否使用角色混合轨道 //ShallowDiffusion:SoVits浅扩散模型,须填写ShallowDiffusion模型配置文件名(不带后缀和完整路径),小显存或内存下速度巨慢,效果未知,请根据实际情况决定是否使用) //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) //Cluster:聚类类型,包括"KMeans"和"Index",KMeans需要前往SoVits仓库将KMeans文件导出为可用格式,放置到模型文件夹;Index同理,需要前往SoVits仓库导出为可用格式(如果是RVC的单角色Index只需要改名为Index-0.index)然后放置到模型文件夹下(有几个角色就有几个Index文件) ```
SoVits_3.0_32k: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 32000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert", "SoVits3": true, "ShallowDiffusion" : "NyaruTaffy" "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Cluster": "KMeans" "Characters" : ["Taffy","Nyaru"] } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Diffusion:是否为DDSP仓库下的扩散模型 //ShallowDiffusion:SoVits浅扩散模型,须填写ShallowDiffusion模型配置文件名(不带后缀和完整路径),小显存或内存下速度巨慢,效果未知,请根据实际情况决定是否使用) //CharaMix:是否使用角色混合轨道 //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) //Cluster:聚类类型,包括"KMeans"和"Index",KMeans需要前往SoVits仓库将KMeans文件导出为可用格式,放置到模型文件夹;Index同理,需要前往SoVits仓库导出为可用格式(如果是RVC的单角色Index只需要改名为Index-0.index)然后放置到模型文件夹下(有几个角色就有几个Index文件) ```
SoVits_3.0_48k: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 48000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert", "SoVits3": true, "ShallowDiffusion" : "NyaruTaffy" "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Cluster": "KMeans" "Characters" : ["Taffy","Nyaru"] } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Diffusion:是否为DDSP仓库下的扩散模型 //ShallowDiffusion:SoVits浅扩散模型,须填写ShallowDiffusion模型配置文件名(不带后缀和完整路径),小显存或内存下速度巨慢,效果未知,请根据实际情况决定是否使用) //CharaMix:是否使用角色混合轨道 //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) //Cluster:聚类类型,包括"KMeans"和"Index",KMeans需要前往SoVits仓库将KMeans文件导出为可用格式,放置到模型文件夹;Index同理,需要前往SoVits仓库导出为可用格式(如果是RVC的单角色Index只需要改名为Index-0.index)然后放置到模型文件夹下(有几个角色就有几个Index文件) ```
SoVits_4.0: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hubert": "hubert4.0", "SoVits4.0V2": false, "ShallowDiffusion" : "NyaruTaffy" "Diffusion" : false, "CharaMix" : true, "Volume" : false, "HiddenSize" : 256, "Cluster" : "KMeans" "Characters" : ["Taffy","Nyaru"] } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Diffusion:是否为DDSP仓库下的扩散模型 //ShallowDiffusion:SoVits浅扩散模型,须填写ShallowDiffusion模型配置文件名(不带后缀和完整路径),小显存或内存下速度巨慢,效果未知,请根据实际情况决定是否使用) //CharaMix:是否使用角色混合轨道 //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) //Cluster:聚类类型,包括"KMeans"和"Index",KMeans需要前往SoVits仓库将KMeans文件导出为可用格式,放置到模型文件夹;Index同理,需要前往SoVits仓库导出为可用格式(如果是RVC的单角色Index只需要改名为Index-0.index)然后放置到模型文件夹下(有几个角色就有几个Index文件) //SoVits4.0V2: 是否为SoVits4.0V2模型 ```
DiffSVC: ```jsonc { "Folder" : "DiffShiroha", "Name" : "白羽", "Type" : "DiffSvc", "Rate" : 44100, "Hop" : 512, "MelBins" : 128, "Cleaner" : "", "Hifigan": "nsf_hifigan", "Hubert": "hubert", "Characters" : [], "Pndm" : 100, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "V2" : true } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //MelBins:模型的MelBins,不知道MelBins是啥的建议多看几个视频了解了解梅尔基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Hifigan:Hifigan模型名,必须填且必须将在前置模型中下载到的nsf_hifigan放置到hifigan文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Pndm:加速倍数,如果是V1模型则必填且必须为导出时设置的加速倍率 //V2:是否为V2模型,V2模型就是后来我分4个模块导出的那个 //Diffusion:是否为DDSP仓库下的扩散模型 //CharaMix:是否使用角色混合轨道 //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) ```
DiffSinger: ```jsonc { "Folder" : "utagoe", "Name" : "utagoe", "Type" : "DiffSinger", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hifigan": "singer_nsf_hifigan", "Characters" : [], "MelBins" : 128 } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hifigan:Hifigan模型名,必须填且必须将在前置模型中下载到的singer_nsf_hifigan放置到hifigan文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //MelBins:模型的MelBins,不知道MelBins是啥的建议多看几个视频了解了解梅尔基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) ```
BertVits: ```jsonc { "Folder": "HimenoSena", "Name": "HimenoSena", "Type": "BertVits", "Symbol": [ "_", "AA", "E", "EE", "En", "N", "OO", "V", "a", "a:", "aa", "ae", "ah", "ai", "an", "ang", "ao", "aw", "ay", "b", "by", "c", "ch", "d", "dh", "dy", "e", "e:", "eh", "ei", "en", "eng", "er", "ey", "f", "g", "gy", "h", "hh", "hy", "i", "i0", "i:", "ia", "ian", "iang", "iao", "ie", "ih", "in", "ing", "iong", "ir", "iu", "iy", "j", "jh", "k", "ky", "l", "m", "my", "n", "ng", "ny", "o", "o:", "ong", "ou", "ow", "oy", "p", "py", "q", "r", "ry", "s", "sh", "t", "th", "ts", "ty", "u", "u:", "ua", "uai", "uan", "uang", "uh", "ui", "un", "uo", "uw", "v", "van", "ve", "vn", "w", "x", "y", "z", "zh", "zy", "!", "?", "\u2026", ",", ".", "'", "-", "SP", "UNK" ], "Cleaner": "", "Rate": 44100, "CharaMix": true, "Characters": [ "\u56fd\u89c1\u83dc\u5b50", "\u59ec\u91ce\u661f\u594f", "\u65b0\u5802\u5f69\u97f3", "\u56db\u6761\u51db\u9999", "\u5c0f\u97a0\u7531\u4f9d" ], "LanguageMap": { "ZH": [ 0, 0 ], "JP": [ 1, 6 ], "EN": [ 2, 8 ] }, "Dict": "BasicDict", "BertPath": [ "chinese-roberta-wwm-ext-large", "deberta-v2-large-japanese", "bert-base-japanese-v3" ] } ```
## 支持的项目 ```cmake // ${xxx}是什么意思大家应该都知道吧,总之以下是多个不同项目需要的模型文件(需要放置在对应的模型文件夹下)。 // Tacotron2: ${Folder}_decoder_iter.onnx ${Folder}_encoder.onnx ${Folder}_postnet.onnx // Vits: 单角色VITS ${Folder}_dec.onnx ${Folder}_flow.onnx ${Folder}_enc_p.onnx ${Folder}_dp.onnx // Vits: 多角色VITS ${Folder}_dec.onnx ${Folder}_emb.onnx ${Folder}_flow.onnx ${Folder}_enc_p.onnx ${Folder}_dp.onnx // SoVits: ${Folder}_SoVits.onnx // RVC: ${Folder}_RVC.onnx // DiffSvc: ${Folder}_diffSvc.onnx // DiffSvc: V2 ${Folder}_encoder.onnx ${Folder}_denoise.onnx ${Folder}_pred.onnx ${Folder}_after.onnx // DiffSinger: OpenVpiVersion ${Folder}_diffSinger.onnx // DiffSinger: ${Folder}_encoder.onnx ${Folder}_denoise.onnx ${Folder}_pred.onnx ${Folder}_after.onnx ``` ## 其他设置 ### Symbol 例如:_-!'(),.:;? ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 打开你训练模型的项目,打开text\symbol.py,如图按照划线的List顺序将上面的4个字符串连接即可 ![image](https://user-images.githubusercontent.com/40709280/183290732-dcb93323-1061-431b-aafa-c285a3ec5e82.png) ### Cleaner ```cxx /* Cleaner请放置于根目录的Cleaners文件夹内,应该是一个按照要求定义的动态库(.dll),dll应当命名为Cleaner名,Cleaner名即为模型定义Json文件中Cleaner一栏填写的内容。 所有的插件dll需要定义以下函数,函数名必须为PluginMain,Dll名必须为插件名(或Cleaner名): */ const wchar_t* PluginMain(const wchar_t*); // 该接口只要求输入输出一致,并不要求功能一致,也就是说,你可以在改Dll中实现任何想要的功能,比方说ChatGpt,机器翻译等等。 // 以ChatGpt为例,PluginMain函数传入了一个输入字符串input,将该输入传入ChatGpt,再将ChatGpt的输出传入PluginMain,最后返回输出。 wchar_t* PluginMain(wchar_t* input){ wchar_t* tmpOutput = ChatGpt(input); return Clean(tmpOutput); } // 注意:导出dll时请使用 extern "C" 关键字来防止C++语言的破坏性命名。 ``` ## 本地编译 ```cxx git clone https://github.com/NaruseMioShirakana/MoeVoiceStudio.git //自行配置OnnxRuntime和FFMPEG的Dll //使用VisualStudio构建 ``` ## 依赖列表 - [FFmpeg](https://ffmpeg.org/) - [World](https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder) - [rapidJson](https://github.com/Tencent/rapidjson) - [mecab](https://github.com/taku910/mecab) - [yyjson](https://github.com/ibireme/yyjson) - [onnxruntime](https://github.com/microsoft/onnxruntime) - [faiss](https://github.com/facebookresearch/faiss) - [中文词典](https://www.zdic.net/) ## 📚 相关法规 #### 使用该项目的任何组织或个人都应当遵守包括但不限于以下的法律。 #### 《民法典》 ##### 第一千零一十九条 任何组织或者个人不得以丑化、污损,或者利用信息技术手段伪造等方式侵害他人的肖像权。未经肖像权人同意,不得制作、使用、公开肖像权人的肖像,但是法律另有规定的除外。 未经肖像权人同意,肖像作品权利人不得以发表、复制、发行、出租、展览等方式使用或者公开肖像权人的肖像。 对自然人声音的保护,参照适用肖像权保护的有关规定。 ##### 第一千零二十四条 【名誉权】民事主体享有名誉权。任何组织或者个人不得以侮辱、诽谤等方式侵害他人的名誉权。 ##### 第一千零二十七条 【作品侵害名誉权】行为人发表的文学、艺术作品以真人真事或者特定人为描述对象,含有侮辱、诽谤内容,侵害他人名誉权的,受害人有权依法请求该行为人承担民事责任。 行为人发表的文学、艺术作品不以特定人为描述对象,仅其中的情节与该特定人的情况相似的,不承担民事责任。 #### 《[中华人民共和国宪法](http://www.gov.cn/guoqing/2018-03/22/content_5276318.htm)》 #### 《[中华人民共和国刑法](http://gongbao.court.gov.cn/Details/f8e30d0689b23f57bfc782d21035c3.html?sw=%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E5%88%91%E6%B3%95)》 #### 《[中华人民共和国民法典](http://gongbao.court.gov.cn/Details/51eb6750b8361f79be8f90d09bc202.html)》 # MoeSS使用的图像素材来源于: - [SummerPockets](http://key.visualarts.gr.jp/summer/) ## 💪 感谢所有贡献者的努力 ================================================ FILE: CSharpDemo/README_en.md ================================================ ## Note: TTS & SVS Support:[MoeVoiceStudio](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudio) [MoeVoiceStudioCore](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore). # MoeVoiceStudio | [Chinese](README.md) | [English](README_en.md) This project is a voice assistant software focused on the Otaku subculture and targeted at anime fans.
Supported Frameworks: - [DeepLearningExamples](https://github.com/NVIDIA/DeepLearningExamples) - [VITS](https://github.com/jaywalnut310/vits) - [SoVits](https://github.com/svc-develop-team/so-vits-svc) - [DiffSvc](https://github.com/prophesier/diff-SVC) - [DiffSinger](https://github.com/openvpi/DiffSinger) - [RVC](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) - [FishDiffusion](https://github.com/fishaudio/fish-diffusion)
## Contents - [User Agreement](#user-agreement) - [Disclaimer](#disclaimer) - [Description](#description) - [Branches](#branches) - [FAQ](#faq) - Q: [What is the purpose of this project?](#q-what-is-the-purpose-of-this-project) - Q: [Will this project charge fees in the future?](#q-will-this-project-be-charged-in-the-future) - Q: [Do you provide paid model training?](#q-do-you-provide-paid-model-training) - Q: [What are the criteria for digital garbage?](#q-what-are-the-criteria-for-digital-garbage) - Q: [Technical support?](#q-technical-support) - [Notes](#notes) - [Usage](#usage) - [Model Configuration](#model-configuration) - [Pre-models](#pre-models) - [Configuration File](#configuration-file) - [Supported Projects](#supported-projects) - [Other Settings](#other-settings) - [Symbol](#symbol) - [Cleaner](#cleaner) - [Build](#build) - [List of dependencies](#list-of-dependencies) - [Relevant Regulations](#relevant-regulations) ## User Agreement: ### To use this project, you must agree to the following terms. If you do not agree, you are prohibited from using this project: 1. You must bear all the consequences caused by using this project. 2. It is forbidden to sell this program. 3. When using this project, you must conscientiously abide by local laws and regulations, and it is forbidden to use this project for illegal activities. 4. It is forbidden to use for any commercial games, low-creation games[^1], and Galgame production, but non-commercial high-quality game and Mod production are acceptable. 5. It is forbidden to use this project and its derivatives, and the release of models, etc., to produce various electronic wastes[^2] (such as AIGalgame, AI game production, etc.). 6. All political-related content is prohibited. 7. All content generated by using this project has nothing to do with the developers of this project. [^1]: The criteria for low creativity are: any content generated in large amounts by AI, with low original content, unclear meaning, low quality of content, etc. [^2]: Criteria for digital garbage are: Originality. The proportion of your own work in the entire project (for AI, creations using models trained completely independently by you belong to you; creations using others' models belong to others). Aspects covered include but are not limited to programming, art, audio, planning, etc. For example, reskinning using templates from engines like Unity is considered digital garbage. ## Disclaimer This project is an **open-source, offline project. All developers and maintainers (hereinafter referred to as contributors) of this project have no control over it**. The contributors to this project have never provided any form of help to any organization or individual, including but not limited to data set extraction, data set processing, computational power support, training support, inference, etc. The contributors of this project are unaware and cannot be aware of the purpose of the user's use of the project. Therefore, all audio synthesized based on this project is unrelated to the contributors of this project. **Any problems arising from this will be borne by the users themselves**. This project itself does not have any speech synthesis capabilities, all functions need to be trained by the user themselves and convert into Onnx models, and the training of the model and Converted Onnx models are unrelated to the contributors of this project, all are the actions of the user themselves, and the contributors of this project have not participated in any user's model training and production. This project runs completely offline, it cannot collect any user information, nor can it get user input data, so the contributors of this project are unaware of all user input and the model, and therefore are not responsible for any user input. **This project does not come with any models, any models attached to any secondary release and models used for this project are unrelated to the developers of this project.** ## Description This project currently fully supports calling its own methods to achieve command-line inference or other software, and everyone is welcome to contribute PRs to this project. The author's other projects: [AiToolKits](https://github.com/NaruseMioShirakana/ShirakanaNoAiToolKits) If you want to participate in development, you can join QQ group: 263805400 or directly open Push Requests. **Models need to be converted into ONNX models, the program for converting ONNX has already been pulled to each project's source repository, PTH cannot be used directly!!!!!!!!!!!!!!!!!!!** ## Branches The branches of this project: - [MoeVoiceStudioCore(main branch)](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore) Project core - [MoeVoiceStudio](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudio) A simple GUI implementation of this project based on QT - [MoeSSV2](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/V2) Old version of MoeSS V2 version archive - [MoeSSV1](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/V1) Old version of MoeSS V1 version archive ## FAQ ### Q: What is the purpose of this project?
A: > The original intention of this project's development is mainly to implement various speech synthesis projects without the need for environment deployment, and now it is planned to be made into an auxiliary editor of SVC. Because this project is after all a "personal" "non-professional" project, so if you have more professional software, or you are a Python Cli lover, or you are a big shot in the relevant field. I know that this software is not professional enough and is very likely to be unable to meet your needs or even useless to you. This project is not an irreplaceable project, on the contrary, you can use various tools to replace the functions of this project, I have no extravagant hopes that this project will become a leading project in the relevant field, I am just continuing the development of this project with enthusiasm. But passion always has a day to dissipate, but the project promises to keep maintenance as long as my development passion has not completely dissipated (regardless of whether there are any users, even if the number of users is 0). > > There may be various problems in the design of this project, so we also need everyone to actively point out to help me improve the functionality. Most optimizations for functionality and experience I will accept. > > Finally, let me say one more thing about my view of this project: MoeSS and MoeVS are relying on the defense.
### Q: Will this project be charged in the future?
A: > This project will remain open-source and free forever, if there are paid versions of this project elsewhere, please report immediately and do not purchase, this project is always free. If you want to donate the developer, you can go to Shirakana's Afdian site: https://afdian.net/a/NaruseMioShirakana .
### Q: Do you provide paid model training?
A: > No, training models is relatively simple, there is no need to waste money, just follow the online tutorials step by step.
### Q: What are the criteria for digital garbage?
A: > Originality. Your own work's proportion in the entire project (for AI, creations using completely independently trained models by you belong to you; creations using models from others belong to others). This includes but is not limited to programming, art, audio, planning, etc. For example, reskinning using templates from engines like Unity is considered digital garbage. Developer's attitude. Whether the author's development attitude is to gain traffic and money and leave, or purely vanity. For example, using a lot of tags like "domestic", "first", "strongest", "homemade" for traffic attraction, but the result is very bad or mediocre work, and the author obviously does not have a good idea to make the project, this is considered digital garbage. We oppose all commercial use of AI models trained using unauthorized datasets.
### Q: Technical support?
A: > If I can confirm that what you're doing is not digital garbage, is legal and compliant, and does not have serious political errors, I will provide some technical support within my capacity.
## Notes ### Due to issues raised by OnnxRuntime For using GPU (CUDA) version, please install CUDA driver version between 11.0 and 12.0, and CUDNN dynamic library version below 83.0, following the tutorials available online. Why such requirements? That would be a question for NVIDIA, the company behind CUDA, CUDNN, and the OnnxRuntime officials. Both issues are caused by certain features of CUDA driver and problems with OnnxRuntime. What's the reason for the previous versions not supporting Chinese paths? Actually, it's just a manifestation of the above issue. The project itself supports Chinese paths, but its underlying OnnxRuntime doesn't, because the Windows version of OnnxRuntime uses the A series functions of Win32Api, and the A series functions do not support paths with non-ANSI encoding. This issue is not something I can solve, nor should I. Only when the OnnxRuntime officials fix this bug can it be resolved. Fortunately, the latest OnnxRuntime uses W series functions, solving this problem with Chinese paths. Errors popping up when loading the model are caused by the above issues (mainly due to not installing CUDA and CUDNN or not installing them as required). If these issues are triggered, you can go to the Onnx official repository's Issue page at https://github.com/microsoft/onnxruntime to find solutions. It's recommended to use the CPU version, as its inference speed is quite impressive and it doesn't have other problems. ## Usage MoeVoiceStudioCore is provided as a library, to be called with C++. Refer to the following corresponding classes as needed: ```cpp #include #include #include #include #include InferClass::Tacotron2; InferClass::Vits; InferClass::VitsSvc; InferClass::DiffusionSvc; InferClass::DiffusionSinger; /* The first parameter of the constructor is the JSON configuration file, the second one is a callback for the progress bar, the third one is a callback for parameters (if for TTS, this can be left empty), and the fourth one is the device. You can call the Inference function to use it. */ ``` For model configuration, please refer to [#Model Configuration](#Model Configuration) Demo: [RVC command-line example](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore/CMD-RVC-Onnx-Inference) ## Model Configuration ### Pre-models #### Not related to the few projects we support, they are universal models in the deep learning domain Stopped updating (due to download and upload speeds): [Vocoder & HiddenUnitBert](https://github.com/NaruseMioShirakana/RequireMent-Model-For-MoeSS) Latest repository: [HuggingFace](https://huggingface.co/NaruseMioShirakana/MoeSS-SUBModel) Export frontend yourself: - HuBert: `input_names` should be `["source"]`, `output_names` should be `["embed"]`, `dynamic_axes` should be `{" source":[0,2],}` - Hifigan used by the Diffusion model: `input_names` should be `["c","f0"]`, `output_names` should be `["audio"]`, `dynamic_axes` should be `{"c":[0,1],"f0":[0,1],}` - Hifigan used by Tacotron2: `input_names` should be `["x"]`, `output_names` should be `["audio"]`, `dynamic_axes` should be `{"x":[0,1],}` ## Configuration File - This project has standardized the model loading module, the models are saved in subfolders under the Mods folder. `xxx.json` is the configuration file for the model, which needs to be written manually according to the template, and the model needs to be converted to Onnx manually. #### Universal Parameters (These are mandatory for any model. If not filled, it won't be recognized): - `Folder`: The folder name where the model is stored - `Name`: The display name of the model in UI - `Type`: The category of the model - `Rate`: Sample rate (it must be exactly the same as when you trained, if you don't understand why, you are recommended to learn about computer audio related knowledge) ### Examples Notice: `Diff-SVC` model and `Diffusion-SVC` model are basically **NOT** the same model, and the same applies to the `Fish-Diffusion` model, though all of them are based on the Diffusion algorithm.
Tacotron2: ```jsonc { "Folder" : "Atri", "Name" : "ATRI-Tacotron2", "Type" : "Tacotron2", "Rate" : 22050, "Symbol" : "_-!'(),.:;? ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "Cleaner" : "", "AddBlank": false, "Hifigan": "hifigan" } //Symbol:Symbol of the model,If you don't know what it is, you are advised to check the TTS information on the internet.This field must be filled in the Tacotron2 model's configuration file. //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hifigan:Hifigan model name, required and must be placed in the "hifigan" folder for hifigan model downloaded from the Pre-model repository //AddBlank:Whether to insert a 0 as a separator between phonemes ```
Vits: ```jsonc { "Folder" : "SummerPockets", "Name" : "SummerPocketsReflectionBlue", "Type" : "Vits", "Rate" : 22050, "Symbol" : "_,.!?-~…AEINOQUabdefghijkmnoprstuvwyzʃʧʦ↓↑ ", "Cleaner" : "", "AddBlank": true, "Emotional" : true, "EmotionalPath" : "all_emotions", "Characters" : ["鳴瀬しろは","空門蒼","鷹原うみ","紬ヴェンダース","神山識","水織静久","野村美希","久島鴎","岬鏡子"] } //Symbol:Symbol of the model,If you don't know what it is, you are advised to check the TTS information on the internet.This field must be filled in the VITS model's configuration file. //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //AddBlank:Whether to insert a 0 as a separator between phonemes(For most VITS models, you must set this to "true"..) //Emotional:whether to add a emotional vector //EmotionalPath:emotional vector file(.npy) path ```
Pits: ```jsonc { "Folder" : "SummerPockets", "Name" : "SummerPocketsReflectionBlue", "Type" : "Pits", "Rate" : 22050, "Symbol" : "_,.!?-~…AEINOQUabdefghijkmnoprstuvwyzʃʧʦ↓↑ ", "Cleaner" : "", "AddBlank": true, "Emotional" : true, "EmotionalPath" : "all_emotions", "Characters" : ["鳴瀬しろは","空門蒼","鷹原うみ","紬ヴェンダース","神山識","水織静久","野村美希","久島鴎","岬鏡子"] } //Symbol:Symbol of the model,If you don't know what it is, you are advised to check the TTS information on the internet.This field must be filled in the VITS model's configuration file. //Cleaner:The name of the plugin, can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //AddBlank:Whether to insert a 0 as a separator between phonemes(For most VITS models, you must set this to "true"..) //Emotional:whether to add a emotional vector //EmotionalPath:emotional vector file(.npy) path ```
RVC: ```jsonc { "Folder" : "NyaruTaffy", "Name" : "NyaruTaffy", "Type" : "RVC", "Rate" : 40000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert4.0", "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Characters" : ["Taffy","Nyaru"] } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
SoVits_3.0_32k: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 32000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert", "SoVits3": true, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Characters" : ["Taffy","Nyaru"] } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
SoVits_3.0_48k: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 48000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert", "SoVits3": true, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Characters" : ["Taffy","Nyaru"] } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
SoVits_4.0: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hubert": "hubert4.0", "SoVits4": true, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Characters" : ["Taffy","Nyaru"] } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
DiffSVC: ```jsonc { "Folder" : "DiffShiroha", "Name" : "白羽", "Type" : "DiffSvc", "Rate" : 44100, "Hop" : 512, "MelBins" : 128, "Cleaner" : "", "Hifigan": "nsf_hifigan", "Hubert": "hubert", "Characters" : [], "Pndm" : 100, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "V2" : true } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Melbins:Melbins of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the Diffsvc model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert models downloaded from the Pre-model repository //Hifigan:Hifigan model name, required and must be placed in the "hifigan" folder for nsf-hifigan model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Pndm:Acceleration multiplier, required in the case of V1 models and must be the acceleration multiplier set at the time of export //V2:If your diffsvc model is a V2 model(Fish-Diffusion model), set this to "true". //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
DiffSinger: ```jsonc { "Folder" : "utagoe", "Name" : "utagoe", "Type" : "DiffSinger", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hifigan": "singer_nsf_hifigan", "Characters" : [], "MelBins" : 128 } ```jsonc { "Folder" : "utagoe", "Name" : "utagoe", "Type" : "DiffSinger", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hifigan": "singer_nsf_hifigan", "Characters" : [], "MelBins" : 128 } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the Diffsinger model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Melbins:Melbins of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the Diffsvc model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hifigan:Hifigan model name, required and must be placed in the "hifigan" folder for nsf-hifigan model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out ```
BertVits: ```jsonc { "Folder": "HimenoSena", "Name": "HimenoSena", "Type": "BertVits", "Symbol": [ "_", "AA", "E", "EE", "En", "N", "OO", "V", "a", "a:", "aa", "ae", "ah", "ai", "an", "ang", "ao", "aw", "ay", "b", "by", "c", "ch", "d", "dh", "dy", "e", "e:", "eh", "ei", "en", "eng", "er", "ey", "f", "g", "gy", "h", "hh", "hy", "i", "i0", "i:", "ia", "ian", "iang", "iao", "ie", "ih", "in", "ing", "iong", "ir", "iu", "iy", "j", "jh", "k", "ky", "l", "m", "my", "n", "ng", "ny", "o", "o:", "ong", "ou", "ow", "oy", "p", "py", "q", "r", "ry", "s", "sh", "t", "th", "ts", "ty", "u", "u:", "ua", "uai", "uan", "uang", "uh", "ui", "un", "uo", "uw", "v", "van", "ve", "vn", "w", "x", "y", "z", "zh", "zy", "!", "?", "\u2026", ",", ".", "'", "-", "SP", "UNK" ], "Cleaner": "", "Rate": 44100, "CharaMix": true, "Characters": [ "\u56fd\u89c1\u83dc\u5b50", "\u59ec\u91ce\u661f\u594f", "\u65b0\u5802\u5f69\u97f3", "\u56db\u6761\u51db\u9999", "\u5c0f\u97a0\u7531\u4f9d" ], "LanguageMap": { "ZH": [ 0, 0 ], "JP": [ 1, 6 ], "EN": [ 2, 8 ] }, "Dict": "BasicDict", "BertPath": [ "chinese-roberta-wwm-ext-large", "deberta-v2-large-japanese", "bert-base-japanese-v3" ] } ```
## Supported Projects ```cxx // $Below are the model files needed for several different projects (they need to be placed in the corresponding model folders). // Tacotron2: ${Folder}_decoder_iter.onnx ${Folder}_encoder.onnx ${Folder}_postnet.onnx // Vits: Single-speaker VITS ${Folder}_dec.onnx ${Folder}_flow.onnx ${Folder}_enc_p.onnx ${Folder}_dp.onnx // Vits: multi-speaker VITS ${Folder}_dec.onnx ${Folder}_emb.onnx ${Folder}_flow.onnx ${Folder}_enc_p.onnx ${Folder}_dp.onnx // SoVits: ${Folder}_SoVits.onnx // DiffSvc: ${Folder}_diffSvc.onnx // DiffSvc: V2 ${Folder}_encoder.onnx ${Folder}_denoise.onnx ${Folder}_pred.onnx ${Folder}_after.onnx // DiffSinger: OpenVpiVersion ${Folder}_diffSinger.onnx // DiffSinger: ${Folder}_encoder.onnx ${Folder}_denoise.onnx ${Folder}_pred.onnx ${Folder}_after.onnx ``` ## Other Settings ### Symbol settings For example:_-!'(),.:;? ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz Open the project you are using to train the model, open text\symbol.py and join the 4 strings above in the order of the underlined list as shown ![image](https://user-images.githubusercontent.com/40709280/183290732-dcb93323-1061-431b-aafa-c285a3ec5e82.png) ### Cleaner settings ```cxx /* The Cleaner should be placed in the Cleaners folder in the root directory and should be a dynamic library (.dll) defined as required. The dll should be named Cleaner and the Cleaner name is what is entered in the "Cleaner" of the model configuration file. The following functions need to be defined for all plug-in dlls, the function name must be PluginMain and the Dll name must be the plug-in name (or Cleaner name). */ const wchar_t* PluginMain(const wchar_t*); // The interface only requires consistent input and output, not consistent functionality, which means that you can implement any functionality you want in the Dll, such as ChatGpt, translation, etc. // Using ChatGpt as an example, the PluginMain function passes in an input string input, passes that input into ChatGpt, passes ChatGpt's output into PluginMain, and finally returns the output. wchar_t* PluginMain(wchar_t* input){ wchar_t* tmpOutput = ChatGpt(input); return Clean(tmpOutput); } // Note: Please use the extern "C" keyword when exporting the dll to prevent destructive naming in C++. ``` ## Build ```cxx git clone https://github.com/NaruseMioShirakana/MoeVoiceStudio.git //Place OnnxRuntime.dll and FFMPEG's Dll in the correct folder //Build With VisualStudio ``` ## List of dependencies - [FFmpeg](https://ffmpeg.org/) - [World](https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder) - [rapidJson](https://github.com/Tencent/rapidjson) ## 📚 相关法规 #### Any country, region, organization, or individual using this project must comply with the following laws. #### 《民法典》 ##### 第一千零一十九条 任何组织或者个人不得以丑化、污损,或者利用信息技术手段伪造等方式侵害他人的肖像权。未经肖像权人同意,不得制作、使用、公开肖像权人的肖像,但是法律另有规定的除外。 未经肖像权人同意,肖像作品权利人不得以发表、复制、发行、出租、展览等方式使用或者公开肖像权人的肖像。 对自然人声音的保护,参照适用肖像权保护的有关规定。 ##### 第一千零二十四条 【名誉权】民事主体享有名誉权。任何组织或者个人不得以侮辱、诽谤等方式侵害他人的名誉权。 ##### 第一千零二十七条 【作品侵害名誉权】行为人发表的文学、艺术作品以真人真事或者特定人为描述对象,含有侮辱、诽谤内容,侵害他人名誉权的,受害人有权依法请求该行为人承担民事责任。 行为人发表的文学、艺术作品不以特定人为描述对象,仅其中的情节与该特定人的情况相似的,不承担民事责任。 #### 《[中华人民共和国宪法](http://www.gov.cn/guoqing/2018-03/22/content_5276318.htm)》 #### 《[中华人民共和国刑法](http://gongbao.court.gov.cn/Details/f8e30d0689b23f57bfc782d21035c3.html?sw=%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E5%88%91%E6%B3%95)》 #### 《[中华人民共和国民法典](http://gongbao.court.gov.cn/Details/51eb6750b8361f79be8f90d09bc202.html)》 # The image resource MoeVS used is derived from: - [SummerPockets](http://key.visualarts.gr.jp/summer/) ## 💪 Thanks to all contributors for their efforts ================================================ FILE: DotNetApi/DotNetApi.csproj ================================================  net8.0 enable enable True Debug;Release ================================================ FILE: DotNetApi/LibSvcApi.cs ================================================ using System; using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; using static LibSvcApi.LibSvc; using static System.Runtime.InteropServices.JavaScript.JSType; namespace LibSvcApi { public unsafe class FloatVector { private FloatVector() { } public FloatVector(void* _Obj) { Obj_ = _Obj; } public void* Object { get { return Obj_; } } public float* Data() { return LibSvcGetFloatVectorData(Obj_); } public ulong Size() { return LibSvcGetFloatVectorSize(Obj_); } [DllImport("libsvc.dll")] private static extern float* LibSvcGetFloatVectorData(void* _Obj); [DllImport("libsvc.dll")] private static extern ulong LibSvcGetFloatVectorSize(void* _Obj); private void* Obj_ = null; } public unsafe class DFloatVector { private DFloatVector() { } public DFloatVector(void* _Obj) { Obj_ = _Obj; } public FloatVector Data(ulong _Index) { return new FloatVector(LibSvcGetDFloatVectorData(Obj_, _Index)); } public FloatVector this[ulong i] => Data(i); public void* Object { get { return Obj_; } } public ulong Size() { return LibSvcGetDFloatVectorSize(Obj_); } [DllImport("libsvc.dll")] private static extern void* LibSvcGetDFloatVectorData(void* _Obj, ulong _Index); [DllImport("libsvc.dll")] private static extern ulong LibSvcGetDFloatVectorSize(void* _Obj); private void* Obj_ = null; } public unsafe class Int16Vector { public Int16Vector() { Obj_ = LibSvcAllocateAudio(); Owner_ = true; } public Int16Vector(void* _Obj) { Obj_ = _Obj; } ~Int16Vector() { if (Owner_) LibSvcReleaseAudio(Obj_); } public void* Object { get { return Obj_; } } public short* Data() { return LibSvcGetAudioData(Obj_); } public ulong Size() { return LibSvcGetAudioSize(Obj_); } public void Resize(ulong _Size) { LibSvcSetAudioLength(Obj_, _Size); } public void Insert(ref Int16Vector _Input) { LibSvcInsertAudio(Obj_, _Input.Object); } [DllImport("libsvc.dll")] private static extern short* LibSvcGetAudioData(void* _Obj); [DllImport("libsvc.dll")] private static extern ulong LibSvcGetAudioSize(void* _Obj); [DllImport("libsvc.dll")] private static extern void* LibSvcAllocateAudio(); [DllImport("libsvc.dll")] private static extern void LibSvcReleaseAudio(void* _Obj); [DllImport("libsvc.dll")] private static extern void LibSvcSetAudioLength(void* _Obj, ulong _Size); [DllImport("libsvc.dll")] private static extern void LibSvcInsertAudio(void* _ObjA, void* _ObjB); private void* Obj_ = null; private bool Owner_ = false; } public unsafe class UInt64Vector { public UInt64Vector() { Obj_ = LibSvcAllocateOffset(); Owner_ = true; } public UInt64Vector(void* _Obj) { Obj_ = _Obj; } ~UInt64Vector() { if (Owner_) LibSvcReleaseOffset(Obj_); } public void* Object { get { return Obj_; } } public ulong* Data() { return LibSvcGetOffsetData(Obj_); } public ulong Size() { return LibSvcGetOffsetSize(Obj_); } public void Resize(ulong _Size) { LibSvcSetOffsetLength(Obj_, _Size); } [DllImport("libsvc.dll")] private static extern ulong* LibSvcGetOffsetData(void* _Obj); [DllImport("libsvc.dll")] private static extern ulong LibSvcGetOffsetSize(void* _Obj); [DllImport("libsvc.dll")] private static extern void* LibSvcAllocateOffset(); [DllImport("libsvc.dll")] private static extern void LibSvcReleaseOffset(void* _Obj); [DllImport("libsvc.dll")] private static extern void LibSvcSetOffsetLength(void* _Obj, ulong _Size); private void* Obj_ = null; private bool Owner_ = false; } public unsafe class Mel { public Mel() { Obj_ = LibSvcAllocateMel(); Owner_ = true; } public Mel(void* _Obj) { Obj_ = _Obj; } ~Mel() { if (Owner_) LibSvcReleaseMel(Obj_); } public void* Object { get { return Obj_; } } public FloatVector MelData() { return new FloatVector(LibSvcGetMelData(Obj_)); } public long Size() { return LibSvcGetMelSize(Obj_); } [DllImport("libsvc.dll")] private static extern void* LibSvcGetMelData(void* _Obj); [DllImport("libsvc.dll")] private static extern long LibSvcGetMelSize(void* _Obj); [DllImport("libsvc.dll")] private static extern void* LibSvcAllocateMel(); [DllImport("libsvc.dll")] private static extern void LibSvcReleaseMel(void* _Obj); private void* Obj_ = null; private bool Owner_ = false; } public unsafe class Slice { private Slice() { } public Slice(void* _Obj) { Obj_ = _Obj; } public void* Object { get { return Obj_; } } public Int16Vector GetAudio() { return new Int16Vector(LibSvcGetAudio(Obj_)); } public FloatVector GetF0() { return new FloatVector(LibSvcGetF0(Obj_)); } public FloatVector GetVolume() { return new FloatVector(LibSvcGetVolume(Obj_)); } public DFloatVector GetSpeaker() { return new DFloatVector(LibSvcGetSpeaker(Obj_)); } public int SrcLength() { return LibSvcGetSrcLength(Obj_); } public bool IsNotMute() { return LibSvcGetIsNotMute(Obj_) != 0; } public void SetSpeakerMixDataCount(ulong _NSpeaker) { LibSvcSetSpeakerMixDataSize(Obj_, _NSpeaker); } [DllImport("libsvc.dll")] private static extern void* LibSvcGetAudio(void* _Obj); [DllImport("libsvc.dll")] private static extern void* LibSvcGetF0(void* _Obj); [DllImport("libsvc.dll")] private static extern void* LibSvcGetVolume(void* _Obj); [DllImport("libsvc.dll")] private static extern void* LibSvcGetSpeaker(void* _Obj); [DllImport("libsvc.dll")] private static extern int LibSvcGetSrcLength(void* _Obj); [DllImport("libsvc.dll")] private static extern int LibSvcGetIsNotMute(void* _Obj); [DllImport("libsvc.dll")] private static extern void LibSvcSetSpeakerMixDataSize(void* _Obj, ulong _NSpeaker); private void* Obj_ = null; } public unsafe class Slices { public Slices() { Obj_ = LibSvcAllocateSliceData(); Owner_ = true; } public Slices(void* _Obj) { Obj_ = _Obj; } ~Slices() { if (Owner_) LibSvcReleaseSliceData(Obj_); } public void* Object { get { return Obj_; } } public Slice GetSlice(ulong _Index) { return new Slice(LibSvcGetSlice(Obj_, _Index)); } public string GetAudioPath() { return LibSvcGetAudioPath(Obj_); } public ulong Size() { return LibSvcGetSliceCount(Obj_); } public Slice this[ulong i] => GetSlice(i); [DllImport("libsvc.dll")] private static extern void* LibSvcAllocateSliceData(); [DllImport("libsvc.dll")] private static extern void LibSvcReleaseSliceData(void* _Obj); [DllImport("libsvc.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.BStr)] private static extern string LibSvcGetAudioPath(void * _Obj); [DllImport("libsvc.dll")] private static extern void* LibSvcGetSlice(void* _Obj, ulong _Index); [DllImport("libsvc.dll")] private static extern ulong LibSvcGetSliceCount(void* _Obj); private void* Obj_ = null; private bool Owner_ = false; } public unsafe class ModelBase { protected ModelBase() { } [DllImport("libsvc.dll")] protected static extern int LibSvcInferSlice( void* _Model, uint _T, void* _Slice, ref Params _InferParams, ref ulong _Process, void* _Output ); [DllImport("libsvc.dll")] protected static extern int LibSvcUnloadModel( uint _T, void* _Model ); } public unsafe class VitsModel : ModelBase { private VitsModel() { } public VitsModel(void* _Obj) { Model_ = _Obj; } ~VitsModel() { if (LibSvcUnloadModel(0, Model_) == 0) return; throw new Exception(GetError(0)); } public Int16Vector Inference( Slice _Slice, ref Params _InferParams, ref ulong _Process ) { Int16Vector Ret = new(); if (LibSvcInferSlice(Model_, 0, _Slice.Object, ref _InferParams, ref _Process, Ret.Object) == 0) return Ret; throw new Exception(GetError(0)); } private void* Model_ = null; } public unsafe class UnionModel : ModelBase { private UnionModel() { } public UnionModel(void* _Obj) { Model_ = _Obj; } ~UnionModel() { if (LibSvcUnloadModel(1, Model_) == 0) return; throw new Exception(GetError(0)); } public void* GetModel() { return Model_; } public Int16Vector Inference( Slice _Slice, ref Params _InferParams, ref ulong _Process ) { Int16Vector Ret = new(); if (LibSvcInferSlice(Model_, 1, _Slice.Object, ref _InferParams, ref _Process, Ret.Object) == 0) return Ret; throw new Exception(GetError(0)); } public Int16Vector ShallowDiffusionInference( ref Int16Vector _16KAudioHubert, ref Mel _Mel, ref FloatVector _SrcF0, ref FloatVector _SrcVolume, ref DFloatVector _SrcSpeakerMap, long _SrcSize, ref Params _InferParams, ref ulong _Process ) { Int16Vector Ret = new(); if ( LibSvcShallowDiffusionInference( Model_, _16KAudioHubert.Object, _Mel.Object, _SrcF0.Object, _SrcVolume.Object, _SrcSpeakerMap.Object, _SrcSize, ref _InferParams, ref _Process, Ret.Object ) == 0 ) return Ret; throw new Exception(GetError(0)); } [DllImport("libsvc.dll")] private static extern int LibSvcShallowDiffusionInference( void* _Model, void* _16KAudioHubert, void* _Mel, void* _SrcF0, void* _SrcVolume, void* _SrcSpeakerMap, long _SrcSize, ref Params _InferParams, ref ulong _Process, void* _Output ); private void* Model_ = null; } public unsafe class VocoderModel { private VocoderModel() { } public VocoderModel(void* _Obj) { Model_ = _Obj; } ~VocoderModel() { if (LibSvcUnloadVocoder(Model_) == 0) return; throw new Exception(GetError(0)); } public void* GetModel() { return Model_; } public Int16Vector Inference( ref Mel _Mel, ref FloatVector _F0, int _VocoderMelBins ) { Int16Vector Ret = new(); if (LibSvcVocoderEnhance(Model_, _Mel.Object, _F0.Object, _VocoderMelBins, Ret.Object) == 0) return Ret; throw new Exception(GetError(0)); } [DllImport("libsvc.dll")] private static extern int LibSvcVocoderEnhance( void* Model, void* Mel, void* F0, int VocoderMelBins, void* _Output ); [DllImport("libsvc.dll")] private static extern int LibSvcUnloadVocoder(void* _Model); private void* Model_ = null; } public unsafe class LibSvc { public enum Device { CPU = 0, CUDA = 1, DML = 2 } [StructLayout(LayoutKind.Sequential, Pack = 4)] public unsafe struct SlicerSettings { public int SamplingRate = 48000; public double Threshold = 30; public double MinLength = 3; public int WindowLength = 2048; public int HopSize = 512; public SlicerSettings() { } }; [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] public unsafe struct Params { public Params() { } public float NoiseScale = 0.3f; //噪声修正因子 0-10 public long Seed = 52468; //种子 public long SpeakerId = 0; //角色ID public ulong SrcSamplingRate = 48000; //源采样率 public long SpkCount = 2; //模型角色数 public float IndexRate = 0; //索引比 0-1 public float ClusterRate = 0; //聚类比 0-1 public float DDSPNoiseScale = 0.8f; //DDSP噪声修正因子 0-10 public float Keys = 0; //升降调 -64-64 public ulong MeanWindowLength = 2; //均值滤波器窗口大小 1-20 public ulong Pndm = 100; //Diffusion加速倍数 1-200 public ulong Step = 1000; //Diffusion总步数 1-1000 public float TBegin = 0; public float TEnd = 1; //"Pndm" "DDim" [MarshalAs(UnmanagedType.LPWStr)] public string Sampler = "Pndm"; //Diffusion采样器 //"Eular" "Rk4" "Heun" "Pecece" [MarshalAs(UnmanagedType.LPWStr)] public string ReflowSampler = "Eular"; //Reflow采样器 //"Dio" "Harvest" "RMVPE" "FCPE" [MarshalAs(UnmanagedType.LPWStr)] public string F0Method = "Dio"; //F0提取算法 public int UseShallowDiffusion = 0; //使用浅扩散 public void* _VocoderModel = null; public void* _ShallowDiffusionModel = null; public int ShallowDiffusionUseSrcAudio = 1; public int VocoderHopSize = 512; public int VocoderMelBins = 128; public int VocoderSamplingRate = 44100; public long ShallowDiffuisonSpeaker = 0; public void SetVocoder(ref VocoderModel Vocoder) { _VocoderModel = Vocoder.GetModel(); } public void SetShallowDiffusion(ref UnionModel UnionMod) { _ShallowDiffusionModel = UnionMod.GetModel(); } }; [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] public unsafe struct DiffusionSvcPaths { public DiffusionSvcPaths() { } [MarshalAs(UnmanagedType.LPWStr)] public string Encoder = ""; [MarshalAs(UnmanagedType.LPWStr)] public string Denoise = ""; [MarshalAs(UnmanagedType.LPWStr)] public string Pred = ""; [MarshalAs(UnmanagedType.LPWStr)] public string After = ""; [MarshalAs(UnmanagedType.LPWStr)] public string Alpha = ""; [MarshalAs(UnmanagedType.LPWStr)] public string Naive = ""; [MarshalAs(UnmanagedType.LPWStr)] public string DiffSvc = ""; }; [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] public unsafe struct ReflowSvcPaths { public ReflowSvcPaths() { } [MarshalAs(UnmanagedType.LPWStr)] public string Encoder = ""; [MarshalAs(UnmanagedType.LPWStr)] public string VelocityFn = ""; [MarshalAs(UnmanagedType.LPWStr)] public string After = ""; }; [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] public unsafe struct VitsSvcPaths { public VitsSvcPaths() { } [MarshalAs(UnmanagedType.LPWStr)] public string VitsSvc = ""; }; [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] public unsafe struct LibSvcClusterConfig { public LibSvcClusterConfig() { } public long ClusterCenterSize = 10000; [MarshalAs(UnmanagedType.LPWStr)] public string Path = ""; //"KMeans" "Index" [MarshalAs(UnmanagedType.LPWStr)] public string Type = ""; }; [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] public unsafe struct LibSvcHparams { public LibSvcHparams() { } [MarshalAs(UnmanagedType.LPWStr)] //"SoVits2.0" "SoVits3.0" "SoVits4.0" "SoVits4.0-DDSP" "RVC" "DiffSvc" "DiffusionSvc" public string TensorExtractor = ""; [MarshalAs(UnmanagedType.LPWStr)] public string HubertPath = ""; public DiffusionSvcPaths DiffusionSvc; public VitsSvcPaths VitsSvc; public ReflowSvcPaths ReflowSvc; public LibSvcClusterConfig Cluster; public int SamplingRate = 22050; public int HopSize = 320; public long HiddenUnitKDims = 256; public long SpeakerCount = 1; public int EnableCharaMix = 0; public int EnableVolume = 0; public int VaeMode = 1; public long MelBins = 128; public long Pndms = 100; public long MaxStep = 1000; public float SpecMin = -12; public float SpecMax = 2; public float Scale = 1000; }; public delegate void CallbackProgress(ulong arg1, ulong arg2); private LibSvc() { Init(); } private static LibSvc? instance = null; public static LibSvc Factory { get { instance ??= new LibSvc(); return instance; } } public void Init() { LibSvcInit(); EnableFileLogger(false); SetF0PredictorEnv(8, 0, 0); } public void SetF0PredictorEnv(uint ThreadCount, uint DeviceID, Device Provider) { if (LibSvcSetGlobalEnv(ThreadCount, DeviceID, (uint)Provider) == 0) return; throw new Exception(GetError(0)); } public static void SetMaxErrorCount(ulong Count) { LibSvcSetMaxErrorCount(Count); } public static string GetError(ulong Index) { return LibSvcGetError(Index); } public Int16Vector ReadAudio(ref string _Path, int _SamplingRate) { Int16Vector Ret = new(); if (LibSvcReadAudio(_Path, _SamplingRate, Ret.Object) == 0) return Ret; throw new Exception(GetError(0)); } public UInt64Vector SliceAudio( ref Int16Vector Audio, ref SlicerSettings Setting ) { UInt64Vector Ret = new(); if(LibSvcSliceAudio(Audio.Object, ref Setting, Ret.Object) == 0) return Ret; throw new Exception(GetError(0)); } public Slices Preprocess( ref Int16Vector Audio, ref UInt64Vector SlicePos, int SamplingRate = 48000, int HopSize = 480, double Threshold = 30, string F0Method = "Dio" ) { Slices Ret = new(); if (LibSvcPreprocess(Audio.Object, SlicePos.Object, SamplingRate, HopSize, Threshold, F0Method, Ret.Object) == 0) return Ret; throw new Exception(GetError(0)); } public Mel Stft( ref Int16Vector Audio, int SamplingRate, int Hopsize, int MelBins ) { Mel Ret = new(); if (LibSvcStft(Audio.Object, SamplingRate, Hopsize, MelBins, Ret.Object) == 0) return Ret; throw new Exception(GetError(0)); } public VitsModel LoadVitsSvcModel( ref LibSvcHparams _Config, ref CallbackProgress _ProgressCallback, Device _ExecutionProvider, uint _DeviceID, uint _ThreadCount ) { void* Model = LibSvcLoadModel(0, ref _Config, _ProgressCallback, (uint)_ExecutionProvider, _DeviceID, _ThreadCount); if(Model != null) return new VitsModel(Model); throw new Exception(GetError(0)); } public UnionModel LoadUnionSvcModel( ref LibSvcHparams _Config, ref CallbackProgress _ProgressCallback, Device _ExecutionProvider, uint _DeviceID, uint _ThreadCount ) { void* Model = LibSvcLoadModel(1, ref _Config, _ProgressCallback, (uint)_ExecutionProvider, _DeviceID, _ThreadCount); if (Model != null) return new UnionModel(Model); throw new Exception(GetError(0)); } public VocoderModel LoadVocoderModel(ref string _Path) { void* Model = LibSvcLoadVocoder(_Path); if (Model != null) return new VocoderModel(Model); throw new Exception(GetError(0)); } public void EnableFileLogger(bool _Cond) { LibSvcEnableFileLogger(_Cond); } public void WriteAudio(Int16Vector _PCMData, string _OutputPath, int _SamplingRate) { LibSvcWriteAudioFile(_PCMData.Object, _OutputPath, _SamplingRate); } [DllImport("libsvc.dll")] private static extern void LibSvcInit(); [DllImport("libsvc.dll")] private static extern int LibSvcSetGlobalEnv(uint ThreadCount, uint DeviceID, uint Provider); [DllImport("libsvc.dll")] private static extern void LibSvcSetMaxErrorCount(ulong Count); [DllImport("libsvc.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.BStr)] private static extern string LibSvcGetError(ulong Index); [DllImport("libsvc.dll")] private static extern int LibSvcSliceAudio( void* _Audio, ref SlicerSettings _Setting, void* _Output ); [DllImport("libsvc.dll", CharSet = CharSet.Unicode)] private static extern int LibSvcPreprocess( void* _Audio, void* _SlicePos, int _SamplingRate, int _HopSize, double _Threshold, string _F0Method, void* _Output ); [DllImport("libsvc.dll")] private static extern int LibSvcStft( void* _Audio, int _SamplingRate, int _Hopsize, int _MelBins, void* _Output ); [DllImport("libsvc.dll", CharSet = CharSet.Unicode)] private static extern void* LibSvcLoadModel( uint _T, ref LibSvcHparams _Config, CallbackProgress _ProgressCallback, uint _ExecutionProvider, uint _DeviceID, uint _ThreadCount ); [DllImport("libsvc.dll", CharSet = CharSet.Unicode)] private static extern void* LibSvcLoadVocoder(string VocoderPath); [DllImport("libsvc.dll", CharSet = CharSet.Unicode)] private static extern int LibSvcReadAudio(string _AudioPath, int _SamplingRate, void* _Output); [DllImport("libsvc.dll", CharSet = CharSet.Unicode)] private static extern void LibSvcWriteAudioFile(void* _PCMData, string _OutputPath, int _SamplingRate); [DllImport("libsvc.dll")] private static extern void LibSvcEnableFileLogger(bool _Cond); } } ================================================ FILE: DotNetApi/Properties/launchSettings.json ================================================ { "profiles": { "DotNetApi": { "commandName": "Project", "nativeDebugging": true } } } ================================================ FILE: DragonianSpeech.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33627.172 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsvc", "libsvc\libsvc.vcxproj", "{DC31109B-1984-41DB-BD9F-4261675C3962}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtts", "libtts\libtts.vcxproj", "{3CA188F3-E511-486C-AC28-CCFC6D893861}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetApi", "DotNetApi\DotNetApi.csproj", "{E202AF11-FD77-4E39-B582-F3493874F6F5}" ProjectSection(ProjectDependencies) = postProject {3CA188F3-E511-486C-AC28-CCFC6D893861} = {3CA188F3-E511-486C-AC28-CCFC6D893861} {DC31109B-1984-41DB-BD9F-4261675C3962} = {DC31109B-1984-41DB-BD9F-4261675C3962} EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpDemo", "CSharpDemo\CSharpDemo.csproj", "{984EEE57-4582-4699-A9BE-E64D13439208}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 DebugLib|Any CPU = DebugLib|Any CPU DebugLib|x64 = DebugLib|x64 DebugLib|x86 = DebugLib|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 ReleaseLib|Any CPU = ReleaseLib|Any CPU ReleaseLib|x64 = ReleaseLib|x64 ReleaseLib|x86 = ReleaseLib|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {DC31109B-1984-41DB-BD9F-4261675C3962}.Debug|Any CPU.ActiveCfg = Debug|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.Debug|Any CPU.Build.0 = Debug|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.Debug|x64.ActiveCfg = Debug|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.Debug|x64.Build.0 = Debug|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.Debug|x86.ActiveCfg = Debug|Win32 {DC31109B-1984-41DB-BD9F-4261675C3962}.Debug|x86.Build.0 = Debug|Win32 {DC31109B-1984-41DB-BD9F-4261675C3962}.DebugLib|Any CPU.ActiveCfg = DebugLib|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.DebugLib|Any CPU.Build.0 = DebugLib|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.DebugLib|x64.ActiveCfg = DebugLib|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.DebugLib|x64.Build.0 = DebugLib|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.DebugLib|x86.ActiveCfg = DebugLib|Win32 {DC31109B-1984-41DB-BD9F-4261675C3962}.DebugLib|x86.Build.0 = DebugLib|Win32 {DC31109B-1984-41DB-BD9F-4261675C3962}.Release|Any CPU.ActiveCfg = Release|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.Release|Any CPU.Build.0 = Release|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.Release|x64.ActiveCfg = Release|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.Release|x64.Build.0 = Release|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.Release|x86.ActiveCfg = Release|Win32 {DC31109B-1984-41DB-BD9F-4261675C3962}.Release|x86.Build.0 = Release|Win32 {DC31109B-1984-41DB-BD9F-4261675C3962}.ReleaseLib|Any CPU.ActiveCfg = ReleaseLib|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.ReleaseLib|Any CPU.Build.0 = ReleaseLib|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.ReleaseLib|x64.ActiveCfg = ReleaseLib|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.ReleaseLib|x64.Build.0 = ReleaseLib|x64 {DC31109B-1984-41DB-BD9F-4261675C3962}.ReleaseLib|x86.ActiveCfg = ReleaseLib|Win32 {DC31109B-1984-41DB-BD9F-4261675C3962}.ReleaseLib|x86.Build.0 = ReleaseLib|Win32 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Debug|Any CPU.ActiveCfg = Debug|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Debug|Any CPU.Build.0 = Debug|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Debug|x64.ActiveCfg = Debug|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Debug|x64.Build.0 = Debug|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Debug|x86.ActiveCfg = Debug|Win32 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Debug|x86.Build.0 = Debug|Win32 {3CA188F3-E511-486C-AC28-CCFC6D893861}.DebugLib|Any CPU.ActiveCfg = Debug|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.DebugLib|Any CPU.Build.0 = Debug|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.DebugLib|x64.ActiveCfg = DebugLib|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.DebugLib|x64.Build.0 = DebugLib|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.DebugLib|x86.ActiveCfg = Debug|Win32 {3CA188F3-E511-486C-AC28-CCFC6D893861}.DebugLib|x86.Build.0 = Debug|Win32 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Release|Any CPU.ActiveCfg = Release|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Release|Any CPU.Build.0 = Release|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Release|x64.ActiveCfg = Release|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Release|x64.Build.0 = Release|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Release|x86.ActiveCfg = Release|Win32 {3CA188F3-E511-486C-AC28-CCFC6D893861}.Release|x86.Build.0 = Release|Win32 {3CA188F3-E511-486C-AC28-CCFC6D893861}.ReleaseLib|Any CPU.ActiveCfg = Release|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.ReleaseLib|x64.ActiveCfg = ReleaseLib|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.ReleaseLib|x64.Build.0 = ReleaseLib|x64 {3CA188F3-E511-486C-AC28-CCFC6D893861}.ReleaseLib|x86.ActiveCfg = Release|Win32 {E202AF11-FD77-4E39-B582-F3493874F6F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Debug|Any CPU.Build.0 = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Debug|x64.ActiveCfg = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Debug|x64.Build.0 = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Debug|x86.ActiveCfg = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Debug|x86.Build.0 = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.DebugLib|Any CPU.ActiveCfg = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.DebugLib|Any CPU.Build.0 = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.DebugLib|x64.ActiveCfg = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.DebugLib|x86.ActiveCfg = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.DebugLib|x86.Build.0 = Debug|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Release|Any CPU.ActiveCfg = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Release|Any CPU.Build.0 = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Release|x64.ActiveCfg = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Release|x64.Build.0 = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Release|x86.ActiveCfg = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.Release|x86.Build.0 = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.ReleaseLib|Any CPU.ActiveCfg = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.ReleaseLib|x64.ActiveCfg = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.ReleaseLib|x86.ActiveCfg = Release|Any CPU {E202AF11-FD77-4E39-B582-F3493874F6F5}.ReleaseLib|x86.Build.0 = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Debug|Any CPU.Build.0 = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Debug|x64.ActiveCfg = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Debug|x64.Build.0 = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Debug|x86.ActiveCfg = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Debug|x86.Build.0 = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.DebugLib|Any CPU.ActiveCfg = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.DebugLib|Any CPU.Build.0 = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.DebugLib|x64.ActiveCfg = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.DebugLib|x86.ActiveCfg = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.DebugLib|x86.Build.0 = Debug|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Release|Any CPU.ActiveCfg = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Release|Any CPU.Build.0 = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Release|x64.ActiveCfg = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Release|x64.Build.0 = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Release|x86.ActiveCfg = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.Release|x86.Build.0 = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.ReleaseLib|Any CPU.ActiveCfg = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.ReleaseLib|x64.ActiveCfg = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.ReleaseLib|x86.ActiveCfg = Release|Any CPU {984EEE57-4582-4699-A9BE-E64D13439208}.ReleaseLib|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4EA568DA-C661-4A8C-BA02-1185BFA9DCF0} EndGlobalSection EndGlobal ================================================ FILE: LICENSE ================================================ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . ================================================ FILE: README.md ================================================
![image](logo/logo256(AIGen).png) # DragonianVoice [中文](README.md) | [English](README_en.md)
> 本仓库已经永久停止了UI项目的维护,会成为一个纯Lib项目,代码仓库地址:[DragonianLib](https://github.com/NaruseMioShirakana/DragonianLib),但是有关SVC和TTS的Release仍然在此仓库发布。 > 本仓库为:1、TTS(Tacotron2、Vits、EmotionalVits、BERTVits2、GPtSoVits);2、SVC(SoVitsSvc、RVC、DiffusionSvc、FishDiffusion、ReflowSvc);3、SVS(DiffSinger) 的Onnx框架推理仓库,目前支持C/Cpp/C#调用。 > 本仓库的最新版本已经与 [fish-speech](https://github.com/fishaudio/fish-speech) 联动,使用ggml框架重写fish-speech,组成fish-speech.cpp子项目 > 注意:支持SVS的分支:[MoeVoiceStudio](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudio) [MoeVoiceStudioCore](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore) > 关于Cuda支持的相关问题可以前往 [OnnxRuntime官方仓库](https://github.com/microsoft/onnxruntime/releases) 查看 > 经过实验,Dml会导致Onnx中一些不支持的算子在使用时并不会报错,而是会返回一个不可预料的结果,所以会导致SoVits3.0和SoVits4.0在DmlEP上的推理结果错误。不过最新的SoVits仓库中的Onnx导出已经替换了这些算子,故SoVits3.0和SoVits4.0恢复支持Dml使用,但是要使用最新(2023/7/17)版本的SoVitsOnnx导出重新导出Onnx模型 > 由于Diffusion和Reflow模型的特性,如果你推理的总步数大于模型训练时最大的步数(实际步数=总步数/加速倍率,这个总步数不是推理时实际走过的步数,而是K_Step),会导致输出音频炸掉或者出现非常大的噪声,所以建议在推理前请仔细观察自己模型配置文件中的MaxStep(或K_Step_Max)
支持的Net: - [DeepLearningExamples](https://github.com/NVIDIA/DeepLearningExamples) - [Vits](https://github.com/jaywalnut310/vits) - [EmotionalVits](https://github.com/innnky/emotional-vits) - [BertVits2](https://github.com/fishaudio/Bert-VITS2) - [SoVitsSvc (v2/v3/v4)](https://github.com/svc-develop-team/so-vits-svc) - [RVC](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) - [DiffSvc](https://github.com/prophesier/diff-SVC) - [DiffusionSvc (v1/v2)](https://github.com/CNChTu/Diffusion-SVC) - [FishDiffusion](https://github.com/fishaudio/fish-diffusion) - [ReflowSvc](https://github.com/prophesier/diff-SVC) - [DiffSinger](https://github.com/openvpi/DiffSinger) - [FCPE](https://github.com/CNChTu/MelPE) - [RMVPE](https://github.com/yxlllc/RMVPE)
## 目录 - [协议](#用户协议) - [免责声明](#免责声明) - [说明](#说明) - [分支说明](#分支) - [FAQ问答](#faq) - Q: [项目名的来历是什么?](#q-项目名的来历) - Q: [这个项目到底有什么作用?](#q-这个项目到底有什么作用) - Q: [该项目以后会收费吗?](#q-该项目以后会收费吗) - Q: [是否提供有偿模型代训练?](#q-是否提供有偿模型代训练) - Q: [电子垃圾评判标准是什么?](#q-电子垃圾评判标准是什么) - Q: [技术支持?](#q-技术支持) - [注意事项](#注意事项) - [使用方法](#使用方法) - [模型配置](#模型配置) - [前置模型](#前置模型) - [配置文件](#配置文件) - [支持的项目](#支持的项目) - [其他设置](#其他设置) - [Symbol](#symbol) - [Cleaner](#cleaner) - [本地编译](#本地编译) - [依赖列表](#依赖列表) - [相关法规](#-相关法规) ## 用户协议: ### 使用该项目你必须同意以下条款,若不同意则禁止使用该项目: 1. 你必须自行承担由于使用该项目而造成的一切后果。 2. 禁止出售该程序。 3. 使用该项目时,你必须自觉遵守当地的法律法规,禁止使用该项目从事违法活动。 4. 禁止用于任何商业游戏、低创游戏[^1]以及Galgame制作,不反对无偿的精品游戏制作以及Mod制作。 5. 禁止使用该项目及该项目衍生物以及发布模型等制作各种电子垃圾[^2] (例如AIGalgame,AI游戏制作等)。 6. 禁止一切政治相关内容。 7. 你使用该项目生成的一切内容均与该项目开发者无关。 8. 本项目开发者主张使用者不具有其所生成“音频本身”的版权,应当划归公共领域;而音频背后涉及到的歌词、乐曲的版权所有者均为该歌词、乐曲的版权所有方。 [^1]: 低创的评判标准为: 大量使用AI生成的任何内容,原创内容较低,意义不明,内容质量低下等。 [^2]: 电子垃圾评判标准: 1、原创度。自己的东西在整个项目中的比例(对于AI来说,使用完全由你独立训练模型的创作属于你自己;使用他人模型的创作属于别人)。涵盖的方面包括但不限于程序、美工、音频、策划等等。例如,套用Unity等引擎模板换皮属于电子垃圾。 ## 免责声明 本项目为**开源、离线的项目,本项目的所有开发者以及维护者(以下简称贡献者)对本项目没有控制力**。本项目的贡献者从未向任何组织或个人提供包括但不限于数据集提取、数据集加工、算力支持、训练支持、推理等一切形式的帮助;本项目的贡献者不知晓也无法知晓使用者使用该项目的用途。故一切基于本项目合成的音频都与本项目贡献者无关。**一切由此造成的问题由使用者自行承担**。 本项目本身不具备任何语音合成的功能,只是用于启动使用者自行训练并自行制作为Onnx模型的模型,且模型的训练与Onnx模型的制作均与本项目的贡献者无关,均为使用者自己的行为,本项目贡献者未参与一切使用者的模型训练与制作。 本项目为完全离线状态下运行,无法采集任何用户信息,也无法获取用户的输入数据,故本项目贡献者对用户的一切输入以及模型不知情,因此不对任何用户输入负责。 **本项目也没有附带任何模型,任何二次发布所附带的模型以及用于此项目的模型均与此项目开发者无关。** ## 说明 本项目目前已完全支持自行调用其中方法来实现命令行推理或其他软件,欢迎大家向本项目提PR 作者的其他项目:[AiToolKits](https://github.com/NaruseMioShirakana/ShirakanaNoAiToolKits) 如果想要参加开发,可以加入QQ群:263805400或直接提PR **模型需要转换为ONNX模型,详情见你选择的项目的源仓库,PTH模型不能直接使用!!!!!!!!!!!!!** ## 分支 本项目的各分支: - [MoeVoiceStudioCore(主分支)](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore) 项目核心 - [MoeVoiceStudio](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudio) 本项目的简单GUI实现 基于qt - [MoeSSV2](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/V2) 旧版MoeSSV2版本存档 - [MoeSSV1](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/V2) 旧版MoeSSV1版本存档 ## FAQ ### Q: 项目名的来历?
A: > XP至上主义者狂喜,有谁不喜欢龙娘呢
### Q: 这个项目到底有什么作用?
A: > 这个项目的开发初衷主要是实现无需环境部属各个语音合成项目,而现在打算制作为一个SVC的辅助编辑器。 > > 由于这个项目毕竟是一个"个人的" "不专业"的项目,所以在您拥有更专业的软件,或者您是Python Cli爱好者,又或者您是相关领域大佬。我自知本软件不够专业且很大可能无法满足您的需求甚至对您没有用处。 > > 本项目并不是不可替代的项目,相反的本项目的功能您可以使用各种工具替代,我没有奢望本项目成为相关领域的领军项目,我只是怀着一腔热情继续着该项目的开发。但是热情总有消散的一天,但是该项目承诺在我的开 > 发热情完全消散之前会一直保持维护(不管有没有人使用,就算用户数目为0) > > 本项目在设计上可能存在着各种各样的问题,所以也是需要大家积极的点炒饭来帮助我完善功能的,大部分对于功能和体验的优化我都会接受。
### Q: 该项目以后会收费吗?
A: > 该项目永久开源免费,如果在其他地方存在本项目的收费版本,请立即举报且不要购买,本项目永久免费。如果想用疯狂星期四塞满白叶,可以前往爱发癫 https://afdian.net/a/NaruseMioShirakana >
### Q: 是否提供有偿模型代训练?
A: > 不提供,训练模型比较简单,没必要花冤枉钱,按照网上教程一步一步走就可以了。
### Q: 电子垃圾评判标准是什么?
A: > 1. 原创度。自己的东西在整个项目中的比例(对于AI来说,使用完全由你独立训练模型的创作属于你自己;使用他人模型的创作属于别人)。涵盖的方面包括但不限于程序、美工、音频、策划等等。举个例子,套用Unity等引擎模板换皮属于电子垃圾。 > 2. 开发者态度。作者开发的态度是不是捞一波流量和钱走人或单纯虚荣。比方说打了无数的tag,像什么“国产”“首个”“最强”“自制”这种引流宣传,结果是非常烂或是平庸的东西,且作者明显没有好好制作该项目的想法,属于电子垃圾。 > 3. 反对一切使用未授权的数据集训练出来的AI模型商用的行为。
### Q: 技术支持?
A: > 如果能够确定你做的不是电子垃圾,同时合法合规,没有严重的政治错误,我会提供一些力所能及的技术支持。
## 注意事项 ### 由于OnnxRuntime引发的问题 不支持中文路径?实际上项目本体是支持中文路径的,不过2023年3月前版本的OnnxRuntime是不支持中文路径的,因为这些版本的OnnxRuntime使用了Win32Api的A系列函数,A系列函数都是不支持非ANSI编码的路径的。这个问题并不是我能够解决的也不是我应该解决的,只有微软官方才可以修复这个BUG,不过好在最新的OnnxRuntime使用了W系列函数,解决了中文路径问题。 ### Cuda版本问题 由于Cuda有着极差的兼容性,导致一个基于Cuda的程序在使用时,必须安装和编译该程序时相同或是未修改Api最近版本的Cuda。这个问题只能等英伟达公司重视兼容性了。 ## 使用方法 MoeVoiceStudioCore以Lib的形式提供 使用C++语言调用 按需引用以下对应的类 ```cpp #include #include #include #include #include InferClass::Tacotron2; InferClass::Vits; InferClass::VitsSvc; InferClass::DiffusionSvc; InferClass::DiffusionSinger; /* 构造函数第一个是配置文件json 第二个是进度条回调 第三个是参数回调 (若为TTS 此参数为空即可) 第四个参数为设备 使用调用Inference函数即可 */ ``` 模型配置请参见[#模型配置](#模型配置) demo: [RVC命令行示例](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore/CMD-RVC-Onnx-Inference) ## 模型配置 ### 前置模型 #### 与所支持的几个项目无关 为深度学习领域的通用模型 停止更新(由于下载和上传速度): [Vocoder & HiddenUnitBert](https://github.com/NaruseMioShirakana/RequireMent-Model-For-MoeSS) 停止更新(由于HuggingFace被墙) : [HuggingFace](https://huggingface.co/NaruseMioShirakana/MoeSS-SUBModel) 最新仓库:[Openi](https://openi.pcl.ac.cn/Shirakana/SubModel) 自己导出前置: - HuBert:`input_names`应该为`["source"]`,`output_names`应该为`["embed"]`,`dynamic_axes`应当为`{"source":[0,2],}` - Diffusion模型使用的hifigan:`input_names`应该为`["c","f0"]`,`output_names`应该为`["audio"]`,`dynamic_axes`应当为`{"c":[0,1],"f0":[0,1],}` - Tacotron2使用的hifigan:`input_names`应该为`["x"]`,`output_names`应该为`["audio"]`,`dynamic_axes`应当为`{"x":[0,1],}` Vec模型和Hubert模型放在Hubert文件夹下,Hifigan模型放在Hifigan文件夹下 如需使用FCPE或RMVPE这两个F0预测器,则需要在根目录创建F0Predictor文件夹并将onnx模型放置在其中 ## 配置文件 - 本项目标准化了模型读取模块,模型保存在Mods文件夹下的子文件夹中。`xxx.json` 为模型的配置文件,需要自行按照模板编写,同时需要自行将模型转换为Onnx。 #### 通用参数(不管是啥模型都必须填的,不填就不识别): - `Folder`:保存模型的文件夹名 - `Name`:模型在UI中的显示名称 - `Type`:模型类别 - `Rate`:采样率(必须和你训练时候的一模一样,不明白原因建议去学计算机音频相关的知识) ### 配置示例
Tacotron2: ```jsonc { "Folder" : "Atri", "Name" : "亚托莉-Tacotron2", "Type" : "Tacotron2", "Rate" : 22050, "Symbol" : "_-!'(),.:;? ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "Cleaner" : "", "AddBlank": false, "Hifigan": "hifigan" } //Symbol:模型的Symbol,不知道Symbol是啥的建议多看几个视频了解了解TTS的基础知识,这一项在Tacotron2中必须填。 //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hifigan:Hifigan模型名,必须填且必须将在前置模型中下载到的hifigan放置到hifigan文件夹 //AddBlank:是否在音素之间插0作为分隔 ```
Vits: ```jsonc { "Folder" : "SummerPockets", "Name" : "SummerPocketsReflectionBlue", "Type" : "Vits", "Rate" : 22050, "Symbol" : "_,.!?-~…AEINOQUabdefghijkmnoprstuvwyzʃʧʦ↓↑ ", "Cleaner" : "", "AddBlank": true, "Emotional" : true, "EmotionalPath" : "all_emotions", "Characters" : ["鳴瀬しろは","空門蒼","鷹原うみ","紬ヴェンダース","神山識","水織静久","野村美希","久島鴎","岬鏡子"] } //Symbol:模型的Symbol,不知道Symbol是啥的建议多看几个视频了解了解TTS的基础知识,这一项在Vits中必须填。 //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //AddBlank:是否在音素之间插0作为分隔(大多数Vits模型必须为true) //Emotional:是否加入情感向量 //EmotionalPath:情感向量npy文件名 ```
Pits: ```jsonc { "Folder" : "SummerPockets", "Name" : "SummerPocketsReflectionBlue", "Type" : "Pits", "Rate" : 22050, "Symbol" : "_,.!?-~…AEINOQUabdefghijkmnoprstuvwyzʃʧʦ↓↑ ", "Cleaner" : "", "AddBlank": true, "Emotional" : true, "EmotionalPath" : "all_emotions", "Characters" : ["鳴瀬しろは","空門蒼","鷹原うみ","紬ヴェンダース","神山識","水織静久","野村美希","久島鴎","岬鏡子"] } //Symbol:模型的Symbol,不知道Symbol是啥的建议多看几个视频了解了解TTS的基础知识,这一项在Vits中必须填。 //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //AddBlank:是否在音素之间插0作为分隔(大多数Pits模型必须为true) //Emotional:是否加入情感向量 //EmotionalPath:情感向量npy文件名 ```
RVC: ```jsonc { "Folder" : "NyaruTaffy", "Name" : "NyaruTaffy", "Type" : "RVC", "Rate" : 40000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert4.0", "Diffusion": false, "CharaMix": true, "Volume": false, "SoVits2": true, "ShallowDiffusion" : "NyaruTaffy" "HiddenSize": 256, "Cluster": "Index" "Characters" : ["Taffy","Nyaru"] } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Diffusion:是否为DDSP仓库下的扩散模型 //CharaMix:是否使用角色混合轨道 //ShallowDiffusion:SoVits浅扩散模型,须填写ShallowDiffusion模型配置文件名(不带后缀和完整路径),小显存或内存下速度巨慢,效果未知,请根据实际情况决定是否使用) //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) //Cluster:聚类类型,包括"KMeans"和"Index",KMeans需要前往SoVits仓库将KMeans文件导出为可用格式,放置到模型文件夹;Index同理,需要前往SoVits仓库导出为可用格式(如果是RVC的单角色Index只需要改名为Index-0.index)然后放置到模型文件夹下(有几个角色就有几个Index文件) ```
SoVits_3.0_32k: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 32000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert", "SoVits3": true, "ShallowDiffusion" : "NyaruTaffy" "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Cluster": "KMeans" "Characters" : ["Taffy","Nyaru"] } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Diffusion:是否为DDSP仓库下的扩散模型 //ShallowDiffusion:SoVits浅扩散模型,须填写ShallowDiffusion模型配置文件名(不带后缀和完整路径),小显存或内存下速度巨慢,效果未知,请根据实际情况决定是否使用) //CharaMix:是否使用角色混合轨道 //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) //Cluster:聚类类型,包括"KMeans"和"Index",KMeans需要前往SoVits仓库将KMeans文件导出为可用格式,放置到模型文件夹;Index同理,需要前往SoVits仓库导出为可用格式(如果是RVC的单角色Index只需要改名为Index-0.index)然后放置到模型文件夹下(有几个角色就有几个Index文件) ```
SoVits_3.0_48k: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 48000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert", "SoVits3": true, "ShallowDiffusion" : "NyaruTaffy" "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Cluster": "KMeans" "Characters" : ["Taffy","Nyaru"] } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Diffusion:是否为DDSP仓库下的扩散模型 //ShallowDiffusion:SoVits浅扩散模型,须填写ShallowDiffusion模型配置文件名(不带后缀和完整路径),小显存或内存下速度巨慢,效果未知,请根据实际情况决定是否使用) //CharaMix:是否使用角色混合轨道 //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) //Cluster:聚类类型,包括"KMeans"和"Index",KMeans需要前往SoVits仓库将KMeans文件导出为可用格式,放置到模型文件夹;Index同理,需要前往SoVits仓库导出为可用格式(如果是RVC的单角色Index只需要改名为Index-0.index)然后放置到模型文件夹下(有几个角色就有几个Index文件) ```
SoVits_4.0: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hubert": "hubert4.0", "SoVits4.0V2": false, "ShallowDiffusion" : "NyaruTaffy" "Diffusion" : false, "CharaMix" : true, "Volume" : false, "HiddenSize" : 256, "Cluster" : "KMeans" "Characters" : ["Taffy","Nyaru"] } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Diffusion:是否为DDSP仓库下的扩散模型 //ShallowDiffusion:SoVits浅扩散模型,须填写ShallowDiffusion模型配置文件名(不带后缀和完整路径),小显存或内存下速度巨慢,效果未知,请根据实际情况决定是否使用) //CharaMix:是否使用角色混合轨道 //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) //Cluster:聚类类型,包括"KMeans"和"Index",KMeans需要前往SoVits仓库将KMeans文件导出为可用格式,放置到模型文件夹;Index同理,需要前往SoVits仓库导出为可用格式(如果是RVC的单角色Index只需要改名为Index-0.index)然后放置到模型文件夹下(有几个角色就有几个Index文件) //SoVits4.0V2: 是否为SoVits4.0V2模型 ```
DiffSVC: ```jsonc { "Folder" : "DiffShiroha", "Name" : "白羽", "Type" : "DiffSvc", "Rate" : 44100, "Hop" : 512, "MelBins" : 128, "Cleaner" : "", "Hifigan": "nsf_hifigan", "Hubert": "hubert", "Characters" : [], "Pndm" : 100, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "V2" : true } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //MelBins:模型的MelBins,不知道MelBins是啥的建议多看几个视频了解了解梅尔基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hubert:Hubert模型名,必须填且必须将在前置模型中下载到的Hubert放置到Hubert文件夹 //Hifigan:Hifigan模型名,必须填且必须将在前置模型中下载到的nsf_hifigan放置到hifigan文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //Pndm:加速倍数,如果是V1模型则必填且必须为导出时设置的加速倍率 //V2:是否为V2模型,V2模型就是后来我分4个模块导出的那个 //Diffusion:是否为DDSP仓库下的扩散模型 //CharaMix:是否使用角色混合轨道 //Volume:该模型是否有音量Emb //HiddenSize:Vec模型的尺寸(768/256) ```
DiffSinger: ```jsonc { "Folder" : "utagoe", "Name" : "utagoe", "Type" : "DiffSinger", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hifigan": "singer_nsf_hifigan", "Characters" : [], "MelBins" : 128 } //Hop:模型的HopLength,不知道HopLength是啥的建议多看几个视频了解了解音频的基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) //Cleaner:插件名,可以不填,填了就必须要在Cleaner文件夹防止相应的CleanerDll,如果Dll不存在或者是Dll内部有问题,则会在加载模型时报插件错误 //Hifigan:Hifigan模型名,必须填且必须将在前置模型中下载到的singer_nsf_hifigan放置到hifigan文件夹 //Characters:如果是多角色模型必须填写为你的角色名称组成的列表,如果是单角色模型可以不填 //MelBins:模型的MelBins,不知道MelBins是啥的建议多看几个视频了解了解梅尔基础知识,这一项在SoVits中必须填。(数值必须为你训练时的数值,可以在你训练模型时候的配置文件里看到) ```
BertVits: ```jsonc { "Folder": "HimenoSena", "Name": "HimenoSena", "Type": "BertVits", "Symbol": [ "_", "AA", "E", "EE", "En", "N", "OO", "V", "a", "a:", "aa", "ae", "ah", "ai", "an", "ang", "ao", "aw", "ay", "b", "by", "c", "ch", "d", "dh", "dy", "e", "e:", "eh", "ei", "en", "eng", "er", "ey", "f", "g", "gy", "h", "hh", "hy", "i", "i0", "i:", "ia", "ian", "iang", "iao", "ie", "ih", "in", "ing", "iong", "ir", "iu", "iy", "j", "jh", "k", "ky", "l", "m", "my", "n", "ng", "ny", "o", "o:", "ong", "ou", "ow", "oy", "p", "py", "q", "r", "ry", "s", "sh", "t", "th", "ts", "ty", "u", "u:", "ua", "uai", "uan", "uang", "uh", "ui", "un", "uo", "uw", "v", "van", "ve", "vn", "w", "x", "y", "z", "zh", "zy", "!", "?", "\u2026", ",", ".", "'", "-", "SP", "UNK" ], "Cleaner": "", "Rate": 44100, "CharaMix": true, "Characters": [ "\u56fd\u89c1\u83dc\u5b50", "\u59ec\u91ce\u661f\u594f", "\u65b0\u5802\u5f69\u97f3", "\u56db\u6761\u51db\u9999", "\u5c0f\u97a0\u7531\u4f9d" ], "LanguageMap": { "ZH": [ 0, 0 ], "JP": [ 1, 6 ], "EN": [ 2, 8 ] }, "Dict": "BasicDict", "BertPath": [ "chinese-roberta-wwm-ext-large", "deberta-v2-large-japanese", "bert-base-japanese-v3" ] } ```
## 支持的项目 ```cmake // ${xxx}是什么意思大家应该都知道吧,总之以下是多个不同项目需要的模型文件(需要放置在对应的模型文件夹下)。 // Tacotron2: ${Folder}_decoder_iter.onnx ${Folder}_encoder.onnx ${Folder}_postnet.onnx // Vits: 单角色VITS ${Folder}_dec.onnx ${Folder}_flow.onnx ${Folder}_enc_p.onnx ${Folder}_dp.onnx // Vits: 多角色VITS ${Folder}_dec.onnx ${Folder}_emb.onnx ${Folder}_flow.onnx ${Folder}_enc_p.onnx ${Folder}_dp.onnx // SoVits: ${Folder}_SoVits.onnx // RVC: ${Folder}_RVC.onnx // DiffSvc: ${Folder}_diffSvc.onnx // DiffSvc: V2 ${Folder}_encoder.onnx ${Folder}_denoise.onnx ${Folder}_pred.onnx ${Folder}_after.onnx // DiffSinger: OpenVpiVersion ${Folder}_diffSinger.onnx // DiffSinger: ${Folder}_encoder.onnx ${Folder}_denoise.onnx ${Folder}_pred.onnx ${Folder}_after.onnx ``` ## 其他设置 ### Symbol 例如:_-!'(),.:;? ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 打开你训练模型的项目,打开text\symbol.py,如图按照划线的List顺序将上面的4个字符串连接即可 ![image](https://user-images.githubusercontent.com/40709280/183290732-dcb93323-1061-431b-aafa-c285a3ec5e82.png) ### Cleaner ```cxx /* Cleaner请放置于根目录的Cleaners文件夹内,应该是一个按照要求定义的动态库(.dll),dll应当命名为Cleaner名,Cleaner名即为模型定义Json文件中Cleaner一栏填写的内容。 所有的插件dll需要定义以下函数,函数名必须为PluginMain,Dll名必须为插件名(或Cleaner名): */ const wchar_t* PluginMain(const wchar_t*); // 该接口只要求输入输出一致,并不要求功能一致,也就是说,你可以在改Dll中实现任何想要的功能,比方说ChatGpt,机器翻译等等。 // 以ChatGpt为例,PluginMain函数传入了一个输入字符串input,将该输入传入ChatGpt,再将ChatGpt的输出传入PluginMain,最后返回输出。 wchar_t* PluginMain(wchar_t* input){ wchar_t* tmpOutput = ChatGpt(input); return Clean(tmpOutput); } // 注意:导出dll时请使用 extern "C" 关键字来防止C++语言的破坏性命名。 ``` ## 本地编译 ```cxx git clone https://github.com/NaruseMioShirakana/MoeVoiceStudio.git //自行配置OnnxRuntime和FFMPEG的Dll //使用VisualStudio构建 ``` ## 依赖列表 - [FFmpeg](https://ffmpeg.org/) - [World](https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder) - [rapidJson](https://github.com/Tencent/rapidjson) - [mecab](https://github.com/taku910/mecab) - [yyjson](https://github.com/ibireme/yyjson) - [onnxruntime](https://github.com/microsoft/onnxruntime) - [faiss](https://github.com/facebookresearch/faiss) - [中文词典](https://www.zdic.net/) ## 📚 相关法规 #### 使用该项目的任何组织或个人都应当遵守包括但不限于以下的法律。 #### 《民法典》 ##### 第一千零一十九条 任何组织或者个人不得以丑化、污损,或者利用信息技术手段伪造等方式侵害他人的肖像权。未经肖像权人同意,不得制作、使用、公开肖像权人的肖像,但是法律另有规定的除外。 未经肖像权人同意,肖像作品权利人不得以发表、复制、发行、出租、展览等方式使用或者公开肖像权人的肖像。 对自然人声音的保护,参照适用肖像权保护的有关规定。 ##### 第一千零二十四条 【名誉权】民事主体享有名誉权。任何组织或者个人不得以侮辱、诽谤等方式侵害他人的名誉权。 ##### 第一千零二十七条 【作品侵害名誉权】行为人发表的文学、艺术作品以真人真事或者特定人为描述对象,含有侮辱、诽谤内容,侵害他人名誉权的,受害人有权依法请求该行为人承担民事责任。 行为人发表的文学、艺术作品不以特定人为描述对象,仅其中的情节与该特定人的情况相似的,不承担民事责任。 #### 《[中华人民共和国宪法](http://www.gov.cn/guoqing/2018-03/22/content_5276318.htm)》 #### 《[中华人民共和国刑法](http://gongbao.court.gov.cn/Details/f8e30d0689b23f57bfc782d21035c3.html?sw=%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E5%88%91%E6%B3%95)》 #### 《[中华人民共和国民法典](http://gongbao.court.gov.cn/Details/51eb6750b8361f79be8f90d09bc202.html)》 # MoeSS使用的图像素材来源于: - [SummerPockets](http://key.visualarts.gr.jp/summer/) ## 💪 感谢所有贡献者的努力 ================================================ FILE: README_en.md ================================================ ## Note: TTS & SVS Support:[MoeVoiceStudio](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudio) [MoeVoiceStudioCore](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore). # MoeVoiceStudio | [Chinese](README.md) | [English](README_en.md) This project is a voice assistant software focused on the Otaku subculture and targeted at anime fans.
Supported Frameworks: - [DeepLearningExamples](https://github.com/NVIDIA/DeepLearningExamples) - [VITS](https://github.com/jaywalnut310/vits) - [SoVits](https://github.com/svc-develop-team/so-vits-svc) - [DiffSvc](https://github.com/prophesier/diff-SVC) - [DiffSinger](https://github.com/openvpi/DiffSinger) - [RVC](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) - [FishDiffusion](https://github.com/fishaudio/fish-diffusion)
## Contents - [User Agreement](#user-agreement) - [Disclaimer](#disclaimer) - [Description](#description) - [Branches](#branches) - [FAQ](#faq) - Q: [What is the purpose of this project?](#q-what-is-the-purpose-of-this-project) - Q: [Will this project charge fees in the future?](#q-will-this-project-be-charged-in-the-future) - Q: [Do you provide paid model training?](#q-do-you-provide-paid-model-training) - Q: [What are the criteria for digital garbage?](#q-what-are-the-criteria-for-digital-garbage) - Q: [Technical support?](#q-technical-support) - [Notes](#notes) - [Usage](#usage) - [Model Configuration](#model-configuration) - [Pre-models](#pre-models) - [Configuration File](#configuration-file) - [Supported Projects](#supported-projects) - [Other Settings](#other-settings) - [Symbol](#symbol) - [Cleaner](#cleaner) - [Build](#build) - [List of dependencies](#list-of-dependencies) - [Relevant Regulations](#relevant-regulations) ## User Agreement: ### To use this project, you must agree to the following terms. If you do not agree, you are prohibited from using this project: 1. You must bear all the consequences caused by using this project. 2. It is forbidden to sell this program. 3. When using this project, you must conscientiously abide by local laws and regulations, and it is forbidden to use this project for illegal activities. 4. It is forbidden to use for any commercial games, low-creation games[^1], and Galgame production, but non-commercial high-quality game and Mod production are acceptable. 5. It is forbidden to use this project and its derivatives, and the release of models, etc., to produce various electronic wastes[^2] (such as AIGalgame, AI game production, etc.). 6. All political-related content is prohibited. 7. All content generated by using this project has nothing to do with the developers of this project. [^1]: The criteria for low creativity are: any content generated in large amounts by AI, with low original content, unclear meaning, low quality of content, etc. [^2]: Criteria for digital garbage are: Originality. The proportion of your own work in the entire project (for AI, creations using models trained completely independently by you belong to you; creations using others' models belong to others). Aspects covered include but are not limited to programming, art, audio, planning, etc. For example, reskinning using templates from engines like Unity is considered digital garbage. ## Disclaimer This project is an **open-source, offline project. All developers and maintainers (hereinafter referred to as contributors) of this project have no control over it**. The contributors to this project have never provided any form of help to any organization or individual, including but not limited to data set extraction, data set processing, computational power support, training support, inference, etc. The contributors of this project are unaware and cannot be aware of the purpose of the user's use of the project. Therefore, all audio synthesized based on this project is unrelated to the contributors of this project. **Any problems arising from this will be borne by the users themselves**. This project itself does not have any speech synthesis capabilities, all functions need to be trained by the user themselves and convert into Onnx models, and the training of the model and Converted Onnx models are unrelated to the contributors of this project, all are the actions of the user themselves, and the contributors of this project have not participated in any user's model training and production. This project runs completely offline, it cannot collect any user information, nor can it get user input data, so the contributors of this project are unaware of all user input and the model, and therefore are not responsible for any user input. **This project does not come with any models, any models attached to any secondary release and models used for this project are unrelated to the developers of this project.** ## Description This project currently fully supports calling its own methods to achieve command-line inference or other software, and everyone is welcome to contribute PRs to this project. The author's other projects: [AiToolKits](https://github.com/NaruseMioShirakana/ShirakanaNoAiToolKits) If you want to participate in development, you can join QQ group: 263805400 or directly open Push Requests. **Models need to be converted into ONNX models, the program for converting ONNX has already been pulled to each project's source repository, PTH cannot be used directly!!!!!!!!!!!!!!!!!!!** ## Branches The branches of this project: - [MoeVoiceStudioCore(main branch)](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore) Project core - [MoeVoiceStudio](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudio) A simple GUI implementation of this project based on QT - [MoeSSV2](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/V2) Old version of MoeSS V2 version archive - [MoeSSV1](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/V1) Old version of MoeSS V1 version archive ## FAQ ### Q: What is the purpose of this project?
A: > The original intention of this project's development is mainly to implement various speech synthesis projects without the need for environment deployment, and now it is planned to be made into an auxiliary editor of SVC. Because this project is after all a "personal" "non-professional" project, so if you have more professional software, or you are a Python Cli lover, or you are a big shot in the relevant field. I know that this software is not professional enough and is very likely to be unable to meet your needs or even useless to you. This project is not an irreplaceable project, on the contrary, you can use various tools to replace the functions of this project, I have no extravagant hopes that this project will become a leading project in the relevant field, I am just continuing the development of this project with enthusiasm. But passion always has a day to dissipate, but the project promises to keep maintenance as long as my development passion has not completely dissipated (regardless of whether there are any users, even if the number of users is 0). > > There may be various problems in the design of this project, so we also need everyone to actively point out to help me improve the functionality. Most optimizations for functionality and experience I will accept. > > Finally, let me say one more thing about my view of this project: MoeSS and MoeVS are relying on the defense.
### Q: Will this project be charged in the future?
A: > This project will remain open-source and free forever, if there are paid versions of this project elsewhere, please report immediately and do not purchase, this project is always free. If you want to donate the developer, you can go to Shirakana's Afdian site: https://afdian.net/a/NaruseMioShirakana .
### Q: Do you provide paid model training?
A: > No, training models is relatively simple, there is no need to waste money, just follow the online tutorials step by step.
### Q: What are the criteria for digital garbage?
A: > Originality. Your own work's proportion in the entire project (for AI, creations using completely independently trained models by you belong to you; creations using models from others belong to others). This includes but is not limited to programming, art, audio, planning, etc. For example, reskinning using templates from engines like Unity is considered digital garbage. Developer's attitude. Whether the author's development attitude is to gain traffic and money and leave, or purely vanity. For example, using a lot of tags like "domestic", "first", "strongest", "homemade" for traffic attraction, but the result is very bad or mediocre work, and the author obviously does not have a good idea to make the project, this is considered digital garbage. We oppose all commercial use of AI models trained using unauthorized datasets.
### Q: Technical support?
A: > If I can confirm that what you're doing is not digital garbage, is legal and compliant, and does not have serious political errors, I will provide some technical support within my capacity.
## Notes ### Due to issues raised by OnnxRuntime For using GPU (CUDA) version, please install CUDA driver version between 11.0 and 12.0, and CUDNN dynamic library version below 83.0, following the tutorials available online. Why such requirements? That would be a question for NVIDIA, the company behind CUDA, CUDNN, and the OnnxRuntime officials. Both issues are caused by certain features of CUDA driver and problems with OnnxRuntime. What's the reason for the previous versions not supporting Chinese paths? Actually, it's just a manifestation of the above issue. The project itself supports Chinese paths, but its underlying OnnxRuntime doesn't, because the Windows version of OnnxRuntime uses the A series functions of Win32Api, and the A series functions do not support paths with non-ANSI encoding. This issue is not something I can solve, nor should I. Only when the OnnxRuntime officials fix this bug can it be resolved. Fortunately, the latest OnnxRuntime uses W series functions, solving this problem with Chinese paths. Errors popping up when loading the model are caused by the above issues (mainly due to not installing CUDA and CUDNN or not installing them as required). If these issues are triggered, you can go to the Onnx official repository's Issue page at https://github.com/microsoft/onnxruntime to find solutions. It's recommended to use the CPU version, as its inference speed is quite impressive and it doesn't have other problems. ## Usage MoeVoiceStudioCore is provided as a library, to be called with C++. Refer to the following corresponding classes as needed: ```cpp #include #include #include #include #include InferClass::Tacotron2; InferClass::Vits; InferClass::VitsSvc; InferClass::DiffusionSvc; InferClass::DiffusionSinger; /* The first parameter of the constructor is the JSON configuration file, the second one is a callback for the progress bar, the third one is a callback for parameters (if for TTS, this can be left empty), and the fourth one is the device. You can call the Inference function to use it. */ ``` For model configuration, please refer to [#Model Configuration](#Model Configuration) Demo: [RVC command-line example](https://github.com/NaruseMioShirakana/MoeVoiceStudio/tree/MoeVoiceStudioCore/CMD-RVC-Onnx-Inference) ## Model Configuration ### Pre-models #### Not related to the few projects we support, they are universal models in the deep learning domain Stopped updating (due to download and upload speeds): [Vocoder & HiddenUnitBert](https://github.com/NaruseMioShirakana/RequireMent-Model-For-MoeSS) Latest repository: [HuggingFace](https://huggingface.co/NaruseMioShirakana/MoeSS-SUBModel) Export frontend yourself: - HuBert: `input_names` should be `["source"]`, `output_names` should be `["embed"]`, `dynamic_axes` should be `{" source":[0,2],}` - Hifigan used by the Diffusion model: `input_names` should be `["c","f0"]`, `output_names` should be `["audio"]`, `dynamic_axes` should be `{"c":[0,1],"f0":[0,1],}` - Hifigan used by Tacotron2: `input_names` should be `["x"]`, `output_names` should be `["audio"]`, `dynamic_axes` should be `{"x":[0,1],}` ## Configuration File - This project has standardized the model loading module, the models are saved in subfolders under the Mods folder. `xxx.json` is the configuration file for the model, which needs to be written manually according to the template, and the model needs to be converted to Onnx manually. #### Universal Parameters (These are mandatory for any model. If not filled, it won't be recognized): - `Folder`: The folder name where the model is stored - `Name`: The display name of the model in UI - `Type`: The category of the model - `Rate`: Sample rate (it must be exactly the same as when you trained, if you don't understand why, you are recommended to learn about computer audio related knowledge) ### Examples Notice: `Diff-SVC` model and `Diffusion-SVC` model are basically **NOT** the same model, and the same applies to the `Fish-Diffusion` model, though all of them are based on the Diffusion algorithm.
Tacotron2: ```jsonc { "Folder" : "Atri", "Name" : "ATRI-Tacotron2", "Type" : "Tacotron2", "Rate" : 22050, "Symbol" : "_-!'(),.:;? ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "Cleaner" : "", "AddBlank": false, "Hifigan": "hifigan" } //Symbol:Symbol of the model,If you don't know what it is, you are advised to check the TTS information on the internet.This field must be filled in the Tacotron2 model's configuration file. //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hifigan:Hifigan model name, required and must be placed in the "hifigan" folder for hifigan model downloaded from the Pre-model repository //AddBlank:Whether to insert a 0 as a separator between phonemes ```
Vits: ```jsonc { "Folder" : "SummerPockets", "Name" : "SummerPocketsReflectionBlue", "Type" : "Vits", "Rate" : 22050, "Symbol" : "_,.!?-~…AEINOQUabdefghijkmnoprstuvwyzʃʧʦ↓↑ ", "Cleaner" : "", "AddBlank": true, "Emotional" : true, "EmotionalPath" : "all_emotions", "Characters" : ["鳴瀬しろは","空門蒼","鷹原うみ","紬ヴェンダース","神山識","水織静久","野村美希","久島鴎","岬鏡子"] } //Symbol:Symbol of the model,If you don't know what it is, you are advised to check the TTS information on the internet.This field must be filled in the VITS model's configuration file. //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //AddBlank:Whether to insert a 0 as a separator between phonemes(For most VITS models, you must set this to "true"..) //Emotional:whether to add a emotional vector //EmotionalPath:emotional vector file(.npy) path ```
Pits: ```jsonc { "Folder" : "SummerPockets", "Name" : "SummerPocketsReflectionBlue", "Type" : "Pits", "Rate" : 22050, "Symbol" : "_,.!?-~…AEINOQUabdefghijkmnoprstuvwyzʃʧʦ↓↑ ", "Cleaner" : "", "AddBlank": true, "Emotional" : true, "EmotionalPath" : "all_emotions", "Characters" : ["鳴瀬しろは","空門蒼","鷹原うみ","紬ヴェンダース","神山識","水織静久","野村美希","久島鴎","岬鏡子"] } //Symbol:Symbol of the model,If you don't know what it is, you are advised to check the TTS information on the internet.This field must be filled in the VITS model's configuration file. //Cleaner:The name of the plugin, can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //AddBlank:Whether to insert a 0 as a separator between phonemes(For most VITS models, you must set this to "true"..) //Emotional:whether to add a emotional vector //EmotionalPath:emotional vector file(.npy) path ```
RVC: ```jsonc { "Folder" : "NyaruTaffy", "Name" : "NyaruTaffy", "Type" : "RVC", "Rate" : 40000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert4.0", "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Characters" : ["Taffy","Nyaru"] } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
SoVits_3.0_32k: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 32000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert", "SoVits3": true, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Characters" : ["Taffy","Nyaru"] } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
SoVits_3.0_48k: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 48000, "Hop" : 320, "Cleaner" : "", "Hubert": "hubert", "SoVits3": true, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Characters" : ["Taffy","Nyaru"] } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
SoVits_4.0: ```jsonc { "Folder" : "NyaruTaffySo", "Name" : "NyaruTaffy-SoVits", "Type" : "SoVits", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hubert": "hubert4.0", "SoVits4": true, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "Characters" : ["Taffy","Nyaru"] } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
DiffSVC: ```jsonc { "Folder" : "DiffShiroha", "Name" : "白羽", "Type" : "DiffSvc", "Rate" : 44100, "Hop" : 512, "MelBins" : 128, "Cleaner" : "", "Hifigan": "nsf_hifigan", "Hubert": "hubert", "Characters" : [], "Pndm" : 100, "Diffusion": false, "CharaMix": true, "Volume": false, "HiddenSize": 256, "V2" : true } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the SoVits model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Melbins:Melbins of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the Diffsvc model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hubert:Hubert model name, required and must be placed in the "Hubert" folder for Hubert models downloaded from the Pre-model repository //Hifigan:Hifigan model name, required and must be placed in the "hifigan" folder for nsf-hifigan model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out //Pndm:Acceleration multiplier, required in the case of V1 models and must be the acceleration multiplier set at the time of export //V2:If your diffsvc model is a V2 model(Fish-Diffusion model), set this to "true". //Diffusion:if this diffusion model is trained by DDSP-SVC (Diffusion-SVC) , set this to "true". //CharaMix:whether or not to use the character mixing track //Volume:whether the model have volume Embedding, if it has, set this to "true". //HiddenSize:Size of the Vec model(256/768) ```
DiffSinger: ```jsonc { "Folder" : "utagoe", "Name" : "utagoe", "Type" : "DiffSinger", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hifigan": "singer_nsf_hifigan", "Characters" : [], "MelBins" : 128 } ```jsonc { "Folder" : "utagoe", "Name" : "utagoe", "Type" : "DiffSinger", "Rate" : 44100, "Hop" : 512, "Cleaner" : "", "Hifigan": "singer_nsf_hifigan", "Characters" : [], "MelBins" : 128 } //Hop:HopLength of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the Diffsinger model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Melbins:Melbins of the model, if you don't know what it is you are advised to look up the information on the internet. This must be filled in the configuration file of the Diffsvc model.(The value must be the one you set during training and can be seen in the configuration file you used to train the model) //Cleaner:The name of the plugin,can be left blank, but if it is filled in, the corresponding CleanerDll must be placed in the Cleaner folder, if the Dll does not exist or if there is an internal error in the Dll, it will report an error when loading the model //Hifigan:Hifigan model name, required and must be placed in the "hifigan" folder for nsf-hifigan model downloaded from the Pre-model repository //Characters:For multi-speaker model this must be filled in as a list of your speakers' names, for single-speaker model it can be left out ```
BertVits: ```jsonc { "Folder": "HimenoSena", "Name": "HimenoSena", "Type": "BertVits", "Symbol": [ "_", "AA", "E", "EE", "En", "N", "OO", "V", "a", "a:", "aa", "ae", "ah", "ai", "an", "ang", "ao", "aw", "ay", "b", "by", "c", "ch", "d", "dh", "dy", "e", "e:", "eh", "ei", "en", "eng", "er", "ey", "f", "g", "gy", "h", "hh", "hy", "i", "i0", "i:", "ia", "ian", "iang", "iao", "ie", "ih", "in", "ing", "iong", "ir", "iu", "iy", "j", "jh", "k", "ky", "l", "m", "my", "n", "ng", "ny", "o", "o:", "ong", "ou", "ow", "oy", "p", "py", "q", "r", "ry", "s", "sh", "t", "th", "ts", "ty", "u", "u:", "ua", "uai", "uan", "uang", "uh", "ui", "un", "uo", "uw", "v", "van", "ve", "vn", "w", "x", "y", "z", "zh", "zy", "!", "?", "\u2026", ",", ".", "'", "-", "SP", "UNK" ], "Cleaner": "", "Rate": 44100, "CharaMix": true, "Characters": [ "\u56fd\u89c1\u83dc\u5b50", "\u59ec\u91ce\u661f\u594f", "\u65b0\u5802\u5f69\u97f3", "\u56db\u6761\u51db\u9999", "\u5c0f\u97a0\u7531\u4f9d" ], "LanguageMap": { "ZH": [ 0, 0 ], "JP": [ 1, 6 ], "EN": [ 2, 8 ] }, "Dict": "BasicDict", "BertPath": [ "chinese-roberta-wwm-ext-large", "deberta-v2-large-japanese", "bert-base-japanese-v3" ] } ```
## Supported Projects ```cxx // $Below are the model files needed for several different projects (they need to be placed in the corresponding model folders). // Tacotron2: ${Folder}_decoder_iter.onnx ${Folder}_encoder.onnx ${Folder}_postnet.onnx // Vits: Single-speaker VITS ${Folder}_dec.onnx ${Folder}_flow.onnx ${Folder}_enc_p.onnx ${Folder}_dp.onnx // Vits: multi-speaker VITS ${Folder}_dec.onnx ${Folder}_emb.onnx ${Folder}_flow.onnx ${Folder}_enc_p.onnx ${Folder}_dp.onnx // SoVits: ${Folder}_SoVits.onnx // DiffSvc: ${Folder}_diffSvc.onnx // DiffSvc: V2 ${Folder}_encoder.onnx ${Folder}_denoise.onnx ${Folder}_pred.onnx ${Folder}_after.onnx // DiffSinger: OpenVpiVersion ${Folder}_diffSinger.onnx // DiffSinger: ${Folder}_encoder.onnx ${Folder}_denoise.onnx ${Folder}_pred.onnx ${Folder}_after.onnx ``` ## Other Settings ### Symbol settings For example:_-!'(),.:;? ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz Open the project you are using to train the model, open text\symbol.py and join the 4 strings above in the order of the underlined list as shown ![image](https://user-images.githubusercontent.com/40709280/183290732-dcb93323-1061-431b-aafa-c285a3ec5e82.png) ### Cleaner settings ```cxx /* The Cleaner should be placed in the Cleaners folder in the root directory and should be a dynamic library (.dll) defined as required. The dll should be named Cleaner and the Cleaner name is what is entered in the "Cleaner" of the model configuration file. The following functions need to be defined for all plug-in dlls, the function name must be PluginMain and the Dll name must be the plug-in name (or Cleaner name). */ const wchar_t* PluginMain(const wchar_t*); // The interface only requires consistent input and output, not consistent functionality, which means that you can implement any functionality you want in the Dll, such as ChatGpt, translation, etc. // Using ChatGpt as an example, the PluginMain function passes in an input string input, passes that input into ChatGpt, passes ChatGpt's output into PluginMain, and finally returns the output. wchar_t* PluginMain(wchar_t* input){ wchar_t* tmpOutput = ChatGpt(input); return Clean(tmpOutput); } // Note: Please use the extern "C" keyword when exporting the dll to prevent destructive naming in C++. ``` ## Build ```cxx git clone https://github.com/NaruseMioShirakana/MoeVoiceStudio.git //Place OnnxRuntime.dll and FFMPEG's Dll in the correct folder //Build With VisualStudio ``` ## List of dependencies - [FFmpeg](https://ffmpeg.org/) - [World](https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder) - [rapidJson](https://github.com/Tencent/rapidjson) ## 📚 相关法规 #### Any country, region, organization, or individual using this project must comply with the following laws. #### 《民法典》 ##### 第一千零一十九条 任何组织或者个人不得以丑化、污损,或者利用信息技术手段伪造等方式侵害他人的肖像权。未经肖像权人同意,不得制作、使用、公开肖像权人的肖像,但是法律另有规定的除外。 未经肖像权人同意,肖像作品权利人不得以发表、复制、发行、出租、展览等方式使用或者公开肖像权人的肖像。 对自然人声音的保护,参照适用肖像权保护的有关规定。 ##### 第一千零二十四条 【名誉权】民事主体享有名誉权。任何组织或者个人不得以侮辱、诽谤等方式侵害他人的名誉权。 ##### 第一千零二十七条 【作品侵害名誉权】行为人发表的文学、艺术作品以真人真事或者特定人为描述对象,含有侮辱、诽谤内容,侵害他人名誉权的,受害人有权依法请求该行为人承担民事责任。 行为人发表的文学、艺术作品不以特定人为描述对象,仅其中的情节与该特定人的情况相似的,不承担民事责任。 #### 《[中华人民共和国宪法](http://www.gov.cn/guoqing/2018-03/22/content_5276318.htm)》 #### 《[中华人民共和国刑法](http://gongbao.court.gov.cn/Details/f8e30d0689b23f57bfc782d21035c3.html?sw=%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E5%88%91%E6%B3%95)》 #### 《[中华人民共和国民法典](http://gongbao.court.gov.cn/Details/51eb6750b8361f79be8f90d09bc202.html)》 # The image resource MoeVS used is derived from: - [SummerPockets](http://key.visualarts.gr.jp/summer/) ## 💪 Thanks to all contributors for their efforts ================================================ FILE: TTSProjectTemplate.ttsproj ================================================ [ { "Tokens": "私は誰?", "Seq": ["w", "a", "t", "a", "s", "h", "i", "w", "a", "d", "a", "r", "e", "?"], "Tones": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "Durations": [2, 5, 2, 5, 2, 2, 5, 2, 5, 2, 5, 2, 5], "Language": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "SpeakerMix": [1.000000, 0.000000, 0.000000], "EmotionPrompt": ["sad", "happy"], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 114514, "Seed": 1919810, "SpeakerId": 2, "RestTime": 1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は鳴瀬しろは", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [], "EmotionPrompt": [], "NoiseScale": 0.666000, "LengthScale": 1.000000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 1145147, "Seed": 1919810, "SpeakerId": 0, "RestTime": 1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は誰?", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [0.666000, 0.233000, 0.444000], "EmotionPrompt": ["sad", "happy"], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 1145145, "Seed": 19198101, "SpeakerId": 1, "RestTime": -1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は鷗です、くみの名前は?", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [], "EmotionPrompt": [], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.222000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 114514, "Seed": 1919810, "SpeakerId": 3, "RestTime": 1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" } ] ================================================ FILE: VitsInputTemplate.json ================================================ [ { "Tokens": "私は誰?", "Seq": ["w","a","t","a","s","h","i","w","a","d","a","r","e","?"], "Tones": [0,0,0,0,0,0,0,0,0,0,0,0,0], "Durations": [2,5,2,5,2,2,5,2,5,2,5,2,5], "Language": [0,0,0,0,0,0,0,0,0,0,0,0,0], "SpeakerMix": [1,0,0], "EmotionPrompt": ["sad", "happy"], "NoiseScale": 0.666, "LengthScale": 1.1, "DurationPredictorNoiseScale": 0.333, "FactorDpSdp": 0.6, "GateThreshold": 0.777, "MaxDecodeStep": 114514, "Seed": 1919810, "SpeakerId": 2, "RestTime": 1.0, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は鳴瀬しろは", "Seq": "[ph]w|a|t|a|s|h|i|h|a|n|a|r|u|s|e|s|h|i|r|o|h|a", "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [], "EmotionPrompt": [], "NoiseScale": 0.666, "LengthScale": 1.0, "DurationPredictorNoiseScale": 0.333, "FactorDpSdp": 0.6, "GateThreshold": 0.777, "MaxDecodeStep": 1145147, "Seed": 1919810, "SpeakerId": 0, "RestTime": 1.0, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は誰?", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [0.666, 0.233, 0.444], "EmotionPrompt": ["sad", "happy"], "NoiseScale": 0.666, "LengthScale": 1.1, "DurationPredictorNoiseScale": 0.333, "FactorDpSdp": 0.6, "GateThreshold": 0.777, "MaxDecodeStep": 1145145, "Seed": 19198101, "SpeakerId": 1, "RestTime": -1.0, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "", "Seq": "私は鷗です、くみの名前は?", "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [], "EmotionPrompt": [], "NoiseScale": 0.666, "LengthScale": 1.1, "DurationPredictorNoiseScale": 0.222, "FactorDpSdp": 0.6, "GateThreshold": 0.777, "MaxDecodeStep": 114514, "Seed": 1919810, "SpeakerId": 3, "RestTime": 1.0, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" } ] ================================================ FILE: fish-speech.cpp/CMakeLists.txt ================================================ cmake_minimum_required (VERSION 3.8) add_compile_options("$<$:/utf-8>") add_compile_options("$<$:/utf-8>") option(FISHSPEECHCPP_CUDA "cuda backend" OFF) option(FISHSPEECHCPP_ROCM "rocm backend" OFF) option(FISHSPEECHCPP_SHARED_LIBS "build shared libs" OFF) option(FISHSPEECHCPP_BUILD_DEMO "build demo" ON) add_definitions(-DUNICODE) set(FishSpeechLib fish-speech-cpp) set(BUILD_SHARED_LIBS OFF) if(FISHSPEECHCPP_CUDA) endif() if (FISHSPEECHCPP_ROCM) endif () project (${FishSpeechLib}) set(CMAKE_CXX_SCAN_FOR_MODULES ON) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/out/archive/${CMAKE_BUILD_TYPE}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/out/library/${CMAKE_BUILD_TYPE}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/out/runtime/${CMAKE_BUILD_TYPE}) set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/out/lib/${CMAKE_BUILD_TYPE}) if(${CMAKE_BUILD_TYPE} STREQUAL "Release") message("Build Release") add_compile_options(/GS- /arch:AVX2 /O2 /Ob2 /Ot) elseif(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") add_compile_options(/Zi /Gy) else() message("Build Debug") add_definitions(-DFISHSPEECH_DEBUG) add_compile_options(/Zi /Gy) endif() if (POLICY CMP0141) cmake_policy(SET CMP0141 NEW) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") endif() function(FISHSPEECHAddFiles _out) file(GLOB_RECURSE _tmp ${ARGN}) list(APPEND ${_out} ${_tmp}) set(${_out} ${${_out}} PARENT_SCOPE) endfunction() set(PROJECT_SOURCES) FISHSPEECHAddFiles(PROJECT_SOURCES ${PROJECT_SOURCE_DIR}/include/*.hpp ${PROJECT_SOURCE_DIR}/include/*.h ${PROJECT_SOURCE_DIR}/src/*.cpp ${PROJECT_SOURCE_DIR}/src/*.c ) if(FISHSPEECHCPP_SHARED_LIBS) add_library( ${FishSpeechLib} SHARED ${PROJECT_SOURCES} ) add_definitions(-DFISHSPEECH_EXPORT) target_compile_definitions(${FishSpeechLib} PRIVATE -DFISHSPEECH_DLL) set(CMAKE_POSITION_INDEPENDENT_CODE ON) else() add_library( ${FishSpeechLib} STATIC ${PROJECT_SOURCES} ) endif() message(${PROJECT_SOURCES}) include_directories(${PROJECT_SOURCE_DIR}/include) add_subdirectory(ggml) target_link_libraries(${FishSpeechLib} PUBLIC ggml) include_directories(${PROJECT_SOURCE_DIR}/ggml/src) if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET ${FishSpeechLib} PROPERTY CXX_STANDARD 23) endif() if(FISHSPEECHCPP_BUILD_DEMO) add_subdirectory(Demo) endif() ================================================ FILE: fish-speech.cpp/Demo/CMakeLists.txt ================================================ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(EXE_DEMO Demo) add_compile_options(/ZI) add_executable(${EXE_DEMO} main.cpp) target_link_libraries(${EXE_DEMO} PRIVATE fish-speech-cpp) if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET ${EXE_DEMO} PROPERTY CXX_STANDARD 20) endif() ================================================ FILE: fish-speech.cpp/Demo/main.cpp ================================================ #include #include #include "llama.h" using namespace libtts; int main() { auto a = BaseTransformer(nullptr, L"", BaseModelArgs()); std::cout << UnicodeToByte(a.DumpLayerNameInfo()); system("pause"); return 0; } ================================================ FILE: fish-speech.cpp/include/Base.h ================================================ #pragma once #include #include #include #include #ifndef UNUSED #define UNUSED(x) (void)(x) #endif #define LibTTSBegin namespace libtts { #define LibTTSEnd } #define LIBTTSND [[nodiscard]] #define LibTTSThrowImpl(message, exception_type) do {\ const std::string __LibTTS__Message__ = message;\ const std::string __LibTTS__Message__Prefix__ =\ std::string("[In File: \"") + std::filesystem::path(__FILE__).filename().string() + "\", " +\ "Function: \"" + __FUNCSIG__ + "\", " +\ "Line: " + std::to_string(__LINE__) + " ] ";\ if (__LibTTS__Message__.substr(0, __LibTTS__Message__Prefix__.length()) != __LibTTS__Message__Prefix__)\ throw exception_type((__LibTTS__Message__Prefix__ + __LibTTS__Message__).c_str());\ throw exception_type(__LibTTS__Message__.c_str());\ } while(false) #define LibTTSThrow(message) LibTTSThrowImpl(message, std::exception) #define LibTTSNotImplementedError LibTTSThrow("NotImplementedError!") #define RegisterLayer(MemberName, ...) MemberName(this, L#MemberName, __VA_ARGS__) #define LayerItem(TypeName, ...) new TypeName(nullptr, L"", __VA_ARGS__) #define LogMessage(message) LibTTS::GetLogger().log(message) #define ErrorMessage(message) LibTTS::GetLogger().error(message) LibTTSBegin using int8 = int8_t; using int16 = int16_t; using int32 = int32_t; using int64 = int64_t; using float32 = float; using float64 = double; using byte = unsigned char; using lpvoid = void*; using cpvoid = const void*; using uint8 = uint8_t; using uint16 = uint16_t; using uint32 = uint32_t; using uint64 = uint64_t; struct NoneType {}; static constexpr NoneType None; using SizeType = int32; using DictType = ggml_context*; std::string UnicodeToByte(const std::wstring& input); std::string UnicodeToAnsi(const std::wstring& input); std::wstring ByteToUnicode(const std::string& input); class FileGuard { public: FileGuard() = default; ~FileGuard(); FileGuard(const FileGuard& _Left) = delete; FileGuard& operator=(const FileGuard& _Left) = delete; FileGuard(FileGuard&& _Right) noexcept; FileGuard& operator=(FileGuard&& _Right) noexcept; void Open(const std::wstring& _Path, const std::wstring& _Mode); void Close(); operator FILE* () const; LIBTTSND bool Enabled() const; private: FILE* file_ = nullptr; }; class Value { public: Value() = default; Value(const Value& _Left) = delete; virtual ~Value(); protected: std::wstring RegName_; public: virtual Value& load(const std::wstring& _Path, bool _Strict = false); virtual Value& save(const std::wstring& _Path); virtual void loadData(const DictType& _WeightDict, bool _Strict = false); virtual void saveData(FileGuard& _File); private: ggml_context* DictCtx = nullptr; gguf_context* DictGuf = nullptr; }; class Module : public Value { public: Module(Module* _Parent, const std::wstring& _Name); ~Module() override = default; virtual ggml_tensor* operator()(ggml_tensor*, ggml_context*, bool _Inplace = false); std::wstring& Name() { return RegName_; } std::wstring DumpLayerNameInfo(); private: void DumpLayerNameInfoImpl(std::wstring& _Tmp, int TabCount); virtual void DumpCurrentLayerInfo(std::wstring& _Tmp); protected: std::unordered_map Layers_; public: void loadData(const DictType& _WeightDict, bool _Strict) override; void saveData(FileGuard& _File) override; void ReCalcLayerName(const std::wstring& _Parent); }; class Parameter : public Module { public: using Ty = float; Parameter(Module* _Parent, const std::wstring& _Name, std::vector _Shape); ~Parameter() override = default; operator ggml_tensor* () const; void ChangeShape(std::vector _Shape); protected: ggml_tensor* Weight_ = nullptr; std::vector Shape_; public: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; void loadData(const DictType& _WeightDict, bool _Strict) override; void saveData(FileGuard& _File) override; }; class Sequential : public Module { public: Sequential(Module* _Parent, const std::wstring& _Name); ~Sequential() override; ggml_tensor* operator()(ggml_tensor* _Input, ggml_context* _Ctx, bool _Inplace = false) override; void Append(Module* _Module); virtual Sequential& operator=(const std::initializer_list& _Input); Module** begin() { return _Items.data(); } Module** end() { return _Items.data() + _Items.size(); } Module* operator[](int64_t _Index) const { return *(_Items.data() + _Index); } private: std::vector _Items; }; class ModuleList : public Sequential { public: ModuleList(Module* _Parent, const std::wstring& _Name); ~ModuleList() override; ModuleList& operator=(const std::initializer_list& _Input) override; private: ggml_tensor* operator()(ggml_tensor* _Input, ggml_context* _Ctx, bool _Inplace) override; }; LibTTSEnd ================================================ FILE: fish-speech.cpp/include/Module.h ================================================ #pragma once #include "Base.h" LibTTSBegin enum PaddingType { Zeros, Constant, Reflect, Replicate, Cycle }; class Conv1D : public Module { public: struct ConvParam { SizeType InChannels; SizeType OutChannels; SizeType KernelSize; int Stride = 1; int Padding = 0; int Dilation = 1; int Groups = 1; bool Bias = true; PaddingType PaddingMode = Zeros; }; Conv1D(Module* _Parent, const std::wstring& _Name, const ConvParam& _Params); ggml_tensor* operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace = false) override; void ChangeParam(const ConvParam& _Params); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Parameter weight; Parameter bias; ConvParam params; }; class Conv2D : public Module { public: struct ConvParam { SizeType InChannels; SizeType OutChannels; SizeType KernelSize[2]; int Stride[2] = { 1, 1 }; int Padding[2] = { 0, 0 }; int Dilation[2] = { 1, 1 }; int Groups = 1; bool Bias = true; PaddingType PaddingMode = Zeros; }; Conv2D(Module* _Parent, const std::wstring& _Name, const ConvParam& _Params); ggml_tensor* operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace = false) override; void ChangeParam(const ConvParam& _Params); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Parameter weight; Parameter bias; ConvParam params; }; class ConvTranspose1D : public Module { public: struct ConvParam { SizeType InChannels; SizeType OutChannels; SizeType KernelSize; int Stride = 1; int Padding = 0; int OutPutPadding = 0; int Dilation = 1; int Groups = 1; bool Bias = true; PaddingType PaddingMode = Zeros; }; ConvTranspose1D(Module* _Parent, const std::wstring& _Name, const ConvParam& _Params); ggml_tensor* operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace = false) override; void ChangeParam(const ConvParam& _Params); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Parameter weight; Parameter bias; ConvParam params; }; class ConvTranspose2D : public Module { public: struct ConvParam { SizeType InChannels; SizeType OutChannels; SizeType KernelSize[2]; int Stride[2] = { 1, 1 }; int Padding[2] = { 0, 0 }; int OutPutPadding[2] = { 0, 0 }; int Dilation[2] = { 1, 1 }; int Groups = 1; bool Bias = true; PaddingType PaddingMode = Zeros; }; ConvTranspose2D(Module* _Parent, const std::wstring& _Name, const ConvParam& _Params); ggml_tensor* operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace = false) override; void ChangeParam(const ConvParam& _Params); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Parameter weight; Parameter bias; ConvParam params; }; class Linear : public Module { public: struct LinearParam { SizeType InFeatures; SizeType OutFeatures; bool Bias = true; }; Linear(Module* _Parent, const std::wstring& _Name, const LinearParam& _Params); ggml_tensor* operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace = false) override; void ChangeParam(const LinearParam& _Params); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Parameter weight; Parameter bias; LinearParam params; }; class Embedding : public Module { public: struct EmbeddingParam { int NumEmbeddings; int EmbeddingDim; int PaddingIdx = INT_MAX; float MaxNorm = NAN; float NormType = 2.f; bool ScaleGradByFreq = false; bool Sparse = false; bool Freeze = false; }; Embedding(Module* _Parent, const std::wstring& _Name, const EmbeddingParam& _Params); ggml_tensor* operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace = false) override; void ChangeParam(const EmbeddingParam& _Params); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Parameter weight; //Parameter bias; EmbeddingParam params; }; LibTTSEnd ================================================ FILE: fish-speech.cpp/include/llama.h ================================================ #pragma once #include "Module.h" LibTTSBegin struct BaseModelArgs { int vocab_size = 32000; int n_layer = 32; int n_head = 32; int dim = 4096; int intermediate_size = 1; int n_local_heads = -1; int head_dim = 64; float rope_base = 10000.f; float norm_eps = 1e-5f; int max_seq_len = 2048; float dropout = 0.f; // Codebook configs int codebook_size = 160; int num_codebooks = 4; int num_in_codebooks = 0; int codebook_padding_idx = 0; // Gradient checkpointing bool use_gradient_checkpointing = true; }; class RMSNorm : public Module { public: RMSNorm(Module* _Parent, const std::wstring& _Name, SizeType dim, float eps = 1e-5f); ggml_tensor* operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace = false) override; void ChangeParam(SizeType dim, float eps = 1e-5f); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Parameter weight; SizeType dim_; float eps_; }; class FeedForward : public Module { public: FeedForward(Module* _Parent, const std::wstring& _Name, const BaseModelArgs& config); ggml_tensor* operator()(ggml_tensor* x, ggml_context* _Ctx, bool _Inplace = false) override; void ChangeParam(const BaseModelArgs& config); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Linear w1, w3, w2; BaseModelArgs args_; }; class Attention : public Module { public: Attention(Module* _Parent, const std::wstring& _Name, const BaseModelArgs& config, bool use_sdpa = true); ggml_tensor* operator()( ggml_tensor* x, ggml_tensor* freqs_cis, ggml_tensor* mask, ggml_tensor* input_pos, ggml_context* _Ctx, bool _Inplace = false ); bool training = false; private: ggml_tensor* apply_rotary_emb( ggml_tensor* x, ggml_tensor* freqs_cis, ggml_context* _Ctx, bool _Inplace = false ); static ggml_tensor* scaled_dot_product_attention( ggml_tensor* query, ggml_tensor* key, ggml_tensor* value, ggml_context* _Ctx, ggml_tensor* attn_mask = nullptr, float dropout_p = 0.0, bool _Inplace = false ); static ggml_tensor* eq_scaled_dot_product_attention( ggml_tensor* query, ggml_tensor* key, ggml_tensor* value, ggml_context* _Ctx, ggml_tensor* attn_mask = nullptr, float dropout_p = 0.0, bool _Inplace = false ); void DumpCurrentLayerInfo(std::wstring& _Tmp) override; int total_head_dim; Linear wqkv, wo; float dropout; int n_head; int head_dim; int n_local_heads; int dim; bool use_sdpa; BaseModelArgs args_; }; class TransformerBlock : public Module { public: TransformerBlock(Module* _Parent, const std::wstring& _Name, const BaseModelArgs& config, bool use_sdpa = true); ggml_tensor* operator()( ggml_tensor* x, ggml_tensor* freqs_cis, ggml_tensor* mask, ggml_tensor* input_pos, ggml_context* _Ctx, bool _Inplace = false ); private: void DumpCurrentLayerInfo(std::wstring& _Tmp) override; Attention attention; FeedForward feed_forward; RMSNorm ffn_norm; RMSNorm attention_norm; }; class BaseTransformer : public Module { public: BaseTransformer(Module* _Parent, const std::wstring& _Name, const BaseModelArgs& config); private: BaseModelArgs config_; Embedding embeddings; ModuleList layers; RMSNorm norm; Linear output; Parameter freqs_cis; Parameter causal_mask; int max_batch_size = -1; int max_seq_len = -1; }; LibTTSEnd ================================================ FILE: fish-speech.cpp/src/Base.cpp ================================================ #include "../include/Base.h" #include #ifdef _WIN32 #include #else #error #endif LibTTSBegin std::string UnicodeToByte(const std::wstring& input) { #ifdef _WIN32 std::vector ByteString(input.length() * 6); WideCharToMultiByte( CP_UTF8, 0, input.c_str(), int(input.length()), ByteString.data(), int(ByteString.size()), nullptr, nullptr ); return ByteString.data(); #else //TODO #endif } std::string UnicodeToAnsi(const std::wstring& input) { #ifdef _WIN32 std::vector ByteString(input.length() * 6); WideCharToMultiByte( CP_ACP, 0, input.c_str(), int(input.length()), ByteString.data(), int(ByteString.size()), nullptr, nullptr ); return ByteString.data(); #else //TODO #endif } std::wstring ByteToUnicode(const std::string& input) { #ifdef _WIN32 std::vector WideString(input.length() * 2); MultiByteToWideChar( CP_UTF8, 0, input.c_str(), int(input.length()), WideString.data(), int(WideString.size()) ); return WideString.data(); #else //TODO #endif } FileGuard::~FileGuard() { Close(); } FileGuard::FileGuard(FileGuard&& _Right) noexcept { file_ = _Right.file_; _Right.file_ = nullptr; } FileGuard& FileGuard::operator=(FileGuard&& _Right) noexcept { file_ = _Right.file_; _Right.file_ = nullptr; return *this; } void FileGuard::Open(const std::wstring& _Path, const std::wstring& _Mode) { #ifdef _WIN32 _wfopen_s(&file_, _Path.c_str(), _Mode.c_str()); #else file_ = _wfopen(_Path.c_str(), _Mode.c_str()); #endif } FileGuard::operator FILE* () const { return file_; } bool FileGuard::Enabled() const { return file_; } void FileGuard::Close() { if (file_) fclose(file_); file_ = nullptr; } Value::~Value() { if (DictGuf) gguf_free(DictGuf); if (DictCtx) ggml_free(DictCtx); DictGuf = nullptr; DictCtx = nullptr; } Value& Value::load(const std::wstring& _Path, bool _Strict) { FileGuard DictFile; DictFile.Open(_Path, L"rb"); if (!DictFile.Enabled()) LibTTSThrow("Failed To Open File!"); DictFile.Close(); gguf_init_params params{ false,&DictCtx }; DictGuf = gguf_init_from_file(UnicodeToByte(_Path).c_str(), params); loadData(DictCtx, _Strict); return *this; } Value& Value::save(const std::wstring& _Path) { FileGuard file; file.Open(_Path, L"rb"); if (!file.Enabled()) LibTTSThrow("Failed to open file!"); saveData(file); return *this; } void Value::loadData(const DictType& _WeightDict, bool _Strict) { LibTTSNotImplementedError; } void Value::saveData(FileGuard& _File) { LibTTSNotImplementedError; } Module::Module(Module* _Parent, const std::wstring& _Name) { if (_Parent != nullptr) { if(!_Parent->RegName_.empty()) RegName_ = _Parent->RegName_ + L"." + _Name; else RegName_ = _Name; _Parent->Layers_[RegName_] = this; } else RegName_ = _Name; } void Module::loadData(const DictType& _WeightDict, bool _Strict) { for (const auto& it : Layers_ | std::views::values) it->loadData(_WeightDict, _Strict); } void Module::saveData(FileGuard& _File) { for (const auto& it : Layers_ | std::views::values) it->saveData(_File); } ggml_tensor* Module::operator()(ggml_tensor*, ggml_context*, bool _Inplace) { LibTTSNotImplementedError; } void Module::ReCalcLayerName(const std::wstring& _Parent) { std::unordered_map Lay; for (auto i : Layers_ | std::ranges::views::values) { i->ReCalcLayerName(_Parent); i->RegName_ = _Parent + L"." + i->RegName_; Lay[i->RegName_] = i; } Layers_ = std::move(Lay); } std::wstring Module::DumpLayerNameInfo() { std::wstring Ret; DumpLayerNameInfoImpl(Ret, 0); return Ret; } void Module::DumpLayerNameInfoImpl(std::wstring& _Tmp, int TabCount) { for (int i = 0; i < TabCount; ++i) _Tmp += L" "; DumpCurrentLayerInfo(_Tmp); if(!Layers_.empty()) { if(!_Tmp.empty()) _Tmp += L" = {"; else _Tmp += L"{"; _Tmp += '\n'; for (auto i : Layers_ | std::ranges::views::values) i->DumpLayerNameInfoImpl(_Tmp, TabCount + 1); for (int i = 0; i < TabCount; ++i) _Tmp += L" "; _Tmp += L'}'; _Tmp += '\n'; } else _Tmp += '\n'; } void Module::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += RegName_; } Parameter::Parameter(Module* _Parent, const std::wstring& _Name, std::vector _Shape) : Module(_Parent, _Name), Shape_(std::move(_Shape)) { std::ranges::reverse(Shape_); } Parameter::operator ggml_tensor*() const { if (!Weight_) LibTTSThrow(UnicodeToByte(L"\"" + RegName_ + L"\" Is Null!")); return Weight_; } void Parameter::ChangeShape(std::vector _Shape) { Shape_ = std::move(_Shape); std::ranges::reverse(Shape_); } void Parameter::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += (RegName_ + L" (Size["); auto RShape = Shape_; std::ranges::reverse(RShape); for (auto i : RShape) _Tmp += (std::to_wstring(i) + L", "); if(!RShape.empty()) { _Tmp.pop_back(); _Tmp.pop_back(); } _Tmp += L"])"; } void Parameter::loadData(const DictType& _WeightDict, bool _Strict) { try { Weight_ = ggml_get_tensor(_WeightDict, UnicodeToByte(RegName_).c_str()); } catch (std::exception& e) { LibTTSThrow(e.what()); } size_t Index = 0; for (const auto Value : Shape_) if (Value != Weight_->ne[Index++]) LibTTSThrow(UnicodeToByte(L"Size Of \"" + RegName_ + L"\" Size Of Pretrained Model!")); if (!Weight_) LibTTSThrow("Missing Weight \"" + UnicodeToByte(RegName_) + '\"'); } void Parameter::saveData(FileGuard& _File) { LibTTSNotImplementedError; } Sequential::Sequential(Module* _Parent, const std::wstring& _Name) : Module(_Parent, _Name) { } Sequential::~Sequential() { for (auto i : _Items) delete i; _Items.clear(); } ggml_tensor* Sequential::operator()(ggml_tensor* _Input, ggml_context* _Ctx, bool _Inplace) { for (auto i : _Items) _Input = i->operator()(_Input, _Ctx, _Inplace); return _Input; } void Sequential::Append(Module* _Module) { _Module->Name() = RegName_ + L"." + std::to_wstring(_Items.size()); _Module->ReCalcLayerName(_Module->Name()); _Items.emplace_back(_Module); Layers_[_Module->Name()] = _Module; } Sequential& Sequential::operator=(const std::initializer_list& _Input) { for (auto i : _Input) Append(i); return *this; } ModuleList::ModuleList(Module* _Parent, const std::wstring& _Name) : Sequential(_Parent, _Name) { } ModuleList::~ModuleList() { } ggml_tensor* ModuleList::operator()(ggml_tensor* _Input, ggml_context* _Ctx, bool _Inplace) { LibTTSNotImplementedError; } ModuleList& ModuleList::operator=(const std::initializer_list& _Input) { for (auto i : _Input) Append(i); return *this; } LibTTSEnd ================================================ FILE: fish-speech.cpp/src/Module.cpp ================================================ #include "Module.h" LibTTSBegin Conv1D::Conv1D(Module* _Parent, const std::wstring& _Name, const ConvParam& _Params) : Module(_Parent, _Name), RegisterLayer(weight, { _Params.OutChannels, _Params.InChannels / _Params.Groups, _Params.KernelSize }), RegisterLayer(bias, { _Params.OutChannels }), params(_Params) { if (!_Params.Bias) Layers_.erase(bias.Name()); } void Conv1D::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} Conv1D(in_channel[{}], out_channel[{}], kernel_size[{}])", RegName_, params.InChannels, params.OutChannels, params.KernelSize ); } ggml_tensor* Conv1D::operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace) { if (params.Bias) return ggml_add( _Ctx, ggml_conv_1d( _Ctx, _Tensor, weight, params.Stride, params.Padding, params.Dilation ), bias ); return ggml_conv_1d( _Ctx, _Tensor, weight, params.Stride, params.Padding, params.Dilation ); } void Conv1D::ChangeParam(const ConvParam& _Params) { params = _Params; weight.ChangeShape({ _Params.OutChannels, _Params.InChannels / _Params.Groups, _Params.KernelSize }); bias.ChangeShape({ _Params.OutChannels }); } Conv2D::Conv2D(Module* _Parent, const std::wstring& _Name, const ConvParam& _Params) : Module(_Parent, _Name), RegisterLayer( weight, { _Params.OutChannels, _Params.InChannels / _Params.Groups, _Params.KernelSize[0], _Params.KernelSize[1] } ), RegisterLayer(bias, { _Params.OutChannels }), params(_Params) { if (!_Params.Bias) Layers_.erase(bias.Name()); } void Conv2D::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} Conv2D(in_channel[{}], out_channel[{}], kernel_size[{}, {}])", RegName_, params.InChannels, params.OutChannels, params.KernelSize[0], params.KernelSize[1] ); } ggml_tensor* Conv2D::operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace) { if (params.Bias) return ggml_add( _Ctx, ggml_conv_2d( _Ctx, _Tensor, weight, params.Stride[0], params.Stride[1], params.Padding[0], params.Padding[1], params.Dilation[0], params.Dilation[1] ), bias ); return ggml_conv_2d( _Ctx, _Tensor, weight, params.Stride[0], params.Stride[1], params.Padding[0], params.Padding[1], params.Dilation[0], params.Dilation[1] ); } void Conv2D::ChangeParam(const ConvParam& _Params) { params = _Params; weight.ChangeShape({ _Params.OutChannels, _Params.InChannels / _Params.Groups, _Params.KernelSize[0], _Params.KernelSize[1] }); bias.ChangeShape({ _Params.OutChannels }); } ConvTranspose1D::ConvTranspose1D(Module* _Parent, const std::wstring& _Name, const ConvParam& _Params) : Module(_Parent, _Name), RegisterLayer(weight, { _Params.InChannels, _Params.OutChannels / _Params.Groups, _Params.KernelSize }), RegisterLayer(bias, { _Params.OutChannels }), params(_Params) { if (_Params.PaddingMode != Zeros) LibTTSThrow("Only `Zeros` Padding Mode Is Supported For ConvTranspose1D"); if (!_Params.Bias) Layers_.erase(bias.Name()); } void ConvTranspose1D::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} ConvTranspose1D(in_channel[{}], out_channel[{}], kernel_size[{}])", RegName_, params.InChannels, params.OutChannels, params.KernelSize ); } ggml_tensor* ConvTranspose1D::operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace) { if(params.Bias) { if (params.OutPutPadding) return ggml_add( _Ctx, ggml_pad( _Ctx, ggml_conv_transpose_1d( _Ctx, _Tensor, weight, params.Stride, params.Padding, params.Dilation ), params.OutPutPadding, 0, 0, 0 ), bias ); return ggml_add( _Ctx, ggml_conv_transpose_1d( _Ctx, _Tensor, weight, params.Stride, params.Padding, params.Dilation ), bias ); } if (params.OutPutPadding) return ggml_pad( _Ctx, ggml_conv_transpose_1d( _Ctx, _Tensor, weight, params.Stride, params.Padding, params.Dilation ), params.OutPutPadding, 0, 0, 0 ); return ggml_conv_transpose_1d( _Ctx, _Tensor, weight, params.Stride, params.Padding, params.Dilation ); } void ConvTranspose1D::ChangeParam(const ConvParam& _Params) { params = _Params; weight.ChangeShape({ _Params.InChannels, _Params.OutChannels / _Params.Groups, _Params.KernelSize }); bias.ChangeShape({ _Params.OutChannels }); } ConvTranspose2D::ConvTranspose2D(Module* _Parent, const std::wstring& _Name, const ConvParam& _Params) : Module(_Parent, _Name), RegisterLayer( weight, { _Params.InChannels, _Params.OutChannels / _Params.Groups, _Params.KernelSize[0], _Params.KernelSize[1] } ), RegisterLayer(bias, { _Params.OutChannels }), params(_Params) { if (!_Params.Bias) Layers_.erase(bias.Name()); } void ConvTranspose2D::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} ConvTranspose2D(in_channel[{}], out_channel[{}], kernel_size[{}, {}])", RegName_, params.InChannels, params.OutChannels, params.KernelSize[0], params.KernelSize[1] ); } ggml_tensor* ConvTranspose2D::operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace) { LibTTSNotImplementedError; //TODO } void ConvTranspose2D::ChangeParam(const ConvParam& _Params) { params = _Params; weight.ChangeShape({ _Params.InChannels, _Params.OutChannels / _Params.Groups, _Params.KernelSize[0], _Params.KernelSize[1] }); bias.ChangeShape({ _Params.OutChannels }); } Linear::Linear(Module* _Parent, const std::wstring& _Name, const LinearParam& _Params): Module(_Parent, _Name), RegisterLayer(weight, { _Params.OutFeatures, _Params.InFeatures }), RegisterLayer(bias, { _Params.OutFeatures }), params(_Params) { if (!_Params.Bias) Layers_.erase(bias.Name()); } void Linear::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} Linear(in_feature[{}], out_feature[{}])", RegName_, params.InFeatures, params.OutFeatures ); } ggml_tensor* Linear::operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace) { if (params.Bias) return ggml_add(_Ctx, ggml_mul_mat(_Ctx, _Tensor, weight), bias); return ggml_mul_mat(_Ctx, _Tensor, weight); } void Linear::ChangeParam(const LinearParam& _Params) { params = _Params; weight.ChangeShape({ _Params.OutFeatures, _Params.InFeatures }); bias.ChangeShape({ _Params.OutFeatures }); } Embedding::Embedding(Module* _Parent, const std::wstring& _Name, const EmbeddingParam& _Params) : Module(_Parent, _Name), RegisterLayer(weight, { _Params.NumEmbeddings, _Params.EmbeddingDim }), params(_Params) { } void Embedding::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} Embedding(num_embeddings[{}], embedding_dim[{}])", RegName_, params.NumEmbeddings, params.EmbeddingDim ); } ggml_tensor* Embedding::operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace) { return ggml_get_rows(_Ctx, weight, _Tensor); } void Embedding::ChangeParam(const EmbeddingParam& _Params) { params = _Params; weight.ChangeShape({ _Params.NumEmbeddings, _Params.EmbeddingDim }); } LibTTSEnd ================================================ FILE: fish-speech.cpp/src/llama.cpp ================================================ #include "llama.h" LibTTSBegin inline void UnUsedPtr(void*) {} RMSNorm::RMSNorm(Module* _Parent, const std::wstring& _Name, SizeType dim, float eps) : Module(_Parent, _Name), RegisterLayer(weight, { dim }), dim_(dim), eps_(eps) { } ggml_tensor* RMSNorm::operator()(ggml_tensor* _Tensor, ggml_context* _Ctx, bool _Inplace) { if(_Inplace) return ggml_mul_inplace(_Ctx, ggml_rms_norm_inplace(_Ctx, _Tensor, eps_), weight); return ggml_mul(_Ctx, ggml_rms_norm(_Ctx, _Tensor, eps_), weight); } void RMSNorm::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} RMSNorm(dim[{}], eps[{}])", RegName_, dim_, eps_ ); } void RMSNorm::ChangeParam(SizeType dim, float eps) { weight.ChangeShape({ dim }); eps_ = eps; } FeedForward::FeedForward(Module* _Parent, const std::wstring& _Name, const BaseModelArgs& config) : Module(_Parent, _Name), RegisterLayer(w1, { config.dim, config.intermediate_size, false }), RegisterLayer(w3, { config.dim, config.intermediate_size, false }), RegisterLayer(w2, { config.intermediate_size, config.dim, false }), args_(config) { } ggml_tensor* FeedForward::operator()(ggml_tensor* x, ggml_context* _Ctx, bool _Inplace) { return w2( ggml_mul( _Ctx, ggml_silu_inplace(_Ctx, w1(x, _Ctx, _Inplace)), w3(x, _Ctx, _Inplace) ), _Ctx, _Inplace ); } void FeedForward::ChangeParam(const BaseModelArgs& config) { args_ = config; w1.ChangeParam({ config.dim, config.intermediate_size, false }); w3.ChangeParam({ config.dim, config.intermediate_size, false }); w2.ChangeParam({ config.intermediate_size, config.dim, false }); } void FeedForward::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} FeedForward()", RegName_ ); } Attention::Attention(Module* _Parent, const std::wstring& _Name, const BaseModelArgs& config, bool use_sdpa) : Module(_Parent, _Name), total_head_dim((config.n_head + 2 * config.n_local_heads)* config.head_dim), RegisterLayer(wqkv, { config.dim, (config.n_head + 2 * config.n_local_heads) * config.head_dim, false }), RegisterLayer(wo, { config.dim, config.dim, false }), dropout(config.dropout), n_head(config.n_head), head_dim(config.head_dim), n_local_heads(config.n_local_heads), dim(config.dim), use_sdpa(use_sdpa), args_(config) { } ggml_tensor* Attention::operator()( ggml_tensor* x, ggml_tensor* freqs_cis, ggml_tensor* mask, ggml_tensor* input_pos, ggml_context* _Ctx, bool _Inplace ) { int64_t bsz = x->ne[2], seqlen = x->ne[1]; int64_t kv_size = (int64_t)n_local_heads * head_dim; auto QKV = wqkv(x, _Ctx); int64_t n_tokens = 1; for (size_t i = 1; i < 4; ++i) n_tokens *= QKV->ne[i]; auto Q = ggml_cont( _Ctx, ggml_view_2d(_Ctx, QKV, dim, n_tokens, QKV->nb[1], 0 * sizeof(float) * (dim)) ); auto K = ggml_cont( _Ctx, ggml_view_2d(_Ctx, QKV, kv_size, n_tokens, QKV->nb[1], 1 * sizeof(float) * (dim)) ); auto V = ggml_cont( _Ctx, ggml_view_2d(_Ctx, QKV, kv_size, n_tokens, QKV->nb[1], 1 * sizeof(float) * (dim + kv_size)) ); Q = ggml_reshape_4d(_Ctx, Q, head_dim, n_head, seqlen, bsz); K = ggml_reshape_4d(_Ctx, K, head_dim, n_local_heads, seqlen, bsz); V = ggml_reshape_4d(_Ctx, V, head_dim, n_local_heads, seqlen, bsz); Q = apply_rotary_emb(Q, freqs_cis, _Ctx, _Inplace); K = apply_rotary_emb(K, freqs_cis, _Ctx, _Inplace); Q = ggml_cont(_Ctx, ggml_permute(_Ctx, Q, 0, 2, 1, 3)); K = ggml_cont(_Ctx, ggml_permute(_Ctx, K, 0, 2, 1, 3)); V = ggml_cont(_Ctx, ggml_permute(_Ctx, V, 0, 2, 1, 3)); //TODO KVCACHE int Scale = n_head / n_local_heads; if(Scale > 1) { K = ggml_repeat(_Ctx, K, ggml_new_tensor_4d(_Ctx, K->type, K->ne[0], K->ne[1] * Scale, K->ne[2], K->ne[3])); V = ggml_repeat(_Ctx, V, ggml_new_tensor_4d(_Ctx, V->type, V->ne[0], V->ne[1] * Scale, V->ne[2], V->ne[3])); } ggml_tensor* y; if(use_sdpa) y = scaled_dot_product_attention( Q, K, V, _Ctx, mask, training ? dropout : 0.f ); else y = eq_scaled_dot_product_attention( Q, K, V, _Ctx, mask, training ? dropout : 0.f ); y = ggml_reshape_3d(_Ctx, ggml_cont(_Ctx, ggml_permute(_Ctx, y, 0, 2, 1, 3)), dim, seqlen, bsz); return wo(y, _Ctx, _Inplace); } ggml_tensor* Attention::apply_rotary_emb(ggml_tensor* x, ggml_tensor* freqs_cis, ggml_context* _Ctx, bool _Inplace) { int ndim = int(x->ne[0]) / 2; int64_t n_tokens = x->ne[0] / 2; for (size_t i = 1; i < 4; ++i) n_tokens *= x->ne[i]; auto xshape = ggml_reshape_2d(_Ctx, x, 2, n_tokens); auto xshape0 = ggml_view_4d(_Ctx, xshape, ndim, x->ne[1], x->ne[2], x->ne[3], x->nb[1], x->nb[2], x->nb[3], 0); auto xshape1 = ggml_view_4d(_Ctx, xshape, ndim, x->ne[1], x->ne[2], x->ne[3], x->nb[1], x->nb[2], x->nb[3], sizeof(float)); return nullptr; } ggml_tensor* Attention::scaled_dot_product_attention( ggml_tensor* query, ggml_tensor* key, ggml_tensor* value, ggml_context* _Ctx, ggml_tensor* attn_mask, float dropout_p, bool _Inplace ) { UnUsedPtr(attn_mask); UNUSED(dropout_p); UNUSED(_Inplace); return ggml_flash_attn(_Ctx, query, key, value, false); } ggml_tensor* Attention::eq_scaled_dot_product_attention( ggml_tensor* query, ggml_tensor* key, ggml_tensor* value, ggml_context* _Ctx, ggml_tensor* attn_mask, float dropout_p, bool _Inplace ) { UnUsedPtr(attn_mask); UNUSED(dropout_p); UNUSED(_Inplace); return ggml_flash_attn(_Ctx, query, key, value, false); } void Attention::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} AttentionLayer()", RegName_ ); } TransformerBlock::TransformerBlock(Module* _Parent, const std::wstring& _Name, const BaseModelArgs& config, bool use_sdpa): Module(_Parent, _Name), RegisterLayer(attention, config, use_sdpa), RegisterLayer(feed_forward, config), RegisterLayer(ffn_norm, config.dim, config.norm_eps), RegisterLayer(attention_norm, config.dim, config.norm_eps) { } ggml_tensor* TransformerBlock::operator()( ggml_tensor* x, ggml_tensor* freqs_cis, ggml_tensor* mask, ggml_tensor* input_pos, ggml_context* _Ctx, bool _Inplace ) { UNUSED(_Inplace); auto h = attention(attention_norm(x, _Ctx, true), freqs_cis, mask, input_pos, _Ctx); return ggml_add_inplace(_Ctx, h, feed_forward(ffn_norm(h, _Ctx), _Ctx)); } void TransformerBlock::DumpCurrentLayerInfo(std::wstring& _Tmp) { _Tmp += std::format( L"{} TransformerBlock()", RegName_ ); } BaseTransformer::BaseTransformer(Module* _Parent, const std::wstring& _Name, const BaseModelArgs& config): Module(_Parent, _Name), config_(config), RegisterLayer(embeddings, { config.vocab_size + config.codebook_size * config.num_in_codebooks, config.dim }), RegisterLayer(layers), RegisterLayer(norm, config.dim, config.norm_eps), RegisterLayer(output, { config.dim, config.vocab_size, false }), RegisterLayer(freqs_cis, { config.max_seq_len, (config.dim / config.n_head) / 2 }), RegisterLayer(causal_mask, { config.max_seq_len, config.max_seq_len }) { for (int i = 0; i < config.n_layer; ++i) layers.Append(LayerItem(TransformerBlock, config, true)); } LibTTSEnd ================================================ FILE: fish-speech.cpp/test.py ================================================ import torch import time for i in range(20): a = torch.ones(size=(1, 768, 100000)) beg = time.time() a.fill_(i) print(time.time() - beg) ================================================ FILE: fish-speech.cpp/test.txt ================================================ { embeddings Embedding(num_embeddings[32000], embedding_dim[4096]) = { embeddings.weight (Size[32000, 4096]) } layers = { layers.0 TransformerBlock() = { layers.0.attention AttentionLayer() = { layers.0.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.0.attention.wqkv.weight (Size[1920, 4096]) } layers.0.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.0.attention.wo.weight (Size[4096, 4096]) } } layers.0.feed_forward FeedForward() = { layers.0.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.0.feed_forward.w1.weight (Size[1, 4096]) } layers.0.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.0.feed_forward.w3.weight (Size[1, 4096]) } layers.0.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.0.feed_forward.w2.weight (Size[4096, 1]) } } layers.0.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.0.ffn_norm.weight (Size[4096]) } layers.0.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.0.attention_norm.weight (Size[4096]) } } layers.1 TransformerBlock() = { layers.1.attention AttentionLayer() = { layers.1.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.1.attention.wqkv.weight (Size[1920, 4096]) } layers.1.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.1.attention.wo.weight (Size[4096, 4096]) } } layers.1.feed_forward FeedForward() = { layers.1.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.1.feed_forward.w1.weight (Size[1, 4096]) } layers.1.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.1.feed_forward.w3.weight (Size[1, 4096]) } layers.1.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.1.feed_forward.w2.weight (Size[4096, 1]) } } layers.1.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.1.ffn_norm.weight (Size[4096]) } layers.1.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.1.attention_norm.weight (Size[4096]) } } layers.28 TransformerBlock() = { layers.28.attention AttentionLayer() = { layers.28.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.28.attention.wqkv.weight (Size[1920, 4096]) } layers.28.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.28.attention.wo.weight (Size[4096, 4096]) } } layers.28.feed_forward FeedForward() = { layers.28.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.28.feed_forward.w1.weight (Size[1, 4096]) } layers.28.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.28.feed_forward.w3.weight (Size[1, 4096]) } layers.28.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.28.feed_forward.w2.weight (Size[4096, 1]) } } layers.28.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.28.ffn_norm.weight (Size[4096]) } layers.28.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.28.attention_norm.weight (Size[4096]) } } layers.2 TransformerBlock() = { layers.2.attention AttentionLayer() = { layers.2.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.2.attention.wqkv.weight (Size[1920, 4096]) } layers.2.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.2.attention.wo.weight (Size[4096, 4096]) } } layers.2.feed_forward FeedForward() = { layers.2.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.2.feed_forward.w1.weight (Size[1, 4096]) } layers.2.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.2.feed_forward.w3.weight (Size[1, 4096]) } layers.2.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.2.feed_forward.w2.weight (Size[4096, 1]) } } layers.2.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.2.ffn_norm.weight (Size[4096]) } layers.2.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.2.attention_norm.weight (Size[4096]) } } layers.29 TransformerBlock() = { layers.29.attention AttentionLayer() = { layers.29.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.29.attention.wqkv.weight (Size[1920, 4096]) } layers.29.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.29.attention.wo.weight (Size[4096, 4096]) } } layers.29.feed_forward FeedForward() = { layers.29.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.29.feed_forward.w1.weight (Size[1, 4096]) } layers.29.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.29.feed_forward.w3.weight (Size[1, 4096]) } layers.29.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.29.feed_forward.w2.weight (Size[4096, 1]) } } layers.29.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.29.ffn_norm.weight (Size[4096]) } layers.29.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.29.attention_norm.weight (Size[4096]) } } layers.3 TransformerBlock() = { layers.3.attention AttentionLayer() = { layers.3.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.3.attention.wqkv.weight (Size[1920, 4096]) } layers.3.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.3.attention.wo.weight (Size[4096, 4096]) } } layers.3.feed_forward FeedForward() = { layers.3.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.3.feed_forward.w1.weight (Size[1, 4096]) } layers.3.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.3.feed_forward.w3.weight (Size[1, 4096]) } layers.3.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.3.feed_forward.w2.weight (Size[4096, 1]) } } layers.3.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.3.ffn_norm.weight (Size[4096]) } layers.3.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.3.attention_norm.weight (Size[4096]) } } layers.4 TransformerBlock() = { layers.4.attention AttentionLayer() = { layers.4.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.4.attention.wqkv.weight (Size[1920, 4096]) } layers.4.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.4.attention.wo.weight (Size[4096, 4096]) } } layers.4.feed_forward FeedForward() = { layers.4.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.4.feed_forward.w1.weight (Size[1, 4096]) } layers.4.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.4.feed_forward.w3.weight (Size[1, 4096]) } layers.4.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.4.feed_forward.w2.weight (Size[4096, 1]) } } layers.4.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.4.ffn_norm.weight (Size[4096]) } layers.4.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.4.attention_norm.weight (Size[4096]) } } layers.5 TransformerBlock() = { layers.5.attention AttentionLayer() = { layers.5.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.5.attention.wqkv.weight (Size[1920, 4096]) } layers.5.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.5.attention.wo.weight (Size[4096, 4096]) } } layers.5.feed_forward FeedForward() = { layers.5.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.5.feed_forward.w1.weight (Size[1, 4096]) } layers.5.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.5.feed_forward.w3.weight (Size[1, 4096]) } layers.5.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.5.feed_forward.w2.weight (Size[4096, 1]) } } layers.5.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.5.ffn_norm.weight (Size[4096]) } layers.5.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.5.attention_norm.weight (Size[4096]) } } layers.6 TransformerBlock() = { layers.6.attention AttentionLayer() = { layers.6.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.6.attention.wqkv.weight (Size[1920, 4096]) } layers.6.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.6.attention.wo.weight (Size[4096, 4096]) } } layers.6.feed_forward FeedForward() = { layers.6.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.6.feed_forward.w1.weight (Size[1, 4096]) } layers.6.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.6.feed_forward.w3.weight (Size[1, 4096]) } layers.6.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.6.feed_forward.w2.weight (Size[4096, 1]) } } layers.6.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.6.ffn_norm.weight (Size[4096]) } layers.6.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.6.attention_norm.weight (Size[4096]) } } layers.7 TransformerBlock() = { layers.7.attention AttentionLayer() = { layers.7.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.7.attention.wqkv.weight (Size[1920, 4096]) } layers.7.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.7.attention.wo.weight (Size[4096, 4096]) } } layers.7.feed_forward FeedForward() = { layers.7.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.7.feed_forward.w1.weight (Size[1, 4096]) } layers.7.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.7.feed_forward.w3.weight (Size[1, 4096]) } layers.7.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.7.feed_forward.w2.weight (Size[4096, 1]) } } layers.7.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.7.ffn_norm.weight (Size[4096]) } layers.7.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.7.attention_norm.weight (Size[4096]) } } layers.22 TransformerBlock() = { layers.22.attention AttentionLayer() = { layers.22.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.22.attention.wqkv.weight (Size[1920, 4096]) } layers.22.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.22.attention.wo.weight (Size[4096, 4096]) } } layers.22.feed_forward FeedForward() = { layers.22.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.22.feed_forward.w1.weight (Size[1, 4096]) } layers.22.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.22.feed_forward.w3.weight (Size[1, 4096]) } layers.22.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.22.feed_forward.w2.weight (Size[4096, 1]) } } layers.22.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.22.ffn_norm.weight (Size[4096]) } layers.22.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.22.attention_norm.weight (Size[4096]) } } layers.8 TransformerBlock() = { layers.8.attention AttentionLayer() = { layers.8.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.8.attention.wqkv.weight (Size[1920, 4096]) } layers.8.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.8.attention.wo.weight (Size[4096, 4096]) } } layers.8.feed_forward FeedForward() = { layers.8.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.8.feed_forward.w1.weight (Size[1, 4096]) } layers.8.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.8.feed_forward.w3.weight (Size[1, 4096]) } layers.8.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.8.feed_forward.w2.weight (Size[4096, 1]) } } layers.8.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.8.ffn_norm.weight (Size[4096]) } layers.8.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.8.attention_norm.weight (Size[4096]) } } layers.23 TransformerBlock() = { layers.23.attention AttentionLayer() = { layers.23.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.23.attention.wqkv.weight (Size[1920, 4096]) } layers.23.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.23.attention.wo.weight (Size[4096, 4096]) } } layers.23.feed_forward FeedForward() = { layers.23.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.23.feed_forward.w1.weight (Size[1, 4096]) } layers.23.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.23.feed_forward.w3.weight (Size[1, 4096]) } layers.23.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.23.feed_forward.w2.weight (Size[4096, 1]) } } layers.23.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.23.ffn_norm.weight (Size[4096]) } layers.23.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.23.attention_norm.weight (Size[4096]) } } layers.9 TransformerBlock() = { layers.9.attention AttentionLayer() = { layers.9.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.9.attention.wqkv.weight (Size[1920, 4096]) } layers.9.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.9.attention.wo.weight (Size[4096, 4096]) } } layers.9.feed_forward FeedForward() = { layers.9.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.9.feed_forward.w1.weight (Size[1, 4096]) } layers.9.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.9.feed_forward.w3.weight (Size[1, 4096]) } layers.9.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.9.feed_forward.w2.weight (Size[4096, 1]) } } layers.9.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.9.ffn_norm.weight (Size[4096]) } layers.9.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.9.attention_norm.weight (Size[4096]) } } layers.10 TransformerBlock() = { layers.10.attention AttentionLayer() = { layers.10.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.10.attention.wqkv.weight (Size[1920, 4096]) } layers.10.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.10.attention.wo.weight (Size[4096, 4096]) } } layers.10.feed_forward FeedForward() = { layers.10.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.10.feed_forward.w1.weight (Size[1, 4096]) } layers.10.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.10.feed_forward.w3.weight (Size[1, 4096]) } layers.10.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.10.feed_forward.w2.weight (Size[4096, 1]) } } layers.10.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.10.ffn_norm.weight (Size[4096]) } layers.10.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.10.attention_norm.weight (Size[4096]) } } layers.11 TransformerBlock() = { layers.11.attention AttentionLayer() = { layers.11.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.11.attention.wqkv.weight (Size[1920, 4096]) } layers.11.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.11.attention.wo.weight (Size[4096, 4096]) } } layers.11.feed_forward FeedForward() = { layers.11.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.11.feed_forward.w1.weight (Size[1, 4096]) } layers.11.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.11.feed_forward.w3.weight (Size[1, 4096]) } layers.11.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.11.feed_forward.w2.weight (Size[4096, 1]) } } layers.11.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.11.ffn_norm.weight (Size[4096]) } layers.11.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.11.attention_norm.weight (Size[4096]) } } layers.12 TransformerBlock() = { layers.12.attention AttentionLayer() = { layers.12.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.12.attention.wqkv.weight (Size[1920, 4096]) } layers.12.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.12.attention.wo.weight (Size[4096, 4096]) } } layers.12.feed_forward FeedForward() = { layers.12.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.12.feed_forward.w1.weight (Size[1, 4096]) } layers.12.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.12.feed_forward.w3.weight (Size[1, 4096]) } layers.12.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.12.feed_forward.w2.weight (Size[4096, 1]) } } layers.12.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.12.ffn_norm.weight (Size[4096]) } layers.12.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.12.attention_norm.weight (Size[4096]) } } layers.13 TransformerBlock() = { layers.13.attention AttentionLayer() = { layers.13.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.13.attention.wqkv.weight (Size[1920, 4096]) } layers.13.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.13.attention.wo.weight (Size[4096, 4096]) } } layers.13.feed_forward FeedForward() = { layers.13.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.13.feed_forward.w1.weight (Size[1, 4096]) } layers.13.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.13.feed_forward.w3.weight (Size[1, 4096]) } layers.13.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.13.feed_forward.w2.weight (Size[4096, 1]) } } layers.13.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.13.ffn_norm.weight (Size[4096]) } layers.13.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.13.attention_norm.weight (Size[4096]) } } layers.14 TransformerBlock() = { layers.14.attention AttentionLayer() = { layers.14.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.14.attention.wqkv.weight (Size[1920, 4096]) } layers.14.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.14.attention.wo.weight (Size[4096, 4096]) } } layers.14.feed_forward FeedForward() = { layers.14.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.14.feed_forward.w1.weight (Size[1, 4096]) } layers.14.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.14.feed_forward.w3.weight (Size[1, 4096]) } layers.14.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.14.feed_forward.w2.weight (Size[4096, 1]) } } layers.14.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.14.ffn_norm.weight (Size[4096]) } layers.14.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.14.attention_norm.weight (Size[4096]) } } layers.15 TransformerBlock() = { layers.15.attention AttentionLayer() = { layers.15.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.15.attention.wqkv.weight (Size[1920, 4096]) } layers.15.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.15.attention.wo.weight (Size[4096, 4096]) } } layers.15.feed_forward FeedForward() = { layers.15.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.15.feed_forward.w1.weight (Size[1, 4096]) } layers.15.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.15.feed_forward.w3.weight (Size[1, 4096]) } layers.15.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.15.feed_forward.w2.weight (Size[4096, 1]) } } layers.15.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.15.ffn_norm.weight (Size[4096]) } layers.15.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.15.attention_norm.weight (Size[4096]) } } layers.16 TransformerBlock() = { layers.16.attention AttentionLayer() = { layers.16.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.16.attention.wqkv.weight (Size[1920, 4096]) } layers.16.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.16.attention.wo.weight (Size[4096, 4096]) } } layers.16.feed_forward FeedForward() = { layers.16.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.16.feed_forward.w1.weight (Size[1, 4096]) } layers.16.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.16.feed_forward.w3.weight (Size[1, 4096]) } layers.16.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.16.feed_forward.w2.weight (Size[4096, 1]) } } layers.16.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.16.ffn_norm.weight (Size[4096]) } layers.16.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.16.attention_norm.weight (Size[4096]) } } layers.17 TransformerBlock() = { layers.17.attention AttentionLayer() = { layers.17.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.17.attention.wqkv.weight (Size[1920, 4096]) } layers.17.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.17.attention.wo.weight (Size[4096, 4096]) } } layers.17.feed_forward FeedForward() = { layers.17.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.17.feed_forward.w1.weight (Size[1, 4096]) } layers.17.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.17.feed_forward.w3.weight (Size[1, 4096]) } layers.17.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.17.feed_forward.w2.weight (Size[4096, 1]) } } layers.17.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.17.ffn_norm.weight (Size[4096]) } layers.17.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.17.attention_norm.weight (Size[4096]) } } layers.18 TransformerBlock() = { layers.18.attention AttentionLayer() = { layers.18.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.18.attention.wqkv.weight (Size[1920, 4096]) } layers.18.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.18.attention.wo.weight (Size[4096, 4096]) } } layers.18.feed_forward FeedForward() = { layers.18.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.18.feed_forward.w1.weight (Size[1, 4096]) } layers.18.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.18.feed_forward.w3.weight (Size[1, 4096]) } layers.18.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.18.feed_forward.w2.weight (Size[4096, 1]) } } layers.18.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.18.ffn_norm.weight (Size[4096]) } layers.18.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.18.attention_norm.weight (Size[4096]) } } layers.19 TransformerBlock() = { layers.19.attention AttentionLayer() = { layers.19.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.19.attention.wqkv.weight (Size[1920, 4096]) } layers.19.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.19.attention.wo.weight (Size[4096, 4096]) } } layers.19.feed_forward FeedForward() = { layers.19.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.19.feed_forward.w1.weight (Size[1, 4096]) } layers.19.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.19.feed_forward.w3.weight (Size[1, 4096]) } layers.19.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.19.feed_forward.w2.weight (Size[4096, 1]) } } layers.19.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.19.ffn_norm.weight (Size[4096]) } layers.19.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.19.attention_norm.weight (Size[4096]) } } layers.20 TransformerBlock() = { layers.20.attention AttentionLayer() = { layers.20.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.20.attention.wqkv.weight (Size[1920, 4096]) } layers.20.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.20.attention.wo.weight (Size[4096, 4096]) } } layers.20.feed_forward FeedForward() = { layers.20.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.20.feed_forward.w1.weight (Size[1, 4096]) } layers.20.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.20.feed_forward.w3.weight (Size[1, 4096]) } layers.20.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.20.feed_forward.w2.weight (Size[4096, 1]) } } layers.20.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.20.ffn_norm.weight (Size[4096]) } layers.20.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.20.attention_norm.weight (Size[4096]) } } layers.21 TransformerBlock() = { layers.21.attention AttentionLayer() = { layers.21.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.21.attention.wqkv.weight (Size[1920, 4096]) } layers.21.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.21.attention.wo.weight (Size[4096, 4096]) } } layers.21.feed_forward FeedForward() = { layers.21.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.21.feed_forward.w1.weight (Size[1, 4096]) } layers.21.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.21.feed_forward.w3.weight (Size[1, 4096]) } layers.21.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.21.feed_forward.w2.weight (Size[4096, 1]) } } layers.21.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.21.ffn_norm.weight (Size[4096]) } layers.21.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.21.attention_norm.weight (Size[4096]) } } layers.24 TransformerBlock() = { layers.24.attention AttentionLayer() = { layers.24.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.24.attention.wqkv.weight (Size[1920, 4096]) } layers.24.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.24.attention.wo.weight (Size[4096, 4096]) } } layers.24.feed_forward FeedForward() = { layers.24.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.24.feed_forward.w1.weight (Size[1, 4096]) } layers.24.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.24.feed_forward.w3.weight (Size[1, 4096]) } layers.24.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.24.feed_forward.w2.weight (Size[4096, 1]) } } layers.24.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.24.ffn_norm.weight (Size[4096]) } layers.24.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.24.attention_norm.weight (Size[4096]) } } layers.25 TransformerBlock() = { layers.25.attention AttentionLayer() = { layers.25.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.25.attention.wqkv.weight (Size[1920, 4096]) } layers.25.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.25.attention.wo.weight (Size[4096, 4096]) } } layers.25.feed_forward FeedForward() = { layers.25.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.25.feed_forward.w1.weight (Size[1, 4096]) } layers.25.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.25.feed_forward.w3.weight (Size[1, 4096]) } layers.25.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.25.feed_forward.w2.weight (Size[4096, 1]) } } layers.25.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.25.ffn_norm.weight (Size[4096]) } layers.25.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.25.attention_norm.weight (Size[4096]) } } layers.26 TransformerBlock() = { layers.26.attention AttentionLayer() = { layers.26.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.26.attention.wqkv.weight (Size[1920, 4096]) } layers.26.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.26.attention.wo.weight (Size[4096, 4096]) } } layers.26.feed_forward FeedForward() = { layers.26.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.26.feed_forward.w1.weight (Size[1, 4096]) } layers.26.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.26.feed_forward.w3.weight (Size[1, 4096]) } layers.26.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.26.feed_forward.w2.weight (Size[4096, 1]) } } layers.26.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.26.ffn_norm.weight (Size[4096]) } layers.26.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.26.attention_norm.weight (Size[4096]) } } layers.27 TransformerBlock() = { layers.27.attention AttentionLayer() = { layers.27.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.27.attention.wqkv.weight (Size[1920, 4096]) } layers.27.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.27.attention.wo.weight (Size[4096, 4096]) } } layers.27.feed_forward FeedForward() = { layers.27.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.27.feed_forward.w1.weight (Size[1, 4096]) } layers.27.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.27.feed_forward.w3.weight (Size[1, 4096]) } layers.27.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.27.feed_forward.w2.weight (Size[4096, 1]) } } layers.27.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.27.ffn_norm.weight (Size[4096]) } layers.27.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.27.attention_norm.weight (Size[4096]) } } layers.30 TransformerBlock() = { layers.30.attention AttentionLayer() = { layers.30.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.30.attention.wqkv.weight (Size[1920, 4096]) } layers.30.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.30.attention.wo.weight (Size[4096, 4096]) } } layers.30.feed_forward FeedForward() = { layers.30.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.30.feed_forward.w1.weight (Size[1, 4096]) } layers.30.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.30.feed_forward.w3.weight (Size[1, 4096]) } layers.30.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.30.feed_forward.w2.weight (Size[4096, 1]) } } layers.30.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.30.ffn_norm.weight (Size[4096]) } layers.30.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.30.attention_norm.weight (Size[4096]) } } layers.31 TransformerBlock() = { layers.31.attention AttentionLayer() = { layers.31.attention.wqkv Linear(in_feature[4096], out_feature[1920]) = { layers.31.attention.wqkv.weight (Size[1920, 4096]) } layers.31.attention.wo Linear(in_feature[4096], out_feature[4096]) = { layers.31.attention.wo.weight (Size[4096, 4096]) } } layers.31.feed_forward FeedForward() = { layers.31.feed_forward.w1 Linear(in_feature[4096], out_feature[1]) = { layers.31.feed_forward.w1.weight (Size[1, 4096]) } layers.31.feed_forward.w3 Linear(in_feature[4096], out_feature[1]) = { layers.31.feed_forward.w3.weight (Size[1, 4096]) } layers.31.feed_forward.w2 Linear(in_feature[1], out_feature[4096]) = { layers.31.feed_forward.w2.weight (Size[4096, 1]) } } layers.31.ffn_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.31.ffn_norm.weight (Size[4096]) } layers.31.attention_norm RMSNorm(dim[4096], eps[1e-05]) = { layers.31.attention_norm.weight (Size[4096]) } } } norm RMSNorm(dim[4096], eps[1e-05]) = { norm.weight (Size[4096]) } output Linear(in_feature[4096], out_feature[32000]) = { output.weight (Size[32000, 4096]) } freqs_cis (Size[2048, 64]) causal_mask (Size[2048, 2048]) } ================================================ FILE: libdlvoicecodec/LibDLVoiceCodec/base.cpp ================================================ #include "base.h" ================================================ FILE: libdlvoicecodec/LibDLVoiceCodec/base.h ================================================ #pragma once #include #include #include #include #include #define LibDLVoiceCodecBegin namespace libdlvcodec { #define LibDLVoiceCodecEnd } #define LIBDVCND [[nodiscard]] #define LibDLVoiceCodecThrow(message) throw std::exception((std::string("[At \"") + __FILE__ + "\" Line " + std::to_string(__LINE__) + "]\n" + (message)).c_str()) LibDLVoiceCodecBegin using int8 = int8_t; using int16 = int16_t; using int32 = int32_t; using int64 = int64_t; using float32 = float; using float64 = double; using byte = unsigned char; using lpvoid = void*; using uint8 = uint8_t; using uint16 = uint16_t; using uint32 = uint32_t; using uint64 = uint64_t; class TensorView; class Tensor; const std::unordered_map __Dtype {{"int8", 1}, { "int16", 2 }, { "int32", 4 }, { "int64", 8 }, { "float8", 1 }, { "float16", 2 }, { "bfloat16", 2 }, { "float32", 4 }, { "float64", 8 }, { "bool", 1 } }; template > using MResource = std::vector<_Ty, _Alloc>; template std::ostream& operator<<(std::ostream& _Stream, const std::vector& _Data) { _Stream << '['; for (const auto& i : _Data) _Stream << i << ", "; _Stream << "]\n"; return _Stream; } class FileWrapper { public: FileWrapper() = default; ~FileWrapper() { if (file_) fclose(file_); file_ = nullptr; } FileWrapper(const FileWrapper& _Left) = delete; FileWrapper& operator=(const FileWrapper& _Left) = delete; FileWrapper(FileWrapper&& _Right) noexcept { file_ = _Right.file_; _Right.file_ = nullptr; } FileWrapper& operator=(FileWrapper&& _Right) noexcept { file_ = _Right.file_; _Right.file_ = nullptr; return *this; } void open(const std::wstring& _Path, const std::wstring& _Mode) { #ifdef _WIN32 _wfopen_s(&file_, _Path.c_str(), _Mode.c_str()); #else file_ = _wfopen(_Path.c_str(), _Mode.c_str()); #endif } operator FILE* () const { return file_; } LIBDVCND bool enabled() const { return file_; } private: FILE* file_ = nullptr; }; LibDLVoiceCodecEnd ================================================ FILE: libdlvoicecodec/LibDLVoiceCodec/operator.cpp ================================================ #include "operator.h" #include "value.h" #include LibDLVoiceCodecBegin LibDLVoiceCodecEnd ================================================ FILE: libdlvoicecodec/LibDLVoiceCodec/operator.h ================================================ #pragma once #include "base.h" LibDLVoiceCodecBegin Tensor equal(const Tensor& _A, const Tensor& _B); Tensor add(const Tensor& _A, const Tensor& _B); Tensor sub(const Tensor& _A, const Tensor& _B); Tensor mul(const Tensor& _A, const Tensor& _B); Tensor div(const Tensor& _A, const Tensor& _B); void selfAdd(Tensor& _Self, const Tensor& _O); void selfSub(Tensor& _Self, const Tensor& _O); void selfMul(Tensor& _Self, const Tensor& _O); void selfDiv(Tensor& _Self, const Tensor& _O); Tensor matmul(const Tensor& _A, const Tensor& _B); Tensor conv1d(const Tensor& _Input, const Tensor& _Weight, const Tensor& _Bias, int64 _Stride = 1, int64 _Padding = 0, int64 _Dilation = 1, int64 _Groups = 1); Tensor conv2d(const Tensor& _Input, const Tensor& _Weight, const Tensor& _Bias, int64 _Stride = 1, int64 _Padding = 0, int64 _Dilation = 1, int64 _Groups = 1); Tensor conv3d(const Tensor& _Input, const Tensor& _Weight, const Tensor& _Bias, int64 _Stride = 1, int64 _Padding = 0, int64 _Dilation = 1, int64 _Groups = 1); Tensor conv_transpose1d(const Tensor& _Input, const Tensor& _Weight, const Tensor& _Bias, int64 _Stride = 1, int64 _Padding = 0, int64 _OutputPadding = 0, int64 _Dilation = 1, int64 _Groups = 1); Tensor conv_transpose2d(const Tensor& _Input, const Tensor& _Weight, const Tensor& _Bias, int64 _Stride = 1, int64 _Padding = 0, int64 _OutputPadding = 0, int64 _Dilation = 1, int64 _Groups = 1); Tensor conv_transpose3d(const Tensor& _Input, const Tensor& _Weight, const Tensor& _Bias, int64 _Stride = 1, int64 _Padding = 0, int64 _OutputPadding = 0, int64 _Dilation = 1, int64 _Groups = 1); LibDLVoiceCodecEnd ================================================ FILE: libdlvoicecodec/LibDLVoiceCodec/value.cpp ================================================ #include "value.h" #include LibDLVoiceCodecBegin Value& Value::load(const std::wstring& _Path) { FileWrapper file; file.open(_Path, L"rb"); if (!file.enabled()) LibDLVoiceCodecThrow("Failed to open file!"); char Header[4]; fread(Header, 1, 4, file); if (Header[0] != 'L' || Header[1] != 'S' || Header[2] != 'B' || Header[3] != 'V') LibDLVoiceCodecThrow("File does not recognize!"); size_t MemberNameSize = 0; WeightDict weight; char MemberName[1025]; /* MemberNameSize (size_t) MemberName (char[MemberNameSize]) _WeightData.Size (size_t) _WeightData.ShapeSize (size_t) _WeightData.Shape (int64_t[_WeightData.ShapeSize]) _WeightData.Data (byte[_WeightData.Size]) */ while (fread(&MemberNameSize, 1, sizeof(size_t), file) == sizeof(size_t)) { if (MemberNameSize == 0) LibDLVoiceCodecThrow("Size of attrib name must higer than 0!"); if (MemberNameSize > 1024) LibDLVoiceCodecThrow("Size of attrib name must lower than 1024!"); if (fread(MemberName, 1, MemberNameSize, file) != MemberNameSize) LibDLVoiceCodecThrow("Unexpected EOF!"); MemberName[MemberNameSize] = 0; std::string AttribName = MemberName; if (weight.find(AttribName) != weight.end()) continue; WeightData _WeightData; if (fread(&_WeightData.Size, 1, sizeof(size_t), file) != sizeof(size_t)) LibDLVoiceCodecThrow("Unexpected EOF!"); if (_WeightData.Size == 0) continue; if (fread(&_WeightData.ShapeSize, 1, sizeof(size_t), file) != sizeof(size_t)) LibDLVoiceCodecThrow("Unexpected EOF!"); if (_WeightData.ShapeSize == 0) continue; size_t __SIZE = sizeof(int64_t) * _WeightData.ShapeSize; _WeightData.Shape = std::vector(_WeightData.ShapeSize); if (fread(_WeightData.Shape.data(), 1, __SIZE, file) != __SIZE) LibDLVoiceCodecThrow("Unexpected EOF!"); __SIZE = _WeightData.Size; _WeightData.Data = MResource(_WeightData.Size); if (fread(_WeightData.Data.data(), 1, __SIZE, file) != __SIZE) LibDLVoiceCodecThrow("Unexpected EOF!"); weight[AttribName] = std::move(_WeightData); } loadData(weight); return *this; } Value& Value::save(const std::wstring& _Path) { FileWrapper file; file.open(_Path, L"rb"); if (!file.enabled()) LibDLVoiceCodecThrow("Failed to open file!"); constexpr char Header[5] = "LSBV"; fwrite(Header, 1, 4, file); saveData(file); return *this; } void Value::loadData(WeightDict& _Dict) { LibDLVoiceCodecThrow("Not implemented error!"); } void Value::saveData(FileWrapper& _File) { LibDLVoiceCodecThrow("Not implemented error!"); } TensorView TensorData::operator[](int64_t index) const { if (index < 0) { if (index < -Shape_[0]) LibDLVoiceCodecThrow("Index Out Of Range"); index += Shape_[0]; std::vector NewShape{Shape_.begin() + 1, Shape_.end()}; if (NewShape.empty()) NewShape.emplace_back(1); return { std::move(NewShape) ,DataPtr_ + index * (step() * DTypeAligBytes_) }; } if (index > Shape_[0]) LibDLVoiceCodecThrow("Index Out Of Range"); std::vector NewShape{Shape_.begin() + 1, Shape_.end()}; if (NewShape.empty()) NewShape.emplace_back(1); return { std::move(NewShape) ,DataPtr_ + index * (step() * DTypeAligBytes_) }; } template TensorData& TensorData::operator=(const _TypeName& _Val) { assert(sizeof(_TypeName) == DTypeAligBytes_); //TODO return *this; } void Module::loadData(WeightDict& _Dict) { for(const auto& it : Layers_) { it.second->loadData(_Dict); } } void Module::saveData(FileWrapper& _File) { for (const auto& it : Layers_) { it.second->saveData(_File); } } void Tensor::loadData(WeightDict& _Dict) { const auto res = _Dict.find(RegName_); if (res != _Dict.end()) { Shape_ = res->second.Shape; size_t TotalSize = 1; for (const auto i : Shape_) TotalSize *= i; if (TotalSize * DTypeAligBytes_ != res->second.Size) LibDLVoiceCodecThrow("Expected size does not match actual size!"); Data_ = std::move(res->second.Data); DataPtr_ = Data_.data(); } } void Tensor::saveData(FileWrapper& _File) { } Tensor::Tensor(const std::initializer_list& _Shape, const std::string& _Dtype, const std::string& _Name) { if (__Dtype.find(_Dtype) == __Dtype.end()) LibDLVoiceCodecThrow("DType Not Recognized"); DTypeAligBytes_ = __Dtype.at(Type_); Shape_ = _Shape; Step_ = std::vector(Shape_.size(), 0ui64); Step_.back() = DTypeAligBytes_; for (size_t i = Step_.size() - 2; i != size_t(-1); --i) Step_[i] = Step_[i + 1] * Shape_[i + 1]; Transopse_ = std::vector(Shape_.size(), 0i64); for (size_t i = 1; i < Transopse_.size(); ++i) Transopse_[i] = Transopse_[i - 1] + 1; size_t TotalSize = 1; for (const auto i : Shape_) TotalSize *= i; if (TotalSize) Data_ = MResource(DTypeAligBytes_ * TotalSize); RegName_ = _Name; MemOwner_ = true; DataPtr_ = Data_.data(); ThisPtr_ = Data_.data(); Type_ = _Dtype; } Tensor::Tensor(const std::vector& _Shape, const std::string& _Dtype, const std::string& _Name) { if (__Dtype.find(_Dtype) == __Dtype.end()) LibDLVoiceCodecThrow("DType Not Recognized"); DTypeAligBytes_ = __Dtype.at(Type_); Shape_ = _Shape; Step_ = std::vector(Shape_.size(), 0ui64); Step_.back() = DTypeAligBytes_; for (size_t i = Step_.size() - 2; i != size_t(-1); --i) Step_[i] = Step_[i + 1] * Shape_[i + 1]; Transopse_ = std::vector(Shape_.size(), 0i64); for (size_t i = 1; i < Transopse_.size(); ++i) Transopse_[i] = Transopse_[i - 1] + 1; size_t TotalSize = 1; for (const auto i : Shape_) TotalSize *= i; if (TotalSize) Data_ = MResource(DTypeAligBytes_ * TotalSize); RegName_ = _Name; MemOwner_ = true; DataPtr_ = Data_.data(); ThisPtr_ = Data_.data(); Type_ = _Dtype; } Tensor::Tensor(const Tensor& _Left) { Shape_ = _Left.Shape_; Data_ = _Left.Data_; Step_ = _Left.Step_; Transopse_ = _Left.Transopse_; RegName_ = _Left.RegName_; MemOwner_ = true; DataPtr_ = Data_.data(); ThisPtr_ = Data_.data(); Type_ = _Left.Type_; DTypeAligBytes_ = __Dtype.at(Type_); } Tensor::Tensor(Tensor&& _Right) noexcept { Shape_ = _Right.Shape_; Data_ = std::move(_Right.Data_); Step_ = std::move(_Right.Step_); Transopse_ = std::move(_Right.Transopse_); RegName_ = _Right.RegName_; MemOwner_ = _Right.MemOwner_; DataPtr_ = Data_.data(); ThisPtr_ = Data_.data(); Type_ = _Right.Type_; DTypeAligBytes_ = __Dtype.at(Type_); } Tensor& Tensor::operator=(const Tensor& _Left) { if (&_Left == this) return *this; Shape_ = _Left.Shape_; Data_ = _Left.Data_; Step_ = _Left.Step_; Transopse_ = _Left.Transopse_; RegName_ = _Left.RegName_; MemOwner_ = true; DataPtr_ = Data_.data(); ThisPtr_ = Data_.data(); Type_ = _Left.Type_; DTypeAligBytes_ = __Dtype.at(Type_); return *this; } Tensor& Tensor::operator=(Tensor&& _Right) noexcept { Shape_ = _Right.Shape_; Data_ = std::move(_Right.Data_); Step_ = std::move(_Right.Step_); Transopse_ = std::move(_Right.Transopse_); RegName_ = _Right.RegName_; MemOwner_ = _Right.MemOwner_; DataPtr_ = Data_.data(); ThisPtr_ = Data_.data(); Type_ = _Right.Type_; DTypeAligBytes_ = __Dtype.at(Type_); return *this; } template void AssignPtr(__TY* Begin, __TY* End, __TY Val) { while (Begin != End) *(Begin++) = Val; } template void AssignPtr(__TY* Begin, __TY* End, __TY(*Val)()) { while (Begin != End) *(Begin++) = Val(); } Tensor Tensor::zeros(const std::vector& _Shape, const std::string& _Dtype, const std::string& _Name) { Tensor Output{ _Shape ,_Dtype, _Name }; memset(Output.Data_.data(), 0, Output.Data_.size()); return Output; } Tensor Tensor::zeros_like(const Tensor& _O) { Tensor Output{ _O.shape() ,_O.dtype(), _O.RegName_ }; memset(Output.Data_.data(), 0, Output.Data_.size()); return Output; } Tensor Tensor::ones(const std::vector& _Shape, const std::string& _Dtype, const std::string& _Name) { Tensor Output{ _Shape ,_Dtype, _Name }; if (Output.Type_ == "int8") AssignPtr(Output.buf_begin(), Output.buf_end(), int8(1)); else if (Output.Type_ == "int16") AssignPtr(Output.buf_begin(), Output.buf_end(), 1i16); else if (Output.Type_ == "int32") AssignPtr(Output.buf_begin(), Output.buf_end(), 1i32); else if (Output.Type_ == "int64") AssignPtr(Output.buf_begin(), Output.buf_end(), 1i64); else if (Output.Type_ == "float8") ; else if (Output.Type_ == "float16") ; else if (Output.Type_ == "bfloat16") ; else if (Output.Type_ == "float32") AssignPtr(Output.buf_begin(), Output.buf_end(), 1.f); else if (Output.Type_ == "float64") AssignPtr(Output.buf_begin(), Output.buf_end(), 1.); else AssignPtr(Output.buf_begin(), Output.buf_end(), true); return Output; } Tensor Tensor::ones_like(const Tensor& _O) { return ones(_O.Shape_, _O.Type_, _O.RegName_); } Tensor Tensor::rand(const std::vector& _Shape, int _Seed, const std::string& _Dtype, const std::string& _Name) { return {}; } Tensor Tensor::rand_like(const Tensor& _O, int _Seed) { return rand(_O.Shape_, _Seed, _O.Type_, _O.RegName_); } Tensor Tensor::randn(const std::vector& _Shape, int _Seed, const std::string& _Dtype, const std::string& _Name) { return {}; } Tensor Tensor::randn_like(const Tensor& _O, int _Seed) { return randn(_O.Shape_, _Seed, _O.Type_, _O.RegName_); } LibDLVoiceCodecEnd ================================================ FILE: libdlvoicecodec/LibDLVoiceCodec/value.h ================================================ #pragma once #include #include #include "base.h" #define RegLayer(ModuleName, MemberName, ...) ModuleName MemberName{this, #MemberName, __VA_ARGS__} LibDLVoiceCodecBegin struct WeightData { size_t Size = 0; size_t ShapeSize = 0; std::vector Shape; MResource Data; }; class Value { public: Value() = default; Value(const Value& _Left) = delete; virtual ~Value() = default; using WeightDict = std::unordered_map; protected: std::string RegName_; public: Value& load(const std::wstring& _Path); Value& save(const std::wstring& _Path); virtual void loadData(WeightDict& _Dict); virtual void saveData(FileWrapper& _File); }; class Module : public Value { public: Module(Module* _Parent, const std::string& _Name) { if (_Parent != nullptr) { RegName_ = _Parent->RegName_ + "." + _Name; _Parent->Layers_[RegName_] = this; } else RegName_ = _Name; } ~Module() override = default; private: std::unordered_map Layers_; public: void loadData(WeightDict& _Dict) override; void saveData(FileWrapper& _File) override; }; class TensorData : public Value { public: TensorData() = default; TensorData(const TensorData& _Left) = delete; TensorData(TensorData&& _Right) = delete; ~TensorData() override = default; protected: std::vector Shape_; std::vector Step_; std::vector Transopse_; size_t DTypeAligBytes_ = 4; std::string Type_ = "float32"; bool MemOwner_ = false; public: LIBDVCND const std::string& dtype() const { return Type_; } LIBDVCND const std::vector& shape() const { return Shape_; } LIBDVCND size_t size() const { if (Shape_.empty()) return 0; return Shape_[0]; } LIBDVCND size_t total_size() const { if (Shape_.empty()) return 0; size_t ttsize = 1; for (const auto i : Shape_) ttsize *= i; return ttsize; } LIBDVCND size_t buf_size() const { return total_size() * DTypeAligBytes_; } LIBDVCND size_t step() const { if (Step_.empty()) return 0; return Step_[0]; } LIBDVCND byte* data() const { return DataPtr_; } template LIBDVCND _ValueType& item() { assert(sizeof(_ValueType) == DTypeAligBytes_); return *(_ValueType*)(ThisPtr_); } protected: byte* DataPtr_ = nullptr; byte* ThisPtr_ = nullptr; public: LIBDVCND TensorView operator[](int64_t index) const; template LIBDVCND TensorData& operator=(const _TypeName& _Val); }; class Tensor : public TensorData { public: using DType = float; Tensor() = default; Tensor(const std::initializer_list& _Shape, const std::string& _Dtype = "float32", const std::string& _Name = "Tensor"); Tensor(const std::vector& _Shape, const std::string& _Dtype = "float32", const std::string& _Name = "Tensor"); Tensor(const Tensor& _Left); Tensor(Tensor&& _Right) noexcept; ~Tensor() override = default; Tensor& operator=(const Tensor& _Left); Tensor& operator=(Tensor&& _Right) noexcept; protected: MResource Data_; private: template LIBDVCND _ValueType* buf_begin() { assert(sizeof(_ValueType) == DTypeAligBytes_); return (_ValueType*)(Data_.begin()._Ptr); } template LIBDVCND _ValueType* buf_end() { assert(sizeof(_ValueType) == DTypeAligBytes_); return (_ValueType*)(Data_.end()._Ptr); } public: static Tensor zeros(const std::vector& _Shape, const std::string& _Dtype = "float32", const std::string& _Name = "Tensor"); static Tensor zeros_like(const Tensor& _O); static Tensor ones(const std::vector& _Shape, const std::string& _Dtype = "float32", const std::string& _Name = "Tensor"); static Tensor ones_like(const Tensor& _O); static Tensor rand(const std::vector& _Shape, int _Seed = 114514, const std::string& _Dtype = "float32", const std::string& _Name = "Tensor"); static Tensor rand_like(const Tensor& _O, int _Seed = 114514); static Tensor randn(const std::vector& _Shape, int _Seed = 114514, const std::string& _Dtype = "float32", const std::string& _Name = "Tensor"); static Tensor randn_like(const Tensor& _O, int _Seed = 114514); template static Tensor arange(__TY _Begin, __TY _End, __TY _Step, const std::string& _Dtype = "float32", const std::string& _Name = "Tensor") { if (__Dtype.find(_Dtype) == __Dtype.end()) LibDLVoiceCodecThrow("DType Not Recognized"); if (sizeof(__TY) != __Dtype.at(_Dtype)) LibDLVoiceCodecThrow("Size Of DType MisMatch"); Tensor ret; ret.Type_ = _Dtype; ret.RegName_ = _Name; ret.DTypeAligBytes_ = __Dtype.at(ret.Type_); ret.MemOwner_ = true; const auto diff = _End - _Begin; const auto len = size_t(diff / _Step); if (len <= 0) LibDLVoiceCodecThrow("The Positive And Negative Of Both _End - _Begin And _Step Must Be The Same"); ret.Shape_ = { len }; ret.Data_ = MResource(len * ret.DTypeAligBytes_); ret.Step_ = { ret.DTypeAligBytes_ }; ret.Transopse_ = { 0 }; ret.DataPtr_ = ret.Data_.data(); ret.ThisPtr_ = ret.Data_.data(); __TY* pdata = ret.DataPtr_; *(pdata++) = _Begin; for (size_t i = 1; i < len; ++i) { *pdata = *(pdata - 1) + _Step; ++pdata; } return ret; } template static Tensor linspace(__TY _Begin, __TY _End, size_t _Len, const std::string& _Dtype = "float32", const std::string& _Name = "Tensor") { if (__Dtype.find(_Dtype) == __Dtype.end()) LibDLVoiceCodecThrow("DType Not Recognized"); if (sizeof(__TY) != __Dtype.at(_Dtype)) LibDLVoiceCodecThrow("Size Of DType MisMatch"); Tensor ret; ret.Type_ = _Dtype; ret.RegName_ = _Name; ret.DTypeAligBytes_ = __Dtype.at(ret.Type_); ret.MemOwner_ = true; const auto diff = _End - _Begin; const auto step = size_t(diff / __TY(_Len)); ret.Shape_ = { _Len }; ret.Data_ = MResource(_Len * ret.DTypeAligBytes_); ret.Step_ = { ret.DTypeAligBytes_ }; ret.Transopse_ = { 0 }; ret.DataPtr_ = ret.Data_.data(); ret.ThisPtr_ = ret.Data_.data(); __TY* pdata = ret.DataPtr_; *(pdata++) = _Begin; for (size_t i = 1; i < _Len; ++i) { *pdata = *(pdata - 1) + step; ++pdata; } return ret; } protected: void loadData(WeightDict& _Dict) override; void saveData(FileWrapper& _File) override; }; class TensorView : public TensorData { public: TensorView() = default; ~TensorView() override = default; TensorView(const Tensor& _T) { Shape_ = _T.shape(); DataPtr_ = _T.data(); } TensorView(Tensor&& _T) = delete; TensorView(const TensorView& _T) { Shape_ = _T.shape(); DataPtr_ = _T.data(); } TensorView(TensorView&& _T) noexcept { Shape_ = _T.shape(); DataPtr_ = _T.data(); } TensorView(const std::initializer_list& _Shape, byte* _DataPtr) { Shape_ = _Shape; DataPtr_ = _DataPtr; } TensorView(const std::vector& _Shape, byte* _DataPtr) { Shape_ = _Shape; DataPtr_ = _DataPtr; } TensorView(std::vector&& _Shape, byte* _DataPtr) { Shape_ = _Shape; DataPtr_ = _DataPtr; } TensorView& operator=(const TensorView& _Left) { DataPtr_ = _Left.DataPtr_; Shape_ = _Left.Shape_; return *this; } TensorView& operator=(TensorView&& _Right) noexcept { DataPtr_ = _Right.DataPtr_; Shape_ = _Right.Shape_; return *this; } TensorView& operator=(const Tensor& _T) { Shape_ = _T.shape(); DataPtr_ = _T.data(); return *this; } TensorView& operator=(Tensor&& _T) { Shape_ = _T.shape(); DataPtr_ = _T.data(); return *this; } }; LibDLVoiceCodecEnd ================================================ FILE: libdlvoicecodec/Modules/AvCodec/AvCodeResample.h ================================================ #pragma once #include #include #include "../StringPreprocess.hpp" #include "matlabfunctions.h" #include "../InferTools/inferTools.hpp" extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "libswresample/swresample.h" #include "libavutil/samplefmt.h" } class AudioPreprocess { public: struct WAV_HEADER { char RIFF[4] = { 'R','I','F','F' }; //RIFF标识 unsigned long ChunkSize; //文件大小-8 char WAVE[4] = { 'W','A','V','E' }; //WAVE块 char fmt[4] = { 'f','m','t',' ' }; //fmt块 unsigned long Subchunk1Size; //fmt块大小 unsigned short AudioFormat; //编码格式 unsigned short NumOfChan; //声道数 WAV_HEADER(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1) :ChunkSize(cs), Subchunk1Size(sc1s), AudioFormat(af), NumOfChan(nc) {} }; static WAV_HEADER GetHeader(const std::wstring& path) { WAV_HEADER header; char buf[1024]; FILE* stream; _wfreopen_s(&stream, path.c_str(), L"rb", stderr); if (stream == nullptr) { throw (std::exception("Wav Load Error")); } fread(buf, 1, 1024, stream); int pos = 0; while (pos < InferTools::Wav::HEAD_LENGTH) { if ((buf[pos] == 'R') && (buf[pos + 1] == 'I') && (buf[pos + 2] == 'F') && (buf[pos + 3] == 'F')) { pos += 4; break; } ++pos; } if (pos >= InferTools::Wav::HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.ChunkSize = *(int*)&buf[pos]; pos += 8; while (pos < InferTools::Wav::HEAD_LENGTH) { if ((buf[pos] == 'f') && (buf[pos + 1] == 'm') && (buf[pos + 2] == 't')) { pos += 4; break; } ++pos; } if (pos >= InferTools::Wav::HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk1Size = *(int*)&buf[pos]; pos += 4; header.AudioFormat = *(short*)&buf[pos]; pos += 2; header.NumOfChan = *(short*)&buf[pos]; if (stream != nullptr) { fclose(stream); } return header; } static std::vector arange(double start, double end, double step = 1.0, double div = 1.0) { std::vector output; while (start < end) { output.push_back(start / div); start += step; } return output; } std::vector codec(const std::wstring& path, int sr) { //if (path.substr(path.rfind(L'.')) == L".wav") // return resample(path, sr); std::vector outData; int ret = avformat_open_input(&avFormatContext, to_byte_string(path).c_str(), nullptr, nullptr); if (ret != 0) { LibDLVoiceCodecThrow((std::string("Can't Open Audio File [ErrCode]")+std::to_string(ret)).c_str()); } ret = avformat_find_stream_info(avFormatContext, nullptr); if (ret < 0) { LibDLVoiceCodecThrow("Can't Get Audio Info"); } int streamIndex = 0; for (unsigned i = 0; i < avFormatContext->nb_streams; ++i) { const AVMediaType avMediaType = avFormatContext->streams[i]->codecpar->codec_type; if (avMediaType == AVMEDIA_TYPE_AUDIO) { streamIndex = static_cast(i); } } const AVCodecParameters* avCodecParameters = avFormatContext->streams[streamIndex]->codecpar; const AVCodecID avCodecId = avCodecParameters->codec_id; const AVCodec* avCodec = avcodec_find_decoder(avCodecId); if (avCodec == nullptr) LibDLVoiceCodecThrow("Don't order fried rice (annoyed)"); if (avCodecContext == nullptr) { LibDLVoiceCodecThrow("Can't Get Decoder Info"); } avcodec_parameters_to_context(avCodecContext, avCodecParameters); ret = avcodec_open2(avCodecContext, avCodec, nullptr); if (ret < 0) { LibDLVoiceCodecThrow("Can't Open Decoder"); } packet = (AVPacket*)av_malloc(sizeof(AVPacket)); const AVSampleFormat inFormat = avCodecContext->sample_fmt; constexpr AVSampleFormat outFormat = AV_SAMPLE_FMT_S16; const int inSampleRate = avCodecContext->sample_rate; const int outSampleRate = sr; const auto nSample = static_cast(avFormatContext->duration * sr / AV_TIME_BASE); uint64_t in_ch_layout = avCodecContext->channel_layout; if (path.substr(path.rfind(L'.')) == L".wav") { const auto head = GetHeader(path); if (head.NumOfChan == 1) in_ch_layout = AV_CH_LAYOUT_MONO; else if (head.NumOfChan == 2) in_ch_layout = AV_CH_LAYOUT_STEREO; else LibDLVoiceCodecThrow("unsupported Channel Num"); } constexpr uint64_t out_ch_layout = AV_CH_LAYOUT_MONO; swr_alloc_set_opts(swrContext, out_ch_layout, outFormat, outSampleRate, static_cast(in_ch_layout), inFormat, inSampleRate, 0, nullptr ); swr_init(swrContext); const int outChannelCount = av_get_channel_layout_nb_channels(out_ch_layout); int currentIndex = 0; out_buffer = (uint8_t*)av_malloc(2ull * sr); while (av_read_frame(avFormatContext, packet) >= 0) { if (packet->stream_index == streamIndex) { avcodec_send_packet(avCodecContext, packet); ret = avcodec_receive_frame(avCodecContext, inFrame); if (ret == 0) { swr_convert(swrContext, &out_buffer, 2ull * sr, (const uint8_t**)inFrame->data, inFrame->nb_samples); const int out_buffer_size = av_samples_get_buffer_size(nullptr, outChannelCount, (inFrame->nb_samples * sr / inSampleRate) - 1, outFormat, 1); outData.insert(outData.end(), out_buffer, out_buffer + out_buffer_size); } ++currentIndex; av_packet_unref(packet); } } //Wav outWav(static_cast(sr), static_cast(outData.size()), outData.data()); auto outWav = reinterpret_cast(outData.data()); const auto RawWavLen = int64_t(outData.size()) / 2; if (nSample != static_cast(RawWavLen)) { const double interpOff = static_cast(RawWavLen) / static_cast(nSample); const auto x0 = arange(0.0, static_cast(RawWavLen), 1.0, 1.0); std::vector y0(RawWavLen); for (int64_t i = 0; i < RawWavLen; ++i) y0[i] = outWav[i] ? static_cast(outWav[i]) : NAN; const auto yi = new double[nSample]; auto xi = arange(0.0, static_cast(RawWavLen), interpOff, 1.0); while (xi.size() < nSample) xi.push_back(*(xi.end() - 1) + interpOff); while (xi.size() > nSample) xi.pop_back(); interp1(x0.data(), y0.data(), static_cast(RawWavLen), xi.data(), static_cast(nSample), yi); std::vector DataChun(nSample); for (size_t i = 0; i < nSample; ++i) DataChun[i] = isnan(yi[i]) ? 0i16 : static_cast(yi[i]); delete[] yi; return DataChun; } release(); return { outWav , outWav + RawWavLen }; } void release() { if (packet) av_packet_free(&packet); if (inFrame) av_frame_free(&inFrame); if (out_buffer) av_free(out_buffer); if (swrContext) swr_free(&swrContext); if (avCodecContext) avcodec_close(avCodecContext); if (avFormatContext) avformat_close_input(&avFormatContext); inFrame = nullptr; out_buffer = nullptr; swrContext = nullptr; avCodecContext = nullptr; avFormatContext = nullptr; packet = nullptr; } void init() { inFrame = av_frame_alloc(); out_buffer = nullptr; swrContext = swr_alloc(); avCodecContext = avcodec_alloc_context3(nullptr); avFormatContext = avformat_alloc_context(); packet = nullptr; } AudioPreprocess() { inFrame = av_frame_alloc(); out_buffer = nullptr; swrContext = swr_alloc(); avCodecContext = avcodec_alloc_context3(nullptr); avFormatContext = avformat_alloc_context(); packet = nullptr; } ~AudioPreprocess() { release(); } private: AVFrame* inFrame; uint8_t* out_buffer; SwrContext* swrContext; AVCodecContext* avCodecContext; AVFormatContext* avFormatContext; AVPacket* packet; }; ================================================ FILE: libdlvoicecodec/Modules/AvCodec/Recorder.cpp ================================================ #include "Recorder.h" MRecorder::~MRecorder() { //释放录制线程 m_runing = false; m_iscapture = true; if (m_thread) { m_signal.notify_all(); m_thread->join(); delete m_thread; } //释放设备资源 if (m_event[0]) { for (Mui::_m_byte i = 0; i < 2; i++) { SetEvent(m_event[i]); CloseHandle(m_event[i]); } } if (m_captureBuffer) m_captureBuffer->Release(); if (m_captureDriver) m_captureDriver->Release(); //释放队列数据 while (true) { const auto data = GetStreamData(); delete data; if (!data) break; } } bool MRecorder::InitRecorder(std::wstring& error, Mui::_m_uint sampleRate, Mui::_m_byte channels, Mui::_m_byte bit, Mui::_m_uint fs) { if (m_captureDriver && m_captureBuffer) { error = L"Initialized"; return false; } CoInitializeEx(nullptr, COINIT_MULTITHREADED); //创建录音设备 HRESULT hr = DirectSoundCaptureCreate(nullptr, &m_captureDriver, nullptr); if (FAILED(hr)) { error = L"DirectSoundCaptureCreate failed!"; return false; } if(sampleRate != 0) m_sampleRate = sampleRate; if(channels != 0) m_channels = channels; if(bit != 0) m_bit = bit; //创建录音缓冲区 m_blockAlign = 2 * m_channels; WAVEFORMATEX wavFormatEx; wavFormatEx.wFormatTag = WAVE_FORMAT_PCM; wavFormatEx.nChannels = m_channels; wavFormatEx.nSamplesPerSec = m_sampleRate; wavFormatEx.nAvgBytesPerSec = m_sampleRate * m_blockAlign; wavFormatEx.nBlockAlign = WORD(m_blockAlign); wavFormatEx.wBitsPerSample = m_bit; m_frameSize = fs*2; DSCBUFFERDESC dsBufferDesc = { sizeof(DSCBUFFERDESC) }; dsBufferDesc.lpwfxFormat = &wavFormatEx; dsBufferDesc.dwBufferBytes = m_frameSize * 2; //dsBufferDesc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY; hr = m_captureDriver->CreateCaptureBuffer(&dsBufferDesc, &m_captureBuffer, nullptr); if (FAILED(hr)) { error = L"DirectSoundCaptureCreate failed!"; m_captureDriver->Release(); m_captureDriver = nullptr; return false; } //创建通知事件 IDirectSoundNotify* Notify = nullptr; m_captureBuffer->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&Notify); DSBPOSITIONNOTIFY notify[2] = { 0 }; int offset = int(m_frameSize - 1); for (int i = 0; i < 2; i++) { notify[i].dwOffset = offset; m_event[i] = CreateEventW(nullptr, false, false, nullptr); notify[i].hEventNotify = m_event[i]; offset += (int)m_frameSize; } Notify->SetNotificationPositions(2, notify); Notify->Release(); //创建录制线程 m_runing = true; m_iscapture = false; m_thread = new std::thread(&MRecorder::CaptureThread, this); return true; } bool MRecorder::Start() { if(m_captureBuffer) { if (m_iscapture) return true; m_iscapture = true; m_signal.notify_all(); return SUCCEEDED(m_captureBuffer->Start(DSBPLAY_LOOPING)); } return false; } bool MRecorder::Stop() { if(m_captureBuffer) { if (!m_iscapture) return true; m_iscapture = false; return SUCCEEDED(m_captureBuffer->Stop()); } return false; } MRecorder::PCMData* MRecorder::GetStreamData() { PCMData* ret = nullptr; m_queue.dequeue(ret); return ret; } Mui::_m_size MRecorder::GetDataSize() { return Mui::_m_size(m_queue.size() * m_frameSize); } void MRecorder::CaptureThread() { while (m_runing) { //休眠线程 if (!m_iscapture) { std::unique_lock lock(m_lock); while (!m_iscapture) m_signal.wait(lock); } //等待通知事件 const DWORD res = WaitForMultipleObjects(2, m_event, FALSE, INFINITE); if (!m_iscapture) continue; if (res >= WAIT_OBJECT_0 && res <= WAIT_OBJECT_0 + 1) { auto data = new PCMData(); UCHAR* buffer = nullptr; DWORD dwBufferSize = 0; if (FAILED(m_captureBuffer->Lock(m_offsetNum * m_frameSize, m_frameSize, (LPVOID*)&buffer, &dwBufferSize, nullptr, nullptr, 0))) continue; data->data = new Mui::_m_byte[dwBufferSize]; data->size = dwBufferSize; memcpy(data->data, buffer, dwBufferSize); m_queue.enqueue(data); m_captureBuffer->Unlock(buffer, dwBufferSize, nullptr, 0); m_offsetNum++; if (m_offsetNum == 2) m_offsetNum = 0; } } } ================================================ FILE: libdlvoicecodec/Modules/AvCodec/Recorder.h ================================================ #pragma once #include #include #include #pragma comment(lib, "dsound.lib") class MRecorder { public: struct PCMData { Mui::_m_lpbyte data = nullptr; Mui::_m_uint size = 0; ~PCMData() { delete data; } }; MRecorder() = default; ~MRecorder(); /*初始化录音器 * @param out error - 错误信息输出 * @param sampleRate - 采样率 为0则默认 44100 (最大支持44100) * @param channels - 声道数 为0则默认 2 (最大2声道立体声) * @param bit - 位数 为0则默认 16 (最大支持16位) */ bool InitRecorder(std::wstring& error, Mui::_m_uint sampleRate = 0, Mui::_m_byte channels = 0, Mui::_m_byte bit = 0, Mui::_m_uint fs = 0); bool Start(); bool Stop(); //获取一段已录制的PCM音频数据 nullptr则没有数据 PCMData* GetStreamData(); //获取总dataSize Mui::_m_size GetDataSize(); //获取采样率 Mui::_m_uint GetSampleRate() const { return m_sampleRate; } //获取声道数 Mui::_m_byte GetChannels() const { return m_channels; } //获取位数 Mui::_m_byte GetBitRate() const { return m_bit; } //获取音频帧尺寸 Mui::_m_uint GetFrameSize() const { return m_frameSize; } //获取BlockAlign Mui::_m_uint GetBlockAlign() const { return m_blockAlign; } private: //音频参数设置 Mui::_m_uint m_sampleRate = 44100; Mui::_m_byte m_channels = 2; Mui::_m_byte m_bit = 16; Mui::_m_uint m_frameSize = 0; Mui::_m_uint m_blockAlign = 0; HANDLE m_event[2] = { nullptr }; IDirectSoundCapture* m_captureDriver = nullptr; IDirectSoundCaptureBuffer* m_captureBuffer = nullptr; //录音线程相关 std::mutex m_lock; std::condition_variable m_signal; std::atomic_bool m_runing; std::atomic_bool m_iscapture; std::thread* m_thread = nullptr; Mui::_m_uint m_offsetNum = 0; void CaptureThread(); //录音数据 template class Queue { std::deque m_queue; std::mutex m_mutex; public: Queue() = default; bool empty() { std::unique_lock lock(m_mutex); return m_queue.empty(); } auto size() { std::unique_lock lock(m_mutex); return m_queue.size(); } void enqueue(T& t) { std::unique_lock lock(m_mutex); m_queue.push_back(t); } bool dequeue(T& t) { std::unique_lock lock(m_mutex); if (m_queue.empty()) return false; t = std::move(m_queue.front()); m_queue.pop_front(); return true; } void clear() { std::unique_lock lock(m_mutex); m_queue.clear(); } }; Queue m_queue; }; ================================================ FILE: libdlvoicecodec/Modules/DataStruct/KDTree.cpp ================================================ /* * file: KDTree.hpp * author: J. Frederico Carvalho * * This is an adaptation of the KD-tree implementation in rosetta code * https://rosettacode.org/wiki/K-d_tree * * It is a reimplementation of the C code using C++. It also includes a few * more queries than the original, namely finding all points at a distance * smaller than some given distance to a point. * */ #include #include #include #include #include #include #include "KDTree.hpp" KDNode::KDNode() = default; KDNode::KDNode(const point_t &pt, const size_t &idx_, const KDNodePtr &left_, const KDNodePtr &right_) { x = pt; index = idx_; left = left_; right = right_; } KDNode::KDNode(const pointIndex &pi, const KDNodePtr &left_, const KDNodePtr &right_) { x = pi.first; index = pi.second; left = left_; right = right_; } KDNode::~KDNode() = default; float KDNode::coord(const size_t &idx) { return x.at(idx); } KDNode::operator bool() { return (!x.empty()); } KDNode::operator point_t() { return x; } KDNode::operator size_t() { return index; } KDNode::operator pointIndex() { return pointIndex(x, index); } KDNodePtr NewKDNodePtr() { KDNodePtr mynode = std::make_shared< KDNode >(); return mynode; } inline float dist2(const point_t &a, const point_t &b) { float distc = 0; for (size_t i = 0; i < a.size(); i++) { float di = a.at(i) - b.at(i); distc += di * di; } return distc; } inline float dist2(const KDNodePtr &a, const KDNodePtr &b) { return dist2(a->x, b->x); } inline float dist(const point_t &a, const point_t &b) { return std::sqrt(dist2(a, b)); } inline float dist(const KDNodePtr &a, const KDNodePtr &b) { return std::sqrt(dist2(a, b)); } comparer::comparer(size_t idx_) : idx{idx_} {}; inline bool comparer::compare_idx(const pointIndex &a, // const pointIndex &b // ) { return (a.first.at(idx) < b.first.at(idx)); // } inline void sort_on_idx(const pointIndexArr::iterator &begin, // const pointIndexArr::iterator &end, // size_t idx) { comparer comp(idx); comp.idx = idx; using std::placeholders::_1; using std::placeholders::_2; std::nth_element(begin, begin + std::distance(begin, end) / 2, end, std::bind(&comparer::compare_idx, comp, _1, _2)); } using pointVec = std::vector< point_t >; KDNodePtr KDTree::make_tree(const pointIndexArr::iterator &begin, // const pointIndexArr::iterator &end, // const size_t &length, // const size_t &level // ) { if (begin == end) { return NewKDNodePtr(); // empty tree } size_t dim = begin->first.size(); if (length > 1) { sort_on_idx(begin, end, level); } auto middle = begin + (length / 2); auto l_begin = begin; auto l_end = middle; auto r_begin = middle + 1; auto r_end = end; size_t l_len = length / 2; size_t r_len = length - l_len - 1; KDNodePtr left; if (l_len > 0 && dim > 0) { left = make_tree(l_begin, l_end, l_len, (level + 1) % dim); } else { left = leaf; } KDNodePtr right; if (r_len > 0 && dim > 0) { right = make_tree(r_begin, r_end, r_len, (level + 1) % dim); } else { right = leaf; } // KDNode result = KDNode(); return std::make_shared< KDNode >(*middle, left, right); } KDTree::KDTree(pointVec point_array) { leaf = std::make_shared< KDNode >(); // iterators pointIndexArr arr; for (size_t i = 0; i < point_array.size(); i++) { arr.push_back(pointIndex(point_array.at(i), i)); } auto begin = arr.begin(); auto end = arr.end(); size_t length = arr.size(); size_t level = 0; // starting root = KDTree::make_tree(begin, end, length, level); } KDNodePtr KDTree::nearest_( // const KDNodePtr &branch, // const point_t &pt, // const size_t &level, // const KDNodePtr &best, // const float&best_dist // ) { float d, dx, dx2; if (!bool(*branch)) { return NewKDNodePtr(); // basically, null } point_t branch_pt(*branch); size_t dim = branch_pt.size(); d = dist2(branch_pt, pt); dx = branch_pt.at(level) - pt.at(level); dx2 = dx * dx; KDNodePtr best_l = best; float best_dist_l = best_dist; if (d < best_dist) { best_dist_l = d; best_l = branch; } size_t next_lv = (level + 1) % dim; KDNodePtr section; KDNodePtr other; // select which branch makes sense to check if (dx > 0) { section = branch->left; other = branch->right; } else { section = branch->right; other = branch->left; } // keep nearest neighbor from further down the tree KDNodePtr further = nearest_(section, pt, next_lv, best_l, best_dist_l); if (!further->x.empty()) { float dl = dist2(further->x, pt); if (dl < best_dist_l) { best_dist_l = dl; best_l = further; } } // only check the other branch if it makes sense to do so if (dx2 < best_dist_l) { further = nearest_(other, pt, next_lv, best_l, best_dist_l); if (!further->x.empty()) { float dl = dist2(further->x, pt); if (dl < best_dist_l) { best_dist_l = dl; best_l = further; } } } return best_l; }; // default caller KDNodePtr KDTree::nearest_(const point_t &pt) { size_t level = 0; // KDNodePtr best = branch; float branch_dist = dist2(point_t(*root), pt); return nearest_(root, // beginning of tree pt, // point we are querying level, // start from level 0 root, // best is the root branch_dist); // best_dist = branch_dist }; point_t KDTree::nearest_point(const point_t &pt) { return point_t(*nearest_(pt)); }; size_t KDTree::nearest_index(const point_t &pt) { return size_t(*nearest_(pt)); }; pointIndex KDTree::nearest_pointIndex(const point_t &pt) { KDNodePtr Nearest = nearest_(pt); return pointIndex(point_t(*Nearest), size_t(*Nearest)); } pointIndexArr KDTree::neighborhood_( // const KDNodePtr &branch, // const point_t &pt, // const float&rad, // const size_t &level // ) { float d, dx, dx2; if (!bool(*branch)) { // branch has no point, means it is a leaf, // no points to add return pointIndexArr(); } size_t dim = pt.size(); float r2 = rad * rad; d = dist2(point_t(*branch), pt); dx = point_t(*branch).at(level) - pt.at(level); dx2 = dx * dx; pointIndexArr nbh, nbh_s, nbh_o; if (d <= r2) { nbh.push_back(pointIndex(*branch)); } // KDNodePtr section; KDNodePtr other; if (dx > 0) { section = branch->left; other = branch->right; } else { section = branch->right; other = branch->left; } nbh_s = neighborhood_(section, pt, rad, (level + 1) % dim); nbh.insert(nbh.end(), nbh_s.begin(), nbh_s.end()); if (dx2 < r2) { nbh_o = neighborhood_(other, pt, rad, (level + 1) % dim); nbh.insert(nbh.end(), nbh_o.begin(), nbh_o.end()); } return nbh; }; pointIndexArr KDTree::neighborhood( // const point_t &pt, // const float&rad) { size_t level = 0; return neighborhood_(root, pt, rad, level); } pointVec KDTree::neighborhood_points( // const point_t &pt, // const float&rad) { size_t level = 0; pointIndexArr nbh = neighborhood_(root, pt, rad, level); pointVec nbhp; nbhp.resize(nbh.size()); std::transform(nbh.begin(), nbh.end(), nbhp.begin(), [](pointIndex x) { return x.first; }); return nbhp; } indexArr KDTree::neighborhood_indices( // const point_t &pt, // const float&rad) { size_t level = 0; pointIndexArr nbh = neighborhood_(root, pt, rad, level); indexArr nbhi; nbhi.resize(nbh.size()); std::transform(nbh.begin(), nbh.end(), nbhi.begin(), [](pointIndex x) { return x.second; }); return nbhi; } ================================================ FILE: libdlvoicecodec/Modules/DataStruct/KDTree.hpp ================================================ #pragma once /* * file: KDTree.hpp * author: J. Frederico Carvalho * * This is an adaptation of the KD-tree implementation in rosetta code * https://rosettacode.org/wiki/K-d_tree * It is a reimplementation of the C code using C++. * It also includes a few more queries than the original * */ #include #include #include using point_t = std::vector; using indexArr = std::vector< size_t >; using pointIndex = std::pair< std::vector< float >, size_t >; class KDNode { public: using KDNodePtr = std::shared_ptr< KDNode >; size_t index; point_t x; KDNodePtr left; KDNodePtr right; // initializer KDNode(); KDNode(const point_t &, const size_t &, const KDNodePtr &, const KDNodePtr &); KDNode(const pointIndex &, const KDNodePtr &, const KDNodePtr &); ~KDNode(); // getter float coord(const size_t &); // conversions explicit operator bool(); explicit operator point_t(); explicit operator size_t(); explicit operator pointIndex(); }; using KDNodePtr = std::shared_ptr< KDNode >; KDNodePtr NewKDNodePtr(); // square euclidean distance inline float dist2(const point_t &, const point_t &); inline float dist2(const KDNodePtr &, const KDNodePtr &); // euclidean distance inline float dist(const point_t &, const point_t &); inline float dist(const KDNodePtr &, const KDNodePtr &); // Need for sorting class comparer { public: size_t idx; explicit comparer(size_t idx_); inline bool compare_idx( const std::pair< std::vector< float >, size_t > &, // const std::pair< std::vector< float >, size_t > & // ); }; using pointIndexArr = std::vector< pointIndex >; inline void sort_on_idx(const pointIndexArr::iterator &, // const pointIndexArr::iterator &, // size_t idx); using pointVec = std::vector; class KDTree { KDNodePtr root; KDNodePtr leaf; KDNodePtr make_tree(const pointIndexArr::iterator &begin, // const pointIndexArr::iterator &end, // const size_t &length, // const size_t &level // ); public: KDTree() = default; explicit KDTree(pointVec point_array); private: KDNodePtr nearest_( // const KDNodePtr &branch, // const point_t &pt, // const size_t &level, // const KDNodePtr &best, // const float&best_dist // ); // default caller KDNodePtr nearest_(const point_t &pt); public: point_t nearest_point(const point_t &pt); size_t nearest_index(const point_t &pt); pointIndex nearest_pointIndex(const point_t &pt); private: pointIndexArr neighborhood_( // const KDNodePtr &branch, // const point_t &pt, // const float&rad, // const size_t &level // ); public: pointIndexArr neighborhood( // const point_t &pt, // const float&rad); pointVec neighborhood_points( // const point_t &pt, // const float&rad); indexArr neighborhood_indices( // const point_t &pt, // const float&rad); }; ================================================ FILE: libdlvoicecodec/Modules/DataStruct/README.md ================================================ ## KdTree From J. Frederico Carvalho ================================================ FILE: libdlvoicecodec/Modules/InferTools/Cluster/MoeVSBaseCluster.cpp ================================================ #include "MoeVSBaseCluster.hpp" #include "../inferTools.hpp" std::vector MoeVoiceStudioCluster::MoeVoiceStudioBaseCluster::find(float* point, long sid, int64_t n_points) { LibDLVoiceCodecThrow("NotImplementedError"); } ================================================ FILE: libdlvoicecodec/Modules/InferTools/Cluster/MoeVSBaseCluster.hpp ================================================ /** * FileName: MoeVSBaseCluster.hpp * Note: MoeVoiceStudioCore 聚类基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #define MoeVoiceStudioClusterHeader namespace MoeVoiceStudioCluster { #define MoeVoiceStudioClusterEnd } MoeVoiceStudioClusterHeader class MoeVoiceStudioBaseCluster { public: MoeVoiceStudioBaseCluster() = default; virtual ~MoeVoiceStudioBaseCluster() = default; /** * \brief 查找聚类最邻近点 * \param point 待查找的点 * \param sid 角色ID * \param n_points 点数 * \return 查找到的最邻近点 */ virtual std::vector find(float* point, long sid, int64_t n_points = 1); }; MoeVoiceStudioClusterEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Cluster/MoeVSClusterManager.cpp ================================================ #include "MoeVSClusterManager.hpp" #include #include #include "../../Logger/MoeSSLogger.hpp" MoeVoiceStudioClusterHeader std::map RegisteredMoeVSCluster; MoeVSCluster GetMoeVSCluster(const std::wstring& _name, const std::wstring& _path, size_t hidden_size, size_t KmeansLen) { const auto f_ClusterFn = RegisteredMoeVSCluster.find(_name); if (f_ClusterFn != RegisteredMoeVSCluster.end()) return f_ClusterFn->second(_path, hidden_size, KmeansLen); throw std::runtime_error("Unable To Find An Available MoeVSCluster"); } void RegisterMoeVSCluster(const std::wstring& _name, const GetMoeVSClusterFn& _constructor_fn) { if (RegisteredMoeVSCluster.find(_name) != RegisteredMoeVSCluster.end()) { logger.log(L"[Warn] MoeVSClusterNameConflict"); return; } RegisteredMoeVSCluster[_name] = _constructor_fn; } MoeVoiceStudioClusterEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Cluster/MoeVSClusterManager.hpp ================================================ /** * FileName: MoeVSClusterManager.hpp * Note: MoeVoiceStudioCore 聚类管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVSBaseCluster.hpp" #include #include MoeVoiceStudioClusterHeader class MoeVSCluster { public: MoeVSCluster() = default; MoeVSCluster(MoeVoiceStudioBaseCluster* _ext) : _cluster_ext(_ext) {} MoeVSCluster(const MoeVSCluster&) = delete; MoeVSCluster(MoeVSCluster&& _ext) noexcept { delete _cluster_ext; _cluster_ext = _ext._cluster_ext; _ext._cluster_ext = nullptr; } MoeVSCluster& operator=(const MoeVSCluster&) = delete; MoeVSCluster& operator=(MoeVSCluster&& _ext) noexcept { if (this == &_ext) return *this; delete _cluster_ext; _cluster_ext = _ext._cluster_ext; _ext._cluster_ext = nullptr; return *this; } ~MoeVSCluster() { delete _cluster_ext; _cluster_ext = nullptr; } MoeVoiceStudioBaseCluster* operator->() const { return _cluster_ext; } private: MoeVoiceStudioBaseCluster* _cluster_ext = nullptr; }; using GetMoeVSClusterFn = std::function; void RegisterMoeVSCluster(const std::wstring& _name, const GetMoeVSClusterFn& _constructor_fn); /** * \brief 获取聚类 * \param _name 类名 * \param _path 聚类数据路径 * \param hidden_size hubert维数 * \param KmeansLen 聚类的长度 * \return 聚类 */ MoeVSCluster GetMoeVSCluster(const std::wstring& _name, const std::wstring& _path, size_t hidden_size, size_t KmeansLen); MoeVoiceStudioClusterEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Cluster/MoeVSIndexCluster.cpp ================================================ #ifdef MoeVoiceStudioIndexCluster #include "MoeVSIndexCluster.hpp" #include #include "../inferTools.hpp" MoeVoiceStudioClusterHeader IndexClusterCore::~IndexClusterCore() { delete IndexPtr; IndexPtr = nullptr; } IndexClusterCore::IndexClusterCore(const char* _path) { IndexPtr = faiss::read_index(_path); IndexsVector = std::vector(IndexPtr->ntotal * IndexPtr->d, 0.f); IndexPtr->reconstruct_n(0, IndexPtr->ntotal, IndexsVector.data()); Dim = IndexPtr->d; } IndexClusterCore::IndexClusterCore(IndexClusterCore&& move) noexcept { IndexPtr = move.IndexPtr; Dim = move.Dim; IndexsVector = std::move(move.IndexsVector); move.IndexPtr = nullptr; } IndexClusterCore& IndexClusterCore::operator=(IndexClusterCore&& move) noexcept { if (&move == this) return *this; delete IndexPtr; IndexPtr = move.IndexPtr; Dim = move.Dim; IndexsVector = std::move(move.IndexsVector); move.IndexPtr = nullptr; return *this; } float* IndexClusterCore::GetVec(faiss::idx_t index) { return IndexsVector.data() + index * Dim; } std::vector IndexClusterCore::find(const float* points, faiss::idx_t n_points, faiss::idx_t n_searched_points) { std::vector result(Dim * n_points); std::vector distances(n_searched_points * n_points); std::vector labels(n_searched_points * n_points); IndexPtr->search(n_points, points, n_searched_points, distances.data(), labels.data()); for (faiss::idx_t pt = 0; pt < n_points; ++pt) { std::vector result_pt(Dim, 0.f); const auto idx_vec = labels.data() + pt * n_searched_points; // SIZE:[n_searched_points] const auto dis_vec = distances.data() + pt * n_searched_points; // SIZE:[n_searched_points] float sum = 0.f; // dis_vec[i] / sum = pGetVec(idx_vec[i]) for (faiss::idx_t spt = 0; spt < n_searched_points; ++spt) // result_pt = GetVec(idx_vec[i]) { if(idx_vec[spt] < 0) continue; dis_vec[spt] = (1 / dis_vec[spt]) * (1 / dis_vec[spt]); sum += dis_vec[spt]; } if (sum == 0.f) sum = 1.f; for (faiss::idx_t spt = 0; spt < n_searched_points; ++spt) { if (idx_vec[spt] < 0) continue; const auto sedpt = GetVec(idx_vec[spt]); const auto pcnt = (dis_vec[spt] / sum); for (faiss::idx_t sptp = 0; sptp < Dim; ++sptp) result_pt[sptp] += pcnt * sedpt[sptp]; } memcpy(result.data() + pt * Dim, result_pt.data(), Dim * sizeof(float)); } return result; } IndexCluster::IndexCluster(const std::wstring& _path, size_t hidden_size, size_t KmeansLen) { const auto RawPath = _path + L"/Index-"; size_t idx = 0; while(true) { std::filesystem::path IndexPath = RawPath + std::to_wstring(idx++) + L".index"; if(!exists(IndexPath)) break; Indexs.emplace_back(IndexPath.string().c_str()); } if (Indexs.empty()) LibDLVoiceCodecThrow("Index Is Empty"); } std::vector IndexCluster::find(float* point, long sid, int64_t n_points) { if (size_t(sid) < Indexs.size()) return Indexs[sid].find(point, n_points); return { point,point + n_hidden_size * n_points }; } MoeVoiceStudioClusterEnd #endif ================================================ FILE: libdlvoicecodec/Modules/InferTools/Cluster/MoeVSIndexCluster.hpp ================================================ /** * FileName: MoeVSIndexCluster.hpp * Note: MoeVoiceStudioCore 官方聚类(Index) * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #ifdef MoeVoiceStudioIndexCluster #include #include "MoeVSBaseCluster.hpp" #include #include #ifdef NDEBUG #pragma comment (lib,"../../../Lib/faiss/out/build/x64-Release/faiss/faiss.lib") #endif #ifdef _DEBUG #pragma comment (lib,"../../../Lib/faiss/out/build/x64-Debug/faiss/faiss.lib") #endif #pragma comment (lib,"../../../Lib/faiss/faiss/libblas.lib") #pragma comment (lib,"../../../Lib/faiss/faiss/liblapack.lib") #pragma comment (lib,"../../../Lib/faiss/faiss/liblapacke.lib") MoeVoiceStudioClusterHeader class IndexClusterCore { public: IndexClusterCore() = delete; ~IndexClusterCore(); IndexClusterCore(const char* _path); IndexClusterCore(const IndexClusterCore&) = delete; IndexClusterCore(IndexClusterCore&& move) noexcept; IndexClusterCore& operator=(const IndexClusterCore&) = delete; IndexClusterCore& operator=(IndexClusterCore&& move) noexcept; std::vector find(const float* points, faiss::idx_t n_points, faiss::idx_t n_searched_points = 8); float* GetVec(faiss::idx_t index); private: faiss::Index* IndexPtr = nullptr; faiss::idx_t Dim = 0; std::vector IndexsVector; }; class IndexCluster : public MoeVoiceStudioBaseCluster { public: IndexCluster() = delete; ~IndexCluster() override = default; IndexCluster(const std::wstring& _path, size_t hidden_size, size_t KmeansLen); std::vector find(float* point, long sid, int64_t n_points = 1) override; private: std::vector Indexs; size_t n_hidden_size = 256; }; MoeVoiceStudioClusterEnd #endif ================================================ FILE: libdlvoicecodec/Modules/InferTools/Cluster/MoeVSKmeansCluster.cpp ================================================ #include "MoeVSKmeansCluster.hpp" #include "../inferTools.hpp" std::vector MoeVoiceStudioCluster::KMeansCluster::find(float* point, long sid, int64_t n_points) { if (size_t(sid) < _tree.size()) { std::vector res; res.reserve(dims * n_points * 2); for (int64_t pt = 0; pt < n_points; ++pt) { auto tmp = _tree[sid].nearest_point({ point + pt * dims,point + (pt + 1) * dims }); res.insert(res.end(), tmp.begin(), tmp.end()); } return res; } return { point, point + dims * n_points }; } MoeVoiceStudioCluster::KMeansCluster::KMeansCluster(const std::wstring& _path, size_t hidden_size, size_t KmeansLen) { dims = hidden_size; FILE* file = nullptr; _wfopen_s(&file, (_path + L"/KMeans.npy").c_str(), L"rb"); if (!file) LibDLVoiceCodecThrow("KMeansFileNotExist"); constexpr long idx = 128; fseek(file, idx, SEEK_SET); std::vector tmpData(hidden_size); const size_t ec = size_t(hidden_size) * sizeof(float); std::vector> _tmp; _tmp.reserve(KmeansLen); while (fread(tmpData.data(), 1, ec, file) == ec) { _tmp.emplace_back(tmpData); if (_tmp.size() == KmeansLen) { _tree.emplace_back(_tmp); _tmp.clear(); } } } ================================================ FILE: libdlvoicecodec/Modules/InferTools/Cluster/MoeVSKmeansCluster.hpp ================================================ /** * FileName: MoeVSKmeansCluster.hpp * Note: MoeVoiceStudioCore 官方聚类(Kmeans) * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVSBaseCluster.hpp" #include "../../DataStruct/KDTree.hpp" #include MoeVoiceStudioClusterHeader class KMeansCluster : public MoeVoiceStudioBaseCluster { public: KMeansCluster() = delete; ~KMeansCluster() override = default; KMeansCluster(const std::wstring& _path, size_t hidden_size, size_t KmeansLen); std::vector find(float* point, long sid, int64_t n_points = 1) override; private: std::vector _tree; size_t dims = 0; }; MoeVoiceStudioClusterEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/BaseF0Extractor/BaseF0Extractor.cpp ================================================ #include "BaseF0Extractor.hpp" #include #include "../../../Logger/MoeSSLogger.hpp" #include "../../inferTools.hpp" MoeVSF0Extractor::BaseF0Extractor::BaseF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0) : fs(sampling_rate), hop(hop_size), f0_bin(n_f0_bins), f0_max(max_f0), f0_min(min_f0) { f0_mel_min = (1127.0 * log(1.0 + f0_min / 700.0)); f0_mel_max = (1127.0 * log(1.0 + f0_max / 700.0)); } std::vector MoeVSF0Extractor::BaseF0Extractor::arange(double start, double end, double step, double div) { std::vector output; while (start < end) { output.push_back(start / div); start += step; } return output; } std::vector MoeVSF0Extractor::BaseF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { LibDLVoiceCodecThrow("NotImplementedError"); } std::vector MoeVSF0Extractor::BaseF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { std::vector PCMVector(PCMData.size()); for (size_t i = 0; i < PCMData.size(); ++i) PCMVector[i] = double(PCMData[i]); return ExtractF0(PCMVector, TargetLength); } std::vector MoeVSF0Extractor::BaseF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { std::vector PCMVector(PCMData.size()); for (size_t i = 0; i < PCMData.size(); ++i) PCMVector[i] = double(PCMData[i]); return ExtractF0(PCMVector, TargetLength); } ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/BaseF0Extractor/BaseF0Extractor.hpp ================================================ /** * FileName: BaseF0Extractor.hpp * Note: MoeVoiceStudioCore F0提取算法基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include #define MoeVoiceStudioF0ExtractorHeader namespace MoeVSF0Extractor{ #define MoeVoiceStudioF0ExtractorEnd } MoeVoiceStudioF0ExtractorHeader #define __NAME__MOEVS(x) std::wstring ClassName = (x) class BaseF0Extractor { public: __NAME__MOEVS(L"MoeVSF0Extractor"); BaseF0Extractor() = delete; /** * \brief 构造F0提取器 * \param sampling_rate 采样率 * \param hop_size HopSize * \param n_f0_bins F0Bins * \param max_f0 最大F0 * \param min_f0 最小F0 */ BaseF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); virtual ~BaseF0Extractor() = default; /** * \brief 提取F0 * \param PCMData 音频PCM数据(SignedInt16 单声道) * \param TargetLength 目标F0长度 * \return F0 */ virtual std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength); /** * \brief 提取F0 * \param PCMData 音频PCM数据(SignedInt16 单声道) * \param TargetLength 目标F0长度 * \return F0 */ std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength); /** * \brief 提取F0 * \param PCMData 音频PCM数据(SignedInt16 单声道) * \param TargetLength 目标F0长度 * \return F0 */ std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength); static std::vector arange(double start, double end, double step = 1.0, double div = 1.0); protected: const uint32_t fs; const uint32_t hop; const uint32_t f0_bin; const double f0_max; const double f0_min; double f0_mel_min; double f0_mel_max; }; #undef __NAME__MOEVS MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/DioF0Extractor/DioF0Extractor.cpp ================================================ #include "DioF0Extractor.hpp" #include "dio.h" #include "stonemask.h" #include "matlabfunctions.h" MoeVoiceStudioF0ExtractorHeader DioF0Extractor::DioF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0): BaseF0Extractor(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0) { } void DioF0Extractor::InterPf0(size_t TargetLength) { const auto f0Len = refined_f0.size(); if (abs((int64_t)TargetLength - (int64_t)f0Len) < 3) { refined_f0.resize(TargetLength, 0.0); return; } for (size_t i = 0; i < f0Len; ++i) if (refined_f0[i] < 0.001) refined_f0[i] = NAN; auto xi = arange(0.0, (double)f0Len * (double)TargetLength, (double)f0Len, (double)TargetLength); while (xi.size() < TargetLength) xi.emplace_back(*(xi.end() - 1) + ((double)f0Len / (double)TargetLength)); while (xi.size() > TargetLength) xi.pop_back(); auto x0 = arange(0, (double)f0Len); while (x0.size() < f0Len) x0.emplace_back(*(x0.end() - 1) + 1.); while (x0.size() > f0Len) x0.pop_back(); auto raw_f0 = std::vector(xi.size()); interp1(x0.data(), refined_f0.data(), static_cast(x0.size()), xi.data(), (int)xi.size(), raw_f0.data()); for (size_t i = 0; i < xi.size(); i++) if (isnan(raw_f0[i])) raw_f0[i] = 0.0; refined_f0 = std::move(raw_f0); } std::vector DioF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { compute_f0(PCMData.data(), PCMData.size()); InterPf0(TargetLength); std::vector f0(refined_f0.size()); for (size_t i = 0; i < refined_f0.size(); ++i) f0[i] = (float)refined_f0[i]; return f0; } void DioF0Extractor::compute_f0(const double* PCMData, size_t PCMLen) { DioOption Doption; InitializeDioOption(&Doption); Doption.f0_ceil = f0_max; Doption.f0_floor = f0_min; Doption.frame_period = 1000.0 * hop / fs; const size_t f0Length = GetSamplesForDIO(int(fs), (int)PCMLen, Doption.frame_period); auto temporal_positions = std::vector(f0Length); auto raw_f0 = std::vector(f0Length); refined_f0 = std::vector(f0Length); Dio(PCMData, (int)PCMLen, int(fs), &Doption, temporal_positions.data(), raw_f0.data()); StoneMask(PCMData, (int)PCMLen, int(fs), temporal_positions.data(), raw_f0.data(), (int)f0Length, refined_f0.data()); } MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/DioF0Extractor/DioF0Extractor.hpp ================================================ /** * FileName: DioF0Extractor.hpp * Note: MoeVoiceStudioCore 官方F0提取算法 Dio * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "../BaseF0Extractor/BaseF0Extractor.hpp" MoeVoiceStudioF0ExtractorHeader class DioF0Extractor : public BaseF0Extractor { public: DioF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); ~DioF0Extractor() override = default; void compute_f0(const double* PCMData, size_t PCMLen); void InterPf0(size_t TargetLength); std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength) override; private: std::vector refined_f0; }; MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/F0ExtractorManager.cpp ================================================ #include "F0ExtractorManager.hpp" #include #include #include "../../Logger/MoeSSLogger.hpp" MoeVoiceStudioF0ExtractorHeader std::map RegisteredF0Extractors; F0Extractor GetF0Extractor(const std::wstring& _name, const uint32_t fs, const uint32_t hop, const uint32_t f0_bin, const double f0_max, const double f0_min) { const auto f_F0Extractor = RegisteredF0Extractors.find(_name); if (f_F0Extractor != RegisteredF0Extractors.end()) return f_F0Extractor->second(fs, hop, f0_bin, f0_max, f0_min); throw std::runtime_error("Unable To Find An Available F0Extractor"); } void RegisterF0Extractor(const std::wstring& _name, const GetF0ExtractorFn& _constructor_fn) { if (RegisteredF0Extractors.find(_name) != RegisteredF0Extractors.end()) { logger.log(L"[Warn] F0ExtractorNameConflict"); return; } RegisteredF0Extractors[_name] = _constructor_fn; } std::vector GetF0ExtractorList() { std::vector F0ExtractorsVec; F0ExtractorsVec.reserve(RegisteredF0Extractors.size()); for (const auto& i : RegisteredF0Extractors) F0ExtractorsVec.emplace_back(i.first); return F0ExtractorsVec; } MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/F0ExtractorManager.hpp ================================================ /** * FileName: F0ExtractorManager.hpp * Note: MoeVoiceStudioCore F0提取器管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "BaseF0Extractor/BaseF0Extractor.hpp" #include MoeVoiceStudioF0ExtractorHeader class F0Extractor { public: F0Extractor() = delete; F0Extractor(BaseF0Extractor* _ext) : _f0_ext(_ext) {} F0Extractor(const F0Extractor&) = delete; F0Extractor(F0Extractor&& _ext) noexcept { delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; } F0Extractor& operator=(const F0Extractor&) = delete; F0Extractor& operator=(F0Extractor&& _ext) noexcept { if (this == &_ext) return *this; delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; return *this; } ~F0Extractor() { delete _f0_ext; _f0_ext = nullptr; } BaseF0Extractor* operator->() const { return _f0_ext; } private: BaseF0Extractor* _f0_ext = nullptr; }; using GetF0ExtractorFn = std::function; void RegisterF0Extractor(const std::wstring& _name, const GetF0ExtractorFn& _constructor_fn); /** * \brief 获取F0提取器 * \param _name 类名 * \param fs 采样率 * \param hop HopSize * \param f0_bin F0Bins * \param f0_max 最大F0 * \param f0_min 最小F0 * \return F0提取器 */ F0Extractor GetF0Extractor(const std::wstring& _name, uint32_t fs = 48000, uint32_t hop = 512, uint32_t f0_bin = 256, double f0_max = 1100.0, double f0_min = 50.0); std::vector GetF0ExtractorList(); MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/HarvestF0Extractor/HarvestF0Extractor.cpp ================================================ #include "HarvestF0Extractor.hpp" #include "matlabfunctions.h" #include "harvest.h" #include "stonemask.h" MoeVoiceStudioF0ExtractorHeader HarvestF0Extractor::HarvestF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0): BaseF0Extractor(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0) { } void HarvestF0Extractor::InterPf0(size_t TargetLength) { const auto f0Len = refined_f0.size(); if (abs((int64_t)TargetLength - (int64_t)f0Len) < 3) { refined_f0.resize(TargetLength, 0.0); return; } for (size_t i = 0; i < f0Len; ++i) if (refined_f0[i] < 0.001) refined_f0[i] = NAN; auto xi = arange(0.0, (double)f0Len * (double)TargetLength, (double)f0Len, (double)TargetLength); while (xi.size() < TargetLength) xi.emplace_back(*(xi.end() - 1) + ((double)f0Len / (double)TargetLength)); while (xi.size() > TargetLength) xi.pop_back(); auto x0 = arange(0, (double)f0Len); while (x0.size() < f0Len) x0.emplace_back(*(x0.end() - 1) + 1.); while (x0.size() > f0Len) x0.pop_back(); auto raw_f0 = std::vector(xi.size()); interp1(x0.data(), refined_f0.data(), static_cast(x0.size()), xi.data(), (int)xi.size(), raw_f0.data()); for (size_t i = 0; i < xi.size(); i++) if (isnan(raw_f0[i])) raw_f0[i] = 0.0; refined_f0 = std::move(raw_f0); } std::vector HarvestF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { compute_f0(PCMData.data(), PCMData.size()); InterPf0(TargetLength); std::vector f0(refined_f0.size()); for (size_t i = 0; i < refined_f0.size(); ++i) f0[i] = (float)refined_f0[i]; return f0; } void HarvestF0Extractor::compute_f0(const double* PCMData, size_t PCMLen) { HarvestOption Doption; InitializeHarvestOption(&Doption); Doption.f0_ceil = f0_max; Doption.f0_floor = f0_min; Doption.frame_period = 1000.0 * hop / fs; const size_t f0Length = GetSamplesForHarvest(int(fs), (int)PCMLen, Doption.frame_period); auto temporal_positions = std::vector(f0Length); auto raw_f0 = std::vector(f0Length); refined_f0 = std::vector(f0Length); Harvest(PCMData, (int)PCMLen, int(fs), &Doption, temporal_positions.data(), raw_f0.data()); StoneMask(PCMData, (int)PCMLen, int(fs), temporal_positions.data(), raw_f0.data(), (int)f0Length, refined_f0.data()); } MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/HarvestF0Extractor/HarvestF0Extractor.hpp ================================================ /** * FileName: HarvestF0Extractor.hpp * Note: MoeVoiceStudioCore 官方F0提取算法 Harvest * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "../BaseF0Extractor/BaseF0Extractor.hpp" MoeVoiceStudioF0ExtractorHeader class HarvestF0Extractor : public BaseF0Extractor { public: HarvestF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); ~HarvestF0Extractor() override = default; void compute_f0(const double* PCMData, size_t PCMLen); void InterPf0(size_t TargetLength); std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength) override; private: std::vector refined_f0; }; MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/NetF0Predictors/NetF0Predictors.cpp ================================================ #include "NetF0Predictors.hpp" #include #include "matlabfunctions.h" #include "../DioF0Extractor/DioF0Extractor.hpp" #include "../../../Logger/MoeSSLogger.hpp" #include "../../../Models/EnvManager.hpp" #include "../../inferTools.hpp" #ifdef _WIN32 #include #else #error #endif MoeVoiceStudioF0ExtractorHeader NetF0Class::NetF0Class() #ifdef INITF0NETPREDICTOR { try { wchar_t path[1024]; #ifdef _WIN32 GetModuleFileName(nullptr, path, 1024); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); const auto cpath = _curPath + L"/F0Predictor/config.json"; NetF0PathDir = _curPath + L"/F0Predictor/"; #endif const MJson json(to_byte_string(cpath).c_str()); int DeviceId = 0, Device = 0, NumThread = (int)std::thread::hardware_concurrency(); if (json["DeviceId"].IsInt()) DeviceId = json["DeviceId"].GetInt(); if (json["Device"].IsString()) { const std::string tmp = json["Device"].GetString(); if (tmp == "CUDA") Device = 1; else if (tmp == "DML") Device = 2; } if (json["NumThread"].IsInt()) NumThread = json["NumThread"].GetInt(); if (Device == 0) BuildCPUEnv(NumThread); else if (Device == 1) BuildCUDAEnv(DeviceId); else if (Device == 2) BuildDMLEnv(DeviceId); } catch (std::exception& e) { logger.log(to_wide_string(e.what())); BuildCPUEnv(std::thread::hardware_concurrency()); } } #else { wchar_t path[1024]; #ifdef _WIN32 GetModuleFileName(nullptr, path, 1024); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); NetF0PathDir = _curPath + L"/F0Predictor/"; #endif } #endif void NetF0Class::Destory() { delete Model; Model = nullptr; NetF0Options = nullptr; NetF0Env = nullptr; Memory = nullptr; } void NetF0Class::BuildCPUEnv(unsigned ThreadCount) { Destory(); NetF0Options = new Ort::SessionOptions; NetF0Env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); NetF0Options->SetIntraOpNumThreads(static_cast(ThreadCount)); NetF0Options->SetGraphOptimizationLevel(ORT_ENABLE_ALL); Memory = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); } void NetF0Class::BuildCUDAEnv(unsigned Did) { Destory(); const auto AvailableProviders = Ort::GetAvailableProviders(); bool ret = true; for (const auto& it : AvailableProviders) if (it.find("CUDA") != std::string::npos) ret = false; if (ret) LibDLVoiceCodecThrow("CUDA Provider Not Found"); OrtCUDAProviderOptions cuda_option; cuda_option.device_id = int(Did); NetF0Options = new Ort::SessionOptions; NetF0Env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); NetF0Options->AppendExecutionProvider_CUDA(cuda_option); NetF0Options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); NetF0Options->SetIntraOpNumThreads(1); Memory = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); } void NetF0Class::BuildDMLEnv(unsigned Did) { Destory(); const auto AvailableProviders = Ort::GetAvailableProviders(); std::string ret; for (const auto& it : AvailableProviders) if (it.find("Dml") != std::string::npos) ret = it; if (ret.empty()) LibDLVoiceCodecThrow("DML Provider Not Found"); const OrtApi& ortApi = Ort::GetApi(); const OrtDmlApi* ortDmlApi = nullptr; ortApi.GetExecutionProviderApi("DML", ORT_API_VERSION, reinterpret_cast(&ortDmlApi)); const Ort::ThreadingOptions threadingOptions; NetF0Env = new Ort::Env(threadingOptions, ORT_LOGGING_LEVEL_VERBOSE, ""); NetF0Env->DisableTelemetryEvents(); NetF0Options = new Ort::SessionOptions; ortDmlApi->SessionOptionsAppendExecutionProvider_DML(*NetF0Options, int(Did)); NetF0Options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); NetF0Options->DisablePerSessionThreads(); NetF0Options->SetExecutionMode(ORT_SEQUENTIAL); NetF0Options->DisableMemPattern(); Memory = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU)); } void NetF0Class::LoadModel(const std::wstring& path) { Destory(); if (!moevsenv::GetGlobalMoeVSEnv().IsEnabled()) return; NetF0Env = moevsenv::GetGlobalMoeVSEnv().GetEnv(); Memory = moevsenv::GetGlobalMoeVSEnv().GetMemoryInfo(); NetF0Options = moevsenv::GetGlobalMoeVSEnv().GetSessionOptions(); try { Model = new Ort::Session(*NetF0Env, (NetF0PathDir + path).c_str(), *NetF0Options); } catch (Ort::Exception& e) { logger.log(to_wide_string(e.what())); delete Model; Model = nullptr; } } NetF0Class RMVPECORE; NetF0Class MELPECORE; RMVPEF0Extractor::RMVPEF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0) : BaseF0Extractor(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0) { if (MELPECORE.Model) MELPECORE.Destory(); if (!RMVPECORE.Model) RMVPECORE.LoadModel(L"RMVPE.onnx"); } double average(const double* begin, const double* end) { const auto mp = double(end - begin); double sum = 0.; while (begin != end) sum += *(begin++); return sum / mp; } std::vector RMVPEF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { if (!RMVPECORE.Model) return DioF0Extractor((int)fs, (int)hop, (int)f0_bin, f0_max, f0_min).ExtractF0(PCMData, TargetLength); const double step = double(fs) / 16000.; const auto window_len = (size_t)round(step); const auto half_window_len = window_len / 2; const auto f0_size = size_t((double)PCMData.size() / step); const auto pcm_idx_size = PCMData.size() - 2; std::vector pcm(f0_size, 0.f); auto idx = double(half_window_len + 1); for (size_t i = 0; i < f0_size; ++i) { const auto index = size_t(round(idx)); if(index + half_window_len > pcm_idx_size) break; if (half_window_len == 0) pcm[i] = (float)PCMData[index]; else pcm[i] = (float)average(&PCMData[index - half_window_len], &PCMData[index + half_window_len]); idx += step; } std::vector Tensors; const int64_t pcm_shape[] = { 1, (int64_t)pcm.size() }; constexpr int64_t one_shape[] = { 1 }; float threshold[] = { 0.03f }; Tensors.emplace_back(Ort::Value::CreateTensor(*RMVPECORE.Memory, pcm.data(), pcm.size(), pcm_shape, 2)); Tensors.emplace_back(Ort::Value::CreateTensor(*RMVPECORE.Memory, threshold, 1, one_shape, 1)); const auto out = RMVPECORE.Model->Run(Ort::RunOptions{ nullptr }, InputNames.data(), Tensors.data(), Tensors.size(), OutputNames.data(), OutputNames.size()); const auto osize = out[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto of0 = out[0].GetTensorData(); refined_f0 = std::vector(osize); for (size_t i = 0; i < osize; ++i) refined_f0[i] = ((of0[i] > 0.001f) ? (double)out[0].GetTensorData()[i] : NAN); InterPf0(TargetLength); std::vector finaF0(refined_f0.size()); for (size_t i = 0; i < refined_f0.size(); ++i) finaF0[i] = isnan(refined_f0[i]) ? 0 : (float)refined_f0[i]; return finaF0; } void RMVPEF0Extractor::InterPf0(size_t TargetLength) { const auto f0Len = refined_f0.size(); if (abs((int64_t)TargetLength - (int64_t)f0Len) < 3) { refined_f0.resize(TargetLength, 0.0); return; } for (size_t i = 0; i < f0Len; ++i) if (refined_f0[i] < 0.001) refined_f0[i] = NAN; auto xi = arange(0.0, (double)f0Len * (double)TargetLength, (double)f0Len, (double)TargetLength); while (xi.size() < TargetLength) xi.emplace_back(*(xi.end() - 1) + ((double)f0Len / (double)TargetLength)); while (xi.size() > TargetLength) xi.pop_back(); auto x0 = arange(0, (double)f0Len); while (x0.size() < f0Len) x0.emplace_back(*(x0.end() - 1) + 1.); while (x0.size() > f0Len) x0.pop_back(); auto raw_f0 = std::vector(xi.size()); interp1(x0.data(), refined_f0.data(), static_cast(x0.size()), xi.data(), (int)xi.size(), raw_f0.data()); for (size_t i = 0; i < xi.size(); i++) if (isnan(raw_f0[i])) raw_f0[i] = 0.0; refined_f0 = std::move(raw_f0); } MELPEF0Extractor::MELPEF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0) : BaseF0Extractor(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0) { if (RMVPECORE.Model) RMVPECORE.Destory(); if (!MELPECORE.Model) MELPECORE.LoadModel(L"MELPE.onnx"); } void MELPEF0Extractor::InterPf0(size_t TargetLength) { const auto f0Len = refined_f0.size(); if (abs((int64_t)TargetLength - (int64_t)f0Len) < 3) { refined_f0.resize(TargetLength, 0.0); return; } for (size_t i = 0; i < f0Len; ++i) if (refined_f0[i] < 0.001) refined_f0[i] = NAN; auto xi = arange(0.0, (double)f0Len * (double)TargetLength, (double)f0Len, (double)TargetLength); while (xi.size() < TargetLength) xi.emplace_back(*(xi.end() - 1) + ((double)f0Len / (double)TargetLength)); while (xi.size() > TargetLength) xi.pop_back(); auto x0 = arange(0, (double)f0Len); while (x0.size() < f0Len) x0.emplace_back(*(x0.end() - 1) + 1.); while (x0.size() > f0Len) x0.pop_back(); auto raw_f0 = std::vector(xi.size()); interp1(x0.data(), refined_f0.data(), static_cast(x0.size()), xi.data(), (int)xi.size(), raw_f0.data()); for (size_t i = 0; i < xi.size(); i++) if (isnan(raw_f0[i])) raw_f0[i] = 0.0; refined_f0 = std::move(raw_f0); } std::vector MELPEF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { if (!MELPECORE.Model) return DioF0Extractor((int)fs, (int)hop, (int)f0_bin, f0_max, f0_min).ExtractF0(PCMData, TargetLength); const double step = double(fs) / 16000.; const auto window_len = (size_t)round(step); const auto half_window_len = window_len / 2; const auto f0_size = size_t((double)PCMData.size() / step); const auto pcm_idx_size = PCMData.size() - 2; std::vector pcm(f0_size, 0.f); auto idx = double(half_window_len + 1); for (size_t i = 0; i < f0_size; ++i) { const auto index = size_t(round(idx)); if (index + half_window_len > pcm_idx_size) break; if (half_window_len == 0) pcm[i] = (float)PCMData[index]; else pcm[i] = (float)average(&PCMData[index - half_window_len], &PCMData[index + half_window_len]); idx += step; } std::vector Tensors; const int64_t pcm_shape[] = { 1, (int64_t)pcm.size() }; Tensors.emplace_back(Ort::Value::CreateTensor(*MELPECORE.Memory, pcm.data(), pcm.size(), pcm_shape, 2)); const auto out = MELPECORE.Model->Run(Ort::RunOptions{ nullptr }, InputNames.data(), Tensors.data(), Tensors.size(), OutputNames.data(), OutputNames.size()); const auto osize = out[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto of0 = out[0].GetTensorData(); refined_f0 = std::vector(osize); for (size_t i = 0; i < osize; ++i) refined_f0[i] = ((of0[i] > 0.001f) ? (double)out[0].GetTensorData()[i] : NAN); InterPf0(TargetLength); std::vector finaF0(refined_f0.size()); for (size_t i = 0; i < refined_f0.size(); ++i) finaF0[i] = isnan(refined_f0[i]) ? 0 : (float)refined_f0[i]; return finaF0; } void EmptyCache() { RMVPECORE.Destory(); MELPECORE.Destory(); } MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/F0Extractor/NetF0Predictors/NetF0Predictors.hpp ================================================ /** * FileName: NetF0Predictors.hpp * Note: MoeVoiceStudioCore 官方F0提取算法 Net * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "../BaseF0Extractor/BaseF0Extractor.hpp" #include MoeVoiceStudioF0ExtractorHeader class NetF0Class { public: NetF0Class(); ~NetF0Class() { Destory(); } void Destory(); void BuildCPUEnv(unsigned ThreadCount); void BuildCUDAEnv(unsigned Did); void BuildDMLEnv(unsigned Did); void LoadModel(const std::wstring& path); Ort::Env* NetF0Env = nullptr; Ort::SessionOptions* NetF0Options = nullptr; Ort::Session* Model = nullptr; Ort::MemoryInfo* Memory = nullptr; private: std::wstring NetF0PathDir; }; class RMVPEF0Extractor : public BaseF0Extractor { public: RMVPEF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); ~RMVPEF0Extractor() override = default; void InterPf0(size_t TargetLength); std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength) override; private: std::vector InputNames = { "waveform", "threshold" }; std::vector OutputNames = { "f0", "uv" }; std::vector refined_f0; }; class MELPEF0Extractor : public BaseF0Extractor { public: MELPEF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); ~MELPEF0Extractor() override = default; void InterPf0(size_t TargetLength); std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength) override; private: std::vector InputNames = { "waveform"}; std::vector OutputNames = { "f0" }; std::vector refined_f0; }; void EmptyCache(); MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/G2P/MoeVSG2P.cpp ================================================ #include "MoeVSG2P.hpp" #include "MJson.h" #include "../../StringPreprocess.hpp" #include "../../InferTools/inferTools.hpp" #include MoeVoiceStudioG2PHeader std::wregex SignRegex(L"[!@#$%^&*()_+\\-=`~,./;'\\[\\]<>?:\"{}|\\\\。?!,、;:“”‘’『』「」()〔〕【】─…·—~《》〈〉]+"); std::wregex WordRegex(L"[^!@#$%^&*()_+\\-=`~,./;'\\[\\]<>?:\"{}|\\\\。?!,、;:“”‘’『』「」()〔〕【】─…·—~《》〈〉]+"); std::wregex BlankRegex(L"[ ]+"); std::wregex ChineseRegex(L"^[\\u4e00-\\u9fa5]{0,}$"); std::wregex NumberRegex(L"\\d+(?:\\.?\\d+)?"); std::wstring ChineseNumber[] = { L"零",L"一",L"二",L"三",L"四",L"五",L"六",L"七",L"八",L"九",L"十" }; std::wstring ChineseNumberDigit[] = { L"",L"十",L"百",L"千",L"万",L"十万",L"百万",L"千万",L"亿" }; std::wstring JapaneseNumber[] = { L"零",L"一",L"ニ",L"三",L"四",L"五",L"六",L"七",L"八",L"九",L"十" }; std::wstring JapaneseNumberDigit[] = { L"",L"十",L"百",L"千",L"万",L"十万",L"百万",L"千万",L"億" }; std::unordered_map _PUNCTUATION_MAP{ { L":", L"," }, { L";", L"," }, { L",", L"," }, { L"。", L"." }, { L"!", L"!" }, { L"?", L"?" }, { L"·", L"," }, { L"、", L"," }, { L"...", L"…" }, { L"$", L"." }, { L"“", L"'" }, { L"”", L"'" }, { L"‘", L"'" }, { L"’", L"'" }, { L"(", L"'" }, { L")", L"'" }, { L"(", L"'" }, { L")", L"'" }, { L"《", L"'" }, { L"》", L"'" }, { L"【", L"'" }, { L"】", L"'" }, { L"[", L"'" }, { L"]", L"'" }, { L"—", L"-" }, { L"~", L"-" }, { L"~", L"-" }, { L"「", L"'" }, { L"」", L"'" } }; std::unordered_map _ALPHASYMBOL_MAP{ {L"#", L"シャープ"}, { L"%", L"パーセント" }, { L"&", L"アンド" }, { L"+", L"プラス" }, { L"-", L"マイナス" }, { L":", L"コロン" }, { L";", L"セミコロン" }, { L"<", L"小なり" }, { L"=", L"イコール" }, { L">", L"大なり" }, { L"@", L"アット" }, { L"a", L"エー" }, { L"b", L"ビー" }, { L"c", L"シー" }, { L"d", L"ディー" }, { L"e", L"イー" }, { L"f", L"エフ" }, { L"g", L"ジー" }, { L"h", L"エイチ" }, { L"i", L"アイ" }, { L"j", L"ジェー" }, { L"k", L"ケー" }, { L"l", L"エル" }, { L"m", L"エム" }, { L"n", L"エヌ" }, { L"o", L"オー" }, { L"p", L"ピー" }, { L"q", L"キュー" }, { L"r", L"アール" }, { L"s", L"エス" }, { L"t", L"ティー" }, { L"u", L"ユー" }, { L"v", L"ブイ" }, { L"w", L"ダブリュー" }, { L"x", L"エックス" }, { L"y", L"ワイ" }, { L"z", L"ゼット" }, { L"α", L"アルファ" }, { L"β", L"ベータ" }, { L"γ", L"ガンマ" }, { L"δ", L"デルタ" }, { L"ε", L"イプシロン" }, { L"ζ", L"ゼータ" }, { L"η", L"イータ" }, { L"θ", L"シータ" }, { L"ι", L"イオタ" }, { L"κ", L"カッパ" }, { L"λ", L"ラムダ" }, { L"μ", L"ミュー" }, { L"ν", L"ニュー" }, { L"ξ", L"クサイ" }, { L"ο", L"オミクロン" }, { L"π", L"パイ" }, { L"ρ", L"ロー" }, { L"σ", L"シグマ" }, { L"τ", L"タウ" }, { L"υ", L"ウプシロン" }, { L"φ", L"ファイ" }, { L"χ", L"カイ" }, { L"ψ", L"プサイ" }, { L"ω", L"オメガ", }}; std::vector> _CURRENCY_MAP{{L"\\$", L"ドル"}, { L"¥", L"円" }, { L"£", L"ポンド" }, { L"€", L"ユーロ" }}; MVSCleaner DefaultCleaner; MVSCleaner* GetDefCleaner() { return &DefaultCleaner; } #ifdef WIN32 MoeVoiceStudioG2PApi::~MoeVoiceStudioG2PApi() { unLoad(); } MoeVoiceStudioG2PApi& MoeVoiceStudioG2PApi::operator=(MoeVoiceStudioG2PApi&& move) noexcept { func = move.func; m_hDynLib = move.m_hDynLib; move.func = nullptr; move.m_hDynLib = nullptr; return *this; } bool MoeVoiceStudioG2PApi::enabled() const { return m_hDynLib != nullptr; } MoeVoiceStudioG2PApi::SplitData MoeVoiceStudioG2PApi::GetSplitWords(const std::wstring& inputLen) const { SplitData TempData; if (getvocab) TempData = (*(SplitData*)getvocab(inputLen.c_str())); return TempData; } void MoeVoiceStudioG2PApi::LoadDict(const std::wstring& Path) const { if (loaddic) loaddic(Path.c_str()); } char MoeVoiceStudioG2PApi::Load(const std::wstring& PluginName) { func = nullptr; frel = nullptr; if (m_hDynLib) { FreeLibrary(m_hDynLib); m_hDynLib = nullptr; } m_hDynLib = LoadLibrary((PluginName).c_str()); if (m_hDynLib == nullptr) return -1; func = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "PluginMain") ) ); frel = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "Release") ) ); getvocab = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "GetSplitData") ) ); vocabrel = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "RefreshTokenizer") ) ); loaddic = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "LoadDict") ) ); if (func == nullptr) return 1; return 0; } std::wstring MoeVoiceStudioG2PApi::functionAPI(const std::wstring& inputLen, const std::wstring& placeholderSymbol, const std::wstring& extraInfo, const std::string& languageID) const { if (func) { const auto tmp = func(inputLen.c_str(), placeholderSymbol.c_str(), extraInfo.c_str(), languageID.c_str()); std::wstring ret = tmp; return ret; } return inputLen; } void MoeVoiceStudioG2PApi::unLoad() { if (frel) frel(); if (vocabrel) vocabrel(); vocabrel = nullptr; getvocab = nullptr; loaddic = nullptr; func = nullptr; frel = nullptr; if (m_hDynLib) FreeLibrary(m_hDynLib); m_hDynLib = nullptr; } #endif void MVSDict::GetDict(const std::wstring& path) { if (path.empty()) { _Dict.clear(); return; } PlaceholderSymbol = L"|"; std::string phoneInfo, phoneInfoAll; std::ifstream phonefile(path.c_str()); if (!phonefile.is_open()) LibDLVoiceCodecThrow("phone file not found") while (std::getline(phonefile, phoneInfo)) phoneInfoAll += phoneInfo; phonefile.close(); MJson PhoneJson; PhoneJson.Parse(phoneInfoAll); if (PhoneJson.HasParseError()) LibDLVoiceCodecThrow("json file error") for (const auto& itr : PhoneJson.GetMemberArray()) { std::wstring Key = to_wide_string(itr.first); if (Key == L"PlaceholderSymbol") { if (itr.second.IsString() && itr.second.GetStringLength()) PlaceholderSymbol = to_wide_string(itr.second.GetString()); if (PlaceholderSymbol.length() > 1) PlaceholderSymbol = L"|"; continue; } const auto Value = itr.second.GetArray(); _Dict[Key] = std::vector(); for (const auto& it : Value) _Dict[Key].push_back(to_wide_string(it.GetString())); } } std::vector MVSDict::DictReplace(const std::vector& input) const { std::vector _out; for (const auto& i : input) if (_Dict.find(i) != _Dict.end()) { const auto& Value = _Dict.at(i); _out.insert(_out.end(), Value.begin(), Value.end()); } else _out.emplace_back(i); return _out; } std::vector MVSDict::DictReplace(const std::wstring& input, const std::wstring& tPlaceholderSymbol) const { std::vector _output; auto tmp = input; tmp += tPlaceholderSymbol; while (!tmp.empty()) { const size_t pos = tmp.find(tPlaceholderSymbol); const auto Key = tmp.substr(0, pos); tmp = tmp.substr(pos + 1); if (_Dict.find(Key) != _Dict.end()) { const auto& Value = _Dict.at(Key); _output.insert(_output.end(), Value.begin(), Value.end()); } else _output.emplace_back(Key); } for (int64_t i = int64_t(_output.size()) - 1; i >= 0; --i) if (_output[i].empty()) _output.erase(_output.begin() + i); return _output; } std::wstring MVSDict::DictReplaceGetStr(const std::wstring& input, const std::wstring& tPlaceholderSymbol, bool usePlaceholderSymbol) const { const auto tmp = DictReplace(input, tPlaceholderSymbol); std::wstring output; for (const auto& i : tmp) if (usePlaceholderSymbol) output += i + tPlaceholderSymbol; else output += i; return output; } void Tokenizer::load(const std::wstring& _Path) { const MJson _VocabJson(_Path); if (!_VocabJson.HasMember("ContinuingSubwordPrefix") || !_VocabJson.HasMember("Type") || !_VocabJson.HasMember("Vocab") || _VocabJson["ContinuingSubwordPrefix"].Empty() || _VocabJson["Type"].Empty() || !_VocabJson["ContinuingSubwordPrefix"].IsString() || !_VocabJson["Type"].IsString()) LibDLVoiceCodecThrow("Vocab.json Error") const std::string Type = _VocabJson["Type"].GetString(); if (Type == "Unigram") Model = TokenizerModel::Unigram; Symbol = to_wide_string(_VocabJson["ContinuingSubwordPrefix"].GetString()); if (_VocabJson["Vocab"].IsArray()) { const auto _VocabArray = _VocabJson["Vocab"].GetArray(); int64_t Index = 0; for (const auto& Object : _VocabArray) { if (!(Object.IsString() || Object.IsArray())) { auto Beg = Object.MemberBegin(); if (Beg.first.empty()) continue; Vocab[to_wide_string(Beg.first)] = Beg.second.GetInt64(); } else Vocab[to_wide_string(Object.IsString() ? Object.GetString() : Object.GetArray()[0].GetString())] = Index++; } } else { const auto _VocabDict = _VocabJson["Vocab"].GetMemberArray(); for (const auto& Pair : _VocabDict) { if (Pair.second.IsInt()) Vocab[to_wide_string(Pair.first)] = TokenizerType(Pair.second.GetInt()); else if (Pair.second.IsFloat()) Vocab[to_wide_string(Pair.first)] = TokenizerType(Pair.second.GetFloat()); } } if (_VocabJson.HasMember("UseSplit") && _VocabJson["UseSplit"].IsBool()) UseSplit = _VocabJson["UseSplit"].GetBool(); } void Tokenizer::loadCleaner(const std::wstring& _Path) const { if (Cleaner) Cleaner->loadG2p(_Path); } void Tokenizer::loadDict(const std::wstring& _Path) const { if (Cleaner) Cleaner->loadDict(_Path); } std::vector Tokenizer::UnigramMethod(const std::wstring& Seq, size_t MaxWordLength, TokenizerMethod Method) const { if (Seq.empty()) return {}; //auto SeqVector = SplitString(Seq, SignRegex); std::vector Tokens; Tokens.emplace_back(L"[CLS]"); std::wstring SeqWord = Seq; if (Method == TokenizerMethod::Left) { bool FirstTime = true; while (!SeqWord.empty()) { for (size_t SearchLength = min(MaxWordLength, SeqWord.length()); SearchLength > 0; --SearchLength) { if (FirstTime) { size_t SubVal = 0; if (SearchLength > Symbol.length()) SubVal = Symbol.length(); const auto SearchResult = Vocab.find(Symbol + SeqWord.substr(0, SearchLength - SubVal)); if (SearchResult != Vocab.end()) { Tokens.emplace_back(SearchResult->first); SeqWord = SeqWord.substr(SearchLength - SubVal); FirstTime = false; break; } } const auto SearchResult = Vocab.find(SeqWord.substr(0, SearchLength)); if (SearchResult != Vocab.end()) { Tokens.emplace_back(SearchResult->first); SeqWord = SeqWord.substr(SearchLength); if (FirstTime) FirstTime = false; break; } if (SearchLength == 1) { const auto SubStr = SeqWord.substr(0, SearchLength); const auto SearchRes = _PUNCTUATION_MAP.find(SubStr); if (SearchRes != _PUNCTUATION_MAP.end()) { const auto SearchR = Vocab.find(SearchRes->second); if (SearchR != Vocab.end()) Tokens.emplace_back(SearchR->first); SeqWord = SeqWord.substr(1); break; } if (Tokens.empty() || Tokens.back() != L"[UNK]") Tokens.emplace_back(SubStr); SeqWord = SeqWord.substr(1); } } } } else LibDLVoiceCodecThrow("NotImplementedError") Tokens.emplace_back(L"[SEP]"); return Tokens; } std::vector Tokenizer::WordPieceMethod(const std::wstring& Seq, size_t MaxWordLength, TokenizerMethod Method) const { if (Seq.empty()) return {}; auto SeqVector = SplitString(Seq, SignRegex); std::vector Tokens; Tokens.emplace_back(L"[CLS]"); if (Method == TokenizerMethod::Left) { for (auto& SeqWord : SeqVector) { bool FirstTime = true; while (!SeqWord.empty()) { if (regex_match(SeqWord.substr(0, 1), ChineseRegex)) { const auto SearchResult = Vocab.find(SeqWord.substr(0, 1)); if (SearchResult != Vocab.end()) Tokens.emplace_back(SearchResult->first); else Tokens.emplace_back(SeqWord.substr(0, 1)); SeqWord = SeqWord.substr(1); continue; } for (size_t SearchLength = min(MaxWordLength, SeqWord.length()); SearchLength > 0; --SearchLength) { if (!FirstTime) { size_t SubVal = 0; if (SearchLength > Symbol.length()) SubVal = Symbol.length(); const auto SearchResult = Vocab.find(Symbol + SeqWord.substr(0, SearchLength - SubVal)); if (SearchResult != Vocab.end()) { Tokens.emplace_back(SearchResult->first); SeqWord = SeqWord.substr(SearchLength - SubVal); break; } } const auto SearchResult = Vocab.find(SeqWord.substr(0, SearchLength)); if (SearchResult != Vocab.end()) { Tokens.emplace_back(SearchResult->first); SeqWord = SeqWord.substr(SearchLength); if (FirstTime) FirstTime = false; break; } if (SearchLength == 1) { const auto SubStr = SeqWord.substr(0, SearchLength); const auto SearchRes = _PUNCTUATION_MAP.find(SubStr); if (SearchRes != _PUNCTUATION_MAP.end()) { const auto SearchR = Vocab.find(SearchRes->second); if (SearchR != Vocab.end()) Tokens.emplace_back(SearchR->first); SeqWord = SeqWord.substr(1); break; } if (Tokens.empty() || Tokens.back() != L"[UNK]") Tokens.emplace_back(SubStr); SeqWord = SeqWord.substr(1); } } } } } else LibDLVoiceCodecThrow("NotImplementedError") Tokens.emplace_back(L"[SEP]"); return Tokens; } std::vector Tokenizer::operator()(const std::vector& Seq, bool SkipBlank) const { std::vector Tokens; const auto UNKID = Vocab.at(L"[UNK]"); for (const auto& iter : Seq) { const auto res = Vocab.find(iter); if (res != Vocab.end()) Tokens.emplace_back(res->second); else if(iter.empty() || Tokens.back() != UNKID) { if (SkipBlank && std::regex_match(iter, BlankRegex)) continue; Tokens.emplace_back(UNKID); } } return Tokens; } std::vector Tokenizer::Tokenize(const std::wstring& Seq, size_t MaxWordLength, TokenizerMethod Method) const { if (Model == TokenizerModel::WordPiece) return WordPieceMethod(Seq, MaxWordLength, Method); return UnigramMethod(Seq, MaxWordLength, Method); } std::vector Tokenizer::SplitString(const std::wstring& _InputRef, const std::wregex & _SignRegex) { if (_InputRef.empty()) return {}; std::wstring InputStr = _InputRef; std::vector TmpStrVec, StrVec; std::wsmatch MatchedSign; while (std::regex_search(InputStr, MatchedSign, _SignRegex)) { if (MatchedSign.prefix().matched) TmpStrVec.push_back(MatchedSign.prefix()); TmpStrVec.push_back(MatchedSign.str()); InputStr = MatchedSign.suffix(); } if (!InputStr.empty()) TmpStrVec.emplace_back(InputStr); for(const auto& i : TmpStrVec) { std::wsregex_token_iterator TokenIter(i.begin(), i.end(), BlankRegex, -1); decltype(TokenIter) TokenIterEnd; for (; TokenIter != TokenIterEnd; ++TokenIter) if (!TokenIter->str().empty()) StrVec.push_back(TokenIter->str()); } return StrVec; } std::vector Tokenizer::SplitWithPlugin(const std::vector& _Inputs) const { std::vector SeqVec; for(const auto& Seq : _Inputs) { const auto SplitedWords = GetCleaner().GetCleaner().GetSplitWords(Seq); for (size_t i = 0; i < SplitedWords.Size; ++i) { auto TmpString = to_wide_string(SplitedWords.Data[i]); TmpString = TmpString.substr(0, TmpString.find(L',')); SeqVec.emplace_back(std::move(TmpString)); } } return SeqVec; } std::wstring NumberToChinese(double Number) { std::wstring StrRtn; std::wstring InputStr = std::to_wstring(Number); const size_t PIndex = InputStr.find(L'.'); std::wstring IntegerStr, FractionStr; if (PIndex != std::wstring::npos) { IntegerStr = InputStr.substr(0, PIndex); FractionStr = InputStr.substr(PIndex + 1); while (!FractionStr.empty() && FractionStr.back() == L'0') FractionStr.pop_back(); } else IntegerStr = std::move(InputStr); if (IntegerStr != L"0") { size_t MaxIntegerStrLength = IntegerStr.length(); for (; MaxIntegerStrLength > 0; --MaxIntegerStrLength) if (IntegerStr[MaxIntegerStrLength - 1] != L'0') break; if (MaxIntegerStrLength < 1) MaxIntegerStrLength = 1; const auto DigitNum = IntegerStr.length(); for (size_t i = 0; i < MaxIntegerStrLength; i++) { const auto NumberIndex = IntegerStr[i] - L'0'; const auto DigitIndex = DigitNum - i - 1; if (0 == NumberIndex) { if ((i > 0 && L'0' == IntegerStr[i - 1]) || i == IntegerStr.length() - 1) continue; if (DigitIndex >= 4 && 0 == DigitIndex % 4) StrRtn += ChineseNumberDigit[DigitIndex]; else StrRtn += ChineseNumber[NumberIndex]; } else { StrRtn += ChineseNumber[NumberIndex]; if (IntegerStr.length() == 2 && IntegerStr[0] == '1' && i == 0) StrRtn.erase(0); if (0 == DigitIndex % 4) StrRtn += ChineseNumberDigit[DigitIndex]; else StrRtn += ChineseNumberDigit[DigitIndex % 4]; } } } else StrRtn += L"零"; if (!FractionStr.empty()) StrRtn += L"点"; for(const auto FractionI : FractionStr) { const auto NumberIndex = FractionI - L'0'; StrRtn += ChineseNumber[NumberIndex]; } return StrRtn; } std::wstring NumberToJapanese(double Number) { std::wstring StrRtn; std::wstring InputStr = std::to_wstring(Number); const size_t PIndex = InputStr.find(L'.'); std::wstring IntegerStr, FractionStr; if (PIndex != std::wstring::npos) { IntegerStr = InputStr.substr(0, PIndex); FractionStr = InputStr.substr(PIndex + 1); while (!FractionStr.empty() && FractionStr.back() == L'0') FractionStr.pop_back(); } else IntegerStr = std::move(InputStr); if (IntegerStr != L"0") { size_t MaxIntegerStrLength = IntegerStr.length(); for (; MaxIntegerStrLength > 0; --MaxIntegerStrLength) if (IntegerStr[MaxIntegerStrLength - 1] != L'0') break; if (MaxIntegerStrLength < 1) MaxIntegerStrLength = 1; const auto DigitNum = IntegerStr.length(); for (size_t i = 0; i < MaxIntegerStrLength; i++) { const auto NumberIndex = IntegerStr[i] - L'0'; const auto DigitIndex = DigitNum - i - 1; if (0 == NumberIndex) { if ((i > 0 && L'0' == IntegerStr[i - 1]) || i == IntegerStr.length() - 1) continue; if (DigitIndex >= 4 && 0 == DigitIndex % 4) StrRtn += JapaneseNumberDigit[DigitIndex]; else StrRtn += JapaneseNumber[NumberIndex]; } else { StrRtn += JapaneseNumber[NumberIndex]; if (IntegerStr.length() == 2 && IntegerStr[0] == '1' && i == 0) StrRtn.erase(0); if (0 == DigitIndex % 4) StrRtn += JapaneseNumberDigit[DigitIndex]; else StrRtn += JapaneseNumberDigit[DigitIndex % 4]; } } } else StrRtn += L"零"; if (!FractionStr.empty()) StrRtn += L"点"; for (const auto FractionI : FractionStr) { const auto NumberIndex = FractionI - L'0'; StrRtn += JapaneseNumber[NumberIndex]; } return StrRtn; } std::wstring ChineseNormalize(const std::wstring& _Input) { std::wstring RtnStr; const auto StrVec = Tokenizer::SplitString(_Input, NumberRegex); for(const auto& Str : StrVec) { if (std::regex_match(Str, NumberRegex)) RtnStr += NumberToChinese(_wtof(Str.c_str())); else RtnStr += Str; } RtnStr = std::regex_replace(RtnStr, std::wregex(L"嗯"), L"恩"); RtnStr = std::regex_replace(RtnStr, std::wregex(L"呣"), L"母"); return RtnStr; } std::wstring JapaneseNormalize(const std::wstring& _Input) { std::wstring RtnStr; const auto StrVec = Tokenizer::SplitString(_Input, NumberRegex); for (const auto& Str : StrVec) { if (std::regex_match(Str, NumberRegex)) RtnStr += NumberToJapanese(_wtof(Str.c_str())); else RtnStr += Str; } for (const auto& PunPair : _CURRENCY_MAP) RtnStr = std::regex_replace(RtnStr, std::wregex(PunPair.first), PunPair.second); return RtnStr; } std::wstring NormalizeText(const std::wstring& _Input, const std::string& _Language) { if (_Language == "ZH") return ChineseNormalize(_Input); if (_Language == "JP") return JapaneseNormalize(_Input); return _Input; } MoeVoiceStudioG2PEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/G2P/MoeVSG2P.hpp ================================================ /** * FileName: MoeVSG2P.hpp * Note: MoeVoiceStudioCore G2P及字典(TTS用) * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2023-11-9 Create */ #pragma once #include #ifdef _WIN32 #ifndef UNICODE #define UNICODE #endif #include #endif #include #include #include #include #define MoeVoiceStudioG2PHeader namespace MoeVSG2P { #define MoeVoiceStudioG2PEnd } MoeVoiceStudioG2PHeader class MoeVoiceStudioG2PApi { public: struct SplitData { char** Data = nullptr; size_t Size = 0; }; using funTy = const wchar_t* (*)(const wchar_t*, const wchar_t*, const wchar_t*, const char*); using freTy = void (*)(); using vocabFn = void* (*)(const wchar_t*); using loadFn = void (*)(const wchar_t*); MoeVoiceStudioG2PApi() = default; ~MoeVoiceStudioG2PApi(); char Load(const std::wstring& PluginName); void unLoad(); void ReleaseVoc() const { if (vocabrel) vocabrel(); } [[nodiscard]] SplitData GetSplitWords(const std::wstring& inputLen) const; [[nodiscard]] std::wstring functionAPI(const std::wstring& inputLen, const std::wstring& placeholderSymbol, const std::wstring& extraInfo, const std::string& languageID) const; MoeVoiceStudioG2PApi(const MoeVoiceStudioG2PApi&) = delete; MoeVoiceStudioG2PApi(MoeVoiceStudioG2PApi&&) = delete; MoeVoiceStudioG2PApi& operator=(MoeVoiceStudioG2PApi&& move) noexcept; [[nodiscard]] bool enabled() const; MoeVoiceStudioG2PApi& operator=(const MoeVoiceStudioG2PApi&) = delete; void LoadDict(const std::wstring& Path) const; private: #ifdef WIN32 const wchar_t*(*func)(const wchar_t*, const wchar_t*, const wchar_t*, const char*) = nullptr; void (*frel)() = nullptr; void* (*getvocab)(const wchar_t*) = nullptr; void (*vocabrel)() = nullptr; void (*loaddic)(const wchar_t*) = nullptr; HINSTANCE m_hDynLib = nullptr; #endif }; class MVSDict { public: MVSDict() = default; ~MVSDict() = default; [[nodiscard]] bool enabled() const { return !_Dict.empty(); } void unload() { _Dict.clear(); } [[nodiscard]] std::vector DictReplace(const std::vector& input) const; [[nodiscard]] std::vector DictReplace(const std::wstring& input, const std::wstring& tPlaceholderSymbol) const; [[nodiscard]] std::wstring DictReplaceGetStr(const std::wstring& input, const std::wstring& tPlaceholderSymbol, bool usePlaceholderSymbol = true) const; void GetDict(const std::wstring& path); [[nodiscard]] std::wstring getPlaceholderSymbol() const { return PlaceholderSymbol; } private: std::map> _Dict; std::wstring PlaceholderSymbol = L"|"; }; class MVSCleaner { public: MVSCleaner() = default; ~MVSCleaner() { unloadDict(); unloadG2p(); } void unloadDict() { _Dict.unload(); } void unloadG2p() { _G2p.unLoad(); } void loadDict(const std::wstring& _path) { if (_Dict.enabled()) unloadDict(); _Dict.GetDict(_path); } void loadG2p(const std::wstring& _path) { if (_G2p.enabled()) unloadG2p(); _G2p.Load(_path); } [[nodiscard]] bool G2pEnabled() const { return _G2p.enabled(); } [[nodiscard]] bool DictEnabled() const { return _Dict.enabled(); } [[nodiscard]] std::wstring G2p(const std::wstring& _text, const std::wstring& placeholderSymbol, const std::wstring& extraInfo, std::string languageID) const { return _G2p.functionAPI(_text, placeholderSymbol, extraInfo, languageID); } [[nodiscard]] const MoeVoiceStudioG2PApi& GetCleaner() const { return _G2p; } [[nodiscard]] auto DictReplace(const std::vector& input) const { return _Dict.DictReplace(input); } [[nodiscard]] auto DictReplace(const std::wstring& input, const std::wstring& tPlaceholderSymbol) const { return _Dict.DictReplace(input, tPlaceholderSymbol); } [[nodiscard]] auto DictReplaceGetStr(const std::wstring& input, const std::wstring& tPlaceholderSymbol, bool usePlaceholderSymbol = true) const { return _Dict.DictReplaceGetStr(input, tPlaceholderSymbol, usePlaceholderSymbol); } [[nodiscard]] std::wstring getPlaceholderSymbol() const { return _Dict.getPlaceholderSymbol(); } protected: MoeVoiceStudioG2PApi _G2p; MVSDict _Dict; }; class Tokenizer { public: using TokenizerType = int64_t; enum class TokenizerMethod { Left, Right }; enum class TokenizerModel { Unigram, WordPiece }; Tokenizer() = default; Tokenizer(const std::wstring& _Path) { load(_Path); } void BondCleaner(MVSCleaner* MCleaner) { Cleaner = MCleaner; } void load(const std::wstring& _Path); void loadCleaner(const std::wstring& _Path) const; void loadDict(const std::wstring& _Path) const; [[nodiscard]] const MVSCleaner& GetCleaner() const { return *Cleaner; } const MVSCleaner* operator->() const { return Cleaner; } [[nodiscard]] std::vector WordPieceMethod(const std::wstring& Seq, size_t MaxWordLength = 25, TokenizerMethod Method = TokenizerMethod::Left) const; [[nodiscard]] std::vector UnigramMethod(const std::wstring& Seq, size_t MaxWordLength = 25, TokenizerMethod Method = TokenizerMethod::Left) const; std::vector operator()(const std::vector& Seq, bool SkipBlank = false) const; [[nodiscard]] std::vector Tokenize(const std::wstring& Seq, size_t MaxWordLength = 25, TokenizerMethod Method = TokenizerMethod::Left) const; [[nodiscard]] std::vector SplitWithPlugin(const std::vector& _Inputs) const; static std::vector SplitString(const std::wstring& _InputRef, const std::wregex& _SignRegex); private: std::unordered_map Vocab; std::wstring Symbol = L"##"; TokenizerModel Model = TokenizerModel::WordPiece; MVSCleaner* Cleaner = nullptr; bool UseSplit = false; }; MVSCleaner* GetDefCleaner(); std::wstring JapaneseNormalize(const std::wstring& _Input); std::wstring ChineseNormalize(const std::wstring& _Input); std::wstring NormalizeText(const std::wstring& _Input, const std::string& _Language); std::wstring NumberToChinese(double Number); std::wstring NumberToJapanese(double Number); MoeVoiceStudioG2PEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Sampler/MoeVSBaseSampler.cpp ================================================ #include "MoeVSBaseSampler.hpp" #include "../inferTools.hpp" MoeVoiceStudioSamplerHeader MoeVSBaseSampler::MoeVSBaseSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) : MelBins(Mel_Bins), Alpha(alpha), DenoiseFn(dfn), NoisePredictor(pred) { _callback = _ProgressCallback; Memory = memory; }; std::vector MoeVSBaseSampler::Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) { LibDLVoiceCodecThrow("NotImplementedError"); } MoeVoiceStudioSamplerEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Sampler/MoeVSBaseSampler.hpp ================================================ /** * FileName: MoeVSBaseSampler.hpp * Note: MoeVoiceStudioCore Diffusion 采样器基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #define MoeVoiceStudioSamplerHeader namespace MoeVSSampler { #define MoeVoiceStudioSamplerEnd } #include #include MoeVoiceStudioSamplerHeader class MoeVSBaseSampler { public: using ProgressCallback = std::function; /** * \brief 构造采样器 * \param alpha Alphas Onnx模型Session * \param dfn DenoiseFn Onnx模型Session * \param pred Predictor Onnx模型Session * \param Mel_Bins MelBins * \param _ProgressCallback 进度条回调(直接传模型的回调就可以了) * \param memory 模型的OrtMemoryInfo */ MoeVSBaseSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); virtual ~MoeVSBaseSampler() = default; /** * \brief 采样 * \param Tensors 输入张量(Tensors[0]为Condition,Tensors[1]为初始噪声) * \param Steps 采样步数 * \param SpeedUp 加速倍数 * \param NoiseScale 噪声规模 * \param Seed 种子 * \param Process 当前进度 * \return Mel张量 */ virtual std::vector Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process); protected: int64_t MelBins = 128; Ort::Session* Alpha = nullptr; Ort::Session* DenoiseFn = nullptr; Ort::Session* NoisePredictor = nullptr; ProgressCallback _callback; Ort::MemoryInfo* Memory = nullptr; }; MoeVoiceStudioSamplerEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Sampler/MoeVSSamplerManager.cpp ================================================ #include "MoeVSSamplerManager.hpp" #include #include "../../Logger/MoeSSLogger.hpp" MoeVoiceStudioSamplerHeader std::map RegisteredMoeVSSamplers; MoeVSSampler GetMoeVSSampler(const std::wstring& _name, Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const MoeVSBaseSampler::ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) { const auto f_Sampler = RegisteredMoeVSSamplers.find(_name); if (f_Sampler != RegisteredMoeVSSamplers.end()) return f_Sampler->second(alpha, dfn, pred, Mel_Bins, _ProgressCallback, memory); throw std::runtime_error("Unable To Find An Available Sampler"); } void RegisterMoeVSSampler(const std::wstring& _name, const GetMoeVSSamplerFn& _constructor_fn) { if (RegisteredMoeVSSamplers.find(_name) != RegisteredMoeVSSamplers.end()) { logger.log(L"[Warn] F0ExtractorNameConflict"); return; } RegisteredMoeVSSamplers[_name] = _constructor_fn; } std::vector GetMoeVSSamplerList() { std::vector SamplersVec; SamplersVec.reserve(RegisteredMoeVSSamplers.size()); for (const auto& i : RegisteredMoeVSSamplers) SamplersVec.emplace_back(i.first); return SamplersVec; } MoeVoiceStudioSamplerEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Sampler/MoeVSSamplerManager.hpp ================================================ /** * FileName: MoeVSSamplerManager.hpp * Note: MoeVoiceStudioCore Diffusion 采样器管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVSBaseSampler.hpp" MoeVoiceStudioSamplerHeader class MoeVSSampler { public: MoeVSSampler() = delete; MoeVSSampler(MoeVSBaseSampler* _ext) : _f0_ext(_ext) {} MoeVSSampler(const MoeVSSampler&) = delete; MoeVSSampler(MoeVSSampler&& _ext) noexcept { delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; } MoeVSSampler& operator=(const MoeVSSampler&) = delete; MoeVSSampler& operator=(MoeVSSampler&& _ext) noexcept { if (this == &_ext) return *this; delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; return *this; } ~MoeVSSampler() { delete _f0_ext; _f0_ext = nullptr; } MoeVSBaseSampler* operator->() const { return _f0_ext; } private: MoeVSBaseSampler* _f0_ext = nullptr; }; using GetMoeVSSamplerFn = std::function; void RegisterMoeVSSampler(const std::wstring& _name, const GetMoeVSSamplerFn& _constructor_fn); /** * \brief 获取采样器 * \param _name 类名 * \param alpha Alphas Onnx模型Session * \param dfn DenoiseFn Onnx模型Session * \param pred Predictor Onnx模型Session * \param Mel_Bins MelBins * \param _ProgressCallback 进度条回调(直接传模型的回调就可以了) * \param memory 模型的OrtMemoryInfo * \return 采样器 */ MoeVSSampler GetMoeVSSampler(const std::wstring& _name, Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const MoeVSBaseSampler::ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); std::vector GetMoeVSSamplerList(); MoeVoiceStudioSamplerEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Sampler/MoeVSSamplers.cpp ================================================ #include "MoeVSSamplers.hpp" #include #include #include "../inferTools.hpp" MoeVoiceStudioSamplerHeader PndmSampler::PndmSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) : MoeVSBaseSampler(alpha, dfn, pred, Mel_Bins, _ProgressCallback, memory) {} DDimSampler::DDimSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) : MoeVSBaseSampler(alpha, dfn, pred, Mel_Bins, _ProgressCallback, memory) {} std::vector PndmSampler::Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) { std::vector diffusionSteps; for (int64_t itt = Steps - SpeedUp; itt >= 0; itt -= SpeedUp) diffusionSteps.push_back(itt); std::vector DenoiseIn; std::vector DenoiseOut; std::vector PredIn; std::vector PredOut; std::vector DiffOut; std::deque> noiseList; constexpr int64_t timeshape[1] = { 1 }; // PLMS SAMPLING for (const auto& t : diffusionSteps) { int64_t time[1] = { t }; int64_t time_prev[1] = { t - SpeedUp > 0 ? t - SpeedUp : 0 }; if (noiseList.empty()) { DenoiseIn.emplace_back(std::move(Tensors[1])); // noise DenoiseIn[0] DenoiseIn.emplace_back(Ort::Value::CreateTensor(*Memory, time, 1, timeshape, 1)); // time DenoiseIn[1] DenoiseIn.emplace_back(std::move(Tensors[0])); // condition DenoiseIn[2] try { DenoiseOut = DenoiseFn->Run(Ort::RunOptions{ nullptr }, denoiseInput.data(), DenoiseIn.data(), DenoiseIn.size(), denoiseOutput.data(), denoiseOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: denoise\n") + e1.what()).c_str()); } noiseList.emplace_back(std::vector(DenoiseOut[0].GetTensorData(), DenoiseOut[0].GetTensorData() + DenoiseOut[0].GetTensorTypeAndShapeInfo().GetElementCount())); // NoiseListExpand PredIn.emplace_back(std::move(DenoiseIn[0])); // noise PredIn[0] PredIn.emplace_back(std::move(DenoiseOut[0])); // noise_pred PredIn[1] PredIn.emplace_back(std::move(DenoiseIn[1])); // time PredIn[2] PredIn.emplace_back(Ort::Value::CreateTensor(*Memory, time_prev, 1, timeshape, 1)); // time_prev PredIn[3] try { PredOut = NoisePredictor->Run(Ort::RunOptions{ nullptr }, predInput.data(), PredIn.data(), PredIn.size(), predOutput.data(), predOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what()).c_str()); } DenoiseIn[0] = std::move(PredOut[0]); // x_pred DenoiseIn[1] = std::move(PredIn[3]); // time_prev //DenoiseIn[2] = std::move(DenoiseIn[2]); // condition try { DenoiseOut = DenoiseFn->Run(Ort::RunOptions{ nullptr }, denoiseInput.data(), DenoiseIn.data(), DenoiseIn.size(), denoiseOutput.data(), denoiseOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: denoise\n") + e1.what()).c_str()); } auto noise_pred_prev = DenoiseOut[0].GetTensorMutableData(); for (const auto it : noiseList[0]) (*(noise_pred_prev++) += it) /= 2.0f; //PredIn[0] = std::move(PredIn[0]); // noise PredIn[1] = std::move(DenoiseOut[0]); // noise_pred_prime //PredIn[2] = std::move(PredIn[2]); // time PredIn[3] = std::move(DenoiseIn[1]); // time_prev } else { DenoiseIn[0] = std::move(PredOut[0]); // x DenoiseIn[1] = Ort::Value::CreateTensor(*Memory, time, 1, timeshape, 1); // time //DenoiseIn[2] = std::move(DenoiseIn[2]); // condition try { DenoiseOut = DenoiseFn->Run(Ort::RunOptions{ nullptr }, denoiseInput.data(), DenoiseIn.data(), DenoiseIn.size(), denoiseOutput.data(), denoiseOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: denoise\n") + e1.what()).c_str()); } if (noiseList.size() < 4) noiseList.emplace_back(std::vector(DenoiseOut[0].GetTensorData(), DenoiseOut[0].GetTensorData() + DenoiseOut[0].GetTensorTypeAndShapeInfo().GetElementCount())); else { noiseList.pop_front(); noiseList.emplace_back(std::vector(DenoiseOut[0].GetTensorData(), DenoiseOut[0].GetTensorData() + DenoiseOut[0].GetTensorTypeAndShapeInfo().GetElementCount())); } auto noise_pred_prime = DenoiseOut[0].GetTensorMutableData(); if (noiseList.size() == 2) for (size_t it = 0; it < noiseList[0].size(); ++it) ((*(noise_pred_prime++) *= 3.0f) -= noiseList[0][it]) /= 2.0f; if (noiseList.size() == 3) for (size_t it = 0; it < noiseList[0].size(); ++it) (((*(noise_pred_prime++) *= 23.0f) -= noiseList[1][it] * 16.0f) += noiseList[0][it] * 5.0f) /= 12.0f; if (noiseList.size() == 4) for (size_t it = 0; it < noiseList[0].size(); ++it) ((((*(noise_pred_prime++) *= 55.0f) -= noiseList[2][it] * 59.0f) += noiseList[1][it] * 37.0f) -= noiseList[0][it] * 9.0f) /= 24.0f; PredIn[0] = std::move(DenoiseIn[0]); // x PredIn[1] = std::move(DenoiseOut[0]); // noise_pred_prime PredIn[2] = std::move(DenoiseIn[1]); // time PredIn[3] = Ort::Value::CreateTensor(*Memory, time_prev, 1, timeshape, 1); } try { PredOut = NoisePredictor->Run(Ort::RunOptions{ nullptr }, predInput.data(), PredIn.data(), PredIn.size(), predOutput.data(), predOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what()).c_str()); } _callback(++Process, 1); } return PredOut; } std::vector DDimSampler::Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) { std::vector diffusionSteps; for (int64_t itt = Steps - SpeedUp; itt >= 0; itt -= SpeedUp) diffusionSteps.push_back(itt); std::vector DenoiseIn; std::vector AlphaIn1, AlphaIn2; int64_t time[1] = { 0 }; int64_t time_prev[1] = { 0 }; constexpr int64_t timeshape[1] = { 1 }; // DDIM SAMPLING AlphaIn1.emplace_back(Ort::Value::CreateTensor(*Memory, time, 1, timeshape, 1)); AlphaIn2.emplace_back(Ort::Value::CreateTensor(*Memory, time_prev, 1, timeshape, 1)); DenoiseIn.emplace_back(std::move(Tensors[1])); // noise DenoiseIn[0] DenoiseIn.emplace_back(Ort::Value::CreateTensor(*Memory, time, 1, timeshape, 1)); // time DenoiseIn[1] DenoiseIn.emplace_back(std::move(Tensors[0])); // condition DenoiseIn[2] for (const auto& t : diffusionSteps) { std::vector DenoiseOut; float a_t, a_prev; try { time[0] = t; a_t = Alpha->Run(Ort::RunOptions{ nullptr }, alphain.data(), AlphaIn1.data(), AlphaIn1.size(), alphaout.data(), alphaout.size())[0].GetTensorData()[0]; time_prev[0] = (((t - SpeedUp) > 0) ? t - SpeedUp : 0); a_prev = Alpha->Run(Ort::RunOptions{ nullptr }, alphain.data(), AlphaIn2.data(), AlphaIn2.size(), alphaout.data(), alphaout.size())[0].GetTensorData()[0]; } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: alphas\n") + e1.what()).c_str()); } try { DenoiseOut = DenoiseFn->Run(Ort::RunOptions{ nullptr }, denoiseInput.data(), DenoiseIn.data(), DenoiseIn.size(), denoiseOutput.data(), denoiseOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: denoise\n") + e1.what()).c_str()); } const auto x = DenoiseIn[0].GetTensorMutableData(); const auto noise_pred = DenoiseOut[0].GetTensorMutableData(); const auto noise_size = DenoiseOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto sq_aprev = sqrt(a_prev); const auto sq_at = sqrt(a_t); const auto np_m_op = (sqrt((1 - a_prev) / a_prev) - sqrt((1 - a_t) / a_t)); #ifndef MoeVoiceStudioAvxAcc for (size_t i = 0; i < noise_size; ++i) noise_pred[i] = (x[i] / sq_at + (sqrt((1 - a_prev) / a_prev) - sqrt((1 - a_t) / a_t)) * noise_pred[i]) * sq_aprev; #else InferTools::FloatTensorWrapper XWrapper(x, noise_size); InferTools::FloatTensorWrapper PredWrapper(noise_pred, noise_size); XWrapper /= sq_at; ((PredWrapper *= np_m_op) += XWrapper) *= sq_aprev; #endif DenoiseIn[0] = std::move(DenoiseOut[0]); _callback(++Process, 1); } std::vector out; out.emplace_back(std::move(DenoiseIn[0])); return out; } MoeVoiceStudioSamplerEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Sampler/MoeVSSamplers.hpp ================================================ /** * FileName: MoeVSSamplers.hpp * Note: MoeVoiceStudioCore Diffusion 官方采样器 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVSBaseSampler.hpp" MoeVoiceStudioSamplerHeader class PndmSampler : public MoeVSBaseSampler { public: PndmSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); ~PndmSampler() override = default; std::vector Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) override; private: const std::vector denoiseInput = { "noise", "time", "condition" }; const std::vector predInput = { "noise", "noise_pred", "time", "time_prev" }; const std::vector denoiseOutput = { "noise_pred" }; const std::vector predOutput = { "noise_pred_o" }; }; class DDimSampler : public MoeVSBaseSampler { public: DDimSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); ~DDimSampler() override = default; std::vector Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) override; private: const std::vector alphain = { "time" }; const std::vector alphaout = { "alphas_cumprod" }; const std::vector denoiseInput = { "noise", "time", "condition" }; const std::vector denoiseOutput = { "noise_pred" }; }; MoeVoiceStudioSamplerEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/Stft/stft.cpp ================================================ #include "stft.hpp" #include "../inferTools.hpp" #include "../../Logger/MoeSSLogger.hpp" #include "cblas.h" #ifdef max #undef max #endif #ifdef min #undef min #endif namespace DlCodecStft { void HannWindow(double* data, int size) { for (int i = 0; i < size; i++) { const double windowValue = 0.5 * (1 - cos(2 * STFT::PI * i / (size - 1))); data[i] *= windowValue; } } void ConvertDoubleToFloat(const std::vector& input, float* output) { for (size_t i = 0; i < input.size(); i++) { output[i] = static_cast(input[i]); } } double CalculatePowerSpectrum(fftw_complex fc) { return sqrt(fc[0] * fc[0] + fc[1] * fc[1]); } void CalculatePowerSpectrum(double* real, const double* imag, int size) { for (int i = 0; i < size; i++) { real[i] = real[i] * real[i] + imag[i] * imag[i]; } } void ConvertPowerSpectrumToDecibels(double* data, int size) { for (int i = 0; i < size; i++) { data[i] = 10 * log10(data[i]); } } double HZ2Mel(const double frequency) { constexpr auto f_min = 0.0; constexpr auto f_sp = 200.0 / 3; auto mel = (frequency - f_min) / f_sp; constexpr auto min_log_hz = 1000.0; constexpr auto min_log_mel = (min_log_hz - f_min) / f_sp; const auto logstep = log(6.4) / 27.0; if (frequency >= min_log_hz) mel = min_log_mel + log(frequency / min_log_hz) / logstep; return mel; } double Mel2HZ(const double mel) { constexpr auto f_min = 0.0; constexpr auto f_sp = 200.0 / 3; auto freqs = f_min + f_sp * mel; constexpr auto min_log_hz = 1000.0; constexpr auto min_log_mel = (min_log_hz - f_min) / f_sp; const auto logstep = log(6.4) / 27.0; if (mel >= min_log_mel) freqs = min_log_hz * exp(logstep * (mel - min_log_mel)); return freqs; } static double mel_min = HZ2Mel(20.); static double mel_max = HZ2Mel(11025.); STFT::STFT(int WindowSize, int HopSize, int FFTSize) { WINDOW_SIZE = WindowSize; HOP_SIZE = HopSize; if (FFTSize > 0) FFT_SIZE = FFTSize; else FFT_SIZE = WINDOW_SIZE / 2 + 1; } STFT::~STFT() = default; std::pair, int64_t> STFT::operator()(const std::vector& audioData) const { const int NUM_FRAMES = (int(audioData.size()) - WINDOW_SIZE) / HOP_SIZE + 1; std::vector hannWindow(WINDOW_SIZE, 0.0); const auto fftOut = reinterpret_cast(fftw_malloc(sizeof(fftw_complex) * FFT_SIZE)); const fftw_plan plan = fftw_plan_dft_r2c_1d(WINDOW_SIZE, hannWindow.data(), fftOut, FFTW_ESTIMATE); std::vector spectrogram(size_t(NUM_FRAMES) * FFT_SIZE, 0.f); for (int i = 0; i < NUM_FRAMES; i++) { std::memcpy(hannWindow.data(), &audioData[size_t(i) * HOP_SIZE], size_t(sizeof(double)) * WINDOW_SIZE); HannWindow(hannWindow.data(), WINDOW_SIZE); fftw_execute(plan); const auto BgnPtn = size_t(unsigned(i * FFT_SIZE)); for (int j = 0; j < FFT_SIZE; j++) spectrogram[BgnPtn + j] = float(CalculatePowerSpectrum(fftOut[j])); } fftw_destroy_plan(plan); fftw_free(fftOut); return { std::move(spectrogram), int64_t(NUM_FRAMES) }; } std::pair, int64_t> Mel::GetMel(const std::vector& audioData) const { auto BgnTime = clock(); const auto Spec = stft(audioData); //[frame, nfft] * [nfft, mel_bins] | [mel_bins, nfft] * [nfft, frame] logger.log(("[Inference] Slice Stft Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); const auto NFrames = Spec.second; std::vector Mel(MEL_SIZE * NFrames, 0.f); BgnTime = clock(); cblas_sgemm( CblasRowMajor, CblasNoTrans, CblasTrans, MEL_SIZE, blasint(NFrames), FFT_SIZE, 1.f, MelBasis.data(), FFT_SIZE, Spec.first.data(), blasint(FFT_SIZE), 0.f, Mel.data(), blasint(NFrames) ); for (auto& it : Mel) it = log(std::max(1e-5f, it)); logger.log(("[Inference] Slice Mel Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); return { std::move(Mel), (int64_t)NFrames }; } std::pair, int64_t> Mel::operator()(const std::vector& audioData) const { return GetMel(audioData); } Mel::Mel(int WindowSize, int HopSize, int SamplingRate, int MelSize) : stft(WindowSize, HopSize, WindowSize / 2 + 1) { if (MelSize > 0) MEL_SIZE = MelSize; FFT_SIZE = WindowSize / 2 + 1; sr = SamplingRate; const int nfft = (FFT_SIZE - 1) * 2; const double fftfreqval = 1. / (double(nfft) / double(SamplingRate)); auto fftfreqs = InferTools::arange(0, FFT_SIZE + 2); fftfreqs.resize(FFT_SIZE); for (auto& i : fftfreqs) i *= fftfreqval; auto mel_f = InferTools::arange(mel_min, mel_max + 1., (mel_max - mel_min) / (MEL_SIZE + 1)); mel_f.resize(MEL_SIZE + 2); //[MEL_SIZE + 2] std::vector fdiff; std::vector> ramps; //[MEL_SIZE + 2, FFTSize] ramps.reserve(MEL_SIZE + 2); for (auto& i : mel_f) { i = Mel2HZ(i); ramps.emplace_back(FFT_SIZE, i); } for (size_t i = 0; i < ramps.size(); ++i) for (int j = 0; j < FFT_SIZE; ++j) ramps[i][j] -= fftfreqs[j]; fdiff.reserve(MEL_SIZE + 2); //[MEL_SIZE + 1] for (size_t i = 1; i < mel_f.size(); ++i) fdiff.emplace_back(mel_f[i] - mel_f[i - 1]); MelBasis = std::vector(size_t(FFT_SIZE) * MelSize, 0.f); for (int i = 0; i < MelSize; ++i) { const auto enorm = 2. / (mel_f[i + 2] - mel_f[i]); for (int j = 0; j < FFT_SIZE; ++j) MelBasis[i * FFT_SIZE + j] = (float)(std::max(0., std::min(-ramps[i][j] / fdiff[i], ramps[i + 2][j] / fdiff[i + 1])) * enorm); } } } ================================================ FILE: libdlvoicecodec/Modules/InferTools/Stft/stft.hpp ================================================ #pragma once #include #include "fftw3.h" namespace DlCodecStft { class STFT { public: STFT() = default; ~STFT(); STFT(int WindowSize, int HopSize, int FFTSize = 0); inline static double PI = 3.14159265358979323846; std::pair, int64_t> operator()(const std::vector& audioData) const; private: int WINDOW_SIZE = 2048; int HOP_SIZE = WINDOW_SIZE / 4; int FFT_SIZE = WINDOW_SIZE / 2 + 1; }; class Mel { public: Mel() = delete; ~Mel() = default; Mel(int WindowSize, int HopSize, int SamplingRate, int MelSize = 0); std::pair, int64_t> GetMel(const std::vector& audioData) const; std::pair, int64_t> operator()(const std::vector& audioData) const; private: STFT stft; int MEL_SIZE = 128; int FFT_SIZE = 0; int sr = 22050; std::vector MelBasis; }; } ================================================ FILE: libdlvoicecodec/Modules/InferTools/TensorExtractor/MoeVSCoreTensorExtractor.cpp ================================================ #include "MoeVSCoreTensorExtractor.hpp" #include #include "../../Logger/MoeSSLogger.hpp" #include "../inferTools.hpp" MoeVoiceStudioTensorExtractorHeader MoeVoiceStudioTensorExtractor::Inputs SoVits2TensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, HubertLen }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; // SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.Length[0] = HubertLen; SvcTensors.Data.F0 = InferTools::InterpFunc(F0, (long)F0.size(), (long)HubertLen); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.NSFF0 = GetNSFF0(SvcTensors.Data.F0); SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Length, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.NSFF0.data(), SvcTensors.Data.NSFF0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs SoVits3TensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; // SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; const int64_t upSample = int64_t(_SamplingRate) / 16000; const auto srcHubertSize = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.HiddenUnitShape[1] *= upSample; HubertSize *= upSample; SvcTensors.Data.FrameShape[1] = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.HiddenUnit.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < srcHubertSize; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) SvcTensors.Data.HiddenUnit.insert(SvcTensors.Data.HiddenUnit.end(), HiddenUnit.begin() + itS * (int64_t)_HiddenSize, HiddenUnit.begin() + (itS + 1) * (int64_t)_HiddenSize); SvcTensors.Data.F0 = GetInterpedF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.HiddenUnitShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Data.Length[0] = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Length, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs SoVits4TensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; std::mt19937 gen(int(params.Seed)); std::normal_distribution normal(0, 1); const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.NoiseShape = { 1, 192, SvcTensors.Data.FrameShape[1] }; const auto NoiseSize = SvcTensors.Data.NoiseShape[1] * SvcTensors.Data.NoiseShape[2] * SvcTensors.Data.NoiseShape[0]; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.F0 = GetInterpedF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.FrameShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.UnVoice = GetUV(F0); SvcTensors.Data.Noise = std::vector(NoiseSize, 0.f); for (auto& it : SvcTensors.Data.Noise) it = normal(gen) * params.NoiseScale; SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Alignment.data(), SvcTensors.Data.Alignment.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.UnVoice.data(), SvcTensors.Data.UnVoice.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Noise.data(), SvcTensors.Data.Noise.size(), SvcTensors.Data.NoiseShape.data(), 3 )); if (_SpeakerMix) { SvcTensors.Data.SpkMap = GetCurrectSpkMixData(SpkMap, SvcTensors.Data.FrameShape[1], params.Chara); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.SpkMap.data(), SvcTensors.Data.SpkMap.size(), SvcTensors.Data.SpkShape.data(), 2 )); } else { SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); } if (_Volume) { SvcTensors.InputNames = InputNamesVol.data(); SvcTensors.Data.Volume = InferTools::InterpFunc(Volume, long(Volume.size()), long(SvcTensors.Data.FrameShape[1])); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Volume.data(), SvcTensors.Data.FrameShape[1], SvcTensors.Data.FrameShape.data(), 2 )); } else SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs SoVits4DDSPTensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; std::mt19937 gen(int(params.Seed)); std::normal_distribution normal(0, 1); const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.NoiseShape = { 1, 192, SvcTensors.Data.FrameShape[1] }; const auto NoiseSize = SvcTensors.Data.NoiseShape[1] * SvcTensors.Data.NoiseShape[2] * SvcTensors.Data.NoiseShape[0]; SvcTensors.Data.DDSPNoiseShape = { 1, 2048, SvcTensors.Data.FrameShape[1] }; const int64_t IstftCount = SvcTensors.Data.FrameShape[1] * 2048; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.F0 = GetInterpedF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.FrameShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.DDSPNoise = std::vector(IstftCount, params.DDSPNoiseScale); SvcTensors.Data.Noise = std::vector(NoiseSize, 0.f); for (auto& it : SvcTensors.Data.Noise) it = normal(gen) * params.NoiseScale; SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Alignment.data(), SvcTensors.Data.Alignment.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.DDSPNoise.data(), SvcTensors.Data.DDSPNoise.size(), SvcTensors.Data.DDSPNoiseShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Noise.data(), SvcTensors.Data.Noise.size(), SvcTensors.Data.NoiseShape.data(), 3 )); if (_SpeakerMix) { SvcTensors.Data.SpkMap = GetCurrectSpkMixData(SpkMap, SvcTensors.Data.FrameShape[1], params.Chara); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.SpkMap.data(), SvcTensors.Data.SpkMap.size(), SvcTensors.Data.SpkShape.data(), 2 )); } else { SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); } if (_Volume) { SvcTensors.InputNames = InputNamesVol.data(); SvcTensors.Data.Volume = InferTools::InterpFunc(Volume, long(Volume.size()), long(SvcTensors.Data.FrameShape[1])); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Volume.data(), SvcTensors.Data.FrameShape[1], SvcTensors.Data.FrameShape.data(), 2 )); } else SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs RVCTensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; std::mt19937 gen(int(params.Seed)); std::normal_distribution normal(0, 1); auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; constexpr int64_t upSample = 2; const auto srcHubertSize = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.HiddenUnitShape[1] *= upSample; HubertSize *= upSample; SvcTensors.Data.FrameShape[1] = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.NoiseShape = { 1, 192, SvcTensors.Data.FrameShape[1] }; const auto NoiseSize = SvcTensors.Data.NoiseShape[1] * SvcTensors.Data.NoiseShape[2] * SvcTensors.Data.NoiseShape[0]; SvcTensors.Data.HiddenUnit.reserve(HubertSize); for (int64_t itS = 0; itS < srcHubertSize; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) SvcTensors.Data.HiddenUnit.insert(SvcTensors.Data.HiddenUnit.end(), HiddenUnit.begin() + itS * (int64_t)_HiddenSize, HiddenUnit.begin() + (itS + 1) * (int64_t)_HiddenSize); SvcTensors.Data.Length[0] = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.F0 = GetInterpedF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.HiddenUnitShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.NSFF0 = GetNSFF0(SvcTensors.Data.F0); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.Noise = std::vector(NoiseSize, 0.f); for (auto& it : SvcTensors.Data.Noise) it = normal(gen) * params.NoiseScale; SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Length, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.NSFF0.data(), SvcTensors.Data.NSFF0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); if (_SpeakerMix) { SvcTensors.Data.SpkMap = GetCurrectSpkMixData(SpkMap, SvcTensors.Data.FrameShape[1], params.Chara); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.SpkMap.data(), SvcTensors.Data.SpkMap.size(), SvcTensors.Data.SpkShape.data(), 2 )); } else { SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); } SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Noise.data(), SvcTensors.Data.Noise.size(), SvcTensors.Data.NoiseShape.data(), 3 )); if (_Volume) { SvcTensors.InputNames = InputNamesVol.data(); SvcTensors.Data.Volume = InferTools::InterpFunc(Volume, long(Volume.size()), long(SvcTensors.Data.FrameShape[1])); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Volume.data(), SvcTensors.Data.FrameShape[1], SvcTensors.Data.FrameShape.data(), 2 )); } else SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs DiffSvcTensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.F0 = InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.FrameShape[1])); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.F0 = GetInterpedF0log(SvcTensors.Data.F0, true); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Alignment.data(), SvcTensors.Data.Alignment.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.InputNames = InputNames.data(); SvcTensors.OutputNames = OutputNames.data(); SvcTensors.OutputCount = OutputNames.size(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs DiffusionSvcTensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.F0 = InterpUVF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.FrameShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Alignment.data(), SvcTensors.Data.Alignment.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); if (_Volume) { SvcTensors.InputNames = InputNamesVol.data(); SvcTensors.Data.Volume = InferTools::InterpFunc(Volume, long(Volume.size()), long(SvcTensors.Data.FrameShape[1])); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Volume.data(), SvcTensors.Data.FrameShape[1], SvcTensors.Data.FrameShape.data(), 2 )); } else SvcTensors.InputNames = InputNames.data(); if (_SpeakerMix) { SvcTensors.Data.SpkMap = GetCurrectSpkMixData(SpkMap, SvcTensors.Data.FrameShape[1], params.Chara); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.SpkMap.data(), SvcTensors.Data.SpkMap.size(), SvcTensors.Data.SpkShape.data(), 2 )); } else { SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); } SvcTensors.OutputNames = OutputNames.data(); SvcTensors.OutputCount = OutputNames.size(); return SvcTensors; } MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/TensorExtractor/MoeVSCoreTensorExtractor.hpp ================================================ /** * FileName: MoeVSCoreTensorExtractor.hpp * Note: MoeVoiceStudioCore 官方张量预处理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVoiceStudioTensorExtractor.hpp" MoeVoiceStudioTensorExtractorHeader class SoVits2TensorExtractor : public MoeVoiceStudioTensorExtractor { public: SoVits2TensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~SoVits2TensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "hidden_unit", "lengths", "pitch", "sid" }; }; class SoVits3TensorExtractor : public MoeVoiceStudioTensorExtractor { public: SoVits3TensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~SoVits3TensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "hidden_unit", "lengths", "pitch", "sid" }; }; class SoVits4TensorExtractor : public MoeVoiceStudioTensorExtractor { public: SoVits4TensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~SoVits4TensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "c", "f0", "mel2ph", "uv", "noise", "sid" }; const std::vector InputNamesVol = { "c", "f0", "mel2ph", "uv", "noise", "sid", "vol" }; }; class SoVits4DDSPTensorExtractor : public MoeVoiceStudioTensorExtractor { public: SoVits4DDSPTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~SoVits4DDSPTensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "c", "f0", "mel2ph", "t_window", "noise", "sid" }; const std::vector InputNamesVol = { "c", "f0", "mel2ph", "t_window", "noise", "sid", "vol" }; }; class RVCTensorExtractor : public MoeVoiceStudioTensorExtractor { public: RVCTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~RVCTensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd" }; const std::vector InputNamesVol = { "phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd", "vol" }; }; class DiffSvcTensorExtractor : public MoeVoiceStudioTensorExtractor { public: DiffSvcTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~DiffSvcTensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "hubert", "mel2ph", "spk_embed", "f0" }; const std::vector OutputNames = { "mel_pred", "f0_pred" }; }; class DiffusionSvcTensorExtractor : public MoeVoiceStudioTensorExtractor { public: DiffusionSvcTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~DiffusionSvcTensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNamesVol = { "hubert", "mel2ph", "f0", "volume", "spk_mix" }; const std::vector InputNames = { "hubert", "mel2ph", "f0", "spk_mix" }; const std::vector OutputNames = { "mel_pred" }; }; MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/TensorExtractor/MoeVoiceStudioTensorExtractor.cpp ================================================ #include "MoeVoiceStudioTensorExtractor.hpp" #include "../inferTools.hpp" MoeVoiceStudioTensorExtractorHeader MoeVoiceStudioTensorExtractor::MoeVoiceStudioTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) { _SrcSamplingRate = _srcsr; _SamplingRate = _sr; _HopSize = _hop; _SpeakerMix = _smix; _Volume = _volume; _HiddenSize = _hidden_size; _NSpeaker = _nspeaker; f0_bin = _other.f0_bin; f0_max = _other.f0_max; f0_min = _other.f0_min; f0_mel_min = 1127.f * log(1.f + f0_min / 700.f); f0_mel_max = 1127.f * log(1.f + f0_max / 700.f); Memory = _other.Memory; } MoeVoiceStudioTensorExtractor::Inputs MoeVoiceStudioTensorExtractor::Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) { LibDLVoiceCodecThrow("NotImplementedError"); } std::vector MoeVoiceStudioTensorExtractor::GetCurrectSpkMixData(const std::vector>& _input, size_t dst_len, int64_t curspk) const { std::vector mixData; mixData.reserve(_NSpeaker * dst_len); if(_input.empty()) { std::vector LenData(_NSpeaker, 0.0); LenData[curspk] = 1.0; for (size_t i = 0; i < dst_len; ++i) mixData.insert(mixData.end(), LenData.begin(), LenData.end()); } else { std::vector> _spkMap; for (size_t i = 0; i < _input.size() && i < _NSpeaker; ++i) _spkMap.emplace_back(InferTools::InterpFunc(_input[i], long(_input[i].size()), long(dst_len))); LinearCombination(_spkMap, curspk); const auto curnspk = _input.size(); if (curnspk < _NSpeaker) { std::vector LenData(_NSpeaker - curnspk, 0.0); for (size_t i = 0; i < dst_len; ++i) { for (size_t j = 0; j < curnspk; ++j) mixData.emplace_back(_spkMap[j][i]); mixData.insert(mixData.end(), LenData.begin(), LenData.end()); } } else for (size_t i = 0; i < dst_len; ++i) for (size_t j = 0; j < _NSpeaker; ++j) mixData.emplace_back(_spkMap[j][i]); } return mixData; } std::vector MoeVoiceStudioTensorExtractor::GetSpkMixData(const std::vector>& _input, size_t dst_len, size_t spk_count) { std::vector mixData; mixData.reserve(spk_count * dst_len); if (_input.empty()) { std::vector LenData(spk_count, 0.0); LenData[0] = 1.0; for (size_t i = 0; i < dst_len; ++i) mixData.insert(mixData.end(), LenData.begin(), LenData.end()); } else { std::vector> _spkMap; for (size_t i = 0; i < _input.size() && i < spk_count; ++i) _spkMap.emplace_back(InferTools::InterpFunc(_input[i], long(_input[i].size()), long(dst_len))); LinearCombination(_spkMap, 0); const auto curnspk = _input.size(); if (curnspk < spk_count) { std::vector LenData(spk_count - curnspk, 0.0); for (size_t i = 0; i < dst_len; ++i) { for (size_t j = 0; j < curnspk; ++j) mixData.emplace_back(_spkMap[j][i]); mixData.insert(mixData.end(), LenData.begin(), LenData.end()); } } else for (size_t i = 0; i < dst_len; ++i) for (size_t j = 0; j < spk_count; ++j) mixData.emplace_back(_spkMap[j][i]); } return mixData; } std::vector MoeVoiceStudioTensorExtractor::GetNSFF0(const std::vector& F0) const { const auto f0Len = F0.size(); std::vector NSFF0(f0Len); for (size_t i = 0; i < f0Len; ++i) { float f0_mel = 1127.f * log(1.f + F0[i] / 700.f); if (f0_mel > 0.f) f0_mel = (f0_mel - f0_mel_min) * (float(f0_bin) - 2.f) / (f0_mel_max - f0_mel_min) + 1.f; if (f0_mel < 1.f) f0_mel = 1.f; if (f0_mel > float(f0_bin) - 1.f) f0_mel = float(f0_bin) - 1.f; NSFF0[i] = (int64_t)round(f0_mel); } return NSFF0; } std::vector MoeVoiceStudioTensorExtractor::GetInterpedF0(const std::vector& F0) { const auto specLen = F0.size(); std::vector Of0(specLen, 0.0); float last_value = 0.0; for (size_t i = 0; i < specLen; ++i) { if (F0[i] <= 0.f) { size_t j = i + 1; for (; j < specLen; ++j) { if (F0[j] > 0.f) break; } if (j < specLen - 1) { if (last_value > 0.f) { const auto step = (F0[j] - F0[i - 1]) / float(j - i); for (size_t k = i; k < j; ++k) Of0[k] = float(F0[i - 1] + step * float(k - i + 1)); } else for (size_t k = i; k < j; ++k) Of0[k] = float(F0[j]); i = j; } else { for (size_t k = i; k < specLen; ++k) Of0[k] = float(last_value); i = specLen; } } else { if (i == 0) { Of0[i] = float(F0[i]); continue; } Of0[i] = float(F0[i - 1]); last_value = F0[i]; } } return Of0; } std::vector MoeVoiceStudioTensorExtractor::InterpUVF0(const std::vector& F0) { std::vector NUVF0; std::vector UVF0Indices, NUVF0Indices; UVF0Indices.reserve(F0.size()); NUVF0.reserve(F0.size()); NUVF0Indices.reserve(F0.size()); if(F0[0] < 0.0001f) { NUVF0.emplace_back(0); NUVF0Indices.emplace_back(0); } for (size_t i = 1; i < F0.size(); ++i) { if (F0[i] < 0.0001f) UVF0Indices.emplace_back((double)i); else { NUVF0.emplace_back((double)F0[i]); NUVF0Indices.emplace_back((double)i); } } if (UVF0Indices.empty() || NUVF0Indices.empty()) return F0; std::vector UVF0(F0.size()); std::vector Of0 = F0; interp1(NUVF0Indices.data(), NUVF0.data(), (int)NUVF0.size(), UVF0Indices.data(), (int)UVF0Indices.size(), UVF0.data()); for (size_t i = 0; i < UVF0Indices.size(); ++i) Of0[size_t(UVF0Indices[i])] = (float)UVF0[i]; return Of0; } std::vector MoeVoiceStudioTensorExtractor::GetUV(const std::vector& F0) { const auto specLen = F0.size(); std::vector ruv(specLen, 1.0); for (size_t i = 0; i < specLen; ++i) { if (F0[i] < 0.001f) ruv[i] = 0.f; } return ruv; } std::vector MoeVoiceStudioTensorExtractor::GetAligments(size_t specLen, size_t hubertLen) { std::vector mel2ph(specLen + 1, 0); size_t startFrame = 0; const double ph_durs = static_cast(specLen) / static_cast(hubertLen); for (size_t iph = 0; iph < hubertLen; ++iph) { const auto endFrame = static_cast(round(static_cast(iph) * ph_durs + ph_durs)); for (auto j = startFrame; j < endFrame + 1; ++j) mel2ph[j] = static_cast(iph) + 1; startFrame = endFrame + 1; } return mel2ph; } std::vector MoeVoiceStudioTensorExtractor::GetInterpedF0log(const std::vector& rF0, bool enable_log) { const auto specLen = rF0.size(); std::vector F0(specLen); std::vector Of0(specLen, 0.0); for (size_t i = 0; i < specLen; ++i) { if (enable_log) F0[i] = log2(rF0[i]); else F0[i] = rF0[i]; if (isnan(F0[i]) || isinf(F0[i])) F0[i] = 0.f; } float last_value = 0.0; for (size_t i = 0; i < specLen; ++i) { if (F0[i] <= 0.f) { size_t j = i + 1; for (; j < specLen; ++j) { if (F0[j] > 0.f) break; } if (j < specLen - 1) { if (last_value > 0.f) { const auto step = (F0[j] - F0[i - 1]) / float(j - i); for (size_t k = i; k < j; ++k) Of0[k] = float(F0[i - 1] + step * float(k - i + 1)); } else for (size_t k = i; k < j; ++k) Of0[k] = float(F0[j]); i = j; } else { for (size_t k = i; k < specLen; ++k) Of0[k] = float(last_value); i = specLen; } } else { Of0[i] = float(F0[i - 1]); last_value = F0[i]; } } return Of0; } MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/TensorExtractor/MoeVoiceStudioTensorExtractor.hpp ================================================ /** * FileName: MoeVoiceStudioTensorExtractor.hpp * Note: MoeVoiceStudioCore 张量预处理基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include "onnxruntime_cxx_api.h" #define MoeVoiceStudioTensorExtractorHeader namespace MoeVSTensorPreprocess{ #define MoeVoiceStudioTensorExtractorEnd } MoeVoiceStudioTensorExtractorHeader class MoeVoiceStudioTensorExtractor { public: struct Tensors { std::vector HiddenUnit; std::vector F0; std::vector Volume; std::vector SpkMap; std::vector DDSPNoise; std::vector Noise; std::vector Alignment; std::vector UnVoice; std::vector NSFF0; int64_t Length[1] = { 0 }; int64_t Speaker[1] = { 0 }; std::vector HiddenUnitShape; std::vector FrameShape; std::vector SpkShape; std::vector DDSPNoiseShape; std::vector NoiseShape; int64_t OneShape[1] = { 1 }; }; struct InferParams { float NoiseScale = 0.3f; float DDSPNoiseScale = 1.0f; int Seed = 520468; size_t AudioSize = 0; int64_t Chara = 0; float upKeys = 0.f; void* Other = nullptr; }; struct Others { int f0_bin = 256; float f0_max = 1100.0; float f0_min = 50.0; OrtMemoryInfo* Memory = nullptr; void* Other = nullptr; }; using Params = const InferParams&; struct Inputs { Tensors Data; std::vector Tensor; const char* const* InputNames = nullptr; const char* const* OutputNames = nullptr; size_t InputCount = 1; size_t OutputCount = 1; }; /** * \brief 构造张量预处理器 * \param _srcsr 原始采样率 * \param _sr 目标采样率 * \param _hop HopSize * \param _smix 是否启用角色混合 * \param _volume 是否启用音量emb * \param _hidden_size hubert的维数 * \param _nspeaker 角色数 * \param _other 其他参数,其中的memoryInfo必须为你当前模型的memoryInfo */ MoeVoiceStudioTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other); virtual ~MoeVoiceStudioTensorExtractor() = default; /** * \brief 预处理张量 * \param HiddenUnit HiddenUnit * \param F0 F0 * \param Volume 音量 * \param SpkMap 角色混合数据 * \param params 参数 * \return 完成预处理的张量(请将张量接管的所有Vector的数据都存储到Tensors Data中,因为ORT创建的张量要求调用方管理内存,如果不存储到这个位置会导致数据提前析构 */ virtual Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ); void SetSrcSamplingRates(uint64_t sr) { _SrcSamplingRate = sr; } //获取换算为0-255的f0 [[nodiscard]] std::vector GetNSFF0(const std::vector&) const; //将F0中0值单独插值 static std::vector GetInterpedF0(const std::vector&); // static std::vector InterpUVF0(const std::vector&); //获取UnVoiceMask static std::vector GetUV(const std::vector&); //获取对齐矩阵 static std::vector GetAligments(size_t, size_t); //线性组合 template static void LinearCombination(std::vector>& _data, size_t default_id, T Value = T(1.0)) { if (_data.empty()) return; if (default_id > _data.size()) default_id = 0; for (size_t i = 0; i < _data[0].size(); ++i) { T Sum = T(0.0); for (size_t j = 0; j < _data.size(); ++j) Sum += _data[j][i]; if (Sum < T(0.0001)) { for (size_t j = 0; j < _data.size(); ++j) _data[j][i] = T(0); _data[default_id][i] = T(1); continue; } Sum *= T(Value); for (size_t j = 0; j < _data.size(); ++j) _data[j][i] /= Sum; } } //将F0中0值单独插值(可设置是否取log) [[nodiscard]] static std::vector GetInterpedF0log(const std::vector&, bool); //获取正确的角色混合数据 [[nodiscard]] std::vector GetCurrectSpkMixData(const std::vector>& _input, size_t dst_len, int64_t curspk) const; //获取正确的角色混合数据 [[nodiscard]] static std::vector GetSpkMixData(const std::vector>& _input, size_t dst_len, size_t spk_count); protected: uint64_t _NSpeaker = 1; uint64_t _SrcSamplingRate = 32000; uint64_t _SamplingRate = 32000; uint64_t _HopSize = 512; bool _SpeakerMix = false; bool _Volume = false; uint64_t _HiddenSize = 256; int f0_bin = 256; float f0_max = 1100.0; float f0_min = 50.0; float f0_mel_min = 1127.f * log(1.f + f0_min / 700.f); float f0_mel_max = 1127.f * log(1.f + f0_max / 700.f); OrtMemoryInfo* Memory = nullptr; private: std::wstring __NAME__CLASS__ = L"MoeVoiceStudioTensorExtractor"; }; MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/TensorExtractor/TensorExtractorManager.cpp ================================================ #include "TensorExtractorManager.hpp" #include #include "../../Logger/MoeSSLogger.hpp" MoeVoiceStudioTensorExtractorHeader inline std::map RegisteredTensorExtractors; void RegisterTensorExtractor(const std::wstring& _name, const GetTensorExtractorFn& _constructor_fn) { if (RegisteredTensorExtractors.find(_name) != RegisteredTensorExtractors.end()) { logger.log(L"[Warn] TensorExtractorNameConflict"); return; } RegisteredTensorExtractors[_name] = _constructor_fn; } TensorExtractor GetTensorExtractor(const std::wstring& _name, uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const MoeVoiceStudioTensorExtractor::Others& _other) { const auto f_TensorExtractor = RegisteredTensorExtractors.find(_name); if (f_TensorExtractor != RegisteredTensorExtractors.end()) return f_TensorExtractor->second(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other); throw std::runtime_error("Unable To Find An Available TensorExtractor"); } MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/TensorExtractor/TensorExtractorManager.hpp ================================================ /** * FileName: TensorExtractorManager.hpp * Note: MoeVoiceStudioCore 张量预处理类的注册和管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include "MoeVoiceStudioTensorExtractor.hpp" MoeVoiceStudioTensorExtractorHeader class TensorExtractor { public: TensorExtractor() = default; TensorExtractor(MoeVoiceStudioTensorExtractor* _ext) : _f0_ext(_ext) {} TensorExtractor(const TensorExtractor&) = delete; TensorExtractor(TensorExtractor&& _ext) noexcept { delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; } TensorExtractor& operator=(const TensorExtractor&) = delete; TensorExtractor& operator=(TensorExtractor&& _ext) noexcept { if (this == &_ext) return *this; delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; return *this; } ~TensorExtractor() { delete _f0_ext; _f0_ext = nullptr; } MoeVoiceStudioTensorExtractor* operator->() const { return _f0_ext; } private: MoeVoiceStudioTensorExtractor* _f0_ext = nullptr; }; using GetTensorExtractorFn = std::function; void RegisterTensorExtractor(const std::wstring& _name, const GetTensorExtractorFn& _constructor_fn); /** * \brief 获取张量预处理器 * \param _name 类名 * \param _srcsr 原始采样率 * \param _sr 目标采样率 * \param _hop HopSize * \param _smix 是否启用角色混合 * \param _volume 是否启用音量emb * \param _hidden_size hubert的维数 * \param _nspeaker 角色数 * \param _other 其他参数,其中的memoryInfo必须为你当前模型的memoryInfo * \return 张量预处理器 */ TensorExtractor GetTensorExtractor( const std::wstring& _name, uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const MoeVoiceStudioTensorExtractor::Others& _other ); MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libdlvoicecodec/Modules/InferTools/inferTools.cpp ================================================ #include "inferTools.hpp" #include "string" #ifdef MoeVoiceStudioAvxAcc #include #endif InferTools::Wav::Wav(const wchar_t* Path) :header(WAV_HEADER()) { char buf[1024]; FILE* stream; _wfreopen_s(&stream, Path, L"rb", stderr); if (stream == nullptr) { throw (std::exception("File not exists")); } fread(buf, 1, HEAD_LENGTH, stream); int pos = 0; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'R') && (buf[pos + 1] == 'I') && (buf[pos + 2] == 'F') && (buf[pos + 3] == 'F')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.ChunkSize = *(int*)&buf[pos]; pos += 8; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'f') && (buf[pos + 1] == 'm') && (buf[pos + 2] == 't')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk1Size = *(int*)&buf[pos]; pos += 4; header.AudioFormat = *(short*)&buf[pos]; pos += 2; header.NumOfChan = *(short*)&buf[pos]; pos += 2; header.SamplesPerSec = *(int*)&buf[pos]; pos += 4; header.bytesPerSec = *(int*)&buf[pos]; pos += 4; header.blockAlign = *(short*)&buf[pos]; pos += 2; header.bitsPerSample = *(short*)&buf[pos]; pos += 2; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'd') && (buf[pos + 1] == 'a') && (buf[pos + 2] == 't') && (buf[pos + 3] == 'a')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk2Size = *(int*)&buf[pos]; pos += 4; StartPos = pos; Data = new char[header.Subchunk2Size + 1]; fseek(stream, StartPos, SEEK_SET); fread(Data, 1, header.Subchunk2Size, stream); if (stream != nullptr) { fclose(stream); } SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav::Wav(const Wav& input) :header(WAV_HEADER()) { Data = new char[(input.header.Subchunk2Size + 1)]; if (Data == nullptr) { LibDLVoiceCodecThrow("OOM") } memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; memcpy(Data, input.Data, input.header.Subchunk2Size); SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav::Wav(Wav&& input) noexcept { Data = input.Data; input.Data = nullptr; memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav& InferTools::Wav::operator=(Wav&& input) noexcept { destory(); Data = input.Data; input.Data = nullptr; memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; return *this; } InferTools::Wav& InferTools::Wav::cat(const Wav& input) { if (header.AudioFormat != 1) return *this; if (header.SamplesPerSec != input.header.bitsPerSample || header.NumOfChan != input.header.NumOfChan) return *this; char* buffer = new char[(int64_t)header.Subchunk2Size + (int64_t)input.header.Subchunk2Size + 1]; if (buffer == nullptr)return *this; memcpy(buffer, Data, header.Subchunk2Size); memcpy(buffer + header.Subchunk2Size, input.Data, input.header.Subchunk2Size); header.ChunkSize += input.header.Subchunk2Size; header.Subchunk2Size += input.header.Subchunk2Size; delete[] Data; Data = buffer; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; return *this; } std::vector InferTools::SliceAudio(const std::vector& input, const SlicerSettings& _slicer) { if (input.size() < size_t(_slicer.MinLength) * _slicer.SamplingRate) return {0, input.size()}; std::vector slice_point; bool slice_tag = true; slice_point.emplace_back(0); unsigned long CurLength = 0; for (size_t i = 0; i + _slicer.WindowLength < input.size(); i += _slicer.HopSize) { if (slice_tag) { const auto vol = abs(getAvg(input.data() + i, input.data() + i + _slicer.WindowLength)); if (vol < _slicer.Threshold) { slice_tag = false; if (CurLength > _slicer.MinLength * _slicer.SamplingRate) { CurLength = 0; slice_point.emplace_back(i + (_slicer.WindowLength / 2)); } } else slice_tag = true; } else { const auto vol = abs(getAvg(input.data() + i, input.data() + i + _slicer.WindowLength)); if (vol < _slicer.Threshold) slice_tag = false; else { slice_tag = true; if (CurLength > _slicer.MinLength * _slicer.SamplingRate) { CurLength = 0; slice_point.emplace_back(i + (_slicer.WindowLength / 2)); } } } CurLength += _slicer.HopSize; } slice_point.push_back(input.size()); return slice_point; } std::vector InferTools::arange(double start, double end, double step, double div) { std::vector output; while (start < end) { output.push_back(start / div); start += step; } return output; } std::vector InferTools::mean_filter(const std::vector& vec, size_t window_size) { std::vector result; if (window_size > vec.size() || window_size < 2) return vec; const size_t half = window_size / 2; // 窗口半径,向下取整 for (size_t i = half; i < vec.size() - half; i++) { float sum = 0.0f; for (size_t j = i - half; j <= i + half; j++) { sum += vec[j]; } result.push_back(sum / (float)(window_size % 2 ? window_size : window_size + 1)); } return result; } #ifdef MoeVoiceStudioAvxAcc InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator+=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_add_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] += _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator-=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_sub_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] -= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator*=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_mul_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] *= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator/=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_div_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] /= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator+=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_add_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] += _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator-=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_sub_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] -= _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator*=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_mul_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] *= _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator/=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_div_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] /= _right; return *this; } #endif ================================================ FILE: libdlvoicecodec/Modules/InferTools/inferTools.hpp ================================================ /** * FileName: InferTools.hpp * Note: MoeVoiceStudioCore 推理工具的定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include #include #include #include #define MOEVSINFERTOOLSHEADER namespace InferTools { #define MOEVSINFERTOOLSEND } #define LibDLVoiceCodecThrow(message) { \ const std::string LibDlCodecThrowMessage = message;\ const std::string LibDlCodecThrowMessagePrefix = std::string("[In \"") + std::filesystem::path(__FILE__).filename().string() + "\" Line " + std::to_string(__LINE__) + "] "; \ if(LibDlCodecThrowMessage.substr(0, LibDlCodecThrowMessagePrefix.length()) != LibDlCodecThrowMessagePrefix) \ throw std::exception((LibDlCodecThrowMessagePrefix + LibDlCodecThrowMessage).c_str()); \ else \ throw std::exception(LibDlCodecThrowMessage.c_str()); \ } MOEVSINFERTOOLSHEADER struct SlicerSettings { int32_t SamplingRate = 48000; double Threshold = 30.; double MinLength = 3.; int32_t WindowLength = 2048; int32_t HopSize = 512; }; class Wav { public: static constexpr int HEAD_LENGTH = 1024; struct WAV_HEADER { char RIFF[4] = { 'R','I','F','F' }; unsigned long ChunkSize; char WAVE[4] = { 'W','A','V','E' }; char fmt[4] = { 'f','m','t',' ' }; unsigned long Subchunk1Size; unsigned short AudioFormat; unsigned short NumOfChan; unsigned long SamplesPerSec; unsigned long bytesPerSec; unsigned short blockAlign; unsigned short bitsPerSample; char Subchunk2ID[4] = { 'd','a','t','a' }; unsigned long Subchunk2Size; WAV_HEADER(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1, unsigned long sr = 22050, unsigned long bps = 44100, unsigned short ba = 2, unsigned short bips = 16, unsigned long sc2s = 0) :ChunkSize(cs), Subchunk1Size(sc1s), AudioFormat(af), NumOfChan(nc), SamplesPerSec(sr), bytesPerSec(bps), blockAlign(ba), bitsPerSample(bips), Subchunk2Size(sc2s) {} }; using iterator = int16_t*; Wav(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1, unsigned long sr = 22050, unsigned long bps = 44100, unsigned short ba = 2, unsigned short bips = 16, unsigned long sc2s = 0) :header({ cs, sc1s, af, nc, sr, bps, ba, bips, sc2s }), Data(nullptr), StartPos(44) { dataSize = 0; SData = nullptr; } Wav(unsigned long sr, unsigned long length, const void* data) :header({ 36, 16, 1, 1, sr, sr * 2, 2, 16, length }), Data(new char[length + 1]), StartPos(44) { header.ChunkSize = 36 + length; memcpy(Data, data, length); SData = reinterpret_cast(Data); dataSize = length / 2; } Wav(const wchar_t* Path); Wav(const Wav& input); Wav(Wav&& input) noexcept; Wav& operator=(const Wav& input) = delete; Wav& operator=(Wav&& input) noexcept; ~Wav() { destory(); } Wav& cat(const Wav& input); [[nodiscard]] bool isEmpty() const { return this->header.Subchunk2Size == 0; } [[nodiscard]] const char* getData() const { return Data; } char* getData() { return Data; } [[nodiscard]] WAV_HEADER getHeader() const { return header; } WAV_HEADER& Header() { return header; } void destory() const { delete[] Data; } void changeData(const void* indata, long length, int sr) { delete[] Data; Data = new char[length]; memcpy(Data, indata, length); header.ChunkSize = 36 + length; header.Subchunk2Size = length; header.SamplesPerSec = sr; header.bytesPerSec = 2 * sr; } int16_t& operator[](const size_t index) const { if (index < dataSize) return *(SData + index); return *(SData + dataSize - 1); } [[nodiscard]] iterator begin() const { return reinterpret_cast(Data); } [[nodiscard]] iterator end() const { return reinterpret_cast(Data + header.Subchunk2Size); } [[nodiscard]] int64_t getDataLen()const { return static_cast(dataSize); } void Writef(const std::wstring& filepath) const { FILE* FOut = nullptr; _wfopen_s(&FOut, filepath.c_str(), L"wb"); if (!FOut) return; fwrite(&header, 1, sizeof(header), FOut); fwrite(Data, 1, dataSize * 2, FOut); fclose(FOut); FOut = nullptr; } static void WritePCMData(int samplingrate, int channel, const std::vector& PCMDATA, const std::wstring& filepath) { const WAV_HEADER TmpHeader(long(36 + 2 * PCMDATA.size()), 16, 1, short(channel), samplingrate, samplingrate * 2 * channel, short(2 * channel), short(16), long(2 * PCMDATA.size())); FILE* FOut = nullptr; _wfopen_s(&FOut, filepath.c_str(), L"wb"); if (!FOut) return; fwrite(&TmpHeader, 1, sizeof(TmpHeader), FOut); fwrite(PCMDATA.data(), 1, PCMDATA.size() * 2, FOut); fclose(FOut); FOut = nullptr; } private: WAV_HEADER header; char* Data; int16_t* SData; size_t dataSize; int StartPos; }; /** * \brief 切片机切片(获取切片位置) * \param input PCM数据(SignedInt16) * \param _slicer 切片机设置 * \return 切片位置 */ std::vector SliceAudio(const std::vector& input, const SlicerSettings& _slicer); /** * \brief 均值滤波器 * \param vec 待滤波的数据 * \param window_size 窗口大小 * \return 滤波后数据 */ std::vector mean_filter(const std::vector& vec, size_t window_size); template double getAvg(const T* start, const T* end) { const auto size = end - start + 1; auto avg = (double)(*start); for (auto i = 1; i < size; i++) avg = avg + (abs((double)start[i]) - avg) / (double)(i + 1ull); return avg; } std::vector arange(double start, double end, double step = 1.0, double div = 1.0); /** * \brief 重采样(插值) * \tparam TOut 输出类型 * \tparam TIn 输入类型 * \param _Data 输入数据 * \param src 输入采样率 * \param dst 输出采样率 * \param n_Div 给输出的数据统一除以这个数 * \return 输出数据 */ template static std::vector InterpResample(const std::vector& _Data, long src, long dst, TOut n_Div = TOut(1)) { if (src != dst) { const double intstep = double(src) / double(dst); const auto xi = InferTools::arange(0, double(_Data.size()), intstep); auto x0 = InferTools::arange(0, double(_Data.size())); while (x0.size() < _Data.size()) x0.emplace_back(x0[x0.size() - 1] + 1.0); while (x0.size() > _Data.size()) x0.pop_back(); std::vector y0(_Data.size()); for (size_t i = 0; i < _Data.size(); ++i) y0[i] = double(_Data[i]) / double(n_Div); std::vector yi(xi.size()); interp1(x0.data(), y0.data(), long(x0.size()), xi.data(), long(xi.size()), yi.data()); std::vector out(xi.size()); for (size_t i = 0; i < yi.size(); ++i) out[i] = TOut(yi[i]); return out; } std::vector out(_Data.size()); for (size_t i = 0; i < _Data.size(); ++i) out[i] = TOut(_Data[i]) / n_Div; return out; } /** * \brief 重采样(插值) * \tparam T 数据类型 * \param Data 输入数据 * \param src 输入采样率 * \param dst 输出采样率 * \return 输出数据 */ template static std::vector InterpFunc(const std::vector& Data, long src, long dst) { if (src != dst) { const double intstep = double(src) / double(dst); auto xi = InferTools::arange(0, double(Data.size()), intstep); while (xi.size() < size_t(dst)) xi.emplace_back(xi[xi.size() - 1] + 1.0); while (xi.size() > size_t(dst)) xi.pop_back(); auto x0 = InferTools::arange(0, double(Data.size())); while (x0.size() < Data.size()) x0.emplace_back(x0[x0.size() - 1] + 1.0); while (x0.size() > Data.size()) x0.pop_back(); std::vector y0(Data.size()); for (size_t i = 0; i < Data.size(); ++i) y0[i] = Data[i] <= T(0.0001) ? NAN : double(Data[i]); std::vector yi(xi.size()); interp1(x0.data(), y0.data(), long(x0.size()), xi.data(), long(xi.size()), yi.data()); std::vector out(xi.size()); for (size_t i = 0; i < yi.size(); ++i) out[i] = isnan(yi[i]) ? T(0.0) : T(yi[i]); return out; } return Data; } #ifdef MoeVoiceStudioAvxAcc class FloatTensorWrapper { public: FloatTensorWrapper() = delete; ~FloatTensorWrapper() { _data_ptr = nullptr; } FloatTensorWrapper(float* const data_p, size_t _size) : _data_ptr(data_p), _data_size(_size) {} FloatTensorWrapper(const FloatTensorWrapper& _copy) = delete; FloatTensorWrapper& operator=(const FloatTensorWrapper&) = delete; FloatTensorWrapper(FloatTensorWrapper&& _move) noexcept:_data_ptr(_move._data_ptr), _data_size(_move._data_size) {} FloatTensorWrapper& operator=(FloatTensorWrapper&& _move) noexcept { _data_ptr = _move._data_ptr; _data_size = _move._data_size; return *this; } template static const T& Min(const T& a, const T& b) { return (a > b) ? b : a; } float& operator[](size_t index) const { return *(_data_ptr + Min(index, _data_size)); } FloatTensorWrapper& operator+=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator-=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator*=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator/=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator+=(float _right); FloatTensorWrapper& operator-=(float _right); FloatTensorWrapper& operator*=(float _right); FloatTensorWrapper& operator/=(float _right); private: float* _data_ptr = nullptr; size_t _data_size = 0; }; #endif MOEVSINFERTOOLSEND ================================================ FILE: libdlvoicecodec/Modules/Logger/MoeSSLogger.cpp ================================================ #include "MoeSSLogger.hpp" #include #include "../StringPreprocess.hpp" #include namespace MoeSSLogger { static Logger MoeVsLogger; static std::wstring GetCurrentFolder(const std::wstring& defualt = L"") { wchar_t path[1024]; #ifdef _WIN32 GetModuleFileName(nullptr, path, 1024); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); return _curPath; #else //TODO Other System #error Other System ToDO #endif } void RemoveDir(const std::filesystem::directory_entry& dir) { if (!dir.exists()) return; if (dir.is_directory() && !is_empty(dir)) { const std::filesystem::directory_iterator dirs(dir); for (const auto& i : dirs) RemoveDir(i); } remove(dir); } Logger::~Logger() { #ifndef MoeVoiceStudioCommandLineProg if (log_file) fclose(log_file); if (error_file) fclose(error_file); log_file = nullptr; error_file = nullptr; #endif } Logger::Logger() { #ifndef MoeVoiceStudioCommandLineProg const std::wstring LogPath = GetCurrentFolder() + L"/log"; const std::filesystem::path logger_path(LogPath); if (!exists(logger_path)) create_directory(logger_path); const std::filesystem::directory_entry logger_path_entry(LogPath); if (logger_path_entry.is_directory()) { time_t curtime; time(&curtime); tm nowtime{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }; localtime_s(&nowtime, &curtime); const std::wstring dir_name = L"MoeVoiceStudioLog " + std::to_wstring(nowtime.tm_year + 1900) + L'-' + std::to_wstring(nowtime.tm_mon) + L'-' + std::to_wstring(nowtime.tm_mday) + L'-' + std::to_wstring(nowtime.tm_hour) + L'-' + std::to_wstring(nowtime.tm_min) + L'-' + std::to_wstring(nowtime.tm_sec); cur_log_dir = LogPath + L'/' + dir_name; const std::filesystem::directory_iterator logger_path_list(LogPath); std::filesystem::directory_entry remove_dir; size_t log_count = 0; for (const auto& i : logger_path_list) if (i.is_directory() && i.path().filename().wstring().substr(0, 17) == L"MoeVoiceStudioLog") { if (!log_count) remove_dir = i; else if (i.last_write_time() < remove_dir.last_write_time()) remove_dir = i; ++log_count; } if (log_count > 10) RemoveDir(remove_dir); if (!exists(cur_log_dir)) create_directory(cur_log_dir); logpath = cur_log_dir; logpath.append("log.txt"); errorpath = cur_log_dir; errorpath.append("error.txt"); } #endif } void Logger::log(const std::wstring& format) { std::lock_guard mtx(mx); #ifndef MoeVoiceStudioCommandLineProg _wfopen_s(&log_file, logpath.c_str(), L"a+"); if (log_file) { fprintf_s(log_file, "%s\n", to_byte_string(format).c_str()); fclose(log_file); log_file = nullptr; } #else fprintf_s(stdout, "%s\n", to_byte_string(format).c_str()); #endif } void Logger::log(const char* format) { std::lock_guard mtx(mx); #ifndef MoeVoiceStudioCommandLineProg _wfopen_s(&log_file, logpath.c_str(), L"a+"); if (log_file) { fprintf_s(log_file, "%s\n", format); fclose(log_file); log_file = nullptr; } #else fprintf_s(stdout, "%s\n", format); #endif } void Logger::error(const std::wstring& format) { std::lock_guard mtx(mx); #ifndef MoeVoiceStudioCommandLineProg _wfopen_s(&log_file, logpath.c_str(), L"a+"); _wfopen_s(&error_file, errorpath.c_str(), L"a+"); if (log_file) { fprintf(log_file, "[ERROR]%s\n", to_byte_string(format).c_str()); fclose(log_file); log_file = nullptr; } if (error_file) { fprintf(error_file, "[ERROR]%s\n", to_byte_string(format).c_str()); fclose(error_file); error_file = nullptr; } #else fprintf(stdout, "[ERROR]%s\n", to_byte_string(format).c_str()); #endif } void Logger::error(const char* format) { std::lock_guard mtx(mx); #ifndef MoeVoiceStudioCommandLineProg _wfopen_s(&log_file, logpath.c_str(), L"a+"); _wfopen_s(&error_file, errorpath.c_str(), L"a+"); if (log_file) { fprintf(log_file, "[ERROR]%s\n", format); fclose(log_file); log_file = nullptr; } if (error_file) { fprintf(error_file, "[ERROR]%s\n", format); fclose(error_file); error_file = nullptr; } #else fprintf(stdout, "[ERROR]%s\n", format); #endif } Logger& GetLogger() { return MoeVsLogger; } } ================================================ FILE: libdlvoicecodec/Modules/Logger/MoeSSLogger.hpp ================================================ #pragma once #include #include "../StringPreprocess.hpp" #include #include #define __MOEVS_DEBUG_MESSAGE(msg) __MOEVS_DEBUG_INFO(__FILE__, __LINE__, msg) #define logger MoeSSLogger::GetLogger() inline std::string __MOEVS_DEBUG_INFO(const char* filename, int line, const char* msg) { return std::string("[In \"") + std::filesystem::path(filename).filename().string() + "\" Line " + std::to_string(line) + "] " + msg; } inline std::wstring __MOEVS_DEBUG_INFO(const char* filename, int line, const wchar_t* msg) { return std::wstring(L"[In \"") + std::filesystem::path(filename).filename().wstring() + L"\" Line " + std::to_wstring(line) + L"] " + msg; } namespace MoeSSLogger { class Logger { public: Logger(); ~Logger(); void log(const std::wstring&); void log(const char*); void error(const std::wstring&); void error(const char*); private: std::filesystem::path cur_log_dir, logpath, errorpath; FILE* log_file = nullptr,* error_file = nullptr; std::mutex mx; }; Logger& GetLogger(); } ================================================ FILE: libdlvoicecodec/Modules/Models/EnvManager.cpp ================================================ #include "EnvManager.hpp" #ifdef _WIN32 #ifdef MOEVSDMLPROVIDER #include #endif #endif #include #include "../Logger/MoeSSLogger.hpp" #include "../InferTools/F0Extractor/NetF0Predictors/NetF0Predictors.hpp" #include "../Modules.hpp" MoeVoiceStudioCoreEnvManagerHeader const char* logger_id = "MoeVoiceStudioCore"; void MoeVSOrtLoggingFn(void* param, OrtLoggingLevel severity, const char* category, const char* logid, const char* code_location, const char* message) { std::string ort_message = "["; ort_message += category; ort_message += "; In "; ort_message += code_location; ort_message += "; By"; ort_message += logger_id; ort_message += "] "; ort_message += message; logger.log(ort_message.c_str()); } void MoeVoiceStudioEnv::Destory() { MoeVSF0Extractor::EmptyCache(); logger.log(L"[Info] Removing Env & Release Memory"); delete GlobalOrtSessionOptions; delete GlobalOrtEnv; delete GlobalOrtMemoryInfo; GlobalOrtSessionOptions = nullptr; GlobalOrtEnv = nullptr; GlobalOrtMemoryInfo = nullptr; if (cuda_option_v2) Ort::GetApi().ReleaseCUDAProviderOptions(cuda_option_v2); cuda_option_v2 = nullptr; logger.log(L"[Info] Complete!"); } void MoeVoiceStudioEnv::Load(unsigned ThreadCount, unsigned DeviceID, unsigned Provider) { if (((Provider != CurProvider) || (Provider == 0 && ThreadCount != CurThreadCount) || ((Provider == 1 || Provider == 2) && DeviceID != CurDeviceID)) && (MoeVSModuleManager::GetDiffusionSvcModel() || MoeVSModuleManager::GetVitsSvcModel() || MoeVSModuleManager::VocoderEnabled())) LibDLVoiceCodecThrow("A Model Has Been Loaded, You Cannot Change Env When A Model Has Been Loaded"); try { if (Provider != CurProvider) Create(ThreadCount, DeviceID, Provider); if (Provider == 0 && ThreadCount != CurThreadCount) Create(ThreadCount, DeviceID, Provider); if ((Provider == 1 || Provider == 2) && DeviceID != CurDeviceID) Create(ThreadCount, DeviceID, Provider); CurProvider = Provider; } catch(std::exception& e) { Destory(); CurThreadCount = unsigned(-1); CurDeviceID = unsigned(-1); CurProvider = unsigned(-1); logger.log(to_wide_string(e.what())); LibDLVoiceCodecThrow(e.what()); } } void MoeVoiceStudioEnv::Create(unsigned ThreadCount_, unsigned DeviceID_, unsigned ExecutionProvider_) { Destory(); logger.log(L"[Info] Creating Env"); switch (ExecutionProvider_) { case 1: { const auto AvailableProviders = Ort::GetAvailableProviders(); bool ret = true; for (const auto& it : AvailableProviders) if (it.find("CUDA") != std::string::npos) ret = false; if (ret) LibDLVoiceCodecThrow("CUDA Provider Not Found"); GlobalOrtSessionOptions = new Ort::SessionOptions; #ifdef MoeVSCUDAProviderV1 OrtCUDAProviderOptions cuda_option; cuda_option.device_id = int(DeviceID_); cuda_option.do_copy_in_default_stream = false; GlobalOrtSessionOptions->AppendExecutionProvider_CUDA(cuda_option); #else const OrtApi& ortApi = Ort::GetApi(); if (cuda_option_v2) ortApi.ReleaseCUDAProviderOptions(cuda_option_v2); ortApi.CreateCUDAProviderOptions(&cuda_option_v2); const std::vector keys{ "device_id", "gpu_mem_limit", "arena_extend_strategy", "cudnn_conv_algo_search", "do_copy_in_default_stream", "cudnn_conv_use_max_workspace", "cudnn_conv1d_pad_to_nc1d", "enable_cuda_graph", "enable_skip_layer_norm_strict_mode" }; const std::vector values{ std::to_string(DeviceID_).c_str(), "2147483648", "kNextPowerOfTwo", "EXHAUSTIVE", "1", "1", "1", "0", "0" }; ortApi.UpdateCUDAProviderOptions(cuda_option_v2, keys.data(), values.data(), keys.size()); GlobalOrtSessionOptions->AppendExecutionProvider_CUDA_V2(*cuda_option_v2); //ortApi.ReleaseCUDAProviderOptions(cuda_option_v2); #endif GlobalOrtEnv = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, logger_id, MoeVSOrtLoggingFn, nullptr); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtSessionOptions->SetIntraOpNumThreads((int)std::thread::hardware_concurrency()); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); CurDeviceID = DeviceID_; break; } #ifdef MOEVSDMLPROVIDER case 2: { const auto AvailableProviders = Ort::GetAvailableProviders(); std::string ret; for (const auto& it : AvailableProviders) if (it.find("Dml") != std::string::npos) ret = it; if (ret.empty()) LibDLVoiceCodecThrow("DML Provider Not Found"); const OrtApi& ortApi = Ort::GetApi(); const OrtDmlApi* ortDmlApi = nullptr; ortApi.GetExecutionProviderApi("DML", ORT_API_VERSION, reinterpret_cast(&ortDmlApi)); Ort::ThreadingOptions threading_options; threading_options.SetGlobalInterOpNumThreads((int)std::thread::hardware_concurrency()); GlobalOrtEnv = new Ort::Env(threading_options, MoeVSOrtLoggingFn, nullptr, ORT_LOGGING_LEVEL_WARNING, logger_id); GlobalOrtEnv->DisableTelemetryEvents(); GlobalOrtSessionOptions = new Ort::SessionOptions; ortDmlApi->SessionOptionsAppendExecutionProvider_DML(*GlobalOrtSessionOptions, int(DeviceID_)); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtSessionOptions->DisablePerSessionThreads(); GlobalOrtSessionOptions->SetExecutionMode(ORT_SEQUENTIAL); GlobalOrtSessionOptions->DisableMemPattern(); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU)); CurDeviceID = DeviceID_; break; } #endif default: { if (ThreadCount_ == 0) ThreadCount_ = std::thread::hardware_concurrency(); GlobalOrtSessionOptions = new Ort::SessionOptions; GlobalOrtEnv = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, logger_id, MoeVSOrtLoggingFn, nullptr); GlobalOrtSessionOptions->SetIntraOpNumThreads(static_cast(ThreadCount_)); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); CurThreadCount = ThreadCount_; break; } } logger.log(L"[Info] Env Created"); } bool MoeVoiceStudioEnv::IsEnabled() const { return GlobalOrtEnv && GlobalOrtMemoryInfo && GlobalOrtSessionOptions; } MoeVoiceStudioEnv GlobalMoeVSEnv; MoeVoiceStudioEnv& GetGlobalMoeVSEnv() { return GlobalMoeVSEnv; } MoeVoiceStudioCoreEnvManagerEnd ================================================ FILE: libdlvoicecodec/Modules/Models/EnvManager.hpp ================================================ /** * FileName: EnvManager.hpp * Note: MoeVoiceStudioCore 环境管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #define MoeVoiceStudioCoreEnvManagerHeader namespace moevsenv{ #define MoeVoiceStudioCoreEnvManagerEnd } MoeVoiceStudioCoreEnvManagerHeader class MoeVoiceStudioEnv { public: MoeVoiceStudioEnv() = default; ~MoeVoiceStudioEnv() { Destory(); } void Load(unsigned ThreadCount, unsigned DeviceID, unsigned Provider); void Destory(); [[nodiscard]] bool IsEnabled() const; [[nodiscard]] Ort::Env* GetEnv() const { return GlobalOrtEnv; } [[nodiscard]] Ort::SessionOptions* GetSessionOptions() const { return GlobalOrtSessionOptions; } [[nodiscard]] Ort::MemoryInfo* GetMemoryInfo() const { return GlobalOrtMemoryInfo; } [[nodiscard]] int GetCurThreadCount() const { return (int)CurThreadCount; } [[nodiscard]] int GetCurDeviceID() const { return (int)CurDeviceID; } [[nodiscard]] int GetCurProvider() const { return (int)CurProvider; } private: void Create(unsigned ThreadCount_, unsigned DeviceID_, unsigned ExecutionProvider_); Ort::Env* GlobalOrtEnv = nullptr; Ort::SessionOptions* GlobalOrtSessionOptions = nullptr; Ort::MemoryInfo* GlobalOrtMemoryInfo = nullptr; unsigned CurThreadCount = unsigned(-1); unsigned CurDeviceID = unsigned(-1); unsigned CurProvider = unsigned(-1); OrtCUDAProviderOptionsV2* cuda_option_v2 = nullptr; }; MoeVoiceStudioEnv& GetGlobalMoeVSEnv(); MoeVoiceStudioCoreEnvManagerEnd ================================================ FILE: libdlvoicecodec/Modules/Models/header/DiffSvc.hpp ================================================ /** * FileName: DiffSvc.hpp * Note: MoeVoiceStudioCore Onnx Diffusion系Svc 模型定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include "SVC.hpp" MoeVoiceStudioCoreHeader void LoadVocoderModel(const std::wstring& VocoderPath); void UnLoadVocoderModel(); bool VocoderEnabled(); /** * \brief DiffSvc模型 */ class DiffusionSvc : public SingingVoiceConversion { public: DiffusionSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); /** * \brief 加载DiffSvc模型 * \param _PathDict 路径,Key分别为["Hubert", "Hifigan", "Encoder", "DenoiseFn", "NoisePredictor", "AfterProcess", "DiffSvc", "Naive", "Alphas"],其中"DiffSvc"、"Naive"、"Alphas"为可选项 * \param _Config 配置Json * \param _ProgressCallback 进度条回调函数 * \param ExecutionProvider_ Provider * \param DeviceID_ GPU设备ID * \param ThreadCount_ 线程数 */ DiffusionSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); ~DiffusionSvc() override; void load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback); void Destory(); [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const override; [[nodiscard]] std::vector Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; [[nodiscard]] std::vector InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector ShallowDiffusionInference( std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize ) const; [[nodiscard]] int64_t GetMaxStep() const { return MaxStep; } [[nodiscard]] bool OldVersion() const { return diffSvc; } [[nodiscard]] const std::wstring& GetDiffSvcVer() const { return DiffSvcVersion; } [[nodiscard]] int64_t GetMelBins() const { return melBins; } void NormMel(std::vector& MelSpec) const; private: Ort::Session* encoder = nullptr; Ort::Session* denoise = nullptr; Ort::Session* pred = nullptr; Ort::Session* after = nullptr; Ort::Session* alpha = nullptr; Ort::Session* naive = nullptr; Ort::Session* diffSvc = nullptr; int64_t melBins = 128; int64_t Pndms = 100; int64_t MaxStep = 1000; float SpecMin = -12; float SpecMax = 2; std::wstring DiffSvcVersion = L"DiffSvc"; const std::vector nsfInput = { "c", "f0" }; const std::vector nsfOutput = { "audio" }; const std::vector DiffInput = { "hubert", "mel2ph", "spk_embed", "f0", "initial_noise", "speedup" }; const std::vector DiffOutput = { "mel_pred", "f0_pred" }; const std::vector afterInput = { "x" }; const std::vector afterOutput = { "mel_out" }; const std::vector naiveOutput = { "mel" }; }; MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/header/GPT-SoVits.hpp ================================================ /** * FileName: GPT-SoVits.hpp * Note: MoeVoiceStudioCore GPT-SoVits模型类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2023-11-9 Create */ #pragma once #include "TTS.hpp" MoeVoiceStudioCoreHeader class GptSoVits : public TextToSpeech { public: GptSoVits(const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); GptSoVits(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); void load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback); ~GptSoVits() override; void destory() { delete sessionBert; delete sessionVits; delete sessionSSL; sessionBert = nullptr; sessionVits = nullptr; sessionSSL = nullptr; delete sessionEncoder; delete sessionFDecoder; delete sessionDecoder; sessionEncoder = nullptr; sessionFDecoder = nullptr; sessionDecoder = nullptr; } [[nodiscard]] std::tuple, std::vector> GetBertPhs(const MoeVSProjectSpace::MoeVSTTSSeq& Seq, const MoeVSG2P::Tokenizer& Tokenizer) const; [[nodiscard]] std::vector> Inference(const std::vector& _Input) const override; private: Ort::Session* sessionBert = nullptr; Ort::Session* sessionVits = nullptr; Ort::Session* sessionSSL = nullptr; Ort::Session* sessionEncoder = nullptr; Ort::Session* sessionFDecoder = nullptr; Ort::Session* sessionDecoder = nullptr; int64_t NumLayers = 24; int64_t EmbeddingDim = 512; int64_t EOSId = 1024; std::vector VitsInputNames = { "text_seq", "pred_semantic", "ref_audio" }; const std::vector VitsOutputNames = { "audio" }; std::vector EncoderInputNames = { "ref_seq", "text_seq", "ref_bert", "text_bert", "ssl_content" }; const std::vector EncoderOutputNames = { "x", "prompts" }; std::vector DecoderInputNames = { "iy", "ik", "iv", "iy_emb", "ix_example" }; const std::vector DecoderOutputNames = { "y", "k", "v", "y_emb", "logits", "samples" }; std::vector FDecoderInputNames = { "x", "prompts" }; const std::vector FDecoderOutputNames = { "y", "k", "v", "y_emb", "x_example" }; std::vector SSLInputNames = { "audio" }; const std::vector SSLOutputNames = { "last_hidden_state" }; const std::vector BertInputNames = { "input_ids", "attention_mask", "token_type_ids" }; const std::vector BertInputNames2 = { "input_ids", "attention_mask" }; const std::vector BertInputNames3 = { "input_ids" }; const std::vector BertOutputNames = { "last_hidden_state" }; }; MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/header/ModelBase.hpp ================================================ /** * FileName: ModelBase.hpp * Note: MoeVoiceStudioCore Onnx 模型基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #endif #include #include "MoeVSProject.hpp" #include "../../InferTools/inferTools.hpp" #define MoeVoiceStudioCoreHeader namespace MoeVoiceStudioCore{ #define MoeVoiceStudioCoreEnd } #define MoeVSNotImplementedError LibDLVoiceCodecThrow("NotImplementedError") #define MoeVSClassName(__Moe__VSClassName) __NAME__CLASS__.emplace_back((__Moe__VSClassName)) #define MoeVSMaxPath 1024 static std::wstring GetCurrentFolder(const std::wstring& defualt = L"") { wchar_t path[MoeVSMaxPath]; #ifdef _WIN32 GetModuleFileName(nullptr, path, MoeVSMaxPath); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); return _curPath; #else //TODO Other System #error Other System ToDO #endif } MoeVoiceStudioCoreHeader class MoeVoiceStudioModule { public: //进度条回调 using ProgressCallback = std::function; //Provicer enum class ExecutionProviders { CPU = 0, CUDA = 1, #ifdef MOEVSDMLPROVIDER DML = 2 #endif }; static [[nodiscard]] std::vector GetOpenFileNameMoeVS(); static std::vector CutLens(const std::wstring& input); /** * \brief 构造Onnx模型基类 * \param ExecutionProvider_ ExecutionProvider(可以理解为设备) * \param DeviceID_ 设备ID * \param ThreadCount_ 线程数 */ MoeVoiceStudioModule(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_ = 0); virtual ~MoeVoiceStudioModule(); /** * \brief 输入路径推理 * \param _Datas [路径,多个路径使用换行符隔开, 推理文本] * \param _InferParams 推理参数 * \param _SlicerSettings 切片机配置 * \return 输出路径 */ [[nodiscard]] virtual std::vector Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const; /** * \brief 获取采样率 * \return 采样率 */ [[nodiscard]] long GetSamplingRate() const { return _samplingRate; } static float Clamp(float in, float min = -1.f, float max = 1.f) { if (in > max) return max; if (in < min) return min; return in; } protected: //采样率 long _samplingRate = 22050; Ort::Env* env = nullptr; Ort::SessionOptions* session_options = nullptr; Ort::MemoryInfo* memory_info = nullptr; ExecutionProviders _cur_execution_provider = ExecutionProviders::CPU; ProgressCallback _callback; std::vector __NAME__CLASS__ = { L"MoeVoiceStudioModule" }; public: //*******************删除的函数********************// MoeVoiceStudioModule& operator=(MoeVoiceStudioModule&&) = delete; MoeVoiceStudioModule& operator=(const MoeVoiceStudioModule&) = delete; MoeVoiceStudioModule(const MoeVoiceStudioModule&) = delete; MoeVoiceStudioModule(MoeVoiceStudioModule&&) = delete; }; MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/header/MoeVSProject.hpp ================================================ /** * FileName: MoeVSProject.hpp * Note: MoeVoiceStudioCore 项目相关的定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include "../../StringPreprocess.hpp" #include "MJson.h" namespace MoeVSProjectSpace { class FileWrapper { public: FileWrapper() = delete; FileWrapper(const wchar_t* _path, const wchar_t* _mode) { _wfopen_s(&file_, _path, _mode); } ~FileWrapper() { if (file_) fclose(file_); file_ = nullptr; } operator FILE* () const { return file_; } [[nodiscard]] bool IsOpen() const { return file_; } private: FILE* file_ = nullptr; }; using size_type = size_t; template size_type GetSize(const std::vector& inp_vec) { return inp_vec.size() * sizeof(T); } struct MoeVoiceStudioSvcSlice { std::vector Audio; std::vector F0; std::vector Volume; std::vector< std::vector> Speaker; long OrgLen = 0; bool IsNotMute = false; MoeVoiceStudioSvcSlice() = default; }; struct MoeVoiceStudioSvcData { /*std::vector> Audio; std::vector> F0; std::vector> Volume; std::vector>> Speaker; std::vector OrgLen; std::vector IsNotMute;*/ std::vector Slices; std::wstring Path; MoeVoiceStudioSvcData() = default; [[nodiscard]] size_type Size() const { size_type _size = 0; const std::string bytePath = to_byte_string(Path); _size += sizeof(long) * Slices.size() + Slices.size() + bytePath.length() + 1; for (const auto& Slice : Slices) { _size += GetSize(Slice.Audio) + GetSize(Slice.F0) + GetSize(Slice.Volume); for (const auto& it : Slice.Speaker) _size += GetSize(it); } return _size; } }; struct MoeVSAudioSliceRef { const std::vector& Audio; const std::vector& F0; const std::vector& Volume; const std::vector>& Speaker; bool IsNotMute; long OrgLen; const std::wstring& Path; size_t Slice = 0; void* Mel = nullptr; MoeVSAudioSliceRef( const std::vector& audio, const std::vector& f0, const std::vector& volume, const std::vector>& speaker, bool isnotmute, long orglen, const std::wstring& path, size_t sli, void* mel_tensor_ptr = nullptr ) : Audio(audio), F0(f0), Volume(volume), Speaker(speaker), IsNotMute(isnotmute), OrgLen(orglen), Path(path), Slice(sli), Mel(mel_tensor_ptr) {} }; struct MoeVSParams { //通用 float NoiseScale = 0.3f; //噪声修正因子 0-10 int64_t Seed = 52468; //种子 int64_t SpeakerId = 0; //角色ID uint64_t SrcSamplingRate = 48000; //源采样率 int64_t SpkCount = 2; //模型角色数 //SVC float IndexRate = 0.f; //索引比 0-1 float ClusterRate = 0.f; //聚类比 0-1 float DDSPNoiseScale = 0.8f; //DDSP噪声修正因子 0-10 float Keys = 0.f; //升降调 -64-64 size_t MeanWindowLength = 2; //均值滤波器窗口大小 1-20 size_t Pndm = 100; //Diffusion加速倍数 2-200 size_t Step = 1000; //Diffusion总步数 200-1000 std::wstring Sampler = L"Pndm"; //Diffusion采样器 std::wstring F0Method = L"Dio"; //F0提取算法 bool UseShallowDiffusion = false; //使用浅扩散 //SVCRTInfer int64_t RTSampleSize = 44100; int64_t CrossFadeLength = 320; //TTS std::vector SpeakerMix; //角色混合比例 float LengthScale = 1.0f; //时长修正因子 float DurationPredictorNoiseScale = 0.8f; //随机时长预测器噪声修正因子 float FactorDpSdp = 0.f; //随机时长预测器与时长预测器混合比例 float GateThreshold = 0.66666f; //Tacotron2解码器EOS阈值 int64_t MaxDecodeStep = 2000; //Tacotron2最大解码步数 std::vector EmotionPrompt; //情感标记 std::wstring PlaceHolderSymbol = L"|"; //音素分隔符 float RestTime = 0.5f; //停顿时间,为负数则直接断开音频并创建新音频 std::string LanguageSymbol = "JP"; //语言 std::wstring AdditionalInfo; //G2P额外信息 std::wstring SpeakerName = L"0"; //角色名 }; struct MoeVSTTSToken { std::wstring Text; //输入文本 std::vector Phonemes; //音素序列 std::vector Tones; //音调序列 std::vector Durations; //时长序列 std::vector Language; //语言序列 MoeVSTTSToken() = default; MoeVSTTSToken(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams); [[nodiscard]] std::wstring Serialization() const; }; struct MoeVSTTSSeq { std::wstring TextSeq; std::vector SlicedTokens; std::vector SpeakerMix; //角色混合比例 std::vector EmotionPrompt; //情感标记 std::wstring PlaceHolderSymbol = L"|"; //音素分隔符 float NoiseScale = 0.3f; //噪声修正因子 0-10 float LengthScale = 1.0f; //时长修正因子 float DurationPredictorNoiseScale = 0.3f; //随机时长预测器噪声修正因子 float FactorDpSdp = 0.3f; //随机时长预测器与时长预测器混合比例 float GateThreshold = 0.66666f; //Tacotron2解码器EOS阈值 int64_t MaxDecodeStep = 2000; //Tacotron2最大解码步数 int64_t Seed = 52468; //种子 float RestTime = 0.5f; //停顿时间,为负数则直接断开音频并创建新音频 std::string LanguageSymbol = "ZH"; //语言标记 std::wstring SpeakerName = L"0"; //角色或名称ID std::wstring AdditionalInfo; //G2P额外信息 MoeVSTTSSeq() = default; MoeVSTTSSeq(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams); [[nodiscard]] std::wstring Serialization() const; bool operator==(const MoeVSTTSSeq& right) const; }; using MoeVSSvcParams = MoeVSParams; using MoeVSTTSParams = MoeVSParams; struct ParamsOffset { std::vector OrgAudio; //std::vector Hidden_Unit; std::vector F0; std::vector Volume; std::vector Speaker; [[nodiscard]] size_type Size() const { return size_type(OrgAudio.size() + F0.size() + Volume.size() + Speaker.size()) * sizeof(size_type); } ParamsOffset() = default; }; class MoeVSProject { public: struct Header { char ChunkSymbol[8] = { 'M','O','E','V','S','P','R','J' }; size_type DataHeaderAmount = 0; }; struct DataHeader { char ChunkSymbol[4] = { 'D','A','T','A' }; size_type OrgAudioOffsetPosSize = 0; size_type F0OffsetPosSize = 0; size_type VolumeOffsetPosSize = 0; size_type CharacterOffsetPosSize = 0; size_type OrgLenSize = 0; size_type SymbolSize = 0; size_type PathSize = 0; size_type HeaderSize = sizeof(DataHeader) - sizeof(size_type); }; struct Data { DataHeader Header; ParamsOffset Offset; MoeVoiceStudioSvcData ParamData; [[nodiscard]] size_type Size() const { size_type size = sizeof(DataHeader); size += Offset.Size(); size += ParamData.Size(); return size; } }; MoeVSProject() = delete; ~MoeVSProject() = default; //从文件读取项目 MoeVSProject(const std::wstring& _path); //从音频数据构造项目 MoeVSProject(const std::vector& _params); //写入文件 void Write(const std::wstring& _path) const; //从项目获取音频数据 [[nodiscard]] std::vector GetParams() const { std::vector Params_data; Params_data.reserve(data_.size()); for (const auto& i : data_) Params_data.emplace_back(i.ParamData); return Params_data; } //从项目获取音频数据(移动构造) [[nodiscard]] std::vector GetParamsMove() { std::vector Params_data; Params_data.reserve(data_.size()); for (auto& i : data_) Params_data.emplace_back(std::move(i.ParamData)); return Params_data; } private: static constexpr size_t begin_offset = sizeof(Header); Header moevs_proj_header_; std::vector data_pos_; size_type data_chunk_begin_ = 0; std::vector data_; }; } ================================================ FILE: libdlvoicecodec/Modules/Models/header/SVC.hpp ================================================ /** * FileName: SVC.hpp * Note: MoeVoiceStudioCore OnnxSvc 模型基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "ModelBase.hpp" #include "../../Logger/MoeSSLogger.hpp" #include "MJson.h" #include "../../InferTools/inferTools.hpp" #include "../../InferTools/TensorExtractor/TensorExtractorManager.hpp" #include "../../InferTools/Cluster/MoeVSClusterManager.hpp" MoeVoiceStudioCoreHeader /* class OnnxModule { public: enum class Device { CPU = 0, CUDA = 1, #ifdef MOEVSDMLPROVIDER DML = 2 #endif }; using callback = std::function; using int64 = int64_t; using MTensor = Ort::Value; OnnxModule(); virtual ~OnnxModule(); void ChangeDevice(Device _dev); static std::vector CutLens(const std::wstring& input); [[nodiscard]] long GetSamplingRate() const { return _samplingRate; } template static void LinearCombination(std::vector& _data, T Value = T(1.0)) { if(_data.empty()) { _data = std::vector(1, Value); return; } T Sum = T(0.0); for(const auto& i : _data) Sum += i; if (Sum < T(0.0001)) { _data = std::vector(_data.size(), T(0.0)); _data[0] = Value; return; } Sum *= T(Value); for (auto& i : _data) i /= Sum; } protected: Ort::Env* env = nullptr; Ort::SessionOptions* session_options = nullptr; Ort::MemoryInfo* memory_info = nullptr; modelType _modelType = modelType::SoVits; Device device_ = Device::CPU; long _samplingRate = 22050; callback _callback; static constexpr long MaxPath = 8000l; std::wstring _outputPath = GetCurrentFolder() + L"\\outputs"; }; */ class SingingVoiceConversion : public MoeVoiceStudioModule { public: SingingVoiceConversion(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_ = 0); /** * \brief 输入路径推理 * \param _Paths 路径,多个路径使用换行符隔开 * \param _InferParams 推理参数 * \param _SlicerSettings 切片机配置 * \return 输出路径 */ [[nodiscard]] std::vector Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; /** * \brief 推理一个音频 * \param _Slice 音频数据 * \param _InferParams 推理参数 * \return 推理结果(PCM signed-int16 单声道) */ [[nodiscard]] virtual std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const; /** * \brief 推理一个音频(使用引用) * \param _Slice 音频数据引用 * \param _InferParams 推理参数 * \param _Process 推理进度 * \return 推理结果(PCM signed-int16 单声道) */ [[nodiscard]] virtual std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const; /** * \brief 推理一个音频(使用PCM) * \param PCMData 输入的PCM数据(signed-int16 单声道) * \param srcSr 输入PCM的采样率 * \param _InferParams 推理参数 * \return 推理结果(PCM signed-int16 单声道) */ [[nodiscard]] virtual std::vector InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const; //提取音量 [[nodiscard]] static std::vector ExtractVolume(const std::vector& OrgAudio, int hop_size); //提取音量 [[nodiscard]] std::vector ExtractVolume(const std::vector& OrgAudio) const; //获取HopSize [[nodiscard]] int GetHopSize() const { return HopSize; } //获取HiddenUnitKDims [[nodiscard]] int64_t GetHiddenUnitKDims() const { return HiddenUnitKDims; } //获取角色数量 [[nodiscard]] int64_t GetSpeakerCount() const { return SpeakerCount; } //获取角色混合启用状态 [[nodiscard]] bool CharaMixEnabled() const { return EnableCharaMix; } /** * \brief 切片一个音频 * \param input 输入的PCM数据(signed-int16 单声道) * \param _slice_pos 切片位置(单位为采样) * \param _slicer 切片机设置 * \return 音频数据 */ [[nodiscard]] static MoeVSProjectSpace::MoeVoiceStudioSvcData GetAudioSlice(const std::vector& input, const std::vector& _slice_pos, const InferTools::SlicerSettings& _slicer); /** * \brief 预处理音频数据 * \param input 完成切片的音频数据 * \param __SamplingRate 采样率 * \param __HopSize HopSize * \param _f0_method F0算法 */ static void PreProcessAudio(MoeVSProjectSpace::MoeVoiceStudioSvcData& input, int __SamplingRate = 48000, int __HopSize = 512, const std::wstring& _f0_method = L"Dio"); ~SingingVoiceConversion() override; protected: MoeVSTensorPreprocess::TensorExtractor _TensorExtractor; Ort::Session* hubert = nullptr; int HopSize = 320; int64_t HiddenUnitKDims = 256; int64_t SpeakerCount = 1; bool EnableCharaMix = false; bool EnableVolume = false; MoeVoiceStudioCluster::MoeVSCluster Cluster; int64_t ClusterCenterSize = 10000; bool EnableCluster = false; bool EnableIndex = false; const std::vector hubertOutput = { "embed" }; const std::vector hubertInput = { "source" }; }; MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/header/TTS.hpp ================================================ /** * FileName: TTS.hpp * Note: MoeVoiceStudioCore TTS基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2023-11-9 Create */ #pragma once #include #include "ModelBase.hpp" #include "../../Logger/MoeSSLogger.hpp" #include "../../InferTools/G2P/MoeVSG2P.hpp" #include "MJson.h" MoeVoiceStudioCoreHeader class EmoLoader { public: static constexpr long startPos = 128; EmoLoader() = default; EmoLoader(const std::wstring& path) { if (emofile) fclose(emofile); emofile = nullptr; _wfopen_s(&emofile, path.c_str(), L"r"); if (!emofile) LibDLVoiceCodecThrow("emoFile not exists") } ~EmoLoader() { if (emofile) fclose(emofile); emofile = nullptr; } void close() { if (emofile) fclose(emofile); emofile = nullptr; } void open(const std::wstring& path) { if (emofile) fclose(emofile); emofile = nullptr; _wfopen_s(&emofile, path.c_str(), L"rb"); if (!emofile) LibDLVoiceCodecThrow("emoFile not exists") } std::vector operator[](long index) const { if (emofile) { fseek(emofile, index * 4096 + startPos, SEEK_SET); char buffer[4096]; const auto buf = reinterpret_cast(buffer); const auto bufread = fread_s(buffer, 4096, 1, 4096, emofile); if (bufread == 4096) return { buf ,buf + 1024 }; LibDLVoiceCodecThrow("emo index out of range") } LibDLVoiceCodecThrow("emo file not opened") } private: FILE* emofile = nullptr; }; class TextToSpeech : public MoeVoiceStudioModule { public: using DurationCallback = std::function&)>; TextToSpeech(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_ = 0); [[nodiscard]] std::vector GetInputSeqs(const MJson& _Input, const MoeVSProjectSpace::MoeVSParams& _InitParams) const; std::vector& SpecializeInputSeqs(std::vector& _Seq) const; [[nodiscard]] static std::vector GetInputSeqsStatic(const MJson& _Input, const MoeVSProjectSpace::MoeVSParams& _InitParams); static std::vector> generatePath(float* duration, size_t durationSize, size_t maskSize); [[nodiscard]] std::vector GetEmotionVector(const std::vector& src) const; [[nodiscard]] std::vector> Inference(const std::wstring& _Seq, const MoeVSProjectSpace::MoeVSParams& _InferParams = MoeVSProjectSpace::MoeVSParams()) const; [[nodiscard]] std::vector Inference(const std::wstring& _Seq, const MoeVSProjectSpace::MoeVSParams& _InferParams, bool T) const; [[nodiscard]] std::vector> Inference(const MJson& _Inputs, const MoeVSProjectSpace::MoeVSParams& _InferParams = MoeVSProjectSpace::MoeVSParams()) const; [[nodiscard]] virtual std::vector> Inference(const std::vector& _Input) const; [[nodiscard]] std::vector Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; [[nodiscard]] static std::vector GetAligments(size_t DstLen, size_t SrcLen); [[nodiscard]] std::wstring TextNormalize(const std::wstring& _Input, int64_t LanguageId) const; [[nodiscard]] int64_t GetLanguageToneIdx(int64_t _Index) const { std::string LanguageSymb; for(const auto& i : LanguageMap) if (_Index == i.second) LanguageSymb = i.first; if (LanguageSymb.empty()) return 0; const auto Iter = LanguageTones.find(LanguageSymb); if (Iter != LanguageTones.end()) return Iter->second; return 0; } [[nodiscard]] std::vector AligPhoneAttn(const std::string& LanguageStr, const std::vector& PhoneSeq, size_t BertSize) const; static int64_t find_max_idx(const std::vector& inp) { int64_t idx = 0; for (size_t i = 1; i < inp.size(); ++i) if (inp[i] > inp[idx]) idx = int64_t(i); return idx; } ~TextToSpeech() override = default; template void LinearCombination(std::vector& _data, T Value = T(1.0)) const { _data.resize(SpeakerCount, 0.f); if (_data.empty()) { _data = std::vector(1, Value); return; } T Sum = T(0.0); for (const auto& i : _data) Sum += i; if (Sum < T(0.0001)) { _data = std::vector(_data.size(), T(0.0)); _data[0] = Value; return; } Sum *= T(Value); for (auto& i : _data) i /= Sum; } [[nodiscard]] const MoeVSG2P::Tokenizer& GetTokenizer(const std::string& LanguageId) const { return Tokenizers.at(LanguageTokenizerMap.at(LanguageId)); } [[nodiscard]] static std::tuple, std::vector> SplitTonesFromTokens(const std::vector& _Src, const std::vector& _ToneRef, int64_t FirstToneIdx, const std::string& LanguageSymbol); protected: DurationCallback CustomDurationCallback; int64_t SpeakerCount = 1; std::unordered_map SpeakerMap; std::map LanguageTokenizerMap; std::map LanguageMap = { {"ZH", 0}, {"JP", 1}, {"EN", 2} }; std::map LanguageTones = { {"ZH", 0}, {"JP", 0}, {"EN", 0} }; std::map Tokenizers; MoeVSG2P::MVSCleaner* Cleaner = nullptr; bool AddBlank = true; bool Emotion = false; std::map Symbols; EmoLoader EmoLoader; MJson EmoJson; }; MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/header/Tacotron.hpp ================================================ #pragma once #include "ModelBase.hpp" INFERCLASSHEADER class Tacotron2 : public TTS { public: Tacotron2(const MJson&, const callback&, const callback_params&, const DurationCallback&, Device _dev = Device::CPU); ~Tacotron2() override; std::vector Inference(std::wstring& _inputLens) const override; [[nodiscard]] std::vector Inference(const MoeVSProject::TTSParams& _input) const override; static void cat(std::vector& tensorA, std::vector& Shape, const MTensor& tensorB) { const int64 n = Shape[1]; for (int64 i = n; i > 0; --i) tensorA.insert(tensorA.begin() + (i * Shape[2]), tensorB.GetTensorData()[i - 1]); ++Shape[2]; } private: Ort::Session* sessionEncoder = nullptr; Ort::Session* sessionDecoderIter = nullptr; Ort::Session* sessionPostNet = nullptr; Ort::Session* sessionGan = nullptr; const std::vector ganIn = { "x" }; const std::vector ganOut = { "audio" }; const std::vector inputNodeNamesSessionEncoder = { "sequences","sequence_lengths" }; const std::vector outputNodeNamesSessionEncoder = { "memory","processed_memory","lens" }; const std::vector inputNodeNamesSessionDecoderIter = { "decoder_input","attention_hidden","attention_cell","decoder_hidden","decoder_cell","attention_weights","attention_weights_cum","attention_context","memory","processed_memory","mask" }; const std::vector outputNodeNamesSessionDecoderIter = { "decoder_output","gate_prediction","out_attention_hidden","out_attention_cell","out_decoder_hidden","out_decoder_cell","out_attention_weights","out_attention_weights_cum","out_attention_context" }; const std::vector inputNodeNamesSessionPostNet = { "mel_outputs" }; const std::vector outputNodeNamesSessionPostNet = { "mel_outputs_postnet" }; }; INFERCLASSEND ================================================ FILE: libdlvoicecodec/Modules/Models/header/Vits.hpp ================================================ /** * FileName: Vits.hpp * Note: MoeVoiceStudioCore Vits模型类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2023-11-9 Create */ #pragma once #include "TTS.hpp" MoeVoiceStudioCoreHeader void SetBertEnabled(bool cond); void DestoryAllBerts(); class Vits : public TextToSpeech { public: Vits(const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); Vits(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, const std::vector& _BertPaths, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); void load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, const std::vector& _BertPaths = {}); ~Vits() override; void destory() { delete sessionDec; delete sessionSdp; delete sessionDp; delete sessionEnc_p; delete sessionFlow; delete sessionEmb; sessionDec = nullptr; sessionSdp = nullptr; sessionEnc_p = nullptr; sessionFlow = nullptr; sessionEmb = nullptr; sessionDp = nullptr; } [[nodiscard]] std::vector> Inference(const std::vector& _Input) const override; private: Ort::Session* sessionDec = nullptr; Ort::Session* sessionSdp = nullptr; Ort::Session* sessionDp = nullptr; Ort::Session* sessionEnc_p = nullptr; Ort::Session* sessionFlow = nullptr; Ort::Session* sessionEmb = nullptr; std::string VitsType; bool UseTone = false; bool UseBert = false; bool UseLength = true; bool UseLanguage = false; bool EncoderG = false; std::vector BertNames; std::vector BertNamesIdx; std::wstring ClapName; int64_t VQCodeBookSize = 10; bool UseVQ = false; bool UseClap = false; std::vector EncoderInputNames = { "x" }; const std::vector EncoderOutputNames = { "xout", "m_p", "logs_p", "x_mask" }; std::vector SdpInputNames = { "x", "x_mask", "zin" }; const std::vector SdpOutputNames = { "logw" }; std::vector DpInputNames = { "x", "x_mask" }; const std::vector DpOutputNames = { "logw" }; std::vector FlowInputNames = { "z_p", "y_mask" }; const std::vector FlowOutputNames = { "z" }; std::vector DecInputNames = { "z_in" }; const std::vector DecOutputNames = { "o" }; const std::vector EmbiddingInputNames = { "sid" }; const std::vector EmbiddingOutputNames = { "g" }; const std::vector BertInputNames = { "input_ids", "attention_mask", "token_type_ids" }; const std::vector BertInputNames2 = { "input_ids", "attention_mask" }; const std::vector BertInputNames3 = { "input_ids" }; const std::vector BertOutputNames = { "last_hidden_state" }; }; MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/header/VitsSvc.hpp ================================================ /** * FileName: VitsSvc.hpp * Note: MoeVoiceStudioCore Onnx Vits系Svc 模型定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "SVC.hpp" #ifdef WIN32 #ifdef MoeVSMui #include #include #include "../../AvCodec/Recorder.h" #endif #endif #include "DiffSvc.hpp" MoeVoiceStudioCoreHeader struct ShallowDiffusionData { std::vector _16KAudio, CUDAF0, CUDAVolume; std::vector> CUDASpeaker; bool NeedPadding = false; }; ShallowDiffusionData& GetDataForShallowDiffusion(); class VitsSvc : public SingingVoiceConversion { public: VitsSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); VitsSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); void load( const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_, bool MoeVoiceStudioFrontEnd = false ); ~VitsSvc() override; void Destory(); [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const override; [[nodiscard]] std::vector Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; //[[nodiscard]] std::vector InferSliceTensor(const MoeVSProjectSpace::MoeVSAudioSlice& _Slice, size_t SliceIdx, // const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::vector& _Tensors, // std::vector& SoVitsInput) const; [[nodiscard]] std::vector InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector MelExtractor(const float* PCMAudioBegin, const float* PCMAudioEnd) const = delete; #ifdef WIN32 #ifdef MoeVSMui void StartRT(Mui::Window::UIWindowBasic* window, const MoeVSProjectSpace::MoeVSSvcParams& _Params); void EndRT(); #endif #endif private: Ort::Session* VitsSvcModel = nullptr; std::wstring VitsSvcVersion = L"SoVits4.0"; const std::vector soVitsOutput = { "audio" }; const std::vector soVitsInput = { "hidden_unit", "lengths", "pitch", "sid" }; const std::vector RVCInput = { "phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd" }; const std::vector StftOutput = { "mel" }; const std::vector StftInput = { "waveform", "aligment"}; #ifdef WIN32 #ifdef MoeVSMui bool RTSTAT = false; std::deque> inputBuffer, outputBuffer, rawInputBuffer, rawOutputBuffer; MRecorder* recoder = nullptr; Mui::Render::MDS_AudioPlayer* audio_player = nullptr; Mui::Render::MAudioStream* audio_stream = nullptr; size_t emptyLen = 30000; #endif #endif }; MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/src/DiffSvc.cpp ================================================ #include "../header/DiffSvc.hpp" #include #include "../../AvCodec/AvCodeResample.h" #include #include "../../InferTools/Sampler/MoeVSSamplerManager.hpp" #include "../../InferTools/F0Extractor/F0ExtractorManager.hpp" #include "../EnvManager.hpp" MoeVoiceStudioCoreHeader Ort::Session* Vocoder = nullptr; void LoadVocoderModel(const std::wstring& VocoderPath) { Vocoder = new Ort::Session(*moevsenv::GetGlobalMoeVSEnv().GetEnv(), VocoderPath.c_str(), *moevsenv::GetGlobalMoeVSEnv().GetSessionOptions()); } void UnLoadVocoderModel() { delete Vocoder; Vocoder = nullptr; } bool VocoderEnabled() { return Vocoder; } void DiffusionSvc::Destory() { //AudioEncoder delete hubert; hubert = nullptr; //DiffusionModel delete encoder; //Encoder encoder = nullptr; delete denoise; //WaveNet denoise = nullptr; delete pred; //PndmNoisePredictor pred = nullptr; delete after; //AfterProcess after = nullptr; delete alpha; //AlphasCumpord alpha = nullptr; delete naive; //NaiveShallowDiffusion naive = nullptr; //SingleDiffusionModel delete diffSvc; diffSvc = nullptr; } DiffusionSvc::~DiffusionSvc() { logger.log(L"[Info] unloading DiffSvc Models"); Destory(); logger.log(L"[Info] DiffSvc Models unloaded"); } DiffusionSvc::DiffusionSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_): SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioDiffSingingVoiceConversion"); //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)") if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String") const auto _folder = to_wide_string(_Config["Folder"].GetString()); if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty") const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; const auto cluster_folder = GetCurrentFolder() + L"/Models/" + _folder; if (_Config["Hubert"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Hubert\" (Hubert Folder)") if (!_Config["Hubert"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Must Be String") const std::wstring HuPath = to_wide_string(_Config["Hubert"].GetString()); if (HuPath.empty()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Can Not Be Empty") if (_Config["Hifigan"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Hifigan\" (Hifigan Folder)") if (!_Config["Hifigan"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Hifigan\" (Hifigan Folder) Must Be String") const std::wstring HifiganPath = to_wide_string(_Config["Hifigan"].GetString()); if (HifiganPath.empty()) LibDLVoiceCodecThrow("[Error] Field \"Hifigan\" (Hifigan Folder) Can Not Be Empty") std::map _PathDict; _PathDict["Cluster"] = cluster_folder; _PathDict["DiffHubert"] = GetCurrentFolder() + L"/hubert/" + HuPath + L".onnx"; _PathDict["DiffHifigan"] = GetCurrentFolder() + L"/hifigan/" + HifiganPath + L".onnx"; if(_waccess((_path + L"_encoder.onnx").c_str(), 0) != -1) { _PathDict["Encoder"] = _path + L"_encoder.onnx"; _PathDict["DenoiseFn"] = _path + L"_denoise.onnx"; _PathDict["NoisePredictor"] = _path + L"_pred.onnx"; _PathDict["AfterProcess"] = _path + L"_after.onnx"; if (_waccess((_path + L"_alpha.onnx").c_str(), 0) != -1) _PathDict["Alphas"] = _path + L"_alpha.onnx"; } else _PathDict["DiffSvc"] = _path + L"_DiffSvc.onnx"; if (_waccess((_path + L"_naive.onnx").c_str(), 0) != -1) _PathDict["Naive"] = _path + L"_naive.onnx"; load(_PathDict, _Config, _ProgressCallback); } DiffusionSvc::DiffusionSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioDiffSingingVoiceConversion"); load(_PathDict, _Config, _ProgressCallback); } void DiffusionSvc::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback) { //Check SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)") if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64") logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); if (_Config["MelBins"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"MelBins\" (MelBins)") if (_Config["MelBins"].IsInt() || _Config["MelBins"].IsInt64()) melBins = _Config["MelBins"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"MelBins\" (MelBins) Must Be Int/Int64") if (!(_Config["Hop"].IsInt() || _Config["Hop"].IsInt64())) LibDLVoiceCodecThrow("[Error] Hop Must Be Int") HopSize = _Config["Hop"].GetInt(); if (HopSize < 1) LibDLVoiceCodecThrow("[Error] Hop Must > 0") if (!(_Config["HiddenSize"].IsInt() || _Config["HiddenSize"].IsInt64())) logger.log(L"[Warn] Missing Field \"HiddenSize\", Use Default Value (256)"); else HiddenUnitKDims = _Config["HiddenSize"].GetInt(); if (_Config["Characters"].IsArray()) SpeakerCount = (int64_t)_Config["Characters"].Size(); if (_Config["Volume"].IsBool()) EnableVolume = _Config["Volume"].GetBool(); else logger.log(L"[Warn] Missing Field \"Volume\", Use Default Value (False)"); if (!_Config["CharaMix"].IsBool()) logger.log(L"[Warn] Missing Field \"CharaMix\", Use Default Value (False)"); else EnableCharaMix = _Config["CharaMix"].GetBool(); if (!_Config["Diffusion"].IsBool()) logger.log(L"[Warn] Missing Field \"Diffusion\", Use Default Value (False)"); else if (_Config["Diffusion"].GetBool()) DiffSvcVersion = L"DiffusionSvc"; if (_Config["Pndm"].IsInt()) Pndms = _Config["Pndm"].GetInt(); if (_Config.HasMember("SpecMax") && _Config["SpecMax"].IsDouble()) SpecMax = _Config["SpecMax"].GetFloat(); else logger.log(L"[Warn] Missing Field \"SpecMax\", Use Default Value (2)"); if (_Config.HasMember("SpecMin") && _Config["SpecMin"].IsDouble()) SpecMin = _Config["SpecMin"].GetFloat(); else logger.log(L"[Warn] Missing Field \"SpecMin\", Use Default Value (-12)"); _callback = _ProgressCallback; if (_Config["Cluster"].IsString()) { const auto clus = to_wide_string(_Config["Cluster"].GetString()); if (!(_Config["KMeansLength"].IsInt() || _Config["KMeansLength"].IsInt64())) logger.log(L"[Warn] Missing Field \"KMeansLength\", Use Default Value (10000)"); else ClusterCenterSize = _Config["KMeansLength"].GetInt(); try { Cluster = MoeVoiceStudioCluster::GetMoeVSCluster(clus, _PathDict.at("Cluster"), HiddenUnitKDims, ClusterCenterSize); EnableCluster = true; } catch (std::exception& e) { logger.error(e.what()); EnableCluster = false; } } //LoadModels try { logger.log(L"[Info] loading DiffSvc Models"); hubert = new Ort::Session(*env, _PathDict.at("DiffHubert").c_str(), *session_options); if (_PathDict.find("Encoder")!= _PathDict.end() && _waccess(_PathDict.at("Encoder").c_str(), 0) != -1) { encoder = new Ort::Session(*env, _PathDict.at("Encoder").c_str(), *session_options); denoise = new Ort::Session(*env, _PathDict.at("DenoiseFn").c_str(), *session_options); pred = new Ort::Session(*env, _PathDict.at("NoisePredictor").c_str(), *session_options); after = new Ort::Session(*env, _PathDict.at("AfterProcess").c_str(), *session_options); if (_PathDict.find("Alphas") != _PathDict.end() && _waccess(_PathDict.at("Alphas").c_str(), 0) != -1) alpha = new Ort::Session(*env, _PathDict.at("Alphas").c_str(), *session_options); } else diffSvc = new Ort::Session(*env, _PathDict.at("DiffSvc").c_str(), *session_options); if (_PathDict.find("Naive") != _PathDict.end() && _waccess(_PathDict.at("Naive").c_str(), 0) != -1) naive = new Ort::Session(*env, _PathDict.at("Naive").c_str(), *session_options); logger.log(L"[Info] DiffSvc Models loaded"); } catch (Ort::Exception& _exception) { Destory(); LibDLVoiceCodecThrow(_exception.what()) } if (_Config["TensorExtractor"].IsString()) DiffSvcVersion = to_wide_string(_Config["TensorExtractor"].GetString()); if (_Config["MaxStep"].IsInt()) MaxStep = _Config["MaxStep"].GetInt(); MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others _others_param; _others_param.Memory = *memory_info; try { _TensorExtractor = GetTensorExtractor(DiffSvcVersion, 48000, _samplingRate, HopSize, EnableCharaMix, EnableVolume, HiddenUnitKDims, SpeakerCount, _others_param); } catch (std::exception& e) { Destory(); LibDLVoiceCodecThrow(e.what()) } } std::vector DiffusionSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Start!"); std::vector _data; size_t total_audio_size = 0; for (const auto& data_size : _Slice.Slices) total_audio_size += data_size.OrgLen; _data.reserve(size_t(double(total_audio_size) * 1.5)); auto speedup = (int64_t)_InferParams.Pndm; auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; if (speedup >= step) speedup = step / 5; if (speedup == 0) speedup = 1; const auto RealDiffSteps = step % speedup ? step / speedup + 1 : step / speedup; if (diffSvc) _callback(0, _Slice.Slices.size()); else _callback(0, _Slice.Slices.size() * RealDiffSteps); size_t process = 0; for (const auto& CurSlice : _Slice.Slices) { const auto InferDurTime = clock(); const auto CurRtn = SliceInference(CurSlice, _InferParams, process); _data.insert(_data.end(), CurRtn.data(), CurRtn.data() + CurRtn.size()); if (CurSlice.IsNotMute) logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Segment[" + std::to_wstring(process) + L"] Finished! Segment Use Time: " + std::to_wstring(clock() - InferDurTime) + L"ms, Segment Duration: " + std::to_wstring((size_t)CurSlice.OrgLen * 1000ull / 48000ull) + L"ms"); else { if (!diffSvc) { process += RealDiffSteps; _callback(process, _Slice.Slices.size() * RealDiffSteps); } logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Jump Empty Segment[" + std::to_wstring(process) + L"]!"); } if (diffSvc) _callback(++process, _Slice.Slices.size()); } logger.log(L"[Inferring] \"" + _Slice.Path + L"\" Finished"); return _data; } std::vector DiffusionSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const { std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); auto speedup = (int64_t)_InferParams.Pndm; auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; if (speedup >= step) speedup = step / 5; if (speedup == 0) speedup = 1; if (_Slice.IsNotMute) { auto RawWav = InferTools::InterpResample(_Slice.Audio, 48000, 16000, 32768.0f); const auto src_audio_length = RawWav.size(); bool NeedPadding = false; if (_cur_execution_provider == ExecutionProviders::CUDA && !diffSvc) { NeedPadding = RawWav.size() % 16000; const size_t WavPaddedSize = RawWav.size() / 16000 + 1; if (NeedPadding) RawWav.resize(WavPaddedSize * 16000, 0.f); } const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)RawWav.size() }; std::vector HubertInputTensors, HubertOutPuts; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RawWav.data(), RawWav.size(), HubertInputShape, 3)); try { HubertOutPuts = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } const auto HubertSize = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto HubertOutPutData = HubertOutPuts[0].GetTensorMutableData(); auto HubertOutPutShape = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetShape(); HubertInputTensors.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector srcHiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; const auto max_cluster_size = int64_t((size_t)HubertOutPutShape[1] * src_audio_length / RawWav.size()); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto pts = Cluster->find(srcHiddenUnits.data(), long(SpeakerIdx), max_cluster_size); for (int64_t indexs = 0; indexs < max_cluster_size * HiddenUnitKDims; ++indexs) srcHiddenUnits[indexs] = srcHiddenUnits[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } std::vector finaOut; std::vector DiffOut; if (diffSvc) { const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; const int64_t F0Shape[] = { 1, int64_t(_Slice.Audio.size() * _samplingRate / 48000 / HopSize) }; const int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t CharaEmbShape[] = { 1 }; int64_t speedData[] = { Pndms }; auto srcF0Data = InferTools::InterpFunc(_Slice.F0, long(_Slice.F0.size()), long(F0Shape[1])); for (auto& it : srcF0Data) it *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); auto InterpedF0 = MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::GetInterpedF0log(srcF0Data, true); auto alignment = MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::GetAligments(F0Shape[1], HubertLen); std::vector TensorsInp; int64_t Chara[] = { SpeakerIdx }; TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, srcHiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, alignment.data(), F0Shape[1], F0Shape, 2)); TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, Chara, 1, CharaEmbShape, 1)); TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), F0Shape[1], F0Shape, 2)); std::vector initial_noise(melBins * F0Shape[1], 0.0); long long noise_shape[4] = { 1,1,melBins,F0Shape[1] }; if (!naive) { for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4)); } else MoeVSNotImplementedError TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, speedData, 1, CharaEmbShape, 1)); try { DiffOut = diffSvc->Run(Ort::RunOptions{ nullptr }, DiffInput.data(), TensorsInp.data(), TensorsInp.size(), DiffOutput.data(), DiffOutput.size()); } catch (Ort::Exception& e2) { LibDLVoiceCodecThrow((std::string("Locate: Diff\n") + e2.what())) } try { finaOut = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), DiffOut.data(), DiffOut.size(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } } else { MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::InferParams _Inference_Params; _Inference_Params.AudioSize = _Slice.Audio.size(); _Inference_Params.Chara = SpeakerIdx; _Inference_Params.NoiseScale = _InferParams.NoiseScale; _Inference_Params.DDSPNoiseScale = _InferParams.DDSPNoiseScale; _Inference_Params.Seed = int(_InferParams.Seed); _Inference_Params.upKeys = _InferParams.Keys; MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Inputs InputTensors; if (_cur_execution_provider == ExecutionProviders::CUDA && NeedPadding) { auto CUDAF0 = _Slice.F0; auto CUDAVolume = _Slice.Volume; auto CUDASpeaker = _Slice.Speaker; const auto src_src_audio_length = _Slice.Audio.size(); const size_t WavPaddedSize = ((src_src_audio_length / 48000) + 1) * 48000; const size_t AudioPadSize = WavPaddedSize - src_src_audio_length; const size_t PaddedF0Size = CUDAF0.size() + (CUDAF0.size() * AudioPadSize / src_src_audio_length); if (!CUDAF0.empty()) CUDAF0.resize(PaddedF0Size, 0.f); if (!CUDAVolume.empty()) CUDAVolume.resize(PaddedF0Size, 0.f); for (auto iSpeaker : CUDASpeaker) { if (!iSpeaker.empty()) iSpeaker.resize(PaddedF0Size, 0.f); } _Inference_Params.AudioSize = WavPaddedSize; InputTensors = _TensorExtractor->Extract(srcHiddenUnits, CUDAF0, CUDAVolume, CUDASpeaker, _Inference_Params); } else InputTensors = _TensorExtractor->Extract(srcHiddenUnits, _Slice.F0, _Slice.Volume, _Slice.Speaker, _Inference_Params); std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputTensors.InputNames, InputTensors.Tensor.data(), min(InputTensors.Tensor.size(), encoder->GetInputCount()), InputTensors.OutputNames, InputTensors.OutputCount); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } if (EncoderOut.size() == 1) EncoderOut.emplace_back(Ort::Value::CreateTensor(*memory_info, InputTensors.Data.F0.data(), InputTensors.Data.FrameShape[1], InputTensors.Data.FrameShape.data(), 2)); std::vector DenoiseInTensors; DenoiseInTensors.emplace_back(std::move(EncoderOut[0])); std::vector initial_noise(melBins * InputTensors.Data.FrameShape[1], 0.0); long long noise_shape[4] = { 1,1,melBins,InputTensors.Data.FrameShape[1] }; if (!naive) { for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; DenoiseInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4)); } else { std::vector NaiveOut; try { NaiveOut = naive->Run(Ort::RunOptions{ nullptr }, InputTensors.InputNames, InputTensors.Tensor.data(), min(InputTensors.Tensor.size(), naive->GetInputCount()), naiveOutput.data(), 1); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: naive\n") + e1.what())) } DenoiseInTensors.emplace_back(std::move(NaiveOut[0])); } auto PredOut = MoeVSSampler::GetMoeVSSampler((!alpha ? L"Pndm" : _InferParams.Sampler), alpha, denoise, pred, melBins, _callback, memory_info)->Sample(DenoiseInTensors, step, speedup, _InferParams.NoiseScale, _InferParams.Seed, _Process); try { DiffOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), PredOut.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } DiffOut.emplace_back(std::move(EncoderOut[1])); try { finaOut = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), DiffOut.data(), DiffOut.size(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } } const auto shapeOut = finaOut[0].GetTensorTypeAndShapeInfo().GetShape(); const auto dstWavLen = (_Slice.OrgLen * int64_t(_samplingRate)) / 48000; std::vector TempVecWav(dstWavLen, 0); if (shapeOut[2] < dstWavLen) for (int64_t bbb = 0; bbb < shapeOut[2]; bbb++) TempVecWav[bbb] = static_cast(Clamp(finaOut[0].GetTensorData()[bbb]) * 32766.f); else for (int64_t bbb = 0; bbb < dstWavLen; bbb++) TempVecWav[bbb] = static_cast(Clamp(finaOut[0].GetTensorData()[bbb]) * 32766.f); return TempVecWav; } const auto len = size_t(_Slice.OrgLen * int64_t(_samplingRate) / 48000); return { len, 0i16, std::allocator() }; } std::vector DiffusionSvc::Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { std::vector _Lens = GetOpenFileNameMoeVS(); std::vector AudioFolders; for (auto& path : _Lens) { path = std::regex_replace(path, std::wregex(L"\\\\"), L"/"); auto PCMData = AudioPreprocess().codec(path, 48000); auto SlicePos = SliceAudio(PCMData, _SlicerSettings); auto Audio = GetAudioSlice(PCMData, SlicePos, _SlicerSettings); Audio.Path = path; PreProcessAudio(Audio); std::vector _data = SliceInference(Audio, _InferParams); std::wstring OutFolder = GetCurrentFolder() + L"/Outputs/" + path.substr(path.rfind(L'/') + 1, path.rfind(L'.') - path.rfind(L'/') - 1); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; OutFolder += L"-Params-(-NoiseScale=" + std::to_wstring(_InferParams.NoiseScale) + L"-Speaker=" + (EnableCharaMix ? std::wstring(L"SpeakerMix") : std::to_wstring(SpeakerIdx)) + L"-Seed=" + std::to_wstring(_InferParams.Seed) + L"-Sampler=" + _InferParams.Sampler + L"-F0Method=" + _InferParams.F0Method + L")"; if (_waccess((OutFolder + L".wav").c_str(), 0) != -1) { for (size_t idx = 0; idx < 99999999; ++idx) if (_waccess((OutFolder + L" (" + std::to_wstring(idx) + L").wav").c_str(), 0) == -1) { OutFolder += L" (" + std::to_wstring(idx) + L").wav"; break; } } else OutFolder += L".wav"; AudioFolders.emplace_back(OutFolder); InferTools::Wav::WritePCMData(_samplingRate, 1, _data, OutFolder); } return AudioFolders; } std::vector DiffusionSvc::InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { if (diffSvc || DiffSvcVersion != L"DiffusionSvc") return PCMData; auto hubertin = InferTools::InterpResample(PCMData, srcSr, 16000); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); const int64_t inputShape[3] = { 1i64,1i64,(int64_t)hubertin.size() }; std::vector inputTensorshu; inputTensorshu.emplace_back(Ort::Value::CreateTensor(*memory_info, hubertin.data(), hubertin.size(), inputShape, 3)); std::vector hubertOut; const auto RealDiffSteps = _InferParams.Step % _InferParams.Pndm ? _InferParams.Step / _InferParams.Pndm + 1 : _InferParams.Step / _InferParams.Pndm; _callback(0, RealDiffSteps); try { hubertOut = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), inputTensorshu.data(), inputTensorshu.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } const auto HubertSize = hubertOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto HubertOutPutData = hubertOut[0].GetTensorMutableData(); const auto HubertOutPutShape = hubertOut[0].GetTensorTypeAndShapeInfo().GetShape(); inputTensorshu.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector HiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto clus_size = HubertOutPutShape[1]; const auto pts = Cluster->find(HiddenUnits.data(), long(SpeakerIdx), clus_size); for (size_t indexs = 0; indexs < HiddenUnits.size(); ++indexs) HiddenUnits[indexs] = HiddenUnits[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; const int64_t F0Shape[] = { 1, int64_t(PCMData.size() / HopSize) }; const int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t CharaEmbShape[] = { 1 }; const int64_t CharaMixShape[] = { F0Shape[1], SpeakerCount }; const auto F0Extractor = MoeVSF0Extractor::GetF0Extractor(_InferParams.F0Method, _samplingRate, HopSize); auto F0Data = F0Extractor->ExtractF0(PCMData, PCMData.size() / HopSize); for (auto& ifo : F0Data) ifo *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); F0Data = _TensorExtractor->GetInterpedF0(InferTools::InterpFunc(F0Data, long(F0Data.size()), long(F0Shape[1]))); std::vector Alignment = _TensorExtractor->GetAligments(F0Shape[1], HubertLen); int64_t CharaEmb[] = { SpeakerIdx }; std::vector EncoderTensors; EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Alignment.data(), F0Shape[1], F0Shape, 2 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, F0Data.data(), F0Shape[1], F0Shape, 2 )); std::vector InputNamesEncoder; std::vector Volume, SpkMap; if (EnableVolume) { InputNamesEncoder = { "hubert", "mel2ph", "f0", "volume", "spk_mix" }; Volume = ExtractVolume(PCMData, HopSize); if (abs(int64_t(Volume.size()) - int64_t(F0Data.size())) > 3) Volume = InferTools::InterpFunc(ExtractVolume(PCMData, HopSize), long(Volume.size()), long(F0Shape[1])); else Volume.resize(F0Data.size(), 0.f); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Volume.data(), F0Shape[1], F0Shape, 2 )); } else InputNamesEncoder = { "hubert", "mel2ph", "f0", "spk_mix" }; if (EnableCharaMix) { SpkMap = _TensorExtractor->GetCurrectSpkMixData(std::vector>(), F0Shape[1], SpeakerIdx); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, SpkMap.data(), SpkMap.size(), CharaMixShape, 2 )); } else { EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, CharaEmb, 1, CharaEmbShape, 1 )); } const std::vector OutputNamesEncoder = { "mel_pred" }; std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputNamesEncoder.data(), EncoderTensors.data(), min(EncoderTensors.size(), encoder->GetInputCount()), OutputNamesEncoder.data(), 1); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } EncoderOut.emplace_back(Ort::Value::CreateTensor(*memory_info, F0Data.data(), F0Shape[1], F0Shape, 2)); std::vector DenoiseInTensors; DenoiseInTensors.emplace_back(std::move(EncoderOut[0])); std::vector initial_noise(melBins * F0Shape[1], 0.0); long long noise_shape[4] = { 1,1,melBins,F0Shape[1] }; if (!naive) { for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; DenoiseInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4)); } else { std::vector NaiveOut; try { NaiveOut = naive->Run(Ort::RunOptions{ nullptr }, InputNamesEncoder.data(), EncoderTensors.data(), min(EncoderTensors.size(), naive->GetInputCount()), naiveOutput.data(), 1); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: naive\n") + e1.what())) } DenoiseInTensors.emplace_back(std::move(NaiveOut[0])); } size_t process = 0; auto PredOut = MoeVSSampler::GetMoeVSSampler((!alpha ? L"Pndm" : _InferParams.Sampler), alpha, denoise, pred, melBins, _callback, memory_info)->Sample(DenoiseInTensors, (int64_t)_InferParams.Step, (int64_t)_InferParams.Pndm, _InferParams.NoiseScale, _InferParams.Seed, process); std::vector DiffOut, finaOut; try { DiffOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), PredOut.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } DiffOut.emplace_back(std::move(EncoderOut[1])); try { finaOut = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), DiffOut.data(), DiffOut.size(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } const auto dstWavLen = finaOut[0].GetTensorTypeAndShapeInfo().GetShape()[2]; std::vector TempVecWav(dstWavLen, 0); for (int64_t bbb = 0; bbb < dstWavLen; bbb++) TempVecWav[bbb] = static_cast(Clamp(finaOut[0].GetTensorData()[bbb]) * 32766.0f); return TempVecWav; } void DiffusionSvc::NormMel(std::vector& MelSpec) const { for (auto& it : MelSpec) it = (it - SpecMin) / (SpecMax - SpecMin) * 2 - 1; } std::vector DiffusionSvc::ShallowDiffusionInference( std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize ) const { if (diffSvc || DiffSvcVersion != L"DiffusionSvc") LibDLVoiceCodecThrow("ShallowDiffusion Only Support DiffusionSvc Model") std::vector InputNamesEncoder; const auto _Mel_Size = _Mel.second; std::vector HubertInputTensors, HubertOutputTensors; const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)_16KAudioHubert.size() }; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _16KAudioHubert.data(), _16KAudioHubert.size(), HubertInputShape, 3)); try { HubertOutputTensors = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; const auto HubertLength = HubertOutputTensors[0].GetTensorTypeAndShapeInfo().GetShape()[1]; const int64_t FrameShape[] = { 1, _Mel_Size }; const int64_t CharaMixShape[] = { _Mel_Size, SpeakerCount }; constexpr int64_t OneShape[] = { 1 }; int64_t CharaEmb[] = { SpeakerIdx }; auto Alignment = _TensorExtractor->GetAligments(_Mel_Size, HubertLength); Alignment.resize(FrameShape[1]); auto F0Data = InferTools::InterpFunc(_SrcF0, long(_SrcF0.size()), long(FrameShape[1])); std::vector Volume, SpkMap; std::vector EncoderTensors; EncoderTensors.emplace_back(std::move(HubertOutputTensors[0])); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Alignment.data(), FrameShape[1], FrameShape, 2 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, F0Data.data(), FrameShape[1], FrameShape, 2 )); if (EnableVolume) { InputNamesEncoder = { "hubert", "mel2ph", "f0", "volume", "spk_mix" }; Volume = InferTools::InterpFunc(_SrcVolume, long(_SrcVolume.size()), long(FrameShape[1])); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Volume.data(), FrameShape[1], FrameShape, 2 )); } else InputNamesEncoder = { "hubert", "mel2ph", "f0", "spk_mix" }; if (EnableCharaMix) { SpkMap = _TensorExtractor->GetCurrectSpkMixData(_SrcSpeakerMap, FrameShape[1], CharaEmb[0]); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, SpkMap.data(), SpkMap.size(), CharaMixShape, 2 )); } else { EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, CharaEmb, 1, OneShape, 1 )); } const std::vector OutputNamesEncoder = { "mel_pred" }; std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputNamesEncoder.data(), EncoderTensors.data(), min(EncoderTensors.size(), encoder->GetInputCount()), OutputNamesEncoder.data(), 1); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } std::vector DenoiseInTensors; DenoiseInTensors.emplace_back(std::move(EncoderOut[0])); long long noise_shape[4] = { 1,1,melBins,_Mel_Size }; NormMel(_Mel.first); /*std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); std::vector initial_noise(melBins * _Mel_Size, 0.0); for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; DenoiseInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4));*/ DenoiseInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _Mel.first.data(), _Mel.first.size(), noise_shape, 4)); auto PredOut = MoeVSSampler::GetMoeVSSampler((!alpha ? L"Pndm" : _InferParams.Sampler), alpha, denoise, pred, melBins, [](size_t, size_t) {}, memory_info)->Sample(DenoiseInTensors, (int64_t)_InferParams.Step, (int64_t)_InferParams.Pndm, _InferParams.NoiseScale, _InferParams.Seed, Process); std::vector DiffOut, finaOut; try { DiffOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), PredOut.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } DiffOut.emplace_back(std::move(EncoderTensors[2])); try { finaOut = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), DiffOut.data(), DiffOut.size(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } const auto shapeOut = finaOut[0].GetTensorTypeAndShapeInfo().GetShape(); std::vector TempVecWav(SrcSize, 0); if (shapeOut[2] < SrcSize) for (int64_t bbb = 0; bbb < shapeOut[2]; bbb++) TempVecWav[bbb] = static_cast(Clamp(finaOut[0].GetTensorData()[bbb]) * 32766.f); else for (int64_t bbb = 0; bbb < SrcSize; bbb++) TempVecWav[bbb] = static_cast(Clamp(finaOut[0].GetTensorData()[bbb]) * 32766.f); return TempVecWav; } MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/src/GPT-SoVits.cpp ================================================ #include "../header/GPT-SoVits.hpp" #include "../../InferTools/inferTools.hpp" #include #include MoeVoiceStudioCoreHeader GptSoVits::~GptSoVits() { logger.log(L"[Info] unloading GptSoVits Models"); destory(); logger.log(L"[Info] GptSoVits Models unloaded"); } GptSoVits::GptSoVits(const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : TextToSpeech(ExecutionProvider_, DeviceID_, ThreadCount_) { //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)"); if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String"); const auto _folder = to_wide_string(_Config["Folder"].GetString()); if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty"); const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; std::map _PathDict; _PathDict["SSL"] = GetCurrentFolder() + L"/Bert/" + L"SSLModel.onnx"; _PathDict["Vits"] = _path + L"_vits.onnx"; _PathDict["Encoder"] = _path + L"_t2s_encoder.onnx"; _PathDict["FDecoder"] = _path + L"_t2s_fsdec.onnx"; _PathDict["Decoder"] = _path + L"_t2s_sdec.onnx"; if (_Config.HasMember("Dict") && _Config["Dict"].IsString() && !_Config["Dict"].Empty()) _PathDict["Dict"] = GetCurrentFolder() + L"/Dict/" + to_wide_string(_Config["Dict"].GetString()) + L".json"; if (_Config.HasMember("BertPath") && _Config["BertPath"].IsString() && !_Config["BertPath"].Empty()) _PathDict["Bert"] = GetCurrentFolder() + L"/Bert/" + to_wide_string(_Config["BertPath"].GetString()); else LibDLVoiceCodecThrow("[Error] Missing field \"BertPath\" (Bert Folder)"); load(_PathDict, _Config, _ProgressCallback, _DurationCallback); } void GptSoVits::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback) { Cleaner = MoeVSG2P::GetDefCleaner(); if (_PathDict.find("Dict") != _PathDict.end() && (_waccess(_PathDict.at("Dict").c_str(), 0) != -1)) Cleaner->loadDict(_PathDict.at("Dict")); else Cleaner->loadDict(L""); if (_Config.HasMember("LanguageMap") && !_Config["LanguageMap"].IsNull()) for (const auto& CMember : _Config["LanguageMap"].GetMemberArray()) LanguageMap[CMember.first] = CMember.second.GetInt(); else logger.log("[Warn] Field \"LanguageMap\" Is Missing, Use Default Value"); //Check SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)"); if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64"); logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); //Check Symbol if (!_Config.HasMember("Symbol") || _Config["Symbol"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Symbol\" (PhSymbol)"); if (_Config.HasMember("AddBlank") && !_Config["AddBlank"].IsNull()) AddBlank = _Config["AddBlank"].GetBool(); else logger.log(L"[Warn] Field \"AddBlank\" Is Missing, Use Default Value"); if (_Config.HasMember("NumLayers") && _Config["NumLayers"].IsInt()) NumLayers = _Config["NumLayers"].GetInt(); else logger.log(L"[Warn] Field \"NumLayers\" Is Missing, Use Default Value"); if (_Config.HasMember("EmbeddingDim") && _Config["EmbeddingDim"].IsInt()) EmbeddingDim = _Config["EmbeddingDim"].GetInt(); else logger.log(L"[Warn] Field \"EmbeddingDim\" Is Missing, Use Default Value"); if (_Config.HasMember("EOSId") && _Config["EOSId"].IsInt()) EOSId = _Config["EOSId"].GetInt(); else logger.log(L"[Warn] Field \"EOSId\" Is Missing, Use Default Value"); //Load Symbol int64_t iter_symb = 0; if (_Config["Symbol"].IsArray()) { logger.log(L"[Info] Use Phs"); if (_Config["Symbol"].Empty()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Can Not Be Empty"); const auto SymbolArr = _Config["Symbol"].GetArray(); if (!SymbolArr[0].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Must Be Array or String"); for (const auto& it : SymbolArr) Symbols.insert({ to_wide_string(it.GetString()), iter_symb++ }); } else { if (!_Config["Symbol"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Must Be Array or String"); logger.log(L"[Info] Use Symbols"); const std::wstring SymbolsStr = to_wide_string(_Config["Symbol"].GetString()); if (SymbolsStr.empty()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Can Not Be Empty"); for (size_t i = 0; i < SymbolsStr.length(); ++i) Symbols.insert({ SymbolsStr.substr(i,1) , iter_symb++ }); } if (_Config.HasMember("Characters") && _Config["Characters"].IsArray()) { SpeakerCount = (int64_t)_Config["Characters"].Size(); int64_t SpkIdx = 0; for (const auto& iterator : _Config["Characters"].GetArray()) SpeakerMap[to_wide_string(iterator.GetString())] = SpkIdx++; } try { sessionBert = new Ort::Session(*env, (_PathDict.at("Bert") + L"/model.onnx").c_str(), *session_options); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(e.what()); } if (_waccess((_PathDict.at("Bert") + L"/Tokenizer.json").c_str(), 0) != -1) { Tokenizers.insert({ L"0" ,_PathDict.at("Bert") + L"/Tokenizer.json" }); Tokenizers[L"0"].BondCleaner(Cleaner); } else if (sessionBert) { delete sessionBert; sessionBert = nullptr; LibDLVoiceCodecThrow("Bert Must Have a Tokenizer"); } _callback = _ProgressCallback; CustomDurationCallback = _DurationCallback; //LoadModels try { logger.log(L"[Info] loading GptSoVits Models"); sessionVits = new Ort::Session(*env, _PathDict.at("Vits").c_str(), *session_options); sessionSSL = new Ort::Session(*env, _PathDict.at("SSL").c_str(), *session_options); sessionEncoder = new Ort::Session(*env, _PathDict.at("Encoder").c_str(), *session_options); sessionDecoder = new Ort::Session(*env, _PathDict.at("Decoder").c_str(), *session_options); sessionFDecoder = new Ort::Session(*env, _PathDict.at("FDecoder").c_str(), *session_options); logger.log(L"[Info] GptSoVits Models loaded"); } catch (Ort::Exception& _exception) { destory(); LibDLVoiceCodecThrow(_exception.what()); } SpeakerCount = 0; } GptSoVits::GptSoVits(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : TextToSpeech(ExecutionProvider_, DeviceID_, ThreadCount_) { load(_PathDict, _Config, _ProgressCallback, _DurationCallback); } std::wregex NCH_Regex(L"[^\\u4e00-\\u9fa5 !@#$%^&*()_+\\-=`~,./;'\\[\\]<>?:\"{}|\\\\。?!,、;:“”‘’『』「」()〔〕【】─…·—~《》〈〉]+"); std::set ZH_Vowel{L'a', L'e', L'i', L'o', L'u', L'A', L'E', L'I', L'O', L'U'}; std::set Byte_Symbol{L',', L'.', L'?', L'/', L'\"', L'\'', L';', L':', L'!', L' ', L'…' }; std::unordered_map ToneRepMap{ { L"[acc_6]", 6 }, { L"[acc_5]", 5 }, { L"[acc_4]", 4 }, { L"[acc_3]", 3 }, { L"[acc_2]", 2 }, { L"[acc_1]", 1 }, { L"[acc_-4]", -4 }, { L"[acc_-3]", -3 }, { L"[acc_-2]", -2 }, { L"[acc_-1]", -1 }, }; std::tuple, std::vector> GptSoVits::GetBertPhs(const MoeVSProjectSpace::MoeVSTTSSeq& Seq, const MoeVSG2P::Tokenizer& Tokenizer) const { std::vector Phonemes; std::vector OutBert; if (sessionBert && Seq.LanguageSymbol == "ZH") { std::vector Bert2Ph; std::vector BertSeq; std::vector GlobalTonesSeq; if (Seq.SlicedTokens.empty()) { std::wstring TextSeq = MoeVSG2P::NormalizeText(Seq.TextSeq, "ZH"); if (std::regex_search(TextSeq, NCH_Regex)) LibDLVoiceCodecThrow("Chinese Sentence ShouldNot Have NonChinese Symbols"); Phonemes = MoeVSG2P::GetDefCleaner()->DictReplace(MoeVSG2P::GetDefCleaner()->G2p(TextSeq, Seq.PlaceHolderSymbol, L"wt", "ZH"), Seq.PlaceHolderSymbol); std::vector LocalTonesSeq; std::vector LocalPhonemeSeq; for (const auto& it : Phonemes) { if (ToneRepMap.find(it) == ToneRepMap.end()) { LocalPhonemeSeq.emplace_back(it); LocalTonesSeq.emplace_back(0); } else if (!LocalTonesSeq.empty()) *(LocalTonesSeq.end() - 1) = ToneRepMap.at(it); } if (LocalTonesSeq.size() != LocalPhonemeSeq.size()) LocalTonesSeq.resize(LocalPhonemeSeq.size(), 0); Phonemes = std::move(LocalPhonemeSeq); GlobalTonesSeq = std::move(LocalTonesSeq); const size_t BertSize = TextSeq.length() + 2, PhoneSize = Phonemes.size(); Bert2Ph.resize(PhoneSize, 0); size_t startFrame = 1; for (size_t iph = 0; iph < Phonemes.size(); ++iph) { if (startFrame == BertSize) LibDLVoiceCodecThrow("AligError"); Bert2Ph[iph] = startFrame; if (!Phonemes[iph].empty() && ZH_Vowel.find(Phonemes[iph][0]) != ZH_Vowel.end()) ++startFrame; else if (Byte_Symbol.find(Phonemes[iph][0]) != Byte_Symbol.end()) ++startFrame; else if (Phonemes[iph] == L"[UNK]") ++startFrame; } BertSeq.resize(BertSize); BertSeq[0] = L"[CLS]"; for (size_t iph = 0; iph < Phonemes.size(); ++iph) if (BertSeq[Bert2Ph[iph]].empty()) BertSeq[Bert2Ph[iph]] = TextSeq[Bert2Ph[iph] - 1]; BertSeq[BertSeq.size() - 1] = L"[SEP]"; } else { size_t startFrame = 1; for(const auto& i : Seq.SlicedTokens) { BertSeq.emplace_back(i.Text); if (i.Text == L"[CLS]") continue; if (i.Text == L"[SEP]") break; if(i.Phonemes.empty()) { if(i.Text.empty()) continue; auto TmpPhonemes = MoeVSG2P::GetDefCleaner()->DictReplace(MoeVSG2P::GetDefCleaner()->G2p(i.Text, Seq.PlaceHolderSymbol, L"wt", "ZH"), Seq.PlaceHolderSymbol); std::vector LocalTonesSeq; std::vector LocalPhonemeSeq; for (const auto& it : TmpPhonemes) { if (ToneRepMap.find(it) == ToneRepMap.end()) { LocalPhonemeSeq.emplace_back(it); LocalTonesSeq.emplace_back(0); } else if (!LocalTonesSeq.empty()) *(LocalTonesSeq.end() - 1) = ToneRepMap.at(it); } if (LocalTonesSeq.size() != LocalPhonemeSeq.size()) LocalTonesSeq.resize(LocalPhonemeSeq.size(), 0); for (auto& ph : LocalPhonemeSeq) { Phonemes.emplace_back(std::move(ph)); Bert2Ph.emplace_back(startFrame); } for (const auto& tones : LocalTonesSeq) GlobalTonesSeq.emplace_back(tones); } else { for (const auto& ph : i.Phonemes) { Phonemes.emplace_back(ph); Bert2Ph.emplace_back(startFrame); } auto LocalTonesSeq = i.Tones; LocalTonesSeq.resize(i.Phonemes.size(), 0); for (const auto& tones : LocalTonesSeq) GlobalTonesSeq.emplace_back(tones); } ++startFrame; } } for (size_t i = 0; i < Phonemes.size(); ++i) { if (GlobalTonesSeq[i] == 5) continue; if (GlobalTonesSeq[i] != 0) Phonemes[i] += std::to_wstring(GlobalTonesSeq[i]); } //PromptSeq To Bert Features auto input_ids = Tokenizer(BertSeq); std::vector attention_mask(input_ids.size(), 1), token_type_ids(input_ids.size(), 0); int64_t AttentionShape[2] = { 1, (int64_t)input_ids.size() }; std::vector AttentionInput, AttentionOutput; AttentionInput.emplace_back(Ort::Value::CreateTensor( *memory_info, input_ids.data(), input_ids.size(), AttentionShape, 2)); if (sessionBert->GetInputCount() == 3) AttentionInput.emplace_back(Ort::Value::CreateTensor(*memory_info, attention_mask.data(), attention_mask.size(), AttentionShape, 2)); AttentionInput.emplace_back(Ort::Value::CreateTensor( *memory_info, token_type_ids.data(), token_type_ids.size(), AttentionShape, 2)); logger.log("[Inference] Infer Bert"); try { if (sessionBert->GetInputCount() == 3) { AttentionOutput = sessionBert->Run(Ort::RunOptions{ nullptr }, BertInputNames.data(), AttentionInput.data(), 3, BertOutputNames.data(), 1); } else if (sessionBert->GetInputCount() == 2) { AttentionOutput = sessionBert->Run(Ort::RunOptions{ nullptr }, BertInputNames2.data(), AttentionInput.data(), 2, BertOutputNames.data(), 1); } else { AttentionOutput = sessionBert->Run(Ort::RunOptions{ nullptr }, BertInputNames3.data(), AttentionInput.data(), 1, BertOutputNames.data(), 1); } } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Bert\n") + e.what())) } std::vector BertAligSeq; if (AddBlank) BertAligSeq.emplace_back(0); for(auto i : Bert2Ph) { BertAligSeq.emplace_back(i); if (AddBlank) BertAligSeq.emplace_back(i); } const auto AttnData = AttentionOutput[0].GetTensorData(); for (size_t IndexOfSrcVector = 0; IndexOfSrcVector < BertAligSeq.size(); ++IndexOfSrcVector) OutBert.insert(OutBert.end(), AttnData + BertAligSeq[IndexOfSrcVector] * 1024, AttnData + (BertAligSeq[IndexOfSrcVector] + 1) * 1024); } else { if (Seq.SlicedTokens.empty()) { if (Seq.TextSeq.empty()) return {}; Phonemes = MoeVSG2P::GetDefCleaner()->DictReplace(MoeVSG2P::GetDefCleaner()->G2p(Seq.TextSeq, Seq.PlaceHolderSymbol, Seq.AdditionalInfo, Seq.LanguageSymbol), Seq.PlaceHolderSymbol); } else { for (const auto& i : Seq.SlicedTokens) { if (i.Text == L"[CLS]") continue; if (i.Text == L"[SEP]") break; auto TmpPhonemes = i.Phonemes; if (TmpPhonemes.empty()) { if (i.Text.empty()) continue; TmpPhonemes = MoeVSG2P::GetDefCleaner()->DictReplace(MoeVSG2P::GetDefCleaner()->G2p(i.Text, Seq.PlaceHolderSymbol, Seq.AdditionalInfo, Seq.LanguageSymbol), Seq.PlaceHolderSymbol); } for (auto& ph : TmpPhonemes) Phonemes.emplace_back(ph); } } } //Phoneme To InputSeq std::vector OutPhonemes; if (AddBlank) OutPhonemes.emplace_back(0); for (const auto& i : Phonemes) { if (Symbols.find(i) != Symbols.end()) OutPhonemes.emplace_back(Symbols.at(i)); else OutPhonemes.emplace_back(0); if(AddBlank) OutPhonemes.emplace_back(0); } if (OutBert.empty()) OutBert = std::vector(OutPhonemes.size() * 1024, 0.f); return { std::move(OutBert), std::move(OutPhonemes) }; } std::vector> GptSoVits::Inference(const std::vector& _Input) const { if (_Input.size() < 3 || _Input[0].TextSeq.empty() || _Input[1].TextSeq.empty()) LibDLVoiceCodecThrow("Input[0] Should Be Reference Text, Input[1] Should Be Reference Path, Input[2:n] Should Be TTS Text"); const auto RefAudio = InferTools::Wav(_Input[1].TextSeq.c_str()); if (RefAudio.getHeader().bitsPerSample != 16 || RefAudio.getHeader().NumOfChan != 1) LibDLVoiceCodecThrow("RefAudio Should Be signed-int16 and mono"); std::vector> PCM; PCM.reserve(_Input.size()); std::vector> _Audio(1); logger.log("[Inference] GptSoVits Inference Begin"); size_t proc = 0; const size_t max_proc = _Input.size() + 2; _callback(proc, max_proc); const auto& Tokenizer = Tokenizers.at(L"0"); const auto RefSize = RefAudio.getHeader().Subchunk2Size / 2; const auto RefData = (const int16_t*)RefAudio.getData(); std::vector RefAudioSrc(RefSize); for (size_t i = 0; i < RefSize; ++i) RefAudioSrc[i] = float(*(RefData + i)) / 32768.f; auto RefAudio16K = InferTools::InterpResample(RefAudioSrc, (int)RefAudio.getHeader().SamplesPerSec, 16000, 1.f); auto RefAudioSr = InferTools::InterpResample(RefAudioSrc, (int)RefAudio.getHeader().SamplesPerSec, _samplingRate, 1.f); //Reference SSL logger.log("[Inference] Infer SSL"); const int64_t SSLShape[] = { 1, (int64_t)RefAudio16K.size() }; std::vector SSLInput, SSLOutPut; SSLInput.emplace_back(Ort::Value::CreateTensor(*memory_info, RefAudio16K.data(), RefAudio16K.size(), SSLShape, 2)); try { SSLOutPut = sessionSSL->Run(Ort::RunOptions{ nullptr }, SSLInputNames.data(), SSLInput.data(), SSLInputNames.size(), SSLOutputNames.data(), SSLOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: SSL\n") + e.what())) } _callback(++proc, max_proc); logger.log("[Inference] Infer Ref Data"); auto RefDat = GetBertPhs(_Input[0], Tokenizer); std::vector RefBert = std::move(std::get<0>(RefDat)); std::vector RefSeq = std::move(std::get<1>(RefDat)); int64_t RefSeqShape[] = { 1, (int64_t)RefSeq.size() }; int64_t RefBertShape[] = { RefSeqShape[1], 1024 }; int64_t TempData[] = { 1 }; _callback(++proc, max_proc); std::vector EncoderInpTensor; EncoderInpTensor.emplace_back(Ort::Value::CreateTensor(*memory_info, RefSeq.data(), RefSeq.size(), RefSeqShape, 2)); EncoderInpTensor.emplace_back(Ort::Value::CreateTensor(*memory_info, TempData, 1, TempData, 1)); EncoderInpTensor.emplace_back(Ort::Value::CreateTensor(*memory_info, RefBert.data(), RefBert.size(), RefBertShape, 2)); EncoderInpTensor.emplace_back(Ort::Value::CreateTensor(*memory_info, TempData, 1, TempData, 1)); EncoderInpTensor.emplace_back(std::move(SSLOutPut[0])); for (size_t i = 2; i < _Input.size(); ++i) { const auto& InferSeq = _Input[i]; auto SeqAndBert = GetBertPhs(InferSeq, Tokenizer); std::vector InputBert = std::move(std::get<0>(SeqAndBert)); std::vector InputSeq = std::move(std::get<1>(SeqAndBert)); int64_t SeqShape[] = { 1, (int64_t)InputSeq.size() }; int64_t BertShape[] = { SeqShape[1], 1024 }; EncoderInpTensor[1] = Ort::Value::CreateTensor(*memory_info, InputSeq.data(), InputSeq.size(), SeqShape, 2); EncoderInpTensor[3] = Ort::Value::CreateTensor(*memory_info, InputBert.data(), InputBert.size(), BertShape, 2); std::vector EncoderOutput, FDecoderOutput, DecoderOutput; try { EncoderOutput = sessionEncoder->Run(Ort::RunOptions{ nullptr }, EncoderInputNames.data(), EncoderInpTensor.data(), EncoderInputNames.size(), EncoderOutputNames.data(), EncoderOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Encoder\n") + e.what())) } try { FDecoderOutput = sessionFDecoder->Run(Ort::RunOptions{ nullptr }, FDecoderInputNames.data(), EncoderOutput.data(), FDecoderInputNames.size(), FDecoderOutputNames.data(), FDecoderOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: FDecoder\n") + e.what())) } int64_t idx = 1; for (; idx < InferSeq.MaxDecodeStep; ++idx) { try { DecoderOutput = sessionDecoder->Run(Ort::RunOptions{ nullptr }, DecoderInputNames.data(), FDecoderOutput.data(), DecoderInputNames.size(), DecoderOutputNames.data(), DecoderOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Decoder\n") + e.what())) } const auto Logit = DecoderOutput[4].GetTensorData(); int64_t MaxIdx = 0; for (int64_t midx = 0; midx < EOSId + 1; ++midx) if (Logit[midx] > Logit[MaxIdx]) MaxIdx = midx; if (MaxIdx == EOSId) break; if (*DecoderOutput[5].GetTensorData() == EOSId) break; FDecoderOutput[0] = std::move(DecoderOutput[0]); FDecoderOutput[1] = std::move(DecoderOutput[1]); FDecoderOutput[2] = std::move(DecoderOutput[2]); FDecoderOutput[3] = std::move(DecoderOutput[3]); } auto PredSemanticPtr = DecoderOutput[0].GetTensorData(); auto PredSemanticShape = DecoderOutput[0].GetTensorTypeAndShapeInfo().GetShape(); PredSemanticShape.insert(PredSemanticShape.begin(), 1); std::vector PredSemantic(PredSemanticPtr + max((PredSemanticShape[2] - idx - 1), 0), PredSemanticPtr + PredSemanticShape[2]); if (PredSemantic[PredSemantic.size() - 1] == EOSId) PredSemantic[PredSemantic.size() - 1] = 0; PredSemanticShape[2] = int64_t(PredSemantic.size()); std::vector VitsTensors; VitsTensors.emplace_back(std::move(EncoderInpTensor[1])); VitsTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, PredSemantic.data(), PredSemantic.size(), PredSemanticShape.data(), PredSemanticShape.size())); int64_t AudioShape[] = { 1, (int64_t)RefAudioSr.size() }; VitsTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RefAudioSr.data(), RefAudioSr.size(), AudioShape, 2)); try { VitsTensors = sessionVits->Run(Ort::RunOptions{ nullptr }, VitsInputNames.data(), VitsTensors.data(), VitsInputNames.size(), VitsOutputNames.data(), VitsOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: SoVits\n") + e.what())) } if (!_Audio[0].empty()) { if (InferSeq.RestTime < 0.f) { _Audio[0].insert(_Audio[0].end(), size_t(_samplingRate), 0); PCM.emplace_back(std::move(_Audio[0])); _Audio[0] = std::vector(); } else _Audio[0].insert(_Audio[0].end(), size_t(InferSeq.RestTime * float(_samplingRate)), 0); } const auto shapeOut = VitsTensors[0].GetTensorTypeAndShapeInfo().GetShape(); const auto outData = VitsTensors[0].GetTensorData(); for (int bbb = 0; bbb < shapeOut[0]; bbb++) _Audio[0].emplace_back(static_cast(outData[bbb] * 32768.0f)); _callback(++proc, max_proc); } if (!_Audio[0].empty()) { _Audio[0].insert(_Audio[0].end(), size_t(_samplingRate), 0); PCM.emplace_back(std::move(_Audio[0])); } return PCM; } MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/src/ModelBase.cpp ================================================ #include "../header/ModelBase.hpp" #include #include "../EnvManager.hpp" MoeVoiceStudioCoreHeader MoeVoiceStudioModule::MoeVoiceStudioModule(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) { moevsenv::GetGlobalMoeVSEnv().Load(ThreadCount_, DeviceID_, (unsigned)ExecutionProvider_); _cur_execution_provider = ExecutionProvider_; env = moevsenv::GetGlobalMoeVSEnv().GetEnv(); memory_info = moevsenv::GetGlobalMoeVSEnv().GetMemoryInfo(); session_options = moevsenv::GetGlobalMoeVSEnv().GetSessionOptions(); } MoeVoiceStudioModule::~MoeVoiceStudioModule() { env = nullptr; memory_info = nullptr; session_options = nullptr; } std::vector MoeVoiceStudioModule::CutLens(const std::wstring& input) { std::vector _Lens; std::wstring _tmpLen; for (const auto& chari : input) { if ((chari == L'\n') || (chari == L'\r')) { if (!_tmpLen.empty()) { _Lens.push_back(_tmpLen); _tmpLen = L""; } } else { _tmpLen += chari; } } return _Lens; } std::vector MoeVoiceStudioModule::GetOpenFileNameMoeVS() { constexpr long MaxPath = 8000; std::vector OFNLIST; #ifdef WIN32 std::vector szFileName(MaxPath); std::vector szTitleName(MaxPath); OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lpstrFile = szFileName.data(); ofn.nMaxFile = MaxPath; ofn.lpstrFileTitle = szTitleName.data(); ofn.nMaxFileTitle = MaxPath; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = nullptr; constexpr TCHAR szFilter[] = TEXT("Audio (*.wav;*.mp3;*.ogg;*.flac;*.aac)\0*.wav;*.mp3;*.ogg;*.flac;*.aac\0"); ofn.lpstrFilter = szFilter; ofn.lpstrTitle = nullptr; ofn.lpstrDefExt = TEXT("wav"); ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER; if (GetOpenFileName(&ofn)) { auto filePtr = szFileName.data(); std::wstring preFix = filePtr; filePtr += preFix.length() + 1; if (!*filePtr) OFNLIST.emplace_back(preFix); else { preFix += L'\\'; while (*filePtr != 0) { std::wstring thisPath(filePtr); OFNLIST.emplace_back(preFix + thisPath); filePtr += thisPath.length() + 1; } } } if(OFNLIST.empty()) LibDLVoiceCodecThrow("Please Select Files"); return OFNLIST; #else #endif } std::vector MoeVoiceStudioModule::Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { MoeVSNotImplementedError; } /* int OnnxModule::InsertMessageToEmptyEditBox(std::wstring& _inputLens) { #ifdef WIN32 std::vector szFileName(MaxPath); std::vector szTitleName(MaxPath); OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lpstrFile = szFileName.data(); ofn.nMaxFile = MaxPath; ofn.lpstrFileTitle = szTitleName.data(); ofn.nMaxFileTitle = MaxPath; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = nullptr; constexpr TCHAR szFilter[] = TEXT("Audio (*.wav;*.mp3;*.ogg;*.flac;*.aac)\0*.wav;*.mp3;*.ogg;*.flac;*.aac\0"); ofn.lpstrFilter = szFilter; ofn.lpstrTitle = nullptr; ofn.lpstrDefExt = TEXT("wav"); ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER; if (GetOpenFileName(&ofn)) { auto filePtr = szFileName.data(); std::wstring preFix = filePtr; filePtr += preFix.length() + 1; if (!*filePtr) _inputLens = preFix; else { preFix += L'\\'; while (*filePtr != 0) { std::wstring thisPath(filePtr); _inputLens += preFix + thisPath + L'\n'; filePtr += thisPath.length() + 1; } } } else return -2; return 0; #else #endif } */ /* void OnnxModule::ChangeDevice(Device _dev) { if (_dev == device_) return; device_ = _dev; delete session_options; delete env; delete memory_info; env = nullptr; session_options = nullptr; memory_info = nullptr; switch (_dev) { case Device::CUDA: { const auto AvailableProviders = Ort::GetAvailableProviders(); bool ret = true; for (const auto& it : AvailableProviders) if (it.find("CUDA") != std::string::npos) ret = false; if (ret) LibDLVoiceCodecThrow("CUDA Provider Not Found"); OrtCUDAProviderOptions cuda_option; cuda_option.device_id = int(__MoeVSGPUID); session_options = new Ort::SessionOptions; env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); session_options->AppendExecutionProvider_CUDA(cuda_option); session_options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); session_options->SetIntraOpNumThreads(1); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); break; } #ifdef MOEVSDMLPROVIDER case Device::DML: { const auto AvailableProviders = Ort::GetAvailableProviders(); std::string ret; for (const auto& it : AvailableProviders) if (it.find("Dml") != std::string::npos) ret = it; if (ret.empty()) LibDLVoiceCodecThrow("DML Provider Not Found"); const OrtApi& ortApi = Ort::GetApi(); const OrtDmlApi* ortDmlApi = nullptr; ortApi.GetExecutionProviderApi("DML", ORT_API_VERSION, reinterpret_cast(&ortDmlApi)); const Ort::ThreadingOptions threadingOptions; env = new Ort::Env(threadingOptions, ORT_LOGGING_LEVEL_VERBOSE, ""); env->DisableTelemetryEvents(); session_options = new Ort::SessionOptions; ortDmlApi->SessionOptionsAppendExecutionProvider_DML(*session_options, int(__MoeVSGPUID)); session_options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); session_options->DisablePerSessionThreads(); session_options->SetExecutionMode(ORT_SEQUENTIAL); session_options->DisableMemPattern(); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU)); break; } #endif default: { session_options = new Ort::SessionOptions; env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); session_options->SetIntraOpNumThreads(static_cast(__MoeVSNumThreads)); session_options->SetGraphOptimizationLevel(ORT_ENABLE_ALL); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); break; } } } */ MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/src/MoeVSProject.cpp ================================================ #include "../header/MoeVSProject.hpp" #include "../../InferTools/inferTools.hpp" #include namespace MoeVSProjectSpace { MoeVSProject::MoeVSProject(const std::wstring& _path) { FileWrapper project_file(_path.c_str(), L"rb"); if (!project_file.IsOpen()) LibDLVoiceCodecThrow("File Doesn't Exists"); fseek(project_file, 0, SEEK_SET); if (fread(&moevs_proj_header_, 1, sizeof(Header), project_file) != sizeof(Header)) LibDLVoiceCodecThrow("Unexpected EOF"); if (!(moevs_proj_header_.ChunkSymbol[0] == 'M' && moevs_proj_header_.ChunkSymbol[1] == 'O' && moevs_proj_header_.ChunkSymbol[2] == 'E' && moevs_proj_header_.ChunkSymbol[3] == 'V' && moevs_proj_header_.ChunkSymbol[4] == 'S' && moevs_proj_header_.ChunkSymbol[5] == 'P' && moevs_proj_header_.ChunkSymbol[6] == 'R' && moevs_proj_header_.ChunkSymbol[7] == 'J')) LibDLVoiceCodecThrow("Unrecognized File"); if (moevs_proj_header_.DataHeaderAmount == 0) LibDLVoiceCodecThrow("Empty Project"); data_pos_ = std::vector(moevs_proj_header_.DataHeaderAmount); if (fread(data_pos_.data(), 1, sizeof(size_type) * (moevs_proj_header_.DataHeaderAmount), project_file) != sizeof(size_type) * (moevs_proj_header_.DataHeaderAmount)) LibDLVoiceCodecThrow("Unexpected EOF"); data_chunk_begin_ = sizeof(Header) + sizeof(size_type) * (moevs_proj_header_.DataHeaderAmount); size_type _n_bytes = 0; const size_type _data_begin = data_chunk_begin_; fseek(project_file, long(_data_begin), SEEK_SET); for (const auto& _pos_index : data_pos_) { Data _datas; //Header if (fread(&_datas.Header, 1, sizeof(DataHeader), project_file) != sizeof(DataHeader)) LibDLVoiceCodecThrow("Unexpected EOF"); if (!(_datas.Header.ChunkSymbol[0] == 'D' && _datas.Header.ChunkSymbol[1] == 'A' && _datas.Header.ChunkSymbol[2] == 'T' && _datas.Header.ChunkSymbol[3] == 'A')) LibDLVoiceCodecThrow("Unrecognized File"); _datas.ParamData.Slices.resize(_datas.Header.OrgLenSize); //Audio if (_datas.Header.OrgAudioOffsetPosSize != 0) { _datas.Offset.OrgAudio = std::vector(_datas.Header.OrgAudioOffsetPosSize); _n_bytes = sizeof(size_type) * _datas.Header.OrgAudioOffsetPosSize; if (fread(_datas.Offset.OrgAudio.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); size_t _data_idx = 0; for (const auto& j : _datas.Offset.OrgAudio) { if (!j) continue; std::vector hs_vector(j); _n_bytes = sizeof(int16_t) * j; if (fread(hs_vector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); _datas.ParamData.Slices[_data_idx].Audio = std::move(hs_vector); _data_idx += 1; } } //F0 if (_datas.Header.F0OffsetPosSize != 0) { _datas.Offset.F0 = std::vector(_datas.Header.F0OffsetPosSize); _n_bytes = sizeof(size_type) * _datas.Header.F0OffsetPosSize; if (fread(_datas.Offset.F0.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); size_t _data_idx = 0; for (const auto& j : _datas.Offset.F0) { if (!j) continue; std::vector f0_vector(j); _n_bytes = sizeof(float) * j; if (fread(f0_vector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); _datas.ParamData.Slices[_data_idx].F0 = std::move(f0_vector); _data_idx += 1; } } //Volume if (_datas.Header.VolumeOffsetPosSize != 0) { _datas.Offset.Volume = std::vector(_datas.Header.VolumeOffsetPosSize); _n_bytes = sizeof(size_type) * _datas.Header.VolumeOffsetPosSize; if (fread(_datas.Offset.Volume.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); size_t _data_idx = 0; for (const auto& j : _datas.Offset.Volume) { if (!j) continue; std::vector Volume_vector(j); _n_bytes = sizeof(float) * j; if (fread(Volume_vector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); _datas.ParamData.Slices[_data_idx].Volume = std::move(Volume_vector); _data_idx += 1; } } //ChrarcterMix if (_datas.Header.CharacterOffsetPosSize != 0) { _datas.Offset.Speaker = std::vector(_datas.Header.CharacterOffsetPosSize); _n_bytes = sizeof(size_type) * _datas.Header.CharacterOffsetPosSize; if (fread(_datas.Offset.Speaker.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); size_t _data_idx = 0; for (const auto& j : _datas.Offset.Speaker) { if (!j) continue; size_type NSpeaker = 0; if (fread(&NSpeaker, 1, sizeof(size_type), project_file) != sizeof(size_type)) LibDLVoiceCodecThrow("Unexpected EOF"); if (!NSpeaker) continue; std::vector Speaker_vector(j); _n_bytes = sizeof(float) * j; if (fread(Speaker_vector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); std::vector> SpkVec; if (!Speaker_vector.empty()) { const auto frames = Speaker_vector.size() / NSpeaker; for (size_t idxs = 0; idxs < NSpeaker; ++idxs) SpkVec.emplace_back(Speaker_vector.data() + idxs * frames, Speaker_vector.data() + (idxs + 1) * frames); } _datas.ParamData.Slices[_data_idx].Speaker = std::move(SpkVec); _data_idx += 1; } } //OrgLen if (_datas.Header.OrgLenSize != 0) { std::vector OrgLen(_datas.Header.OrgLenSize); _n_bytes = sizeof(long) * _datas.Header.OrgLenSize; if (fread(OrgLen.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); for (size_t _data_idx = 0; _data_idx < OrgLen.size(); ++_data_idx) _datas.ParamData.Slices[_data_idx].OrgLen = OrgLen[_data_idx]; } //Symbol if (_datas.Header.SymbolSize != 0) { std::vector BooleanVector(_datas.Header.SymbolSize); _n_bytes = _datas.Header.SymbolSize; if (fread(BooleanVector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); for (size_t _data_idx = 0; _data_idx < BooleanVector.size(); ++_data_idx) _datas.ParamData.Slices[_data_idx].IsNotMute = BooleanVector[_data_idx]; } //path if (_datas.Header.PathSize != 0) { std::vector PathStr(_datas.Header.PathSize); _n_bytes = _datas.Header.PathSize; if (fread(PathStr.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); _datas.ParamData.Path = to_wide_string(PathStr.data()); } data_.emplace_back(std::move(_datas)); } } MoeVSProject::MoeVSProject(const std::vector& _params) { moevs_proj_header_.DataHeaderAmount = size_type(_params.size()); data_chunk_begin_ = sizeof(Header) + sizeof(size_type) * (moevs_proj_header_.DataHeaderAmount); data_pos_.push_back(0); size_type _offset = 0; for (const auto& i : _params) { Data _data; _data.ParamData = i; for (const auto& SliceData : i.Slices) { _data.Offset.OrgAudio.push_back(SliceData.Audio.size()); _data.Offset.F0.push_back(SliceData.F0.size()); _data.Offset.Volume.push_back(SliceData.Volume.size()); size_t size__ = 0; for (auto& Speaker : SliceData.Speaker) { size__ += Speaker.size(); } _data.Offset.Speaker.push_back(size__); } _data.Header.OrgAudioOffsetPosSize = _data.Offset.OrgAudio.size(); _data.Header.F0OffsetPosSize = _data.Offset.F0.size(); _data.Header.VolumeOffsetPosSize = _data.Offset.Volume.size(); _data.Header.CharacterOffsetPosSize = _data.Offset.Speaker.size(); _data.Header.OrgLenSize = i.Slices.size(); _data.Header.SymbolSize = i.Slices.size(); const std::string bytePath = to_byte_string(i.Path); _data.Header.PathSize = bytePath.length() + 1; _offset += _data.Size(); data_pos_.push_back(_offset); data_.emplace_back(std::move(_data)); } data_pos_.pop_back(); } void MoeVSProject::Write(const std::wstring& _path) const { FILE* project_file = nullptr; _wfopen_s(&project_file, _path.c_str(), L"wb"); if (!project_file) LibDLVoiceCodecThrow("Cannot Create File"); fwrite(&moevs_proj_header_, 1, sizeof(Header), project_file); fwrite(data_pos_.data(), 1, data_pos_.size() * sizeof(size_type), project_file); for (const auto& i : data_) { fwrite(&i.Header, 1, sizeof(DataHeader), project_file); fwrite(i.Offset.OrgAudio.data(), 1, sizeof(size_type) * i.Offset.OrgAudio.size(), project_file); for (const auto& orgaudio : i.ParamData.Slices) fwrite(orgaudio.Audio.data(), 1, orgaudio.Audio.size() * sizeof(int16_t), project_file); fwrite(i.Offset.F0.data(), 1, sizeof(size_type) * i.Offset.F0.size(), project_file); for (const auto& f0 : i.ParamData.Slices) fwrite(f0.F0.data(), 1, f0.F0.size() * sizeof(float), project_file); if (i.Header.VolumeOffsetPosSize != 0) { fwrite(i.Offset.Volume.data(), 1, sizeof(size_type) * i.Offset.Volume.size(), project_file); for (const auto& volume : i.ParamData.Slices) fwrite(volume.Volume.data(), 1, volume.Volume.size() * sizeof(float), project_file); } if (i.Header.CharacterOffsetPosSize != 0) { fwrite(i.Offset.Speaker.data(), 1, sizeof(size_type) * i.Offset.Speaker.size(), project_file); for (const auto& Speaker : i.ParamData.Slices) { if (Speaker.Speaker.empty()) continue; const size_type NSPK = Speaker.Speaker.size(); fwrite(&NSPK, 1, sizeof(size_type), project_file); for (const auto& Spkk : Speaker.Speaker) fwrite(Spkk.data(), 1, Spkk.size() * sizeof(float), project_file); } } assert(i.ParamData.Slices.size() == i.Header.OrgLenSize); std::vector CurOrgLen(i.Header.OrgLenSize); for (size_t index = 0; index < i.ParamData.Slices.size(); ++index) CurOrgLen[index] = i.ParamData.Slices[index].OrgLen; fwrite(CurOrgLen.data(), 1, sizeof(long) * CurOrgLen.size(), project_file); assert(i.ParamData.Slices.size() == i.Header.SymbolSize); std::vector BooleanVector(i.Header.SymbolSize); for (size_t index = 0; index < i.ParamData.Slices.size(); ++index) BooleanVector[index] = i.ParamData.Slices[index].IsNotMute ? 1 : 0; fwrite(BooleanVector.data(), 1, i.Header.SymbolSize, project_file); const std::string bytePath = to_byte_string(i.ParamData.Path); fwrite(bytePath.data(), 1, i.Header.PathSize, project_file); } fclose(project_file); } std::wstring MoeVSTTSToken::Serialization() const { if (Text.empty()) return L"\t\t\t{ }"; std::wstring rtn = L"\t\t\t{\n"; rtn += L"\t\t\t\t\"Text\": \"" + Text + L"\",\n"; rtn += L"\t\t\t\t\"Phonemes\": " + wstring_vector_to_string(Phonemes) + L",\n"; rtn += L"\t\t\t\t\"Tones\": " + vector_to_string(Tones) + L",\n"; rtn += L"\t\t\t\t\"Durations\": " + vector_to_string(Durations) + L",\n"; rtn += L"\t\t\t\t\"Language\": " + string_vector_to_string(Language) + L"\n\t\t\t}"; return rtn; } MoeVSTTSToken::MoeVSTTSToken(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams) { if (_JsonDocument.HasMember("Text") && _JsonDocument["Text"].IsString() && !_JsonDocument["Text"].Empty()) Text = to_wide_string(_JsonDocument["Text"].GetString()); else LibDLVoiceCodecThrow("Field \"Text\" Should Not Be Empty") if (_JsonDocument.HasMember("Phonemes") && _JsonDocument["Phonemes"].IsArray()) for (const auto& j : _JsonDocument["Phonemes"].GetArray()) Phonemes.emplace_back(j.IsString() ? to_wide_string(j.GetString()) : L"[UNK]"); if (_JsonDocument.HasMember("Tones") && _JsonDocument["Tones"].IsArray()) for (const auto& j : _JsonDocument["Tones"].GetArray()) Tones.emplace_back(j.IsInt() ? j.GetInt() : 0); if (_JsonDocument.HasMember("Durations") && _JsonDocument["Durations"].IsArray()) for (const auto& j : _JsonDocument["Durations"].GetArray()) Durations.emplace_back(j.IsInt() ? j.GetInt() : 0); if (_JsonDocument.HasMember("Language") && _JsonDocument["Language"].IsArray()) { const auto LanguageArr = _JsonDocument["Language"].GetArray(); if (!LanguageArr.empty() && LanguageArr[0].IsString()) for (const auto& j : LanguageArr) Language.emplace_back(j.GetString()); } } std::wstring MoeVSTTSSeq::Serialization() const { if (TextSeq.empty()) return L""; std::wstring rtn = L"\t{\n"; rtn += L"\t\t\"TextSeq\": \"" + TextSeq + L"\",\n"; rtn += L"\t\t\"SlicedTokens\": [\n"; for (const auto& iter : SlicedTokens) rtn += iter.Serialization() + L",\n"; if (!SlicedTokens.empty()) rtn.erase(rtn.end() - 2); rtn += L"\t\t],\n"; rtn += L"\t\t\"SpeakerMix\": " + vector_to_string(SpeakerMix) + L",\n"; rtn += L"\t\t\"EmotionPrompt\": " + wstring_vector_to_string(EmotionPrompt) + L",\n"; rtn += L"\t\t\"NoiseScale\": " + std::to_wstring(NoiseScale) + L",\n"; rtn += L"\t\t\"LengthScale\": " + std::to_wstring(LengthScale) + L",\n"; rtn += L"\t\t\"DurationPredictorNoiseScale\": " + std::to_wstring(DurationPredictorNoiseScale) + L",\n"; rtn += L"\t\t\"FactorDpSdp\": " + std::to_wstring(FactorDpSdp) + L",\n"; rtn += L"\t\t\"GateThreshold\": " + std::to_wstring(GateThreshold) + L",\n"; rtn += L"\t\t\"MaxDecodeStep\": " + std::to_wstring(MaxDecodeStep) + L",\n"; rtn += L"\t\t\"Seed\": " + std::to_wstring(Seed) + L",\n"; rtn += L"\t\t\"SpeakerName\": \"" + SpeakerName + L"\",\n"; rtn += L"\t\t\"RestTime\": " + std::to_wstring(RestTime) + L",\n"; rtn += L"\t\t\"PlaceHolderSymbol\": \"" + PlaceHolderSymbol + L"\",\n"; rtn += L"\t\t\"LanguageSymbol\": \"" + to_wide_string(LanguageSymbol) + L"\",\n"; rtn += L"\t\t\"G2PAdditionalInfo\": \"" + AdditionalInfo + L"\"\n\t}"; return rtn; } MoeVSTTSSeq::MoeVSTTSSeq(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams) { if (_JsonDocument.HasMember("LanguageSymbol") && _JsonDocument["LanguageSymbol"].IsString() && !_JsonDocument["LanguageSymbol"].Empty()) LanguageSymbol = _JsonDocument["LanguageSymbol"].GetString(); else LanguageSymbol = _InitParams.LanguageSymbol; if (_JsonDocument.HasMember("G2PAdditionalInfo") && _JsonDocument["G2PAdditionalInfo"].IsString() && !_JsonDocument["G2PAdditionalInfo"].Empty()) AdditionalInfo = to_wide_string(_JsonDocument["G2PAdditionalInfo"].GetString()); else AdditionalInfo = _InitParams.AdditionalInfo; if (_JsonDocument.HasMember("PlaceHolderSymbol") && _JsonDocument["PlaceHolderSymbol"].IsString() && !_JsonDocument["PlaceHolderSymbol"].Empty()) PlaceHolderSymbol = to_wide_string(_JsonDocument["PlaceHolderSymbol"].GetString()); else PlaceHolderSymbol = _InitParams.PlaceHolderSymbol; if (_JsonDocument.HasMember("TextSeq") && _JsonDocument["TextSeq"].IsString() && !_JsonDocument["TextSeq"].Empty()) TextSeq = to_wide_string(_JsonDocument["TextSeq"].GetString()); else LibDLVoiceCodecThrow("Field \"TextSeq\" Should Not Be Empty") if (_JsonDocument.HasMember("SlicedTokens") && _JsonDocument["SlicedTokens"].IsArray()) { const auto TokensArrayObject = _JsonDocument["SlicedTokens"].GetArray(); for (const auto& iter : TokensArrayObject) SlicedTokens.emplace_back(iter, _InitParams); } if (_JsonDocument.HasMember("SpeakerMix") && _JsonDocument["SpeakerMix"].IsArray()) for (const auto& j : _JsonDocument["SpeakerMix"].GetArray()) SpeakerMix.emplace_back(j.IsFloat() ? j.GetFloat() : 0.f); else SpeakerMix = _InitParams.SpeakerMix; if (_JsonDocument.HasMember("EmotionPrompt") && _JsonDocument["EmotionPrompt"].IsArray()) for (const auto& j : _JsonDocument["EmotionPrompt"].GetArray()) EmotionPrompt.emplace_back(j.IsString() ? to_wide_string(j.GetString()) : std::wstring()); else EmotionPrompt = _InitParams.EmotionPrompt; if (_JsonDocument.HasMember("NoiseScale") && _JsonDocument["NoiseScale"].IsFloat()) NoiseScale = _JsonDocument["NoiseScale"].GetFloat(); else NoiseScale = _InitParams.NoiseScale; if (_JsonDocument.HasMember("LengthScale") && _JsonDocument["LengthScale"].IsFloat()) LengthScale = _JsonDocument["LengthScale"].GetFloat(); else LengthScale = _InitParams.LengthScale; if (_JsonDocument.HasMember("RestTime") && _JsonDocument["RestTime"].IsFloat()) RestTime = _JsonDocument["RestTime"].GetFloat(); else RestTime = _InitParams.RestTime; if (_JsonDocument.HasMember("DurationPredictorNoiseScale") && _JsonDocument["DurationPredictorNoiseScale"].IsFloat()) DurationPredictorNoiseScale = _JsonDocument["DurationPredictorNoiseScale"].GetFloat(); else DurationPredictorNoiseScale = _InitParams.DurationPredictorNoiseScale; if (_JsonDocument.HasMember("FactorDpSdp") && _JsonDocument["FactorDpSdp"].IsFloat()) FactorDpSdp = _JsonDocument["FactorDpSdp"].GetFloat(); else FactorDpSdp = _InitParams.FactorDpSdp; if (_JsonDocument.HasMember("GateThreshold") && _JsonDocument["GateThreshold"].IsFloat()) GateThreshold = _JsonDocument["GateThreshold"].GetFloat(); else GateThreshold = _InitParams.GateThreshold; if (_JsonDocument.HasMember("MaxDecodeStep") && _JsonDocument["MaxDecodeStep"].IsFloat()) MaxDecodeStep = _JsonDocument["MaxDecodeStep"].GetInt(); else MaxDecodeStep = _InitParams.MaxDecodeStep; if (_JsonDocument.HasMember("Seed") && _JsonDocument["Seed"].IsInt()) Seed = _JsonDocument["Seed"].GetInt(); else Seed = _InitParams.Seed; if (_JsonDocument.HasMember("SpeakerName") && _JsonDocument["SpeakerName"].IsString()) SpeakerName = to_wide_string(_JsonDocument["SpeakerName"].GetString()); else SpeakerName = _InitParams.SpeakerName; if (MaxDecodeStep < 2000) MaxDecodeStep = 2000; if (MaxDecodeStep > 20000) MaxDecodeStep = 20000; if (GateThreshold > 0.90f) GateThreshold = 0.90f; if (GateThreshold < 0.2f) GateThreshold = 0.2f; if (FactorDpSdp > 1.f) FactorDpSdp = 1.f; if (FactorDpSdp < 0.f) FactorDpSdp = 0.f; if (NoiseScale > 10.f) NoiseScale = 10.f; if (NoiseScale < 0.f) NoiseScale = 0.f; if (DurationPredictorNoiseScale > 10.f) DurationPredictorNoiseScale = 10.f; if (DurationPredictorNoiseScale < 0.f) DurationPredictorNoiseScale = 0.f; if (RestTime > 30.f) RestTime = 30.f; if (LengthScale > 10.f) LengthScale = 10.f; if (LengthScale < 0.1f) LengthScale = 0.1f; } bool MoeVSTTSSeq::operator==(const MoeVSTTSSeq& right) const { return Serialization() == right.Serialization(); } } ================================================ FILE: libdlvoicecodec/Modules/Models/src/SVC.cpp ================================================ #include "../header/SVC.hpp" #include "../../InferTools/F0Extractor/F0ExtractorManager.hpp" MoeVoiceStudioCoreHeader SingingVoiceConversion::SingingVoiceConversion(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : MoeVoiceStudioModule(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioSingingVoiceConversion"); } SingingVoiceConversion::~SingingVoiceConversion() { delete hubert; hubert = nullptr; } std::vector SingingVoiceConversion::Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { MoeVSNotImplementedError; } std::vector SingingVoiceConversion::InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { MoeVSNotImplementedError; } std::vector SingingVoiceConversion::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { MoeVSNotImplementedError; } std::vector SingingVoiceConversion::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const { MoeVSNotImplementedError; } std::vector SingingVoiceConversion::ExtractVolume(const std::vector& OrgAudio, int hop_size) { std::vector Audio; Audio.reserve(OrgAudio.size() * 2); Audio.insert(Audio.end(), hop_size, double(OrgAudio[0]) / 32768.); for (const auto i : OrgAudio) Audio.emplace_back((double)i / 32768.); Audio.insert(Audio.end(), hop_size, double(OrgAudio[OrgAudio.size() - 1]) / 32768.); const size_t n_frames = (OrgAudio.size() / hop_size) + 1; std::vector volume(n_frames); for (auto& i : Audio) i = pow(i, 2); int64_t index = 0; for (auto& i : volume) { i = sqrt((float)InferTools::getAvg(Audio.begin()._Ptr + index * hop_size, Audio.begin()._Ptr + (index + 1) * hop_size)); ++index; } return volume; } std::vector SingingVoiceConversion::ExtractVolume(const std::vector& OrgAudio) const { std::vector Audio; Audio.reserve(OrgAudio.size() * 2); Audio.insert(Audio.end(), HopSize, OrgAudio[0]); Audio.insert(Audio.end(), OrgAudio.begin(), OrgAudio.end()); Audio.insert(Audio.end(), HopSize, OrgAudio[OrgAudio.size() - 1]); const size_t n_frames = (OrgAudio.size() / HopSize) + 1; std::vector volume(n_frames); for (auto& i : Audio) i = pow(i, 2); int64_t index = 0; for (auto& i : volume) { i = sqrt((float)InferTools::getAvg(Audio.begin()._Ptr + index * HopSize, Audio.begin()._Ptr + (index + 1) * HopSize)); ++index; } return volume; } MoeVSProjectSpace::MoeVoiceStudioSvcData SingingVoiceConversion::GetAudioSlice(const std::vector& input, const std::vector& _slice_pos, const InferTools::SlicerSettings& _slicer) { MoeVSProjectSpace::MoeVoiceStudioSvcData audio_slice; for (size_t i = 1; i < _slice_pos.size(); i++) { MoeVSProjectSpace::MoeVoiceStudioSvcSlice _CurSlice; const bool is_not_mute = abs(InferTools::getAvg((input.data() + _slice_pos[i - 1]), (input.data() + _slice_pos[i]))) > _slicer.Threshold; _CurSlice.IsNotMute = is_not_mute; _CurSlice.OrgLen = long(_slice_pos[i] - _slice_pos[i - 1]); if (is_not_mute) _CurSlice.Audio = { (input.data() + _slice_pos[i - 1]), (input.data() + _slice_pos[i]) }; else _CurSlice.Audio.clear(); audio_slice.Slices.emplace_back(std::move(_CurSlice)); } return audio_slice; } void SingingVoiceConversion::PreProcessAudio(MoeVSProjectSpace::MoeVoiceStudioSvcData& input, int __SamplingRate, int __HopSize, const std::wstring& _f0_method) { const auto F0Extractor = MoeVSF0Extractor::GetF0Extractor(_f0_method, __SamplingRate, __HopSize); const auto num_slice = input.Slices.size(); for (size_t i = 0; i < num_slice; ++i) { if (input.Slices[i].IsNotMute) { input.Slices[i].F0 = F0Extractor->ExtractF0(input.Slices[i].Audio, input.Slices[i].Audio.size() / __HopSize); input.Slices[i].Volume = ExtractVolume(input.Slices[i].Audio, __HopSize); } else { input.Slices[i].F0.clear(); input.Slices[i].Volume.clear(); } input.Slices[i].Speaker.clear(); } } MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/src/TTS.cpp ================================================ #include "../header/TTS.hpp" #include MoeVoiceStudioCoreHeader std::unordered_map _ACCMAP{ { L"[acc_6]", 6 }, { L"[acc_5]", 5 }, { L"[acc_4]", 4 }, { L"[acc_3]", 3 }, { L"[acc_2]", 2 }, { L"[acc_1]", 1 }, { L"[acc_-4]", -4 }, { L"[acc_-3]", -3 }, { L"[acc_-2]", -2 }, { L"[acc_-1]", -1 }, }; std::unordered_map _LANGREPMAP{ {"CHINESE", "ZH"}, { "CHINA", "ZH" }, { "JAPAN", "JP" }, { "JAPANESE", "JP" }, { "JA", "JP" }, { "ENGLISH", "EN" } }; void PreventNoobsInputErrors(std::string& _Src) { for (auto& i : _Src) i = char(toupper(i)); const auto res = _LANGREPMAP.find(_Src); if (res != _LANGREPMAP.end()) _Src = res->second; } TextToSpeech::TextToSpeech(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : MoeVoiceStudioModule(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioTextToSpeech"); } std::vector TextToSpeech::GetInputSeqs(const MJson& _Input, const MoeVSProjectSpace::MoeVSParams& _InitParams) const { auto InputSeq = GetInputSeqsStatic(_Input, _InitParams); return SpecializeInputSeqs(InputSeq); } std::tuple, std::vector> TextToSpeech::SplitTonesFromTokens(const std::vector& _Src, const std::vector& _ToneRef, int64_t FirstToneIdx, const std::string& LanguageSymbol) { if (_Src.empty()) return{ {},{} }; std::vector TempSeqVec; std::vector TempToneVec; TempSeqVec.reserve(_Src.size()); TempToneVec.reserve(_Src.size()); for (const auto& it : _Src) { if (_ACCMAP.find(it) == _ACCMAP.end()) { TempSeqVec.emplace_back(it); TempToneVec.emplace_back(0); } else { if (TempToneVec.empty()) continue; *(TempToneVec.end() - 1) = _ACCMAP.at(it); if (TempToneVec.size() > 1 && *(TempToneVec.end() - 2) == 0 && LanguageSymbol == "ZH") *(TempToneVec.end() - 2) = *(TempToneVec.end() - 1); } } if (TempToneVec.size() == _ToneRef.size()) { for (size_t i = 0; i < _ToneRef.size(); ++i) if (_ToneRef[i] != 0) TempToneVec[i] = _ToneRef[i]; } if (FirstToneIdx) for (auto& it : TempToneVec) it += FirstToneIdx; return { std::move(TempSeqVec) ,std::move(TempToneVec) }; } std::vector& TextToSpeech::SpecializeInputSeqs(std::vector& _Seq) const { for (auto& _Temp : _Seq) { PreventNoobsInputErrors(_Temp.LanguageSymbol); const int64_t FirstToneIdx = LanguageTones.at(_Temp.LanguageSymbol); for(auto& _iter : _Temp.SlicedTokens) { if (!_iter.Phonemes.empty()) { auto RtnData = SplitTonesFromTokens(_iter.Phonemes, _iter.Tones, FirstToneIdx, _Temp.LanguageSymbol); _iter.Phonemes = std::move(std::get<0>(RtnData)); _iter.Tones = std::move(std::get<1>(RtnData)); } else if (FirstToneIdx) for (auto& it : _iter.Tones) it += FirstToneIdx; } } return _Seq; } std::vector TextToSpeech::GetInputSeqsStatic(const MJson& _Input, const MoeVSProjectSpace::MoeVSParams& _InitParams) { if (!_Input.IsArray()) LibDLVoiceCodecThrow("JSON Type Must Be Array") const auto _InpArr = _Input.GetArray(); std::vector _TTSInputSeqs; _TTSInputSeqs.reserve(_InpArr.size()); for (const auto& iter : _InpArr) _TTSInputSeqs.emplace_back(iter, _InitParams); return _TTSInputSeqs; } std::vector TextToSpeech::GetEmotionVector(const std::vector& src) const { if (src.empty()) return EmoLoader[0]; std::vector dst(1024, 0.0); uint64_t mul = 0; for(const auto& iter : src) { long emoId; const auto emoStr = to_byte_string(iter); if (!EmoJson[emoStr].Empty()) emoId = EmoJson[emoStr].GetInt(); else emoId = atoi(emoStr.c_str()); auto emoVec = EmoLoader[emoId]; for (size_t i = 0; i < 1024; ++i) dst[i] = dst[i] + (emoVec[i] - dst[i]) / (float)(mul + 1ull); ++mul; } return dst; } std::vector> TextToSpeech::generatePath(float* duration, size_t durationSize, size_t maskSize) { for (size_t i = 1; i < maskSize; ++i) duration[i] = duration[i - 1] + duration[i]; std::vector> path(durationSize, std::vector(maskSize, false)); //const auto path = new float[maskSize * durationSize]; /* for (size_t i = 0; i < maskSize; ++i) for (size_t j = 0; j < durationSize; ++j) path[i][j] = (j < (size_t)duration[i] ? 1.0f : 0.0f); for (size_t i = maskSize - 1; i > 0ull; --i) for (size_t j = 0; j < durationSize; ++j) path[i][j] -= path[i-1][j]; */ auto dur = (size_t)duration[0]; for (size_t j = 0; j < dur; ++j) path[j][0] = true; /* for (size_t i = maskSize - 1; i > 0ull; --i) for (size_t j = 0; j < durationSize; ++j) path[i][j] = (j < (size_t)duration[i] && j >= (size_t)duration[i - 1]); std::vector> tpath(durationSize, std::vector(maskSize)); for (size_t i = 0; i < maskSize; ++i) for (size_t j = 0; j < durationSize; ++j) tpath[j][i] = path[i][j]; */ for (size_t j = maskSize - 1; j > 0ull; --j) { dur = (size_t)duration[j]; for (auto i = (size_t)duration[j - 1]; i < dur && i < durationSize; ++i) path[i][j] = true; } return path; } std::vector> TextToSpeech::Inference(const std::wstring& _Seq, const MoeVSProjectSpace::MoeVSParams& _InferParams) const { if (_Seq.empty()) return {}; return Inference(GetInputSeqs({ to_byte_string(_Seq), true }, _InferParams)); } std::vector> TextToSpeech::Inference(const MJson& _Inputs, const MoeVSProjectSpace::MoeVSParams& _InferParams) const { return Inference(GetInputSeqs(_Inputs, _InferParams)); } std::vector TextToSpeech::Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { return Inference(_Datas, _InferParams,false); } std::vector TextToSpeech::Inference(const std::wstring& _Seq, const MoeVSProjectSpace::MoeVSParams& _InferParams, bool T) const { const std::vector> PCM = Inference(GetInputSeqs({ to_byte_string(_Seq), true }, _InferParams)); std::vector AudioFolders; if (_Seq.empty()) return {}; AudioFolders.reserve(PCM.size()); for (const auto& i : PCM) { std::wstring OutFolder = GetCurrentFolder() + L"/Outputs/BatchInference"; if (_waccess((OutFolder + L".wav").c_str(), 0) != -1) { for (size_t idx = 0; idx < 99999999; ++idx) if (_waccess((OutFolder + L" (" + std::to_wstring(idx) + L").wav").c_str(), 0) == -1) { OutFolder += L" (" + std::to_wstring(idx) + L").wav"; break; } } else OutFolder += L".wav"; AudioFolders.emplace_back(OutFolder); InferTools::Wav::WritePCMData(_samplingRate, 1, i, OutFolder); } return AudioFolders; } std::vector> TextToSpeech::Inference(const std::vector& _Input) const { MoeVSNotImplementedError } std::vector TextToSpeech::GetAligments(size_t DstLen, size_t SrcLen) { std::vector bert2ph(DstLen + 1, 0); size_t startFrame = 0; const double ph_durs = static_cast(DstLen) / static_cast(SrcLen); for (size_t iph = 0; iph < SrcLen; ++iph) { const auto endFrame = static_cast(round(static_cast(iph) * ph_durs + ph_durs)); for (auto j = startFrame; j < endFrame + 1; ++j) bert2ph[j] = static_cast(iph) + 1; startFrame = endFrame + 1; } return bert2ph; } std::set ChineseVowel{L'a', L'e', L'i', L'o', L'u', L'A', L'E', L'I', L'O', L'U'}; std::set ByteSymbol{L',', L'.', L'?', L'/', L'\"', L'\'', L';', L':', L'!', L' ', L'…' }; std::vector TextToSpeech::AligPhoneAttn(const std::string& LanguageStr, const std::vector& PhoneSeq, size_t BertSize) const { size_t PhoneSize = PhoneSeq.size(); if (AddBlank) PhoneSize = PhoneSize * 2 + 1; if(LanguageStr == "ZH") { std::vector bert2ph(PhoneSize, 0); size_t startFrame = 1; for (size_t iph = 0; iph < PhoneSeq.size(); ++iph) { if (startFrame == BertSize) LibDLVoiceCodecThrow("AligError") if (AddBlank) { bert2ph[(iph + 1) * 2] = startFrame; bert2ph[(iph + 1) * 2 - 1] = startFrame; } else bert2ph[iph] = startFrame; if (!PhoneSeq[iph].empty() && ChineseVowel.find(PhoneSeq[iph][0]) != ChineseVowel.end()) ++startFrame; else if (ByteSymbol.find(PhoneSeq[iph][0]) != ByteSymbol.end()) ++startFrame; else if (Symbols.find(PhoneSeq[iph]) == Symbols.end()) ++startFrame; else if (PhoneSeq[iph] == L"UNK") ++startFrame; } bert2ph.back() = startFrame; return bert2ph; } return GetAligments(PhoneSize, BertSize); } std::wstring TextToSpeech::TextNormalize(const std::wstring& _Input, int64_t LanguageId) const { auto Iterator = LanguageMap.begin(); while(Iterator != LanguageMap.end()) { if (Iterator->second == LanguageId) break; ++Iterator; } if (Iterator != LanguageMap.end()) return MoeVSG2P::NormalizeText(_Input, Iterator->first); return _Input; } MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/src/Vits.cpp ================================================ #include "../header/Vits.hpp" #include "../../InferTools/inferTools.hpp" #include MoeVoiceStudioCoreHeader bool BertEnabled = false; std::unordered_map sessionBert; std::unordered_map sessionClap; void SetBertEnabled(bool cond) { BertEnabled = cond; } void DestoryAllBerts() { for (const auto& it : sessionBert) delete it.second; for (const auto& it : sessionClap) delete it.second; sessionBert.clear(); sessionClap.clear(); } Vits::~Vits() { logger.log(L"[Info] unloading Vits Models"); destory(); logger.log(L"[Info] Vits Models unloaded"); } Vits::Vits(const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : TextToSpeech(ExecutionProvider_, DeviceID_, ThreadCount_) { //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)") if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String") const auto _folder = to_wide_string(_Config["Folder"].GetString()); if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty") const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; std::map _PathDict; if(_Config.HasMember("EmotionalPath") && _Config["EmotionalPath"].IsString()) { const auto emoStringload = to_wide_string(_Config["EmotionalPath"].GetString()); if(!emoStringload.empty()) { _PathDict["EmotionalPath"] = GetCurrentFolder() + L"/emotion/" + emoStringload + L".npy"; _PathDict["EmotionalDictPath"] = GetCurrentFolder() + L"/emotion/" + emoStringload + L".json"; } } if(_Config.HasMember("Clap") && _Config["Clap"].IsString()) { const auto ClapStringload = to_wide_string(_Config["Clap"].GetString()); if (!ClapStringload.empty()) _PathDict["Clap"] = GetCurrentFolder() + L"/clap/" + ClapStringload; } _PathDict["Decoder"] = _path + L"_dec.onnx"; _PathDict["StochasticDurationPredictor"] = _path + L"_sdp.onnx"; _PathDict["DurationPredictor"] = _path + L"_dp.onnx"; _PathDict["Encoder"] = _path + L"_enc_p.onnx"; _PathDict["FlowNet"] = _path + L"_flow.onnx"; _PathDict["Embidding"] = _path + L"_emb.onnx"; if (_Config.HasMember("Dict") && _Config["Dict"].IsString() && !_Config["Dict"].Empty()) _PathDict["Dict"] = GetCurrentFolder() + L"/Dict/" + to_wide_string(_Config["Dict"].GetString()) + L".json"; std::vector _BertPaths; if (_Config.HasMember("BertPath") && _Config["BertPath"].IsArray() && !_Config["BertPath"].Empty()) { for(const auto& BPH : _Config["BertPath"].GetArray()) { const auto BertPath = to_wide_string(BPH.GetString()); if(!BertPath.empty()) _BertPaths.emplace_back(GetCurrentFolder() + L"/Bert/" + BertPath); } } load(_PathDict, _Config, _ProgressCallback, _DurationCallback, _BertPaths); } void Vits::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, const std::vector& _BertPaths) { if (_Config["Type"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Type\" (ModelType)") if (!_Config["Type"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Type\" (ModelType) Must Be String") VitsType = _Config["Type"].GetString(); if (VitsType == "Pits") { UseTone = true; UseLength = false; } if (VitsType == "BertVits") { UseLength = false; UseTone = true; UseBert = true; UseLanguage = true; EncoderG = true; } Cleaner = MoeVSG2P::GetDefCleaner(); if (_PathDict.find("Dict") != _PathDict.end() && (_waccess(_PathDict.at("Dict").c_str(), 0) != -1)) Cleaner->loadDict(_PathDict.at("Dict")); else Cleaner->loadDict(L""); if (_Config.HasMember("LanguageMap") && !_Config["LanguageMap"].IsNull()) for (const auto& CMember : _Config["LanguageMap"].GetMemberArray()) LanguageMap[CMember.first] = CMember.second.GetInt(); else logger.log("[Warn] Field \"LanguageMap\" Is Missing, Use Default Value"); if (UseLength) EncoderInputNames.emplace_back("x_lengths"); if (UseTone) EncoderInputNames.emplace_back("t"); if (Emotion) EncoderInputNames.emplace_back("emotion"); if (UseLanguage) EncoderInputNames.emplace_back("language"); //Check SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)") if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64") logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); //Check Symbol if (!_Config.HasMember("Symbol") || _Config["Symbol"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Symbol\" (PhSymbol)") if (_Config.HasMember("AddBlank") && !_Config["AddBlank"].IsNull()) AddBlank = _Config["AddBlank"].GetBool(); else logger.log(L"[Warn] Field \"AddBlank\" Is Missing, Use Default Value"); //Load Symbol int64_t iter_symb = 0; if (_Config["Symbol"].IsArray()) { logger.log(L"[Info] Use Phs"); if (_Config["Symbol"].Empty()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Can Not Be Empty") const auto SymbolArr = _Config["Symbol"].GetArray(); if (!SymbolArr[0].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Must Be Array or String") for (const auto& it : SymbolArr) Symbols.insert({ to_wide_string(it.GetString()), iter_symb++ }); } else { if (!_Config["Symbol"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Must Be Array or String") logger.log(L"[Info] Use Symbols"); const std::wstring SymbolsStr = to_wide_string(_Config["Symbol"].GetString()); if (SymbolsStr.empty()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Can Not Be Empty") for (size_t i = 0; i < SymbolsStr.length(); ++i) Symbols.insert({ SymbolsStr.substr(i,1) , iter_symb++ }); } if (_Config.HasMember("VQSize") && _Config["VQSize"].IsInt64()) VQCodeBookSize = _Config["VQSize"].GetInt64(); else logger.log(L"[Warn] Field \"VQSize\" Is Missing, Use Default Value"); try { if (_PathDict.find("EmotionalPath") != _PathDict.end()) { const auto EmotionPath = _PathDict.at("EmotionalPath"); if (!EmotionPath.empty()) { logger.log(L"[Info] Loading EmotionVector"); EmoLoader.open(EmotionPath); logger.log(L"[Info] EmotionVector Loaded"); Emotion = true; } } if (_PathDict.find("EmotionalDictPath") != _PathDict.end()) { const auto EmotionPath = _PathDict.at("EmotionalDictPath"); if (!EmotionPath.empty()) EmoJson = { EmotionPath }; } } catch (std::exception& e) { logger.log((std::string("[Warn] EmotionPath Error ") + e.what()).c_str()); } if (_Config.HasMember("Characters") && _Config["Characters"].IsArray()) { SpeakerCount = (int64_t)_Config["Characters"].Size(); int64_t SpkIdx = 0; for (const auto& iterator : _Config["Characters"].GetArray()) SpeakerMap[to_wide_string(iterator.GetString())] = SpkIdx++; } if(UseLanguage) { if (_Config["LanguageMap"].IsNull() || !_Config.HasMember("LanguageMap")) LibDLVoiceCodecThrow("[Error] Missing field \"LanguageMap\" (LanguageMap)") for(const auto& Item : _Config["LanguageMap"].GetMemberArray()) { if (!Item.second.IsArray()) continue; const auto LangArr = Item.second.GetArray(); if (LangArr.size() != 2) continue; LanguageMap[Item.first] = LangArr[0].GetInt(); LanguageTones[Item.first] = LangArr[1].GetInt(); } } if (UseBert) { if (_Config.HasMember("BertPath") && _Config["BertPath"].IsArray() && !_Config["BertPath"].Empty()) { for (const auto& BPH : _Config["BertPath"].GetArray()) { const auto BertPath = to_wide_string(BPH.GetString()); if (!BertPath.empty()) BertNamesIdx.emplace_back(BertPath); } } if (LanguageMap.size() != _BertPaths.size()) EncoderInputNames.emplace_back("bert"); else { BertNames.reserve(_BertPaths.size() * 2); for (size_t i = 0; i < _BertPaths.size(); ++i) BertNames.emplace_back("bert_" + std::to_string(i)); for(const auto& NameInp : BertNames) EncoderInputNames.emplace_back(NameInp.data()); } for(const auto& Path : _BertPaths) { const auto BertName = Path.substr(Path.rfind(L'/') + 1); if (LanguageTokenizerMap.find("ZH") == LanguageTokenizerMap.end() && BertName.find(L"chinese") != std::string::npos) LanguageTokenizerMap["ZH"] = BertName; if (LanguageTokenizerMap.find("JP") == LanguageTokenizerMap.end() && BertName.find(L"japanese") != std::string::npos) LanguageTokenizerMap["JP"] = BertName; Ort::Session* SessionBert = nullptr; if (sessionBert.find(BertName) != sessionBert.end() && sessionBert.at(BertName) != nullptr) SessionBert = sessionBert.at(BertName); if (_waccess(Path.c_str(), 0) != -1) { if(!SessionBert) { try { SessionBert = new Ort::Session(*env, (Path + L"/model.onnx").c_str(), *session_options); } catch(Ort::Exception& e) { logger.log(L"[Warn] " + to_wide_string(e.what())); delete SessionBert; SessionBert = nullptr; } } if (_waccess((Path + L"/Tokenizer.json").c_str(), 0) != -1) { Tokenizers.insert({ BertName ,Path + L"/Tokenizer.json" }); Tokenizers[BertName].BondCleaner(Cleaner); } else if (SessionBert) { delete SessionBert; LibDLVoiceCodecThrow("Bert Must Have a Tokenizer") } } sessionBert[BertName] = SessionBert; } for (auto& iter : sessionBert) if (std::find(BertNamesIdx.begin(), BertNamesIdx.end(), iter.first) == BertNamesIdx.end()) { delete iter.second; iter.second = nullptr; } } if(_BertPaths.empty()) { for (const auto& iter : sessionBert) delete iter.second; sessionBert.clear(); } if (VitsType == "BertVits" && _PathDict.find("Clap") != _PathDict.end()) { EncoderInputNames.emplace_back("emo"); UseClap = true; const auto& Path = _PathDict.at("Clap"); ClapName = Path.substr(Path.rfind(L'/') + 1); Ort::Session* SessionClap = nullptr; if ((sessionClap.find(ClapName) != sessionClap.end() && sessionClap.at(ClapName) != nullptr)) SessionClap = sessionClap.at(ClapName); if (!SessionClap) { try { SessionClap = new Ort::Session(*env, (Path + L".onnx").c_str(), *session_options); } catch (Ort::Exception& e) { logger.log(L"[Warn] " + to_wide_string(e.what())); delete SessionClap; SessionClap = nullptr; } } if (_waccess((Path + L".json").c_str(), 0) != -1) { Tokenizers.insert({ ClapName , Path + L".json" }); Tokenizers[ClapName].BondCleaner(Cleaner); } else if (SessionClap) { delete SessionClap; LibDLVoiceCodecThrow("Clap Must Have a Tokenizer") } sessionClap[ClapName] = SessionClap; for (auto& iter : sessionClap) if (ClapName != iter.first) { delete iter.second; iter.second = nullptr; } } else { for (auto& iter : sessionClap) delete iter.second; sessionClap.clear(); UseClap = false; } _callback = _ProgressCallback; CustomDurationCallback = _DurationCallback; //LoadModels try { logger.log(L"[Info] loading Vits Models"); sessionDec = new Ort::Session(*env, _PathDict.at("Decoder").c_str(), *session_options); sessionEnc_p = new Ort::Session(*env, _PathDict.at("Encoder").c_str(), *session_options); sessionFlow = new Ort::Session(*env, _PathDict.at("FlowNet").c_str(), *session_options); if (_waccess(_PathDict.at("Embidding").c_str(), 0) != -1) sessionEmb = new Ort::Session(*env, _PathDict.at("Embidding").c_str(), *session_options); else sessionEmb = nullptr; if (_waccess(_PathDict.at("DurationPredictor").c_str(), 0) != -1) sessionDp = new Ort::Session(*env, _PathDict.at("DurationPredictor").c_str(), *session_options); else sessionDp = nullptr; if (_waccess(_PathDict.at("StochasticDurationPredictor").c_str(), 0) != -1) sessionSdp = new Ort::Session(*env, _PathDict.at("StochasticDurationPredictor").c_str(), *session_options); else sessionSdp = nullptr; if (!sessionDp && !sessionSdp) { destory(); LibDLVoiceCodecThrow("You must have a duration predictor") } logger.log(L"[Info] Vits Models loaded"); } catch (Ort::Exception& _exception) { destory(); LibDLVoiceCodecThrow(_exception.what()) } if (sessionEmb) { if(EncoderG) EncoderInputNames.emplace_back("g"); SdpInputNames.emplace_back("g"); DpInputNames.emplace_back("g"); FlowInputNames.emplace_back("g"); DecInputNames.emplace_back("g"); } if(VitsType == "BertVits" && sessionEnc_p->GetInputCount() == EncoderInputNames.size() + 2) { EncoderInputNames.emplace_back("vqidx"); EncoderInputNames.emplace_back("sid"); UseVQ = true; } } Vits::Vits(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, const std::vector& _BertPaths, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : TextToSpeech(ExecutionProvider_, DeviceID_, ThreadCount_) { load(_PathDict, _Config, _ProgressCallback, _DurationCallback, _BertPaths); } std::vector> Vits::Inference(const std::vector& _Input) const { std::vector> PCM; PCM.reserve(_Input.size()); std::vector> _Audio(1); logger.log("[Inference] Vits Inference Begin"); size_t proc = 0; _callback(proc, _Input.size()); for(const auto& Seq : _Input) { _callback(proc++, _Input.size()); auto CurLanguageIdx = _atoi64(Seq.LanguageSymbol.c_str()); if (LanguageMap.find(Seq.LanguageSymbol) != LanguageMap.end()) CurLanguageIdx = LanguageMap.at(Seq.LanguageSymbol); std::vector PhonemeSeq, TokenSeq; std::vector ToneSeq; std::vector LanguageSeq; std::vector DurationSeq; std::vector BertAligSeq; bool HasBertSeq = false; if (AddBlank) BertAligSeq.emplace_back(0); std::vector TmpToken; const std::vector* TokensPtr = &Seq.SlicedTokens; if (BertEnabled && UseBert && Seq.SlicedTokens.empty()) { HasBertSeq = true; if(Seq.LanguageSymbol != "ZH") TokenSeq = GetTokenizer(Seq.LanguageSymbol).Tokenize(Seq.TextSeq); else { auto NewData = GetTokenizer(Seq.LanguageSymbol).Tokenize(Seq.TextSeq); if (NewData.empty()) continue; TmpToken.reserve(NewData.size()); for (const auto& it : NewData) { MoeVSProjectSpace::MoeVSTTSToken Tok; Tok.Text = it; TmpToken.emplace_back(std::move(Tok)); } TokensPtr = &TmpToken; } } if(UseBert && TokensPtr && !TokensPtr->empty()) { size_t TokensIndex = 1; for(const auto& iter : *TokensPtr) { if (iter.Text.empty()) { logger.log("[Info] Skip Empty Slice"); continue; } TokenSeq.emplace_back(iter.Text); if (iter.Text == L"[CLS]") continue; if (iter.Text == L"[SEP]") break; std::vector const* PhonemesPtr; std::vector TempPhonemes; std::vector TempToneVec; if (iter.Phonemes.empty()) { std::vector TempSeqVec; auto TempText = iter.Text; if (TempText == L"[UNK]") TempPhonemes = { L"[UNK]" }; else { if (TempText.find(L"##") == 0) TempText = TempText.substr(2); if (TempText.find(L'▁') == 0) TempText = TempText.substr(1); TempPhonemes = Cleaner->DictReplace(Cleaner->G2p(TempText, Seq.PlaceHolderSymbol, L"/[WithTone]" + Seq.AdditionalInfo, Seq.LanguageSymbol), Seq.PlaceHolderSymbol); } const int64_t FirstToneIdx = LanguageTones.at(Seq.LanguageSymbol); auto RtnData = SplitTonesFromTokens(TempPhonemes, iter.Tones, FirstToneIdx, Seq.LanguageSymbol); TempPhonemes = std::move(std::get<0>(RtnData)); TempToneVec = std::move(std::get<1>(RtnData)); PhonemesPtr = &TempPhonemes; } else PhonemesPtr = &iter.Phonemes; PhonemeSeq.insert(PhonemeSeq.end(), PhonemesPtr->begin(), PhonemesPtr->end()); if (PhonemesPtr->size() == iter.Language.size()) for (const auto& langstr : iter.Language) LanguageSeq.emplace_back(LanguageMap.find(langstr) != LanguageMap.end() ? LanguageMap.at(langstr) : _atoi64(langstr.c_str())); else LanguageSeq.insert(LanguageSeq.end(), PhonemesPtr->size(), CurLanguageIdx); if (PhonemesPtr->size() == iter.Durations.size()) DurationSeq.insert(DurationSeq.end(), iter.Durations.begin(), iter.Durations.end()); if (PhonemesPtr->size() == iter.Tones.size()) ToneSeq.insert(ToneSeq.end(), iter.Tones.begin(), iter.Tones.end()); else if(PhonemesPtr->size() == TempToneVec.size()) ToneSeq.insert(ToneSeq.end(), TempToneVec.begin(), TempToneVec.end()); else ToneSeq.insert(ToneSeq.end(), PhonemesPtr->size(), LanguageTones.at(Seq.LanguageSymbol)); for (size_t idxl = 0; idxl < PhonemesPtr->size(); ++idxl) { BertAligSeq.emplace_back(TokensIndex); if (AddBlank) BertAligSeq.emplace_back(TokensIndex); } ++TokensIndex; } if ((AddBlank && BertAligSeq.size() == PhonemeSeq.size() * 2 + 1) || (!AddBlank && BertAligSeq.size() == PhonemeSeq.size())) HasBertSeq = true; else HasBertSeq = false; } else if (!Seq.TextSeq.empty()) { PhonemeSeq = Cleaner->DictReplace(Cleaner->G2p(Seq.TextSeq, Seq.PlaceHolderSymbol, L"/[WithTone]" + Seq.AdditionalInfo, Seq.LanguageSymbol), Seq.PlaceHolderSymbol); LanguageSeq = std::vector(PhonemeSeq.size(), CurLanguageIdx); auto RtnVal = SplitTonesFromTokens(PhonemeSeq, {}, LanguageTones.at(Seq.LanguageSymbol), Seq.LanguageSymbol); PhonemeSeq = std::move(std::get<0>(RtnVal)); ToneSeq = std::move(std::get<1>(RtnVal)); } else { logger.log("[Info] Skip Empty TextSeq"); continue; } if(PhonemeSeq.empty()) { logger.log("[Info] Skip Empty TextSeq"); continue; } if (!_Audio[0].empty()) { if (Seq.RestTime < 0.f) { _Audio[0].insert(_Audio[0].end(), size_t(_samplingRate), 0); PCM.emplace_back(std::move(_Audio[0])); _Audio[0] = std::vector(); } else _Audio[0].insert(_Audio[0].end(), size_t(Seq.RestTime * float(_samplingRate)), 0); } std::mt19937 gen(static_cast(Seq.Seed)); std::normal_distribution FloatRandFn(0.f, 1.f); std::vector TextSeq; TextSeq.reserve(PhonemeSeq.size() * 4 + 4); for (const auto& it : PhonemeSeq) { if (AddBlank) TextSeq.push_back(0); if (Symbols.find(it) != Symbols.end()) TextSeq.push_back(Symbols.at(it)); else TextSeq.push_back(0); } if (AddBlank) TextSeq.push_back(0); int64_t TextSeqLength[] = { (int64_t)TextSeq.size() }; std::vector EncoderOutputs; std::vector EncoderInputs; const int64_t TextSeqShape[2] = { 1,TextSeqLength[0] }; constexpr int64_t LengthShape[1] = { 1 }; EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, TextSeq.data(), TextSeqLength[0], TextSeqShape, 2)); if (UseLength) EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, TextSeqLength, 1, LengthShape, 1)); std::vector emoVec; constexpr int64_t EmotionShape[1] = { 1024 }; if(Emotion) { emoVec = GetEmotionVector(Seq.EmotionPrompt); EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, emoVec.data(), 1024, EmotionShape, 1)); } std::vector ToneIn(TextSeq.size(), 0i64); if(UseTone) { if (ToneIn.size() == ToneSeq.size()) ToneIn = ToneSeq; else if (AddBlank && ToneIn.size() == ToneSeq.size() * 2 + 1) for (size_t i = 1; i < ToneIn.size(); i += 2) ToneIn[i] = ToneSeq[i / 2]; else if (ToneIn.size() * 2 + 1 == ToneSeq.size()) for (size_t i = 1; i < ToneSeq.size(); i += 2) ToneIn[i / 2] = ToneSeq[i]; EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, ToneIn.data(), TextSeqLength[0], TextSeqShape, 2)); } std::vector LanguageIn(TextSeq.size(), CurLanguageIdx); if(UseLanguage) { if (LanguageIn.size() == LanguageSeq.size()) LanguageIn = LanguageSeq; else if (AddBlank && LanguageIn.size() == LanguageSeq.size() * 2 + 1) for (size_t i = 1; i < LanguageIn.size(); i += 2) { LanguageIn[i] = LanguageSeq[i / 2]; LanguageIn[i - 1] = LanguageSeq[i / 2]; } else if (LanguageIn.size() * 2 + 1 == LanguageSeq.size()) for (size_t i = 1; i < LanguageSeq.size(); i += 2) LanguageIn[i / 2] = LanguageSeq[i]; EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, LanguageIn.data(), TextSeqLength[0], TextSeqShape, 2)); } std::vector BertVecs(sessionBert.size(), std::vector(1024 * TextSeqLength[0], 0.f)); int64_t BertShape[2] = { TextSeqLength[0],1024 }; if(UseBert) { for (size_t IndexOfBert = 0; IndexOfBert < sessionBert.size(); ++IndexOfBert) { auto& BertData = BertVecs[IndexOfBert]; const auto CurBertSession = sessionBert[BertNamesIdx[IndexOfBert]]; if ((CurBertSession && (IndexOfBert == size_t(CurLanguageIdx) || (IndexOfBert != size_t(CurLanguageIdx) && sessionBert.size() == 1))) && BertEnabled && HasBertSeq) { auto input_ids = Tokenizers.at(BertNamesIdx[IndexOfBert])(TokenSeq); std::vector attention_mask(input_ids.size(), 1), token_type_ids(input_ids.size(), 0); int64_t AttentionShape[2] = { 1, (int64_t)input_ids.size() }; std::vector AttentionInput, AttentionOutput; AttentionInput.emplace_back(Ort::Value::CreateTensor( *memory_info, input_ids.data(), input_ids.size(), AttentionShape, 2)); if (CurBertSession->GetInputCount() == 3) AttentionInput.emplace_back(Ort::Value::CreateTensor(*memory_info, attention_mask.data(), attention_mask.size(), AttentionShape, 2)); AttentionInput.emplace_back(Ort::Value::CreateTensor( *memory_info, token_type_ids.data(), token_type_ids.size(), AttentionShape, 2)); try { if(CurBertSession->GetInputCount() == 3) { AttentionOutput = CurBertSession->Run(Ort::RunOptions{ nullptr }, BertInputNames.data(), AttentionInput.data(), 3, BertOutputNames.data(), 1); } else if (CurBertSession->GetInputCount() == 2) { AttentionOutput = CurBertSession->Run(Ort::RunOptions{ nullptr }, BertInputNames2.data(), AttentionInput.data(), 2, BertOutputNames.data(), 1); } else { AttentionOutput = CurBertSession->Run(Ort::RunOptions{ nullptr }, BertInputNames3.data(), AttentionInput.data(), 1, BertOutputNames.data(), 1); } } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Bert\n") + e.what())) } const auto AttnData = AttentionOutput[0].GetTensorData(); if (BertAligSeq.size() == 1) BertAligSeq = GetAligments(TextSeqLength[0], AttentionOutput[0].GetTensorTypeAndShapeInfo().GetShape()[0] - 2); for (int64_t IndexOfSrcVector = 0; IndexOfSrcVector < TextSeqLength[0]; ++IndexOfSrcVector) memcpy(BertData.data() + IndexOfSrcVector * 1024, AttnData + (BertAligSeq[IndexOfSrcVector]) * 1024, 1024 * sizeof(float)); } EncoderInputs.emplace_back(Ort::Value::CreateTensor( *memory_info, BertData.data(), BertData.size(), BertShape, 2)); } } auto ClapData = std::vector(512, 0.f); int64_t ClapShape[2] = { 512, 1 }; if(UseClap) { std::vector ClapInput; const auto CurClapSession = sessionClap[ClapName]; std::wstring ClapSeq; for (const auto& itt : Seq.EmotionPrompt) ClapSeq += itt + L" "; if(CurClapSession && !ClapSeq.empty()) { std::vector ClapOutput; const auto& CurClapTokenizer = Tokenizers.at(ClapName); auto input_ids = CurClapTokenizer(CurClapTokenizer.Tokenize(ClapSeq), true); std::vector attention_mask(input_ids.size(), 1); int64_t AttentionShape[2] = { 1, (int64_t)input_ids.size() }; ClapInput.emplace_back(Ort::Value::CreateTensor( *memory_info, input_ids.data(), input_ids.size(), AttentionShape, 2)); ClapInput.emplace_back(Ort::Value::CreateTensor( *memory_info, attention_mask.data(), attention_mask.size(), AttentionShape, 2)); try { ClapOutput = CurClapSession->Run(Ort::RunOptions{ nullptr }, BertInputNames2.data(), ClapInput.data(), CurClapSession->GetInputCount(), BertOutputNames.data(), 1); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Clap\n") + e.what())) } ClapData = { ClapOutput[0].GetTensorData(),ClapOutput[0].GetTensorData() + 512 }; } EncoderInputs.emplace_back(Ort::Value::CreateTensor(*memory_info, ClapData.data(), ClapData.size(), ClapShape, 2)); } int64_t VQIndices[] = { 0 }; int64_t SidIndices[] = { SpeakerMap.find(Seq.SpeakerName) != SpeakerMap.end() ? SpeakerMap.at(Seq.SpeakerName) : _wtoi64(Seq.SpeakerName.c_str()) }; std::vector GEmbidding; std::vector GOutShape; if (sessionEmb) { auto SpeakerMixData = Seq.SpeakerMix; if (!SpeakerMixData.empty() && SpeakerCount > 1) { LinearCombination(SpeakerMixData); int64_t csid = 0; for (const auto& CharaP : SpeakerMixData) { std::vector EmbiddingInput; std::vector EmbiddingOutput; if (csid >= SpeakerCount) break; if (CharaP < 0.0001f) { ++csid; continue; } int64_t Character[1] = { csid }; EmbiddingInput.push_back(Ort::Value::CreateTensor( *memory_info, Character, 1, LengthShape, 1)); try { EmbiddingOutput = sessionEmb->Run(Ort::RunOptions{ nullptr }, EmbiddingInputNames.data(), EmbiddingInput.data(), EmbiddingInput.size(), EmbiddingOutputNames.data(), EmbiddingOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: emb\n") + e.what())) } const auto GOutCount = EmbiddingOutput[0].GetTensorTypeAndShapeInfo().GetElementCount(); if (GOutShape.empty()) { GEmbidding = std::vector(EmbiddingOutput[0].GetTensorData(), EmbiddingOutput[0].GetTensorData() + GOutCount); GOutShape = EmbiddingOutput[0].GetTensorTypeAndShapeInfo().GetShape(); GOutShape.emplace_back(1); for (auto idx : GEmbidding) idx *= float(CharaP); } else for (size_t i = 0; i < GOutCount; ++i) GEmbidding[i] += EmbiddingOutput[0].GetTensorData()[i] * float(CharaP); ++csid; } } else { std::vector EmbiddingInput; std::vector EmbiddingOutput; EmbiddingInput.push_back(Ort::Value::CreateTensor( *memory_info, SidIndices, 1, LengthShape, 1)); try { EmbiddingOutput = sessionEmb->Run(Ort::RunOptions{ nullptr }, EmbiddingInputNames.data(), EmbiddingInput.data(), EmbiddingInput.size(), EmbiddingOutputNames.data(), EmbiddingOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: emb\n") + e.what())) } const auto GOutCount = EmbiddingOutput[0].GetTensorTypeAndShapeInfo().GetElementCount(); GEmbidding = std::vector(EmbiddingOutput[0].GetTensorData(), EmbiddingOutput[0].GetTensorData() + GOutCount); GOutShape = EmbiddingOutput[0].GetTensorTypeAndShapeInfo().GetShape(); GOutShape.emplace_back(1); } if (EncoderG) EncoderInputs.push_back(Ort::Value::CreateTensor(*memory_info, GEmbidding.data(), GEmbidding.size(), GOutShape.data(), 3)); } if (UseVQ) { if (!Seq.EmotionPrompt.empty()) VQIndices[0] = _wtoi64(Seq.EmotionPrompt[0].c_str()); EncoderInputs.push_back(Ort::Value::CreateTensor(*memory_info, VQIndices, 1, LengthShape, 1)); EncoderInputs.push_back(Ort::Value::CreateTensor(*memory_info, SidIndices, 1, LengthShape, 1)); } try { EncoderOutputs = sessionEnc_p->Run(Ort::RunOptions{ nullptr }, EncoderInputNames.data(), EncoderInputs.data(), EncoderInputs.size(), EncoderOutputNames.data(), EncoderOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: enc_p\n") + e.what())) } std::vector m_p(EncoderOutputs[1].GetTensorData(), EncoderOutputs[1].GetTensorData() + EncoderOutputs[1].GetTensorTypeAndShapeInfo().GetElementCount()), logs_p(EncoderOutputs[2].GetTensorData(), EncoderOutputs[2].GetTensorData() + EncoderOutputs[2].GetTensorTypeAndShapeInfo().GetElementCount()), x_mask(EncoderOutputs[3].GetTensorData(), EncoderOutputs[3].GetTensorData() + EncoderOutputs[3].GetTensorTypeAndShapeInfo().GetElementCount()); const auto xshape = EncoderOutputs[0].GetTensorTypeAndShapeInfo().GetShape(); std::vector w_ceil(TextSeqLength[0], 1.f); bool enable_dp = false; if (DurationSeq.size() == w_ceil.size() || DurationSeq.size() == w_ceil.size() / 2) enable_dp = true; const int64_t zinputShape[3] = { xshape[0],2,xshape[2] }; const int64_t zinputCount = xshape[0] * xshape[2] * 2; std::vector zinput(zinputCount, 0.0); for (auto& it : zinput) it = FloatRandFn(gen) * Seq.DurationPredictorNoiseScale; std::vector DurationPredictorInput; DurationPredictorInput.push_back(std::move(EncoderOutputs[0])); DurationPredictorInput.push_back(std::move(EncoderOutputs[3])); DurationPredictorInput.push_back(Ort::Value::CreateTensor( *memory_info, zinput.data(), zinputCount, zinputShape, 3)); if (sessionEmb) DurationPredictorInput.push_back(Ort::Value::CreateTensor(*memory_info, GEmbidding.data(), GEmbidding.size(), GOutShape.data(), 3)); if(sessionSdp) { std::vector StochasticDurationPredictorOutput; try { StochasticDurationPredictorOutput = sessionSdp->Run(Ort::RunOptions{ nullptr }, SdpInputNames.data(), DurationPredictorInput.data(), DurationPredictorInput.size(), SdpOutputNames.data(), SdpOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: dp\n") + e.what())) } const auto w_data = StochasticDurationPredictorOutput[0].GetTensorMutableData(); const auto w_data_length = StochasticDurationPredictorOutput[0].GetTensorTypeAndShapeInfo().GetElementCount(); if (w_data_length != w_ceil.size()) w_ceil.resize(w_data_length, 0.f); float SdpFactor = 1.f - Seq.FactorDpSdp; if (sessionDp) for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] = ceil(exp(w_data[i] * SdpFactor) * x_mask[i] * Seq.LengthScale); else for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] = ceil(exp(w_data[i]) * x_mask[i] * Seq.LengthScale); } if (sessionDp) { std::vector DurationPredictorOutput; DurationPredictorInput.erase(DurationPredictorInput.begin() + 2); try { DurationPredictorOutput = sessionDp->Run(Ort::RunOptions{ nullptr }, DpInputNames.data(), DurationPredictorInput.data(), DurationPredictorInput.size(), DpOutputNames.data(), DpOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: dp\n") + e.what())) } const auto w_data = DurationPredictorOutput[0].GetTensorMutableData(); const auto w_data_length = DurationPredictorOutput[0].GetTensorTypeAndShapeInfo().GetElementCount(); if (w_data_length != w_ceil.size()) w_ceil.resize(w_data_length, 0.f); if (sessionSdp) for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] += ceil(exp(w_data[i] * Seq.FactorDpSdp) * x_mask[i] * Seq.LengthScale); else for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] = ceil(exp(w_data[i]) * x_mask[i] * Seq.LengthScale); } if(enable_dp) { if (DurationSeq.size() == TextSeq.size()) for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] = float(DurationSeq[i]); else if (AddBlank && DurationSeq.size() == TextSeq.size() / 2ull) for (size_t i = 0; i < DurationSeq.size(); ++i) w_ceil[1 + i * 2] = float(DurationSeq[i]); } CustomDurationCallback(w_ceil); const auto maskSize = x_mask.size(); float y_length_f = 0.0; int64_t y_length; for (size_t i = 0; i < w_ceil.size(); ++i) y_length_f += w_ceil[i]; if (y_length_f < 1.0f) y_length = 1; else y_length = (int64_t)y_length_f; auto attn = generatePath(w_ceil.data(), y_length, maskSize); std::vector logVec(192, std::vector(y_length, 0.0f)); std::vector mpVec(192, std::vector(y_length, 0.0f)); std::vector nlogs_pData(192 * y_length); for (size_t i = 0; i < static_cast(y_length); ++i) { for (size_t j = 0; j < 192; ++j) { for (size_t k = 0; k < maskSize; k++) { if (attn[i][k]) { mpVec[j][i] += m_p[j * maskSize + k]; logVec[j][i] += logs_p[j * maskSize + k]; } } nlogs_pData[j * y_length + i] = mpVec[j][i] + FloatRandFn(gen) * exp(logVec[j][i]) * Seq.NoiseScale; } } std::vector y_mask(y_length, 1.0f); const int64_t zshape[3] = { 1,192,y_length }; const int64_t yshape[3] = { 1,1,y_length }; std::vector FlowDecInputs, FlowDecOutputs; FlowDecInputs.push_back(Ort::Value::CreateTensor( *memory_info, nlogs_pData.data(), 192 * y_length, zshape, 3)); FlowDecInputs.push_back(Ort::Value::CreateTensor( *memory_info, y_mask.data(), y_length, yshape, 3)); if (sessionEmb) FlowDecInputs.push_back(Ort::Value::CreateTensor( *memory_info, GEmbidding.data(), GEmbidding.size(), GOutShape.data(), 3)); try { FlowDecOutputs = sessionFlow->Run(Ort::RunOptions{ nullptr }, FlowInputNames.data(), FlowDecInputs.data(), FlowDecInputs.size(), FlowOutputNames.data(), FlowOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: dec & flow\n") + e.what())) } FlowDecInputs[0] = std::move(FlowDecOutputs[0]); if (sessionEmb) FlowDecInputs[1] = std::move(FlowDecInputs[2]); FlowDecInputs.pop_back(); try { FlowDecOutputs = sessionDec->Run(Ort::RunOptions{ nullptr }, DecInputNames.data(), FlowDecInputs.data(), FlowDecInputs.size(), DecOutputNames.data(), DecOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: dec & flow\n") + e.what())) } const auto shapeOut = FlowDecOutputs[0].GetTensorTypeAndShapeInfo().GetShape(); const auto outData = FlowDecOutputs[0].GetTensorData(); for (int bbb = 0; bbb < shapeOut[2]; bbb++) _Audio[0].emplace_back(static_cast(outData[bbb] * 32768.0f)); } if (!_Audio[0].empty()) { _Audio[0].insert(_Audio[0].end(), size_t(_samplingRate), 0); PCM.emplace_back(std::move(_Audio[0])); } _callback(proc++, _Input.size()); logger.log("[Inference] Vits Inference Fin"); return PCM; } MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Models/src/VitsSvc.cpp ================================================ #include "../header/VitsSvc.hpp" #include "../../AvCodec/AvCodeResample.h" #include "../../InferTools/F0Extractor/F0ExtractorManager.hpp" #include #include "../../Logger/MoeSSLogger.hpp" #include "../../InferTools/TensorExtractor/TensorExtractorManager.hpp" #include MoeVoiceStudioCoreHeader void VitsSvc::Destory() { delete hubert; hubert = nullptr; delete VitsSvcModel; VitsSvcModel = nullptr; } VitsSvc::~VitsSvc() { logger.log(L"[Info] unloading VitsSvc Models"); Destory(); logger.log(L"[Info] VitsSvc Models unloaded"); } VitsSvc::VitsSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_): SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioVitsSingingVoiceConversion"); //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)") if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String") const auto _folder = to_wide_string(_Config["Folder"].GetString()); const auto cluster_folder = GetCurrentFolder() + L"/Models/" + _folder; if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty") const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; if (_Config["Hubert"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Hubert\" (Hubert Folder)") if (!_Config["Hubert"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Must Be String") const std::wstring HuPath = to_wide_string(_Config["Hubert"].GetString()); if (HuPath.empty()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Can Not Be Empty") std::map _PathDict; _PathDict["Cluster"] = cluster_folder; _PathDict["Hubert"] = (GetCurrentFolder() + L"/hubert/" + HuPath + L".onnx"); _PathDict["RVC"] = (_path + L"_RVC.onnx"); _PathDict["SoVits"] = (_path + L"_SoVits.onnx"); if (_Config["ShallowDiffusion"].IsString()) { const std::wstring ShallowDiffusionConf = GetCurrentFolder() + L"/Models/" + to_wide_string(_Config["ShallowDiffusion"].GetString()) + L".json"; _PathDict["ShallowDiffusionConfig"] = ShallowDiffusionConf; if (_Config["MelOperator"].IsString()) _PathDict["MelOperator"] = GetCurrentFolder() + L"/MelOps" + to_wide_string(_Config["MelOperator"].GetString()) + L".onnx"; else _PathDict["MelOperator"] = GetCurrentFolder() + L"/MelOps.onnx"; } load(_PathDict, _Config, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_, true); } VitsSvc::VitsSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioVitsSingingVoiceConversion"); load(_PathDict, _Config, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_, false); } void VitsSvc::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_, bool MoeVoiceStudioFrontEnd) { //Check SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)") if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64") logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); if (!_Config["SoVits3"].IsNull() && _Config["SoVits3"].GetBool()) VitsSvcVersion = L"SoVits3.0"; else if (!_Config["SoVits2"].IsNull() && _Config["SoVits2"].GetBool()) VitsSvcVersion = L"SoVits2.0"; else if (!_Config["SoVits2.0"].IsNull() && _Config["SoVits2.0"].GetBool()) VitsSvcVersion = L"SoVits2.0"; else if (!_Config["SoVits3.0"].IsNull() && _Config["SoVits3.0"].GetBool()) VitsSvcVersion = L"SoVits3.0"; else if (_Config["Type"].GetString() == std::string("RVC")) VitsSvcVersion = L"RVC"; if (!_Config["SoVits4.0V2"].IsNull() && _Config["SoVits4.0V2"].GetBool()) VitsSvcVersion = L"SoVits4.0-DDSP"; #ifdef MOEVSDMLPROVIDER if (ExecutionProvider_ == ExecutionProviders::DML && VitsSvcVersion == L"SoVits4.0-DDSP") LibDLVoiceCodecThrow("[Error] DirectXMl Not Support SoVits4.0V2, Please Use Cuda Or Cpu") #endif if (!(_Config["Hop"].IsInt() || _Config["Hop"].IsInt64())) LibDLVoiceCodecThrow("[Error] Hop Must Exist And Must Be Int") HopSize = _Config["Hop"].GetInt(); if (!(_Config["HiddenSize"].IsInt() || _Config["HiddenSize"].IsInt64())) logger.log(L"[Warn] Missing Field \"HiddenSize\", Use Default Value (256)"); else HiddenUnitKDims = _Config["HiddenSize"].GetInt(); if (!_Config["CharaMix"].IsBool()) logger.log(L"[Warn] Missing Field \"CharaMix\", Use Default Value (False)"); else EnableCharaMix = _Config["CharaMix"].GetBool(); if (_Config["Cluster"].IsString()) { const auto clus = to_wide_string(_Config["Cluster"].GetString()); if (!(_Config["KMeansLength"].IsInt() || _Config["KMeansLength"].IsInt64())) logger.log(L"[Warn] Missing Field \"KMeansLength\", Use Default Value (10000)"); else ClusterCenterSize = _Config["KMeansLength"].GetInt(); try { Cluster = MoeVoiceStudioCluster::GetMoeVSCluster(clus, _PathDict.at("Cluster"), HiddenUnitKDims, ClusterCenterSize); EnableCluster = true; } catch (std::exception& e) { logger.error(e.what()); EnableCluster = false; } } if (HopSize < 1) LibDLVoiceCodecThrow("[Error] Hop Must > 0") if (_Config["Volume"].IsBool()) EnableVolume = _Config["Volume"].GetBool(); else logger.log(L"[Warn] Missing Field \"Volume\", Use Default Value (False)"); if (_Config["Characters"].IsArray()) SpeakerCount = int64_t(_Config["Characters"].Size()); _callback = _ProgressCallback; //LoadModels try { logger.log(L"[Info] loading VitsSvcModel Models"); hubert = new Ort::Session(*env, _PathDict.at("Hubert").c_str(), *session_options); if (VitsSvcVersion == L"RVC") VitsSvcModel = new Ort::Session(*env, _PathDict.at("RVC").c_str(), *session_options); else VitsSvcModel = new Ort::Session(*env, _PathDict.at("SoVits").c_str(), *session_options); logger.log(L"[Info] VitsSvcModel Models loaded"); } catch (Ort::Exception& _exception) { Destory(); LibDLVoiceCodecThrow(_exception.what()) } if (VitsSvcModel->GetInputCount() == 4 && VitsSvcVersion != L"SoVits3.0") VitsSvcVersion = L"SoVits2.0"; if (_Config["TensorExtractor"].IsString()) VitsSvcVersion = to_wide_string(_Config["TensorExtractor"].GetString()); MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others _others_param; _others_param.Memory = *memory_info; try { _TensorExtractor = GetTensorExtractor(VitsSvcVersion, 48000, _samplingRate, HopSize, EnableCharaMix, EnableVolume, HiddenUnitKDims, SpeakerCount, _others_param); } catch (std::exception& e) { Destory(); LibDLVoiceCodecThrow(e.what()) } } std::vector VitsSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Start!"); std::vector _data; size_t total_audio_size = 0; for (const auto& data_size : _Slice.Slices) total_audio_size += data_size.OrgLen; _data.reserve(size_t(double(total_audio_size) * 1.5)); _callback(0, _Slice.Slices.size()); size_t process = 0; for (auto& CurSlice : _Slice.Slices) { const auto InferDurTime = clock(); const auto CurRtn = SliceInference(CurSlice, _InferParams, process); _data.insert(_data.end(), CurRtn.data(), CurRtn.data() + CurRtn.size()); if(CurSlice.IsNotMute) logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Segment[" + std::to_wstring(process) + L"] Finished! Segment Use Time: " + std::to_wstring(clock() - InferDurTime) + L"ms, Segment Duration: " + std::to_wstring((size_t)CurSlice.OrgLen * 1000ull / 48000ull) + L"ms"); else logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Jump Empty Segment[" + std::to_wstring(process) + L"]!"); _callback(++process, _Slice.Slices.size()); } logger.log(L"[Inferring] \"" + _Slice.Path + L"\" Finished"); return _data; } ShallowDiffusionData DataForDiffusion; ShallowDiffusionData& GetDataForShallowDiffusion() { return DataForDiffusion; } std::vector VitsSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const { DataForDiffusion._16KAudio.clear(); DataForDiffusion.CUDAF0.clear(); DataForDiffusion.CUDAVolume.clear(); DataForDiffusion.CUDASpeaker.clear(); DataForDiffusion.NeedPadding = false; if (_Slice.IsNotMute) { DataForDiffusion._16KAudio = InferTools::InterpResample(_Slice.Audio, 48000, 16000, 32768.0f); const auto src_audio_length = DataForDiffusion._16KAudio.size(); bool NeedPadding = false; if (_cur_execution_provider == ExecutionProviders::CUDA) { NeedPadding = DataForDiffusion._16KAudio.size() % 16000; const size_t WavPaddedSize = DataForDiffusion._16KAudio.size() / 16000 + 1; if (NeedPadding) DataForDiffusion._16KAudio.resize(WavPaddedSize * 16000, 0.f); } const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)DataForDiffusion._16KAudio.size() }; std::vector HubertInputTensors, HubertOutPuts; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, DataForDiffusion._16KAudio.data(), DataForDiffusion._16KAudio.size(), HubertInputShape, 3)); try { HubertOutPuts = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } const auto HubertSize = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto HubertOutPutData = HubertOutPuts[0].GetTensorMutableData(); auto HubertOutPutShape = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetShape(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector SrcHiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; const auto max_cluster_size = int64_t((size_t)HubertOutPutShape[1] * src_audio_length / DataForDiffusion._16KAudio.size()); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto pts = Cluster->find(SrcHiddenUnits.data(), long(SpeakerIdx), max_cluster_size); for (int64_t indexs = 0; indexs < max_cluster_size * HiddenUnitKDims; ++indexs) SrcHiddenUnits[indexs] = SrcHiddenUnits[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::InferParams _Inference_Params; _Inference_Params.AudioSize = _Slice.Audio.size(); _Inference_Params.Chara = SpeakerIdx; _Inference_Params.NoiseScale = _InferParams.NoiseScale; _Inference_Params.DDSPNoiseScale = _InferParams.DDSPNoiseScale; _Inference_Params.Seed = int(_InferParams.Seed); _Inference_Params.upKeys = _InferParams.Keys; MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Inputs InputTensors; DataForDiffusion.NeedPadding = NeedPadding; if (_cur_execution_provider == ExecutionProviders::CUDA && NeedPadding) { DataForDiffusion.CUDAF0 = _Slice.F0; DataForDiffusion.CUDAVolume = _Slice.Volume; DataForDiffusion.CUDASpeaker = _Slice.Speaker; const auto src_src_audio_length = _Slice.Audio.size(); const size_t WavPaddedSize = ((src_src_audio_length / 48000) + 1) * 48000; const size_t AudioPadSize = WavPaddedSize - src_src_audio_length; const size_t PaddedF0Size = DataForDiffusion.CUDAF0.size() + (DataForDiffusion.CUDAF0.size() * AudioPadSize / src_src_audio_length); if (!DataForDiffusion.CUDAF0.empty()) DataForDiffusion.CUDAF0.resize(PaddedF0Size, 0.f); if (!DataForDiffusion.CUDAVolume.empty()) DataForDiffusion.CUDAVolume.resize(PaddedF0Size, 0.f); for (auto iSpeaker : DataForDiffusion.CUDASpeaker) { if (!iSpeaker.empty()) iSpeaker.resize(PaddedF0Size, 0.f); } _Inference_Params.AudioSize = WavPaddedSize; InputTensors = _TensorExtractor->Extract(SrcHiddenUnits, DataForDiffusion.CUDAF0, DataForDiffusion.CUDAVolume, DataForDiffusion.CUDASpeaker, _Inference_Params); } else InputTensors = _TensorExtractor->Extract(SrcHiddenUnits, _Slice.F0, _Slice.Volume, _Slice.Speaker, _Inference_Params); std::vector finaOut; try { finaOut = VitsSvcModel->Run(Ort::RunOptions{ nullptr }, InputTensors.InputNames, InputTensors.Tensor.data(), InputTensors.Tensor.size(), soVitsOutput.data(), soVitsOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: VitsSvc\n") + e.what())) } const auto dstWavLen = (_Slice.OrgLen * int64_t(_samplingRate)) / 48000; /*if (shallow_diffusion && stft_operator && _InferParams.UseShallowDiffusion) { auto PCMAudioBegin = finaOut[0].GetTensorData(); auto PCMAudioEnd = PCMAudioBegin + finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto MelSpec = MelExtractor(PCMAudioBegin, PCMAudioEnd); auto ShallowParam = _InferParams; ShallowParam.SrcSamplingRate = _samplingRate; auto ShallowDiffusionOutput = shallow_diffusion->ShallowDiffusionInference( RawWav, ShallowParam, std::move(MelSpec[0]), NeedPadding ? CUDAF0 : _Slice.F0, NeedPadding ? CUDAVolume : _Slice.Volume, NeedPadding ? CUDASpeaker : _Slice.Speaker ); ShallowDiffusionOutput.resize(dstWavLen, 0); return ShallowDiffusionOutput; }*/ const auto shapeOut = finaOut[0].GetTensorTypeAndShapeInfo().GetShape(); std::vector TempVecWav = std::vector(dstWavLen, 0); if (shapeOut[2] < dstWavLen) for (int64_t bbb = 0; bbb < shapeOut[2]; bbb++) TempVecWav[bbb] = static_cast(Clamp(finaOut[0].GetTensorData()[bbb]) * 32766.0f); else for (int64_t bbb = 0; bbb < dstWavLen; bbb++) TempVecWav[bbb] = static_cast(Clamp(finaOut[0].GetTensorData()[bbb]) * 32766.0f); return TempVecWav; } //Mute clips const auto len = size_t(_Slice.OrgLen * int64_t(_samplingRate) / 48000); return { len, 0i16, std::allocator() }; } std::vector VitsSvc::Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { std::vector _Lens = GetOpenFileNameMoeVS(); std::vector AudioFolders; for (auto& path : _Lens) { path = std::regex_replace(path, std::wregex(L"\\\\"), L"/"); auto PCMData = AudioPreprocess().codec(path, 48000); auto slicer_setting = _SlicerSettings; slicer_setting.SamplingRate = 48000; auto SlicePos = SliceAudio(PCMData, slicer_setting); auto Audio = GetAudioSlice(PCMData, SlicePos, slicer_setting); Audio.Path = path; PreProcessAudio(Audio, 48000, 512, _InferParams.F0Method); std::vector _data = SliceInference(Audio, _InferParams); std::wstring OutFolder = GetCurrentFolder() + L"/Outputs/" + path.substr(path.rfind(L'/') + 1, path.rfind(L'.') - path.rfind(L'/') - 1); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; OutFolder += L"-Params-(-NoiseScale=" + std::to_wstring(_InferParams.NoiseScale) + L"-Speaker=" + (EnableCharaMix ? std::wstring(L"SpeakerMix") : std::to_wstring(SpeakerIdx)) + L"-Seed=" + std::to_wstring(_InferParams.Seed) + L"-F0Method=" + _InferParams.F0Method + L")"; if (_waccess((OutFolder + L".wav").c_str(), 0) != -1) { for (size_t idx = 0; idx < 99999999; ++idx) if (_waccess((OutFolder + L" (" + std::to_wstring(idx) + L").wav").c_str(), 0) == -1) { OutFolder += L" (" + std::to_wstring(idx) + L").wav"; break; } } else OutFolder += L".wav"; AudioFolders.emplace_back(OutFolder); _data = InferTools::InterpResample(_data, _samplingRate, 48000, 1i16); InferTools::Wav::WritePCMData(48000, 1, _data, OutFolder); } return AudioFolders; } std::vector VitsSvc::InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { auto hubertin = InferTools::InterpResample(PCMData, srcSr, 16000); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); float noise_scale = _InferParams.NoiseScale; float ddsp_noise_scale = _InferParams.DDSPNoiseScale; const int64_t inputShape[3] = { 1i64,1i64,(int64_t)hubertin.size() }; std::vector inputTensorshu; inputTensorshu.emplace_back(Ort::Value::CreateTensor(*memory_info, hubertin.data(), hubertin.size(), inputShape, 3)); std::vector hubertOut; try { hubertOut = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), inputTensorshu.data(), inputTensorshu.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } auto HubertSize = hubertOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto HubertOutPutData = hubertOut[0].GetTensorMutableData(); auto HubertOutPutShape = hubertOut[0].GetTensorTypeAndShapeInfo().GetShape(); inputTensorshu.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector HiddenUnitsSrc(HubertOutPutData, HubertOutPutData + HubertSize); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto clus_size = HubertOutPutShape[1]; const auto pts = Cluster->find(HiddenUnitsSrc.data(), long(SpeakerIdx), clus_size); for (size_t indexs = 0; indexs < HiddenUnitsSrc.size(); ++indexs) HiddenUnitsSrc[indexs] = HiddenUnitsSrc[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; int64_t F0Shape[] = { 1, int64_t(PCMData.size() / HopSize) }; int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t LengthShape[] = { 1 }; int64_t CharaEmbShape[] = { 1 }; int64_t CharaMixShape[] = { F0Shape[1], SpeakerCount }; int64_t RandnShape[] = { 1, 192, F0Shape[1] }; const int64_t IstftShape[] = { 1, 2048, F0Shape[1] }; int64_t RandnCount = F0Shape[1] * 192; const int64_t IstftCount = F0Shape[1] * 2048; std::vector RandnInput, IstftInput, UV, InterpedF0; std::vector alignment; int64_t XLength[1] = { HubertLen }; std::vector Nsff0; //auto SoVitsInput = soVitsInput; int64_t Chara[] = { SpeakerIdx }; std::vector charaMix; const auto F0Extractor = MoeVSF0Extractor::GetF0Extractor(_InferParams.F0Method, _samplingRate, HopSize); auto srcF0Data = F0Extractor->ExtractF0(PCMData, PCMData.size() / HopSize); for (auto& ifo : srcF0Data) ifo *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); std::vector HiddenUnits; std::vector F0Data; std::vector _Tensors; std::vector SoVitsInput = soVitsInput; //Compatible with all versions if (VitsSvcVersion == L"SoVits3.0") { int64_t upSample = _samplingRate / 16000; HiddenUnits.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < HiddenUnitShape[1]; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) HiddenUnits.insert(HiddenUnits.end(), HiddenUnitsSrc.begin() + itS * HiddenUnitKDims, HiddenUnitsSrc.begin() + (itS + 1) * HiddenUnitKDims); HiddenUnitShape[1] *= upSample; HubertSize *= upSample; F0Data = _TensorExtractor->GetInterpedF0(InferTools::InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1]))); F0Shape[1] = HiddenUnitShape[1]; XLength[0] = HiddenUnitShape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, F0Data.data(), F0Data.size(), F0Shape, 2)); } else if (VitsSvcVersion == L"SoVits2.0") { HiddenUnits = std::move(HiddenUnitsSrc); F0Shape[1] = HiddenUnitShape[1]; F0Data = InferTools::InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1])); XLength[0] = HiddenUnitShape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); Nsff0 = _TensorExtractor->GetNSFF0(F0Data); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Nsff0.data(), Nsff0.size(), F0Shape, 2)); } else if (VitsSvcVersion == L"RVC") { constexpr int64_t upSample = 2; HiddenUnits.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < HiddenUnitShape[1]; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) HiddenUnits.insert(HiddenUnits.end(), HiddenUnitsSrc.begin() + itS * HiddenUnitKDims, HiddenUnitsSrc.begin() + (itS + 1) * HiddenUnitKDims); HiddenUnitShape[1] *= upSample; HubertSize *= upSample; F0Data = InferTools::InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1])); F0Shape[1] = HiddenUnitShape[1]; XLength[0] = HiddenUnitShape[1]; RandnCount = 192 * F0Shape[1]; RandnShape[2] = F0Shape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); InterpedF0 = _TensorExtractor->GetInterpedF0(F0Data); Nsff0 = _TensorExtractor->GetNSFF0(InterpedF0); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Nsff0.data(), Nsff0.size(), F0Shape, 2)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), InterpedF0.size(), F0Shape, 2)); SoVitsInput = RVCInput; RandnInput = std::vector(RandnCount, 0.f); for (auto& it : RandnInput) it = normal(gen) * noise_scale; } else { HiddenUnits = std::move(HiddenUnitsSrc); F0Data = InferTools::InterpFunc(srcF0Data, long(srcF0Data.size()), long(F0Shape[1])); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); InterpedF0 = _TensorExtractor->GetInterpedF0(F0Data); alignment = _TensorExtractor->GetAligments(F0Shape[1], HubertLen); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), InterpedF0.size(), F0Shape, 2)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, alignment.data(), InterpedF0.size(), F0Shape, 2)); if (VitsSvcVersion != L"SoVits4.0-DDSP") { UV = _TensorExtractor->GetUV(F0Data); SoVitsInput = { "c", "f0", "mel2ph", "uv", "noise", "sid" }; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, UV.data(), UV.size(), F0Shape, 2)); } else { SoVitsInput = { "c", "f0", "mel2ph", "t_window", "noise", "sid" }; IstftInput = std::vector(IstftCount, ddsp_noise_scale); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, IstftInput.data(), IstftInput.size(), IstftShape, 3)); } RandnInput = std::vector(RandnCount, 0.f); for (auto& it : RandnInput) it = normal(gen) * noise_scale; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RandnInput.data(), RandnCount, RandnShape, 3)); } if (EnableCharaMix) { CharaMixShape[0] = F0Shape[1]; std::vector charaMap(SpeakerCount, 0.f); charaMap[SpeakerIdx] = 1.f; charaMix.reserve((SpeakerCount + 1) * F0Shape[1]); for (int64_t index = 0; index < F0Shape[1]; ++index) charaMix.insert(charaMix.end(), charaMap.begin(), charaMap.end()); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, charaMix.data(), charaMix.size(), CharaMixShape, 2)); } else _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Chara, 1, CharaEmbShape, 1)); if (VitsSvcVersion == L"RVC") _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RandnInput.data(), RandnCount, RandnShape, 3)); std::vector VolumeData; if (EnableVolume) { SoVitsInput.emplace_back("vol"); VolumeData = ExtractVolume(PCMData, HopSize); VolumeData.resize(F0Shape[1], 0.f); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, VolumeData.data(), F0Shape[1], F0Shape, 2)); } std::vector finaOut; finaOut = VitsSvcModel->Run(Ort::RunOptions{ nullptr }, SoVitsInput.data(), _Tensors.data(), _Tensors.size(), soVitsOutput.data(), soVitsOutput.size()); const auto dstWavLen = finaOut[0].GetTensorTypeAndShapeInfo().GetShape()[2]; std::vector TempVecWav(dstWavLen, 0); for (int64_t bbb = 0; bbb < dstWavLen; bbb++) TempVecWav[bbb] = static_cast(Clamp(finaOut[0].GetTensorData()[bbb]) * 32766.0f); if(VitsSvcVersion == L"RVC") TempVecWav = InferTools::InterpResample(TempVecWav, _samplingRate, 48000, 1i16); return TempVecWav; } /*std::vector VitsSvc::MelExtractor(const float* PCMAudioBegin, const float* PCMAudioEnd) const { std::vector _SRAudio{PCMAudioBegin, PCMAudioEnd}; _SRAudio = InferTools::InterpResample(_SRAudio, _samplingRate, 16000, 1.f); const auto _MelLength = int64_t(_SRAudio.size() * shallow_diffusion->GetSamplingRate() / 16000ull / shallow_diffusion->GetHopSize()); const auto _SpecLength = (int64_t)ceil(double(_SRAudio.size()) / 16000. * 100.); auto Alignment = _TensorExtractor->GetAligments(_MelLength, _SpecLength); Alignment.resize(_MelLength); std::vector AudioTensors; const int64_t AudioInputShape[] = { 1,1,int64_t(_SRAudio.size()) }; const int64_t AligShape[] = { 1,_MelLength }; AudioTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _SRAudio.data(), _SRAudio.size(), AudioInputShape, 3)); AudioTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Alignment.data(), Alignment.size(), AligShape, 2)); try { return stft_operator->Run(Ort::RunOptions{ nullptr }, StftInput.data(), AudioTensors.data(), AudioTensors.size(), StftOutput.data(), StftOutput.size() ); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: ShallowDiffusionStftOperator\n") + e.what()).c_str()); } }*/ //已弃用(旧MoeSS的推理函数) #ifdef MOESSDFN std::vector VitsSvc::InferBatch() const { std::wstring RawPath; int ret = InsertMessageToEmptyEditBox(RawPath); if (ret == -1) LibDLVoiceCodecThrow("TTS Does Not Support Automatic Completion"); if (ret == -2) LibDLVoiceCodecThrow("Please Select Files"); RawPath += L'\n'; std::vector _Lens = CutLens(RawPath); const auto params = _get_init_params(); auto tran = static_cast(params.keys); auto threshold = static_cast(params.threshold); auto minLen = static_cast(params.minLen); auto frame_len = static_cast(params.frame_len); auto frame_shift = static_cast(params.frame_shift); if (frame_shift < 512 || frame_shift > 10240) frame_shift = 512; if (frame_len < 1024 || frame_len > 20480) frame_len = 1024; if (frame_shift > frame_len) { frame_shift = 512; frame_len = 4 * 1024; } if (minLen < 3 || minLen > 30) minLen = 3; if (threshold < 10.0 || threshold > 2000.0) threshold = 30.0; int64_t charEmb = params.chara; std::mt19937 gen(int(params.seed)); std::normal_distribution normal(0, 1); float noise_scale = params.noise_scale; float ddsp_noise_scale = params.noise_scale_w; if (noise_scale > 50.0f) noise_scale = 1.0f; if (ddsp_noise_scale > 50.0f) ddsp_noise_scale = 1.0f; for (auto& path : _Lens) { logger.log(L"[Inferring] Inferring \"" + path + L'\"'); size_t proc = 0; if (path[0] == L'\"') path = path.substr(1); if (path[path.length() - 1] == L'\"') path.pop_back(); std::vector _data; //Audio logger.log(L"[Inferring] PreProcessing \"" + path + L"\" Encoder"); auto RawWav = AudioPreprocess().codec(path, _samplingRate); auto HubertWav = AudioPreprocess().codec(path, 16000); auto info = cutWav(RawWav, threshold, minLen, static_cast(frame_len), static_cast(frame_shift)); for (size_t i = 1; i < info.cutOffset.size(); ++i) if ((info.cutOffset[i] - info.cutOffset[i - 1]) / RawWav.getHeader().bytesPerSec > 90) LibDLVoiceCodecThrow("Reached max slice length, please change slicer param"); const auto LenFactor = ((double)16000 / (double)_samplingRate); _callback(proc, info.cutTag.size()); logger.log(L"[Inferring] Inferring \"" + path + L"\" Svc"); for (size_t i = 1; i < info.cutOffset.size(); ++i) { if (info.cutTag[i - 1]) { auto featureInput = F0PreProcess(_samplingRate, (short)hop); const auto len = (info.cutOffset[i] - info.cutOffset[i - 1]) / 2; const auto srcPos = info.cutOffset[i - 1] / 2; std::vector source(len, 0.0); for (unsigned long long j = 0; j < len; ++j) source[j] = (double)RawWav[srcPos + j] / 32768.0; //hubertIn const auto hubertInLen = (size_t)((double)len * LenFactor); std::vector hubertin(hubertInLen, 0.0); const auto startPos = (size_t)(((double)info.cutOffset[i - 1] / 2.0) * LenFactor); for (size_t j = 0; j < hubertInLen; ++j) hubertin[j] = (float)HubertWav[startPos + j] / 32768.0f; //hubert const int64_t inputShape[3] = { 1i64,1i64,(int64_t)hubertInLen }; std::vector inputTensors; inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, hubertin.data(), hubertInLen, inputShape, 3)); std::vector hubertOut; try { hubertOut = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), inputTensors.data(), inputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what()).c_str()); } auto hubertOutData = hubertOut[0].GetTensorMutableData(); auto hubertOutLen = hubertOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto hubertOutShape = hubertOut[0].GetTensorTypeAndShapeInfo().GetShape(); std::vector inputPitch1, alignment; std::vector inputPitch2; F0PreProcess::V4Return v4_return; std::vector hubOutData(hubertOutData, hubertOutData + hubertOutLen); if (SV3) { if (_samplingRate / 16000 == 2) { for (int64_t itS = hubertOutShape[1] - 1; itS + 1; --itS) { hubOutData.insert(hubOutData.begin() + itS * 256, hubOutData.begin() + itS * 256, hubOutData.begin() + (itS + 1) * 256); } hubertOutShape[1] *= 2; hubertOutLen *= 2; inputPitch2 = featureInput.GetF0AndOtherInput3(source.data(), (long long)len, (long long)hubertOutShape[1], (long long)tran); } else if (_samplingRate / 16000 == 3) { for (int64_t itS = hubertOutShape[1] - 1; itS + 1; --itS) { hubOutData.insert(hubOutData.begin() + itS * 256, hubOutData.begin() + itS * 256, hubOutData.begin() + (itS + 1) * 256); hubOutData.insert(hubOutData.begin() + itS * 256, hubOutData.begin() + itS * 256, hubOutData.begin() + (itS + 1) * 256); } hubertOutShape[1] *= 3; hubertOutLen *= 3; inputPitch2 = featureInput.GetF0AndOtherInput3(source.data(), (long long)len, (long long)hubertOutShape[1], (long long)tran); } else LibDLVoiceCodecThrow("SoVits3.0 Only Support Sr: 48K,32K"); } else if (SV4) { alignment = getAligments(len / hop, hubertOutShape[1]); v4_return = featureInput.GetF0AndOtherInput4(source.data(), (long long)len, tran); } else if (_modelType == modelType::RVC) { for (int64_t itS = hubertOutShape[1] - 1; itS + 1; --itS) { hubOutData.insert(hubOutData.begin() + itS * 256, hubOutData.begin() + itS * 256, hubOutData.begin() + (itS + 1) * 256); } hubertOutShape[1] *= 2; hubertOutLen *= 2; auto f0data = featureInput.GetF0AndOtherInputR(source.data(), (long long)len, (long long)hubertOutShape[1], (long long)tran); inputPitch1 = std::move(f0data.f0); inputPitch2 = std::move(f0data.f0f); } else { inputPitch1 = featureInput.GetF0AndOtherInput(source.data(), (long long)len, (long long)hubertOutShape[1], (long long)tran); } inputTensors.clear(); auto SoVitsInput = soVitsInput; //vits constexpr long long ashape[1] = { 1 }; long long ainput[1] = { hubertOutShape[1] }; const long long bshape[2] = { 1, featureInput.getLen() }; long long cdata[1] = { charEmb }; constexpr long long cshape[1] = { 1 }; const int64 zinputShape[3] = { 1,192,featureInput.getLen() }; const int64 zinputCount = featureInput.getLen() * 192; std::vector zinput(zinputCount, 0.0); inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, hubOutData.data(), hubertOutLen, hubertOutShape.data(), 3)); std::vector T_Window(2048 * featureInput.getLen(), ddsp_noise_scale); int64_t T_WindowShape[] = { 1, 2048, featureInput.getLen() }; if (!SV4) inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, ainput, 1, ashape, 1)); if (SV3) inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, inputPitch2.data(), featureInput.getLen(), bshape, 2)); else if (SV4) { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, v4_return.f0.data(), featureInput.getLen(), bshape, 2)); inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, alignment.data(), featureInput.getLen(), bshape, 2)); if (!SVV2) { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, v4_return.uv.data(), featureInput.getLen(), bshape, 2)); SoVitsInput = { "c", "f0", "mel2ph", "uv", "noise", "sid" }; } else { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, T_Window.data(), T_Window.size(), T_WindowShape, 3)); SoVitsInput = { "c", "f0", "mel2ph", "t_window", "noise", "sid" }; } for (auto& it : zinput) it = normal(gen) * noise_scale; inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, zinput.data(), zinputCount, zinputShape, 3)); } else { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, inputPitch1.data(), featureInput.getLen(), bshape, 2)); if (_modelType == modelType::RVC) { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, inputPitch2.data(), featureInput.getLen(), bshape, 2)); SoVitsInput = RVCInput; for (auto& it : zinput) it = normal(gen) * noise_scale; } } inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, cdata, 1, cshape, 1)); std::vector finaOut; if (_modelType == modelType::RVC) inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, zinput.data(), zinputCount, zinputShape, 3)); try { finaOut = VitsSvcModel->Run(Ort::RunOptions{ nullptr }, SoVitsInput.data(), inputTensors.data(), inputTensors.size(), soVitsOutput.data(), soVitsOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: sovits\n") + e.what()).c_str()); } const auto shapeOut = finaOut[0].GetTensorTypeAndShapeInfo().GetShape(); const auto dstWavLen = int64_t(len); std::vector TempVecWav(dstWavLen, 0); if (shapeOut[2] < dstWavLen) { for (int64_t bbb = 0; bbb < shapeOut[2]; bbb++) TempVecWav[bbb] = static_cast(finaOut[0].GetTensorData()[bbb] * 32768.0f); } else { for (int64_t bbb = 0; bbb < dstWavLen; bbb++) TempVecWav[bbb] = static_cast(finaOut[0].GetTensorData()[bbb] * 32768.0f); } _data.insert(_data.end(), TempVecWav.data(), TempVecWav.data() + (dstWavLen)); } else { const auto len = (info.cutOffset[i] - info.cutOffset[i - 1]) / 2; const auto data = new int16_t[len]; memset(data, 0, len * 2); _data.insert(_data.end(), data, data + len); delete[] data; } _callback(++proc, info.cutTag.size()); } logger.log(L"[Inferring] \"" + path + L"\" Finished"); if (_Lens.size() == 1) { logger.log(L"[Info] Finished, Send To FrontEnd"); return _data; } std::wstring outPutPath = GetCurrentFolder() + L"\\OutPuts\\" + path.substr(path.rfind(L'\\') + 1, path.rfind(L'.')) + L'-' + std::to_wstring(uint64_t(path.data())) + L".wav"; logger.log(L"[Inferring] Write To \"" + outPutPath + L'\"'); Wav(_samplingRate, long(_data.size()) * 2, _data.data()).Writef(outPutPath); } logger.log(L"[Info] Finished"); return {}; } #endif /* std::vector VitsSvc::InferSliceTensor(const MoeVSProjectSpace::MoeVSAudioSlice& _Slice, size_t SliceIdx, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::vector& _Tensors, std::vector& SoVitsInput) const { int64_t charEmb = _InferParams.SpeakerId; float noise_scale = _InferParams.NoiseScale; float ddsp_noise_scale = _InferParams.DDSPNoiseScale; auto RawWav = TensorPreprocess::MoeVoiceStudioTensorExtractor::InterpResample(_Slice.Audio[SliceIdx], 48000, 16000, 32768.0f); const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)RawWav.size() }; std::vector HubertInputTensors, HubertOutPuts; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RawWav.data(), RawWav.size(), HubertInputShape, 3)); try { HubertOutPuts = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what()).c_str()); } auto HubertSize = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto HubertOutPutData = HubertOutPuts[0].GetTensorMutableData(); auto HubertOutPutShape = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetShape(); HubertInputTensors.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch"); std::vector srcHiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { for (int64_t indexs = 0; indexs < HubertOutPutShape[1]; ++indexs) { const auto curbeg = srcHiddenUnits.data() + indexs * HubertOutPutShape[2]; const auto curend = srcHiddenUnits.data() + (indexs + 1) * HubertOutPutShape[2]; const auto hu = Cluster->find({ curbeg ,curend }, long(charEmb)); for (int64_t ind = 0; ind < HubertOutPutShape[2]; ++ind) *(curbeg + ind) = *(curbeg + ind) * (1.f - _InferParams.ClusterRate) + hu[ind] * _InferParams.ClusterRate; } } const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; int64_t F0Shape[] = { 1, int64_t(_Slice.Audio[SliceIdx].size() * _samplingRate / 48000 / HopSize) }; int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t LengthShape[] = { 1 }; int64_t CharaEmbShape[] = { 1 }; int64_t CharaMixShape[] = { F0Shape[1], SpeakerCount }; int64_t RandnShape[] = { 1, 192, F0Shape[1] }; const int64_t IstftShape[] = { 1, 2048, F0Shape[1] }; int64_t RandnCount = F0Shape[1] * 192; const int64_t IstftCount = F0Shape[1] * 2048; std::vector RandnInput, IstftInput, UV, InterpedF0; std::vector alignment; int64_t XLength[1] = { HubertLen }; std::vector Nsff0; //auto SoVitsInput = soVitsInput; int64_t Chara[] = { charEmb }; std::vector charaMix; auto srcF0Data = _Slice.F0[SliceIdx]; for (auto& ifo : srcF0Data) ifo *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); std::vector HiddenUnits; std::vector F0Data; //Compatible with all versions if (SoVits3) { int64_t upSample = _samplingRate / 16000; HiddenUnits.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < HiddenUnitShape[1]; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) HiddenUnits.insert(HiddenUnits.end(), srcHiddenUnits.begin() + itS * HiddenUnitKDims, srcHiddenUnits.begin() + (itS + 1) * HiddenUnitKDims); HiddenUnitShape[1] *= upSample; HubertSize *= upSample; F0Data = GetInterpedF0(InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1]))); F0Shape[1] = HiddenUnitShape[1]; XLength[0] = HiddenUnitShape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, F0Data.data(), F0Data.size(), F0Shape, 2)); } else if (SoVits2) { HiddenUnits = std::move(srcHiddenUnits); F0Shape[1] = HiddenUnitShape[1]; F0Data = InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1])); XLength[0] = HiddenUnitShape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); Nsff0 = GetNSFF0(F0Data); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Nsff0.data(), Nsff0.size(), F0Shape, 2)); } else if (_modelType == modelType::RVC) { constexpr int64_t upSample = 2; HiddenUnits.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < HiddenUnitShape[1]; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) HiddenUnits.insert(HiddenUnits.end(), srcHiddenUnits.begin() + itS * HiddenUnitKDims, srcHiddenUnits.begin() + (itS + 1) * HiddenUnitKDims); HiddenUnitShape[1] *= upSample; HubertSize *= upSample; F0Data = InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1])); F0Shape[1] = HiddenUnitShape[1]; XLength[0] = HiddenUnitShape[1]; RandnCount = 192 * F0Shape[1]; RandnShape[2] = F0Shape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); InterpedF0 = GetInterpedF0(F0Data); Nsff0 = GetNSFF0(InterpedF0); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Nsff0.data(), Nsff0.size(), F0Shape, 2)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), InterpedF0.size(), F0Shape, 2)); SoVitsInput = RVCInput; RandnInput = std::vector(RandnCount, 0.f); for (auto& it : RandnInput) it = normal(gen) * noise_scale; } else { HiddenUnits = std::move(srcHiddenUnits); F0Data = InterpFunc(srcF0Data, long(srcF0Data.size()), long(F0Shape[1])); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); InterpedF0 = GetInterpedF0(F0Data); alignment = GetAligments(F0Shape[1], HubertLen); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), InterpedF0.size(), F0Shape, 2)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, alignment.data(), InterpedF0.size(), F0Shape, 2)); if (!SoVitsDDSP) { UV = GetUV(F0Data); SoVitsInput = { "c", "f0", "mel2ph", "uv", "noise", "sid" }; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, UV.data(), UV.size(), F0Shape, 2)); } else { SoVitsInput = { "c", "f0", "mel2ph", "t_window", "noise", "sid" }; IstftInput = std::vector(IstftCount, ddsp_noise_scale); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, IstftInput.data(), IstftInput.size(), IstftShape, 3)); } RandnInput = std::vector(RandnCount, 0.f); for (auto& it : RandnInput) it = normal(gen) * noise_scale; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RandnInput.data(), RandnCount, RandnShape, 3)); } if (EnableCharaMix) { if (SpeakerCount > 1) charaMix = GetCurrectSpkMixData(_Slice.Speaker[SliceIdx], F0Shape[1]); CharaMixShape[0] = F0Shape[1]; if (charaMix.empty()) { std::vector charaMap(SpeakerCount, 0.f); charaMap[charEmb] = 1.f; charaMix.reserve((SpeakerCount + 1) * F0Shape[1]); for (int64_t index = 0; index < F0Shape[1]; ++index) charaMix.insert(charaMix.end(), charaMap.begin(), charaMap.end()); } _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, charaMix.data(), charaMix.size(), CharaMixShape, 2)); } else _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Chara, 1, CharaEmbShape, 1)); if (_modelType == modelType::RVC) _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RandnInput.data(), RandnCount, RandnShape, 3)); std::vector VolumeData; if (EnableVolume) { SoVitsInput.emplace_back("vol"); VolumeData = InterpFunc(_Slice.Volume[SliceIdx], long(_Slice.Volume[SliceIdx].size()), long(F0Shape[1])); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, VolumeData.data(), F0Shape[1], F0Shape, 2)); } return VitsSvcModel->Run(Ort::RunOptions{ nullptr }, SoVitsInput.data(), _Tensors.data(), _Tensors.size(), soVitsOutput.data(), soVitsOutput.size()); } */ #ifdef WIN32 #ifdef MoeVSMui void VitsSvc::StartRT(Mui::Window::UIWindowBasic* window, const MoeVSProjectSpace::MoeVSSvcParams& _Params) { if (RTSTAT) return; std::wstring error; recoder = new MRecorder(); recoder->InitRecorder(error, _samplingRate, 1, 16, Mui::_m_uint(_samplingRate * 0.5)); recoder->Start(); audio_player = new Mui::Render::MDS_AudioPlayer(window); audio_player->InitAudioPlayer(error); audio_stream = audio_player->CreateStreamPCM(recoder->GetFrameSize(), recoder->GetSampleRate(), recoder->GetChannels(), recoder->GetBitRate(), recoder->GetBlockAlign()); audio_player->PlayTrack(audio_stream); emptyLen = InferPCMData(std::vector(recoder->GetFrameSize() / 4 * 3), _samplingRate, _Params).size(); std::thread RT_RECORD_THREAD = std::thread([&]() { logger.log(L"[RTInference] Recording Thread Start!"); while (RTSTAT) { const auto PCM = recoder->GetStreamData(); if (!PCM) continue; rawInputBuffer.emplace_back((int16_t*)PCM->data, (int16_t*)(PCM->data + PCM->size)); delete PCM; } logger.log(L"[RTInference] Recording Thread End!"); }); std::thread RT_INPUT_CROSSFADE_THREAD = std::thread([&]() { logger.log(L"[RTInference] Input Crossfade Thread Start!"); //const auto config = _get_init_params(); while (RTSTAT) { if (rawInputBuffer.size() > 1) { std::vector pBuffer; pBuffer.reserve(2 * rawInputBuffer[0].size()); pBuffer.insert(pBuffer.end(), rawInputBuffer[0].begin(), rawInputBuffer[0].end()); pBuffer.insert(pBuffer.end(), rawInputBuffer[1].begin(), rawInputBuffer[1].begin() + int64_t(rawInputBuffer[1].size()) / 2); inputBuffer.emplace_back(std::move(pBuffer)); rawInputBuffer.pop_front(); } if (rawInputBuffer.size() > 100) { logger.log(L"[RTInferenceWarn] Raw Input Buffer Is Too Large"); } } logger.log(L"[RTInference] Input Crossfade Thread End!"); }); std::thread RT_INFERENCE_THREAD = std::thread([&]() { logger.log(L"[RTInference] Inferencing Thread Start!"); const auto PCMSIZE = recoder->GetFrameSize() / 2; while (RTSTAT) { //const auto configs = _get_init_params(); if (!inputBuffer.empty()) { try { bool zeroVector = true; for(const auto& i16data : inputBuffer[0]) { if(i16data> 1600) { zeroVector = false; break; } } if(zeroVector) rawOutputBuffer.emplace_back(std::vector(emptyLen, 0)); else { auto RtRES = InferPCMData(inputBuffer[0], _samplingRate, _Params); rawOutputBuffer.emplace_back(std::move(RtRES)); } inputBuffer.pop_front(); } catch (std::exception& e) { RTSTAT = false; inputBuffer.clear(); outputBuffer.clear(); rawInputBuffer.clear(); rawOutputBuffer.clear(); LibDLVoiceCodecThrow(e.what()); } } if (inputBuffer.size() > 100) { logger.log(L"[RTInferenceWarn] Input Buffer Is Too Large"); } } logger.log(L"[RTInference] Inferencing Thread End!"); }); std::thread RT_OUTPUT_CROSSFADE_THREAD = std::thread([&]() { logger.log(L"[RTInference] OutPut Crossfade Thread Start!"); while (RTSTAT) { if (rawOutputBuffer.size() > 1) { const auto cross_fade_size = int64_t(rawOutputBuffer[0].size()) / 3; const auto PCMSIZE = cross_fade_size * 2; for (int64_t i = 0; i < cross_fade_size; ++i) { rawOutputBuffer[0][PCMSIZE + i] = int16_t(((double)rawOutputBuffer[0][PCMSIZE + i] * (1.0 - (double(i) / double(cross_fade_size)))) + ((double)rawOutputBuffer[1][i] * (double(i) / double(cross_fade_size)))); rawOutputBuffer[1][PCMSIZE + i] = int16_t(((double)rawOutputBuffer[0][PCMSIZE + i] * (1.0 - (double(i) / double(cross_fade_size)))) + ((double)rawOutputBuffer[1][i] * (double(i) / double(cross_fade_size)))); } std::vector pBuffer(rawOutputBuffer[0].data() + cross_fade_size / 2, rawOutputBuffer[0].data() + 2 * cross_fade_size + cross_fade_size / 2); outputBuffer.emplace_back(std::move(pBuffer)); rawOutputBuffer.pop_front(); } } logger.log(L"[RTInference] OutPut Crossfade Thread End!"); }); std::thread RT_OUTPUT_THREAD = std::thread([&]() { logger.log(L"[RTInference] OutPut Thread Start!"); const auto PCMSIZE = recoder->GetFrameSize(); std::vector pBuffer(PCMSIZE); Mui::_m_size lastSize = 0; while (RTSTAT) { if (!outputBuffer.empty()) { //audio_player->WriteStreamPCM(audio_stream, (Mui::_m_byte*)outputBuffer.front().data(), Mui::_m_size(RTAudioSize)); //outputBuffer.pop_front(); auto queue_data = (Mui::_m_byte*)outputBuffer[0].data(); auto queue_dataSize = Mui::_m_size(outputBuffer[0].size() * 2); while (queue_dataSize + lastSize >= PCMSIZE) { //每次从队列中拿走帧大小的数据 const auto dataSize = PCMSIZE - lastSize; memcpy(pBuffer.data() + lastSize, queue_data, dataSize); //调用WriteStream 播放 audio_player->WriteStreamPCM(audio_stream, pBuffer.data(), PCMSIZE); //指针偏移 queue_data += dataSize; queue_dataSize -= dataSize; lastSize = 0; } //如果剩余数据不足PCMLength if (queue_dataSize > 0) { //检查本次queue能否把缓冲区填满 if (lastSize + queue_dataSize >= PCMSIZE) { //计算剩余空间 const auto dataSize = PCMSIZE - lastSize; //复制数据到buffer memcpy(pBuffer.data() + lastSize, queue_data, dataSize); audio_player->WriteStreamPCM(audio_stream, pBuffer.data(), PCMSIZE); queue_data += dataSize; queue_dataSize -= dataSize; lastSize = 0; } //如果剩余空间仍然不足PCMLength,将剩余数据复制到buffer中 等待下次循环 if (queue_dataSize > 0) { memcpy(pBuffer.data() + lastSize, queue_data, queue_dataSize); lastSize += queue_dataSize; } } logger.log(L"OUTPUTBUFFERLEN:" + std::to_wstring(outputBuffer.size())); logger.log(L"INPUTBUFFERLEN:" + std::to_wstring(inputBuffer.size())); outputBuffer.pop_front(); } } logger.log(L"[RTInference] OutPut Thread End!"); }); logger.log(L"[RTInference] Start RTInference!"); for (uint64_t idx = 0; idx < 1; ++idx) rawInputBuffer.emplace_back(recoder->GetFrameSize() / 2, 0); RTSTAT = true; RT_RECORD_THREAD.detach(); RT_INPUT_CROSSFADE_THREAD.detach(); RT_INFERENCE_THREAD.detach(); RT_OUTPUT_CROSSFADE_THREAD.detach(); RT_OUTPUT_THREAD.detach(); while (true); } void VitsSvc::EndRT() { recoder->Stop(); audio_player->StopTrack(audio_stream); audio_player->DeleteTrack(audio_stream); delete audio_stream; delete audio_player; delete recoder; audio_stream = nullptr; audio_player = nullptr; recoder = nullptr; if (RTSTAT) RTSTAT = false; inputBuffer.clear(); outputBuffer.clear(); rawInputBuffer.clear(); rawOutputBuffer.clear(); } #endif #endif MoeVoiceStudioCoreEnd ================================================ FILE: libdlvoicecodec/Modules/Modules.cpp ================================================ #include "Modules.hpp" #include "InferTools/F0Extractor/DioF0Extractor/DioF0Extractor.hpp" #include "InferTools/F0Extractor/F0ExtractorManager.hpp" #include "InferTools/TensorExtractor/MoeVSCoreTensorExtractor.hpp" #include "InferTools/Cluster/MoeVSClusterManager.hpp" #include "InferTools/Cluster/MoeVSKmeansCluster.hpp" #include "InferTools/F0Extractor/HarvestF0Extractor/HarvestF0Extractor.hpp" #include "InferTools/Sampler/MoeVSSamplerManager.hpp" #include "InferTools/Sampler/MoeVSSamplers.hpp" #include "InferTools/F0Extractor/NetF0Predictors/NetF0Predictors.hpp" #include "InferTools/Stft/stft.hpp" #ifdef MoeVoiceStudioIndexCluster #ifdef max #undef max #endif #include "InferTools/Cluster/MoeVSIndexCluster.hpp" #endif #define MoeVSRegisterF0Constructor(__RegisterName, __ClassName) MoeVSF0Extractor::RegisterF0Extractor(__RegisterName, \ [](int32_t sampling_rate, int32_t hop_size, \ int32_t n_f0_bins, double max_f0, double min_f0) \ -> MoeVSF0Extractor::F0Extractor \ { \ return new MoeVSF0Extractor::__ClassName(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0); \ }) #define MoeVSRegisterTensorConstructor(__RegisterName, __ClassName) MoeVSTensorPreprocess::RegisterTensorExtractor(__RegisterName,\ [](uint64_t _srcsr, uint64_t _sr, uint64_t _hop, \ bool _smix, bool _volume, uint64_t _hidden_size, \ uint64_t _nspeaker, \ const MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others& _other) \ ->MoeVSTensorPreprocess::TensorExtractor \ { \ return new MoeVSTensorPreprocess::__ClassName(_srcsr, _sr, _hop, _smix, _volume, \ _hidden_size, _nspeaker, _other); \ }) #define MoeVSRegisterCluster(__RegisterName, __ClassName) MoeVoiceStudioCluster::RegisterMoeVSCluster(__RegisterName,\ [](const std::wstring& _path, size_t hidden_size, size_t KmeansLen) \ ->MoeVoiceStudioCluster::MoeVSCluster \ { \ return new MoeVoiceStudioCluster::__ClassName(_path, hidden_size, KmeansLen); \ }) #define MoeVSRegisterSampler(__RegisterName, __ClassName) MoeVSSampler::RegisterMoeVSSampler(__RegisterName, \ [](Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, \ const MoeVSSampler::MoeVSBaseSampler::ProgressCallback& _ProgressCallback, \ Ort::MemoryInfo* memory) -> MoeVSSampler::MoeVSSampler \ { \ return new MoeVSSampler::__ClassName(alpha, dfn, pred, Mel_Bins, _ProgressCallback, memory); \ }) namespace MoeVSModuleManager { bool MoeVoiceStudioCoreInitStat = false; MoeVoiceStudioCore::VitsSvc* GlobalVitsSvcModel = nullptr; MoeVoiceStudioCore::DiffusionSvc* GlobalDiffusionSvcModel = nullptr; MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback ProgessBar; int64_t VitsSamplingRate = 32000; void MoeVoiceStudioCoreInitSetup() { if (MoeVoiceStudioCoreInitStat) return; MoeVSRegisterF0Constructor(L"Dio", DioF0Extractor); MoeVSRegisterF0Constructor(L"Harvest", HarvestF0Extractor); MoeVSRegisterF0Constructor(L"RMVPE", RMVPEF0Extractor); MoeVSRegisterF0Constructor(L"FCPE", MELPEF0Extractor); MoeVSRegisterTensorConstructor(L"SoVits2.0", SoVits2TensorExtractor); MoeVSRegisterTensorConstructor(L"SoVits3.0", SoVits3TensorExtractor); MoeVSRegisterTensorConstructor(L"SoVits4.0", SoVits4TensorExtractor); MoeVSRegisterTensorConstructor(L"SoVits4.0-DDSP", SoVits4DDSPTensorExtractor); MoeVSRegisterTensorConstructor(L"RVC", RVCTensorExtractor); MoeVSRegisterTensorConstructor(L"DiffSvc", DiffSvcTensorExtractor); MoeVSRegisterTensorConstructor(L"DiffusionSvc", DiffusionSvcTensorExtractor); MoeVSRegisterCluster(L"KMeans", KMeansCluster); #ifdef MoeVoiceStudioIndexCluster MoeVSRegisterCluster(L"Index", IndexCluster); #endif MoeVSRegisterSampler(L"Pndm", PndmSampler); MoeVSRegisterSampler(L"DDim", DDimSampler); const auto BasicCleanerDir = GetCurrentFolder() + L"/G2P/BasicCleaner.dll"; if (_waccess(BasicCleanerDir.c_str(), 0) != -1) { const auto Cleaner = MoeVSG2P::GetDefCleaner(); Cleaner->loadG2p(BasicCleanerDir); Cleaner->GetCleaner().LoadDict(GetCurrentFolder() + L"/G2P"); } MoeVoiceStudioCoreInitStat = true; } MoeVoiceStudioCore::VitsSvc* GetVitsSvcModel() { return GlobalVitsSvcModel; } MoeVoiceStudioCore::DiffusionSvc* GetDiffusionSvcModel() { return GlobalDiffusionSvcModel; } void UnloadVitsSvcModel() { delete GlobalVitsSvcModel; GlobalVitsSvcModel = nullptr; } void UnloadDiffusionSvcModel() { delete GlobalDiffusionSvcModel; GlobalDiffusionSvcModel = nullptr; } void LoadVitsSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID) { ProgessBar = Callback; UnloadVitsSvcModel(); if (Config["Type"].GetString() == "DiffSvc") LibDLVoiceCodecThrow("Trying To Load Diffusion Model As VitsSvc Model!") GlobalVitsSvcModel = new MoeVoiceStudioCore::VitsSvc( Config, Callback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ); VitsSamplingRate = GlobalVitsSvcModel->GetSamplingRate(); SamplingRate = VitsSamplingRate; } void LoadDiffusionSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID) { ProgessBar = Callback; UnloadDiffusionSvcModel(); if (Config["Type"].GetString() == "DiffSvc") GlobalDiffusionSvcModel = new MoeVoiceStudioCore::DiffusionSvc( Config, Callback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ); else LibDLVoiceCodecThrow("Trying To Load VitsSvc Model As Diffusion Model!") if(VocoderEnabled()) if (!GetVitsSvcModel() || (!GlobalDiffusionSvcModel->OldVersion() && GlobalDiffusionSvcModel->GetDiffSvcVer() == L"DiffusionSvc")) SamplingRate = GlobalDiffusionSvcModel->GetSamplingRate(); } void LoadVocoderModel(const std::wstring& VocoderPath) { MoeVoiceStudioCore::LoadVocoderModel(VocoderPath); } void UnloadVocoderModel() { MoeVoiceStudioCore::UnLoadVocoderModel(); } bool VocoderEnabled() { return MoeVoiceStudioCore::VocoderEnabled(); } std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) { const bool DiffusionModelEnabled = GlobalDiffusionSvcModel && VocoderEnabled(); std::vector RtnAudio; size_t TotalAudioSize = 0; for (const auto& data_size : _Slice.Slices) TotalAudioSize += data_size.OrgLen; RtnAudio.reserve(size_t(double(TotalAudioSize) * 1.5)); //VitsSteps int64_t GlobalSteps = 0; if (GlobalVitsSvcModel) GlobalSteps = 1; //DiffusionSteps auto SkipDiffusionStep = (int64_t)_InferParams.Pndm; auto DiffusionTotalStep = (int64_t)_InferParams.Step; if (DiffusionModelEnabled && DiffusionTotalStep > GlobalDiffusionSvcModel->GetMaxStep()) DiffusionTotalStep = GlobalDiffusionSvcModel->GetMaxStep(); if (SkipDiffusionStep >= DiffusionTotalStep) SkipDiffusionStep = DiffusionTotalStep / 5; if (SkipDiffusionStep == 0) SkipDiffusionStep = 1; const auto RealDiffSteps = DiffusionTotalStep % SkipDiffusionStep ? DiffusionTotalStep / SkipDiffusionStep + 1 : DiffusionTotalStep / SkipDiffusionStep; if((DiffusionModelEnabled && !GlobalVitsSvcModel) || (DiffusionModelEnabled && ShallowDiffusionEnabled())) { if (GlobalDiffusionSvcModel->OldVersion()) GlobalSteps += 1; else GlobalSteps += RealDiffSteps; } //TotalSteps const int64_t TotalSteps = GlobalSteps * int64_t(_Slice.Slices.size()); size_t ProgressVal = 0; size_t SliceIndex = 0; ProgessBar(0, TotalSteps); for (const auto& CurSlice : _Slice.Slices) { const auto InferBeginTime = clock(); const auto CurRtn = SliceInference(CurSlice, _InferParams, ProgressVal); RtnAudio.insert(RtnAudio.end(), CurRtn.data(), CurRtn.data() + CurRtn.size()); if (CurSlice.IsNotMute) logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Segment[" + std::to_wstring(SliceIndex++) + L"] Finished! Segment Use Time: " + std::to_wstring(clock() - InferBeginTime) + L"ms, Segment Duration: " + std::to_wstring((size_t)CurSlice.OrgLen * 1000ull / 48000ull) + L"ms"); else { if (DiffusionModelEnabled && !GlobalDiffusionSvcModel->OldVersion()) { ProgressVal += RealDiffSteps; ProgessBar(ProgressVal, TotalSteps); } logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Jump Empty Segment[" + std::to_wstring(SliceIndex++) + L"]!"); } if (DiffusionModelEnabled && GlobalDiffusionSvcModel->OldVersion()) ProgessBar(++ProgressVal, TotalSteps); if (GlobalVitsSvcModel) ProgessBar(++ProgressVal, TotalSteps); } logger.log(L"[Inferring] \"" + _Slice.Path + L"\" Finished"); return RtnAudio; } int CurStftSr = -1, CurHopSize = -1; DlCodecStft::Mel* MelOperator = nullptr; std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) { const bool DiffusionModelEnabled = GlobalDiffusionSvcModel && VocoderEnabled(); int64_t SamplingRate_I64 = VitsSamplingRate; SamplingRate = VitsSamplingRate; if ((DiffusionModelEnabled && !GlobalVitsSvcModel) || (_InferParams.UseShallowDiffusion && DiffusionModelEnabled && ShallowDiffusionEnabled())) { SamplingRate_I64 = GlobalDiffusionSvcModel->GetSamplingRate(); SamplingRate = GlobalDiffusionSvcModel->GetSamplingRate(); } if (!_Slice.IsNotMute) return { size_t(_Slice.OrgLen * SamplingRate_I64 / 48000), 0i16, std::allocator() }; std::vector RtnAudio; RtnAudio.reserve(size_t(double(_Slice.Audio.size()) * 1.5)); if (GlobalVitsSvcModel) { auto BgnTime = clock(); RtnAudio = GlobalVitsSvcModel->SliceInference(_Slice, _InferParams, _Process); logger.log(("[Inference] Slice Vits Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); if(_InferParams.UseShallowDiffusion && DiffusionModelEnabled && !GlobalDiffusionSvcModel->OldVersion() && GlobalDiffusionSvcModel->GetDiffSvcVer() == L"DiffusionSvc") { if (CurStftSr != SamplingRate_I64 || CurHopSize != GlobalDiffusionSvcModel->GetHopSize()) { delete MelOperator; CurStftSr = (int)SamplingRate_I64; CurHopSize = GlobalDiffusionSvcModel->GetHopSize(); MelOperator = new DlCodecStft::Mel(2048, CurHopSize, CurStftSr, (int)GlobalDiffusionSvcModel->GetMelBins()); } const std::vector TempAudio = InferTools::InterpResample(RtnAudio, (long)VitsSamplingRate, CurStftSr, 32767.); auto Mel = MelOperator->operator()(TempAudio); auto ShallData = MoeVoiceStudioCore::GetDataForShallowDiffusion(); BgnTime = clock(); RtnAudio = GlobalDiffusionSvcModel->ShallowDiffusionInference( ShallData._16KAudio, _InferParams, Mel, ShallData.NeedPadding ? ShallData.CUDAF0 : _Slice.F0, ShallData.NeedPadding ? ShallData.CUDAVolume : _Slice.Volume, ShallData.NeedPadding ? ShallData.CUDASpeaker : _Slice.Speaker, _Process, TempAudio.size() ); logger.log(("[Inference] Slice Diffusion Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); } } else if (DiffusionModelEnabled) { const auto BgnTime = clock(); RtnAudio = GlobalDiffusionSvcModel->SliceInference(_Slice, _InferParams, _Process); logger.log(("[Inference] Slice Diffusion Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); } else LibDLVoiceCodecThrow("You Must Load A Model To Inference!"); return RtnAudio; } bool ShallowDiffusionEnabled() { const bool DiffusionModelEnabled = GlobalDiffusionSvcModel && VocoderEnabled(); return DiffusionModelEnabled && !GlobalDiffusionSvcModel->OldVersion() && GlobalDiffusionSvcModel->GetDiffSvcVer() == L"DiffusionSvc"; } } ================================================ FILE: libdlvoicecodec/Modules/Modules.hpp ================================================ /** * FileName: Modules.hpp * Note: MoeVoiceStudioCore组件管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "Models/header/VitsSvc.hpp" #include "Models/header/DiffSvc.hpp" #include "Models/header/Vits.hpp" namespace MoeVSModuleManager { inline int64_t SpeakerCount = 0; inline int64_t SamplingRate = 32000; /** * \brief 初始化所有组件 */ void MoeVoiceStudioCoreInitSetup(); /** * \brief 获取当前VitsSvc模型 * \return 当前模型的指针 */ MoeVoiceStudioCore::VitsSvc* GetVitsSvcModel(); /** * \brief 获取当前DiffusionSvc模型 * \return 当前模型的指针 */ MoeVoiceStudioCore::DiffusionSvc* GetDiffusionSvcModel(); /** * \brief 卸载模型 */ void UnloadVitsSvcModel(); /** * \brief 卸载模型 */ void UnloadDiffusionSvcModel(); /** * \brief 载入VitsSvc模型 * \param Config 一个MJson类的实例(配置文件的JSON) * \param Callback 进度条回调函数 * \param ProviderID Provider在所有Provider中的ID(遵循Enum Class的定义) * \param NumThread CPU推理时的线程数(最好设置高一点,GPU不支持的算子可能也会Fallback到CPU) * \param DeviceID GPU设备ID */ void LoadVitsSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID); /** * \brief 载入DiffusionSvc模型 * \param Config 一个MJson类的实例(配置文件的JSON) * \param Callback 进度条回调函数 * \param ProviderID Provider在所有Provider中的ID(遵循Enum Class的定义) * \param NumThread CPU推理时的线程数(最好设置高一点,GPU不支持的算子可能也会Fallback到CPU) * \param DeviceID GPU设备ID */ void LoadDiffusionSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID); /** * \brief 载入Vocoder模型 * \param VocoderPath Vocoder路径 */ void LoadVocoderModel(const std::wstring& VocoderPath); /** * \brief 卸载Vocoder模型 */ void UnloadVocoderModel(); /** * \brief 检查Vocoder是否可用 * \return Vocoder状态 */ bool VocoderEnabled(); /** * \brief 推理多组数据 * \param _Slice 数据包 * \param _InferParams 参数 * \return 音频 */ std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams); /** * \brief 推理切片数据 * \param _Slice 切片数据 * \param _InferParams 参数 * \param _Process 进度条 * \return 音频 */ std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process); bool ShallowDiffusionEnabled(); } namespace MoeVSRename { using MoeVSVitsBasedSvc = MoeVoiceStudioCore::VitsSvc; using MoeVSDiffBasedSvc = MoeVoiceStudioCore::DiffusionSvc; } ================================================ FILE: libdlvoicecodec/Modules/README.md ================================================ # Example ```c++ #include "Modules/Models/header/Vits.hpp" int main(){ rapidjson::Document Config; Config.Parse("Your Config"); //Progress bar InferClass::BaseModelType::callback a_callback = [](size_t a, size_t b) {std::cout << std::to_string((float)a * 100.f / (float)b) << "%\n"; }; //return params for inference InferClass::BaseModelType::callback_params b_callback = []() { auto cbaaa = InferClass::InferConfigs(); cbaaa.kmeans_rate = 0.5; cbaaa.keys = 0; return cbaaa; }; //modify duration per phoneme InferClass::TTS::DurationCallback c_callback = [](std::vector&) {}; std::vector output; try { std::wstring inp("watashinoonaniomitekudasai"); auto model = dynamic_cast(new InferClass::VitsSvc(modConfigJson, a_callback, b_callback)); output = model->Inference(inp); Wav outWav(model->GetSamplingRate(), output.size() * 2, output.data()); outWav.Writef(L"test.wav"); delete model; } catch(std::exception& e) { std::cout << e.what(); } } ``` ================================================ FILE: libdlvoicecodec/Modules/StringPreprocess.hpp ================================================ #pragma once #include #include #include #ifdef _WIN32 #include #else #error #endif inline std::string to_byte_string(const std::wstring& input) { std::vector ByteString(input.length() * 6); WideCharToMultiByte( CP_UTF8, 0, input.c_str(), int(input.length()), ByteString.data(), int(ByteString.size()), nullptr, nullptr ); return ByteString.data(); } inline std::string to_ansi_string(const std::wstring& input) { std::vector ByteString(input.length() * 6); WideCharToMultiByte( CP_ACP, 0, input.c_str(), int(input.length()), ByteString.data(), int(ByteString.size()), nullptr, nullptr ); return ByteString.data(); } inline std::wstring to_wide_string(const std::string& input) { std::vector WideString(input.length() * 2); MultiByteToWideChar( CP_UTF8, 0, input.c_str(), int(input.length()), WideString.data(), int(WideString.size()) ); return WideString.data(); } template std::wstring vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) { std::wstring TmpStr = std::to_wstring(it); if ((std::is_same_v || std::is_same_v) && TmpStr.find(L'.') != std::string::npos) { while (TmpStr.back() == L'0') TmpStr.pop_back(); if (TmpStr.back() == L'.') TmpStr += L"0"; } vecstr += TmpStr + L", "; } if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } inline std::wstring string_vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) if (!it.empty()) vecstr += L'\"' + to_wide_string(it) + L"\", "; if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } inline std::wstring wstring_vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) if (!it.empty()) vecstr += L'\"' + it + L"\", "; if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } ================================================ FILE: libdlvoicecodec/MoeVoiceStudioSvc - Core - Cmd.cpp ================================================ #include #include "../libsvc/Api/header/libsvc.h" //测试用代码 #pragma pack(push, 1) struct WavHeader { char riff[4]; // "RIFF"标志 DWORD fileSize; // 文件大小 char wave[4]; // "WAVE"标志 char fmt[4]; // "fmt "标志 DWORD fmtSize; // 格式数据大小 WORD audioFormat; // 音频格式 WORD numChannels; // 声道数 DWORD sampleRate; // 采样率 DWORD byteRate; // 每秒字节数 WORD blockAlign; // 数据块对齐 WORD bitsPerSample; // 采样位数 char data[4]; // "data"标志 DWORD dataSize; // 音频数据大小 }; #pragma pack(pop) WavHeader header; bool ReadWavFile(const wchar_t* filename, std::vector& audioData) { FILE* file = nullptr; _wfopen_s(&file, filename, L"rb"); if (!file) { return false; } fread(&header, sizeof(WavHeader), 1, file); if (memcmp(header.riff, "RIFF", 4) != 0 || memcmp(header.wave, "WAVE", 4) != 0 || memcmp(header.fmt, "fmt ", 4) != 0 || memcmp(header.data, "data", 4) != 0) { fclose(file); return false; } audioData.resize(header.dataSize / sizeof(short)); fread(audioData.data(), sizeof(short), audioData.size(), file); fclose(file); return true; } void WriteWavFile(const wchar_t* filename, const std::vector& audioData) { FILE* file = nullptr; _wfopen_s(&file, filename, L"wb+"); if (!file) { return; } fwrite(&header, sizeof(WavHeader), 1, file); fwrite(audioData.data(), sizeof(short), audioData.size(), file); fclose(file); } int main() { libsvc::Init(); libsvc::Config Config; Config.TensorExtractor = L"RVC"; Config.SamplingRate = 40000; Config.HopSize = 320; Config.HubertPath = LR"(S:\VSGIT\MoeVoiceStudioSvc - Core - Cmd\x64\Debug\hubert\vec-768-layer-12.onnx)"; Config.SpeakerCount = 1; Config.HiddenUnitKDims = 768; Config.VitsSvc.VitsSvc = LR"(S:\VSGIT\MoeVoiceStudioSvc - Core - Cmd\x64\Debug\Models\NaruseMioShirakana\NaruseMioShirakana_RVC.onnx)"; libsvc::LoadModel(libsvc::ModelType::Vits, Config, L"Shirakana", [](size_t, size_t) {}, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders::CPU, 0, 8); std::vector _Pcm; ReadWavFile(L"input.wav", _Pcm); InferTools::SlicerSettings _SS; _SS.SamplingRate = static_cast(header.sampleRate); const auto pos = libsvc::SliceAudio(_Pcm, _SS); const auto slices = libsvc::PreprocessSlices(_Pcm, pos, _SS, static_cast(header.sampleRate)); size_t prop = 0; _Pcm.clear(); for(const auto& i : slices.Slices) { const auto _Temp = libsvc::InferSlice(libsvc::ModelType::Vits, L"Shirakana", i, {}, prop); _Pcm.insert(_Pcm.end(), _Temp.begin(), _Temp.end()); std::cout << double(++prop) / double(slices.Slices.size()) * 100. << std::endl; } WriteWavFile(L"output.wav", _Pcm); } ================================================ FILE: libdlvoicecodec/MoeVoiceStudioSvc - Core - Cmd.vcxproj ================================================ Debug Win32 Release Win32 Debug x64 Release x64 16.0 Win32Proj {7a5aa3a6-7488-4be9-93c3-c0aa0e39219e} MoeVoiceStudioSvcCoreCmd 10.0 MoeVoiceStudio - Core Application true v143 Unicode Application false v143 true Unicode Application true v143 Unicode true Application false v143 true Unicode true $(IncludePath) $(IncludePath) Level3 true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true Level3 true true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true true true Level3 true _DEBUG;_CONSOLE;MOEVSDMLPROVIDER;MoeVoiceStudioCommandLineProg;MoeVoiceStudioIndexCluster;%(PreprocessorDefinitions) true stdcpp17 4996 MultiThreadedDebug Console true S:\VSGIT\MoeVoiceStudioSvc - Core - Cmd\x64\libsvc\Debug;%(AdditionalLibraryDirectories) libsvc.lib;%(AdditionalDependencies) Level3 true true true NDEBUG;_CONSOLE;MOEVSDMLPROVIDER;MoeVoiceStudioCommandLineProg;%(PreprocessorDefinitions) true stdcpp17 4996 MultiThreaded Console true true true S:\VSGIT\MoeVoiceStudioSvc - Core - Cmd\x64\libsvc\Release;%(AdditionalLibraryDirectories) libsvc.lib;%(AdditionalDependencies) 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 ================================================ FILE: libdlvoicecodec/MoeVoiceStudioSvc - Core - Cmd.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 源文件 资源文件 资源文件 资源文件 ================================================ FILE: libdlvoicecodec/analyse/GptSoVits.md ================================================ # GptSoVits主要分为三个部分 ### VQ(内核为KMeans聚类) - Train:对训练集音频的ssl[^1]进行KMeans聚类,获取到的聚类中心构造一个Embedding(CodeBook.embed) - Infer:使用Indices获取聚类中心(CodeBook.embed)中的元素,构造一个ssl[^1]矩阵 与SoVits的KMeans/Index聚类类似,只不过SoVits的聚类在使用时是使用输入的HuBert在CodeBook中查找与其距离排名前K的点后加权平均,而GptSoVits则是使用一个AR循环预测所需的HuBert在CodeBook中的下标,之后使用该下标获取CodeBook中对应元素 --- ### AR(GPT) - Inputs: - text_seq:输入文本音素序列的数字ID(在Symbols数组中的下标) - text_bert:输入文本的Bert - ref_seq:参考文本音素序列的数字ID(在Symbols数组中的下标) - ref_bert:参考文本的Bert - ref_ssl:参考音频的ssl[^1] - OutPuts: - codes:输入到VQ的Indices,用于获取ssl[^1]的聚类中心 与Gpt类似,使用一个AR循环,通过输入文本编码后的信息预测一个响应序列(序列终止为EOS),该响应序列为训练集音频聚类后的聚类中心在CodeBook中的下标,之后会从CodeBook中获取相应的元素,相当于SoVits中的Hubert。 --- ### SoVits - Inputs: - codes:输入到VQ的Indices,用于获取ssl[^1]的聚类中心 - text_seq:输入文本音素序列的数字ID(在Symbols数组中的下标) - ref_audio:参考音频(训练集内音频) 与SoVits比较,其中的codes实际上相当于SoVits的Hubert,只不过这个Hubert是使用AR预测所得序列生成的。 GptSoVits使用输入音素的Embedding,AR预测所得的Hubert以及参考音频的Mel共通指导音频生成,可以有效的控制音频的语气,感情。 然而在一些时候,会出现漏字和错字的情况,可能和AR有较大的关系 --- ### 实验方案 将GptSovits中的AR部分去除,将VQ的输入从Indices(code)替换为ssl(即使用最临近点搜索)。即可获得一个svc模型。 两个音频,一个训练集参考音频,一个输入音频。需完成以下步骤。 1、训练集参考音频直接编码为mel记作ref_audio。 2、输入音频经过一个asr处理为音素序列记作text_seq。 3、输入音频经过hubert后使用最临近点搜索,从vq的embedding中取元素,记作ssl。 4、将ssl,text_seq和ref_audio作为vits的输入进行推理。 --- [^1]: ssl其实就是音频的Hubert,与SoVits的Hubert一致 ================================================ FILE: libdlvoicecodec/packages.config ================================================  ================================================ FILE: libsvc/Api/header/NativeApi.h ================================================ #pragma once #ifdef LIBSVC_EXPORTS #define LibSvcApi __declspec(dllexport) #else #ifndef LibSvcStaticLib #define LibSvcApi __declspec(dllimport) #else #define LibSvcApi #endif #endif #ifdef __GNUC__ #define LibSvcDeprecated __attribute__((deprecated)) #else #ifdef _MSC_VER #define LibSvcDeprecated __declspec(deprecated) #endif #endif #ifdef _WIN32 #include "windows.h" #endif #ifdef __cplusplus extern "C" { #endif #ifndef _WIN32 typedef signed char INT8, * PINT8; typedef signed short INT16, * PINT16; typedef signed int INT32, * PINT32; typedef signed long long INT64, * PINT64; typedef unsigned char UINT8, * PUINT8; typedef unsigned short UINT16, * PUINT16; typedef unsigned int UINT32, * PUINT32; typedef unsigned long long UINT64, * PUINT64; typedef wchar_t* NWPSTR, * LPWSTR, * PWSTR, * BSTR; #endif typedef void(*ProgCallback)(size_t, size_t); enum LibSvcExecutionProviders { CPU = 0, CUDA = 1, DML = 2 }; enum LibSvcModelType { Vits, Diffusion, Reflow }; #ifdef _MSC_VER #pragma pack(push, 4) #else #pragma pack(4) #endif struct LibSvcSlicerSettings { INT32 SamplingRate; double Threshold; double MinLength; INT32 WindowLength; INT32 HopSize; }; struct LibSvcParams { //ͨ float NoiseScale; // [ 0 ~ 10 ] INT64 Seed; // [ INT64 ] INT64 SpeakerId; //ĬϽɫID [ 0 ~ NS ] size_t SrcSamplingRate; //Դ [ SR ] INT64 SpkCount; //ģͽɫ [ NS ] //SVC float IndexRate; // [ 0 ~ 1 ] float ClusterRate; // [ 0 ~ 1 ] float DDSPNoiseScale; //DDSP [ 0 ~ 10 ] float Keys; // [ -64 ~ 64 ] size_t MeanWindowLength; //ֵ˲ڴС [ 1 ~ 20 ] size_t Pndm; //Diffusionٱ [ 1 ~ 200 ] size_t Step; //Diffusionܲ [ 1 ~ 1000 ] float TBegin; //Reflowʼ float TEnd; //Reflowֹ LPWSTR Sampler; //Diffusion ["Pndm" "DDim"] LPWSTR ReflowSampler; //Reflow ["Eular" "Rk4" "Heun" "Pecece"] LPWSTR F0Method; //F0ȡ㷨 ["Dio" "Harvest" "RMVPE" "FCPE"] INT32 UseShallowDiffusionOrEnhancer; //Ƿʹdzɢ/ǿ [0(false)/1(true)] void* _VocoderModel; //ģ Diffusionģͱ趨Ŀ void* _ShallowDiffusionModel; //ɢģ dzɢΪɢģ͵ַ INT32 ShallowDiffusionUseSrcAudio; //dzɢģǷʹԭʼƵ [0(false)/1(true)] INT32 VocoderHopSize; //HopSize [ Hop ] INT32 VocoderMelBins; //MelBins [ Bins ] INT32 VocoderSamplingRate; // [ SR ] INT64 ShallowDiffuisonSpeaker; //dzɢVitsģĽɫID [ 0 ~ NS ] }; struct DiffusionSvcPaths { LPWSTR Encoder; LPWSTR Denoise; LPWSTR Pred; LPWSTR After; LPWSTR Alpha; LPWSTR Naive; LPWSTR DiffSvc; }; struct ReflowSvcPaths { LPWSTR Encoder; LPWSTR VelocityFn; LPWSTR After; }; struct VitsSvcPaths { LPWSTR VitsSvc; }; struct LibSvcClusterConfig { INT64 ClusterCenterSize; LPWSTR Path; LPWSTR Type; //"KMeans" "Index" }; struct LibSvcHparams { LPWSTR TensorExtractor; LPWSTR HubertPath; DiffusionSvcPaths DiffusionSvc; VitsSvcPaths VitsSvc; ReflowSvcPaths ReflowSvc; LibSvcClusterConfig Cluster; INT32 SamplingRate; INT32 HopSize; INT64 HiddenUnitKDims; INT64 SpeakerCount; INT32 EnableCharaMix; INT32 EnableVolume; INT32 VaeMode; INT64 MelBins; INT64 Pndms; INT64 MaxStep; float SpecMin; float SpecMax; float Scale; }; #ifdef _MSC_VER #pragma pack(pop) #else #pragma pack() #endif typedef void* FloatVector, * DoubleDimsFloatVector, * Int16Vector, * UInt64Vector, * MelType, * SliceType, * SlicesType, * SvcModel, * VocoderModel; typedef const void* CFloatVector, * CDoubleDimsFloatVector, * CInt16Vector, * CUInt64Vector, * CMelType, * CSliceType, * CSlicesType; LibSvcApi void InitLibSvcHparams(LibSvcHparams* _Input); LibSvcApi void InitLibSvcParams(LibSvcParams* _Input); LibSvcApi void InitLibSvcSlicerSettings(LibSvcSlicerSettings* _Input); LibSvcApi float* LibSvcGetFloatVectorData(FloatVector _Obj); LibSvcApi size_t LibSvcGetFloatVectorSize(FloatVector _Obj); //DFloatVector LibSvcApi FloatVector LibSvcGetDFloatVectorData(DoubleDimsFloatVector _Obj, size_t _Index); LibSvcApi size_t LibSvcGetDFloatVectorSize(DoubleDimsFloatVector _Obj); //Audio - vector LibSvcApi Int16Vector LibSvcAllocateAudio(); LibSvcApi void LibSvcReleaseAudio(Int16Vector _Obj); LibSvcApi void LibSvcSetAudioLength(Int16Vector _Obj, size_t _Size); LibSvcApi void LibSvcInsertAudio(Int16Vector _ObjA, Int16Vector _ObjB); LibSvcApi short* LibSvcGetAudioData(Int16Vector _Obj); LibSvcApi size_t LibSvcGetAudioSize(Int16Vector _Obj); //Offset - vector LibSvcApi UInt64Vector LibSvcAllocateOffset(); LibSvcApi void LibSvcReleaseOffset(UInt64Vector _Obj); LibSvcApi void LibSvcSetOffsetLength(UInt64Vector _Obj, size_t _Size); LibSvcApi size_t* LibSvcGetOffsetData(UInt64Vector _Obj); LibSvcApi size_t LibSvcGetOffsetSize(UInt64Vector _Obj); //Mel - pair, int64_t> LibSvcApi MelType LibSvcAllocateMel(); LibSvcApi void LibSvcReleaseMel(MelType _Obj); LibSvcApi FloatVector LibSvcGetMelData(MelType _Obj); LibSvcApi INT64 LibSvcGetMelSize(MelType _Obj); //Slice - MoeVoiceStudioSvcSlice LibSvcApi Int16Vector LibSvcGetAudio(SliceType _Obj); LibSvcApi FloatVector LibSvcGetF0(SliceType _Obj); LibSvcApi FloatVector LibSvcGetVolume(SliceType _Obj); LibSvcApi DoubleDimsFloatVector LibSvcGetSpeaker(SliceType _Obj); LibSvcApi INT32 LibSvcGetSrcLength(SliceType _Obj); LibSvcApi INT32 LibSvcGetIsNotMute(SliceType _Obj); LibSvcApi void LibSvcSetSpeakerMixDataSize(SliceType _Obj, size_t _NSpeaker); //Slices - MoeVoiceStudioSvcData LibSvcApi SlicesType LibSvcAllocateSliceData(); LibSvcApi void LibSvcReleaseSliceData(SlicesType _Obj); LibSvcApi BSTR LibSvcGetAudioPath(SlicesType _Obj); LibSvcApi SliceType LibSvcGetSlice(SlicesType _Obj, size_t _Index); LibSvcApi size_t LibSvcGetSliceCount(SlicesType _Obj); /******************************************Fun**********************************************/ LibSvcApi void LibSvcInit(); LibSvcApi void LibSvcFreeString( BSTR _String ); LibSvcApi INT32 LibSvcSetGlobalEnv( UINT32 ThreadCount, UINT32 DeviceID, UINT32 Provider ); LibSvcApi void LibSvcSetMaxErrorCount( size_t Count ); LibSvcApi BSTR LibSvcGetError( size_t Index ); LibSvcApi INT32 LibSvcSliceAudio( CInt16Vector _Audio, //std::vector By "LibSvcAllocateAudio()" const void* _Setting, //Ptr Of LibSvcSlicerSettings UInt64Vector _Output //std::vector By "LibSvcAllocateOffset()" ); LibSvcApi INT32 LibSvcPreprocess( CInt16Vector _Audio, //std::vector By "LibSvcAllocateAudio()" CUInt64Vector _SlicePos, //std::vector By "LibSvcAllocateOffset()" INT32 _SamplingRate, INT32 _HopSize, double _Threshold, const wchar_t* _F0Method, //"Dio" "Harvest" "RMVPE" "FCPE" SlicesType _Output //Slices By "LibSvcAllocateSliceData()" ); LibSvcApi INT32 LibSvcStft( CInt16Vector _Audio, //std::vector By "LibSvcAllocateAudio()" INT32 _SamplingRate, INT32 _Hopsize, INT32 _MelBins, MelType _Output //Mel By "LibSvcAllocateMel()" ); LibSvcApi INT32 LibSvcInferSlice( SvcModel _Model, //SingingVoiceConversion Model UINT32 _T, CSliceType _Slice, //Slices By "LibSvcAllocateSliceData()" const void* _InferParams, //Ptr Of LibSvcParams size_t* _Process, Int16Vector _Output //std::vector By "LibSvcAllocateAudio()" ); LibSvcApi INT32 LibSvcInferPCMData( SvcModel _Model, //SingingVoiceConversion Model UINT32 _T, CInt16Vector _PCMData, const void* _InferParams, //Ptr Of LibSvcParams Int16Vector _Output //std::vector By "LibSvcAllocateAudio()" ); LibSvcApi LibSvcDeprecated INT32 LibSvcShallowDiffusionInference( SvcModel _Model, //SingingVoiceConversion Model CInt16Vector _16KAudioHubert, //SamplingRate Must Be 16000 MelType _Mel, //Mel By "LibSvcAllocateMel()" CFloatVector _SrcF0, CFloatVector _SrcVolume, CDoubleDimsFloatVector _SrcSpeakerMap, INT64 _SrcSize, const void* _InferParams, //Ptr Of LibSvcParams size_t* _Process, Int16Vector _Output //std::vector By "LibSvcAllocateAudio()" ); LibSvcApi LibSvcDeprecated INT32 LibSvcVocoderEnhance( VocoderModel _Model, //Vocoder Model MelType _Mel, //Mel By "LibSvcAllocateMel()" CFloatVector _F0, INT32 _VocoderMelBins, Int16Vector _Output //std::vector By "LibSvcAllocateAudio()" ); LibSvcApi SvcModel LibSvcLoadModel( UINT32 _T, const void* _Config, //Ptr Of LibSvcParams ProgCallback _ProgressCallback, UINT32 _ExecutionProvider = CPU, UINT32 _DeviceID = 0, UINT32 _ThreadCount = 0 ); LibSvcApi INT32 LibSvcUnloadModel( UINT32 _T, SvcModel _Model ); LibSvcApi VocoderModel LibSvcLoadVocoder( LPWSTR VocoderPath ); LibSvcApi INT32 LibSvcUnloadVocoder( VocoderModel _Model ); LibSvcApi INT32 LibSvcReadAudio( LPWSTR _AudioPath, INT32 _SamplingRate, Int16Vector _Output ); LibSvcApi void LibSvcEnableFileLogger( bool _Cond ); LibSvcApi void LibSvcWriteAudioFile( Int16Vector _PCMData, LPWSTR _OutputPath, INT32 _SamplingRate ); #ifdef __cplusplus } #endif ================================================ FILE: libsvc/Api/header/libsvc.h ================================================ #pragma once #include "../../Modules/header/Modules.hpp" #include namespace libsvccore { using Config = MoeVoiceStudioCore::Hparams; using VitsSvc = MoeVoiceStudioCore::VitsSvc; using DiffusionSvc = MoeVoiceStudioCore::DiffusionSvc; using ReflowSvc = MoeVoiceStudioCore::ReflowSvc; using ClusterBase = MoeVoiceStudioCluster::MoeVoiceStudioBaseCluster; using TensorExtractorBase = MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor; using ProgressCallback = MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback; using ExecutionProvider = MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders; using Slices = MoeVSProjectSpace::MoeVoiceStudioSvcData; using SingleSlice = MoeVSProjectSpace::MoeVoiceStudioSvcSlice; using Params = MoeVSProjectSpace::MoeVSSvcParams; enum class ModelType { Vits, Diffusion, Reflow }; LibSvcApi void SliceAudio(size_t& _Id, const std::vector& _Audio, const InferTools::SlicerSettings& _Setting); LibSvcApi void Preprocess(size_t& _Id, const std::vector& _Audio, const std::vector& _SlicePos, const InferTools::SlicerSettings& _Setting, int _SamplingRate, int _HopSize, const std::wstring& _F0Method); LibSvcApi int InferSlice(size_t& _Id, ModelType _T, const std::wstring& _Name, const SingleSlice& _Slice, const Params& _InferParams, size_t& _Process); LibSvcApi int ShallowDiffusionInference(size_t& _Id, const std::wstring& _Name, const std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize); LibSvcApi int Stft(size_t& _Id, const std::vector& _NormalizedAudio, int _SamplingRate, int _Hopsize, int _MelBins); LibSvcApi int VocoderEnhance(size_t& _Id, const std::vector& Mel, const std::vector& F0, size_t MelSize, long VocoderMelBins); LibSvcApi int LoadModel(ModelType _T, const Config& _Config, const std::wstring& _Name, const ProgressCallback& _ProgressCallback, ExecutionProvider ExecutionProvider_ = ExecutionProvider::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); LibSvcApi void UnloadModel(ModelType _T, const std::wstring& _Name); LibSvcApi std::any& GetData(size_t _Id); LibSvcApi void PopData(size_t _Id); /// /// Errorе󳤶ȣErrorϢ /// /// /// LibSvcApi void SetMaxErrorCount(size_t Count); /// /// ȡErrorеĵIndex /// /// /// LibSvcApi std::wstring& GetLastError(size_t Index); /// /// Stft /// /// LibSvcApi void EmptyStftCache(); /// /// ģ /// /// ģ· /// LibSvcApi void LoadVocoder(const std::wstring& VocoderPath); /// /// ʼʹǰã /// /// LibSvcApi void Init(); /// /// ȫֻҪӰF0Predictor /// /// LibSvcApi void SetGlobalEnv(unsigned ThreadCount, unsigned DeviceID, unsigned Provider); } namespace libsvc { using libsvccore::Config; using libsvccore::VitsSvc; using libsvccore::DiffusionSvc; using libsvccore::ClusterBase; using libsvccore::TensorExtractorBase; using libsvccore::ProgressCallback; using libsvccore::ExecutionProvider; using libsvccore::ModelType; using libsvccore::Slices; using libsvccore::SingleSlice; using libsvccore::Params; using MelContainer = std::pair, int64_t>; using libsvccore::SetMaxErrorCount; using libsvccore::GetLastError; using libsvccore::EmptyStftCache; using libsvccore::LoadVocoder; using libsvccore::Init; using libsvccore::SetGlobalEnv; /// /// жһģ /// /// ģ /// ģID /// inline void UnloadModel( ModelType _T, const std::wstring& _Name ) { libsvccore::UnloadModel(_T, _Name); } /// /// һģ /// /// ģ /// Ŀ /// ģID /// ص /// ExecutionProvider /// GPUID /// ߳ /// ɹأ0 ʧܣ0 inline int LoadModel( ModelType _T, const Config& _Config, const std::wstring& _Name, const ProgressCallback& _ProgressCallback, ExecutionProvider ExecutionProvider_ = ExecutionProvider::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0 ) { return libsvccore::LoadModel(_T, _Config, _Name, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_); } /** * \brief ƬƵ * \param _Audio ƵPCM-Signed-Int16 * \param _Setting Ƭ * \return ƬPos */ inline std::vector SliceAudio( const std::vector& _Audio, const InferTools::SlicerSettings& _Setting ) { size_t _Ptr = 0; libsvccore::SliceAudio(_Ptr, _Audio, _Setting); std::vector temp = std::any_cast>(libsvccore::GetData(_Ptr)); libsvccore::PopData(_Ptr); return temp; } /** * \brief ԤƬõƵ * \param _Audio Ƶ * \param _SlicePos ƬPos * \param _Setting Ƭ * \param _SamplingRate * \param _HopSize Hopsize * \param _F0Method F0㷨 * \return ԤݣԼһֱͽ */ inline Slices PreprocessSlices( const std::vector& _Audio, const std::vector& _SlicePos, const InferTools::SlicerSettings& _Setting, int _SamplingRate = 48000, int _HopSize = 512, const std::wstring& _F0Method = L"Dio" ) { size_t _Ptr = 0; libsvccore::Preprocess(_Ptr, _Audio, _SlicePos, _Setting, _SamplingRate, _HopSize, _F0Method); Slices temp = std::any_cast(libsvccore::GetData(_Ptr)); libsvccore::PopData(_Ptr); return temp; } /** * \brief ʱҶ任Mel * \param _NormalizedAudio һƵPCM * \param _SamplingRate * \param _Hopsize HopSize * \param _MelBins MelBins * \return Mel */ inline MelContainer Stft( const std::vector& _NormalizedAudio, int _SamplingRate, int _Hopsize, int _MelBins ) { size_t _Ptr = 0; libsvccore::Stft(_Ptr, _NormalizedAudio, _SamplingRate, _Hopsize, _MelBins); MelContainer temp = std::any_cast(libsvccore::GetData(_Ptr)); libsvccore::PopData(_Ptr); return temp; } /** * \brief һƬ * \param _T ģ * \param _Name ģID * \param _Slice Ƭ * \param _InferParams * \param _Process ܽ * \return ƵPCM */ inline std::vector InferSlice( ModelType _T, const std::wstring& _Name, const SingleSlice& _Slice, const Params& _InferParams, size_t& _Process ) { size_t _Ptr = 0; if(!libsvccore::InferSlice(_Ptr, _T, _Name, _Slice, _InferParams, _Process)) { std::vector temp = std::any_cast>(libsvccore::GetData(_Ptr)); libsvccore::PopData(_Ptr); return temp; } return {}; } /** * \brief dzɢ * \param _Name DiffusionģID * \param _16KAudioHubert 16000ʵԭʼƵǰƵ * \param _InferParams * \param _Mel Mel * \param _SrcF0 Ƶ * \param _SrcVolume * \param _SrcSpeakerMap ˵˱ * \param Process * \param SrcSize ԭʼƵȣƬƬijȣ * \return ƵPCM */ inline std::vector ShallowDiffusionInference( const std::wstring& _Name, const std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const MelContainer& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize ) { size_t _Ptr = 0; if(!libsvccore::ShallowDiffusionInference(_Ptr, _Name, _16KAudioHubert, _InferParams, _Mel, _SrcF0, _SrcVolume, _SrcSpeakerMap, Process, SrcSize)) { std::vector temp = std::any_cast>(libsvccore::GetData(_Ptr)); libsvccore::PopData(_Ptr); return temp; } return {}; } /** * \brief ǿ * \param Mel Mel * \param F0 Ƶ * \param MelSize Mel֡ * \param VocoderMelBins MelBins * \return PCM */ inline std::vector VocoderEnhance(const std::vector& Mel, const std::vector& F0, size_t MelSize, long VocoderMelBins) { size_t _Ptr = 0; if(!libsvccore::VocoderEnhance(_Ptr, Mel, F0, MelSize, VocoderMelBins)) { std::vector temp = std::any_cast>(libsvccore::GetData(_Ptr)); libsvccore::PopData(_Ptr); return temp; } return {}; } } ================================================ FILE: libsvc/Api/readme.md ================================================ ```c #include "NativeApi.h" //注意,一切设置对象长度/大小的操作都会realloc,缓冲区的地址会发生变化 void callback(size_t,size_t) {} SliceType _SingleSlice = 0; LibSvcSlicerSettings _Settings; //切片机设置 short* _InputBuffer = 0; PUINT64 _OffsetBuffer = 0; float* _F0Buffer = 0, * _VolumeBuffer = 0, * _CurSpeakerBuffer = 0; INT32 _Error = 0; size_t _SliceCount = 0; FloatVector _F0 = 0, _Volume = 0, _CurSpeaker = 0; DoubleDimsFloatVector _Speaker = 0; LibSvcHparams _ModelConfig; //模型配置 LibSvcParams _Params; //推理参数 SvcModel _Model = 0; VocoderModel _Vocoder = 0; bool _SpeakerMix = false; //启用角色混合 size_t _Process = 0; void func(){ LibSvcInit(); //在进行所有操作之前,必须调用该函数(该函数只能调用一次) //为内部实现类申请内存 Int16Vector _InputAudio = LibSvcAllocateAudio(); Int16Vector _OutPutAudio = LibSvcAllocateAudio(); UInt64Vector _SliceOffset = LibSvcAllocateOffset(); SlicesType _Slices = LibSvcAllocateSliceData(); MelType _Mel = LibSvcAllocateMel(); InitLibSvcSlicerSettings(&_Settings); InitLibSvcHparams(&_ModelConfig); InitLibSvcParams(&_Params); //设置输入缓冲区的大小 LibSvcSetAudioLength( _InputAudio, 114514 //输入音频的长度 ); //获取输入缓冲区 _InputBuffer = LibSvcGetAudioData( _InputAudio ); /* 此处自行实现:将你输入的音频(格式必须为PCM-SignedInt16-LE)写入_InputBuffer */ /* 此处自行修改_Settings(切片机设置) */ //对音频进行切片(获取切片的位置) _Error = LibSvcSliceAudio( _InputAudio, &_Settings, _SliceOffset ); if (_Error) { BSTR ErrorMessage = LibSvcGetError(0); LibSvcFreeString(ErrorMessage); } /* 此时切片位置已经保存在了_SliceOffset中,你可以通过调用LibSvcGetOffsetData来获取 其缓冲区修改其数值,也可以调用LibSvcSetOffsetLength来修改切片位置的个数 */ //预处理数据(提取F0、音量) _Error = LibSvcPreprocess( _InputAudio, _SliceOffset, 32000, //输入音频的采样率 512, //STFT HopSize 20.0, //静音阈值(0 - 32767) L"Dio", //F0算法("Dio" "Harvest" "RMVPE" "FCPE") _Slices ); if (_Error) { BSTR ErrorMessage = LibSvcGetError(0); LibSvcFreeString(ErrorMessage); } /* 此时推理所必须的数据均已存储入了_Slices中_Slices为一个切片的容器 */ //此处获取了数据的个数(等同于切片的个数) _SliceCount = LibSvcGetSliceCount( _Slices ); //此处获取了指定Index的单个切片 _SingleSlice = LibSvcGetSlice( _Slices, 0 //你需要获取到的Slice的索引 ); /* _SingleSlice为其中一个切片的数据(要注意如果_Slices的内存被释放,那么该_SingleSlice也会被释放) */ //获取F0容器,为一个Float数组,该数组的长度为音频长度(频谱帧数),表示每一帧的F0频率 _F0 = LibSvcGetF0(_SingleSlice); //获取F0Buffer _F0Buffer = LibSvcGetFloatVectorData(_F0); //获取Volume容器,为一个Float数组,该数组的长度为音频长度(频谱帧数),表示每一帧的音量(0-1) _Volume = LibSvcGetVolume(_SingleSlice); //获取VolumeBuffer _VolumeBuffer = LibSvcGetFloatVectorData(_Volume); /* 此处自己使用_F0Buffer与_VolumeBuffer修改切片中F0和Volume的数值 */ if(_SpeakerMix){ //此Scope中代码处理说话人混合数据(如果不需要角色混合那么就忽略该Scope) //设置说话人的数量(每一个SingleSlice都必须单独设置) LibSvcSetSpeakerMixDataSize( _SingleSlice, 114 //你模型说话人的数量 ); //获取说话人混合信息,包含所有说话人,一共[114]个(上一个函数中设置的说话人数量),相当于float[SpeakerCount][SpecFrameCount] _Speaker = LibSvcGetSpeaker( _SingleSlice ); //获取指定ID的说话人混合信息,为一个Float数组,该数组的长度为音频长度(频谱帧数),相当于float[SpecFrameCount],该容器代表每一帧中该角色的 //音色占全体说话人音色的比例,该容器中的数据必须 ≥ 0,可以 > 1,大于一的数据将会自动归一化(在Speaker维度上归一化)。 _CurSpeaker = LibSvcGetDFloatVectorData( _Speaker, 0 //说话人ID ); //获取说话人混合信息的Buffer _CurSpeakerBuffer = LibSvcGetFloatVectorData( _CurSpeaker ); /* 接下来就可以用_CurSpeakerBuffer修改角色混合比例了 */ } //加载模型,第一个参数为Type,0为Vits系SVC,1为Diffusion/ReflowSvc _Model = LibSvcLoadModel( 0, //模型类型(0为Vits系SVC,1为Diffusion/ReflowSvc) &_ModelConfig, //模型配置 callback, //进度条回调函数 CPU, //算子提供器 0, //GPU ID 8 //线程数 ); if (!_Model) { BSTR ErrorMessage = LibSvcGetError(0); LibSvcFreeString(ErrorMessage); } //加载声码器模型 _Vocoder = LibSvcLoadVocoder( nullptr //声码器模型路径 ); if (!_Vocoder) { BSTR ErrorMessage = LibSvcGetError(0); LibSvcFreeString(ErrorMessage); } //一定要把_Vocoder模型的指针加载到_Params中 _Params._VocoderModel = _Vocoder; //普通推理 { LibSvcInferSlice( _Model, //模型 0, //模型类型 _SingleSlice, //切片 &_Params, //参数 &_Process, //当前进度 _OutPutAudio //输出 ); } //声码器增强 { _Params.VocoderHopSize = 512; _Params.VocoderMelBins = 128; _Params.VocoderSamplingRate = 44100; _Params._VocoderModel = _Vocoder; LibSvcInferSlice( _Model, //模型 0, //模型类型 _SingleSlice, //切片 &_Params, //参数 &_Process, //当前进度 _OutPutAudio //输出 ); } //浅扩散推理 { _Params.VocoderHopSize = 512; _Params.VocoderMelBins = 128; _Params.VocoderSamplingRate = 44100; _Params._VocoderModel = _Vocoder; _Params._ShallowDiffusionModel = nullptr; //改为你的Diffusion模型 LibSvcInferSlice( _Model, //模型 0, //模型类型 _SingleSlice, //切片 &_Params, //参数 &_Process, //当前进度 _OutPutAudio //输出 ); } //释放模型,第一个参数为类型 LibSvcUnloadModel( 0, _Model ); //释放声码器 LibSvcUnloadVocoder( _Vocoder ); //释放其他资源 LibSvcReleaseAudio(_OutPutAudio); LibSvcReleaseAudio(_InputAudio); LibSvcReleaseMel(_Mel); LibSvcReleaseOffset(_SliceOffset); LibSvcReleaseSliceData(_Slices); } ``` ================================================ FILE: libsvc/Api/src/NativeApi.cpp ================================================ #include "../header/NativeApi.h" #include #include #include "../../Modules/header/Modules.hpp" #include "../../header/InferTools/Stft/stft.hpp" #include "../../Modules/header/InferTools/AvCodec/AvCodeResample.h" #ifdef _MSC_VER #pragma warning(disable:4996) #endif const wchar_t* LibSvcNullString = L""; #define LibSvcNullStrCheck(Str) ((Str)?(Str):(LibSvcNullString)) #ifndef _WIN32 BSTR SysAllocString(const wchar_t* _String) { wchar_t* ret = new wchar_t[wcslen(_String)]; wcscpy(ret, _String); return ret; } void SysFreeString(BSTR _String) { delete[] _String; } #endif std::deque ErrorQueue; size_t MaxErrorCount = 20; using Config = MoeVoiceStudioCore::Hparams; using VitsSvc = MoeVoiceStudioCore::VitsSvc; using UnionSvc = MoeVSModuleManager::UnionSvcModel; using ReflowSvc = MoeVoiceStudioCore::ReflowSvc; using ClusterBase = MoeVoiceStudioCluster::MoeVoiceStudioBaseCluster; using TensorExtractorBase = MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor; using ProgressCallback = MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback; using ExecutionProvider = MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders; using Slices = MoeVSProjectSpace::MoeVoiceStudioSvcData; using SingleSlice = MoeVSProjectSpace::MoeVoiceStudioSvcSlice; using Params = MoeVSProjectSpace::MoeVSSvcParams; using AudioContainer = std::vector; using OffsetContainer = std::vector; using MelContainer = std::pair, int64_t>; using DataContainer = Slices; std::unordered_map MelOperators; void InitLibSvcHparams(LibSvcHparams* _Input) { _Input->TensorExtractor = nullptr; _Input->HubertPath = nullptr; _Input->DiffusionSvc = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; _Input->VitsSvc = { nullptr }; _Input->ReflowSvc = { nullptr, nullptr, nullptr }; _Input->Cluster = { 10000, nullptr, nullptr }; _Input->SamplingRate = 22050; _Input->HopSize = 320; _Input->HiddenUnitKDims = 256; _Input->SpeakerCount = 1; _Input->EnableCharaMix = false; _Input->EnableVolume = false; _Input->VaeMode = true; _Input->MelBins = 128; _Input->Pndms = 100; _Input->MaxStep = 1000; _Input->SpecMin = -12; _Input->SpecMax = 2; _Input->Scale = 1000.f; } void InitLibSvcParams(LibSvcParams* _Input) { //ͨ _Input->NoiseScale = 0.3f; // 0-10 _Input->Seed = 52468; // _Input->SpeakerId = 0; //ɫID _Input->SrcSamplingRate = 48000; //Դ _Input->SpkCount = 2; //ģͽɫ //SVC _Input->IndexRate = 0.f; // 0-1 _Input->ClusterRate = 0.f; // 0-1 _Input->DDSPNoiseScale = 0.8f; //DDSP 0-10 _Input->Keys = 0.f; // -64-64 _Input->MeanWindowLength = 2; //ֵ˲ڴС 1-20 _Input->Pndm = 100; //Diffusionٱ 1-200 _Input->Step = 1000; //Diffusionܲ 1-1000 _Input->TBegin = 0.f; _Input->TEnd = 1.f; _Input->Sampler = nullptr; //Diffusion _Input->ReflowSampler = nullptr; //Reflow _Input->F0Method = nullptr; //F0ȡ㷨 _Input->UseShallowDiffusionOrEnhancer = false; //ʹdzɢ _Input->_VocoderModel = nullptr; _Input->_ShallowDiffusionModel = nullptr; _Input->ShallowDiffusionUseSrcAudio = 1; _Input->VocoderHopSize = 512; _Input->VocoderMelBins = 128; _Input->VocoderSamplingRate = 44100; _Input->ShallowDiffuisonSpeaker = 0; } void InitLibSvcSlicerSettings(LibSvcSlicerSettings* _Input) { _Input->SamplingRate = 48000; _Input->Threshold = 30.; _Input->MinLength = 3.; _Input->WindowLength = 2048; _Input->HopSize = 512; } float* LibSvcGetFloatVectorData(void* _Obj) { auto& Obj = *(std::vector*)_Obj; return Obj.data(); } size_t LibSvcGetFloatVectorSize(void* _Obj) { auto& Obj = *(std::vector*)_Obj; return Obj.size(); } void* LibSvcGetDFloatVectorData(void* _Obj, size_t _Index) { auto& Obj = *(std::vector>*)_Obj; return Obj.data() + _Index; } size_t LibSvcGetDFloatVectorSize(void* _Obj) { auto& Obj = *(std::vector>*)_Obj; return Obj.size(); } void* LibSvcAllocateAudio() { return new AudioContainer; } void* LibSvcAllocateMel() { return new MelContainer; } void* LibSvcAllocateOffset() { return new OffsetContainer; } void* LibSvcAllocateSliceData() { return new DataContainer; } void LibSvcReleaseAudio(void* _Obj) { delete (AudioContainer*)_Obj; } void LibSvcReleaseMel(void* _Obj) { delete (MelContainer*)_Obj; } void LibSvcReleaseOffset(void* _Obj) { delete (OffsetContainer*)_Obj; } void LibSvcSetOffsetLength(void* _Obj, size_t _Size) { auto& Obj = *(OffsetContainer*)_Obj; Obj.resize(_Size); } void LibSvcReleaseSliceData(void* _Obj) { delete (DataContainer*)_Obj; } size_t* LibSvcGetOffsetData(void* _Obj) { auto& Obj = *(OffsetContainer*)_Obj; return Obj.data(); } size_t LibSvcGetOffsetSize(void* _Obj) { auto& Obj = *(OffsetContainer*)_Obj; return Obj.size(); } void LibSvcSetAudioLength(void* _Obj, size_t _Size) { auto& Obj = *(AudioContainer*)_Obj; Obj.resize(_Size); } void LibSvcInsertAudio(void* _ObjA, void* _ObjB) { auto& ObjA = *(AudioContainer*)_ObjA; auto& ObjB = *(AudioContainer*)_ObjB; ObjA.insert(ObjA.end(), ObjB.begin(), ObjB.end()); } int16_t* LibSvcGetAudioData(void* _Obj) { auto& Obj = *(AudioContainer*)_Obj; return Obj.data(); } size_t LibSvcGetAudioSize(void* _Obj) { auto& Obj = *(AudioContainer*)_Obj; return Obj.size(); } void* LibSvcGetMelData(void* _Obj) { auto& Obj = *(MelContainer*)_Obj; return &Obj.first; } int64_t LibSvcGetMelSize(void* _Obj) { auto& Obj = *(MelContainer*)_Obj; return Obj.second; } void LibSvcSetMaxErrorCount(size_t Count) { MaxErrorCount = Count; } BSTR LibSvcGetAudioPath(void* _Obj) { auto& Obj = *(DataContainer*)_Obj; return SysAllocString(Obj.Path.c_str()); } void* LibSvcGetSlice(void* _Obj, size_t _Index) { auto& Obj = *(DataContainer*)_Obj; return Obj.Slices.data() + _Index; } size_t LibSvcGetSliceCount(void* _Obj) { auto& Obj = *(DataContainer*)_Obj; return Obj.Slices.size(); } void* LibSvcGetAudio(void* _Obj) { auto& Obj = *(SingleSlice*)_Obj; return &Obj.Audio; } void* LibSvcGetF0(void* _Obj) { auto& Obj = *(SingleSlice*)_Obj; return &Obj.F0; } void* LibSvcGetVolume(void* _Obj) { auto& Obj = *(SingleSlice*)_Obj; return &Obj.Volume; } void* LibSvcGetSpeaker(void* _Obj) { auto& Obj = *(SingleSlice*)_Obj; return &Obj.Speaker; } INT32 LibSvcGetSrcLength(void* _Obj) { auto& Obj = *(SingleSlice*)_Obj; return Obj.OrgLen; } INT32 LibSvcGetIsNotMute(void* _Obj) { auto& Obj = *(SingleSlice*)_Obj; return Obj.IsNotMute; } void LibSvcSetSpeakerMixDataSize(void* _Obj, size_t _NSpeaker) { auto& Obj = *(SingleSlice*)_Obj; Obj.Speaker.resize(_NSpeaker, std::vector(Obj.F0.size(), 0.f)); } void LibSvcInit() { MoeVSModuleManager::MoeVoiceStudioCoreInitSetup(); moevsenv::UseSingleOrtApiEnv(true); } std::mutex ErrorMx; void LibSvcFreeString(BSTR _String) { SysFreeString(_String); } BSTR LibSvcGetError(size_t Index) { const auto& Ref = ErrorQueue.at(Index); auto Ret = SysAllocString(Ref.c_str()); ErrorQueue.erase(ErrorQueue.begin() + ptrdiff_t(Index)); ErrorMx.unlock(); return Ret; } void RaiseError(const std::wstring& _Msg) { logger.log(_Msg); ErrorMx.lock(); ErrorQueue.emplace_front(_Msg); if (ErrorQueue.size() > MaxErrorCount) ErrorQueue.pop_back(); } INT32 LibSvcSetGlobalEnv(UINT32 ThreadCount, UINT32 DeviceID, UINT32 Provider) { try { moevsenv::GetGlobalMoeVSEnv().Load(ThreadCount, DeviceID, Provider); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } int32_t LibSvcSliceAudio( const void* _Audio, //std::vector By "LibSvcAllocateAudio()" const void* _Setting, //LibSvcSlicerSettings void* _Output //std::vector By "LibSvcAllocateOffset()" ) { if (!_Audio) { RaiseError(L"Audio Could Not Be Null!"); return 1; } if (!_Output) { RaiseError(L"_Output Could Not Be Null!"); return 1; } const LibSvcSlicerSettings* _SettingInp = (const LibSvcSlicerSettings*)_Setting; auto& Ret = *(std::vector*)(_Output); InferTools::SlicerSettings SliSetting{ _SettingInp->SamplingRate, _SettingInp->Threshold, _SettingInp->MinLength, _SettingInp->WindowLength, _SettingInp->HopSize }; try { Ret = InferTools::SliceAudio(*(const AudioContainer*)(_Audio), SliSetting); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } int32_t LibSvcPreprocess( const void* _Audio, //std::vector By "LibSvcAllocateAudio()" const void* _SlicePos, //std::vector By "LibSvcAllocateOffset()" int32_t _SamplingRate, int32_t _HopSize, double _Threshold, const wchar_t* _F0Method, void* _Output // Slices By "LibSvcAllocateSliceData()" ) { InferTools::SlicerSettings _Setting{ .Threshold = _Threshold }; if (!_Audio) { RaiseError(L"Audio Could Not Be Null!"); return 1; } if (!_SlicePos) { RaiseError(L"Slice Pos Could Not Be Null!"); return 1; } if(!_Output) { RaiseError(L"_Output Could Not Be Null!"); return 1; } Slices& Ret = *static_cast(_Output); try { Ret = MoeVoiceStudioCore::SingingVoiceConversion::GetAudioSlice( *(const AudioContainer*)(_Audio), *(const OffsetContainer*)(_SlicePos), _Setting ); MoeVoiceStudioCore::SingingVoiceConversion::PreProcessAudio(Ret, _SamplingRate, _HopSize, _F0Method); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } INT32 LibSvcStft( const void* _Audio, INT32 _SamplingRate, INT32 _Hopsize, INT32 _MelBins, void* _Output ) { if (!_Audio) { RaiseError(L"Audio Could Not Be Null!"); return 1; } if (!_Output) { RaiseError(L"_Output Could Not Be Null!"); return 1; } if (MelOperators.size() > 5) { delete MelOperators.begin()->second; MelOperators.erase(MelOperators.begin()); } try { const std::wstring _Name = L"S" + std::to_wstring(_SamplingRate) + L"H" + std::to_wstring(_Hopsize) + L"M" + std::to_wstring(_MelBins); if (!MelOperators.contains(_Name)) MelOperators[_Name] = new DlCodecStft::Mel(_Hopsize * 4, _Hopsize, _SamplingRate, _MelBins); auto _NormalizedAudio = InferTools::InterpResample( *(const AudioContainer*)_Audio, _SamplingRate, _SamplingRate, 32768. ); *(MelContainer*)(_Output) = MelOperators.at(_Name)->operator()(_NormalizedAudio); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } INT32 LibSvcInferSlice( void* _Model, UINT32 _T, const void* _Slice, const void* _InferParams, size_t* _Process, void* _Output ) { if (!_Model) { RaiseError(L"_Model Could Not Be Null!"); return 1; } if (!_Slice) { RaiseError(L"_Slice Could Not Be Null!"); return 1; } if (!_InferParams) { RaiseError(L"_InferParams Could Not Be Null!"); return 1; } if (!_Process) { RaiseError(L"_Process Could Not Be Null!"); return 1; } if (!_Output) { RaiseError(L"_Output Could Not Be Null!"); return 1; } const auto& InpParam = *(const LibSvcParams*)(_InferParams); if (!InpParam._VocoderModel && _T == 1) { RaiseError(L"_VocoderModel Could Not Be Null!"); return 1; } const Params Param { InpParam.NoiseScale, InpParam.Seed, InpParam.SpeakerId, InpParam.SrcSamplingRate, InpParam.SpkCount, InpParam.IndexRate, InpParam.ClusterRate, InpParam.DDSPNoiseScale, InpParam.Keys, InpParam.MeanWindowLength, InpParam.Pndm, InpParam.Step, InpParam.TBegin, InpParam.TEnd, LibSvcNullStrCheck(InpParam.Sampler), LibSvcNullStrCheck(InpParam.ReflowSampler), LibSvcNullStrCheck(InpParam.F0Method), (bool)InpParam.UseShallowDiffusionOrEnhancer, InpParam._VocoderModel, InpParam._ShallowDiffusionModel, (bool)InpParam.ShallowDiffusionUseSrcAudio, InpParam.VocoderHopSize, InpParam.VocoderMelBins, InpParam.VocoderSamplingRate, InpParam.ShallowDiffuisonSpeaker }; try { if (_T == 0) *(AudioContainer*)(_Output) = ((VitsSvc*)(_Model))->SliceInference(*(const SingleSlice*)(_Slice), Param, *_Process); else if (_T == 1) *(AudioContainer*)(_Output) = ((UnionSvc*)(_Model))->SliceInference(*(const SingleSlice*)(_Slice), Param, *_Process); else { RaiseError(L"UnSupported Model Type!"); return 1; } } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } INT32 LibSvcInferPCMData( SvcModel _Model, //SingingVoiceConversion Model UINT32 _T, CInt16Vector _PCMData, const void* _InferParams, //Ptr Of LibSvcParams Int16Vector _Output //std::vector By "LibSvcAllocateAudio()" ) { if (!_Model) { RaiseError(L"_Model Could Not Be Null!"); return 1; } if (!_PCMData) { RaiseError(L"_PCMData Could Not Be Null!"); return 1; } if (!_InferParams) { RaiseError(L"_InferParams Could Not Be Null!"); return 1; } if (!_Output) { RaiseError(L"_Output Could Not Be Null!"); return 1; } const auto& InpParam = *(const LibSvcParams*)(_InferParams); if (!InpParam._VocoderModel && _T == 1) { RaiseError(L"_VocoderModel Could Not Be Null!"); return 1; } const Params Param { InpParam.NoiseScale, InpParam.Seed, InpParam.SpeakerId, InpParam.SrcSamplingRate, InpParam.SpkCount, InpParam.IndexRate, InpParam.ClusterRate, InpParam.DDSPNoiseScale, InpParam.Keys, InpParam.MeanWindowLength, InpParam.Pndm, InpParam.Step, InpParam.TBegin, InpParam.TEnd, LibSvcNullStrCheck(InpParam.Sampler), LibSvcNullStrCheck(InpParam.ReflowSampler), LibSvcNullStrCheck(InpParam.F0Method), (bool)InpParam.UseShallowDiffusionOrEnhancer, InpParam._VocoderModel, InpParam._ShallowDiffusionModel, (bool)InpParam.ShallowDiffusionUseSrcAudio, InpParam.VocoderHopSize, InpParam.VocoderMelBins, InpParam.VocoderSamplingRate, InpParam.ShallowDiffuisonSpeaker }; auto& InputData = *(const AudioContainer*)(_PCMData); try { if (_T == 0) *(AudioContainer*)(_Output) = ((VitsSvc*)(_Model))->InferPCMData(InputData, (long)InputData.size(), Param); else if (_T == 1) *(AudioContainer*)(_Output) = ((UnionSvc*)(_Model))->InferPCMData(InputData, (long)InputData.size(), Param); else { RaiseError(L"UnSupported Model Type!"); return 1; } } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } INT32 LibSvcShallowDiffusionInference( void* _Model, const void* _16KAudioHubert, void* _Mel, const void* _SrcF0, const void* _SrcVolume, const void* _SrcSpeakerMap, INT64 _SrcSize, const void* _InferParams, size_t* _Process, void* _Output ) { if (!_Model) { RaiseError(L"_Model Could Not Be Null!"); return 1; } if (!_16KAudioHubert) { RaiseError(L"_16KAudioHubert Could Not Be Null!"); return 1; } if (!_Mel) { RaiseError(L"_Mel Could Not Be Null!"); return 1; } if (!_SrcF0) { RaiseError(L"_SrcF0 Could Not Be Null!"); return 1; } if (!_SrcVolume) { RaiseError(L"_SrcVolume Could Not Be Null!"); return 1; } if (!_SrcSpeakerMap) { RaiseError(L"_SrcSpeakerMap Could Not Be Null!"); return 1; } if (!_InferParams) { RaiseError(L"_InferParams Could Not Be Null!"); return 1; } if (!_Process) { RaiseError(L"_Process Could Not Be Null!"); return 1; } if (!_Output) { RaiseError(L"_Output Could Not Be Null!"); return 1; } const auto& InpParam = *(const LibSvcParams*)(_InferParams); if(!InpParam._VocoderModel) { RaiseError(L"_VocoderModel Could Not Be Null!"); return 1; } const Params Param { InpParam.NoiseScale, InpParam.Seed, InpParam.SpeakerId, InpParam.SrcSamplingRate, InpParam.SpkCount, InpParam.IndexRate, InpParam.ClusterRate, InpParam.DDSPNoiseScale, InpParam.Keys, InpParam.MeanWindowLength, InpParam.Pndm, InpParam.Step, InpParam.TBegin, InpParam.TEnd, LibSvcNullStrCheck(InpParam.Sampler), LibSvcNullStrCheck(InpParam.ReflowSampler), LibSvcNullStrCheck(InpParam.F0Method), (bool)InpParam.UseShallowDiffusionOrEnhancer, InpParam._VocoderModel, InpParam._ShallowDiffusionModel, (bool)InpParam.ShallowDiffusionUseSrcAudio, InpParam.VocoderHopSize, InpParam.VocoderMelBins, InpParam.VocoderSamplingRate, InpParam.ShallowDiffuisonSpeaker }; auto _NormalizedAudio = InferTools::InterpResample( *(const AudioContainer*)_16KAudioHubert, 16000, 16000, 32768.f ); try { *(AudioContainer*)(_Output) = ((UnionSvc*)(_Model))->ShallowDiffusionInference( _NormalizedAudio, Param, *(MelContainer*)(_Mel), *(const std::vector*)(_SrcF0), *(const std::vector*)(_SrcVolume), *(const std::vector>*)(_SrcSpeakerMap), *_Process, _SrcSize ); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } INT32 LibSvcVocoderEnhance( void* _Model, void* _Mel, const void* _F0, INT32 _VocoderMelBins, void* _Output ) { if (!_Model) { RaiseError(L"_Model Could Not Be Null!"); return 1; } if (!_F0) { RaiseError(L"_16KAudioHubert Could Not Be Null!"); return 1; } if (!_Mel) { RaiseError(L"_Mel Could Not Be Null!"); return 1; } if (!_Output) { RaiseError(L"_Output Could Not Be Null!"); return 1; } auto Rf0 = *(const std::vector*)(_F0); auto& MelTemp = *(MelContainer*)(_Mel); if (Rf0.size() != (size_t)MelTemp.second) Rf0 = InferTools::InterpFunc(Rf0, (long)Rf0.size(), (long)MelTemp.second); try { *(AudioContainer*)(_Output) = MoeVoiceStudioCore::VocoderInfer( MelTemp.first, Rf0, _VocoderMelBins, MelTemp.second, moevsenv::GetGlobalMoeVSEnv().GetMemoryInfo(), _Model ); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } void* LibSvcLoadModel( UINT32 _T, const void* _Config, ProgCallback _ProgressCallback, UINT32 _ExecutionProvider, UINT32 _DeviceID, UINT32 _ThreadCount ) { if (!_Config) { RaiseError(L"_Model Could Not Be Null!"); return nullptr; } auto& Config = *(const LibSvcHparams*)(_Config); //printf("%lld", (long long)(Config.DiffusionSvc.Encoder)); MoeVoiceStudioCore::Hparams ModelConfig{ LibSvcNullStrCheck(Config.TensorExtractor), LibSvcNullStrCheck(Config.HubertPath), { LibSvcNullStrCheck(Config.DiffusionSvc.Encoder), LibSvcNullStrCheck(Config.DiffusionSvc.Denoise), LibSvcNullStrCheck(Config.DiffusionSvc.Pred), LibSvcNullStrCheck(Config.DiffusionSvc.After), LibSvcNullStrCheck(Config.DiffusionSvc.Alpha), LibSvcNullStrCheck(Config.DiffusionSvc.Naive), LibSvcNullStrCheck(Config.DiffusionSvc.DiffSvc) }, { LibSvcNullStrCheck(Config.VitsSvc.VitsSvc) }, { LibSvcNullStrCheck(Config.ReflowSvc.Encoder), LibSvcNullStrCheck(Config.ReflowSvc.VelocityFn), LibSvcNullStrCheck(Config.ReflowSvc.After) }, { Config.Cluster.ClusterCenterSize, LibSvcNullStrCheck(Config.Cluster.Path), LibSvcNullStrCheck(Config.Cluster.Type) }, Config.SamplingRate, Config.HopSize, Config.HiddenUnitKDims, Config.SpeakerCount, (bool)Config.EnableCharaMix, (bool)Config.EnableVolume, (bool)Config.VaeMode, Config.MelBins, Config.Pndms, Config.MaxStep, Config.SpecMin, Config.SpecMax, Config.Scale }; try { if(_T == 0) { return new VitsSvc(ModelConfig, _ProgressCallback, static_cast(_ExecutionProvider), _DeviceID, _ThreadCount); } return new UnionSvc(ModelConfig, _ProgressCallback, int(_ExecutionProvider), int(_DeviceID), int(_ThreadCount)); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return nullptr; } } INT32 LibSvcUnloadModel( UINT32 _T, void* _Model ) { try { if (_T == 0) delete (VitsSvc*)_Model; else delete (UnionSvc*)_Model; } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } void* LibSvcLoadVocoder(LPWSTR VocoderPath) { if (!VocoderPath) { RaiseError(L"VocoderPath Could Not Be Null"); return nullptr; } const auto& Env = moevsenv::GetGlobalMoeVSEnv(); try { return new Ort::Session(*Env.GetEnv(), VocoderPath, *Env.GetSessionOptions()); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return nullptr; } } INT32 LibSvcUnloadVocoder(void* _Model) { try { delete (Ort::Session*)_Model; } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } INT32 LibSvcReadAudio(LPWSTR _AudioPath, INT32 _SamplingRate, void* _Output) { try { *(std::vector*)(_Output) = AudioPreprocess().codec(_AudioPath, _SamplingRate); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } void LibSvcEnableFileLogger(bool _Cond) { MoeSSLogger::GetLogger().enable(_Cond); } void LibSvcWriteAudioFile(void* _PCMData, LPWSTR _OutputPath, INT32 _SamplingRate) { InferTools::Wav::WritePCMData(_SamplingRate, 1, *(std::vector*)(_PCMData), _OutputPath); } ================================================ FILE: libsvc/Api/src/libsvc.cpp ================================================ #include "../header/libsvc.h" #include #include "../../header/InferTools/Stft/stft.hpp" #include namespace libsvccore { std::unordered_map DiffusionSvcSessions; std::unordered_map VitsSvcSessions; std::unordered_map ReflowSvcSessions; std::deque ErrorMessage; std::wstring NoneError; size_t MaxErrorCount = 10; std::unordered_map MelOperators; Ort::MemoryInfo* vocoder_memory_info = nullptr; std::any NoneType(false); void RaiseError(const std::wstring& _Msg) { ErrorMessage.emplace_back(_Msg); logger.log(_Msg); if (ErrorMessage.size() > MaxErrorCount) ErrorMessage.pop_front(); } void UnloadVitsSvcSession(const std::wstring& _Name) { const auto ModelPair = VitsSvcSessions.find(_Name); if (ModelPair != VitsSvcSessions.end()) { delete ModelPair->second; VitsSvcSessions.erase(ModelPair); } } void UnloadDiffusionSvcSession(const std::wstring& _Name) { const auto ModelPair = DiffusionSvcSessions.find(_Name); if (ModelPair != DiffusionSvcSessions.end()) { delete ModelPair->second; DiffusionSvcSessions.erase(ModelPair); } } void UnloadReflowSvcSession(const std::wstring& _Name) { const auto ModelPair = ReflowSvcSessions.find(_Name); if (ModelPair != ReflowSvcSessions.end()) { delete ModelPair->second; ReflowSvcSessions.erase(ModelPair); } } int LoadDiffusionSvcSession(const Config& _Config, const std::wstring& _Name, const ProgressCallback& _ProgressCallback, ExecutionProvider ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) { const auto ModelPair = DiffusionSvcSessions.find(_Name); if(ModelPair != DiffusionSvcSessions.end()) delete ModelPair->second; try { DiffusionSvcSessions[_Name] = new MoeVoiceStudioCore::DiffusionSvc( _Config, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_ ); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); UnloadDiffusionSvcSession(_Name); return 1; } return 0; } int LoadReflowSvcSession(const Config& _Config, const std::wstring& _Name, const ProgressCallback& _ProgressCallback, ExecutionProvider ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) { const auto ModelPair = ReflowSvcSessions.find(_Name); if (ModelPair != ReflowSvcSessions.end()) delete ModelPair->second; try { ReflowSvcSessions[_Name] = new MoeVoiceStudioCore::ReflowSvc( _Config, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_ ); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); UnloadDiffusionSvcSession(_Name); return 1; } return 0; } int LoadVitsSvcSession(const Config& _Config, const std::wstring& _Name, const ProgressCallback& _ProgressCallback, ExecutionProvider ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) { const auto ModelPair = VitsSvcSessions.find(_Name); if (ModelPair != VitsSvcSessions.end()) delete ModelPair->second; try { VitsSvcSessions[_Name] = new MoeVoiceStudioCore::VitsSvc( _Config, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_ ); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); UnloadVitsSvcSession(_Name); return 1; } return 0; } void SetMaxErrorCount(size_t Count) { MaxErrorCount = Count; } std::wstring& GetLastError(size_t Index) { if (Index < MaxErrorCount) return ErrorMessage.at(MaxErrorCount - Index - 1); return NoneError; } int LoadModel(ModelType _T, const Config& _Config, const std::wstring& _Name, const ProgressCallback& _ProgressCallback, ExecutionProvider ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) { if (_T == ModelType::Vits) return LoadVitsSvcSession(_Config, _Name, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_); if (_T == ModelType::Diffusion) return LoadDiffusionSvcSession(_Config, _Name, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_); return LoadReflowSvcSession(_Config, _Name, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_); } void UnloadModel(ModelType _T, const std::wstring& _Name) { if (_T == ModelType::Diffusion) UnloadDiffusionSvcSession(_Name); else if (_T == ModelType::Vits) UnloadVitsSvcSession(_Name); else UnloadReflowSvcSession(_Name); } std::mt19937 gen(114514); std::uniform_int_distribution normal; std::unordered_map LibSvcRtnData; std::mutex RtnDataMx; void EmplaceRtnData(size_t& _Id, std::any&& _Val) { std::lock_guard lg(RtnDataMx); for (_Id = normal(gen); LibSvcRtnData.find(_Id) != LibSvcRtnData.end(); ) _Id = normal(gen); LibSvcRtnData[_Id] = std::move(_Val); } void SliceAudio(size_t& _Id, const std::vector& _Audio, const InferTools::SlicerSettings& _Setting) { EmplaceRtnData(_Id, InferTools::SliceAudio(_Audio, _Setting)); } void Preprocess(size_t& _Id, const std::vector& _Audio, const std::vector& _SlicePos, const InferTools::SlicerSettings& _Setting, int _SamplingRate, int _HopSize, const std::wstring& _F0Method) { auto Rtn = MoeVoiceStudioCore::SingingVoiceConversion::GetAudioSlice(_Audio, _SlicePos, _Setting); MoeVoiceStudioCore::SingingVoiceConversion::PreProcessAudio(Rtn, _SamplingRate, _HopSize, _F0Method); EmplaceRtnData(_Id, std::move(Rtn)); } int InferSlice(size_t& _Id, ModelType _T, const std::wstring& _Name, const SingleSlice& _Slice, const Params& _InferParams, size_t& _Process) { const MoeVoiceStudioCore::SingingVoiceConversion* _Model = nullptr; if (_T == ModelType::Vits && VitsSvcSessions.find(_Name) != VitsSvcSessions.end()) _Model = dynamic_cast(VitsSvcSessions.at(_Name)); else if (_T == ModelType::Diffusion && DiffusionSvcSessions.find(_Name) != DiffusionSvcSessions.end()) { _Model = dynamic_cast(DiffusionSvcSessions.at(_Name)); if(!MoeVSModuleManager::VocoderEnabled()) { RaiseError(L"Vocoder Not Exists"); return 1; } } else if(_T == ModelType::Reflow && ReflowSvcSessions.find(_Name) != ReflowSvcSessions.end()) { _Model = dynamic_cast(ReflowSvcSessions.at(_Name)); if (!MoeVSModuleManager::VocoderEnabled()) { RaiseError(L"Vocoder Not Exists"); return 1; } } if(!_Model) { RaiseError(L"Model Not Exists"); return 1; } std::vector Rtn; try { Rtn = _Model->SliceInference(_Slice, _InferParams, _Process); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } EmplaceRtnData(_Id, std::move(Rtn)); return 0; } int ShallowDiffusionInference(size_t& _Id, const std::wstring& _Name, const std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize) { if (!MoeVSModuleManager::VocoderEnabled()) { RaiseError(L"Vocoder Not Exists"); return 1; } if(DiffusionSvcSessions.find(_Name) != DiffusionSvcSessions.end()) { std::vector Rtn; try { auto _Hubert = _16KAudioHubert; auto _MelCopy = _Mel; Rtn = DiffusionSvcSessions.at(_Name)->ShallowDiffusionInference(_Hubert, _InferParams, _MelCopy, _SrcF0, _SrcVolume, _SrcSpeakerMap, Process, SrcSize); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } EmplaceRtnData(_Id, std::move(Rtn)); return 0; } RaiseError(L"Model Not Exists"); return 1; } int Stft(size_t& _Id, const std::vector& _NormalizedAudio, int _SamplingRate, int _Hopsize, int _MelBins) { const std::wstring _Name = L"S" + std::to_wstring(_SamplingRate) + L"H" + std::to_wstring(_Hopsize) + L"M" + std::to_wstring(_MelBins); if (MelOperators.find(_Name) == MelOperators.end()) MelOperators[_Name] = new DlCodecStft::Mel(_Hopsize * 4, _Hopsize, _SamplingRate, _MelBins); EmplaceRtnData(_Id, MelOperators.at(_Name)->operator()(_NormalizedAudio)); return 0; } int VocoderEnhance(size_t& _Id, const std::vector& Mel, const std::vector& F0, size_t MelSize, long VocoderMelBins) { if(!MoeVoiceStudioCore::VocoderEnabled()) { RaiseError(L"Vocoder Not Exists"); return 1; } auto Rf0 = F0; auto MelTemp = Mel; if (Rf0.size() != MelSize) Rf0 = InferTools::InterpFunc(Rf0, (long)Rf0.size(), (long)MelSize); EmplaceRtnData(_Id, MoeVoiceStudioCore::VocoderInfer( MelTemp, Rf0, VocoderMelBins, (int64_t)MelSize, vocoder_memory_info )); return 0; } void EmptyStftCache() { for (const auto& i : MelOperators) delete i.second; MelOperators.clear(); } void LoadVocoder(const std::wstring& VocoderPath) { MoeVoiceStudioCore::LoadVocoderModel(VocoderPath); } void Init() { MoeVSModuleManager::MoeVoiceStudioCoreInitSetup(); vocoder_memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); moevsenv::UseSingleOrtApiEnv(true); } void SetGlobalEnv(unsigned ThreadCount, unsigned DeviceID, unsigned Provider) { moevsenv::GetGlobalMoeVSEnv().Load(ThreadCount, DeviceID, Provider); } std::any& GetData(size_t _Id) { if (LibSvcRtnData.find(_Id) != LibSvcRtnData.end()) return LibSvcRtnData.at(_Id); return NoneType; } void PopData(size_t _Id) { std::lock_guard lg(RtnDataMx); LibSvcRtnData.erase(_Id); } } ================================================ FILE: libsvc/Modules/Lib/MJson/MJson.cpp ================================================ #include "MJson.h" class FileGuard { public: FileGuard() = delete; ~FileGuard() { if (_fp) fclose(_fp); _fp = nullptr; } FileGuard(const char* _path) { if (_fp) fclose(_fp); _wfopen_s(&_fp, to_wide_string(_path).c_str(), L"rb"); } operator FILE* () const { return _fp; } private: FILE* _fp = nullptr; static std::wstring to_wide_string(const std::string& input) { std::vector WideString(input.length() * 2); MultiByteToWideChar( CP_UTF8, 0, input.c_str(), int(input.length()), WideString.data(), int(WideString.size()) ); return WideString.data(); } }; MJson::MJson(const char* _path) { const auto file = FileGuard(_path); _document = yyjson_read_file(_path, YYJSON_READ_NOFLAG, nullptr, nullptr); if (!_document) throw std::exception("Json Parse Error !"); root = yyjson_doc_get_root(_document); } MJson::MJson(const std::string& _data, bool _read_from_string) { if (_read_from_string) _document = yyjson_read(_data.c_str(), _data.length(), YYJSON_READ_NOFLAG); else { const auto file = FileGuard(_data.c_str()); _document = yyjson_read_fp(file, YYJSON_READ_NOFLAG, nullptr, nullptr); } if (!_document) throw std::exception("Json Parse Error !"); root = yyjson_doc_get_root(_document); } ================================================ FILE: libsvc/Modules/Lib/MJson/MJson.h ================================================ #pragma once #include "../../framework.h" #include #include "yyjson.h" #include #ifdef _WIN32 #include #else #error #endif class MJsonValue { public: MJsonValue() = default; MJsonValue(yyjson_val* _val) : _Ptr(_val) {} ~MJsonValue() = default; MJsonValue(MJsonValue&& _val) noexcept { _Ptr = _val._Ptr; _val._Ptr = nullptr; } MJsonValue(const MJsonValue& _val) = delete; MJsonValue& operator=(MJsonValue&& _val) noexcept { _Ptr = _val._Ptr; _val._Ptr = nullptr; return *this; } MJsonValue& operator=(const MJsonValue& _val) = delete; [[nodiscard]] bool IsNull() const { return yyjson_is_null(_Ptr); } [[nodiscard]] bool IsBoolean() const { return yyjson_is_bool(_Ptr); } [[nodiscard]] bool IsBool() const { return yyjson_is_bool(_Ptr); } [[nodiscard]] bool IsInt() const { return yyjson_is_num(_Ptr); } [[nodiscard]] bool IsFloat() const { return yyjson_is_num(_Ptr); } [[nodiscard]] bool IsInt64() const { return yyjson_is_num(_Ptr); } [[nodiscard]] bool IsDouble() const { return yyjson_is_num(_Ptr); } [[nodiscard]] bool IsString() const { return yyjson_is_str(_Ptr); } [[nodiscard]] bool IsArray() const { return yyjson_is_arr(_Ptr); } [[nodiscard]] bool GetBool() const { return yyjson_get_bool(_Ptr); } [[nodiscard]] bool GetBoolean() const { return yyjson_get_bool(_Ptr); } [[nodiscard]] int GetInt() const { return int(yyjson_get_num(_Ptr)); } [[nodiscard]] int64_t GetInt64() const { return int64_t(yyjson_get_num(_Ptr)); } [[nodiscard]] float GetFloat() const { return float(yyjson_get_num(_Ptr)); } [[nodiscard]] double GetDouble() const { return yyjson_get_num(_Ptr); } [[nodiscard]] std::string GetString() const { if (const auto _str = yyjson_get_str(_Ptr)) return _str; return ""; } [[nodiscard]] std::vector GetArray() const { std::vector _ret; if (!IsArray()) return {}; const auto _PArray = _Ptr; size_t idx, max; yyjson_val* _Object; yyjson_arr_foreach(_PArray, idx, max, _Object) _ret.emplace_back(_Object); return _ret; } [[nodiscard]] size_t GetSize() const { return yyjson_get_len(_Ptr); } [[nodiscard]] size_t Size() const { return yyjson_get_len(_Ptr); } [[nodiscard]] size_t GetStringLength() const { return yyjson_get_len(_Ptr); } [[nodiscard]] MJsonValue Get(const std::string& _key) const { return yyjson_obj_get(_Ptr, _key.c_str()); } [[nodiscard]] MJsonValue operator[](const std::string& _key) const { return yyjson_obj_get(_Ptr, _key.c_str()); } [[nodiscard]] MJsonValue operator[](size_t _idx) const { if (!IsArray()) return _Ptr; const auto _max = yyjson_arr_size(_Ptr); const auto _val = yyjson_arr_get_first(_Ptr); return _idx < _max ? _val + _idx : _val + _max - 1; } [[nodiscard]] bool Empty() const { if (!IsArray() && !IsString()) return true; auto _max = yyjson_arr_size(_Ptr); if (IsString()) _max = yyjson_get_len(_Ptr); return !_max; } [[nodiscard]] size_t GetMemberCount() const { return yyjson_obj_size(_Ptr); } [[nodiscard]] std::vector> GetMemberArray() const { std::vector> ret; yyjson_val* key; yyjson_obj_iter iter = yyjson_obj_iter_with(_Ptr); while ((key = yyjson_obj_iter_next(&iter))) { const auto val = yyjson_obj_iter_get_val(key); ret.emplace_back(MJsonValue(key).GetString(), val); } return ret; } [[nodiscard]] bool HasMember(const std::string& _key) const { return yyjson_obj_get(_Ptr, _key.c_str()); } private: yyjson_val* _Ptr = nullptr; }; class MJson { public: MJson() = default; LibSvcApi MJson(const char* _path); LibSvcApi MJson(const std::string& _data, bool _read_from_string); ~MJson() { if(_document) { yyjson_doc_free(_document); _document = nullptr; root = nullptr; } } MJson(MJson&& _Right) noexcept { _document = _Right._document; _Right._document = nullptr; root = yyjson_doc_get_root(_document); } MJson(const MJson& _Right) = delete; MJson& operator=(MJson&& _Right) noexcept { if (_document) yyjson_doc_free(_document); _document = _Right._document; _Right._document = nullptr; root = yyjson_doc_get_root(_document); return *this; } MJson& operator=(const MJson& _Right) = delete; void Parse(const std::string& _str) { _document = yyjson_read(_str.c_str(), _str.length(), YYJSON_READ_NOFLAG); if (!_document) throw std::exception("Json Parse Error !"); root = yyjson_doc_get_root(_document); } [[nodiscard]] bool HasMember(const std::string& _key) const { return yyjson_obj_get(root, _key.c_str()); } [[nodiscard]] MJsonValue Get(const std::string& _key) const { return yyjson_obj_get(root, _key.c_str()); } [[nodiscard]] MJsonValue operator[](const std::string& _key) const { return yyjson_obj_get(root, _key.c_str()); } [[nodiscard]] MJsonValue operator[](size_t _idx) const { if (MJsonValue(root).IsArray()) return root; const auto _max = yyjson_arr_size(root); const auto _val = yyjson_arr_get_first(root); return _idx < _max ? _val + _idx : _val + _max - 1; } [[nodiscard]] bool HasParseError() const { return _document == nullptr; } [[nodiscard]] bool IsNull() const { return yyjson_is_null(root); } [[nodiscard]] bool IsBoolean() const { return yyjson_is_bool(root); } [[nodiscard]] bool IsBool() const { return yyjson_is_bool(root); } [[nodiscard]] bool IsInt() const { return yyjson_is_num(root); } [[nodiscard]] bool IsFloat() const { return yyjson_is_num(root); } [[nodiscard]] bool IsInt64() const { return yyjson_is_num(root); } [[nodiscard]] bool IsDouble() const { return yyjson_is_num(root); } [[nodiscard]] bool IsString() const { return yyjson_is_str(root); } [[nodiscard]] bool IsArray() const { return yyjson_is_arr(root); } [[nodiscard]] bool GetBool() const { return yyjson_get_bool(root); } [[nodiscard]] bool GetBoolean() const { return yyjson_get_bool(root); } [[nodiscard]] int GetInt() const { return int(yyjson_get_num(root)); } [[nodiscard]] int64_t GetInt64() const { return int64_t(yyjson_get_num(root)); } [[nodiscard]] float GetFloat() const { return float(yyjson_get_num(root)); } [[nodiscard]] double GetDouble() const { return yyjson_get_num(root); } [[nodiscard]] std::string GetString() const { if (const auto _str = yyjson_get_str(root)) return _str; return ""; } [[nodiscard]] std::vector GetArray() const { std::vector _ret; if (!IsArray()) return {}; const auto _PArray = root; size_t idx, max; yyjson_val* _Object; yyjson_arr_foreach(_PArray, idx, max, _Object) _ret.emplace_back(_Object); return _ret; } [[nodiscard]] size_t GetSize() const { return yyjson_get_len(root); } [[nodiscard]] size_t Size() const { return yyjson_get_len(root); } [[nodiscard]] size_t GetStringLength() const { return yyjson_get_len(root); } [[nodiscard]] size_t GetMemberCount() const { return yyjson_obj_size(root); } [[nodiscard]] std::vector> GetMemberArray() const { std::vector> ret; yyjson_val* key; yyjson_obj_iter iter = yyjson_obj_iter_with(root); while ((key = yyjson_obj_iter_next(&iter))) { const auto val = yyjson_obj_iter_get_val(key); ret.emplace_back(MJsonValue(key).GetString(), val); } return ret; } private: yyjson_doc* _document = nullptr; yyjson_val* root = nullptr; }; ================================================ FILE: libsvc/Modules/Lib/MJson/yyjson.c ================================================ /*============================================================================== * Created by Yaoyuan on 2019/3/9. * Copyright (C) 2019 Yaoyuan . * * Released under the MIT License: * https://github.com/ibireme/yyjson/blob/master/LICENSE *============================================================================*/ #include "yyjson.h" #include /*============================================================================== * Compile Hint Begin *============================================================================*/ /* warning suppress begin */ #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunused-function" # pragma clang diagnostic ignored "-Wunused-parameter" # pragma clang diagnostic ignored "-Wunused-label" # pragma clang diagnostic ignored "-Wunused-macros" #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-function" # pragma GCC diagnostic ignored "-Wunused-parameter" # pragma GCC diagnostic ignored "-Wunused-label" # pragma GCC diagnostic ignored "-Wunused-macros" #elif defined(_MSC_VER) # pragma warning(push) # pragma warning(disable:4100) /* unreferenced formal parameter */ # pragma warning(disable:4102) /* unreferenced label */ # pragma warning(disable:4127) /* conditional expression is constant */ # pragma warning(disable:4706) /* assignment within conditional expression */ #endif /*============================================================================== * Version *============================================================================*/ uint32_t yyjson_version(void) { return YYJSON_VERSION_HEX; } /*============================================================================== * Flags *============================================================================*/ /* gcc version check */ #if defined(__GNUC__) # if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) # define yyjson_gcc_available(major, minor, patch) \ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \ >= (major * 10000 + minor * 100 + patch)) # elif defined(__GNUC_MINOR__) # define yyjson_gcc_available(major, minor, patch) \ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) \ >= (major * 10000 + minor * 100 + patch)) # else # define yyjson_gcc_available(major, minor, patch) \ ((__GNUC__ * 10000) >= (major * 10000 + minor * 100 + patch)) # endif #else # define yyjson_gcc_available(major, minor, patch) 0 #endif /* real gcc check */ #if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__ICC) && \ defined(__GNUC__) && defined(__GNUC_MINOR__) # define YYJSON_IS_REAL_GCC 1 #else # define YYJSON_IS_REAL_GCC 0 #endif /* msvc intrinsic */ #if YYJSON_MSC_VER >= 1400 # include # if defined(_M_AMD64) || defined(_M_ARM64) # define MSC_HAS_BIT_SCAN_64 1 # pragma intrinsic(_BitScanForward64) # pragma intrinsic(_BitScanReverse64) # else # define MSC_HAS_BIT_SCAN_64 0 # endif # if defined(_M_AMD64) || defined(_M_ARM64) || \ defined(_M_IX86) || defined(_M_ARM) # define MSC_HAS_BIT_SCAN 1 # pragma intrinsic(_BitScanForward) # pragma intrinsic(_BitScanReverse) # else # define MSC_HAS_BIT_SCAN 0 # endif # if defined(_M_AMD64) # define MSC_HAS_UMUL128 1 # pragma intrinsic(_umul128) # else # define MSC_HAS_UMUL128 0 # endif #else # define MSC_HAS_BIT_SCAN_64 0 # define MSC_HAS_BIT_SCAN 0 # define MSC_HAS_UMUL128 0 #endif /* gcc builtin */ #if yyjson_has_builtin(__builtin_clzll) || yyjson_gcc_available(3, 4, 0) # define GCC_HAS_CLZLL 1 #else # define GCC_HAS_CLZLL 0 #endif #if yyjson_has_builtin(__builtin_ctzll) || yyjson_gcc_available(3, 4, 0) # define GCC_HAS_CTZLL 1 #else # define GCC_HAS_CTZLL 0 #endif /* int128 type */ #if defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16) && \ (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)) # define YYJSON_HAS_INT128 1 #else # define YYJSON_HAS_INT128 0 #endif /* IEEE 754 floating-point binary representation */ #if defined(__STDC_IEC_559__) || defined(__STDC_IEC_60559_BFP__) # define YYJSON_HAS_IEEE_754 1 #elif (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_DIG == 15) && \ (DBL_MIN_EXP == -1021) && (DBL_MAX_EXP == 1024) && \ (DBL_MIN_10_EXP == -307) && (DBL_MAX_10_EXP == 308) # define YYJSON_HAS_IEEE_754 1 #else # define YYJSON_HAS_IEEE_754 0 #endif /* Correct rounding in double number computations. On the x86 architecture, some compilers may use x87 FPU instructions for floating-point arithmetic. The x87 FPU loads all floating point number as 80-bit double-extended precision internally, then rounds the result to original precision, which may produce inaccurate results. For a more detailed explanation, see the paper: https://arxiv.org/abs/cs/0701192 Here are some examples of double precision calculation error: 2877.0 / 1e6 == 0.002877, but x87 returns 0.0028770000000000002 43683.0 * 1e21 == 4.3683e25, but x87 returns 4.3683000000000004e25 Here are some examples of compiler flags to generate x87 instructions on x86: clang -m32 -mno-sse gcc/icc -m32 -mfpmath=387 msvc /arch:SSE or /arch:IA32 If we are sure that there's no similar error described above, we can define the YYJSON_DOUBLE_MATH_CORRECT as 1 to enable the fast path calculation. This is not an accurate detection, it's just try to avoid the error at compile-time. An accurate detection can be done at run-time: bool is_double_math_correct(void) { volatile double r = 43683.0; r *= 1e21; return r == 4.3683e25; } See also: utils.h in https://github.com/google/double-conversion/ */ #if !defined(FLT_EVAL_METHOD) && defined(__FLT_EVAL_METHOD__) # define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ #endif #if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1 # define YYJSON_DOUBLE_MATH_CORRECT 0 #elif defined(i386) || defined(__i386) || defined(__i386__) || \ defined(_X86_) || defined(__X86__) || defined(_M_IX86) || \ defined(__I86__) || defined(__IA32__) || defined(__THW_INTEL) # if (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 2) || \ (defined(__SSE2_MATH__) && __SSE2_MATH__) # define YYJSON_DOUBLE_MATH_CORRECT 1 # else # define YYJSON_DOUBLE_MATH_CORRECT 0 # endif #elif defined(__mc68000__) || defined(__pnacl__) || defined(__native_client__) # define YYJSON_DOUBLE_MATH_CORRECT 0 #else # define YYJSON_DOUBLE_MATH_CORRECT 1 #endif /* endian */ #if yyjson_has_include() # include #endif #if yyjson_has_include() # include #elif yyjson_has_include() # include #elif yyjson_has_include() # include #endif #define YYJSON_BIG_ENDIAN 4321 #define YYJSON_LITTLE_ENDIAN 1234 #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN # elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif #elif defined(__BYTE_ORDER) && __BYTE_ORDER # if __BYTE_ORDER == __BIG_ENDIAN # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN # elif __BYTE_ORDER == __LITTLE_ENDIAN # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif #elif defined(BYTE_ORDER) && BYTE_ORDER # if BYTE_ORDER == BIG_ENDIAN # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN # elif BYTE_ORDER == LITTLE_ENDIAN # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif #elif (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \ defined(__i386) || defined(__i386__) || \ defined(_X86_) || defined(__X86__) || \ defined(_M_IX86) || defined(__THW_INTEL__) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(__amd64) || defined(__amd64__) || \ defined(_M_AMD64) || defined(_M_X64) || \ defined(__ia64) || defined(_IA64) || defined(__IA64__) || \ defined(__ia64__) || defined(_M_IA64) || defined(__itanium__) || \ defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ defined(__alpha) || defined(__alpha__) || defined(_M_ALPHA) || \ defined(__riscv) || defined(__riscv__) || \ defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \ defined(__EMSCRIPTEN__) || defined(__wasm__) || \ defined(__loongarch__) # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN #elif (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ defined(__ppc) || defined(__ppc__) || \ defined(__sparc) || defined(__sparc__) || defined(__sparc64__) || \ defined(__or1k__) || defined(__OR1K__) # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN #else # define YYJSON_ENDIAN 0 /* unknown endian, detect at run-time */ #endif /* Unaligned memory access detection. Some architectures cannot perform unaligned memory access, or unaligned memory accesses can have a large performance penalty. Modern compilers can make some optimizations for unaligned access. For example: https://godbolt.org/z/Ejo3Pa typedef struct { char c[2] } vec2; void copy_vec2(vec2 *dst, vec2 *src) { *dst = *src; } Compiler may generate `load/store` or `move` instruction if target architecture supports unaligned access, otherwise it may generate `call memcpy` instruction. We want to avoid `memcpy` calls, so we should disable unaligned access by define `YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS` as 1 on these architectures. */ #ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS # if defined(i386) || defined(__i386) || defined(__i386__) || \ defined(__i486__) || defined(__i586__) || defined(__i686__) || \ defined(_X86_) || defined(__X86__) || defined(_M_IX86) || \ defined(__I86__) || defined(__IA32__) || \ defined(__THW_INTEL) || defined(__THW_INTEL__) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(__amd64) || defined(__amd64__) || \ defined(_M_AMD64) || defined(_M_X64) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* x86 */ # elif defined(__ia64) || defined(_IA64) || defined(__IA64__) || \ defined(__ia64__) || defined(_M_IA64) || defined(__itanium__) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* Itanium */ # elif defined(__arm64) || defined(__arm64__) || \ defined(__AARCH64EL__) || defined(__AARCH64EB__) || \ defined(__aarch64__) || defined(_M_ARM64) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* ARM64 */ # elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || \ defined(__ARM_ARCH_5TEJ__) || defined(__ARM_ARCH_5TE__) || \ defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6KZ__) || \ defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* ARM */ # elif defined(__ppc64__) || defined(__PPC64__) || \ defined(__powerpc64__) || defined(_ARCH_PPC64) || \ defined(__ppc) || defined(__ppc__) || defined(__PPC__) || \ defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || \ defined(_ARCH_PPC) || defined(_M_PPC) || \ defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || defined(_XENON) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* PowerPC */ # elif defined(__loongarch__) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* loongarch */ # else # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* Unknown */ # endif #endif /* Estimated initial ratio of the JSON data (data_size / value_count). For example: data: {"id":12345678,"name":"Harry"} data_size: 30 value_count: 5 ratio: 6 yyjson uses dynamic memory with a growth factor of 1.5 when reading and writing JSON, the ratios below are used to determine the initial memory size. A too large ratio will waste memory, and a too small ratio will cause multiple memory growths and degrade performance. Currently, these ratios are generated with some commonly used JSON datasets. */ #define YYJSON_READER_ESTIMATED_PRETTY_RATIO 16 #define YYJSON_READER_ESTIMATED_MINIFY_RATIO 6 #define YYJSON_WRITER_ESTIMATED_PRETTY_RATIO 32 #define YYJSON_WRITER_ESTIMATED_MINIFY_RATIO 18 /* The initial and maximum size of the memory pool's chunk in yyjson_mut_doc. */ #define YYJSON_MUT_DOC_STR_POOL_INIT_SIZE 0x100 #define YYJSON_MUT_DOC_STR_POOL_MAX_SIZE 0x10000000 #define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val)) #define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val)) /* Default value for compile-time options. */ #ifndef YYJSON_DISABLE_READER #define YYJSON_DISABLE_READER 0 #endif #ifndef YYJSON_DISABLE_WRITER #define YYJSON_DISABLE_WRITER 0 #endif #ifndef YYJSON_DISABLE_UTILS #define YYJSON_DISABLE_UTILS 0 #endif #ifndef YYJSON_DISABLE_FAST_FP_CONV #define YYJSON_DISABLE_FAST_FP_CONV 0 #endif #ifndef YYJSON_DISABLE_NON_STANDARD #define YYJSON_DISABLE_NON_STANDARD 0 #endif /*============================================================================== * Macros *============================================================================*/ /* Macros used for loop unrolling and other purpose. */ #define repeat2(x) { x x } #define repeat3(x) { x x x } #define repeat4(x) { x x x x } #define repeat8(x) { x x x x x x x x } #define repeat16(x) { x x x x x x x x x x x x x x x x } #define repeat2_incr(x) { x(0) x(1) } #define repeat4_incr(x) { x(0) x(1) x(2) x(3) } #define repeat8_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) } #define repeat16_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) } #define repeat_in_1_18(x) { x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) \ x(16) x(17) x(18) } /* Macros used to provide branch prediction information for compiler. */ #undef likely #define likely(x) yyjson_likely(x) #undef unlikely #define unlikely(x) yyjson_unlikely(x) /* Macros used to provide inline information for compiler. */ #undef static_inline #define static_inline static yyjson_inline #undef static_noinline #define static_noinline static yyjson_noinline /* Macros for min and max. */ #undef yyjson_min #define yyjson_min(x, y) ((x) < (y) ? (x) : (y)) #undef yyjson_max #define yyjson_max(x, y) ((x) > (y) ? (x) : (y)) /* Used to write u64 literal for C89 which doesn't support "ULL" suffix. */ #undef U64 #define U64(hi, lo) ((((u64)hi##UL) << 32U) + lo##UL) /* Used to cast away (remove) const qualifier. */ #define constcast(type) (type)(void *)(size_t)(const void *) /*============================================================================== * Integer Constants *============================================================================*/ /* U64 constant values */ #undef U64_MAX #define U64_MAX U64(0xFFFFFFFF, 0xFFFFFFFF) #undef I64_MAX #define I64_MAX U64(0x7FFFFFFF, 0xFFFFFFFF) #undef USIZE_MAX #define USIZE_MAX ((usize)(~(usize)0)) /* Maximum number of digits for reading u32/u64/usize safety (not overflow). */ #undef U32_SAFE_DIG #define U32_SAFE_DIG 9 /* u32 max is 4294967295, 10 digits */ #undef U64_SAFE_DIG #define U64_SAFE_DIG 19 /* u64 max is 18446744073709551615, 20 digits */ #undef USIZE_SAFE_DIG #define USIZE_SAFE_DIG (sizeof(usize) == 64 ? U64_SAFE_DIG : U32_SAFE_DIG) /*============================================================================== * IEEE-754 Double Number Constants *============================================================================*/ /* Inf raw value (positive) */ #define F64_RAW_INF U64(0x7FF00000, 0x00000000) /* NaN raw value (quiet NaN, no payload, no sign) */ #if defined(__hppa__) || (defined(__mips__) && !defined(__mips_nan2008)) #define F64_RAW_NAN U64(0x7FF7FFFF, 0xFFFFFFFF) #else #define F64_RAW_NAN U64(0x7FF80000, 0x00000000) #endif /* double number bits */ #define F64_BITS 64 /* double number exponent part bits */ #define F64_EXP_BITS 11 /* double number significand part bits */ #define F64_SIG_BITS 52 /* double number significand part bits (with 1 hidden bit) */ #define F64_SIG_FULL_BITS 53 /* double number significand bit mask */ #define F64_SIG_MASK U64(0x000FFFFF, 0xFFFFFFFF) /* double number exponent bit mask */ #define F64_EXP_MASK U64(0x7FF00000, 0x00000000) /* double number exponent bias */ #define F64_EXP_BIAS 1023 /* double number significant digits count in decimal */ #define F64_DEC_DIG 17 /* max significant digits count in decimal when reading double number */ #define F64_MAX_DEC_DIG 768 /* maximum decimal power of double number (1.7976931348623157e308) */ #define F64_MAX_DEC_EXP 308 /* minimum decimal power of double number (4.9406564584124654e-324) */ #define F64_MIN_DEC_EXP (-324) /* maximum binary power of double number */ #define F64_MAX_BIN_EXP 1024 /* minimum binary power of double number */ #define F64_MIN_BIN_EXP (-1021) /*============================================================================== * Types *============================================================================*/ /** Type define for primitive types. */ typedef float f32; typedef double f64; typedef int8_t i8; typedef uint8_t u8; typedef int16_t i16; typedef uint16_t u16; typedef int32_t i32; typedef uint32_t u32; typedef int64_t i64; typedef uint64_t u64; typedef size_t usize; /** 128-bit integer, used by floating-point number reader and writer. */ #if YYJSON_HAS_INT128 __extension__ typedef __int128 i128; __extension__ typedef unsigned __int128 u128; #endif /** 16/32/64-bit vector */ typedef struct v16 { char c1, c2; } v16; typedef struct v32 { char c1, c2, c3, c4; } v32; typedef struct v64 { char c1, c2, c3, c4, c5, c6, c7, c8; } v64; /** 16/32/64-bit vector union, used for unaligned memory access on modern CPU */ typedef union v16_uni { v16 v; u16 u; } v16_uni; typedef union v32_uni { v32 v; u32 u; } v32_uni; typedef union v64_uni { v64 v; u64 u; } v64_uni; /*============================================================================== * Load/Store Utils *============================================================================*/ #define byte_move_idx(x) ((u8 *)dst)[x] = ((u8 *)src)[x]; static_inline void byte_move_2(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat2_incr(byte_move_idx) #else memmove(dst, src, 2); #endif } static_inline void byte_move_4(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat4_incr(byte_move_idx) #else memmove(dst, src, 4); #endif } static_inline void byte_move_8(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat8_incr(byte_move_idx) #else memmove(dst, src, 8); #endif } static_inline void byte_move_16(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat16_incr(byte_move_idx) #else memmove(dst, src, 16); #endif } static_inline void byte_copy_2(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat2_incr(byte_move_idx) #else memcpy(dst, src, 2); #endif } static_inline void byte_copy_4(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat4_incr(byte_move_idx) #else memcpy(dst, src, 4); #endif } static_inline void byte_copy_8(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat8_incr(byte_move_idx) #else memcpy(dst, src, 8); #endif } static_inline void byte_copy_16(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat16_incr(byte_move_idx) #else memcpy(dst, src, 16); #endif } static_inline bool byte_match_2(void *buf, const char *pat) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS return ((u8 *)buf)[0] == ((const u8 *)pat)[0] && ((u8 *)buf)[1] == ((const u8 *)pat)[1]; #else v16_uni u1, u2; u1.v = *(const v16 *)pat; u2.v = *(const v16 *)buf; return u1.u == u2.u; #endif } static_inline bool byte_match_4(void *buf, const char *pat) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS return ((u8 *)buf)[0] == ((const u8 *)pat)[0] && ((u8 *)buf)[1] == ((const u8 *)pat)[1] && ((u8 *)buf)[2] == ((const u8 *)pat)[2] && ((u8 *)buf)[3] == ((const u8 *)pat)[3]; #else v32_uni u1, u2; u1.v = *(const v32 *)pat; u2.v = *(const v32 *)buf; return u1.u == u2.u; #endif } static_inline u16 byte_load_2(const void *src) { v16_uni uni; uni.v = *(const v16 *)src; return uni.u; } static_inline u32 byte_load_3(const void *src) { v32_uni uni; ((v16_uni *)&uni)->v = *(const v16 *)src; uni.v.c3 = ((const char *)src)[2]; uni.v.c4 = 0; return uni.u; } static_inline u32 byte_load_4(const void *src) { v32_uni uni; uni.v = *(const v32 *)src; return uni.u; } #undef byte_move_expr /*============================================================================== * Number Utils * These functions are used to detect and convert NaN and Inf numbers. *============================================================================*/ /** This union is used to avoid violating the strict aliasing rule in C. `memcpy` can be used in both C and C++, but it may reduce performance without compiler optimization. */ typedef union { u64 u; f64 f; } f64_uni; /** Convert raw binary to double. */ static_inline f64 f64_from_raw(u64 u) { #ifndef __cplusplus f64_uni uni; uni.u = u; return uni.f; #else f64 f; memcpy(&f, &u, 8); return f; #endif } /** Convert double to raw binary. */ static_inline u64 f64_to_raw(f64 f) { #ifndef __cplusplus f64_uni uni; uni.f = f; return uni.u; #else u64 u; memcpy(&u, &f, 8); return u; #endif } /** Get raw 'infinity' with sign. */ static_inline u64 f64_raw_get_inf(bool sign) { #if YYJSON_HAS_IEEE_754 return F64_RAW_INF | ((u64)sign << 63); #elif defined(INFINITY) return f64_to_raw(sign ? -INFINITY : INFINITY); #else return f64_to_raw(sign ? -HUGE_VAL : HUGE_VAL); #endif } /** Get raw 'nan' with sign. */ static_inline u64 f64_raw_get_nan(bool sign) { #if YYJSON_HAS_IEEE_754 return F64_RAW_NAN | ((u64)sign << 63); #elif defined(NAN) return f64_to_raw(sign ? (f64)-NAN : (f64)NAN); #else return f64_to_raw((sign ? -0.0 : 0.0) / 0.0); #endif } /** Convert normalized u64 (highest bit is 1) to f64. Some compiler (such as Microsoft Visual C++ 6.0) do not support converting number from u64 to f64. This function will first convert u64 to i64 and then to f64, with `to nearest` rounding mode. */ static_inline f64 normalized_u64_to_f64(u64 val) { #if YYJSON_U64_TO_F64_NO_IMPL i64 sig = (i64)((val >> 1) | (val & 1)); return ((f64)sig) * (f64)2.0; #else return (f64)val; #endif } /*============================================================================== * Size Utils * These functions are used for memory allocation. *============================================================================*/ /** Returns whether the size is overflow after increment. */ static_inline bool size_add_is_overflow(usize size, usize add) { return size > (size + add); } /** Returns whether the size is power of 2 (size should not be 0). */ static_inline bool size_is_pow2(usize size) { return (size & (size - 1)) == 0; } /** Align size upwards (may overflow). */ static_inline usize size_align_up(usize size, usize align) { if (size_is_pow2(align)) { return (size + (align - 1)) & ~(align - 1); } else { return size + align - (size + align - 1) % align - 1; } } /** Align size downwards. */ static_inline usize size_align_down(usize size, usize align) { if (size_is_pow2(align)) { return size & ~(align - 1); } else { return size - (size % align); } } /** Align address upwards (may overflow). */ static_inline void *mem_align_up(void *mem, usize align) { usize size; memcpy(&size, &mem, sizeof(usize)); size = size_align_up(size, align); memcpy(&mem, &size, sizeof(usize)); return mem; } /*============================================================================== * Bits Utils * These functions are used by the floating-point number reader and writer. *============================================================================*/ /** Returns the number of leading 0-bits in value (input should not be 0). */ static_inline u32 u64_lz_bits(u64 v) { #if GCC_HAS_CLZLL return (u32)__builtin_clzll(v); #elif MSC_HAS_BIT_SCAN_64 unsigned long r; _BitScanReverse64(&r, v); return (u32)63 - (u32)r; #elif MSC_HAS_BIT_SCAN unsigned long hi, lo; bool hi_set = _BitScanReverse(&hi, (u32)(v >> 32)) != 0; _BitScanReverse(&lo, (u32)v); hi |= 32; return (u32)63 - (u32)(hi_set ? hi : lo); #else /* branchless, use de Bruijn sequences see: https://www.chessprogramming.org/BitScan */ const u8 table[64] = { 63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2, 9, 5, 28, 11, 13, 21, 42, 19, 25, 31, 34, 40, 46, 52, 59, 1, 17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41, 53, 18, 38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0 }; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v |= v >> 32; return table[(v * U64(0x03F79D71, 0xB4CB0A89)) >> 58]; #endif } /** Returns the number of trailing 0-bits in value (input should not be 0). */ static_inline u32 u64_tz_bits(u64 v) { #if GCC_HAS_CTZLL return (u32)__builtin_ctzll(v); #elif MSC_HAS_BIT_SCAN_64 unsigned long r; _BitScanForward64(&r, v); return (u32)r; #elif MSC_HAS_BIT_SCAN unsigned long lo, hi; bool lo_set = _BitScanForward(&lo, (u32)(v)) != 0; _BitScanForward(&hi, (u32)(v >> 32)); hi += 32; return lo_set ? lo : hi; #else /* branchless, use de Bruijn sequences see: https://www.chessprogramming.org/BitScan */ const u8 table[64] = { 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 }; return table[((v & (~v + 1)) * U64(0x022FDD63, 0xCC95386D)) >> 58]; #endif } /*============================================================================== * 128-bit Integer Utils * These functions are used by the floating-point number reader and writer. *============================================================================*/ /** Multiplies two 64-bit unsigned integers (a * b), returns the 128-bit result as 'hi' and 'lo'. */ static_inline void u128_mul(u64 a, u64 b, u64 *hi, u64 *lo) { #if YYJSON_HAS_INT128 u128 m = (u128)a * b; *hi = (u64)(m >> 64); *lo = (u64)(m); #elif MSC_HAS_UMUL128 *lo = _umul128(a, b, hi); #else u32 a0 = (u32)(a), a1 = (u32)(a >> 32); u32 b0 = (u32)(b), b1 = (u32)(b >> 32); u64 p00 = (u64)a0 * b0, p01 = (u64)a0 * b1; u64 p10 = (u64)a1 * b0, p11 = (u64)a1 * b1; u64 m0 = p01 + (p00 >> 32); u32 m00 = (u32)(m0), m01 = (u32)(m0 >> 32); u64 m1 = p10 + m00; u32 m10 = (u32)(m1), m11 = (u32)(m1 >> 32); *hi = p11 + m01 + m11; *lo = ((u64)m10 << 32) | (u32)p00; #endif } /** Multiplies two 64-bit unsigned integers and add a value (a * b + c), returns the 128-bit result as 'hi' and 'lo'. */ static_inline void u128_mul_add(u64 a, u64 b, u64 c, u64 *hi, u64 *lo) { #if YYJSON_HAS_INT128 u128 m = (u128)a * b + c; *hi = (u64)(m >> 64); *lo = (u64)(m); #else u64 h, l, t; u128_mul(a, b, &h, &l); t = l + c; h += (u64)(((t < l) | (t < c))); *hi = h; *lo = t; #endif } /*============================================================================== * File Utils * These functions are used to read and write JSON files. *============================================================================*/ #define YYJSON_FOPEN_EXT #if !defined(_MSC_VER) && defined(__GLIBC__) && defined(__GLIBC_PREREQ) # if __GLIBC_PREREQ(2, 7) # undef YYJSON_FOPEN_EXT # define YYJSON_FOPEN_EXT "e" /* glibc extension to enable O_CLOEXEC */ # endif #endif static_inline FILE *fopen_safe(const char *path, const char *mode) { #if YYJSON_MSC_VER >= 1400 FILE *file = NULL; if (fopen_s(&file, path, mode) != 0) return NULL; return file; #else return fopen(path, mode); #endif } static_inline FILE *fopen_readonly(const char *path) { return fopen_safe(path, "rb" YYJSON_FOPEN_EXT); } static_inline FILE *fopen_writeonly(const char *path) { return fopen_safe(path, "wb" YYJSON_FOPEN_EXT); } static_inline usize fread_safe(void *buf, usize size, FILE *file) { #if YYJSON_MSC_VER >= 1400 return fread_s(buf, size, 1, size, file); #else return fread(buf, 1, size, file); #endif } /*============================================================================== * Default Memory Allocator * This is a simple libc memory allocator wrapper. *============================================================================*/ static void *default_malloc(void *ctx, usize size) { return malloc(size); } static void *default_realloc(void *ctx, void *ptr, usize old_size, usize size) { return realloc(ptr, size); } static void default_free(void *ctx, void *ptr) { free(ptr); } static const yyjson_alc YYJSON_DEFAULT_ALC = { default_malloc, default_realloc, default_free, NULL }; static void *null_malloc(void *ctx, usize size) { return NULL; } static void *null_realloc(void *ctx, void *ptr, usize old_size, usize size) { return NULL; } static void null_free(void *ctx, void *ptr) { return; } static const yyjson_alc YYJSON_NULL_ALC = { null_malloc, null_realloc, null_free, NULL }; /*============================================================================== * Pool Memory Allocator * This is a simple memory allocator that uses linked list memory chunk. * The following code will be executed only when the library user creates * this allocator manually. *============================================================================*/ /** chunk header */ typedef struct pool_chunk { usize size; /* chunk memory size (include chunk header) */ struct pool_chunk *next; } pool_chunk; /** ctx header */ typedef struct pool_ctx { usize size; /* total memory size (include ctx header) */ pool_chunk *free_list; } pool_ctx; static void *pool_malloc(void *ctx_ptr, usize size) { pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *next, *prev = NULL, *cur = ctx->free_list; if (unlikely(size == 0 || size >= ctx->size)) return NULL; size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk); while (cur) { if (cur->size < size) { /* not enough space, try next chunk */ prev = cur; cur = cur->next; continue; } if (cur->size >= size + sizeof(pool_chunk) * 2) { /* too much space, split this chunk */ next = (pool_chunk *)(void *)((u8 *)cur + size); next->size = cur->size - size; next->next = cur->next; cur->size = size; } else { /* just enough space, use whole chunk */ next = cur->next; } if (prev) prev->next = next; else ctx->free_list = next; return (void *)(cur + 1); } return NULL; } static void pool_free(void *ctx_ptr, void *ptr) { pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *cur = ((pool_chunk *)ptr) - 1; pool_chunk *prev = NULL, *next = ctx->free_list; while (next && next < cur) { prev = next; next = next->next; } if (prev) prev->next = cur; else ctx->free_list = cur; cur->next = next; if (next && ((u8 *)cur + cur->size) == (u8 *)next) { /* merge cur to higher chunk */ cur->size += next->size; cur->next = next->next; } if (prev && ((u8 *)prev + prev->size) == (u8 *)cur) { /* merge cur to lower chunk */ prev->size += cur->size; prev->next = cur->next; } } static void *pool_realloc(void *ctx_ptr, void *ptr, usize old_size, usize size) { pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *cur = ((pool_chunk *)ptr) - 1, *prev, *next, *tmp; usize free_size; void *new_ptr; if (unlikely(size == 0 || size >= ctx->size)) return NULL; size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk); /* reduce size */ if (unlikely(size <= cur->size)) { free_size = cur->size - size; if (free_size >= sizeof(pool_chunk) * 2) { tmp = (pool_chunk *)(void *)((u8 *)cur + cur->size - free_size); tmp->size = free_size; pool_free(ctx_ptr, (void *)(tmp + 1)); cur->size -= free_size; } return ptr; } /* find next and prev chunk */ prev = NULL; next = ctx->free_list; while (next && next < cur) { prev = next; next = next->next; } /* merge to higher chunk if they are contiguous */ if ((u8 *)cur + cur->size == (u8 *)next && cur->size + next->size >= size) { free_size = cur->size + next->size - size; if (free_size > sizeof(pool_chunk) * 2) { tmp = (pool_chunk *)(void *)((u8 *)cur + size); if (prev) prev->next = tmp; else ctx->free_list = tmp; tmp->next = next->next; tmp->size = free_size; cur->size = size; } else { if (prev) prev->next = next->next; else ctx->free_list = next->next; cur->size += next->size; } return ptr; } /* fallback to malloc and memcpy */ new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk)); if (new_ptr) { memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk)); pool_free(ctx_ptr, ptr); } return new_ptr; } bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) { pool_chunk *chunk; pool_ctx *ctx; if (unlikely(!alc)) return false; *alc = YYJSON_NULL_ALC; if (size < sizeof(pool_ctx) * 4) return false; ctx = (pool_ctx *)mem_align_up(buf, sizeof(pool_ctx)); if (unlikely(!ctx)) return false; size -= (usize)((u8 *)ctx - (u8 *)buf); size = size_align_down(size, sizeof(pool_ctx)); chunk = (pool_chunk *)(ctx + 1); chunk->size = size - sizeof(pool_ctx); chunk->next = NULL; ctx->size = size; ctx->free_list = chunk; alc->malloc = pool_malloc; alc->realloc = pool_realloc; alc->free = pool_free; alc->ctx = (void *)ctx; return true; } /*============================================================================== * JSON document and value *============================================================================*/ static_inline void unsafe_yyjson_str_pool_release(yyjson_str_pool *pool, yyjson_alc *alc) { yyjson_str_chunk *chunk = pool->chunks, *next; while (chunk) { next = chunk->next; alc->free(alc->ctx, chunk); chunk = next; } } static_inline void unsafe_yyjson_val_pool_release(yyjson_val_pool *pool, yyjson_alc *alc) { yyjson_val_chunk *chunk = pool->chunks, *next; while (chunk) { next = chunk->next; alc->free(alc->ctx, chunk); chunk = next; } } bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool, const yyjson_alc *alc, usize len) { yyjson_str_chunk *chunk; usize size, max_len; /* create a new chunk */ max_len = USIZE_MAX - sizeof(yyjson_str_chunk); if (unlikely(len > max_len)) return false; size = len + sizeof(yyjson_str_chunk); size = yyjson_max(pool->chunk_size, size); chunk = (yyjson_str_chunk *)alc->malloc(alc->ctx, size); if (unlikely(!chunk)) return false; /* insert the new chunk as the head of the linked list */ chunk->next = pool->chunks; chunk->chunk_size = size; pool->chunks = chunk; pool->cur = (char *)chunk + sizeof(yyjson_str_chunk); pool->end = (char *)chunk + size; /* the next chunk is twice the size of the current one */ size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max); if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */ pool->chunk_size = size; return true; } bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool, const yyjson_alc *alc, usize count) { yyjson_val_chunk *chunk; usize size, max_count; /* create a new chunk */ max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1; if (unlikely(count > max_count)) return false; size = (count + 1) * sizeof(yyjson_mut_val); size = yyjson_max(pool->chunk_size, size); chunk = (yyjson_val_chunk *)alc->malloc(alc->ctx, size); if (unlikely(!chunk)) return false; /* insert the new chunk as the head of the linked list */ chunk->next = pool->chunks; chunk->chunk_size = size; pool->chunks = chunk; pool->cur = (yyjson_mut_val *)(void *)((u8 *)chunk) + 1; pool->end = (yyjson_mut_val *)(void *)((u8 *)chunk + size); /* the next chunk is twice the size of the current one */ size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max); if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */ pool->chunk_size = size; return true; } bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc, size_t len) { usize max_size = USIZE_MAX - sizeof(yyjson_str_chunk); if (!doc || !len || len > max_size) return false; doc->str_pool.chunk_size = len + sizeof(yyjson_str_chunk); return true; } bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count) { usize max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1; if (!doc || !count || count > max_count) return false; doc->val_pool.chunk_size = (count + 1) * sizeof(yyjson_mut_val); return true; } void yyjson_mut_doc_free(yyjson_mut_doc *doc) { if (doc) { yyjson_alc alc = doc->alc; unsafe_yyjson_str_pool_release(&doc->str_pool, &alc); unsafe_yyjson_val_pool_release(&doc->val_pool, &alc); alc.free(alc.ctx, doc); } } yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc) { yyjson_mut_doc *doc; if (!alc) alc = &YYJSON_DEFAULT_ALC; doc = (yyjson_mut_doc *)alc->malloc(alc->ctx, sizeof(yyjson_mut_doc)); if (!doc) return NULL; memset(doc, 0, sizeof(yyjson_mut_doc)); doc->alc = *alc; doc->str_pool.chunk_size = YYJSON_MUT_DOC_STR_POOL_INIT_SIZE; doc->str_pool.chunk_size_max = YYJSON_MUT_DOC_STR_POOL_MAX_SIZE; doc->val_pool.chunk_size = YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE; doc->val_pool.chunk_size_max = YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE; return doc; } yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, const yyjson_alc *alc) { yyjson_mut_doc *m_doc; yyjson_mut_val *m_val; if (!doc || !doc->root) return NULL; m_doc = yyjson_mut_doc_new(alc); if (!m_doc) return NULL; m_val = yyjson_val_mut_copy(m_doc, doc->root); if (!m_val) { yyjson_mut_doc_free(m_doc); return NULL; } yyjson_mut_doc_set_root(m_doc, m_val); return m_doc; } yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc, const yyjson_alc *alc) { yyjson_mut_doc *m_doc; yyjson_mut_val *m_val; if (!doc) return NULL; if (!doc->root) return yyjson_mut_doc_new(alc); m_doc = yyjson_mut_doc_new(alc); if (!m_doc) return NULL; m_val = yyjson_mut_val_mut_copy(m_doc, doc->root); if (!m_val) { yyjson_mut_doc_free(m_doc); return NULL; } yyjson_mut_doc_set_root(m_doc, m_val); return m_doc; } yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc, yyjson_val *i_vals) { /* The immutable object or array stores all sub-values in a contiguous memory, We copy them to another contiguous memory as mutable values, then reconnect the mutable values with the original relationship. */ usize i_vals_len; yyjson_mut_val *m_vals, *m_val; yyjson_val *i_val, *i_end; if (!m_doc || !i_vals) return NULL; i_end = unsafe_yyjson_get_next(i_vals); i_vals_len = (usize)(unsafe_yyjson_get_next(i_vals) - i_vals); m_vals = unsafe_yyjson_mut_val(m_doc, i_vals_len); if (!m_vals) return NULL; i_val = i_vals; m_val = m_vals; for (; i_val < i_end; i_val++, m_val++) { yyjson_type type = unsafe_yyjson_get_type(i_val); m_val->tag = i_val->tag; m_val->uni.u64 = i_val->uni.u64; if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { const char *str = i_val->uni.str; usize str_len = unsafe_yyjson_get_len(i_val); m_val->uni.str = unsafe_yyjson_mut_strncpy(m_doc, str, str_len); if (!m_val->uni.str) return NULL; } else if (type == YYJSON_TYPE_ARR) { usize len = unsafe_yyjson_get_len(i_val); if (len > 0) { yyjson_val *ii_val = i_val + 1, *ii_next; yyjson_mut_val *mm_val = m_val + 1, *mm_ctn = m_val, *mm_next; while (len-- > 1) { ii_next = unsafe_yyjson_get_next(ii_val); mm_next = mm_val + (ii_next - ii_val); mm_val->next = mm_next; ii_val = ii_next; mm_val = mm_next; } mm_val->next = mm_ctn + 1; mm_ctn->uni.ptr = mm_val; } } else if (type == YYJSON_TYPE_OBJ) { usize len = unsafe_yyjson_get_len(i_val); if (len > 0) { yyjson_val *ii_key = i_val + 1, *ii_nextkey; yyjson_mut_val *mm_key = m_val + 1, *mm_ctn = m_val; yyjson_mut_val *mm_nextkey; while (len-- > 1) { ii_nextkey = unsafe_yyjson_get_next(ii_key + 1); mm_nextkey = mm_key + (ii_nextkey - ii_key); mm_key->next = mm_key + 1; mm_key->next->next = mm_nextkey; ii_key = ii_nextkey; mm_key = mm_nextkey; } mm_key->next = mm_key + 1; mm_key->next->next = mm_ctn + 1; mm_ctn->uni.ptr = mm_key; } } } return m_vals; } static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc, yyjson_mut_val *m_vals) { /* The mutable object or array stores all sub-values in a circular linked list, so we can traverse them in the same loop. The traversal starts from the last item, continues with the first item in a list, and ends with the second to last item, which needs to be linked to the last item to close the circle. */ yyjson_mut_val *m_val = unsafe_yyjson_mut_val(m_doc, 1); if (unlikely(!m_val)) return NULL; m_val->tag = m_vals->tag; switch (unsafe_yyjson_get_type(m_vals)) { case YYJSON_TYPE_OBJ: case YYJSON_TYPE_ARR: if (unsafe_yyjson_get_len(m_vals) > 0) { yyjson_mut_val *last = (yyjson_mut_val *)m_vals->uni.ptr; yyjson_mut_val *next = last->next, *prev; prev = unsafe_yyjson_mut_val_mut_copy(m_doc, last); if (!prev) return NULL; m_val->uni.ptr = (void *)prev; while (next != last) { prev->next = unsafe_yyjson_mut_val_mut_copy(m_doc, next); if (!prev->next) return NULL; prev = prev->next; next = next->next; } prev->next = (yyjson_mut_val *)m_val->uni.ptr; } break; case YYJSON_TYPE_RAW: case YYJSON_TYPE_STR: { const char *str = m_vals->uni.str; usize str_len = unsafe_yyjson_get_len(m_vals); m_val->uni.str = unsafe_yyjson_mut_strncpy(m_doc, str, str_len); if (!m_val->uni.str) return NULL; break; } default: m_val->uni = m_vals->uni; break; } return m_val; } yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc, yyjson_mut_val *val) { if (doc && val) return unsafe_yyjson_mut_val_mut_copy(doc, val); return NULL; } /* Count the number of values and the total length of the strings. */ static void yyjson_mut_stat(yyjson_mut_val *val, usize *val_sum, usize *str_sum) { yyjson_type type = unsafe_yyjson_get_type(val); *val_sum += 1; if (type == YYJSON_TYPE_ARR || type == YYJSON_TYPE_OBJ) { yyjson_mut_val *child = (yyjson_mut_val *)val->uni.ptr; usize len = unsafe_yyjson_get_len(val), i; len <<= (u8)(type == YYJSON_TYPE_OBJ); *val_sum += len; for (i = 0; i < len; i++) { yyjson_type stype = unsafe_yyjson_get_type(child); if (stype == YYJSON_TYPE_STR || stype == YYJSON_TYPE_RAW) { *str_sum += unsafe_yyjson_get_len(child) + 1; } else if (stype == YYJSON_TYPE_ARR || stype == YYJSON_TYPE_OBJ) { yyjson_mut_stat(child, val_sum, str_sum); *val_sum -= 1; } child = child->next; } } else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { *str_sum += unsafe_yyjson_get_len(val) + 1; } } /* Copy mutable values to immutable value pool. */ static usize yyjson_imut_copy(yyjson_val **val_ptr, char **buf_ptr, yyjson_mut_val *mval) { yyjson_val *val = *val_ptr; yyjson_type type = unsafe_yyjson_get_type(mval); if (type == YYJSON_TYPE_ARR || type == YYJSON_TYPE_OBJ) { yyjson_mut_val *child = (yyjson_mut_val *)mval->uni.ptr; usize len = unsafe_yyjson_get_len(mval), i; usize val_sum = 1; if (type == YYJSON_TYPE_OBJ) { if (len) child = child->next->next; len <<= 1; } else { if (len) child = child->next; } *val_ptr = val + 1; for (i = 0; i < len; i++) { val_sum += yyjson_imut_copy(val_ptr, buf_ptr, child); child = child->next; } val->tag = mval->tag; val->uni.ofs = val_sum * sizeof(yyjson_val); return val_sum; } else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { char *buf = *buf_ptr; usize len = unsafe_yyjson_get_len(mval); memcpy((void *)buf, (const void *)mval->uni.str, len); buf[len] = '\0'; val->tag = mval->tag; val->uni.str = buf; *val_ptr = val + 1; *buf_ptr = buf + len + 1; return 1; } else { val->tag = mval->tag; val->uni = mval->uni; *val_ptr = val + 1; return 1; } } yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *mdoc, const yyjson_alc *alc) { if (!mdoc) return NULL; return yyjson_mut_val_imut_copy(mdoc->root, alc); } yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *mval, const yyjson_alc *alc) { usize val_num = 0, str_sum = 0, hdr_size, buf_size; yyjson_doc *doc = NULL; yyjson_val *val_hdr = NULL; /* This value should be NULL here. Setting a non-null value suppresses warning from the clang analyzer. */ char *str_hdr = (char *)(void *)&str_sum; if (!mval) return NULL; if (!alc) alc = &YYJSON_DEFAULT_ALC; /* traverse the input value to get pool size */ yyjson_mut_stat(mval, &val_num, &str_sum); /* create doc and val pool */ hdr_size = size_align_up(sizeof(yyjson_doc), sizeof(yyjson_val)); buf_size = hdr_size + val_num * sizeof(yyjson_val); doc = (yyjson_doc *)alc->malloc(alc->ctx, buf_size); if (!doc) return NULL; memset(doc, 0, sizeof(yyjson_doc)); val_hdr = (yyjson_val *)(void *)((char *)(void *)doc + hdr_size); doc->root = val_hdr; doc->alc = *alc; /* create str pool */ if (str_sum > 0) { str_hdr = (char *)alc->malloc(alc->ctx, str_sum); doc->str_pool = str_hdr; if (!str_hdr) { alc->free(alc->ctx, (void *)doc); return NULL; } } /* copy vals and strs */ doc->val_read = yyjson_imut_copy(&val_hdr, &str_hdr, mval); doc->dat_read = str_sum + 1; return doc; } static_inline bool unsafe_yyjson_num_equals(void *lhs, void *rhs) { yyjson_val_uni *luni = &((yyjson_val *)lhs)->uni; yyjson_val_uni *runi = &((yyjson_val *)rhs)->uni; yyjson_subtype lt = unsafe_yyjson_get_subtype(lhs); yyjson_subtype rt = unsafe_yyjson_get_subtype(rhs); if (lt == rt) return luni->u64 == runi->u64; if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) return luni->i64 >= 0 && luni->u64 == runi->u64; if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) return runi->i64 >= 0 && luni->u64 == runi->u64; return false; } static_inline bool unsafe_yyjson_str_equals(void *lhs, void *rhs) { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; return !memcmp(unsafe_yyjson_get_str(lhs), unsafe_yyjson_get_str(rhs), len); } bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { yyjson_type type = unsafe_yyjson_get_type(lhs); if (type != unsafe_yyjson_get_type(rhs)) return false; switch (type) { case YYJSON_TYPE_OBJ: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; if (len > 0) { yyjson_obj_iter iter; yyjson_obj_iter_init(rhs, &iter); lhs = unsafe_yyjson_get_first(lhs); while (len-- > 0) { rhs = yyjson_obj_iter_getn(&iter, lhs->uni.str, unsafe_yyjson_get_len(lhs)); if (!rhs || !unsafe_yyjson_equals(lhs + 1, rhs)) return false; lhs = unsafe_yyjson_get_next(lhs + 1); } } /* yyjson allows duplicate keys, so the check may be inaccurate */ return true; } case YYJSON_TYPE_ARR: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; if (len > 0) { lhs = unsafe_yyjson_get_first(lhs); rhs = unsafe_yyjson_get_first(rhs); while (len-- > 0) { if (!unsafe_yyjson_equals(lhs, rhs)) return false; lhs = unsafe_yyjson_get_next(lhs); rhs = unsafe_yyjson_get_next(rhs); } } return true; } case YYJSON_TYPE_NUM: return unsafe_yyjson_num_equals(lhs, rhs); case YYJSON_TYPE_RAW: case YYJSON_TYPE_STR: return unsafe_yyjson_str_equals(lhs, rhs); case YYJSON_TYPE_NULL: case YYJSON_TYPE_BOOL: return lhs->tag == rhs->tag; default: return false; } } bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { yyjson_type type = unsafe_yyjson_get_type(lhs); if (type != unsafe_yyjson_get_type(rhs)) return false; switch (type) { case YYJSON_TYPE_OBJ: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; if (len > 0) { yyjson_mut_obj_iter iter; yyjson_mut_obj_iter_init(rhs, &iter); lhs = (yyjson_mut_val *)lhs->uni.ptr; while (len-- > 0) { rhs = yyjson_mut_obj_iter_getn(&iter, lhs->uni.str, unsafe_yyjson_get_len(lhs)); if (!rhs || !unsafe_yyjson_mut_equals(lhs->next, rhs)) return false; lhs = lhs->next->next; } } /* yyjson allows duplicate keys, so the check may be inaccurate */ return true; } case YYJSON_TYPE_ARR: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; if (len > 0) { lhs = (yyjson_mut_val *)lhs->uni.ptr; rhs = (yyjson_mut_val *)rhs->uni.ptr; while (len-- > 0) { if (!unsafe_yyjson_mut_equals(lhs, rhs)) return false; lhs = lhs->next; rhs = rhs->next; } } return true; } case YYJSON_TYPE_NUM: return unsafe_yyjson_num_equals(lhs, rhs); case YYJSON_TYPE_RAW: case YYJSON_TYPE_STR: return unsafe_yyjson_str_equals(lhs, rhs); case YYJSON_TYPE_NULL: case YYJSON_TYPE_BOOL: return lhs->tag == rhs->tag; default: return false; } } #if !YYJSON_DISABLE_UTILS /*============================================================================== * JSON Pointer API (RFC 6901) *============================================================================*/ /** Get a token from JSON pointer string. @param ptr [in,out] in: string that points to current token prefix `/` out: string that points to next token prefix `/`, or string end @param end [in] end of the entire JSON Pointer string @param len [out] unescaped token length @param esc [out] number of escaped characters in this token @return head of the token, or NULL if syntax error */ static_inline const char *ptr_next_token(const char **ptr, const char *end, usize *len, usize *esc) { const char *hdr = *ptr + 1; const char *cur = hdr; /* skip unescaped characters */ while (cur < end && *cur != '/' && *cur != '~') cur++; if (likely(cur == end || *cur != '~')) { /* no escaped characters, return */ *ptr = cur; *len = (usize)(cur - hdr); *esc = 0; return hdr; } else { /* handle escaped characters */ usize esc_num = 0; while (cur < end && *cur != '/') { if (*cur++ == '~') { if (cur == end || (*cur != '0' && *cur != '1')) { *ptr = cur - 1; return NULL; } esc_num++; } } *ptr = cur; *len = (usize)(cur - hdr) - esc_num; *esc = esc_num; return hdr; } } /** Convert token string to index. @param cur [in] token head @param len [in] token length @param idx [out] the index number, or USIZE_MAX if token is '-' @return true if token is a valid array index */ static_inline bool ptr_token_to_idx(const char *cur, usize len, usize *idx) { const char *end = cur + len; usize num = 0, add; if (unlikely(len == 0 || len > USIZE_SAFE_DIG)) return false; if (*cur == '0') { if (unlikely(len > 1)) return false; *idx = 0; return true; } if (*cur == '-') { if (unlikely(len > 1)) return false; *idx = USIZE_MAX; return true; } for (; cur < end && (add = (usize)((u8)*cur - (u8)'0')) <= 9; cur++) { num = num * 10 + add; } if (unlikely(num == 0 || cur < end)) return false; *idx = num; return true; } /** Compare JSON key with token. @param key a string key (yyjson_val or yyjson_mut_val) @param tag the expected string key tag @param token a JSON pointer token @param len unescaped token length @param esc number of escaped characters in this token @return true if `str` is equals to `token` */ static_inline bool ptr_token_eq(void *key, u64 tag, const char *token, usize len, usize esc) { yyjson_val *val = (yyjson_val *)key; if (val->tag != tag) return false; if (likely(!esc)) { return memcmp(val->uni.str, token, len) == 0; } else { const char *str = val->uni.str; for (; len-- > 0; token++, str++) { if (*token == '~') { if (*str != (*++token == '0' ? '~' : '/')) return false; } else { if (*str != *token) return false; } } return true; } } /** Get a value from array by token. @param arr an array, should not be NULL or non-array type @param token a JSON pointer token @param len unescaped token length @param esc number of escaped characters in this token @return value at index, or NULL if token is not index or index is out of range */ static_inline yyjson_val *ptr_arr_get(yyjson_val *arr, const char *token, usize len, usize esc) { yyjson_val *val = unsafe_yyjson_get_first(arr); usize num = unsafe_yyjson_get_len(arr), idx; if (unlikely(num == 0)) return NULL; if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL; if (unlikely(idx >= num)) return NULL; if (unsafe_yyjson_arr_is_flat(arr)) { return val + idx; } else { while (idx-- > 0) val = unsafe_yyjson_get_next(val); return val; } } /** Get a value from object by token. @param obj [in] an object, should not be NULL or non-object type @param token [in] a JSON pointer token @param len [in] unescaped token length @param esc [in] number of escaped characters in this token @return value associated with the token, or NULL if no value */ static_inline yyjson_val *ptr_obj_get(yyjson_val *obj, const char *token, usize len, usize esc) { u64 tag = (((u64)len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; yyjson_val *key = unsafe_yyjson_get_first(obj); usize num = unsafe_yyjson_get_len(obj); if (unlikely(num == 0)) return NULL; for (; num > 0; num--, key = unsafe_yyjson_get_next(key + 1)) { if (ptr_token_eq(key, tag, token, len, esc)) return key + 1; } return NULL; } /** Get a value from array by token. @param arr [in] an array, should not be NULL or non-array type @param token [in] a JSON pointer token @param len [in] unescaped token length @param esc [in] number of escaped characters in this token @param pre [out] previous (sibling) value of the returned value @param last [out] whether index is last @return value at index, or NULL if token is not index or index is out of range */ static_inline yyjson_mut_val *ptr_mut_arr_get(yyjson_mut_val *arr, const char *token, usize len, usize esc, yyjson_mut_val **pre, bool *last) { yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; /* last (tail) */ usize num = unsafe_yyjson_get_len(arr), idx; if (last) *last = false; if (pre) *pre = NULL; if (unlikely(num == 0)) { if (last && len == 1 && (*token == '0' || *token == '-')) *last = true; return NULL; } if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL; if (last) *last = (idx == num || idx == USIZE_MAX); if (unlikely(idx >= num)) return NULL; while (idx-- > 0) val = val->next; *pre = val; return val->next; } /** Get a value from object by token. @param obj [in] an object, should not be NULL or non-object type @param token [in] a JSON pointer token @param len [in] unescaped token length @param esc [in] number of escaped characters in this token @param pre [out] previous (sibling) key of the returned value's key @return value associated with the token, or NULL if no value */ static_inline yyjson_mut_val *ptr_mut_obj_get(yyjson_mut_val *obj, const char *token, usize len, usize esc, yyjson_mut_val **pre) { u64 tag = (((u64)len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr, *key; usize num = unsafe_yyjson_get_len(obj); if (pre) *pre = NULL; if (unlikely(num == 0)) return NULL; for (; num > 0; num--, pre_key = key) { key = pre_key->next->next; if (ptr_token_eq(key, tag, token, len, esc)) { *pre = pre_key; return key->next; } } return NULL; } /** Create a string value with JSON pointer token. @param token [in] a JSON pointer token @param len [in] unescaped token length @param esc [in] number of escaped characters in this token @param doc [in] used for memory allocation when creating value @return new string value, or NULL if memory allocation failed */ static_inline yyjson_mut_val *ptr_new_key(const char *token, usize len, usize esc, yyjson_mut_doc *doc) { const char *src = token; if (likely(!esc)) { return yyjson_mut_strncpy(doc, src, len); } else { const char *end = src + len + esc; char *dst = unsafe_yyjson_mut_str_alc(doc, len + esc); char *str = dst; if (unlikely(!dst)) return NULL; for (; src < end; src++, dst++) { if (*src != '~') *dst = *src; else *dst = (*++src == '0' ? '~' : '/'); } *dst = '\0'; return yyjson_mut_strn(doc, str, len); } } /* macros for yyjson_ptr */ #define return_err(_ret, _code, _pos, _msg) do { \ if (err) { \ err->code = YYJSON_PTR_ERR_##_code; \ err->msg = _msg; \ err->pos = (usize)(_pos); \ } \ return _ret; \ } while (false) #define return_err_resolve(_ret, _pos) \ return_err(_ret, RESOLVE, _pos, "JSON pointer cannot be resolved") #define return_err_syntax(_ret, _pos) \ return_err(_ret, SYNTAX, _pos, "invalid escaped character") #define return_err_alloc(_ret) \ return_err(_ret, MEMORY_ALLOCATION, 0, "failed to create value") yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val, const char *ptr, size_t ptr_len, yyjson_ptr_err *err) { const char *hdr = ptr, *end = ptr + ptr_len, *token; usize len, esc; yyjson_type type; while (true) { token = ptr_next_token(&ptr, end, &len, &esc); if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr); type = unsafe_yyjson_get_type(val); if (type == YYJSON_TYPE_OBJ) { val = ptr_obj_get(val, token, len, esc); } else if (type == YYJSON_TYPE_ARR) { val = ptr_arr_get(val, token, len, esc); } else { val = NULL; } if (!val) return_err_resolve(NULL, token - hdr); if (ptr == end) return val; } } yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val, const char *ptr, size_t ptr_len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { const char *hdr = ptr, *end = ptr + ptr_len, *token; usize len, esc; yyjson_mut_val *ctn, *pre = NULL; yyjson_type type; bool idx_is_last = false; while (true) { token = ptr_next_token(&ptr, end, &len, &esc); if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr); ctn = val; type = unsafe_yyjson_get_type(val); if (type == YYJSON_TYPE_OBJ) { val = ptr_mut_obj_get(val, token, len, esc, &pre); } else if (type == YYJSON_TYPE_ARR) { val = ptr_mut_arr_get(val, token, len, esc, &pre, &idx_is_last); } else { val = NULL; } if (ctx && (ptr == end)) { if (type == YYJSON_TYPE_OBJ || (type == YYJSON_TYPE_ARR && (val || idx_is_last))) { ctx->ctn = ctn; ctx->pre = pre; } } if (!val) return_err_resolve(NULL, token - hdr); if (ptr == end) return val; } } bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val, const char *ptr, size_t ptr_len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, bool insert_new, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { const char *hdr = ptr, *end = ptr + ptr_len, *token; usize token_len, esc, ctn_len; yyjson_mut_val *ctn, *key, *pre = NULL; yyjson_mut_val *sep_ctn = NULL, *sep_key = NULL, *sep_val = NULL; yyjson_type ctn_type; bool idx_is_last = false; /* skip exist parent nodes */ while (true) { token = ptr_next_token(&ptr, end, &token_len, &esc); if (unlikely(!token)) return_err_syntax(false, ptr - hdr); ctn = val; ctn_type = unsafe_yyjson_get_type(ctn); if (ctn_type == YYJSON_TYPE_OBJ) { val = ptr_mut_obj_get(ctn, token, token_len, esc, &pre); } else if (ctn_type == YYJSON_TYPE_ARR) { val = ptr_mut_arr_get(ctn, token, token_len, esc, &pre, &idx_is_last); } else return_err_resolve(false, token - hdr); if (!val) break; if (ptr == end) break; /* is last token */ } /* create parent nodes if not exist */ if (unlikely(ptr != end)) { /* not last token */ if (!create_parent) return_err_resolve(false, token - hdr); /* add value at last index if container is array */ if (ctn_type == YYJSON_TYPE_ARR) { if (!idx_is_last || !insert_new) { return_err_resolve(false, token - hdr); } val = yyjson_mut_obj(doc); if (!val) return_err_alloc(false); /* delay attaching until all operations are completed */ sep_ctn = ctn; sep_key = NULL; sep_val = val; /* move to next token */ ctn = val; val = NULL; ctn_type = YYJSON_TYPE_OBJ; token = ptr_next_token(&ptr, end, &token_len, &esc); if (unlikely(!token)) return_err_resolve(false, token - hdr); } /* container is object, create parent nodes */ while (ptr != end) { /* not last token */ key = ptr_new_key(token, token_len, esc, doc); if (!key) return_err_alloc(false); val = yyjson_mut_obj(doc); if (!val) return_err_alloc(false); /* delay attaching until all operations are completed */ if (!sep_ctn) { sep_ctn = ctn; sep_key = key; sep_val = val; } else { yyjson_mut_obj_add(ctn, key, val); } /* move to next token */ ctn = val; val = NULL; token = ptr_next_token(&ptr, end, &token_len, &esc); if (unlikely(!token)) return_err_syntax(false, ptr - hdr); } } /* JSON pointer is resolved, insert or replace target value */ ctn_len = unsafe_yyjson_get_len(ctn); if (ctn_type == YYJSON_TYPE_OBJ) { if (ctx) ctx->ctn = ctn; if (!val || insert_new) { /* insert new key-value pair */ key = ptr_new_key(token, token_len, esc, doc); if (unlikely(!key)) return_err_alloc(false); if (ctx) ctx->pre = ctn_len ? (yyjson_mut_val *)ctn->uni.ptr : key; unsafe_yyjson_mut_obj_add(ctn, key, new_val, ctn_len); } else { /* replace exist value */ key = pre->next->next; if (ctx) ctx->pre = pre; if (ctx) ctx->old = val; yyjson_mut_obj_put(ctn, key, new_val); } } else { /* array */ if (ctx && (val || idx_is_last)) ctx->ctn = ctn; if (insert_new) { /* append new value */ if (val) { pre->next = new_val; new_val->next = val; if (ctx) ctx->pre = pre; unsafe_yyjson_set_len(ctn, ctn_len + 1); } else if (idx_is_last) { if (ctx) ctx->pre = ctn_len ? (yyjson_mut_val *)ctn->uni.ptr : new_val; yyjson_mut_arr_append(ctn, new_val); } else { return_err_resolve(false, token - hdr); } } else { /* replace exist value */ if (!val) return_err_resolve(false, token - hdr); if (ctn_len > 1) { new_val->next = val->next; pre->next = new_val; if (ctn->uni.ptr == val) ctn->uni.ptr = new_val; } else { new_val->next = new_val; ctn->uni.ptr = new_val; pre = new_val; } if (ctx) ctx->pre = pre; if (ctx) ctx->old = val; } } /* all operations are completed, attach the new components to the target */ if (unlikely(sep_ctn)) { if (sep_key) yyjson_mut_obj_add(sep_ctn, sep_key, sep_val); else yyjson_mut_arr_append(sep_ctn, sep_val); } return true; } yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_mut_val *cur_val; yyjson_ptr_ctx cur_ctx; memset(&cur_ctx, 0, sizeof(cur_ctx)); if (!ctx) ctx = &cur_ctx; cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); if (!cur_val) return NULL; if (yyjson_mut_is_obj(ctx->ctn)) { yyjson_mut_val *key = ctx->pre->next->next; yyjson_mut_obj_put(ctx->ctn, key, new_val); } else { yyjson_ptr_ctx_replace(ctx, new_val); } ctx->old = cur_val; return cur_val; } yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_mut_val *cur_val; yyjson_ptr_ctx cur_ctx; memset(&cur_ctx, 0, sizeof(cur_ctx)); if (!ctx) ctx = &cur_ctx; cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); if (cur_val) { if (yyjson_mut_is_obj(ctx->ctn)) { yyjson_mut_val *key = ctx->pre->next->next; yyjson_mut_obj_put(ctx->ctn, key, NULL); } else { yyjson_ptr_ctx_remove(ctx); } ctx->pre = NULL; ctx->old = cur_val; } return cur_val; } /* macros for yyjson_ptr */ #undef return_err #undef return_err_resolve #undef return_err_syntax #undef return_err_alloc /*============================================================================== * JSON Patch API (RFC 6902) *============================================================================*/ /* JSON Patch operation */ typedef enum patch_op { PATCH_OP_ADD, /* path, value */ PATCH_OP_REMOVE, /* path */ PATCH_OP_REPLACE, /* path, value */ PATCH_OP_MOVE, /* from, path */ PATCH_OP_COPY, /* from, path */ PATCH_OP_TEST, /* path, value */ PATCH_OP_NONE /* invalid */ } patch_op; static patch_op patch_op_get(yyjson_val *op) { const char *str = op->uni.str; switch (unsafe_yyjson_get_len(op)) { case 3: if (!memcmp(str, "add", 3)) return PATCH_OP_ADD; return PATCH_OP_NONE; case 4: if (!memcmp(str, "move", 4)) return PATCH_OP_MOVE; if (!memcmp(str, "copy", 4)) return PATCH_OP_COPY; if (!memcmp(str, "test", 4)) return PATCH_OP_TEST; return PATCH_OP_NONE; case 6: if (!memcmp(str, "remove", 6)) return PATCH_OP_REMOVE; return PATCH_OP_NONE; case 7: if (!memcmp(str, "replace", 7)) return PATCH_OP_REPLACE; return PATCH_OP_NONE; default: return PATCH_OP_NONE; } } /* macros for yyjson_patch */ #define return_err(_code, _msg) do { \ if (err->ptr.code == YYJSON_PTR_ERR_MEMORY_ALLOCATION) { \ err->code = YYJSON_PATCH_ERROR_MEMORY_ALLOCATION; \ err->msg = _msg; \ memset(&err->ptr, 0, sizeof(yyjson_ptr_err)); \ } else { \ err->code = YYJSON_PATCH_ERROR_##_code; \ err->msg = _msg; \ err->idx = iter.idx ? iter.idx - 1 : 0; \ } \ return NULL; \ } while (false) #define return_err_copy() \ return_err(MEMORY_ALLOCATION, "failed to copy value") #define return_err_key(_key) \ return_err(MISSING_KEY, "missing key " _key) #define return_err_val(_key) \ return_err(INVALID_MEMBER, "invalid member " _key) #define ptr_get(_ptr) yyjson_mut_ptr_getx( \ root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr) #define ptr_add(_ptr, _val) yyjson_mut_ptr_addx( \ root, _ptr->uni.str, _ptr##_len, _val, doc, false, NULL, &err->ptr) #define ptr_remove(_ptr) yyjson_mut_ptr_removex( \ root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr) #define ptr_replace(_ptr, _val)yyjson_mut_ptr_replacex( \ root, _ptr->uni.str, _ptr##_len, _val, NULL, &err->ptr) yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch, yyjson_patch_err *err) { yyjson_mut_val *root; yyjson_val *obj; yyjson_arr_iter iter; yyjson_patch_err err_tmp; if (!err) err = &err_tmp; memset(err, 0, sizeof(*err)); memset(&iter, 0, sizeof(iter)); if (unlikely(!doc || !orig || !patch)) { return_err(INVALID_PARAMETER, "input parameter is NULL"); } if (unlikely(!yyjson_is_arr(patch))) { return_err(INVALID_PARAMETER, "input patch is not array"); } root = yyjson_val_mut_copy(doc, orig); if (unlikely(!root)) return_err_copy(); /* iterate through the patch array */ yyjson_arr_iter_init(patch, &iter); while ((obj = yyjson_arr_iter_next(&iter))) { patch_op op_enum; yyjson_val *op, *path, *from = NULL, *value; yyjson_mut_val *val = NULL, *test; usize path_len, from_len = 0; if (unlikely(!unsafe_yyjson_is_obj(obj))) { return_err(INVALID_OPERATION, "JSON patch operation is not object"); } /* get required member: op */ op = yyjson_obj_get(obj, "op"); if (unlikely(!op)) return_err_key("`op`"); if (unlikely(!yyjson_is_str(op))) return_err_val("`op`"); op_enum = patch_op_get(op); /* get required member: path */ path = yyjson_obj_get(obj, "path"); if (unlikely(!path)) return_err_key("`path`"); if (unlikely(!yyjson_is_str(path))) return_err_val("`path`"); path_len = unsafe_yyjson_get_len(path); /* get required member: value, from */ switch (op_enum) { case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST: value = yyjson_obj_get(obj, "value"); if (unlikely(!value)) return_err_key("`value`"); val = yyjson_val_mut_copy(doc, value); if (unlikely(!val)) return_err_copy(); break; case PATCH_OP_MOVE: case PATCH_OP_COPY: from = yyjson_obj_get(obj, "from"); if (unlikely(!from)) return_err_key("`from`"); if (unlikely(!yyjson_is_str(from))) return_err_val("`from`"); from_len = unsafe_yyjson_get_len(from); break; default: break; } /* perform an operation */ switch (op_enum) { case PATCH_OP_ADD: /* add(path, val) */ if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_REMOVE: /* remove(path) */ if (unlikely(!ptr_remove(path))) { return_err(POINTER, "failed to remove `path`"); } break; case PATCH_OP_REPLACE: /* replace(path, val) */ if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_replace(path, val))) { return_err(POINTER, "failed to replace `path`"); } break; case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */ if (unlikely(from_len == 0 && path_len == 0)) break; val = ptr_remove(from); if (unlikely(!val)) { return_err(POINTER, "failed to remove `from`"); } if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */ val = ptr_get(from); if (unlikely(!val)) { return_err(POINTER, "failed to get `from`"); } if (unlikely(path_len == 0)) { root = val; break; } val = yyjson_mut_val_mut_copy(doc, val); if (unlikely(!val)) return_err_copy(); if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_TEST: /* test = get(path), test.eq(val) */ test = ptr_get(path); if (unlikely(!test)) { return_err(POINTER, "failed to get `path`"); } if (unlikely(!yyjson_mut_equals(val, test))) { return_err(EQUAL, "failed to test equal"); } break; default: return_err(INVALID_MEMBER, "unsupported `op`"); } } return root; } yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch, yyjson_patch_err *err) { yyjson_mut_val *root, *obj; yyjson_mut_arr_iter iter; yyjson_patch_err err_tmp; if (!err) err = &err_tmp; memset(err, 0, sizeof(*err)); memset(&iter, 0, sizeof(iter)); if (unlikely(!doc || !orig || !patch)) { return_err(INVALID_PARAMETER, "input parameter is NULL"); } if (unlikely(!yyjson_mut_is_arr(patch))) { return_err(INVALID_PARAMETER, "input patch is not array"); } root = yyjson_mut_val_mut_copy(doc, orig); if (unlikely(!root)) return_err_copy(); /* iterate through the patch array */ yyjson_mut_arr_iter_init(patch, &iter); while ((obj = yyjson_mut_arr_iter_next(&iter))) { patch_op op_enum; yyjson_mut_val *op, *path, *from = NULL, *value; yyjson_mut_val *val = NULL, *test; usize path_len, from_len = 0; if (!unsafe_yyjson_is_obj(obj)) { return_err(INVALID_OPERATION, "JSON patch operation is not object"); } /* get required member: op */ op = yyjson_mut_obj_get(obj, "op"); if (unlikely(!op)) return_err_key("`op`"); if (unlikely(!yyjson_mut_is_str(op))) return_err_val("`op`"); op_enum = patch_op_get((yyjson_val *)(void *)op); /* get required member: path */ path = yyjson_mut_obj_get(obj, "path"); if (unlikely(!path)) return_err_key("`path`"); if (unlikely(!yyjson_mut_is_str(path))) return_err_val("`path`"); path_len = unsafe_yyjson_get_len(path); /* get required member: value, from */ switch (op_enum) { case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST: value = yyjson_mut_obj_get(obj, "value"); if (unlikely(!value)) return_err_key("`value`"); val = yyjson_mut_val_mut_copy(doc, value); if (unlikely(!val)) return_err_copy(); break; case PATCH_OP_MOVE: case PATCH_OP_COPY: from = yyjson_mut_obj_get(obj, "from"); if (unlikely(!from)) return_err_key("`from`"); if (unlikely(!yyjson_mut_is_str(from))) { return_err_val("`from`"); } from_len = unsafe_yyjson_get_len(from); break; default: break; } /* perform an operation */ switch (op_enum) { case PATCH_OP_ADD: /* add(path, val) */ if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_REMOVE: /* remove(path) */ if (unlikely(!ptr_remove(path))) { return_err(POINTER, "failed to remove `path`"); } break; case PATCH_OP_REPLACE: /* replace(path, val) */ if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_replace(path, val))) { return_err(POINTER, "failed to replace `path`"); } break; case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */ if (unlikely(from_len == 0 && path_len == 0)) break; val = ptr_remove(from); if (unlikely(!val)) { return_err(POINTER, "failed to remove `from`"); } if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */ val = ptr_get(from); if (unlikely(!val)) { return_err(POINTER, "failed to get `from`"); } if (unlikely(path_len == 0)) { root = val; break; } val = yyjson_mut_val_mut_copy(doc, val); if (unlikely(!val)) return_err_copy(); if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_TEST: /* test = get(path), test.eq(val) */ test = ptr_get(path); if (unlikely(!test)) { return_err(POINTER, "failed to get `path`"); } if (unlikely(!yyjson_mut_equals(val, test))) { return_err(EQUAL, "failed to test equal"); } break; default: return_err(INVALID_MEMBER, "unsupported `op`"); } } return root; } /* macros for yyjson_patch */ #undef return_err #undef return_err_copy #undef return_err_key #undef return_err_val #undef ptr_get #undef ptr_add #undef ptr_remove #undef ptr_replace /*============================================================================== * JSON Merge-Patch API (RFC 7386) *============================================================================*/ yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch) { usize idx, max; yyjson_val *key, *orig_val, *patch_val, local_orig; yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val; if (unlikely(!yyjson_is_obj(patch))) { return yyjson_val_mut_copy(doc, patch); } builder = yyjson_mut_obj(doc); if (unlikely(!builder)) return NULL; if (!yyjson_is_obj(orig)) { orig = &local_orig; orig->tag = builder->tag; orig->uni = builder->uni; } /* If orig is contributing, copy any items not modified by the patch */ if (orig != &local_orig) { yyjson_obj_foreach(orig, idx, max, key, orig_val) { patch_val = yyjson_obj_getn(patch, unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); if (!patch_val) { mut_key = yyjson_val_mut_copy(doc, key); mut_val = yyjson_val_mut_copy(doc, orig_val); if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; } } } /* Merge items modified by the patch. */ yyjson_obj_foreach(patch, idx, max, key, patch_val) { /* null indicates the field is removed. */ if (unsafe_yyjson_is_null(patch_val)) { continue; } mut_key = yyjson_val_mut_copy(doc, key); orig_val = yyjson_obj_getn(orig, unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); merged_val = yyjson_merge_patch(doc, orig_val, patch_val); if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL; } return builder; } yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch) { usize idx, max; yyjson_mut_val *key, *orig_val, *patch_val, local_orig; yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val; if (unlikely(!yyjson_mut_is_obj(patch))) { return yyjson_mut_val_mut_copy(doc, patch); } builder = yyjson_mut_obj(doc); if (unlikely(!builder)) return NULL; if (!yyjson_mut_is_obj(orig)) { orig = &local_orig; orig->tag = builder->tag; orig->uni = builder->uni; } /* If orig is contributing, copy any items not modified by the patch */ if (orig != &local_orig) { yyjson_mut_obj_foreach(orig, idx, max, key, orig_val) { patch_val = yyjson_mut_obj_getn(patch, unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); if (!patch_val) { mut_key = yyjson_mut_val_mut_copy(doc, key); mut_val = yyjson_mut_val_mut_copy(doc, orig_val); if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; } } } /* Merge items modified by the patch. */ yyjson_mut_obj_foreach(patch, idx, max, key, patch_val) { /* null indicates the field is removed. */ if (unsafe_yyjson_is_null(patch_val)) { continue; } mut_key = yyjson_mut_val_mut_copy(doc, key); orig_val = yyjson_mut_obj_getn(orig, unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); merged_val = yyjson_mut_merge_patch(doc, orig_val, patch_val); if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL; } return builder; } #endif /* YYJSON_DISABLE_UTILS */ /*============================================================================== * Power10 Lookup Table * These data are used by the floating-point number reader and writer. *============================================================================*/ #if (!YYJSON_DISABLE_READER || !YYJSON_DISABLE_WRITER) && \ (!YYJSON_DISABLE_FAST_FP_CONV) /** Minimum decimal exponent in pow10_sig_table. */ #define POW10_SIG_TABLE_MIN_EXP -343 /** Maximum decimal exponent in pow10_sig_table. */ #define POW10_SIG_TABLE_MAX_EXP 324 /** Minimum exact decimal exponent in pow10_sig_table */ #define POW10_SIG_TABLE_MIN_EXACT_EXP 0 /** Maximum exact decimal exponent in pow10_sig_table */ #define POW10_SIG_TABLE_MAX_EXACT_EXP 55 /** Normalized significant 128 bits of pow10, no rounded up (size: 10.4KB). This lookup table is used by both the double number reader and writer. (generate with misc/make_tables.c) */ static const u64 pow10_sig_table[] = { U64(0xBF29DCAB, 0xA82FDEAE), U64(0x7432EE87, 0x3880FC33), /* ~= 10^-343 */ U64(0xEEF453D6, 0x923BD65A), U64(0x113FAA29, 0x06A13B3F), /* ~= 10^-342 */ U64(0x9558B466, 0x1B6565F8), U64(0x4AC7CA59, 0xA424C507), /* ~= 10^-341 */ U64(0xBAAEE17F, 0xA23EBF76), U64(0x5D79BCF0, 0x0D2DF649), /* ~= 10^-340 */ U64(0xE95A99DF, 0x8ACE6F53), U64(0xF4D82C2C, 0x107973DC), /* ~= 10^-339 */ U64(0x91D8A02B, 0xB6C10594), U64(0x79071B9B, 0x8A4BE869), /* ~= 10^-338 */ U64(0xB64EC836, 0xA47146F9), U64(0x9748E282, 0x6CDEE284), /* ~= 10^-337 */ U64(0xE3E27A44, 0x4D8D98B7), U64(0xFD1B1B23, 0x08169B25), /* ~= 10^-336 */ U64(0x8E6D8C6A, 0xB0787F72), U64(0xFE30F0F5, 0xE50E20F7), /* ~= 10^-335 */ U64(0xB208EF85, 0x5C969F4F), U64(0xBDBD2D33, 0x5E51A935), /* ~= 10^-334 */ U64(0xDE8B2B66, 0xB3BC4723), U64(0xAD2C7880, 0x35E61382), /* ~= 10^-333 */ U64(0x8B16FB20, 0x3055AC76), U64(0x4C3BCB50, 0x21AFCC31), /* ~= 10^-332 */ U64(0xADDCB9E8, 0x3C6B1793), U64(0xDF4ABE24, 0x2A1BBF3D), /* ~= 10^-331 */ U64(0xD953E862, 0x4B85DD78), U64(0xD71D6DAD, 0x34A2AF0D), /* ~= 10^-330 */ U64(0x87D4713D, 0x6F33AA6B), U64(0x8672648C, 0x40E5AD68), /* ~= 10^-329 */ U64(0xA9C98D8C, 0xCB009506), U64(0x680EFDAF, 0x511F18C2), /* ~= 10^-328 */ U64(0xD43BF0EF, 0xFDC0BA48), U64(0x0212BD1B, 0x2566DEF2), /* ~= 10^-327 */ U64(0x84A57695, 0xFE98746D), U64(0x014BB630, 0xF7604B57), /* ~= 10^-326 */ U64(0xA5CED43B, 0x7E3E9188), U64(0x419EA3BD, 0x35385E2D), /* ~= 10^-325 */ U64(0xCF42894A, 0x5DCE35EA), U64(0x52064CAC, 0x828675B9), /* ~= 10^-324 */ U64(0x818995CE, 0x7AA0E1B2), U64(0x7343EFEB, 0xD1940993), /* ~= 10^-323 */ U64(0xA1EBFB42, 0x19491A1F), U64(0x1014EBE6, 0xC5F90BF8), /* ~= 10^-322 */ U64(0xCA66FA12, 0x9F9B60A6), U64(0xD41A26E0, 0x77774EF6), /* ~= 10^-321 */ U64(0xFD00B897, 0x478238D0), U64(0x8920B098, 0x955522B4), /* ~= 10^-320 */ U64(0x9E20735E, 0x8CB16382), U64(0x55B46E5F, 0x5D5535B0), /* ~= 10^-319 */ U64(0xC5A89036, 0x2FDDBC62), U64(0xEB2189F7, 0x34AA831D), /* ~= 10^-318 */ U64(0xF712B443, 0xBBD52B7B), U64(0xA5E9EC75, 0x01D523E4), /* ~= 10^-317 */ U64(0x9A6BB0AA, 0x55653B2D), U64(0x47B233C9, 0x2125366E), /* ~= 10^-316 */ U64(0xC1069CD4, 0xEABE89F8), U64(0x999EC0BB, 0x696E840A), /* ~= 10^-315 */ U64(0xF148440A, 0x256E2C76), U64(0xC00670EA, 0x43CA250D), /* ~= 10^-314 */ U64(0x96CD2A86, 0x5764DBCA), U64(0x38040692, 0x6A5E5728), /* ~= 10^-313 */ U64(0xBC807527, 0xED3E12BC), U64(0xC6050837, 0x04F5ECF2), /* ~= 10^-312 */ U64(0xEBA09271, 0xE88D976B), U64(0xF7864A44, 0xC633682E), /* ~= 10^-311 */ U64(0x93445B87, 0x31587EA3), U64(0x7AB3EE6A, 0xFBE0211D), /* ~= 10^-310 */ U64(0xB8157268, 0xFDAE9E4C), U64(0x5960EA05, 0xBAD82964), /* ~= 10^-309 */ U64(0xE61ACF03, 0x3D1A45DF), U64(0x6FB92487, 0x298E33BD), /* ~= 10^-308 */ U64(0x8FD0C162, 0x06306BAB), U64(0xA5D3B6D4, 0x79F8E056), /* ~= 10^-307 */ U64(0xB3C4F1BA, 0x87BC8696), U64(0x8F48A489, 0x9877186C), /* ~= 10^-306 */ U64(0xE0B62E29, 0x29ABA83C), U64(0x331ACDAB, 0xFE94DE87), /* ~= 10^-305 */ U64(0x8C71DCD9, 0xBA0B4925), U64(0x9FF0C08B, 0x7F1D0B14), /* ~= 10^-304 */ U64(0xAF8E5410, 0x288E1B6F), U64(0x07ECF0AE, 0x5EE44DD9), /* ~= 10^-303 */ U64(0xDB71E914, 0x32B1A24A), U64(0xC9E82CD9, 0xF69D6150), /* ~= 10^-302 */ U64(0x892731AC, 0x9FAF056E), U64(0xBE311C08, 0x3A225CD2), /* ~= 10^-301 */ U64(0xAB70FE17, 0xC79AC6CA), U64(0x6DBD630A, 0x48AAF406), /* ~= 10^-300 */ U64(0xD64D3D9D, 0xB981787D), U64(0x092CBBCC, 0xDAD5B108), /* ~= 10^-299 */ U64(0x85F04682, 0x93F0EB4E), U64(0x25BBF560, 0x08C58EA5), /* ~= 10^-298 */ U64(0xA76C5823, 0x38ED2621), U64(0xAF2AF2B8, 0x0AF6F24E), /* ~= 10^-297 */ U64(0xD1476E2C, 0x07286FAA), U64(0x1AF5AF66, 0x0DB4AEE1), /* ~= 10^-296 */ U64(0x82CCA4DB, 0x847945CA), U64(0x50D98D9F, 0xC890ED4D), /* ~= 10^-295 */ U64(0xA37FCE12, 0x6597973C), U64(0xE50FF107, 0xBAB528A0), /* ~= 10^-294 */ U64(0xCC5FC196, 0xFEFD7D0C), U64(0x1E53ED49, 0xA96272C8), /* ~= 10^-293 */ U64(0xFF77B1FC, 0xBEBCDC4F), U64(0x25E8E89C, 0x13BB0F7A), /* ~= 10^-292 */ U64(0x9FAACF3D, 0xF73609B1), U64(0x77B19161, 0x8C54E9AC), /* ~= 10^-291 */ U64(0xC795830D, 0x75038C1D), U64(0xD59DF5B9, 0xEF6A2417), /* ~= 10^-290 */ U64(0xF97AE3D0, 0xD2446F25), U64(0x4B057328, 0x6B44AD1D), /* ~= 10^-289 */ U64(0x9BECCE62, 0x836AC577), U64(0x4EE367F9, 0x430AEC32), /* ~= 10^-288 */ U64(0xC2E801FB, 0x244576D5), U64(0x229C41F7, 0x93CDA73F), /* ~= 10^-287 */ U64(0xF3A20279, 0xED56D48A), U64(0x6B435275, 0x78C1110F), /* ~= 10^-286 */ U64(0x9845418C, 0x345644D6), U64(0x830A1389, 0x6B78AAA9), /* ~= 10^-285 */ U64(0xBE5691EF, 0x416BD60C), U64(0x23CC986B, 0xC656D553), /* ~= 10^-284 */ U64(0xEDEC366B, 0x11C6CB8F), U64(0x2CBFBE86, 0xB7EC8AA8), /* ~= 10^-283 */ U64(0x94B3A202, 0xEB1C3F39), U64(0x7BF7D714, 0x32F3D6A9), /* ~= 10^-282 */ U64(0xB9E08A83, 0xA5E34F07), U64(0xDAF5CCD9, 0x3FB0CC53), /* ~= 10^-281 */ U64(0xE858AD24, 0x8F5C22C9), U64(0xD1B3400F, 0x8F9CFF68), /* ~= 10^-280 */ U64(0x91376C36, 0xD99995BE), U64(0x23100809, 0xB9C21FA1), /* ~= 10^-279 */ U64(0xB5854744, 0x8FFFFB2D), U64(0xABD40A0C, 0x2832A78A), /* ~= 10^-278 */ U64(0xE2E69915, 0xB3FFF9F9), U64(0x16C90C8F, 0x323F516C), /* ~= 10^-277 */ U64(0x8DD01FAD, 0x907FFC3B), U64(0xAE3DA7D9, 0x7F6792E3), /* ~= 10^-276 */ U64(0xB1442798, 0xF49FFB4A), U64(0x99CD11CF, 0xDF41779C), /* ~= 10^-275 */ U64(0xDD95317F, 0x31C7FA1D), U64(0x40405643, 0xD711D583), /* ~= 10^-274 */ U64(0x8A7D3EEF, 0x7F1CFC52), U64(0x482835EA, 0x666B2572), /* ~= 10^-273 */ U64(0xAD1C8EAB, 0x5EE43B66), U64(0xDA324365, 0x0005EECF), /* ~= 10^-272 */ U64(0xD863B256, 0x369D4A40), U64(0x90BED43E, 0x40076A82), /* ~= 10^-271 */ U64(0x873E4F75, 0xE2224E68), U64(0x5A7744A6, 0xE804A291), /* ~= 10^-270 */ U64(0xA90DE353, 0x5AAAE202), U64(0x711515D0, 0xA205CB36), /* ~= 10^-269 */ U64(0xD3515C28, 0x31559A83), U64(0x0D5A5B44, 0xCA873E03), /* ~= 10^-268 */ U64(0x8412D999, 0x1ED58091), U64(0xE858790A, 0xFE9486C2), /* ~= 10^-267 */ U64(0xA5178FFF, 0x668AE0B6), U64(0x626E974D, 0xBE39A872), /* ~= 10^-266 */ U64(0xCE5D73FF, 0x402D98E3), U64(0xFB0A3D21, 0x2DC8128F), /* ~= 10^-265 */ U64(0x80FA687F, 0x881C7F8E), U64(0x7CE66634, 0xBC9D0B99), /* ~= 10^-264 */ U64(0xA139029F, 0x6A239F72), U64(0x1C1FFFC1, 0xEBC44E80), /* ~= 10^-263 */ U64(0xC9874347, 0x44AC874E), U64(0xA327FFB2, 0x66B56220), /* ~= 10^-262 */ U64(0xFBE91419, 0x15D7A922), U64(0x4BF1FF9F, 0x0062BAA8), /* ~= 10^-261 */ U64(0x9D71AC8F, 0xADA6C9B5), U64(0x6F773FC3, 0x603DB4A9), /* ~= 10^-260 */ U64(0xC4CE17B3, 0x99107C22), U64(0xCB550FB4, 0x384D21D3), /* ~= 10^-259 */ U64(0xF6019DA0, 0x7F549B2B), U64(0x7E2A53A1, 0x46606A48), /* ~= 10^-258 */ U64(0x99C10284, 0x4F94E0FB), U64(0x2EDA7444, 0xCBFC426D), /* ~= 10^-257 */ U64(0xC0314325, 0x637A1939), U64(0xFA911155, 0xFEFB5308), /* ~= 10^-256 */ U64(0xF03D93EE, 0xBC589F88), U64(0x793555AB, 0x7EBA27CA), /* ~= 10^-255 */ U64(0x96267C75, 0x35B763B5), U64(0x4BC1558B, 0x2F3458DE), /* ~= 10^-254 */ U64(0xBBB01B92, 0x83253CA2), U64(0x9EB1AAED, 0xFB016F16), /* ~= 10^-253 */ U64(0xEA9C2277, 0x23EE8BCB), U64(0x465E15A9, 0x79C1CADC), /* ~= 10^-252 */ U64(0x92A1958A, 0x7675175F), U64(0x0BFACD89, 0xEC191EC9), /* ~= 10^-251 */ U64(0xB749FAED, 0x14125D36), U64(0xCEF980EC, 0x671F667B), /* ~= 10^-250 */ U64(0xE51C79A8, 0x5916F484), U64(0x82B7E127, 0x80E7401A), /* ~= 10^-249 */ U64(0x8F31CC09, 0x37AE58D2), U64(0xD1B2ECB8, 0xB0908810), /* ~= 10^-248 */ U64(0xB2FE3F0B, 0x8599EF07), U64(0x861FA7E6, 0xDCB4AA15), /* ~= 10^-247 */ U64(0xDFBDCECE, 0x67006AC9), U64(0x67A791E0, 0x93E1D49A), /* ~= 10^-246 */ U64(0x8BD6A141, 0x006042BD), U64(0xE0C8BB2C, 0x5C6D24E0), /* ~= 10^-245 */ U64(0xAECC4991, 0x4078536D), U64(0x58FAE9F7, 0x73886E18), /* ~= 10^-244 */ U64(0xDA7F5BF5, 0x90966848), U64(0xAF39A475, 0x506A899E), /* ~= 10^-243 */ U64(0x888F9979, 0x7A5E012D), U64(0x6D8406C9, 0x52429603), /* ~= 10^-242 */ U64(0xAAB37FD7, 0xD8F58178), U64(0xC8E5087B, 0xA6D33B83), /* ~= 10^-241 */ U64(0xD5605FCD, 0xCF32E1D6), U64(0xFB1E4A9A, 0x90880A64), /* ~= 10^-240 */ U64(0x855C3BE0, 0xA17FCD26), U64(0x5CF2EEA0, 0x9A55067F), /* ~= 10^-239 */ U64(0xA6B34AD8, 0xC9DFC06F), U64(0xF42FAA48, 0xC0EA481E), /* ~= 10^-238 */ U64(0xD0601D8E, 0xFC57B08B), U64(0xF13B94DA, 0xF124DA26), /* ~= 10^-237 */ U64(0x823C1279, 0x5DB6CE57), U64(0x76C53D08, 0xD6B70858), /* ~= 10^-236 */ U64(0xA2CB1717, 0xB52481ED), U64(0x54768C4B, 0x0C64CA6E), /* ~= 10^-235 */ U64(0xCB7DDCDD, 0xA26DA268), U64(0xA9942F5D, 0xCF7DFD09), /* ~= 10^-234 */ U64(0xFE5D5415, 0x0B090B02), U64(0xD3F93B35, 0x435D7C4C), /* ~= 10^-233 */ U64(0x9EFA548D, 0x26E5A6E1), U64(0xC47BC501, 0x4A1A6DAF), /* ~= 10^-232 */ U64(0xC6B8E9B0, 0x709F109A), U64(0x359AB641, 0x9CA1091B), /* ~= 10^-231 */ U64(0xF867241C, 0x8CC6D4C0), U64(0xC30163D2, 0x03C94B62), /* ~= 10^-230 */ U64(0x9B407691, 0xD7FC44F8), U64(0x79E0DE63, 0x425DCF1D), /* ~= 10^-229 */ U64(0xC2109436, 0x4DFB5636), U64(0x985915FC, 0x12F542E4), /* ~= 10^-228 */ U64(0xF294B943, 0xE17A2BC4), U64(0x3E6F5B7B, 0x17B2939D), /* ~= 10^-227 */ U64(0x979CF3CA, 0x6CEC5B5A), U64(0xA705992C, 0xEECF9C42), /* ~= 10^-226 */ U64(0xBD8430BD, 0x08277231), U64(0x50C6FF78, 0x2A838353), /* ~= 10^-225 */ U64(0xECE53CEC, 0x4A314EBD), U64(0xA4F8BF56, 0x35246428), /* ~= 10^-224 */ U64(0x940F4613, 0xAE5ED136), U64(0x871B7795, 0xE136BE99), /* ~= 10^-223 */ U64(0xB9131798, 0x99F68584), U64(0x28E2557B, 0x59846E3F), /* ~= 10^-222 */ U64(0xE757DD7E, 0xC07426E5), U64(0x331AEADA, 0x2FE589CF), /* ~= 10^-221 */ U64(0x9096EA6F, 0x3848984F), U64(0x3FF0D2C8, 0x5DEF7621), /* ~= 10^-220 */ U64(0xB4BCA50B, 0x065ABE63), U64(0x0FED077A, 0x756B53A9), /* ~= 10^-219 */ U64(0xE1EBCE4D, 0xC7F16DFB), U64(0xD3E84959, 0x12C62894), /* ~= 10^-218 */ U64(0x8D3360F0, 0x9CF6E4BD), U64(0x64712DD7, 0xABBBD95C), /* ~= 10^-217 */ U64(0xB080392C, 0xC4349DEC), U64(0xBD8D794D, 0x96AACFB3), /* ~= 10^-216 */ U64(0xDCA04777, 0xF541C567), U64(0xECF0D7A0, 0xFC5583A0), /* ~= 10^-215 */ U64(0x89E42CAA, 0xF9491B60), U64(0xF41686C4, 0x9DB57244), /* ~= 10^-214 */ U64(0xAC5D37D5, 0xB79B6239), U64(0x311C2875, 0xC522CED5), /* ~= 10^-213 */ U64(0xD77485CB, 0x25823AC7), U64(0x7D633293, 0x366B828B), /* ~= 10^-212 */ U64(0x86A8D39E, 0xF77164BC), U64(0xAE5DFF9C, 0x02033197), /* ~= 10^-211 */ U64(0xA8530886, 0xB54DBDEB), U64(0xD9F57F83, 0x0283FDFC), /* ~= 10^-210 */ U64(0xD267CAA8, 0x62A12D66), U64(0xD072DF63, 0xC324FD7B), /* ~= 10^-209 */ U64(0x8380DEA9, 0x3DA4BC60), U64(0x4247CB9E, 0x59F71E6D), /* ~= 10^-208 */ U64(0xA4611653, 0x8D0DEB78), U64(0x52D9BE85, 0xF074E608), /* ~= 10^-207 */ U64(0xCD795BE8, 0x70516656), U64(0x67902E27, 0x6C921F8B), /* ~= 10^-206 */ U64(0x806BD971, 0x4632DFF6), U64(0x00BA1CD8, 0xA3DB53B6), /* ~= 10^-205 */ U64(0xA086CFCD, 0x97BF97F3), U64(0x80E8A40E, 0xCCD228A4), /* ~= 10^-204 */ U64(0xC8A883C0, 0xFDAF7DF0), U64(0x6122CD12, 0x8006B2CD), /* ~= 10^-203 */ U64(0xFAD2A4B1, 0x3D1B5D6C), U64(0x796B8057, 0x20085F81), /* ~= 10^-202 */ U64(0x9CC3A6EE, 0xC6311A63), U64(0xCBE33036, 0x74053BB0), /* ~= 10^-201 */ U64(0xC3F490AA, 0x77BD60FC), U64(0xBEDBFC44, 0x11068A9C), /* ~= 10^-200 */ U64(0xF4F1B4D5, 0x15ACB93B), U64(0xEE92FB55, 0x15482D44), /* ~= 10^-199 */ U64(0x99171105, 0x2D8BF3C5), U64(0x751BDD15, 0x2D4D1C4A), /* ~= 10^-198 */ U64(0xBF5CD546, 0x78EEF0B6), U64(0xD262D45A, 0x78A0635D), /* ~= 10^-197 */ U64(0xEF340A98, 0x172AACE4), U64(0x86FB8971, 0x16C87C34), /* ~= 10^-196 */ U64(0x9580869F, 0x0E7AAC0E), U64(0xD45D35E6, 0xAE3D4DA0), /* ~= 10^-195 */ U64(0xBAE0A846, 0xD2195712), U64(0x89748360, 0x59CCA109), /* ~= 10^-194 */ U64(0xE998D258, 0x869FACD7), U64(0x2BD1A438, 0x703FC94B), /* ~= 10^-193 */ U64(0x91FF8377, 0x5423CC06), U64(0x7B6306A3, 0x4627DDCF), /* ~= 10^-192 */ U64(0xB67F6455, 0x292CBF08), U64(0x1A3BC84C, 0x17B1D542), /* ~= 10^-191 */ U64(0xE41F3D6A, 0x7377EECA), U64(0x20CABA5F, 0x1D9E4A93), /* ~= 10^-190 */ U64(0x8E938662, 0x882AF53E), U64(0x547EB47B, 0x7282EE9C), /* ~= 10^-189 */ U64(0xB23867FB, 0x2A35B28D), U64(0xE99E619A, 0x4F23AA43), /* ~= 10^-188 */ U64(0xDEC681F9, 0xF4C31F31), U64(0x6405FA00, 0xE2EC94D4), /* ~= 10^-187 */ U64(0x8B3C113C, 0x38F9F37E), U64(0xDE83BC40, 0x8DD3DD04), /* ~= 10^-186 */ U64(0xAE0B158B, 0x4738705E), U64(0x9624AB50, 0xB148D445), /* ~= 10^-185 */ U64(0xD98DDAEE, 0x19068C76), U64(0x3BADD624, 0xDD9B0957), /* ~= 10^-184 */ U64(0x87F8A8D4, 0xCFA417C9), U64(0xE54CA5D7, 0x0A80E5D6), /* ~= 10^-183 */ U64(0xA9F6D30A, 0x038D1DBC), U64(0x5E9FCF4C, 0xCD211F4C), /* ~= 10^-182 */ U64(0xD47487CC, 0x8470652B), U64(0x7647C320, 0x0069671F), /* ~= 10^-181 */ U64(0x84C8D4DF, 0xD2C63F3B), U64(0x29ECD9F4, 0x0041E073), /* ~= 10^-180 */ U64(0xA5FB0A17, 0xC777CF09), U64(0xF4681071, 0x00525890), /* ~= 10^-179 */ U64(0xCF79CC9D, 0xB955C2CC), U64(0x7182148D, 0x4066EEB4), /* ~= 10^-178 */ U64(0x81AC1FE2, 0x93D599BF), U64(0xC6F14CD8, 0x48405530), /* ~= 10^-177 */ U64(0xA21727DB, 0x38CB002F), U64(0xB8ADA00E, 0x5A506A7C), /* ~= 10^-176 */ U64(0xCA9CF1D2, 0x06FDC03B), U64(0xA6D90811, 0xF0E4851C), /* ~= 10^-175 */ U64(0xFD442E46, 0x88BD304A), U64(0x908F4A16, 0x6D1DA663), /* ~= 10^-174 */ U64(0x9E4A9CEC, 0x15763E2E), U64(0x9A598E4E, 0x043287FE), /* ~= 10^-173 */ U64(0xC5DD4427, 0x1AD3CDBA), U64(0x40EFF1E1, 0x853F29FD), /* ~= 10^-172 */ U64(0xF7549530, 0xE188C128), U64(0xD12BEE59, 0xE68EF47C), /* ~= 10^-171 */ U64(0x9A94DD3E, 0x8CF578B9), U64(0x82BB74F8, 0x301958CE), /* ~= 10^-170 */ U64(0xC13A148E, 0x3032D6E7), U64(0xE36A5236, 0x3C1FAF01), /* ~= 10^-169 */ U64(0xF18899B1, 0xBC3F8CA1), U64(0xDC44E6C3, 0xCB279AC1), /* ~= 10^-168 */ U64(0x96F5600F, 0x15A7B7E5), U64(0x29AB103A, 0x5EF8C0B9), /* ~= 10^-167 */ U64(0xBCB2B812, 0xDB11A5DE), U64(0x7415D448, 0xF6B6F0E7), /* ~= 10^-166 */ U64(0xEBDF6617, 0x91D60F56), U64(0x111B495B, 0x3464AD21), /* ~= 10^-165 */ U64(0x936B9FCE, 0xBB25C995), U64(0xCAB10DD9, 0x00BEEC34), /* ~= 10^-164 */ U64(0xB84687C2, 0x69EF3BFB), U64(0x3D5D514F, 0x40EEA742), /* ~= 10^-163 */ U64(0xE65829B3, 0x046B0AFA), U64(0x0CB4A5A3, 0x112A5112), /* ~= 10^-162 */ U64(0x8FF71A0F, 0xE2C2E6DC), U64(0x47F0E785, 0xEABA72AB), /* ~= 10^-161 */ U64(0xB3F4E093, 0xDB73A093), U64(0x59ED2167, 0x65690F56), /* ~= 10^-160 */ U64(0xE0F218B8, 0xD25088B8), U64(0x306869C1, 0x3EC3532C), /* ~= 10^-159 */ U64(0x8C974F73, 0x83725573), U64(0x1E414218, 0xC73A13FB), /* ~= 10^-158 */ U64(0xAFBD2350, 0x644EEACF), U64(0xE5D1929E, 0xF90898FA), /* ~= 10^-157 */ U64(0xDBAC6C24, 0x7D62A583), U64(0xDF45F746, 0xB74ABF39), /* ~= 10^-156 */ U64(0x894BC396, 0xCE5DA772), U64(0x6B8BBA8C, 0x328EB783), /* ~= 10^-155 */ U64(0xAB9EB47C, 0x81F5114F), U64(0x066EA92F, 0x3F326564), /* ~= 10^-154 */ U64(0xD686619B, 0xA27255A2), U64(0xC80A537B, 0x0EFEFEBD), /* ~= 10^-153 */ U64(0x8613FD01, 0x45877585), U64(0xBD06742C, 0xE95F5F36), /* ~= 10^-152 */ U64(0xA798FC41, 0x96E952E7), U64(0x2C481138, 0x23B73704), /* ~= 10^-151 */ U64(0xD17F3B51, 0xFCA3A7A0), U64(0xF75A1586, 0x2CA504C5), /* ~= 10^-150 */ U64(0x82EF8513, 0x3DE648C4), U64(0x9A984D73, 0xDBE722FB), /* ~= 10^-149 */ U64(0xA3AB6658, 0x0D5FDAF5), U64(0xC13E60D0, 0xD2E0EBBA), /* ~= 10^-148 */ U64(0xCC963FEE, 0x10B7D1B3), U64(0x318DF905, 0x079926A8), /* ~= 10^-147 */ U64(0xFFBBCFE9, 0x94E5C61F), U64(0xFDF17746, 0x497F7052), /* ~= 10^-146 */ U64(0x9FD561F1, 0xFD0F9BD3), U64(0xFEB6EA8B, 0xEDEFA633), /* ~= 10^-145 */ U64(0xC7CABA6E, 0x7C5382C8), U64(0xFE64A52E, 0xE96B8FC0), /* ~= 10^-144 */ U64(0xF9BD690A, 0x1B68637B), U64(0x3DFDCE7A, 0xA3C673B0), /* ~= 10^-143 */ U64(0x9C1661A6, 0x51213E2D), U64(0x06BEA10C, 0xA65C084E), /* ~= 10^-142 */ U64(0xC31BFA0F, 0xE5698DB8), U64(0x486E494F, 0xCFF30A62), /* ~= 10^-141 */ U64(0xF3E2F893, 0xDEC3F126), U64(0x5A89DBA3, 0xC3EFCCFA), /* ~= 10^-140 */ U64(0x986DDB5C, 0x6B3A76B7), U64(0xF8962946, 0x5A75E01C), /* ~= 10^-139 */ U64(0xBE895233, 0x86091465), U64(0xF6BBB397, 0xF1135823), /* ~= 10^-138 */ U64(0xEE2BA6C0, 0x678B597F), U64(0x746AA07D, 0xED582E2C), /* ~= 10^-137 */ U64(0x94DB4838, 0x40B717EF), U64(0xA8C2A44E, 0xB4571CDC), /* ~= 10^-136 */ U64(0xBA121A46, 0x50E4DDEB), U64(0x92F34D62, 0x616CE413), /* ~= 10^-135 */ U64(0xE896A0D7, 0xE51E1566), U64(0x77B020BA, 0xF9C81D17), /* ~= 10^-134 */ U64(0x915E2486, 0xEF32CD60), U64(0x0ACE1474, 0xDC1D122E), /* ~= 10^-133 */ U64(0xB5B5ADA8, 0xAAFF80B8), U64(0x0D819992, 0x132456BA), /* ~= 10^-132 */ U64(0xE3231912, 0xD5BF60E6), U64(0x10E1FFF6, 0x97ED6C69), /* ~= 10^-131 */ U64(0x8DF5EFAB, 0xC5979C8F), U64(0xCA8D3FFA, 0x1EF463C1), /* ~= 10^-130 */ U64(0xB1736B96, 0xB6FD83B3), U64(0xBD308FF8, 0xA6B17CB2), /* ~= 10^-129 */ U64(0xDDD0467C, 0x64BCE4A0), U64(0xAC7CB3F6, 0xD05DDBDE), /* ~= 10^-128 */ U64(0x8AA22C0D, 0xBEF60EE4), U64(0x6BCDF07A, 0x423AA96B), /* ~= 10^-127 */ U64(0xAD4AB711, 0x2EB3929D), U64(0x86C16C98, 0xD2C953C6), /* ~= 10^-126 */ U64(0xD89D64D5, 0x7A607744), U64(0xE871C7BF, 0x077BA8B7), /* ~= 10^-125 */ U64(0x87625F05, 0x6C7C4A8B), U64(0x11471CD7, 0x64AD4972), /* ~= 10^-124 */ U64(0xA93AF6C6, 0xC79B5D2D), U64(0xD598E40D, 0x3DD89BCF), /* ~= 10^-123 */ U64(0xD389B478, 0x79823479), U64(0x4AFF1D10, 0x8D4EC2C3), /* ~= 10^-122 */ U64(0x843610CB, 0x4BF160CB), U64(0xCEDF722A, 0x585139BA), /* ~= 10^-121 */ U64(0xA54394FE, 0x1EEDB8FE), U64(0xC2974EB4, 0xEE658828), /* ~= 10^-120 */ U64(0xCE947A3D, 0xA6A9273E), U64(0x733D2262, 0x29FEEA32), /* ~= 10^-119 */ U64(0x811CCC66, 0x8829B887), U64(0x0806357D, 0x5A3F525F), /* ~= 10^-118 */ U64(0xA163FF80, 0x2A3426A8), U64(0xCA07C2DC, 0xB0CF26F7), /* ~= 10^-117 */ U64(0xC9BCFF60, 0x34C13052), U64(0xFC89B393, 0xDD02F0B5), /* ~= 10^-116 */ U64(0xFC2C3F38, 0x41F17C67), U64(0xBBAC2078, 0xD443ACE2), /* ~= 10^-115 */ U64(0x9D9BA783, 0x2936EDC0), U64(0xD54B944B, 0x84AA4C0D), /* ~= 10^-114 */ U64(0xC5029163, 0xF384A931), U64(0x0A9E795E, 0x65D4DF11), /* ~= 10^-113 */ U64(0xF64335BC, 0xF065D37D), U64(0x4D4617B5, 0xFF4A16D5), /* ~= 10^-112 */ U64(0x99EA0196, 0x163FA42E), U64(0x504BCED1, 0xBF8E4E45), /* ~= 10^-111 */ U64(0xC06481FB, 0x9BCF8D39), U64(0xE45EC286, 0x2F71E1D6), /* ~= 10^-110 */ U64(0xF07DA27A, 0x82C37088), U64(0x5D767327, 0xBB4E5A4C), /* ~= 10^-109 */ U64(0x964E858C, 0x91BA2655), U64(0x3A6A07F8, 0xD510F86F), /* ~= 10^-108 */ U64(0xBBE226EF, 0xB628AFEA), U64(0x890489F7, 0x0A55368B), /* ~= 10^-107 */ U64(0xEADAB0AB, 0xA3B2DBE5), U64(0x2B45AC74, 0xCCEA842E), /* ~= 10^-106 */ U64(0x92C8AE6B, 0x464FC96F), U64(0x3B0B8BC9, 0x0012929D), /* ~= 10^-105 */ U64(0xB77ADA06, 0x17E3BBCB), U64(0x09CE6EBB, 0x40173744), /* ~= 10^-104 */ U64(0xE5599087, 0x9DDCAABD), U64(0xCC420A6A, 0x101D0515), /* ~= 10^-103 */ U64(0x8F57FA54, 0xC2A9EAB6), U64(0x9FA94682, 0x4A12232D), /* ~= 10^-102 */ U64(0xB32DF8E9, 0xF3546564), U64(0x47939822, 0xDC96ABF9), /* ~= 10^-101 */ U64(0xDFF97724, 0x70297EBD), U64(0x59787E2B, 0x93BC56F7), /* ~= 10^-100 */ U64(0x8BFBEA76, 0xC619EF36), U64(0x57EB4EDB, 0x3C55B65A), /* ~= 10^-99 */ U64(0xAEFAE514, 0x77A06B03), U64(0xEDE62292, 0x0B6B23F1), /* ~= 10^-98 */ U64(0xDAB99E59, 0x958885C4), U64(0xE95FAB36, 0x8E45ECED), /* ~= 10^-97 */ U64(0x88B402F7, 0xFD75539B), U64(0x11DBCB02, 0x18EBB414), /* ~= 10^-96 */ U64(0xAAE103B5, 0xFCD2A881), U64(0xD652BDC2, 0x9F26A119), /* ~= 10^-95 */ U64(0xD59944A3, 0x7C0752A2), U64(0x4BE76D33, 0x46F0495F), /* ~= 10^-94 */ U64(0x857FCAE6, 0x2D8493A5), U64(0x6F70A440, 0x0C562DDB), /* ~= 10^-93 */ U64(0xA6DFBD9F, 0xB8E5B88E), U64(0xCB4CCD50, 0x0F6BB952), /* ~= 10^-92 */ U64(0xD097AD07, 0xA71F26B2), U64(0x7E2000A4, 0x1346A7A7), /* ~= 10^-91 */ U64(0x825ECC24, 0xC873782F), U64(0x8ED40066, 0x8C0C28C8), /* ~= 10^-90 */ U64(0xA2F67F2D, 0xFA90563B), U64(0x72890080, 0x2F0F32FA), /* ~= 10^-89 */ U64(0xCBB41EF9, 0x79346BCA), U64(0x4F2B40A0, 0x3AD2FFB9), /* ~= 10^-88 */ U64(0xFEA126B7, 0xD78186BC), U64(0xE2F610C8, 0x4987BFA8), /* ~= 10^-87 */ U64(0x9F24B832, 0xE6B0F436), U64(0x0DD9CA7D, 0x2DF4D7C9), /* ~= 10^-86 */ U64(0xC6EDE63F, 0xA05D3143), U64(0x91503D1C, 0x79720DBB), /* ~= 10^-85 */ U64(0xF8A95FCF, 0x88747D94), U64(0x75A44C63, 0x97CE912A), /* ~= 10^-84 */ U64(0x9B69DBE1, 0xB548CE7C), U64(0xC986AFBE, 0x3EE11ABA), /* ~= 10^-83 */ U64(0xC24452DA, 0x229B021B), U64(0xFBE85BAD, 0xCE996168), /* ~= 10^-82 */ U64(0xF2D56790, 0xAB41C2A2), U64(0xFAE27299, 0x423FB9C3), /* ~= 10^-81 */ U64(0x97C560BA, 0x6B0919A5), U64(0xDCCD879F, 0xC967D41A), /* ~= 10^-80 */ U64(0xBDB6B8E9, 0x05CB600F), U64(0x5400E987, 0xBBC1C920), /* ~= 10^-79 */ U64(0xED246723, 0x473E3813), U64(0x290123E9, 0xAAB23B68), /* ~= 10^-78 */ U64(0x9436C076, 0x0C86E30B), U64(0xF9A0B672, 0x0AAF6521), /* ~= 10^-77 */ U64(0xB9447093, 0x8FA89BCE), U64(0xF808E40E, 0x8D5B3E69), /* ~= 10^-76 */ U64(0xE7958CB8, 0x7392C2C2), U64(0xB60B1D12, 0x30B20E04), /* ~= 10^-75 */ U64(0x90BD77F3, 0x483BB9B9), U64(0xB1C6F22B, 0x5E6F48C2), /* ~= 10^-74 */ U64(0xB4ECD5F0, 0x1A4AA828), U64(0x1E38AEB6, 0x360B1AF3), /* ~= 10^-73 */ U64(0xE2280B6C, 0x20DD5232), U64(0x25C6DA63, 0xC38DE1B0), /* ~= 10^-72 */ U64(0x8D590723, 0x948A535F), U64(0x579C487E, 0x5A38AD0E), /* ~= 10^-71 */ U64(0xB0AF48EC, 0x79ACE837), U64(0x2D835A9D, 0xF0C6D851), /* ~= 10^-70 */ U64(0xDCDB1B27, 0x98182244), U64(0xF8E43145, 0x6CF88E65), /* ~= 10^-69 */ U64(0x8A08F0F8, 0xBF0F156B), U64(0x1B8E9ECB, 0x641B58FF), /* ~= 10^-68 */ U64(0xAC8B2D36, 0xEED2DAC5), U64(0xE272467E, 0x3D222F3F), /* ~= 10^-67 */ U64(0xD7ADF884, 0xAA879177), U64(0x5B0ED81D, 0xCC6ABB0F), /* ~= 10^-66 */ U64(0x86CCBB52, 0xEA94BAEA), U64(0x98E94712, 0x9FC2B4E9), /* ~= 10^-65 */ U64(0xA87FEA27, 0xA539E9A5), U64(0x3F2398D7, 0x47B36224), /* ~= 10^-64 */ U64(0xD29FE4B1, 0x8E88640E), U64(0x8EEC7F0D, 0x19A03AAD), /* ~= 10^-63 */ U64(0x83A3EEEE, 0xF9153E89), U64(0x1953CF68, 0x300424AC), /* ~= 10^-62 */ U64(0xA48CEAAA, 0xB75A8E2B), U64(0x5FA8C342, 0x3C052DD7), /* ~= 10^-61 */ U64(0xCDB02555, 0x653131B6), U64(0x3792F412, 0xCB06794D), /* ~= 10^-60 */ U64(0x808E1755, 0x5F3EBF11), U64(0xE2BBD88B, 0xBEE40BD0), /* ~= 10^-59 */ U64(0xA0B19D2A, 0xB70E6ED6), U64(0x5B6ACEAE, 0xAE9D0EC4), /* ~= 10^-58 */ U64(0xC8DE0475, 0x64D20A8B), U64(0xF245825A, 0x5A445275), /* ~= 10^-57 */ U64(0xFB158592, 0xBE068D2E), U64(0xEED6E2F0, 0xF0D56712), /* ~= 10^-56 */ U64(0x9CED737B, 0xB6C4183D), U64(0x55464DD6, 0x9685606B), /* ~= 10^-55 */ U64(0xC428D05A, 0xA4751E4C), U64(0xAA97E14C, 0x3C26B886), /* ~= 10^-54 */ U64(0xF5330471, 0x4D9265DF), U64(0xD53DD99F, 0x4B3066A8), /* ~= 10^-53 */ U64(0x993FE2C6, 0xD07B7FAB), U64(0xE546A803, 0x8EFE4029), /* ~= 10^-52 */ U64(0xBF8FDB78, 0x849A5F96), U64(0xDE985204, 0x72BDD033), /* ~= 10^-51 */ U64(0xEF73D256, 0xA5C0F77C), U64(0x963E6685, 0x8F6D4440), /* ~= 10^-50 */ U64(0x95A86376, 0x27989AAD), U64(0xDDE70013, 0x79A44AA8), /* ~= 10^-49 */ U64(0xBB127C53, 0xB17EC159), U64(0x5560C018, 0x580D5D52), /* ~= 10^-48 */ U64(0xE9D71B68, 0x9DDE71AF), U64(0xAAB8F01E, 0x6E10B4A6), /* ~= 10^-47 */ U64(0x92267121, 0x62AB070D), U64(0xCAB39613, 0x04CA70E8), /* ~= 10^-46 */ U64(0xB6B00D69, 0xBB55C8D1), U64(0x3D607B97, 0xC5FD0D22), /* ~= 10^-45 */ U64(0xE45C10C4, 0x2A2B3B05), U64(0x8CB89A7D, 0xB77C506A), /* ~= 10^-44 */ U64(0x8EB98A7A, 0x9A5B04E3), U64(0x77F3608E, 0x92ADB242), /* ~= 10^-43 */ U64(0xB267ED19, 0x40F1C61C), U64(0x55F038B2, 0x37591ED3), /* ~= 10^-42 */ U64(0xDF01E85F, 0x912E37A3), U64(0x6B6C46DE, 0xC52F6688), /* ~= 10^-41 */ U64(0x8B61313B, 0xBABCE2C6), U64(0x2323AC4B, 0x3B3DA015), /* ~= 10^-40 */ U64(0xAE397D8A, 0xA96C1B77), U64(0xABEC975E, 0x0A0D081A), /* ~= 10^-39 */ U64(0xD9C7DCED, 0x53C72255), U64(0x96E7BD35, 0x8C904A21), /* ~= 10^-38 */ U64(0x881CEA14, 0x545C7575), U64(0x7E50D641, 0x77DA2E54), /* ~= 10^-37 */ U64(0xAA242499, 0x697392D2), U64(0xDDE50BD1, 0xD5D0B9E9), /* ~= 10^-36 */ U64(0xD4AD2DBF, 0xC3D07787), U64(0x955E4EC6, 0x4B44E864), /* ~= 10^-35 */ U64(0x84EC3C97, 0xDA624AB4), U64(0xBD5AF13B, 0xEF0B113E), /* ~= 10^-34 */ U64(0xA6274BBD, 0xD0FADD61), U64(0xECB1AD8A, 0xEACDD58E), /* ~= 10^-33 */ U64(0xCFB11EAD, 0x453994BA), U64(0x67DE18ED, 0xA5814AF2), /* ~= 10^-32 */ U64(0x81CEB32C, 0x4B43FCF4), U64(0x80EACF94, 0x8770CED7), /* ~= 10^-31 */ U64(0xA2425FF7, 0x5E14FC31), U64(0xA1258379, 0xA94D028D), /* ~= 10^-30 */ U64(0xCAD2F7F5, 0x359A3B3E), U64(0x096EE458, 0x13A04330), /* ~= 10^-29 */ U64(0xFD87B5F2, 0x8300CA0D), U64(0x8BCA9D6E, 0x188853FC), /* ~= 10^-28 */ U64(0x9E74D1B7, 0x91E07E48), U64(0x775EA264, 0xCF55347D), /* ~= 10^-27 */ U64(0xC6120625, 0x76589DDA), U64(0x95364AFE, 0x032A819D), /* ~= 10^-26 */ U64(0xF79687AE, 0xD3EEC551), U64(0x3A83DDBD, 0x83F52204), /* ~= 10^-25 */ U64(0x9ABE14CD, 0x44753B52), U64(0xC4926A96, 0x72793542), /* ~= 10^-24 */ U64(0xC16D9A00, 0x95928A27), U64(0x75B7053C, 0x0F178293), /* ~= 10^-23 */ U64(0xF1C90080, 0xBAF72CB1), U64(0x5324C68B, 0x12DD6338), /* ~= 10^-22 */ U64(0x971DA050, 0x74DA7BEE), U64(0xD3F6FC16, 0xEBCA5E03), /* ~= 10^-21 */ U64(0xBCE50864, 0x92111AEA), U64(0x88F4BB1C, 0xA6BCF584), /* ~= 10^-20 */ U64(0xEC1E4A7D, 0xB69561A5), U64(0x2B31E9E3, 0xD06C32E5), /* ~= 10^-19 */ U64(0x9392EE8E, 0x921D5D07), U64(0x3AFF322E, 0x62439FCF), /* ~= 10^-18 */ U64(0xB877AA32, 0x36A4B449), U64(0x09BEFEB9, 0xFAD487C2), /* ~= 10^-17 */ U64(0xE69594BE, 0xC44DE15B), U64(0x4C2EBE68, 0x7989A9B3), /* ~= 10^-16 */ U64(0x901D7CF7, 0x3AB0ACD9), U64(0x0F9D3701, 0x4BF60A10), /* ~= 10^-15 */ U64(0xB424DC35, 0x095CD80F), U64(0x538484C1, 0x9EF38C94), /* ~= 10^-14 */ U64(0xE12E1342, 0x4BB40E13), U64(0x2865A5F2, 0x06B06FB9), /* ~= 10^-13 */ U64(0x8CBCCC09, 0x6F5088CB), U64(0xF93F87B7, 0x442E45D3), /* ~= 10^-12 */ U64(0xAFEBFF0B, 0xCB24AAFE), U64(0xF78F69A5, 0x1539D748), /* ~= 10^-11 */ U64(0xDBE6FECE, 0xBDEDD5BE), U64(0xB573440E, 0x5A884D1B), /* ~= 10^-10 */ U64(0x89705F41, 0x36B4A597), U64(0x31680A88, 0xF8953030), /* ~= 10^-9 */ U64(0xABCC7711, 0x8461CEFC), U64(0xFDC20D2B, 0x36BA7C3D), /* ~= 10^-8 */ U64(0xD6BF94D5, 0xE57A42BC), U64(0x3D329076, 0x04691B4C), /* ~= 10^-7 */ U64(0x8637BD05, 0xAF6C69B5), U64(0xA63F9A49, 0xC2C1B10F), /* ~= 10^-6 */ U64(0xA7C5AC47, 0x1B478423), U64(0x0FCF80DC, 0x33721D53), /* ~= 10^-5 */ U64(0xD1B71758, 0xE219652B), U64(0xD3C36113, 0x404EA4A8), /* ~= 10^-4 */ U64(0x83126E97, 0x8D4FDF3B), U64(0x645A1CAC, 0x083126E9), /* ~= 10^-3 */ U64(0xA3D70A3D, 0x70A3D70A), U64(0x3D70A3D7, 0x0A3D70A3), /* ~= 10^-2 */ U64(0xCCCCCCCC, 0xCCCCCCCC), U64(0xCCCCCCCC, 0xCCCCCCCC), /* ~= 10^-1 */ U64(0x80000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^0 */ U64(0xA0000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^1 */ U64(0xC8000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^2 */ U64(0xFA000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^3 */ U64(0x9C400000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^4 */ U64(0xC3500000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^5 */ U64(0xF4240000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^6 */ U64(0x98968000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^7 */ U64(0xBEBC2000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^8 */ U64(0xEE6B2800, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^9 */ U64(0x9502F900, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^10 */ U64(0xBA43B740, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^11 */ U64(0xE8D4A510, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^12 */ U64(0x9184E72A, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^13 */ U64(0xB5E620F4, 0x80000000), U64(0x00000000, 0x00000000), /* == 10^14 */ U64(0xE35FA931, 0xA0000000), U64(0x00000000, 0x00000000), /* == 10^15 */ U64(0x8E1BC9BF, 0x04000000), U64(0x00000000, 0x00000000), /* == 10^16 */ U64(0xB1A2BC2E, 0xC5000000), U64(0x00000000, 0x00000000), /* == 10^17 */ U64(0xDE0B6B3A, 0x76400000), U64(0x00000000, 0x00000000), /* == 10^18 */ U64(0x8AC72304, 0x89E80000), U64(0x00000000, 0x00000000), /* == 10^19 */ U64(0xAD78EBC5, 0xAC620000), U64(0x00000000, 0x00000000), /* == 10^20 */ U64(0xD8D726B7, 0x177A8000), U64(0x00000000, 0x00000000), /* == 10^21 */ U64(0x87867832, 0x6EAC9000), U64(0x00000000, 0x00000000), /* == 10^22 */ U64(0xA968163F, 0x0A57B400), U64(0x00000000, 0x00000000), /* == 10^23 */ U64(0xD3C21BCE, 0xCCEDA100), U64(0x00000000, 0x00000000), /* == 10^24 */ U64(0x84595161, 0x401484A0), U64(0x00000000, 0x00000000), /* == 10^25 */ U64(0xA56FA5B9, 0x9019A5C8), U64(0x00000000, 0x00000000), /* == 10^26 */ U64(0xCECB8F27, 0xF4200F3A), U64(0x00000000, 0x00000000), /* == 10^27 */ U64(0x813F3978, 0xF8940984), U64(0x40000000, 0x00000000), /* == 10^28 */ U64(0xA18F07D7, 0x36B90BE5), U64(0x50000000, 0x00000000), /* == 10^29 */ U64(0xC9F2C9CD, 0x04674EDE), U64(0xA4000000, 0x00000000), /* == 10^30 */ U64(0xFC6F7C40, 0x45812296), U64(0x4D000000, 0x00000000), /* == 10^31 */ U64(0x9DC5ADA8, 0x2B70B59D), U64(0xF0200000, 0x00000000), /* == 10^32 */ U64(0xC5371912, 0x364CE305), U64(0x6C280000, 0x00000000), /* == 10^33 */ U64(0xF684DF56, 0xC3E01BC6), U64(0xC7320000, 0x00000000), /* == 10^34 */ U64(0x9A130B96, 0x3A6C115C), U64(0x3C7F4000, 0x00000000), /* == 10^35 */ U64(0xC097CE7B, 0xC90715B3), U64(0x4B9F1000, 0x00000000), /* == 10^36 */ U64(0xF0BDC21A, 0xBB48DB20), U64(0x1E86D400, 0x00000000), /* == 10^37 */ U64(0x96769950, 0xB50D88F4), U64(0x13144480, 0x00000000), /* == 10^38 */ U64(0xBC143FA4, 0xE250EB31), U64(0x17D955A0, 0x00000000), /* == 10^39 */ U64(0xEB194F8E, 0x1AE525FD), U64(0x5DCFAB08, 0x00000000), /* == 10^40 */ U64(0x92EFD1B8, 0xD0CF37BE), U64(0x5AA1CAE5, 0x00000000), /* == 10^41 */ U64(0xB7ABC627, 0x050305AD), U64(0xF14A3D9E, 0x40000000), /* == 10^42 */ U64(0xE596B7B0, 0xC643C719), U64(0x6D9CCD05, 0xD0000000), /* == 10^43 */ U64(0x8F7E32CE, 0x7BEA5C6F), U64(0xE4820023, 0xA2000000), /* == 10^44 */ U64(0xB35DBF82, 0x1AE4F38B), U64(0xDDA2802C, 0x8A800000), /* == 10^45 */ U64(0xE0352F62, 0xA19E306E), U64(0xD50B2037, 0xAD200000), /* == 10^46 */ U64(0x8C213D9D, 0xA502DE45), U64(0x4526F422, 0xCC340000), /* == 10^47 */ U64(0xAF298D05, 0x0E4395D6), U64(0x9670B12B, 0x7F410000), /* == 10^48 */ U64(0xDAF3F046, 0x51D47B4C), U64(0x3C0CDD76, 0x5F114000), /* == 10^49 */ U64(0x88D8762B, 0xF324CD0F), U64(0xA5880A69, 0xFB6AC800), /* == 10^50 */ U64(0xAB0E93B6, 0xEFEE0053), U64(0x8EEA0D04, 0x7A457A00), /* == 10^51 */ U64(0xD5D238A4, 0xABE98068), U64(0x72A49045, 0x98D6D880), /* == 10^52 */ U64(0x85A36366, 0xEB71F041), U64(0x47A6DA2B, 0x7F864750), /* == 10^53 */ U64(0xA70C3C40, 0xA64E6C51), U64(0x999090B6, 0x5F67D924), /* == 10^54 */ U64(0xD0CF4B50, 0xCFE20765), U64(0xFFF4B4E3, 0xF741CF6D), /* == 10^55 */ U64(0x82818F12, 0x81ED449F), U64(0xBFF8F10E, 0x7A8921A4), /* ~= 10^56 */ U64(0xA321F2D7, 0x226895C7), U64(0xAFF72D52, 0x192B6A0D), /* ~= 10^57 */ U64(0xCBEA6F8C, 0xEB02BB39), U64(0x9BF4F8A6, 0x9F764490), /* ~= 10^58 */ U64(0xFEE50B70, 0x25C36A08), U64(0x02F236D0, 0x4753D5B4), /* ~= 10^59 */ U64(0x9F4F2726, 0x179A2245), U64(0x01D76242, 0x2C946590), /* ~= 10^60 */ U64(0xC722F0EF, 0x9D80AAD6), U64(0x424D3AD2, 0xB7B97EF5), /* ~= 10^61 */ U64(0xF8EBAD2B, 0x84E0D58B), U64(0xD2E08987, 0x65A7DEB2), /* ~= 10^62 */ U64(0x9B934C3B, 0x330C8577), U64(0x63CC55F4, 0x9F88EB2F), /* ~= 10^63 */ U64(0xC2781F49, 0xFFCFA6D5), U64(0x3CBF6B71, 0xC76B25FB), /* ~= 10^64 */ U64(0xF316271C, 0x7FC3908A), U64(0x8BEF464E, 0x3945EF7A), /* ~= 10^65 */ U64(0x97EDD871, 0xCFDA3A56), U64(0x97758BF0, 0xE3CBB5AC), /* ~= 10^66 */ U64(0xBDE94E8E, 0x43D0C8EC), U64(0x3D52EEED, 0x1CBEA317), /* ~= 10^67 */ U64(0xED63A231, 0xD4C4FB27), U64(0x4CA7AAA8, 0x63EE4BDD), /* ~= 10^68 */ U64(0x945E455F, 0x24FB1CF8), U64(0x8FE8CAA9, 0x3E74EF6A), /* ~= 10^69 */ U64(0xB975D6B6, 0xEE39E436), U64(0xB3E2FD53, 0x8E122B44), /* ~= 10^70 */ U64(0xE7D34C64, 0xA9C85D44), U64(0x60DBBCA8, 0x7196B616), /* ~= 10^71 */ U64(0x90E40FBE, 0xEA1D3A4A), U64(0xBC8955E9, 0x46FE31CD), /* ~= 10^72 */ U64(0xB51D13AE, 0xA4A488DD), U64(0x6BABAB63, 0x98BDBE41), /* ~= 10^73 */ U64(0xE264589A, 0x4DCDAB14), U64(0xC696963C, 0x7EED2DD1), /* ~= 10^74 */ U64(0x8D7EB760, 0x70A08AEC), U64(0xFC1E1DE5, 0xCF543CA2), /* ~= 10^75 */ U64(0xB0DE6538, 0x8CC8ADA8), U64(0x3B25A55F, 0x43294BCB), /* ~= 10^76 */ U64(0xDD15FE86, 0xAFFAD912), U64(0x49EF0EB7, 0x13F39EBE), /* ~= 10^77 */ U64(0x8A2DBF14, 0x2DFCC7AB), U64(0x6E356932, 0x6C784337), /* ~= 10^78 */ U64(0xACB92ED9, 0x397BF996), U64(0x49C2C37F, 0x07965404), /* ~= 10^79 */ U64(0xD7E77A8F, 0x87DAF7FB), U64(0xDC33745E, 0xC97BE906), /* ~= 10^80 */ U64(0x86F0AC99, 0xB4E8DAFD), U64(0x69A028BB, 0x3DED71A3), /* ~= 10^81 */ U64(0xA8ACD7C0, 0x222311BC), U64(0xC40832EA, 0x0D68CE0C), /* ~= 10^82 */ U64(0xD2D80DB0, 0x2AABD62B), U64(0xF50A3FA4, 0x90C30190), /* ~= 10^83 */ U64(0x83C7088E, 0x1AAB65DB), U64(0x792667C6, 0xDA79E0FA), /* ~= 10^84 */ U64(0xA4B8CAB1, 0xA1563F52), U64(0x577001B8, 0x91185938), /* ~= 10^85 */ U64(0xCDE6FD5E, 0x09ABCF26), U64(0xED4C0226, 0xB55E6F86), /* ~= 10^86 */ U64(0x80B05E5A, 0xC60B6178), U64(0x544F8158, 0x315B05B4), /* ~= 10^87 */ U64(0xA0DC75F1, 0x778E39D6), U64(0x696361AE, 0x3DB1C721), /* ~= 10^88 */ U64(0xC913936D, 0xD571C84C), U64(0x03BC3A19, 0xCD1E38E9), /* ~= 10^89 */ U64(0xFB587849, 0x4ACE3A5F), U64(0x04AB48A0, 0x4065C723), /* ~= 10^90 */ U64(0x9D174B2D, 0xCEC0E47B), U64(0x62EB0D64, 0x283F9C76), /* ~= 10^91 */ U64(0xC45D1DF9, 0x42711D9A), U64(0x3BA5D0BD, 0x324F8394), /* ~= 10^92 */ U64(0xF5746577, 0x930D6500), U64(0xCA8F44EC, 0x7EE36479), /* ~= 10^93 */ U64(0x9968BF6A, 0xBBE85F20), U64(0x7E998B13, 0xCF4E1ECB), /* ~= 10^94 */ U64(0xBFC2EF45, 0x6AE276E8), U64(0x9E3FEDD8, 0xC321A67E), /* ~= 10^95 */ U64(0xEFB3AB16, 0xC59B14A2), U64(0xC5CFE94E, 0xF3EA101E), /* ~= 10^96 */ U64(0x95D04AEE, 0x3B80ECE5), U64(0xBBA1F1D1, 0x58724A12), /* ~= 10^97 */ U64(0xBB445DA9, 0xCA61281F), U64(0x2A8A6E45, 0xAE8EDC97), /* ~= 10^98 */ U64(0xEA157514, 0x3CF97226), U64(0xF52D09D7, 0x1A3293BD), /* ~= 10^99 */ U64(0x924D692C, 0xA61BE758), U64(0x593C2626, 0x705F9C56), /* ~= 10^100 */ U64(0xB6E0C377, 0xCFA2E12E), U64(0x6F8B2FB0, 0x0C77836C), /* ~= 10^101 */ U64(0xE498F455, 0xC38B997A), U64(0x0B6DFB9C, 0x0F956447), /* ~= 10^102 */ U64(0x8EDF98B5, 0x9A373FEC), U64(0x4724BD41, 0x89BD5EAC), /* ~= 10^103 */ U64(0xB2977EE3, 0x00C50FE7), U64(0x58EDEC91, 0xEC2CB657), /* ~= 10^104 */ U64(0xDF3D5E9B, 0xC0F653E1), U64(0x2F2967B6, 0x6737E3ED), /* ~= 10^105 */ U64(0x8B865B21, 0x5899F46C), U64(0xBD79E0D2, 0x0082EE74), /* ~= 10^106 */ U64(0xAE67F1E9, 0xAEC07187), U64(0xECD85906, 0x80A3AA11), /* ~= 10^107 */ U64(0xDA01EE64, 0x1A708DE9), U64(0xE80E6F48, 0x20CC9495), /* ~= 10^108 */ U64(0x884134FE, 0x908658B2), U64(0x3109058D, 0x147FDCDD), /* ~= 10^109 */ U64(0xAA51823E, 0x34A7EEDE), U64(0xBD4B46F0, 0x599FD415), /* ~= 10^110 */ U64(0xD4E5E2CD, 0xC1D1EA96), U64(0x6C9E18AC, 0x7007C91A), /* ~= 10^111 */ U64(0x850FADC0, 0x9923329E), U64(0x03E2CF6B, 0xC604DDB0), /* ~= 10^112 */ U64(0xA6539930, 0xBF6BFF45), U64(0x84DB8346, 0xB786151C), /* ~= 10^113 */ U64(0xCFE87F7C, 0xEF46FF16), U64(0xE6126418, 0x65679A63), /* ~= 10^114 */ U64(0x81F14FAE, 0x158C5F6E), U64(0x4FCB7E8F, 0x3F60C07E), /* ~= 10^115 */ U64(0xA26DA399, 0x9AEF7749), U64(0xE3BE5E33, 0x0F38F09D), /* ~= 10^116 */ U64(0xCB090C80, 0x01AB551C), U64(0x5CADF5BF, 0xD3072CC5), /* ~= 10^117 */ U64(0xFDCB4FA0, 0x02162A63), U64(0x73D9732F, 0xC7C8F7F6), /* ~= 10^118 */ U64(0x9E9F11C4, 0x014DDA7E), U64(0x2867E7FD, 0xDCDD9AFA), /* ~= 10^119 */ U64(0xC646D635, 0x01A1511D), U64(0xB281E1FD, 0x541501B8), /* ~= 10^120 */ U64(0xF7D88BC2, 0x4209A565), U64(0x1F225A7C, 0xA91A4226), /* ~= 10^121 */ U64(0x9AE75759, 0x6946075F), U64(0x3375788D, 0xE9B06958), /* ~= 10^122 */ U64(0xC1A12D2F, 0xC3978937), U64(0x0052D6B1, 0x641C83AE), /* ~= 10^123 */ U64(0xF209787B, 0xB47D6B84), U64(0xC0678C5D, 0xBD23A49A), /* ~= 10^124 */ U64(0x9745EB4D, 0x50CE6332), U64(0xF840B7BA, 0x963646E0), /* ~= 10^125 */ U64(0xBD176620, 0xA501FBFF), U64(0xB650E5A9, 0x3BC3D898), /* ~= 10^126 */ U64(0xEC5D3FA8, 0xCE427AFF), U64(0xA3E51F13, 0x8AB4CEBE), /* ~= 10^127 */ U64(0x93BA47C9, 0x80E98CDF), U64(0xC66F336C, 0x36B10137), /* ~= 10^128 */ U64(0xB8A8D9BB, 0xE123F017), U64(0xB80B0047, 0x445D4184), /* ~= 10^129 */ U64(0xE6D3102A, 0xD96CEC1D), U64(0xA60DC059, 0x157491E5), /* ~= 10^130 */ U64(0x9043EA1A, 0xC7E41392), U64(0x87C89837, 0xAD68DB2F), /* ~= 10^131 */ U64(0xB454E4A1, 0x79DD1877), U64(0x29BABE45, 0x98C311FB), /* ~= 10^132 */ U64(0xE16A1DC9, 0xD8545E94), U64(0xF4296DD6, 0xFEF3D67A), /* ~= 10^133 */ U64(0x8CE2529E, 0x2734BB1D), U64(0x1899E4A6, 0x5F58660C), /* ~= 10^134 */ U64(0xB01AE745, 0xB101E9E4), U64(0x5EC05DCF, 0xF72E7F8F), /* ~= 10^135 */ U64(0xDC21A117, 0x1D42645D), U64(0x76707543, 0xF4FA1F73), /* ~= 10^136 */ U64(0x899504AE, 0x72497EBA), U64(0x6A06494A, 0x791C53A8), /* ~= 10^137 */ U64(0xABFA45DA, 0x0EDBDE69), U64(0x0487DB9D, 0x17636892), /* ~= 10^138 */ U64(0xD6F8D750, 0x9292D603), U64(0x45A9D284, 0x5D3C42B6), /* ~= 10^139 */ U64(0x865B8692, 0x5B9BC5C2), U64(0x0B8A2392, 0xBA45A9B2), /* ~= 10^140 */ U64(0xA7F26836, 0xF282B732), U64(0x8E6CAC77, 0x68D7141E), /* ~= 10^141 */ U64(0xD1EF0244, 0xAF2364FF), U64(0x3207D795, 0x430CD926), /* ~= 10^142 */ U64(0x8335616A, 0xED761F1F), U64(0x7F44E6BD, 0x49E807B8), /* ~= 10^143 */ U64(0xA402B9C5, 0xA8D3A6E7), U64(0x5F16206C, 0x9C6209A6), /* ~= 10^144 */ U64(0xCD036837, 0x130890A1), U64(0x36DBA887, 0xC37A8C0F), /* ~= 10^145 */ U64(0x80222122, 0x6BE55A64), U64(0xC2494954, 0xDA2C9789), /* ~= 10^146 */ U64(0xA02AA96B, 0x06DEB0FD), U64(0xF2DB9BAA, 0x10B7BD6C), /* ~= 10^147 */ U64(0xC83553C5, 0xC8965D3D), U64(0x6F928294, 0x94E5ACC7), /* ~= 10^148 */ U64(0xFA42A8B7, 0x3ABBF48C), U64(0xCB772339, 0xBA1F17F9), /* ~= 10^149 */ U64(0x9C69A972, 0x84B578D7), U64(0xFF2A7604, 0x14536EFB), /* ~= 10^150 */ U64(0xC38413CF, 0x25E2D70D), U64(0xFEF51385, 0x19684ABA), /* ~= 10^151 */ U64(0xF46518C2, 0xEF5B8CD1), U64(0x7EB25866, 0x5FC25D69), /* ~= 10^152 */ U64(0x98BF2F79, 0xD5993802), U64(0xEF2F773F, 0xFBD97A61), /* ~= 10^153 */ U64(0xBEEEFB58, 0x4AFF8603), U64(0xAAFB550F, 0xFACFD8FA), /* ~= 10^154 */ U64(0xEEAABA2E, 0x5DBF6784), U64(0x95BA2A53, 0xF983CF38), /* ~= 10^155 */ U64(0x952AB45C, 0xFA97A0B2), U64(0xDD945A74, 0x7BF26183), /* ~= 10^156 */ U64(0xBA756174, 0x393D88DF), U64(0x94F97111, 0x9AEEF9E4), /* ~= 10^157 */ U64(0xE912B9D1, 0x478CEB17), U64(0x7A37CD56, 0x01AAB85D), /* ~= 10^158 */ U64(0x91ABB422, 0xCCB812EE), U64(0xAC62E055, 0xC10AB33A), /* ~= 10^159 */ U64(0xB616A12B, 0x7FE617AA), U64(0x577B986B, 0x314D6009), /* ~= 10^160 */ U64(0xE39C4976, 0x5FDF9D94), U64(0xED5A7E85, 0xFDA0B80B), /* ~= 10^161 */ U64(0x8E41ADE9, 0xFBEBC27D), U64(0x14588F13, 0xBE847307), /* ~= 10^162 */ U64(0xB1D21964, 0x7AE6B31C), U64(0x596EB2D8, 0xAE258FC8), /* ~= 10^163 */ U64(0xDE469FBD, 0x99A05FE3), U64(0x6FCA5F8E, 0xD9AEF3BB), /* ~= 10^164 */ U64(0x8AEC23D6, 0x80043BEE), U64(0x25DE7BB9, 0x480D5854), /* ~= 10^165 */ U64(0xADA72CCC, 0x20054AE9), U64(0xAF561AA7, 0x9A10AE6A), /* ~= 10^166 */ U64(0xD910F7FF, 0x28069DA4), U64(0x1B2BA151, 0x8094DA04), /* ~= 10^167 */ U64(0x87AA9AFF, 0x79042286), U64(0x90FB44D2, 0xF05D0842), /* ~= 10^168 */ U64(0xA99541BF, 0x57452B28), U64(0x353A1607, 0xAC744A53), /* ~= 10^169 */ U64(0xD3FA922F, 0x2D1675F2), U64(0x42889B89, 0x97915CE8), /* ~= 10^170 */ U64(0x847C9B5D, 0x7C2E09B7), U64(0x69956135, 0xFEBADA11), /* ~= 10^171 */ U64(0xA59BC234, 0xDB398C25), U64(0x43FAB983, 0x7E699095), /* ~= 10^172 */ U64(0xCF02B2C2, 0x1207EF2E), U64(0x94F967E4, 0x5E03F4BB), /* ~= 10^173 */ U64(0x8161AFB9, 0x4B44F57D), U64(0x1D1BE0EE, 0xBAC278F5), /* ~= 10^174 */ U64(0xA1BA1BA7, 0x9E1632DC), U64(0x6462D92A, 0x69731732), /* ~= 10^175 */ U64(0xCA28A291, 0x859BBF93), U64(0x7D7B8F75, 0x03CFDCFE), /* ~= 10^176 */ U64(0xFCB2CB35, 0xE702AF78), U64(0x5CDA7352, 0x44C3D43E), /* ~= 10^177 */ U64(0x9DEFBF01, 0xB061ADAB), U64(0x3A088813, 0x6AFA64A7), /* ~= 10^178 */ U64(0xC56BAEC2, 0x1C7A1916), U64(0x088AAA18, 0x45B8FDD0), /* ~= 10^179 */ U64(0xF6C69A72, 0xA3989F5B), U64(0x8AAD549E, 0x57273D45), /* ~= 10^180 */ U64(0x9A3C2087, 0xA63F6399), U64(0x36AC54E2, 0xF678864B), /* ~= 10^181 */ U64(0xC0CB28A9, 0x8FCF3C7F), U64(0x84576A1B, 0xB416A7DD), /* ~= 10^182 */ U64(0xF0FDF2D3, 0xF3C30B9F), U64(0x656D44A2, 0xA11C51D5), /* ~= 10^183 */ U64(0x969EB7C4, 0x7859E743), U64(0x9F644AE5, 0xA4B1B325), /* ~= 10^184 */ U64(0xBC4665B5, 0x96706114), U64(0x873D5D9F, 0x0DDE1FEE), /* ~= 10^185 */ U64(0xEB57FF22, 0xFC0C7959), U64(0xA90CB506, 0xD155A7EA), /* ~= 10^186 */ U64(0x9316FF75, 0xDD87CBD8), U64(0x09A7F124, 0x42D588F2), /* ~= 10^187 */ U64(0xB7DCBF53, 0x54E9BECE), U64(0x0C11ED6D, 0x538AEB2F), /* ~= 10^188 */ U64(0xE5D3EF28, 0x2A242E81), U64(0x8F1668C8, 0xA86DA5FA), /* ~= 10^189 */ U64(0x8FA47579, 0x1A569D10), U64(0xF96E017D, 0x694487BC), /* ~= 10^190 */ U64(0xB38D92D7, 0x60EC4455), U64(0x37C981DC, 0xC395A9AC), /* ~= 10^191 */ U64(0xE070F78D, 0x3927556A), U64(0x85BBE253, 0xF47B1417), /* ~= 10^192 */ U64(0x8C469AB8, 0x43B89562), U64(0x93956D74, 0x78CCEC8E), /* ~= 10^193 */ U64(0xAF584166, 0x54A6BABB), U64(0x387AC8D1, 0x970027B2), /* ~= 10^194 */ U64(0xDB2E51BF, 0xE9D0696A), U64(0x06997B05, 0xFCC0319E), /* ~= 10^195 */ U64(0x88FCF317, 0xF22241E2), U64(0x441FECE3, 0xBDF81F03), /* ~= 10^196 */ U64(0xAB3C2FDD, 0xEEAAD25A), U64(0xD527E81C, 0xAD7626C3), /* ~= 10^197 */ U64(0xD60B3BD5, 0x6A5586F1), U64(0x8A71E223, 0xD8D3B074), /* ~= 10^198 */ U64(0x85C70565, 0x62757456), U64(0xF6872D56, 0x67844E49), /* ~= 10^199 */ U64(0xA738C6BE, 0xBB12D16C), U64(0xB428F8AC, 0x016561DB), /* ~= 10^200 */ U64(0xD106F86E, 0x69D785C7), U64(0xE13336D7, 0x01BEBA52), /* ~= 10^201 */ U64(0x82A45B45, 0x0226B39C), U64(0xECC00246, 0x61173473), /* ~= 10^202 */ U64(0xA34D7216, 0x42B06084), U64(0x27F002D7, 0xF95D0190), /* ~= 10^203 */ U64(0xCC20CE9B, 0xD35C78A5), U64(0x31EC038D, 0xF7B441F4), /* ~= 10^204 */ U64(0xFF290242, 0xC83396CE), U64(0x7E670471, 0x75A15271), /* ~= 10^205 */ U64(0x9F79A169, 0xBD203E41), U64(0x0F0062C6, 0xE984D386), /* ~= 10^206 */ U64(0xC75809C4, 0x2C684DD1), U64(0x52C07B78, 0xA3E60868), /* ~= 10^207 */ U64(0xF92E0C35, 0x37826145), U64(0xA7709A56, 0xCCDF8A82), /* ~= 10^208 */ U64(0x9BBCC7A1, 0x42B17CCB), U64(0x88A66076, 0x400BB691), /* ~= 10^209 */ U64(0xC2ABF989, 0x935DDBFE), U64(0x6ACFF893, 0xD00EA435), /* ~= 10^210 */ U64(0xF356F7EB, 0xF83552FE), U64(0x0583F6B8, 0xC4124D43), /* ~= 10^211 */ U64(0x98165AF3, 0x7B2153DE), U64(0xC3727A33, 0x7A8B704A), /* ~= 10^212 */ U64(0xBE1BF1B0, 0x59E9A8D6), U64(0x744F18C0, 0x592E4C5C), /* ~= 10^213 */ U64(0xEDA2EE1C, 0x7064130C), U64(0x1162DEF0, 0x6F79DF73), /* ~= 10^214 */ U64(0x9485D4D1, 0xC63E8BE7), U64(0x8ADDCB56, 0x45AC2BA8), /* ~= 10^215 */ U64(0xB9A74A06, 0x37CE2EE1), U64(0x6D953E2B, 0xD7173692), /* ~= 10^216 */ U64(0xE8111C87, 0xC5C1BA99), U64(0xC8FA8DB6, 0xCCDD0437), /* ~= 10^217 */ U64(0x910AB1D4, 0xDB9914A0), U64(0x1D9C9892, 0x400A22A2), /* ~= 10^218 */ U64(0xB54D5E4A, 0x127F59C8), U64(0x2503BEB6, 0xD00CAB4B), /* ~= 10^219 */ U64(0xE2A0B5DC, 0x971F303A), U64(0x2E44AE64, 0x840FD61D), /* ~= 10^220 */ U64(0x8DA471A9, 0xDE737E24), U64(0x5CEAECFE, 0xD289E5D2), /* ~= 10^221 */ U64(0xB10D8E14, 0x56105DAD), U64(0x7425A83E, 0x872C5F47), /* ~= 10^222 */ U64(0xDD50F199, 0x6B947518), U64(0xD12F124E, 0x28F77719), /* ~= 10^223 */ U64(0x8A5296FF, 0xE33CC92F), U64(0x82BD6B70, 0xD99AAA6F), /* ~= 10^224 */ U64(0xACE73CBF, 0xDC0BFB7B), U64(0x636CC64D, 0x1001550B), /* ~= 10^225 */ U64(0xD8210BEF, 0xD30EFA5A), U64(0x3C47F7E0, 0x5401AA4E), /* ~= 10^226 */ U64(0x8714A775, 0xE3E95C78), U64(0x65ACFAEC, 0x34810A71), /* ~= 10^227 */ U64(0xA8D9D153, 0x5CE3B396), U64(0x7F1839A7, 0x41A14D0D), /* ~= 10^228 */ U64(0xD31045A8, 0x341CA07C), U64(0x1EDE4811, 0x1209A050), /* ~= 10^229 */ U64(0x83EA2B89, 0x2091E44D), U64(0x934AED0A, 0xAB460432), /* ~= 10^230 */ U64(0xA4E4B66B, 0x68B65D60), U64(0xF81DA84D, 0x5617853F), /* ~= 10^231 */ U64(0xCE1DE406, 0x42E3F4B9), U64(0x36251260, 0xAB9D668E), /* ~= 10^232 */ U64(0x80D2AE83, 0xE9CE78F3), U64(0xC1D72B7C, 0x6B426019), /* ~= 10^233 */ U64(0xA1075A24, 0xE4421730), U64(0xB24CF65B, 0x8612F81F), /* ~= 10^234 */ U64(0xC94930AE, 0x1D529CFC), U64(0xDEE033F2, 0x6797B627), /* ~= 10^235 */ U64(0xFB9B7CD9, 0xA4A7443C), U64(0x169840EF, 0x017DA3B1), /* ~= 10^236 */ U64(0x9D412E08, 0x06E88AA5), U64(0x8E1F2895, 0x60EE864E), /* ~= 10^237 */ U64(0xC491798A, 0x08A2AD4E), U64(0xF1A6F2BA, 0xB92A27E2), /* ~= 10^238 */ U64(0xF5B5D7EC, 0x8ACB58A2), U64(0xAE10AF69, 0x6774B1DB), /* ~= 10^239 */ U64(0x9991A6F3, 0xD6BF1765), U64(0xACCA6DA1, 0xE0A8EF29), /* ~= 10^240 */ U64(0xBFF610B0, 0xCC6EDD3F), U64(0x17FD090A, 0x58D32AF3), /* ~= 10^241 */ U64(0xEFF394DC, 0xFF8A948E), U64(0xDDFC4B4C, 0xEF07F5B0), /* ~= 10^242 */ U64(0x95F83D0A, 0x1FB69CD9), U64(0x4ABDAF10, 0x1564F98E), /* ~= 10^243 */ U64(0xBB764C4C, 0xA7A4440F), U64(0x9D6D1AD4, 0x1ABE37F1), /* ~= 10^244 */ U64(0xEA53DF5F, 0xD18D5513), U64(0x84C86189, 0x216DC5ED), /* ~= 10^245 */ U64(0x92746B9B, 0xE2F8552C), U64(0x32FD3CF5, 0xB4E49BB4), /* ~= 10^246 */ U64(0xB7118682, 0xDBB66A77), U64(0x3FBC8C33, 0x221DC2A1), /* ~= 10^247 */ U64(0xE4D5E823, 0x92A40515), U64(0x0FABAF3F, 0xEAA5334A), /* ~= 10^248 */ U64(0x8F05B116, 0x3BA6832D), U64(0x29CB4D87, 0xF2A7400E), /* ~= 10^249 */ U64(0xB2C71D5B, 0xCA9023F8), U64(0x743E20E9, 0xEF511012), /* ~= 10^250 */ U64(0xDF78E4B2, 0xBD342CF6), U64(0x914DA924, 0x6B255416), /* ~= 10^251 */ U64(0x8BAB8EEF, 0xB6409C1A), U64(0x1AD089B6, 0xC2F7548E), /* ~= 10^252 */ U64(0xAE9672AB, 0xA3D0C320), U64(0xA184AC24, 0x73B529B1), /* ~= 10^253 */ U64(0xDA3C0F56, 0x8CC4F3E8), U64(0xC9E5D72D, 0x90A2741E), /* ~= 10^254 */ U64(0x88658996, 0x17FB1871), U64(0x7E2FA67C, 0x7A658892), /* ~= 10^255 */ U64(0xAA7EEBFB, 0x9DF9DE8D), U64(0xDDBB901B, 0x98FEEAB7), /* ~= 10^256 */ U64(0xD51EA6FA, 0x85785631), U64(0x552A7422, 0x7F3EA565), /* ~= 10^257 */ U64(0x8533285C, 0x936B35DE), U64(0xD53A8895, 0x8F87275F), /* ~= 10^258 */ U64(0xA67FF273, 0xB8460356), U64(0x8A892ABA, 0xF368F137), /* ~= 10^259 */ U64(0xD01FEF10, 0xA657842C), U64(0x2D2B7569, 0xB0432D85), /* ~= 10^260 */ U64(0x8213F56A, 0x67F6B29B), U64(0x9C3B2962, 0x0E29FC73), /* ~= 10^261 */ U64(0xA298F2C5, 0x01F45F42), U64(0x8349F3BA, 0x91B47B8F), /* ~= 10^262 */ U64(0xCB3F2F76, 0x42717713), U64(0x241C70A9, 0x36219A73), /* ~= 10^263 */ U64(0xFE0EFB53, 0xD30DD4D7), U64(0xED238CD3, 0x83AA0110), /* ~= 10^264 */ U64(0x9EC95D14, 0x63E8A506), U64(0xF4363804, 0x324A40AA), /* ~= 10^265 */ U64(0xC67BB459, 0x7CE2CE48), U64(0xB143C605, 0x3EDCD0D5), /* ~= 10^266 */ U64(0xF81AA16F, 0xDC1B81DA), U64(0xDD94B786, 0x8E94050A), /* ~= 10^267 */ U64(0x9B10A4E5, 0xE9913128), U64(0xCA7CF2B4, 0x191C8326), /* ~= 10^268 */ U64(0xC1D4CE1F, 0x63F57D72), U64(0xFD1C2F61, 0x1F63A3F0), /* ~= 10^269 */ U64(0xF24A01A7, 0x3CF2DCCF), U64(0xBC633B39, 0x673C8CEC), /* ~= 10^270 */ U64(0x976E4108, 0x8617CA01), U64(0xD5BE0503, 0xE085D813), /* ~= 10^271 */ U64(0xBD49D14A, 0xA79DBC82), U64(0x4B2D8644, 0xD8A74E18), /* ~= 10^272 */ U64(0xEC9C459D, 0x51852BA2), U64(0xDDF8E7D6, 0x0ED1219E), /* ~= 10^273 */ U64(0x93E1AB82, 0x52F33B45), U64(0xCABB90E5, 0xC942B503), /* ~= 10^274 */ U64(0xB8DA1662, 0xE7B00A17), U64(0x3D6A751F, 0x3B936243), /* ~= 10^275 */ U64(0xE7109BFB, 0xA19C0C9D), U64(0x0CC51267, 0x0A783AD4), /* ~= 10^276 */ U64(0x906A617D, 0x450187E2), U64(0x27FB2B80, 0x668B24C5), /* ~= 10^277 */ U64(0xB484F9DC, 0x9641E9DA), U64(0xB1F9F660, 0x802DEDF6), /* ~= 10^278 */ U64(0xE1A63853, 0xBBD26451), U64(0x5E7873F8, 0xA0396973), /* ~= 10^279 */ U64(0x8D07E334, 0x55637EB2), U64(0xDB0B487B, 0x6423E1E8), /* ~= 10^280 */ U64(0xB049DC01, 0x6ABC5E5F), U64(0x91CE1A9A, 0x3D2CDA62), /* ~= 10^281 */ U64(0xDC5C5301, 0xC56B75F7), U64(0x7641A140, 0xCC7810FB), /* ~= 10^282 */ U64(0x89B9B3E1, 0x1B6329BA), U64(0xA9E904C8, 0x7FCB0A9D), /* ~= 10^283 */ U64(0xAC2820D9, 0x623BF429), U64(0x546345FA, 0x9FBDCD44), /* ~= 10^284 */ U64(0xD732290F, 0xBACAF133), U64(0xA97C1779, 0x47AD4095), /* ~= 10^285 */ U64(0x867F59A9, 0xD4BED6C0), U64(0x49ED8EAB, 0xCCCC485D), /* ~= 10^286 */ U64(0xA81F3014, 0x49EE8C70), U64(0x5C68F256, 0xBFFF5A74), /* ~= 10^287 */ U64(0xD226FC19, 0x5C6A2F8C), U64(0x73832EEC, 0x6FFF3111), /* ~= 10^288 */ U64(0x83585D8F, 0xD9C25DB7), U64(0xC831FD53, 0xC5FF7EAB), /* ~= 10^289 */ U64(0xA42E74F3, 0xD032F525), U64(0xBA3E7CA8, 0xB77F5E55), /* ~= 10^290 */ U64(0xCD3A1230, 0xC43FB26F), U64(0x28CE1BD2, 0xE55F35EB), /* ~= 10^291 */ U64(0x80444B5E, 0x7AA7CF85), U64(0x7980D163, 0xCF5B81B3), /* ~= 10^292 */ U64(0xA0555E36, 0x1951C366), U64(0xD7E105BC, 0xC332621F), /* ~= 10^293 */ U64(0xC86AB5C3, 0x9FA63440), U64(0x8DD9472B, 0xF3FEFAA7), /* ~= 10^294 */ U64(0xFA856334, 0x878FC150), U64(0xB14F98F6, 0xF0FEB951), /* ~= 10^295 */ U64(0x9C935E00, 0xD4B9D8D2), U64(0x6ED1BF9A, 0x569F33D3), /* ~= 10^296 */ U64(0xC3B83581, 0x09E84F07), U64(0x0A862F80, 0xEC4700C8), /* ~= 10^297 */ U64(0xF4A642E1, 0x4C6262C8), U64(0xCD27BB61, 0x2758C0FA), /* ~= 10^298 */ U64(0x98E7E9CC, 0xCFBD7DBD), U64(0x8038D51C, 0xB897789C), /* ~= 10^299 */ U64(0xBF21E440, 0x03ACDD2C), U64(0xE0470A63, 0xE6BD56C3), /* ~= 10^300 */ U64(0xEEEA5D50, 0x04981478), U64(0x1858CCFC, 0xE06CAC74), /* ~= 10^301 */ U64(0x95527A52, 0x02DF0CCB), U64(0x0F37801E, 0x0C43EBC8), /* ~= 10^302 */ U64(0xBAA718E6, 0x8396CFFD), U64(0xD3056025, 0x8F54E6BA), /* ~= 10^303 */ U64(0xE950DF20, 0x247C83FD), U64(0x47C6B82E, 0xF32A2069), /* ~= 10^304 */ U64(0x91D28B74, 0x16CDD27E), U64(0x4CDC331D, 0x57FA5441), /* ~= 10^305 */ U64(0xB6472E51, 0x1C81471D), U64(0xE0133FE4, 0xADF8E952), /* ~= 10^306 */ U64(0xE3D8F9E5, 0x63A198E5), U64(0x58180FDD, 0xD97723A6), /* ~= 10^307 */ U64(0x8E679C2F, 0x5E44FF8F), U64(0x570F09EA, 0xA7EA7648), /* ~= 10^308 */ U64(0xB201833B, 0x35D63F73), U64(0x2CD2CC65, 0x51E513DA), /* ~= 10^309 */ U64(0xDE81E40A, 0x034BCF4F), U64(0xF8077F7E, 0xA65E58D1), /* ~= 10^310 */ U64(0x8B112E86, 0x420F6191), U64(0xFB04AFAF, 0x27FAF782), /* ~= 10^311 */ U64(0xADD57A27, 0xD29339F6), U64(0x79C5DB9A, 0xF1F9B563), /* ~= 10^312 */ U64(0xD94AD8B1, 0xC7380874), U64(0x18375281, 0xAE7822BC), /* ~= 10^313 */ U64(0x87CEC76F, 0x1C830548), U64(0x8F229391, 0x0D0B15B5), /* ~= 10^314 */ U64(0xA9C2794A, 0xE3A3C69A), U64(0xB2EB3875, 0x504DDB22), /* ~= 10^315 */ U64(0xD433179D, 0x9C8CB841), U64(0x5FA60692, 0xA46151EB), /* ~= 10^316 */ U64(0x849FEEC2, 0x81D7F328), U64(0xDBC7C41B, 0xA6BCD333), /* ~= 10^317 */ U64(0xA5C7EA73, 0x224DEFF3), U64(0x12B9B522, 0x906C0800), /* ~= 10^318 */ U64(0xCF39E50F, 0xEAE16BEF), U64(0xD768226B, 0x34870A00), /* ~= 10^319 */ U64(0x81842F29, 0xF2CCE375), U64(0xE6A11583, 0x00D46640), /* ~= 10^320 */ U64(0xA1E53AF4, 0x6F801C53), U64(0x60495AE3, 0xC1097FD0), /* ~= 10^321 */ U64(0xCA5E89B1, 0x8B602368), U64(0x385BB19C, 0xB14BDFC4), /* ~= 10^322 */ U64(0xFCF62C1D, 0xEE382C42), U64(0x46729E03, 0xDD9ED7B5), /* ~= 10^323 */ U64(0x9E19DB92, 0xB4E31BA9), U64(0x6C07A2C2, 0x6A8346D1) /* ~= 10^324 */ }; /** Get the cached pow10 value from pow10_sig_table. @param exp10 The exponent of pow(10, e). This value must in range POW10_SIG_TABLE_MIN_EXP to POW10_SIG_TABLE_MAX_EXP. @param hi The highest 64 bits of pow(10, e). @param lo The lower 64 bits after `hi`. */ static_inline void pow10_table_get_sig(i32 exp10, u64 *hi, u64 *lo) { i32 idx = exp10 - (POW10_SIG_TABLE_MIN_EXP); *hi = pow10_sig_table[idx * 2]; *lo = pow10_sig_table[idx * 2 + 1]; } /** Get the exponent (base 2) for highest 64 bits significand in pow10_sig_table. */ static_inline void pow10_table_get_exp(i32 exp10, i32 *exp2) { /* e2 = floor(log2(pow(10, e))) - 64 + 1 */ /* = floor(e * log2(10) - 63) */ *exp2 = (exp10 * 217706 - 4128768) >> 16; } #endif #if !YYJSON_DISABLE_READER /*============================================================================== * JSON Character Matcher *============================================================================*/ /** Character type */ typedef u8 char_type; /** Whitespace character: ' ', '\\t', '\\n', '\\r'. */ static const char_type CHAR_TYPE_SPACE = 1 << 0; /** Number character: '-', [0-9]. */ static const char_type CHAR_TYPE_NUMBER = 1 << 1; /** JSON Escaped character: '"', '\', [0x00-0x1F]. */ static const char_type CHAR_TYPE_ESC_ASCII = 1 << 2; /** Non-ASCII character: [0x80-0xFF]. */ static const char_type CHAR_TYPE_NON_ASCII = 1 << 3; /** JSON container character: '{', '['. */ static const char_type CHAR_TYPE_CONTAINER = 1 << 4; /** Comment character: '/'. */ static const char_type CHAR_TYPE_COMMENT = 1 << 5; /** Line end character: '\\n', '\\r', '\0'. */ static const char_type CHAR_TYPE_LINE_END = 1 << 6; /** Hexadecimal numeric character: [0-9a-fA-F]. */ static const char_type CHAR_TYPE_HEX = 1 << 7; /** Character type table (generate with misc/make_tables.c) */ static const char_type char_table[256] = { 0x44, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x45, 0x04, 0x04, 0x45, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }; /** Match a character with specified type. */ static_inline bool char_is_type(u8 c, char_type type) { return (char_table[c] & type) != 0; } /** Match a whitespace: ' ', '\\t', '\\n', '\\r'. */ static_inline bool char_is_space(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_SPACE); } /** Match a whitespace or comment: ' ', '\\t', '\\n', '\\r', '/'. */ static_inline bool char_is_space_or_comment(u8 c) { return char_is_type(c, (char_type)(CHAR_TYPE_SPACE | CHAR_TYPE_COMMENT)); } /** Match a JSON number: '-', [0-9]. */ static_inline bool char_is_number(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_NUMBER); } /** Match a JSON container: '{', '['. */ static_inline bool char_is_container(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_CONTAINER); } /** Match a stop character in ASCII string: '"', '\', [0x00-0x1F,0x80-0xFF]. */ static_inline bool char_is_ascii_stop(u8 c) { return char_is_type(c, (char_type)(CHAR_TYPE_ESC_ASCII | CHAR_TYPE_NON_ASCII)); } /** Match a line end character: '\\n', '\\r', '\0'. */ static_inline bool char_is_line_end(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_LINE_END); } /** Match a hexadecimal numeric character: [0-9a-fA-F]. */ static_inline bool char_is_hex(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_HEX); } /*============================================================================== * Digit Character Matcher *============================================================================*/ /** Digit type */ typedef u8 digi_type; /** Digit: '0'. */ static const digi_type DIGI_TYPE_ZERO = 1 << 0; /** Digit: [1-9]. */ static const digi_type DIGI_TYPE_NONZERO = 1 << 1; /** Plus sign (positive): '+'. */ static const digi_type DIGI_TYPE_POS = 1 << 2; /** Minus sign (negative): '-'. */ static const digi_type DIGI_TYPE_NEG = 1 << 3; /** Decimal point: '.' */ static const digi_type DIGI_TYPE_DOT = 1 << 4; /** Exponent sign: 'e, 'E'. */ static const digi_type DIGI_TYPE_EXP = 1 << 5; /** Digit type table (generate with misc/make_tables.c) */ static const digi_type digi_table[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x10, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /** Match a character with specified type. */ static_inline bool digi_is_type(u8 d, digi_type type) { return (digi_table[d] & type) != 0; } /** Match a sign: '+', '-' */ static_inline bool digi_is_sign(u8 d) { return digi_is_type(d, (digi_type)(DIGI_TYPE_POS | DIGI_TYPE_NEG)); } /** Match a none zero digit: [1-9] */ static_inline bool digi_is_nonzero(u8 d) { return digi_is_type(d, (digi_type)DIGI_TYPE_NONZERO); } /** Match a digit: [0-9] */ static_inline bool digi_is_digit(u8 d) { return digi_is_type(d, (digi_type)(DIGI_TYPE_ZERO | DIGI_TYPE_NONZERO)); } /** Match an exponent sign: 'e', 'E'. */ static_inline bool digi_is_exp(u8 d) { return digi_is_type(d, (digi_type)DIGI_TYPE_EXP); } /** Match a floating point indicator: '.', 'e', 'E'. */ static_inline bool digi_is_fp(u8 d) { return digi_is_type(d, (digi_type)(DIGI_TYPE_DOT | DIGI_TYPE_EXP)); } /** Match a digit or floating point indicator: [0-9], '.', 'e', 'E'. */ static_inline bool digi_is_digit_or_fp(u8 d) { return digi_is_type(d, (digi_type)(DIGI_TYPE_ZERO | DIGI_TYPE_NONZERO | DIGI_TYPE_DOT | DIGI_TYPE_EXP)); } /*============================================================================== * Hex Character Reader * This function is used by JSON reader to read escaped characters. *============================================================================*/ /** This table is used to convert 4 hex character sequence to a number. A valid hex character [0-9A-Fa-f] will mapped to it's raw number [0x00, 0x0F], an invalid hex character will mapped to [0xF0]. (generate with misc/make_tables.c) */ static const u8 hex_conv_table[256] = { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0 }; /** Scans an escaped character sequence as a UTF-16 code unit (branchless). e.g. "\\u005C" should pass "005C" as `cur`. This requires the string has 4-byte zero padding. */ static_inline bool read_hex_u16(const u8 *cur, u16 *val) { u16 c0, c1, c2, c3, t0, t1; c0 = hex_conv_table[cur[0]]; c1 = hex_conv_table[cur[1]]; c2 = hex_conv_table[cur[2]]; c3 = hex_conv_table[cur[3]]; t0 = (u16)((c0 << 8) | c2); t1 = (u16)((c1 << 8) | c3); *val = (u16)((t0 << 4) | t1); return ((t0 | t1) & (u16)0xF0F0) == 0; } /*============================================================================== * JSON Reader Utils * These functions are used by JSON reader to read literals and comments. *============================================================================*/ /** Read 'true' literal, '*cur' should be 't'. */ static_inline bool read_true(u8 **ptr, yyjson_val *val) { u8 *cur = *ptr; u8 **end = ptr; if (likely(byte_match_4(cur, "true"))) { val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; *end = cur + 4; return true; } return false; } /** Read 'false' literal, '*cur' should be 'f'. */ static_inline bool read_false(u8 **ptr, yyjson_val *val) { u8 *cur = *ptr; u8 **end = ptr; if (likely(byte_match_4(cur + 1, "alse"))) { val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; *end = cur + 5; return true; } return false; } /** Read 'null' literal, '*cur' should be 'n'. */ static_inline bool read_null(u8 **ptr, yyjson_val *val) { u8 *cur = *ptr; u8 **end = ptr; if (likely(byte_match_4(cur, "null"))) { val->tag = YYJSON_TYPE_NULL; *end = cur + 4; return true; } return false; } /** Read 'Inf' or 'Infinity' literal (ignoring case). */ static_inline bool read_inf(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { #if !YYJSON_DISABLE_NON_STANDARD u8 *hdr = *ptr - sign; u8 *cur = *ptr; u8 **end = ptr; if ((cur[0] == 'I' || cur[0] == 'i') && (cur[1] == 'N' || cur[1] == 'n') && (cur[2] == 'F' || cur[2] == 'f')) { if ((cur[3] == 'I' || cur[3] == 'i') && (cur[4] == 'N' || cur[4] == 'n') && (cur[5] == 'I' || cur[5] == 'i') && (cur[6] == 'T' || cur[6] == 't') && (cur[7] == 'Y' || cur[7] == 'y')) { cur += 8; } else { cur += 3; } *end = cur; if (pre) { /* add null-terminator for previous raw string */ if (*pre) **pre = '\0'; *pre = cur; val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; val->uni.str = (const char *)hdr; } else { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.u64 = f64_raw_get_inf(sign); } return true; } #endif return false; } /** Read 'NaN' literal (ignoring case). */ static_inline bool read_nan(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { #if !YYJSON_DISABLE_NON_STANDARD u8 *hdr = *ptr - sign; u8 *cur = *ptr; u8 **end = ptr; if ((cur[0] == 'N' || cur[0] == 'n') && (cur[1] == 'A' || cur[1] == 'a') && (cur[2] == 'N' || cur[2] == 'n')) { cur += 3; *end = cur; if (pre) { /* add null-terminator for previous raw string */ if (*pre) **pre = '\0'; *pre = cur; val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; val->uni.str = (const char *)hdr; } else { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.u64 = f64_raw_get_nan(sign); } return true; } #endif return false; } /** Read 'Inf', 'Infinity' or 'NaN' literal (ignoring case). */ static_inline bool read_inf_or_nan(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { if (read_inf(sign, ptr, pre, val)) return true; if (read_nan(sign, ptr, pre, val)) return true; return false; } /** Read a JSON number as raw string. */ static_noinline bool read_number_raw(u8 **ptr, u8 **pre, yyjson_read_flag flg, yyjson_val *val, const char **msg) { #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) #define return_raw() do { \ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ val->uni.str = (const char *)hdr; \ *pre = cur; *end = cur; return true; \ } while (false) u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; /* add null-terminator for previous raw string */ if (*pre) **pre = '\0'; /* skip sign */ cur += (*cur == '-'); /* read first digit, check leading zero */ if (unlikely(!digi_is_digit(*cur))) { if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) { if (read_inf_or_nan(*hdr == '-', &cur, pre, val)) return_raw(); } return_err(cur, "no digit after minus sign"); } /* read integral part */ if (*cur == '0') { cur++; if (unlikely(digi_is_digit(*cur))) { return_err(cur - 1, "number with leading zero is not allowed"); } if (!digi_is_fp(*cur)) return_raw(); } else { while (digi_is_digit(*cur)) cur++; if (!digi_is_fp(*cur)) return_raw(); } /* read fraction part */ if (*cur == '.') { cur++; if (!digi_is_digit(*cur++)) { return_err(cur, "no digit after decimal point"); } while (digi_is_digit(*cur)) cur++; } /* read exponent part */ if (digi_is_exp(*cur)) { cur += 1 + digi_is_sign(cur[1]); if (!digi_is_digit(*cur++)) { return_err(cur, "no digit after exponent sign"); } while (digi_is_digit(*cur)) cur++; } return_raw(); #undef return_err #undef return_raw } /** Skips spaces and comments as many as possible. It will return false in these cases: 1. No character is skipped. The 'end' pointer is set as input cursor. 2. A multiline comment is not closed. The 'end' pointer is set as the head of this comment block. */ static_noinline bool skip_spaces_and_comments(u8 **ptr) { u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; while (true) { if (byte_match_2(cur, "/*")) { hdr = cur; cur += 2; while (true) { if (byte_match_2(cur, "*/")) { cur += 2; break; } if (*cur == 0) { *end = hdr; return false; } cur++; } continue; } if (byte_match_2(cur, "//")) { cur += 2; while (!char_is_line_end(*cur)) cur++; continue; } if (char_is_space(*cur)) { cur += 1; while (char_is_space(*cur)) cur++; continue; } break; } *end = cur; return hdr != cur; } /** Check truncated string. Returns true if `cur` match `str` but is truncated. */ static_inline bool is_truncated_str(u8 *cur, u8 *end, const char *str, bool case_sensitive) { usize len = strlen(str); if (cur + len <= end || end <= cur) return false; if (case_sensitive) { return memcmp(cur, str, (usize)(end - cur)) == 0; } for (; cur < end; cur++, str++) { if ((*cur != (u8)*str) && (*cur != (u8)*str - 'a' + 'A')) { return false; } } return true; } /** Check truncated JSON on parsing errors. Returns true if the input is valid but truncated. */ static_noinline bool is_truncated_end(u8 *hdr, u8 *cur, u8 *end, yyjson_read_code code, yyjson_read_flag flg) { if (cur >= end) return true; if (code == YYJSON_READ_ERROR_LITERAL) { if (is_truncated_str(cur, end, "true", true) || is_truncated_str(cur, end, "false", true) || is_truncated_str(cur, end, "null", true)) { return true; } } if (code == YYJSON_READ_ERROR_UNEXPECTED_CHARACTER || code == YYJSON_READ_ERROR_INVALID_NUMBER || code == YYJSON_READ_ERROR_LITERAL) { if ((flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (*cur == '-') cur++; if (is_truncated_str(cur, end, "infinity", false) || is_truncated_str(cur, end, "nan", false)) { return true; } } } if (code == YYJSON_READ_ERROR_UNEXPECTED_CONTENT) { if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) { if (hdr + 3 <= cur && is_truncated_str(cur - 3, end, "infinity", false)) { return true; /* e.g. infin would be read as inf + in */ } } } if (code == YYJSON_READ_ERROR_INVALID_STRING) { usize len = (usize)(end - cur); /* unicode escape sequence */ if (*cur == '\\') { if (len == 1) return true; if (len <= 5) { if (*++cur != 'u') return false; for (++cur; cur < end; cur++) { if (!char_is_hex(*cur)) return false; } return true; } return false; } /* 2 to 4 bytes UTF-8, see `read_string()` for details. */ if (*cur & 0x80) { u8 c0 = cur[0], c1 = cur[1], c2 = cur[2]; if (len == 1) { /* 2 bytes UTF-8, truncated */ if ((c0 & 0xE0) == 0xC0 && (c0 & 0x1E) != 0x00) return true; /* 3 bytes UTF-8, truncated */ if ((c0 & 0xF0) == 0xE0) return true; /* 4 bytes UTF-8, truncated */ if ((c0 & 0xF8) == 0xF0 && (c0 & 0x07) <= 0x04) return true; } if (len == 2) { /* 3 bytes UTF-8, truncated */ if ((c0 & 0xF0) == 0xE0 && (c1 & 0xC0) == 0x80) { u8 pat = (u8)(((c0 & 0x0F) << 1) | ((c1 & 0x20) >> 5)); return 0x01 <= pat && pat != 0x1B; } /* 4 bytes UTF-8, truncated */ if ((c0 & 0xF8) == 0xF0 && (c1 & 0xC0) == 0x80) { u8 pat = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4)); return 0x01 <= pat && pat <= 0x10; } } if (len == 3) { /* 4 bytes UTF-8, truncated */ if ((c0 & 0xF8) == 0xF0 && (c1 & 0xC0) == 0x80 && (c2 & 0xC0) == 0x80) { u8 pat = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4)); return 0x01 <= pat && pat <= 0x10; } } } } return false; } #if YYJSON_HAS_IEEE_754 && !YYJSON_DISABLE_FAST_FP_CONV /* FP_READER */ /*============================================================================== * BigInt For Floating Point Number Reader * * The bigint algorithm is used by floating-point number reader to get correctly * rounded result for numbers with lots of digits. This part of code is rarely * used for common numbers. *============================================================================*/ /** Maximum exponent of exact pow10 */ #define U64_POW10_MAX_EXP 19 /** Table: [ 10^0, ..., 10^19 ] (generate with misc/make_tables.c) */ static const u64 u64_pow10_table[U64_POW10_MAX_EXP + 1] = { U64(0x00000000, 0x00000001), U64(0x00000000, 0x0000000A), U64(0x00000000, 0x00000064), U64(0x00000000, 0x000003E8), U64(0x00000000, 0x00002710), U64(0x00000000, 0x000186A0), U64(0x00000000, 0x000F4240), U64(0x00000000, 0x00989680), U64(0x00000000, 0x05F5E100), U64(0x00000000, 0x3B9ACA00), U64(0x00000002, 0x540BE400), U64(0x00000017, 0x4876E800), U64(0x000000E8, 0xD4A51000), U64(0x00000918, 0x4E72A000), U64(0x00005AF3, 0x107A4000), U64(0x00038D7E, 0xA4C68000), U64(0x002386F2, 0x6FC10000), U64(0x01634578, 0x5D8A0000), U64(0x0DE0B6B3, 0xA7640000), U64(0x8AC72304, 0x89E80000) }; /** Maximum numbers of chunks used by a bigint (58 is enough here). */ #define BIGINT_MAX_CHUNKS 64 /** Unsigned arbitrarily large integer */ typedef struct bigint { u32 used; /* used chunks count, should not be 0 */ u64 bits[BIGINT_MAX_CHUNKS]; /* chunks */ } bigint; /** Evaluate 'big += val'. @param big A big number (can be 0). @param val An unsigned integer (can be 0). */ static_inline void bigint_add_u64(bigint *big, u64 val) { u32 idx, max; u64 num = big->bits[0]; u64 add = num + val; big->bits[0] = add; if (likely((add >= num) || (add >= val))) return; for ((void)(idx = 1), max = big->used; idx < max; idx++) { if (likely(big->bits[idx] != U64_MAX)) { big->bits[idx] += 1; return; } big->bits[idx] = 0; } big->bits[big->used++] = 1; } /** Evaluate 'big *= val'. @param big A big number (can be 0). @param val An unsigned integer (cannot be 0). */ static_inline void bigint_mul_u64(bigint *big, u64 val) { u32 idx = 0, max = big->used; u64 hi, lo, carry = 0; for (; idx < max; idx++) { if (big->bits[idx]) break; } for (; idx < max; idx++) { u128_mul_add(big->bits[idx], val, carry, &hi, &lo); big->bits[idx] = lo; carry = hi; } if (carry) big->bits[big->used++] = carry; } /** Evaluate 'big *= 2^exp'. @param big A big number (can be 0). @param exp An exponent integer (can be 0). */ static_inline void bigint_mul_pow2(bigint *big, u32 exp) { u32 shft = exp % 64; u32 move = exp / 64; u32 idx = big->used; if (unlikely(shft == 0)) { for (; idx > 0; idx--) { big->bits[idx + move - 1] = big->bits[idx - 1]; } big->used += move; while (move) big->bits[--move] = 0; } else { big->bits[idx] = 0; for (; idx > 0; idx--) { u64 num = big->bits[idx] << shft; num |= big->bits[idx - 1] >> (64 - shft); big->bits[idx + move] = num; } big->bits[move] = big->bits[0] << shft; big->used += move + (big->bits[big->used + move] > 0); while (move) big->bits[--move] = 0; } } /** Evaluate 'big *= 10^exp'. @param big A big number (can be 0). @param exp An exponent integer (cannot be 0). */ static_inline void bigint_mul_pow10(bigint *big, i32 exp) { for (; exp >= U64_POW10_MAX_EXP; exp -= U64_POW10_MAX_EXP) { bigint_mul_u64(big, u64_pow10_table[U64_POW10_MAX_EXP]); } if (exp) { bigint_mul_u64(big, u64_pow10_table[exp]); } } /** Compare two bigint. @return -1 if 'a < b', +1 if 'a > b', 0 if 'a == b'. */ static_inline i32 bigint_cmp(bigint *a, bigint *b) { u32 idx = a->used; if (a->used < b->used) return -1; if (a->used > b->used) return +1; while (idx-- > 0) { u64 av = a->bits[idx]; u64 bv = b->bits[idx]; if (av < bv) return -1; if (av > bv) return +1; } return 0; } /** Evaluate 'big = val'. @param big A big number (can be 0). @param val An unsigned integer (can be 0). */ static_inline void bigint_set_u64(bigint *big, u64 val) { big->used = 1; big->bits[0] = val; } /** Set a bigint with floating point number string. */ static_noinline void bigint_set_buf(bigint *big, u64 sig, i32 *exp, u8 *sig_cut, u8 *sig_end, u8 *dot_pos) { if (unlikely(!sig_cut)) { /* no digit cut, set significant part only */ bigint_set_u64(big, sig); return; } else { /* some digits were cut, read them from 'sig_cut' to 'sig_end' */ u8 *hdr = sig_cut; u8 *cur = hdr; u32 len = 0; u64 val = 0; bool dig_big_cut = false; bool has_dot = (hdr < dot_pos) & (dot_pos < sig_end); u32 dig_len_total = U64_SAFE_DIG + (u32)(sig_end - hdr) - has_dot; sig -= (*sig_cut >= '5'); /* sig was rounded before */ if (dig_len_total > F64_MAX_DEC_DIG) { dig_big_cut = true; sig_end -= dig_len_total - (F64_MAX_DEC_DIG + 1); sig_end -= (dot_pos + 1 == sig_end); dig_len_total = (F64_MAX_DEC_DIG + 1); } *exp -= (i32)dig_len_total - U64_SAFE_DIG; big->used = 1; big->bits[0] = sig; while (cur < sig_end) { if (likely(cur != dot_pos)) { val = val * 10 + (u8)(*cur++ - '0'); len++; if (unlikely(cur == sig_end && dig_big_cut)) { /* The last digit must be non-zero, */ /* set it to '1' for correct rounding. */ val = val - (val % 10) + 1; } if (len == U64_SAFE_DIG || cur == sig_end) { bigint_mul_pow10(big, (i32)len); bigint_add_u64(big, val); val = 0; len = 0; } } else { cur++; } } } } /*============================================================================== * Diy Floating Point *============================================================================*/ /** "Do It Yourself Floating Point" struct. */ typedef struct diy_fp { u64 sig; /* significand */ i32 exp; /* exponent, base 2 */ i32 pad; /* padding, useless */ } diy_fp; /** Get cached rounded diy_fp with pow(10, e) The input value must in range [POW10_SIG_TABLE_MIN_EXP, POW10_SIG_TABLE_MAX_EXP]. */ static_inline diy_fp diy_fp_get_cached_pow10(i32 exp10) { diy_fp fp; u64 sig_ext; pow10_table_get_sig(exp10, &fp.sig, &sig_ext); pow10_table_get_exp(exp10, &fp.exp); fp.sig += (sig_ext >> 63); return fp; } /** Returns fp * fp2. */ static_inline diy_fp diy_fp_mul(diy_fp fp, diy_fp fp2) { u64 hi, lo; u128_mul(fp.sig, fp2.sig, &hi, &lo); fp.sig = hi + (lo >> 63); fp.exp += fp2.exp + 64; return fp; } /** Convert diy_fp to IEEE-754 raw value. */ static_inline u64 diy_fp_to_ieee_raw(diy_fp fp) { u64 sig = fp.sig; i32 exp = fp.exp; u32 lz_bits; if (unlikely(fp.sig == 0)) return 0; lz_bits = u64_lz_bits(sig); sig <<= lz_bits; sig >>= F64_BITS - F64_SIG_FULL_BITS; exp -= (i32)lz_bits; exp += F64_BITS - F64_SIG_FULL_BITS; exp += F64_SIG_BITS; if (unlikely(exp >= F64_MAX_BIN_EXP)) { /* overflow */ return F64_RAW_INF; } else if (likely(exp >= F64_MIN_BIN_EXP - 1)) { /* normal */ exp += F64_EXP_BIAS; return ((u64)exp << F64_SIG_BITS) | (sig & F64_SIG_MASK); } else if (likely(exp >= F64_MIN_BIN_EXP - F64_SIG_FULL_BITS)) { /* subnormal */ return sig >> (F64_MIN_BIN_EXP - exp - 1); } else { /* underflow */ return 0; } } /*============================================================================== * JSON Number Reader (IEEE-754) *============================================================================*/ /** Maximum exact pow10 exponent for double value. */ #define F64_POW10_EXP_MAX_EXACT 22 /** Cached pow10 table. */ static const f64 f64_pow10_table[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 }; /** Read a JSON number. 1. This function assume that the floating-point number is in IEEE-754 format. 2. This function support uint64/int64/double number. If an integer number cannot fit in uint64/int64, it will returns as a double number. If a double number is infinite, the return value is based on flag. 3. This function (with inline attribute) may generate a lot of instructions. */ static_inline bool read_number(u8 **ptr, u8 **pre, yyjson_read_flag flg, yyjson_val *val, const char **msg) { #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) #define return_0() do { \ val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \ val->uni.u64 = 0; \ *end = cur; return true; \ } while (false) #define return_i64(_v) do { \ val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \ val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \ *end = cur; return true; \ } while (false) #define return_f64(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \ *end = cur; return true; \ } while (false) #define return_f64_bin(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \ *end = cur; return true; \ } while (false) #define return_inf() do { \ if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); \ if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) return_f64_bin(F64_RAW_INF); \ else return_err(hdr, "number is infinity when parsed as double"); \ } while (false) #define return_raw() do { \ if (*pre) **pre = '\0'; /* add null-terminator for previous raw string */ \ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ val->uni.str = (const char *)hdr; \ *pre = cur; *end = cur; return true; \ } while (false) u8 *sig_cut = NULL; /* significant part cutting position for long number */ u8 *sig_end = NULL; /* significant part ending position */ u8 *dot_pos = NULL; /* decimal point position */ u64 sig = 0; /* significant part of the number */ i32 exp = 0; /* exponent part of the number */ bool exp_sign; /* temporary exponent sign from literal part */ i64 exp_sig = 0; /* temporary exponent number from significant part */ i64 exp_lit = 0; /* temporary exponent number from exponent literal part */ u64 num; /* temporary number for reading */ u8 *tmp; /* temporary cursor for reading */ u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; bool sign; /* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */ if (unlikely(pre && !(flg & YYJSON_READ_BIGNUM_AS_RAW))) { return read_number_raw(ptr, pre, flg, val, msg); } sign = (*hdr == '-'); cur += sign; /* begin with a leading zero or non-digit */ if (unlikely(!digi_is_nonzero(*cur))) { /* 0 or non-digit char */ if (unlikely(*cur != '0')) { /* non-digit char */ if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) { if (read_inf_or_nan(sign, &cur, pre, val)) { *end = cur; return true; } } return_err(cur, "no digit after minus sign"); } /* begin with 0 */ if (likely(!digi_is_digit_or_fp(*++cur))) return_0(); if (likely(*cur == '.')) { dot_pos = cur++; if (unlikely(!digi_is_digit(*cur))) { return_err(cur, "no digit after decimal point"); } while (unlikely(*cur == '0')) cur++; if (likely(digi_is_digit(*cur))) { /* first non-zero digit after decimal point */ sig = (u64)(*cur - '0'); /* read first digit */ cur--; goto digi_frac_1; /* continue read fraction part */ } } if (unlikely(digi_is_digit(*cur))) { return_err(cur - 1, "number with leading zero is not allowed"); } if (unlikely(digi_is_exp(*cur))) { /* 0 with any exponent is still 0 */ cur += (usize)1 + digi_is_sign(cur[1]); if (unlikely(!digi_is_digit(*cur))) { return_err(cur, "no digit after exponent sign"); } while (digi_is_digit(*++cur)); } return_f64_bin(0); } /* begin with non-zero digit */ sig = (u64)(*cur - '0'); /* Read integral part, same as the following code. for (int i = 1; i <= 18; i++) { num = cur[i] - '0'; if (num <= 9) sig = num + sig * 10; else goto digi_sepr_i; } */ #define expr_intg(i) \ if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \ else { goto digi_sepr_##i; } repeat_in_1_18(expr_intg) #undef expr_intg cur += 19; /* skip continuous 19 digits */ if (!digi_is_digit_or_fp(*cur)) { /* this number is an integer consisting of 19 digits */ if (sign && (sig > ((u64)1 << 63))) { /* overflow */ if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } goto digi_intg_more; /* read more digits in integral part */ /* process first non-digit character */ #define expr_sepr(i) \ digi_sepr_##i: \ if (likely(!digi_is_fp(cur[i]))) { cur += i; return_i64(sig); } \ dot_pos = cur + i; \ if (likely(cur[i] == '.')) goto digi_frac_##i; \ cur += i; sig_end = cur; goto digi_exp_more; repeat_in_1_18(expr_sepr) #undef expr_sepr /* read fraction part */ #define expr_frac(i) \ digi_frac_##i: \ if (likely((num = (u64)(cur[i + 1] - (u8)'0')) <= 9)) \ sig = num + sig * 10; \ else { goto digi_stop_##i; } repeat_in_1_18(expr_frac) #undef expr_frac cur += 20; /* skip 19 digits and 1 decimal point */ if (!digi_is_digit(*cur)) goto digi_frac_end; /* fraction part end */ goto digi_frac_more; /* read more digits in fraction part */ /* significant part end */ #define expr_stop(i) \ digi_stop_##i: \ cur += i + 1; \ goto digi_frac_end; repeat_in_1_18(expr_stop) #undef expr_stop /* read more digits in integral part */ digi_intg_more: if (digi_is_digit(*cur)) { if (!digi_is_digit_or_fp(cur[1])) { /* this number is an integer consisting of 20 digits */ num = (u64)(*cur - '0'); if ((sig < (U64_MAX / 10)) || (sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) { sig = num + sig * 10; cur++; /* convert to double if overflow */ if (sign) { if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } } } if (digi_is_exp(*cur)) { dot_pos = cur; goto digi_exp_more; } if (*cur == '.') { dot_pos = cur++; if (!digi_is_digit(*cur)) { return_err(cur, "no digit after decimal point"); } } /* read more digits in fraction part */ digi_frac_more: sig_cut = cur; /* too large to fit in u64, excess digits need to be cut */ sig += (*cur >= '5'); /* round */ while (digi_is_digit(*++cur)); if (!dot_pos) { if (!digi_is_fp(*cur) && (flg & YYJSON_READ_BIGNUM_AS_RAW)) { return_raw(); /* it's a large integer */ } dot_pos = cur; if (*cur == '.') { if (!digi_is_digit(*++cur)) { return_err(cur, "no digit after decimal point"); } while (digi_is_digit(*cur)) cur++; } } exp_sig = (i64)(dot_pos - sig_cut); exp_sig += (dot_pos < sig_cut); /* ignore trailing zeros */ tmp = cur - 1; while (*tmp == '0' || *tmp == '.') tmp--; if (tmp < sig_cut) { sig_cut = NULL; } else { sig_end = cur; } if (digi_is_exp(*cur)) goto digi_exp_more; goto digi_exp_finish; /* fraction part end */ digi_frac_end: if (unlikely(dot_pos + 1 == cur)) { return_err(cur, "no digit after decimal point"); } sig_end = cur; exp_sig = -(i64)((u64)(cur - dot_pos) - 1); if (likely(!digi_is_exp(*cur))) { if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) { return_f64_bin(0); /* underflow */ } exp = (i32)exp_sig; goto digi_finish; } else { goto digi_exp_more; } /* read exponent part */ digi_exp_more: exp_sign = (*++cur == '-'); cur += digi_is_sign(*cur); if (unlikely(!digi_is_digit(*cur))) { return_err(cur, "no digit after exponent sign"); } while (*cur == '0') cur++; /* read exponent literal */ tmp = cur; while (digi_is_digit(*cur)) { exp_lit = (i64)((u8)(*cur++ - '0') + (u64)exp_lit * 10); } if (unlikely(cur - tmp >= U64_SAFE_DIG)) { if (exp_sign) { return_f64_bin(0); /* underflow */ } else { return_inf(); /* overflow */ } } exp_sig += exp_sign ? -exp_lit : exp_lit; /* validate exponent value */ digi_exp_finish: if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) { return_f64_bin(0); /* underflow */ } if (unlikely(exp_sig > F64_MAX_DEC_EXP)) { return_inf(); /* overflow */ } exp = (i32)exp_sig; /* all digit read finished */ digi_finish: /* Fast path 1: 1. The floating-point number calculation should be accurate, see the comments of macro `YYJSON_DOUBLE_MATH_CORRECT`. 2. Correct rounding should be performed (fegetround() == FE_TONEAREST). 3. The input of floating point number calculation does not lose precision, which means: 64 - leading_zero(input) - trailing_zero(input) < 53. We don't check all available inputs here, because that would make the code more complicated, and not friendly to branch predictor. */ #if YYJSON_DOUBLE_MATH_CORRECT if (sig < ((u64)1 << 53) && exp >= -F64_POW10_EXP_MAX_EXACT && exp <= +F64_POW10_EXP_MAX_EXACT) { f64 dbl = (f64)sig; if (exp < 0) { dbl /= f64_pow10_table[-exp]; } else { dbl *= f64_pow10_table[+exp]; } return_f64(dbl); } #endif /* Fast path 2: To keep it simple, we only accept normal number here, let the slow path to handle subnormal and infinity number. */ if (likely(!sig_cut && exp > -F64_MAX_DEC_EXP + 1 && exp < +F64_MAX_DEC_EXP - 20)) { /* The result value is exactly equal to (sig * 10^exp), the exponent part (10^exp) can be converted to (sig2 * 2^exp2). The sig2 can be an infinite length number, only the highest 128 bits is cached in the pow10_sig_table. Now we have these bits: sig1 (normalized 64bit) : aaaaaaaa sig2 (higher 64bit) : bbbbbbbb sig2_ext (lower 64bit) : cccccccc sig2_cut (extra unknown bits) : dddddddddddd.... And the calculation process is: ---------------------------------------- aaaaaaaa * bbbbbbbbccccccccdddddddddddd.... ---------------------------------------- abababababababab + acacacacacacacac + adadadadadadadadadad.... ---------------------------------------- [hi____][lo____] + [hi2___][lo2___] + [unknown___________....] ---------------------------------------- The addition with carry may affect higher bits, but if there is a 0 in higher bits, the bits higher than 0 will not be affected. `lo2` + `unknown` may get a carry bit and may affect `hi2`, the max value of `hi2` is 0xFFFFFFFFFFFFFFFE, so `hi2` will not overflow. `lo` + `hi2` may also get a carry bit and may affect `hi`, but only the highest significant 53 bits of `hi` is needed. If there is a 0 in the lower bits of `hi`, then all the following bits can be dropped. To convert the result to IEEE-754 double number, we need to perform correct rounding: 1. if bit 54 is 0, round down, 2. if bit 54 is 1 and any bit beyond bit 54 is 1, round up, 3. if bit 54 is 1 and all bits beyond bit 54 are 0, round to even, as the extra bits is unknown, this case will not be handled here. */ u64 raw; u64 sig1, sig2, sig2_ext, hi, lo, hi2, lo2, add, bits; i32 exp2; u32 lz; bool exact = false, carry, round_up; /* convert (10^exp) to (sig2 * 2^exp2) */ pow10_table_get_sig(exp, &sig2, &sig2_ext); pow10_table_get_exp(exp, &exp2); /* normalize and multiply */ lz = u64_lz_bits(sig); sig1 = sig << lz; exp2 -= (i32)lz; u128_mul(sig1, sig2, &hi, &lo); /* The `hi` is in range [0x4000000000000000, 0xFFFFFFFFFFFFFFFE], To get normalized value, `hi` should be shifted to the left by 0 or 1. The highest significant 53 bits is used by IEEE-754 double number, and the bit 54 is used to detect rounding direction. The lowest (64 - 54 - 1) bits is used to check whether it contains 0. */ bits = hi & (((u64)1 << (64 - 54 - 1)) - 1); if (bits - 1 < (((u64)1 << (64 - 54 - 1)) - 2)) { /* (bits != 0 && bits != 0x1FF) => (bits - 1 < 0x1FF - 1) The `bits` is not zero, so we don't need to check `round to even` case. The `bits` contains bit `0`, so we can drop the extra bits after `0`. */ exact = true; } else { /* (bits == 0 || bits == 0x1FF) The `bits` is filled with all `0` or all `1`, so we need to check lower bits with another 64-bit multiplication. */ u128_mul(sig1, sig2_ext, &hi2, &lo2); add = lo + hi2; if (add + 1 > (u64)1) { /* (add != 0 && add != U64_MAX) => (add + 1 > 1) The `add` is not zero, so we don't need to check `round to even` case. The `add` contains bit `0`, so we can drop the extra bits after `0`. The `hi` cannot be U64_MAX, so it will not overflow. */ carry = add < lo || add < hi2; hi += carry; exact = true; } } if (exact) { /* normalize */ lz = hi < ((u64)1 << 63); hi <<= lz; exp2 -= (i32)lz; exp2 += 64; /* test the bit 54 and get rounding direction */ round_up = (hi & ((u64)1 << (64 - 54))) > (u64)0; hi += (round_up ? ((u64)1 << (64 - 54)) : (u64)0); /* test overflow */ if (hi < ((u64)1 << (64 - 54))) { hi = ((u64)1 << 63); exp2 += 1; } /* This is a normal number, convert it to IEEE-754 format. */ hi >>= F64_BITS - F64_SIG_FULL_BITS; exp2 += F64_BITS - F64_SIG_FULL_BITS + F64_SIG_BITS; exp2 += F64_EXP_BIAS; raw = ((u64)exp2 << F64_SIG_BITS) | (hi & F64_SIG_MASK); return_f64_bin(raw); } } /* Slow path: read double number exactly with diyfp. 1. Use cached diyfp to get an approximation value. 2. Use bigcomp to check the approximation value if needed. This algorithm refers to google's double-conversion project: https://github.com/google/double-conversion */ { const i32 ERR_ULP_LOG = 3; const i32 ERR_ULP = 1 << ERR_ULP_LOG; const i32 ERR_CACHED_POW = ERR_ULP / 2; const i32 ERR_MUL_FIXED = ERR_ULP / 2; const i32 DIY_SIG_BITS = 64; const i32 EXP_BIAS = F64_EXP_BIAS + F64_SIG_BITS; const i32 EXP_SUBNORMAL = -EXP_BIAS + 1; u64 fp_err; u32 bits; i32 order_of_magnitude; i32 effective_significand_size; i32 precision_digits_count; u64 precision_bits; u64 half_way; u64 raw; diy_fp fp, fp_upper; bigint big_full, big_comp; i32 cmp; fp.sig = sig; fp.exp = 0; fp_err = sig_cut ? (u64)(ERR_ULP / 2) : (u64)0; /* normalize */ bits = u64_lz_bits(fp.sig); fp.sig <<= bits; fp.exp -= (i32)bits; fp_err <<= bits; /* multiply and add error */ fp = diy_fp_mul(fp, diy_fp_get_cached_pow10(exp)); fp_err += (u64)ERR_CACHED_POW + (fp_err != 0) + (u64)ERR_MUL_FIXED; /* normalize */ bits = u64_lz_bits(fp.sig); fp.sig <<= bits; fp.exp -= (i32)bits; fp_err <<= bits; /* effective significand */ order_of_magnitude = DIY_SIG_BITS + fp.exp; if (likely(order_of_magnitude >= EXP_SUBNORMAL + F64_SIG_FULL_BITS)) { effective_significand_size = F64_SIG_FULL_BITS; } else if (order_of_magnitude <= EXP_SUBNORMAL) { effective_significand_size = 0; } else { effective_significand_size = order_of_magnitude - EXP_SUBNORMAL; } /* precision digits count */ precision_digits_count = DIY_SIG_BITS - effective_significand_size; if (unlikely(precision_digits_count + ERR_ULP_LOG >= DIY_SIG_BITS)) { i32 shr = (precision_digits_count + ERR_ULP_LOG) - DIY_SIG_BITS + 1; fp.sig >>= shr; fp.exp += shr; fp_err = (fp_err >> shr) + 1 + (u32)ERR_ULP; precision_digits_count -= shr; } /* half way */ precision_bits = fp.sig & (((u64)1 << precision_digits_count) - 1); precision_bits *= (u32)ERR_ULP; half_way = (u64)1 << (precision_digits_count - 1); half_way *= (u32)ERR_ULP; /* rounding */ fp.sig >>= precision_digits_count; fp.sig += (precision_bits >= half_way + fp_err); fp.exp += precision_digits_count; /* get IEEE double raw value */ raw = diy_fp_to_ieee_raw(fp); if (unlikely(raw == F64_RAW_INF)) return_inf(); if (likely(precision_bits <= half_way - fp_err || precision_bits >= half_way + fp_err)) { return_f64_bin(raw); /* number is accurate */ } /* now the number is the correct value, or the next lower value */ /* upper boundary */ if (raw & F64_EXP_MASK) { fp_upper.sig = (raw & F64_SIG_MASK) + ((u64)1 << F64_SIG_BITS); fp_upper.exp = (i32)((raw & F64_EXP_MASK) >> F64_SIG_BITS); } else { fp_upper.sig = (raw & F64_SIG_MASK); fp_upper.exp = 1; } fp_upper.exp -= F64_EXP_BIAS + F64_SIG_BITS; fp_upper.sig <<= 1; fp_upper.exp -= 1; fp_upper.sig += 1; /* add half ulp */ /* compare with bigint */ bigint_set_buf(&big_full, sig, &exp, sig_cut, sig_end, dot_pos); bigint_set_u64(&big_comp, fp_upper.sig); if (exp >= 0) { bigint_mul_pow10(&big_full, +exp); } else { bigint_mul_pow10(&big_comp, -exp); } if (fp_upper.exp > 0) { bigint_mul_pow2(&big_comp, (u32)+fp_upper.exp); } else { bigint_mul_pow2(&big_full, (u32)-fp_upper.exp); } cmp = bigint_cmp(&big_full, &big_comp); if (likely(cmp != 0)) { /* round down or round up */ raw += (cmp > 0); } else { /* falls midway, round to even */ raw += (raw & 1); } if (unlikely(raw == F64_RAW_INF)) return_inf(); return_f64_bin(raw); } #undef return_err #undef return_inf #undef return_0 #undef return_i64 #undef return_f64 #undef return_f64_bin #undef return_raw } #else /* FP_READER */ /** Read a JSON number. This is a fallback function if the custom number reader is disabled. This function use libc's strtod() to read floating-point number. */ static_noinline bool read_number(u8 **ptr, u8 **pre, yyjson_read_flag flg, yyjson_val *val, const char **msg) { #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) #define return_0() do { \ val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \ val->uni.u64 = 0; \ *end = cur; return true; \ } while (false) #define return_i64(_v) do { \ val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \ val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \ *end = cur; return true; \ } while (false) #define return_f64(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \ *end = cur; return true; \ } while (false) #define return_f64_bin(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \ *end = cur; return true; \ } while (false) #define return_inf() do { \ if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); \ if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) return_f64_bin(F64_RAW_INF); \ else return_err(hdr, "number is infinity when parsed as double"); \ } while (false) #define return_raw() do { \ if (*pre) **pre = '\0'; /* add null-terminator for previous raw string */ \ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ val->uni.str = (const char *)hdr; \ *pre = cur; *end = cur; return true; \ } while (false) u64 sig, num; u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; u8 *dot = NULL; u8 *f64_end = NULL; bool sign; /* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */ if (unlikely(pre && !(flg & YYJSON_READ_BIGNUM_AS_RAW))) { return read_number_raw(ptr, pre, flg, val, msg); } sign = (*hdr == '-'); cur += sign; sig = (u8)(*cur - '0'); /* read first digit, check leading zero */ if (unlikely(!digi_is_digit(*cur))) { if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) { if (read_inf_or_nan(sign, &cur, pre, val)) { *end = cur; return true; } } return_err(cur, "no digit after minus sign"); } if (*cur == '0') { cur++; if (unlikely(digi_is_digit(*cur))) { return_err(cur - 1, "number with leading zero is not allowed"); } if (!digi_is_fp(*cur)) return_0(); goto read_double; } /* read continuous digits, up to 19 characters */ #define expr_intg(i) \ if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \ else { cur += i; goto intg_end; } repeat_in_1_18(expr_intg) #undef expr_intg /* here are 19 continuous digits, skip them */ cur += 19; if (digi_is_digit(cur[0]) && !digi_is_digit_or_fp(cur[1])) { /* this number is an integer consisting of 20 digits */ num = (u8)(*cur - '0'); if ((sig < (U64_MAX / 10)) || (sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) { sig = num + sig * 10; cur++; if (sign) { if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } } intg_end: /* continuous digits ended */ if (!digi_is_digit_or_fp(*cur)) { /* this number is an integer consisting of 1 to 19 digits */ if (sign && (sig > ((u64)1 << 63))) { if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } read_double: /* this number should be read as double */ while (digi_is_digit(*cur)) cur++; if (!digi_is_fp(*cur) && (flg & YYJSON_READ_BIGNUM_AS_RAW)) { return_raw(); /* it's a large integer */ } if (*cur == '.') { /* skip fraction part */ dot = cur; cur++; if (!digi_is_digit(*cur)) { return_err(cur, "no digit after decimal point"); } cur++; while (digi_is_digit(*cur)) cur++; } if (digi_is_exp(*cur)) { /* skip exponent part */ cur += 1 + digi_is_sign(cur[1]); if (!digi_is_digit(*cur)) { return_err(cur, "no digit after exponent sign"); } cur++; while (digi_is_digit(*cur)) cur++; } /* libc's strtod() is used to parse the floating-point number. Note that the decimal point character used by strtod() is locale-dependent, and the rounding direction may affected by fesetround(). For currently known locales, (en, zh, ja, ko, am, he, hi) use '.' as the decimal point, while other locales use ',' as the decimal point. Here strtod() is called twice for different locales, but if another thread happens calls setlocale() between two strtod(), parsing may still fail. */ val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end); if (unlikely(f64_end != cur)) { /* replace '.' with ',' for locale */ bool cut = (*cur == ','); if (cut) *cur = ' '; if (dot) *dot = ','; val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end); /* restore ',' to '.' */ if (cut) *cur = ','; if (dot) *dot = '.'; if (unlikely(f64_end != cur)) { return_err(hdr, "strtod() failed to parse the number"); } } if (unlikely(val->uni.f64 >= HUGE_VAL || val->uni.f64 <= -HUGE_VAL)) { return_inf(); } val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; *end = cur; return true; #undef return_err #undef return_0 #undef return_i64 #undef return_f64 #undef return_f64_bin #undef return_inf #undef return_raw } #endif /* FP_READER */ /*============================================================================== * JSON String Reader *============================================================================*/ /** Read a JSON string. @param ptr The head pointer of string before '"' prefix (inout). @param lst JSON last position. @param inv Allow invalid unicode. @param val The string value to be written. @param msg The error message pointer. @return Whether success. */ static_inline bool read_string(u8 **ptr, u8 *lst, bool inv, yyjson_val *val, const char **msg) { /* Each unicode code point is encoded as 1 to 4 bytes in UTF-8 encoding, we use 4-byte mask and pattern value to validate UTF-8 byte sequence, this requires the input data to have 4-byte zero padding. --------------------------------------------------- 1 byte unicode range [U+0000, U+007F] unicode min [.......0] unicode max [.1111111] bit pattern [0.......] --------------------------------------------------- 2 byte unicode range [U+0080, U+07FF] unicode min [......10 ..000000] unicode max [...11111 ..111111] bit require [...xxxx. ........] (1E 00) bit mask [xxx..... xx......] (E0 C0) bit pattern [110..... 10......] (C0 80) --------------------------------------------------- 3 byte unicode range [U+0800, U+FFFF] unicode min [........ ..100000 ..000000] unicode max [....1111 ..111111 ..111111] bit require [....xxxx ..x..... ........] (0F 20 00) bit mask [xxxx.... xx...... xx......] (F0 C0 C0) bit pattern [1110.... 10...... 10......] (E0 80 80) --------------------------------------------------- 3 byte invalid (reserved for surrogate halves) unicode range [U+D800, U+DFFF] unicode min [....1101 ..100000 ..000000] unicode max [....1101 ..111111 ..111111] bit mask [....xxxx ..x..... ........] (0F 20 00) bit pattern [....1101 ..1..... ........] (0D 20 00) --------------------------------------------------- 4 byte unicode range [U+10000, U+10FFFF] unicode min [........ ...10000 ..000000 ..000000] unicode max [.....100 ..001111 ..111111 ..111111] bit require [.....xxx ..xx.... ........ ........] (07 30 00 00) bit mask [xxxxx... xx...... xx...... xx......] (F8 C0 C0 C0) bit pattern [11110... 10...... 10...... 10......] (F0 80 80 80) --------------------------------------------------- */ #if YYJSON_ENDIAN == YYJSON_BIG_ENDIAN const u32 b1_mask = 0x80000000UL; const u32 b1_patt = 0x00000000UL; const u32 b2_mask = 0xE0C00000UL; const u32 b2_patt = 0xC0800000UL; const u32 b2_requ = 0x1E000000UL; const u32 b3_mask = 0xF0C0C000UL; const u32 b3_patt = 0xE0808000UL; const u32 b3_requ = 0x0F200000UL; const u32 b3_erro = 0x0D200000UL; const u32 b4_mask = 0xF8C0C0C0UL; const u32 b4_patt = 0xF0808080UL; const u32 b4_requ = 0x07300000UL; const u32 b4_err0 = 0x04000000UL; const u32 b4_err1 = 0x03300000UL; #elif YYJSON_ENDIAN == YYJSON_LITTLE_ENDIAN const u32 b1_mask = 0x00000080UL; const u32 b1_patt = 0x00000000UL; const u32 b2_mask = 0x0000C0E0UL; const u32 b2_patt = 0x000080C0UL; const u32 b2_requ = 0x0000001EUL; const u32 b3_mask = 0x00C0C0F0UL; const u32 b3_patt = 0x008080E0UL; const u32 b3_requ = 0x0000200FUL; const u32 b3_erro = 0x0000200DUL; const u32 b4_mask = 0xC0C0C0F8UL; const u32 b4_patt = 0x808080F0UL; const u32 b4_requ = 0x00003007UL; const u32 b4_err0 = 0x00000004UL; const u32 b4_err1 = 0x00003003UL; #else v32_uni b1_mask_uni = {{ 0x80, 0x00, 0x00, 0x00 }}; v32_uni b1_patt_uni = {{ 0x00, 0x00, 0x00, 0x00 }}; v32_uni b2_mask_uni = {{ 0xE0, 0xC0, 0x00, 0x00 }}; v32_uni b2_patt_uni = {{ 0xC0, 0x80, 0x00, 0x00 }}; v32_uni b2_requ_uni = {{ 0x1E, 0x00, 0x00, 0x00 }}; v32_uni b3_mask_uni = {{ 0xF0, 0xC0, 0xC0, 0x00 }}; v32_uni b3_patt_uni = {{ 0xE0, 0x80, 0x80, 0x00 }}; v32_uni b3_requ_uni = {{ 0x0F, 0x20, 0x00, 0x00 }}; v32_uni b3_erro_uni = {{ 0x0D, 0x20, 0x00, 0x00 }}; v32_uni b4_mask_uni = {{ 0xF8, 0xC0, 0xC0, 0xC0 }}; v32_uni b4_patt_uni = {{ 0xF0, 0x80, 0x80, 0x80 }}; v32_uni b4_requ_uni = {{ 0x07, 0x30, 0x00, 0x00 }}; v32_uni b4_err0_uni = {{ 0x04, 0x00, 0x00, 0x00 }}; v32_uni b4_err1_uni = {{ 0x03, 0x30, 0x00, 0x00 }}; u32 b1_mask = b1_mask_uni.u; u32 b1_patt = b1_patt_uni.u; u32 b2_mask = b2_mask_uni.u; u32 b2_patt = b2_patt_uni.u; u32 b2_requ = b2_requ_uni.u; u32 b3_mask = b3_mask_uni.u; u32 b3_patt = b3_patt_uni.u; u32 b3_requ = b3_requ_uni.u; u32 b3_erro = b3_erro_uni.u; u32 b4_mask = b4_mask_uni.u; u32 b4_patt = b4_patt_uni.u; u32 b4_requ = b4_requ_uni.u; u32 b4_err0 = b4_err0_uni.u; u32 b4_err1 = b4_err1_uni.u; #endif #define is_valid_seq_1(uni) ( \ ((uni & b1_mask) == b1_patt) \ ) #define is_valid_seq_2(uni) ( \ ((uni & b2_mask) == b2_patt) && \ ((uni & b2_requ)) \ ) #define is_valid_seq_3(uni) ( \ ((uni & b3_mask) == b3_patt) && \ ((tmp = (uni & b3_requ))) && \ ((tmp != b3_erro)) \ ) #define is_valid_seq_4(uni) ( \ ((uni & b4_mask) == b4_patt) && \ ((tmp = (uni & b4_requ))) && \ ((tmp & b4_err0) == 0 || (tmp & b4_err1) == 0) \ ) #define return_err(_end, _msg) do { \ *msg = _msg; \ *end = _end; \ return false; \ } while (false) u8 *cur = *ptr; u8 **end = ptr; u8 *src = ++cur, *dst, *pos; u16 hi, lo; u32 uni, tmp; skip_ascii: /* Most strings have no escaped characters, so we can jump them quickly. */ skip_ascii_begin: /* We want to make loop unrolling, as shown in the following code. Some compiler may not generate instructions as expected, so we rewrite it with explicit goto statements. We hope the compiler can generate instructions like this: https://godbolt.org/z/8vjsYq while (true) repeat16({ if (likely(!(char_is_ascii_stop(*src)))) src++; else break; }) */ #define expr_jump(i) \ if (likely(!char_is_ascii_stop(src[i]))) {} \ else goto skip_ascii_stop##i; #define expr_stop(i) \ skip_ascii_stop##i: \ src += i; \ goto skip_ascii_end; repeat16_incr(expr_jump) src += 16; goto skip_ascii_begin; repeat16_incr(expr_stop) #undef expr_jump #undef expr_stop skip_ascii_end: /* GCC may store src[i] in a register at each line of expr_jump(i) above. These instructions are useless and will degrade performance. This inline asm is a hint for gcc: "the memory has been modified, do not cache it". MSVC, Clang, ICC can generate expected instructions without this hint. */ #if YYJSON_IS_REAL_GCC __asm__ volatile("":"=m"(*src)); #endif if (likely(*src == '"')) { val->tag = ((u64)(src - cur) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = (const char *)cur; *src = '\0'; *end = src + 1; return true; } skip_utf8: if (*src & 0x80) { /* non-ASCII character */ /* Non-ASCII character appears here, which means that the text is likely to be written in non-English or emoticons. According to some common data set statistics, byte sequences of the same length may appear consecutively. We process the byte sequences of the same length in each loop, which is more friendly to branch prediction. */ pos = src; uni = byte_load_4(src); while (is_valid_seq_3(uni)) { src += 3; uni = byte_load_4(src); } if (is_valid_seq_1(uni)) goto skip_ascii; while (is_valid_seq_2(uni)) { src += 2; uni = byte_load_4(src); } while (is_valid_seq_4(uni)) { src += 4; uni = byte_load_4(src); } if (unlikely(pos == src)) { if (!inv) return_err(src, "invalid UTF-8 encoding in string"); ++src; } goto skip_ascii; } /* The escape character appears, we need to copy it. */ dst = src; copy_escape: if (likely(*src == '\\')) { switch (*++src) { case '"': *dst++ = '"'; src++; break; case '\\': *dst++ = '\\'; src++; break; case '/': *dst++ = '/'; src++; break; case 'b': *dst++ = '\b'; src++; break; case 'f': *dst++ = '\f'; src++; break; case 'n': *dst++ = '\n'; src++; break; case 'r': *dst++ = '\r'; src++; break; case 't': *dst++ = '\t'; src++; break; case 'u': if (unlikely(!read_hex_u16(++src, &hi))) { return_err(src - 2, "invalid escaped sequence in string"); } src += 4; if (likely((hi & 0xF800) != 0xD800)) { /* a BMP character */ if (hi >= 0x800) { *dst++ = (u8)(0xE0 | (hi >> 12)); *dst++ = (u8)(0x80 | ((hi >> 6) & 0x3F)); *dst++ = (u8)(0x80 | (hi & 0x3F)); } else if (hi >= 0x80) { *dst++ = (u8)(0xC0 | (hi >> 6)); *dst++ = (u8)(0x80 | (hi & 0x3F)); } else { *dst++ = (u8)hi; } } else { /* a non-BMP character, represented as a surrogate pair */ if (unlikely((hi & 0xFC00) != 0xD800)) { return_err(src - 6, "invalid high surrogate in string"); } if (unlikely(!byte_match_2(src, "\\u"))) { return_err(src, "no low surrogate in string"); } if (unlikely(!read_hex_u16(src + 2, &lo))) { return_err(src, "invalid escaped sequence in string"); } if (unlikely((lo & 0xFC00) != 0xDC00)) { return_err(src, "invalid low surrogate in string"); } uni = ((((u32)hi - 0xD800) << 10) | ((u32)lo - 0xDC00)) + 0x10000; *dst++ = (u8)(0xF0 | (uni >> 18)); *dst++ = (u8)(0x80 | ((uni >> 12) & 0x3F)); *dst++ = (u8)(0x80 | ((uni >> 6) & 0x3F)); *dst++ = (u8)(0x80 | (uni & 0x3F)); src += 6; } break; default: return_err(src, "invalid escaped character in string"); } } else if (likely(*src == '"')) { val->tag = ((u64)(dst - cur) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = (const char *)cur; *dst = '\0'; *end = src + 1; return true; } else { if (!inv) return_err(src, "unexpected control character in string"); if (src >= lst) return_err(src, "unclosed string"); *dst++ = *src++; } copy_ascii: /* Copy continuous ASCII, loop unrolling, same as the following code: while (true) repeat16({ if (unlikely(char_is_ascii_stop(*src))) break; *dst++ = *src++; }) */ #if YYJSON_IS_REAL_GCC # define expr_jump(i) \ if (likely(!(char_is_ascii_stop(src[i])))) {} \ else { __asm__ volatile("":"=m"(src[i])); goto copy_ascii_stop_##i; } #else # define expr_jump(i) \ if (likely(!(char_is_ascii_stop(src[i])))) {} \ else { goto copy_ascii_stop_##i; } #endif repeat16_incr(expr_jump) #undef expr_jump byte_move_16(dst, src); src += 16; dst += 16; goto copy_ascii; copy_ascii_stop_0: goto copy_utf8; copy_ascii_stop_1: byte_move_2(dst, src); src += 1; dst += 1; goto copy_utf8; copy_ascii_stop_2: byte_move_2(dst, src); src += 2; dst += 2; goto copy_utf8; copy_ascii_stop_3: byte_move_4(dst, src); src += 3; dst += 3; goto copy_utf8; copy_ascii_stop_4: byte_move_4(dst, src); src += 4; dst += 4; goto copy_utf8; copy_ascii_stop_5: byte_move_4(dst, src); byte_move_2(dst + 4, src + 4); src += 5; dst += 5; goto copy_utf8; copy_ascii_stop_6: byte_move_4(dst, src); byte_move_2(dst + 4, src + 4); src += 6; dst += 6; goto copy_utf8; copy_ascii_stop_7: byte_move_8(dst, src); src += 7; dst += 7; goto copy_utf8; copy_ascii_stop_8: byte_move_8(dst, src); src += 8; dst += 8; goto copy_utf8; copy_ascii_stop_9: byte_move_8(dst, src); byte_move_2(dst + 8, src + 8); src += 9; dst += 9; goto copy_utf8; copy_ascii_stop_10: byte_move_8(dst, src); byte_move_2(dst + 8, src + 8); src += 10; dst += 10; goto copy_utf8; copy_ascii_stop_11: byte_move_8(dst, src); byte_move_4(dst + 8, src + 8); src += 11; dst += 11; goto copy_utf8; copy_ascii_stop_12: byte_move_8(dst, src); byte_move_4(dst + 8, src + 8); src += 12; dst += 12; goto copy_utf8; copy_ascii_stop_13: byte_move_8(dst, src); byte_move_4(dst + 8, src + 8); byte_move_2(dst + 12, src + 12); src += 13; dst += 13; goto copy_utf8; copy_ascii_stop_14: byte_move_8(dst, src); byte_move_4(dst + 8, src + 8); byte_move_2(dst + 12, src + 12); src += 14; dst += 14; goto copy_utf8; copy_ascii_stop_15: byte_move_16(dst, src); src += 15; dst += 15; goto copy_utf8; copy_utf8: if (*src & 0x80) { /* non-ASCII character */ pos = src; uni = byte_load_4(src); while (is_valid_seq_3(uni)) { byte_move_4(dst, &uni); dst += 3; src += 3; uni = byte_load_4(src); } if (is_valid_seq_1(uni)) goto copy_ascii; while (is_valid_seq_2(uni)) { byte_move_2(dst, &uni); dst += 2; src += 2; uni = byte_load_4(src); } while (is_valid_seq_4(uni)) { byte_move_4(dst, &uni); dst += 4; src += 4; uni = byte_load_4(src); } if (unlikely(pos == src)) { if (!inv) return_err(src, "invalid UTF-8 encoding in string"); goto copy_ascii_stop_1; } goto copy_ascii; } goto copy_escape; #undef return_err #undef is_valid_seq_1 #undef is_valid_seq_2 #undef is_valid_seq_3 #undef is_valid_seq_4 } /*============================================================================== * JSON Reader Implementation * * We use goto statements to build the finite state machine (FSM). * The FSM's state was held by program counter (PC) and the 'goto' make the * state transitions. *============================================================================*/ /** Read single value JSON document. */ static_noinline yyjson_doc *read_root_single(u8 *hdr, u8 *cur, u8 *end, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { #define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) #define return_err(_pos, _code, _msg) do { \ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ } else { \ err->pos = (usize)(_pos - hdr); \ err->code = YYJSON_READ_ERROR_##_code; \ err->msg = _msg; \ } \ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) usize hdr_len; /* value count used by doc */ usize alc_num; /* value count capacity */ yyjson_val *val_hdr; /* the head of allocated values */ yyjson_val *val; /* current value */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ bool raw; /* read number as raw */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_num = hdr_len + 1; /* single value */ val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_num * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val = val_hdr + hdr_len; raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; if (char_is_number(*cur)) { if (likely(read_number(&cur, pre, flg, val, &msg))) goto doc_end; goto fail_number; } if (*cur == '"') { if (likely(read_string(&cur, end, inv, val, &msg))) goto doc_end; goto fail_string; } if (*cur == 't') { if (likely(read_true(&cur, val))) goto doc_end; goto fail_literal; } if (*cur == 'f') { if (likely(read_false(&cur, val))) goto doc_end; goto fail_literal; } if (*cur == 'n') { if (likely(read_null(&cur, val))) goto doc_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto doc_end; } goto fail_literal; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_inf_or_nan(false, &cur, pre, val)) goto doc_end; } goto fail_character; doc_end: /* check invalid contents after json document */ if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { if (has_flag(ALLOW_COMMENTS)) { if (!skip_spaces_and_comments(&cur)) { if (byte_match_2(cur, "/*")) goto fail_comment; } } else { while (char_is_space(*cur)) cur++; } if (unlikely(cur < end)) goto fail_garbage; } if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = 1; doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; return doc; fail_string: return_err(cur, INVALID_STRING, msg); fail_number: return_err(cur, INVALID_NUMBER, msg); fail_alloc: return_err(cur, MEMORY_ALLOCATION, "memory allocation failed"); fail_literal: return_err(cur, LITERAL, "invalid literal"); fail_comment: return_err(cur, INVALID_COMMENT, "unclosed multiline comment"); fail_character: return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); #undef has_flag #undef return_err } /** Read JSON document (accept all style, but optimized for minify). */ static_inline yyjson_doc *read_root_minify(u8 *hdr, u8 *cur, u8 *end, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { #define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) #define return_err(_pos, _code, _msg) do { \ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ } else { \ err->pos = (usize)(_pos - hdr); \ err->code = YYJSON_READ_ERROR_##_code; \ err->msg = _msg; \ } \ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) #define val_incr() do { \ val++; \ if (unlikely(val >= val_end)) { \ usize alc_old = alc_len; \ alc_len += alc_len / 2; \ if ((alc_len >= alc_max)) goto fail_alloc; \ val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ alc_old * sizeof(yyjson_val), \ alc_len * sizeof(yyjson_val)); \ if ((!val_tmp)) goto fail_alloc; \ val = val_tmp + (usize)(val - val_hdr); \ ctn = val_tmp + (usize)(ctn - val_hdr); \ val_hdr = val_tmp; \ val_end = val_tmp + (alc_len - 2); \ } \ } while (false) usize dat_len; /* data length in bytes, hint for allocator */ usize hdr_len; /* value count used by yyjson_doc */ usize alc_len; /* value count allocated */ usize alc_max; /* maximum value count for allocator */ usize ctn_len; /* the number of elements in current container */ yyjson_val *val_hdr; /* the head of allocated values */ yyjson_val *val_end; /* the end of allocated values */ yyjson_val *val_tmp; /* temporary pointer for realloc */ yyjson_val *val; /* current JSON value */ yyjson_val *ctn; /* current container */ yyjson_val *ctn_parent; /* parent of current container */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ bool raw; /* read number as raw */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ dat_len = has_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur); hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_max = USIZE_MAX / sizeof(yyjson_val); alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_MINIFY_RATIO) + 4; alc_len = yyjson_min(alc_len, alc_max); val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */ val = val_hdr + hdr_len; ctn = val; ctn_len = 0; raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; if (*cur++ == '{') { ctn->tag = YYJSON_TYPE_OBJ; ctn->uni.ofs = 0; goto obj_key_begin; } else { ctn->tag = YYJSON_TYPE_ARR; ctn->uni.ofs = 0; goto arr_val_begin; } arr_begin: /* save current container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); /* create a new array value, save parent container offset */ val_incr(); val->tag = YYJSON_TYPE_ARR; val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); /* push the new array value as current container */ ctn = val; ctn_len = 0; arr_val_begin: if (*cur == '{') { cur++; goto obj_begin; } if (*cur == '[') { cur++; goto arr_begin; } if (char_is_number(*cur)) { val_incr(); ctn_len++; if (likely(read_number(&cur, pre, flg, val, &msg))) goto arr_val_end; goto fail_number; } if (*cur == '"') { val_incr(); ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto arr_val_end; goto fail_string; } if (*cur == 't') { val_incr(); ctn_len++; if (likely(read_true(&cur, val))) goto arr_val_end; goto fail_literal; } if (*cur == 'f') { val_incr(); ctn_len++; if (likely(read_false(&cur, val))) goto arr_val_end; goto fail_literal; } if (*cur == 'n') { val_incr(); ctn_len++; if (likely(read_null(&cur, val))) goto arr_val_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto arr_val_end; } goto fail_literal; } if (*cur == ']') { cur++; if (likely(ctn_len == 0)) goto arr_end; if (has_flag(ALLOW_TRAILING_COMMAS)) goto arr_end; while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_begin; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val_incr(); ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end; goto fail_character; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; arr_val_end: if (*cur == ',') { cur++; goto arr_val_begin; } if (*cur == ']') { cur++; goto arr_end; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; arr_end: /* get parent container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); /* save the next sibling value offset */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; if (unlikely(ctn == ctn_parent)) goto doc_end; /* pop parent as current container */ ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { goto obj_val_end; } else { goto arr_val_end; } obj_begin: /* push container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); val_incr(); val->tag = YYJSON_TYPE_OBJ; /* offset to the parent */ val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); ctn = val; ctn_len = 0; obj_key_begin: if (likely(*cur == '"')) { val_incr(); ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_key_end; goto fail_string; } if (likely(*cur == '}')) { cur++; if (likely(ctn_len == 0)) goto obj_end; if (has_flag(ALLOW_TRAILING_COMMAS)) goto obj_end; while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_begin; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_key_end: if (*cur == ':') { cur++; goto obj_val_begin; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_val_begin: if (*cur == '"') { val++; ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_val_end; goto fail_string; } if (char_is_number(*cur)) { val++; ctn_len++; if (likely(read_number(&cur, pre, flg, val, &msg))) goto obj_val_end; goto fail_number; } if (*cur == '{') { cur++; goto obj_begin; } if (*cur == '[') { cur++; goto arr_begin; } if (*cur == 't') { val++; ctn_len++; if (likely(read_true(&cur, val))) goto obj_val_end; goto fail_literal; } if (*cur == 'f') { val++; ctn_len++; if (likely(read_false(&cur, val))) goto obj_val_end; goto fail_literal; } if (*cur == 'n') { val++; ctn_len++; if (likely(read_null(&cur, val))) goto obj_val_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto obj_val_end; } goto fail_literal; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_val_begin; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val++; ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end; goto fail_character; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_val_end: if (likely(*cur == ',')) { cur++; goto obj_key_begin; } if (likely(*cur == '}')) { cur++; goto obj_end; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_val_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_end: /* pop container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); /* point to the next value */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ; if (unlikely(ctn == ctn_parent)) goto doc_end; ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { goto obj_val_end; } else { goto arr_val_end; } doc_end: /* check invalid contents after json document */ if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { if (has_flag(ALLOW_COMMENTS)) { skip_spaces_and_comments(&cur); if (byte_match_2(cur, "/*")) goto fail_comment; } else while (char_is_space(*cur)) cur++; if (unlikely(cur < end)) goto fail_garbage; } if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = (usize)((val - doc->root) + 1); doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; return doc; fail_string: return_err(cur, INVALID_STRING, msg); fail_number: return_err(cur, INVALID_NUMBER, msg); fail_alloc: return_err(cur, MEMORY_ALLOCATION, "memory allocation failed"); fail_trailing_comma: return_err(cur, JSON_STRUCTURE, "trailing comma is not allowed"); fail_literal: return_err(cur, LITERAL, "invalid literal"); fail_comment: return_err(cur, INVALID_COMMENT, "unclosed multiline comment"); fail_character: return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); #undef has_flag #undef val_incr #undef return_err } /** Read JSON document (accept all style, but optimized for pretty). */ static_inline yyjson_doc *read_root_pretty(u8 *hdr, u8 *cur, u8 *end, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { #define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) #define return_err(_pos, _code, _msg) do { \ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ } else { \ err->pos = (usize)(_pos - hdr); \ err->code = YYJSON_READ_ERROR_##_code; \ err->msg = _msg; \ } \ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) #define val_incr() do { \ val++; \ if (unlikely(val >= val_end)) { \ usize alc_old = alc_len; \ alc_len += alc_len / 2; \ if ((alc_len >= alc_max)) goto fail_alloc; \ val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ alc_old * sizeof(yyjson_val), \ alc_len * sizeof(yyjson_val)); \ if ((!val_tmp)) goto fail_alloc; \ val = val_tmp + (usize)(val - val_hdr); \ ctn = val_tmp + (usize)(ctn - val_hdr); \ val_hdr = val_tmp; \ val_end = val_tmp + (alc_len - 2); \ } \ } while (false) usize dat_len; /* data length in bytes, hint for allocator */ usize hdr_len; /* value count used by yyjson_doc */ usize alc_len; /* value count allocated */ usize alc_max; /* maximum value count for allocator */ usize ctn_len; /* the number of elements in current container */ yyjson_val *val_hdr; /* the head of allocated values */ yyjson_val *val_end; /* the end of allocated values */ yyjson_val *val_tmp; /* temporary pointer for realloc */ yyjson_val *val; /* current JSON value */ yyjson_val *ctn; /* current container */ yyjson_val *ctn_parent; /* parent of current container */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ bool raw; /* read number as raw */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ dat_len = has_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur); hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_max = USIZE_MAX / sizeof(yyjson_val); alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_PRETTY_RATIO) + 4; alc_len = yyjson_min(alc_len, alc_max); val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */ val = val_hdr + hdr_len; ctn = val; ctn_len = 0; raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; if (*cur++ == '{') { ctn->tag = YYJSON_TYPE_OBJ; ctn->uni.ofs = 0; if (*cur == '\n') cur++; goto obj_key_begin; } else { ctn->tag = YYJSON_TYPE_ARR; ctn->uni.ofs = 0; if (*cur == '\n') cur++; goto arr_val_begin; } arr_begin: /* save current container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); /* create a new array value, save parent container offset */ val_incr(); val->tag = YYJSON_TYPE_ARR; val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); /* push the new array value as current container */ ctn = val; ctn_len = 0; if (*cur == '\n') cur++; arr_val_begin: #if YYJSON_IS_REAL_GCC while (true) repeat16({ if (byte_match_2(cur, " ")) cur += 2; else break; }) #else while (true) repeat16({ if (likely(byte_match_2(cur, " "))) cur += 2; else break; }) #endif if (*cur == '{') { cur++; goto obj_begin; } if (*cur == '[') { cur++; goto arr_begin; } if (char_is_number(*cur)) { val_incr(); ctn_len++; if (likely(read_number(&cur, pre, flg, val, &msg))) goto arr_val_end; goto fail_number; } if (*cur == '"') { val_incr(); ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto arr_val_end; goto fail_string; } if (*cur == 't') { val_incr(); ctn_len++; if (likely(read_true(&cur, val))) goto arr_val_end; goto fail_literal; } if (*cur == 'f') { val_incr(); ctn_len++; if (likely(read_false(&cur, val))) goto arr_val_end; goto fail_literal; } if (*cur == 'n') { val_incr(); ctn_len++; if (likely(read_null(&cur, val))) goto arr_val_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto arr_val_end; } goto fail_literal; } if (*cur == ']') { cur++; if (likely(ctn_len == 0)) goto arr_end; if (has_flag(ALLOW_TRAILING_COMMAS)) goto arr_end; while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_begin; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val_incr(); ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end; goto fail_character; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; arr_val_end: if (byte_match_2(cur, ",\n")) { cur += 2; goto arr_val_begin; } if (*cur == ',') { cur++; goto arr_val_begin; } if (*cur == ']') { cur++; goto arr_end; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; arr_end: /* get parent container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); /* save the next sibling value offset */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; if (unlikely(ctn == ctn_parent)) goto doc_end; /* pop parent as current container */ ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); if (*cur == '\n') cur++; if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { goto obj_val_end; } else { goto arr_val_end; } obj_begin: /* push container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); val_incr(); val->tag = YYJSON_TYPE_OBJ; /* offset to the parent */ val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); ctn = val; ctn_len = 0; if (*cur == '\n') cur++; obj_key_begin: #if YYJSON_IS_REAL_GCC while (true) repeat16({ if (byte_match_2(cur, " ")) cur += 2; else break; }) #else while (true) repeat16({ if (likely(byte_match_2(cur, " "))) cur += 2; else break; }) #endif if (likely(*cur == '"')) { val_incr(); ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_key_end; goto fail_string; } if (likely(*cur == '}')) { cur++; if (likely(ctn_len == 0)) goto obj_end; if (has_flag(ALLOW_TRAILING_COMMAS)) goto obj_end; while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_begin; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_key_end: if (byte_match_2(cur, ": ")) { cur += 2; goto obj_val_begin; } if (*cur == ':') { cur++; goto obj_val_begin; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_val_begin: if (*cur == '"') { val++; ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_val_end; goto fail_string; } if (char_is_number(*cur)) { val++; ctn_len++; if (likely(read_number(&cur, pre, flg, val, &msg))) goto obj_val_end; goto fail_number; } if (*cur == '{') { cur++; goto obj_begin; } if (*cur == '[') { cur++; goto arr_begin; } if (*cur == 't') { val++; ctn_len++; if (likely(read_true(&cur, val))) goto obj_val_end; goto fail_literal; } if (*cur == 'f') { val++; ctn_len++; if (likely(read_false(&cur, val))) goto obj_val_end; goto fail_literal; } if (*cur == 'n') { val++; ctn_len++; if (likely(read_null(&cur, val))) goto obj_val_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto obj_val_end; } goto fail_literal; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_val_begin; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val++; ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end; goto fail_character; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_val_end: if (byte_match_2(cur, ",\n")) { cur += 2; goto obj_key_begin; } if (likely(*cur == ',')) { cur++; goto obj_key_begin; } if (likely(*cur == '}')) { cur++; goto obj_end; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_val_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_end: /* pop container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); /* point to the next value */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ; if (unlikely(ctn == ctn_parent)) goto doc_end; ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); if (*cur == '\n') cur++; if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { goto obj_val_end; } else { goto arr_val_end; } doc_end: /* check invalid contents after json document */ if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { if (has_flag(ALLOW_COMMENTS)) { skip_spaces_and_comments(&cur); if (byte_match_2(cur, "/*")) goto fail_comment; } else while (char_is_space(*cur)) cur++; if (unlikely(cur < end)) goto fail_garbage; } if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = (usize)((val - val_hdr)) - hdr_len + 1; doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; return doc; fail_string: return_err(cur, INVALID_STRING, msg); fail_number: return_err(cur, INVALID_NUMBER, msg); fail_alloc: return_err(cur, MEMORY_ALLOCATION, "memory allocation failed"); fail_trailing_comma: return_err(cur, JSON_STRUCTURE, "trailing comma is not allowed"); fail_literal: return_err(cur, LITERAL, "invalid literal"); fail_comment: return_err(cur, INVALID_COMMENT, "unclosed multiline comment"); fail_character: return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); #undef has_flag #undef val_incr #undef return_err } /*============================================================================== * JSON Reader Entrance *============================================================================*/ yyjson_doc *yyjson_read_opts(char *dat, usize len, yyjson_read_flag flg, const yyjson_alc *alc_ptr, yyjson_read_err *err) { #define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) #define return_err(_pos, _code, _msg) do { \ err->pos = (usize)(_pos); \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ if (!has_flag(INSITU) && hdr) alc.free(alc.ctx, (void *)hdr); \ return NULL; \ } while (false) yyjson_read_err dummy_err; yyjson_alc alc; yyjson_doc *doc; u8 *hdr = NULL, *end, *cur; #if YYJSON_DISABLE_NON_STANDARD flg &= ~YYJSON_READ_ALLOW_TRAILING_COMMAS; flg &= ~YYJSON_READ_ALLOW_COMMENTS; flg &= ~YYJSON_READ_ALLOW_INF_AND_NAN; flg &= ~YYJSON_READ_ALLOW_INVALID_UNICODE; #endif /* validate input parameters */ if (!err) err = &dummy_err; if (likely(!alc_ptr)) { alc = YYJSON_DEFAULT_ALC; } else { alc = *alc_ptr; } if (unlikely(!dat)) { return_err(0, INVALID_PARAMETER, "input data is NULL"); } if (unlikely(!len)) { return_err(0, INVALID_PARAMETER, "input length is 0"); } /* add 4-byte zero padding for input data if necessary */ if (has_flag(INSITU)) { hdr = (u8 *)dat; end = (u8 *)dat + len; cur = (u8 *)dat; } else { if (unlikely(len >= USIZE_MAX - YYJSON_PADDING_SIZE)) { return_err(0, MEMORY_ALLOCATION, "memory allocation failed"); } hdr = (u8 *)alc.malloc(alc.ctx, len + YYJSON_PADDING_SIZE); if (unlikely(!hdr)) { return_err(0, MEMORY_ALLOCATION, "memory allocation failed"); } end = hdr + len; cur = hdr; memcpy(hdr, dat, len); memset(end, 0, YYJSON_PADDING_SIZE); } /* skip empty contents before json document */ if (unlikely(char_is_space_or_comment(*cur))) { if (has_flag(ALLOW_COMMENTS)) { if (!skip_spaces_and_comments(&cur)) { return_err(cur - hdr, INVALID_COMMENT, "unclosed multiline comment"); } } else { if (likely(char_is_space(*cur))) { while (char_is_space(*++cur)); } } if (unlikely(cur >= end)) { return_err(0, EMPTY_CONTENT, "input data is empty"); } } /* read json document */ if (likely(char_is_container(*cur))) { if (char_is_space(cur[1]) && char_is_space(cur[2])) { doc = read_root_pretty(hdr, cur, end, alc, flg, err); } else { doc = read_root_minify(hdr, cur, end, alc, flg, err); } } else { doc = read_root_single(hdr, cur, end, alc, flg, err); } /* check result */ if (likely(doc)) { memset(err, 0, sizeof(yyjson_read_err)); } else { /* RFC 8259: JSON text MUST be encoded using UTF-8 */ if (err->pos == 0 && err->code != YYJSON_READ_ERROR_MEMORY_ALLOCATION) { if ((hdr[0] == 0xEF && hdr[1] == 0xBB && hdr[2] == 0xBF)) { err->msg = "byte order mark (BOM) is not supported"; } else if (len >= 4 && ((hdr[0] == 0x00 && hdr[1] == 0x00 && hdr[2] == 0xFE && hdr[3] == 0xFF) || (hdr[0] == 0xFF && hdr[1] == 0xFE && hdr[2] == 0x00 && hdr[3] == 0x00))) { err->msg = "UTF-32 encoding is not supported"; } else if (len >= 2 && ((hdr[0] == 0xFE && hdr[1] == 0xFF) || (hdr[0] == 0xFF && hdr[1] == 0xFE))) { err->msg = "UTF-16 encoding is not supported"; } } if (!has_flag(INSITU)) alc.free(alc.ctx, (void *)hdr); } return doc; #undef has_flag #undef return_err } yyjson_doc *yyjson_read_file(const char *path, yyjson_read_flag flg, const yyjson_alc *alc_ptr, yyjson_read_err *err) { #define return_err(_code, _msg) do { \ err->pos = 0; \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ return NULL; \ } while (false) yyjson_read_err dummy_err; yyjson_doc *doc; FILE *file; if (!err) err = &dummy_err; if (unlikely(!path)) return_err(INVALID_PARAMETER, "input path is NULL"); file = fopen_readonly(path); if (unlikely(!file)) return_err(FILE_OPEN, "file opening failed"); doc = yyjson_read_fp(file, flg, alc_ptr, err); fclose(file); return doc; #undef return_err } yyjson_doc *yyjson_read_fp(FILE *file, yyjson_read_flag flg, const yyjson_alc *alc_ptr, yyjson_read_err *err) { #define return_err(_code, _msg) do { \ err->pos = 0; \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ if (buf) alc.free(alc.ctx, buf); \ return NULL; \ } while (false) yyjson_read_err dummy_err; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; yyjson_doc *doc; long file_size = 0, file_pos; void *buf = NULL; usize buf_size = 0; /* validate input parameters */ if (!err) err = &dummy_err; if (unlikely(!file)) return_err(INVALID_PARAMETER, "input file is NULL"); /* get current position */ file_pos = ftell(file); if (file_pos != -1) { /* get total file size, may fail */ if (fseek(file, 0, SEEK_END) == 0) file_size = ftell(file); /* reset to original position, may fail */ if (fseek(file, file_pos, SEEK_SET) != 0) file_size = 0; /* get file size from current postion to end */ if (file_size > 0) file_size -= file_pos; } /* read file */ if (file_size > 0) { /* read the entire file in one call */ buf_size = (usize)file_size + YYJSON_PADDING_SIZE; buf = alc.malloc(alc.ctx, buf_size); if (buf == NULL) { return_err(MEMORY_ALLOCATION, "fail to alloc memory"); } if (fread_safe(buf, (usize)file_size, file) != (usize)file_size) { return_err(FILE_READ, "file reading failed"); } } else { /* failed to get file size, read it as a stream */ usize chunk_min = (usize)64; usize chunk_max = (usize)512 * 1024 * 1024; usize chunk_now = chunk_min; usize read_size; void *tmp; buf_size = YYJSON_PADDING_SIZE; while (true) { if (buf_size + chunk_now < buf_size) { /* overflow */ return_err(MEMORY_ALLOCATION, "fail to alloc memory"); } buf_size += chunk_now; if (!buf) { buf = alc.malloc(alc.ctx, buf_size); if (!buf) return_err(MEMORY_ALLOCATION, "fail to alloc memory"); } else { tmp = alc.realloc(alc.ctx, buf, buf_size - chunk_now, buf_size); if (!tmp) return_err(MEMORY_ALLOCATION, "fail to alloc memory"); buf = tmp; } tmp = ((u8 *)buf) + buf_size - YYJSON_PADDING_SIZE - chunk_now; read_size = fread_safe(tmp, chunk_now, file); file_size += (long)read_size; if (read_size != chunk_now) break; chunk_now *= 2; if (chunk_now > chunk_max) chunk_now = chunk_max; } } /* read JSON */ memset((u8 *)buf + file_size, 0, YYJSON_PADDING_SIZE); flg |= YYJSON_READ_INSITU; doc = yyjson_read_opts((char *)buf, (usize)file_size, flg, &alc, err); if (doc) { doc->str_pool = (char *)buf; return doc; } else { alc.free(alc.ctx, buf); return NULL; } #undef return_err } const char *yyjson_read_number(const char *dat, yyjson_val *val, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err) { #define return_err(_pos, _code, _msg) do { \ err->pos = _pos > hdr ? (usize)(_pos - hdr) : 0; \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ return NULL; \ } while (false) u8 *hdr = constcast(u8 *)dat, *cur = hdr; bool raw; /* read number as raw */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ const char *msg; yyjson_read_err dummy_err; #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV u8 buf[128]; usize dat_len; #endif if (!err) err = &dummy_err; if (unlikely(!dat)) { return_err(cur, INVALID_PARAMETER, "input data is NULL"); } if (unlikely(!val)) { return_err(cur, INVALID_PARAMETER, "output value is NULL"); } #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV if (!alc) alc = &YYJSON_DEFAULT_ALC; dat_len = strlen(dat); if (dat_len < sizeof(buf)) { memcpy(buf, dat, dat_len + 1); hdr = buf; cur = hdr; } else { hdr = (u8 *)alc->malloc(alc->ctx, dat_len + 1); cur = hdr; if (unlikely(!hdr)) { return_err(cur, MEMORY_ALLOCATION, "memory allocation failed"); } memcpy(hdr, dat, dat_len + 1); } hdr[dat_len] = 0; #endif #if YYJSON_DISABLE_NON_STANDARD flg &= ~YYJSON_READ_ALLOW_INF_AND_NAN; #endif raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV if (!read_number(&cur, pre, flg, val, &msg)) { if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr); return_err(cur, INVALID_NUMBER, msg); } if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr); if (yyjson_is_raw(val)) val->uni.str = dat; return dat + (cur - hdr); #else if (!read_number(&cur, pre, flg, val, &msg)) { return_err(cur, INVALID_NUMBER, msg); } return (const char *)cur; #endif #undef return_err } #endif /* YYJSON_DISABLE_READER */ #if !YYJSON_DISABLE_WRITER /*============================================================================== * Integer Writer * * The maximum value of uint32_t is 4294967295 (10 digits), * these digits are named as 'aabbccddee' here. * * Although most compilers may convert the "division by constant value" into * "multiply and shift", manual conversion can still help some compilers * generate fewer and better instructions. * * Reference: * Division by Invariant Integers using Multiplication, 1994. * https://gmplib.org/~tege/divcnst-pldi94.pdf * Improved division by invariant integers, 2011. * https://gmplib.org/~tege/division-paper.pdf *============================================================================*/ /** Digit table from 00 to 99. */ yyjson_align(2) static const char digit_table[200] = { '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' }; static_inline u8 *write_u32_len_8(u32 val, u8 *buf) { u32 aa, bb, cc, dd, aabb, ccdd; /* 8 digits: aabbccdd */ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ ccdd = val - aabb * 10000; /* (val % 10000) */ aa = (aabb * 5243) >> 19; /* (aabb / 100) */ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ ((v16 *)buf)[0] = ((const v16 *)digit_table)[aa]; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; return buf + 8; } static_inline u8 *write_u32_len_4(u32 val, u8 *buf) { u32 aa, bb; /* 4 digits: aabb */ aa = (val * 5243) >> 19; /* (val / 100) */ bb = val - aa * 100; /* (val % 100) */ ((v16 *)buf)[0] = ((const v16 *)digit_table)[aa]; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; return buf + 4; } static_inline u8 *write_u32_len_1_8(u32 val, u8 *buf) { u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz; if (val < 100) { /* 1-2 digits: aa */ lz = val < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (val * 2 + lz)); buf -= lz; return buf + 2; } else if (val < 10000) { /* 3-4 digits: aabb */ aa = (val * 5243) >> 19; /* (val / 100) */ bb = val - aa * 100; /* (val % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; return buf + 4; } else if (val < 1000000) { /* 5-6 digits: aabbcc */ aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */ bbcc = val - aa * 10000; /* (val % 10000) */ bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */ cc = bbcc - bb * 100; /* (bbcc % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; return buf + 6; } else { /* 7-8 digits: aabbccdd */ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ ccdd = val - aabb * 10000; /* (val % 10000) */ aa = (aabb * 5243) >> 19; /* (aabb / 100) */ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; return buf + 8; } } static_inline u8 *write_u64_len_5_8(u32 val, u8 *buf) { u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz; if (val < 1000000) { /* 5-6 digits: aabbcc */ aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */ bbcc = val - aa * 10000; /* (val % 10000) */ bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */ cc = bbcc - bb * 100; /* (bbcc % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; return buf + 6; } else { /* 7-8 digits: aabbccdd */ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ ccdd = val - aabb * 10000; /* (val % 10000) */ aa = (aabb * 5243) >> 19; /* (aabb / 100) */ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; return buf + 8; } } static_inline u8 *write_u64(u64 val, u8 *buf) { u64 tmp, hgh; u32 mid, low; if (val < 100000000) { /* 1-8 digits */ buf = write_u32_len_1_8((u32)val, buf); return buf; } else if (val < (u64)100000000 * 100000000) { /* 9-16 digits */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ buf = write_u32_len_1_8((u32)hgh, buf); buf = write_u32_len_8(low, buf); return buf; } else { /* 17-20 digits */ tmp = val / 100000000; /* (val / 100000000) */ low = (u32)(val - tmp * 100000000); /* (val % 100000000) */ hgh = (u32)(tmp / 10000); /* (tmp / 10000) */ mid = (u32)(tmp - hgh * 10000); /* (tmp % 10000) */ buf = write_u64_len_5_8((u32)hgh, buf); buf = write_u32_len_4(mid, buf); buf = write_u32_len_8(low, buf); return buf; } } /*============================================================================== * Number Writer *============================================================================*/ #if YYJSON_HAS_IEEE_754 && !YYJSON_DISABLE_FAST_FP_CONV /* FP_WRITER */ /** Trailing zero count table for number 0 to 99. (generate with misc/make_tables.c) */ static const u8 dec_trailing_zero_table[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /** Write an unsigned integer with a length of 1 to 16. */ static_inline u8 *write_u64_len_1_to_16(u64 val, u8 *buf) { u64 hgh; u32 low; if (val < 100000000) { /* 1-8 digits */ buf = write_u32_len_1_8((u32)val, buf); return buf; } else { /* 9-16 digits */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ buf = write_u32_len_1_8((u32)hgh, buf); buf = write_u32_len_8(low, buf); return buf; } } /** Write an unsigned integer with a length of 1 to 17. */ static_inline u8 *write_u64_len_1_to_17(u64 val, u8 *buf) { u64 hgh; u32 mid, low, one; if (val >= (u64)100000000 * 10000000) { /* len: 16 to 17 */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ one = (u32)(hgh / 100000000); /* (hgh / 100000000) */ mid = (u32)(hgh - (u64)one * 100000000); /* (hgh % 100000000) */ *buf = (u8)((u8)one + (u8)'0'); buf += one > 0; buf = write_u32_len_8(mid, buf); buf = write_u32_len_8(low, buf); return buf; } else if (val >= (u64)100000000){ /* len: 9 to 15 */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ buf = write_u32_len_1_8((u32)hgh, buf); buf = write_u32_len_8(low, buf); return buf; } else { /* len: 1 to 8 */ buf = write_u32_len_1_8((u32)val, buf); return buf; } } /** Write an unsigned integer with a length of 15 to 17 with trailing zero trimmed. These digits are named as "aabbccddeeffgghhii" here. For example, input 1234567890123000, output "1234567890123". */ static_inline u8 *write_u64_len_15_to_17_trim(u8 *buf, u64 sig) { bool lz; /* leading zero */ u32 tz1, tz2, tz; /* trailing zero */ u32 abbccddee = (u32)(sig / 100000000); u32 ffgghhii = (u32)(sig - (u64)abbccddee * 100000000); u32 abbcc = abbccddee / 10000; /* (abbccddee / 10000) */ u32 ddee = abbccddee - abbcc * 10000; /* (abbccddee % 10000) */ u32 abb = (u32)(((u64)abbcc * 167773) >> 24); /* (abbcc / 100) */ u32 a = (abb * 41) >> 12; /* (abb / 100) */ u32 bb = abb - a * 100; /* (abb % 100) */ u32 cc = abbcc - abb * 100; /* (abbcc % 100) */ /* write abbcc */ buf[0] = (u8)(a + '0'); buf += a > 0; lz = bb < 10 && a == 0; ((v16 *)buf)[0] = *(const v16 *)(digit_table + (bb * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[cc]; if (ffgghhii) { u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ u32 ee = ddee - dd * 100; /* (ddee % 100) */ u32 ffgg = (u32)(((u64)ffgghhii * 109951163) >> 40); /* (val / 10000) */ u32 hhii = ffgghhii - ffgg * 10000; /* (val % 10000) */ u32 ff = (ffgg * 5243) >> 19; /* (aabb / 100) */ u32 gg = ffgg - ff * 100; /* (aabb % 100) */ ((v16 *)buf)[2] = ((const v16 *)digit_table)[dd]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[ee]; ((v16 *)buf)[4] = ((const v16 *)digit_table)[ff]; ((v16 *)buf)[5] = ((const v16 *)digit_table)[gg]; if (hhii) { u32 hh = (hhii * 5243) >> 19; /* (ccdd / 100) */ u32 ii = hhii - hh * 100; /* (ccdd % 100) */ ((v16 *)buf)[6] = ((const v16 *)digit_table)[hh]; ((v16 *)buf)[7] = ((const v16 *)digit_table)[ii]; tz1 = dec_trailing_zero_table[hh]; tz2 = dec_trailing_zero_table[ii]; tz = ii ? tz2 : (tz1 + 2); buf += 16 - tz; return buf; } else { tz1 = dec_trailing_zero_table[ff]; tz2 = dec_trailing_zero_table[gg]; tz = gg ? tz2 : (tz1 + 2); buf += 12 - tz; return buf; } } else { if (ddee) { u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ u32 ee = ddee - dd * 100; /* (ddee % 100) */ ((v16 *)buf)[2] = ((const v16 *)digit_table)[dd]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[ee]; tz1 = dec_trailing_zero_table[dd]; tz2 = dec_trailing_zero_table[ee]; tz = ee ? tz2 : (tz1 + 2); buf += 8 - tz; return buf; } else { tz1 = dec_trailing_zero_table[bb]; tz2 = dec_trailing_zero_table[cc]; tz = cc ? tz2 : (tz1 + tz2); buf += 4 - tz; return buf; } } } /** Write a signed integer in the range -324 to 308. */ static_inline u8 *write_f64_exp(i32 exp, u8 *buf) { buf[0] = '-'; buf += exp < 0; exp = exp < 0 ? -exp : exp; if (exp < 100) { u32 lz = exp < 10; *(v16 *)&buf[0] = *(const v16 *)(digit_table + ((u32)exp * 2 + lz)); return buf + 2 - lz; } else { u32 hi = ((u32)exp * 656) >> 16; /* exp / 100 */ u32 lo = (u32)exp - hi * 100; /* exp % 100 */ buf[0] = (u8)((u8)hi + (u8)'0'); *(v16 *)&buf[1] = *(const v16 *)(digit_table + (lo * 2)); return buf + 3; } } /** Multiplies 128-bit integer and returns highest 64-bit rounded value. */ static_inline u64 round_to_odd(u64 hi, u64 lo, u64 cp) { u64 x_hi, x_lo, y_hi, y_lo; u128_mul(cp, lo, &x_hi, &x_lo); u128_mul_add(cp, hi, x_hi, &y_hi, &y_lo); return y_hi | (y_lo > 1); } /** Convert double number from binary to decimal. The output significand is shortest decimal but may have trailing zeros. This function use the Schubfach algorithm: Raffaello Giulietti, The Schubfach way to render doubles (5th version), 2022. https://drive.google.com/file/d/1gp5xv4CAa78SVgCeWfGqqI4FfYYYuNFb https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-November/083536.html https://github.com/openjdk/jdk/pull/3402 (Java implementation) https://github.com/abolz/Drachennest (C++ implementation) See also: Dragonbox: A New Floating-Point Binary-to-Decimal Conversion Algorithm, 2022. https://github.com/jk-jeon/dragonbox/blob/master/other_files/Dragonbox.pdf https://github.com/jk-jeon/dragonbox @param sig_raw The raw value of significand in IEEE 754 format. @param exp_raw The raw value of exponent in IEEE 754 format. @param sig_bin The decoded value of significand in binary. @param exp_bin The decoded value of exponent in binary. @param sig_dec The output value of significand in decimal. @param exp_dec The output value of exponent in decimal. @warning The input double number should not be 0, inf, nan. */ static_inline void f64_bin_to_dec(u64 sig_raw, u32 exp_raw, u64 sig_bin, i32 exp_bin, u64 *sig_dec, i32 *exp_dec) { bool is_even, regular_spacing, u_inside, w_inside, round_up; u64 s, sp, cb, cbl, cbr, vb, vbl, vbr, pow10hi, pow10lo, upper, lower, mid; i32 k, h, exp10; is_even = !(sig_bin & 1); regular_spacing = (sig_raw == 0 && exp_raw > 1); cbl = 4 * sig_bin - 2 + regular_spacing; cb = 4 * sig_bin; cbr = 4 * sig_bin + 2; /* exp_bin: [-1074, 971] */ /* k = regular_spacing ? floor(log10(pow(2, exp_bin))) */ /* : floor(log10(pow(2, exp_bin) * 3.0 / 4.0)) */ /* = regular_spacing ? floor(exp_bin * log10(2)) */ /* : floor(exp_bin * log10(2) + log10(3.0 / 4.0)) */ k = (i32)(exp_bin * 315653 - (regular_spacing ? 131237 : 0)) >> 20; /* k: [-324, 292] */ /* h = exp_bin + floor(log2(pow(10, e))) */ /* = exp_bin + floor(log2(10) * e) */ exp10 = -k; h = exp_bin + ((exp10 * 217707) >> 16) + 1; pow10_table_get_sig(exp10, &pow10hi, &pow10lo); pow10lo += (exp10 < POW10_SIG_TABLE_MIN_EXACT_EXP || exp10 > POW10_SIG_TABLE_MAX_EXACT_EXP); vbl = round_to_odd(pow10hi, pow10lo, cbl << h); vb = round_to_odd(pow10hi, pow10lo, cb << h); vbr = round_to_odd(pow10hi, pow10lo, cbr << h); lower = vbl + !is_even; upper = vbr - !is_even; s = vb / 4; if (s >= 10) { sp = s / 10; u_inside = (lower <= 40 * sp); w_inside = (upper >= 40 * sp + 40); if (u_inside != w_inside) { *sig_dec = sp + w_inside; *exp_dec = k + 1; return; } } u_inside = (lower <= 4 * s); w_inside = (upper >= 4 * s + 4); mid = 4 * s + 2; round_up = (vb > mid) || (vb == mid && (s & 1) != 0); *sig_dec = s + ((u_inside != w_inside) ? w_inside : round_up); *exp_dec = k; } /** Write a double number (requires 32 bytes buffer). We follows the ECMAScript specification to print floating point numbers, but with the following changes: 1. Keep the negative sign of 0.0 to preserve input information. 2. Keep decimal point to indicate the number is floating point. 3. Remove positive sign of exponent part. */ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { u64 sig_bin, sig_dec, sig_raw; i32 exp_bin, exp_dec, sig_len, dot_pos, i, max; u32 exp_raw, hi, lo; u8 *hdr, *num_hdr, *num_end, *dot_end; bool sign; /* decode raw bytes from IEEE-754 double format. */ sign = (bool)(raw >> (F64_BITS - 1)); sig_raw = raw & F64_SIG_MASK; exp_raw = (u32)((raw & F64_EXP_MASK) >> F64_SIG_BITS); /* return inf and nan */ if (unlikely(exp_raw == ((u32)1 << F64_EXP_BITS) - 1)) { if (flg & YYJSON_WRITE_INF_AND_NAN_AS_NULL) { byte_copy_4(buf, "null"); return buf + 4; } else if (flg & YYJSON_WRITE_ALLOW_INF_AND_NAN) { if (sig_raw == 0) { buf[0] = '-'; buf += sign; byte_copy_8(buf, "Infinity"); buf += 8; return buf; } else { byte_copy_4(buf, "NaN"); return buf + 3; } } else { return NULL; } } /* add sign for all finite double value, including 0.0 and inf */ buf[0] = '-'; buf += sign; hdr = buf; /* return zero */ if ((raw << 1) == 0) { byte_copy_4(buf, "0.0"); buf += 3; return buf; } if (likely(exp_raw != 0)) { /* normal number */ sig_bin = sig_raw | ((u64)1 << F64_SIG_BITS); exp_bin = (i32)exp_raw - F64_EXP_BIAS - F64_SIG_BITS; /* fast path for small integer number without fraction */ if (-F64_SIG_BITS <= exp_bin && exp_bin <= 0) { if (u64_tz_bits(sig_bin) >= (u32)-exp_bin) { /* number is integer in range 1 to 0x1FFFFFFFFFFFFF */ sig_dec = sig_bin >> -exp_bin; buf = write_u64_len_1_to_16(sig_dec, buf); byte_copy_2(buf, ".0"); buf += 2; return buf; } } /* binary to decimal */ f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); /* the sig length is 15 to 17 */ sig_len = 17; sig_len -= (sig_dec < (u64)100000000 * 100000000); sig_len -= (sig_dec < (u64)100000000 * 10000000); /* the decimal point position relative to the first digit */ dot_pos = sig_len + exp_dec; if (-6 < dot_pos && dot_pos <= 21) { /* no need to write exponent part */ if (dot_pos <= 0) { /* dot before first digit */ /* such as 0.1234, 0.000001234 */ num_hdr = hdr + (2 - dot_pos); num_end = write_u64_len_15_to_17_trim(num_hdr, sig_dec); hdr[0] = '0'; hdr[1] = '.'; hdr += 2; max = -dot_pos; for (i = 0; i < max; i++) hdr[i] = '0'; return num_end; } else { /* dot after first digit */ /* such as 1.234, 1234.0, 123400000000000000000.0 */ memset(hdr + 0, '0', 8); memset(hdr + 8, '0', 8); memset(hdr + 16, '0', 8); num_hdr = hdr + 1; num_end = write_u64_len_15_to_17_trim(num_hdr, sig_dec); for (i = 0; i < dot_pos; i++) hdr[i] = hdr[i + 1]; hdr[dot_pos] = '.'; dot_end = hdr + dot_pos + 2; return dot_end < num_end ? num_end : dot_end; } } else { /* write with scientific notation */ /* such as 1.234e56 */ u8 *end = write_u64_len_15_to_17_trim(buf + 1, sig_dec); end -= (end == buf + 2); /* remove '.0', e.g. 2.0e34 -> 2e34 */ exp_dec += sig_len - 1; hdr[0] = hdr[1]; hdr[1] = '.'; end[0] = 'e'; buf = write_f64_exp(exp_dec, end + 1); return buf; } } else { /* subnormal number */ sig_bin = sig_raw; exp_bin = 1 - F64_EXP_BIAS - F64_SIG_BITS; /* binary to decimal */ f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); /* write significand part */ buf = write_u64_len_1_to_17(sig_dec, buf + 1); hdr[0] = hdr[1]; hdr[1] = '.'; do { buf--; exp_dec++; } while (*buf == '0'); exp_dec += (i32)(buf - hdr - 2); buf += (*buf != '.'); buf[0] = 'e'; buf++; /* write exponent part */ buf[0] = '-'; buf++; exp_dec = -exp_dec; hi = ((u32)exp_dec * 656) >> 16; /* exp / 100 */ lo = (u32)exp_dec - hi * 100; /* exp % 100 */ buf[0] = (u8)((u8)hi + (u8)'0'); *(v16 *)&buf[1] = *(const v16 *)(digit_table + (lo * 2)); buf += 3; return buf; } } #else /* FP_WRITER */ /** Write a double number (requires 32 bytes buffer). */ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { /* For IEEE 754, `DBL_DECIMAL_DIG` is 17 for round-trip. For non-IEEE formats, 17 is used to avoid buffer overflow, round-trip is not guaranteed. */ #if defined(DBL_DECIMAL_DIG) && DBL_DECIMAL_DIG != 17 int dig = DBL_DECIMAL_DIG > 17 ? 17 : DBL_DECIMAL_DIG; #else int dig = 17; #endif /* The snprintf() function is locale-dependent. For currently known locales, (en, zh, ja, ko, am, he, hi) use '.' as the decimal point, while other locales use ',' as the decimal point. we need to replace ',' with '.' to avoid the locale setting. */ f64 val = f64_from_raw(raw); #if YYJSON_MSC_VER >= 1400 int len = sprintf_s((char *)buf, 32, "%.*g", dig, val); #elif defined(snprintf) || (YYJSON_STDC_VER >= 199901L) int len = snprintf((char *)buf, 32, "%.*g", dig, val); #else int len = sprintf((char *)buf, "%.*g", dig, val); #endif u8 *cur = buf; if (unlikely(len < 1)) return NULL; cur += (*cur == '-'); if (unlikely(!digi_is_digit(*cur))) { /* nan, inf, or bad output */ if (flg & YYJSON_WRITE_INF_AND_NAN_AS_NULL) { byte_copy_4(buf, "null"); return buf + 4; } else if (flg & YYJSON_WRITE_ALLOW_INF_AND_NAN) { if (*cur == 'i') { byte_copy_8(cur, "Infinity"); cur += 8; return cur; } else if (*cur == 'n') { byte_copy_4(buf, "NaN"); return buf + 3; } } return NULL; } else { /* finite number */ int i = 0; bool fp = false; for (; i < len; i++) { if (buf[i] == ',') buf[i] = '.'; if (digi_is_fp((u8)buf[i])) fp = true; } if (!fp) { buf[len++] = '.'; buf[len++] = '0'; } } return buf + len; } #endif /* FP_WRITER */ /** Write a JSON number (requires 32 bytes buffer). */ static_inline u8 *write_number(u8 *cur, yyjson_val *val, yyjson_write_flag flg) { if (val->tag & YYJSON_SUBTYPE_REAL) { u64 raw = val->uni.u64; return write_f64_raw(cur, raw, flg); } else { u64 pos = val->uni.u64; u64 neg = ~pos + 1; usize sgn = ((val->tag & YYJSON_SUBTYPE_SINT) > 0) & ((i64)pos < 0); *cur = '-'; return write_u64(sgn ? neg : pos, cur + sgn); } } /*============================================================================== * String Writer *============================================================================*/ /** Character encode type, if (type > CHAR_ENC_ERR_1) bytes = type / 2; */ typedef u8 char_enc_type; #define CHAR_ENC_CPY_1 0 /* 1-byte UTF-8, copy. */ #define CHAR_ENC_ERR_1 1 /* 1-byte UTF-8, error. */ #define CHAR_ENC_ESC_A 2 /* 1-byte ASCII, escaped as '\x'. */ #define CHAR_ENC_ESC_1 3 /* 1-byte UTF-8, escaped as '\uXXXX'. */ #define CHAR_ENC_CPY_2 4 /* 2-byte UTF-8, copy. */ #define CHAR_ENC_ESC_2 5 /* 2-byte UTF-8, escaped as '\uXXXX'. */ #define CHAR_ENC_CPY_3 6 /* 3-byte UTF-8, copy. */ #define CHAR_ENC_ESC_3 7 /* 3-byte UTF-8, escaped as '\uXXXX'. */ #define CHAR_ENC_CPY_4 8 /* 4-byte UTF-8, copy. */ #define CHAR_ENC_ESC_4 9 /* 4-byte UTF-8, escaped as '\uXXXX\uXXXX'. */ /** Character encode type table: don't escape unicode, don't escape '/'. (generate with misc/make_tables.c) */ static const char_enc_type enc_table_cpy[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1 }; /** Character encode type table: don't escape unicode, escape '/'. (generate with misc/make_tables.c) */ static const char_enc_type enc_table_cpy_slash[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1 }; /** Character encode type table: escape unicode, don't escape '/'. (generate with misc/make_tables.c) */ static const char_enc_type enc_table_esc[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1 }; /** Character encode type table: escape unicode, escape '/'. (generate with misc/make_tables.c) */ static const char_enc_type enc_table_esc_slash[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1 }; /** Escaped hex character table: ["00" "01" "02" ... "FD" "FE" "FF"]. (generate with misc/make_tables.c) */ yyjson_align(2) static const u8 esc_hex_char_table[512] = { '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '0', 'A', '0', 'B', '0', 'C', '0', 'D', '0', 'E', '0', 'F', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '1', 'A', '1', 'B', '1', 'C', '1', 'D', '1', 'E', '1', 'F', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '2', 'A', '2', 'B', '2', 'C', '2', 'D', '2', 'E', '2', 'F', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '3', 'A', '3', 'B', '3', 'C', '3', 'D', '3', 'E', '3', 'F', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '4', 'A', '4', 'B', '4', 'C', '4', 'D', '4', 'E', '4', 'F', '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', '5', 'A', '5', 'B', '5', 'C', '5', 'D', '5', 'E', '5', 'F', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', '6', 'A', '6', 'B', '6', 'C', '6', 'D', '6', 'E', '6', 'F', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '7', 'A', '7', 'B', '7', 'C', '7', 'D', '7', 'E', '7', 'F', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '8', 'A', '8', 'B', '8', 'C', '8', 'D', '8', 'E', '8', 'F', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9', '9', 'A', '9', 'B', '9', 'C', '9', 'D', '9', 'E', '9', 'F', 'A', '0', 'A', '1', 'A', '2', 'A', '3', 'A', '4', 'A', '5', 'A', '6', 'A', '7', 'A', '8', 'A', '9', 'A', 'A', 'A', 'B', 'A', 'C', 'A', 'D', 'A', 'E', 'A', 'F', 'B', '0', 'B', '1', 'B', '2', 'B', '3', 'B', '4', 'B', '5', 'B', '6', 'B', '7', 'B', '8', 'B', '9', 'B', 'A', 'B', 'B', 'B', 'C', 'B', 'D', 'B', 'E', 'B', 'F', 'C', '0', 'C', '1', 'C', '2', 'C', '3', 'C', '4', 'C', '5', 'C', '6', 'C', '7', 'C', '8', 'C', '9', 'C', 'A', 'C', 'B', 'C', 'C', 'C', 'D', 'C', 'E', 'C', 'F', 'D', '0', 'D', '1', 'D', '2', 'D', '3', 'D', '4', 'D', '5', 'D', '6', 'D', '7', 'D', '8', 'D', '9', 'D', 'A', 'D', 'B', 'D', 'C', 'D', 'D', 'D', 'E', 'D', 'F', 'E', '0', 'E', '1', 'E', '2', 'E', '3', 'E', '4', 'E', '5', 'E', '6', 'E', '7', 'E', '8', 'E', '9', 'E', 'A', 'E', 'B', 'E', 'C', 'E', 'D', 'E', 'E', 'E', 'F', 'F', '0', 'F', '1', 'F', '2', 'F', '3', 'F', '4', 'F', '5', 'F', '6', 'F', '7', 'F', '8', 'F', '9', 'F', 'A', 'F', 'B', 'F', 'C', 'F', 'D', 'F', 'E', 'F', 'F' }; /** Escaped single character table. (generate with misc/make_tables.c) */ yyjson_align(2) static const u8 esc_single_char_table[512] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\\', 'b', '\\', 't', '\\', 'n', ' ', ' ', '\\', 'f', '\\', 'r', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\\', '"', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\\', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\\', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; /** Returns the encode table with options. */ static_inline const char_enc_type *get_enc_table_with_flag( yyjson_read_flag flg) { if (unlikely(flg & YYJSON_WRITE_ESCAPE_UNICODE)) { if (unlikely(flg & YYJSON_WRITE_ESCAPE_SLASHES)) { return enc_table_esc_slash; } else { return enc_table_esc; } } else { if (unlikely(flg & YYJSON_WRITE_ESCAPE_SLASHES)) { return enc_table_cpy_slash; } else { return enc_table_cpy; } } } /** Write raw string. */ static_inline u8 *write_raw(u8 *cur, const u8 *raw, usize raw_len) { memcpy(cur, raw, raw_len); return cur + raw_len; } /** Write UTF-8 string (requires len * 6 + 2 bytes buffer). @param cur Buffer cursor. @param esc Escape unicode. @param inv Allow invalid unicode. @param str A UTF-8 string, null-terminator is not required. @param str_len Length of string in bytes. @param enc_table Encode type table for character. @return The buffer cursor after string, or NULL on invalid unicode. */ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, const u8 *str, usize str_len, const char_enc_type *enc_table) { /* UTF-8 character mask and pattern, see `read_string()` for details. */ #if YYJSON_ENDIAN == YYJSON_BIG_ENDIAN const u16 b2_mask = 0xE0C0UL; const u16 b2_patt = 0xC080UL; const u16 b2_requ = 0x1E00UL; const u32 b3_mask = 0xF0C0C000UL; const u32 b3_patt = 0xE0808000UL; const u32 b3_requ = 0x0F200000UL; const u32 b3_erro = 0x0D200000UL; const u32 b4_mask = 0xF8C0C0C0UL; const u32 b4_patt = 0xF0808080UL; const u32 b4_requ = 0x07300000UL; const u32 b4_err0 = 0x04000000UL; const u32 b4_err1 = 0x03300000UL; #elif YYJSON_ENDIAN == YYJSON_LITTLE_ENDIAN const u16 b2_mask = 0xC0E0UL; const u16 b2_patt = 0x80C0UL; const u16 b2_requ = 0x001EUL; const u32 b3_mask = 0x00C0C0F0UL; const u32 b3_patt = 0x008080E0UL; const u32 b3_requ = 0x0000200FUL; const u32 b3_erro = 0x0000200DUL; const u32 b4_mask = 0xC0C0C0F8UL; const u32 b4_patt = 0x808080F0UL; const u32 b4_requ = 0x00003007UL; const u32 b4_err0 = 0x00000004UL; const u32 b4_err1 = 0x00003003UL; #else v16_uni b2_mask_uni = {{ 0xE0, 0xC0 }}; v16_uni b2_patt_uni = {{ 0xC0, 0x80 }}; v16_uni b2_requ_uni = {{ 0x1E, 0x00 }}; v32_uni b3_mask_uni = {{ 0xF0, 0xC0, 0xC0, 0x00 }}; v32_uni b3_patt_uni = {{ 0xE0, 0x80, 0x80, 0x00 }}; v32_uni b3_requ_uni = {{ 0x0F, 0x20, 0x00, 0x00 }}; v32_uni b3_erro_uni = {{ 0x0D, 0x20, 0x00, 0x00 }}; v32_uni b4_mask_uni = {{ 0xF8, 0xC0, 0xC0, 0xC0 }}; v32_uni b4_patt_uni = {{ 0xF0, 0x80, 0x80, 0x80 }}; v32_uni b4_requ_uni = {{ 0x07, 0x30, 0x00, 0x00 }}; v32_uni b4_err0_uni = {{ 0x04, 0x00, 0x00, 0x00 }}; v32_uni b4_err1_uni = {{ 0x03, 0x30, 0x00, 0x00 }}; u16 b2_mask = b2_mask_uni.u; u16 b2_patt = b2_patt_uni.u; u16 b2_requ = b2_requ_uni.u; u32 b3_mask = b3_mask_uni.u; u32 b3_patt = b3_patt_uni.u; u32 b3_requ = b3_requ_uni.u; u32 b3_erro = b3_erro_uni.u; u32 b4_mask = b4_mask_uni.u; u32 b4_patt = b4_patt_uni.u; u32 b4_requ = b4_requ_uni.u; u32 b4_err0 = b4_err0_uni.u; u32 b4_err1 = b4_err1_uni.u; #endif #define is_valid_seq_2(uni) ( \ ((uni & b2_mask) == b2_patt) && \ ((uni & b2_requ)) \ ) #define is_valid_seq_3(uni) ( \ ((uni & b3_mask) == b3_patt) && \ ((tmp = (uni & b3_requ))) && \ ((tmp != b3_erro)) \ ) #define is_valid_seq_4(uni) ( \ ((uni & b4_mask) == b4_patt) && \ ((tmp = (uni & b4_requ))) && \ ((tmp & b4_err0) == 0 || (tmp & b4_err1) == 0) \ ) /* The replacement character U+FFFD, used to indicate invalid character. */ const v32 rep = { 'F', 'F', 'F', 'D' }; const v32 pre = { '\\', 'u', '0', '0' }; const u8 *src = str; const u8 *end = str + str_len; *cur++ = '"'; copy_ascii: /* Copy continuous ASCII, loop unrolling, same as the following code: while (end > src) ( if (unlikely(enc_table[*src])) break; *cur++ = *src++; ); */ #define expr_jump(i) \ if (unlikely(enc_table[src[i]])) goto stop_char_##i; #define expr_stop(i) \ stop_char_##i: \ memcpy(cur, src, i); \ cur += i; src += i; goto copy_utf8; while (end - src >= 16) { repeat16_incr(expr_jump) byte_copy_16(cur, src); cur += 16; src += 16; } while (end - src >= 4) { repeat4_incr(expr_jump) byte_copy_4(cur, src); cur += 4; src += 4; } while (end > src) { expr_jump(0) *cur++ = *src++; } *cur++ = '"'; return cur; repeat16_incr(expr_stop) #undef expr_jump #undef expr_stop copy_utf8: if (unlikely(src + 4 > end)) { if (end == src) goto copy_end; if (end - src < enc_table[*src] / 2) goto err_one; } switch (enc_table[*src]) { case CHAR_ENC_CPY_1: { *cur++ = *src++; goto copy_ascii; } case CHAR_ENC_CPY_2: { u16 v; v = byte_load_2(src); if (unlikely(!is_valid_seq_2(v))) goto err_cpy; byte_copy_2(cur, src); cur += 2; src += 2; goto copy_utf8; } case CHAR_ENC_CPY_3: { u32 v, tmp; if (likely(src + 4 <= end)) { v = byte_load_4(src); if (unlikely(!is_valid_seq_3(v))) goto err_cpy; byte_copy_4(cur, src); } else { v = byte_load_3(src); if (unlikely(!is_valid_seq_3(v))) goto err_cpy; byte_copy_4(cur, &v); } cur += 3; src += 3; goto copy_utf8; } case CHAR_ENC_CPY_4: { u32 v, tmp; v = byte_load_4(src); if (unlikely(!is_valid_seq_4(v))) goto err_cpy; byte_copy_4(cur, src); cur += 4; src += 4; goto copy_utf8; } case CHAR_ENC_ESC_A: { byte_move_2(cur, &esc_single_char_table[*src * 2]); cur += 2; src += 1; goto copy_utf8; } case CHAR_ENC_ESC_1: { byte_copy_4(cur + 0, &pre); byte_copy_2(cur + 4, &esc_hex_char_table[*src * 2]); cur += 6; src += 1; goto copy_utf8; } case CHAR_ENC_ESC_2: { u16 u, v; v = byte_load_2(src); if (unlikely(!is_valid_seq_2(v))) goto err_esc; u = (u16)(((u16)(src[0] & 0x1F) << 6) | ((u16)(src[1] & 0x3F) << 0)); byte_copy_2(cur + 0, &pre); byte_copy_2(cur + 2, &esc_hex_char_table[(u >> 8) * 2]); byte_copy_2(cur + 4, &esc_hex_char_table[(u & 0xFF) * 2]); cur += 6; src += 2; goto copy_utf8; } case CHAR_ENC_ESC_3: { u16 u; u32 v, tmp; v = byte_load_3(src); if (unlikely(!is_valid_seq_3(v))) goto err_esc; u = (u16)(((u16)(src[0] & 0x0F) << 12) | ((u16)(src[1] & 0x3F) << 6) | ((u16)(src[2] & 0x3F) << 0)); byte_copy_2(cur + 0, &pre); byte_copy_2(cur + 2, &esc_hex_char_table[(u >> 8) * 2]); byte_copy_2(cur + 4, &esc_hex_char_table[(u & 0xFF) * 2]); cur += 6; src += 3; goto copy_utf8; } case CHAR_ENC_ESC_4: { u32 hi, lo, u, v, tmp; v = byte_load_4(src); if (unlikely(!is_valid_seq_4(v))) goto err_esc; u = ((u32)(src[0] & 0x07) << 18) | ((u32)(src[1] & 0x3F) << 12) | ((u32)(src[2] & 0x3F) << 6) | ((u32)(src[3] & 0x3F) << 0); u -= 0x10000; hi = (u >> 10) + 0xD800; lo = (u & 0x3FF) + 0xDC00; byte_copy_2(cur + 0, &pre); byte_copy_2(cur + 2, &esc_hex_char_table[(hi >> 8) * 2]); byte_copy_2(cur + 4, &esc_hex_char_table[(hi & 0xFF) * 2]); byte_copy_2(cur + 6, &pre); byte_copy_2(cur + 8, &esc_hex_char_table[(lo >> 8) * 2]); byte_copy_2(cur + 10, &esc_hex_char_table[(lo & 0xFF) * 2]); cur += 12; src += 4; goto copy_utf8; } case CHAR_ENC_ERR_1: { goto err_one; } default: break; } copy_end: *cur++ = '"'; return cur; err_one: if (esc) goto err_esc; else goto err_cpy; err_cpy: if (!inv) return NULL; *cur++ = *src++; goto copy_utf8; err_esc: if (!inv) return NULL; byte_copy_2(cur + 0, &pre); byte_copy_4(cur + 2, &rep); cur += 6; src += 1; goto copy_utf8; #undef is_valid_seq_2 #undef is_valid_seq_3 #undef is_valid_seq_4 } /*============================================================================== * Writer Utilities *============================================================================*/ /** Write null (requires 8 bytes buffer). */ static_inline u8 *write_null(u8 *cur) { v64 v = { 'n', 'u', 'l', 'l', ',', '\n', 0, 0 }; byte_copy_8(cur, &v); return cur + 4; } /** Write bool (requires 8 bytes buffer). */ static_inline u8 *write_bool(u8 *cur, bool val) { v64 v0 = { 'f', 'a', 'l', 's', 'e', ',', '\n', 0 }; v64 v1 = { 't', 'r', 'u', 'e', ',', '\n', 0, 0 }; if (val) { byte_copy_8(cur, &v1); } else { byte_copy_8(cur, &v0); } return cur + 5 - val; } /** Write indent (requires level x 4 bytes buffer). Param spaces should not larger than 4. */ static_inline u8 *write_indent(u8 *cur, usize level, usize spaces) { while (level-- > 0) { byte_copy_4(cur, " "); cur += spaces; } return cur; } /** Write data to file pointer. */ static bool write_dat_to_fp(FILE *fp, u8 *dat, usize len, yyjson_write_err *err) { if (fwrite(dat, len, 1, fp) != 1) { err->msg = "file writing failed"; err->code = YYJSON_WRITE_ERROR_FILE_WRITE; return false; } return true; } /** Write data to file. */ static bool write_dat_to_file(const char *path, u8 *dat, usize len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ err->msg = _msg; \ err->code = YYJSON_WRITE_ERROR_##_code; \ if (file) fclose(file); \ return false; \ } while (false) FILE *file = fopen_writeonly(path); if (file == NULL) { return_err(FILE_OPEN, "file opening failed"); } if (fwrite(dat, len, 1, file) != 1) { return_err(FILE_WRITE, "file writing failed"); } if (fclose(file) != 0) { file = NULL; return_err(FILE_WRITE, "file closing failed"); } return true; #undef return_err } /*============================================================================== * JSON Writer Implementation *============================================================================*/ typedef struct yyjson_write_ctx { usize tag; } yyjson_write_ctx; static_inline void yyjson_write_ctx_set(yyjson_write_ctx *ctx, usize size, bool is_obj) { ctx->tag = (size << 1) | (usize)is_obj; } static_inline void yyjson_write_ctx_get(yyjson_write_ctx *ctx, usize *size, bool *is_obj) { usize tag = ctx->tag; *size = tag >> 1; *is_obj = (bool)(tag & 1); } /** Write single JSON value. */ static_inline u8 *yyjson_write_single(yyjson_val *val, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ if (hdr) alc.free(alc.ctx, (void *)hdr); \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ return NULL; \ } while (false) #define incr_len(_len) do { \ hdr = (u8 *)alc.malloc(alc.ctx, _len); \ if (!hdr) goto fail_alloc; \ cur = hdr; \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) u8 *hdr = NULL, *cur; usize str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; switch (unsafe_yyjson_get_type(val)) { case YYJSON_TYPE_RAW: str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 1); cur = write_raw(cur, str_ptr, str_len); break; case YYJSON_TYPE_STR: str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 4); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; break; case YYJSON_TYPE_NUM: incr_len(32); cur = write_number(cur, val, flg); if (unlikely(!cur)) goto fail_num; break; case YYJSON_TYPE_BOOL: incr_len(8); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); break; case YYJSON_TYPE_NULL: incr_len(8); cur = write_null(cur); break; case YYJSON_TYPE_ARR: incr_len(4); byte_copy_2(cur, "[]"); cur += 2; break; case YYJSON_TYPE_OBJ: incr_len(4); byte_copy_2(cur, "{}"); cur += 2; break; default: goto fail_type; } *cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef check_str_len #undef incr_len } /** Write JSON document minify. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_write_minify(const yyjson_val *root, const yyjson_write_flag flg, const yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \ if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ ctx_len = (usize)(end - (u8 *)ctx); \ ctx_tmp = (yyjson_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \ ctx = ctx_tmp; \ cur = tmp + (cur - hdr); \ end = tmp + alc_len; \ hdr = tmp; \ } \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) yyjson_val *val; yyjson_type val_type; usize ctn_len, ctn_len_tmp; bool ctn_obj, ctn_obj_tmp, is_key; u8 *hdr, *cur, *end, *tmp; yyjson_write_ctx *ctx, *ctx_tmp; usize alc_len, alc_inc, ctx_len, ext_len, str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; alc_len = root->uni.ofs / sizeof(yyjson_val); alc_len = alc_len * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_write_ctx *)(void *)end; doc_begin: val = constcast(yyjson_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); val++; val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { is_key = ((u8)ctn_obj & (u8)~ctn_len); str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; *cur++ = is_key ? ':' : ','; goto val_end; } if (val_type == YYJSON_TYPE_NUM) { incr_len(32); cur = write_number(cur, val, flg); if (unlikely(!cur)) goto fail_num; *cur++ = ','; goto val_end; } if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { ctn_len_tmp = unsafe_yyjson_get_len(val); ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); incr_len(16); if (unlikely(ctn_len_tmp == 0)) { /* write empty container */ *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); *cur++ = ','; goto val_end; } else { /* push context, setup new container */ yyjson_write_ctx_set(--ctx, ctn_len, ctn_obj); ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; ctn_obj = ctn_obj_tmp; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); val++; goto val_begin; } } if (val_type == YYJSON_TYPE_BOOL) { incr_len(16); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); cur++; goto val_end; } if (val_type == YYJSON_TYPE_NULL) { incr_len(16); cur = write_null(cur); cur++; goto val_end; } if (val_type == YYJSON_TYPE_RAW) { str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 2); cur = write_raw(cur, str_ptr, str_len); *cur++ = ','; goto val_end; } goto fail_type; val_end: val++; ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; goto val_begin; ctn_end: cur--; *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); *cur++ = ','; if (unlikely((u8 *)ctx >= end)) goto doc_end; yyjson_write_ctx_get(ctx++, &ctn_len, &ctn_obj); ctn_len--; if (likely(ctn_len > 0)) { goto val_begin; } else { goto ctn_end; } doc_end: *--cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef incr_len #undef check_str_len } /** Write JSON document pretty. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, const yyjson_write_flag flg, const yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \ if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ ctx_len = (usize)(end - (u8 *)ctx); \ ctx_tmp = (yyjson_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \ ctx = ctx_tmp; \ cur = tmp + (cur - hdr); \ end = tmp + alc_len; \ hdr = tmp; \ } \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) yyjson_val *val; yyjson_type val_type; usize ctn_len, ctn_len_tmp; bool ctn_obj, ctn_obj_tmp, is_key, no_indent; u8 *hdr, *cur, *end, *tmp; yyjson_write_ctx *ctx, *ctx_tmp; usize alc_len, alc_inc, ctx_len, ext_len, str_len, level; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; usize spaces = (flg & YYJSON_WRITE_PRETTY_TWO_SPACES) ? 2 : 4; alc_len = root->uni.ofs / sizeof(yyjson_val); alc_len = alc_len * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_write_ctx *)(void *)end; doc_begin: val = constcast(yyjson_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); *cur++ = '\n'; val++; level = 1; val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { is_key = (bool)((u8)ctn_obj & (u8)~ctn_len); no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; *cur++ = is_key ? ':' : ','; *cur++ = is_key ? ' ' : '\n'; goto val_end; } if (val_type == YYJSON_TYPE_NUM) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(32 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_number(cur, val, flg); if (unlikely(!cur)) goto fail_num; *cur++ = ','; *cur++ = '\n'; goto val_end; } if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); ctn_len_tmp = unsafe_yyjson_get_len(val); ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); if (unlikely(ctn_len_tmp == 0)) { /* write empty container */ incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); *cur++ = ','; *cur++ = '\n'; goto val_end; } else { /* push context, setup new container */ incr_len(32 + (no_indent ? 0 : level * 4)); yyjson_write_ctx_set(--ctx, ctn_len, ctn_obj); ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; ctn_obj = ctn_obj_tmp; cur = write_indent(cur, no_indent ? 0 : level, spaces); level++; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); *cur++ = '\n'; val++; goto val_begin; } } if (val_type == YYJSON_TYPE_BOOL) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); cur += 2; goto val_end; } if (val_type == YYJSON_TYPE_NULL) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_null(cur); cur += 2; goto val_end; } if (val_type == YYJSON_TYPE_RAW) { str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 3); cur = write_raw(cur, str_ptr, str_len); *cur++ = ','; *cur++ = '\n'; goto val_end; } goto fail_type; val_end: val++; ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; goto val_begin; ctn_end: cur -= 2; *cur++ = '\n'; incr_len(level * 4); cur = write_indent(cur, --level, spaces); *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); if (unlikely((u8 *)ctx >= end)) goto doc_end; yyjson_write_ctx_get(ctx++, &ctn_len, &ctn_obj); ctn_len--; *cur++ = ','; *cur++ = '\n'; if (likely(ctn_len > 0)) { goto val_begin; } else { goto ctn_end; } doc_end: *cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef incr_len #undef check_str_len } char *yyjson_val_write_opts(const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { yyjson_write_err dummy_err; usize dummy_dat_len; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; yyjson_val *root = constcast(yyjson_val *)val; err = err ? err : &dummy_err; dat_len = dat_len ? dat_len : &dummy_dat_len; #if YYJSON_DISABLE_NON_STANDARD flg &= ~YYJSON_WRITE_ALLOW_INF_AND_NAN; flg &= ~YYJSON_WRITE_ALLOW_INVALID_UNICODE; #endif if (unlikely(!root)) { *dat_len = 0; err->msg = "input JSON is NULL"; err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; return NULL; } if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) { return (char *)yyjson_write_single(root, flg, alc, dat_len, err); } else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) { return (char *)yyjson_write_pretty(root, flg, alc, dat_len, err); } else { return (char *)yyjson_write_minify(root, flg, alc, dat_len, err); } } char *yyjson_write_opts(const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { yyjson_val *root = doc ? doc->root : NULL; return yyjson_val_write_opts(root, flg, alc_ptr, dat_len, err); } bool yyjson_val_write_file(const char *path, const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; yyjson_val *root = constcast(yyjson_val *)val; bool suc; alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!path || !*path)) { err->msg = "input path is invalid"; err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; return false; } dat = (u8 *)yyjson_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_file(path, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; } bool yyjson_val_write_fp(FILE *fp, const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; yyjson_val *root = constcast(yyjson_val *)val; bool suc; alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!fp)) { err->msg = "input fp is invalid"; err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; return false; } dat = (u8 *)yyjson_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_fp(fp, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; } bool yyjson_write_file(const char *path, const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_val *root = doc ? doc->root : NULL; return yyjson_val_write_file(path, root, flg, alc_ptr, err); } bool yyjson_write_fp(FILE *fp, const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_val *root = doc ? doc->root : NULL; return yyjson_val_write_fp(fp, root, flg, alc_ptr, err); } /*============================================================================== * Mutable JSON Writer Implementation *============================================================================*/ typedef struct yyjson_mut_write_ctx { usize tag; yyjson_mut_val *ctn; } yyjson_mut_write_ctx; static_inline void yyjson_mut_write_ctx_set(yyjson_mut_write_ctx *ctx, yyjson_mut_val *ctn, usize size, bool is_obj) { ctx->tag = (size << 1) | (usize)is_obj; ctx->ctn = ctn; } static_inline void yyjson_mut_write_ctx_get(yyjson_mut_write_ctx *ctx, yyjson_mut_val **ctn, usize *size, bool *is_obj) { usize tag = ctx->tag; *size = tag >> 1; *is_obj = (bool)(tag & 1); *ctn = ctx->ctn; } /** Get the estimated number of values for the mutable JSON document. */ static_inline usize yyjson_mut_doc_estimated_val_num( const yyjson_mut_doc *doc) { usize sum = 0; yyjson_val_chunk *chunk = doc->val_pool.chunks; while (chunk) { sum += chunk->chunk_size / sizeof(yyjson_mut_val) - 1; if (chunk == doc->val_pool.chunks) { sum -= (usize)(doc->val_pool.end - doc->val_pool.cur); } chunk = chunk->next; } return sum; } /** Write single JSON value. */ static_inline u8 *yyjson_mut_write_single(yyjson_mut_val *val, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { return yyjson_write_single((yyjson_val *)val, flg, alc, dat_len, err); } /** Write JSON document minify. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, usize estimated_val_num, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \ if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ ctx_len = (usize)(end - (u8 *)ctx); \ ctx_tmp = (yyjson_mut_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \ ctx = ctx_tmp; \ cur = tmp + (cur - hdr); \ end = tmp + alc_len; \ hdr = tmp; \ } \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) yyjson_mut_val *val, *ctn; yyjson_type val_type; usize ctn_len, ctn_len_tmp; bool ctn_obj, ctn_obj_tmp, is_key; u8 *hdr, *cur, *end, *tmp; yyjson_mut_write_ctx *ctx, *ctx_tmp; usize alc_len, alc_inc, ctx_len, ext_len, str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_mut_write_ctx *)(void *)end; doc_begin: val = constcast(yyjson_mut_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); ctn = val; val = (yyjson_mut_val *)val->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { is_key = ((u8)ctn_obj & (u8)~ctn_len); str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; *cur++ = is_key ? ':' : ','; goto val_end; } if (val_type == YYJSON_TYPE_NUM) { incr_len(32); cur = write_number(cur, (yyjson_val *)val, flg); if (unlikely(!cur)) goto fail_num; *cur++ = ','; goto val_end; } if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { ctn_len_tmp = unsafe_yyjson_get_len(val); ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); incr_len(16); if (unlikely(ctn_len_tmp == 0)) { /* write empty container */ *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); *cur++ = ','; goto val_end; } else { /* push context, setup new container */ yyjson_mut_write_ctx_set(--ctx, ctn, ctn_len, ctn_obj); ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; ctn_obj = ctn_obj_tmp; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); ctn = val; val = (yyjson_mut_val *)ctn->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; goto val_begin; } } if (val_type == YYJSON_TYPE_BOOL) { incr_len(16); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); cur++; goto val_end; } if (val_type == YYJSON_TYPE_NULL) { incr_len(16); cur = write_null(cur); cur++; goto val_end; } if (val_type == YYJSON_TYPE_RAW) { str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 2); cur = write_raw(cur, str_ptr, str_len); *cur++ = ','; goto val_end; } goto fail_type; val_end: ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; val = val->next; goto val_begin; ctn_end: cur--; *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); *cur++ = ','; if (unlikely((u8 *)ctx >= end)) goto doc_end; val = ctn->next; yyjson_mut_write_ctx_get(ctx++, &ctn, &ctn_len, &ctn_obj); ctn_len--; if (likely(ctn_len > 0)) { goto val_begin; } else { goto ctn_end; } doc_end: *--cur = '\0'; *dat_len = (usize)(cur - hdr); err->code = YYJSON_WRITE_SUCCESS; err->msg = "success"; return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef incr_len #undef check_str_len } /** Write JSON document pretty. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, usize estimated_val_num, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \ if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ ctx_len = (usize)(end - (u8 *)ctx); \ ctx_tmp = (yyjson_mut_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \ ctx = ctx_tmp; \ cur = tmp + (cur - hdr); \ end = tmp + alc_len; \ hdr = tmp; \ } \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) yyjson_mut_val *val, *ctn; yyjson_type val_type; usize ctn_len, ctn_len_tmp; bool ctn_obj, ctn_obj_tmp, is_key, no_indent; u8 *hdr, *cur, *end, *tmp; yyjson_mut_write_ctx *ctx, *ctx_tmp; usize alc_len, alc_inc, ctx_len, ext_len, str_len, level; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; usize spaces = (flg & YYJSON_WRITE_PRETTY_TWO_SPACES) ? 2 : 4; alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_mut_write_ctx *)(void *)end; doc_begin: val = constcast(yyjson_mut_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); *cur++ = '\n'; ctn = val; val = (yyjson_mut_val *)val->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; level = 1; val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { is_key = (bool)((u8)ctn_obj & (u8)~ctn_len); no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; *cur++ = is_key ? ':' : ','; *cur++ = is_key ? ' ' : '\n'; goto val_end; } if (val_type == YYJSON_TYPE_NUM) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(32 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_number(cur, (yyjson_val *)val, flg); if (unlikely(!cur)) goto fail_num; *cur++ = ','; *cur++ = '\n'; goto val_end; } if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); ctn_len_tmp = unsafe_yyjson_get_len(val); ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); if (unlikely(ctn_len_tmp == 0)) { /* write empty container */ incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); *cur++ = ','; *cur++ = '\n'; goto val_end; } else { /* push context, setup new container */ incr_len(32 + (no_indent ? 0 : level * 4)); yyjson_mut_write_ctx_set(--ctx, ctn, ctn_len, ctn_obj); ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; ctn_obj = ctn_obj_tmp; cur = write_indent(cur, no_indent ? 0 : level, spaces); level++; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); *cur++ = '\n'; ctn = val; val = (yyjson_mut_val *)ctn->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; goto val_begin; } } if (val_type == YYJSON_TYPE_BOOL) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); cur += 2; goto val_end; } if (val_type == YYJSON_TYPE_NULL) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_null(cur); cur += 2; goto val_end; } if (val_type == YYJSON_TYPE_RAW) { str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 3); cur = write_raw(cur, str_ptr, str_len); *cur++ = ','; *cur++ = '\n'; goto val_end; } goto fail_type; val_end: ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; val = val->next; goto val_begin; ctn_end: cur -= 2; *cur++ = '\n'; incr_len(level * 4); cur = write_indent(cur, --level, spaces); *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); if (unlikely((u8 *)ctx >= end)) goto doc_end; val = ctn->next; yyjson_mut_write_ctx_get(ctx++, &ctn, &ctn_len, &ctn_obj); ctn_len--; *cur++ = ','; *cur++ = '\n'; if (likely(ctn_len > 0)) { goto val_begin; } else { goto ctn_end; } doc_end: *cur = '\0'; *dat_len = (usize)(cur - hdr); err->code = YYJSON_WRITE_SUCCESS; err->msg = "success"; return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef incr_len #undef check_str_len } static char *yyjson_mut_write_opts_impl(const yyjson_mut_val *val, usize estimated_val_num, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { yyjson_write_err dummy_err; usize dummy_dat_len; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; yyjson_mut_val *root = constcast(yyjson_mut_val *)val; err = err ? err : &dummy_err; dat_len = dat_len ? dat_len : &dummy_dat_len; #if YYJSON_DISABLE_NON_STANDARD flg &= ~YYJSON_WRITE_ALLOW_INF_AND_NAN; flg &= ~YYJSON_WRITE_ALLOW_INVALID_UNICODE; #endif if (unlikely(!root)) { *dat_len = 0; err->msg = "input JSON is NULL"; err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; return NULL; } if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) { return (char *)yyjson_mut_write_single(root, flg, alc, dat_len, err); } else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) { return (char *)yyjson_mut_write_pretty(root, estimated_val_num, flg, alc, dat_len, err); } else { return (char *)yyjson_mut_write_minify(root, estimated_val_num, flg, alc, dat_len, err); } } char *yyjson_mut_val_write_opts(const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { return yyjson_mut_write_opts_impl(val, 0, flg, alc_ptr, dat_len, err); } char *yyjson_mut_write_opts(const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { yyjson_mut_val *root; usize estimated_val_num; if (likely(doc)) { root = doc->root; estimated_val_num = yyjson_mut_doc_estimated_val_num(doc); } else { root = NULL; estimated_val_num = 0; } return yyjson_mut_write_opts_impl(root, estimated_val_num, flg, alc_ptr, dat_len, err); } bool yyjson_mut_val_write_file(const char *path, const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; yyjson_mut_val *root = constcast(yyjson_mut_val *)val; bool suc; alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!path || !*path)) { err->msg = "input path is invalid"; err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; return false; } dat = (u8 *)yyjson_mut_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_file(path, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; } bool yyjson_mut_val_write_fp(FILE *fp, const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; yyjson_mut_val *root = constcast(yyjson_mut_val *)val; bool suc; alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!fp)) { err->msg = "input fp is invalid"; err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; return false; } dat = (u8 *)yyjson_mut_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_fp(fp, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; } bool yyjson_mut_write_file(const char *path, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_mut_val *root = doc ? doc->root : NULL; return yyjson_mut_val_write_file(path, root, flg, alc_ptr, err); } bool yyjson_mut_write_fp(FILE *fp, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_mut_val *root = doc ? doc->root : NULL; return yyjson_mut_val_write_fp(fp, root, flg, alc_ptr, err); } #endif /* YYJSON_DISABLE_WRITER */ /*============================================================================== * Compiler Hint End *============================================================================*/ #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic pop # endif #elif defined(_MSC_VER) # pragma warning(pop) #endif /* warning suppress end */ ================================================ FILE: libsvc/Modules/Lib/MJson/yyjson.h ================================================ /*============================================================================== * Created by Yaoyuan on 2019/3/9. * Copyright (C) 2019 Yaoyuan . * * Released under the MIT License: * https://github.com/ibireme/yyjson/blob/master/LICENSE *============================================================================*/ /** @file yyjson.h */ #ifndef YYJSON_H #define YYJSON_H /*============================================================================== * Header Files *============================================================================*/ #include #include #include #include #include #include /*============================================================================== * Compile-time Options *============================================================================*/ /* Define as 1 to disable JSON reader if JSON parsing is not required. This will disable these functions at compile-time: - yyjson_read_opts() - yyjson_read_file() - yyjson_read() - yyjson_read_number() - yyjson_mut_read_number() This will reduce the binary size by about 60%. */ #ifndef YYJSON_DISABLE_READER #endif /* Define as 1 to disable JSON writer if JSON serialization is not required. This will disable these functions at compile-time: - yyjson_write() - yyjson_write_file() - yyjson_write_opts() - yyjson_val_write() - yyjson_val_write_file() - yyjson_val_write_opts() - yyjson_mut_write() - yyjson_mut_write_file() - yyjson_mut_write_opts() - yyjson_mut_val_write() - yyjson_mut_val_write_file() - yyjson_mut_val_write_opts() This will reduce the binary size by about 30%. */ #ifndef YYJSON_DISABLE_WRITER #endif /* Define as 1 to disable JSON Pointer, JSON Patch and JSON Merge Patch supports. This will disable these functions at compile-time: - yyjson_ptr_xxx() - yyjson_mut_ptr_xxx() - yyjson_doc_ptr_xxx() - yyjson_mut_doc_ptr_xxx() - yyjson_patch() - yyjson_mut_patch() - yyjson_merge_patch() - yyjson_mut_merge_patch() */ #ifndef YYJSON_DISABLE_UTILS #endif /* Define as 1 to disable the fast floating-point number conversion in yyjson, and use libc's `strtod/snprintf` instead. This will reduce the binary size by about 30%, but significantly slow down the floating-point read/write speed. */ #ifndef YYJSON_DISABLE_FAST_FP_CONV #endif /* Define as 1 to disable non-standard JSON support at compile-time: - Reading and writing inf/nan literal, such as `NaN`, `-Infinity`. - Single line and multiple line comments. - Single trailing comma at the end of an object or array. - Invalid unicode in string value. This will also invalidate these run-time options: - YYJSON_READ_ALLOW_INF_AND_NAN - YYJSON_READ_ALLOW_COMMENTS - YYJSON_READ_ALLOW_TRAILING_COMMAS - YYJSON_READ_ALLOW_INVALID_UNICODE - YYJSON_WRITE_ALLOW_INF_AND_NAN - YYJSON_WRITE_ALLOW_INVALID_UNICODE This will reduce the binary size by about 10%, and slightly improve the JSON read/write speed. */ #ifndef YYJSON_DISABLE_NON_STANDARD #endif /* Define as 1 to disable unaligned memory access if target architecture does not support unaligned memory access (such as some embedded processors). If this value is not defined, yyjson will perform some automatic detection. The wrong definition of this option may cause some performance degradation, but will not cause any run-time errors. */ #ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS #endif /* Define as 1 to export symbols when building this library as Windows DLL. */ #ifndef YYJSON_EXPORTS #endif /* Define as 1 to import symbols when using this library as Windows DLL. */ #ifndef YYJSON_IMPORTS #endif /* Define as 1 to include for compiler which doesn't support C99. */ #ifndef YYJSON_HAS_STDINT_H #endif /* Define as 1 to include for compiler which doesn't support C99. */ #ifndef YYJSON_HAS_STDBOOL_H #endif /*============================================================================== * Compiler Macros *============================================================================*/ /** compiler version (MSVC) */ #ifdef _MSC_VER # define YYJSON_MSC_VER _MSC_VER #else # define YYJSON_MSC_VER 0 #endif /** compiler version (GCC) */ #ifdef __GNUC__ # define YYJSON_GCC_VER __GNUC__ #else # define YYJSON_GCC_VER 0 #endif /** C version (STDC) */ #if defined(__STDC__) && (__STDC__ >= 1) && defined(__STDC_VERSION__) # define YYJSON_STDC_VER __STDC_VERSION__ #else # define YYJSON_STDC_VER 0 #endif /** C++ version */ #if defined(__cplusplus) # define YYJSON_CPP_VER __cplusplus #else # define YYJSON_CPP_VER 0 #endif /** compiler builtin check (since gcc 10.0, clang 2.6, icc 2021) */ #ifndef yyjson_has_builtin # ifdef __has_builtin # define yyjson_has_builtin(x) __has_builtin(x) # else # define yyjson_has_builtin(x) 0 # endif #endif /** compiler attribute check (since gcc 5.0, clang 2.9, icc 17) */ #ifndef yyjson_has_attribute # ifdef __has_attribute # define yyjson_has_attribute(x) __has_attribute(x) # else # define yyjson_has_attribute(x) 0 # endif #endif /** compiler feature check (since clang 2.6, icc 17) */ #ifndef yyjson_has_feature # ifdef __has_feature # define yyjson_has_feature(x) __has_feature(x) # else # define yyjson_has_feature(x) 0 # endif #endif /** include check (since gcc 5.0, clang 2.7, icc 16, msvc 2017 15.3) */ #ifndef yyjson_has_include # ifdef __has_include # define yyjson_has_include(x) __has_include(x) # else # define yyjson_has_include(x) 0 # endif #endif /** inline for compiler */ #ifndef yyjson_inline # if YYJSON_MSC_VER >= 1200 # define yyjson_inline __forceinline # elif defined(_MSC_VER) # define yyjson_inline __inline # elif yyjson_has_attribute(always_inline) || YYJSON_GCC_VER >= 4 # define yyjson_inline __inline__ __attribute__((always_inline)) # elif defined(__clang__) || defined(__GNUC__) # define yyjson_inline __inline__ # elif defined(__cplusplus) || YYJSON_STDC_VER >= 199901L # define yyjson_inline inline # else # define yyjson_inline # endif #endif /** noinline for compiler */ #ifndef yyjson_noinline # if YYJSON_MSC_VER >= 1400 # define yyjson_noinline __declspec(noinline) # elif yyjson_has_attribute(noinline) || YYJSON_GCC_VER >= 4 # define yyjson_noinline __attribute__((noinline)) # else # define yyjson_noinline # endif #endif /** align for compiler */ #ifndef yyjson_align # if YYJSON_MSC_VER >= 1300 # define yyjson_align(x) __declspec(align(x)) # elif yyjson_has_attribute(aligned) || defined(__GNUC__) # define yyjson_align(x) __attribute__((aligned(x))) # elif YYJSON_CPP_VER >= 201103L # define yyjson_align(x) alignas(x) # else # define yyjson_align(x) # endif #endif /** likely for compiler */ #ifndef yyjson_likely # if yyjson_has_builtin(__builtin_expect) || \ (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5) # define yyjson_likely(expr) __builtin_expect(!!(expr), 1) # else # define yyjson_likely(expr) (expr) # endif #endif /** unlikely for compiler */ #ifndef yyjson_unlikely # if yyjson_has_builtin(__builtin_expect) || \ (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5) # define yyjson_unlikely(expr) __builtin_expect(!!(expr), 0) # else # define yyjson_unlikely(expr) (expr) # endif #endif /** deprecate warning */ #ifndef yyjson_deprecated # if YYJSON_MSC_VER >= 1400 # define yyjson_deprecated(msg) __declspec(deprecated(msg)) # elif yyjson_has_feature(attribute_deprecated_with_message) || \ (YYJSON_GCC_VER > 4 || (YYJSON_GCC_VER == 4 && __GNUC_MINOR__ >= 5)) # define yyjson_deprecated(msg) __attribute__((deprecated(msg))) # elif YYJSON_GCC_VER >= 3 # define yyjson_deprecated(msg) __attribute__((deprecated)) # else # define yyjson_deprecated(msg) # endif #endif /** function export */ #ifndef yyjson_api # if defined(_WIN32) # if defined(YYJSON_EXPORTS) && YYJSON_EXPORTS # define yyjson_api __declspec(dllexport) # elif defined(YYJSON_IMPORTS) && YYJSON_IMPORTS # define yyjson_api __declspec(dllimport) # else # define yyjson_api # endif # elif yyjson_has_attribute(visibility) || YYJSON_GCC_VER >= 4 # define yyjson_api __attribute__((visibility("default"))) # else # define yyjson_api # endif #endif /** inline function export */ #ifndef yyjson_api_inline # define yyjson_api_inline static yyjson_inline #endif /** stdint (C89 compatible) */ #if (defined(YYJSON_HAS_STDINT_H) && YYJSON_HAS_STDINT_H) || \ YYJSON_MSC_VER >= 1600 || YYJSON_STDC_VER >= 199901L || \ defined(_STDINT_H) || defined(_STDINT_H_) || \ defined(__CLANG_STDINT_H) || defined(_STDINT_H_INCLUDED) || \ yyjson_has_include() # include #elif defined(_MSC_VER) # if _MSC_VER < 1300 typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; # else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; # endif #else # if UCHAR_MAX == 0xFFU typedef signed char int8_t; typedef unsigned char uint8_t; # else # error cannot find 8-bit integer type # endif # if USHRT_MAX == 0xFFFFU typedef unsigned short uint16_t; typedef signed short int16_t; # elif UINT_MAX == 0xFFFFU typedef unsigned int uint16_t; typedef signed int int16_t; # else # error cannot find 16-bit integer type # endif # if UINT_MAX == 0xFFFFFFFFUL typedef unsigned int uint32_t; typedef signed int int32_t; # elif ULONG_MAX == 0xFFFFFFFFUL typedef unsigned long uint32_t; typedef signed long int32_t; # elif USHRT_MAX == 0xFFFFFFFFUL typedef unsigned short uint32_t; typedef signed short int32_t; # else # error cannot find 32-bit integer type # endif # if defined(__INT64_TYPE__) && defined(__UINT64_TYPE__) typedef __INT64_TYPE__ int64_t; typedef __UINT64_TYPE__ uint64_t; # elif defined(__GNUC__) || defined(__clang__) # if !defined(_SYS_TYPES_H) && !defined(__int8_t_defined) __extension__ typedef long long int64_t; # endif __extension__ typedef unsigned long long uint64_t; # elif defined(_LONG_LONG) || defined(__MWERKS__) || defined(_CRAYC) || \ defined(__SUNPRO_C) || defined(__SUNPRO_CC) typedef long long int64_t; typedef unsigned long long uint64_t; # elif (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || \ defined(__WATCOM_INT64__) || defined (__alpha) || defined (__DECC) typedef __int64 int64_t; typedef unsigned __int64 uint64_t; # else # error cannot find 64-bit integer type # endif #endif /** stdbool (C89 compatible) */ #if (defined(YYJSON_HAS_STDBOOL_H) && YYJSON_HAS_STDBOOL_H) || \ (yyjson_has_include() && !defined(__STRICT_ANSI__)) || \ YYJSON_MSC_VER >= 1800 || YYJSON_STDC_VER >= 199901L # include #elif !defined(__bool_true_false_are_defined) # define __bool_true_false_are_defined 1 # if defined(__cplusplus) # if defined(__GNUC__) && !defined(__STRICT_ANSI__) # define _Bool bool # if __cplusplus < 201103L # define bool bool # define false false # define true true # endif # endif # else # define bool unsigned char # define true 1 # define false 0 # endif #endif /** char bit check */ #if defined(CHAR_BIT) # if CHAR_BIT != 8 # error non 8-bit char is not supported # endif #endif /** Microsoft Visual C++ 6.0 doesn't support converting number from u64 to f64: error C2520: conversion from unsigned __int64 to double not implemented. */ #ifndef YYJSON_U64_TO_F64_NO_IMPL # if (0 < YYJSON_MSC_VER) && (YYJSON_MSC_VER <= 1200) # define YYJSON_U64_TO_F64_NO_IMPL 1 # else # define YYJSON_U64_TO_F64_NO_IMPL 0 # endif #endif /*============================================================================== * Compile Hint Begin *============================================================================*/ /* extern "C" begin */ #ifdef __cplusplus extern "C" { #endif /* warning suppress begin */ #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunused-function" # pragma clang diagnostic ignored "-Wunused-parameter" #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-function" # pragma GCC diagnostic ignored "-Wunused-parameter" #elif defined(_MSC_VER) # pragma warning(push) # pragma warning(disable:4800) /* 'int': forcing value to 'true' or 'false' */ #endif /*============================================================================== * Version *============================================================================*/ /** The major version of yyjson. */ #define YYJSON_VERSION_MAJOR 0 /** The minor version of yyjson. */ #define YYJSON_VERSION_MINOR 7 /** The patch version of yyjson. */ #define YYJSON_VERSION_PATCH 0 /** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */ #define YYJSON_VERSION_HEX 0x000700 /** The version string of yyjson. */ #define YYJSON_VERSION_STRING "0.7.0" /** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */ yyjson_api uint32_t yyjson_version(void); /*============================================================================== * JSON Types *============================================================================*/ /** Type of JSON value (3 bit). */ typedef uint8_t yyjson_type; #define YYJSON_TYPE_NONE ((uint8_t)0) /* _____000 */ #define YYJSON_TYPE_RAW ((uint8_t)1) /* _____001 */ #define YYJSON_TYPE_NULL ((uint8_t)2) /* _____010 */ #define YYJSON_TYPE_BOOL ((uint8_t)3) /* _____011 */ #define YYJSON_TYPE_NUM ((uint8_t)4) /* _____100 */ #define YYJSON_TYPE_STR ((uint8_t)5) /* _____101 */ #define YYJSON_TYPE_ARR ((uint8_t)6) /* _____110 */ #define YYJSON_TYPE_OBJ ((uint8_t)7) /* _____111 */ /** Subtype of JSON value (2 bit). */ typedef uint8_t yyjson_subtype; #define YYJSON_SUBTYPE_NONE ((uint8_t)(0 << 3)) /* ___00___ */ #define YYJSON_SUBTYPE_FALSE ((uint8_t)(0 << 3)) /* ___00___ */ #define YYJSON_SUBTYPE_TRUE ((uint8_t)(1 << 3)) /* ___01___ */ #define YYJSON_SUBTYPE_UINT ((uint8_t)(0 << 3)) /* ___00___ */ #define YYJSON_SUBTYPE_SINT ((uint8_t)(1 << 3)) /* ___01___ */ #define YYJSON_SUBTYPE_REAL ((uint8_t)(2 << 3)) /* ___10___ */ /** Mask and bits of JSON value tag. */ #define YYJSON_TYPE_MASK ((uint8_t)0x07) /* _____111 */ #define YYJSON_TYPE_BIT ((uint8_t)3) #define YYJSON_SUBTYPE_MASK ((uint8_t)0x18) /* ___11___ */ #define YYJSON_SUBTYPE_BIT ((uint8_t)2) #define YYJSON_RESERVED_MASK ((uint8_t)0xE0) /* 111_____ */ #define YYJSON_RESERVED_BIT ((uint8_t)3) #define YYJSON_TAG_MASK ((uint8_t)0xFF) /* 11111111 */ #define YYJSON_TAG_BIT ((uint8_t)8) /** Padding size for JSON reader. */ #define YYJSON_PADDING_SIZE 4 /*============================================================================== * Allocator *============================================================================*/ /** A memory allocator. Typically you don't need to use it, unless you want to customize your own memory allocator. */ typedef struct yyjson_alc { /** Same as libc's malloc(size), should not be NULL. */ void *(*malloc)(void *ctx, size_t size); /** Same as libc's realloc(ptr, size), should not be NULL. */ void *(*realloc)(void *ctx, void *ptr, size_t old_size, size_t size); /** Same as libc's free(ptr), should not be NULL. */ void (*free)(void *ctx, void *ptr); /** A context for malloc/realloc/free, can be NULL. */ void *ctx; } yyjson_alc; /** A pool allocator uses fixed length pre-allocated memory. This allocator may be used to avoid malloc/realloc calls. The pre-allocated memory should be held by the caller. The maximum amount of memory required to read a JSON can be calculated using the `yyjson_read_max_memory_usage()` function, but the amount of memory required to write a JSON cannot be directly calculated. This is not a general-purpose allocator. If used to read multiple JSON documents and only some of them are released, it may cause memory fragmentation, leading to performance degradation and memory waste. Therefore, it is recommended to use this allocator only for reading or writing a single JSON document. @param alc The allocator to be initialized. If this parameter is NULL, the function will fail and return false. If `buf` or `size` is invalid, this will be set to an empty allocator. @param buf The buffer memory for this allocator. If this parameter is NULL, the function will fail and return false. @param size The size of `buf`, in bytes. If this parameter is less than 8 words (32/64 bytes on 32/64-bit OS), the function will fail and return false. @return true if the `alc` has been successfully initialized. @par Example @code // parse JSON with stack memory char buf[1024]; yyjson_alc alc; yyjson_alc_pool_init(&alc, buf, 1024); const char *json = "{\"name\":\"Helvetica\",\"size\":16}" yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL); // the memory of `doc` is on the stack @endcode */ yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size); /*============================================================================== * JSON Structure *============================================================================*/ /** An immutable document for reading JSON. This document holds memory for all its JSON values and strings. When it is no longer used, the user should call `yyjson_doc_free()` to free its memory. */ typedef struct yyjson_doc yyjson_doc; /** An immutable value for reading JSON. A JSON Value has the same lifetime as its document. The memory is held by its document and and cannot be freed alone. */ typedef struct yyjson_val yyjson_val; /** A mutable document for building JSON. This document holds memory for all its JSON values and strings. When it is no longer used, the user should call `yyjson_mut_doc_free()` to free its memory. */ typedef struct yyjson_mut_doc yyjson_mut_doc; /** A mutable value for building JSON. A JSON Value has the same lifetime as its document. The memory is held by its document and and cannot be freed alone. */ typedef struct yyjson_mut_val yyjson_mut_val; /*============================================================================== * JSON Reader API *============================================================================*/ /** Run-time options for JSON reader. */ typedef uint32_t yyjson_read_flag; /** Default option (RFC 8259 compliant): - Read positive integer as uint64_t. - Read negative integer as int64_t. - Read floating-point number as double with round-to-nearest mode. - Read integer which cannot fit in uint64_t or int64_t as double. - Report error if double number is infinity. - Report error if string contains invalid UTF-8 character or BOM. - Report error on trailing commas, comments, inf and nan literals. */ static const yyjson_read_flag YYJSON_READ_NOFLAG = 0 << 0; /** Read the input data in-situ. This option allows the reader to modify and use input data to store string values, which can increase reading speed slightly. The caller should hold the input data before free the document. The input data must be padded by at least `YYJSON_PADDING_SIZE` bytes. For example: `[1,2]` should be `[1,2]\0\0\0\0`, input length should be 5. */ static const yyjson_read_flag YYJSON_READ_INSITU = 1 << 0; /** Stop when done instead of issuing an error if there's additional content after a JSON document. This option may be used to parse small pieces of JSON in larger data, such as `NDJSON`. */ static const yyjson_read_flag YYJSON_READ_STOP_WHEN_DONE = 1 << 1; /** Allow single trailing comma at the end of an object or array, such as `[1,2,3,]`, `{"a":1,"b":2,}` (non-standard). */ static const yyjson_read_flag YYJSON_READ_ALLOW_TRAILING_COMMAS = 1 << 2; /** Allow C-style single line and multiple line comments (non-standard). */ static const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS = 1 << 3; /** Allow inf/nan number and literal, case-insensitive, such as 1e999, NaN, inf, -Infinity (non-standard). */ static const yyjson_read_flag YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4; /** Read all numbers as raw strings (value with `YYJSON_TYPE_RAW` type), inf/nan literal is also read as raw with `ALLOW_INF_AND_NAN` flag. */ static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5; /** Allow reading invalid unicode when parsing string values (non-standard). Invalid characters will be allowed to appear in the string values, but invalid escape sequences will still be reported as errors. This flag does not affect the performance of correctly encoded strings. @warning Strings in JSON values may contain incorrect encoding when this option is used, you need to handle these strings carefully to avoid security risks. */ static const yyjson_read_flag YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6; /** Read big numbers as raw strings. These big numbers include integers that cannot be represented by `int64_t` and `uint64_t`, and floating-point numbers that cannot be represented by finite `double`. The flag will be overridden by `YYJSON_READ_NUMBER_AS_RAW` flag. */ static const yyjson_read_flag YYJSON_READ_BIGNUM_AS_RAW = 1 << 7; /** Result code for JSON reader. */ typedef uint32_t yyjson_read_code; /** Success, no error. */ static const yyjson_read_code YYJSON_READ_SUCCESS = 0; /** Invalid parameter, such as NULL input string or 0 input length. */ static const yyjson_read_code YYJSON_READ_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failure occurs. */ static const yyjson_read_code YYJSON_READ_ERROR_MEMORY_ALLOCATION = 2; /** Input JSON string is empty. */ static const yyjson_read_code YYJSON_READ_ERROR_EMPTY_CONTENT = 3; /** Unexpected content after document, such as `[123]abc`. */ static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CONTENT = 4; /** Unexpected ending, such as `[123`. */ static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_END = 5; /** Unexpected character inside the document, such as `[abc]`. */ static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CHARACTER = 6; /** Invalid JSON structure, such as `[1,]`. */ static const yyjson_read_code YYJSON_READ_ERROR_JSON_STRUCTURE = 7; /** Invalid comment, such as unclosed multi-line comment. */ static const yyjson_read_code YYJSON_READ_ERROR_INVALID_COMMENT = 8; /** Invalid number, such as `123.e12`, `000`. */ static const yyjson_read_code YYJSON_READ_ERROR_INVALID_NUMBER = 9; /** Invalid string, such as invalid escaped character inside a string. */ static const yyjson_read_code YYJSON_READ_ERROR_INVALID_STRING = 10; /** Invalid JSON literal, such as `truu`. */ static const yyjson_read_code YYJSON_READ_ERROR_LITERAL = 11; /** Failed to open a file. */ static const yyjson_read_code YYJSON_READ_ERROR_FILE_OPEN = 12; /** Failed to read a file. */ static const yyjson_read_code YYJSON_READ_ERROR_FILE_READ = 13; /** Error information for JSON reader. */ typedef struct yyjson_read_err { /** Error code, see `yyjson_read_code` for all possible values. */ yyjson_read_code code; /** Error message, constant, no need to free (NULL if success). */ const char *msg; /** Error byte position for input data (0 if success). */ size_t pos; } yyjson_read_err; /** Read JSON with options. This function is thread-safe when: 1. The `dat` is not modified by other threads. 2. The `alc` is thread-safe or NULL. @param dat The JSON data (UTF-8 without BOM), null-terminator is not required. If this parameter is NULL, the function will fail and return NULL. The `dat` will not be modified without the flag `YYJSON_READ_INSITU`, so you can pass a `const char *` string and case it to `char *` if you don't use the `YYJSON_READ_INSITU` flag. @param len The length of JSON data in bytes. If this parameter is 0, the function will fail and return NULL. @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON reader. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON document, or NULL if an error occurs. When it's no longer needed, it should be freed with `yyjson_doc_free()`. */ yyjson_api yyjson_doc *yyjson_read_opts(char *dat, size_t len, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err); /** Read a JSON file. This function is thread-safe when: 1. The file is not modified by other threads. 2. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return NULL. @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON reader. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON document, or NULL if an error occurs. When it's no longer needed, it should be freed with `yyjson_doc_free()`. @warning On 32-bit operating system, files larger than 2GB may fail to read. */ yyjson_api yyjson_doc *yyjson_read_file(const char *path, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err); /** Read JSON from a file pointer. @param fp The file pointer. The data will be read from the current position of the FILE to the end. If this fp is NULL or invalid, the function will fail and return NULL. @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON reader. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON document, or NULL if an error occurs. When it's no longer needed, it should be freed with `yyjson_doc_free()`. @warning On 32-bit operating system, files larger than 2GB may fail to read. */ yyjson_api yyjson_doc *yyjson_read_fp(FILE *fp, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err); /** Read a JSON string. This function is thread-safe. @param dat The JSON data (UTF-8 without BOM), null-terminator is not required. If this parameter is NULL, the function will fail and return NULL. @param len The length of JSON data in bytes. If this parameter is 0, the function will fail and return NULL. @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. @return A new JSON document, or NULL if an error occurs. When it's no longer needed, it should be freed with `yyjson_doc_free()`. */ yyjson_api_inline yyjson_doc *yyjson_read(const char *dat, size_t len, yyjson_read_flag flg) { flg &= ~YYJSON_READ_INSITU; /* const string cannot be modified */ return yyjson_read_opts((char *)(void *)(size_t)(const void *)dat, len, flg, NULL, NULL); } /** Returns the size of maximum memory usage to read a JSON data. You may use this value to avoid malloc() or calloc() call inside the reader to get better performance, or read multiple JSON with one piece of memory. @param len The length of JSON data in bytes. @param flg The JSON read options. @return The maximum memory size to read this JSON, or 0 if overflow. @par Example @code // read multiple JSON with same pre-allocated memory char *dat1, *dat2, *dat3; // JSON data size_t len1, len2, len3; // JSON length size_t max_len = MAX(len1, MAX(len2, len3)); yyjson_doc *doc; // use one allocator for multiple JSON size_t size = yyjson_read_max_memory_usage(max_len, 0); void *buf = malloc(size); yyjson_alc alc; yyjson_alc_pool_init(&alc, buf, size); // no more alloc() or realloc() call during reading doc = yyjson_read_opts(dat1, len1, 0, &alc, NULL); yyjson_doc_free(doc); doc = yyjson_read_opts(dat2, len2, 0, &alc, NULL); yyjson_doc_free(doc); doc = yyjson_read_opts(dat3, len3, 0, &alc, NULL); yyjson_doc_free(doc); free(buf); @endcode @see yyjson_alc_pool_init() */ yyjson_api_inline size_t yyjson_read_max_memory_usage(size_t len, yyjson_read_flag flg) { /* 1. The max value count is (json_size / 2 + 1), for example: "[1,2,3,4]" size is 9, value count is 5. 2. Some broken JSON may cost more memory during reading, but fail at end, for example: "[[[[[[[[". 3. yyjson use 16 bytes per value, see struct yyjson_val. 4. yyjson use dynamic memory with a growth factor of 1.5. The max memory size is (json_size / 2 * 16 * 1.5 + padding). */ size_t mul = (size_t)12 + !(flg & YYJSON_READ_INSITU); size_t pad = 256; size_t max = (size_t)(~(size_t)0); if (flg & YYJSON_READ_STOP_WHEN_DONE) len = len < 256 ? 256 : len; if (len >= (max - pad - mul) / mul) return 0; return len * mul + pad; } /** Read a JSON number. This function is thread-safe when data is not modified by other threads. @param dat The JSON data (UTF-8 without BOM), null-terminator is required. If this parameter is NULL, the function will fail and return NULL. @param val The output value where result is stored. If this parameter is NULL, the function will fail and return NULL. The value will hold either UINT or SINT or REAL number; @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`. @param alc The memory allocator used for long number. It is only used when the built-in floating point reader is disabled. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return If successful, a pointer to the character after the last character used in the conversion, NULL if an error occurs. */ yyjson_api const char *yyjson_read_number(const char *dat, yyjson_val *val, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err); /** Read a JSON number. This function is thread-safe when data is not modified by other threads. @param dat The JSON data (UTF-8 without BOM), null-terminator is required. If this parameter is NULL, the function will fail and return NULL. @param val The output value where result is stored. If this parameter is NULL, the function will fail and return NULL. The value will hold either UINT or SINT or REAL number; @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`. @param alc The memory allocator used for long number. It is only used when the built-in floating point reader is disabled. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return If successful, a pointer to the character after the last character used in the conversion, NULL if an error occurs. */ yyjson_api_inline const char *yyjson_mut_read_number(const char *dat, yyjson_mut_val *val, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err) { return yyjson_read_number(dat, (yyjson_val *)val, flg, alc, err); } /*============================================================================== * JSON Writer API *============================================================================*/ /** Run-time options for JSON writer. */ typedef uint32_t yyjson_write_flag; /** Default option: - Write JSON minify. - Report error on inf or nan number. - Report error on invalid UTF-8 string. - Do not escape unicode or slash. */ static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0 << 0; /** Write JSON pretty with 4 space indent. */ static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0; /** Escape unicode as `uXXXX`, make the output ASCII only. */ static const yyjson_write_flag YYJSON_WRITE_ESCAPE_UNICODE = 1 << 1; /** Escape '/' as '\/'. */ static const yyjson_write_flag YYJSON_WRITE_ESCAPE_SLASHES = 1 << 2; /** Write inf and nan number as 'Infinity' and 'NaN' literal (non-standard). */ static const yyjson_write_flag YYJSON_WRITE_ALLOW_INF_AND_NAN = 1 << 3; /** Write inf and nan number as null literal. This flag will override `YYJSON_WRITE_ALLOW_INF_AND_NAN` flag. */ static const yyjson_write_flag YYJSON_WRITE_INF_AND_NAN_AS_NULL = 1 << 4; /** Allow invalid unicode when encoding string values (non-standard). Invalid characters in string value will be copied byte by byte. If `YYJSON_WRITE_ESCAPE_UNICODE` flag is also set, invalid character will be escaped as `U+FFFD` (replacement character). This flag does not affect the performance of correctly encoded strings. */ static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5; /** Write JSON pretty with 2 space indent. This flag will override `YYJSON_WRITE_PRETTY` flag. */ static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6; /** Result code for JSON writer */ typedef uint32_t yyjson_write_code; /** Success, no error. */ static const yyjson_write_code YYJSON_WRITE_SUCCESS = 0; /** Invalid parameter, such as NULL document. */ static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failure occurs. */ static const yyjson_write_code YYJSON_WRITE_ERROR_MEMORY_ALLOCATION = 2; /** Invalid value type in JSON document. */ static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_VALUE_TYPE = 3; /** NaN or Infinity number occurs. */ static const yyjson_write_code YYJSON_WRITE_ERROR_NAN_OR_INF = 4; /** Failed to open a file. */ static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_OPEN = 5; /** Failed to write a file. */ static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_WRITE = 6; /** Invalid unicode in string. */ static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_STRING = 7; /** Error information for JSON writer. */ typedef struct yyjson_write_err { /** Error code, see `yyjson_write_code` for all possible values. */ yyjson_write_code code; /** Error message, constant, no need to free (NULL if success). */ const char *msg; } yyjson_write_err; /*============================================================================== * JSON Document Writer API *============================================================================*/ /** Write a document to JSON string with options. This function is thread-safe when: The `alc` is thread-safe or NULL. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free() or alc->free(). */ yyjson_api char *yyjson_write_opts(const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, size_t *len, yyjson_write_err *err); /** Write a document to JSON file with options. This function is thread-safe when: 1. The file is not accessed by other threads. 2. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return false. If this file is not empty, the content will be discarded. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_write_file(const char *path, const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a document to file pointer with options. @param fp The file pointer. The data will be written to the current position of the file. If this fp is NULL or invalid, the function will fail and return false. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_write_fp(FILE *fp, const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a document to JSON string. This function is thread-safe. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). */ yyjson_api_inline char *yyjson_write(const yyjson_doc *doc, yyjson_write_flag flg, size_t *len) { return yyjson_write_opts(doc, flg, NULL, len, NULL); } /** Write a document to JSON string with options. This function is thread-safe when: 1. The `doc` is not modified by other threads. 2. The `alc` is thread-safe or NULL. @param doc The mutable JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free() or alc->free(). */ yyjson_api char *yyjson_mut_write_opts(const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, size_t *len, yyjson_write_err *err); /** Write a document to JSON file with options. This function is thread-safe when: 1. The file is not accessed by other threads. 2. The `doc` is not modified by other threads. 3. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return false. If this file is not empty, the content will be discarded. @param doc The mutable JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_mut_write_file(const char *path, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a document to file pointer with options. @param fp The file pointer. The data will be written to the current position of the file. If this fp is NULL or invalid, the function will fail and return false. @param doc The mutable JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_mut_write_fp(FILE *fp, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a document to JSON string. This function is thread-safe when: The `doc` is not modified by other threads. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). */ yyjson_api_inline char *yyjson_mut_write(const yyjson_mut_doc *doc, yyjson_write_flag flg, size_t *len) { return yyjson_mut_write_opts(doc, flg, NULL, len, NULL); } /*============================================================================== * JSON Value Writer API *============================================================================*/ /** Write a value to JSON string with options. This function is thread-safe when: The `alc` is thread-safe or NULL. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free() or alc->free(). */ yyjson_api char *yyjson_val_write_opts(const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc, size_t *len, yyjson_write_err *err); /** Write a value to JSON file with options. This function is thread-safe when: 1. The file is not accessed by other threads. 2. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return false. If this file is not empty, the content will be discarded. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_val_write_file(const char *path, const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a value to file pointer with options. @param fp The file pointer. The data will be written to the current position of the file. If this path is NULL or invalid, the function will fail and return false. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_val_write_fp(FILE *fp, const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a value to JSON string. This function is thread-safe. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). */ yyjson_api_inline char *yyjson_val_write(const yyjson_val *val, yyjson_write_flag flg, size_t *len) { return yyjson_val_write_opts(val, flg, NULL, len, NULL); } /** Write a value to JSON string with options. This function is thread-safe when: 1. The `val` is not modified by other threads. 2. The `alc` is thread-safe or NULL. @param val The mutable JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free() or alc->free(). */ yyjson_api char *yyjson_mut_val_write_opts(const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc, size_t *len, yyjson_write_err *err); /** Write a value to JSON file with options. This function is thread-safe when: 1. The file is not accessed by other threads. 2. The `val` is not modified by other threads. 3. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return false. If this file is not empty, the content will be discarded. @param val The mutable JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_mut_val_write_file(const char *path, const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a value to JSON file with options. @param fp The file pointer. The data will be written to the current position of the file. If this path is NULL or invalid, the function will fail and return false. @param val The mutable JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_mut_val_write_fp(FILE *fp, const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a value to JSON string. This function is thread-safe when: The `val` is not modified by other threads. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). */ yyjson_api_inline char *yyjson_mut_val_write(const yyjson_mut_val *val, yyjson_write_flag flg, size_t *len) { return yyjson_mut_val_write_opts(val, flg, NULL, len, NULL); } /*============================================================================== * JSON Document API *============================================================================*/ /** Returns the root value of this JSON document. Returns NULL if `doc` is NULL. */ yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc); /** Returns read size of input JSON data. Returns 0 if `doc` is NULL. For example: the read size of `[1,2,3]` is 7 bytes. */ yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc); /** Returns total value count in this JSON document. Returns 0 if `doc` is NULL. For example: the value count of `[1,2,3]` is 4. */ yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc); /** Release the JSON document and free the memory. After calling this function, the `doc` and all values from the `doc` are no longer available. This function will do nothing if the `doc` is NULL. */ yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc); /*============================================================================== * JSON Value Type API *============================================================================*/ /** Returns whether the JSON value is raw. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_raw(yyjson_val *val); /** Returns whether the JSON value is `null`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_null(yyjson_val *val); /** Returns whether the JSON value is `true`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_true(yyjson_val *val); /** Returns whether the JSON value is `false`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_false(yyjson_val *val); /** Returns whether the JSON value is bool (true/false). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_bool(yyjson_val *val); /** Returns whether the JSON value is unsigned integer (uint64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_uint(yyjson_val *val); /** Returns whether the JSON value is signed integer (int64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_sint(yyjson_val *val); /** Returns whether the JSON value is integer (uint64_t/int64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_int(yyjson_val *val); /** Returns whether the JSON value is real number (double). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_real(yyjson_val *val); /** Returns whether the JSON value is number (uint64_t/int64_t/double). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_num(yyjson_val *val); /** Returns whether the JSON value is string. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_str(yyjson_val *val); /** Returns whether the JSON value is array. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_arr(yyjson_val *val); /** Returns whether the JSON value is object. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_obj(yyjson_val *val); /** Returns whether the JSON value is container (array/object). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val); /*============================================================================== * JSON Value Content API *============================================================================*/ /** Returns the JSON value's type. Returns YYJSON_TYPE_NONE if `val` is NULL. */ yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val); /** Returns the JSON value's subtype. Returns YYJSON_SUBTYPE_NONE if `val` is NULL. */ yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val); /** Returns the JSON value's tag. Returns 0 if `val` is NULL. */ yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val); /** Returns the JSON value's type description. The return value should be one of these strings: "raw", "null", "string", "array", "object", "true", "false", "uint", "sint", "real", "unknown". */ yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val); /** Returns the content if the value is raw. Returns NULL if `val` is NULL or type is not raw. */ yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val); /** Returns the content if the value is bool. Returns NULL if `val` is NULL or type is not bool. */ yyjson_api_inline bool yyjson_get_bool(yyjson_val *val); /** Returns the content and cast to uint64_t. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val); /** Returns the content and cast to int64_t. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val); /** Returns the content and cast to int. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline int yyjson_get_int(yyjson_val *val); /** Returns the content if the value is real number, or 0.0 on error. Returns 0.0 if `val` is NULL or type is not real(double). */ yyjson_api_inline double yyjson_get_real(yyjson_val *val); /** Returns the content and typecast to `double` if the value is number. Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */ yyjson_api_inline double yyjson_get_num(yyjson_val *val); /** Returns the content if the value is string. Returns NULL if `val` is NULL or type is not string. */ yyjson_api_inline const char *yyjson_get_str(yyjson_val *val); /** Returns the content length (string length, array size, object size. Returns 0 if `val` is NULL or type is not string/array/object. */ yyjson_api_inline size_t yyjson_get_len(yyjson_val *val); /** Returns whether the JSON value is equals to a string. Returns false if input is NULL or type is not string. */ yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str); /** Returns whether the JSON value is equals to a string. The `str` should be a UTF-8 string, null-terminator is not required. Returns false if input is NULL or type is not string. */ yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str, size_t len); /** Returns whether two JSON values are equal (deep compare). Returns false if input is NULL. @note the result may be inaccurate if object has duplicate keys. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs); /** Set the value to raw. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_raw(yyjson_val *val, const char *raw, size_t len); /** Set the value to null. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_null(yyjson_val *val); /** Set the value to bool. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num); /** Set the value to uint. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num); /** Set the value to sint. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num); /** Set the value to int. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num); /** Set the value to real. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num); /** Set the value to string (null-terminated). Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str); /** Set the value to string (with length). Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_strn(yyjson_val *val, const char *str, size_t len); /*============================================================================== * JSON Array API *============================================================================*/ /** Returns the number of elements in this array. Returns 0 if `arr` is NULL or type is not array. */ yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr); /** Returns the element at the specified position in this array. Returns NULL if array is NULL/empty or the index is out of bounds. @warning This function takes a linear search time if array is not flat. For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat. */ yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx); /** Returns the first element of this array. Returns NULL if `arr` is NULL/empty or type is not array. */ yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr); /** Returns the last element of this array. Returns NULL if `arr` is NULL/empty or type is not array. @warning This function takes a linear search time if array is not flat. For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat.*/ yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr); /*============================================================================== * JSON Array Iterator API *============================================================================*/ /** A JSON array iterator. @par Example @code yyjson_val *val; yyjson_arr_iter iter = yyjson_arr_iter_with(arr); while ((val = yyjson_arr_iter_next(&iter))) { your_func(val); } @endcode */ typedef struct yyjson_arr_iter { size_t idx; /**< next value's index */ size_t max; /**< maximum index (arr.size) */ yyjson_val *cur; /**< next value */ } yyjson_arr_iter; /** Initialize an iterator for this array. @param arr The array to be iterated over. If this parameter is NULL or not an array, `iter` will be set to empty. @param iter The iterator to be initialized. If this parameter is NULL, the function will fail and return false. @return true if the `iter` has been successfully initialized. @note The iterator does not need to be destroyed. */ yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr, yyjson_arr_iter *iter); /** Create an iterator with an array , same as `yyjson_arr_iter_init()`. @param arr The array to be iterated over. If this parameter is NULL or not an array, an empty iterator will returned. @return A new iterator for the array. @note The iterator does not need to be destroyed. */ yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr); /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. */ yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter); /** Returns the next element in the iteration, or NULL on end. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter); /** Macro for iterating over an array. It works like iterator, but with a more intuitive API. @par Example @code size_t idx, max; yyjson_val *val; yyjson_arr_foreach(arr, idx, max, val) { your_func(idx, val); } @endcode */ #define yyjson_arr_foreach(arr, idx, max, val) \ for ((idx) = 0, \ (max) = yyjson_arr_size(arr), \ (val) = yyjson_arr_get_first(arr); \ (idx) < (max); \ (idx)++, \ (val) = unsafe_yyjson_get_next(val)) /*============================================================================== * JSON Object API *============================================================================*/ /** Returns the number of key-value pairs in this object. Returns 0 if `obj` is NULL or type is not object. */ yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj); /** Returns the value to which the specified key is mapped. Returns NULL if this object contains no mapping for the key. Returns NULL if `obj/key` is NULL, or type is not object. The `key` should be a null-terminated UTF-8 string. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj, const char *key); /** Returns the value to which the specified key is mapped. Returns NULL if this object contains no mapping for the key. Returns NULL if `obj/key` is NULL, or type is not object. The `key` should be a UTF-8 string, null-terminator is not required. The `key_len` should be the length of the key, in bytes. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *key, size_t key_len); /*============================================================================== * JSON Object Iterator API *============================================================================*/ /** A JSON object iterator. @par Example @code yyjson_val *key, *val; yyjson_obj_iter iter = yyjson_obj_iter_with(obj); while ((key = yyjson_obj_iter_next(&iter))) { val = yyjson_obj_iter_get_val(key); your_func(key, val); } @endcode If the ordering of the keys is known at compile-time, you can use this method to speed up value lookups: @code // {"k1":1, "k2": 3, "k3": 3} yyjson_val *key, *val; yyjson_obj_iter iter = yyjson_obj_iter_with(obj); yyjson_val *v1 = yyjson_obj_iter_get(&iter, "k1"); yyjson_val *v3 = yyjson_obj_iter_get(&iter, "k3"); @endcode @see yyjson_obj_iter_get() and yyjson_obj_iter_getn() */ typedef struct yyjson_obj_iter { size_t idx; /**< next key's index */ size_t max; /**< maximum key index (obj.size) */ yyjson_val *cur; /**< next key */ yyjson_val *obj; /**< the object being iterated */ } yyjson_obj_iter; /** Initialize an iterator for this object. @param obj The object to be iterated over. If this parameter is NULL or not an object, `iter` will be set to empty. @param iter The iterator to be initialized. If this parameter is NULL, the function will fail and return false. @return true if the `iter` has been successfully initialized. @note The iterator does not need to be destroyed. */ yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj, yyjson_obj_iter *iter); /** Create an iterator with an object, same as `yyjson_obj_iter_init()`. @param obj The object to be iterated over. If this parameter is NULL or not an object, an empty iterator will returned. @return A new iterator for the object. @note The iterator does not need to be destroyed. */ yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj); /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. */ yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter); /** Returns the next key in the iteration, or NULL on end. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter); /** Returns the value for key inside the iteration. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key); /** Iterates to a specified key and returns the value. This function does the same thing as `yyjson_obj_get()`, but is much faster if the ordering of the keys is known at compile-time and you are using the same order to look up the values. If the key exists in this object, then the iterator will stop at the next key, otherwise the iterator will not change and NULL is returned. @param iter The object iterator, should not be NULL. @param key The key, should be a UTF-8 string with null-terminator. @return The value to which the specified key is mapped. NULL if this object contains no mapping for the key or input is invalid. @warning This function takes a linear search time if the key is not nearby. */ yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter, const char *key); /** Iterates to a specified key and returns the value. This function does the same thing as `yyjson_obj_getn()`, but is much faster if the ordering of the keys is known at compile-time and you are using the same order to look up the values. If the key exists in this object, then the iterator will stop at the next key, otherwise the iterator will not change and NULL is returned. @param iter The object iterator, should not be NULL. @param key The key, should be a UTF-8 string, null-terminator is not required. @param key_len The the length of `key`, in bytes. @return The value to which the specified key is mapped. NULL if this object contains no mapping for the key or input is invalid. @warning This function takes a linear search time if the key is not nearby. */ yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter, const char *key, size_t key_len); /** Macro for iterating over an object. It works like iterator, but with a more intuitive API. @par Example @code size_t idx, max; yyjson_val *key, *val; yyjson_obj_foreach(obj, idx, max, key, val) { your_func(key, val); } @endcode */ #define yyjson_obj_foreach(obj, idx, max, key, val) \ for ((idx) = 0, \ (max) = yyjson_obj_size(obj), \ (key) = (obj) ? unsafe_yyjson_get_first(obj) : NULL, \ (val) = (key) + 1; \ (idx) < (max); \ (idx)++, \ (key) = unsafe_yyjson_get_next(val), \ (val) = (key) + 1) /*============================================================================== * Mutable JSON Document API *============================================================================*/ /** Returns the root value of this JSON document. Returns NULL if `doc` is NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc); /** Sets the root value of this JSON document. Pass NULL to clear root value of the document. */ yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc, yyjson_mut_val *root); /** Set the string pool size for a mutable document. This function does not allocate memory immediately, but uses the size when the next memory allocation is needed. If the caller knows the approximate bytes of strings that the document needs to store (e.g. copy string with `yyjson_mut_strcpy` function), setting a larger size can avoid multiple memory allocations and improve performance. @param doc The mutable document. @param len The desired string pool size in bytes (total string length). @return true if successful, false if size is 0 or overflow. */ yyjson_api bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc, size_t len); /** Set the value pool size for a mutable document. This function does not allocate memory immediately, but uses the size when the next memory allocation is needed. If the caller knows the approximate number of values that the document needs to store (e.g. create new value with `yyjson_mut_xxx` functions), setting a larger size can avoid multiple memory allocations and improve performance. @param doc The mutable document. @param count The desired value pool size (number of `yyjson_mut_val`). @return true if successful, false if size is 0 or overflow. */ yyjson_api bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count); /** Release the JSON document and free the memory. After calling this function, the `doc` and all values from the `doc` are no longer available. This function will do nothing if the `doc` is NULL. */ yyjson_api void yyjson_mut_doc_free(yyjson_mut_doc *doc); /** Creates and returns a new mutable JSON document, returns NULL on error. If allocator is NULL, the default allocator will be used. */ yyjson_api yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc); /** Copies and returns a new mutable document from input, returns NULL on error. This makes a `deep-copy` on the immutable document. If allocator is NULL, the default allocator will be used. @note `imut_doc` -> `mut_doc`. */ yyjson_api yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, const yyjson_alc *alc); /** Copies and returns a new mutable document from input, returns NULL on error. This makes a `deep-copy` on the mutable document. If allocator is NULL, the default allocator will be used. @note `mut_doc` -> `mut_doc`. */ yyjson_api yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc, const yyjson_alc *alc); /** Copies and returns a new mutable value from input, returns NULL on error. This makes a `deep-copy` on the immutable value. The memory was managed by mutable document. @note `imut_val` -> `mut_val`. */ yyjson_api yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *doc, yyjson_val *val); /** Copies and returns a new mutable value from input, returns NULL on error. This makes a `deep-copy` on the mutable value. The memory was managed by mutable document. @note `mut_val` -> `mut_val`. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc, yyjson_mut_val *val); /** Copies and returns a new immutable document from input, returns NULL on error. This makes a `deep-copy` on the mutable document. The returned document should be freed with `yyjson_doc_free()`. @note `mut_doc` -> `imut_doc`. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *doc, const yyjson_alc *alc); /** Copies and returns a new immutable document from input, returns NULL on error. This makes a `deep-copy` on the mutable value. The returned document should be freed with `yyjson_doc_free()`. @note `mut_val` -> `imut_doc`. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *val, const yyjson_alc *alc); /*============================================================================== * Mutable JSON Value Type API *============================================================================*/ /** Returns whether the JSON value is raw. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val); /** Returns whether the JSON value is `null`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val); /** Returns whether the JSON value is `true`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val); /** Returns whether the JSON value is `false`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val); /** Returns whether the JSON value is bool (true/false). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val); /** Returns whether the JSON value is unsigned integer (uint64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val); /** Returns whether the JSON value is signed integer (int64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val); /** Returns whether the JSON value is integer (uint64_t/int64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val); /** Returns whether the JSON value is real number (double). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val); /** Returns whether the JSON value is number (uint/sint/real). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val); /** Returns whether the JSON value is string. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val); /** Returns whether the JSON value is array. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val); /** Returns whether the JSON value is object. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val); /** Returns whether the JSON value is container (array/object). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val); /*============================================================================== * Mutable JSON Value Content API *============================================================================*/ /** Returns the JSON value's type. Returns `YYJSON_TYPE_NONE` if `val` is NULL. */ yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val); /** Returns the JSON value's subtype. Returns `YYJSON_SUBTYPE_NONE` if `val` is NULL. */ yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val); /** Returns the JSON value's tag. Returns 0 if `val` is NULL. */ yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val); /** Returns the JSON value's type description. The return value should be one of these strings: "raw", "null", "string", "array", "object", "true", "false", "uint", "sint", "real", "unknown". */ yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val); /** Returns the content if the value is raw. Returns NULL if `val` is NULL or type is not raw. */ yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val); /** Returns the content if the value is bool. Returns NULL if `val` is NULL or type is not bool. */ yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val); /** Returns the content and cast to uint64_t. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val); /** Returns the content and cast to int64_t. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val); /** Returns the content and cast to int. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val); /** Returns the content if the value is real number. Returns 0.0 if `val` is NULL or type is not real(double). */ yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val); /** Returns the content and typecast to `double` if the value is number. Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */ yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val); /** Returns the content if the value is string. Returns NULL if `val` is NULL or type is not string. */ yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val); /** Returns the content length (string length, array size, object size. Returns 0 if `val` is NULL or type is not string/array/object. */ yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val); /** Returns whether the JSON value is equals to a string. The `str` should be a null-terminated UTF-8 string. Returns false if input is NULL or type is not string. */ yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val, const char *str); /** Returns whether the JSON value is equals to a string. The `str` should be a UTF-8 string, null-terminator is not required. Returns false if input is NULL or type is not string. */ yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val, const char *str, size_t len); /** Returns whether two JSON values are equal (deep compare). Returns false if input is NULL. @note the result may be inaccurate if object has duplicate keys. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs); /** Set the value to raw. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val, const char *raw, size_t len); /** Set the value to null. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val); /** Set the value to bool. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num); /** Set the value to uint. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num); /** Set the value to sint. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num); /** Set the value to int. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num); /** Set the value to real. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num); /** Set the value to string (null-terminated). Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val, const char *str); /** Set the value to string (with length). Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val, const char *str, size_t len); /** Set the value to array. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val); /** Set the value to array. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val); /*============================================================================== * Mutable JSON Value Creation API *============================================================================*/ /** Creates and returns a raw value, returns NULL on error. The `str` should be a null-terminated UTF-8 string. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc, const char *str); /** Creates and returns a raw value, returns NULL on error. The `str` should be a UTF-8 string, null-terminator is not required. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc, const char *str, size_t len); /** Creates and returns a raw value, returns NULL on error. The `str` should be a null-terminated UTF-8 string. The input string is copied and held by the document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc, const char *str); /** Creates and returns a raw value, returns NULL on error. The `str` should be a UTF-8 string, null-terminator is not required. The input string is copied and held by the document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc, const char *str, size_t len); /** Creates and returns a null value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc); /** Creates and returns a true value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc); /** Creates and returns a false value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc); /** Creates and returns a bool value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc, bool val); /** Creates and returns an unsigned integer value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc, uint64_t num); /** Creates and returns a signed integer value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc, int64_t num); /** Creates and returns a signed integer value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc, int64_t num); /** Creates and returns an real number value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc, double num); /** Creates and returns a string value, returns NULL on error. The `str` should be a null-terminated UTF-8 string. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc, const char *str); /** Creates and returns a string value, returns NULL on error. The `str` should be a UTF-8 string, null-terminator is not required. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc, const char *str, size_t len); /** Creates and returns a string value, returns NULL on error. The `str` should be a null-terminated UTF-8 string. The input string is copied and held by the document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc, const char *str); /** Creates and returns a string value, returns NULL on error. The `str` should be a UTF-8 string, null-terminator is not required. The input string is copied and held by the document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc, const char *str, size_t len); /*============================================================================== * Mutable JSON Array API *============================================================================*/ /** Returns the number of elements in this array. Returns 0 if `arr` is NULL or type is not array. */ yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr); /** Returns the element at the specified position in this array. Returns NULL if array is NULL/empty or the index is out of bounds. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr, size_t idx); /** Returns the first element of this array. Returns NULL if `arr` is NULL/empty or type is not array. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first(yyjson_mut_val *arr); /** Returns the last element of this array. Returns NULL if `arr` is NULL/empty or type is not array. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(yyjson_mut_val *arr); /*============================================================================== * Mutable JSON Array Iterator API *============================================================================*/ /** A mutable JSON array iterator. @warning You should not modify the array while iterating over it, but you can use `yyjson_mut_arr_iter_remove()` to remove current value. @par Example @code yyjson_mut_val *val; yyjson_mut_arr_iter iter = yyjson_mut_arr_iter_with(arr); while ((val = yyjson_mut_arr_iter_next(&iter))) { your_func(val); if (your_val_is_unused(val)) { yyjson_mut_arr_iter_remove(&iter); } } @endcode */ typedef struct yyjson_mut_arr_iter { size_t idx; /**< next value's index */ size_t max; /**< maximum index (arr.size) */ yyjson_mut_val *cur; /**< current value */ yyjson_mut_val *pre; /**< previous value */ yyjson_mut_val *arr; /**< the array being iterated */ } yyjson_mut_arr_iter; /** Initialize an iterator for this array. @param arr The array to be iterated over. If this parameter is NULL or not an array, `iter` will be set to empty. @param iter The iterator to be initialized. If this parameter is NULL, the function will fail and return false. @return true if the `iter` has been successfully initialized. @note The iterator does not need to be destroyed. */ yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr, yyjson_mut_arr_iter *iter); /** Create an iterator with an array , same as `yyjson_mut_arr_iter_init()`. @param arr The array to be iterated over. If this parameter is NULL or not an array, an empty iterator will returned. @return A new iterator for the array. @note The iterator does not need to be destroyed. */ yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with( yyjson_mut_val *arr); /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. */ yyjson_api_inline bool yyjson_mut_arr_iter_has_next( yyjson_mut_arr_iter *iter); /** Returns the next element in the iteration, or NULL on end. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next( yyjson_mut_arr_iter *iter); /** Removes and returns current element in the iteration. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove( yyjson_mut_arr_iter *iter); /** Macro for iterating over an array. It works like iterator, but with a more intuitive API. @warning You should not modify the array while iterating over it. @par Example @code size_t idx, max; yyjson_mut_val *val; yyjson_mut_arr_foreach(arr, idx, max, val) { your_func(idx, val); } @endcode */ #define yyjson_mut_arr_foreach(arr, idx, max, val) \ for ((idx) = 0, \ (max) = yyjson_mut_arr_size(arr), \ (val) = yyjson_mut_arr_get_first(arr); \ (idx) < (max); \ (idx)++, \ (val) = (val)->next) /*============================================================================== * Mutable JSON Array Creation API *============================================================================*/ /** Creates and returns an empty mutable array. @param doc A mutable document, used for memory allocation only. @return The new array. NULL if input is NULL or memory allocation failed. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc); /** Creates and returns a new mutable array with the given boolean values. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of boolean values. @param count The value count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const bool vals[3] = { true, false, true }; yyjson_mut_val *arr = yyjson_mut_arr_with_bool(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool( yyjson_mut_doc *doc, const bool *vals, size_t count); /** Creates and returns a new mutable array with the given sint numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of sint numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int64_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint( yyjson_mut_doc *doc, const int64_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint64_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint( yyjson_mut_doc *doc, const uint64_t *vals, size_t count); /** Creates and returns a new mutable array with the given real numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of real numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const double vals[3] = { 0.1, 0.2, 0.3 }; yyjson_mut_val *arr = yyjson_mut_arr_with_real(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real( yyjson_mut_doc *doc, const double *vals, size_t count); /** Creates and returns a new mutable array with the given int8 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of int8 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int8_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint8(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8( yyjson_mut_doc *doc, const int8_t *vals, size_t count); /** Creates and returns a new mutable array with the given int16 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of int16 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int16_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint16(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16( yyjson_mut_doc *doc, const int16_t *vals, size_t count); /** Creates and returns a new mutable array with the given int32 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of int32 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int32_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint32(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32( yyjson_mut_doc *doc, const int32_t *vals, size_t count); /** Creates and returns a new mutable array with the given int64 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of int64 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int64_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64( yyjson_mut_doc *doc, const int64_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint8 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint8 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint8_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint8(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8( yyjson_mut_doc *doc, const uint8_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint16 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint16 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint16_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint16(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16( yyjson_mut_doc *doc, const uint16_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint32 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint32 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint32_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint32(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32( yyjson_mut_doc *doc, const uint32_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint64 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint64 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint64_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint64(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64( yyjson_mut_doc *doc, const uint64_t *vals, size_t count); /** Creates and returns a new mutable array with the given float numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of float numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const float vals[3] = { -1.0f, 0.0f, 1.0f }; yyjson_mut_val *arr = yyjson_mut_arr_with_float(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float( yyjson_mut_doc *doc, const float *vals, size_t count); /** Creates and returns a new mutable array with the given double numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of double numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const double vals[3] = { -1.0, 0.0, 1.0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_double(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double( yyjson_mut_doc *doc, const double *vals, size_t count); /** Creates and returns a new mutable array with the given strings, these strings will not be copied. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of UTF-8 null-terminator strings. If this array contains NULL, the function will fail and return NULL. @param count The number of values in `vals`. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @warning The input strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. If these strings will be modified, you should use `yyjson_mut_arr_with_strcpy()` instead. @par Example @code const char *vals[3] = { "a", "b", "c" }; yyjson_mut_val *arr = yyjson_mut_arr_with_str(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str( yyjson_mut_doc *doc, const char **vals, size_t count); /** Creates and returns a new mutable array with the given strings and string lengths, these strings will not be copied. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of UTF-8 strings, null-terminator is not required. If this array contains NULL, the function will fail and return NULL. @param lens A C array of string lengths, in bytes. @param count The number of strings in `vals`. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @warning The input strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. If these strings will be modified, you should use `yyjson_mut_arr_with_strncpy()` instead. @par Example @code const char *vals[3] = { "a", "bb", "c" }; const size_t lens[3] = { 1, 2, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn( yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count); /** Creates and returns a new mutable array with the given strings, these strings will be copied. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of UTF-8 null-terminator strings. If this array contains NULL, the function will fail and return NULL. @param count The number of values in `vals`. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const char *vals[3] = { "a", "b", "c" }; yyjson_mut_val *arr = yyjson_mut_arr_with_strcpy(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy( yyjson_mut_doc *doc, const char **vals, size_t count); /** Creates and returns a new mutable array with the given strings and string lengths, these strings will be copied. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of UTF-8 strings, null-terminator is not required. If this array contains NULL, the function will fail and return NULL. @param lens A C array of string lengths, in bytes. @param count The number of strings in `vals`. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const char *vals[3] = { "a", "bb", "c" }; const size_t lens[3] = { 1, 2, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy( yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count); /*============================================================================== * Mutable JSON Array Modification API *============================================================================*/ /** Inserts a value into an array at a given index. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The value to be inserted. Returns false if it is NULL. @param idx The index to which to insert the new value. Returns false if the index is out of range. @return Whether successful. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr, yyjson_mut_val *val, size_t idx); /** Inserts a value at the end of the array. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The value to be inserted. Returns false if it is NULL. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr, yyjson_mut_val *val); /** Inserts a value at the head of the array. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The value to be inserted. Returns false if it is NULL. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr, yyjson_mut_val *val); /** Replaces a value at index and returns old value. @param arr The array to which the value is to be replaced. Returns false if it is NULL or not an array. @param idx The index to which to replace the value. Returns false if the index is out of range. @param val The new value to replace. Returns false if it is NULL. @return Old value, or NULL on error. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr, size_t idx, yyjson_mut_val *val); /** Removes and returns a value at index. @param arr The array from which the value is to be removed. Returns false if it is NULL or not an array. @param idx The index from which to remove the value. Returns false if the index is out of range. @return Old value, or NULL on error. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr, size_t idx); /** Removes and returns the first value in this array. @param arr The array from which the value is to be removed. Returns false if it is NULL or not an array. @return The first value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first( yyjson_mut_val *arr); /** Removes and returns the last value in this array. @param arr The array from which the value is to be removed. Returns false if it is NULL or not an array. @return The last value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last( yyjson_mut_val *arr); /** Removes all values within a specified range in the array. @param arr The array from which the value is to be removed. Returns false if it is NULL or not an array. @param idx The start index of the range (0 is the first). @param len The number of items in the range (can be 0). @return Whether successful. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr, size_t idx, size_t len); /** Removes all values in this array. @param arr The array from which all of the values are to be removed. Returns false if it is NULL or not an array. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr); /** Rotates values in this array for the given number of times. For example: `[1,2,3,4,5]` rotate 2 is `[3,4,5,1,2]`. @param arr The array to be rotated. @param idx Index (or times) to rotate. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr, size_t idx); /*============================================================================== * Mutable JSON Array Modification Convenience API *============================================================================*/ /** Adds a value at the end of the array. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The value to be inserted. Returns false if it is NULL. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr, yyjson_mut_val *val); /** Adds a `null` value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc, yyjson_mut_val *arr); /** Adds a `true` value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc, yyjson_mut_val *arr); /** Adds a `false` value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc, yyjson_mut_val *arr); /** Adds a bool value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The bool value to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *arr, bool val); /** Adds an unsigned integer value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param num The number to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *arr, uint64_t num); /** Adds a signed integer value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param num The number to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *arr, int64_t num); /** Adds a integer value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param num The number to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc, yyjson_mut_val *arr, int64_t num); /** Adds a double value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param num The number to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc, yyjson_mut_val *arr, double num); /** Adds a string value at the end of the array (no copy). @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param str A null-terminated UTF-8 string. @return Whether successful. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str); /** Adds a string value at the end of the array (no copy). @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param str A UTF-8 string, null-terminator is not required. @param len The length of the string, in bytes. @return Whether successful. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str, size_t len); /** Adds a string value at the end of the array (copied). @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param str A null-terminated UTF-8 string. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str); /** Adds a string value at the end of the array (copied). @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param str A UTF-8 string, null-terminator is not required. @param len The length of the string, in bytes. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str, size_t len); /** Creates and adds a new array at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return The new array, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc, yyjson_mut_val *arr); /** Creates and adds a new object at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return The new object, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc, yyjson_mut_val *arr); /*============================================================================== * Mutable JSON Object API *============================================================================*/ /** Returns the number of key-value pairs in this object. Returns 0 if `obj` is NULL or type is not object. */ yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj); /** Returns the value to which the specified key is mapped. Returns NULL if this object contains no mapping for the key. Returns NULL if `obj/key` is NULL, or type is not object. The `key` should be a null-terminated UTF-8 string. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj, const char *key); /** Returns the value to which the specified key is mapped. Returns NULL if this object contains no mapping for the key. Returns NULL if `obj/key` is NULL, or type is not object. The `key` should be a UTF-8 string, null-terminator is not required. The `key_len` should be the length of the key, in bytes. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj, const char *key, size_t key_len); /*============================================================================== * Mutable JSON Object Iterator API *============================================================================*/ /** A mutable JSON object iterator. @warning You should not modify the object while iterating over it, but you can use `yyjson_mut_obj_iter_remove()` to remove current value. @par Example @code yyjson_mut_val *key, *val; yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj); while ((key = yyjson_mut_obj_iter_next(&iter))) { val = yyjson_mut_obj_iter_get_val(key); your_func(key, val); if (your_val_is_unused(key, val)) { yyjson_mut_obj_iter_remove(&iter); } } @endcode If the ordering of the keys is known at compile-time, you can use this method to speed up value lookups: @code // {"k1":1, "k2": 3, "k3": 3} yyjson_mut_val *key, *val; yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj); yyjson_mut_val *v1 = yyjson_mut_obj_iter_get(&iter, "k1"); yyjson_mut_val *v3 = yyjson_mut_obj_iter_get(&iter, "k3"); @endcode @see `yyjson_mut_obj_iter_get()` and `yyjson_mut_obj_iter_getn()` */ typedef struct yyjson_mut_obj_iter { size_t idx; /**< next key's index */ size_t max; /**< maximum key index (obj.size) */ yyjson_mut_val *cur; /**< current key */ yyjson_mut_val *pre; /**< previous key */ yyjson_mut_val *obj; /**< the object being iterated */ } yyjson_mut_obj_iter; /** Initialize an iterator for this object. @param obj The object to be iterated over. If this parameter is NULL or not an array, `iter` will be set to empty. @param iter The iterator to be initialized. If this parameter is NULL, the function will fail and return false. @return true if the `iter` has been successfully initialized. @note The iterator does not need to be destroyed. */ yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj, yyjson_mut_obj_iter *iter); /** Create an iterator with an object, same as `yyjson_obj_iter_init()`. @param obj The object to be iterated over. If this parameter is NULL or not an object, an empty iterator will returned. @return A new iterator for the object. @note The iterator does not need to be destroyed. */ yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with( yyjson_mut_val *obj); /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. */ yyjson_api_inline bool yyjson_mut_obj_iter_has_next( yyjson_mut_obj_iter *iter); /** Returns the next key in the iteration, or NULL on end. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next( yyjson_mut_obj_iter *iter); /** Returns the value for key inside the iteration. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val( yyjson_mut_val *key); /** Removes current key-value pair in the iteration, returns the removed value. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove( yyjson_mut_obj_iter *iter); /** Iterates to a specified key and returns the value. This function does the same thing as `yyjson_mut_obj_get()`, but is much faster if the ordering of the keys is known at compile-time and you are using the same order to look up the values. If the key exists in this object, then the iterator will stop at the next key, otherwise the iterator will not change and NULL is returned. @param iter The object iterator, should not be NULL. @param key The key, should be a UTF-8 string with null-terminator. @return The value to which the specified key is mapped. NULL if this object contains no mapping for the key or input is invalid. @warning This function takes a linear search time if the key is not nearby. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get( yyjson_mut_obj_iter *iter, const char *key); /** Iterates to a specified key and returns the value. This function does the same thing as `yyjson_mut_obj_getn()` but is much faster if the ordering of the keys is known at compile-time and you are using the same order to look up the values. If the key exists in this object, then the iterator will stop at the next key, otherwise the iterator will not change and NULL is returned. @param iter The object iterator, should not be NULL. @param key The key, should be a UTF-8 string, null-terminator is not required. @param key_len The the length of `key`, in bytes. @return The value to which the specified key is mapped. NULL if this object contains no mapping for the key or input is invalid. @warning This function takes a linear search time if the key is not nearby. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn( yyjson_mut_obj_iter *iter, const char *key, size_t key_len); /** Macro for iterating over an object. It works like iterator, but with a more intuitive API. @warning You should not modify the object while iterating over it. @par Example @code size_t idx, max; yyjson_val *key, *val; yyjson_obj_foreach(obj, idx, max, key, val) { your_func(key, val); } @endcode */ #define yyjson_mut_obj_foreach(obj, idx, max, key, val) \ for ((idx) = 0, \ (max) = yyjson_mut_obj_size(obj), \ (key) = (max) ? ((yyjson_mut_val *)(obj)->uni.ptr)->next->next : NULL, \ (val) = (key) ? (key)->next : NULL; \ (idx) < (max); \ (idx)++, \ (key) = (val)->next, \ (val) = (key)->next) /*============================================================================== * Mutable JSON Object Creation API *============================================================================*/ /** Creates and returns a mutable object, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc); /** Creates and returns a mutable object with keys and values, returns NULL on error. The keys and values are not copied. The strings should be a null-terminated UTF-8 string. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. @par Example @code const char *keys[2] = { "id", "name" }; const char *vals[2] = { "01", "Harry" }; yyjson_mut_val *obj = yyjson_mut_obj_with_str(doc, keys, vals, 2); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc, const char **keys, const char **vals, size_t count); /** Creates and returns a mutable object with key-value pairs and pair count, returns NULL on error. The keys and values are not copied. The strings should be a null-terminated UTF-8 string. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. @par Example @code const char *kv_pairs[4] = { "id", "01", "name", "Harry" }; yyjson_mut_val *obj = yyjson_mut_obj_with_kv(doc, kv_pairs, 2); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc, const char **kv_pairs, size_t pair_count); /*============================================================================== * Mutable JSON Object Modification API *============================================================================*/ /** Adds a key-value pair at the end of the object. This function allows duplicated key in one object. @param obj The object to which the new key-value pair is to be added. @param key The key, should be a string which is created by `yyjson_mut_str()`, `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`. @param val The value to add to the object. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val); /** Sets a key-value pair at the end of the object. This function may remove all key-value pairs for the given key before add. @param obj The object to which the new key-value pair is to be added. @param key The key, should be a string which is created by `yyjson_mut_str()`, `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`. @param val The value to add to the object. If this value is null, the behavior is same as `yyjson_mut_obj_remove()`. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val); /** Inserts a key-value pair to the object at the given position. This function allows duplicated key in one object. @param obj The object to which the new key-value pair is to be added. @param key The key, should be a string which is created by `yyjson_mut_str()`, `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`. @param val The value to add to the object. @param idx The index to which to insert the new pair. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val, size_t idx); /** Removes all key-value pair from the object with given key. @param obj The object from which the key-value pair is to be removed. @param key The key, should be a string value. @return The first matched value, or NULL if no matched value. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj, yyjson_mut_val *key); /** Removes all key-value pair from the object with given key. @param obj The object from which the key-value pair is to be removed. @param key The key, should be a UTF-8 string with null-terminator. @return The first matched value, or NULL if no matched value. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key( yyjson_mut_val *obj, const char *key); /** Removes all key-value pair from the object with given key. @param obj The object from which the key-value pair is to be removed. @param key The key, should be a UTF-8 string, null-terminator is not required. @param key_len The length of the key. @return The first matched value, or NULL if no matched value. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn( yyjson_mut_val *obj, const char *key, size_t key_len); /** Removes all key-value pairs in this object. @param obj The object from which all of the values are to be removed. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj); /** Replaces value from the object with given key. If the key is not exist, or the value is NULL, it will fail. @param obj The object to which the value is to be replaced. @param key The key, should be a string value. @param val The value to replace into the object. @return Whether successful. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val); /** Rotates key-value pairs in the object for the given number of times. For example: `{"a":1,"b":2,"c":3,"d":4}` rotate 1 is `{"b":2,"c":3,"d":4,"a":1}`. @param obj The object to be rotated. @param idx Index (or times) to rotate. @return Whether successful. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj, size_t idx); /*============================================================================== * Mutable JSON Object Modification Convenience API *============================================================================*/ /** Adds a `null` value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key); /** Adds a `true` value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key); /** Adds a `false` value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key); /** Adds a bool value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, bool val); /** Adds an unsigned integer value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, uint64_t val); /** Adds a signed integer value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, int64_t val); /** Adds an int value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, int64_t val); /** Adds a double value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, double val); /** Adds a string value at the end of the object. The `key` and `val` should be null-terminated UTF-8 strings. This function allows duplicated key in one object. @warning The key/value string are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val); /** Adds a string value at the end of the object. The `key` should be a null-terminated UTF-8 string. The `val` should be a UTF-8 string, null-terminator is not required. The `len` should be the length of the `val`, in bytes. This function allows duplicated key in one object. @warning The key/value string are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val, size_t len); /** Adds a string value at the end of the object. The `key` and `val` should be null-terminated UTF-8 strings. The value string is copied. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val); /** Adds a string value at the end of the object. The `key` should be a null-terminated UTF-8 string. The `val` should be a UTF-8 string, null-terminator is not required. The `len` should be the length of the `val`, in bytes. This function allows duplicated key in one object. @warning The key/value string are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val, size_t len); /** Adds a JSON value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, yyjson_mut_val *val); /** Removes all key-value pairs for the given key. Returns the first value to which the specified key is mapped or NULL if this object contains no mapping for the key. The `key` should be a null-terminated UTF-8 string. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str( yyjson_mut_val *obj, const char *key); /** Removes all key-value pairs for the given key. Returns the first value to which the specified key is mapped or NULL if this object contains no mapping for the key. The `key` should be a UTF-8 string, null-terminator is not required. The `len` should be the length of the key, in bytes. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn( yyjson_mut_val *obj, const char *key, size_t len); /** Replaces all matching keys with the new key. Returns true if at least one key was renamed. The `key` and `new_key` should be a null-terminated UTF-8 string. The `new_key` is copied and held by doc. @warning This function takes a linear search time. If `new_key` already exists, it will cause duplicate keys. */ yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *new_key); /** Replaces all matching keys with the new key. Returns true if at least one key was renamed. The `key` and `new_key` should be a UTF-8 string, null-terminator is not required. The `new_key` is copied and held by doc. @warning This function takes a linear search time. If `new_key` already exists, it will cause duplicate keys. */ yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, size_t len, const char *new_key, size_t new_len); /*============================================================================== * JSON Pointer API (RFC 6901) * https://tools.ietf.org/html/rfc6901 *============================================================================*/ /** JSON Pointer error code. */ typedef uint32_t yyjson_ptr_code; /** No JSON pointer error. */ static const yyjson_ptr_code YYJSON_PTR_ERR_NONE = 0; /** Invalid input parameter, such as NULL input. */ static const yyjson_ptr_code YYJSON_PTR_ERR_PARAMETER = 1; /** JSON pointer syntax error, such as invalid escape, token no prefix. */ static const yyjson_ptr_code YYJSON_PTR_ERR_SYNTAX = 2; /** JSON pointer resolve failed, such as index out of range, key not found. */ static const yyjson_ptr_code YYJSON_PTR_ERR_RESOLVE = 3; /** Document's root is NULL, but it is required for the function call. */ static const yyjson_ptr_code YYJSON_PTR_ERR_NULL_ROOT = 4; /** Cannot set root as the target is not a document. */ static const yyjson_ptr_code YYJSON_PTR_ERR_SET_ROOT = 5; /** The memory allocation failed and a new value could not be created. */ static const yyjson_ptr_code YYJSON_PTR_ERR_MEMORY_ALLOCATION = 6; /** Error information for JSON pointer. */ typedef struct yyjson_ptr_err { /** Error code, see `yyjson_ptr_code` for all possible values. */ yyjson_ptr_code code; /** Error message, constant, no need to free (NULL if no error). */ const char *msg; /** Error byte position for input JSON pointer (0 if no error). */ size_t pos; } yyjson_ptr_err; /** A context for JSON pointer operation. This struct stores the context of JSON Pointer operation result. The struct can be used with three helper functions: `ctx_append()`, `ctx_replace()`, and `ctx_remove()`, which perform the corresponding operations on the container without re-parsing the JSON Pointer. For example: @code // doc before: {"a":[0,1,null]} // ptr: "/a/2" val = yyjson_mut_doc_ptr_getx(doc, ptr, strlen(ptr), &ctx, &err); if (yyjson_is_null(val)) { yyjson_ptr_ctx_remove(&ctx); } // doc after: {"a":[0,1]} @endcode */ typedef struct yyjson_ptr_ctx { /** The container (parent) of the target value. It can be either an array or an object. If the target location has no value, but all its parent containers exist, and the target location can be used to insert a new value, then `ctn` is the parent container of the target location. Otherwise, `ctn` is NULL. */ yyjson_mut_val *ctn; /** The previous sibling of the target value. It can be either a value in an array or a key in an object. As the container is a `circular linked list` of elements, `pre` is the previous node of the target value. If the operation is `add` or `set`, then `pre` is the previous node of the new value, not the original target value. If the target value does not exist, `pre` is NULL. */ yyjson_mut_val *pre; /** The removed value if the operation is `set`, `replace` or `remove`. It can be used to restore the original state of the document if needed. */ yyjson_mut_val *old; } yyjson_ptr_ctx; /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc, const char *ptr); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc, const char *ptr, size_t len); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param err A pointer to store the error information, or NULL if not needed. @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc, const char *ptr, size_t len, yyjson_ptr_err *err); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val, const char *ptr); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val, const char *ptr, size_t len); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param err A pointer to store the error information, or NULL if not needed. @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val, const char *ptr, size_t len, yyjson_ptr_err *err); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc, const char *ptr); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc, const char *ptr, size_t len); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val, const char *ptr); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val, const char *ptr, size_t len); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Add (insert) value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The value to be added. @return true if JSON pointer is valid and new value is added, false otherwise. @note The parent nodes will be created if they do not exist. */ yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val); /** Add (insert) value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be added. @return true if JSON pointer is valid and new value is added, false otherwise. @note The parent nodes will be created if they do not exist. */ yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val); /** Add (insert) value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be added. @param create_parent Whether to create parent nodes if not exist. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return true if JSON pointer is valid and new value is added, false otherwise. */ yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Add (insert) value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param doc Only used to create new values when needed. @param new_val The value to be added. @return true if JSON pointer is valid and new value is added, false otherwise. @note The parent nodes will be created if they do not exist. */ yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val, yyjson_mut_doc *doc); /** Add (insert) value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param doc Only used to create new values when needed. @param new_val The value to be added. @return true if JSON pointer is valid and new value is added, false otherwise. @note The parent nodes will be created if they do not exist. */ yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc); /** Add (insert) value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param doc Only used to create new values when needed. @param new_val The value to be added. @param create_parent Whether to create parent nodes if not exist. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return true if JSON pointer is valid and new value is added, false otherwise. */ yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Set value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The value to be set, pass NULL to remove. @return true if JSON pointer is valid and new value is set, false otherwise. @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val); /** Set value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be set, pass NULL to remove. @return true if JSON pointer is valid and new value is set, false otherwise. @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val); /** Set value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be set, pass NULL to remove. @param create_parent Whether to create parent nodes if not exist. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return true if JSON pointer is valid and new value is set, false otherwise. @note If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Set value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The value to be set, pass NULL to remove. @param doc Only used to create new values when needed. @return true if JSON pointer is valid and new value is set, false otherwise. @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val, yyjson_mut_doc *doc); /** Set value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be set, pass NULL to remove. @param doc Only used to create new values when needed. @return true if JSON pointer is valid and new value is set, false otherwise. @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc); /** Set value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be set, pass NULL to remove. @param doc Only used to create new values when needed. @param create_parent Whether to create parent nodes if not exist. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return true if JSON pointer is valid and new value is set, false otherwise. @note If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Replace value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The new value to replace the old one. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace( yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val); /** Replace value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The new value to replace the old one. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val); /** Replace value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The new value to replace the old one. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Replace value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The new value to replace the old one. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace( yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val); /** Replace value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The new value to replace the old one. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val); /** Replace value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The new value to replace the old one. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Remove value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove( yyjson_mut_doc *doc, const char *ptr); /** Remove value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen( yyjson_mut_doc *doc, const char *ptr, size_t len); /** Remove value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Remove value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val, const char *ptr); /** Remove value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val, const char *ptr, size_t len); /** Remove value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Append value by JSON pointer context. @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. @param key New key if `ctx->ctn` is object, or NULL if `ctx->ctn` is array. @param val New value to be added. @return true on success or false on fail. */ yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx, yyjson_mut_val *key, yyjson_mut_val *val); /** Replace value by JSON pointer context. @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. @param val New value to be replaced. @return true on success or false on fail. @note If success, the old value will be returned via `ctx->old`. */ yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx, yyjson_mut_val *val); /** Remove value by JSON pointer context. @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. @return true on success or false on fail. @note If success, the old value will be returned via `ctx->old`. */ yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx); /*============================================================================== * JSON Patch API (RFC 6902) * https://tools.ietf.org/html/rfc6902 *============================================================================*/ /** Result code for JSON patch. */ typedef uint32_t yyjson_patch_code; /** Success, no error. */ static const yyjson_patch_code YYJSON_PATCH_SUCCESS = 0; /** Invalid parameter, such as NULL input or non-array patch. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failure occurs. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_MEMORY_ALLOCATION = 2; /** JSON patch operation is not object type. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_OPERATION = 3; /** JSON patch operation is missing a required key. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_MISSING_KEY = 4; /** JSON patch operation member is invalid. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_MEMBER = 5; /** JSON patch operation `test` not equal. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_EQUAL = 6; /** JSON patch operation failed on JSON pointer. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_POINTER = 7; /** Error information for JSON patch. */ typedef struct yyjson_patch_err { /** Error code, see `yyjson_patch_code` for all possible values. */ yyjson_patch_code code; /** Index of the error operation (0 if no error). */ size_t idx; /** Error message, constant, no need to free (NULL if no error). */ const char *msg; /** JSON pointer error if `code == YYJSON_PATCH_ERROR_POINTER`. */ yyjson_ptr_err ptr; } yyjson_patch_err; /** Creates and returns a patched JSON value (RFC 6902). The memory of the returned value is allocated by the `doc`. The `err` is used to receive error information, pass NULL if not needed. Returns NULL if the patch could not be applied. */ yyjson_api yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch, yyjson_patch_err *err); /** Creates and returns a patched JSON value (RFC 6902). The memory of the returned value is allocated by the `doc`. The `err` is used to receive error information, pass NULL if not needed. Returns NULL if the patch could not be applied. */ yyjson_api yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch, yyjson_patch_err *err); /*============================================================================== * JSON Merge-Patch API (RFC 7386) * https://tools.ietf.org/html/rfc7386 *============================================================================*/ /** Creates and returns a merge-patched JSON value (RFC 7386). The memory of the returned value is allocated by the `doc`. Returns NULL if the patch could not be applied. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch); /** Creates and returns a merge-patched JSON value (RFC 7386). The memory of the returned value is allocated by the `doc`. Returns NULL if the patch could not be applied. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch); /*============================================================================== * JSON Structure (Implementation) *============================================================================*/ /** Payload of a JSON value (8 bytes). */ typedef union yyjson_val_uni { uint64_t u64; int64_t i64; double f64; const char *str; void *ptr; size_t ofs; } yyjson_val_uni; /** Immutable JSON value, 16 bytes. */ struct yyjson_val { uint64_t tag; /**< type, subtype and length */ yyjson_val_uni uni; /**< payload */ }; struct yyjson_doc { /** Root value of the document (nonnull). */ yyjson_val *root; /** Allocator used by document (nonnull). */ yyjson_alc alc; /** The total number of bytes read when parsing JSON (nonzero). */ size_t dat_read; /** The total number of value read when parsing JSON (nonzero). */ size_t val_read; /** The string pool used by JSON values (nullable). */ char *str_pool; }; /*============================================================================== * Unsafe JSON Value API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_type unsafe_yyjson_get_type(void *val) { uint8_t tag = (uint8_t)((yyjson_val *)val)->tag; return (yyjson_type)(tag & YYJSON_TYPE_MASK); } yyjson_api_inline yyjson_subtype unsafe_yyjson_get_subtype(void *val) { uint8_t tag = (uint8_t)((yyjson_val *)val)->tag; return (yyjson_subtype)(tag & YYJSON_SUBTYPE_MASK); } yyjson_api_inline uint8_t unsafe_yyjson_get_tag(void *val) { uint8_t tag = (uint8_t)((yyjson_val *)val)->tag; return (uint8_t)(tag & YYJSON_TAG_MASK); } yyjson_api_inline bool unsafe_yyjson_is_raw(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_RAW; } yyjson_api_inline bool unsafe_yyjson_is_null(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NULL; } yyjson_api_inline bool unsafe_yyjson_is_bool(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_BOOL; } yyjson_api_inline bool unsafe_yyjson_is_num(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NUM; } yyjson_api_inline bool unsafe_yyjson_is_str(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_STR; } yyjson_api_inline bool unsafe_yyjson_is_arr(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_ARR; } yyjson_api_inline bool unsafe_yyjson_is_obj(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_OBJ; } yyjson_api_inline bool unsafe_yyjson_is_ctn(void *val) { uint8_t mask = YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ; return (unsafe_yyjson_get_tag(val) & mask) == mask; } yyjson_api_inline bool unsafe_yyjson_is_uint(void *val) { const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_is_sint(void *val) { const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_is_int(void *val) { const uint8_t mask = YYJSON_TAG_MASK & (~YYJSON_SUBTYPE_SINT); const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; return (unsafe_yyjson_get_tag(val) & mask) == patt; } yyjson_api_inline bool unsafe_yyjson_is_real(void *val) { const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_is_true(void *val) { const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_is_false(void *val) { const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_arr_is_flat(yyjson_val *val) { size_t ofs = val->uni.ofs; size_t len = (size_t)(val->tag >> YYJSON_TAG_BIT); return len * sizeof(yyjson_val) + sizeof(yyjson_val) == ofs; } yyjson_api_inline const char *unsafe_yyjson_get_raw(void *val) { return ((yyjson_val *)val)->uni.str; } yyjson_api_inline bool unsafe_yyjson_get_bool(void *val) { uint8_t tag = unsafe_yyjson_get_tag(val); return (bool)((tag & YYJSON_SUBTYPE_MASK) >> YYJSON_TYPE_BIT); } yyjson_api_inline uint64_t unsafe_yyjson_get_uint(void *val) { return ((yyjson_val *)val)->uni.u64; } yyjson_api_inline int64_t unsafe_yyjson_get_sint(void *val) { return ((yyjson_val *)val)->uni.i64; } yyjson_api_inline int unsafe_yyjson_get_int(void *val) { return (int)((yyjson_val *)val)->uni.i64; } yyjson_api_inline double unsafe_yyjson_get_real(void *val) { return ((yyjson_val *)val)->uni.f64; } yyjson_api_inline double unsafe_yyjson_get_num(void *val) { uint8_t tag = unsafe_yyjson_get_tag(val); if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL)) { return ((yyjson_val *)val)->uni.f64; } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT)) { return (double)((yyjson_val *)val)->uni.i64; } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT)) { #if YYJSON_U64_TO_F64_NO_IMPL uint64_t msb = ((uint64_t)1) << 63; uint64_t num = ((yyjson_val *)val)->uni.u64; if ((num & msb) == 0) { return (double)(int64_t)num; } else { return ((double)(int64_t)((num >> 1) | (num & 1))) * (double)2.0; } #else return (double)((yyjson_val *)val)->uni.u64; #endif } return 0.0; } yyjson_api_inline const char *unsafe_yyjson_get_str(void *val) { return ((yyjson_val *)val)->uni.str; } yyjson_api_inline size_t unsafe_yyjson_get_len(void *val) { return (size_t)(((yyjson_val *)val)->tag >> YYJSON_TAG_BIT); } yyjson_api_inline yyjson_val *unsafe_yyjson_get_first(yyjson_val *ctn) { return ctn + 1; } yyjson_api_inline yyjson_val *unsafe_yyjson_get_next(yyjson_val *val) { bool is_ctn = unsafe_yyjson_is_ctn(val); size_t ctn_ofs = val->uni.ofs; size_t ofs = (is_ctn ? ctn_ofs : sizeof(yyjson_val)); return (yyjson_val *)(void *)((uint8_t *)val + ofs); } yyjson_api_inline bool unsafe_yyjson_equals_strn(void *val, const char *str, size_t len) { uint64_t tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; return ((yyjson_val *)val)->tag == tag && memcmp(((yyjson_val *)val)->uni.str, str, len) == 0; } yyjson_api_inline bool unsafe_yyjson_equals_str(void *val, const char *str) { return unsafe_yyjson_equals_strn(val, str, strlen(str)); } yyjson_api_inline void unsafe_yyjson_set_type(void *val, yyjson_type type, yyjson_subtype subtype) { uint8_t tag = (type | subtype); uint64_t new_tag = ((yyjson_val *)val)->tag; new_tag = (new_tag & (~(uint64_t)YYJSON_TAG_MASK)) | (uint64_t)tag; ((yyjson_val *)val)->tag = new_tag; } yyjson_api_inline void unsafe_yyjson_set_len(void *val, size_t len) { uint64_t tag = ((yyjson_val *)val)->tag & YYJSON_TAG_MASK; tag |= (uint64_t)len << YYJSON_TAG_BIT; ((yyjson_val *)val)->tag = tag; } yyjson_api_inline void unsafe_yyjson_inc_len(void *val) { uint64_t tag = ((yyjson_val *)val)->tag; tag += (uint64_t)(1 << YYJSON_TAG_BIT); ((yyjson_val *)val)->tag = tag; } yyjson_api_inline void unsafe_yyjson_set_raw(void *val, const char *raw, size_t len) { unsafe_yyjson_set_type(val, YYJSON_TYPE_RAW, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, len); ((yyjson_val *)val)->uni.str = raw; } yyjson_api_inline void unsafe_yyjson_set_null(void *val) { unsafe_yyjson_set_type(val, YYJSON_TYPE_NULL, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, 0); } yyjson_api_inline void unsafe_yyjson_set_bool(void *val, bool num) { yyjson_subtype subtype = num ? YYJSON_SUBTYPE_TRUE : YYJSON_SUBTYPE_FALSE; unsafe_yyjson_set_type(val, YYJSON_TYPE_BOOL, subtype); unsafe_yyjson_set_len(val, 0); } yyjson_api_inline void unsafe_yyjson_set_uint(void *val, uint64_t num) { unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_UINT); unsafe_yyjson_set_len(val, 0); ((yyjson_val *)val)->uni.u64 = num; } yyjson_api_inline void unsafe_yyjson_set_sint(void *val, int64_t num) { unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_SINT); unsafe_yyjson_set_len(val, 0); ((yyjson_val *)val)->uni.i64 = num; } yyjson_api_inline void unsafe_yyjson_set_real(void *val, double num) { unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_REAL); unsafe_yyjson_set_len(val, 0); ((yyjson_val *)val)->uni.f64 = num; } yyjson_api_inline void unsafe_yyjson_set_str(void *val, const char *str) { unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, strlen(str)); ((yyjson_val *)val)->uni.str = str; } yyjson_api_inline void unsafe_yyjson_set_strn(void *val, const char *str, size_t len) { unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, len); ((yyjson_val *)val)->uni.str = str; } yyjson_api_inline void unsafe_yyjson_set_arr(void *val, size_t size) { unsafe_yyjson_set_type(val, YYJSON_TYPE_ARR, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, size); } yyjson_api_inline void unsafe_yyjson_set_obj(void *val, size_t size) { unsafe_yyjson_set_type(val, YYJSON_TYPE_OBJ, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, size); } /*============================================================================== * JSON Document API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc) { return doc ? doc->root : NULL; } yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc) { return doc ? doc->dat_read : 0; } yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc) { return doc ? doc->val_read : 0; } yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc) { if (doc) { yyjson_alc alc = doc->alc; if (doc->str_pool) alc.free(alc.ctx, doc->str_pool); alc.free(alc.ctx, doc); } } /*============================================================================== * JSON Value Type API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_is_raw(yyjson_val *val) { return val ? unsafe_yyjson_is_raw(val) : false; } yyjson_api_inline bool yyjson_is_null(yyjson_val *val) { return val ? unsafe_yyjson_is_null(val) : false; } yyjson_api_inline bool yyjson_is_true(yyjson_val *val) { return val ? unsafe_yyjson_is_true(val) : false; } yyjson_api_inline bool yyjson_is_false(yyjson_val *val) { return val ? unsafe_yyjson_is_false(val) : false; } yyjson_api_inline bool yyjson_is_bool(yyjson_val *val) { return val ? unsafe_yyjson_is_bool(val) : false; } yyjson_api_inline bool yyjson_is_uint(yyjson_val *val) { return val ? unsafe_yyjson_is_uint(val) : false; } yyjson_api_inline bool yyjson_is_sint(yyjson_val *val) { return val ? unsafe_yyjson_is_sint(val) : false; } yyjson_api_inline bool yyjson_is_int(yyjson_val *val) { return val ? unsafe_yyjson_is_int(val) : false; } yyjson_api_inline bool yyjson_is_real(yyjson_val *val) { return val ? unsafe_yyjson_is_real(val) : false; } yyjson_api_inline bool yyjson_is_num(yyjson_val *val) { return val ? unsafe_yyjson_is_num(val) : false; } yyjson_api_inline bool yyjson_is_str(yyjson_val *val) { return val ? unsafe_yyjson_is_str(val) : false; } yyjson_api_inline bool yyjson_is_arr(yyjson_val *val) { return val ? unsafe_yyjson_is_arr(val) : false; } yyjson_api_inline bool yyjson_is_obj(yyjson_val *val) { return val ? unsafe_yyjson_is_obj(val) : false; } yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val) { return val ? unsafe_yyjson_is_ctn(val) : false; } /*============================================================================== * JSON Value Content API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val) { return val ? unsafe_yyjson_get_type(val) : YYJSON_TYPE_NONE; } yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val) { return val ? unsafe_yyjson_get_subtype(val) : YYJSON_SUBTYPE_NONE; } yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val) { return val ? unsafe_yyjson_get_tag(val) : 0; } yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val) { switch (yyjson_get_tag(val)) { case YYJSON_TYPE_RAW | YYJSON_SUBTYPE_NONE: return "raw"; case YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE: return "null"; case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return "string"; case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: return "array"; case YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE: return "object"; case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE: return "true"; case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE: return "false"; case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT: return "uint"; case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT: return "sint"; case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL: return "real"; default: return "unknown"; } } yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val) { return yyjson_is_raw(val) ? unsafe_yyjson_get_raw(val) : NULL; } yyjson_api_inline bool yyjson_get_bool(yyjson_val *val) { return yyjson_is_bool(val) ? unsafe_yyjson_get_bool(val) : false; } yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val) { return yyjson_is_int(val) ? unsafe_yyjson_get_uint(val) : 0; } yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val) { return yyjson_is_int(val) ? unsafe_yyjson_get_sint(val) : 0; } yyjson_api_inline int yyjson_get_int(yyjson_val *val) { return yyjson_is_int(val) ? unsafe_yyjson_get_int(val) : 0; } yyjson_api_inline double yyjson_get_real(yyjson_val *val) { return yyjson_is_real(val) ? unsafe_yyjson_get_real(val) : 0.0; } yyjson_api_inline double yyjson_get_num(yyjson_val *val) { return val ? unsafe_yyjson_get_num(val) : 0.0; } yyjson_api_inline const char *yyjson_get_str(yyjson_val *val) { return yyjson_is_str(val) ? unsafe_yyjson_get_str(val) : NULL; } yyjson_api_inline size_t yyjson_get_len(yyjson_val *val) { return val ? unsafe_yyjson_get_len(val) : 0; } yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str) { if (yyjson_likely(val && str)) { return unsafe_yyjson_equals_str(val, str); } return false; } yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str, size_t len) { if (yyjson_likely(val && str)) { return unsafe_yyjson_equals_strn(val, str, len); } return false; } yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs); yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { if (yyjson_unlikely(!lhs || !rhs)) return false; return unsafe_yyjson_equals(lhs, rhs); } yyjson_api_inline bool yyjson_set_raw(yyjson_val *val, const char *raw, size_t len) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_raw(val, raw, len); return true; } yyjson_api_inline bool yyjson_set_null(yyjson_val *val) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_null(val); return true; } yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_bool(val, num); return true; } yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_uint(val, num); return true; } yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_sint(val, num); return true; } yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_sint(val, (int64_t)num); return true; } yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_real(val, num); return true; } yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; if (yyjson_unlikely(!str)) return false; unsafe_yyjson_set_str(val, str); return true; } yyjson_api_inline bool yyjson_set_strn(yyjson_val *val, const char *str, size_t len) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; if (yyjson_unlikely(!str)) return false; unsafe_yyjson_set_strn(val, str, len); return true; } /*============================================================================== * JSON Array API (Implementation) *============================================================================*/ yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr) { return yyjson_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0; } yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx) { if (yyjson_likely(yyjson_is_arr(arr))) { if (yyjson_likely(unsafe_yyjson_get_len(arr) > idx)) { yyjson_val *val = unsafe_yyjson_get_first(arr); if (unsafe_yyjson_arr_is_flat(arr)) { return val + idx; } else { while (idx-- > 0) val = unsafe_yyjson_get_next(val); return val; } } } return NULL; } yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr) { if (yyjson_likely(yyjson_is_arr(arr))) { if (yyjson_likely(unsafe_yyjson_get_len(arr) > 0)) { return unsafe_yyjson_get_first(arr); } } return NULL; } yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr) { if (yyjson_likely(yyjson_is_arr(arr))) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(len > 0)) { yyjson_val *val = unsafe_yyjson_get_first(arr); if (unsafe_yyjson_arr_is_flat(arr)) { return val + (len - 1); } else { while (len-- > 1) val = unsafe_yyjson_get_next(val); return val; } } } return NULL; } /*============================================================================== * JSON Array Iterator API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr, yyjson_arr_iter *iter) { if (yyjson_likely(yyjson_is_arr(arr) && iter)) { iter->idx = 0; iter->max = unsafe_yyjson_get_len(arr); iter->cur = unsafe_yyjson_get_first(arr); return true; } if (iter) memset(iter, 0, sizeof(yyjson_arr_iter)); return false; } yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr) { yyjson_arr_iter iter; yyjson_arr_iter_init(arr, &iter); return iter; } yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter) { return iter ? iter->idx < iter->max : false; } yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter) { yyjson_val *val; if (iter && iter->idx < iter->max) { val = iter->cur; iter->cur = unsafe_yyjson_get_next(val); iter->idx++; return val; } return NULL; } /*============================================================================== * JSON Object API (Implementation) *============================================================================*/ yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj) { return yyjson_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0; } yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj, const char *key) { return yyjson_obj_getn(obj, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *_key, size_t key_len) { uint64_t tag = (((uint64_t)key_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; if (yyjson_likely(yyjson_is_obj(obj) && _key)) { size_t len = unsafe_yyjson_get_len(obj); yyjson_val *key = unsafe_yyjson_get_first(obj); while (len-- > 0) { if (key->tag == tag && memcmp(key->uni.ptr, _key, key_len) == 0) { return key + 1; } key = unsafe_yyjson_get_next(key + 1); } } return NULL; } /*============================================================================== * JSON Object Iterator API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj, yyjson_obj_iter *iter) { if (yyjson_likely(yyjson_is_obj(obj) && iter)) { iter->idx = 0; iter->max = unsafe_yyjson_get_len(obj); iter->cur = unsafe_yyjson_get_first(obj); iter->obj = obj; return true; } if (iter) memset(iter, 0, sizeof(yyjson_obj_iter)); return false; } yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj) { yyjson_obj_iter iter; yyjson_obj_iter_init(obj, &iter); return iter; } yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter) { return iter ? iter->idx < iter->max : false; } yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter) { if (iter && iter->idx < iter->max) { yyjson_val *key = iter->cur; iter->idx++; iter->cur = unsafe_yyjson_get_next(key + 1); return key; } return NULL; } yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key) { return key ? key + 1 : NULL; } yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter, const char *key) { return yyjson_obj_iter_getn(iter, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter, const char *key, size_t key_len) { if (iter && key) { size_t idx = iter->idx; size_t max = iter->max; yyjson_val *cur = iter->cur; if (yyjson_unlikely(idx == max)) { idx = 0; cur = unsafe_yyjson_get_first(iter->obj); } while (idx++ < max) { yyjson_val *next = unsafe_yyjson_get_next(cur + 1); if (unsafe_yyjson_get_len(cur) == key_len && memcmp(cur->uni.str, key, key_len) == 0) { iter->idx = idx; iter->cur = next; return cur + 1; } cur = next; if (idx == iter->max && iter->idx < iter->max) { idx = 0; max = iter->idx; cur = unsafe_yyjson_get_first(iter->obj); } } } return NULL; } /*============================================================================== * Mutable JSON Structure (Implementation) *============================================================================*/ /** Mutable JSON value, 24 bytes. The 'tag' and 'uni' field is same as immutable value. The 'next' field links all elements inside the container to be a cycle. */ struct yyjson_mut_val { uint64_t tag; /**< type, subtype and length */ yyjson_val_uni uni; /**< payload */ yyjson_mut_val *next; /**< the next value in circular linked list */ }; /** A memory chunk in string memory pool. */ typedef struct yyjson_str_chunk { struct yyjson_str_chunk *next; /* next chunk linked list */ size_t chunk_size; /* chunk size in bytes */ /* char str[]; flexible array member */ } yyjson_str_chunk; /** A memory pool to hold all strings in a mutable document. */ typedef struct yyjson_str_pool { char *cur; /* cursor inside current chunk */ char *end; /* the end of current chunk */ size_t chunk_size; /* chunk size in bytes while creating new chunk */ size_t chunk_size_max; /* maximum chunk size in bytes */ yyjson_str_chunk *chunks; /* a linked list of chunks, nullable */ } yyjson_str_pool; /** A memory chunk in value memory pool. `sizeof(yyjson_val_chunk)` should not larger than `sizeof(yyjson_mut_val)`. */ typedef struct yyjson_val_chunk { struct yyjson_val_chunk *next; /* next chunk linked list */ size_t chunk_size; /* chunk size in bytes */ /* char pad[sizeof(yyjson_mut_val) - sizeof(yyjson_val_chunk)]; padding */ /* yyjson_mut_val vals[]; flexible array member */ } yyjson_val_chunk; /** A memory pool to hold all values in a mutable document. */ typedef struct yyjson_val_pool { yyjson_mut_val *cur; /* cursor inside current chunk */ yyjson_mut_val *end; /* the end of current chunk */ size_t chunk_size; /* chunk size in bytes while creating new chunk */ size_t chunk_size_max; /* maximum chunk size in bytes */ yyjson_val_chunk *chunks; /* a linked list of chunks, nullable */ } yyjson_val_pool; struct yyjson_mut_doc { yyjson_mut_val *root; /**< root value of the JSON document, nullable */ yyjson_alc alc; /**< a valid allocator, nonnull */ yyjson_str_pool str_pool; /**< string memory pool */ yyjson_val_pool val_pool; /**< value memory pool */ }; /* Ensures the capacity to at least equal to the specified byte length. */ yyjson_api bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool, const yyjson_alc *alc, size_t len); /* Ensures the capacity to at least equal to the specified value count. */ yyjson_api bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool, const yyjson_alc *alc, size_t count); /* Allocate memory for string. */ yyjson_api_inline char *unsafe_yyjson_mut_str_alc(yyjson_mut_doc *doc, size_t len) { char *mem; const yyjson_alc *alc = &doc->alc; yyjson_str_pool *pool = &doc->str_pool; if (yyjson_unlikely((size_t)(pool->end - pool->cur) <= len)) { if (yyjson_unlikely(!unsafe_yyjson_str_pool_grow(pool, alc, len + 1))) { return NULL; } } mem = pool->cur; pool->cur = mem + len + 1; return mem; } yyjson_api_inline char *unsafe_yyjson_mut_strncpy(yyjson_mut_doc *doc, const char *str, size_t len) { char *mem = unsafe_yyjson_mut_str_alc(doc, len); if (yyjson_unlikely(!mem)) return NULL; memcpy((void *)mem, (const void *)str, len); mem[len] = '\0'; return mem; } yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_val(yyjson_mut_doc *doc, size_t count) { yyjson_mut_val *val; yyjson_alc *alc = &doc->alc; yyjson_val_pool *pool = &doc->val_pool; if (yyjson_unlikely((size_t)(pool->end - pool->cur) < count)) { if (yyjson_unlikely(!unsafe_yyjson_val_pool_grow(pool, alc, count))) { return NULL; } } val = pool->cur; pool->cur += count; return val; } /*============================================================================== * Mutable JSON Document API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc) { return doc ? doc->root : NULL; } yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc, yyjson_mut_val *root) { if (doc) doc->root = root; } /*============================================================================== * Mutable JSON Value Type API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_raw(val) : false; } yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_null(val) : false; } yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_true(val) : false; } yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_false(val) : false; } yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_bool(val) : false; } yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_uint(val) : false; } yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_sint(val) : false; } yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_int(val) : false; } yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_real(val) : false; } yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_num(val) : false; } yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_str(val) : false; } yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_arr(val) : false; } yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_obj(val) : false; } yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_ctn(val) : false; } /*============================================================================== * Mutable JSON Value Content API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val) { return yyjson_get_type((yyjson_val *)val); } yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val) { return yyjson_get_subtype((yyjson_val *)val); } yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val) { return yyjson_get_tag((yyjson_val *)val); } yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val) { return yyjson_get_type_desc((yyjson_val *)val); } yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val) { return yyjson_get_raw((yyjson_val *)val); } yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val) { return yyjson_get_bool((yyjson_val *)val); } yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val) { return yyjson_get_uint((yyjson_val *)val); } yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val) { return yyjson_get_sint((yyjson_val *)val); } yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val) { return yyjson_get_int((yyjson_val *)val); } yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val) { return yyjson_get_real((yyjson_val *)val); } yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val) { return yyjson_get_num((yyjson_val *)val); } yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val) { return yyjson_get_str((yyjson_val *)val); } yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val) { return yyjson_get_len((yyjson_val *)val); } yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val, const char *str) { return yyjson_equals_str((yyjson_val *)val, str); } yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val, const char *str, size_t len) { return yyjson_equals_strn((yyjson_val *)val, str, len); } yyjson_api bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs); yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { if (yyjson_unlikely(!lhs || !rhs)) return false; return unsafe_yyjson_mut_equals(lhs, rhs); } yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val, const char *raw, size_t len) { if (yyjson_unlikely(!val || !raw)) return false; unsafe_yyjson_set_raw(val, raw, len); return true; } yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_null(val); return true; } yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_bool(val, num); return true; } yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_uint(val, num); return true; } yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_sint(val, num); return true; } yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_sint(val, (int64_t)num); return true; } yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_real(val, num); return true; } yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val, const char *str) { if (yyjson_unlikely(!val || !str)) return false; unsafe_yyjson_set_str(val, str); return true; } yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val, const char *str, size_t len) { if (yyjson_unlikely(!val || !str)) return false; unsafe_yyjson_set_strn(val, str, len); return true; } yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_arr(val, 0); return true; } yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_obj(val, 0); return true; } /*============================================================================== * Mutable JSON Value Creation API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc, const char *str) { if (yyjson_likely(str)) return yyjson_mut_rawn(doc, str, strlen(str)); return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc, const char *str, size_t len) { if (yyjson_likely(doc && str)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; val->uni.str = str; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc, const char *str) { if (yyjson_likely(str)) return yyjson_mut_rawncpy(doc, str, strlen(str)); return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc, const char *str, size_t len) { if (yyjson_likely(doc && str)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len); if (yyjson_likely(val && new_str)) { val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; val->uni.str = new_str; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc, bool _val) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3); return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc, uint64_t num) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = num; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc, int64_t num) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = num; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc, int64_t num) { return yyjson_mut_sint(doc, num); } yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc, double num) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.f64 = num; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc, const char *str) { if (yyjson_likely(str)) return yyjson_mut_strn(doc, str, strlen(str)); return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc, const char *str, size_t len) { if (yyjson_likely(doc && str)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = str; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc, const char *str) { if (yyjson_likely(str)) return yyjson_mut_strncpy(doc, str, strlen(str)); return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc, const char *str, size_t len) { if (yyjson_likely(doc && str)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len); if (yyjson_likely(val && new_str)) { val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = new_str; return val; } } return NULL; } /*============================================================================== * Mutable JSON Array API (Implementation) *============================================================================*/ yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr) { return yyjson_mut_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr, size_t idx) { if (yyjson_likely(idx < yyjson_mut_arr_size(arr))) { yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; while (idx-- > 0) val = val->next; return val->next; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first( yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) { return ((yyjson_mut_val *)arr->uni.ptr)->next; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last( yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) { return ((yyjson_mut_val *)arr->uni.ptr); } return NULL; } /*============================================================================== * Mutable JSON Array Iterator API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr, yyjson_mut_arr_iter *iter) { if (yyjson_likely(yyjson_mut_is_arr(arr) && iter)) { iter->idx = 0; iter->max = unsafe_yyjson_get_len(arr); iter->cur = iter->max ? (yyjson_mut_val *)arr->uni.ptr : NULL; iter->pre = NULL; iter->arr = arr; return true; } if (iter) memset(iter, 0, sizeof(yyjson_mut_arr_iter)); return false; } yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with( yyjson_mut_val *arr) { yyjson_mut_arr_iter iter; yyjson_mut_arr_iter_init(arr, &iter); return iter; } yyjson_api_inline bool yyjson_mut_arr_iter_has_next(yyjson_mut_arr_iter *iter) { return iter ? iter->idx < iter->max : false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next( yyjson_mut_arr_iter *iter) { if (iter && iter->idx < iter->max) { yyjson_mut_val *val = iter->cur; iter->pre = val; iter->cur = val->next; iter->idx++; return iter->cur; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove( yyjson_mut_arr_iter *iter) { if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) { yyjson_mut_val *prev = iter->pre; yyjson_mut_val *cur = iter->cur; yyjson_mut_val *next = cur->next; if (yyjson_unlikely(iter->idx == iter->max)) iter->arr->uni.ptr = prev; iter->idx--; iter->max--; unsafe_yyjson_set_len(iter->arr, iter->max); prev->next = next; iter->cur = next; return cur; } return NULL; } /*============================================================================== * Mutable JSON Array Creation API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE; return val; } } return NULL; } #define yyjson_mut_arr_with_func(func) \ if (yyjson_likely(doc && ((0 < count && count < \ (~(size_t)0) / sizeof(yyjson_mut_val) && vals) || count == 0))) { \ yyjson_mut_val *arr = unsafe_yyjson_mut_val(doc, 1 + count); \ if (yyjson_likely(arr)) { \ arr->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; \ if (count > 0) { \ size_t i; \ for (i = 0; i < count; i++) { \ yyjson_mut_val *val = arr + i + 1; \ func \ val->next = val + 1; \ } \ arr[count].next = arr + 1; \ arr->uni.ptr = arr + count; \ } \ return arr; \ } \ } \ return NULL yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool( yyjson_mut_doc *doc, const bool *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)vals[i] << 3); }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint( yyjson_mut_doc *doc, const int64_t *vals, size_t count) { return yyjson_mut_arr_with_sint64(doc, vals, count); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint( yyjson_mut_doc *doc, const uint64_t *vals, size_t count) { return yyjson_mut_arr_with_uint64(doc, vals, count); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real( yyjson_mut_doc *doc, const double *vals, size_t count) { return yyjson_mut_arr_with_double(doc, vals, count); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8( yyjson_mut_doc *doc, const int8_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = (int64_t)vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16( yyjson_mut_doc *doc, const int16_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32( yyjson_mut_doc *doc, const int32_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64( yyjson_mut_doc *doc, const int64_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8( yyjson_mut_doc *doc, const uint8_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16( yyjson_mut_doc *doc, const uint16_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32( yyjson_mut_doc *doc, const uint32_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64( yyjson_mut_doc *doc, const uint64_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float( yyjson_mut_doc *doc, const float *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.f64 = (double)vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double( yyjson_mut_doc *doc, const double *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.f64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str( yyjson_mut_doc *doc, const char **vals, size_t count) { yyjson_mut_arr_with_func({ uint64_t len = (uint64_t)strlen(vals[i]); val->tag = (len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = vals[i]; if (yyjson_unlikely(!val->uni.str)) return NULL; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn( yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) { if (yyjson_unlikely(count > 0 && !lens)) return NULL; yyjson_mut_arr_with_func({ val->tag = ((uint64_t)lens[i] << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = vals[i]; if (yyjson_unlikely(!val->uni.str)) return NULL; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy( yyjson_mut_doc *doc, const char **vals, size_t count) { size_t len; const char *str; yyjson_mut_arr_with_func({ str = vals[i]; if (!str) return NULL; len = strlen(str); val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = unsafe_yyjson_mut_strncpy(doc, str, len); if (yyjson_unlikely(!val->uni.str)) return NULL; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy( yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) { size_t len; const char *str; if (yyjson_unlikely(count > 0 && !lens)) return NULL; yyjson_mut_arr_with_func({ str = vals[i]; len = lens[i]; val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = unsafe_yyjson_mut_strncpy(doc, str, len); if (yyjson_unlikely(!val->uni.str)) return NULL; }); } #undef yyjson_mut_arr_with_func /*============================================================================== * Mutable JSON Array Modification API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr, yyjson_mut_val *val, size_t idx) { if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(idx <= len)) { unsafe_yyjson_set_len(arr, len + 1); if (len == 0) { val->next = val; arr->uni.ptr = val; } else { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; if (idx == len) { prev->next = val; val->next = next; arr->uni.ptr = val; } else { while (idx-- > 0) { prev = next; next = next->next; } prev->next = val; val->next = next; } } return true; } } return false; } yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) { size_t len = unsafe_yyjson_get_len(arr); unsafe_yyjson_set_len(arr, len + 1); if (len == 0) { val->next = val; } else { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; prev->next = val; val->next = next; } arr->uni.ptr = val; return true; } return false; } yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) { size_t len = unsafe_yyjson_get_len(arr); unsafe_yyjson_set_len(arr, len + 1); if (len == 0) { val->next = val; arr->uni.ptr = val; } else { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; prev->next = val; val->next = next; } return true; } return false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr, size_t idx, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(idx < len)) { if (yyjson_likely(len > 1)) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; while (idx-- > 0) { prev = next; next = next->next; } prev->next = val; val->next = next->next; if ((void *)next == arr->uni.ptr) arr->uni.ptr = val; return next; } else { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); val->next = val; arr->uni.ptr = val; return prev; } } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr, size_t idx) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(idx < len)) { unsafe_yyjson_set_len(arr, len - 1); if (yyjson_likely(len > 1)) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; while (idx-- > 0) { prev = next; next = next->next; } prev->next = next->next; if ((void *)next == arr->uni.ptr) arr->uni.ptr = prev; return next; } else { return ((yyjson_mut_val *)arr->uni.ptr); } } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first( yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { size_t len = unsafe_yyjson_get_len(arr); if (len > 1) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; prev->next = next->next; unsafe_yyjson_set_len(arr, len - 1); return next; } else if (len == 1) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); unsafe_yyjson_set_len(arr, 0); return prev; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last( yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(len > 1)) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; unsafe_yyjson_set_len(arr, len - 1); while (--len > 0) prev = prev->next; prev->next = next; next = (yyjson_mut_val *)arr->uni.ptr; arr->uni.ptr = prev; return next; } else if (len == 1) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); unsafe_yyjson_set_len(arr, 0); return prev; } } return NULL; } yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr, size_t _idx, size_t _len) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { yyjson_mut_val *prev, *next; bool tail_removed; size_t len = unsafe_yyjson_get_len(arr); if (yyjson_unlikely(_idx + _len > len)) return false; if (yyjson_unlikely(_len == 0)) return true; unsafe_yyjson_set_len(arr, len - _len); if (yyjson_unlikely(len == _len)) return true; tail_removed = (_idx + _len == len); prev = ((yyjson_mut_val *)arr->uni.ptr); while (_idx-- > 0) prev = prev->next; next = prev->next; while (_len-- > 0) next = next->next; prev->next = next; if (yyjson_unlikely(tail_removed)) arr->uni.ptr = prev; return true; } return false; } yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { unsafe_yyjson_set_len(arr, 0); return true; } return false; } yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr, size_t idx) { if (yyjson_likely(yyjson_mut_is_arr(arr) && unsafe_yyjson_get_len(arr) > idx)) { yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; while (idx-- > 0) val = val->next; arr->uni.ptr = (void *)val; return true; } return false; } /*============================================================================== * Mutable JSON Array Modification Convenience API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr, yyjson_mut_val *val) { return yyjson_mut_arr_append(arr, val); } yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_null(doc); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_true(doc); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_false(doc); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *arr, bool _val) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_bool(doc, _val); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *arr, uint64_t num) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_uint(doc, num); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *arr, int64_t num) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_sint(doc, num); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc, yyjson_mut_val *arr, int64_t num) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_sint(doc, num); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc, yyjson_mut_val *arr, double num) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_real(doc, num); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_str(doc, str); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str, size_t len) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_strn(doc, str, len); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_strcpy(doc, str); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str, size_t len) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_strncpy(doc, str, len); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_arr(doc); return yyjson_mut_arr_append(arr, val) ? val : NULL; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_obj(doc); return yyjson_mut_arr_append(arr, val) ? val : NULL; } return NULL; } /*============================================================================== * Mutable JSON Object API (Implementation) *============================================================================*/ yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj) { return yyjson_mut_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj, const char *key) { return yyjson_mut_obj_getn(obj, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj, const char *_key, size_t key_len) { uint64_t tag = (((uint64_t)key_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; size_t len = yyjson_mut_obj_size(obj); if (yyjson_likely(len && _key)) { yyjson_mut_val *key = ((yyjson_mut_val *)obj->uni.ptr)->next->next; while (len-- > 0) { if (key->tag == tag && memcmp(key->uni.ptr, _key, key_len) == 0) { return key->next; } key = key->next->next; } } return NULL; } /*============================================================================== * Mutable JSON Object Iterator API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj, yyjson_mut_obj_iter *iter) { if (yyjson_likely(yyjson_mut_is_obj(obj) && iter)) { iter->idx = 0; iter->max = unsafe_yyjson_get_len(obj); iter->cur = iter->max ? (yyjson_mut_val *)obj->uni.ptr : NULL; iter->pre = NULL; iter->obj = obj; return true; } if (iter) memset(iter, 0, sizeof(yyjson_mut_obj_iter)); return false; } yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with( yyjson_mut_val *obj) { yyjson_mut_obj_iter iter; yyjson_mut_obj_iter_init(obj, &iter); return iter; } yyjson_api_inline bool yyjson_mut_obj_iter_has_next(yyjson_mut_obj_iter *iter) { return iter ? iter->idx < iter->max : false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next( yyjson_mut_obj_iter *iter) { if (iter && iter->idx < iter->max) { yyjson_mut_val *key = iter->cur; iter->pre = key; iter->cur = key->next->next; iter->idx++; return iter->cur; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val( yyjson_mut_val *key) { return key ? key->next : NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove( yyjson_mut_obj_iter *iter) { if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) { yyjson_mut_val *prev = iter->pre; yyjson_mut_val *cur = iter->cur; yyjson_mut_val *next = cur->next->next; if (yyjson_unlikely(iter->idx == iter->max)) iter->obj->uni.ptr = prev; iter->idx--; iter->max--; unsafe_yyjson_set_len(iter->obj, iter->max); prev->next->next = next; iter->cur = prev; return cur->next; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get( yyjson_mut_obj_iter *iter, const char *key) { return yyjson_mut_obj_iter_getn(iter, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn( yyjson_mut_obj_iter *iter, const char *key, size_t key_len) { if (iter && key) { size_t idx = 0; size_t max = iter->max; yyjson_mut_val *pre, *cur = iter->cur; while (idx++ < max) { pre = cur; cur = cur->next->next; if (unsafe_yyjson_get_len(cur) == key_len && memcmp(cur->uni.str, key, key_len) == 0) { iter->idx += idx; if (iter->idx > max) iter->idx -= max + 1; iter->pre = pre; iter->cur = cur; return cur->next; } } } return NULL; } /*============================================================================== * Mutable JSON Object Creation API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc, const char **keys, const char **vals, size_t count) { if (yyjson_likely(doc && ((count > 0 && keys && vals) || (count == 0)))) { yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2); if (yyjson_likely(obj)) { obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ; if (count > 0) { size_t i; for (i = 0; i < count; i++) { yyjson_mut_val *key = obj + (i * 2 + 1); yyjson_mut_val *val = obj + (i * 2 + 2); uint64_t key_len = (uint64_t)strlen(keys[i]); uint64_t val_len = (uint64_t)strlen(vals[i]); key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; key->uni.str = keys[i]; val->uni.str = vals[i]; key->next = val; val->next = val + 1; } obj[count * 2].next = obj + 1; obj->uni.ptr = obj + (count * 2 - 1); } return obj; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc, const char **pairs, size_t count) { if (yyjson_likely(doc && ((count > 0 && pairs) || (count == 0)))) { yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2); if (yyjson_likely(obj)) { obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ; if (count > 0) { size_t i; for (i = 0; i < count; i++) { yyjson_mut_val *key = obj + (i * 2 + 1); yyjson_mut_val *val = obj + (i * 2 + 2); const char *key_str = pairs[i * 2 + 0]; const char *val_str = pairs[i * 2 + 1]; uint64_t key_len = (uint64_t)strlen(key_str); uint64_t val_len = (uint64_t)strlen(val_str); key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; key->uni.str = key_str; val->uni.str = val_str; key->next = val; val->next = val + 1; } obj[count * 2].next = obj + 1; obj->uni.ptr = obj + (count * 2 - 1); } return obj; } } return NULL; } /*============================================================================== * Mutable JSON Object Modification API (Implementation) *============================================================================*/ yyjson_api_inline void unsafe_yyjson_mut_obj_add(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val, size_t len) { if (yyjson_likely(len)) { yyjson_mut_val *prev_val = ((yyjson_mut_val *)obj->uni.ptr)->next; yyjson_mut_val *next_key = prev_val->next; prev_val->next = key; val->next = next_key; } else { val->next = key; } key->next = val; obj->uni.ptr = (void *)key; unsafe_yyjson_set_len(obj, len + 1); } yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_obj_remove( yyjson_mut_val *obj, const char *key, size_t key_len, uint64_t key_tag) { size_t obj_len = unsafe_yyjson_get_len(obj); if (obj_len) { yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr; yyjson_mut_val *cur_key = pre_key->next->next; yyjson_mut_val *removed_item = NULL; size_t i; for (i = 0; i < obj_len; i++) { if (key_tag == cur_key->tag && memcmp(key, cur_key->uni.ptr, key_len) == 0) { if (!removed_item) removed_item = cur_key->next; cur_key = cur_key->next->next; pre_key->next->next = cur_key; if (i + 1 == obj_len) obj->uni.ptr = pre_key; i--; obj_len--; } else { pre_key = cur_key; cur_key = cur_key->next->next; } } unsafe_yyjson_set_len(obj, obj_len); return removed_item; } else { return NULL; } } yyjson_api_inline bool unsafe_yyjson_mut_obj_replace(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { size_t key_len = unsafe_yyjson_get_len(key); size_t obj_len = unsafe_yyjson_get_len(obj); if (obj_len) { yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr; yyjson_mut_val *cur_key = pre_key->next->next; size_t i; for (i = 0; i < obj_len; i++) { if (key->tag == cur_key->tag && memcmp(key->uni.str, cur_key->uni.ptr, key_len) == 0) { cur_key->next->tag = val->tag; cur_key->next->uni.u64 = val->uni.u64; return true; } else { cur_key = cur_key->next->next; } } } return false; } yyjson_api_inline void unsafe_yyjson_mut_obj_rotate(yyjson_mut_val *obj, size_t idx) { yyjson_mut_val *key = (yyjson_mut_val *)obj->uni.ptr; while (idx-- > 0) key = key->next->next; obj->uni.ptr = (void *)key; } yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key) && val)) { unsafe_yyjson_mut_obj_add(obj, key, val, unsafe_yyjson_get_len(obj)); return true; } return false; } yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { bool replaced = false; size_t key_len; yyjson_mut_obj_iter iter; yyjson_mut_val *cur_key; if (yyjson_unlikely(!yyjson_mut_is_obj(obj) || !yyjson_mut_is_str(key))) return false; key_len = unsafe_yyjson_get_len(key); yyjson_mut_obj_iter_init(obj, &iter); while ((cur_key = yyjson_mut_obj_iter_next(&iter))) { if (key->tag == cur_key->tag && memcmp(key->uni.str, cur_key->uni.ptr, key_len) == 0) { if (!replaced && val) { replaced = true; val->next = cur_key->next->next; cur_key->next = val; } else { yyjson_mut_obj_iter_remove(&iter); } } } if (!replaced && val) unsafe_yyjson_mut_obj_add(obj, key, val, iter.max); return true; } yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val, size_t idx) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key) && val)) { size_t len = unsafe_yyjson_get_len(obj); if (yyjson_likely(len >= idx)) { if (len > idx) { void *ptr = obj->uni.ptr; unsafe_yyjson_mut_obj_rotate(obj, idx); unsafe_yyjson_mut_obj_add(obj, key, val, len); obj->uni.ptr = ptr; } else { unsafe_yyjson_mut_obj_add(obj, key, val, len); } return true; } } return false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj, yyjson_mut_val *key) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key))) { return unsafe_yyjson_mut_obj_remove(obj, key->uni.str, unsafe_yyjson_get_len(key), key->tag); } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key( yyjson_mut_val *obj, const char *key) { if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) { size_t key_len = strlen(key); uint64_t tag = ((uint64_t)key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; return unsafe_yyjson_mut_obj_remove(obj, key, key_len, tag); } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn( yyjson_mut_val *obj, const char *key, size_t key_len) { if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) { uint64_t tag = ((uint64_t)key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; return unsafe_yyjson_mut_obj_remove(obj, key, key_len, tag); } return NULL; } yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj) { if (yyjson_likely(yyjson_mut_is_obj(obj))) { unsafe_yyjson_set_len(obj, 0); return true; } return false; } yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key) && val)) { return unsafe_yyjson_mut_obj_replace(obj, key, val); } return false; } yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj, size_t idx) { if (yyjson_likely(yyjson_mut_is_obj(obj) && unsafe_yyjson_get_len(obj) > idx)) { unsafe_yyjson_mut_obj_rotate(obj, idx); return true; } return false; } /*============================================================================== * Mutable JSON Object Modification Convenience API (Implementation) *============================================================================*/ #define yyjson_mut_obj_add_func(func) \ if (yyjson_likely(doc && yyjson_mut_is_obj(obj) && _key)) { \ yyjson_mut_val *key = unsafe_yyjson_mut_val(doc, 2); \ if (yyjson_likely(key)) { \ size_t len = unsafe_yyjson_get_len(obj); \ yyjson_mut_val *val = key + 1; \ key->tag = YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE; \ key->tag |= (uint64_t)strlen(_key) << YYJSON_TAG_BIT; \ key->uni.str = _key; \ func \ unsafe_yyjson_mut_obj_add(obj, key, val, len); \ return true; \ } \ } \ return false yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE; }); } yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; }); } yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; }); } yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, bool _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)(_val) << 3); }); } yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, uint64_t _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, int64_t _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, int64_t _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, double _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.f64 = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, const char *_val) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ val->tag = ((uint64_t)strlen(_val) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, const char *_val, size_t _len) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, const char *_val) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ size_t _len = strlen(_val); val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len); if (yyjson_unlikely(!val->uni.str)) return false; val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; }); } yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, const char *_val, size_t _len) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len); if (yyjson_unlikely(!val->uni.str)) return false; val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; }); } yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, yyjson_mut_val *_val) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ val = _val; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str(yyjson_mut_val *obj, const char *key) { return yyjson_mut_obj_remove_strn(obj, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn( yyjson_mut_val *obj, const char *_key, size_t _len) { if (yyjson_likely(yyjson_mut_is_obj(obj) && _key)) { yyjson_mut_val *key; yyjson_mut_obj_iter iter; yyjson_mut_val *val_removed = NULL; yyjson_mut_obj_iter_init(obj, &iter); while ((key = yyjson_mut_obj_iter_next(&iter)) != NULL) { if (unsafe_yyjson_get_len(key) == _len && memcmp(key->uni.str, _key, _len) == 0) { if (!val_removed) val_removed = key->next; yyjson_mut_obj_iter_remove(&iter); } } return val_removed; } return NULL; } yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *new_key) { if (!key || !new_key) return false; return yyjson_mut_obj_rename_keyn(doc, obj, key, strlen(key), new_key, strlen(new_key)); } yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, size_t len, const char *new_key, size_t new_len) { char *cpy_key = NULL; yyjson_mut_val *old_key; yyjson_mut_obj_iter iter; if (!doc || !obj || !key || !new_key) return false; yyjson_mut_obj_iter_init(obj, &iter); while ((old_key = yyjson_mut_obj_iter_next(&iter))) { if (unsafe_yyjson_equals_strn((void *)old_key, key, len)) { if (!cpy_key) { cpy_key = unsafe_yyjson_mut_strncpy(doc, new_key, new_len); if (!cpy_key) return false; } yyjson_mut_set_strn(old_key, cpy_key, new_len); } } return cpy_key != NULL; } /*============================================================================== * JSON Pointer API (Implementation) *============================================================================*/ #define yyjson_ptr_set_err(_code, _msg) do { \ if (err) { \ err->code = YYJSON_PTR_ERR_##_code; \ err->msg = _msg; \ err->pos = 0; \ } \ } while(false) /* require: val != NULL, *ptr == '/', len > 0 */ yyjson_api yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val, const char *ptr, size_t len, yyjson_ptr_err *err); /* require: val != NULL, *ptr == '/', len > 0 */ yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /* require: val/new_val/doc != NULL, *ptr == '/', len > 0 */ yyjson_api bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, bool insert_new, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /* require: val/err != NULL, *ptr == '/', len > 0 */ yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /* require: val/err != NULL, *ptr == '/', len > 0 */ yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc, const char *ptr) { if (yyjson_unlikely(!ptr)) return NULL; return yyjson_doc_ptr_getn(doc, ptr, strlen(ptr)); } yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc, const char *ptr, size_t len) { return yyjson_doc_ptr_getx(doc, ptr, len, NULL); } yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc, const char *ptr, size_t len, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (yyjson_unlikely(!doc || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(!doc->root)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { return doc->root; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_ptr_getx(doc->root, ptr, len, err); } yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val, const char *ptr) { if (yyjson_unlikely(!ptr)) return NULL; return yyjson_ptr_getn(val, ptr, strlen(ptr)); } yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val, const char *ptr, size_t len) { return yyjson_ptr_getx(val, ptr, len, NULL); } yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val, const char *ptr, size_t len, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (yyjson_unlikely(!val || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { return val; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_ptr_getx(val, ptr, len, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc, const char *ptr) { if (!ptr) return NULL; return yyjson_mut_doc_ptr_getn(doc, ptr, strlen(ptr)); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc, const char *ptr, size_t len) { return yyjson_mut_doc_ptr_getx(doc, ptr, len, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(!doc->root)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { return doc->root; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_getx(doc->root, ptr, len, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val, const char *ptr) { if (!ptr) return NULL; return yyjson_mut_ptr_getn(val, ptr, strlen(ptr)); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val, const char *ptr, size_t len) { return yyjson_mut_ptr_getx(val, ptr, len, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { return val; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); } yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) { if (yyjson_unlikely(!ptr)) return false; return yyjson_mut_doc_ptr_addn(doc, ptr, strlen(ptr), new_val); } yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) { return yyjson_mut_doc_ptr_addx(doc, ptr, len, new_val, true, NULL, NULL); } yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr || !new_val)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return false; } if (yyjson_unlikely(len == 0)) { if (doc->root) { yyjson_ptr_set_err(SET_ROOT, "cannot set document's root"); return false; } else { doc->root = new_val; return true; } } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return false; } if (yyjson_unlikely(!doc->root && !create_parent)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return false; } if (yyjson_unlikely(!doc->root)) { yyjson_mut_val *root = yyjson_mut_obj(doc); if (yyjson_unlikely(!root)) { yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value"); return false; } if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc, create_parent, true, ctx, err)) { doc->root = root; return true; } return false; } return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc, create_parent, true, ctx, err); } yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val, yyjson_mut_doc *doc) { if (yyjson_unlikely(!ptr)) return false; return yyjson_mut_ptr_addn(val, ptr, strlen(ptr), new_val, doc); } yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc) { return yyjson_mut_ptr_addx(val, ptr, len, new_val, doc, true, NULL, NULL); } yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr || !new_val || !doc)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return false; } if (yyjson_unlikely(len == 0)) { yyjson_ptr_set_err(SET_ROOT, "cannot set root"); return false; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return false; } return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, doc, create_parent, true, ctx, err); } yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) { if (yyjson_unlikely(!ptr)) return false; return yyjson_mut_doc_ptr_setn(doc, ptr, strlen(ptr), new_val); } yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) { return yyjson_mut_doc_ptr_setx(doc, ptr, len, new_val, true, NULL, NULL); } yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return false; } if (yyjson_unlikely(len == 0)) { if (ctx) ctx->old = doc->root; doc->root = new_val; return true; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return false; } if (!new_val) { if (!doc->root) { yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved"); return false; } return !!unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err); } if (yyjson_unlikely(!doc->root && !create_parent)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return false; } if (yyjson_unlikely(!doc->root)) { yyjson_mut_val *root = yyjson_mut_obj(doc); if (yyjson_unlikely(!root)) { yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value"); return false; } if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc, create_parent, false, ctx, err)) { doc->root = root; return true; } return false; } return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc, create_parent, false, ctx, err); } yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val, yyjson_mut_doc *doc) { if (yyjson_unlikely(!ptr)) return false; return yyjson_mut_ptr_setn(val, ptr, strlen(ptr), new_val, doc); } yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc) { return yyjson_mut_ptr_setx(val, ptr, len, new_val, doc, true, NULL, NULL); } yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr || !doc)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return false; } if (yyjson_unlikely(len == 0)) { yyjson_ptr_set_err(SET_ROOT, "cannot set root"); return false; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return false; } if (!new_val) { return !!unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err); } return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, doc, create_parent, false, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace( yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) { if (!ptr) return NULL; return yyjson_mut_doc_ptr_replacen(doc, ptr, strlen(ptr), new_val); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) { return yyjson_mut_doc_ptr_replacex(doc, ptr, len, new_val, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr || !new_val)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { yyjson_mut_val *root = doc->root; if (yyjson_unlikely(!root)) { yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved"); return NULL; } if (ctx) ctx->old = root; doc->root = new_val; return root; } if (yyjson_unlikely(!doc->root)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return NULL; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_replacex(doc->root, ptr, len, new_val, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace( yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val) { if (!ptr) return NULL; return yyjson_mut_ptr_replacen(val, ptr, strlen(ptr), new_val); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val) { return yyjson_mut_ptr_replacex(val, ptr, len, new_val, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr || !new_val)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { yyjson_ptr_set_err(SET_ROOT, "cannot set root"); return NULL; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_replacex(val, ptr, len, new_val, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove( yyjson_mut_doc *doc, const char *ptr) { if (!ptr) return NULL; return yyjson_mut_doc_ptr_removen(doc, ptr, strlen(ptr)); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen( yyjson_mut_doc *doc, const char *ptr, size_t len) { return yyjson_mut_doc_ptr_removex(doc, ptr, len, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(!doc->root)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { yyjson_mut_val *root = doc->root; if (ctx) ctx->old = root; doc->root = NULL; return root; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val, const char *ptr) { if (!ptr) return NULL; return yyjson_mut_ptr_removen(val, ptr, strlen(ptr)); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val, const char *ptr, size_t len) { return yyjson_mut_ptr_removex(val, ptr, len, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { yyjson_ptr_set_err(SET_ROOT, "cannot set root"); return NULL; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err); } yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx, yyjson_mut_val *key, yyjson_mut_val *val) { yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val; if (!ctx || !ctx->ctn || !val) return false; ctn = ctx->ctn; if (yyjson_mut_is_obj(ctn)) { if (!key) return false; key->next = val; pre_key = ctx->pre; if (unsafe_yyjson_get_len(ctn) == 0) { val->next = key; ctn->uni.ptr = key; ctx->pre = key; } else if (!pre_key) { pre_key = (yyjson_mut_val *)ctn->uni.ptr; pre_val = pre_key->next; val->next = pre_val->next; pre_val->next = key; ctn->uni.ptr = key; ctx->pre = pre_key; } else { cur_key = pre_key->next->next; cur_val = cur_key->next; val->next = cur_val->next; cur_val->next = key; if (ctn->uni.ptr == cur_key) ctn->uni.ptr = key; ctx->pre = cur_key; } } else { pre_val = ctx->pre; if (unsafe_yyjson_get_len(ctn) == 0) { val->next = val; ctn->uni.ptr = val; ctx->pre = val; } else if (!pre_val) { pre_val = (yyjson_mut_val *)ctn->uni.ptr; val->next = pre_val->next; pre_val->next = val; ctn->uni.ptr = val; ctx->pre = pre_val; } else { cur_val = pre_val->next; val->next = cur_val->next; cur_val->next = val; if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val; ctx->pre = cur_val; } } unsafe_yyjson_inc_len(ctn); return true; } yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx, yyjson_mut_val *val) { yyjson_mut_val *ctn, *pre_key, *cur_key, *pre_val, *cur_val; if (!ctx || !ctx->ctn || !ctx->pre || !val) return false; ctn = ctx->ctn; if (yyjson_mut_is_obj(ctn)) { pre_key = ctx->pre; pre_val = pre_key->next; cur_key = pre_val->next; cur_val = cur_key->next; /* replace current value */ cur_key->next = val; val->next = cur_val->next; ctx->old = cur_val; } else { pre_val = ctx->pre; cur_val = pre_val->next; /* replace current value */ if (pre_val != cur_val) { val->next = cur_val->next; pre_val->next = val; if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val; } else { val->next = val; ctn->uni.ptr = val; ctx->pre = val; } ctx->old = cur_val; } return true; } yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx) { yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val; size_t len; if (!ctx || !ctx->ctn || !ctx->pre) return false; ctn = ctx->ctn; if (yyjson_mut_is_obj(ctn)) { pre_key = ctx->pre; pre_val = pre_key->next; cur_key = pre_val->next; cur_val = cur_key->next; /* remove current key-value */ pre_val->next = cur_val->next; if (ctn->uni.ptr == cur_key) ctn->uni.ptr = pre_key; ctx->pre = NULL; ctx->old = cur_val; } else { pre_val = ctx->pre; cur_val = pre_val->next; /* remove current key-value */ pre_val->next = cur_val->next; if (ctn->uni.ptr == cur_val) ctn->uni.ptr = pre_val; ctx->pre = NULL; ctx->old = cur_val; } len = unsafe_yyjson_get_len(ctn) - 1; if (len == 0) ctn->uni.ptr = NULL; unsafe_yyjson_set_len(ctn, len); return true; } #undef yyjson_ptr_set_err /*============================================================================== * JSON Value at Pointer API (Implementation) *============================================================================*/ /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type bool. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_bool( yyjson_val *root, const char *ptr, bool *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_bool(val)) { *value = unsafe_yyjson_get_bool(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type uint. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_uint( yyjson_val *root, const char *ptr, uint64_t *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_uint(val)) { *value = unsafe_yyjson_get_uint(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_sint( yyjson_val *root, const char *ptr, int64_t *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_sint(val)) { *value = unsafe_yyjson_get_sint(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type real. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_real( yyjson_val *root, const char *ptr, double *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_real(val)) { *value = unsafe_yyjson_get_real(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint, uint or real. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_num( yyjson_val *root, const char *ptr, double *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_num(val)) { *value = unsafe_yyjson_get_num(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type string. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_str( yyjson_val *root, const char *ptr, const char **value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_str(val)) { *value = unsafe_yyjson_get_str(val); return true; } else { return false; } } /*============================================================================== * Deprecated *============================================================================*/ /** @deprecated renamed to `yyjson_doc_ptr_get` */ yyjson_deprecated("renamed to yyjson_doc_ptr_get") yyjson_api_inline yyjson_val *yyjson_doc_get_pointer(yyjson_doc *doc, const char *ptr) { return yyjson_doc_ptr_get(doc, ptr); } /** @deprecated renamed to `yyjson_doc_ptr_getn` */ yyjson_deprecated("renamed to yyjson_doc_ptr_getn") yyjson_api_inline yyjson_val *yyjson_doc_get_pointern(yyjson_doc *doc, const char *ptr, size_t len) { return yyjson_doc_ptr_getn(doc, ptr, len); } /** @deprecated renamed to `yyjson_mut_doc_ptr_get` */ yyjson_deprecated("renamed to yyjson_mut_doc_ptr_get") yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer( yyjson_mut_doc *doc, const char *ptr) { return yyjson_mut_doc_ptr_get(doc, ptr); } /** @deprecated renamed to `yyjson_mut_doc_ptr_getn` */ yyjson_deprecated("renamed to yyjson_mut_doc_ptr_getn") yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointern( yyjson_mut_doc *doc, const char *ptr, size_t len) { return yyjson_mut_doc_ptr_getn(doc, ptr, len); } /** @deprecated renamed to `yyjson_ptr_get` */ yyjson_deprecated("renamed to yyjson_ptr_get") yyjson_api_inline yyjson_val *yyjson_get_pointer(yyjson_val *val, const char *ptr) { return yyjson_ptr_get(val, ptr); } /** @deprecated renamed to `yyjson_ptr_getn` */ yyjson_deprecated("renamed to yyjson_ptr_getn") yyjson_api_inline yyjson_val *yyjson_get_pointern(yyjson_val *val, const char *ptr, size_t len) { return yyjson_ptr_getn(val, ptr, len); } /** @deprecated renamed to `yyjson_mut_ptr_get` */ yyjson_deprecated("renamed to yyjson_mut_ptr_get") yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointer(yyjson_mut_val *val, const char *ptr) { return yyjson_mut_ptr_get(val, ptr); } /** @deprecated renamed to `yyjson_mut_ptr_getn` */ yyjson_deprecated("renamed to yyjson_mut_ptr_getn") yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointern(yyjson_mut_val *val, const char *ptr, size_t len) { return yyjson_mut_ptr_getn(val, ptr, len); } /** @deprecated renamed to `yyjson_mut_ptr_getn` */ yyjson_deprecated("renamed to unsafe_yyjson_ptr_getn") yyjson_api_inline yyjson_val *unsafe_yyjson_get_pointer(yyjson_val *val, const char *ptr, size_t len) { yyjson_ptr_err err; return unsafe_yyjson_ptr_getx(val, ptr, len, &err); } /** @deprecated renamed to `unsafe_yyjson_mut_ptr_getx` */ yyjson_deprecated("renamed to unsafe_yyjson_mut_ptr_getx") yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_get_pointer( yyjson_mut_val *val, const char *ptr, size_t len) { yyjson_ptr_err err; return unsafe_yyjson_mut_ptr_getx(val, ptr, len, NULL, &err); } /*============================================================================== * Compiler Hint End *============================================================================*/ #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic pop # endif #elif defined(_MSC_VER) # pragma warning(pop) #endif /* warning suppress end */ #ifdef __cplusplus } #endif /* extern "C" end */ #endif /* YYJSON_H */ ================================================ FILE: libsvc/Modules/Lib/World/LICENSE.txt ================================================ /* ----------------------------------------------------------------- */ /* WORLD: High-quality speech analysis, */ /* manipulation and synthesis system */ /* developed by M. Morise */ /* http://www.kisc.meiji.ac.jp/~mmorise/world/english/ */ /* ----------------------------------------------------------------- */ /* */ /* Copyright (c) 2010 M. Morise */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or */ /* without modification, are permitted provided that the following */ /* conditions are met: */ /* */ /* - Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* - Redistributions in binary form must reproduce the above */ /* copyright notice, this list of conditions and the following */ /* disclaimer in the documentation and/or other materials provided */ /* with the distribution. */ /* - Neither the name of the M. Morise nor the names of its */ /* contributors may be used to endorse or promote products derived */ /* from this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */ /* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */ /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS */ /* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */ /* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY */ /* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ /* POSSIBILITY OF SUCH DAMAGE. */ /* ----------------------------------------------------------------- */ ================================================ FILE: libsvc/Modules/Lib/World/src/cheaptrick.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Spectral envelope estimation on the basis of the idea of CheapTrick. //----------------------------------------------------------------------------- #include "world/cheaptrick.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { //----------------------------------------------------------------------------- // SmoothingWithRecovery() carries out the spectral smoothing and spectral // recovery on the Cepstrum domain. //----------------------------------------------------------------------------- static void SmoothingWithRecovery(double f0, int fs, int fft_size, double q1, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, double *spectral_envelope) { double *smoothing_lifter = new double[fft_size]; double *compensation_lifter = new double[fft_size]; smoothing_lifter[0] = 1.0; compensation_lifter[0] = (1.0 - 2.0 * q1) + 2.0 * q1; double quefrency; for (int i = 1; i <= forward_real_fft->fft_size / 2; ++i) { quefrency = static_cast(i) / fs; smoothing_lifter[i] = sin(world::kPi * f0 * quefrency) / (world::kPi * f0 * quefrency); compensation_lifter[i] = (1.0 - 2.0 * q1) + 2.0 * q1 * cos(2.0 * world::kPi * quefrency * f0); } for (int i = 0; i <= fft_size / 2; ++i) forward_real_fft->waveform[i] = log(forward_real_fft->waveform[i]); for (int i = 1; i < fft_size / 2; ++i) forward_real_fft->waveform[fft_size - i] = forward_real_fft->waveform[i]; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = forward_real_fft->spectrum[i][0] * smoothing_lifter[i] * compensation_lifter[i] / fft_size; inverse_real_fft->spectrum[i][1] = 0.0; } fft_execute(inverse_real_fft->inverse_fft); for (int i = 0; i <= fft_size / 2; ++i) spectral_envelope[i] = exp(inverse_real_fft->waveform[i]); delete[] smoothing_lifter; delete[] compensation_lifter; } //----------------------------------------------------------------------------- // GetPowerSpectrum() calculates the power_spectrum with DC correction. // DC stands for Direct Current. In this case, the component from 0 to F0 Hz // is corrected. //----------------------------------------------------------------------------- static void GetPowerSpectrum(int fs, double f0, int fft_size, const ForwardRealFFT *forward_real_fft) { int half_window_length = matlab_round(1.5 * fs / f0); // FFT for (int i = half_window_length * 2 + 1; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); // Calculation of the power spectrum. double *power_spectrum = forward_real_fft->waveform; for (int i = 0; i <= fft_size / 2; ++i) power_spectrum[i] = forward_real_fft->spectrum[i][0] * forward_real_fft->spectrum[i][0] + forward_real_fft->spectrum[i][1] * forward_real_fft->spectrum[i][1]; // DC correction DCCorrection(power_spectrum, f0, fs, fft_size, power_spectrum); } //----------------------------------------------------------------------------- // SetParametersForGetWindowedWaveform() //----------------------------------------------------------------------------- static void SetParametersForGetWindowedWaveform(int half_window_length, int x_length, double currnet_position, int fs, double current_f0, int *base_index, int *safe_index, double *window) { for (int i = -half_window_length; i <= half_window_length; ++i) base_index[i + half_window_length] = i; int origin = matlab_round(currnet_position * fs + 0.001); for (int i = 0; i <= half_window_length * 2; ++i) safe_index[i] = MyMinInt(x_length - 1, MyMaxInt(0, origin + base_index[i])); // Designing of the window function double average = 0.0; double position; for (int i = 0; i <= half_window_length * 2; ++i) { position = base_index[i] / 1.5 / fs; window[i] = 0.5 * cos(world::kPi * position * current_f0) + 0.5; average += window[i] * window[i]; } average = sqrt(average); for (int i = 0; i <= half_window_length * 2; ++i) window[i] /= average; } //----------------------------------------------------------------------------- // GetWindowedWaveform() windows the waveform by F0-adaptive window //----------------------------------------------------------------------------- static void GetWindowedWaveform(const double *x, int x_length, int fs, double current_f0, double currnet_position, const ForwardRealFFT *forward_real_fft) { int half_window_length = matlab_round(1.5 * fs / current_f0); int *base_index = new int[half_window_length * 2 + 1]; int *safe_index = new int[half_window_length * 2 + 1]; double *window = new double[half_window_length * 2 + 1]; SetParametersForGetWindowedWaveform(half_window_length, x_length, currnet_position, fs, current_f0, base_index, safe_index, window); // F0-adaptive windowing double *waveform = forward_real_fft->waveform; for (int i = 0; i <= half_window_length * 2; ++i) waveform[i] = x[safe_index[i]] * window[i] + randn() * world::kMySafeGuardMinimum; double tmp_weight1 = 0; double tmp_weight2 = 0; for (int i = 0; i <= half_window_length * 2; ++i) { tmp_weight1 += waveform[i]; tmp_weight2 += window[i]; } double weighting_coefficient = tmp_weight1 / tmp_weight2; for (int i = 0; i <= half_window_length * 2; ++i) waveform[i] -= window[i] * weighting_coefficient; delete[] base_index; delete[] safe_index; delete[] window; } //----------------------------------------------------------------------------- // AddInfinitesimalNoise() //----------------------------------------------------------------------------- static void AddInfinitesimalNoise(const double *input_spectrum, int fft_size, double *output_spectrum) { for (int i = 0; i <= fft_size / 2; ++i) output_spectrum[i] = input_spectrum[i] + fabs(randn()) * world::kEps; } //----------------------------------------------------------------------------- // CheapTrickGeneralBody() calculates a spectral envelope at a temporal // position. This function is only used in CheapTrick(). // Caution: // forward_fft is allocated in advance to speed up the processing. //----------------------------------------------------------------------------- static void CheapTrickGeneralBody(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, double q1, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, double *spectral_envelope) { // F0-adaptive windowing GetWindowedWaveform(x, x_length, fs, current_f0, current_position, forward_real_fft); // Calculate power spectrum with DC correction // Note: The calculated power spectrum is stored in an array for waveform. // In this imprementation, power spectrum is transformed by FFT (NOT IFFT). // However, the same result is obtained. // This is tricky but important for simple implementation. GetPowerSpectrum(fs, current_f0, fft_size, forward_real_fft); // Smoothing of the power (linear axis) // forward_real_fft.waveform is the power spectrum. LinearSmoothing(forward_real_fft->waveform, current_f0 * 2.0 / 3.0, fs, fft_size, forward_real_fft->waveform); // Add infinitesimal noise // This is a safeguard to avoid including zero in the spectrum. AddInfinitesimalNoise(forward_real_fft->waveform, fft_size, forward_real_fft->waveform); // Smoothing (log axis) and spectral recovery on the cepstrum domain. SmoothingWithRecovery(current_f0, fs, fft_size, q1, forward_real_fft, inverse_real_fft, spectral_envelope); } } // namespace int GetFFTSizeForCheapTrick(int fs, const CheapTrickOption *option) { return static_cast(pow(2.0, 1.0 + static_cast(log(3.0 * fs / option->f0_floor + 1) / world::kLog2))); } double GetF0FloorForCheapTrick(int fs, int fft_size) { return 3.0 * fs / (fft_size - 3.0); } void CheapTrick(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, const CheapTrickOption *option, double **spectrogram) { int fft_size = option->fft_size; randn_reseed(); double f0_floor = GetF0FloorForCheapTrick(fs, fft_size); double *spectral_envelope = new double[fft_size]; ForwardRealFFT forward_real_fft = {0}; InitializeForwardRealFFT(fft_size, &forward_real_fft); InverseRealFFT inverse_real_fft = {0}; InitializeInverseRealFFT(fft_size, &inverse_real_fft); double current_f0; for (int i = 0; i < f0_length; ++i) { current_f0 = f0[i] <= f0_floor ? world::kDefaultF0 : f0[i]; CheapTrickGeneralBody(x, x_length, fs, current_f0, fft_size, temporal_positions[i], option->q1, &forward_real_fft, &inverse_real_fft, spectral_envelope); for (int j = 0; j <= fft_size / 2; ++j) spectrogram[i][j] = spectral_envelope[j]; } DestroyForwardRealFFT(&forward_real_fft); DestroyInverseRealFFT(&inverse_real_fft); delete[] spectral_envelope; } void InitializeCheapTrickOption(int fs, CheapTrickOption *option) { // q1 is the parameter used for the spectral recovery. // Since The parameter is optimized, you don't need to change the parameter. option->q1 = -0.15; // f0_floor and fs are used to determine fft_size; // We strongly recommend not to change this value unless you have enough // knowledge of the signal processing in CheapTrick. option->f0_floor = world::kFloorF0; option->fft_size = GetFFTSizeForCheapTrick(fs, option); } ================================================ FILE: libsvc/Modules/Lib/World/src/codec.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2017 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Coder/decoder functions for the spectral envelope and aperiodicity. //----------------------------------------------------------------------------- #include "world/codec.h" #include #include "world/constantnumbers.h" #include "world/fft.h" #include "world/matlabfunctions.h" namespace { //----------------------------------------------------------------------------- // Aperiodicity is initialized by the value 1.0 - world::kMySafeGuardMinimum. // This value means the frame/frequency index is aperiodic. //----------------------------------------------------------------------------- static void InitializeAperiodicity(int f0_length, int fft_size, double **aperiodicity) { for (int i = 0; i < f0_length; ++i) for (int j = 0; j < fft_size / 2 + 1; ++j) aperiodicity[i][j] = 1.0 - world::kMySafeGuardMinimum; } //----------------------------------------------------------------------------- // This function identifies whether this frame is voiced or unvoiced. //----------------------------------------------------------------------------- static int CheckVUV(const double *coarse_aperiodicity, int number_of_aperiodicities, double *tmp_aperiodicity) { double tmp = 0.0; for (int i = 0; i < number_of_aperiodicities; ++i) { tmp += coarse_aperiodicity[i]; tmp_aperiodicity[i + 1] = coarse_aperiodicity[i]; } tmp /= number_of_aperiodicities; return tmp > -0.5 ? 1 : 0; // -0.5 is not optimized, but okay. } //----------------------------------------------------------------------------- // Aperiodicity is obtained from the coded aperiodicity. //----------------------------------------------------------------------------- static void GetAperiodicity(const double *coarse_frequency_axis, const double *coarse_aperiodicity, int number_of_aperiodicities, const double *frequency_axis, int fft_size, double *aperiodicity) { interp1(coarse_frequency_axis, coarse_aperiodicity, number_of_aperiodicities + 2, frequency_axis, fft_size / 2 + 1, aperiodicity); for (int i = 0; i <= fft_size / 2; ++i) aperiodicity[i] = pow(10.0, aperiodicity[i] / 20.0); } //----------------------------------------------------------------------------- // Frequency is converted into its mel representation. //----------------------------------------------------------------------------- static inline double FrequencyToMel(double frequency) { return world::kM0 * log(frequency / world::kF0 + 1.0); } //----------------------------------------------------------------------------- // Mel is converted into frequency. //----------------------------------------------------------------------------- static inline double MelToFrequency(double mel) { return world::kF0 * (exp(mel / world::kM0) - 1.0); } //----------------------------------------------------------------------------- // DCT for spectral envelope coding //----------------------------------------------------------------------------- static void DCTForCodec(const double *mel_spectrum, int max_dimension, const fft_complex *weight, const ForwardRealFFT *forward_real_fft, int number_of_dimensions, double *mel_cepstrum) { int bias = max_dimension / 2; for (int i = 0; i < max_dimension / 2; ++i) { forward_real_fft->waveform[i] = mel_spectrum[i * 2]; forward_real_fft->waveform[i + bias] = mel_spectrum[max_dimension - (i * 2) - 1]; } fft_execute(forward_real_fft->forward_fft); double normalization = sqrt(forward_real_fft->fft_size); for (int i = 0; i < number_of_dimensions; ++i) mel_cepstrum[i] = (forward_real_fft->spectrum[i][0] * weight[i][0] - forward_real_fft->spectrum[i][1] * weight[i][1]) / normalization; } //----------------------------------------------------------------------------- // IDCT for spectral envelope decoding //----------------------------------------------------------------------------- static void IDCTForCodec(const double *mel_cepstrum, int max_dimension, const fft_complex *weight, const InverseComplexFFT *inverse_complex_fft, int number_of_dimensions, double *mel_spectrum) { double normalization = sqrt(inverse_complex_fft->fft_size); for (int i = 0; i < number_of_dimensions; ++i) { inverse_complex_fft->input[i][0] = mel_cepstrum[i] * weight[i][0] * normalization; inverse_complex_fft->input[i][1] = -mel_cepstrum[i] * weight[i][1] * normalization; } for (int i = number_of_dimensions; i < max_dimension; ++i) { inverse_complex_fft->input[i][0] = 0.0; inverse_complex_fft->input[i][1] = 0.0; } fft_execute(inverse_complex_fft->inverse_fft); for (int i = 0; i < max_dimension / 2; ++i) { mel_spectrum[i * 2] = inverse_complex_fft->output[i][0]; mel_spectrum[(i * 2) + 1] = inverse_complex_fft->output[max_dimension - i - 1][0]; } } //----------------------------------------------------------------------------- // Spectral envelope in a frame is coded //----------------------------------------------------------------------------- static void CodeOneFrame(const double *log_spectral_envelope, const double *frequency_axis, int fft_size, const double *mel_axis, const fft_complex *weight, int max_dimension, int number_of_dimensions, const ForwardRealFFT *forward_real_fft, double *coded_spectral_envelope) { double *mel_spectrum = new double[max_dimension]; interp1(frequency_axis, log_spectral_envelope, fft_size / 2 + 1, mel_axis, max_dimension, mel_spectrum); // DCT DCTForCodec(mel_spectrum, max_dimension, weight, forward_real_fft, number_of_dimensions, coded_spectral_envelope); delete[] mel_spectrum; } //----------------------------------------------------------------------------- // Coded spectral envelope in a frame is decoded //----------------------------------------------------------------------------- static void DecodeOneFrame(const double *coded_spectral_envelope, const double *frequency_axis, int fft_size, const double *mel_axis, const fft_complex *weight, int max_dimension, int number_of_dimensions, const InverseComplexFFT *inverse_complex_fft, double *spectral_envelope) { double *mel_spectrum = new double[max_dimension + 2]; // IDCT IDCTForCodec(coded_spectral_envelope, max_dimension, weight, inverse_complex_fft, number_of_dimensions, &mel_spectrum[1]); mel_spectrum[0] = mel_spectrum[1]; mel_spectrum[max_dimension + 1] = mel_spectrum[max_dimension]; interp1(mel_axis, mel_spectrum, max_dimension + 2, frequency_axis, fft_size / 2 + 1, spectral_envelope); for (int i = 0; i < fft_size / 2 + 1; ++i) spectral_envelope[i] = exp(spectral_envelope[i] / max_dimension); delete[] mel_spectrum; } //----------------------------------------------------------------------------- // GetParameters() generates the required parameters. //----------------------------------------------------------------------------- static void GetParametersForCoding(double floor_frequency, double ceil_frequency, int fs, int fft_size, double *mel_axis, double *frequency_axis, fft_complex *weight) { int max_dimension = fft_size / 2; double floor_mel = FrequencyToMel(floor_frequency); double ceil_mel = FrequencyToMel(ceil_frequency); // Generate the mel axis and the weighting vector for DCT. for (int i = 0; i < max_dimension; ++i) { mel_axis[i] = (ceil_mel - floor_mel) * i / max_dimension + floor_mel; weight[i][0] = 2.0 * cos(i * world::kPi / fft_size) / sqrt(fft_size); weight[i][1] = 2.0 * sin(i * world::kPi / fft_size) / sqrt(fft_size); } weight[0][0] /= sqrt(2.0); // Generate the frequency axis on mel scale for (int i = 0; i <= max_dimension; ++i) frequency_axis[i] = FrequencyToMel(static_cast(i) * fs / fft_size); } //----------------------------------------------------------------------------- // GetParameters() generates the required parameters. //----------------------------------------------------------------------------- static void GetParametersForDecoding(double floor_frequency, double ceil_frequency, int fs, int fft_size, int number_of_dimensions, double *mel_axis, double *frequency_axis, fft_complex *weight) { int max_dimension = fft_size / 2; double floor_mel = FrequencyToMel(floor_frequency); double ceil_mel = FrequencyToMel(ceil_frequency); // Generate the weighting vector for IDCT. for (int i = 0; i < number_of_dimensions; ++i) { weight[i][0] = cos(i * world::kPi / fft_size) * sqrt(fft_size); weight[i][1] = sin(i * world::kPi / fft_size) * sqrt(fft_size); } weight[0][0] /= sqrt(2.0); // Generate the mel axis for IDCT. for (int i = 0; i < max_dimension; ++i) mel_axis[i + 1] = MelToFrequency((ceil_mel - floor_mel) * i / max_dimension + floor_mel); mel_axis[0] = 0; mel_axis[max_dimension + 1] = fs / 2.0; // Generate the frequency axis for (int i = 0; i < fft_size / 2 + 1; ++i) frequency_axis[i] = static_cast(i) * fs / fft_size; } } // namespace int GetNumberOfAperiodicities(int fs) { return static_cast(MyMinDouble(world::kUpperLimit, fs / 2.0 - world::kFrequencyInterval) / world::kFrequencyInterval); } void CodeAperiodicity(const double * const *aperiodicity, int f0_length, int fs, int fft_size, double **coded_aperiodicity) { int number_of_aperiodicities = GetNumberOfAperiodicities(fs); double *coarse_frequency_axis = new double[number_of_aperiodicities]; for (int i = 0; i < number_of_aperiodicities; ++i) coarse_frequency_axis[i] = world::kFrequencyInterval * (i + 1.0); double *log_aperiodicity = new double[fft_size / 2 + 1]; for (int i = 0; i < f0_length; ++i) { for (int j = 0; j < fft_size / 2 + 1; ++j) log_aperiodicity[j] = 20 * log10(aperiodicity[i][j]); interp1Q(0, static_cast(fs) / fft_size, log_aperiodicity, fft_size / 2 + 1, coarse_frequency_axis, number_of_aperiodicities, coded_aperiodicity[i]); } delete[] coarse_frequency_axis; delete[] log_aperiodicity; } void DecodeAperiodicity(const double * const *coded_aperiodicity, int f0_length, int fs, int fft_size, double **aperiodicity) { InitializeAperiodicity(f0_length, fft_size, aperiodicity); int number_of_aperiodicities = GetNumberOfAperiodicities(fs); double *frequency_axis = new double[fft_size / 2 + 1]; for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] = static_cast(fs) / fft_size * i; double *coarse_frequency_axis = new double[number_of_aperiodicities + 2]; for (int i = 0; i <= number_of_aperiodicities; ++i) coarse_frequency_axis[i] = i * world::kFrequencyInterval; coarse_frequency_axis[number_of_aperiodicities + 1] = fs / 2.0; double *coarse_aperiodicity = new double[number_of_aperiodicities + 2]; coarse_aperiodicity[0] = -60.0; coarse_aperiodicity[number_of_aperiodicities + 1] = -world::kMySafeGuardMinimum; for (int i = 0; i < f0_length; ++i) { if (CheckVUV(coded_aperiodicity[i], number_of_aperiodicities, coarse_aperiodicity) == 1) continue; GetAperiodicity(coarse_frequency_axis, coarse_aperiodicity, number_of_aperiodicities, frequency_axis, fft_size, aperiodicity[i]); } delete[] coarse_aperiodicity; delete[] coarse_frequency_axis; delete[] frequency_axis; } void CodeSpectralEnvelope(const double * const *spectrogram, int f0_length, int fs, int fft_size, int number_of_dimensions, double **coded_spectral_envelope) { double *mel_axis = new double[fft_size / 2]; double *frequency_axis = new double[fft_size / 2 + 1]; double *tmp_spectrum = new double[fft_size / 2 + 1]; fft_complex *weight = new fft_complex[fft_size / 2]; // Generation of the required parameters GetParametersForCoding(world::kFloorFrequency, MyMinDouble(fs / 2.0, world::kCeilFrequency), fs, fft_size, mel_axis, frequency_axis, weight); ForwardRealFFT forward_real_fft = { 0 }; InitializeForwardRealFFT(fft_size / 2, &forward_real_fft); for (int i = 0; i < f0_length; ++i) { for (int j = 0; j < fft_size / 2 + 1; ++j) tmp_spectrum[j] = log(spectrogram[i][j]); CodeOneFrame(tmp_spectrum, frequency_axis, fft_size, mel_axis, weight, fft_size / 2, number_of_dimensions, &forward_real_fft, coded_spectral_envelope[i]); } DestroyForwardRealFFT(&forward_real_fft); delete[] weight; delete[] tmp_spectrum; delete[] frequency_axis; delete[] mel_axis; } void DecodeSpectralEnvelope(const double * const *coded_spectral_envelope, int f0_length, int fs, int fft_size, int number_of_dimensions, double **spectrogram) { double *mel_axis = new double[fft_size / 2 + 2]; double *frequency_axis = new double[fft_size / 2 + 1]; fft_complex *weight = new fft_complex[fft_size / 2]; // Generation of the required parameters GetParametersForDecoding(world::kFloorFrequency, MyMinDouble(fs / 2.0, world::kCeilFrequency), fs, fft_size, number_of_dimensions, mel_axis, frequency_axis, weight); InverseComplexFFT inverse_complex_fft = { 0 }; InitializeInverseComplexFFT(fft_size / 2, &inverse_complex_fft); for (int i = 0; i < f0_length; ++i) { DecodeOneFrame(coded_spectral_envelope[i], frequency_axis, fft_size, mel_axis, weight, fft_size / 2, number_of_dimensions, &inverse_complex_fft, spectrogram[i]); } DestroyInverseComplexFFT(&inverse_complex_fft); delete[] weight; delete[] frequency_axis; delete[] mel_axis; } ================================================ FILE: libsvc/Modules/Lib/World/src/common.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // common.cpp includes functions used in at least two files. // (1) Common functions // (2) FFT, IFFT and minimum phase analysis. // // In FFT analysis and minimum phase analysis, // Functions "Initialize*()" allocate the mamory. // Functions "Destroy*()" free the accolated memory. // FFT size is used for initialization, and structs are used to keep the memory. // Functions "GetMinimumPhaseSpectrum()" calculate minimum phase spectrum. // Forward and inverse FFT do not have the function "Get*()", // because forward FFT and inverse FFT can run in one step. // //----------------------------------------------------------------------------- #include "world/common.h" #include #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { static void SetParametersForLinearSmoothing(int boundary, int fft_size, int fs, double width, const double *power_spectrum, double *mirroring_spectrum, double *mirroring_segment, double *frequency_axis) { for (int i = 0; i < boundary; ++i) mirroring_spectrum[i] = power_spectrum[boundary - i]; for (int i = boundary; i < fft_size / 2 + boundary; ++i) mirroring_spectrum[i] = power_spectrum[i - boundary]; for (int i = fft_size / 2 + boundary; i <= fft_size / 2 + boundary * 2; ++i) mirroring_spectrum[i] = power_spectrum[fft_size / 2 - (i - (fft_size / 2 + boundary))]; mirroring_segment[0] = mirroring_spectrum[0] * fs / fft_size; for (int i = 1; i < fft_size / 2 + boundary * 2 + 1; ++i) mirroring_segment[i] = mirroring_spectrum[i] * fs / fft_size + mirroring_segment[i - 1]; for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] = static_cast(i) / fft_size * fs - width / 2.0; } } // namespace //----------------------------------------------------------------------------- int GetSuitableFFTSize(int sample) { return static_cast(pow(2.0, static_cast(log(static_cast(sample)) / world::kLog2) + 1.0)); } void DCCorrection(const double *input, double f0, int fs, int fft_size, double *output) { int upper_limit = 2 + static_cast(f0 * fft_size / fs); double *low_frequency_replica = new double[upper_limit]; double *low_frequency_axis = new double[upper_limit]; for (int i = 0; i < upper_limit; ++i) low_frequency_axis[i] = static_cast(i) * fs / fft_size; int upper_limit_replica = upper_limit - 1; interp1Q(f0 - low_frequency_axis[0], -static_cast(fs) / fft_size, input, upper_limit + 1, low_frequency_axis, upper_limit_replica, low_frequency_replica); for (int i = 0; i < upper_limit_replica; ++i) output[i] = input[i] + low_frequency_replica[i]; delete[] low_frequency_replica; delete[] low_frequency_axis; } void LinearSmoothing(const double *input, double width, int fs, int fft_size, double *output) { int boundary = static_cast(width * fft_size / fs) + 1; // These parameters are set by the other function. double *mirroring_spectrum = new double[fft_size / 2 + boundary * 2 + 1]; double *mirroring_segment = new double[fft_size / 2 + boundary * 2 + 1]; double *frequency_axis = new double[fft_size / 2 + 1]; SetParametersForLinearSmoothing(boundary, fft_size, fs, width, input, mirroring_spectrum, mirroring_segment, frequency_axis); double *low_levels = new double[fft_size / 2 + 1]; double *high_levels = new double[fft_size / 2 + 1]; double origin_of_mirroring_axis = -(boundary - 0.5) * fs / fft_size; double discrete_frequency_interval = static_cast(fs) / fft_size; interp1Q(origin_of_mirroring_axis, discrete_frequency_interval, mirroring_segment, fft_size / 2 + boundary * 2 + 1, frequency_axis, fft_size / 2 + 1, low_levels); for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] += width; interp1Q(origin_of_mirroring_axis, discrete_frequency_interval, mirroring_segment, fft_size / 2 + boundary * 2 + 1, frequency_axis, fft_size / 2 + 1, high_levels); for (int i = 0; i <= fft_size / 2; ++i) output[i] = (high_levels[i] - low_levels[i]) / width; delete[] mirroring_spectrum; delete[] mirroring_segment; delete[] frequency_axis; delete[] low_levels; delete[] high_levels; } void NuttallWindow(int y_length, double *y) { double tmp; for (int i = 0; i < y_length; ++i) { tmp = i / (y_length - 1.0); y[i] = 0.355768 - 0.487396 * cos(2.0 * world::kPi * tmp) + 0.144232 * cos(4.0 * world::kPi * tmp) - 0.012604 * cos(6.0 * world::kPi * tmp); } } //----------------------------------------------------------------------------- // FFT, IFFT and minimum phase analysis void InitializeForwardRealFFT(int fft_size, ForwardRealFFT *forward_real_fft) { forward_real_fft->fft_size = fft_size; forward_real_fft->waveform = new double[fft_size]; forward_real_fft->spectrum = new fft_complex[fft_size]; forward_real_fft->forward_fft = fft_plan_dft_r2c_1d(fft_size, forward_real_fft->waveform, forward_real_fft->spectrum, FFT_ESTIMATE); } void DestroyForwardRealFFT(ForwardRealFFT *forward_real_fft) { fft_destroy_plan(forward_real_fft->forward_fft); delete[] forward_real_fft->spectrum; delete[] forward_real_fft->waveform; } void InitializeInverseRealFFT(int fft_size, InverseRealFFT *inverse_real_fft) { inverse_real_fft->fft_size = fft_size; inverse_real_fft->waveform = new double[fft_size]; inverse_real_fft->spectrum = new fft_complex[fft_size]; inverse_real_fft->inverse_fft = fft_plan_dft_c2r_1d(fft_size, inverse_real_fft->spectrum, inverse_real_fft->waveform, FFT_ESTIMATE); } void DestroyInverseRealFFT(InverseRealFFT *inverse_real_fft) { fft_destroy_plan(inverse_real_fft->inverse_fft); delete[] inverse_real_fft->spectrum; delete[] inverse_real_fft->waveform; } void InitializeInverseComplexFFT(int fft_size, InverseComplexFFT *inverse_complex_fft) { inverse_complex_fft->fft_size = fft_size; inverse_complex_fft->input = new fft_complex[fft_size]; inverse_complex_fft->output = new fft_complex[fft_size]; inverse_complex_fft->inverse_fft = fft_plan_dft_1d(fft_size, inverse_complex_fft->input, inverse_complex_fft->output, FFT_BACKWARD, FFT_ESTIMATE); } void DestroyInverseComplexFFT(InverseComplexFFT *inverse_complex_fft) { fft_destroy_plan(inverse_complex_fft->inverse_fft); delete[] inverse_complex_fft->input; delete[] inverse_complex_fft->output; } void InitializeMinimumPhaseAnalysis(int fft_size, MinimumPhaseAnalysis *minimum_phase) { minimum_phase->fft_size = fft_size; minimum_phase->log_spectrum = new double[fft_size]; minimum_phase->minimum_phase_spectrum = new fft_complex[fft_size]; minimum_phase->cepstrum = new fft_complex[fft_size]; minimum_phase->inverse_fft = fft_plan_dft_r2c_1d(fft_size, minimum_phase->log_spectrum, minimum_phase->cepstrum, FFT_ESTIMATE); minimum_phase->forward_fft = fft_plan_dft_1d(fft_size, minimum_phase->cepstrum, minimum_phase->minimum_phase_spectrum, FFT_FORWARD, FFT_ESTIMATE); } void GetMinimumPhaseSpectrum(const MinimumPhaseAnalysis *minimum_phase) { // Mirroring for (int i = minimum_phase->fft_size / 2 + 1; i < minimum_phase->fft_size; ++i) minimum_phase->log_spectrum[i] = minimum_phase->log_spectrum[minimum_phase->fft_size - i]; // This fft_plan carries out "forward" FFT. // To carriy out the Inverse FFT, the sign of imaginary part // is inverted after FFT. fft_execute(minimum_phase->inverse_fft); minimum_phase->cepstrum[0][1] *= -1.0; for (int i = 1; i < minimum_phase->fft_size / 2; ++i) { minimum_phase->cepstrum[i][0] *= 2.0; minimum_phase->cepstrum[i][1] *= -2.0; } minimum_phase->cepstrum[minimum_phase->fft_size / 2][1] *= -1.0; for (int i = minimum_phase->fft_size / 2 + 1; i < minimum_phase->fft_size; ++i) { minimum_phase->cepstrum[i][0] = 0.0; minimum_phase->cepstrum[i][1] = 0.0; } fft_execute(minimum_phase->forward_fft); // Since x is complex number, calculation of exp(x) is as following. // Note: This FFT library does not keep the aliasing. double tmp; for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) { tmp = exp(minimum_phase->minimum_phase_spectrum[i][0] / minimum_phase->fft_size); minimum_phase->minimum_phase_spectrum[i][0] = tmp * cos(minimum_phase->minimum_phase_spectrum[i][1] / minimum_phase->fft_size); minimum_phase->minimum_phase_spectrum[i][1] = tmp * sin(minimum_phase->minimum_phase_spectrum[i][1] / minimum_phase->fft_size); } } void DestroyMinimumPhaseAnalysis(MinimumPhaseAnalysis *minimum_phase) { fft_destroy_plan(minimum_phase->forward_fft); fft_destroy_plan(minimum_phase->inverse_fft); delete[] minimum_phase->cepstrum; delete[] minimum_phase->log_spectrum; delete[] minimum_phase->minimum_phase_spectrum; } ================================================ FILE: libsvc/Modules/Lib/World/src/d4c.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Band-aperiodicity estimation on the basis of the idea of D4C. //----------------------------------------------------------------------------- #include "world/d4c.h" #include #include // for std::sort() #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { //----------------------------------------------------------------------------- // SetParametersForGetWindowedWaveform() //----------------------------------------------------------------------------- static void SetParametersForGetWindowedWaveform(int half_window_length, int x_length, double current_position, int fs, double current_f0, int window_type, double window_length_ratio, int *base_index, int *safe_index, double *window) { for (int i = -half_window_length; i <= half_window_length; ++i) base_index[i + half_window_length] = i; int origin = matlab_round(current_position * fs + 0.001); for (int i = 0; i <= half_window_length * 2; ++i) safe_index[i] = MyMinInt(x_length - 1, MyMaxInt(0, origin + base_index[i])); // Designing of the window function double position; if (window_type == world::kHanning) { // Hanning window for (int i = 0; i <= half_window_length * 2; ++i) { position = (2.0 * base_index[i] / window_length_ratio) / fs; window[i] = 0.5 * cos(world::kPi * position * current_f0) + 0.5; } } else { // Blackman window for (int i = 0; i <= half_window_length * 2; ++i) { position = (2.0 * base_index[i] / window_length_ratio) / fs; window[i] = 0.42 + 0.5 * cos(world::kPi * position * current_f0) + 0.08 * cos(world::kPi * position * current_f0 * 2); } } } //----------------------------------------------------------------------------- // GetWindowedWaveform() windows the waveform by F0-adaptive window // In the variable window_type, 1: hanning, 2: blackman //----------------------------------------------------------------------------- static void GetWindowedWaveform(const double *x, int x_length, int fs, double current_f0, double current_position, int window_type, double window_length_ratio, double *waveform) { int half_window_length = matlab_round(window_length_ratio * fs / current_f0 / 2.0); int *base_index = new int[half_window_length * 2 + 1]; int *safe_index = new int[half_window_length * 2 + 1]; double *window = new double[half_window_length * 2 + 1]; SetParametersForGetWindowedWaveform(half_window_length, x_length, current_position, fs, current_f0, window_type, window_length_ratio, base_index, safe_index, window); // F0-adaptive windowing for (int i = 0; i <= half_window_length * 2; ++i) waveform[i] = x[safe_index[i]] * window[i] + randn() * world::kMySafeGuardMinimum; double tmp_weight1 = 0; double tmp_weight2 = 0; for (int i = 0; i <= half_window_length * 2; ++i) { tmp_weight1 += waveform[i]; tmp_weight2 += window[i]; } double weighting_coefficient = tmp_weight1 / tmp_weight2; for (int i = 0; i <= half_window_length * 2; ++i) waveform[i] -= window[i] * weighting_coefficient; delete[] base_index; delete[] safe_index; delete[] window; } //----------------------------------------------------------------------------- // GetCentroid() calculates the energy centroid (see the book, time-frequency // analysis written by L. Cohen). //----------------------------------------------------------------------------- static void GetCentroid(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, const ForwardRealFFT *forward_real_fft, double *centroid) { for (int i = 0; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; GetWindowedWaveform(x, x_length, fs, current_f0, current_position, world::kBlackman, 4.0, forward_real_fft->waveform); double power = 0.0; for (int i = 0; i <= matlab_round(2.0 * fs / current_f0) * 2; ++i) power += forward_real_fft->waveform[i] * forward_real_fft->waveform[i]; for (int i = 0; i <= matlab_round(2.0 * fs / current_f0) * 2; ++i) forward_real_fft->waveform[i] /= sqrt(power); fft_execute(forward_real_fft->forward_fft); double *tmp_real = new double[fft_size / 2 + 1]; double *tmp_imag = new double[fft_size / 2 + 1]; for (int i = 0; i <= fft_size / 2; ++i) { tmp_real[i] = forward_real_fft->spectrum[i][0]; tmp_imag[i] = forward_real_fft->spectrum[i][1]; } for (int i = 0; i < fft_size; ++i) forward_real_fft->waveform[i] *= i + 1.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) centroid[i] = forward_real_fft->spectrum[i][0] * tmp_real[i] + tmp_imag[i] * forward_real_fft->spectrum[i][1]; delete[] tmp_real; delete[] tmp_imag; } //----------------------------------------------------------------------------- // GetStaticCentroid() calculates the temporally static energy centroid. // Basic idea was proposed by H. Kawahara. //----------------------------------------------------------------------------- static void GetStaticCentroid(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, const ForwardRealFFT *forward_real_fft, double *static_centroid) { double *centroid1 = new double[fft_size / 2 + 1]; double *centroid2 = new double[fft_size / 2 + 1]; GetCentroid(x, x_length, fs, current_f0, fft_size, current_position - 0.25 / current_f0, forward_real_fft, centroid1); GetCentroid(x, x_length, fs, current_f0, fft_size, current_position + 0.25 / current_f0, forward_real_fft, centroid2); for (int i = 0; i <= fft_size / 2; ++i) static_centroid[i] = centroid1[i] + centroid2[i]; DCCorrection(static_centroid, current_f0, fs, fft_size, static_centroid); delete[] centroid1; delete[] centroid2; } //----------------------------------------------------------------------------- // GetSmoothedPowerSpectrum() calculates the smoothed power spectrum. // The parameters used for smoothing are optimized in davance. //----------------------------------------------------------------------------- static void GetSmoothedPowerSpectrum(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, const ForwardRealFFT *forward_real_fft, double *smoothed_power_spectrum) { for (int i = 0; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; GetWindowedWaveform(x, x_length, fs, current_f0, current_position, world::kHanning, 4.0, forward_real_fft->waveform); fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) smoothed_power_spectrum[i] = forward_real_fft->spectrum[i][0] * forward_real_fft->spectrum[i][0] + forward_real_fft->spectrum[i][1] * forward_real_fft->spectrum[i][1]; DCCorrection(smoothed_power_spectrum, current_f0, fs, fft_size, smoothed_power_spectrum); LinearSmoothing(smoothed_power_spectrum, current_f0, fs, fft_size, smoothed_power_spectrum); } //----------------------------------------------------------------------------- // GetStaticGroupDelay() calculates the temporally static group delay. // This is the fundamental parameter in D4C. //----------------------------------------------------------------------------- static void GetStaticGroupDelay(const double *static_centroid, const double *smoothed_power_spectrum, int fs, double f0, int fft_size, double *static_group_delay) { for (int i = 0; i <= fft_size / 2; ++i) static_group_delay[i] = static_centroid[i] / smoothed_power_spectrum[i]; LinearSmoothing(static_group_delay, f0 / 2.0, fs, fft_size, static_group_delay); double *smoothed_group_delay = new double[fft_size / 2 + 1]; LinearSmoothing(static_group_delay, f0, fs, fft_size, smoothed_group_delay); for (int i = 0; i <= fft_size / 2; ++i) static_group_delay[i] -= smoothed_group_delay[i]; delete[] smoothed_group_delay; } //----------------------------------------------------------------------------- // GetCoarseAperiodicity() calculates the aperiodicity in multiples of 3 kHz. // The upper limit is given based on the sampling frequency. //----------------------------------------------------------------------------- static void GetCoarseAperiodicity(const double *static_group_delay, int fs, int fft_size, int number_of_aperiodicities, const double *window, int window_length, const ForwardRealFFT *forward_real_fft, double *coarse_aperiodicity) { int boundary = matlab_round(fft_size * 8.0 / window_length); int half_window_length = window_length / 2; for (int i = 0; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; double *power_spectrum = new double[fft_size / 2 + 1]; int center; for (int i = 0; i < number_of_aperiodicities; ++i) { center = static_cast(world::kFrequencyInterval * (i + 1) * fft_size / fs); for (int j = 0; j <= half_window_length * 2; ++j) forward_real_fft->waveform[j] = static_group_delay[center - half_window_length + j] * window[j]; fft_execute(forward_real_fft->forward_fft); for (int j = 0 ; j <= fft_size / 2; ++j) power_spectrum[j] = forward_real_fft->spectrum[j][0] * forward_real_fft->spectrum[j][0] + forward_real_fft->spectrum[j][1] * forward_real_fft->spectrum[j][1]; std::sort(power_spectrum, power_spectrum + fft_size / 2 + 1); for (int j = 1 ; j <= fft_size / 2; ++j) power_spectrum[j] += power_spectrum[j - 1]; coarse_aperiodicity[i] = 10 * log10(power_spectrum[fft_size / 2 - boundary - 1] / power_spectrum[fft_size / 2]); } delete[] power_spectrum; } static double D4CLoveTrainSub(const double *x, int fs, int x_length, double current_f0, double current_position, int f0_length, int fft_size, int boundary0, int boundary1, int boundary2, ForwardRealFFT *forward_real_fft) { double *power_spectrum = new double[fft_size]; int window_length = matlab_round(1.5 * fs / current_f0) * 2 + 1; GetWindowedWaveform(x, x_length, fs, current_f0, current_position, world::kBlackman, 3.0, forward_real_fft->waveform); for (int i = window_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= boundary0; ++i) power_spectrum[i] = 0.0; for (int i = boundary0 + 1; i < fft_size / 2 + 1; ++i) power_spectrum[i] = forward_real_fft->spectrum[i][0] * forward_real_fft->spectrum[i][0] + forward_real_fft->spectrum[i][1] * forward_real_fft->spectrum[i][1]; for (int i = boundary0; i <= boundary2; ++i) power_spectrum[i] += +power_spectrum[i - 1]; double aperiodicity0 = power_spectrum[boundary1] / power_spectrum[boundary2]; delete[] power_spectrum; return aperiodicity0; } //----------------------------------------------------------------------------- // D4CLoveTrain() determines the aperiodicity with VUV detection. // If a frame was determined as the unvoiced section, aperiodicity is set to // very high value as the safeguard. // If it was voiced section, the aperiodicity of 0 Hz is set to -60 dB. //----------------------------------------------------------------------------- static void D4CLoveTrain(const double *x, int fs, int x_length, const double *f0, int f0_length, const double *temporal_positions, double *aperiodicity0) { double lowest_f0 = 40.0; int fft_size = static_cast(pow(2.0, 1.0 + static_cast(log(3.0 * fs / lowest_f0 + 1) / world::kLog2))); ForwardRealFFT forward_real_fft = { 0 }; InitializeForwardRealFFT(fft_size, &forward_real_fft); // Cumulative powers at 100, 4000, 7900 Hz are used for VUV identification. int boundary0 = static_cast(ceil(100.0 * fft_size / fs)); int boundary1 = static_cast(ceil(4000.0 * fft_size / fs)); int boundary2 = static_cast(ceil(7900.0 * fft_size / fs)); for (int i = 0; i < f0_length; ++i) { if (f0[i] == 0.0) { aperiodicity0[i] = 0.0; continue; } aperiodicity0[i] = D4CLoveTrainSub(x, fs, x_length, MyMaxDouble(f0[i], lowest_f0), temporal_positions[i], f0_length, fft_size, boundary0, boundary1, boundary2, &forward_real_fft); } DestroyForwardRealFFT(&forward_real_fft); } //----------------------------------------------------------------------------- // D4CGeneralBody() calculates a spectral envelope at a temporal // position. This function is only used in D4C(). // Caution: // forward_fft is allocated in advance to speed up the processing. //----------------------------------------------------------------------------- static void D4CGeneralBody(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, int number_of_aperiodicities, const double *window, int window_length, const ForwardRealFFT *forward_real_fft, double *coarse_aperiodicity) { double *static_centroid = new double[fft_size / 2 + 1]; double *smoothed_power_spectrum = new double[fft_size / 2 + 1]; double *static_group_delay = new double[fft_size / 2 + 1]; GetStaticCentroid(x, x_length, fs, current_f0, fft_size, current_position, forward_real_fft, static_centroid); GetSmoothedPowerSpectrum(x, x_length, fs, current_f0, fft_size, current_position, forward_real_fft, smoothed_power_spectrum); GetStaticGroupDelay(static_centroid, smoothed_power_spectrum, fs, current_f0, fft_size, static_group_delay); GetCoarseAperiodicity(static_group_delay, fs, fft_size, number_of_aperiodicities, window, window_length, forward_real_fft, coarse_aperiodicity); // Revision of the result based on the F0 for (int i = 0; i < number_of_aperiodicities; ++i) coarse_aperiodicity[i] = MyMinDouble(0.0, coarse_aperiodicity[i] + (current_f0 - 100) / 50.0); delete[] static_centroid; delete[] smoothed_power_spectrum; delete[] static_group_delay; } static void InitializeAperiodicity(int f0_length, int fft_size, double **aperiodicity) { for (int i = 0; i < f0_length; ++i) for (int j = 0; j < fft_size / 2 + 1; ++j) aperiodicity[i][j] = 1.0 - world::kMySafeGuardMinimum; } static void GetAperiodicity(const double *coarse_frequency_axis, const double *coarse_aperiodicity, int number_of_aperiodicities, const double *frequency_axis, int fft_size, double *aperiodicity) { interp1(coarse_frequency_axis, coarse_aperiodicity, number_of_aperiodicities + 2, frequency_axis, fft_size / 2 + 1, aperiodicity); for (int i = 0; i <= fft_size / 2; ++i) aperiodicity[i] = pow(10.0, aperiodicity[i] / 20.0); } } // namespace void D4C(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, int fft_size, const D4COption *option, double **aperiodicity) { randn_reseed(); InitializeAperiodicity(f0_length, fft_size, aperiodicity); int fft_size_d4c = static_cast(pow(2.0, 1.0 + static_cast(log(4.0 * fs / world::kFloorF0D4C + 1) / world::kLog2))); ForwardRealFFT forward_real_fft = {0}; InitializeForwardRealFFT(fft_size_d4c, &forward_real_fft); int number_of_aperiodicities = static_cast(MyMinDouble(world::kUpperLimit, fs / 2.0 - world::kFrequencyInterval) / world::kFrequencyInterval); // Since the window function is common in D4CGeneralBody(), // it is designed here to speed up. int window_length = static_cast(world::kFrequencyInterval * fft_size_d4c / fs) * 2 + 1; double *window = new double[window_length]; NuttallWindow(window_length, window); // D4C Love Train (Aperiodicity of 0 Hz is given by the different algorithm) double *aperiodicity0 = new double[f0_length]; D4CLoveTrain(x, fs, x_length, f0, f0_length, temporal_positions, aperiodicity0); double *coarse_aperiodicity = new double[number_of_aperiodicities + 2]; coarse_aperiodicity[0] = -60.0; coarse_aperiodicity[number_of_aperiodicities + 1] = -world::kMySafeGuardMinimum; double *coarse_frequency_axis = new double[number_of_aperiodicities + 2]; for (int i = 0; i <= number_of_aperiodicities; ++i) coarse_frequency_axis[i] = i * world::kFrequencyInterval; coarse_frequency_axis[number_of_aperiodicities + 1] = fs / 2.0; double *frequency_axis = new double[fft_size / 2 + 1]; for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] = static_cast(i) * fs / fft_size; for (int i = 0; i < f0_length; ++i) { if (f0[i] == 0 || aperiodicity0[i] <= option->threshold) continue; D4CGeneralBody(x, x_length, fs, MyMaxDouble(world::kFloorF0D4C, f0[i]), fft_size_d4c, temporal_positions[i], number_of_aperiodicities, window, window_length, &forward_real_fft, &coarse_aperiodicity[1]); // Linear interpolation to convert the coarse aperiodicity into its // spectral representation. GetAperiodicity(coarse_frequency_axis, coarse_aperiodicity, number_of_aperiodicities, frequency_axis, fft_size, aperiodicity[i]); } DestroyForwardRealFFT(&forward_real_fft); delete[] aperiodicity0; delete[] coarse_frequency_axis; delete[] coarse_aperiodicity; delete[] window; delete[] frequency_axis; } void InitializeD4COption(D4COption *option) { option->threshold = world::kThreshold; } ================================================ FILE: libsvc/Modules/Lib/World/src/dio.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // F0 estimation based on DIO (Distributed Inline-filter Operation). //----------------------------------------------------------------------------- #include "world/dio.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" //----------------------------------------------------------------------------- // struct for GetFourZeroCrossingIntervals() // "negative" means "zero-crossing point going from positive to negative" // "positive" means "zero-crossing point going from negative to positive" //----------------------------------------------------------------------------- typedef struct { double *negative_interval_locations; double *negative_intervals; int number_of_negatives; double *positive_interval_locations; double *positive_intervals; int number_of_positives; double *peak_interval_locations; double *peak_intervals; int number_of_peaks; double *dip_interval_locations; double *dip_intervals; int number_of_dips; } ZeroCrossings; namespace { //----------------------------------------------------------------------------- // DesignLowCutFilter() calculates the coefficients the filter. //----------------------------------------------------------------------------- static void DesignLowCutFilter(int N, int fft_size, double *low_cut_filter) { for (int i = 1; i <= N; ++i) low_cut_filter[i - 1] = 0.5 - 0.5 * cos(i * 2.0 * world::kPi / (N + 1)); for (int i = N; i < fft_size; ++i) low_cut_filter[i] = 0.0; double sum_of_amplitude = 0.0; for (int i = 0; i < N; ++i) sum_of_amplitude += low_cut_filter[i]; for (int i = 0; i < N; ++i) low_cut_filter[i] = -low_cut_filter[i] / sum_of_amplitude; for (int i = 0; i < (N - 1) / 2; ++i) low_cut_filter[fft_size - (N - 1) / 2 + i] = low_cut_filter[i]; for (int i = 0; i < N; ++i) low_cut_filter[i] = low_cut_filter[i + (N - 1) / 2]; low_cut_filter[0] += 1.0; } //----------------------------------------------------------------------------- // GetSpectrumForEstimation() calculates the spectrum for estimation. // This function carries out downsampling to speed up the estimation process // and calculates the spectrum of the downsampled signal. //----------------------------------------------------------------------------- static void GetSpectrumForEstimation(const double *x, int x_length, int y_length, double actual_fs, int fft_size, int decimation_ratio, fft_complex *y_spectrum) { double *y = new double[fft_size]; // Initialization for (int i = 0; i < fft_size; ++i) y[i] = 0.0; // Downsampling if (decimation_ratio != 1) decimate(x, x_length, decimation_ratio, y); else for (int i = 0; i < x_length; ++i) y[i] = x[i]; // Removal of the DC component (y = y - mean value of y) double mean_y = 0.0; for (int i = 0; i < y_length; ++i) mean_y += y[i]; mean_y /= y_length; for (int i = 0; i < y_length; ++i) y[i] -= mean_y; for (int i = y_length; i < fft_size; ++i) y[i] = 0.0; fft_plan forwardFFT = fft_plan_dft_r2c_1d(fft_size, y, y_spectrum, FFT_ESTIMATE); fft_execute(forwardFFT); // Low cut filtering (from 0.1.4). Cut off frequency is 50.0 Hz. int cutoff_in_sample = matlab_round(actual_fs / world::kCutOff); DesignLowCutFilter(cutoff_in_sample * 2 + 1, fft_size, y); fft_complex *filter_spectrum = new fft_complex[fft_size]; forwardFFT.c_out = filter_spectrum; fft_execute(forwardFFT); double tmp = 0; for (int i = 0; i <= fft_size / 2; ++i) { // Complex number multiplications. tmp = y_spectrum[i][0] * filter_spectrum[i][0] - y_spectrum[i][1] * filter_spectrum[i][1]; y_spectrum[i][1] = y_spectrum[i][0] * filter_spectrum[i][1] + y_spectrum[i][1] * filter_spectrum[i][0]; y_spectrum[i][0] = tmp; } fft_destroy_plan(forwardFFT); delete[] y; delete[] filter_spectrum; } //----------------------------------------------------------------------------- // GetBestF0Contour() calculates the best f0 contour based on scores of // all candidates. The F0 with highest score is selected. //----------------------------------------------------------------------------- static void GetBestF0Contour(int f0_length, const double * const * f0_candidates, const double * const * f0_scores, int number_of_bands, double *best_f0_contour) { double tmp; for (int i = 0; i < f0_length; ++i) { tmp = f0_scores[0][i]; best_f0_contour[i] = f0_candidates[0][i]; for (int j = 1; j < number_of_bands; ++j) { if (tmp > f0_scores[j][i]) { tmp = f0_scores[j][i]; best_f0_contour[i] = f0_candidates[j][i]; } } } } //----------------------------------------------------------------------------- // FixStep1() is the 1st step of the postprocessing. // This function eliminates the unnatural change of f0 based on allowed_range. //----------------------------------------------------------------------------- static void FixStep1(const double *best_f0_contour, int f0_length, int voice_range_minimum, double allowed_range, double *f0_step1) { double *f0_base = new double[f0_length]; // Initialization for (int i = 0; i < voice_range_minimum; ++i) f0_base[i] = 0.0; for (int i = voice_range_minimum; i < f0_length - voice_range_minimum; ++i) f0_base[i] = best_f0_contour[i]; for (int i = f0_length - voice_range_minimum; i < f0_length; ++i) f0_base[i] = 0.0; // Processing to prevent the jumping of f0 for (int i = 0; i < voice_range_minimum; ++i) f0_step1[i] = 0.0; for (int i = voice_range_minimum; i < f0_length; ++i) f0_step1[i] = fabs((f0_base[i] - f0_base[i - 1]) / (world::kMySafeGuardMinimum + f0_base[i])) < allowed_range ? f0_base[i] : 0.0; delete[] f0_base; } //----------------------------------------------------------------------------- // FixStep2() is the 2nd step of the postprocessing. // This function eliminates the suspected f0 in the anlaut and auslaut. //----------------------------------------------------------------------------- static void FixStep2(const double *f0_step1, int f0_length, int voice_range_minimum, double *f0_step2) { for (int i = 0; i < f0_length; ++i) f0_step2[i] = f0_step1[i]; int center = (voice_range_minimum - 1) / 2; for (int i = center; i < f0_length - center; ++i) { for (int j = -center; j <= center; ++j) { if (f0_step1[i + j] == 0) { f0_step2[i] = 0.0; break; } } } } //----------------------------------------------------------------------------- // GetNumberOfVoicedSections() counts the number of voiced sections. //----------------------------------------------------------------------------- static void GetNumberOfVoicedSections(const double *f0, int f0_length, int *positive_index, int *negative_index, int *positive_count, int *negative_count) { *positive_count = *negative_count = 0; for (int i = 1; i < f0_length; ++i) if (f0[i] == 0 && f0[i - 1] != 0) negative_index[(*negative_count)++] = i - 1; else if (f0[i - 1] == 0 && f0[i] != 0) positive_index[(*positive_count)++] = i; } //----------------------------------------------------------------------------- // SelectOneF0() corrects the f0[current_index] based on // f0[current_index + sign]. //----------------------------------------------------------------------------- static double SelectBestF0(double current_f0, double past_f0, const double * const * f0_candidates, int number_of_candidates, int target_index, double allowed_range) { double reference_f0 = (current_f0 * 3.0 - past_f0) / 2.0; double minimum_error = fabs(reference_f0 - f0_candidates[0][target_index]); double best_f0 = f0_candidates[0][target_index]; double current_error; for (int i = 1; i < number_of_candidates; ++i) { current_error = fabs(reference_f0 - f0_candidates[i][target_index]); if (current_error < minimum_error) { minimum_error = current_error; best_f0 = f0_candidates[i][target_index]; } } if (fabs(1.0 - best_f0 / reference_f0) > allowed_range) return 0.0; return best_f0; } //----------------------------------------------------------------------------- // FixStep3() is the 3rd step of the postprocessing. // This function corrects the f0 candidates from backward to forward. //----------------------------------------------------------------------------- static void FixStep3(const double *f0_step2, int f0_length, const double * const * f0_candidates, int number_of_candidates, double allowed_range, const int *negative_index, int negative_count, double *f0_step3) { for (int i = 0; i < f0_length; i++) f0_step3[i] = f0_step2[i]; int limit; for (int i = 0; i < negative_count; ++i) { limit = i == negative_count - 1 ? f0_length - 1 : negative_index[i + 1]; for (int j = negative_index[i]; j < limit; ++j) { f0_step3[j + 1] = SelectBestF0(f0_step3[j], f0_step3[j - 1], f0_candidates, number_of_candidates, j + 1, allowed_range); if (f0_step3[j + 1] == 0) break; } } } //----------------------------------------------------------------------------- // FixStep4() is the 4th step of the postprocessing. // This function corrects the f0 candidates from forward to backward. //----------------------------------------------------------------------------- static void FixStep4(const double *f0_step3, int f0_length, const double * const * f0_candidates, int number_of_candidates, double allowed_range, const int *positive_index, int positive_count, double *f0_step4) { for (int i = 0; i < f0_length; ++i) f0_step4[i] = f0_step3[i]; int limit; for (int i = positive_count - 1; i >= 0; --i) { limit = i == 0 ? 1 : positive_index[i - 1]; for (int j = positive_index[i]; j > limit; --j) { f0_step4[j - 1] = SelectBestF0(f0_step4[j], f0_step4[j + 1], f0_candidates, number_of_candidates, j - 1, allowed_range); if (f0_step4[j - 1] == 0) break; } } } //----------------------------------------------------------------------------- // FixF0Contour() calculates the definitive f0 contour based on all f0 // candidates. There are four steps. //----------------------------------------------------------------------------- static void FixF0Contour(double frame_period, int number_of_candidates, int fs, const double * const * f0_candidates, const double *best_f0_contour, int f0_length, double f0_floor, double allowed_range, double *fixed_f0_contour) { int voice_range_minimum = static_cast(0.5 + 1000.0 / frame_period / f0_floor) * 2 + 1; if (f0_length <= voice_range_minimum) return; double *f0_tmp1 = new double[f0_length]; double *f0_tmp2 = new double[f0_length]; FixStep1(best_f0_contour, f0_length, voice_range_minimum, allowed_range, f0_tmp1); FixStep2(f0_tmp1, f0_length, voice_range_minimum, f0_tmp2); int positive_count, negative_count; int *positive_index = new int[f0_length]; int *negative_index = new int[f0_length]; GetNumberOfVoicedSections(f0_tmp2, f0_length, positive_index, negative_index, &positive_count, &negative_count); FixStep3(f0_tmp2, f0_length, f0_candidates, number_of_candidates, allowed_range, negative_index, negative_count, f0_tmp1); FixStep4(f0_tmp1, f0_length, f0_candidates, number_of_candidates, allowed_range, positive_index, positive_count, fixed_f0_contour); delete[] f0_tmp1; delete[] f0_tmp2; delete[] positive_index; delete[] negative_index; } //----------------------------------------------------------------------------- // GetFilteredSignal() calculates the signal that is the convolution of the // input signal and low-pass filter. // This function is only used in RawEventByDio() //----------------------------------------------------------------------------- static void GetFilteredSignal(int half_average_length, int fft_size, const fft_complex *y_spectrum, int y_length, double *filtered_signal) { double *low_pass_filter = new double[fft_size]; // Nuttall window is used as a low-pass filter. // Cutoff frequency depends on the window length. NuttallWindow(half_average_length * 4, low_pass_filter); for (int i = half_average_length * 4; i < fft_size; ++i) low_pass_filter[i] = 0.0; fft_complex *low_pass_filter_spectrum = new fft_complex[fft_size]; fft_plan forwardFFT = fft_plan_dft_r2c_1d(fft_size, low_pass_filter, low_pass_filter_spectrum, FFT_ESTIMATE); fft_execute(forwardFFT); // Convolution double tmp = y_spectrum[0][0] * low_pass_filter_spectrum[0][0] - y_spectrum[0][1] * low_pass_filter_spectrum[0][1]; low_pass_filter_spectrum[0][1] = y_spectrum[0][0] * low_pass_filter_spectrum[0][1] + y_spectrum[0][1] * low_pass_filter_spectrum[0][0]; low_pass_filter_spectrum[0][0] = tmp; for (int i = 1; i <= fft_size / 2; ++i) { tmp = y_spectrum[i][0] * low_pass_filter_spectrum[i][0] - y_spectrum[i][1] * low_pass_filter_spectrum[i][1]; low_pass_filter_spectrum[i][1] = y_spectrum[i][0] * low_pass_filter_spectrum[i][1] + y_spectrum[i][1] * low_pass_filter_spectrum[i][0]; low_pass_filter_spectrum[i][0] = tmp; low_pass_filter_spectrum[fft_size - i - 1][0] = low_pass_filter_spectrum[i][0]; low_pass_filter_spectrum[fft_size - i - 1][1] = low_pass_filter_spectrum[i][1]; } fft_plan inverseFFT = fft_plan_dft_c2r_1d(fft_size, low_pass_filter_spectrum, filtered_signal, FFT_ESTIMATE); fft_execute(inverseFFT); // Compensation of the delay. int index_bias = half_average_length * 2; for (int i = 0; i < y_length; ++i) filtered_signal[i] = filtered_signal[i + index_bias]; fft_destroy_plan(inverseFFT); fft_destroy_plan(forwardFFT); delete[] low_pass_filter_spectrum; delete[] low_pass_filter; } //----------------------------------------------------------------------------- // CheckEvent() returns 1, provided that the input value is over 1. // This function is for RawEventByDio(). //----------------------------------------------------------------------------- static inline int CheckEvent(int x) { return x > 0 ? 1 : 0; } //----------------------------------------------------------------------------- // ZeroCrossingEngine() calculates the zero crossing points from positive to // negative. Thanks to Custom.Maid http://custom-made.seesaa.net/ (2012/8/19) //----------------------------------------------------------------------------- static int ZeroCrossingEngine(const double *filtered_signal, int y_length, double fs, double *interval_locations, double *intervals) { int *negative_going_points = new int[y_length]; for (int i = 0; i < y_length - 1; ++i) negative_going_points[i] = 0.0 < filtered_signal[i] && filtered_signal[i + 1] <= 0.0 ? i + 1 : 0; negative_going_points[y_length - 1] = 0; int *edges = new int[y_length]; int count = 0; for (int i = 0; i < y_length; ++i) if (negative_going_points[i] > 0) edges[count++] = negative_going_points[i]; if (count < 2) { delete[] edges; delete[] negative_going_points; return 0; } double *fine_edges = new double[count]; for (int i = 0; i < count; ++i) fine_edges[i] = edges[i] - filtered_signal[edges[i] - 1] / (filtered_signal[edges[i]] - filtered_signal[edges[i] - 1]); for (int i = 0; i < count - 1; ++i) { intervals[i] = fs / (fine_edges[i + 1] - fine_edges[i]); interval_locations[i] = (fine_edges[i] + fine_edges[i + 1]) / 2.0 / fs; } delete[] fine_edges; delete[] edges; delete[] negative_going_points; return count - 1; } //----------------------------------------------------------------------------- // GetFourZeroCrossingIntervals() calculates four zero-crossing intervals. // (1) Zero-crossing going from negative to positive. // (2) Zero-crossing going from positive to negative. // (3) Peak, and (4) dip. (3) and (4) are calculated from the zero-crossings of // the differential of waveform. //----------------------------------------------------------------------------- static void GetFourZeroCrossingIntervals(double *filtered_signal, int y_length, double actual_fs, ZeroCrossings *zero_crossings) { // x_length / 4 (old version) is fixed at 2013/07/14 const int kMaximumNumber = y_length; zero_crossings->negative_interval_locations = new double[kMaximumNumber]; zero_crossings->positive_interval_locations = new double[kMaximumNumber]; zero_crossings->peak_interval_locations = new double[kMaximumNumber]; zero_crossings->dip_interval_locations = new double[kMaximumNumber]; zero_crossings->negative_intervals = new double[kMaximumNumber]; zero_crossings->positive_intervals = new double[kMaximumNumber]; zero_crossings->peak_intervals = new double[kMaximumNumber]; zero_crossings->dip_intervals = new double[kMaximumNumber]; zero_crossings->number_of_negatives = ZeroCrossingEngine(filtered_signal, y_length, actual_fs, zero_crossings->negative_interval_locations, zero_crossings->negative_intervals); for (int i = 0; i < y_length; ++i) filtered_signal[i] = -filtered_signal[i]; zero_crossings->number_of_positives = ZeroCrossingEngine(filtered_signal, y_length, actual_fs, zero_crossings->positive_interval_locations, zero_crossings->positive_intervals); for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] = filtered_signal[i] - filtered_signal[i + 1]; zero_crossings->number_of_peaks = ZeroCrossingEngine(filtered_signal, y_length - 1, actual_fs, zero_crossings->peak_interval_locations, zero_crossings->peak_intervals); for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] = -filtered_signal[i]; zero_crossings->number_of_dips = ZeroCrossingEngine(filtered_signal, y_length - 1, actual_fs, zero_crossings->dip_interval_locations, zero_crossings->dip_intervals); } //----------------------------------------------------------------------------- // GetF0CandidateContourSub() calculates the f0 candidates and deviations. // This is the sub-function of GetF0Candidates() and assumes the calculation. //----------------------------------------------------------------------------- static void GetF0CandidateContourSub( const double * const * interpolated_f0_set, int f0_length, double f0_floor, double f0_ceil, double boundary_f0, double *f0_candidate, double *f0_score) { for (int i = 0; i < f0_length; ++i) { f0_candidate[i] = (interpolated_f0_set[0][i] + interpolated_f0_set[1][i] + interpolated_f0_set[2][i] + interpolated_f0_set[3][i]) / 4.0; f0_score[i] = sqrt(((interpolated_f0_set[0][i] - f0_candidate[i]) * (interpolated_f0_set[0][i] - f0_candidate[i]) + (interpolated_f0_set[1][i] - f0_candidate[i]) * (interpolated_f0_set[1][i] - f0_candidate[i]) + (interpolated_f0_set[2][i] - f0_candidate[i]) * (interpolated_f0_set[2][i] - f0_candidate[i]) + (interpolated_f0_set[3][i] - f0_candidate[i]) * (interpolated_f0_set[3][i] - f0_candidate[i])) / 3.0); if (f0_candidate[i] > boundary_f0 || f0_candidate[i] < boundary_f0 / 2.0 || f0_candidate[i] > f0_ceil || f0_candidate[i] < f0_floor) { f0_candidate[i] = 0.0; f0_score[i] = world::kMaximumValue; } } } //----------------------------------------------------------------------------- // GetF0CandidateContour() calculates the F0 candidates based on the // zero-crossings. //----------------------------------------------------------------------------- static void GetF0CandidateContour(const ZeroCrossings *zero_crossings, double boundary_f0, double f0_floor, double f0_ceil, const double *temporal_positions, int f0_length, double *f0_candidate, double *f0_score) { if (0 == CheckEvent(zero_crossings->number_of_negatives - 2) * CheckEvent(zero_crossings->number_of_positives - 2) * CheckEvent(zero_crossings->number_of_peaks - 2) * CheckEvent(zero_crossings->number_of_dips - 2)) { for (int i = 0; i < f0_length; ++i) { f0_score[i] = world::kMaximumValue; f0_candidate[i] = 0.0; } return; } double *interpolated_f0_set[4]; for (int i = 0; i < 4; ++i) interpolated_f0_set[i] = new double[f0_length]; interp1(zero_crossings->negative_interval_locations, zero_crossings->negative_intervals, zero_crossings->number_of_negatives, temporal_positions, f0_length, interpolated_f0_set[0]); interp1(zero_crossings->positive_interval_locations, zero_crossings->positive_intervals, zero_crossings->number_of_positives, temporal_positions, f0_length, interpolated_f0_set[1]); interp1(zero_crossings->peak_interval_locations, zero_crossings->peak_intervals, zero_crossings->number_of_peaks, temporal_positions, f0_length, interpolated_f0_set[2]); interp1(zero_crossings->dip_interval_locations, zero_crossings->dip_intervals, zero_crossings->number_of_dips, temporal_positions, f0_length, interpolated_f0_set[3]); GetF0CandidateContourSub(interpolated_f0_set, f0_length, f0_floor, f0_ceil, boundary_f0, f0_candidate, f0_score); for (int i = 0; i < 4; ++i) delete[] interpolated_f0_set[i]; } //----------------------------------------------------------------------------- // DestroyZeroCrossings() frees the memory of array in the struct //----------------------------------------------------------------------------- static void DestroyZeroCrossings(ZeroCrossings *zero_crossings) { delete[] zero_crossings->negative_interval_locations; delete[] zero_crossings->positive_interval_locations; delete[] zero_crossings->peak_interval_locations; delete[] zero_crossings->dip_interval_locations; delete[] zero_crossings->negative_intervals; delete[] zero_crossings->positive_intervals; delete[] zero_crossings->peak_intervals; delete[] zero_crossings->dip_intervals; } //----------------------------------------------------------------------------- // GetF0CandidateFromRawEvent() calculates F0 candidate contour in 1-ch signal //----------------------------------------------------------------------------- static void GetF0CandidateFromRawEvent(double boundary_f0, double fs, const fft_complex *y_spectrum, int y_length, int fft_size, double f0_floor, double f0_ceil, const double *temporal_positions, int f0_length, double *f0_score, double *f0_candidate) { double *filtered_signal = new double[fft_size]; GetFilteredSignal(matlab_round(fs / boundary_f0 / 2.0), fft_size, y_spectrum, y_length, filtered_signal); ZeroCrossings zero_crossings = {0}; GetFourZeroCrossingIntervals(filtered_signal, y_length, fs, &zero_crossings); GetF0CandidateContour(&zero_crossings, boundary_f0, f0_floor, f0_ceil, temporal_positions, f0_length, f0_candidate, f0_score); DestroyZeroCrossings(&zero_crossings); delete[] filtered_signal; } //----------------------------------------------------------------------------- // GetF0CandidatesAndScores() calculates all f0 candidates and their scores. //----------------------------------------------------------------------------- static void GetF0CandidatesAndScores(const double *boundary_f0_list, int number_of_bands, double actual_fs, int y_length, const double *temporal_positions, int f0_length, const fft_complex *y_spectrum, int fft_size, double f0_floor, double f0_ceil, double **raw_f0_candidates, double **raw_f0_scores) { double *f0_candidate = new double[f0_length]; double *f0_score = new double[f0_length]; // Calculation of the acoustics events (zero-crossing) for (int i = 0; i < number_of_bands; ++i) { GetF0CandidateFromRawEvent(boundary_f0_list[i], actual_fs, y_spectrum, y_length, fft_size, f0_floor, f0_ceil, temporal_positions, f0_length, f0_score, f0_candidate); for (int j = 0; j < f0_length; ++j) { // A way to avoid zero division raw_f0_scores[i][j] = f0_score[j] / (f0_candidate[j] + world::kMySafeGuardMinimum); raw_f0_candidates[i][j] = f0_candidate[j]; } } delete[] f0_candidate; delete[] f0_score; } //----------------------------------------------------------------------------- // DioGeneralBody() estimates the F0 based on Distributed Inline-filter // Operation. //----------------------------------------------------------------------------- static void DioGeneralBody(const double *x, int x_length, int fs, double frame_period, double f0_floor, double f0_ceil, double channels_in_octave, int speed, double allowed_range, double *temporal_positions, double *f0) { int number_of_bands = 1 + static_cast(log(f0_ceil / f0_floor) / world::kLog2 * channels_in_octave); double *boundary_f0_list = new double[number_of_bands]; for (int i = 0; i < number_of_bands; ++i) boundary_f0_list[i] = f0_floor * pow(2.0, (i + 1) / channels_in_octave); // normalization int decimation_ratio = MyMaxInt(MyMinInt(speed, 12), 1); int y_length = (1 + static_cast(x_length / decimation_ratio)); double actual_fs = static_cast(fs) / decimation_ratio; int fft_size = GetSuitableFFTSize(y_length + matlab_round(actual_fs / world::kCutOff) * 2 + 1 + (4 * static_cast(1.0 + actual_fs / boundary_f0_list[0] / 2.0))); // Calculation of the spectrum used for the f0 estimation fft_complex *y_spectrum = new fft_complex[fft_size]; GetSpectrumForEstimation(x, x_length, y_length, actual_fs, fft_size, decimation_ratio, y_spectrum); double **f0_candidates = new double *[number_of_bands]; double **f0_scores = new double *[number_of_bands]; int f0_length = GetSamplesForDIO(fs, x_length, frame_period); for (int i = 0; i < number_of_bands; ++i) { f0_candidates[i] = new double[f0_length]; f0_scores[i] = new double[f0_length]; } for (int i = 0; i < f0_length; ++i) temporal_positions[i] = i * frame_period / 1000.0; GetF0CandidatesAndScores(boundary_f0_list, number_of_bands, actual_fs, y_length, temporal_positions, f0_length, y_spectrum, fft_size, f0_floor, f0_ceil, f0_candidates, f0_scores); // Selection of the best value based on fundamental-ness. // This function is related with SortCandidates() in MATLAB. double *best_f0_contour = new double[f0_length]; GetBestF0Contour(f0_length, f0_candidates, f0_scores, number_of_bands, best_f0_contour); // Postprocessing to find the best f0-contour. FixF0Contour(frame_period, number_of_bands, fs, f0_candidates, best_f0_contour, f0_length, f0_floor, allowed_range, f0); delete[] best_f0_contour; delete[] y_spectrum; for (int i = 0; i < number_of_bands; ++i) { delete[] f0_scores[i]; delete[] f0_candidates[i]; } delete[] f0_scores; delete[] f0_candidates; delete[] boundary_f0_list; } } // namespace int GetSamplesForDIO(int fs, int x_length, double frame_period) { return static_cast(1000.0 * x_length / fs / frame_period) + 1; } void Dio(const double *x, int x_length, int fs, const DioOption *option, double *temporal_positions, double *f0) { DioGeneralBody(x, x_length, fs, option->frame_period, option->f0_floor, option->f0_ceil, option->channels_in_octave, option->speed, option->allowed_range, temporal_positions, f0); } void InitializeDioOption(DioOption *option) { // You can change default parameters. option->channels_in_octave = 2.0; option->f0_ceil = world::kCeilF0; option->f0_floor = world::kFloorF0; option->frame_period = 5; // You can use the value from 1 to 12. // Default value 11 is for the fs of 44.1 kHz. // The lower value you use, the better performance you can obtain. option->speed = 1; // You can give a positive real number as the threshold. // The most strict value is 0, and there is no upper limit. // On the other hand, I think that the value from 0.02 to 0.2 is reasonable. option->allowed_range = 0.1; } ================================================ FILE: libsvc/Modules/Lib/World/src/fft.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // This file represents the functions about FFT (Fast Fourier Transform) // implemented by Mr. Ooura, and wrapper functions implemented by M. Morise. // We can use these wrapper functions as well as the FFTW functions. // Please see the FFTW web-page to show the usage of the wrapper functions. // Ooura FFT: // (Japanese) http://www.kurims.kyoto-u.ac.jp/~ooura/index-j.html // (English) http://www.kurims.kyoto-u.ac.jp/~ooura/index.html // FFTW: // (English) http://www.fftw.org/ // 2012/08/24 by M. Morise //----------------------------------------------------------------------------- #include "world/fft.h" #include #include void cdft(int n, int isgn, double *a, int *ip, double *w); void rdft(int n, int isgn, double *a, int *ip, double *w); namespace { static void BackwardFFT(fft_plan p) { if (p.c_out == NULL) { // c2r p.input[0] = p.c_in[0][0]; p.input[1] = p.c_in[p.n / 2][0]; for (int i = 1; i < p.n / 2; ++i) { p.input[i * 2] = p.c_in[i][0]; p.input[i * 2 + 1] = -p.c_in[i][1]; } rdft(p.n, -1, p.input, p.ip, p.w); for (int i = 0; i < p.n; ++i) p.out[i] = p.input[i] * 2.0; } else { // c2c for (int i = 0; i < p.n; ++i) { p.input[i * 2] = p.c_in[i][0]; p.input[i * 2 + 1] = p.c_in[i][1]; } cdft(p.n * 2, -1, p.input, p.ip, p.w); for (int i = 0; i < p.n; ++i) { p.c_out[i][0] = p.input[i * 2]; p.c_out[i][1] = -p.input[i * 2 + 1]; } } } static void ForwardFFT(fft_plan p) { if (p.c_in == NULL) { // r2c for (int i = 0; i < p.n; ++i) p.input[i] = p.in[i]; rdft(p.n, 1, p.input, p.ip, p.w); p.c_out[0][0] = p.input[0]; p.c_out[0][1] = 0.0; for (int i = 1; i < p.n / 2; ++i) { p.c_out[i][0] = p.input[i * 2]; p.c_out[i][1] = -p.input[i * 2 + 1]; } p.c_out[p.n / 2][0] = p.input[1]; p.c_out[p.n / 2][1] = 0.0; } else { // c2c for (int i = 0; i < p.n; ++i) { p.input[i * 2] = p.c_in[i][0]; p.input[i * 2 + 1] = p.c_in[i][1]; } cdft(p.n * 2, 1, p.input, p.ip, p.w); for (int i = 0; i < p.n; ++i) { p.c_out[i][0] = p.input[i * 2]; p.c_out[i][1] = -p.input[i * 2 + 1]; } } } } // namespace fft_plan fft_plan_dft_1d(int n, fft_complex *in, fft_complex *out, int sign, unsigned int flags) { void makewt(int nw, int *ip, double *w); fft_plan output = {0}; output.n = n; output.in = NULL; output.c_in = in; output.out = NULL; output.c_out = out; output.sign = sign; output.flags = flags; output.input = new double[n * 2]; output.ip = new int[n]; output.w = new double[n * 5 / 4]; output.ip[0] = 0; makewt(output.n >> 1, output.ip, output.w); return output; } fft_plan fft_plan_dft_c2r_1d(int n, fft_complex *in, double *out, unsigned int flags) { void makewt(int nw, int *ip, double *w); void makect(int nc, int *ip, double *c); fft_plan output = {0}; output.n = n; output.in = NULL; output.c_in = in; output.out = out; output.c_out = NULL; output.sign = FFT_BACKWARD; output.flags = flags; output.input = new double[n]; output.ip = new int[n]; output.w = new double[n * 5 / 4]; output.ip[0] = 0; makewt(output.n >> 2, output.ip, output.w); makect(output.n >> 2, output.ip, output.w + (output.n >> 2)); return output; } fft_plan fft_plan_dft_r2c_1d(int n, double *in, fft_complex *out, unsigned int flags) { void makewt(int nw, int *ip, double *w); void makect(int nc, int *ip, double *c); fft_plan output = {0}; output.n = n; output.in = in; output.c_in = NULL; output.out = NULL; output.c_out = out; output.sign = FFT_FORWARD; output.flags = flags; output.input = new double[n]; output.ip = new int[n]; output.w = new double[n * 5 / 4]; output.ip[0] = 0; makewt(output.n >> 2, output.ip, output.w); makect(output.n >> 2, output.ip, output.w + (output.n >> 2)); return output; } void fft_execute(fft_plan p) { if (p.sign == FFT_FORWARD) { ForwardFFT(p); } else { // ifft BackwardFFT(p); } } void fft_destroy_plan(fft_plan p) { p.n = 0; p.in = NULL; p.c_in = NULL; p.out = NULL; p.c_out = NULL; p.sign = 0; p.flags = 0; delete[] p.input; delete[] p.ip; delete[] p.w; } //----------------------------------------------------------------------- // The following functions are reffered by // http://www.kurims.kyoto-u.ac.jp/~ooura/index.html void cdft(int n, int isgn, double *a, int *ip, double *w) { void cftfsub(int n, double *a, int *ip, int nw, double *w); void cftbsub(int n, double *a, int *ip, int nw, double *w); int nw; nw = ip[0]; if (isgn >= 0) { cftfsub(n, a, ip, nw, w); } else { cftbsub(n, a, ip, nw, w); } } void rdft(int n, int isgn, double *a, int *ip, double *w) { void cftfsub(int n, double *a, int *ip, int nw, double *w); void cftbsub(int n, double *a, int *ip, int nw, double *w); void rftfsub(int n, double *a, int nc, double *c); void rftbsub(int n, double *a, int nc, double *c); double xi; int nw = ip[0]; int nc = ip[1]; if (isgn >= 0) { if (n > 4) { cftfsub(n, a, ip, nw, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, ip, nw, w); } xi = a[0] - a[1]; a[0] += a[1]; a[1] = xi; } else { a[1] = 0.5 * (a[0] - a[1]); a[0] -= a[1]; if (n > 4) { rftbsub(n, a, nc, w + nw); cftbsub(n, a, ip, nw, w); } else if (n == 4) { cftbsub(n, a, ip, nw, w); } } } void makewt(int nw, int *ip, double *w) { void makeipt(int nw, int *ip); int j, nwh, nw0, nw1; double delta, wn4r, wk1r, wk1i, wk3r, wk3i; ip[0] = nw; ip[1] = 1; if (nw > 2) { nwh = nw >> 1; delta = atan(1.0) / nwh; wn4r = cos(delta * nwh); w[0] = 1; w[1] = wn4r; if (nwh == 4) { w[2] = cos(delta * 2); w[3] = sin(delta * 2); } else if (nwh > 4) { makeipt(nw, ip); w[2] = 0.5 / cos(delta * 2); w[3] = 0.5 / cos(delta * 6); for (j = 4; j < nwh; j += 4) { w[j] = cos(delta * j); w[j + 1] = sin(delta * j); w[j + 2] = cos(3 * delta * j); w[j + 3] = -sin(3 * delta * j); } } nw0 = 0; while (nwh > 2) { nw1 = nw0 + nwh; nwh >>= 1; w[nw1] = 1; w[nw1 + 1] = wn4r; if (nwh == 4) { wk1r = w[nw0 + 4]; wk1i = w[nw0 + 5]; w[nw1 + 2] = wk1r; w[nw1 + 3] = wk1i; } else if (nwh > 4) { wk1r = w[nw0 + 4]; wk3r = w[nw0 + 6]; w[nw1 + 2] = 0.5 / wk1r; w[nw1 + 3] = 0.5 / wk3r; for (j = 4; j < nwh; j += 4) { wk1r = w[nw0 + 2 * j]; wk1i = w[nw0 + 2 * j + 1]; wk3r = w[nw0 + 2 * j + 2]; wk3i = w[nw0 + 2 * j + 3]; w[nw1 + j] = wk1r; w[nw1 + j + 1] = wk1i; w[nw1 + j + 2] = wk3r; w[nw1 + j + 3] = wk3i; } } nw0 = nw1; } } } void makeipt(int nw, int *ip) { int j, l, m, m2, p, q; ip[2] = 0; ip[3] = 16; m = 2; for (l = nw; l > 32; l >>= 2) { m2 = m << 1; q = m2 << 3; for (j = m; j < m2; j++) { p = ip[j] << 2; ip[m + j] = p; ip[m2 + j] = p + q; } m = m2; } } void makect(int nc, int *ip, double *c) { int j, nch; double delta; ip[1] = nc; if (nc > 1) { nch = nc >> 1; delta = atan(1.0) / nch; c[0] = cos(delta * nch); c[nch] = 0.5 * c[0]; for (j = 1; j < nch; j++) { c[j] = 0.5 * cos(delta * j); c[nc - j] = 0.5 * sin(delta * j); } } } // -------- child routines -------- void cftfsub(int n, double *a, int *ip, int nw, double *w) { void bitrv2(int n, int *ip, double *a); void bitrv216(double *a); void bitrv208(double *a); void cftf1st(int n, double *a, double *w); void cftrec4(int n, double *a, int nw, double *w); void cftleaf(int n, int isplt, double *a, int nw, double *w); void cftfx41(int n, double *a, int nw, double *w); void cftf161(double *a, double *w); void cftf081(double *a, double *w); void cftf040(double *a); void cftx020(double *a); if (n > 8) { if (n > 32) { cftf1st(n, a, &w[nw - (n >> 2)]); if (n > 512) { cftrec4(n, a, nw, w); } else if (n > 128) { cftleaf(n, 1, a, nw, w); } else { cftfx41(n, a, nw, w); } bitrv2(n, ip, a); } else if (n == 32) { cftf161(a, &w[nw - 8]); bitrv216(a); } else { cftf081(a, w); bitrv208(a); } } else if (n == 8) { cftf040(a); } else if (n == 4) { cftx020(a); } } void cftbsub(int n, double *a, int *ip, int nw, double *w) { void bitrv2conj(int n, int *ip, double *a); void bitrv216neg(double *a); void bitrv208neg(double *a); void cftb1st(int n, double *a, double *w); void cftrec4(int n, double *a, int nw, double *w); void cftleaf(int n, int isplt, double *a, int nw, double *w); void cftfx41(int n, double *a, int nw, double *w); void cftf161(double *a, double *w); void cftf081(double *a, double *w); void cftb040(double *a); void cftx020(double *a); if (n > 8) { if (n > 32) { cftb1st(n, a, &w[nw - (n >> 2)]); if (n > 512) { cftrec4(n, a, nw, w); } else if (n > 128) { cftleaf(n, 1, a, nw, w); } else { cftfx41(n, a, nw, w); } bitrv2conj(n, ip, a); } else if (n == 32) { cftf161(a, &w[nw - 8]); bitrv216neg(a); } else { cftf081(a, w); bitrv208neg(a); } } else if (n == 8) { cftb040(a); } else if (n == 4) { cftx020(a); } } void bitrv2(int n, int *ip, double *a) { int j, j1, k, k1, l, m, nh, nm; double xr, xi, yr, yi; m = 1; for (l = n >> 2; l > 8; l >>= 2) { m <<= 1; } nh = n >> 1; nm = 4 * m; if (l == 8) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + 2 * ip[m + k]; k1 = 4 * k + 2 * ip[m + j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + 2 * ip[m + k]; j1 = k1 + 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= 2; k1 -= nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh + 2; k1 += nh + 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh - nm; k1 += 2 * nm - 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } else { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + ip[m + k]; k1 = 4 * k + ip[m + j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + ip[m + k]; j1 = k1 + 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } } void bitrv2conj(int n, int *ip, double *a) { int j, j1, k, k1, l, m, nh, nm; double xr, xi, yr, yi; m = 1; for (l = n >> 2; l > 8; l >>= 2) { m <<= 1; } nh = n >> 1; nm = 4 * m; if (l == 8) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + 2 * ip[m + k]; k1 = 4 * k + 2 * ip[m + j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + 2 * ip[m + k]; j1 = k1 + 2; k1 += nh; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= 2; k1 -= nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh + 2; k1 += nh + 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh - nm; k1 += 2 * nm - 2; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; } } else { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + ip[m + k]; k1 = 4 * k + ip[m + j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + ip[m + k]; j1 = k1 + 2; k1 += nh; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; j1 += nm; k1 += nm; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; } } } void bitrv216(double *a) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x7r = a[14]; x7i = a[15]; x8r = a[16]; x8i = a[17]; x10r = a[20]; x10i = a[21]; x11r = a[22]; x11i = a[23]; x12r = a[24]; x12i = a[25]; x13r = a[26]; x13i = a[27]; x14r = a[28]; x14i = a[29]; a[2] = x8r; a[3] = x8i; a[4] = x4r; a[5] = x4i; a[6] = x12r; a[7] = x12i; a[8] = x2r; a[9] = x2i; a[10] = x10r; a[11] = x10i; a[14] = x14r; a[15] = x14i; a[16] = x1r; a[17] = x1i; a[20] = x5r; a[21] = x5i; a[22] = x13r; a[23] = x13i; a[24] = x3r; a[25] = x3i; a[26] = x11r; a[27] = x11i; a[28] = x7r; a[29] = x7i; } void bitrv216neg(double *a) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i, x15r, x15i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x6r = a[12]; x6i = a[13]; x7r = a[14]; x7i = a[15]; x8r = a[16]; x8i = a[17]; x9r = a[18]; x9i = a[19]; x10r = a[20]; x10i = a[21]; x11r = a[22]; x11i = a[23]; x12r = a[24]; x12i = a[25]; x13r = a[26]; x13i = a[27]; x14r = a[28]; x14i = a[29]; x15r = a[30]; x15i = a[31]; a[2] = x15r; a[3] = x15i; a[4] = x7r; a[5] = x7i; a[6] = x11r; a[7] = x11i; a[8] = x3r; a[9] = x3i; a[10] = x13r; a[11] = x13i; a[12] = x5r; a[13] = x5i; a[14] = x9r; a[15] = x9i; a[16] = x1r; a[17] = x1i; a[18] = x14r; a[19] = x14i; a[20] = x6r; a[21] = x6i; a[22] = x10r; a[23] = x10i; a[24] = x2r; a[25] = x2i; a[26] = x12r; a[27] = x12i; a[28] = x4r; a[29] = x4i; a[30] = x8r; a[31] = x8i; } void bitrv208(double *a) { double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; x1r = a[2]; x1i = a[3]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x6r = a[12]; x6i = a[13]; a[2] = x4r; a[3] = x4i; a[6] = x6r; a[7] = x6i; a[8] = x1r; a[9] = x1i; a[12] = x3r; a[13] = x3i; } void bitrv208neg(double *a) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x6r = a[12]; x6i = a[13]; x7r = a[14]; x7i = a[15]; a[2] = x7r; a[3] = x7i; a[4] = x3r; a[5] = x3i; a[6] = x5r; a[7] = x5i; a[8] = x1r; a[9] = x1i; a[10] = x6r; a[11] = x6i; a[12] = x2r; a[13] = x2i; a[14] = x4r; a[15] = x4i; } void cftf1st(int n, double *a, double *w) { int j, j0, j1, j2, j3, k, m, mh; double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = a[1] + a[j2 + 1]; x1r = a[0] - a[j2]; x1i = a[1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j2] = x1r - x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; csc1 = w[2]; csc3 = w[3]; wd1r = 1; wd1i = 0; wd3r = 1; wd3i = 0; k = 0; for (j = 2; j < mh - 2; j += 4) { k += 4; wk1r = csc1 * (wd1r + w[k]); wk1i = csc1 * (wd1i + w[k + 1]); wk3r = csc3 * (wd3r + w[k + 2]); wk3i = csc3 * (wd3i + w[k + 3]); wd1r = w[k]; wd1i = w[k + 1]; wd3r = w[k + 2]; wd3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = a[j + 1] + a[j2 + 1]; x1r = a[j] - a[j2]; x1i = a[j + 1] - a[j2 + 1]; y0r = a[j + 2] + a[j2 + 2]; y0i = a[j + 3] + a[j2 + 3]; y1r = a[j + 2] - a[j2 + 2]; y1i = a[j + 3] - a[j2 + 3]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 + 2] + a[j3 + 2]; y2i = a[j1 + 3] + a[j3 + 3]; y3r = a[j1 + 2] - a[j3 + 2]; y3i = a[j1 + 3] - a[j3 + 3]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j + 2] = y0r + y2r; a[j + 3] = y0i + y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j1 + 2] = y0r - y2r; a[j1 + 3] = y0i - y2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = y1r - y3i; x0i = y1i + y3r; a[j2 + 2] = wd1r * x0r - wd1i * x0i; a[j2 + 3] = wd1r * x0i + wd1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; x0r = y1r + y3i; x0i = y1i - y3r; a[j3 + 2] = wd3r * x0r + wd3i * x0i; a[j3 + 3] = wd3r * x0i - wd3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; y0r = a[j0 - 2] + a[j2 - 2]; y0i = a[j0 - 1] + a[j2 - 1]; y1r = a[j0 - 2] - a[j2 - 2]; y1i = a[j0 - 1] - a[j2 - 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 - 2] + a[j3 - 2]; y2i = a[j1 - 1] + a[j3 - 1]; y3r = a[j1 - 2] - a[j3 - 2]; y3i = a[j1 - 1] - a[j3 - 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j0 - 2] = y0r + y2r; a[j0 - 1] = y0i + y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j1 - 2] = y0r - y2r; a[j1 - 1] = y0i - y2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = y1r - y3i; x0i = y1i + y3r; a[j2 - 2] = wd1i * x0r - wd1r * x0i; a[j2 - 1] = wd1i * x0i + wd1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; x0r = y1r + y3i; x0i = y1i - y3r; a[j3 - 2] = wd3i * x0r + wd3r * x0i; a[j3 - 1] = wd3i * x0i - wd3r * x0r; } wk1r = csc1 * (wd1r + wn4r); wk1i = csc1 * (wd1i + wn4r); wk3r = csc3 * (wd3r - wn4r); wk3i = csc3 * (wd3i - wn4r); j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] + a[j2 - 2]; x0i = a[j0 - 1] + a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = a[j0 - 1] - a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i + x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 - 2] = wk1r * x0r - wk1i * x0i; a[j2 - 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 - 2] = wk3r * x0r + wk3i * x0i; a[j3 - 1] = wk3r * x0i - wk3i * x0r; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); x0r = a[j0 + 2] + a[j2 + 2]; x0i = a[j0 + 3] + a[j2 + 3]; x1r = a[j0 + 2] - a[j2 + 2]; x1i = a[j0 + 3] - a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j0 + 2] = x0r + x2r; a[j0 + 3] = x0i + x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 + 2] = wk1i * x0r - wk1r * x0i; a[j2 + 3] = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 + 2] = wk3i * x0r + wk3r * x0i; a[j3 + 3] = wk3i * x0i - wk3r * x0r; } void cftb1st(int n, double *a, double *w) { int j, j0, j1, j2, j3, k, m, mh; double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = -a[1] - a[j2 + 1]; x1r = a[0] - a[j2]; x1i = -a[1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j2] = x1r + x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r - x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; csc1 = w[2]; csc3 = w[3]; wd1r = 1; wd1i = 0; wd3r = 1; wd3i = 0; k = 0; for (j = 2; j < mh - 2; j += 4) { k += 4; wk1r = csc1 * (wd1r + w[k]); wk1i = csc1 * (wd1i + w[k + 1]); wk3r = csc3 * (wd3r + w[k + 2]); wk3i = csc3 * (wd3i + w[k + 3]); wd1r = w[k]; wd1i = w[k + 1]; wd3r = w[k + 2]; wd3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = -a[j + 1] - a[j2 + 1]; x1r = a[j] - a[j2]; x1i = -a[j + 1] + a[j2 + 1]; y0r = a[j + 2] + a[j2 + 2]; y0i = -a[j + 3] - a[j2 + 3]; y1r = a[j + 2] - a[j2 + 2]; y1i = -a[j + 3] + a[j2 + 3]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 + 2] + a[j3 + 2]; y2i = a[j1 + 3] + a[j3 + 3]; y3r = a[j1 + 2] - a[j3 + 2]; y3i = a[j1 + 3] - a[j3 + 3]; a[j] = x0r + x2r; a[j + 1] = x0i - x2i; a[j + 2] = y0r + y2r; a[j + 3] = y0i - y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j1 + 2] = y0r - y2r; a[j1 + 3] = y0i + y2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = y1r + y3i; x0i = y1i + y3r; a[j2 + 2] = wd1r * x0r - wd1i * x0i; a[j2 + 3] = wd1r * x0i + wd1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; x0r = y1r - y3i; x0i = y1i - y3r; a[j3 + 2] = wd3r * x0r + wd3i * x0i; a[j3 + 3] = wd3r * x0i - wd3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = -a[j0 + 1] - a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = -a[j0 + 1] + a[j2 + 1]; y0r = a[j0 - 2] + a[j2 - 2]; y0i = -a[j0 - 1] - a[j2 - 1]; y1r = a[j0 - 2] - a[j2 - 2]; y1i = -a[j0 - 1] + a[j2 - 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 - 2] + a[j3 - 2]; y2i = a[j1 - 1] + a[j3 - 1]; y3r = a[j1 - 2] - a[j3 - 2]; y3i = a[j1 - 1] - a[j3 - 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i - x2i; a[j0 - 2] = y0r + y2r; a[j0 - 1] = y0i - y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j1 - 2] = y0r - y2r; a[j1 - 1] = y0i + y2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = y1r + y3i; x0i = y1i + y3r; a[j2 - 2] = wd1i * x0r - wd1r * x0i; a[j2 - 1] = wd1i * x0i + wd1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; x0r = y1r - y3i; x0i = y1i - y3r; a[j3 - 2] = wd3i * x0r + wd3r * x0i; a[j3 - 1] = wd3i * x0i - wd3r * x0r; } wk1r = csc1 * (wd1r + wn4r); wk1i = csc1 * (wd1i + wn4r); wk3r = csc3 * (wd3r - wn4r); wk3i = csc3 * (wd3i - wn4r); j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] + a[j2 - 2]; x0i = -a[j0 - 1] - a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = -a[j0 - 1] + a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i - x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 - 2] = wk1r * x0r - wk1i * x0i; a[j2 - 1] = wk1r * x0i + wk1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 - 2] = wk3r * x0r + wk3i * x0i; a[j3 - 1] = wk3r * x0i - wk3i * x0r; x0r = a[j0] + a[j2]; x0i = -a[j0 + 1] - a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = -a[j0 + 1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); x0r = a[j0 + 2] + a[j2 + 2]; x0i = -a[j0 + 3] - a[j2 + 3]; x1r = a[j0 + 2] - a[j2 + 2]; x1i = -a[j0 + 3] + a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j0 + 2] = x0r + x2r; a[j0 + 3] = x0i - x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 + 2] = wk1i * x0r - wk1r * x0i; a[j2 + 3] = wk1i * x0i + wk1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 + 2] = wk3i * x0r + wk3r * x0i; a[j3 + 3] = wk3i * x0i - wk3r * x0r; } void cftrec4(int n, double *a, int nw, double *w) { int cfttree(int n, int j, int k, double *a, int nw, double *w); void cftleaf(int n, int isplt, double *a, int nw, double *w); void cftmdl1(int n, double *a, double *w); int isplt, j, k, m; m = n; while (m > 512) { m >>= 2; cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]); } cftleaf(m, 1, &a[n - m], nw, w); k = 0; for (j = n - m; j > 0; j -= m) { k++; isplt = cfttree(m, j, k, a, nw, w); cftleaf(m, isplt, &a[j - m], nw, w); } } int cfttree(int n, int j, int k, double *a, int nw, double *w) { void cftmdl1(int n, double *a, double *w); void cftmdl2(int n, double *a, double *w); int i, isplt, m; if ((k & 3) != 0) { isplt = k & 1; if (isplt != 0) { cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]); } else { cftmdl2(n, &a[j - n], &w[nw - n]); } } else { m = n; for (i = k; (i & 3) == 0; i >>= 2) { m <<= 2; } isplt = i & 1; if (isplt != 0) { while (m > 128) { cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]); m >>= 2; } } else { while (m > 128) { cftmdl2(m, &a[j - m], &w[nw - m]); m >>= 2; } } } return isplt; } void cftleaf(int n, int isplt, double *a, int nw, double *w) { void cftmdl1(int n, double *a, double *w); void cftmdl2(int n, double *a, double *w); void cftf161(double *a, double *w); void cftf162(double *a, double *w); void cftf081(double *a, double *w); void cftf082(double *a, double *w); if (n == 512) { cftmdl1(128, a, &w[nw - 64]); cftf161(a, &w[nw - 8]); cftf162(&a[32], &w[nw - 32]); cftf161(&a[64], &w[nw - 8]); cftf161(&a[96], &w[nw - 8]); cftmdl2(128, &a[128], &w[nw - 128]); cftf161(&a[128], &w[nw - 8]); cftf162(&a[160], &w[nw - 32]); cftf161(&a[192], &w[nw - 8]); cftf162(&a[224], &w[nw - 32]); cftmdl1(128, &a[256], &w[nw - 64]); cftf161(&a[256], &w[nw - 8]); cftf162(&a[288], &w[nw - 32]); cftf161(&a[320], &w[nw - 8]); cftf161(&a[352], &w[nw - 8]); if (isplt != 0) { cftmdl1(128, &a[384], &w[nw - 64]); cftf161(&a[480], &w[nw - 8]); } else { cftmdl2(128, &a[384], &w[nw - 128]); cftf162(&a[480], &w[nw - 32]); } cftf161(&a[384], &w[nw - 8]); cftf162(&a[416], &w[nw - 32]); cftf161(&a[448], &w[nw - 8]); } else { cftmdl1(64, a, &w[nw - 32]); cftf081(a, &w[nw - 8]); cftf082(&a[16], &w[nw - 8]); cftf081(&a[32], &w[nw - 8]); cftf081(&a[48], &w[nw - 8]); cftmdl2(64, &a[64], &w[nw - 64]); cftf081(&a[64], &w[nw - 8]); cftf082(&a[80], &w[nw - 8]); cftf081(&a[96], &w[nw - 8]); cftf082(&a[112], &w[nw - 8]); cftmdl1(64, &a[128], &w[nw - 32]); cftf081(&a[128], &w[nw - 8]); cftf082(&a[144], &w[nw - 8]); cftf081(&a[160], &w[nw - 8]); cftf081(&a[176], &w[nw - 8]); if (isplt != 0) { cftmdl1(64, &a[192], &w[nw - 32]); cftf081(&a[240], &w[nw - 8]); } else { cftmdl2(64, &a[192], &w[nw - 64]); cftf082(&a[240], &w[nw - 8]); } cftf081(&a[192], &w[nw - 8]); cftf082(&a[208], &w[nw - 8]); cftf081(&a[224], &w[nw - 8]); } } void cftmdl1(int n, double *a, double *w) { int j, j0, j1, j2, j3, k, m, mh; double wn4r, wk1r, wk1i, wk3r, wk3i; double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = a[1] + a[j2 + 1]; x1r = a[0] - a[j2]; x1i = a[1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j2] = x1r - x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; k = 0; for (j = 2; j < mh; j += 2) { k += 4; wk1r = w[k]; wk1i = w[k + 1]; wk3r = w[k + 2]; wk3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = a[j + 1] + a[j2 + 1]; x1r = a[j] - a[j2]; x1i = a[j + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; } j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); } void cftmdl2(int n, double *a, double *w) { int j, j0, j1, j2, j3, k, kr, m, mh; double wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; mh = n >> 3; m = 2 * mh; wn4r = w[1]; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] - a[j2 + 1]; x0i = a[1] + a[j2]; x1r = a[0] + a[j2 + 1]; x1i = a[1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wn4r * (x2r - x2i); y0i = wn4r * (x2i + x2r); a[0] = x0r + y0r; a[1] = x0i + y0i; a[j1] = x0r - y0r; a[j1 + 1] = x0i - y0i; y0r = wn4r * (x3r - x3i); y0i = wn4r * (x3i + x3r); a[j2] = x1r - y0i; a[j2 + 1] = x1i + y0r; a[j3] = x1r + y0i; a[j3 + 1] = x1i - y0r; k = 0; kr = 2 * m; for (j = 2; j < mh; j += 2) { k += 4; wk1r = w[k]; wk1i = w[k + 1]; wk3r = w[k + 2]; wk3i = w[k + 3]; kr -= 4; wd1i = w[kr]; wd1r = w[kr + 1]; wd3i = w[kr + 2]; wd3r = w[kr + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] - a[j2 + 1]; x0i = a[j + 1] + a[j2]; x1r = a[j] + a[j2 + 1]; x1i = a[j + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wk1r * x0r - wk1i * x0i; y0i = wk1r * x0i + wk1i * x0r; y2r = wd1r * x2r - wd1i * x2i; y2i = wd1r * x2i + wd1i * x2r; a[j] = y0r + y2r; a[j + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wk3r * x1r + wk3i * x1i; y0i = wk3r * x1i - wk3i * x1r; y2r = wd3r * x3r + wd3i * x3i; y2i = wd3r * x3i - wd3i * x3r; a[j2] = y0r + y2r; a[j2 + 1] = y0i + y2i; a[j3] = y0r - y2r; a[j3 + 1] = y0i - y2i; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] - a[j2 + 1]; x0i = a[j0 + 1] + a[j2]; x1r = a[j0] + a[j2 + 1]; x1i = a[j0 + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wd1i * x0r - wd1r * x0i; y0i = wd1i * x0i + wd1r * x0r; y2r = wk1i * x2r - wk1r * x2i; y2i = wk1i * x2i + wk1r * x2r; a[j0] = y0r + y2r; a[j0 + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wd3i * x1r + wd3r * x1i; y0i = wd3i * x1i - wd3r * x1r; y2r = wk3i * x3r + wk3r * x3i; y2i = wk3i * x3i - wk3r * x3r; a[j2] = y0r + y2r; a[j2 + 1] = y0i + y2i; a[j3] = y0r - y2r; a[j3 + 1] = y0i - y2i; } wk1r = w[m]; wk1i = w[m + 1]; j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] - a[j2 + 1]; x0i = a[j0 + 1] + a[j2]; x1r = a[j0] + a[j2 + 1]; x1i = a[j0 + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wk1r * x0r - wk1i * x0i; y0i = wk1r * x0i + wk1i * x0r; y2r = wk1i * x2r - wk1r * x2i; y2i = wk1i * x2i + wk1r * x2r; a[j0] = y0r + y2r; a[j0 + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wk1i * x1r - wk1r * x1i; y0i = wk1i * x1i + wk1r * x1r; y2r = wk1r * x3r - wk1i * x3i; y2i = wk1r * x3i + wk1i * x3r; a[j2] = y0r - y2r; a[j2 + 1] = y0i - y2i; a[j3] = y0r + y2r; a[j3 + 1] = y0i + y2i; } void cftfx41(int n, double *a, int nw, double *w) { void cftf161(double *a, double *w); void cftf162(double *a, double *w); void cftf081(double *a, double *w); void cftf082(double *a, double *w); if (n == 128) { cftf161(a, &w[nw - 8]); cftf162(&a[32], &w[nw - 32]); cftf161(&a[64], &w[nw - 8]); cftf161(&a[96], &w[nw - 8]); } else { cftf081(a, &w[nw - 8]); cftf082(&a[16], &w[nw - 8]); cftf081(&a[32], &w[nw - 8]); cftf081(&a[48], &w[nw - 8]); } } void cftf161(double *a, double *w) { double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; wn4r = w[1]; wk1r = w[2]; wk1i = w[3]; x0r = a[0] + a[16]; x0i = a[1] + a[17]; x1r = a[0] - a[16]; x1i = a[1] - a[17]; x2r = a[8] + a[24]; x2i = a[9] + a[25]; x3r = a[8] - a[24]; x3i = a[9] - a[25]; y0r = x0r + x2r; y0i = x0i + x2i; y4r = x0r - x2r; y4i = x0i - x2i; y8r = x1r - x3i; y8i = x1i + x3r; y12r = x1r + x3i; y12i = x1i - x3r; x0r = a[2] + a[18]; x0i = a[3] + a[19]; x1r = a[2] - a[18]; x1i = a[3] - a[19]; x2r = a[10] + a[26]; x2i = a[11] + a[27]; x3r = a[10] - a[26]; x3i = a[11] - a[27]; y1r = x0r + x2r; y1i = x0i + x2i; y5r = x0r - x2r; y5i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y9r = wk1r * x0r - wk1i * x0i; y9i = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; y13r = wk1i * x0r - wk1r * x0i; y13i = wk1i * x0i + wk1r * x0r; x0r = a[4] + a[20]; x0i = a[5] + a[21]; x1r = a[4] - a[20]; x1i = a[5] - a[21]; x2r = a[12] + a[28]; x2i = a[13] + a[29]; x3r = a[12] - a[28]; x3i = a[13] - a[29]; y2r = x0r + x2r; y2i = x0i + x2i; y6r = x0r - x2r; y6i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y10r = wn4r * (x0r - x0i); y10i = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; y14r = wn4r * (x0r + x0i); y14i = wn4r * (x0i - x0r); x0r = a[6] + a[22]; x0i = a[7] + a[23]; x1r = a[6] - a[22]; x1i = a[7] - a[23]; x2r = a[14] + a[30]; x2i = a[15] + a[31]; x3r = a[14] - a[30]; x3i = a[15] - a[31]; y3r = x0r + x2r; y3i = x0i + x2i; y7r = x0r - x2r; y7i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y11r = wk1i * x0r - wk1r * x0i; y11i = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; y15r = wk1r * x0r - wk1i * x0i; y15i = wk1r * x0i + wk1i * x0r; x0r = y12r - y14r; x0i = y12i - y14i; x1r = y12r + y14r; x1i = y12i + y14i; x2r = y13r - y15r; x2i = y13i - y15i; x3r = y13r + y15r; x3i = y13i + y15i; a[24] = x0r + x2r; a[25] = x0i + x2i; a[26] = x0r - x2r; a[27] = x0i - x2i; a[28] = x1r - x3i; a[29] = x1i + x3r; a[30] = x1r + x3i; a[31] = x1i - x3r; x0r = y8r + y10r; x0i = y8i + y10i; x1r = y8r - y10r; x1i = y8i - y10i; x2r = y9r + y11r; x2i = y9i + y11i; x3r = y9r - y11r; x3i = y9i - y11i; a[16] = x0r + x2r; a[17] = x0i + x2i; a[18] = x0r - x2r; a[19] = x0i - x2i; a[20] = x1r - x3i; a[21] = x1i + x3r; a[22] = x1r + x3i; a[23] = x1i - x3r; x0r = y5r - y7i; x0i = y5i + y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); x0r = y5r + y7i; x0i = y5i - y7r; x3r = wn4r * (x0r - x0i); x3i = wn4r * (x0i + x0r); x0r = y4r - y6i; x0i = y4i + y6r; x1r = y4r + y6i; x1i = y4i - y6r; a[8] = x0r + x2r; a[9] = x0i + x2i; a[10] = x0r - x2r; a[11] = x0i - x2i; a[12] = x1r - x3i; a[13] = x1i + x3r; a[14] = x1r + x3i; a[15] = x1i - x3r; x0r = y0r + y2r; x0i = y0i + y2i; x1r = y0r - y2r; x1i = y0i - y2i; x2r = y1r + y3r; x2i = y1i + y3i; x3r = y1r - y3r; x3i = y1i - y3i; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x0r - x2r; a[3] = x0i - x2i; a[4] = x1r - x3i; a[5] = x1i + x3r; a[6] = x1r + x3i; a[7] = x1i - x3r; } void cftf162(double *a, double *w) { double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; wn4r = w[1]; wk1r = w[4]; wk1i = w[5]; wk3r = w[6]; wk3i = -w[7]; wk2r = w[8]; wk2i = w[9]; x1r = a[0] - a[17]; x1i = a[1] + a[16]; x0r = a[8] - a[25]; x0i = a[9] + a[24]; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); y0r = x1r + x2r; y0i = x1i + x2i; y4r = x1r - x2r; y4i = x1i - x2i; x1r = a[0] + a[17]; x1i = a[1] - a[16]; x0r = a[8] + a[25]; x0i = a[9] - a[24]; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); y8r = x1r - x2i; y8i = x1i + x2r; y12r = x1r + x2i; y12i = x1i - x2r; x0r = a[2] - a[19]; x0i = a[3] + a[18]; x1r = wk1r * x0r - wk1i * x0i; x1i = wk1r * x0i + wk1i * x0r; x0r = a[10] - a[27]; x0i = a[11] + a[26]; x2r = wk3i * x0r - wk3r * x0i; x2i = wk3i * x0i + wk3r * x0r; y1r = x1r + x2r; y1i = x1i + x2i; y5r = x1r - x2r; y5i = x1i - x2i; x0r = a[2] + a[19]; x0i = a[3] - a[18]; x1r = wk3r * x0r - wk3i * x0i; x1i = wk3r * x0i + wk3i * x0r; x0r = a[10] + a[27]; x0i = a[11] - a[26]; x2r = wk1r * x0r + wk1i * x0i; x2i = wk1r * x0i - wk1i * x0r; y9r = x1r - x2r; y9i = x1i - x2i; y13r = x1r + x2r; y13i = x1i + x2i; x0r = a[4] - a[21]; x0i = a[5] + a[20]; x1r = wk2r * x0r - wk2i * x0i; x1i = wk2r * x0i + wk2i * x0r; x0r = a[12] - a[29]; x0i = a[13] + a[28]; x2r = wk2i * x0r - wk2r * x0i; x2i = wk2i * x0i + wk2r * x0r; y2r = x1r + x2r; y2i = x1i + x2i; y6r = x1r - x2r; y6i = x1i - x2i; x0r = a[4] + a[21]; x0i = a[5] - a[20]; x1r = wk2i * x0r - wk2r * x0i; x1i = wk2i * x0i + wk2r * x0r; x0r = a[12] + a[29]; x0i = a[13] - a[28]; x2r = wk2r * x0r - wk2i * x0i; x2i = wk2r * x0i + wk2i * x0r; y10r = x1r - x2r; y10i = x1i - x2i; y14r = x1r + x2r; y14i = x1i + x2i; x0r = a[6] - a[23]; x0i = a[7] + a[22]; x1r = wk3r * x0r - wk3i * x0i; x1i = wk3r * x0i + wk3i * x0r; x0r = a[14] - a[31]; x0i = a[15] + a[30]; x2r = wk1i * x0r - wk1r * x0i; x2i = wk1i * x0i + wk1r * x0r; y3r = x1r + x2r; y3i = x1i + x2i; y7r = x1r - x2r; y7i = x1i - x2i; x0r = a[6] + a[23]; x0i = a[7] - a[22]; x1r = wk1i * x0r + wk1r * x0i; x1i = wk1i * x0i - wk1r * x0r; x0r = a[14] + a[31]; x0i = a[15] - a[30]; x2r = wk3i * x0r - wk3r * x0i; x2i = wk3i * x0i + wk3r * x0r; y11r = x1r + x2r; y11i = x1i + x2i; y15r = x1r - x2r; y15i = x1i - x2i; x1r = y0r + y2r; x1i = y0i + y2i; x2r = y1r + y3r; x2i = y1i + y3i; a[0] = x1r + x2r; a[1] = x1i + x2i; a[2] = x1r - x2r; a[3] = x1i - x2i; x1r = y0r - y2r; x1i = y0i - y2i; x2r = y1r - y3r; x2i = y1i - y3i; a[4] = x1r - x2i; a[5] = x1i + x2r; a[6] = x1r + x2i; a[7] = x1i - x2r; x1r = y4r - y6i; x1i = y4i + y6r; x0r = y5r - y7i; x0i = y5i + y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[8] = x1r + x2r; a[9] = x1i + x2i; a[10] = x1r - x2r; a[11] = x1i - x2i; x1r = y4r + y6i; x1i = y4i - y6r; x0r = y5r + y7i; x0i = y5i - y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[12] = x1r - x2i; a[13] = x1i + x2r; a[14] = x1r + x2i; a[15] = x1i - x2r; x1r = y8r + y10r; x1i = y8i + y10i; x2r = y9r - y11r; x2i = y9i - y11i; a[16] = x1r + x2r; a[17] = x1i + x2i; a[18] = x1r - x2r; a[19] = x1i - x2i; x1r = y8r - y10r; x1i = y8i - y10i; x2r = y9r + y11r; x2i = y9i + y11i; a[20] = x1r - x2i; a[21] = x1i + x2r; a[22] = x1r + x2i; a[23] = x1i - x2r; x1r = y12r - y14i; x1i = y12i + y14r; x0r = y13r + y15i; x0i = y13i - y15r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[24] = x1r + x2r; a[25] = x1i + x2i; a[26] = x1r - x2r; a[27] = x1i - x2i; x1r = y12r + y14i; x1i = y12i - y14r; x0r = y13r - y15i; x0i = y13i + y15r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[28] = x1r - x2i; a[29] = x1i + x2r; a[30] = x1r + x2i; a[31] = x1i - x2r; } void cftf081(double *a, double *w) { double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; wn4r = w[1]; x0r = a[0] + a[8]; x0i = a[1] + a[9]; x1r = a[0] - a[8]; x1i = a[1] - a[9]; x2r = a[4] + a[12]; x2i = a[5] + a[13]; x3r = a[4] - a[12]; x3i = a[5] - a[13]; y0r = x0r + x2r; y0i = x0i + x2i; y2r = x0r - x2r; y2i = x0i - x2i; y1r = x1r - x3i; y1i = x1i + x3r; y3r = x1r + x3i; y3i = x1i - x3r; x0r = a[2] + a[10]; x0i = a[3] + a[11]; x1r = a[2] - a[10]; x1i = a[3] - a[11]; x2r = a[6] + a[14]; x2i = a[7] + a[15]; x3r = a[6] - a[14]; x3i = a[7] - a[15]; y4r = x0r + x2r; y4i = x0i + x2i; y6r = x0r - x2r; y6i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; x2r = x1r + x3i; x2i = x1i - x3r; y5r = wn4r * (x0r - x0i); y5i = wn4r * (x0r + x0i); y7r = wn4r * (x2r - x2i); y7i = wn4r * (x2r + x2i); a[8] = y1r + y5r; a[9] = y1i + y5i; a[10] = y1r - y5r; a[11] = y1i - y5i; a[12] = y3r - y7i; a[13] = y3i + y7r; a[14] = y3r + y7i; a[15] = y3i - y7r; a[0] = y0r + y4r; a[1] = y0i + y4i; a[2] = y0r - y4r; a[3] = y0i - y4i; a[4] = y2r - y6i; a[5] = y2i + y6r; a[6] = y2r + y6i; a[7] = y2i - y6r; } void cftf082(double *a, double *w) { double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; wn4r = w[1]; wk1r = w[2]; wk1i = w[3]; y0r = a[0] - a[9]; y0i = a[1] + a[8]; y1r = a[0] + a[9]; y1i = a[1] - a[8]; x0r = a[4] - a[13]; x0i = a[5] + a[12]; y2r = wn4r * (x0r - x0i); y2i = wn4r * (x0i + x0r); x0r = a[4] + a[13]; x0i = a[5] - a[12]; y3r = wn4r * (x0r - x0i); y3i = wn4r * (x0i + x0r); x0r = a[2] - a[11]; x0i = a[3] + a[10]; y4r = wk1r * x0r - wk1i * x0i; y4i = wk1r * x0i + wk1i * x0r; x0r = a[2] + a[11]; x0i = a[3] - a[10]; y5r = wk1i * x0r - wk1r * x0i; y5i = wk1i * x0i + wk1r * x0r; x0r = a[6] - a[15]; x0i = a[7] + a[14]; y6r = wk1i * x0r - wk1r * x0i; y6i = wk1i * x0i + wk1r * x0r; x0r = a[6] + a[15]; x0i = a[7] - a[14]; y7r = wk1r * x0r - wk1i * x0i; y7i = wk1r * x0i + wk1i * x0r; x0r = y0r + y2r; x0i = y0i + y2i; x1r = y4r + y6r; x1i = y4i + y6i; a[0] = x0r + x1r; a[1] = x0i + x1i; a[2] = x0r - x1r; a[3] = x0i - x1i; x0r = y0r - y2r; x0i = y0i - y2i; x1r = y4r - y6r; x1i = y4i - y6i; a[4] = x0r - x1i; a[5] = x0i + x1r; a[6] = x0r + x1i; a[7] = x0i - x1r; x0r = y1r - y3i; x0i = y1i + y3r; x1r = y5r - y7r; x1i = y5i - y7i; a[8] = x0r + x1r; a[9] = x0i + x1i; a[10] = x0r - x1r; a[11] = x0i - x1i; x0r = y1r + y3i; x0i = y1i - y3r; x1r = y5r + y7r; x1i = y5i + y7i; a[12] = x0r - x1i; a[13] = x0i + x1r; a[14] = x0r + x1i; a[15] = x0i - x1r; } void cftf040(double *a) { double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[4]; x0i = a[1] + a[5]; x1r = a[0] - a[4]; x1i = a[1] - a[5]; x2r = a[2] + a[6]; x2i = a[3] + a[7]; x3r = a[2] - a[6]; x3i = a[3] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x1r - x3i; a[3] = x1i + x3r; a[4] = x0r - x2r; a[5] = x0i - x2i; a[6] = x1r + x3i; a[7] = x1i - x3r; } void cftb040(double *a) { double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[4]; x0i = a[1] + a[5]; x1r = a[0] - a[4]; x1i = a[1] - a[5]; x2r = a[2] + a[6]; x2i = a[3] + a[7]; x3r = a[2] - a[6]; x3i = a[3] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x1r + x3i; a[3] = x1i - x3r; a[4] = x0r - x2r; a[5] = x0i - x2i; a[6] = x1r - x3i; a[7] = x1i + x3r; } void cftx020(double *a) { double x0r, x0i; x0r = a[0] - a[2]; x0i = a[1] - a[3]; a[0] += a[2]; a[1] += a[3]; a[2] = x0r; a[3] = x0i; } void rftfsub(int n, double *a, int nc, double *c) { int j, k, kk, ks, m; double wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5 - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } void rftbsub(int n, double *a, int nc, double *c) { int j, k, kk, ks, m; double wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5 - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr + wki * xi; yi = wkr * xi - wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } void dctsub(int n, double *a, int nc, double *c) { int j, k, kk, ks, m; double wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[j] - wkr * a[k]; a[j] = wkr * a[j] + wki * a[k]; a[k] = xr; } a[m] *= c[0]; } void dstsub(int n, double *a, int nc, double *c) { int j, k, kk, ks, m; double wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[k] - wkr * a[j]; a[k] = wkr * a[k] + wki * a[j]; a[j] = xr; } a[m] *= c[0]; } ================================================ FILE: libsvc/Modules/Lib/World/src/harvest.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // F0 estimation based on Harvest. //----------------------------------------------------------------------------- #include "world/harvest.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/fft.h" #include "world/matlabfunctions.h" //----------------------------------------------------------------------------- // struct for RawEventByHarvest() // "negative" means "zero-crossing point going from positive to negative" // "positive" means "zero-crossing point going from negative to positive" //----------------------------------------------------------------------------- typedef struct { double *negative_interval_locations; double *negative_intervals; int number_of_negatives; double *positive_interval_locations; double *positive_intervals; int number_of_positives; double *peak_interval_locations; double *peak_intervals; int number_of_peaks; double *dip_interval_locations; double *dip_intervals; int number_of_dips; } ZeroCrossings; namespace { //----------------------------------------------------------------------------- // Since the waveform of beginning and ending after decimate include noise, // the input waveform is extended. This is the processing for the // compatibility with MATLAB version. //----------------------------------------------------------------------------- static void GetWaveformAndSpectrumSub(const double *x, int x_length, int y_length, double actual_fs, int decimation_ratio, double *y) { if (decimation_ratio == 1) { for (int i = 0; i < x_length; ++i) y[i] = x[i]; return; } int lag = static_cast(ceil(140.0 / decimation_ratio) * decimation_ratio); int new_x_length = x_length + lag * 2; double *new_y = new double[new_x_length]; for (int i = 0; i < new_x_length; ++i) new_y[i] = 0.0; double *new_x = new double[new_x_length]; for (int i = 0; i < lag; ++i) new_x[i] = x[0]; for (int i = lag; i < lag + x_length; ++i) new_x[i] = x[i - lag]; for (int i = lag + x_length; i < new_x_length; ++i) new_x[i] = x[x_length - 1]; decimate(new_x, new_x_length, decimation_ratio, new_y); for (int i = 0; i < y_length; ++i) y[i] = new_y[lag / decimation_ratio + i]; delete[] new_x; delete[] new_y; } //----------------------------------------------------------------------------- // GetWaveformAndSpectrum() calculates the downsampled signal and its spectrum //----------------------------------------------------------------------------- static void GetWaveformAndSpectrum(const double *x, int x_length, int y_length, double actual_fs, int fft_size, int decimation_ratio, double *y, fft_complex *y_spectrum) { // Initialization for (int i = 0; i < fft_size; ++i) y[i] = 0.0; // Processing for the compatibility with MATLAB version GetWaveformAndSpectrumSub(x, x_length, y_length, actual_fs, decimation_ratio, y); // Removal of the DC component (y = y - mean value of y) double mean_y = 0.0; for (int i = 0; i < y_length; ++i) mean_y += y[i]; mean_y /= y_length; for (int i = 0; i < y_length; ++i) y[i] -= mean_y; for (int i = y_length; i < fft_size; ++i) y[i] = 0.0; fft_plan forwardFFT = fft_plan_dft_r2c_1d(fft_size, y, y_spectrum, FFT_ESTIMATE); fft_execute(forwardFFT); fft_destroy_plan(forwardFFT); } //----------------------------------------------------------------------------- // GetFilteredSignal() calculates the signal that is the convolution of the // input signal and band-pass filter. //----------------------------------------------------------------------------- static void GetFilteredSignal(double boundary_f0, int fft_size, double fs, const fft_complex *y_spectrum, int y_length, double *filtered_signal) { int filter_length_half = matlab_round(fs / boundary_f0 * 2.0); double *band_pass_filter = new double[fft_size]; NuttallWindow(filter_length_half * 2 + 1, band_pass_filter); for (int i = -filter_length_half; i <= filter_length_half; ++i) band_pass_filter[i + filter_length_half] *= cos(2 * world::kPi * boundary_f0 * i / fs); for (int i = filter_length_half * 2 + 1; i < fft_size; ++i) band_pass_filter[i] = 0.0; fft_complex *band_pass_filter_spectrum = new fft_complex[fft_size]; fft_plan forwardFFT = fft_plan_dft_r2c_1d(fft_size, band_pass_filter, band_pass_filter_spectrum, FFT_ESTIMATE); fft_execute(forwardFFT); // Convolution double tmp = y_spectrum[0][0] * band_pass_filter_spectrum[0][0] - y_spectrum[0][1] * band_pass_filter_spectrum[0][1]; band_pass_filter_spectrum[0][1] = y_spectrum[0][0] * band_pass_filter_spectrum[0][1] + y_spectrum[0][1] * band_pass_filter_spectrum[0][0]; band_pass_filter_spectrum[0][0] = tmp; for (int i = 1; i <= fft_size / 2; ++i) { tmp = y_spectrum[i][0] * band_pass_filter_spectrum[i][0] - y_spectrum[i][1] * band_pass_filter_spectrum[i][1]; band_pass_filter_spectrum[i][1] = y_spectrum[i][0] * band_pass_filter_spectrum[i][1] + y_spectrum[i][1] * band_pass_filter_spectrum[i][0]; band_pass_filter_spectrum[i][0] = tmp; band_pass_filter_spectrum[fft_size - i - 1][0] = band_pass_filter_spectrum[i][0]; band_pass_filter_spectrum[fft_size - i - 1][1] = band_pass_filter_spectrum[i][1]; } fft_plan inverseFFT = fft_plan_dft_c2r_1d(fft_size, band_pass_filter_spectrum, filtered_signal, FFT_ESTIMATE); fft_execute(inverseFFT); // Compensation of the delay. int index_bias = filter_length_half + 1; for (int i = 0; i < y_length; ++i) filtered_signal[i] = filtered_signal[i + index_bias]; fft_destroy_plan(inverseFFT); fft_destroy_plan(forwardFFT); delete[] band_pass_filter_spectrum; delete[] band_pass_filter; } //----------------------------------------------------------------------------- // CheckEvent() returns 1, provided that the input value is over 1. // This function is for RawEventByDio(). //----------------------------------------------------------------------------- static inline int CheckEvent(int x) { return x > 0 ? 1 : 0; } //----------------------------------------------------------------------------- // ZeroCrossingEngine() calculates the zero crossing points from positive to // negative. //----------------------------------------------------------------------------- static int ZeroCrossingEngine(const double *filtered_signal, int y_length, double fs, double *interval_locations, double *intervals) { int *negative_going_points = new int[y_length]; for (int i = 0; i < y_length - 1; ++i) negative_going_points[i] = 0.0 < filtered_signal[i] && filtered_signal[i + 1] <= 0.0 ? i + 1 : 0; negative_going_points[y_length - 1] = 0; int *edges = new int[y_length]; int count = 0; for (int i = 0; i < y_length; ++i) if (negative_going_points[i] > 0) edges[count++] = negative_going_points[i]; if (count < 2) { delete[] edges; delete[] negative_going_points; return 0; } double *fine_edges = new double[count]; for (int i = 0; i < count; ++i) fine_edges[i] = edges[i] - filtered_signal[edges[i] - 1] / (filtered_signal[edges[i]] - filtered_signal[edges[i] - 1]); for (int i = 0; i < count - 1; ++i) { intervals[i] = fs / (fine_edges[i + 1] - fine_edges[i]); interval_locations[i] = (fine_edges[i] + fine_edges[i + 1]) / 2.0 / fs; } delete[] fine_edges; delete[] edges; delete[] negative_going_points; return count - 1; } //----------------------------------------------------------------------------- // GetFourZeroCrossingIntervals() calculates four zero-crossing intervals. // (1) Zero-crossing going from negative to positive. // (2) Zero-crossing going from positive to negative. // (3) Peak, and (4) dip. (3) and (4) are calculated from the zero-crossings of // the differential of waveform. //----------------------------------------------------------------------------- static void GetFourZeroCrossingIntervals(double *filtered_signal, int y_length, double actual_fs, ZeroCrossings *zero_crossings) { int maximum_number = y_length; zero_crossings->negative_interval_locations = new double[maximum_number]; zero_crossings->positive_interval_locations = new double[maximum_number]; zero_crossings->peak_interval_locations = new double[maximum_number]; zero_crossings->dip_interval_locations = new double[maximum_number]; zero_crossings->negative_intervals = new double[maximum_number]; zero_crossings->positive_intervals = new double[maximum_number]; zero_crossings->peak_intervals = new double[maximum_number]; zero_crossings->dip_intervals = new double[maximum_number]; zero_crossings->number_of_negatives = ZeroCrossingEngine(filtered_signal, y_length, actual_fs, zero_crossings->negative_interval_locations, zero_crossings->negative_intervals); for (int i = 0; i < y_length; ++i) filtered_signal[i] = -filtered_signal[i]; zero_crossings->number_of_positives = ZeroCrossingEngine(filtered_signal, y_length, actual_fs, zero_crossings->positive_interval_locations, zero_crossings->positive_intervals); for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] = filtered_signal[i] - filtered_signal[i + 1]; zero_crossings->number_of_peaks = ZeroCrossingEngine(filtered_signal, y_length - 1, actual_fs, zero_crossings->peak_interval_locations, zero_crossings->peak_intervals); for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] = -filtered_signal[i]; zero_crossings->number_of_dips = ZeroCrossingEngine(filtered_signal, y_length - 1, actual_fs, zero_crossings->dip_interval_locations, zero_crossings->dip_intervals); } static void GetF0CandidateContourSub(const double * const *interpolated_f0_set, int f0_length, double f0_floor, double f0_ceil, double boundary_f0, double *f0_candidate) { double upper = boundary_f0 * 1.1; double lower = boundary_f0 * 0.9; for (int i = 0; i < f0_length; ++i) { f0_candidate[i] = (interpolated_f0_set[0][i] + interpolated_f0_set[1][i] + interpolated_f0_set[2][i] + interpolated_f0_set[3][i]) / 4.0; if (f0_candidate[i] > upper || f0_candidate[i] < lower || f0_candidate[i] > f0_ceil || f0_candidate[i] < f0_floor) f0_candidate[i] = 0.0; } } //----------------------------------------------------------------------------- // GetF0CandidateContour() calculates the F0 candidate contour in 1-ch signal. // Calculation of F0 candidates is carried out in GetF0CandidatesSub(). //----------------------------------------------------------------------------- static void GetF0CandidateContour(const ZeroCrossings *zero_crossings, double boundary_f0, double f0_floor, double f0_ceil, const double *temporal_positions, int f0_length, double *f0_candidate) { if (0 == CheckEvent(zero_crossings->number_of_negatives - 2) * CheckEvent(zero_crossings->number_of_positives - 2) * CheckEvent(zero_crossings->number_of_peaks - 2) * CheckEvent(zero_crossings->number_of_dips - 2)) { for (int i = 0; i < f0_length; ++i) f0_candidate[i] = 0.0; return; } double *interpolated_f0_set[4]; for (int i = 0; i < 4; ++i) interpolated_f0_set[i] = new double[f0_length]; interp1(zero_crossings->negative_interval_locations, zero_crossings->negative_intervals, zero_crossings->number_of_negatives, temporal_positions, f0_length, interpolated_f0_set[0]); interp1(zero_crossings->positive_interval_locations, zero_crossings->positive_intervals, zero_crossings->number_of_positives, temporal_positions, f0_length, interpolated_f0_set[1]); interp1(zero_crossings->peak_interval_locations, zero_crossings->peak_intervals, zero_crossings->number_of_peaks, temporal_positions, f0_length, interpolated_f0_set[2]); interp1(zero_crossings->dip_interval_locations, zero_crossings->dip_intervals, zero_crossings->number_of_dips, temporal_positions, f0_length, interpolated_f0_set[3]); GetF0CandidateContourSub(interpolated_f0_set, f0_length, f0_floor, f0_ceil, boundary_f0, f0_candidate); for (int i = 0; i < 4; ++i) delete[] interpolated_f0_set[i]; } //----------------------------------------------------------------------------- // DestroyZeroCrossings() frees the memory of array in the struct //----------------------------------------------------------------------------- static void DestroyZeroCrossings(ZeroCrossings *zero_crossings) { delete[] zero_crossings->negative_interval_locations; delete[] zero_crossings->positive_interval_locations; delete[] zero_crossings->peak_interval_locations; delete[] zero_crossings->dip_interval_locations; delete[] zero_crossings->negative_intervals; delete[] zero_crossings->positive_intervals; delete[] zero_crossings->peak_intervals; delete[] zero_crossings->dip_intervals; } //----------------------------------------------------------------------------- // GetF0CandidateFromRawEvent() f0 candidate contour in 1-ch signal //----------------------------------------------------------------------------- static void GetF0CandidateFromRawEvent(double boundary_f0, double fs, const fft_complex *y_spectrum, int y_length, int fft_size, double f0_floor, double f0_ceil, const double *temporal_positions, int f0_length, double *f0_candidate) { double *filtered_signal = new double[fft_size]; GetFilteredSignal(boundary_f0, fft_size, fs, y_spectrum, y_length, filtered_signal); ZeroCrossings zero_crossings = { 0 }; GetFourZeroCrossingIntervals(filtered_signal, y_length, fs, &zero_crossings); GetF0CandidateContour(&zero_crossings, boundary_f0, f0_floor, f0_ceil, temporal_positions, f0_length, f0_candidate); DestroyZeroCrossings(&zero_crossings); delete[] filtered_signal; } //----------------------------------------------------------------------------- // GetRawF0Candidates() calculates f0 candidates in all channels. //----------------------------------------------------------------------------- static void GetRawF0Candidates(const double *boundary_f0_list, int number_of_bands, double actual_fs, int y_length, const double *temporal_positions, int f0_length, const fft_complex *y_spectrum, int fft_size, double f0_floor, double f0_ceil, double **raw_f0_candidates) { for (int i = 0; i < number_of_bands; ++i) GetF0CandidateFromRawEvent(boundary_f0_list[i], actual_fs, y_spectrum, y_length, fft_size, f0_floor, f0_ceil, temporal_positions, f0_length, raw_f0_candidates[i]); } //----------------------------------------------------------------------------- // DetectF0CandidatesSub1() calculates VUV areas. //----------------------------------------------------------------------------- static int DetectOfficialF0CandidatesSub1(const int *vuv, int number_of_channels, int *st, int *ed) { int number_of_voiced_sections = 0; int tmp; for (int i = 1; i < number_of_channels; ++i) { tmp = vuv[i] - vuv[i - 1]; if (tmp == 1) st[number_of_voiced_sections] = i; if (tmp == -1) ed[number_of_voiced_sections++] = i; } return number_of_voiced_sections; } //----------------------------------------------------------------------------- // DetectOfficialF0CandidatesSub2() calculates F0 candidates in a frame //----------------------------------------------------------------------------- static int DetectOfficialF0CandidatesSub2(const int *vuv, const double * const *raw_f0_candidates, int index, int number_of_voiced_sections, const int *st, const int *ed, int max_candidates, double *f0_list) { int number_of_candidates = 0; double tmp_f0; for (int i = 0; i < number_of_voiced_sections; ++i) { if (ed[i] - st[i] < 10) continue; tmp_f0 = 0.0; for (int j = st[i]; j < ed[i]; ++j) tmp_f0 += raw_f0_candidates[j][index]; tmp_f0 /= (ed[i] - st[i]); f0_list[number_of_candidates++] = tmp_f0; } for (int i = number_of_candidates; i < max_candidates; ++i) f0_list[i] = 0.0; return number_of_candidates; } //----------------------------------------------------------------------------- // DetectOfficialF0Candidates() detectes F0 candidates from multi-channel // candidates. //----------------------------------------------------------------------------- static int DetectOfficialF0Candidates(const double * const * raw_f0_candidates, int number_of_channels, int f0_length, int max_candidates, double **f0_candidates) { int number_of_candidates = 0; int *vuv = new int[number_of_channels]; int *st = new int[number_of_channels]; int *ed = new int[number_of_channels]; int number_of_voiced_sections; for (int i = 0; i < f0_length; ++i) { for (int j = 0; j < number_of_channels; ++j) vuv[j] = raw_f0_candidates[j][i] > 0 ? 1 : 0; vuv[0] = vuv[number_of_channels - 1] = 0; number_of_voiced_sections = DetectOfficialF0CandidatesSub1(vuv, number_of_channels, st, ed); number_of_candidates = MyMaxInt(number_of_candidates, DetectOfficialF0CandidatesSub2(vuv, raw_f0_candidates, i, number_of_voiced_sections, st, ed, max_candidates, f0_candidates[i])); } delete[] vuv; delete[] st; delete[] ed; return number_of_candidates; } //----------------------------------------------------------------------------- // OverlapF0Candidates() spreads the candidates to anteroposterior frames. //----------------------------------------------------------------------------- static void OverlapF0Candidates(int f0_length, int number_of_candidates, double **f0_candidates) { int n = 3; for (int i = 1; i <= n; ++i) for (int j = 0; j < number_of_candidates; ++j) { for (int k = i; k < f0_length; ++k) f0_candidates[k][j + (number_of_candidates * i)] = f0_candidates[k - i][j]; for (int k = 0; k < f0_length - i; ++k) f0_candidates[k][j + (number_of_candidates * (i + n))] = f0_candidates[k + i][j]; } } //----------------------------------------------------------------------------- // GetBaseIndex() calculates the temporal positions for windowing. //----------------------------------------------------------------------------- static void GetBaseIndex(double current_position, const double *base_time, int base_time_length, double fs, int *base_index) { // First-aid treatment int basic_index = matlab_round((current_position + base_time[0]) * fs + 0.001); for (int i = 0; i < base_time_length; ++i) base_index[i] = basic_index + i; } //----------------------------------------------------------------------------- // GetMainWindow() generates the window function. //----------------------------------------------------------------------------- static void GetMainWindow(double current_position, const int *base_index, int base_time_length, double fs, double window_length_in_time, double *main_window) { double tmp = 0.0; for (int i = 0; i < base_time_length; ++i) { tmp = (base_index[i] - 1.0) / fs - current_position; main_window[i] = 0.42 + 0.5 * cos(2.0 * world::kPi * tmp / window_length_in_time) + 0.08 * cos(4.0 * world::kPi * tmp / window_length_in_time); } } //----------------------------------------------------------------------------- // GetDiffWindow() generates the differentiated window. // Diff means differential. //----------------------------------------------------------------------------- static void GetDiffWindow(const double *main_window, int base_time_length, double *diff_window) { diff_window[0] = -main_window[1] / 2.0; for (int i = 1; i < base_time_length - 1; ++i) diff_window[i] = -(main_window[i + 1] - main_window[i - 1]) / 2.0; diff_window[base_time_length - 1] = main_window[base_time_length - 2] / 2.0; } //----------------------------------------------------------------------------- // GetSpectra() calculates two spectra of the waveform windowed by windows // (main window and diff window). //----------------------------------------------------------------------------- static void GetSpectra(const double *x, int x_length, int fft_size, const int *base_index, const double *main_window, const double *diff_window, int base_time_length, const ForwardRealFFT *forward_real_fft, fft_complex *main_spectrum, fft_complex *diff_spectrum) { int *safe_index = new int[base_time_length]; for (int i = 0; i < base_time_length; ++i) safe_index[i] = MyMaxInt(0, MyMinInt(x_length - 1, base_index[i] - 1)); for (int i = 0; i < base_time_length; ++i) forward_real_fft->waveform[i] = x[safe_index[i]] * main_window[i]; for (int i = base_time_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { main_spectrum[i][0] = forward_real_fft->spectrum[i][0]; main_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } for (int i = 0; i < base_time_length; ++i) forward_real_fft->waveform[i] = x[safe_index[i]] * diff_window[i]; for (int i = base_time_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { diff_spectrum[i][0] = forward_real_fft->spectrum[i][0]; diff_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } delete[] safe_index; } static void FixF0(const double *power_spectrum, const double *numerator_i, int fft_size, double fs, double current_f0, int number_of_harmonics, double *refined_f0, double *score) { double *amplitude_list = new double[number_of_harmonics]; double *instantaneous_frequency_list = new double[number_of_harmonics]; int index; for (int i = 0; i < number_of_harmonics; ++i) { index = matlab_round(current_f0 * fft_size / fs * (i + 1)); instantaneous_frequency_list[i] = power_spectrum[index] == 0.0 ? 0.0 : static_cast(index) * fs / fft_size + numerator_i[index] / power_spectrum[index] * fs / 2.0 / world::kPi; amplitude_list[i] = sqrt(power_spectrum[index]); } double denominator = 0.0; double numerator = 0.0; *score = 0.0; for (int i = 0; i < number_of_harmonics; ++i) { numerator += amplitude_list[i] * instantaneous_frequency_list[i]; denominator += amplitude_list[i] * (i + 1.0); *score += fabs((instantaneous_frequency_list[i] / (i + 1.0) - current_f0) / current_f0); } *refined_f0 = numerator / (denominator + world::kMySafeGuardMinimum); *score = 1.0 / (*score / number_of_harmonics + world::kMySafeGuardMinimum); delete[] amplitude_list; delete[] instantaneous_frequency_list; } //----------------------------------------------------------------------------- // GetMeanF0() calculates the instantaneous frequency. //----------------------------------------------------------------------------- static void GetMeanF0(const double *x, int x_length, double fs, double current_position, double current_f0, int fft_size, double window_length_in_time, const double *base_time, int base_time_length, double *refined_f0, double *refined_score) { ForwardRealFFT forward_real_fft = { 0 }; InitializeForwardRealFFT(fft_size, &forward_real_fft); fft_complex *main_spectrum = new fft_complex[fft_size]; fft_complex *diff_spectrum = new fft_complex[fft_size]; int *base_index = new int[base_time_length]; double *main_window = new double[base_time_length]; double *diff_window = new double[base_time_length]; GetBaseIndex(current_position, base_time, base_time_length, fs, base_index); GetMainWindow(current_position, base_index, base_time_length, fs, window_length_in_time, main_window); GetDiffWindow(main_window, base_time_length, diff_window); GetSpectra(x, x_length, fft_size, base_index, main_window, diff_window, base_time_length, &forward_real_fft, main_spectrum, diff_spectrum); double *power_spectrum = new double[fft_size / 2 + 1]; double *numerator_i = new double[fft_size / 2 + 1]; for (int j = 0; j <= fft_size / 2; ++j) { numerator_i[j] = main_spectrum[j][0] * diff_spectrum[j][1] - main_spectrum[j][1] * diff_spectrum[j][0]; power_spectrum[j] = main_spectrum[j][0] * main_spectrum[j][0] + main_spectrum[j][1] * main_spectrum[j][1]; } int number_of_harmonics = MyMinInt(static_cast(fs / 2.0 / current_f0), 6); FixF0(power_spectrum, numerator_i, fft_size, fs, current_f0, number_of_harmonics, refined_f0, refined_score); delete[] diff_spectrum; delete[] diff_window; delete[] main_window; delete[] base_index; delete[] numerator_i; delete[] power_spectrum; delete[] main_spectrum; DestroyForwardRealFFT(&forward_real_fft); } //----------------------------------------------------------------------------- // GetRefinedF0() calculates F0 and its score based on instantaneous frequency. //----------------------------------------------------------------------------- static void GetRefinedF0(const double *x, int x_length, double fs, double current_position, double current_f0, double f0_floor, double f0_ceil, double *refined_f0, double *refined_score) { if (current_f0 <= 0.0) { *refined_f0 = 0.0; *refined_score = 0.0; return; } int half_window_length = static_cast(1.5 * fs / current_f0 + 1.0); double window_length_in_time = (2.0 * half_window_length + 1.0) / fs; double *base_time = new double[half_window_length * 2 + 1]; for (int i = 0; i < half_window_length * 2 + 1; i++) base_time[i] = (-half_window_length + i) / fs; int fft_size = static_cast(pow(2.0, 2.0 + static_cast(log(half_window_length * 2.0 + 1.0) / world::kLog2))); GetMeanF0(x, x_length, fs, current_position, current_f0, fft_size, window_length_in_time, base_time, half_window_length * 2 + 1, refined_f0, refined_score); if (*refined_f0 < f0_floor || *refined_f0 > f0_ceil || *refined_score < 2.5) { *refined_f0 = 0.0; *refined_score = 0.0; } delete[] base_time; } //----------------------------------------------------------------------------- // RefineF0() modifies the F0 by instantaneous frequency. //----------------------------------------------------------------------------- static void RefineF0Candidates(const double *x, int x_length, double fs, const double *temporal_positions, int f0_length, int max_candidates, double f0_floor, double f0_ceil, double **refined_f0_candidates, double **f0_scores) { for (int i = 0; i < f0_length; i++) for (int j = 0; j < max_candidates; ++j) GetRefinedF0(x, x_length, fs, temporal_positions[i], refined_f0_candidates[i][j], f0_floor, f0_ceil, &refined_f0_candidates[i][j], &f0_scores[i][j]); } //----------------------------------------------------------------------------- // SelectBestF0() obtains the nearlest F0 in reference_f0. //----------------------------------------------------------------------------- static double SelectBestF0(double reference_f0, const double *f0_candidates, int number_of_candidates, double allowed_range, double *best_error) { double best_f0 = 0.0; *best_error = allowed_range; double tmp; for (int i = 0; i < number_of_candidates; ++i) { tmp = fabs(reference_f0 - f0_candidates[i]) / reference_f0; if (tmp > *best_error) continue; best_f0 = f0_candidates[i]; *best_error = tmp; } return best_f0; } static void RemoveUnreliableCandidatesSub(int i, int j, const double * const *tmp_f0_candidates, int number_of_candidates, double **f0_candidates, double **f0_scores) { double reference_f0 = f0_candidates[i][j]; double error1, error2, min_error; double threshold = 0.05; if (reference_f0 == 0) return; SelectBestF0(reference_f0, tmp_f0_candidates[i + 1], number_of_candidates, 1.0, &error1); SelectBestF0(reference_f0, tmp_f0_candidates[i - 1], number_of_candidates, 1.0, &error2); min_error = MyMinDouble(error1, error2); if (min_error <= threshold) return; f0_candidates[i][j] = 0; f0_scores[i][j] = 0; } //----------------------------------------------------------------------------- // RemoveUnreliableCandidates(). //----------------------------------------------------------------------------- static void RemoveUnreliableCandidates(int f0_length, int number_of_candidates, double **f0_candidates, double **f0_scores) { double **tmp_f0_candidates = new double *[f0_length]; for (int i = 0; i < f0_length; ++i) tmp_f0_candidates[i] = new double[number_of_candidates]; for (int i = 0; i < f0_length; ++i) for (int j = 0; j < number_of_candidates; ++j) tmp_f0_candidates[i][j] = f0_candidates[i][j]; for (int i = 1; i < f0_length - 1; ++i) for (int j = 0; j < number_of_candidates; ++j) RemoveUnreliableCandidatesSub(i, j, tmp_f0_candidates, number_of_candidates, f0_candidates, f0_scores); for (int i = 0; i < f0_length; ++i) delete[] tmp_f0_candidates[i]; delete[] tmp_f0_candidates; } //----------------------------------------------------------------------------- // SearchF0Base() gets the F0 with the highest score. //----------------------------------------------------------------------------- static void SearchF0Base(const double * const *f0_candidates, const double * const *f0_scores, int f0_length, int number_of_candidates, double *base_f0_contour) { double tmp_best_score; for (int i = 0; i < f0_length; ++i) { base_f0_contour[i] = tmp_best_score = 0.0; for (int j = 0; j < number_of_candidates; ++j) if (f0_scores[i][j] > tmp_best_score) { base_f0_contour[i] = f0_candidates[i][j]; tmp_best_score = f0_scores[i][j]; } } } //----------------------------------------------------------------------------- // Step 1: Rapid change of F0 contour is replaced by 0. //----------------------------------------------------------------------------- static void FixStep1(const double *f0_base, int f0_length, double allowed_range, double *f0_step1) { for (int i = 0; i < f0_length; ++i) f0_step1[i] = 0.0; double reference_f0; for (int i = 2; i < f0_length; ++i) { if (f0_base[i] == 0.0) continue; reference_f0 = f0_base[i - 1] * 2 - f0_base[i - 2]; f0_step1[i] = fabs((f0_base[i] - reference_f0) / reference_f0) > allowed_range && fabs((f0_base[i] - f0_base[i - 1])) / f0_base[i - 1] > allowed_range ? 0.0 : f0_base[i]; } } //----------------------------------------------------------------------------- // GetBoundaryList() detects boundaries between voiced and unvoiced sections. //----------------------------------------------------------------------------- static int GetBoundaryList(const double *f0, int f0_length, int *boundary_list) { int number_of_boundaries = 0; int *vuv = new int[f0_length]; for (int i = 0; i < f0_length; ++i) vuv[i] = f0[i] > 0 ? 1 : 0; vuv[0] = vuv[f0_length - 1] = 0; for (int i = 1; i < f0_length; ++i) if (vuv[i] - vuv[i - 1] != 0) { boundary_list[number_of_boundaries] = i - number_of_boundaries % 2; number_of_boundaries++; } delete[] vuv; return number_of_boundaries; } //----------------------------------------------------------------------------- // Step 2: Voiced sections with a short period are removed. //----------------------------------------------------------------------------- static void FixStep2(const double *f0_step1, int f0_length, int voice_range_minimum, double *f0_step2) { for (int i = 0; i < f0_length; ++i) f0_step2[i] = f0_step1[i]; int *boundary_list = new int[f0_length]; int number_of_boundaries = GetBoundaryList(f0_step1, f0_length, boundary_list); for (int i = 0; i < number_of_boundaries / 2; ++i) { if (boundary_list[i * 2 + 1] - boundary_list[i * 2] >= voice_range_minimum) continue; for (int j = boundary_list[i * 2]; j <= boundary_list[(i * 2) + 1]; ++j) f0_step2[j] = 0.0; } delete[] boundary_list; } //----------------------------------------------------------------------------- // GetMultiChannelF0() separates each voiced section into independent channel. //----------------------------------------------------------------------------- static void GetMultiChannelF0(const double *f0, int f0_length, const int *boundary_list, int number_of_boundaries, double **multi_channel_f0) { for (int i = 0; i < number_of_boundaries / 2; ++i) { for (int j = 0; j < boundary_list[i * 2]; ++j) multi_channel_f0[i][j] = 0.0; for (int j = boundary_list[i * 2]; j <= boundary_list[i * 2 + 1]; ++j) multi_channel_f0[i][j] = f0[j]; for (int j = boundary_list[i * 2 + 1] + 1; j < f0_length; ++j) multi_channel_f0[i][j] = 0.0; } } //----------------------------------------------------------------------------- // abs() often causes bugs, an original function is used. //----------------------------------------------------------------------------- static inline int MyAbsInt(int x) { return x > 0 ? x : -x; } //----------------------------------------------------------------------------- // ExtendF0() : The Hand erasing the Space. // The subfunction of Extend(). //----------------------------------------------------------------------------- static int ExtendF0(const double *f0, int f0_length, int origin, int last_point, int shift, const double * const *f0_candidates, int number_of_candidates, double allowed_range, double *extended_f0) { int threshold = 4; double tmp_f0 = extended_f0[origin]; int shifted_origin = origin; int distance = MyAbsInt(last_point - origin); int *index_list = new int[distance + 1]; for (int i = 0; i <= distance; ++i) index_list[i] = origin + shift * i; int count = 0; double dammy; for (int i = 0; i <= distance; ++i) { extended_f0[index_list[i] + shift] = SelectBestF0(tmp_f0, f0_candidates[index_list[i] + shift], number_of_candidates, allowed_range, &dammy); if (extended_f0[index_list[i] + shift] == 0.0) { count++; } else { tmp_f0 = extended_f0[index_list[i] + shift]; count = 0; shifted_origin = index_list[i] + shift; } if (count == threshold) break; } delete[] index_list; return shifted_origin; } //----------------------------------------------------------------------------- // Swap the f0 contour and boundary. // It is used in ExtendSub() and MergeF0(); //----------------------------------------------------------------------------- static void Swap(int index1, int index2, double **f0, int *boundary) { double *tmp_pointer; int tmp_index; tmp_pointer = f0[index1]; f0[index1] = f0[index2]; f0[index2] = tmp_pointer; tmp_index = boundary[index1 * 2]; boundary[index1 * 2] = boundary[index2 * 2]; boundary[index2 * 2] = tmp_index; tmp_index = boundary[index1 * 2 + 1]; boundary[index1 * 2 + 1] = boundary[index2 * 2 + 1]; boundary[index2 * 2 + 1] = tmp_index; } static int ExtendSub(const double * const *extended_f0, const int *boundary_list, int number_of_sections, double **selected_extended_f0, int *selected_boundary_list) { double threshold = 2200.0; int count = 0; double mean_f0 = 0.0; int st, ed; for (int i = 0; i < number_of_sections; ++i) { st = boundary_list[i * 2]; ed = boundary_list[i * 2 + 1]; for (int j = st; j < ed; ++j) mean_f0 += extended_f0[i][j]; mean_f0 /= ed - st; if (threshold / mean_f0 < ed - st) Swap(count++, i, selected_extended_f0, selected_boundary_list); } return count; } //----------------------------------------------------------------------------- // Extend() : The Hand erasing the Space. //----------------------------------------------------------------------------- static int Extend(const double * const *multi_channel_f0, int number_of_sections, int f0_length, const int *boundary_list, const double * const *f0_candidates, int number_of_candidates, double allowed_range, double **extended_f0, int *shifted_boundary_list) { int threshold = 100; for (int i = 0; i < number_of_sections; ++i) { shifted_boundary_list[i * 2 + 1] = ExtendF0(multi_channel_f0[i], f0_length, boundary_list[i * 2 + 1], MyMinInt(f0_length - 2, boundary_list[i * 2 + 1] + threshold), 1, f0_candidates, number_of_candidates, allowed_range, extended_f0[i]); shifted_boundary_list[i * 2] = ExtendF0(multi_channel_f0[i], f0_length, boundary_list[i * 2], MyMaxInt(1, boundary_list[i * 2] - threshold), -1, f0_candidates, number_of_candidates, allowed_range, extended_f0[i]); } return ExtendSub(multi_channel_f0, shifted_boundary_list, number_of_sections, extended_f0, shifted_boundary_list); } //----------------------------------------------------------------------------- // Indices are sorted. //----------------------------------------------------------------------------- static void MakeSortedOrder(const int *boundary_list, int number_of_sections, int *order) { for (int i = 0; i < number_of_sections; ++i) order[i] = i; int tmp; for (int i = 1; i < number_of_sections; ++i) for (int j = i - 1; j >= 0; --j) if (boundary_list[order[j] * 2] > boundary_list[order[i] * 2]) { tmp = order[i]; order[i] = order[j]; order[j] = tmp; } else { break; } } //----------------------------------------------------------------------------- // Serach the highest score with the candidate F0. //----------------------------------------------------------------------------- static double SearchScore(double f0, const double *f0_candidates, const double *f0_scores, int number_of_candidates) { double score = 0.0; for (int i = 0; i < number_of_candidates; ++i) if (f0 == f0_candidates[i] && score < f0_scores[i]) score = f0_scores[i]; return score; } //----------------------------------------------------------------------------- // Subfunction of MergeF0() //----------------------------------------------------------------------------- static int MergeF0Sub(const double *f0_1, int f0_length, int st1, int ed1, const double *f0_2, int st2, int ed2, const double * const *f0_candidates, const double * const *f0_scores, int number_of_candidates, double *merged_f0) { if (st1 <= st2 && ed1 >= ed2) return ed1; double score1 = 0.0; double score2 = 0.0; for (int i = st2; i <= ed1; ++i) { score1 += SearchScore(f0_1[i], f0_candidates[i], f0_scores[i], number_of_candidates); score2 += SearchScore(f0_2[i], f0_candidates[i], f0_scores[i], number_of_candidates); } if (score1 > score2) for (int i = ed1; i <= ed2; ++i) merged_f0[i] = f0_2[i]; else for (int i = st2; i <= ed2; ++i) merged_f0[i] = f0_2[i]; return ed2; } //----------------------------------------------------------------------------- // Overlapped F0 contours are merged by the likability score. //----------------------------------------------------------------------------- static void MergeF0(const double * const *multi_channel_f0, int *boundary_list, int number_of_channels, int f0_length, const double * const *f0_candidates, const double * const *f0_scores, int number_of_candidates, double *merged_f0) { int *order = new int[number_of_channels]; MakeSortedOrder(boundary_list, number_of_channels, order); for (int i = 0; i < f0_length; ++i) merged_f0[i] = multi_channel_f0[0][i]; for (int i = 1; i < number_of_channels; ++i) if (boundary_list[order[i] * 2] - boundary_list[1] > 0) { for (int j = boundary_list[order[i] * 2]; j <= boundary_list[order[i] * 2 + 1]; ++j) merged_f0[j] = multi_channel_f0[order[i]][j]; boundary_list[0] = boundary_list[order[i] * 2]; boundary_list[1] = boundary_list[order[i] * 2 + 1]; } else { boundary_list[1] = MergeF0Sub(merged_f0, f0_length, boundary_list[0], boundary_list[1], multi_channel_f0[order[i]], boundary_list[order[i] * 2], boundary_list[order[i] * 2 + 1], f0_candidates, f0_scores, number_of_candidates, merged_f0); } delete[] order; } //----------------------------------------------------------------------------- // Step 3: Voiced sections are extended based on the continuity of F0 contour //----------------------------------------------------------------------------- static void FixStep3(const double *f0_step2, int f0_length, int number_of_candidates, const double * const *f0_candidates, double allowed_range, const double * const *f0_scores, double *f0_step3) { for (int i = 0; i < f0_length; ++i) f0_step3[i] = f0_step2[i]; int *boundary_list = new int[f0_length]; int number_of_boundaries = GetBoundaryList(f0_step2, f0_length, boundary_list); double **multi_channel_f0 = new double *[number_of_boundaries / 2]; for (int i = 0; i < number_of_boundaries / 2; ++i) multi_channel_f0[i] = new double[f0_length]; GetMultiChannelF0(f0_step2, f0_length, boundary_list, number_of_boundaries, multi_channel_f0); int number_of_channels = Extend(multi_channel_f0, number_of_boundaries / 2, f0_length, boundary_list, f0_candidates, number_of_candidates, allowed_range, multi_channel_f0, boundary_list); if (number_of_channels != 0) MergeF0(multi_channel_f0, boundary_list, number_of_channels, f0_length, f0_candidates, f0_scores, number_of_candidates, f0_step3); for (int i = 0; i < number_of_boundaries / 2; ++i) delete[] multi_channel_f0[i]; delete[] multi_channel_f0; delete[] boundary_list; } //----------------------------------------------------------------------------- // Step 4: F0s in short unvoiced section are faked //----------------------------------------------------------------------------- static void FixStep4(const double *f0_step3, int f0_length, int threshold, double *f0_step4) { for (int i = 0; i < f0_length; ++i) f0_step4[i] = f0_step3[i]; int *boundary_list = new int[f0_length]; int number_of_boundaries = GetBoundaryList(f0_step3, f0_length, boundary_list); int distance; double tmp0, tmp1, coefficient; int count; for (int i = 0; i < number_of_boundaries / 2 - 1; ++i) { distance = boundary_list[(i + 1) * 2] - boundary_list[i * 2 + 1] - 1; if (distance >= threshold) continue; tmp0 = f0_step3[boundary_list[i * 2 + 1]] + 1; tmp1 = f0_step3[boundary_list[(i + 1) * 2]] - 1; coefficient = (tmp1 - tmp0) / (distance + 1.0); count = 1; for (int j = boundary_list[i * 2 + 1] + 1; j <= boundary_list[(i + 1) * 2] - 1; ++j) f0_step4[j] = tmp0 + coefficient * count++; } delete[] boundary_list; } //----------------------------------------------------------------------------- // FixF0Contour() obtains the likely F0 contour. //----------------------------------------------------------------------------- static void FixF0Contour(const double * const *f0_candidates, const double * const *f0_scores, int f0_length, int number_of_candidates, double *best_f0_contour) { double *tmp_f0_contour1 = new double[f0_length]; double *tmp_f0_contour2 = new double[f0_length]; // These parameters are optimized by speech databases. SearchF0Base(f0_candidates, f0_scores, f0_length, number_of_candidates, tmp_f0_contour1); FixStep1(tmp_f0_contour1, f0_length, 0.008, tmp_f0_contour2); FixStep2(tmp_f0_contour2, f0_length, 6, tmp_f0_contour1); FixStep3(tmp_f0_contour1, f0_length, number_of_candidates, f0_candidates, 0.18, f0_scores, tmp_f0_contour2); FixStep4(tmp_f0_contour2, f0_length, 9, best_f0_contour); delete[] tmp_f0_contour1; delete[] tmp_f0_contour2; } //----------------------------------------------------------------------------- // This function uses zero-lag Butterworth filter. //----------------------------------------------------------------------------- static void FilteringF0(const double *a, const double *b, double *x, int x_length, int st, int ed, double *y) { double w[2] = { 0.0, 0.0 }; double wt; double *tmp_x = new double[x_length]; for (int i = 0; i < st; ++i) x[i] = x[st]; for (int i = ed + 1; i < x_length; ++i) x[i] = x[ed]; for (int i = 0; i < x_length; ++i) { wt = x[i] + a[0] * w[0] + a[1] * w[1]; tmp_x[x_length - i - 1] = b[0] * wt + b[1] * w[0] + b[0] * w[1]; w[1] = w[0]; w[0] = wt; } w[0] = w[1] = 0.0; for (int i = 0; i < x_length; ++i) { wt = tmp_x[i] + a[0] * w[0] + a[1] * w[1]; y[x_length - i - 1] = b[0] * wt + b[1] * w[0] + b[0] * w[1]; w[1] = w[0]; w[0] = wt; } delete[] tmp_x; } //----------------------------------------------------------------------------- // SmoothF0Contour() uses the zero-lag Butterworth filter for smoothing. //----------------------------------------------------------------------------- static void SmoothF0Contour(const double *f0, int f0_length, double *smoothed_f0) { const double b[2] = { 0.0078202080334971724, 0.015640416066994345 }; const double a[2] = { 1.7347257688092754, -0.76600660094326412 }; int lag = 300; int new_f0_length = f0_length + lag * 2; double *f0_contour = new double[new_f0_length]; for (int i = 0; i < lag; ++i) f0_contour[i] = 0.0; for (int i = lag; i < lag + f0_length; ++i) f0_contour[i] = f0[i - lag]; for (int i = lag + f0_length; i < new_f0_length; ++i) f0_contour[i] = 0.0; int *boundary_list = new int[new_f0_length]; int number_of_boundaries = GetBoundaryList(f0_contour, new_f0_length, boundary_list); double **multi_channel_f0 = new double *[number_of_boundaries / 2]; for (int i = 0; i < number_of_boundaries / 2; ++i) multi_channel_f0[i] = new double[new_f0_length]; GetMultiChannelF0(f0_contour, new_f0_length, boundary_list, number_of_boundaries, multi_channel_f0); for (int i = 0; i < number_of_boundaries / 2; ++i) { FilteringF0(a, b, multi_channel_f0[i], new_f0_length, boundary_list[i * 2], boundary_list[i * 2 + 1], f0_contour); for (int j = boundary_list[i * 2]; j <= boundary_list[i * 2 + 1]; ++j) smoothed_f0[j - lag] = f0_contour[j]; } for (int i = 0; i < number_of_boundaries / 2; ++i) delete[] multi_channel_f0[i]; delete[] multi_channel_f0; delete[] f0_contour; delete[] boundary_list; } //----------------------------------------------------------------------------- // HarvestGeneralBodySub() is the subfunction of HarvestGeneralBody() //----------------------------------------------------------------------------- static int HarvestGeneralBodySub(const double *boundary_f0_list, int number_of_channels, int f0_length, double actual_fs, int y_length, const double *temporal_positions, const fft_complex *y_spectrum, int fft_size, double f0_floor, double f0_ceil, int max_candidates, double **f0_candidates) { double **raw_f0_candidates = new double *[number_of_channels]; for (int i = 0; i < number_of_channels; ++i) raw_f0_candidates[i] = new double[f0_length]; GetRawF0Candidates(boundary_f0_list, number_of_channels, actual_fs, y_length, temporal_positions, f0_length, y_spectrum, fft_size, f0_floor, f0_ceil, raw_f0_candidates); int number_of_candidates = DetectOfficialF0Candidates(raw_f0_candidates, number_of_channels, f0_length, max_candidates, f0_candidates); OverlapF0Candidates(f0_length, number_of_candidates, f0_candidates); for (int i = 0; i < number_of_channels; ++i) delete[] raw_f0_candidates[i]; delete[] raw_f0_candidates; return number_of_candidates; } //----------------------------------------------------------------------------- // HarvestGeneralBody() estimates the F0 contour based on Harvest. //----------------------------------------------------------------------------- static void HarvestGeneralBody(const double *x, int x_length, int fs, int frame_period, double f0_floor, double f0_ceil, double channels_in_octave, int speed, double *temporal_positions, double *f0) { double adjusted_f0_floor = f0_floor * 0.9; double adjusted_f0_ceil = f0_ceil * 1.1; int number_of_channels = 1 + static_cast(log(adjusted_f0_ceil / adjusted_f0_floor) / world::kLog2 * channels_in_octave); double *boundary_f0_list = new double[number_of_channels]; for (int i = 0; i < number_of_channels; ++i) boundary_f0_list[i] = adjusted_f0_floor * pow(2.0, (i + 1) / channels_in_octave); // normalization int decimation_ratio = MyMaxInt(MyMinInt(speed, 12), 1); int y_length = static_cast(ceil(static_cast(x_length) / decimation_ratio)); double actual_fs = static_cast(fs) / decimation_ratio; int fft_size = GetSuitableFFTSize(y_length + 5 + 2 * static_cast(2.0 * actual_fs / boundary_f0_list[0])); // Calculation of the spectrum used for the f0 estimation double *y = new double[fft_size]; fft_complex *y_spectrum = new fft_complex[fft_size]; GetWaveformAndSpectrum(x, x_length, y_length, actual_fs, fft_size, decimation_ratio, y, y_spectrum); int f0_length = GetSamplesForHarvest(fs, x_length, frame_period); for (int i = 0; i < f0_length; ++i) { temporal_positions[i] = i * frame_period / 1000.0; f0[i] = 0.0; } int overlap_parameter = 7; int max_candidates = matlab_round(number_of_channels / 10.0) * overlap_parameter; double **f0_candidates = new double *[f0_length]; double **f0_candidates_score = new double *[f0_length]; for (int i = 0; i < f0_length; ++i) { f0_candidates[i] = new double[max_candidates]; f0_candidates_score[i] = new double[max_candidates]; } int number_of_candidates = HarvestGeneralBodySub(boundary_f0_list, number_of_channels, f0_length, actual_fs, y_length, temporal_positions, y_spectrum, fft_size, f0_floor, f0_ceil, max_candidates, f0_candidates) * overlap_parameter; RefineF0Candidates(y, y_length, actual_fs, temporal_positions, f0_length, number_of_candidates, f0_floor, f0_ceil, f0_candidates, f0_candidates_score); RemoveUnreliableCandidates(f0_length, number_of_candidates, f0_candidates, f0_candidates_score); double *best_f0_contour = new double[f0_length]; FixF0Contour(f0_candidates, f0_candidates_score, f0_length, number_of_candidates, best_f0_contour); SmoothF0Contour(best_f0_contour, f0_length, f0); delete[] y; delete[] best_f0_contour; delete[] y_spectrum; for (int i = 0; i < f0_length; ++i) { delete[] f0_candidates[i]; delete[] f0_candidates_score[i]; } delete[] f0_candidates; delete[] f0_candidates_score; delete[] boundary_f0_list; } } // namespace int GetSamplesForHarvest(int fs, int x_length, double frame_period) { return static_cast(1000.0 * x_length / fs / frame_period) + 1; } void Harvest(const double *x, int x_length, int fs, const HarvestOption *option, double *temporal_positions, double *f0) { // Several parameters will be controllable for debug. double target_fs = 8000.0; int dimension_ratio = matlab_round(fs / target_fs); double channels_in_octave = 40; if (option->frame_period == 1.0) { HarvestGeneralBody(x, x_length, fs, 1, option->f0_floor, option->f0_ceil, channels_in_octave, dimension_ratio, temporal_positions, f0); return; } int basic_frame_period = 1; int basic_f0_length = GetSamplesForHarvest(fs, x_length, basic_frame_period); double *basic_f0 = new double[basic_f0_length]; double *basic_temporal_positions = new double[basic_f0_length]; HarvestGeneralBody(x, x_length, fs, basic_frame_period, option->f0_floor, option->f0_ceil, channels_in_octave, dimension_ratio, basic_temporal_positions, basic_f0); int f0_length = GetSamplesForHarvest(fs, x_length, option->frame_period); for (int i = 0; i < f0_length; ++i) { temporal_positions[i] = i * option->frame_period / 1000.0; f0[i] = basic_f0[MyMinInt(basic_f0_length - 1, matlab_round(temporal_positions[i] * 1000.0))]; } delete[] basic_f0; delete[] basic_temporal_positions; } void InitializeHarvestOption(HarvestOption *option) { // You can change default parameters. option->f0_ceil = world::kCeilF0; option->f0_floor = world::kFloorF0; option->frame_period = 5; } ================================================ FILE: libsvc/Modules/Lib/World/src/matlabfunctions.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Matlab functions implemented for WORLD // Since these functions are implemented as the same function of Matlab, // the source code does not follow the style guide (Names of variables // and functions). // Please see the reference of Matlab to show the usage of functions. // Caution: // The functions wavread() and wavwrite() were removed to the /src. // they were moved to the test/audioio.cpp. (2016/01/28) //----------------------------------------------------------------------------- #include "world/matlabfunctions.h" #include #include #include "world/constantnumbers.h" namespace { //----------------------------------------------------------------------------- // FilterForDecimate() calculates the coefficients of low-pass filter and // carries out the filtering. This function is only used for decimate(). //----------------------------------------------------------------------------- static void FilterForDecimate(const double *x, int x_length, int r, double *y) { double a[3], b[2]; // filter Coefficients switch (r) { case 11: // fs : 44100 (default) a[0] = 2.450743295230728; a[1] = -2.06794904601978; a[2] = 0.59574774438332101; b[0] = 0.0026822508007163792; b[1] = 0.0080467524021491377; break; case 12: // fs : 48000 a[0] = 2.4981398605924205; a[1] = -2.1368928194784025; a[2] = 0.62187513816221485; b[0] = 0.0021097275904709001; b[1] = 0.0063291827714127002; break; case 10: a[0] = 2.3936475118069387; a[1] = -1.9873904075111861; a[2] = 0.5658879979027055; b[0] = 0.0034818622251927556; b[1] = 0.010445586675578267; break; case 9: a[0] = 2.3236003491759578; a[1] = -1.8921545617463598; a[2] = 0.53148928133729068; b[0] = 0.0046331164041389372; b[1] = 0.013899349212416812; break; case 8: // fs : 32000 a[0] = 2.2357462340187593; a[1] = -1.7780899984041358; a[2] = 0.49152555365968692; b[0] = 0.0063522763407111993; b[1] = 0.019056829022133598; break; case 7: a[0] = 2.1225239019534703; a[1] = -1.6395144861046302; a[2] = 0.44469707800587366; b[0] = 0.0090366882681608418; b[1] = 0.027110064804482525; break; case 6: // fs : 24000 and 22050 a[0] = 1.9715352749512141; a[1] = -1.4686795689225347; a[2] = 0.3893908434965701; b[0] = 0.013469181309343825; b[1] = 0.040407543928031475; break; case 5: a[0] = 1.7610939654280557; a[1] = -1.2554914843859768; a[2] = 0.3237186507788215; b[0] = 0.021334858522387423; b[1] = 0.06400457556716227; break; case 4: // fs : 16000 a[0] = 1.4499664446880227; a[1] = -0.98943497080950582; a[2] = 0.24578252340690215; b[0] = 0.036710750339322612; b[1] = 0.11013225101796784; break; case 3: a[0] = 0.95039378983237421; a[1] = -0.67429146741526791; a[2] = 0.15412211621346475; b[0] = 0.071221945171178636; b[1] = 0.21366583551353591; break; case 2: // fs : 8000 a[0] = 0.041156734567757189; a[1] = -0.42599112459189636; a[2] = 0.041037215479961225; b[0] = 0.16797464681802227; b[1] = 0.50392394045406674; break; default: a[0] = 0.0; a[1] = 0.0; a[2] = 0.0; b[0] = 0.0; b[1] = 0.0; } // Filtering on time domain. double w[3] = {0.0, 0.0, 0.0}; double wt; for (int i = 0; i < x_length; ++i) { wt = x[i] + a[0] * w[0] + a[1] * w[1] + a[2] * w[2]; y[i] = b[0] * wt + b[1] * w[0] + b[1] * w[1] + b[0] * w[2]; w[2] = w[1]; w[1] = w[0]; w[0] = wt; } } } // namespace void fftshift(const double *x, int x_length, double *y) { for (int i = 0; i < x_length / 2; ++i) { y[i] = x[i + x_length / 2]; y[i + x_length / 2] = x[i]; } } void histc(const double *x, int x_length, const double *edges, int edges_length, int *index) { int count = 1; int i = 0; for (; i < edges_length; ++i) { index[i] = 1; if (edges[i] >= x[0]) break; } for (; i < edges_length; ++i) { if (edges[i] < x[count]) { index[i] = count; } else { index[i--] = count++; } if (count == x_length) break; } count--; for (i++; i < edges_length; ++i) index[i] = count; } void interp1(const double *x, const double *y, int x_length, const double *xi, int xi_length, double *yi) { double *h = new double[x_length - 1]; int *k = new int[xi_length]; for (int i = 0; i < x_length - 1; ++i) h[i] = x[i + 1] - x[i]; for (int i = 0; i < xi_length; ++i) { k[i] = 0; } histc(x, x_length, xi, xi_length, k); for (int i = 0; i < xi_length; ++i) { double s = (xi[i] - x[k[i] - 1]) / h[k[i] - 1]; yi[i] = y[k[i] - 1] + s * (y[k[i]] - y[k[i] - 1]); } delete[] k; delete[] h; } void decimate(const double *x, int x_length, int r, double *y) { const int kNFact = 9; double *tmp1 = new double[x_length + kNFact * 2]; double *tmp2 = new double[x_length + kNFact * 2]; for (int i = 0; i < kNFact; ++i) tmp1[i] = 2 * x[0] - x[kNFact - i]; for (int i = kNFact; i < kNFact + x_length; ++i) tmp1[i] = x[i - kNFact]; for (int i = kNFact + x_length; i < 2 * kNFact + x_length; ++i) tmp1[i] = 2 * x[x_length - 1] - x[x_length - 2 - (i - (kNFact + x_length))]; FilterForDecimate(tmp1, 2 * kNFact + x_length, r, tmp2); for (int i = 0; i < 2 * kNFact + x_length; ++i) tmp1[i] = tmp2[2 * kNFact + x_length - i - 1]; FilterForDecimate(tmp1, 2 * kNFact + x_length, r, tmp2); for (int i = 0; i < 2 * kNFact + x_length; ++i) tmp1[i] = tmp2[2 * kNFact + x_length - i - 1]; int nout = (x_length - 1) / r + 1; int nbeg = r - r * nout + x_length; int count = 0; for (int i = nbeg; i < x_length + kNFact; i += r) y[count++] = tmp1[i + kNFact - 1]; delete[] tmp1; delete[] tmp2; } int matlab_round(double x) { return x > 0 ? static_cast(x + 0.5) : static_cast(x - 0.5); } void diff(const double *x, int x_length, double *y) { for (int i = 0; i < x_length - 1; ++i) y[i] = x[i + 1] - x[i]; } void interp1Q(double x, double shift, const double *y, int x_length, const double *xi, int xi_length, double *yi) { double *xi_fraction = new double[xi_length]; double *delta_y = new double[x_length]; int *xi_base = new int[xi_length]; double delta_x = shift; for (int i = 0; i < xi_length; ++i) { xi_base[i] = static_cast((xi[i] - x) / delta_x); xi_fraction[i] = (xi[i] - x) / delta_x - xi_base[i]; } diff(y, x_length, delta_y); delta_y[x_length - 1] = 0.0; for (int i = 0; i < xi_length; ++i) yi[i] = y[xi_base[i]] + delta_y[xi_base[i]] * xi_fraction[i]; // Bug was fixed at 2013/07/14 by M. Morise delete[] xi_fraction; delete[] xi_base; delete[] delta_y; } // You must not use these variables. // Note: // I have no idea to implement the randn() and randn_reseed() without the // global variables. If you have a good idea, please give me the information. static uint32_t g_randn_x = 123456789; static uint32_t g_randn_y = 362436069; static uint32_t g_randn_z = 521288629; static uint32_t g_randn_w = 88675123; void randn_reseed() { g_randn_x = 123456789; g_randn_y = 362436069; g_randn_z = 521288629; g_randn_w = 88675123; } double randn(void) { uint32_t t; t = g_randn_x ^ (g_randn_x << 11); g_randn_x = g_randn_y; g_randn_y = g_randn_z; g_randn_z = g_randn_w; g_randn_w = (g_randn_w ^ (g_randn_w >> 19)) ^ (t ^ (t >> 8)); uint32_t tmp = g_randn_w >> 4; for (int i = 0; i < 11; ++i) { t = g_randn_x ^ (g_randn_x << 11); g_randn_x = g_randn_y; g_randn_y = g_randn_z; g_randn_z = g_randn_w; g_randn_w = (g_randn_w ^ (g_randn_w >> 19)) ^ (t ^ (t >> 8)); tmp += g_randn_w >> 4; } return tmp / 268435456.0 - 6.0; } void fast_fftfilt(const double *x, int x_length, const double *h, int h_length, int fft_size, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, double *y) { fft_complex *x_spectrum = new fft_complex[fft_size]; for (int i = 0; i < x_length; ++i) forward_real_fft->waveform[i] = x[i] / fft_size; for (int i = x_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { x_spectrum[i][0] = forward_real_fft->spectrum[i][0]; x_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } for (int i = 0; i < h_length; ++i) forward_real_fft->waveform[i] = h[i] / fft_size; for (int i = h_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = x_spectrum[i][0] * forward_real_fft->spectrum[i][0] - x_spectrum[i][1] * forward_real_fft->spectrum[i][1]; inverse_real_fft->spectrum[i][1] = x_spectrum[i][0] * forward_real_fft->spectrum[i][1] + x_spectrum[i][1] * forward_real_fft->spectrum[i][0]; } fft_execute(inverse_real_fft->inverse_fft); for (int i = 0; i < fft_size; ++i) y[i] = inverse_real_fft->waveform[i]; delete[] x_spectrum; } double matlab_std(const double *x, int x_length) { double average = 0.0; for (int i = 0; i < x_length; ++i) average += x[i]; average /= x_length; double s = 0.0; for (int i = 0; i < x_length; ++i) s += pow(x[i] - average, 2.0); s /= (x_length - 1); return sqrt(s); } ================================================ FILE: libsvc/Modules/Lib/World/src/stonemask.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // F0 estimation based on instantaneous frequency. // This method is carried out by using the output of Dio(). //----------------------------------------------------------------------------- #include "world/stonemask.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/fft.h" #include "world/matlabfunctions.h" namespace { //----------------------------------------------------------------------------- // GetBaseIndex() calculates the temporal positions for windowing. // Since the result includes negative value and the value that exceeds the // length of the input signal, it must be modified appropriately. //----------------------------------------------------------------------------- static void GetBaseIndex(double current_position, const double *base_time, int base_time_length, int fs, int *index_raw) { for (int i = 0; i < base_time_length; ++i) index_raw[i] = matlab_round((current_position + base_time[i]) * fs); } //----------------------------------------------------------------------------- // GetMainWindow() generates the window function. //----------------------------------------------------------------------------- static void GetMainWindow(double current_position, const int *index_raw, int base_time_length, int fs, double window_length_in_time, double *main_window) { double tmp = 0.0; for (int i = 0; i < base_time_length; ++i) { tmp = (index_raw[i] - 1.0) / fs - current_position; main_window[i] = 0.42 + 0.5 * cos(2.0 * world::kPi * tmp / window_length_in_time) + 0.08 * cos(4.0 * world::kPi * tmp / window_length_in_time); } } //----------------------------------------------------------------------------- // GetDiffWindow() generates the differentiated window. // Diff means differential. //----------------------------------------------------------------------------- static void GetDiffWindow(const double *main_window, int base_time_length, double *diff_window) { diff_window[0] = -main_window[1] / 2.0; for (int i = 1; i < base_time_length - 1; ++i) diff_window[i] = -(main_window[i + 1] - main_window[i - 1]) / 2.0; diff_window[base_time_length - 1] = main_window[base_time_length - 2] / 2.0; } //----------------------------------------------------------------------------- // GetSpectra() calculates two spectra of the waveform windowed by windows // (main window and diff window). //----------------------------------------------------------------------------- static void GetSpectra(const double *x, int x_length, int fft_size, const int *index_raw, const double *main_window, const double *diff_window, int base_time_length, const ForwardRealFFT *forward_real_fft, fft_complex *main_spectrum, fft_complex *diff_spectrum) { int *index = new int[base_time_length]; for (int i = 0; i < base_time_length; ++i) index[i] = MyMaxInt(0, MyMinInt(x_length - 1, index_raw[i] - 1)); for (int i = 0; i < base_time_length; ++i) forward_real_fft->waveform[i] = x[index[i]] * main_window[i]; for (int i = base_time_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { main_spectrum[i][0] = forward_real_fft->spectrum[i][0]; main_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } for (int i = 0; i < base_time_length; ++i) forward_real_fft->waveform[i] = x[index[i]] * diff_window[i]; for (int i = base_time_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { diff_spectrum[i][0] = forward_real_fft->spectrum[i][0]; diff_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } delete[] index; } //----------------------------------------------------------------------------- // FixF0() fixed the F0 by instantaneous frequency. //----------------------------------------------------------------------------- static double FixF0(const double *power_spectrum, const double *numerator_i, int fft_size, int fs, double initial_f0, int number_of_harmonics) { double *amplitude_list = new double[number_of_harmonics]; double *instantaneous_frequency_list = new double[number_of_harmonics]; int index; for (int i = 0; i < number_of_harmonics; ++i) { index = MyMinInt(matlab_round(initial_f0 * fft_size / fs * (i + 1)), fft_size / 2); instantaneous_frequency_list[i] = power_spectrum[index] == 0.0 ? 0.0 : static_cast(index) * fs / fft_size + numerator_i[index] / power_spectrum[index] * fs / 2.0 / world::kPi; amplitude_list[i] = sqrt(power_spectrum[index]); } double denominator = 0.0; double numerator = 0.0; for (int i = 0; i < number_of_harmonics; ++i) { numerator += amplitude_list[i] * instantaneous_frequency_list[i]; denominator += amplitude_list[i] * (i + 1); } delete[] amplitude_list; delete[] instantaneous_frequency_list; return numerator / (denominator + world::kMySafeGuardMinimum); } //----------------------------------------------------------------------------- // GetTentativeF0() calculates the F0 based on the instantaneous frequency. //----------------------------------------------------------------------------- static double GetTentativeF0(const double *power_spectrum, const double *numerator_i, int fft_size, int fs, double initial_f0) { double tentative_f0 = FixF0(power_spectrum, numerator_i, fft_size, fs, initial_f0, 2); // If the fixed value is too large, the result will be rejected. if (tentative_f0 <= 0.0 || tentative_f0 > initial_f0 * 2) return 0.0; return FixF0(power_spectrum, numerator_i, fft_size, fs, tentative_f0, 6); } //----------------------------------------------------------------------------- // GetMeanF0() calculates the instantaneous frequency. //----------------------------------------------------------------------------- static double GetMeanF0(const double *x, int x_length, int fs, double current_position, double initial_f0, int fft_size, double window_length_in_time, const double *base_time, int base_time_length) { ForwardRealFFT forward_real_fft = {0}; InitializeForwardRealFFT(fft_size, &forward_real_fft); fft_complex *main_spectrum = new fft_complex[fft_size]; fft_complex *diff_spectrum = new fft_complex[fft_size]; int *index_raw = new int[base_time_length]; double *main_window = new double[base_time_length]; double *diff_window = new double[base_time_length]; GetBaseIndex(current_position, base_time, base_time_length, fs, index_raw); GetMainWindow(current_position, index_raw, base_time_length, fs, window_length_in_time, main_window); GetDiffWindow(main_window, base_time_length, diff_window); GetSpectra(x, x_length, fft_size, index_raw, main_window, diff_window, base_time_length, &forward_real_fft, main_spectrum, diff_spectrum); double *power_spectrum = new double[fft_size / 2 + 1]; double *numerator_i = new double[fft_size / 2 + 1]; for (int j = 0; j <= fft_size / 2; ++j) { numerator_i[j] = main_spectrum[j][0] * diff_spectrum[j][1] - main_spectrum[j][1] * diff_spectrum[j][0]; power_spectrum[j] = main_spectrum[j][0] * main_spectrum[j][0] + main_spectrum[j][1] * main_spectrum[j][1]; } double tentative_f0 = GetTentativeF0(power_spectrum, numerator_i, fft_size, fs, initial_f0); delete[] diff_spectrum; delete[] diff_window; delete[] main_window; delete[] index_raw; delete[] numerator_i; delete[] power_spectrum; delete[] main_spectrum; DestroyForwardRealFFT(&forward_real_fft); return tentative_f0; } //----------------------------------------------------------------------------- // GetRefinedF0() fixes the F0 estimated by Dio(). This function uses // instantaneous frequency. //----------------------------------------------------------------------------- static double GetRefinedF0(const double *x, int x_length, int fs, double current_potision, double initial_f0) { if (initial_f0 <= world::kFloorF0StoneMask || initial_f0 > fs / 12.0) return 0.0; int half_window_length = static_cast(1.5 * fs / initial_f0 + 1.0); double window_length_in_time = (2.0 * half_window_length + 1.0) / fs; double *base_time = new double[half_window_length * 2 + 1]; for (int i = 0; i < half_window_length * 2 + 1; i++) base_time[i] = static_cast(-half_window_length + i) / fs; int fft_size = static_cast(pow(2.0, 2.0 + static_cast(log(half_window_length * 2.0 + 1.0) / world::kLog2))); double mean_f0 = GetMeanF0(x, x_length, fs, current_potision, initial_f0, fft_size, window_length_in_time, base_time, half_window_length * 2 + 1); // If amount of correction is overlarge (20 %), initial F0 is employed. if (fabs(mean_f0 - initial_f0) > initial_f0 * 0.2) mean_f0 = initial_f0; delete[] base_time; return mean_f0; } } // namespace void StoneMask(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, double *refined_f0) { for (int i = 0; i < f0_length; i++) refined_f0[i] = GetRefinedF0(x, x_length, fs, temporal_positions[i], f0[i]); } ================================================ FILE: libsvc/Modules/Lib/World/src/synthesis.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Voice synthesis based on f0, spectrogram and aperiodicity. // forward_real_fft, inverse_real_fft and minimum_phase are used to speed up. //----------------------------------------------------------------------------- #include "world/synthesis.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { static void GetNoiseSpectrum(int noise_size, int fft_size, const ForwardRealFFT *forward_real_fft) { double average = 0.0; for (int i = 0; i < noise_size; ++i) { forward_real_fft->waveform[i] = randn(); average += forward_real_fft->waveform[i]; } average /= noise_size; for (int i = 0; i < noise_size; ++i) forward_real_fft->waveform[i] -= average; for (int i = noise_size; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); } //----------------------------------------------------------------------------- // GetAperiodicResponse() calculates an aperiodic response. //----------------------------------------------------------------------------- static void GetAperiodicResponse(int noise_size, int fft_size, const double *spectrum, const double *aperiodic_ratio, double current_vuv, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, double *aperiodic_response) { GetNoiseSpectrum(noise_size, fft_size, forward_real_fft); if (current_vuv != 0.0) for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i] * aperiodic_ratio[i]) / 2.0; else for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i]) / 2.0; GetMinimumPhaseSpectrum(minimum_phase); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = minimum_phase->minimum_phase_spectrum[i][0] * forward_real_fft->spectrum[i][0] - minimum_phase->minimum_phase_spectrum[i][1] * forward_real_fft->spectrum[i][1]; inverse_real_fft->spectrum[i][1] = minimum_phase->minimum_phase_spectrum[i][0] * forward_real_fft->spectrum[i][1] + minimum_phase->minimum_phase_spectrum[i][1] * forward_real_fft->spectrum[i][0]; } fft_execute(inverse_real_fft->inverse_fft); fftshift(inverse_real_fft->waveform, fft_size, aperiodic_response); } //----------------------------------------------------------------------------- // RemoveDCComponent() //----------------------------------------------------------------------------- static void RemoveDCComponent(const double *periodic_response, int fft_size, const double *dc_remover, double *new_periodic_response) { double dc_component = 0.0; for (int i = fft_size / 2; i < fft_size; ++i) dc_component += periodic_response[i]; for (int i = 0; i < fft_size / 2; ++i) new_periodic_response[i] = -dc_component * dc_remover[i]; for (int i = fft_size / 2; i < fft_size; ++i) new_periodic_response[i] -= dc_component * dc_remover[i]; } //----------------------------------------------------------------------------- // GetSpectrumWithFractionalTimeShift() calculates a periodic spectrum with // the fractional time shift under 1/fs. //----------------------------------------------------------------------------- static void GetSpectrumWithFractionalTimeShift(int fft_size, double coefficient, const InverseRealFFT *inverse_real_fft) { double re, im, re2, im2; for (int i = 0; i <= fft_size / 2; ++i) { re = inverse_real_fft->spectrum[i][0]; im = inverse_real_fft->spectrum[i][1]; re2 = cos(coefficient * i); im2 = sqrt(1.0 - re2 * re2); // sin(pshift) inverse_real_fft->spectrum[i][0] = re * re2 + im * im2; inverse_real_fft->spectrum[i][1] = im * re2 - re * im2; } } //----------------------------------------------------------------------------- // GetPeriodicResponse() calculates a periodic response. //----------------------------------------------------------------------------- static void GetPeriodicResponse(int fft_size, const double *spectrum, const double *aperiodic_ratio, double current_vuv, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, const double *dc_remover, double fractional_time_shift, int fs, double *periodic_response) { if (current_vuv <= 0.5 || aperiodic_ratio[0] > 0.999) { for (int i = 0; i < fft_size; ++i) periodic_response[i] = 0.0; return; } for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i] * (1.0 - aperiodic_ratio[i]) + world::kMySafeGuardMinimum) / 2.0; GetMinimumPhaseSpectrum(minimum_phase); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = minimum_phase->minimum_phase_spectrum[i][0]; inverse_real_fft->spectrum[i][1] = minimum_phase->minimum_phase_spectrum[i][1]; } // apply fractional time delay of fractional_time_shift seconds // using linear phase shift double coefficient = 2.0 * world::kPi * fractional_time_shift * fs / fft_size; GetSpectrumWithFractionalTimeShift(fft_size, coefficient, inverse_real_fft); fft_execute(inverse_real_fft->inverse_fft); fftshift(inverse_real_fft->waveform, fft_size, periodic_response); RemoveDCComponent(periodic_response, fft_size, dc_remover, periodic_response); } static void GetSpectralEnvelope(double current_time, double frame_period, int f0_length, const double * const *spectrogram, int fft_size, double *spectral_envelope) { int current_frame_floor = MyMinInt(f0_length - 1, static_cast(floor(current_time / frame_period))); int current_frame_ceil = MyMinInt(f0_length - 1, static_cast(ceil(current_time / frame_period))); double interpolation = current_time / frame_period - current_frame_floor; if (current_frame_floor == current_frame_ceil) for (int i = 0; i <= fft_size / 2; ++i) spectral_envelope[i] = fabs(spectrogram[current_frame_floor][i]); else for (int i = 0; i <= fft_size / 2; ++i) spectral_envelope[i] = (1.0 - interpolation) * fabs(spectrogram[current_frame_floor][i]) + interpolation * fabs(spectrogram[current_frame_ceil][i]); } static void GetAperiodicRatio(double current_time, double frame_period, int f0_length, const double * const *aperiodicity, int fft_size, double *aperiodic_spectrum) { int current_frame_floor = MyMinInt(f0_length - 1, static_cast(floor(current_time / frame_period))); int current_frame_ceil = MyMinInt(f0_length - 1, static_cast(ceil(current_time / frame_period))); double interpolation = current_time / frame_period - current_frame_floor; if (current_frame_floor == current_frame_ceil) for (int i = 0; i <= fft_size / 2; ++i) aperiodic_spectrum[i] = pow(GetSafeAperiodicity(aperiodicity[current_frame_floor][i]), 2.0); else for (int i = 0; i <= fft_size / 2; ++i) aperiodic_spectrum[i] = pow((1.0 - interpolation) * GetSafeAperiodicity(aperiodicity[current_frame_floor][i]) + interpolation * GetSafeAperiodicity(aperiodicity[current_frame_ceil][i]), 2.0); } //----------------------------------------------------------------------------- // GetOneFrameSegment() calculates a periodic and aperiodic response at a time. //----------------------------------------------------------------------------- static void GetOneFrameSegment(double current_vuv, int noise_size, const double * const *spectrogram, int fft_size, const double * const *aperiodicity, int f0_length, double frame_period, double current_time, double fractional_time_shift, int fs, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, const double *dc_remover, double *response) { double *aperiodic_response = new double[fft_size]; double *periodic_response = new double[fft_size]; double *spectral_envelope = new double[fft_size]; double *aperiodic_ratio = new double[fft_size]; GetSpectralEnvelope(current_time, frame_period, f0_length, spectrogram, fft_size, spectral_envelope); GetAperiodicRatio(current_time, frame_period, f0_length, aperiodicity, fft_size, aperiodic_ratio); // Synthesis of the periodic response GetPeriodicResponse(fft_size, spectral_envelope, aperiodic_ratio, current_vuv, inverse_real_fft, minimum_phase, dc_remover, fractional_time_shift, fs, periodic_response); // Synthesis of the aperiodic response GetAperiodicResponse(noise_size, fft_size, spectral_envelope, aperiodic_ratio, current_vuv, forward_real_fft, inverse_real_fft, minimum_phase, aperiodic_response); double sqrt_noise_size = sqrt(static_cast(noise_size)); for (int i = 0; i < fft_size; ++i) response[i] = (periodic_response[i] * sqrt_noise_size + aperiodic_response[i]) / fft_size; delete[] spectral_envelope; delete[] aperiodic_ratio; delete[] periodic_response; delete[] aperiodic_response; } static void GetTemporalParametersForTimeBase(const double *f0, int f0_length, int fs, int y_length, double frame_period, double lowest_f0, double *time_axis, double *coarse_time_axis, double *coarse_f0, double *coarse_vuv) { for (int i = 0; i < y_length; ++i) time_axis[i] = i / static_cast(fs); // the array 'coarse_time_axis' is supposed to have 'f0_length + 1' positions for (int i = 0; i < f0_length; ++i) { coarse_time_axis[i] = i * frame_period; coarse_f0[i] = f0[i] < lowest_f0 ? 0.0 : f0[i]; coarse_vuv[i] = coarse_f0[i] == 0.0 ? 0.0 : 1.0; } coarse_time_axis[f0_length] = f0_length * frame_period; coarse_f0[f0_length] = coarse_f0[f0_length - 1] * 2 - coarse_f0[f0_length - 2]; coarse_vuv[f0_length] = coarse_vuv[f0_length - 1] * 2 - coarse_vuv[f0_length - 2]; } static int GetPulseLocationsForTimeBase(const double *interpolated_f0, const double *time_axis, int y_length, int fs, double *pulse_locations, int *pulse_locations_index, double *pulse_locations_time_shift) { double *total_phase = new double[y_length]; double *wrap_phase = new double[y_length]; double *wrap_phase_abs = new double[y_length - 1]; total_phase[0] = 2.0 * world::kPi * interpolated_f0[0] / fs; wrap_phase[0] = fmod(total_phase[0], 2.0 * world::kPi); for (int i = 1; i < y_length; ++i) { total_phase[i] = total_phase[i - 1] + 2.0 * world::kPi * interpolated_f0[i] / fs; wrap_phase[i] = fmod(total_phase[i], 2.0 * world::kPi); wrap_phase_abs[i - 1] = fabs(wrap_phase[i] - wrap_phase[i - 1]); } int number_of_pulses = 0; for (int i = 0; i < y_length - 1; ++i) { if (wrap_phase_abs[i] > world::kPi) { pulse_locations[number_of_pulses] = time_axis[i]; pulse_locations_index[number_of_pulses] = i; // calculate the time shift in seconds between exact fractional pulse // position and the integer pulse position (sample i) // as we don't have access to the exact pulse position, we infer it // from the point between sample i and sample i + 1 where the // accummulated phase cross a multiple of 2pi // this point is found by solving y1 + x * (y2 - y1) = 0 for x, where y1 // and y2 are the phases corresponding to sample i and i + 1, offset so // they cross zero; x >= 0 double y1 = wrap_phase[i] - 2.0 * world::kPi; double y2 = wrap_phase[i + 1]; double x = -y1 / (y2 - y1); pulse_locations_time_shift[number_of_pulses] = x / fs; ++number_of_pulses; } } delete[] wrap_phase_abs; delete[] wrap_phase; delete[] total_phase; return number_of_pulses; } static int GetTimeBase(const double *f0, int f0_length, int fs, double frame_period, int y_length, double lowest_f0, double *pulse_locations, int *pulse_locations_index, double *pulse_locations_time_shift, double *interpolated_vuv) { double *time_axis = new double[y_length]; double *coarse_time_axis = new double[f0_length + 1]; double *coarse_f0 = new double[f0_length + 1]; double *coarse_vuv = new double[f0_length + 1]; GetTemporalParametersForTimeBase(f0, f0_length, fs, y_length, frame_period, lowest_f0, time_axis, coarse_time_axis, coarse_f0, coarse_vuv); double *interpolated_f0 = new double[y_length]; interp1(coarse_time_axis, coarse_f0, f0_length + 1, time_axis, y_length, interpolated_f0); interp1(coarse_time_axis, coarse_vuv, f0_length + 1, time_axis, y_length, interpolated_vuv); for (int i = 0; i < y_length; ++i) { interpolated_vuv[i] = interpolated_vuv[i] > 0.5 ? 1.0 : 0.0; interpolated_f0[i] = interpolated_vuv[i] == 0.0 ? world::kDefaultF0 : interpolated_f0[i]; } int number_of_pulses = GetPulseLocationsForTimeBase(interpolated_f0, time_axis, y_length, fs, pulse_locations, pulse_locations_index, pulse_locations_time_shift); delete[] coarse_vuv; delete[] coarse_f0; delete[] coarse_time_axis; delete[] time_axis; delete[] interpolated_f0; return number_of_pulses; } static void GetDCRemover(int fft_size, double *dc_remover) { double dc_component = 0.0; for (int i = 0; i < fft_size / 2; ++i) { dc_remover[i] = 0.5 - 0.5 * cos(2.0 * world::kPi * (i + 1.0) / (1.0 + fft_size)); dc_remover[fft_size - i - 1] = dc_remover[i]; dc_component += dc_remover[i] * 2.0; } for (int i = 0; i < fft_size / 2; ++i) { dc_remover[i] /= dc_component; dc_remover[fft_size - i - 1] = dc_remover[i]; } } } // namespace void Synthesis(const double *f0, int f0_length, const double * const *spectrogram, const double * const *aperiodicity, int fft_size, double frame_period, int fs, int y_length, double *y) { randn_reseed(); double *impulse_response = new double[fft_size]; for (int i = 0; i < y_length; ++i) y[i] = 0.0; MinimumPhaseAnalysis minimum_phase = {0}; InitializeMinimumPhaseAnalysis(fft_size, &minimum_phase); InverseRealFFT inverse_real_fft = {0}; InitializeInverseRealFFT(fft_size, &inverse_real_fft); ForwardRealFFT forward_real_fft = {0}; InitializeForwardRealFFT(fft_size, &forward_real_fft); double *pulse_locations = new double[y_length]; int *pulse_locations_index = new int[y_length]; double *pulse_locations_time_shift = new double[y_length]; double *interpolated_vuv = new double[y_length]; int number_of_pulses = GetTimeBase(f0, f0_length, fs, frame_period / 1000.0, y_length, fs / fft_size + 1.0, pulse_locations, pulse_locations_index, pulse_locations_time_shift, interpolated_vuv); double *dc_remover = new double[fft_size]; GetDCRemover(fft_size, dc_remover); frame_period /= 1000.0; int noise_size; int index, offset, lower_limit, upper_limit; for (int i = 0; i < number_of_pulses; ++i) { noise_size = pulse_locations_index[MyMinInt(number_of_pulses - 1, i + 1)] - pulse_locations_index[i]; GetOneFrameSegment(interpolated_vuv[pulse_locations_index[i]], noise_size, spectrogram, fft_size, aperiodicity, f0_length, frame_period, pulse_locations[i], pulse_locations_time_shift[i], fs, &forward_real_fft, &inverse_real_fft, &minimum_phase, dc_remover, impulse_response); offset = pulse_locations_index[i] - fft_size / 2 + 1; lower_limit = MyMaxInt(0, -offset); upper_limit = MyMinInt(fft_size, y_length - offset); for (int j = lower_limit; j < upper_limit; ++j) { index = j + offset; y[index] += impulse_response[j]; } } delete[] dc_remover; delete[] pulse_locations; delete[] pulse_locations_index; delete[] pulse_locations_time_shift; delete[] interpolated_vuv; DestroyMinimumPhaseAnalysis(&minimum_phase); DestroyInverseRealFFT(&inverse_real_fft); DestroyForwardRealFFT(&forward_real_fft); delete[] impulse_response; } ================================================ FILE: libsvc/Modules/Lib/World/src/synthesisrealtime.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Voice synthesis based on f0, spectrogram and aperiodicity. // This is an implementation for real-time applications. // Note: Several functions are same as those of synthesis.cpp. // // Caution: This is an implementation as a prototype. // Specifications may change. There may be a bug. // // Caution: DC removal was re-implemented. However, this implementation is // different from the implementation in synthesis.cpp. The sound // quality is almost all the same in both implementations. //----------------------------------------------------------------------------- #include "world/synthesisrealtime.h" #include #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { static void GetNoiseSpectrum(int noise_size, int fft_size, const ForwardRealFFT *forward_real_fft) { double average = 0.0; for (int i = 0; i < noise_size; ++i) { forward_real_fft->waveform[i] = randn(); average += forward_real_fft->waveform[i]; } average /= noise_size; for (int i = 0; i < noise_size; ++i) forward_real_fft->waveform[i] -= average; for (int i = noise_size; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); } //----------------------------------------------------------------------------- // GetAperiodicResponse() calculates an aperiodic response. //----------------------------------------------------------------------------- static void GetAperiodicResponse(int noise_size, int fft_size, const double *spectrum, const double *aperiodic_ratio, double current_vuv, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, double *aperiodic_response) { GetNoiseSpectrum(noise_size, fft_size, forward_real_fft); if (current_vuv != 0.0) for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i] * aperiodic_ratio[i] + world::kMySafeGuardMinimum) / 2.0; else for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i]) / 2.0; GetMinimumPhaseSpectrum(minimum_phase); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = minimum_phase->minimum_phase_spectrum[i][0] * forward_real_fft->spectrum[i][0] - minimum_phase->minimum_phase_spectrum[i][1] * forward_real_fft->spectrum[i][1]; inverse_real_fft->spectrum[i][1] = minimum_phase->minimum_phase_spectrum[i][0] * forward_real_fft->spectrum[i][1] + minimum_phase->minimum_phase_spectrum[i][1] * forward_real_fft->spectrum[i][0]; } fft_execute(inverse_real_fft->inverse_fft); fftshift(inverse_real_fft->waveform, fft_size, aperiodic_response); } static void ClearRingBuffer(int start, int end, WorldSynthesizer *synth) { int pointer; for (int i = start; i < end; ++i) { pointer = i % synth->number_of_pointers; synth->number_of_pulses[pointer] = 0; if (synth->pulse_locations[pointer] != NULL) { delete[] synth->pulse_locations[pointer]; synth->pulse_locations[pointer] = NULL; } if (synth->interpolated_vuv[pointer] != NULL) { delete[] synth->interpolated_vuv[pointer]; synth->interpolated_vuv[pointer] = NULL; } if (synth->pulse_locations_index[pointer] != NULL) { delete[] synth->pulse_locations_index[pointer]; synth->pulse_locations_index[pointer] = NULL; } } } static int SeekSynthesizer(double current_location, WorldSynthesizer *synth) { int frame_number = static_cast(current_location / synth->frame_period); int tmp_pointer = synth->current_pointer2; int tmp; for (int i = 0; i < synth->head_pointer - synth->current_pointer2; ++i) { tmp = (tmp_pointer + i) % synth->number_of_pointers; if (synth->f0_origin[tmp] <= frame_number && frame_number < synth->f0_origin[tmp] + synth->f0_length[tmp]) { tmp_pointer += i; break; } } ClearRingBuffer(synth->current_pointer2, tmp_pointer, synth); synth->current_pointer2 = tmp_pointer; return 1; } static void SearchPointer(int frame, WorldSynthesizer *synth, int flag, double **front, double **next) { int pointer = synth->current_pointer2 % synth->number_of_pointers; int index = -1; for (int i = 0; i < synth->f0_length[pointer]; ++i) if (synth->f0_origin[pointer] + i == frame) { index = i; break; } double ***tmp_pointer = flag == 0 ? synth->spectrogram : synth->aperiodicity; *front = tmp_pointer[pointer][index]; *next = index == synth->f0_length[pointer] - 1 ? tmp_pointer[(synth->current_pointer2 + 1) % synth->number_of_pointers][0] : tmp_pointer[pointer][index + 1]; } //----------------------------------------------------------------------------- // RemoveDCComponent() //----------------------------------------------------------------------------- static void RemoveDCComponent(const double *periodic_response, int fft_size, const double *dc_remover, double *new_periodic_response) { double dc_component = 0.0; for (int i = fft_size / 2; i < fft_size; ++i) dc_component += periodic_response[i]; for (int i = 0; i < fft_size / 2; ++i) new_periodic_response[i] = 0.0; for (int i = fft_size / 2; i < fft_size; ++i) new_periodic_response[i] -= dc_component * dc_remover[i - fft_size / 2]; } //----------------------------------------------------------------------------- // GetPeriodicResponse() calculates an aperiodic response. //----------------------------------------------------------------------------- static void GetPeriodicResponse(int fft_size, const double *spectrum, const double *aperiodic_ratio, double current_vuv, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, const double *dc_remover, double *periodic_response) { if (current_vuv <= 0.5 || aperiodic_ratio[0] > 0.999) { for (int i = 0; i < fft_size; ++i) periodic_response[i] = 0.0; return; } for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i] * (1.0 - aperiodic_ratio[i]) + world::kMySafeGuardMinimum) / 2.0; GetMinimumPhaseSpectrum(minimum_phase); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = minimum_phase->minimum_phase_spectrum[i][0]; inverse_real_fft->spectrum[i][1] = minimum_phase->minimum_phase_spectrum[i][1]; } fft_execute(inverse_real_fft->inverse_fft); fftshift(inverse_real_fft->waveform, fft_size, periodic_response); RemoveDCComponent(periodic_response, fft_size, dc_remover, periodic_response); } static void GetSpectralEnvelope(double current_location, WorldSynthesizer *synth, double *spectral_envelope) { int current_frame_floor = static_cast(current_location / synth->frame_period); int current_frame_ceil = static_cast(ceil(current_location / synth->frame_period)); double interpolation = current_location / synth->frame_period - current_frame_floor; double *front = NULL; double *next = NULL; SearchPointer(current_frame_floor, synth, 0, &front, &next); if (current_frame_floor == current_frame_ceil) for (int i = 0; i <= synth->fft_size / 2; ++i) spectral_envelope[i] = fabs(front[i]); else for (int i = 0; i <= synth->fft_size / 2; ++i) spectral_envelope[i] = (1.0 - interpolation) * fabs(front[i]) + interpolation * fabs(next[i]); } static void GetAperiodicRatio(double current_location, WorldSynthesizer *synth, double *aperiodic_spectrum) { int current_frame_floor = static_cast(current_location / synth->frame_period); int current_frame_ceil = static_cast(ceil(current_location / synth->frame_period)); double interpolation = current_location / synth->frame_period - current_frame_floor; double *front = NULL; double *next = NULL; SearchPointer(current_frame_floor, synth, 1, &front, &next); if (current_frame_floor == current_frame_ceil) for (int i = 0; i <= synth->fft_size / 2; ++i) aperiodic_spectrum[i] = pow(GetSafeAperiodicity(front[i]), 2.0); else for (int i = 0; i <= synth->fft_size / 2; ++i) aperiodic_spectrum[i] = pow((1.0 - interpolation) * GetSafeAperiodicity(front[i]) + interpolation * GetSafeAperiodicity(next[i]), 2.0); } static double GetCurrentVUV(int current_location, WorldSynthesizer *synth) { double current_vuv = 0.0; int pointer = synth->current_pointer % synth->number_of_pointers; int start_sample = MyMaxInt(0, static_cast(ceil((synth->f0_origin[pointer] - 1) * synth->frame_period * synth->fs))); current_vuv = synth->interpolated_vuv[pointer][current_location - start_sample + 1]; return current_vuv; } //----------------------------------------------------------------------------- // GetOneFrameSegment() calculates a periodic and aperiodic response at a time. //----------------------------------------------------------------------------- static void GetOneFrameSegment(int noise_size, int current_location, WorldSynthesizer *synth) { double *aperiodic_response = new double[synth->fft_size]; double *periodic_response = new double[synth->fft_size]; double *spectral_envelope = new double[synth->fft_size]; double *aperiodic_ratio = new double[synth->fft_size]; double tmp_location = static_cast(current_location) / synth->fs; SeekSynthesizer(tmp_location, synth); GetSpectralEnvelope(tmp_location, synth, spectral_envelope); GetAperiodicRatio(tmp_location, synth, aperiodic_ratio); double current_vuv = GetCurrentVUV(current_location, synth); // Synthesis of the periodic response GetPeriodicResponse(synth->fft_size, spectral_envelope, aperiodic_ratio, current_vuv, &synth->inverse_real_fft, &synth->minimum_phase, synth->dc_remover, periodic_response); // Synthesis of the aperiodic response GetAperiodicResponse(noise_size, synth->fft_size, spectral_envelope, aperiodic_ratio, current_vuv, &synth->forward_real_fft, &synth->inverse_real_fft, &synth->minimum_phase, aperiodic_response); double sqrt_noise_size = sqrt(static_cast(noise_size)); for (int i = 0; i < synth->fft_size; ++i) synth->impulse_response[i] = (periodic_response[i] * sqrt_noise_size + aperiodic_response[i]) / synth->fft_size; delete[] spectral_envelope; delete[] aperiodic_ratio; delete[] periodic_response; delete[] aperiodic_response; } static void GetTemporalParametersForTimeBase(const double *f0, int f0_length, WorldSynthesizer *synth, double *coarse_time_axis, double *coarse_f0, double *coarse_vuv) { int cumulative_frame = MyMaxInt(0, synth->cumulative_frame - f0_length); coarse_f0[0] = synth->handoff_f0; coarse_time_axis[0] = cumulative_frame * synth->frame_period; coarse_vuv[0] = synth->handoff_f0 == 0 ? 0.0 : 1.0; for (int i = 0; i < f0_length; ++i) { coarse_time_axis[i + synth->handoff] = (i + cumulative_frame + synth->handoff) * synth->frame_period; coarse_f0[i + synth->handoff] = f0[i]; coarse_vuv[i + synth->handoff] = f0[i] == 0.0 ? 0.0 : 1.0; } } static void GetPulseLocationsForTimeBase(const double *interpolated_f0, const double *time_axis, int number_of_samples, double origin, WorldSynthesizer *synth) { double *total_phase = new double[number_of_samples + synth->handoff]; total_phase[0] = synth->handoff == 1 ? synth->handoff_phase : 2.0 * world::kPi * interpolated_f0[0] / synth->fs; total_phase[1] = total_phase[0] + 2.0 * world::kPi * interpolated_f0[0] / synth->fs; for (int i = 1 + synth->handoff; i < number_of_samples + synth->handoff; ++i) total_phase[i] = total_phase[i - 1] + 2.0 * world::kPi * interpolated_f0[i - synth->handoff] / synth->fs; synth->handoff_phase = total_phase[number_of_samples - 1 + synth->handoff]; double *wrap_phase = new double[number_of_samples + synth->handoff]; for (int i = 0; i < number_of_samples + synth->handoff; ++i) wrap_phase[i] = fmod(total_phase[i], 2.0 * world::kPi); double *wrap_phase_abs = new double[number_of_samples + synth->handoff]; for (int i = 0; i < number_of_samples - 1 + synth->handoff; ++i) wrap_phase_abs[i] = fabs(wrap_phase[i + 1] - wrap_phase[i]); int pointer = synth->head_pointer % synth->number_of_pointers; int number_of_pulses = 0; for (int i = 0; i < number_of_samples - 1 + synth->handoff; ++i) if (wrap_phase_abs[i] > world::kPi) { synth->pulse_locations[pointer][number_of_pulses] = time_axis[i] - static_cast(synth->handoff) / synth->fs; synth->pulse_locations_index[pointer][number_of_pulses] = matlab_round(synth->pulse_locations[pointer][number_of_pulses] * synth->fs); ++number_of_pulses; } synth->number_of_pulses[pointer] = number_of_pulses; if (number_of_pulses != 0) synth->last_location = synth->pulse_locations_index[pointer][number_of_pulses - 1]; delete[] wrap_phase_abs; delete[] wrap_phase; delete[] total_phase; } static void GetTimeBase(const double *f0, int f0_length, int start_sample, int number_of_samples, WorldSynthesizer *synth) { double *coarse_time_axis = new double[f0_length + synth->handoff]; double *coarse_f0 = new double[f0_length + synth->handoff]; double *coarse_vuv = new double[f0_length + synth->handoff]; GetTemporalParametersForTimeBase(f0, f0_length, synth, coarse_time_axis, coarse_f0, coarse_vuv); double *interpolated_f0 = new double[number_of_samples]; double *time_axis = new double[number_of_samples]; for (int i = 0; i < number_of_samples; ++i) time_axis[i] = (i + start_sample) / static_cast(synth->fs); int pointer = synth->head_pointer % synth->number_of_pointers; interp1(coarse_time_axis, coarse_f0, f0_length + synth->handoff, time_axis, number_of_samples, interpolated_f0); interp1(coarse_time_axis, coarse_vuv, f0_length + synth->handoff, time_axis, number_of_samples, synth->interpolated_vuv[pointer]); for (int i = 0; i < number_of_samples; ++i) { synth->interpolated_vuv[pointer][i] = synth->interpolated_vuv[pointer][i] > 0.5 ? 1.0 : 0.0; interpolated_f0[i] = synth->interpolated_vuv[pointer][i] == 0.0 ? world::kDefaultF0 : interpolated_f0[i]; } GetPulseLocationsForTimeBase(interpolated_f0, time_axis, number_of_samples, coarse_time_axis[0], synth); synth->handoff_f0 = interpolated_f0[number_of_samples - 1]; delete[] time_axis; delete[] interpolated_f0; delete[] coarse_time_axis; delete[] coarse_f0; delete[] coarse_vuv; } static int GetNextPulseLocationIndex(WorldSynthesizer *synth) { int pointer = synth->current_pointer % synth->number_of_pointers; if (synth->i < synth->number_of_pulses[pointer] - 1) return synth->pulse_locations_index[pointer][synth->i + 1]; else if (synth->current_pointer == synth->head_pointer - 1) return 0; for (int i = 1; i < synth->number_of_pointers; ++i) { pointer = (i + synth->current_pointer) % synth->number_of_pointers; if (synth->number_of_pulses[pointer] != 0) return synth->pulse_locations_index[pointer][0]; } return 0; } static int UpdateSynthesizer(int current_location, WorldSynthesizer *synth) { int pointer = synth->current_pointer % synth->number_of_pointers; if (synth->i < synth->number_of_pulses[pointer] - 1) { synth->i++; return 1; } else { if (synth->current_pointer == synth->head_pointer - 1) return 0; } for (int i = 1; i < synth->number_of_pointers; ++i) { pointer = (i + synth->current_pointer) % synth->number_of_pointers; if (synth->number_of_pulses[pointer] != 0) { synth->i = 0; synth->current_pointer += i; return 1; } } return 0; } static int CheckSynthesizer(WorldSynthesizer *synth) { if (synth->synthesized_sample + synth->buffer_size >= synth->last_location) return 0; int pointer = synth->current_pointer % synth->number_of_pointers; while (synth->number_of_pulses[pointer] == 0) { if (synth->current_pointer == synth->head_pointer) break; synth->current_pointer++; pointer = synth->current_pointer % synth->number_of_pointers; } return 1; } static void GetDCRemover(int fft_size, double *dc_remover) { double dc_component = 0.0; for (int i = 0; i < fft_size / 2; ++i) { dc_remover[i] = 0.5 - 0.5 * cos(2.0 * world::kPi * (i + 1.0) / (1.0 + fft_size)); dc_remover[fft_size - i - 1] = dc_remover[i]; dc_component += dc_remover[i] * 2.0; } for (int i = 0; i < fft_size / 2; ++i) { dc_remover[i] /= dc_component; dc_remover[fft_size - i - 1] = dc_remover[i]; } } } // namespace void InitializeSynthesizer(int fs, double frame_period, int fft_size, int buffer_size, int number_of_pointers, WorldSynthesizer *synth) { // Set basic parameters synth->fs = fs; synth->frame_period = frame_period / 1000.0; synth->buffer_size = buffer_size; synth->number_of_pointers = number_of_pointers; synth->fft_size = fft_size; // Memory allocations synth->f0_length = new int[number_of_pointers]; synth->spectrogram = new double**[number_of_pointers]; synth->aperiodicity = new double**[number_of_pointers]; synth->interpolated_vuv = new double*[number_of_pointers]; synth->pulse_locations = new double*[number_of_pointers]; synth->pulse_locations_index = new int*[number_of_pointers]; synth->number_of_pulses = new int[number_of_pointers]; synth->f0_origin = new int[number_of_pointers]; for (int i = 0; i < synth->number_of_pointers; ++i) { synth->interpolated_vuv[i] = NULL; synth->pulse_locations[i] = NULL; synth->pulse_locations_index[i] = NULL; } synth->buffer = new double[buffer_size * 2 + fft_size]; synth->impulse_response = new double[synth->fft_size]; synth->dc_remover = new double[synth->fft_size / 2]; // Initilize internal parameters RefreshSynthesizer(synth); InitializeMinimumPhaseAnalysis(fft_size, &synth->minimum_phase); InitializeInverseRealFFT(fft_size, &synth->inverse_real_fft); InitializeForwardRealFFT(fft_size, &synth->forward_real_fft); } int AddParameters(double *f0, int f0_length, double **spectrogram, double **aperiodicity, WorldSynthesizer *synth) { if (synth->head_pointer - synth->current_pointer2 == synth->number_of_pointers) return 0; // Since the queue is full, we cannot add the parameters. int pointer = synth->head_pointer % synth->number_of_pointers; synth->f0_length[pointer] = f0_length; synth->f0_origin[pointer] = synth->cumulative_frame + 1; synth->cumulative_frame += f0_length; synth->spectrogram[pointer] = spectrogram; synth->aperiodicity[pointer] = aperiodicity; if (synth->cumulative_frame < 1) { synth->handoff_f0 = f0[f0_length - 1]; synth->number_of_pulses[pointer] = 0; synth->head_pointer++; synth->handoff = 1; return 1; } int start_sample = MyMaxInt(0, static_cast(ceil((synth->cumulative_frame - f0_length) * synth->frame_period * synth->fs))); int end_sample = static_cast(ceil((synth->cumulative_frame) * synth->frame_period * synth->fs)); int number_of_samples = end_sample - start_sample; // Memory allocation synth->interpolated_vuv[pointer] = new double[number_of_samples + 1]; synth->pulse_locations[pointer] = new double[number_of_samples]; synth->pulse_locations_index[pointer] = new int[number_of_samples]; GetTimeBase(f0, f0_length, start_sample, number_of_samples, synth); synth->handoff_f0 = f0[f0_length - 1]; synth->head_pointer++; synth->handoff = 1; return 1; } void RefreshSynthesizer(WorldSynthesizer *synth) { ClearRingBuffer(0, synth->number_of_pointers, synth); synth->handoff_phase = 0; synth->handoff_f0 = 0; synth->cumulative_frame = -1; synth->last_location = 0; synth->current_pointer = 0; synth->current_pointer2 = 0; synth->head_pointer = 0; synth->handoff = 0; synth->i = 0; synth->current_frame = 0; synth->synthesized_sample = 0; for (int i = 0; i < synth->buffer_size * 2 + synth->fft_size; ++i) synth->buffer[i] = 0; GetDCRemover(synth->fft_size / 2, synth->dc_remover); } void DestroySynthesizer(WorldSynthesizer *synth) { RefreshSynthesizer(synth); delete[] synth->f0_length; delete[] synth->spectrogram; delete[] synth->aperiodicity; delete[] synth->buffer; delete[] synth->impulse_response; delete[] synth->dc_remover; delete[] synth->interpolated_vuv; delete[] synth->pulse_locations; delete[] synth->pulse_locations_index; delete[] synth->number_of_pulses; delete[] synth->f0_origin; DestroyMinimumPhaseAnalysis(&synth->minimum_phase); DestroyInverseRealFFT(&synth->inverse_real_fft); DestroyForwardRealFFT(&synth->forward_real_fft); } int IsLocked(WorldSynthesizer *synth) { int judge = 0; if (synth->head_pointer - synth->current_pointer2 == synth->number_of_pointers) judge++; if (synth->synthesized_sample + synth->buffer_size >= synth->last_location) judge++; return judge == 2 ? 1 : 0; } int Synthesis2(WorldSynthesizer *synth) { if (CheckSynthesizer(synth) == 0) return 0; for (int i = 0; i < synth->buffer_size + synth->fft_size; ++i) synth->buffer[i] = synth->buffer[i + synth->buffer_size]; int pointer = synth->current_pointer % synth->number_of_pointers; int noise_size, offset, tmp, index; int current_location = synth->pulse_locations_index[pointer][synth->i]; while (current_location < synth->synthesized_sample + synth->buffer_size) { tmp = GetNextPulseLocationIndex(synth); noise_size = tmp - current_location; GetOneFrameSegment(noise_size, current_location, synth); offset = current_location - synth->synthesized_sample - synth->fft_size / 2 + 1; for (int i = MyMaxInt(0, -offset); i < synth->fft_size; ++i) { index = i + offset; synth->buffer[index] += synth->impulse_response[i]; } current_location = tmp; UpdateSynthesizer(current_location, synth); } synth->synthesized_sample += synth->buffer_size; SeekSynthesizer(synth->synthesized_sample, synth); return 1; } ================================================ FILE: libsvc/Modules/Lib/World/src/world/cheaptrick.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_CHEAPTRICK_H_ #define WORLD_CHEAPTRICK_H_ #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Struct for CheapTrick //----------------------------------------------------------------------------- typedef struct { double q1; double f0_floor; int fft_size; } CheapTrickOption; //----------------------------------------------------------------------------- // CheapTrick() calculates the spectrogram that consists of spectral envelopes // estimated by CheapTrick. // // Input: // x : Input signal // x_length : Length of x // fs : Sampling frequency // temporal_positions : Time axis // f0 : F0 contour // f0_length : Length of F0 contour // option : Struct to order the parameter for CheapTrick // // Output: // spectrogram : Spectrogram estimated by CheapTrick. //----------------------------------------------------------------------------- void CheapTrick(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, const CheapTrickOption *option, double **spectrogram); //----------------------------------------------------------------------------- // InitializeCheapTrickOption allocates the memory to the struct and sets the // default parameters. // // Input: // fs : Sampling frequency // // Output: // option : Struct for the optional parameter //----------------------------------------------------------------------------- void InitializeCheapTrickOption(int fs, CheapTrickOption *option); //----------------------------------------------------------------------------- // GetFFTSizeForCheapTrick() calculates the FFT size based on the sampling // frequency and the lower limit of f0 (kFloorF0 defined in constantnumbers.h). // // Input: // fs : Sampling frequency // option : Option struct containing the lower f0 limit // // Output: // FFT size //----------------------------------------------------------------------------- int GetFFTSizeForCheapTrick(int fs, const CheapTrickOption *option); //----------------------------------------------------------------------------- // GetF0FloorForCheapTrick() calculates actual lower f0 limit for CheapTrick // based on the sampling frequency and FFT size used. Whenever f0 is below // this threshold the spectrum will be analyzed as if the frame is unvoiced // (using kDefaultF0 defined in constantnumbers.h). // // Input: // fs : Sampling frequency // fft_size : FFT size // // Output: // Lower f0 limit (Hz) //----------------------------------------------------------------------------- double GetF0FloorForCheapTrick(int fs, int fft_size); WORLD_END_C_DECLS #endif // WORLD_CHEAPTRICK_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/codec.h ================================================ //----------------------------------------------------------------------------- // Copyright 2017 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_CODEC_H_ #define WORLD_CODEC_H_ #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // GetNumberOfAperiodicities provides the number of dimensions for aperiodicity // coding. It is determined by only fs. // // Input: // fs : Sampling frequency // // Output: // Number of aperiodicities //----------------------------------------------------------------------------- int GetNumberOfAperiodicities(int fs); //----------------------------------------------------------------------------- // CodeAperiodicity codes the aperiodicity. The number of dimensions is // determined by fs. // // Input: // aperiodicity : Aperiodicity before coding // f0_length : Length of F0 contour // fs : Sampling frequency // fft_size : FFT size // // Output: // coded_aperiodicity : Coded aperiodicity //----------------------------------------------------------------------------- void CodeAperiodicity(const double * const *aperiodicity, int f0_length, int fs, int fft_size, double **coded_aperiodicity); //----------------------------------------------------------------------------- // DecodeAperiodicity decodes the coded aperiodicity. // // Input: // coded_aperiodicity : Coded aperiodicity // f0_length : Length of F0 contour // fs : Sampling frequency // fft_size : FFT size // // Output: // aperiodicity : Decoded aperiodicity //----------------------------------------------------------------------------- void DecodeAperiodicity(const double * const *coded_aperiodicity, int f0_length, int fs, int fft_size, double **aperiodicity); //----------------------------------------------------------------------------- // CodeSpectralEnvelope codes the spectral envelope. // // Input: // aperiodicity : Aperiodicity before coding // f0_length : Length of F0 contour // fs : Sampling frequency // fft_size : FFT size // number_of_dimensions : Parameter for compression // // Output: // coded_spectral_envelope //----------------------------------------------------------------------------- void CodeSpectralEnvelope(const double * const *spectrogram, int f0_length, int fs, int fft_size, int number_of_dimensions, double **coded_spectral_envelope); //----------------------------------------------------------------------------- // DecodeSpectralEnvelope decodes the coded spectral envelope. // // Input: // coded_aperiodicity : Coded aperiodicity // f0_length : Length of F0 contour // fs : Sampling frequency // fft_size : FFT size // number_of_dimensions : Parameter for compression // // Output: // spectrogram //----------------------------------------------------------------------------- void DecodeSpectralEnvelope(const double * const *coded_spectral_envelope, int f0_length, int fs, int fft_size, int number_of_dimensions, double **spectrogram); WORLD_END_C_DECLS #endif // WORLD_CODEC_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/common.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_COMMON_H_ #define WORLD_COMMON_H_ #include "fft.h" #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Structs on FFT //----------------------------------------------------------------------------- // Forward FFT in the real sequence typedef struct { int fft_size; double *waveform; fft_complex *spectrum; fft_plan forward_fft; } ForwardRealFFT; // Inverse FFT in the real sequence typedef struct { int fft_size; double *waveform; fft_complex *spectrum; fft_plan inverse_fft; } InverseRealFFT; // Inverse FFT in the complex sequence typedef struct { int fft_size; fft_complex *input; fft_complex *output; fft_plan inverse_fft; } InverseComplexFFT; // Minimum phase analysis from logarithmic power spectrum typedef struct { int fft_size; double *log_spectrum; fft_complex *minimum_phase_spectrum; fft_complex *cepstrum; fft_plan inverse_fft; fft_plan forward_fft; } MinimumPhaseAnalysis; //----------------------------------------------------------------------------- // GetSuitableFFTSize() calculates the suitable FFT size. // The size is defined as the minimum length whose length is longer than // the input sample. // // Input: // sample : Length of the input signal // // Output: // Suitable FFT size //----------------------------------------------------------------------------- int GetSuitableFFTSize(int sample); //----------------------------------------------------------------------------- // These four functions are simple max() and min() function // for "int" and "double" type. //----------------------------------------------------------------------------- inline int MyMaxInt(int x, int y) { return x > y ? x : y; } inline double MyMaxDouble(double x, double y) { return x > y ? x : y; } inline int MyMinInt(int x, int y) { return x < y ? x : y; } inline double MyMinDouble(double x, double y) { return x < y ? x : y; } //----------------------------------------------------------------------------- // These functions are used in at least two different .cpp files //----------------------------------------------------------------------------- // DCCorrection interpolates the power under f0 Hz // and is used in CheapTrick() and D4C(). //----------------------------------------------------------------------------- void DCCorrection(const double *input, double current_f0, int fs, int fft_size, double *output); //----------------------------------------------------------------------------- // LinearSmoothing() carries out the spectral smoothing by rectangular window // whose length is width Hz and is used in CheapTrick() and D4C(). //----------------------------------------------------------------------------- void LinearSmoothing(const double *input, double width, int fs, int fft_size, double *output); //----------------------------------------------------------------------------- // NuttallWindow() calculates the coefficients of Nuttall window whose length // is y_length and is used in Dio(), Harvest() and D4C(). //----------------------------------------------------------------------------- void NuttallWindow(int y_length, double *y); //----------------------------------------------------------------------------- // GetSafeAperiodicity() limit the range of aperiodicity from 0.001 to // 0.999999999999 (1 - world::kMySafeGuardMinimum). //----------------------------------------------------------------------------- inline double GetSafeAperiodicity(double x) { return MyMaxDouble(0.001, MyMinDouble(0.999999999999, x)); } //----------------------------------------------------------------------------- // These functions are used to speed up the processing. // Forward FFT void InitializeForwardRealFFT(int fft_size, ForwardRealFFT *forward_real_fft); void DestroyForwardRealFFT(ForwardRealFFT *forward_real_fft); // Inverse FFT void InitializeInverseRealFFT(int fft_size, InverseRealFFT *inverse_real_fft); void DestroyInverseRealFFT(InverseRealFFT *inverse_real_fft); // Inverse FFT (Complex) void InitializeInverseComplexFFT(int fft_size, InverseComplexFFT *inverse_complex_fft); void DestroyInverseComplexFFT(InverseComplexFFT *inverse_complex_fft); // Minimum phase analysis (This analysis uses FFT) void InitializeMinimumPhaseAnalysis(int fft_size, MinimumPhaseAnalysis *minimum_phase); void GetMinimumPhaseSpectrum(const MinimumPhaseAnalysis *minimum_phase); void DestroyMinimumPhaseAnalysis(MinimumPhaseAnalysis *minimum_phase); WORLD_END_C_DECLS #endif // WORLD_COMMON_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/constantnumbers.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // This header file only defines constant numbers used for several function. //----------------------------------------------------------------------------- #ifndef WORLD_CONSTANT_NUMBERS_H_ #define WORLD_CONSTANT_NUMBERS_H_ namespace world { // for Dio() const double kCutOff = 50.0; // for StoneMask() const double kFloorF0StoneMask = 40.0; const double kPi = 3.1415926535897932384; const double kMySafeGuardMinimum = 0.000000000001; const double kEps = 0.00000000000000022204460492503131; const double kFloorF0 = 71.0; const double kCeilF0 = 800.0; const double kDefaultF0 = 500.0; const double kLog2 = 0.69314718055994529; // Maximum standard deviation not to be selected as a best f0. const double kMaximumValue = 100000.0; // Note to me (fs: 48000) // 71 Hz is the limit to maintain the FFT size at 2048. // If we use 70 Hz as FLOOR_F0, the FFT size of 4096 is required. // for D4C() const int kHanning = 1; const int kBlackman = 2; const double kFrequencyInterval = 3000.0; const double kUpperLimit = 15000.0; const double kThreshold = 0.85; const double kFloorF0D4C = 47.0; // for Codec (Mel scale) // S. Stevens & J. Volkmann, // The Relation of Pitch to Frequency: A Revised Scale, // American Journal of Psychology, vol. 53, no. 3, pp. 329-353, 1940. const double kM0 = 1127.01048; const double kF0 = 700.0; const double kFloorFrequency = 40.0; const double kCeilFrequency = 20000.0; } // namespace world #endif // WORLD_CONSTANT_NUMBERS_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/d4c.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_D4C_H_ #define WORLD_D4C_H_ #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Struct for D4C //----------------------------------------------------------------------------- typedef struct { double threshold; } D4COption; //----------------------------------------------------------------------------- // D4C() calculates the aperiodicity estimated by D4C. // // Input: // x : Input signal // x_length : Length of x // fs : Sampling frequency // temporal_positions : Time axis // f0 : F0 contour // f0_length : Length of F0 contour // fft_size : Number of samples of the aperiodicity in one frame. // : It is given by the equation fft_size / 2 + 1. // Output: // aperiodicity : Aperiodicity estimated by D4C. //----------------------------------------------------------------------------- void D4C(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, int fft_size, const D4COption *option, double **aperiodicity); //----------------------------------------------------------------------------- // InitializeD4COption allocates the memory to the struct and sets the // default parameters. // // Output: // option : Struct for the optional parameter. //----------------------------------------------------------------------------- void InitializeD4COption(D4COption *option); WORLD_END_C_DECLS #endif // WORLD_D4C_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/dio.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_DIO_H_ #define WORLD_DIO_H_ #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Struct for DIO //----------------------------------------------------------------------------- typedef struct { double f0_floor; double f0_ceil; double channels_in_octave; double frame_period; // msec int speed; // (1, 2, ..., 12) double allowed_range; // Threshold used for fixing the F0 contour. } DioOption; //----------------------------------------------------------------------------- // DIO // // Input: // x : Input signal // x_length : Length of x // fs : Sampling frequency // option : Struct to order the parameter for DIO // // Output: // temporal_positions : Temporal positions. // f0 : F0 contour. //----------------------------------------------------------------------------- void Dio(const double *x, int x_length, int fs, const DioOption *option, double *temporal_positions, double *f0); //----------------------------------------------------------------------------- // InitializeDioOption allocates the memory to the struct and sets the // default parameters. // // Output: // option : Struct for the optional parameter. //----------------------------------------------------------------------------- void InitializeDioOption(DioOption *option); //----------------------------------------------------------------------------- // GetSamplesForDIO() calculates the number of samples required for Dio(). // // Input: // fs : Sampling frequency [Hz] // x_length : Length of the input signal [Sample]. // frame_period : Frame shift [msec] // // Output: // The number of samples required to store the results of Dio() //----------------------------------------------------------------------------- int GetSamplesForDIO(int fs, int x_length, double frame_period); WORLD_END_C_DECLS #endif // WORLD_DIO_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/fft.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // These functions and variables are defined to use FFT as well as FFTW // Please see fft.cpp to show the detailed information //----------------------------------------------------------------------------- #ifndef WORLD_FFT_H_ #define WORLD_FFT_H_ #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS // Commands for FFT (This is the same as FFTW) #define FFT_FORWARD 1 #define FFT_BACKWARD 2 #define FFT_ESTIMATE 3 // Complex number for FFT typedef double fft_complex[2]; // Struct used for FFT typedef struct { int n; int sign; unsigned int flags; fft_complex *c_in; double *in; fft_complex *c_out; double *out; double *input; int *ip; double *w; } fft_plan; fft_plan fft_plan_dft_1d(int n, fft_complex *in, fft_complex *out, int sign, unsigned int flags); fft_plan fft_plan_dft_c2r_1d(int n, fft_complex *in, double *out, unsigned int flags); fft_plan fft_plan_dft_r2c_1d(int n, double *in, fft_complex *out, unsigned int flags); void fft_execute(fft_plan p); void fft_destroy_plan(fft_plan p); WORLD_END_C_DECLS #endif // WORLD_FFT_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/harvest.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_HARVEST_H_ #define WORLD_HARVEST_H_ #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Struct for Harvest //----------------------------------------------------------------------------- typedef struct { double f0_floor; double f0_ceil; double frame_period; } HarvestOption; //----------------------------------------------------------------------------- // Harvest // // Input: // x : Input signal // x_length : Length of x // fs : Sampling frequency // option : Struct to order the parameter for Harvest // // Output: // temporal_positions : Temporal positions. // f0 : F0 contour. //----------------------------------------------------------------------------- void Harvest(const double *x, int x_length, int fs, const HarvestOption *option, double *temporal_positions, double *f0); //----------------------------------------------------------------------------- // InitializeHarvestOption allocates the memory to the struct and sets the // default parameters. // // Output: // option : Struct for the optional parameter. //----------------------------------------------------------------------------- void InitializeHarvestOption(HarvestOption *option); //----------------------------------------------------------------------------- // GetSamplesForHarvest() calculates the number of samples required for // Harvest(). // // Input: // fs : Sampling frequency [Hz] // x_length : Length of the input signal [Sample] // frame_period : Frame shift [msec] // // Output: // The number of samples required to store the results of Harvest(). //----------------------------------------------------------------------------- int GetSamplesForHarvest(int fs, int x_length, double frame_period); WORLD_END_C_DECLS #endif // WORLD_HARVEST_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/macrodefinitions.h ================================================ //----------------------------------------------------------------------------- // Copyright (c) 2008-2011 The Department of Arts and Culture, // The Government of the Republic of South Africa. // // Contributors: Meraka Institute, CSIR, South Africa. // Giulio Paci. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // // MODIFIED: Giulio Paci // DATE : 22 January 2016 // // Some usefull macros and defines. //----------------------------------------------------------------------------- #ifndef WORLD_MACRODEFINITIONS_H_ #define WORLD_MACRODEFINITIONS_H_ // // @file macrodefinitions.h // Definitions of macros that are common to the whole World engine. // // // @ingroup WorldDefines // @defgroup WorldMacros System Macros // Definitions of macros that are common to the whole World engine. // @{ // // // Defines // // // @def WORLD_BEGIN_C_DECLS // Start block for enclosing C code for inclusion in C++ programs. // This allows C++ programs to include the C header files of the World // engine. @code extern "C" { @endcode // @hideinitializer // // // @def WORLD_END_C_DECLS // End block for enclosing C code for inclusion in C++ programs. // This allows C++ programs to include the C header files of the World // engine. @code } @endcode // @hideinitializer // #undef WORLD_BEGIN_C_DECLS #undef WORLD_END_C_DECLS #ifdef __cplusplus # define WORLD_BEGIN_C_DECLS extern "C" { # define WORLD_END_C_DECLS } #else // !__cplusplus # define WORLD_BEGIN_C_DECLS # define WORLD_END_C_DECLS #endif // __cplusplus // // @def WORLD_API // @hideinitializer // Declares a symbol to be exported for shared library usage. // // // @def WORLD_LOCAL // @hideinitializer // Declares a symbol hidden from other libraries. // // // @def WORLD_PLUGIN_API // @hideinitializer // Declares a symbol to be exported for plug-in usage. // // Generic helper definitions for shared library support #if defined _WIN32 || defined __CYGWIN__ # define WORLD_HELPER_DLL_IMPORT __declspec(dllimport) # define WORLD_HELPER_DLL_EXPORT __declspec(dllexport) # define WORLD_HELPER_DLL_LOCAL #else // ! defined _WIN32 || defined __CYGWIN__ || defined WORLD_WIN32 # if __GNUC__ >= 4 # define WORLD_HELPER_DLL_IMPORT __attribute__ ((visibility("default"))) # define WORLD_HELPER_DLL_EXPORT __attribute__ ((visibility("default"))) # define WORLD_HELPER_DLL_LOCAL __attribute__ ((visibility("hidden"))) # else // ! __GNUC__ >= 4 # define WORLD_HELPER_DLL_IMPORT # define WORLD_HELPER_DLL_EXPORT # define WORLD_HELPER_DLL_LOCAL # endif // __GNUC__ >= 4 #endif // defined _WIN32 || defined __CYGWIN__ || defined WORLD_WIN32 // // WORLD_LIBRARIES_EXPORTS // ---------------------- // WORLD_LIBRARIES_EXPORTS should be defined when compiling a // shared/dynamic library. // // Now we use the generic helper definitions above to define // WORLD_API and WORLD_LOCAL. WORLD_API is used for the public API symbols. // It's either DLL imports or DLL exports (or does nothing for static build) // WORLD_LOCAL is used for non-api symbols. // // WORLD_SRC // ------------------ // WORLD_SRC should be defined when building World (instead of just using it). // #ifdef WORLD_LIBRARIES_EXPORTS # ifdef WORLD_SRC # define WORLD_API WORLD_HELPER_DLL_EXPORT # else // !WORLD_SRC # define WORLD_API WORLD_HELPER_DLL_IMPORT # endif // WORLD_SRC # define WORLD_LOCAL WORLD_HELPER_DLL_LOCAL #else // !WORLD_LIBRARIES_EXPORTS (static library) # define WORLD_API # define WORLD_LOCAL #endif // WORLD_LIBRARIES_EXPORTS // // @} // end documentation // #endif // WORLD_MACRODEFINITIONS_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/matlabfunctions.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_MATLABFUNCTIONS_H_ #define WORLD_MATLABFUNCTIONS_H_ #include "../../../../framework.h" #include "common.h" #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // fftshift() swaps the left and right halves of input vector. // http://www.mathworks.com/help/matlab/ref/fftshift.html // // Input: // x : Input vector // x_length : Length of x // // Output: // y : Swapped vector x // // Caution: // Lengths of index and edges must be the same. //----------------------------------------------------------------------------- void fftshift(const double *x, int x_length, double *y); //----------------------------------------------------------------------------- // histc() counts the number of values in vector x that fall between the // elements in the edges vector (which must contain monotonically // nondecreasing values). n is a length(edges) vector containing these counts. // No elements of x can be complex. // http://www.mathworks.co.jp/help/techdoc/ref/histc.html // // Input: // x : Input vector // x_length : Length of x // edges : Input matrix (1-dimension) // edges_length : Length of edges // // Output: // index : Result counted in vector x // Caution: // Lengths of index and edges must be the same. //----------------------------------------------------------------------------- void histc(const double *x, int x_length, const double *edges, int edges_length, int *index); //----------------------------------------------------------------------------- // interp1() interpolates to find yi, the values of the underlying function Y // at the points in the vector or array xi. x must be a vector. // http://www.mathworks.co.jp/help/techdoc/ref/interp1.html // // Input: // x : Input vector (Time axis) // y : Values at x[n] // x_length : Length of x (Length of y must be the same) // xi : Required vector // xi_length : Length of xi (Length of yi must be the same) // // Output: // yi : Interpolated vector //----------------------------------------------------------------------------- LibSvcApi void interp1(const double *x, const double *y, int x_length, const double *xi, int xi_length, double *yi); //----------------------------------------------------------------------------- // decimate() carries out down sampling by both IIR and FIR filters. // Filter coeffiencts are based on FilterForDecimate(). // // Input: // x : Input signal // x_length : Length of x // r : Coefficient used for down sampling // (fs after down sampling is fs/r) // Output: // y : Output signal //----------------------------------------------------------------------------- void decimate(const double *x, int x_length, int r, double *y); //----------------------------------------------------------------------------- // matlab_round() calculates rounding. // // Input: // x : Input value // // Output: // y : Rounded value //----------------------------------------------------------------------------- int matlab_round(double x); //----------------------------------------------------------------------------- // diff() calculates differences and approximate derivatives // http://www.mathworks.co.jp/help/techdoc/ref/diff.html // // Input: // x : Input signal // x_length : Length of x // // Output: // y : Output signal //----------------------------------------------------------------------------- void diff(const double *x, int x_length, double *y); //----------------------------------------------------------------------------- // interp1Q() is the special case of interp1(). // We can use this function, provided that All periods of x-axis is the same. // // Input: // x : Origin of the x-axis // shift : Period of the x-axis // y : Values at x[n] // x_length : Length of x (Length of y must be the same) // xi : Required vector // xi_length : Length of xi (Length of yi must be the same) // // Output: // yi : Interpolated vector // // Caution: // Length of xi and yi must be the same. //----------------------------------------------------------------------------- void interp1Q(double x, double shift, const double *y, int x_length, const double *xi, int xi_length, double *yi); //----------------------------------------------------------------------------- // randn() generates pseudorandom numbers based on xorshift method. // // Output: // A generated pseudorandom number //----------------------------------------------------------------------------- double randn(void); //----------------------------------------------------------------------------- // randn_reseed() forces to seed the pseudorandom generator using initial // values. //----------------------------------------------------------------------------- void randn_reseed(void); //----------------------------------------------------------------------------- // fast_fftfilt() carries out the convolution on the frequency domain. // // Input: // x : Input signal // x_length : Length of x // h : Impulse response // h_length : Length of h // fft_size : Length of FFT // forward_real_fft : Struct to speed up the forward FFT // inverse_real_fft : Struct to speed up the inverse FFT // // Output: // y : Calculated result. //----------------------------------------------------------------------------- void fast_fftfilt(const double *x, int x_length, const double *h, int h_length, int fft_size, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, double *y); //----------------------------------------------------------------------------- // matlab_std() calculates the standard deviation of the input vector. // // Input: // x : Input vector // x_length : Length of x // // Output: // Calculated standard deviation //----------------------------------------------------------------------------- double matlab_std(const double *x, int x_length); WORLD_END_C_DECLS #endif // WORLD_MATLABFUNCTIONS_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/stonemask.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_STONEMASK_H_ #define WORLD_STONEMASK_H_ #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // StoneMask() refines the estimated F0 by Dio() // // Input: // x : Input signal // x_length : Length of the input signal // fs : Sampling frequency // time_axis : Temporal information // f0 : f0 contour // f0_length : Length of f0 // // Output: // refined_f0 : Refined F0 //----------------------------------------------------------------------------- void StoneMask(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, double *refined_f0); WORLD_END_C_DECLS #endif // WORLD_STONEMASK_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/synthesis.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_SYNTHESIS_H_ #define WORLD_SYNTHESIS_H_ #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Synthesis() synthesize the voice based on f0, spectrogram and // aperiodicity (not excitation signal). // // Input: // f0 : f0 contour // f0_length : Length of f0 // spectrogram : Spectrogram estimated by CheapTrick // fft_size : FFT size // aperiodicity : Aperiodicity spectrogram based on D4C // frame_period : Temporal period used for the analysis // fs : Sampling frequency // y_length : Length of the output signal (Memory of y has been // allocated in advance) // Output: // y : Calculated speech //----------------------------------------------------------------------------- void Synthesis(const double *f0, int f0_length, const double * const *spectrogram, const double * const *aperiodicity, int fft_size, double frame_period, int fs, int y_length, double *y); WORLD_END_C_DECLS #endif // WORLD_SYNTHESIS_H_ ================================================ FILE: libsvc/Modules/Lib/World/src/world/synthesisrealtime.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_SYNTHESISREALTIME_H_ #define WORLD_SYNTHESISREALTIME_H_ #include "world/common.h" #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // A struct for real-time synthesis. // I use no class for compatibility in C language. // Please make a class for encapsulating it as needed. // This synthesizer uses a ring buffer. //----------------------------------------------------------------------------- typedef struct { // Basic parameters int fs; double frame_period; int buffer_size; int number_of_pointers; int fft_size; // Sound buffer for output. The length is buffer_size [sample]. double *buffer; int current_pointer; int i; // For DC removal double *dc_remover; //--------------------------------------------------------------------------- // Followings are internal parameters. // You should not modify them if you are not expert. // Speech parameters in each pointer. int *f0_length; int *f0_origin; double ***spectrogram; double ***aperiodicity; // Note: // This is an extremely rough implementation. // I should optimize this implementation. int current_pointer2; int head_pointer; int synthesized_sample; // Internal parameters. int handoff; double handoff_phase; double handoff_f0; int last_location; int cumulative_frame; int current_frame; double **interpolated_vuv; double **pulse_locations; int **pulse_locations_index; int *number_of_pulses; double *impulse_response; // FFT MinimumPhaseAnalysis minimum_phase; InverseRealFFT inverse_real_fft; ForwardRealFFT forward_real_fft; } WorldSynthesizer; //----------------------------------------------------------------------------- // InitializeSynthesizer() initializes the synthesizer based on basic // parameters. // // Input: // fs : Sampling frequency // frame_period : Frame period (ms) // fft_size : FFT size // buffer_size : Buffer size (sample) // number_of_pointers : The number of elements in the ring buffer // // Output: // synth : Initialized synthesizer //----------------------------------------------------------------------------- void InitializeSynthesizer(int fs, double frame_period, int fft_size, int buffer_size, int number_of_pointers, WorldSynthesizer *synth); //----------------------------------------------------------------------------- // AddParameters() attempts to add speech parameters. // You can add several frames at the same time. // // Input: // f0 : F0 contour with length of f0_length // f0_length : This is associated with the number of frames // spectrogram : Spectrogram // aperiodicity : Aperiodicity // // Output: // synth : Synthesizer // // Return value: // 1: True, 0: False. //----------------------------------------------------------------------------- int AddParameters(double *f0, int f0_length, double **spectrogram, double **aperiodicity, WorldSynthesizer *synth); //----------------------------------------------------------------------------- // RefreshSynthesizer() sets the parameters to default. //----------------------------------------------------------------------------- void RefreshSynthesizer(WorldSynthesizer *synth); //----------------------------------------------------------------------------- // DestroySynthesizer() release the memory. //----------------------------------------------------------------------------- void DestroySynthesizer(WorldSynthesizer *synth); //----------------------------------------------------------------------------- // IsLocked() checks whether the synthesizer is locked or not. // "Lock" is defined as the situation that the ring buffer cannot add // parameters and cannot synthesize the waveform. // It will be caused when the duration calculated by the number of added frames // is below 1 / F0 + buffer_size / fs. // If this function returns True, please refresh the synthesizer. // // Input: // Synth : Synthesizer (pointer) // // Output: // 1: True, 0: False. //----------------------------------------------------------------------------- int IsLocked(WorldSynthesizer *synth); //----------------------------------------------------------------------------- // Synthesis2() generates speech with length of synth->buffer_size sample. // The parameters are automatially updated, and memory is also released. // // Input: // Synth : Synthesizer (pointer) // // Output: // 1: True, 0: False. //----------------------------------------------------------------------------- int Synthesis2(WorldSynthesizer *synth); WORLD_END_C_DECLS #endif // WORLD_SYNTHESISREALTIME_H_ ================================================ FILE: libsvc/Modules/Lib/World/tools/audioio.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // .wav input/output functions were modified for compatibility with C language. // Since these functions (wavread() and wavwrite()) are roughly implemented, // we recommend more suitable functions provided by other organizations. // This file is independent of WORLD project and for the test.cpp. //----------------------------------------------------------------------------- #include "./audioio.h" #include #include #include #include #if (defined (__WIN32__) || defined (_WIN32)) && !defined (__MINGW32__) #pragma warning(disable : 4996) #endif namespace { static inline int MyMaxInt(int x, int y) { return x > y ? x : y; } static inline int MyMinInt(int x, int y) { return x < y ? x : y; } //----------------------------------------------------------------------------- // CheckHeader() checks the .wav header. This function can only support the // monaural wave file. This function is only used in waveread(). //----------------------------------------------------------------------------- static int CheckHeader(FILE *fp) { char data_check[5]; fread(data_check, 1, 4, fp); // "RIFF" data_check[4] = '\0'; if (0 != strcmp(data_check, "RIFF")) { printf("RIFF error.\n"); return 0; } fseek(fp, 4, SEEK_CUR); fread(data_check, 1, 4, fp); // "WAVE" if (0 != strcmp(data_check, "WAVE")) { printf("WAVE error.\n"); return 0; } fread(data_check, 1, 4, fp); // "fmt " if (0 != strcmp(data_check, "fmt ")) { printf("fmt error.\n"); return 0; } fread(data_check, 1, 4, fp); // 1 0 0 0 if (!(16 == data_check[0] && 0 == data_check[1] && 0 == data_check[2] && 0 == data_check[3])) { printf("fmt (2) error.\n"); return 0; } fread(data_check, 1, 2, fp); // 1 0 if (!(1 == data_check[0] && 0 == data_check[1])) { printf("Format ID error.\n"); return 0; } fread(data_check, 1, 2, fp); // 1 0 if (!(1 == data_check[0] && 0 == data_check[1])) { printf("This function cannot support stereo file\n"); return 0; } return 1; } //----------------------------------------------------------------------------- // GetParameters() extracts fp, nbit, wav_length from the .wav file // This function is only used in wavread(). //----------------------------------------------------------------------------- static int GetParameters(FILE *fp, int *fs, int *nbit, int *wav_length) { char data_check[5] = {0}; data_check[4] = '\0'; unsigned char for_int_number[4]; fread(for_int_number, 1, 4, fp); *fs = 0; for (int i = 3; i >= 0; --i) *fs = *fs * 256 + for_int_number[i]; // Quantization fseek(fp, 6, SEEK_CUR); fread(for_int_number, 1, 2, fp); *nbit = for_int_number[0]; // Skip until "data" is found. 2011/03/28 while (0 != fread(data_check, 1, 1, fp)) { if (data_check[0] == 'd') { fread(&data_check[1], 1, 3, fp); if (0 != strcmp(data_check, "data")) fseek(fp, -3, SEEK_CUR); else break; } } if (0 != strcmp(data_check, "data")) { printf("data error.\n"); return 0; } fread(for_int_number, 1, 4, fp); // "data" *wav_length = 0; for (int i = 3; i >= 0; --i) *wav_length = *wav_length * 256 + for_int_number[i]; *wav_length /= (*nbit / 8); return 1; } } // namespace void wavwrite(const double *x, int x_length, int fs, int nbit, const char *filename) { FILE *fp = fopen(filename, "wb"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } char text[4] = {'R', 'I', 'F', 'F'}; uint32_t long_number = 36 + x_length * 2; fwrite(text, 1, 4, fp); fwrite(&long_number, 4, 1, fp); text[0] = 'W'; text[1] = 'A'; text[2] = 'V'; text[3] = 'E'; fwrite(text, 1, 4, fp); text[0] = 'f'; text[1] = 'm'; text[2] = 't'; text[3] = ' '; fwrite(text, 1, 4, fp); long_number = 16; fwrite(&long_number, 4, 1, fp); int16_t short_number = 1; fwrite(&short_number, 2, 1, fp); short_number = 1; fwrite(&short_number, 2, 1, fp); long_number = fs; fwrite(&long_number, 4, 1, fp); long_number = fs * 2; fwrite(&long_number, 4, 1, fp); short_number = 2; fwrite(&short_number, 2, 1, fp); short_number = 16; fwrite(&short_number, 2, 1, fp); text[0] = 'd'; text[1] = 'a'; text[2] = 't'; text[3] = 'a'; fwrite(text, 1, 4, fp); long_number = x_length * 2; fwrite(&long_number, 4, 1, fp); int16_t tmp_signal; for (int i = 0; i < x_length; ++i) { tmp_signal = static_cast(MyMaxInt(-32768, MyMinInt(32767, static_cast(x[i] * 32767)))); fwrite(&tmp_signal, 2, 1, fp); } fclose(fp); } int GetAudioLength(const char *filename) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { return 0; } if (0 == CheckHeader(fp)) { fclose(fp); return -1; } char data_check[5] = { 0 }; data_check[4] = '\0'; unsigned char for_int_number[4]; // Quantization fseek(fp, 10, SEEK_CUR); fread(for_int_number, 1, 2, fp); int nbit = for_int_number[0]; while (0 != fread(data_check, 1, 1, fp)) { if ('d' == data_check[0]) { fread(&data_check[1], 1, 3, fp); if (0 != strcmp(data_check, "data")) fseek(fp, -3, SEEK_CUR); else break; } } if (0 != strcmp(data_check, "data")) { fclose(fp); return -1; } fread(for_int_number, 1, 4, fp); // "data" fclose(fp); int wav_length = 0; for (int i = 3; i >= 0; --i) wav_length = wav_length * 256 + for_int_number[i]; wav_length /= (nbit / 8); return wav_length; } void wavread(const char* filename, int *fs, int *nbit, double *x) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File not found.\n"); return; } if (0 == CheckHeader(fp)) { fclose(fp); return; } int x_length; if (0 == GetParameters(fp, fs, nbit, &x_length)) { fclose(fp); return; } int quantization_byte = *nbit / 8; double zero_line = pow(2.0, *nbit - 1); double tmp, sign_bias; unsigned char for_int_number[4]; for (int i = 0; i < x_length; ++i) { sign_bias = tmp = 0.0; fread(for_int_number, 1, quantization_byte, fp); // "data" if (for_int_number[quantization_byte-1] >= 128) { sign_bias = pow(2.0, *nbit - 1); for_int_number[quantization_byte - 1] = for_int_number[quantization_byte - 1] & 0x7F; } for (int j = quantization_byte - 1; j >= 0; --j) tmp = tmp * 256.0 + for_int_number[j]; x[i] = (tmp - sign_bias) / zero_line; } fclose(fp); } ================================================ FILE: libsvc/Modules/Lib/World/tools/audioio.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_AUDIOIO_H_ #define WORLD_AUDIOIO_H_ #ifdef __cplusplus extern "C" { #endif //----------------------------------------------------------------------------- // wavwrite() write a .wav file. // Input: // x : Input signal // x_ength : Signal length of x [sample] // fs : Sampling frequency [Hz] // nbit : Quantization bit [bit] // filename : Name of the output signal. // Caution: // The variable nbit is not used in this function. // This function only supports the 16 bit. //----------------------------------------------------------------------------- void wavwrite(const double *x, int x_length, int fs, int nbit, const char *filename); //----------------------------------------------------------------------------- // GetAudioLength() returns the length of .wav file. // Input: // filename : Filename of a .wav file. // Output: // The number of samples of the file .wav //----------------------------------------------------------------------------- int GetAudioLength(const char *filename); //----------------------------------------------------------------------------- // wavread() read a .wav file. // The memory of output x must be allocated in advance. // Input: // filename : Filename of the input file. // Output: // fs : Sampling frequency [Hz] // nbit : Quantization bit [bit] // x : The output waveform. //----------------------------------------------------------------------------- void wavread(const char* filename, int *fs, int *nbit, double *x); #ifdef __cplusplus } #endif #endif // WORLD_AUDIOIO_H_ ================================================ FILE: libsvc/Modules/Lib/World/tools/parameterio.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2017 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Save/Load functions for three speech parameters. //----------------------------------------------------------------------------- #include "./parameterio.h" #include #include #include namespace { static void WriteOneParameter(FILE *fp, const char *text, double parameter, int size) { fwrite(text, 1, 4, fp); if (size == 4) { int parameter_int = static_cast(parameter); fwrite(¶meter_int, 4, 1, fp); } else { fwrite(¶meter, 8, 1, fp); } } static void LoadParameters(FILE *fp, int *number_of_frames, int *fft_size, int *number_of_dimensions) { char data_check[12]; fread(&data_check, 1, 4, fp); // NOF fread(number_of_frames, 4, 1, fp); fread(&data_check, 1, 12, fp); // FP (skipped) fread(&data_check, 1, 4, fp); // FFT fread(fft_size, 4, 1, fp); fread(&data_check, 1, 4, fp); // NOD fread(number_of_dimensions, 4, 1, fp); *number_of_dimensions = *number_of_dimensions == 0 ? *fft_size / 2 + 1 : *number_of_dimensions; fread(&data_check, 1, 8, fp); // FS (skipped) } static int CheckHeader(FILE *fp, const char *text) { char data_check[5]; fread(data_check, 1, 4, fp); // "F0 " data_check[4] = '\0'; if (0 != strcmp(data_check, text)) { printf("Header error.\n"); fclose(fp); return 0; } return 1; } } // namespace void WriteF0(const char *filename, int f0_length, double frame_period, const double *temporal_positions, const double *f0, int text_flag) { if (text_flag == 1) { FILE *fp = fopen(filename, "w"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } for (int i = 0; i < f0_length; ++i) fprintf(fp, "%.5f %.5f\r\n", temporal_positions[i], f0[i]); fclose(fp); } else { FILE *fp = fopen(filename, "wb"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } // Header fwrite("F0 ", 1, 4, fp); // Parameters WriteOneParameter(fp, "NOF ", f0_length, 4); WriteOneParameter(fp, "FP ", frame_period, 8); // Data fwrite(f0, 8, f0_length, fp); fclose(fp); } } int ReadF0(const char *filename, double *temporal_positions, double *f0) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File cannot be opened.\n"); return 0; } // Header if (CheckHeader(fp, "F0 ") == 0) return 0; // Parameters char data_check[5]; fread(data_check, 1, 4, fp); // "NOF " int number_of_frames; fread(&number_of_frames, 4, 1, fp); fread(data_check, 1, 4, fp); // "FP " double frame_period; fread(&frame_period, 8, 1, fp); // Data fread(f0, 8, number_of_frames, fp); fclose(fp); for (int i = 0; i < number_of_frames; ++i) temporal_positions[i] = i / 1000.0 * frame_period; return 1; } double GetHeaderInformation(const char *filename, const char *parameter) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File cannot be opened.\n"); return 0; } char data_check[5]; data_check[4] = '\0'; for (int i = 0; i < 13; ++i) { fread(data_check, 1, 4, fp); if (0 != strcmp(data_check, parameter)) continue; if (0 == strcmp(parameter, "FP ")) { double answer; fread(&answer, 8, 1, fp); fclose(fp); return answer; } else { int answer; fread(&answer, 4, 1, fp); fclose(fp); return static_cast(answer); } } return 0; } void WriteSpectralEnvelope(const char *filename, int fs, int f0_length, double frame_period, int fft_size, int number_of_dimensions, const double * const *spectrogram) { FILE *fp = fopen(filename, "wb"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } // Header fwrite("SPEC", 1, 4, fp); // Parameters WriteOneParameter(fp, "NOF ", f0_length, 4); WriteOneParameter(fp, "FP ", frame_period, 8); WriteOneParameter(fp, "FFT ", fft_size, 4); WriteOneParameter(fp, "NOD ", number_of_dimensions, 4); WriteOneParameter(fp, "FS ", fs, 4); number_of_dimensions = number_of_dimensions == 0 ? fft_size / 2 + 1 : number_of_dimensions; // Data for (int i = 0; i < f0_length; ++i) fwrite(spectrogram[i], 8, number_of_dimensions, fp); fclose(fp); } int ReadSpectralEnvelope(const char *filename, double **spectrogram) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File cannot be opened.\n"); return 0; } // Header if (CheckHeader(fp, "SPEC") == 0) return 0; // Parameters int number_of_frames, fft_size, number_of_dimensions; LoadParameters(fp, &number_of_frames, &fft_size, &number_of_dimensions); // Data for (int i = 0; i < number_of_frames; ++i) fread(spectrogram[i], 8, number_of_dimensions, fp); fclose(fp); return 1; } void WriteAperiodicity(const char *filename, int fs, int f0_length, double frame_period, int fft_size, int number_of_dimensions, const double * const *aperiodicity) { FILE *fp = fopen(filename, "wb"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } // Header fwrite("AP ", 1, 4, fp); // Parameters WriteOneParameter(fp, "NOF ", f0_length, 4); WriteOneParameter(fp, "FP ", frame_period, 8); WriteOneParameter(fp, "FFT ", fft_size, 4); WriteOneParameter(fp, "NOD ", number_of_dimensions, 4); WriteOneParameter(fp, "FS ", fs, 4); number_of_dimensions = number_of_dimensions == 0 ? fft_size / 2 + 1 : number_of_dimensions; // Data for (int i = 0; i < f0_length; ++i) fwrite(aperiodicity[i], 8, number_of_dimensions, fp); fclose(fp); } int ReadAperiodicity(const char *filename, double **aperiodicity) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File cannot be opened.\n"); return 0; } // Header if (CheckHeader(fp, "AP ") == 0) return 0; // Parameters int number_of_frames, fft_size, number_of_dimensions; LoadParameters(fp, &number_of_frames, &fft_size, &number_of_dimensions); // Data for (int i = 0; i < number_of_frames; ++i) fread(aperiodicity[i], 8, number_of_dimensions, fp); fclose(fp); return 1; } ================================================ FILE: libsvc/Modules/Lib/World/tools/parameterio.h ================================================ //----------------------------------------------------------------------------- // Copyright 2017 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_PARAMETERIO_H_ #define WORLD_PARAMETERIO_H_ #ifdef __cplusplus extern "C" { #endif //----------------------------------------------------------------------------- // WriteF0() writes the F0 contour. // // Input: // filename : Filename used for file output // f0_length : Length of F0 contour // frame_period : Frame shift used for analysis // temporal_positions : Time axis // f0 : F0 contour // text_flag : The file is written as text (NOT binary). //----------------------------------------------------------------------------- void WriteF0(const char *filename, int f0_length, double frame_period, const double *temporal_positions, const double *f0, int text_flag); //----------------------------------------------------------------------------- // ReadF0() reads the F0 contour from a file.. // // Input: // filename : Filename used for file output // // Output: // temporal_positions : Time axis // f0 : F0 contour // // Note: Memory must be allocated before calling this function. //----------------------------------------------------------------------------- int ReadF0(const char *filename, double *temporal_positions, double *f0); //----------------------------------------------------------------------------- // GetHeaderInformation() reads a parameter from a file. // // Input: // filename : Filename used for file output // parameter : Required parameter // : "NOF ": number of samples (int) // : "FP ": frame shift (double) // : "FFT ": FFT size (int) // : "NOD ": number of dimensions (int) // : "FS ": sampling frequency // // Note: F0 does not include "FFT ", "NOD ", and "FS ". // These are ignored in cases where they are used for F0 file. //----------------------------------------------------------------------------- double GetHeaderInformation(const char *filename, const char *parameter); //----------------------------------------------------------------------------- // WriteSpectralEnvelope() writes the spectral envelope. // // Input: // filename : Filename used for file output // fs : Sampling frequency // f0_length : Length of F0 contour // frame_period : Frame shift used for analysis // fft_size : FFT size used for analysis // number_of_dimensions : Number of dimensions per frame // spectrogram : Spectral envelope estimated by CheapTrick //----------------------------------------------------------------------------- void WriteSpectralEnvelope(const char *filename, int fs, int f0_length, double frame_period, int fft_size, int number_of_dimensions, const double * const *spectrogram); //----------------------------------------------------------------------------- // ReadSpectralEnvelope() reads the spectral envelope from a file. // // Input: // filename : Filename used for file output // // Output: // spectrogram : Spectral envelope estimated by CheapTrick // // Note: Memory must be allocated before calling this function. //----------------------------------------------------------------------------- int ReadSpectralEnvelope(const char *filename, double **spectrogram); //----------------------------------------------------------------------------- // WriteAperiodicity() writes the aperiodicity. // // Input: // filename : Filename used for file output // fs : Sampling frequency // f0_length : Length of F0 contour // frame_period : Frame shift used for analysis // fft_size : FFT size used for analysis // number_of_dimensions : Number of dimensions per frame // spectrogram : Spectral envelope estimated by CheapTrick //----------------------------------------------------------------------------- void WriteAperiodicity(const char *filename, int fs, int f0_length, double frame_period, int fft_size, int number_of_dimensions, const double * const *aperiodicity); //----------------------------------------------------------------------------- // ReadAperiodicity() reads the aperiodicity from a file. // // Input: // filename : Filename used for file output // // Output: // spectrogram : Spectral envelope estimated by CheapTrick // // Note: Memory must be allocated before calling this function. //----------------------------------------------------------------------------- int ReadAperiodicity(const char *filename, double **aperiodicity); #ifdef __cplusplus } #endif #endif // WORLD_PARAMETERIO_H_ ================================================ FILE: libsvc/Modules/README.md ================================================ # Example ```c++ #include "Modules/Models/header/Vits.hpp" int main(){ rapidjson::Document Config; Config.Parse("Your Config"); //Progress bar InferClass::BaseModelType::callback a_callback = [](size_t a, size_t b) {std::cout << std::to_string((float)a * 100.f / (float)b) << "%\n"; }; //return params for inference InferClass::BaseModelType::callback_params b_callback = []() { auto cbaaa = InferClass::InferConfigs(); cbaaa.kmeans_rate = 0.5; cbaaa.keys = 0; return cbaaa; }; //modify duration per phoneme InferClass::TTS::DurationCallback c_callback = [](std::vector&) {}; std::vector output; try { std::wstring inp("watashinoonaniomitekudasai"); auto model = dynamic_cast(new InferClass::VitsSvc(modConfigJson, a_callback, b_callback)); output = model->Inference(inp); Wav outWav(model->GetSamplingRate(), output.size() * 2, output.data()); outWav.Writef(L"test.wav"); delete model; } catch(std::exception& e) { std::cout << e.what(); } } ``` ================================================ FILE: libsvc/Modules/framework.h ================================================ #pragma once #ifndef LibSvcApi #ifdef MoeVSDll #ifdef LibSvcDll #define LibSvcApi __declspec(dllexport) #else #ifndef MoeVS #define LibSvcApi __declspec(dllimport) #else #define LibSvcApi #endif #endif #else #define LibSvcApi #endif #endif ================================================ FILE: libsvc/Modules/header/InferTools/AvCodec/AvCodeResample.h ================================================ #pragma once #include #include #include "../../StringPreprocess.hpp" #include "matlabfunctions.h" #include "../inferTools.hpp" extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "libswresample/swresample.h" #include "libavutil/samplefmt.h" } class AudioPreprocess { public: struct WAV_HEADER { char RIFF[4] = { 'R','I','F','F' }; //RIFF标识 unsigned long ChunkSize; //文件大小-8 char WAVE[4] = { 'W','A','V','E' }; //WAVE块 char fmt[4] = { 'f','m','t',' ' }; //fmt块 unsigned long Subchunk1Size; //fmt块大小 unsigned short AudioFormat; //编码格式 unsigned short NumOfChan; //声道数 WAV_HEADER(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1) :ChunkSize(cs), Subchunk1Size(sc1s), AudioFormat(af), NumOfChan(nc) {} }; LibSvcApi static WAV_HEADER GetHeader(const std::wstring& path); LibSvcApi static std::vector arange(double start, double end, double step = 1.0, double div = 1.0); LibSvcApi std::vector codec(const std::wstring& path, int sr); LibSvcApi void release(); LibSvcApi void init(); LibSvcApi AudioPreprocess(); ~AudioPreprocess() { release(); } private: AVFrame* inFrame; uint8_t* out_buffer; SwrContext* swrContext; AVCodecContext* avCodecContext; AVFormatContext* avFormatContext; AVPacket* packet; }; ================================================ FILE: libsvc/Modules/header/InferTools/Cluster/MoeVSBaseCluster.hpp ================================================ /** * FileName: MoeVSBaseCluster.hpp * Note: MoeVoiceStudioCore 聚类基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #define MoeVoiceStudioClusterHeader namespace MoeVoiceStudioCluster { #define MoeVoiceStudioClusterEnd } MoeVoiceStudioClusterHeader class MoeVoiceStudioBaseCluster { public: MoeVoiceStudioBaseCluster() = default; virtual ~MoeVoiceStudioBaseCluster() = default; /** * \brief 查找聚类最邻近点 * \param point 待查找的点 * \param sid 角色ID * \param n_points 点数 * \return 查找到的最邻近点 */ virtual std::vector find(float* point, long sid, int64_t n_points = 1); }; MoeVoiceStudioClusterEnd ================================================ FILE: libsvc/Modules/header/InferTools/Cluster/MoeVSClusterManager.hpp ================================================ /** * FileName: MoeVSClusterManager.hpp * Note: MoeVoiceStudioCore 聚类管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVSBaseCluster.hpp" #include #include #include "../../framework.h" MoeVoiceStudioClusterHeader class MoeVSCluster { public: MoeVSCluster() = default; MoeVSCluster(MoeVoiceStudioBaseCluster* _ext) : _cluster_ext(_ext) {} MoeVSCluster(const MoeVSCluster&) = delete; MoeVSCluster(MoeVSCluster&& _ext) noexcept { delete _cluster_ext; _cluster_ext = _ext._cluster_ext; _ext._cluster_ext = nullptr; } MoeVSCluster& operator=(const MoeVSCluster&) = delete; MoeVSCluster& operator=(MoeVSCluster&& _ext) noexcept { if (this == &_ext) return *this; delete _cluster_ext; _cluster_ext = _ext._cluster_ext; _ext._cluster_ext = nullptr; return *this; } ~MoeVSCluster() { delete _cluster_ext; _cluster_ext = nullptr; } MoeVoiceStudioBaseCluster* operator->() const { return _cluster_ext; } private: MoeVoiceStudioBaseCluster* _cluster_ext = nullptr; }; using GetMoeVSClusterFn = std::function; LibSvcApi void RegisterMoeVSCluster(const std::wstring& _name, const GetMoeVSClusterFn& _constructor_fn); /** * \brief 获取聚类 * \param _name 类名 * \param _path 聚类数据路径 * \param hidden_size hubert维数 * \param KmeansLen 聚类的长度 * \return 聚类 */ LibSvcApi MoeVSCluster GetMoeVSCluster(const std::wstring& _name, const std::wstring& _path, size_t hidden_size, size_t KmeansLen); MoeVoiceStudioClusterEnd ================================================ FILE: libsvc/Modules/header/InferTools/Cluster/MoeVSIndexCluster.hpp ================================================ /** * FileName: MoeVSIndexCluster.hpp * Note: MoeVoiceStudioCore 官方聚类(Index) * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #ifdef MoeVoiceStudioIndexCluster #include #include "MoeVSBaseCluster.hpp" #include #include MoeVoiceStudioClusterHeader class IndexClusterCore { public: IndexClusterCore() = delete; ~IndexClusterCore(); IndexClusterCore(const char* _path); IndexClusterCore(const IndexClusterCore&) = delete; IndexClusterCore(IndexClusterCore&& move) noexcept; IndexClusterCore& operator=(const IndexClusterCore&) = delete; IndexClusterCore& operator=(IndexClusterCore&& move) noexcept; std::vector find(const float* points, faiss::idx_t n_points, faiss::idx_t n_searched_points = 8); float* GetVec(faiss::idx_t index); private: faiss::Index* IndexPtr = nullptr; faiss::idx_t Dim = 0; std::vector IndexsVector; }; class IndexCluster : public MoeVoiceStudioBaseCluster { public: IndexCluster() = delete; ~IndexCluster() override = default; IndexCluster(const std::wstring& _path, size_t hidden_size, size_t KmeansLen); std::vector find(float* point, long sid, int64_t n_points = 1) override; private: std::vector Indexs; size_t n_hidden_size = 256; }; MoeVoiceStudioClusterEnd #endif ================================================ FILE: libsvc/Modules/header/InferTools/Cluster/MoeVSKmeansCluster.hpp ================================================ /** * FileName: MoeVSKmeansCluster.hpp * Note: MoeVoiceStudioCore 官方聚类(Kmeans) * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVSBaseCluster.hpp" #include "../DataStruct/KDTree.hpp" #include MoeVoiceStudioClusterHeader class KMeansCluster : public MoeVoiceStudioBaseCluster { public: KMeansCluster() = delete; ~KMeansCluster() override = default; KMeansCluster(const std::wstring& _path, size_t hidden_size, size_t KmeansLen); std::vector find(float* point, long sid, int64_t n_points = 1) override; private: std::vector _tree; size_t dims = 0; }; MoeVoiceStudioClusterEnd ================================================ FILE: libsvc/Modules/header/InferTools/DataStruct/KDTree.hpp ================================================ #pragma once /* * file: KDTree.hpp * author: J. Frederico Carvalho * * This is an adaptation of the KD-tree implementation in rosetta code * https://rosettacode.org/wiki/K-d_tree * It is a reimplementation of the C code using C++. * It also includes a few more queries than the original * */ #include #include #include using point_t = std::vector; using indexArr = std::vector< size_t >; using pointIndex = std::pair< std::vector< float >, size_t >; class KDNode { public: using KDNodePtr = std::shared_ptr< KDNode >; size_t index; point_t x; KDNodePtr left; KDNodePtr right; // initializer KDNode(); KDNode(const point_t &, const size_t &, const KDNodePtr &, const KDNodePtr &); KDNode(const pointIndex &, const KDNodePtr &, const KDNodePtr &); ~KDNode(); // getter float coord(const size_t &); // conversions explicit operator bool(); explicit operator point_t(); explicit operator size_t(); explicit operator pointIndex(); }; using KDNodePtr = std::shared_ptr< KDNode >; KDNodePtr NewKDNodePtr(); // square euclidean distance inline float dist2(const point_t &, const point_t &); inline float dist2(const KDNodePtr &, const KDNodePtr &); // euclidean distance inline float dist(const point_t &, const point_t &); inline float dist(const KDNodePtr &, const KDNodePtr &); // Need for sorting class comparer { public: size_t idx; explicit comparer(size_t idx_); inline bool compare_idx( const std::pair< std::vector< float >, size_t > &, // const std::pair< std::vector< float >, size_t > & // ); }; using pointIndexArr = std::vector< pointIndex >; inline void sort_on_idx(const pointIndexArr::iterator &, // const pointIndexArr::iterator &, // size_t idx); using pointVec = std::vector; class KDTree { KDNodePtr root; KDNodePtr leaf; KDNodePtr make_tree(const pointIndexArr::iterator &begin, // const pointIndexArr::iterator &end, // const size_t &length, // const size_t &level // ); public: KDTree() = default; explicit KDTree(pointVec point_array); private: KDNodePtr nearest_( // const KDNodePtr &branch, // const point_t &pt, // const size_t &level, // const KDNodePtr &best, // const float&best_dist // ); // default caller KDNodePtr nearest_(const point_t &pt); public: point_t nearest_point(const point_t &pt); size_t nearest_index(const point_t &pt); pointIndex nearest_pointIndex(const point_t &pt); private: pointIndexArr neighborhood_( // const KDNodePtr &branch, // const point_t &pt, // const float&rad, // const size_t &level // ); public: pointIndexArr neighborhood( // const point_t &pt, // const float&rad); pointVec neighborhood_points( // const point_t &pt, // const float&rad); indexArr neighborhood_indices( // const point_t &pt, // const float&rad); }; ================================================ FILE: libsvc/Modules/header/InferTools/DataStruct/README.md ================================================ ## KdTree From J. Frederico Carvalho ================================================ FILE: libsvc/Modules/header/InferTools/F0Extractor/BaseF0Extractor.hpp ================================================ /** * FileName: BaseF0Extractor.hpp * Note: MoeVoiceStudioCore F0提取算法基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include #define MoeVoiceStudioF0ExtractorHeader namespace MoeVSF0Extractor{ #define MoeVoiceStudioF0ExtractorEnd } MoeVoiceStudioF0ExtractorHeader #define __NAME__MOEVS(x) std::wstring ClassName = (x) class BaseF0Extractor { public: __NAME__MOEVS(L"MoeVSF0Extractor"); BaseF0Extractor() = delete; /** * \brief 构造F0提取器 * \param sampling_rate 采样率 * \param hop_size HopSize * \param n_f0_bins F0Bins * \param max_f0 最大F0 * \param min_f0 最小F0 */ BaseF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); virtual ~BaseF0Extractor() = default; /** * \brief 提取F0 * \param PCMData 音频PCM数据(SignedInt16 单声道) * \param TargetLength 目标F0长度 * \return F0 */ virtual std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength); /** * \brief 提取F0 * \param PCMData 音频PCM数据(SignedInt16 单声道) * \param TargetLength 目标F0长度 * \return F0 */ std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength); /** * \brief 提取F0 * \param PCMData 音频PCM数据(SignedInt16 单声道) * \param TargetLength 目标F0长度 * \return F0 */ std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength); static std::vector arange(double start, double end, double step = 1.0, double div = 1.0); protected: const uint32_t fs; const uint32_t hop; const uint32_t f0_bin; const double f0_max; const double f0_min; double f0_mel_min; double f0_mel_max; }; #undef __NAME__MOEVS MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/header/InferTools/F0Extractor/DioF0Extractor.hpp ================================================ /** * FileName: DioF0Extractor.hpp * Note: MoeVoiceStudioCore 官方F0提取算法 Dio * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "BaseF0Extractor.hpp" MoeVoiceStudioF0ExtractorHeader class DioF0Extractor : public BaseF0Extractor { public: DioF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); ~DioF0Extractor() override = default; void compute_f0(const double* PCMData, size_t PCMLen); void InterPf0(size_t TargetLength); std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength) override; private: std::vector refined_f0; }; MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/header/InferTools/F0Extractor/F0ExtractorManager.hpp ================================================ /** * FileName: F0ExtractorManager.hpp * Note: MoeVoiceStudioCore F0提取器管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "BaseF0Extractor.hpp" #include #include "../../framework.h" MoeVoiceStudioF0ExtractorHeader class F0Extractor { public: F0Extractor() = delete; F0Extractor(BaseF0Extractor* _ext) : _f0_ext(_ext) {} F0Extractor(const F0Extractor&) = delete; F0Extractor(F0Extractor&& _ext) noexcept { delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; } F0Extractor& operator=(const F0Extractor&) = delete; F0Extractor& operator=(F0Extractor&& _ext) noexcept { if (this == &_ext) return *this; delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; return *this; } ~F0Extractor() { delete _f0_ext; _f0_ext = nullptr; } BaseF0Extractor* operator->() const { return _f0_ext; } private: BaseF0Extractor* _f0_ext = nullptr; }; using GetF0ExtractorFn = std::function; LibSvcApi void RegisterF0Extractor(const std::wstring& _name, const GetF0ExtractorFn& _constructor_fn); /** * \brief 获取F0提取器 * \param _name 类名 * \param fs 采样率 * \param hop HopSize * \param f0_bin F0Bins * \param f0_max 最大F0 * \param f0_min 最小F0 * \return F0提取器 */ LibSvcApi F0Extractor GetF0Extractor(const std::wstring& _name, uint32_t fs = 48000, uint32_t hop = 512, uint32_t f0_bin = 256, double f0_max = 1100.0, double f0_min = 50.0); LibSvcApi std::vector GetF0ExtractorList(); MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/header/InferTools/F0Extractor/HarvestF0Extractor.hpp ================================================ /** * FileName: HarvestF0Extractor.hpp * Note: MoeVoiceStudioCore 官方F0提取算法 Harvest * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "BaseF0Extractor.hpp" MoeVoiceStudioF0ExtractorHeader class HarvestF0Extractor : public BaseF0Extractor { public: HarvestF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); ~HarvestF0Extractor() override = default; void compute_f0(const double* PCMData, size_t PCMLen); void InterPf0(size_t TargetLength); std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength) override; private: std::vector refined_f0; }; MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/header/InferTools/F0Extractor/NetF0Predictors.hpp ================================================ /** * FileName: NetF0Predictors.hpp * Note: MoeVoiceStudioCore 官方F0提取算法 Net * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "BaseF0Extractor.hpp" #include MoeVoiceStudioF0ExtractorHeader class NetF0Class { public: NetF0Class(); ~NetF0Class() { Destory(); } void Destory(); void BuildCPUEnv(unsigned ThreadCount); void BuildCUDAEnv(unsigned Did); void BuildDMLEnv(unsigned Did); void LoadModel(const std::wstring& path); Ort::Env* NetF0Env = nullptr; Ort::SessionOptions* NetF0Options = nullptr; Ort::Session* Model = nullptr; Ort::MemoryInfo* Memory = nullptr; private: std::wstring NetF0PathDir; }; class RMVPEF0Extractor : public BaseF0Extractor { public: RMVPEF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); ~RMVPEF0Extractor() override = default; void InterPf0(size_t TargetLength); std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength) override; private: std::vector InputNames = { "waveform", "threshold" }; std::vector OutputNames = { "f0", "uv" }; std::vector refined_f0; }; class MELPEF0Extractor : public BaseF0Extractor { public: MELPEF0Extractor(int sampling_rate, int hop_size, int n_f0_bins = 256, double max_f0 = 1100.0, double min_f0 = 50.0); ~MELPEF0Extractor() override = default; void InterPf0(size_t TargetLength); std::vector ExtractF0(const std::vector& PCMData, size_t TargetLength) override; private: std::vector InputNames = { "waveform" }; std::vector OutputNames = { "f0" }; std::vector refined_f0; }; void EmptyCache(); MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/header/InferTools/Sampler/MoeVSBaseSampler.hpp ================================================ /** * FileName: MoeVSBaseSampler.hpp * Note: MoeVoiceStudioCore Diffusion 采样器基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #define MoeVoiceStudioSamplerHeader namespace MoeVSSampler { #define MoeVoiceStudioSamplerEnd } #include #include MoeVoiceStudioSamplerHeader class MoeVSBaseSampler { public: using ProgressCallback = std::function; /** * \brief 构造采样器 * \param alpha Alphas Onnx模型Session * \param dfn DenoiseFn Onnx模型Session * \param pred Predictor Onnx模型Session * \param Mel_Bins MelBins * \param _ProgressCallback 进度条回调(直接传模型的回调就可以了) * \param memory 模型的OrtMemoryInfo */ MoeVSBaseSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); virtual ~MoeVSBaseSampler() = default; /** * \brief 采样 * \param Tensors 输入张量(Tensors[0]为Condition,Tensors[1]为初始噪声) * \param Steps 采样步数 * \param SpeedUp 加速倍数 * \param NoiseScale 噪声规模 * \param Seed 种子 * \param Process 当前进度 * \return Mel张量 */ virtual std::vector Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process); protected: int64_t MelBins = 128; Ort::Session* Alpha = nullptr; Ort::Session* DenoiseFn = nullptr; Ort::Session* NoisePredictor = nullptr; ProgressCallback _callback; Ort::MemoryInfo* Memory = nullptr; }; class MoeVSReflowBaseSampler { public: using ProgressCallback = std::function; /** * \brief 获取采样器 * \param Velocity Velocity Onnx模型Session * \param MelBins MelBins * \param _ProgressCallback 进度条回调(直接传模型的回调就可以了) * \param memory 模型的OrtMemoryInfo * \return 采样器 */ MoeVSReflowBaseSampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); virtual ~MoeVSReflowBaseSampler() = default; /** * \brief 采样 * \param Tensors 输入张量 * \param Steps 采样步数 * \param dt dt * \param Scale Scale * \param Process 当前进度 * \return Mel张量 */ virtual std::vector Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process); protected: int64_t MelBins_ = 128; Ort::Session* Velocity_ = nullptr; ProgressCallback Callback_; Ort::MemoryInfo* Memory_ = nullptr; }; MoeVoiceStudioSamplerEnd ================================================ FILE: libsvc/Modules/header/InferTools/Sampler/MoeVSSamplerManager.hpp ================================================ /** * FileName: MoeVSSamplerManager.hpp * Note: MoeVoiceStudioCore Diffusion 采样器管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVSBaseSampler.hpp" #include "../../framework.h" MoeVoiceStudioSamplerHeader class MoeVSSampler { public: MoeVSSampler() = delete; MoeVSSampler(MoeVSBaseSampler* _ext) : _f0_ext(_ext) {} MoeVSSampler(const MoeVSSampler&) = delete; MoeVSSampler(MoeVSSampler&& _ext) noexcept { delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; } MoeVSSampler& operator=(const MoeVSSampler&) = delete; MoeVSSampler& operator=(MoeVSSampler&& _ext) noexcept { if (this == &_ext) return *this; delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; return *this; } ~MoeVSSampler() { delete _f0_ext; _f0_ext = nullptr; } MoeVSBaseSampler* operator->() const { return _f0_ext; } private: MoeVSBaseSampler* _f0_ext = nullptr; }; class MoeVSReflowSampler { public: MoeVSReflowSampler() = delete; MoeVSReflowSampler(MoeVSReflowBaseSampler* _ext) : _f0_ext(_ext) {} MoeVSReflowSampler(const MoeVSReflowSampler&) = delete; MoeVSReflowSampler(MoeVSReflowSampler&& _ext) noexcept { delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; } MoeVSReflowSampler& operator=(const MoeVSReflowSampler&) = delete; MoeVSReflowSampler& operator=(MoeVSReflowSampler&& _ext) noexcept { if (this == &_ext) return *this; delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; return *this; } ~MoeVSReflowSampler() { delete _f0_ext; _f0_ext = nullptr; } MoeVSReflowBaseSampler* operator->() const { return _f0_ext; } private: MoeVSReflowBaseSampler* _f0_ext = nullptr; }; using GetMoeVSSamplerFn = std::function; LibSvcApi void RegisterMoeVSSampler(const std::wstring& _name, const GetMoeVSSamplerFn& _constructor_fn); /** * \brief 获取采样器 * \param _name 类名 * \param alpha Alphas Onnx模型Session * \param dfn DenoiseFn Onnx模型Session * \param pred Predictor Onnx模型Session * \param Mel_Bins MelBins * \param _ProgressCallback 进度条回调(直接传模型的回调就可以了) * \param memory 模型的OrtMemoryInfo * \return 采样器 */ LibSvcApi MoeVSSampler GetMoeVSSampler( const std::wstring& _name, Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const MoeVSBaseSampler::ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory ); LibSvcApi std::vector GetMoeVSSamplerList(); /******************************* Reflow ***********************************/ using GetMoeVSReflowSamplerFn = std::function; LibSvcApi void RegisterMoeVSReflowSampler(const std::wstring& _name, const GetMoeVSReflowSamplerFn& _constructor_fn); /** * \brief 获取采样器 * \param _name 类名 * \param velocity Velocity Onnx模型Session * \param Mel_Bins MelBins * \param _ProgressCallback 进度条回调(直接传模型的回调就可以了) * \param memory 模型的OrtMemoryInfo * \return 采样器 */ LibSvcApi MoeVSReflowSampler GetMoeVSReflowSampler( const std::wstring& _name, Ort::Session* velocity, int64_t Mel_Bins, const MoeVSBaseSampler::ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory ); LibSvcApi std::vector GetMoeVSReflowSamplerList(); MoeVoiceStudioSamplerEnd ================================================ FILE: libsvc/Modules/header/InferTools/Sampler/MoeVSSamplers.hpp ================================================ /** * FileName: MoeVSSamplers.hpp * Note: MoeVoiceStudioCore Diffusion 官方采样器 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVSBaseSampler.hpp" MoeVoiceStudioSamplerHeader class PndmSampler : public MoeVSBaseSampler { public: PndmSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); ~PndmSampler() override = default; std::vector Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) override; private: const std::vector denoiseInput = { "noise", "time", "condition" }; const std::vector predInput = { "noise", "noise_pred", "time", "time_prev" }; const std::vector denoiseOutput = { "noise_pred" }; const std::vector predOutput = { "noise_pred_o" }; }; class DDimSampler : public MoeVSBaseSampler { public: DDimSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); ~DDimSampler() override = default; std::vector Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) override; private: const std::vector alphain = { "time" }; const std::vector alphaout = { "alphas_cumprod" }; const std::vector denoiseInput = { "noise", "time", "condition" }; const std::vector denoiseOutput = { "noise_pred" }; }; class ReflowEularSampler : public MoeVSReflowBaseSampler { public: ReflowEularSampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); ~ReflowEularSampler() override = default; std::vector Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) override; private: const std::vector velocityInput = { "x", "t", "cond" }; const std::vector velocityOutput = { "o" }; }; class ReflowRk4Sampler : public MoeVSReflowBaseSampler { public: ReflowRk4Sampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); ~ReflowRk4Sampler() override = default; std::vector Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) override; private: const std::vector velocityInput = { "x", "t", "cond" }; const std::vector velocityOutput = { "o" }; }; class ReflowHeunSampler : public MoeVSReflowBaseSampler { public: ReflowHeunSampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); ~ReflowHeunSampler() override = default; std::vector Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) override; private: const std::vector velocityInput = { "x", "t", "cond" }; const std::vector velocityOutput = { "o" }; }; class ReflowPececeSampler : public MoeVSReflowBaseSampler { public: ReflowPececeSampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory); ~ReflowPececeSampler() override = default; std::vector Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) override; private: const std::vector velocityInput = { "x", "t", "cond" }; const std::vector velocityOutput = { "o" }; }; MoeVoiceStudioSamplerEnd ================================================ FILE: libsvc/Modules/header/InferTools/Stft/stft.hpp ================================================ #pragma once #include #include "fftw3.h" namespace DlCodecStft { class STFT { public: STFT() = default; ~STFT(); STFT(int WindowSize, int HopSize, int FFTSize = 0); inline static double PI = 3.14159265358979323846; std::pair, int64_t> operator()(const std::vector& audioData) const; private: int WINDOW_SIZE = 2048; int HOP_SIZE = WINDOW_SIZE / 4; int FFT_SIZE = WINDOW_SIZE / 2 + 1; }; class Mel { public: Mel() = delete; ~Mel() = default; Mel(int WindowSize, int HopSize, int SamplingRate, int MelSize = 0); std::pair, int64_t> GetMel(const std::vector& audioData) const; std::pair, int64_t> operator()(const std::vector& audioData) const; private: STFT stft; int MEL_SIZE = 128; int FFT_SIZE = 0; int sr = 22050; std::vector MelBasis; }; } ================================================ FILE: libsvc/Modules/header/InferTools/TensorExtractor/MoeVSCoreTensorExtractor.hpp ================================================ /** * FileName: MoeVSCoreTensorExtractor.hpp * Note: MoeVoiceStudioCore 官方张量预处理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "MoeVoiceStudioTensorExtractor.hpp" MoeVoiceStudioTensorExtractorHeader class SoVits2TensorExtractor : public MoeVoiceStudioTensorExtractor { public: SoVits2TensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~SoVits2TensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "hidden_unit", "lengths", "pitch", "sid" }; }; class SoVits3TensorExtractor : public MoeVoiceStudioTensorExtractor { public: SoVits3TensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~SoVits3TensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "hidden_unit", "lengths", "pitch", "sid" }; }; class SoVits4TensorExtractor : public MoeVoiceStudioTensorExtractor { public: SoVits4TensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~SoVits4TensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "c", "f0", "mel2ph", "uv", "noise", "sid" }; const std::vector InputNamesVol = { "c", "f0", "mel2ph", "uv", "noise", "sid", "vol" }; }; class SoVits4DDSPTensorExtractor : public MoeVoiceStudioTensorExtractor { public: SoVits4DDSPTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~SoVits4DDSPTensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "c", "f0", "mel2ph", "t_window", "noise", "sid" }; const std::vector InputNamesVol = { "c", "f0", "mel2ph", "t_window", "noise", "sid", "vol" }; }; class RVCTensorExtractor : public MoeVoiceStudioTensorExtractor { public: RVCTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~RVCTensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd" }; const std::vector InputNamesVol = { "phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd", "vol" }; }; class DiffSvcTensorExtractor : public MoeVoiceStudioTensorExtractor { public: DiffSvcTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~DiffSvcTensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNames = { "hubert", "mel2ph", "spk_embed", "f0" }; const std::vector OutputNames = { "mel_pred", "f0_pred" }; }; class DiffusionSvcTensorExtractor : public MoeVoiceStudioTensorExtractor { public: DiffusionSvcTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) : MoeVoiceStudioTensorExtractor(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other) {} ~DiffusionSvcTensorExtractor() override = default; Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) override; const std::vector InputNamesVol = { "hubert", "mel2ph", "f0", "volume", "spk_mix" }; const std::vector InputNames = { "hubert", "mel2ph", "f0", "spk_mix" }; const std::vector OutputNames = { "mel_pred", "f0_pred", "init_noise" }; }; MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libsvc/Modules/header/InferTools/TensorExtractor/MoeVoiceStudioTensorExtractor.hpp ================================================ /** * FileName: MoeVoiceStudioTensorExtractor.hpp * Note: MoeVoiceStudioCore 张量预处理基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include "onnxruntime_cxx_api.h" #define MoeVoiceStudioTensorExtractorHeader namespace MoeVSTensorPreprocess{ #define MoeVoiceStudioTensorExtractorEnd } #include "../../framework.h" MoeVoiceStudioTensorExtractorHeader class MoeVoiceStudioTensorExtractor { public: struct Tensors { std::vector HiddenUnit; std::vector F0; std::vector Volume; std::vector SpkMap; std::vector DDSPNoise; std::vector Noise; std::vector Alignment; std::vector UnVoice; std::vector NSFF0; int64_t Length[1] = { 0 }; int64_t Speaker[1] = { 0 }; std::vector HiddenUnitShape; std::vector FrameShape; std::vector SpkShape; std::vector DDSPNoiseShape; std::vector NoiseShape; int64_t OneShape[1] = { 1 }; }; struct InferParams { float NoiseScale = 0.3f; float DDSPNoiseScale = 1.0f; int Seed = 520468; size_t AudioSize = 0; int64_t Chara = 0; float upKeys = 0.f; void* Other = nullptr; }; struct Others { int f0_bin = 256; float f0_max = 1100.0; float f0_min = 50.0; OrtMemoryInfo* Memory = nullptr; void* Other = nullptr; }; using Params = const InferParams&; struct Inputs { Tensors Data; std::vector Tensor; const char* const* InputNames = nullptr; const char* const* OutputNames = nullptr; size_t InputCount = 1; size_t OutputCount = 1; }; /** * \brief 构造张量预处理器 * \param _srcsr 原始采样率 * \param _sr 目标采样率 * \param _hop HopSize * \param _smix 是否启用角色混合 * \param _volume 是否启用音量emb * \param _hidden_size hubert的维数 * \param _nspeaker 角色数 * \param _other 其他参数,其中的memoryInfo必须为你当前模型的memoryInfo */ MoeVoiceStudioTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other); virtual ~MoeVoiceStudioTensorExtractor() = default; /** * \brief 预处理张量 * \param HiddenUnit HiddenUnit * \param F0 F0 * \param Volume 音量 * \param SpkMap 角色混合数据 * \param params 参数 * \return 完成预处理的张量(请将张量接管的所有Vector的数据都存储到Tensors Data中,因为ORT创建的张量要求调用方管理内存,如果不存储到这个位置会导致数据提前析构 */ virtual Inputs Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ); void SetSrcSamplingRates(uint64_t sr) { _SrcSamplingRate = sr; } //获取换算为0-255的f0 [[nodiscard]] std::vector GetNSFF0(const std::vector&) const; //将F0中0值单独插值 static std::vector GetInterpedF0(const std::vector&); // static std::vector InterpUVF0(const std::vector&); //获取UnVoiceMask static std::vector GetUV(const std::vector&); //获取对齐矩阵 static std::vector GetAligments(size_t, size_t); //线性组合 template static void LinearCombination(std::vector>& _data, size_t default_id, T Value = T(1.0)) { if (_data.empty()) return; if (default_id > _data.size()) default_id = 0; for (size_t i = 0; i < _data[0].size(); ++i) { T Sum = T(0.0); for (size_t j = 0; j < _data.size(); ++j) Sum += _data[j][i]; if (Sum < T(0.0001)) { for (size_t j = 0; j < _data.size(); ++j) _data[j][i] = T(0); _data[default_id][i] = T(1); continue; } Sum *= T(Value); for (size_t j = 0; j < _data.size(); ++j) _data[j][i] /= Sum; } } //将F0中0值单独插值(可设置是否取log) LibSvcApi [[nodiscard]] static std::vector GetInterpedF0log(const std::vector&, bool); //获取正确的角色混合数据 [[nodiscard]] std::vector GetCurrectSpkMixData(const std::vector>& _input, size_t dst_len, int64_t curspk) const; //获取正确的角色混合数据 LibSvcApi [[nodiscard]] static std::vector GetSpkMixData(const std::vector>& _input, size_t dst_len, size_t spk_count); protected: uint64_t _NSpeaker = 1; uint64_t _SrcSamplingRate = 32000; uint64_t _SamplingRate = 32000; uint64_t _HopSize = 512; bool _SpeakerMix = false; bool _Volume = false; uint64_t _HiddenSize = 256; int f0_bin = 256; float f0_max = 1100.0; float f0_min = 50.0; float f0_mel_min = 1127.f * log(1.f + f0_min / 700.f); float f0_mel_max = 1127.f * log(1.f + f0_max / 700.f); OrtMemoryInfo* Memory = nullptr; private: std::wstring __NAME__CLASS__ = L"MoeVoiceStudioTensorExtractor"; }; MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libsvc/Modules/header/InferTools/TensorExtractor/TensorExtractorManager.hpp ================================================ /** * FileName: TensorExtractorManager.hpp * Note: MoeVoiceStudioCore 张量预处理类的注册和管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include "MoeVoiceStudioTensorExtractor.hpp" MoeVoiceStudioTensorExtractorHeader class TensorExtractor { public: TensorExtractor() = default; TensorExtractor(MoeVoiceStudioTensorExtractor* _ext) : _f0_ext(_ext) {} TensorExtractor(const TensorExtractor&) = delete; TensorExtractor(TensorExtractor&& _ext) noexcept { delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; } TensorExtractor& operator=(const TensorExtractor&) = delete; TensorExtractor& operator=(TensorExtractor&& _ext) noexcept { if (this == &_ext) return *this; delete _f0_ext; _f0_ext = _ext._f0_ext; _ext._f0_ext = nullptr; return *this; } ~TensorExtractor() { delete _f0_ext; _f0_ext = nullptr; } MoeVoiceStudioTensorExtractor* operator->() const { return _f0_ext; } private: MoeVoiceStudioTensorExtractor* _f0_ext = nullptr; }; using GetTensorExtractorFn = std::function; LibSvcApi void RegisterTensorExtractor(const std::wstring& _name, const GetTensorExtractorFn& _constructor_fn); /** * \brief 获取张量预处理器 * \param _name 类名 * \param _srcsr 原始采样率 * \param _sr 目标采样率 * \param _hop HopSize * \param _smix 是否启用角色混合 * \param _volume 是否启用音量emb * \param _hidden_size hubert的维数 * \param _nspeaker 角色数 * \param _other 其他参数,其中的memoryInfo必须为你当前模型的memoryInfo * \return 张量预处理器 */ LibSvcApi TensorExtractor GetTensorExtractor( const std::wstring& _name, uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const MoeVoiceStudioTensorExtractor::Others& _other ); MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libsvc/Modules/header/InferTools/inferTools.hpp ================================================ /** * FileName: InferTools.hpp * Note: MoeVoiceStudioCore 推理工具的定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include #include #include "../../Lib/World/src/world/matlabfunctions.h" #include #define MOEVSINFERTOOLSHEADER namespace InferTools { #define MOEVSINFERTOOLSEND } #define LibDLVoiceCodecThrow(message) { \ const std::string LibDlCodecThrowMessage = message;\ const std::string LibDlCodecThrowMessagePrefix = std::string("[In \"") + std::filesystem::path(__FILE__).filename().string() + "\" Line " + std::to_string(__LINE__) + "] "; \ if(LibDlCodecThrowMessage.substr(0, LibDlCodecThrowMessagePrefix.length()) != LibDlCodecThrowMessagePrefix) \ throw std::exception((LibDlCodecThrowMessagePrefix + LibDlCodecThrowMessage).c_str()); \ else \ throw std::exception(LibDlCodecThrowMessage.c_str()); \ } MOEVSINFERTOOLSHEADER struct SlicerSettings { int32_t SamplingRate = 48000; double Threshold = 30.; double MinLength = 3.; int32_t WindowLength = 2048; int32_t HopSize = 512; }; class Wav { public: static constexpr int HEAD_LENGTH = 1024; struct WAV_HEADER { char RIFF[4] = { 'R','I','F','F' }; unsigned long ChunkSize; char WAVE[4] = { 'W','A','V','E' }; char fmt[4] = { 'f','m','t',' ' }; unsigned long Subchunk1Size; unsigned short AudioFormat; unsigned short NumOfChan; unsigned long SamplesPerSec; unsigned long bytesPerSec; unsigned short blockAlign; unsigned short bitsPerSample; char Subchunk2ID[4] = { 'd','a','t','a' }; unsigned long Subchunk2Size; WAV_HEADER(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1, unsigned long sr = 22050, unsigned long bps = 44100, unsigned short ba = 2, unsigned short bips = 16, unsigned long sc2s = 0) :ChunkSize(cs), Subchunk1Size(sc1s), AudioFormat(af), NumOfChan(nc), SamplesPerSec(sr), bytesPerSec(bps), blockAlign(ba), bitsPerSample(bips), Subchunk2Size(sc2s) {} }; using iterator = int16_t*; Wav(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1, unsigned long sr = 22050, unsigned long bps = 44100, unsigned short ba = 2, unsigned short bips = 16, unsigned long sc2s = 0) :header({ cs, sc1s, af, nc, sr, bps, ba, bips, sc2s }), Data(nullptr), StartPos(44) { dataSize = 0; SData = nullptr; } Wav(unsigned long sr, unsigned long length, const void* data) :header({ 36, 16, 1, 1, sr, sr * 2, 2, 16, length }), Data(new char[length + 1]), StartPos(44) { header.ChunkSize = 36 + length; memcpy(Data, data, length); SData = reinterpret_cast(Data); dataSize = length / 2; } Wav(const wchar_t* Path); Wav(const Wav& input); Wav(Wav&& input) noexcept; Wav& operator=(const Wav& input) = delete; Wav& operator=(Wav&& input) noexcept; ~Wav() { destory(); } Wav& cat(const Wav& input); [[nodiscard]] bool isEmpty() const { return this->header.Subchunk2Size == 0; } [[nodiscard]] const char* getData() const { return Data; } char* getData() { return Data; } [[nodiscard]] WAV_HEADER getHeader() const { return header; } WAV_HEADER& Header() { return header; } void destory() const { delete[] Data; } void changeData(const void* indata, long length, int sr) { delete[] Data; Data = new char[length]; memcpy(Data, indata, length); header.ChunkSize = 36 + length; header.Subchunk2Size = length; header.SamplesPerSec = sr; header.bytesPerSec = 2 * sr; } int16_t& operator[](const size_t index) const { if (index < dataSize) return *(SData + index); return *(SData + dataSize - 1); } [[nodiscard]] iterator begin() const { return reinterpret_cast(Data); } [[nodiscard]] iterator end() const { return reinterpret_cast(Data + header.Subchunk2Size); } [[nodiscard]] int64_t getDataLen()const { return static_cast(dataSize); } void Writef(const std::wstring& filepath) const { FILE* FOut = nullptr; _wfopen_s(&FOut, filepath.c_str(), L"wb"); if (!FOut) return; fwrite(&header, 1, sizeof(header), FOut); fwrite(Data, 1, dataSize * 2, FOut); fclose(FOut); FOut = nullptr; } static void WritePCMData(int samplingrate, int channel, const std::vector& PCMDATA, const std::wstring& filepath) { const WAV_HEADER TmpHeader(long(36 + 2 * PCMDATA.size()), 16, 1, short(channel), samplingrate, samplingrate * 2 * channel, short(2 * channel), short(16), long(2 * PCMDATA.size())); FILE* FOut = nullptr; _wfopen_s(&FOut, filepath.c_str(), L"wb"); if (!FOut) return; fwrite(&TmpHeader, 1, sizeof(TmpHeader), FOut); fwrite(PCMDATA.data(), 1, PCMDATA.size() * 2, FOut); fclose(FOut); FOut = nullptr; } private: WAV_HEADER header; char* Data; int16_t* SData; size_t dataSize; int StartPos; }; /** * \brief 切片机切片(获取切片位置) * \param input PCM数据(SignedInt16) * \param _slicer 切片机设置 * \return 切片位置 */ LibSvcApi std::vector SliceAudio(const std::vector& input, const SlicerSettings& _slicer); /** * \brief 均值滤波器 * \param vec 待滤波的数据 * \param window_size 窗口大小 * \return 滤波后数据 */ LibSvcApi std::vector mean_filter(const std::vector& vec, size_t window_size); template double getAvg(const T* start, const T* end) { const auto size = end - start + 1; auto avg = (double)(*start); for (auto i = 1; i < size; i++) avg = avg + (abs((double)start[i]) - avg) / (double)(i + 1ull); return avg; } LibSvcApi std::vector arange(double start, double end, double step = 1.0, double div = 1.0); /** * \brief 重采样(插值) * \tparam TOut 输出类型 * \tparam TIn 输入类型 * \param _Data 输入数据 * \param src 输入采样率 * \param dst 输出采样率 * \param n_Div 给输出的数据统一除以这个数 * \return 输出数据 */ template static std::vector InterpResample(const std::vector& _Data, long src, long dst, TOut n_Div = TOut(1)) { if (src != dst) { const double intstep = double(src) / double(dst); const auto xi = InferTools::arange(0, double(_Data.size()), intstep); auto x0 = InferTools::arange(0, double(_Data.size())); while (x0.size() < _Data.size()) x0.emplace_back(x0[x0.size() - 1] + 1.0); while (x0.size() > _Data.size()) x0.pop_back(); std::vector y0(_Data.size()); for (size_t i = 0; i < _Data.size(); ++i) y0[i] = double(_Data[i]) / double(n_Div); std::vector yi(xi.size()); interp1(x0.data(), y0.data(), long(x0.size()), xi.data(), long(xi.size()), yi.data()); std::vector out(xi.size()); for (size_t i = 0; i < yi.size(); ++i) out[i] = TOut(yi[i]); return out; } std::vector out(_Data.size()); for (size_t i = 0; i < _Data.size(); ++i) out[i] = TOut(_Data[i]) / n_Div; return out; } /** * \brief 重采样(插值) * \tparam T 数据类型 * \param Data 输入数据 * \param src 输入采样率 * \param dst 输出采样率 * \return 输出数据 */ template static std::vector InterpFunc(const std::vector& Data, long src, long dst) { if (src != dst) { const double intstep = double(src) / double(dst); auto xi = InferTools::arange(0, double(Data.size()), intstep); while (xi.size() < size_t(dst)) xi.emplace_back(xi[xi.size() - 1] + 1.0); while (xi.size() > size_t(dst)) xi.pop_back(); auto x0 = InferTools::arange(0, double(Data.size())); while (x0.size() < Data.size()) x0.emplace_back(x0[x0.size() - 1] + 1.0); while (x0.size() > Data.size()) x0.pop_back(); std::vector y0(Data.size()); for (size_t i = 0; i < Data.size(); ++i) y0[i] = Data[i] <= T(0.0001) ? NAN : double(Data[i]); std::vector yi(xi.size()); interp1(x0.data(), y0.data(), long(x0.size()), xi.data(), long(xi.size()), yi.data()); std::vector out(xi.size()); for (size_t i = 0; i < yi.size(); ++i) out[i] = isnan(yi[i]) ? T(0.0) : T(yi[i]); return out; } return Data; } #ifdef MoeVoiceStudioAvxAcc class FloatTensorWrapper { public: FloatTensorWrapper() = delete; ~FloatTensorWrapper() { _data_ptr = nullptr; } FloatTensorWrapper(float* const data_p, size_t _size) : _data_ptr(data_p), _data_size(_size) {} FloatTensorWrapper(const FloatTensorWrapper& _copy) = delete; FloatTensorWrapper& operator=(const FloatTensorWrapper&) = delete; FloatTensorWrapper(FloatTensorWrapper&& _move) noexcept:_data_ptr(_move._data_ptr), _data_size(_move._data_size) {} FloatTensorWrapper& operator=(FloatTensorWrapper&& _move) noexcept { _data_ptr = _move._data_ptr; _data_size = _move._data_size; return *this; } template static const T& Min(const T& a, const T& b) { return (a > b) ? b : a; } float& operator[](size_t index) const { return *(_data_ptr + Min(index, _data_size)); } FloatTensorWrapper& operator+=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator-=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator*=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator/=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator+=(float _right); FloatTensorWrapper& operator-=(float _right); FloatTensorWrapper& operator*=(float _right); FloatTensorWrapper& operator/=(float _right); private: float* _data_ptr = nullptr; size_t _data_size = 0; }; #endif MOEVSINFERTOOLSEND ================================================ FILE: libsvc/Modules/header/Logger/MoeSSLogger.hpp ================================================ #pragma once #include #include "../StringPreprocess.hpp" #include "../../framework.h" #include #include #define __MOEVS_DEBUG_MESSAGE(msg) __MOEVS_DEBUG_INFO(__FILE__, __LINE__, msg) #define logger MoeSSLogger::GetLogger() namespace MoeSSLogger { class Logger { public: using logger_fn = void(*)(const wchar_t*, const char*); Logger(); ~Logger(); Logger(logger_fn error_fn, logger_fn log_fn); void log(const std::wstring&); void log(const char*); void error(const std::wstring&); void error(const char*); void enable(bool _filelogger) { filelogger = _filelogger; } private: bool custom_logger_fn = false; std::filesystem::path cur_log_dir, logpath, errorpath; logger_fn cerror_fn = nullptr, cloggerfn = nullptr; FILE* log_file = nullptr, * error_file = nullptr; bool filelogger = true; std::mutex mx; }; LibSvcApi Logger& GetLogger(); } ================================================ FILE: libsvc/Modules/header/Models/DiffSvc.hpp ================================================ /** * FileName: DiffSvc.hpp * Note: MoeVoiceStudioCore Onnx Diffusion系Svc 模型定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include "SVC.hpp" MoeVoiceStudioCoreHeader LibSvcApi void LoadVocoderModel(const std::wstring& VocoderPath); LibSvcApi void UnLoadVocoderModel(); LibSvcApi bool VocoderEnabled(); LibSvcApi Ort::Session* GetCurrentVocoder(); /** * \brief DiffSvc模型 */ class DiffusionSvc : public SingingVoiceConversion { public: DiffusionSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); /** * \brief 加载DiffSvc模型 * \param _PathDict 路径,Key分别为["Hubert", "Hifigan", "Encoder", "DenoiseFn", "NoisePredictor", "AfterProcess", "DiffSvc", "Naive", "Alphas"],其中"DiffSvc"、"Naive"、"Alphas"为可选项 * \param _Config 配置Json * \param _ProgressCallback 进度条回调函数 * \param ExecutionProvider_ Provider * \param DeviceID_ GPU设备ID * \param ThreadCount_ 线程数 */ DiffusionSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); DiffusionSvc(const Hparams& _Hps, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); ~DiffusionSvc() override; void load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback); void Destory(); [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const override; [[nodiscard]] std::vector Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; [[nodiscard]] std::vector InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector ShallowDiffusionInference( std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize ) const; [[nodiscard]] int64_t GetMaxStep() const { return MaxStep; } [[nodiscard]] bool OldVersion() const { return diffSvc; } [[nodiscard]] const std::wstring& GetDiffSvcVer() const { return DiffSvcVersion; } [[nodiscard]] int64_t GetMelBins() const { return melBins; } void NormMel(std::vector& MelSpec) const; private: Ort::Session* encoder = nullptr; Ort::Session* denoise = nullptr; Ort::Session* pred = nullptr; Ort::Session* after = nullptr; Ort::Session* alpha = nullptr; Ort::Session* naive = nullptr; Ort::Session* diffSvc = nullptr; int64_t melBins = 128; int64_t Pndms = 100; int64_t MaxStep = 1000; float SpecMin = -12; float SpecMax = 2; std::wstring DiffSvcVersion = L"DiffSvc"; const std::vector nsfInput = { "c", "f0" }; const std::vector nsfOutput = { "audio" }; const std::vector DiffInput = { "hubert", "mel2ph", "spk_embed", "f0", "initial_noise", "speedup" }; const std::vector DiffOutput = { "mel_pred", "f0_pred" }; const std::vector afterInput = { "x" }; const std::vector afterOutput = { "mel_out" }; const std::vector naiveOutput = { "mel" }; }; LibSvcApi std::vector VocoderInfer(std::vector& Mel, std::vector& F0, int64_t MelBins, int64_t MelSize, const Ort::MemoryInfo* Mem, void* _VocoderModel = nullptr); MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/header/Models/EnvManager.hpp ================================================ /** * FileName: EnvManager.hpp * Note: MoeVoiceStudioCore 环境管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include "../../header/Logger/MoeSSLogger.hpp" #define MoeVoiceStudioCoreEnvManagerHeader namespace moevsenv{ #define MoeVoiceStudioCoreEnvManagerEnd } MoeVoiceStudioCoreEnvManagerHeader bool SingleOrtApiEnvEnabled(); void UseSingleOrtApiEnv(bool _cond); class MoeVoiceStudioEnv { public: MoeVoiceStudioEnv() = default; ~MoeVoiceStudioEnv() { Destory(); } LibSvcApi void Load(unsigned ThreadCount, unsigned DeviceID, unsigned Provider); LibSvcApi void Destory(); LibSvcApi [[nodiscard]] bool IsEnabled() const; [[nodiscard]] Ort::Env* GetEnv() const { return GlobalOrtEnv; } [[nodiscard]] Ort::SessionOptions* GetSessionOptions() const { return GlobalOrtSessionOptions; } [[nodiscard]] Ort::MemoryInfo* GetMemoryInfo() const { return GlobalOrtMemoryInfo; } [[nodiscard]] int GetCurThreadCount() const { return (int)CurThreadCount; } [[nodiscard]] int GetCurDeviceID() const { return (int)CurDeviceID; } [[nodiscard]] int GetCurProvider() const { return (int)CurProvider; } private: void Create(unsigned ThreadCount_, unsigned DeviceID_, unsigned ExecutionProvider_); Ort::Env* GlobalOrtEnv = nullptr; Ort::SessionOptions* GlobalOrtSessionOptions = nullptr; Ort::MemoryInfo* GlobalOrtMemoryInfo = nullptr; unsigned CurThreadCount = unsigned(-1); unsigned CurDeviceID = unsigned(-1); unsigned CurProvider = unsigned(-1); OrtCUDAProviderOptionsV2* cuda_option_v2 = nullptr; }; LibSvcApi MoeVoiceStudioEnv& GetGlobalMoeVSEnv(); MoeVoiceStudioCoreEnvManagerEnd ================================================ FILE: libsvc/Modules/header/Models/ModelBase.hpp ================================================ /** * FileName: ModelBase.hpp * Note: MoeVoiceStudioCore Onnx 模型基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #endif #include #include "../../Lib/MJson/MJson.h" #include "EnvManager.hpp" #include "MoeVSProject.hpp" #include "../InferTools/inferTools.hpp" #define MoeVoiceStudioCoreHeader namespace MoeVoiceStudioCore{ #define MoeVoiceStudioCoreEnd } #define MoeVSNotImplementedError LibDLVoiceCodecThrow("NotImplementedError") #define MoeVSClassName(__Moe__VSClassName) __NAME__CLASS__.emplace_back((__Moe__VSClassName)) #define MoeVSMaxPath 1024 static std::wstring GetCurrentFolder(const std::wstring& defualt = L"") { wchar_t path[MoeVSMaxPath]; #ifdef _WIN32 GetModuleFileName(nullptr, path, MoeVSMaxPath); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); return _curPath; #else //TODO Other System #error Other System ToDO #endif } MoeVoiceStudioCoreHeader struct DiffusionSvcPaths { std::wstring Encoder; std::wstring Denoise; std::wstring Pred; std::wstring After; std::wstring Alpha; std::wstring Naive; std::wstring DiffSvc; }; struct ReflowSvcPaths { std::wstring Encoder; std::wstring VelocityFn; std::wstring After; }; struct VitsSvcPaths { std::wstring VitsSvc; }; struct ClusterConfig { int64_t ClusterCenterSize = 10000; std::wstring Path; /** * \brief Type Of Cluster : "KMeans" "Index" */ std::wstring Type; }; struct Hparams { /** * \brief Model Version * For VitsSvc : "SoVits2.0" "SoVits3.0" "SoVits4.0" "SoVits4.0-DDSP" "RVC" * For DiffusionSvc : "DiffSvc" "DiffusionSvc" */ std::wstring TensorExtractor = L"DiffSvc"; /** * \brief Path Of Hubert Model */ std::wstring HubertPath; /** * \brief Path Of DiffusionSvc Model */ DiffusionSvcPaths DiffusionSvc; /** * \brief Path Of VitsSvc Model */ VitsSvcPaths VitsSvc; /** * \brief Path Of ReflowSvc Model */ ReflowSvcPaths ReflowSvc; /** * \brief Config Of Cluster */ ClusterConfig Cluster; long SamplingRate = 22050; int HopSize = 320; int64_t HiddenUnitKDims = 256; int64_t SpeakerCount = 1; bool EnableCharaMix = false; bool EnableVolume = false; bool VaeMode = true; int64_t MelBins = 128; int64_t Pndms = 100; int64_t MaxStep = 1000; float SpecMin = -12; float SpecMax = 2; float Scale = 1000.f; }; class MoeVoiceStudioModule { public: //进度条回调 using ProgressCallback = std::function; //Provicer enum class ExecutionProviders { CPU = 0, CUDA = 1, #ifdef MOEVSDMLPROVIDER DML = 2 #endif }; static [[nodiscard]] std::vector GetOpenFileNameMoeVS(); static std::vector CutLens(const std::wstring& input); /** * \brief 构造Onnx模型基类 * \param ExecutionProvider_ ExecutionProvider(可以理解为设备) * \param DeviceID_ 设备ID * \param ThreadCount_ 线程数 */ MoeVoiceStudioModule(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_ = 0); virtual ~MoeVoiceStudioModule(); /** * \brief 输入路径推理 * \param _Datas [路径,多个路径使用换行符隔开, 推理文本] * \param _InferParams 推理参数 * \param _SlicerSettings 切片机配置 * \return 输出路径 */ [[nodiscard]] virtual std::vector Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const; /** * \brief 获取采样率 * \return 采样率 */ [[nodiscard]] long GetSamplingRate() const { return _samplingRate; } static float Clamp(float in, float min = -1.f, float max = 1.f) { if (in > max) return max; if (in < min) return min; return in; } protected: //采样率 long _samplingRate = 22050; Ort::Env* env = nullptr; Ort::SessionOptions* session_options = nullptr; Ort::MemoryInfo* memory_info = nullptr; ExecutionProviders _cur_execution_provider = ExecutionProviders::CPU; ProgressCallback _callback; moevsenv::MoeVoiceStudioEnv OrtApiEnv; std::vector __NAME__CLASS__ = { L"MoeVoiceStudioModule" }; public: //*******************删除的函数********************// MoeVoiceStudioModule& operator=(MoeVoiceStudioModule&&) = delete; MoeVoiceStudioModule& operator=(const MoeVoiceStudioModule&) = delete; MoeVoiceStudioModule(const MoeVoiceStudioModule&) = delete; MoeVoiceStudioModule(MoeVoiceStudioModule&&) = delete; }; MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/header/Models/MoeVSProject.hpp ================================================ /** * FileName: MoeVSProject.hpp * Note: MoeVoiceStudioCore 项目相关的定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include "../StringPreprocess.hpp" #include "../../Lib/MJson/MJson.h" namespace MoeVSProjectSpace { class FileWrapper { public: FileWrapper() = delete; FileWrapper(const wchar_t* _path, const wchar_t* _mode) { _wfopen_s(&file_, _path, _mode); } ~FileWrapper() { if (file_) fclose(file_); file_ = nullptr; } operator FILE* () const { return file_; } [[nodiscard]] bool IsOpen() const { return file_; } private: FILE* file_ = nullptr; }; using size_type = size_t; template size_type GetSize(const std::vector& inp_vec) { return inp_vec.size() * sizeof(T); } struct MoeVoiceStudioSvcSlice { std::vector Audio; std::vector F0; std::vector Volume; std::vector> Speaker; int32_t OrgLen = 0; bool IsNotMute = false; MoeVoiceStudioSvcSlice() = default; }; struct MoeVoiceStudioSvcData { /*std::vector> Audio; std::vector> F0; std::vector> Volume; std::vector>> Speaker; std::vector OrgLen; std::vector IsNotMute;*/ std::vector Slices; std::wstring Path; MoeVoiceStudioSvcData() = default; [[nodiscard]] size_type Size() const { size_type _size = 0; const std::string bytePath = to_byte_string(Path); _size += sizeof(long) * Slices.size() + Slices.size() + bytePath.length() + 1; for (const auto& Slice : Slices) { _size += GetSize(Slice.Audio) + GetSize(Slice.F0) + GetSize(Slice.Volume); for (const auto& it : Slice.Speaker) _size += GetSize(it); } return _size; } }; struct MoeVSParams { //通用 float NoiseScale = 0.3f; //噪声修正因子 0-10 int64_t Seed = 52468; //种子 int64_t SpeakerId = 0; //角色ID uint64_t SrcSamplingRate = 48000; //源采样率 int64_t SpkCount = 2; //模型角色数 //SVC float IndexRate = 0.f; //索引比 0-1 float ClusterRate = 0.f; //聚类比 0-1 float DDSPNoiseScale = 0.8f; //DDSP噪声修正因子 0-10 float Keys = 0.f; //升降调 -64-64 size_t MeanWindowLength = 2; //均值滤波器窗口大小 1-20 size_t Pndm = 1; //Diffusion加速倍数 1-200 size_t Step = 100; //Diffusion总步数 1-1000 float TBegin = 0.f; float TEnd = 1.f; std::wstring Sampler = L"Pndm"; //Diffusion采样器 std::wstring ReflowSampler = L"Eular"; //Reflow采样器 std::wstring F0Method = L"Dio"; //F0提取算法 bool UseShallowDiffusion = false; //使用浅扩散 void* _VocoderModel = nullptr; void* _ShallowDiffusionModel = nullptr; bool ShallowDiffusionUseSrcAudio = true; int VocoderHopSize = 512; int VocoderMelBins = 128; int VocoderSamplingRate = 44100; int64_t ShallowDiffuisonSpeaker = 0; //SVCRTInfer int64_t RTSampleSize = 44100; int64_t CrossFadeLength = 320; //TTS std::vector SpeakerMix; //角色混合比例 float LengthScale = 1.0f; //时长修正因子 float DurationPredictorNoiseScale = 0.8f; //随机时长预测器噪声修正因子 float FactorDpSdp = 0.f; //随机时长预测器与时长预测器混合比例 float GateThreshold = 0.66666f; //Tacotron2解码器EOS阈值 int64_t MaxDecodeStep = 2000; //Tacotron2最大解码步数 std::vector EmotionPrompt; //情感标记 std::wstring PlaceHolderSymbol = L"|"; //音素分隔符 float RestTime = 0.5f; //停顿时间,为负数则直接断开音频并创建新音频 std::string LanguageSymbol = "JP"; //语言 std::wstring AdditionalInfo; //G2P额外信息 std::wstring SpeakerName = L"0"; //角色名 }; struct MoeVSTTSToken { std::wstring Text; //输入文本 std::vector Phonemes; //音素序列 std::vector Tones; //音调序列 std::vector Durations; //时长序列 std::vector Language; //语言序列 MoeVSTTSToken() = default; MoeVSTTSToken(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams); [[nodiscard]] std::wstring Serialization() const; }; struct MoeVSTTSSeq { std::wstring TextSeq; std::vector SlicedTokens; std::vector SpeakerMix; //角色混合比例 std::vector EmotionPrompt; //情感标记 std::wstring PlaceHolderSymbol = L"|"; //音素分隔符 float NoiseScale = 0.3f; //噪声修正因子 0-10 float LengthScale = 1.0f; //时长修正因子 float DurationPredictorNoiseScale = 0.3f; //随机时长预测器噪声修正因子 float FactorDpSdp = 0.3f; //随机时长预测器与时长预测器混合比例 float GateThreshold = 0.66666f; //Tacotron2解码器EOS阈值 int64_t MaxDecodeStep = 2000; //Tacotron2最大解码步数 int64_t Seed = 52468; //种子 float RestTime = 0.5f; //停顿时间,为负数则直接断开音频并创建新音频 std::string LanguageSymbol = "ZH"; //语言标记 std::wstring SpeakerName = L"0"; //角色或名称ID std::wstring AdditionalInfo; //G2P额外信息 MoeVSTTSSeq() = default; MoeVSTTSSeq(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams); [[nodiscard]] std::wstring Serialization() const; bool operator==(const MoeVSTTSSeq& right) const; }; using MoeVSSvcParams = MoeVSParams; using MoeVSTTSParams = MoeVSParams; struct ParamsOffset { std::vector OrgAudio; //std::vector Hidden_Unit; std::vector F0; std::vector Volume; std::vector Speaker; [[nodiscard]] size_type Size() const { return size_type(OrgAudio.size() + F0.size() + Volume.size() + Speaker.size()) * sizeof(size_type); } ParamsOffset() = default; }; class MoeVSProject { public: struct Header { char ChunkSymbol[8] = { 'M','O','E','V','S','P','R','J' }; size_type DataHeaderAmount = 0; }; struct DataHeader { char ChunkSymbol[4] = { 'D','A','T','A' }; size_type OrgAudioOffsetPosSize = 0; size_type F0OffsetPosSize = 0; size_type VolumeOffsetPosSize = 0; size_type CharacterOffsetPosSize = 0; size_type OrgLenSize = 0; size_type SymbolSize = 0; size_type PathSize = 0; size_type HeaderSize = sizeof(DataHeader) - sizeof(size_type); }; struct Data { DataHeader Header; ParamsOffset Offset; MoeVoiceStudioSvcData ParamData; [[nodiscard]] size_type Size() const { size_type size = sizeof(DataHeader); size += Offset.Size(); size += ParamData.Size(); return size; } }; LibSvcApi MoeVSProject() = delete; ~MoeVSProject() = default; //从文件读取项目 LibSvcApi MoeVSProject(const std::wstring& _path); //从音频数据构造项目 LibSvcApi MoeVSProject(const std::vector& _params); //写入文件 LibSvcApi void Write(const std::wstring& _path) const; //从项目获取音频数据 [[nodiscard]] std::vector GetParams() const { std::vector Params_data; Params_data.reserve(data_.size()); for (const auto& i : data_) Params_data.emplace_back(i.ParamData); return Params_data; } //从项目获取音频数据(移动构造) [[nodiscard]] std::vector GetParamsMove() { std::vector Params_data; Params_data.reserve(data_.size()); for (auto& i : data_) Params_data.emplace_back(std::move(i.ParamData)); return Params_data; } private: static constexpr size_t begin_offset = sizeof(Header); Header moevs_proj_header_; std::vector data_pos_; size_type data_chunk_begin_ = 0; std::vector data_; }; } ================================================ FILE: libsvc/Modules/header/Models/ReflowSvc.hpp ================================================ /** * FileName: ReflowSvc.hpp * Note: MoeVoiceStudioCore Onnx Reflow系Svc 模型定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include "SVC.hpp" MoeVoiceStudioCoreHeader /** * \brief Reflow模型 */ class ReflowSvc : public SingingVoiceConversion { public: ReflowSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); /** * \brief 加载Reflow模型 * \param _PathDict 路径,Key分别为["Hubert", "Hifigan", "Encoder", "VelocityFn", "AfterProcess"] * \param _Config 配置Json * \param _ProgressCallback 进度条回调函数 * \param ExecutionProvider_ Provider * \param DeviceID_ GPU设备ID * \param ThreadCount_ 线程数 */ ReflowSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); ReflowSvc(const Hparams& _Hps, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); ~ReflowSvc() override; void load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback); void Destory(); [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const override; [[nodiscard]] std::vector Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; [[nodiscard]] std::vector InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector ShallowDiffusionInference( std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize ) const; [[nodiscard]] int64_t GetMaxStep() const { return MaxStep; } [[nodiscard]] const std::wstring& GetReflowSvcVer() const { return ReflowSvcVersion; } [[nodiscard]] int64_t GetMelBins() const { return melBins; } void NormMel(std::vector& MelSpec) const; private: Ort::Session* encoder = nullptr; Ort::Session* velocity = nullptr; Ort::Session* after = nullptr; int64_t melBins = 128; int64_t MaxStep = 100; float SpecMin = -12; float SpecMax = 2; float Scale = 1000.f; bool VaeMode = true; std::wstring ReflowSvcVersion = L"DiffusionSvc"; const std::vector nsfInput = { "c", "f0" }; const std::vector nsfOutput = { "audio" }; const std::vector afterInput = { "x" }; const std::vector afterOutput = { "mel_out" }; const std::vector OutputNamesEncoder = { "x", "cond", "f0_pred" }; }; MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/header/Models/SVC.hpp ================================================ /** * FileName: SVC.hpp * Note: MoeVoiceStudioCore OnnxSvc 模型基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "ModelBase.hpp" #include "../Logger/MoeSSLogger.hpp" #include "../InferTools/inferTools.hpp" #include "../InferTools/TensorExtractor/TensorExtractorManager.hpp" #include "../InferTools/Cluster/MoeVSClusterManager.hpp" MoeVoiceStudioCoreHeader /* class OnnxModule { public: enum class Device { CPU = 0, CUDA = 1, #ifdef MOEVSDMLPROVIDER DML = 2 #endif }; using callback = std::function; using int64 = int64_t; using MTensor = Ort::Value; OnnxModule(); virtual ~OnnxModule(); void ChangeDevice(Device _dev); static std::vector CutLens(const std::wstring& input); [[nodiscard]] long GetSamplingRate() const { return _samplingRate; } template static void LinearCombination(std::vector& _data, T Value = T(1.0)) { if(_data.empty()) { _data = std::vector(1, Value); return; } T Sum = T(0.0); for(const auto& i : _data) Sum += i; if (Sum < T(0.0001)) { _data = std::vector(_data.size(), T(0.0)); _data[0] = Value; return; } Sum *= T(Value); for (auto& i : _data) i /= Sum; } protected: Ort::Env* env = nullptr; Ort::SessionOptions* session_options = nullptr; Ort::MemoryInfo* memory_info = nullptr; modelType _modelType = modelType::SoVits; Device device_ = Device::CPU; long _samplingRate = 22050; callback _callback; static constexpr long MaxPath = 8000l; std::wstring _outputPath = GetCurrentFolder() + L"\\outputs"; }; */ class SingingVoiceConversion : public MoeVoiceStudioModule { public: SingingVoiceConversion(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_ = 0); /** * \brief 输入路径推理 * \param _Paths 路径,多个路径使用换行符隔开 * \param _InferParams 推理参数 * \param _SlicerSettings 切片机配置 * \return 输出路径 */ [[nodiscard]] std::vector Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; /** * \brief 推理一个音频 * \param _Slice 音频数据 * \param _InferParams 推理参数 * \return 推理结果(PCM signed-int16 单声道) */ [[nodiscard]] virtual std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const; /** * \brief 推理一个音频(使用引用) * \param _Slice 音频数据引用 * \param _InferParams 推理参数 * \param _Process 推理进度 * \return 推理结果(PCM signed-int16 单声道) */ [[nodiscard]] virtual std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const; /** * \brief 推理一个音频(使用PCM) * \param PCMData 输入的PCM数据(signed-int16 单声道) * \param srcSr 输入PCM的采样率 * \param _InferParams 推理参数 * \return 推理结果(PCM signed-int16 单声道) */ [[nodiscard]] virtual std::vector InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const; //提取音量 [[nodiscard]] static std::vector ExtractVolume(const std::vector& OrgAudio, int hop_size); //提取音量 [[nodiscard]] std::vector ExtractVolume(const std::vector& OrgAudio) const; //获取HopSize [[nodiscard]] int GetHopSize() const { return HopSize; } //获取HiddenUnitKDims [[nodiscard]] int64_t GetHiddenUnitKDims() const { return HiddenUnitKDims; } //获取角色数量 [[nodiscard]] int64_t GetSpeakerCount() const { return SpeakerCount; } //获取角色混合启用状态 [[nodiscard]] bool CharaMixEnabled() const { return EnableCharaMix; } /** * \brief 切片一个音频 * \param input 输入的PCM数据(signed-int16 单声道) * \param _slice_pos 切片位置(单位为采样) * \param _slicer 切片机设置 * \return 音频数据 */ LibSvcApi [[nodiscard]] static MoeVSProjectSpace::MoeVoiceStudioSvcData GetAudioSlice(const std::vector& input, const std::vector& _slice_pos, const InferTools::SlicerSettings& _slicer); /** * \brief 预处理音频数据 * \param input 完成切片的音频数据 * \param __SamplingRate 采样率 * \param __HopSize HopSize * \param _f0_method F0算法 */ LibSvcApi static void PreProcessAudio(MoeVSProjectSpace::MoeVoiceStudioSvcData& input, int __SamplingRate = 48000, int __HopSize = 512, const std::wstring& _f0_method = L"Dio"); ~SingingVoiceConversion() override; protected: MoeVSTensorPreprocess::TensorExtractor _TensorExtractor; Ort::Session* hubert = nullptr; int HopSize = 320; int64_t HiddenUnitKDims = 256; int64_t SpeakerCount = 1; bool EnableCharaMix = false; bool EnableVolume = false; MoeVoiceStudioCluster::MoeVSCluster Cluster; int64_t ClusterCenterSize = 10000; bool EnableCluster = false; bool EnableIndex = false; const std::vector hubertOutput = { "embed" }; const std::vector hubertInput = { "source" }; }; MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/header/Models/VitsSvc.hpp ================================================ /** * FileName: VitsSvc.hpp * Note: MoeVoiceStudioCore Onnx Vits系Svc 模型定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "SVC.hpp" #include "DiffSvc.hpp" MoeVoiceStudioCoreHeader class VitsSvc : public SingingVoiceConversion { public: VitsSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); VitsSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); VitsSvc(const Hparams& _Hps, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); void load( const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_, bool MoeVoiceStudioFrontEnd = false ); ~VitsSvc() override; void Destory(); [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const override; [[nodiscard]] std::vector Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; //[[nodiscard]] std::vector InferSliceTensor(const MoeVSProjectSpace::MoeVSAudioSlice& _Slice, size_t SliceIdx, // const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::vector& _Tensors, // std::vector& SoVitsInput) const; [[nodiscard]] std::vector InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const override; [[nodiscard]] std::vector MelExtractor(const float* PCMAudioBegin, const float* PCMAudioEnd) const = delete; [[nodiscard]] Ort::MemoryInfo* GetMemoryInfo() const { return memory_info; } private: Ort::Session* VitsSvcModel = nullptr; std::wstring VitsSvcVersion = L"SoVits4.0"; const std::vector soVitsOutput = { "audio" }; const std::vector soVitsInput = { "hidden_unit", "lengths", "pitch", "sid" }; const std::vector RVCInput = { "phone", "phone_lengths", "pitch", "pitchf", "ds", "rnd" }; const std::vector StftOutput = { "mel" }; const std::vector StftInput = { "waveform", "aligment"}; #ifdef WIN32 #ifdef MoeVSMui bool RTSTAT = false; std::deque> inputBuffer, outputBuffer, rawInputBuffer, rawOutputBuffer; MRecorder* recoder = nullptr; Mui::Render::MDS_AudioPlayer* audio_player = nullptr; Mui::Render::MAudioStream* audio_stream = nullptr; size_t emptyLen = 30000; #endif #endif }; MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/header/Modules.hpp ================================================ /** * FileName: Modules.hpp * Note: MoeVoiceStudioCore组件管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "Models/VitsSvc.hpp" #include "Models/DiffSvc.hpp" #include "Models/ReflowSvc.hpp" #include "../framework.h" #include "InferTools/Stft/stft.hpp" namespace MoeVSModuleManager { class UnionSvcModel { public: UnionSvcModel() = delete; LibSvcApi ~UnionSvcModel(); LibSvcApi UnionSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID); LibSvcApi UnionSvcModel(const MoeVoiceStudioCore::Hparams& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID); LibSvcApi [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const; LibSvcApi [[nodiscard]] std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const; LibSvcApi [[nodiscard]] std::vector Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const; LibSvcApi [[nodiscard]] std::vector InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const; LibSvcApi [[nodiscard]] std::vector ShallowDiffusionInference( std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize ) const; LibSvcApi MoeVoiceStudioCore::SingingVoiceConversion* GetPtr() const; LibSvcApi [[nodiscard]] int64_t GetMaxStep() const; LibSvcApi [[nodiscard]] bool OldVersion() const; LibSvcApi [[nodiscard]] const std::wstring& GetDiffSvcVer() const; LibSvcApi [[nodiscard]] int64_t GetMelBins() const; LibSvcApi [[nodiscard]] int GetHopSize() const; LibSvcApi [[nodiscard]] int64_t GetHiddenUnitKDims() const; LibSvcApi [[nodiscard]] int64_t GetSpeakerCount() const; LibSvcApi [[nodiscard]] bool CharaMixEnabled() const; LibSvcApi [[nodiscard]] long GetSamplingRate() const; LibSvcApi void NormMel(std::vector& MelSpec) const; [[nodiscard]] bool IsDiffusion() const; private: MoeVoiceStudioCore::DiffusionSvc* Diffusion_ = nullptr; MoeVoiceStudioCore::ReflowSvc* Reflow_ = nullptr; }; LibSvcApi int64_t& GetSpeakerCount(); LibSvcApi int64_t& GetSamplingRate(); LibSvcApi int32_t& GetVocoderHopSize(); LibSvcApi int32_t& GetVocoderMelBins(); /** * \brief 初始化所有组件 */ LibSvcApi void MoeVoiceStudioCoreInitSetup(); /** * \brief 获取当前VitsSvc模型 * \return 当前模型的指针 */ LibSvcApi MoeVoiceStudioCore::VitsSvc* GetVitsSvcModel(); /** * \brief 获取当前UnionSvc模型 * \return 当前模型的指针 */ LibSvcApi UnionSvcModel* GetUnionSvcModel(); /** * \brief 卸载模型 */ LibSvcApi void UnloadVitsSvcModel(); /** * \brief 卸载模型 */ LibSvcApi void UnloadUnionSvcModel(); /** * \brief 载入VitsSvc模型 * \param Config 一个MJson类的实例(配置文件的JSON) * \param Callback 进度条回调函数 * \param ProviderID Provider在所有Provider中的ID(遵循Enum Class的定义) * \param NumThread CPU推理时的线程数(最好设置高一点,GPU不支持的算子可能也会Fallback到CPU) * \param DeviceID GPU设备ID */ LibSvcApi void LoadVitsSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID); /** * \brief 载入DiffusionSvc模型 * \param Config 一个MJson类的实例(配置文件的JSON) * \param Callback 进度条回调函数 * \param ProviderID Provider在所有Provider中的ID(遵循Enum Class的定义) * \param NumThread CPU推理时的线程数(最好设置高一点,GPU不支持的算子可能也会Fallback到CPU) * \param DeviceID GPU设备ID */ LibSvcApi void LoadUnionSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID); /** * \brief 载入Vocoder模型 * \param VocoderPath Vocoder路径 */ LibSvcApi void LoadVocoderModel(const std::wstring& VocoderPath); /** * \brief 卸载Vocoder模型 */ LibSvcApi void UnloadVocoderModel(); /** * \brief 检查Vocoder是否可用 * \return Vocoder状态 */ LibSvcApi bool VocoderEnabled(); /** * \brief 推理多组数据 * \param _Slice 数据包 * \param _InferParams 参数 * \return 音频 */ LibSvcApi std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams); /** * \brief 推理切片数据 * \param _Slice 切片数据 * \param _InferParams 参数 * \param _Process 进度条 * \return 音频 */ LibSvcApi std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process); LibSvcApi std::vector Enhancer(std::vector& Mel, const std::vector& F0, size_t MelSize); LibSvcApi void ReloadMelOps(int SamplingRate_I64, int Hopsize_I64, int MelBins_I64); LibSvcApi DlCodecStft::Mel& GetMelOperator(); LibSvcApi bool ShallowDiffusionEnabled(); } namespace MoeVSRename { using MoeVSVitsBasedSvc = MoeVoiceStudioCore::VitsSvc; using MoeVSDiffBasedSvc = MoeVoiceStudioCore::DiffusionSvc; } ================================================ FILE: libsvc/Modules/header/StringPreprocess.hpp ================================================ #pragma once #include #include #include "../framework.h" LibSvcApi std::string to_byte_string(const std::wstring& input); LibSvcApi std::string to_ansi_string(const std::wstring& input); LibSvcApi std::wstring to_wide_string(const std::string& input); LibSvcApi std::wstring string_vector_to_string(const std::vector& vector); LibSvcApi std::wstring wstring_vector_to_string(const std::vector& vector); template std::wstring vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) { std::wstring TmpStr = std::to_wstring(it); if ((std::is_same_v || std::is_same_v) && TmpStr.find(L'.') != std::string::npos) { while (TmpStr.back() == L'0') TmpStr.pop_back(); if (TmpStr.back() == L'.') TmpStr += L"0"; } vecstr += TmpStr + L", "; } if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } ================================================ FILE: libsvc/Modules/src/InferTools/AvCodec/AvCodeResample.cpp ================================================ #include "../../header/InferTools/AvCodec/AvCodeResample.h" AudioPreprocess::WAV_HEADER AudioPreprocess::GetHeader(const std::wstring& path) { WAV_HEADER header; char buf[1024]; FILE* stream; _wfreopen_s(&stream, path.c_str(), L"rb", stderr); if (stream == nullptr) { throw (std::exception("Wav Load Error")); } fread(buf, 1, 1024, stream); int pos = 0; while (pos < InferTools::Wav::HEAD_LENGTH) { if ((buf[pos] == 'R') && (buf[pos + 1] == 'I') && (buf[pos + 2] == 'F') && (buf[pos + 3] == 'F')) { pos += 4; break; } ++pos; } if (pos >= InferTools::Wav::HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.ChunkSize = *(int*)&buf[pos]; pos += 8; while (pos < InferTools::Wav::HEAD_LENGTH) { if ((buf[pos] == 'f') && (buf[pos + 1] == 'm') && (buf[pos + 2] == 't')) { pos += 4; break; } ++pos; } if (pos >= InferTools::Wav::HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk1Size = *(int*)&buf[pos]; pos += 4; header.AudioFormat = *(short*)&buf[pos]; pos += 2; header.NumOfChan = *(short*)&buf[pos]; if (stream != nullptr) { fclose(stream); } return header; } std::vector AudioPreprocess::arange(double start, double end, double step, double div) { std::vector output; while (start < end) { output.push_back(start / div); start += step; } return output; } std::vector AudioPreprocess::codec(const std::wstring& path, int sr) { //if (path.substr(path.rfind(L'.')) == L".wav") // return resample(path, sr); std::vector outData; int ret = avformat_open_input(&avFormatContext, to_byte_string(path).c_str(), nullptr, nullptr); if (ret != 0) { LibDLVoiceCodecThrow(std::string("Can't Open Audio File [ErrCode]") + std::to_string(ret)); } ret = avformat_find_stream_info(avFormatContext, nullptr); if (ret < 0) { LibDLVoiceCodecThrow("Can't Get Audio Info"); } int streamIndex = 0; for (unsigned i = 0; i < avFormatContext->nb_streams; ++i) { const AVMediaType avMediaType = avFormatContext->streams[i]->codecpar->codec_type; if (avMediaType == AVMEDIA_TYPE_AUDIO) { streamIndex = static_cast(i); } } const AVCodecParameters* avCodecParameters = avFormatContext->streams[streamIndex]->codecpar; const AVCodecID avCodecId = avCodecParameters->codec_id; const AVCodec* avCodec = avcodec_find_decoder(avCodecId); if (avCodec == nullptr) LibDLVoiceCodecThrow("Don't order fried rice (annoyed)"); if (avCodecContext == nullptr) { LibDLVoiceCodecThrow("Can't Get Decoder Info"); } avcodec_parameters_to_context(avCodecContext, avCodecParameters); ret = avcodec_open2(avCodecContext, avCodec, nullptr); if (ret < 0) { LibDLVoiceCodecThrow("Can't Open Decoder"); } packet = (AVPacket*)av_malloc(sizeof(AVPacket)); const AVSampleFormat inFormat = avCodecContext->sample_fmt; constexpr AVSampleFormat outFormat = AV_SAMPLE_FMT_S16; const int inSampleRate = avCodecContext->sample_rate; const int outSampleRate = sr; const auto nSample = static_cast(avFormatContext->duration * sr / AV_TIME_BASE); uint64_t in_ch_layout = avCodecContext->channel_layout; if (path.substr(path.rfind(L'.')) == L".wav") { const auto head = GetHeader(path); if (head.NumOfChan == 1) in_ch_layout = AV_CH_LAYOUT_MONO; else if (head.NumOfChan == 2) in_ch_layout = AV_CH_LAYOUT_STEREO; else LibDLVoiceCodecThrow("unsupported Channel Num"); } constexpr uint64_t out_ch_layout = AV_CH_LAYOUT_MONO; swr_alloc_set_opts(swrContext, out_ch_layout, outFormat, outSampleRate, static_cast(in_ch_layout), inFormat, inSampleRate, 0, nullptr ); swr_init(swrContext); const int outChannelCount = av_get_channel_layout_nb_channels(out_ch_layout); int currentIndex = 0; out_buffer = (uint8_t*)av_malloc(2ull * sr); while (av_read_frame(avFormatContext, packet) >= 0) { if (packet->stream_index == streamIndex) { avcodec_send_packet(avCodecContext, packet); ret = avcodec_receive_frame(avCodecContext, inFrame); if (ret == 0) { swr_convert(swrContext, &out_buffer, 2ull * sr, (const uint8_t**)inFrame->data, inFrame->nb_samples); const int out_buffer_size = av_samples_get_buffer_size(nullptr, outChannelCount, (inFrame->nb_samples * sr / inSampleRate) - 1, outFormat, 1); outData.insert(outData.end(), out_buffer, out_buffer + out_buffer_size); } ++currentIndex; av_packet_unref(packet); } } //Wav outWav(static_cast(sr), static_cast(outData.size()), outData.data()); auto outWav = reinterpret_cast(outData.data()); const auto RawWavLen = int64_t(outData.size()) / 2; if (nSample != static_cast(RawWavLen)) { const double interpOff = static_cast(RawWavLen) / static_cast(nSample); const auto x0 = arange(0.0, static_cast(RawWavLen), 1.0, 1.0); std::vector y0(RawWavLen); for (int64_t i = 0; i < RawWavLen; ++i) y0[i] = outWav[i] ? static_cast(outWav[i]) : NAN; const auto yi = new double[nSample]; auto xi = arange(0.0, static_cast(RawWavLen), interpOff, 1.0); while (xi.size() < nSample) xi.push_back(*(xi.end() - 1) + interpOff); while (xi.size() > nSample) xi.pop_back(); interp1(x0.data(), y0.data(), static_cast(RawWavLen), xi.data(), static_cast(nSample), yi); std::vector DataChun(nSample); for (size_t i = 0; i < nSample; ++i) DataChun[i] = isnan(yi[i]) ? 0i16 : static_cast(yi[i]); delete[] yi; return DataChun; } release(); return { outWav , outWav + RawWavLen }; } void AudioPreprocess::release() { if (packet) av_packet_free(&packet); if (inFrame) av_frame_free(&inFrame); if (out_buffer) av_free(out_buffer); if (swrContext) swr_free(&swrContext); if (avCodecContext) avcodec_close(avCodecContext); if (avFormatContext) avformat_close_input(&avFormatContext); inFrame = nullptr; out_buffer = nullptr; swrContext = nullptr; avCodecContext = nullptr; avFormatContext = nullptr; packet = nullptr; } void AudioPreprocess::init() { inFrame = av_frame_alloc(); out_buffer = nullptr; swrContext = swr_alloc(); avCodecContext = avcodec_alloc_context3(nullptr); avFormatContext = avformat_alloc_context(); packet = nullptr; } AudioPreprocess::AudioPreprocess() { inFrame = av_frame_alloc(); out_buffer = nullptr; swrContext = swr_alloc(); avCodecContext = avcodec_alloc_context3(nullptr); avFormatContext = avformat_alloc_context(); packet = nullptr; } ================================================ FILE: libsvc/Modules/src/InferTools/Cluster/MoeVSBaseCluster.cpp ================================================ #include "../../../header/InferTools/Cluster/MoeVSBaseCluster.hpp" #include "../../../header/InferTools/inferTools.hpp" std::vector MoeVoiceStudioCluster::MoeVoiceStudioBaseCluster::find(float* point, long sid, int64_t n_points) { LibDLVoiceCodecThrow("NotImplementedError"); } ================================================ FILE: libsvc/Modules/src/InferTools/Cluster/MoeVSClusterManager.cpp ================================================ #include "../../../header/InferTools/Cluster/MoeVSClusterManager.hpp" #include #include #include "../../../header/Logger/MoeSSLogger.hpp" MoeVoiceStudioClusterHeader std::map RegisteredMoeVSCluster; MoeVSCluster GetMoeVSCluster(const std::wstring& _name, const std::wstring& _path, size_t hidden_size, size_t KmeansLen) { const auto f_ClusterFn = RegisteredMoeVSCluster.find(_name); if (f_ClusterFn != RegisteredMoeVSCluster.end()) return f_ClusterFn->second(_path, hidden_size, KmeansLen); throw std::runtime_error("Unable To Find An Available MoeVSCluster"); } void RegisterMoeVSCluster(const std::wstring& _name, const GetMoeVSClusterFn& _constructor_fn) { if (RegisteredMoeVSCluster.find(_name) != RegisteredMoeVSCluster.end()) { logger.log(L"[Warn] MoeVSClusterNameConflict"); return; } RegisteredMoeVSCluster[_name] = _constructor_fn; } MoeVoiceStudioClusterEnd ================================================ FILE: libsvc/Modules/src/InferTools/Cluster/MoeVSIndexCluster.cpp ================================================ #ifdef MoeVoiceStudioIndexCluster #include "../../../header/InferTools/Cluster/MoeVSIndexCluster.hpp" #include #include "../../../header/InferTools/inferTools.hpp" #ifdef NDEBUG #pragma comment (lib,"../../../../../Lib/faiss/out/build/x64-Release/faiss/faiss.lib") #endif #ifdef _DEBUG #pragma comment (lib,"../../../../../Lib/faiss/out/build/x64-Debug/faiss/faiss.lib") #endif #pragma comment (lib,"../../../../../Lib/faiss/faiss/libblas.lib") #pragma comment (lib,"../../../../../Lib/faiss/faiss/liblapack.lib") #pragma comment (lib,"../../../../../Lib/faiss/faiss/liblapacke.lib") MoeVoiceStudioClusterHeader IndexClusterCore::~IndexClusterCore() { delete IndexPtr; IndexPtr = nullptr; } IndexClusterCore::IndexClusterCore(const char* _path) { IndexPtr = faiss::read_index(_path); IndexsVector = std::vector(IndexPtr->ntotal * IndexPtr->d, 0.f); IndexPtr->reconstruct_n(0, IndexPtr->ntotal, IndexsVector.data()); Dim = IndexPtr->d; } IndexClusterCore::IndexClusterCore(IndexClusterCore&& move) noexcept { IndexPtr = move.IndexPtr; Dim = move.Dim; IndexsVector = std::move(move.IndexsVector); move.IndexPtr = nullptr; } IndexClusterCore& IndexClusterCore::operator=(IndexClusterCore&& move) noexcept { if (&move == this) return *this; delete IndexPtr; IndexPtr = move.IndexPtr; Dim = move.Dim; IndexsVector = std::move(move.IndexsVector); move.IndexPtr = nullptr; return *this; } float* IndexClusterCore::GetVec(faiss::idx_t index) { return IndexsVector.data() + index * Dim; } std::vector IndexClusterCore::find(const float* points, faiss::idx_t n_points, faiss::idx_t n_searched_points) { std::vector result(Dim * n_points); std::vector distances(n_searched_points * n_points); std::vector labels(n_searched_points * n_points); IndexPtr->search(n_points, points, n_searched_points, distances.data(), labels.data()); for (faiss::idx_t pt = 0; pt < n_points; ++pt) { std::vector result_pt(Dim, 0.f); const auto idx_vec = labels.data() + pt * n_searched_points; // SIZE:[n_searched_points] const auto dis_vec = distances.data() + pt * n_searched_points; // SIZE:[n_searched_points] float sum = 0.f; // dis_vec[i] / sum = pGetVec(idx_vec[i]) for (faiss::idx_t spt = 0; spt < n_searched_points; ++spt) // result_pt = GetVec(idx_vec[i]) { if(idx_vec[spt] < 0) continue; dis_vec[spt] = (1 / dis_vec[spt]) * (1 / dis_vec[spt]); sum += dis_vec[spt]; } if (sum == 0.f) sum = 1.f; for (faiss::idx_t spt = 0; spt < n_searched_points; ++spt) { if (idx_vec[spt] < 0) continue; const auto sedpt = GetVec(idx_vec[spt]); const auto pcnt = (dis_vec[spt] / sum); for (faiss::idx_t sptp = 0; sptp < Dim; ++sptp) result_pt[sptp] += pcnt * sedpt[sptp]; } memcpy(result.data() + pt * Dim, result_pt.data(), Dim * sizeof(float)); } return result; } IndexCluster::IndexCluster(const std::wstring& _path, size_t hidden_size, size_t KmeansLen) { const auto RawPath = _path + L"/Index-"; size_t idx = 0; while(true) { std::filesystem::path IndexPath = RawPath + std::to_wstring(idx++) + L".index"; if(!exists(IndexPath)) break; Indexs.emplace_back(IndexPath.string().c_str()); } if (Indexs.empty()) LibDLVoiceCodecThrow("Index Is Empty"); } std::vector IndexCluster::find(float* point, long sid, int64_t n_points) { if (size_t(sid) < Indexs.size()) return Indexs[sid].find(point, n_points); return { point,point + n_hidden_size * n_points }; } MoeVoiceStudioClusterEnd #endif ================================================ FILE: libsvc/Modules/src/InferTools/Cluster/MoeVSKmeansCluster.cpp ================================================ #include "../../../header/InferTools/Cluster/MoeVSKmeansCluster.hpp" #include "../../../header/InferTools/inferTools.hpp" std::vector MoeVoiceStudioCluster::KMeansCluster::find(float* point, long sid, int64_t n_points) { if (size_t(sid) < _tree.size()) { std::vector res; res.reserve(dims * n_points * 2); for (int64_t pt = 0; pt < n_points; ++pt) { auto tmp = _tree[sid].nearest_point({ point + pt * dims,point + (pt + 1) * dims }); res.insert(res.end(), tmp.begin(), tmp.end()); } return res; } return { point, point + dims * n_points }; } MoeVoiceStudioCluster::KMeansCluster::KMeansCluster(const std::wstring& _path, size_t hidden_size, size_t KmeansLen) { dims = hidden_size; FILE* file = nullptr; _wfopen_s(&file, (_path + L"/KMeans.npy").c_str(), L"rb"); if (!file) LibDLVoiceCodecThrow("KMeansFileNotExist"); constexpr long idx = 128; fseek(file, idx, SEEK_SET); std::vector tmpData(hidden_size); const size_t ec = size_t(hidden_size) * sizeof(float); std::vector> _tmp; _tmp.reserve(KmeansLen); while (fread(tmpData.data(), 1, ec, file) == ec) { _tmp.emplace_back(tmpData); if (_tmp.size() == KmeansLen) { _tree.emplace_back(_tmp); _tmp.clear(); } } } ================================================ FILE: libsvc/Modules/src/InferTools/DataStruct/KDTree.cpp ================================================ /* * file: KDTree.hpp * author: J. Frederico Carvalho * * This is an adaptation of the KD-tree implementation in rosetta code * https://rosettacode.org/wiki/K-d_tree * * It is a reimplementation of the C code using C++. It also includes a few * more queries than the original, namely finding all points at a distance * smaller than some given distance to a point. * */ #include #include #include #include #include #include #include "../../../header/InferTools/DataStruct/KDTree.hpp" KDNode::KDNode() = default; KDNode::KDNode(const point_t &pt, const size_t &idx_, const KDNodePtr &left_, const KDNodePtr &right_) { x = pt; index = idx_; left = left_; right = right_; } KDNode::KDNode(const pointIndex &pi, const KDNodePtr &left_, const KDNodePtr &right_) { x = pi.first; index = pi.second; left = left_; right = right_; } KDNode::~KDNode() = default; float KDNode::coord(const size_t &idx) { return x.at(idx); } KDNode::operator bool() { return (!x.empty()); } KDNode::operator point_t() { return x; } KDNode::operator size_t() { return index; } KDNode::operator pointIndex() { return pointIndex(x, index); } KDNodePtr NewKDNodePtr() { KDNodePtr mynode = std::make_shared< KDNode >(); return mynode; } inline float dist2(const point_t &a, const point_t &b) { float distc = 0; for (size_t i = 0; i < a.size(); i++) { float di = a.at(i) - b.at(i); distc += di * di; } return distc; } inline float dist2(const KDNodePtr &a, const KDNodePtr &b) { return dist2(a->x, b->x); } inline float dist(const point_t &a, const point_t &b) { return std::sqrt(dist2(a, b)); } inline float dist(const KDNodePtr &a, const KDNodePtr &b) { return std::sqrt(dist2(a, b)); } comparer::comparer(size_t idx_) : idx{idx_} {}; inline bool comparer::compare_idx(const pointIndex &a, // const pointIndex &b // ) { return (a.first.at(idx) < b.first.at(idx)); // } inline void sort_on_idx(const pointIndexArr::iterator &begin, // const pointIndexArr::iterator &end, // size_t idx) { comparer comp(idx); comp.idx = idx; using std::placeholders::_1; using std::placeholders::_2; std::nth_element(begin, begin + std::distance(begin, end) / 2, end, std::bind(&comparer::compare_idx, comp, _1, _2)); } using pointVec = std::vector< point_t >; KDNodePtr KDTree::make_tree(const pointIndexArr::iterator &begin, // const pointIndexArr::iterator &end, // const size_t &length, // const size_t &level // ) { if (begin == end) { return NewKDNodePtr(); // empty tree } size_t dim = begin->first.size(); if (length > 1) { sort_on_idx(begin, end, level); } auto middle = begin + (length / 2); auto l_begin = begin; auto l_end = middle; auto r_begin = middle + 1; auto r_end = end; size_t l_len = length / 2; size_t r_len = length - l_len - 1; KDNodePtr left; if (l_len > 0 && dim > 0) { left = make_tree(l_begin, l_end, l_len, (level + 1) % dim); } else { left = leaf; } KDNodePtr right; if (r_len > 0 && dim > 0) { right = make_tree(r_begin, r_end, r_len, (level + 1) % dim); } else { right = leaf; } // KDNode result = KDNode(); return std::make_shared< KDNode >(*middle, left, right); } KDTree::KDTree(pointVec point_array) { leaf = std::make_shared< KDNode >(); // iterators pointIndexArr arr; for (size_t i = 0; i < point_array.size(); i++) { arr.push_back(pointIndex(point_array.at(i), i)); } auto begin = arr.begin(); auto end = arr.end(); size_t length = arr.size(); size_t level = 0; // starting root = KDTree::make_tree(begin, end, length, level); } KDNodePtr KDTree::nearest_( // const KDNodePtr &branch, // const point_t &pt, // const size_t &level, // const KDNodePtr &best, // const float&best_dist // ) { float d, dx, dx2; if (!bool(*branch)) { return NewKDNodePtr(); // basically, null } point_t branch_pt(*branch); size_t dim = branch_pt.size(); d = dist2(branch_pt, pt); dx = branch_pt.at(level) - pt.at(level); dx2 = dx * dx; KDNodePtr best_l = best; float best_dist_l = best_dist; if (d < best_dist) { best_dist_l = d; best_l = branch; } size_t next_lv = (level + 1) % dim; KDNodePtr section; KDNodePtr other; // select which branch makes sense to check if (dx > 0) { section = branch->left; other = branch->right; } else { section = branch->right; other = branch->left; } // keep nearest neighbor from further down the tree KDNodePtr further = nearest_(section, pt, next_lv, best_l, best_dist_l); if (!further->x.empty()) { float dl = dist2(further->x, pt); if (dl < best_dist_l) { best_dist_l = dl; best_l = further; } } // only check the other branch if it makes sense to do so if (dx2 < best_dist_l) { further = nearest_(other, pt, next_lv, best_l, best_dist_l); if (!further->x.empty()) { float dl = dist2(further->x, pt); if (dl < best_dist_l) { best_dist_l = dl; best_l = further; } } } return best_l; }; // default caller KDNodePtr KDTree::nearest_(const point_t &pt) { size_t level = 0; // KDNodePtr best = branch; float branch_dist = dist2(point_t(*root), pt); return nearest_(root, // beginning of tree pt, // point we are querying level, // start from level 0 root, // best is the root branch_dist); // best_dist = branch_dist }; point_t KDTree::nearest_point(const point_t &pt) { return point_t(*nearest_(pt)); }; size_t KDTree::nearest_index(const point_t &pt) { return size_t(*nearest_(pt)); }; pointIndex KDTree::nearest_pointIndex(const point_t &pt) { KDNodePtr Nearest = nearest_(pt); return pointIndex(point_t(*Nearest), size_t(*Nearest)); } pointIndexArr KDTree::neighborhood_( // const KDNodePtr &branch, // const point_t &pt, // const float&rad, // const size_t &level // ) { float d, dx, dx2; if (!bool(*branch)) { // branch has no point, means it is a leaf, // no points to add return pointIndexArr(); } size_t dim = pt.size(); float r2 = rad * rad; d = dist2(point_t(*branch), pt); dx = point_t(*branch).at(level) - pt.at(level); dx2 = dx * dx; pointIndexArr nbh, nbh_s, nbh_o; if (d <= r2) { nbh.push_back(pointIndex(*branch)); } // KDNodePtr section; KDNodePtr other; if (dx > 0) { section = branch->left; other = branch->right; } else { section = branch->right; other = branch->left; } nbh_s = neighborhood_(section, pt, rad, (level + 1) % dim); nbh.insert(nbh.end(), nbh_s.begin(), nbh_s.end()); if (dx2 < r2) { nbh_o = neighborhood_(other, pt, rad, (level + 1) % dim); nbh.insert(nbh.end(), nbh_o.begin(), nbh_o.end()); } return nbh; }; pointIndexArr KDTree::neighborhood( // const point_t &pt, // const float&rad) { size_t level = 0; return neighborhood_(root, pt, rad, level); } pointVec KDTree::neighborhood_points( // const point_t &pt, // const float&rad) { size_t level = 0; pointIndexArr nbh = neighborhood_(root, pt, rad, level); pointVec nbhp; nbhp.resize(nbh.size()); std::transform(nbh.begin(), nbh.end(), nbhp.begin(), [](pointIndex x) { return x.first; }); return nbhp; } indexArr KDTree::neighborhood_indices( // const point_t &pt, // const float&rad) { size_t level = 0; pointIndexArr nbh = neighborhood_(root, pt, rad, level); indexArr nbhi; nbhi.resize(nbh.size()); std::transform(nbh.begin(), nbh.end(), nbhi.begin(), [](pointIndex x) { return x.second; }); return nbhi; } ================================================ FILE: libsvc/Modules/src/InferTools/DataStruct/README.md ================================================ ## KdTree From J. Frederico Carvalho ================================================ FILE: libsvc/Modules/src/InferTools/F0Extractor/BaseF0Extractor.cpp ================================================ #include "../../../header/InferTools/F0Extractor/BaseF0Extractor.hpp" #include #include "../../../header/Logger/MoeSSLogger.hpp" #include "../../../header/InferTools/inferTools.hpp" MoeVSF0Extractor::BaseF0Extractor::BaseF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0) : fs(sampling_rate), hop(hop_size), f0_bin(n_f0_bins), f0_max(max_f0), f0_min(min_f0) { f0_mel_min = (1127.0 * log(1.0 + f0_min / 700.0)); f0_mel_max = (1127.0 * log(1.0 + f0_max / 700.0)); } std::vector MoeVSF0Extractor::BaseF0Extractor::arange(double start, double end, double step, double div) { std::vector output; while (start < end) { output.push_back(start / div); start += step; } return output; } std::vector MoeVSF0Extractor::BaseF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { LibDLVoiceCodecThrow("NotImplementedError"); } std::vector MoeVSF0Extractor::BaseF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { std::vector PCMVector(PCMData.size()); for (size_t i = 0; i < PCMData.size(); ++i) PCMVector[i] = double(PCMData[i]); return ExtractF0(PCMVector, TargetLength); } std::vector MoeVSF0Extractor::BaseF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { std::vector PCMVector(PCMData.size()); for (size_t i = 0; i < PCMData.size(); ++i) PCMVector[i] = double(PCMData[i]); return ExtractF0(PCMVector, TargetLength); } ================================================ FILE: libsvc/Modules/src/InferTools/F0Extractor/DioF0Extractor.cpp ================================================ #include "../../../header/InferTools/F0Extractor/DioF0Extractor.hpp" #include "dio.h" #include "stonemask.h" #include "matlabfunctions.h" MoeVoiceStudioF0ExtractorHeader DioF0Extractor::DioF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0): BaseF0Extractor(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0) { } void DioF0Extractor::InterPf0(size_t TargetLength) { const auto f0Len = refined_f0.size(); if (abs((int64_t)TargetLength - (int64_t)f0Len) < 3) { refined_f0.resize(TargetLength, 0.0); return; } for (size_t i = 0; i < f0Len; ++i) if (refined_f0[i] < 0.001) refined_f0[i] = NAN; auto xi = arange(0.0, (double)f0Len * (double)TargetLength, (double)f0Len, (double)TargetLength); while (xi.size() < TargetLength) xi.emplace_back(*(xi.end() - 1) + ((double)f0Len / (double)TargetLength)); while (xi.size() > TargetLength) xi.pop_back(); auto x0 = arange(0, (double)f0Len); while (x0.size() < f0Len) x0.emplace_back(*(x0.end() - 1) + 1.); while (x0.size() > f0Len) x0.pop_back(); auto raw_f0 = std::vector(xi.size()); interp1(x0.data(), refined_f0.data(), static_cast(x0.size()), xi.data(), (int)xi.size(), raw_f0.data()); for (size_t i = 0; i < xi.size(); i++) if (isnan(raw_f0[i])) raw_f0[i] = 0.0; refined_f0 = std::move(raw_f0); } std::vector DioF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { compute_f0(PCMData.data(), PCMData.size()); InterPf0(TargetLength); std::vector f0(refined_f0.size()); for (size_t i = 0; i < refined_f0.size(); ++i) f0[i] = (float)refined_f0[i]; return f0; } void DioF0Extractor::compute_f0(const double* PCMData, size_t PCMLen) { DioOption Doption; InitializeDioOption(&Doption); Doption.f0_ceil = f0_max; Doption.f0_floor = f0_min; Doption.frame_period = 1000.0 * hop / fs; const size_t f0Length = GetSamplesForDIO(int(fs), (int)PCMLen, Doption.frame_period); auto temporal_positions = std::vector(f0Length); auto raw_f0 = std::vector(f0Length); refined_f0 = std::vector(f0Length); Dio(PCMData, (int)PCMLen, int(fs), &Doption, temporal_positions.data(), raw_f0.data()); StoneMask(PCMData, (int)PCMLen, int(fs), temporal_positions.data(), raw_f0.data(), (int)f0Length, refined_f0.data()); } MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/src/InferTools/F0Extractor/F0ExtractorManager.cpp ================================================ #include "../../../header/InferTools/F0Extractor/F0ExtractorManager.hpp" #include #include #include "../../../header/Logger/MoeSSLogger.hpp" MoeVoiceStudioF0ExtractorHeader std::map RegisteredF0Extractors; F0Extractor GetF0Extractor(const std::wstring& _name, const uint32_t fs, const uint32_t hop, const uint32_t f0_bin, const double f0_max, const double f0_min) { const auto f_F0Extractor = RegisteredF0Extractors.find(_name); if (f_F0Extractor != RegisteredF0Extractors.end()) return f_F0Extractor->second(fs, hop, f0_bin, f0_max, f0_min); throw std::runtime_error("Unable To Find An Available F0Extractor"); } void RegisterF0Extractor(const std::wstring& _name, const GetF0ExtractorFn& _constructor_fn) { if (RegisteredF0Extractors.find(_name) != RegisteredF0Extractors.end()) { logger.log(L"[Warn] F0ExtractorNameConflict"); return; } RegisteredF0Extractors[_name] = _constructor_fn; } std::vector GetF0ExtractorList() { std::vector F0ExtractorsVec; F0ExtractorsVec.reserve(RegisteredF0Extractors.size()); for (const auto& i : RegisteredF0Extractors) F0ExtractorsVec.emplace_back(i.first); return F0ExtractorsVec; } MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/src/InferTools/F0Extractor/HarvestF0Extractor.cpp ================================================ #include "../../../header/InferTools/F0Extractor/HarvestF0Extractor.hpp" #include "matlabfunctions.h" #include "harvest.h" #include "stonemask.h" MoeVoiceStudioF0ExtractorHeader HarvestF0Extractor::HarvestF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0): BaseF0Extractor(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0) { } void HarvestF0Extractor::InterPf0(size_t TargetLength) { const auto f0Len = refined_f0.size(); if (abs((int64_t)TargetLength - (int64_t)f0Len) < 3) { refined_f0.resize(TargetLength, 0.0); return; } for (size_t i = 0; i < f0Len; ++i) if (refined_f0[i] < 0.001) refined_f0[i] = NAN; auto xi = arange(0.0, (double)f0Len * (double)TargetLength, (double)f0Len, (double)TargetLength); while (xi.size() < TargetLength) xi.emplace_back(*(xi.end() - 1) + ((double)f0Len / (double)TargetLength)); while (xi.size() > TargetLength) xi.pop_back(); auto x0 = arange(0, (double)f0Len); while (x0.size() < f0Len) x0.emplace_back(*(x0.end() - 1) + 1.); while (x0.size() > f0Len) x0.pop_back(); auto raw_f0 = std::vector(xi.size()); interp1(x0.data(), refined_f0.data(), static_cast(x0.size()), xi.data(), (int)xi.size(), raw_f0.data()); for (size_t i = 0; i < xi.size(); i++) if (isnan(raw_f0[i])) raw_f0[i] = 0.0; refined_f0 = std::move(raw_f0); } std::vector HarvestF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { compute_f0(PCMData.data(), PCMData.size()); InterPf0(TargetLength); std::vector f0(refined_f0.size()); for (size_t i = 0; i < refined_f0.size(); ++i) f0[i] = (float)refined_f0[i]; return f0; } void HarvestF0Extractor::compute_f0(const double* PCMData, size_t PCMLen) { HarvestOption Doption; InitializeHarvestOption(&Doption); Doption.f0_ceil = f0_max; Doption.f0_floor = f0_min; Doption.frame_period = 1000.0 * hop / fs; const size_t f0Length = GetSamplesForHarvest(int(fs), (int)PCMLen, Doption.frame_period); auto temporal_positions = std::vector(f0Length); auto raw_f0 = std::vector(f0Length); refined_f0 = std::vector(f0Length); Harvest(PCMData, (int)PCMLen, int(fs), &Doption, temporal_positions.data(), raw_f0.data()); StoneMask(PCMData, (int)PCMLen, int(fs), temporal_positions.data(), raw_f0.data(), (int)f0Length, refined_f0.data()); } MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/src/InferTools/F0Extractor/NetF0Predictors.cpp ================================================ #include "../../../header/InferTools/F0Extractor/NetF0Predictors.hpp" #include #include "matlabfunctions.h" #include "../../../header/InferTools/F0Extractor/DioF0Extractor.hpp" #include "../../../header/Logger/MoeSSLogger.hpp" #include "../../../header/Models/EnvManager.hpp" #include "../../../header/InferTools/inferTools.hpp" #ifdef _WIN32 #include #else #error #endif MoeVoiceStudioF0ExtractorHeader NetF0Class::NetF0Class() #ifdef INITF0NETPREDICTOR { try { wchar_t path[1024]; #ifdef _WIN32 GetModuleFileName(nullptr, path, 1024); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); const auto cpath = _curPath + L"/F0Predictor/config.json"; NetF0PathDir = _curPath + L"/F0Predictor/"; #endif const MJson json(to_byte_string(cpath).c_str()); int DeviceId = 0, Device = 0, NumThread = (int)std::thread::hardware_concurrency(); if (json["DeviceId"].IsInt()) DeviceId = json["DeviceId"].GetInt(); if (json["Device"].IsString()) { const std::string tmp = json["Device"].GetString(); if (tmp == "CUDA") Device = 1; else if (tmp == "DML") Device = 2; } if (json["NumThread"].IsInt()) NumThread = json["NumThread"].GetInt(); if (Device == 0) BuildCPUEnv(NumThread); else if (Device == 1) BuildCUDAEnv(DeviceId); else if (Device == 2) BuildDMLEnv(DeviceId); } catch (std::exception& e) { logger.log(to_wide_string(e.what())); BuildCPUEnv(std::thread::hardware_concurrency()); } } #else { wchar_t path[1024]; #ifdef _WIN32 GetModuleFileName(nullptr, path, 1024); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); NetF0PathDir = _curPath + L"/F0Predictor/"; #endif } #endif void NetF0Class::Destory() { delete Model; Model = nullptr; NetF0Options = nullptr; NetF0Env = nullptr; Memory = nullptr; } void NetF0Class::BuildCPUEnv(unsigned ThreadCount) { Destory(); NetF0Options = new Ort::SessionOptions; NetF0Env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); NetF0Options->SetIntraOpNumThreads(static_cast(ThreadCount)); NetF0Options->SetGraphOptimizationLevel(ORT_ENABLE_ALL); Memory = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); } void NetF0Class::BuildCUDAEnv(unsigned Did) { Destory(); const auto AvailableProviders = Ort::GetAvailableProviders(); bool ret = true; for (const auto& it : AvailableProviders) if (it.find("CUDA") != std::string::npos) ret = false; if (ret) LibDLVoiceCodecThrow("CUDA Provider Not Found"); OrtCUDAProviderOptions cuda_option; cuda_option.device_id = int(Did); NetF0Options = new Ort::SessionOptions; NetF0Env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); NetF0Options->AppendExecutionProvider_CUDA(cuda_option); NetF0Options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); NetF0Options->SetIntraOpNumThreads(1); Memory = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); } void NetF0Class::BuildDMLEnv(unsigned Did) { Destory(); const auto AvailableProviders = Ort::GetAvailableProviders(); std::string ret; for (const auto& it : AvailableProviders) if (it.find("Dml") != std::string::npos) ret = it; if (ret.empty()) LibDLVoiceCodecThrow("DML Provider Not Found"); const OrtApi& ortApi = Ort::GetApi(); const OrtDmlApi* ortDmlApi = nullptr; ortApi.GetExecutionProviderApi("DML", ORT_API_VERSION, reinterpret_cast(&ortDmlApi)); const Ort::ThreadingOptions threadingOptions; NetF0Env = new Ort::Env(threadingOptions, ORT_LOGGING_LEVEL_VERBOSE, ""); NetF0Env->DisableTelemetryEvents(); NetF0Options = new Ort::SessionOptions; ortDmlApi->SessionOptionsAppendExecutionProvider_DML(*NetF0Options, int(Did)); NetF0Options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); NetF0Options->DisablePerSessionThreads(); NetF0Options->SetExecutionMode(ORT_SEQUENTIAL); NetF0Options->DisableMemPattern(); Memory = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU)); } void NetF0Class::LoadModel(const std::wstring& path) { Destory(); if (!moevsenv::GetGlobalMoeVSEnv().IsEnabled()) return; NetF0Env = moevsenv::GetGlobalMoeVSEnv().GetEnv(); Memory = moevsenv::GetGlobalMoeVSEnv().GetMemoryInfo(); NetF0Options = moevsenv::GetGlobalMoeVSEnv().GetSessionOptions(); try { Model = new Ort::Session(*NetF0Env, (NetF0PathDir + path).c_str(), *NetF0Options); } catch (Ort::Exception& e) { logger.log(to_wide_string(e.what())); delete Model; Model = nullptr; } } NetF0Class RMVPECORE; NetF0Class MELPECORE; RMVPEF0Extractor::RMVPEF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0) : BaseF0Extractor(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0) { if (MELPECORE.Model) MELPECORE.Destory(); if (!RMVPECORE.Model) RMVPECORE.LoadModel(L"RMVPE.onnx"); } double average(const double* begin, const double* end) { const auto mp = double(end - begin); double sum = 0.; while (begin != end) sum += *(begin++); return sum / mp; } std::vector RMVPEF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { if (!RMVPECORE.Model) return DioF0Extractor((int)fs, (int)hop, (int)f0_bin, f0_max, f0_min).ExtractF0(PCMData, TargetLength); const double step = double(fs) / 16000.; const auto window_len = (size_t)round(step); const auto half_window_len = window_len / 2; const auto f0_size = size_t((double)PCMData.size() / step); const auto pcm_idx_size = PCMData.size() - 2; std::vector pcm(f0_size, 0.f); auto idx = double(half_window_len + 1); for (size_t i = 0; i < f0_size; ++i) { const auto index = size_t(round(idx)); if(index + half_window_len > pcm_idx_size) break; if (half_window_len == 0) pcm[i] = (float)PCMData[index]; else pcm[i] = (float)average(&PCMData[index - half_window_len], &PCMData[index + half_window_len]); idx += step; } std::vector Tensors; const int64_t pcm_shape[] = { 1, (int64_t)pcm.size() }; constexpr int64_t one_shape[] = { 1 }; float threshold[] = { 0.03f }; Tensors.emplace_back(Ort::Value::CreateTensor(*RMVPECORE.Memory, pcm.data(), pcm.size(), pcm_shape, 2)); Tensors.emplace_back(Ort::Value::CreateTensor(*RMVPECORE.Memory, threshold, 1, one_shape, 1)); const auto out = RMVPECORE.Model->Run(Ort::RunOptions{ nullptr }, InputNames.data(), Tensors.data(), Tensors.size(), OutputNames.data(), OutputNames.size()); const auto osize = out[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto of0 = out[0].GetTensorData(); refined_f0 = std::vector(osize); for (size_t i = 0; i < osize; ++i) refined_f0[i] = ((of0[i] > 0.001f) ? (double)out[0].GetTensorData()[i] : NAN); InterPf0(TargetLength); std::vector finaF0(refined_f0.size()); for (size_t i = 0; i < refined_f0.size(); ++i) finaF0[i] = isnan(refined_f0[i]) ? 0 : (float)refined_f0[i]; return finaF0; } void RMVPEF0Extractor::InterPf0(size_t TargetLength) { const auto f0Len = refined_f0.size(); if (abs((int64_t)TargetLength - (int64_t)f0Len) < 3) { refined_f0.resize(TargetLength, 0.0); return; } for (size_t i = 0; i < f0Len; ++i) if (refined_f0[i] < 0.001) refined_f0[i] = NAN; auto xi = arange(0.0, (double)f0Len * (double)TargetLength, (double)f0Len, (double)TargetLength); while (xi.size() < TargetLength) xi.emplace_back(*(xi.end() - 1) + ((double)f0Len / (double)TargetLength)); while (xi.size() > TargetLength) xi.pop_back(); auto x0 = arange(0, (double)f0Len); while (x0.size() < f0Len) x0.emplace_back(*(x0.end() - 1) + 1.); while (x0.size() > f0Len) x0.pop_back(); auto raw_f0 = std::vector(xi.size()); interp1(x0.data(), refined_f0.data(), static_cast(x0.size()), xi.data(), (int)xi.size(), raw_f0.data()); for (size_t i = 0; i < xi.size(); i++) if (isnan(raw_f0[i])) raw_f0[i] = 0.0; refined_f0 = std::move(raw_f0); } MELPEF0Extractor::MELPEF0Extractor(int sampling_rate, int hop_size, int n_f0_bins, double max_f0, double min_f0) : BaseF0Extractor(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0) { if (RMVPECORE.Model) RMVPECORE.Destory(); if (!MELPECORE.Model) MELPECORE.LoadModel(L"MELPE.onnx"); } void MELPEF0Extractor::InterPf0(size_t TargetLength) { const auto f0Len = refined_f0.size(); if (abs((int64_t)TargetLength - (int64_t)f0Len) < 3) { refined_f0.resize(TargetLength, 0.0); return; } for (size_t i = 0; i < f0Len; ++i) if (refined_f0[i] < 0.001) refined_f0[i] = NAN; auto xi = arange(0.0, (double)f0Len * (double)TargetLength, (double)f0Len, (double)TargetLength); while (xi.size() < TargetLength) xi.emplace_back(*(xi.end() - 1) + ((double)f0Len / (double)TargetLength)); while (xi.size() > TargetLength) xi.pop_back(); auto x0 = arange(0, (double)f0Len); while (x0.size() < f0Len) x0.emplace_back(*(x0.end() - 1) + 1.); while (x0.size() > f0Len) x0.pop_back(); auto raw_f0 = std::vector(xi.size()); interp1(x0.data(), refined_f0.data(), static_cast(x0.size()), xi.data(), (int)xi.size(), raw_f0.data()); for (size_t i = 0; i < xi.size(); i++) if (isnan(raw_f0[i])) raw_f0[i] = 0.0; refined_f0 = std::move(raw_f0); } std::vector MELPEF0Extractor::ExtractF0(const std::vector& PCMData, size_t TargetLength) { if (!MELPECORE.Model) return DioF0Extractor((int)fs, (int)hop, (int)f0_bin, f0_max, f0_min).ExtractF0(PCMData, TargetLength); const double step = double(fs) / 16000.; const auto window_len = (size_t)round(step); const auto half_window_len = window_len / 2; const auto f0_size = size_t((double)PCMData.size() / step); const auto pcm_idx_size = PCMData.size() - 2; std::vector pcm(f0_size, 0.f); auto idx = double(half_window_len + 1); for (size_t i = 0; i < f0_size; ++i) { const auto index = size_t(round(idx)); if (index + half_window_len > pcm_idx_size) break; if (half_window_len == 0) pcm[i] = (float)PCMData[index]; else pcm[i] = (float)average(&PCMData[index - half_window_len], &PCMData[index + half_window_len]); idx += step; } std::vector Tensors; const int64_t pcm_shape[] = { 1, (int64_t)pcm.size() }; Tensors.emplace_back(Ort::Value::CreateTensor(*MELPECORE.Memory, pcm.data(), pcm.size(), pcm_shape, 2)); const auto out = MELPECORE.Model->Run(Ort::RunOptions{ nullptr }, InputNames.data(), Tensors.data(), Tensors.size(), OutputNames.data(), OutputNames.size()); const auto osize = out[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto of0 = out[0].GetTensorData(); refined_f0 = std::vector(osize); for (size_t i = 0; i < osize; ++i) refined_f0[i] = ((of0[i] > 0.001f) ? (double)out[0].GetTensorData()[i] : NAN); InterPf0(TargetLength); std::vector finaF0(refined_f0.size()); for (size_t i = 0; i < refined_f0.size(); ++i) finaF0[i] = isnan(refined_f0[i]) ? 0 : (float)refined_f0[i]; return finaF0; } void EmptyCache() { RMVPECORE.Destory(); MELPECORE.Destory(); } MoeVoiceStudioF0ExtractorEnd ================================================ FILE: libsvc/Modules/src/InferTools/Sampler/MoeVSBaseSampler.cpp ================================================ #include "../../../header/InferTools/Sampler/MoeVSBaseSampler.hpp" #include "../../../header/InferTools/inferTools.hpp" MoeVoiceStudioSamplerHeader MoeVSBaseSampler::MoeVSBaseSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) : MelBins(Mel_Bins), Alpha(alpha), DenoiseFn(dfn), NoisePredictor(pred) { _callback = _ProgressCallback; Memory = memory; }; std::vector MoeVSBaseSampler::Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) { LibDLVoiceCodecThrow("NotImplementedError"); } MoeVSReflowBaseSampler::MoeVSReflowBaseSampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) : MelBins_(MelBins), Velocity_(Velocity) { Callback_ = _ProgressCallback; Memory_ = memory; } std::vector MoeVSReflowBaseSampler::Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) { LibDLVoiceCodecThrow("NotImplementedError"); } MoeVoiceStudioSamplerEnd ================================================ FILE: libsvc/Modules/src/InferTools/Sampler/MoeVSSamplerManager.cpp ================================================ #include "../../../header/InferTools/Sampler/MoeVSSamplerManager.hpp" #include #include "../../../header/Logger/MoeSSLogger.hpp" MoeVoiceStudioSamplerHeader std::map RegisteredMoeVSSamplers; std::map RegisteredMoeVSReflowSamplers; MoeVSSampler GetMoeVSSampler(const std::wstring& _name, Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const MoeVSBaseSampler::ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) { const auto f_Sampler = RegisteredMoeVSSamplers.find(_name); if (f_Sampler != RegisteredMoeVSSamplers.end()) return f_Sampler->second(alpha, dfn, pred, Mel_Bins, _ProgressCallback, memory); throw std::runtime_error("Unable To Find An Available Sampler"); } void RegisterMoeVSSampler(const std::wstring& _name, const GetMoeVSSamplerFn& _constructor_fn) { if (RegisteredMoeVSSamplers.find(_name) != RegisteredMoeVSSamplers.end()) { logger.log(L"[Warn] SamplerNameConflict"); return; } RegisteredMoeVSSamplers[_name] = _constructor_fn; } std::vector GetMoeVSSamplerList() { std::vector SamplersVec; SamplersVec.reserve(RegisteredMoeVSSamplers.size()); for (const auto& i : RegisteredMoeVSSamplers) SamplersVec.emplace_back(i.first); return SamplersVec; } MoeVSReflowSampler GetMoeVSReflowSampler( const std::wstring& _name, Ort::Session* velocity, int64_t Mel_Bins, const MoeVSBaseSampler::ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory ) { const auto f_Sampler = RegisteredMoeVSReflowSamplers.find(_name); if (f_Sampler != RegisteredMoeVSReflowSamplers.end()) return f_Sampler->second(velocity, Mel_Bins, _ProgressCallback, memory); throw std::runtime_error("Unable To Find An Available Sampler"); } void RegisterMoeVSReflowSampler(const std::wstring& _name, const GetMoeVSReflowSamplerFn& _constructor_fn) { if (RegisteredMoeVSReflowSamplers.find(_name) != RegisteredMoeVSReflowSamplers.end()) { logger.log(L"[Warn] SamplerNameConflict"); return; } RegisteredMoeVSReflowSamplers[_name] = _constructor_fn; } std::vector GetMoeVSReflowSamplerList() { std::vector SamplersVec; SamplersVec.reserve(RegisteredMoeVSReflowSamplers.size()); for (const auto& i : RegisteredMoeVSReflowSamplers) SamplersVec.emplace_back(i.first); return SamplersVec; } MoeVoiceStudioSamplerEnd ================================================ FILE: libsvc/Modules/src/InferTools/Sampler/MoeVSSamplers.cpp ================================================ #include "../../../header/InferTools/Sampler/MoeVSSamplers.hpp" #include #include #include "../../../header/InferTools/inferTools.hpp" MoeVoiceStudioSamplerHeader PndmSampler::PndmSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) : MoeVSBaseSampler(alpha, dfn, pred, Mel_Bins, _ProgressCallback, memory) {} DDimSampler::DDimSampler(Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) : MoeVSBaseSampler(alpha, dfn, pred, Mel_Bins, _ProgressCallback, memory) {} std::vector PndmSampler::Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) { std::vector diffusionSteps; for (int64_t itt = Steps - SpeedUp; itt >= 0; itt -= SpeedUp) diffusionSteps.push_back(itt); std::vector DenoiseIn; std::vector DenoiseOut; std::vector PredIn; std::vector PredOut; std::vector DiffOut; std::deque> noiseList; constexpr int64_t timeshape[1] = { 1 }; // PLMS SAMPLING for (const auto& t : diffusionSteps) { int64_t time[1] = { t }; int64_t time_prev[1] = { t - SpeedUp > 0 ? t - SpeedUp : 0 }; if (noiseList.empty()) { DenoiseIn.emplace_back(std::move(Tensors[1])); // noise DenoiseIn[0] DenoiseIn.emplace_back(Ort::Value::CreateTensor(*Memory, time, 1, timeshape, 1)); // time DenoiseIn[1] DenoiseIn.emplace_back(std::move(Tensors[0])); // condition DenoiseIn[2] try { DenoiseOut = DenoiseFn->Run(Ort::RunOptions{ nullptr }, denoiseInput.data(), DenoiseIn.data(), DenoiseIn.size(), denoiseOutput.data(), denoiseOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow(std::string("Locate: denoise\n") + e1.what()); } noiseList.emplace_back(DenoiseOut[0].GetTensorData(), DenoiseOut[0].GetTensorData() + DenoiseOut[0].GetTensorTypeAndShapeInfo().GetElementCount()); // NoiseListExpand PredIn.emplace_back(std::move(DenoiseIn[0])); // noise PredIn[0] PredIn.emplace_back(std::move(DenoiseOut[0])); // noise_pred PredIn[1] PredIn.emplace_back(std::move(DenoiseIn[1])); // time PredIn[2] PredIn.emplace_back(Ort::Value::CreateTensor(*Memory, time_prev, 1, timeshape, 1)); // time_prev PredIn[3] try { PredOut = NoisePredictor->Run(Ort::RunOptions{ nullptr }, predInput.data(), PredIn.data(), PredIn.size(), predOutput.data(), predOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow(std::string("Locate: pred\n") + e1.what()); } DenoiseIn[0] = std::move(PredOut[0]); // x_pred DenoiseIn[1] = std::move(PredIn[3]); // time_prev //DenoiseIn[2] = std::move(DenoiseIn[2]); // condition try { DenoiseOut = DenoiseFn->Run(Ort::RunOptions{ nullptr }, denoiseInput.data(), DenoiseIn.data(), DenoiseIn.size(), denoiseOutput.data(), denoiseOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow(std::string("Locate: denoise\n") + e1.what()); } auto noise_pred_prev = DenoiseOut[0].GetTensorMutableData(); for (const auto it : noiseList[0]) (*(noise_pred_prev++) += it) /= 2.0f; //PredIn[0] = std::move(PredIn[0]); // noise PredIn[1] = std::move(DenoiseOut[0]); // noise_pred_prime //PredIn[2] = std::move(PredIn[2]); // time PredIn[3] = std::move(DenoiseIn[1]); // time_prev } else { DenoiseIn[0] = std::move(PredOut[0]); // x DenoiseIn[1] = Ort::Value::CreateTensor(*Memory, time, 1, timeshape, 1); // time //DenoiseIn[2] = std::move(DenoiseIn[2]); // condition try { DenoiseOut = DenoiseFn->Run(Ort::RunOptions{ nullptr }, denoiseInput.data(), DenoiseIn.data(), DenoiseIn.size(), denoiseOutput.data(), denoiseOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow(std::string("Locate: denoise\n") + e1.what()); } if (noiseList.size() < 4) noiseList.emplace_back(DenoiseOut[0].GetTensorData(), DenoiseOut[0].GetTensorData() + DenoiseOut[0].GetTensorTypeAndShapeInfo().GetElementCount()); else { noiseList.pop_front(); noiseList.emplace_back(DenoiseOut[0].GetTensorData(), DenoiseOut[0].GetTensorData() + DenoiseOut[0].GetTensorTypeAndShapeInfo().GetElementCount()); } auto noise_pred_prime = DenoiseOut[0].GetTensorMutableData(); if (noiseList.size() == 2) for (size_t it = 0; it < noiseList[0].size(); ++it) ((*(noise_pred_prime++) *= 3.0f) -= noiseList[0][it]) /= 2.0f; if (noiseList.size() == 3) for (size_t it = 0; it < noiseList[0].size(); ++it) (((*(noise_pred_prime++) *= 23.0f) -= noiseList[1][it] * 16.0f) += noiseList[0][it] * 5.0f) /= 12.0f; if (noiseList.size() == 4) for (size_t it = 0; it < noiseList[0].size(); ++it) ((((*(noise_pred_prime++) *= 55.0f) -= noiseList[2][it] * 59.0f) += noiseList[1][it] * 37.0f) -= noiseList[0][it] * 9.0f) /= 24.0f; PredIn[0] = std::move(DenoiseIn[0]); // x PredIn[1] = std::move(DenoiseOut[0]); // noise_pred_prime PredIn[2] = std::move(DenoiseIn[1]); // time PredIn[3] = Ort::Value::CreateTensor(*Memory, time_prev, 1, timeshape, 1); } try { PredOut = NoisePredictor->Run(Ort::RunOptions{ nullptr }, predInput.data(), PredIn.data(), PredIn.size(), predOutput.data(), predOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow(std::string("Locate: pred\n") + e1.what()); } _callback(++Process, 1); } return PredOut; } std::vector DDimSampler::Sample(std::vector& Tensors, int64_t Steps, int64_t SpeedUp, float NoiseScale, int64_t Seed, size_t& Process) { std::vector diffusionSteps; for (int64_t itt = Steps - SpeedUp; itt >= 0; itt -= SpeedUp) diffusionSteps.push_back(itt); std::vector DenoiseIn; std::vector AlphaIn1, AlphaIn2; int64_t time[1] = { 0 }; int64_t time_prev[1] = { 0 }; constexpr int64_t timeshape[1] = { 1 }; // DDIM SAMPLING AlphaIn1.emplace_back(Ort::Value::CreateTensor(*Memory, time, 1, timeshape, 1)); AlphaIn2.emplace_back(Ort::Value::CreateTensor(*Memory, time_prev, 1, timeshape, 1)); DenoiseIn.emplace_back(std::move(Tensors[1])); // noise DenoiseIn[0] DenoiseIn.emplace_back(Ort::Value::CreateTensor(*Memory, time, 1, timeshape, 1)); // time DenoiseIn[1] DenoiseIn.emplace_back(std::move(Tensors[0])); // condition DenoiseIn[2] for (const auto& t : diffusionSteps) { std::vector DenoiseOut; float a_t, a_prev; try { time[0] = t; a_t = Alpha->Run(Ort::RunOptions{ nullptr }, alphain.data(), AlphaIn1.data(), AlphaIn1.size(), alphaout.data(), alphaout.size())[0].GetTensorData()[0]; time_prev[0] = (((t - SpeedUp) > 0) ? t - SpeedUp : 0); a_prev = Alpha->Run(Ort::RunOptions{ nullptr }, alphain.data(), AlphaIn2.data(), AlphaIn2.size(), alphaout.data(), alphaout.size())[0].GetTensorData()[0]; } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow(std::string("Locate: alphas\n") + e1.what()); } try { DenoiseOut = DenoiseFn->Run(Ort::RunOptions{ nullptr }, denoiseInput.data(), DenoiseIn.data(), DenoiseIn.size(), denoiseOutput.data(), denoiseOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow(std::string("Locate: denoise\n") + e1.what()); } const auto x = DenoiseIn[0].GetTensorMutableData(); const auto noise_pred = DenoiseOut[0].GetTensorMutableData(); const auto noise_size = DenoiseOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto sq_aprev = sqrt(a_prev); const auto sq_at = sqrt(a_t); const auto np_m_op = (sqrt((1 - a_prev) / a_prev) - sqrt((1 - a_t) / a_t)); #ifndef MoeVoiceStudioAvxAcc for (size_t i = 0; i < noise_size; ++i) noise_pred[i] = (x[i] / sq_at + np_m_op * noise_pred[i]) * sq_aprev; #else InferTools::FloatTensorWrapper XWrapper(x, noise_size); InferTools::FloatTensorWrapper PredWrapper(noise_pred, noise_size); XWrapper /= sq_at; ((PredWrapper *= np_m_op) += XWrapper) *= sq_aprev; #endif DenoiseIn[0] = std::move(DenoiseOut[0]); _callback(++Process, 1); } std::vector out; out.emplace_back(std::move(DenoiseIn[0])); return out; } ReflowEularSampler::ReflowEularSampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) :MoeVSReflowBaseSampler(Velocity, MelBins, _ProgressCallback, memory) {} ReflowHeunSampler::ReflowHeunSampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) :MoeVSReflowBaseSampler(Velocity, MelBins, _ProgressCallback, memory) {} ReflowPececeSampler::ReflowPececeSampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) :MoeVSReflowBaseSampler(Velocity, MelBins, _ProgressCallback, memory) {} ReflowRk4Sampler::ReflowRk4Sampler(Ort::Session* Velocity, int64_t MelBins, const ProgressCallback& _ProgressCallback, Ort::MemoryInfo* memory) :MoeVSReflowBaseSampler(Velocity, MelBins, _ProgressCallback, memory) {} std::vector ReflowEularSampler::Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) { std::vector Spec ,TensorsOut; Spec.emplace_back(std::move(Tensors[0])); Spec.emplace_back(std::move(Tensors[1])); Spec.emplace_back(std::move(Tensors[2])); const auto x_size = Spec[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto t = *Spec[1].GetTensorMutableData(); int64_t tvec[] = { 0 }; constexpr int64_t tshape[] = { 1 }; Spec[1] = Ort::Value::CreateTensor(*Memory_, tvec, 1, tshape, 1); for (int64_t i = 0; i < Steps; ++i) { *Spec[1].GetTensorMutableData() = int64_t(t * Scale); try { TensorsOut = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), Spec.data(), Spec.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } auto x_it = Spec[0].GetTensorMutableData(); auto k_it = TensorsOut[0].GetTensorMutableData(); #ifndef MoeVoiceStudioAvxAcc const auto x_end = Spec[0].GetTensorMutableData() + x_size; while (x_it != x_end) { *(x_it++) += (*(k_it++) * dt); } #else InferTools::FloatTensorWrapper XWrapper(x_it, x_size); InferTools::FloatTensorWrapper KWrapper(k_it, x_size); KWrapper *= dt; XWrapper += KWrapper #endif t += dt; Callback_(++Process, 1); } return Spec; } std::vector ReflowHeunSampler::Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) { std::vector X1; X1.emplace_back(std::move(Tensors[0])); X1.emplace_back(std::move(Tensors[1])); X1.emplace_back(std::move(Tensors[2])); auto T = *X1[1].GetTensorMutableData(); const auto XSize = X1[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto Shape = X1[0].GetTensorTypeAndShapeInfo().GetShape(); int64_t tvec[] = { 0 }; constexpr int64_t tshape[] = { 1 }; X1[1] = Ort::Value::CreateTensor(*Memory_, tvec, 1, tshape, 1); for (int64_t i = 0; i < Steps; ++i) { std::vector X2, K1, K2; std::vector K2X(X1[0].GetTensorData(), X1[0].GetTensorData() + XSize); //K1 *X1[1].GetTensorMutableData() = int64_t(T * Scale); try { K1 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X1.data(), X1.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } //K2 auto k_it = K1[0].GetTensorData(); for (auto& iter : K2X) iter += ((*(k_it++)) * dt); X2.emplace_back(Ort::Value::CreateTensor(*Memory_, K2X.data(), K2X.size(), Shape.data(), Shape.size())); X2.emplace_back(std::move(X1[1])); X2.emplace_back(std::move(X1[2])); *X2[1].GetTensorMutableData() = int64_t((T + dt) * Scale); try { K2 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X2.data(), X2.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } auto x_it = X1[0].GetTensorMutableData(); auto k1_it = K1[0].GetTensorMutableData(); auto k2_it = K2[0].GetTensorMutableData(); #ifndef MoeVoiceStudioAvxAcc const auto x_end = X1[0].GetTensorMutableData() + XSize; while (x_it != x_end) { *(x_it++) += ((*(k1_it++) + *(k2_it++)) * dt / 2.f); } #else InferTools::FloatTensorWrapper XWrapper(x_it, XSize); InferTools::FloatTensorWrapper K1Wrapper(k1_it, XSize); InferTools::FloatTensorWrapper K2Wrapper(k2_it, XSize); ((K1Wrapper += K2Wrapper) *= dt) /= 2.f; XWrapper += K1Wrapper; #endif X1[1] = std::move(X2[1]); X1[2] = std::move(X2[2]); T += dt; Callback_(++Process, 1); } return X1; } std::vector ReflowPececeSampler::Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) { std::vector X1; X1.emplace_back(std::move(Tensors[0])); X1.emplace_back(std::move(Tensors[1])); X1.emplace_back(std::move(Tensors[2])); auto T = *X1[1].GetTensorMutableData(); const auto Shape = X1[0].GetTensorTypeAndShapeInfo().GetShape(); const auto XSize = X1[0].GetTensorTypeAndShapeInfo().GetElementCount(); int64_t tvec[] = { 0 }; constexpr int64_t tshape[] = { 1 }; X1[1] = Ort::Value::CreateTensor(*Memory_, tvec, 1, tshape, 1); for (int64_t i = 0; i < Steps; ++i) { std::vector X2, X3, X4, K1, K2, K3, K4; std::vector K2X(X1[0].GetTensorData(), X1[0].GetTensorData() + XSize); auto K3X = K2X; //K1 *X1[1].GetTensorMutableData() = int64_t(T * Scale); try { K1 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X1.data(), X1.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } //K2 auto k_it = K1[0].GetTensorData(); for (auto& iter : K2X) iter += ((*(k_it++)) * dt); X2.emplace_back(Ort::Value::CreateTensor(*Memory_, K2X.data(), K2X.size(), Shape.data(), Shape.size())); X2.emplace_back(std::move(X1[1])); X2.emplace_back(std::move(X1[2])); *X2[1].GetTensorMutableData() = int64_t((T + dt) * Scale); try { K2 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X2.data(), X2.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } //K3 auto k_it1 = K1[0].GetTensorData(); auto k_it2 = K2[0].GetTensorData(); for (auto& iter : K3X) iter += (0.5f * (*(k_it1++) + *(k_it2++)) * dt); X3.emplace_back(Ort::Value::CreateTensor(*Memory_, K3X.data(), K3X.size(), Shape.data(), Shape.size())); X3.emplace_back(std::move(X2[1])); X3.emplace_back(std::move(X2[2])); *X3[1].GetTensorMutableData() = int64_t((T + dt) * Scale); try { K3 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X3.data(), X3.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } //K4 k_it = K3[0].GetTensorData(); auto K4X = K3X; for (auto& iter : K4X) iter += (*(k_it++) * dt); X4.emplace_back(Ort::Value::CreateTensor(*Memory_, K4X.data(), K4X.size(), Shape.data(), Shape.size())); X4.emplace_back(std::move(X3[1])); X4.emplace_back(std::move(X3[2])); *X4[1].GetTensorMutableData() = int64_t((T + 2.f * dt) * Scale); try { K4 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X4.data(), X4.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } auto x_it = X1[0].GetTensorMutableData(); auto k3_it = K3[0].GetTensorMutableData(); auto k4_it = K4[0].GetTensorMutableData(); #ifndef MoeVoiceStudioAvxAcc const auto x_end = X1[0].GetTensorMutableData() + XSize; while (x_it != x_end) { *(x_it++) += ((*(k3_it++) + *(k4_it++)) * dt / 2.f); } #else InferTools::FloatTensorWrapper XWrapper(x_it, XSize); InferTools::FloatTensorWrapper K3Wrapper(k3_it, XSize); InferTools::FloatTensorWrapper K4Wrapper(k4_it, XSize); ((K3Wrapper += K4Wrapper) *= dt) /= 2.f; XWrapper += K3Wrapper; #endif X1[1] = std::move(X4[1]); X1[2] = std::move(X4[2]); T += dt; Callback_(++Process, 1); } return X1; } std::vector ReflowRk4Sampler::Sample(std::vector& Tensors, int64_t Steps, float dt, float Scale, size_t& Process) { std::vector X1; X1.emplace_back(std::move(Tensors[0])); X1.emplace_back(std::move(Tensors[1])); X1.emplace_back(std::move(Tensors[2])); auto T = *X1[1].GetTensorMutableData(); const auto Shape = X1[0].GetTensorTypeAndShapeInfo().GetShape(); const auto XSize = X1[0].GetTensorTypeAndShapeInfo().GetElementCount(); int64_t tvec[] = { 0 }; constexpr int64_t tshape[] = { 1 }; X1[1] = Ort::Value::CreateTensor(*Memory_, tvec, 1, tshape, 1); for (int64_t i = 0; i < Steps; ++i) { std::vector X2, X3, X4, K1, K2, K3, K4; std::vector K2X(X1[0].GetTensorData(), X1[0].GetTensorData() + XSize); auto K3X = K2X, K4X = K2X; //K1 *X1[1].GetTensorMutableData() = int64_t(T * Scale); try { K1 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X1.data(), X1.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } //K2 auto k_it = K1[0].GetTensorData(); for (auto& iter : K2X) iter += (0.5f * (*(k_it++)) * dt); X2.emplace_back(Ort::Value::CreateTensor(*Memory_, K2X.data(), K2X.size(), Shape.data(), Shape.size())); X2.emplace_back(std::move(X1[1])); X2.emplace_back(std::move(X1[2])); *X2[1].GetTensorMutableData() = int64_t((T + 0.5f * dt) * Scale); try { K2 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X2.data(), X2.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } //K3 k_it = K2[0].GetTensorData(); for (auto& iter : K3X) iter += (0.5f * (*(k_it++)) * dt); X3.emplace_back(Ort::Value::CreateTensor(*Memory_, K3X.data(), K3X.size(), Shape.data(), Shape.size())); X3.emplace_back(std::move(X2[1])); X3.emplace_back(std::move(X2[2])); *X3[1].GetTensorMutableData() = int64_t((T + 0.5f * dt) * Scale); try { K3 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X3.data(), X3.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } //K4 k_it = K3[0].GetTensorData(); for (auto& iter : K4X) iter += (*(k_it++) * dt); X4.emplace_back(Ort::Value::CreateTensor(*Memory_, K4X.data(), K4X.size(), Shape.data(), Shape.size())); X4.emplace_back(std::move(X3[1])); X4.emplace_back(std::move(X3[2])); *X4[1].GetTensorMutableData() = int64_t((T + dt) * Scale); try { K4 = Velocity_->Run(Ort::RunOptions{ nullptr }, velocityInput.data(), X4.data(), X4.size(), velocityOutput.data(), velocityOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(std::string("Locate: Velocity\n") + e.what()); } auto x_it = X1[0].GetTensorMutableData(); auto k1_it = K1[0].GetTensorMutableData(); auto k2_it = K2[0].GetTensorMutableData(); auto k3_it = K3[0].GetTensorMutableData(); auto k4_it = K4[0].GetTensorMutableData(); #ifndef MoeVoiceStudioAvxAcc const auto x_end = X1[0].GetTensorMutableData() + XSize; while (x_it != x_end) { *(x_it++) += ((*(k1_it++) + (*(k2_it++) * 2.f) + (*(k3_it++) * 2.f) + *(k4_it++)) * dt / 6.f); } #else InferTools::FloatTensorWrapper XWrapper(x_it, XSize); InferTools::FloatTensorWrapper K1Wrapper(k1_it, XSize); InferTools::FloatTensorWrapper K2Wrapper(k2_it, XSize); InferTools::FloatTensorWrapper K3Wrapper(k3_it, XSize); InferTools::FloatTensorWrapper K4Wrapper(k4_it, XSize); K2Wrapper *= 2.f; K3Wrapper *= 2.f; ((((K1Wrapper += K2Wrapper) += K3Wrapper) += K4Wrapper) *= dt) /= 6.f; XWrapper += K1Wrapper; #endif X1[1] = std::move(X4[1]); X1[2] = std::move(X4[2]); T += dt; Callback_(++Process, 1); } return X1; } MoeVoiceStudioSamplerEnd ================================================ FILE: libsvc/Modules/src/InferTools/Stft/stft.cpp ================================================ #include "../../../header/InferTools/Stft/stft.hpp" #include "../../../header/InferTools/inferTools.hpp" #include "../../../header/Logger/MoeSSLogger.hpp" #include "cblas.h" #ifdef max #undef max #endif #ifdef min #undef min #endif namespace DlCodecStft { void HannWindow(double* data, int size) { for (int i = 0; i < size; i++) { const double windowValue = 0.5 * (1 - cos(2 * STFT::PI * i / (size - 1))); data[i] *= windowValue; } } void ConvertDoubleToFloat(const std::vector& input, float* output) { for (size_t i = 0; i < input.size(); i++) { output[i] = static_cast(input[i]); } } double CalculatePowerSpectrum(fftw_complex fc) { return sqrt(fc[0] * fc[0] + fc[1] * fc[1]); } void CalculatePowerSpectrum(double* real, const double* imag, int size) { for (int i = 0; i < size; i++) { real[i] = real[i] * real[i] + imag[i] * imag[i]; } } void ConvertPowerSpectrumToDecibels(double* data, int size) { for (int i = 0; i < size; i++) { data[i] = 10 * log10(data[i]); } } double HZ2Mel(const double frequency) { constexpr auto f_min = 0.0; constexpr auto f_sp = 200.0 / 3; auto mel = (frequency - f_min) / f_sp; constexpr auto min_log_hz = 1000.0; constexpr auto min_log_mel = (min_log_hz - f_min) / f_sp; const auto logstep = log(6.4) / 27.0; if (frequency >= min_log_hz) mel = min_log_mel + log(frequency / min_log_hz) / logstep; return mel; } double Mel2HZ(const double mel) { constexpr auto f_min = 0.0; constexpr auto f_sp = 200.0 / 3; auto freqs = f_min + f_sp * mel; constexpr auto min_log_hz = 1000.0; constexpr auto min_log_mel = (min_log_hz - f_min) / f_sp; const auto logstep = log(6.4) / 27.0; if (mel >= min_log_mel) freqs = min_log_hz * exp(logstep * (mel - min_log_mel)); return freqs; } static double mel_min = HZ2Mel(20.); static double mel_max = HZ2Mel(11025.); STFT::STFT(int WindowSize, int HopSize, int FFTSize) { WINDOW_SIZE = WindowSize; HOP_SIZE = HopSize; if (FFTSize > 0) FFT_SIZE = FFTSize; else FFT_SIZE = WINDOW_SIZE / 2 + 1; } STFT::~STFT() = default; std::pair, int64_t> STFT::operator()(const std::vector& audioData) const { const int NUM_FRAMES = (int(audioData.size()) - WINDOW_SIZE) / HOP_SIZE + 1; std::vector hannWindow(WINDOW_SIZE, 0.0); const auto fftOut = reinterpret_cast(fftw_malloc(sizeof(fftw_complex) * FFT_SIZE)); const fftw_plan plan = fftw_plan_dft_r2c_1d(WINDOW_SIZE, hannWindow.data(), fftOut, FFTW_ESTIMATE); std::vector spectrogram(size_t(NUM_FRAMES) * FFT_SIZE, 0.f); for (int i = 0; i < NUM_FRAMES; i++) { std::memcpy(hannWindow.data(), &audioData[size_t(i) * HOP_SIZE], size_t(sizeof(double)) * WINDOW_SIZE); HannWindow(hannWindow.data(), WINDOW_SIZE); fftw_execute(plan); const auto BgnPtn = size_t(unsigned(i * FFT_SIZE)); for (int j = 0; j < FFT_SIZE; j++) spectrogram[BgnPtn + j] = float(CalculatePowerSpectrum(fftOut[j])); } fftw_destroy_plan(plan); fftw_free(fftOut); return { std::move(spectrogram), int64_t(NUM_FRAMES) }; } std::pair, int64_t> Mel::GetMel(const std::vector& audioData) const { auto BgnTime = clock(); const auto Spec = stft(audioData); //[frame, nfft] * [nfft, mel_bins] | [mel_bins, nfft] * [nfft, frame] logger.log(("[Inference] Slice Stft Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); const auto NFrames = Spec.second; std::vector Mel(MEL_SIZE * NFrames, 0.f); BgnTime = clock(); cblas_sgemm( CblasRowMajor, CblasNoTrans, CblasTrans, MEL_SIZE, blasint(NFrames), FFT_SIZE, 1.f, MelBasis.data(), FFT_SIZE, Spec.first.data(), blasint(FFT_SIZE), 0.f, Mel.data(), blasint(NFrames) ); for (auto& it : Mel) it = log(std::max(1e-5f, it)); logger.log(("[Inference] Slice Mel Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); return { std::move(Mel), (int64_t)NFrames }; } std::pair, int64_t> Mel::operator()(const std::vector& audioData) const { return GetMel(audioData); } Mel::Mel(int WindowSize, int HopSize, int SamplingRate, int MelSize) : stft(WindowSize, HopSize, WindowSize / 2 + 1) { if (MelSize > 0) MEL_SIZE = MelSize; FFT_SIZE = WindowSize / 2 + 1; sr = SamplingRate; const int nfft = (FFT_SIZE - 1) * 2; const double fftfreqval = 1. / (double(nfft) / double(SamplingRate)); auto fftfreqs = InferTools::arange(0, FFT_SIZE + 2); fftfreqs.resize(FFT_SIZE); for (auto& i : fftfreqs) i *= fftfreqval; auto mel_f = InferTools::arange(mel_min, mel_max + 1., (mel_max - mel_min) / (MEL_SIZE + 1)); mel_f.resize(MEL_SIZE + 2); //[MEL_SIZE + 2] std::vector fdiff; std::vector> ramps; //[MEL_SIZE + 2, FFTSize] ramps.reserve(MEL_SIZE + 2); for (auto& i : mel_f) { i = Mel2HZ(i); ramps.emplace_back(FFT_SIZE, i); } for (size_t i = 0; i < ramps.size(); ++i) for (int j = 0; j < FFT_SIZE; ++j) ramps[i][j] -= fftfreqs[j]; fdiff.reserve(MEL_SIZE + 2); //[MEL_SIZE + 1] for (size_t i = 1; i < mel_f.size(); ++i) fdiff.emplace_back(mel_f[i] - mel_f[i - 1]); MelBasis = std::vector(size_t(FFT_SIZE) * MelSize, 0.f); for (int i = 0; i < MelSize; ++i) { const auto enorm = 2. / (mel_f[i + 2] - mel_f[i]); for (int j = 0; j < FFT_SIZE; ++j) MelBasis[i * FFT_SIZE + j] = (float)(std::max(0., std::min(-ramps[i][j] / fdiff[i], ramps[i + 2][j] / fdiff[i + 1])) * enorm); } } } ================================================ FILE: libsvc/Modules/src/InferTools/TensorExtractor/MoeVSCoreTensorExtractor.cpp ================================================ #include "../../../header/InferTools/TensorExtractor/MoeVSCoreTensorExtractor.hpp" #include #include "../../../header/Logger/MoeSSLogger.hpp" #include "../../../header/InferTools/inferTools.hpp" MoeVoiceStudioTensorExtractorHeader MoeVoiceStudioTensorExtractor::Inputs SoVits2TensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, HubertLen }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; // SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.Length[0] = HubertLen; SvcTensors.Data.F0 = InferTools::InterpFunc(F0, (long)F0.size(), (long)HubertLen); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.NSFF0 = GetNSFF0(SvcTensors.Data.F0); SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Length, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.NSFF0.data(), SvcTensors.Data.NSFF0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs SoVits3TensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; // SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; const int64_t upSample = int64_t(_SamplingRate) / 16000; const auto srcHubertSize = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.HiddenUnitShape[1] *= upSample; HubertSize *= upSample; SvcTensors.Data.FrameShape[1] = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.HiddenUnit.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < srcHubertSize; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) SvcTensors.Data.HiddenUnit.insert(SvcTensors.Data.HiddenUnit.end(), HiddenUnit.begin() + itS * (int64_t)_HiddenSize, HiddenUnit.begin() + (itS + 1) * (int64_t)_HiddenSize); SvcTensors.Data.F0 = GetInterpedF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.HiddenUnitShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Data.Length[0] = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Length, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs SoVits4TensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; std::mt19937 gen(int(params.Seed)); std::normal_distribution normal(0, 1); const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.NoiseShape = { 1, 192, SvcTensors.Data.FrameShape[1] }; const auto NoiseSize = SvcTensors.Data.NoiseShape[1] * SvcTensors.Data.NoiseShape[2] * SvcTensors.Data.NoiseShape[0]; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.F0 = GetInterpedF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.FrameShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.UnVoice = GetUV(F0); SvcTensors.Data.Noise = std::vector(NoiseSize, 0.f); for (auto& it : SvcTensors.Data.Noise) it = normal(gen) * params.NoiseScale; SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Alignment.data(), SvcTensors.Data.Alignment.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.UnVoice.data(), SvcTensors.Data.UnVoice.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Noise.data(), SvcTensors.Data.Noise.size(), SvcTensors.Data.NoiseShape.data(), 3 )); if (_SpeakerMix) { SvcTensors.Data.SpkMap = GetCurrectSpkMixData(SpkMap, SvcTensors.Data.FrameShape[1], params.Chara); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.SpkMap.data(), SvcTensors.Data.SpkMap.size(), SvcTensors.Data.SpkShape.data(), 2 )); } else { SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); } if (_Volume) { SvcTensors.InputNames = InputNamesVol.data(); SvcTensors.Data.Volume = InferTools::InterpFunc(Volume, long(Volume.size()), long(SvcTensors.Data.FrameShape[1])); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Volume.data(), SvcTensors.Data.FrameShape[1], SvcTensors.Data.FrameShape.data(), 2 )); } else SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs SoVits4DDSPTensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; std::mt19937 gen(int(params.Seed)); std::normal_distribution normal(0, 1); const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.NoiseShape = { 1, 192, SvcTensors.Data.FrameShape[1] }; const auto NoiseSize = SvcTensors.Data.NoiseShape[1] * SvcTensors.Data.NoiseShape[2] * SvcTensors.Data.NoiseShape[0]; SvcTensors.Data.DDSPNoiseShape = { 1, 2048, SvcTensors.Data.FrameShape[1] }; const int64_t IstftCount = SvcTensors.Data.FrameShape[1] * 2048; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.F0 = GetInterpedF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.FrameShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.DDSPNoise = std::vector(IstftCount, params.DDSPNoiseScale); SvcTensors.Data.Noise = std::vector(NoiseSize, 0.f); for (auto& it : SvcTensors.Data.Noise) it = normal(gen) * params.NoiseScale; SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Alignment.data(), SvcTensors.Data.Alignment.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.DDSPNoise.data(), SvcTensors.Data.DDSPNoise.size(), SvcTensors.Data.DDSPNoiseShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Noise.data(), SvcTensors.Data.Noise.size(), SvcTensors.Data.NoiseShape.data(), 3 )); if (_SpeakerMix) { SvcTensors.Data.SpkMap = GetCurrectSpkMixData(SpkMap, SvcTensors.Data.FrameShape[1], params.Chara); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.SpkMap.data(), SvcTensors.Data.SpkMap.size(), SvcTensors.Data.SpkShape.data(), 2 )); } else { SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); } if (_Volume) { SvcTensors.InputNames = InputNamesVol.data(); SvcTensors.Data.Volume = InferTools::InterpFunc(Volume, long(Volume.size()), long(SvcTensors.Data.FrameShape[1])); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Volume.data(), SvcTensors.Data.FrameShape[1], SvcTensors.Data.FrameShape.data(), 2 )); } else SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs RVCTensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; std::mt19937 gen(int(params.Seed)); std::normal_distribution normal(0, 1); auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; constexpr int64_t upSample = 2; const auto srcHubertSize = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.HiddenUnitShape[1] *= upSample; HubertSize *= upSample; SvcTensors.Data.FrameShape[1] = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.NoiseShape = { 1, 192, SvcTensors.Data.FrameShape[1] }; const auto NoiseSize = SvcTensors.Data.NoiseShape[1] * SvcTensors.Data.NoiseShape[2] * SvcTensors.Data.NoiseShape[0]; SvcTensors.Data.HiddenUnit.reserve(HubertSize); for (int64_t itS = 0; itS < srcHubertSize; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) SvcTensors.Data.HiddenUnit.insert(SvcTensors.Data.HiddenUnit.end(), HiddenUnit.begin() + itS * (int64_t)_HiddenSize, HiddenUnit.begin() + (itS + 1) * (int64_t)_HiddenSize); SvcTensors.Data.Length[0] = SvcTensors.Data.HiddenUnitShape[1]; SvcTensors.Data.F0 = GetInterpedF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.HiddenUnitShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.NSFF0 = GetNSFF0(SvcTensors.Data.F0); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.Noise = std::vector(NoiseSize, 0.f); for (auto& it : SvcTensors.Data.Noise) it = normal(gen) * params.NoiseScale; SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Length, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.NSFF0.data(), SvcTensors.Data.NSFF0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); if (_SpeakerMix) { SvcTensors.Data.SpkMap = GetCurrectSpkMixData(SpkMap, SvcTensors.Data.FrameShape[1], params.Chara); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.SpkMap.data(), SvcTensors.Data.SpkMap.size(), SvcTensors.Data.SpkShape.data(), 2 )); } else { SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); } SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Noise.data(), SvcTensors.Data.Noise.size(), SvcTensors.Data.NoiseShape.data(), 3 )); if (_Volume) { SvcTensors.InputNames = InputNamesVol.data(); SvcTensors.Data.Volume = InferTools::InterpFunc(Volume, long(Volume.size()), long(SvcTensors.Data.FrameShape[1])); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Volume.data(), SvcTensors.Data.FrameShape[1], SvcTensors.Data.FrameShape.data(), 2 )); } else SvcTensors.InputNames = InputNames.data(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs DiffSvcTensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.F0 = InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.FrameShape[1])); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.F0 = GetInterpedF0log(SvcTensors.Data.F0, true); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Alignment.data(), SvcTensors.Data.Alignment.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.InputNames = InputNames.data(); SvcTensors.OutputNames = OutputNames.data(); SvcTensors.OutputCount = OutputNames.size(); return SvcTensors; } MoeVoiceStudioTensorExtractor::Inputs DiffusionSvcTensorExtractor::Extract(const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params) { Inputs SvcTensors; const auto HubertSize = HiddenUnit.size(); const auto HubertLen = int64_t(HubertSize) / int64_t(_HiddenSize); SvcTensors.Data.FrameShape = { 1, int64_t(params.AudioSize * _SamplingRate / _SrcSamplingRate / _HopSize) }; SvcTensors.Data.HiddenUnitShape = { 1, HubertLen, int64_t(_HiddenSize) }; SvcTensors.Data.SpkShape = { SvcTensors.Data.FrameShape[1], int64_t(_NSpeaker) }; SvcTensors.Data.HiddenUnit = HiddenUnit; SvcTensors.Data.F0 = InterpUVF0(InferTools::InterpFunc(F0, long(F0.size()), long(SvcTensors.Data.FrameShape[1]))); for (auto& it : SvcTensors.Data.F0) it *= (float)pow(2.0, static_cast(params.upKeys) / 12.0); SvcTensors.Data.Alignment = GetAligments(SvcTensors.Data.FrameShape[1], HubertLen); SvcTensors.Data.Speaker[0] = params.Chara; SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.HiddenUnit.data(), HubertSize, SvcTensors.Data.HiddenUnitShape.data(), 3 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Alignment.data(), SvcTensors.Data.Alignment.size(), SvcTensors.Data.FrameShape.data(), 2 )); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.F0.data(), SvcTensors.Data.F0.size(), SvcTensors.Data.FrameShape.data(), 2 )); if (_Volume) { SvcTensors.InputNames = InputNamesVol.data(); SvcTensors.Data.Volume = InferTools::InterpFunc(Volume, long(Volume.size()), long(SvcTensors.Data.FrameShape[1])); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Volume.data(), SvcTensors.Data.FrameShape[1], SvcTensors.Data.FrameShape.data(), 2 )); } else SvcTensors.InputNames = InputNames.data(); if (_SpeakerMix) { SvcTensors.Data.SpkMap = GetCurrectSpkMixData(SpkMap, SvcTensors.Data.FrameShape[1], params.Chara); SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.SpkMap.data(), SvcTensors.Data.SpkMap.size(), SvcTensors.Data.SpkShape.data(), 2 )); } else { SvcTensors.Tensor.emplace_back(Ort::Value::CreateTensor( Memory, SvcTensors.Data.Speaker, 1, SvcTensors.Data.OneShape, 1 )); } SvcTensors.OutputNames = OutputNames.data(); SvcTensors.OutputCount = OutputNames.size(); return SvcTensors; } MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libsvc/Modules/src/InferTools/TensorExtractor/MoeVoiceStudioTensorExtractor.cpp ================================================ #include "../../../header/InferTools/TensorExtractor/MoeVoiceStudioTensorExtractor.hpp" #include "../../../header/InferTools/inferTools.hpp" MoeVoiceStudioTensorExtractorHeader MoeVoiceStudioTensorExtractor::MoeVoiceStudioTensorExtractor(uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const Others& _other) { _SrcSamplingRate = _srcsr; _SamplingRate = _sr; _HopSize = _hop; _SpeakerMix = _smix; _Volume = _volume; _HiddenSize = _hidden_size; _NSpeaker = _nspeaker; f0_bin = _other.f0_bin; f0_max = _other.f0_max; f0_min = _other.f0_min; f0_mel_min = 1127.f * log(1.f + f0_min / 700.f); f0_mel_max = 1127.f * log(1.f + f0_max / 700.f); Memory = _other.Memory; } MoeVoiceStudioTensorExtractor::Inputs MoeVoiceStudioTensorExtractor::Extract( const std::vector& HiddenUnit, const std::vector& F0, const std::vector& Volume, const std::vector>& SpkMap, Params params ) { LibDLVoiceCodecThrow("NotImplementedError"); } std::vector MoeVoiceStudioTensorExtractor::GetCurrectSpkMixData(const std::vector>& _input, size_t dst_len, int64_t curspk) const { std::vector mixData; mixData.reserve(_NSpeaker * dst_len); if(_input.empty()) { std::vector LenData(_NSpeaker, 0.0); LenData[curspk] = 1.0; for (size_t i = 0; i < dst_len; ++i) mixData.insert(mixData.end(), LenData.begin(), LenData.end()); } else { std::vector> _spkMap; for (size_t i = 0; i < _input.size() && i < _NSpeaker; ++i) _spkMap.emplace_back(InferTools::InterpFunc(_input[i], long(_input[i].size()), long(dst_len))); LinearCombination(_spkMap, curspk); const auto curnspk = _input.size(); if (curnspk < _NSpeaker) { std::vector LenData(_NSpeaker - curnspk, 0.0); for (size_t i = 0; i < dst_len; ++i) { for (size_t j = 0; j < curnspk; ++j) mixData.emplace_back(_spkMap[j][i]); mixData.insert(mixData.end(), LenData.begin(), LenData.end()); } } else for (size_t i = 0; i < dst_len; ++i) for (size_t j = 0; j < _NSpeaker; ++j) mixData.emplace_back(_spkMap[j][i]); } return mixData; } std::vector MoeVoiceStudioTensorExtractor::GetSpkMixData(const std::vector>& _input, size_t dst_len, size_t spk_count) { std::vector mixData; mixData.reserve(spk_count * dst_len); if (_input.empty()) { std::vector LenData(spk_count, 0.0); LenData[0] = 1.0; for (size_t i = 0; i < dst_len; ++i) mixData.insert(mixData.end(), LenData.begin(), LenData.end()); } else { std::vector> _spkMap; for (size_t i = 0; i < _input.size() && i < spk_count; ++i) _spkMap.emplace_back(InferTools::InterpFunc(_input[i], long(_input[i].size()), long(dst_len))); LinearCombination(_spkMap, 0); const auto curnspk = _input.size(); if (curnspk < spk_count) { std::vector LenData(spk_count - curnspk, 0.0); for (size_t i = 0; i < dst_len; ++i) { for (size_t j = 0; j < curnspk; ++j) mixData.emplace_back(_spkMap[j][i]); mixData.insert(mixData.end(), LenData.begin(), LenData.end()); } } else for (size_t i = 0; i < dst_len; ++i) for (size_t j = 0; j < spk_count; ++j) mixData.emplace_back(_spkMap[j][i]); } return mixData; } std::vector MoeVoiceStudioTensorExtractor::GetNSFF0(const std::vector& F0) const { const auto f0Len = F0.size(); std::vector NSFF0(f0Len); for (size_t i = 0; i < f0Len; ++i) { float f0_mel = 1127.f * log(1.f + F0[i] / 700.f); if (f0_mel > 0.f) f0_mel = (f0_mel - f0_mel_min) * (float(f0_bin) - 2.f) / (f0_mel_max - f0_mel_min) + 1.f; if (f0_mel < 1.f) f0_mel = 1.f; if (f0_mel > float(f0_bin) - 1.f) f0_mel = float(f0_bin) - 1.f; NSFF0[i] = (int64_t)round(f0_mel); } return NSFF0; } std::vector MoeVoiceStudioTensorExtractor::GetInterpedF0(const std::vector& F0) { const auto specLen = F0.size(); std::vector Of0(specLen, 0.0); float last_value = 0.0; for (size_t i = 0; i < specLen; ++i) { if (F0[i] <= 0.f) { size_t j = i + 1; for (; j < specLen; ++j) { if (F0[j] > 0.f) break; } if (j < specLen - 1) { if (last_value > 0.f) { const auto step = (F0[j] - F0[i - 1]) / float(j - i); for (size_t k = i; k < j; ++k) Of0[k] = float(F0[i - 1] + step * float(k - i + 1)); } else for (size_t k = i; k < j; ++k) Of0[k] = float(F0[j]); i = j; } else { for (size_t k = i; k < specLen; ++k) Of0[k] = float(last_value); i = specLen; } } else { if (i == 0) { Of0[i] = float(F0[i]); continue; } Of0[i] = float(F0[i - 1]); last_value = F0[i]; } } return Of0; } std::vector MoeVoiceStudioTensorExtractor::InterpUVF0(const std::vector& F0) { std::vector NUVF0; std::vector UVF0Indices, NUVF0Indices; UVF0Indices.reserve(F0.size()); NUVF0.reserve(F0.size()); NUVF0Indices.reserve(F0.size()); if(F0[0] < 0.0001f) { NUVF0.emplace_back(0); NUVF0Indices.emplace_back(0); } for (size_t i = 1; i < F0.size(); ++i) { if (F0[i] < 0.0001f) UVF0Indices.emplace_back((double)i); else { NUVF0.emplace_back((double)F0[i]); NUVF0Indices.emplace_back((double)i); } } if (UVF0Indices.empty() || NUVF0Indices.empty()) return F0; std::vector UVF0(F0.size()); std::vector Of0 = F0; interp1(NUVF0Indices.data(), NUVF0.data(), (int)NUVF0.size(), UVF0Indices.data(), (int)UVF0Indices.size(), UVF0.data()); for (size_t i = 0; i < UVF0Indices.size(); ++i) Of0[size_t(UVF0Indices[i])] = (float)UVF0[i]; return Of0; } std::vector MoeVoiceStudioTensorExtractor::GetUV(const std::vector& F0) { const auto specLen = F0.size(); std::vector ruv(specLen, 1.0); for (size_t i = 0; i < specLen; ++i) { if (F0[i] < 0.001f) ruv[i] = 0.f; } return ruv; } std::vector MoeVoiceStudioTensorExtractor::GetAligments(size_t specLen, size_t hubertLen) { std::vector mel2ph(specLen + 1, 0); size_t startFrame = 0; const double ph_durs = static_cast(specLen) / static_cast(hubertLen); for (size_t iph = 0; iph < hubertLen; ++iph) { const auto endFrame = static_cast(round(static_cast(iph) * ph_durs + ph_durs)); for (auto j = startFrame; j < endFrame + 1; ++j) mel2ph[j] = static_cast(iph) + 1; startFrame = endFrame + 1; } return mel2ph; } std::vector MoeVoiceStudioTensorExtractor::GetInterpedF0log(const std::vector& rF0, bool enable_log) { const auto specLen = rF0.size(); std::vector F0(specLen); std::vector Of0(specLen, 0.0); for (size_t i = 0; i < specLen; ++i) { if (enable_log) F0[i] = log2(rF0[i]); else F0[i] = rF0[i]; if (isnan(F0[i]) || isinf(F0[i])) F0[i] = 0.f; } float last_value = 0.0; for (size_t i = 0; i < specLen; ++i) { if (F0[i] <= 0.f) { size_t j = i + 1; for (; j < specLen; ++j) { if (F0[j] > 0.f) break; } if (j < specLen - 1) { if (last_value > 0.f) { const auto step = (F0[j] - F0[i - 1]) / float(j - i); for (size_t k = i; k < j; ++k) Of0[k] = float(F0[i - 1] + step * float(k - i + 1)); } else for (size_t k = i; k < j; ++k) Of0[k] = float(F0[j]); i = j; } else { for (size_t k = i; k < specLen; ++k) Of0[k] = float(last_value); i = specLen; } } else { Of0[i] = float(F0[i - 1]); last_value = F0[i]; } } return Of0; } MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libsvc/Modules/src/InferTools/TensorExtractor/TensorExtractorManager.cpp ================================================ #include "../../../header/InferTools/TensorExtractor/TensorExtractorManager.hpp" #include #include "../../../header/Logger/MoeSSLogger.hpp" MoeVoiceStudioTensorExtractorHeader inline std::map RegisteredTensorExtractors; void RegisterTensorExtractor(const std::wstring& _name, const GetTensorExtractorFn& _constructor_fn) { if (RegisteredTensorExtractors.find(_name) != RegisteredTensorExtractors.end()) { logger.log(L"[Warn] TensorExtractorNameConflict"); return; } RegisteredTensorExtractors[_name] = _constructor_fn; } TensorExtractor GetTensorExtractor(const std::wstring& _name, uint64_t _srcsr, uint64_t _sr, uint64_t _hop, bool _smix, bool _volume, uint64_t _hidden_size, uint64_t _nspeaker, const MoeVoiceStudioTensorExtractor::Others& _other) { const auto f_TensorExtractor = RegisteredTensorExtractors.find(_name); if (f_TensorExtractor != RegisteredTensorExtractors.end()) return f_TensorExtractor->second(_srcsr, _sr, _hop, _smix, _volume, _hidden_size, _nspeaker, _other); throw std::runtime_error("Unable To Find An Available TensorExtractor"); } MoeVoiceStudioTensorExtractorEnd ================================================ FILE: libsvc/Modules/src/InferTools/inferTools.cpp ================================================ #include "../../header/InferTools/inferTools.hpp" #include "string" #ifdef MoeVoiceStudioAvxAcc #include #endif InferTools::Wav::Wav(const wchar_t* Path) :header(WAV_HEADER()) { char buf[1024]; FILE* stream; _wfreopen_s(&stream, Path, L"rb", stderr); if (stream == nullptr) { throw (std::exception("File not exists")); } fread(buf, 1, HEAD_LENGTH, stream); int pos = 0; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'R') && (buf[pos + 1] == 'I') && (buf[pos + 2] == 'F') && (buf[pos + 3] == 'F')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.ChunkSize = *(int*)&buf[pos]; pos += 8; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'f') && (buf[pos + 1] == 'm') && (buf[pos + 2] == 't')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk1Size = *(int*)&buf[pos]; pos += 4; header.AudioFormat = *(short*)&buf[pos]; pos += 2; header.NumOfChan = *(short*)&buf[pos]; pos += 2; header.SamplesPerSec = *(int*)&buf[pos]; pos += 4; header.bytesPerSec = *(int*)&buf[pos]; pos += 4; header.blockAlign = *(short*)&buf[pos]; pos += 2; header.bitsPerSample = *(short*)&buf[pos]; pos += 2; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'd') && (buf[pos + 1] == 'a') && (buf[pos + 2] == 't') && (buf[pos + 3] == 'a')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk2Size = *(int*)&buf[pos]; pos += 4; StartPos = pos; Data = new char[header.Subchunk2Size + 1]; fseek(stream, StartPos, SEEK_SET); fread(Data, 1, header.Subchunk2Size, stream); if (stream != nullptr) { fclose(stream); } SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav::Wav(const Wav& input) :header(WAV_HEADER()) { Data = new char[(input.header.Subchunk2Size + 1)]; if (Data == nullptr) { LibDLVoiceCodecThrow("OOM") } memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; memcpy(Data, input.Data, input.header.Subchunk2Size); SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav::Wav(Wav&& input) noexcept { Data = input.Data; input.Data = nullptr; memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav& InferTools::Wav::operator=(Wav&& input) noexcept { destory(); Data = input.Data; input.Data = nullptr; memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; return *this; } InferTools::Wav& InferTools::Wav::cat(const Wav& input) { if (header.AudioFormat != 1) return *this; if (header.SamplesPerSec != input.header.bitsPerSample || header.NumOfChan != input.header.NumOfChan) return *this; char* buffer = new char[(int64_t)header.Subchunk2Size + (int64_t)input.header.Subchunk2Size + 1]; if (buffer == nullptr)return *this; memcpy(buffer, Data, header.Subchunk2Size); memcpy(buffer + header.Subchunk2Size, input.Data, input.header.Subchunk2Size); header.ChunkSize += input.header.Subchunk2Size; header.Subchunk2Size += input.header.Subchunk2Size; delete[] Data; Data = buffer; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; return *this; } std::vector InferTools::SliceAudio(const std::vector& input, const SlicerSettings& _slicer) { if (input.size() < size_t(_slicer.MinLength) * _slicer.SamplingRate) return {0, input.size()}; std::vector slice_point; bool slice_tag = true; slice_point.emplace_back(0); unsigned long CurLength = 0; for (size_t i = 0; i + _slicer.WindowLength < input.size(); i += _slicer.HopSize) { if (slice_tag) { const auto vol = abs(getAvg(input.data() + i, input.data() + i + _slicer.WindowLength)); if (vol < _slicer.Threshold) { slice_tag = false; if (CurLength > _slicer.MinLength * _slicer.SamplingRate) { CurLength = 0; slice_point.emplace_back(i + (_slicer.WindowLength / 2)); } } else slice_tag = true; } else { const auto vol = abs(getAvg(input.data() + i, input.data() + i + _slicer.WindowLength)); if (vol < _slicer.Threshold) slice_tag = false; else { slice_tag = true; if (CurLength > _slicer.MinLength * _slicer.SamplingRate) { CurLength = 0; slice_point.emplace_back(i + (_slicer.WindowLength / 2)); } } } CurLength += _slicer.HopSize; } slice_point.push_back(input.size()); return slice_point; } std::vector InferTools::arange(double start, double end, double step, double div) { std::vector output; while (start < end) { output.push_back(start / div); start += step; } return output; } std::vector InferTools::mean_filter(const std::vector& vec, size_t window_size) { std::vector result; if (window_size > vec.size() || window_size < 2) return vec; const size_t half = window_size / 2; // 窗口半径,向下取整 for (size_t i = half; i < vec.size() - half; i++) { float sum = 0.0f; for (size_t j = i - half; j <= i + half; j++) { sum += vec[j]; } result.push_back(sum / (float)(window_size % 2 ? window_size : window_size + 1)); } return result; } #ifdef MoeVoiceStudioAvxAcc InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator+=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_add_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] += _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator-=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_sub_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] -= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator*=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_mul_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] *= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator/=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_div_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] /= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator+=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_add_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] += _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator-=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_sub_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] -= _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator*=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_mul_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] *= _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator/=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_div_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] /= _right; return *this; } #endif ================================================ FILE: libsvc/Modules/src/Logger/MoeSSLogger.cpp ================================================ #include "../../header/Logger/MoeSSLogger.hpp" #include #include "../../header/StringPreprocess.hpp" #include namespace MoeSSLogger { Logger MoeVsLogger; inline std::wstring GetCurrentFolder(const std::wstring& defualt = L"") { wchar_t path[1024]; #ifdef _WIN32 GetModuleFileName(nullptr, path, 1024); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); return _curPath; #else //TODO Other System #error Other System ToDO #endif } void RemoveDir(const std::filesystem::directory_entry& dir) { if (!dir.exists()) return; if (dir.is_directory() && !is_empty(dir)) { const std::filesystem::directory_iterator dirs(dir); for (const auto& i : dirs) RemoveDir(i); } remove(dir); } Logger::~Logger() { if (log_file) fclose(log_file); if (error_file) fclose(error_file); log_file = nullptr; error_file = nullptr; } Logger::Logger() { const std::wstring LogPath = GetCurrentFolder() + L"/log"; const std::filesystem::path logger_path(LogPath); if (!exists(logger_path)) create_directory(logger_path); const std::filesystem::directory_entry logger_path_entry(LogPath); if (logger_path_entry.is_directory()) { time_t curtime; time(&curtime); tm nowtime{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }; localtime_s(&nowtime, &curtime); const std::wstring dir_name = L"libsvc " + std::to_wstring(nowtime.tm_year + 1900) + L'-' + std::to_wstring(nowtime.tm_mon) + L'-' + std::to_wstring(nowtime.tm_mday) + L'-' + std::to_wstring(nowtime.tm_hour) + L'-' + std::to_wstring(nowtime.tm_min) + L'-' + std::to_wstring(nowtime.tm_sec); cur_log_dir = LogPath + L'/' + dir_name; const std::filesystem::directory_iterator logger_path_list(LogPath); std::filesystem::directory_entry remove_dir; size_t log_count = 0; for (const auto& i : logger_path_list) if (i.is_directory() && i.path().filename().wstring().substr(0, 6) == L"libsvc") { if (!log_count || i.last_write_time() < remove_dir.last_write_time()) remove_dir = i; ++log_count; } if (log_count > 10) RemoveDir(remove_dir); if (!exists(cur_log_dir)) create_directory(cur_log_dir); logpath = cur_log_dir; logpath.append("log.txt"); errorpath = cur_log_dir; errorpath.append("error.txt"); } } Logger::Logger(logger_fn error_fn, logger_fn log_fn) { custom_logger_fn = true; cerror_fn = error_fn; cloggerfn = log_fn; } void Logger::log(const std::wstring& format) { std::lock_guard mtx(mx); if (custom_logger_fn) { cloggerfn(format.c_str(), nullptr); return; } if (filelogger) { _wfopen_s(&log_file, logpath.c_str(), L"a+"); if (log_file) { fprintf_s(log_file, "%s\n", to_byte_string(format).c_str()); fclose(log_file); log_file = nullptr; } } else fprintf_s(stdout, "%s\n", to_byte_string(format).c_str()); } void Logger::log(const char* format) { std::lock_guard mtx(mx); if (custom_logger_fn) { cloggerfn(nullptr, format); return; } if (filelogger) { _wfopen_s(&log_file, logpath.c_str(), L"a+"); if (log_file) { fprintf_s(log_file, "%s\n", format); fclose(log_file); log_file = nullptr; } } else fprintf_s(stdout, "%s\n", format); } void Logger::error(const std::wstring& format) { std::lock_guard mtx(mx); if (custom_logger_fn) { cloggerfn(format.c_str(), nullptr); cerror_fn(format.c_str(), nullptr); return; } if (filelogger) { _wfopen_s(&log_file, logpath.c_str(), L"a+"); _wfopen_s(&error_file, errorpath.c_str(), L"a+"); if (log_file) { fprintf(log_file, "[ERROR]%s\n", to_byte_string(format).c_str()); fclose(log_file); log_file = nullptr; } if (error_file) { fprintf(error_file, "[ERROR]%s\n", to_byte_string(format).c_str()); fclose(error_file); error_file = nullptr; } } else fprintf(stdout, "[ERROR]%s\n", to_byte_string(format).c_str()); } void Logger::error(const char* format) { std::lock_guard mtx(mx); if (custom_logger_fn) { cloggerfn(nullptr, format); cerror_fn(nullptr, format); return; } if (filelogger) { _wfopen_s(&log_file, logpath.c_str(), L"a+"); _wfopen_s(&error_file, errorpath.c_str(), L"a+"); if (log_file) { fprintf(log_file, "[ERROR]%s\n", format); fclose(log_file); log_file = nullptr; } if (error_file) { fprintf(error_file, "[ERROR]%s\n", format); fclose(error_file); error_file = nullptr; } } else fprintf(stdout, "[ERROR]%s\n", format); } Logger& GetLogger() { return MoeVsLogger; } } ================================================ FILE: libsvc/Modules/src/Models/DiffSvc.cpp ================================================ #include "../../header/Models/DiffSvc.hpp" #include #include "../../header/InferTools/AvCodec/AvCodeResample.h" #include #include "../../header/InferTools/Sampler/MoeVSSamplerManager.hpp" #include "../../header/InferTools/F0Extractor/F0ExtractorManager.hpp" #include "../../header/Models/EnvManager.hpp" MoeVoiceStudioCoreHeader Ort::Session* GlobalVocoder = nullptr; void LoadVocoderModel(const std::wstring& VocoderPath) { GlobalVocoder = new Ort::Session(*moevsenv::GetGlobalMoeVSEnv().GetEnv(), VocoderPath.c_str(), *moevsenv::GetGlobalMoeVSEnv().GetSessionOptions()); } void UnLoadVocoderModel() { delete GlobalVocoder; GlobalVocoder = nullptr; } bool VocoderEnabled() { return GlobalVocoder; } Ort::Session* GetCurrentVocoder() { return GlobalVocoder; } void DiffusionSvc::Destory() { //AudioEncoder delete hubert; hubert = nullptr; //DiffusionModel delete encoder; //Encoder encoder = nullptr; delete denoise; //WaveNet denoise = nullptr; delete pred; //PndmNoisePredictor pred = nullptr; delete after; //AfterProcess after = nullptr; delete alpha; //AlphasCumpord alpha = nullptr; delete naive; //NaiveShallowDiffusion naive = nullptr; //SingleDiffusionModel delete diffSvc; diffSvc = nullptr; } DiffusionSvc::~DiffusionSvc() { logger.log(L"[Info] unloading DiffSvc Models"); Destory(); logger.log(L"[Info] DiffSvc Models unloaded"); } DiffusionSvc::DiffusionSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_): SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioDiffSingingVoiceConversion"); //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)") if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String") const auto _folder = to_wide_string(_Config["Folder"].GetString()); if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty") const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; const auto cluster_folder = GetCurrentFolder() + L"/Models/" + _folder; if (_Config["Hubert"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Hubert\" (Hubert Folder)") if (!_Config["Hubert"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Must Be String") const std::wstring HuPath = to_wide_string(_Config["Hubert"].GetString()); if (HuPath.empty()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Can Not Be Empty") std::map _PathDict; _PathDict["Cluster"] = cluster_folder; _PathDict["DiffHubert"] = GetCurrentFolder() + L"/hubert/" + HuPath + L".onnx"; if(_waccess((_path + L"_encoder.onnx").c_str(), 0) != -1) { _PathDict["Encoder"] = _path + L"_encoder.onnx"; _PathDict["DenoiseFn"] = _path + L"_denoise.onnx"; _PathDict["NoisePredictor"] = _path + L"_pred.onnx"; _PathDict["AfterProcess"] = _path + L"_after.onnx"; if (_waccess((_path + L"_alpha.onnx").c_str(), 0) != -1) _PathDict["Alphas"] = _path + L"_alpha.onnx"; } else _PathDict["DiffSvc"] = _path + L"_DiffSvc.onnx"; if (_waccess((_path + L"_naive.onnx").c_str(), 0) != -1) _PathDict["Naive"] = _path + L"_naive.onnx"; logger.log("[Model Loader] Prepeocess Complete!"); load(_PathDict, _Config, _ProgressCallback); } DiffusionSvc::DiffusionSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioDiffSingingVoiceConversion"); load(_PathDict, _Config, _ProgressCallback); } DiffusionSvc::DiffusionSvc(const Hparams& _Hps, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioDiffSingingVoiceConversion"); _samplingRate = max(_Hps.SamplingRate, 2000); melBins = max(_Hps.MelBins, 1); HopSize = max(_Hps.HopSize, 1); HiddenUnitKDims = max(_Hps.HiddenUnitKDims, 1); SpeakerCount = max(_Hps.SpeakerCount, 1); EnableVolume = _Hps.EnableVolume; EnableCharaMix = _Hps.EnableCharaMix; DiffSvcVersion = _Hps.TensorExtractor; Pndms = max(_Hps.Pndms, 1); SpecMax = _Hps.SpecMax; SpecMin = _Hps.SpecMin; MaxStep = max(_Hps.MaxStep, 1); _callback = _ProgressCallback; if (!_Hps.Cluster.Type.empty()) { ClusterCenterSize = _Hps.Cluster.ClusterCenterSize; try { Cluster = MoeVoiceStudioCluster::GetMoeVSCluster(_Hps.Cluster.Type, _Hps.Cluster.Path, HiddenUnitKDims, ClusterCenterSize); EnableCluster = true; } catch (std::exception& e) { logger.error(e.what()); EnableCluster = false; } } //LoadModels try { logger.log(L"[Info] loading DiffSvc Models"); hubert = new Ort::Session(*env, _Hps.HubertPath.c_str(), *session_options); if (!_Hps.DiffusionSvc.Encoder.empty()) { encoder = new Ort::Session(*env, _Hps.DiffusionSvc.Encoder.c_str(), *session_options); denoise = new Ort::Session(*env, _Hps.DiffusionSvc.Denoise.c_str(), *session_options); pred = new Ort::Session(*env, _Hps.DiffusionSvc.Pred.c_str(), *session_options); after = new Ort::Session(*env, _Hps.DiffusionSvc.After.c_str(), *session_options); if (!_Hps.DiffusionSvc.Alpha.empty()) alpha = new Ort::Session(*env, _Hps.DiffusionSvc.Alpha.c_str(), *session_options); } else diffSvc = new Ort::Session(*env, _Hps.DiffusionSvc.DiffSvc.c_str(), *session_options); if (!_Hps.DiffusionSvc.Naive.empty()) naive = new Ort::Session(*env, _Hps.DiffusionSvc.Naive.c_str(), *session_options); logger.log(L"[Info] DiffSvc Models loaded"); } catch (Ort::Exception& _exception) { Destory(); LibDLVoiceCodecThrow(_exception.what()) } MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others _others_param; _others_param.Memory = *memory_info; try { _TensorExtractor = GetTensorExtractor(DiffSvcVersion, 48000, _samplingRate, HopSize, EnableCharaMix, EnableVolume, HiddenUnitKDims, SpeakerCount, _others_param); } catch (std::exception& e) { Destory(); LibDLVoiceCodecThrow(e.what()) } } void DiffusionSvc::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback) { //Check SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)") if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64") logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); if (_Config["MelBins"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"MelBins\" (MelBins)") if (_Config["MelBins"].IsInt() || _Config["MelBins"].IsInt64()) melBins = _Config["MelBins"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"MelBins\" (MelBins) Must Be Int/Int64") if (!(_Config["Hop"].IsInt() || _Config["Hop"].IsInt64())) LibDLVoiceCodecThrow("[Error] Hop Must Be Int") HopSize = _Config["Hop"].GetInt(); if (HopSize < 1) LibDLVoiceCodecThrow("[Error] Hop Must > 0") if (!(_Config["HiddenSize"].IsInt() || _Config["HiddenSize"].IsInt64())) logger.log(L"[Warn] Missing Field \"HiddenSize\", Use Default Value (256)"); else HiddenUnitKDims = _Config["HiddenSize"].GetInt(); if (_Config["Characters"].IsArray()) SpeakerCount = (int64_t)_Config["Characters"].Size(); if (_Config["Volume"].IsBool()) EnableVolume = _Config["Volume"].GetBool(); else logger.log(L"[Warn] Missing Field \"Volume\", Use Default Value (False)"); if (!_Config["CharaMix"].IsBool()) logger.log(L"[Warn] Missing Field \"CharaMix\", Use Default Value (False)"); else EnableCharaMix = _Config["CharaMix"].GetBool(); if (!_Config["Diffusion"].IsBool()) logger.log(L"[Warn] Missing Field \"Diffusion\", Use Default Value (False)"); else if (_Config["Diffusion"].GetBool()) DiffSvcVersion = L"DiffusionSvc"; if (_Config["Pndm"].IsInt()) Pndms = _Config["Pndm"].GetInt(); if (_Config.HasMember("SpecMax") && _Config["SpecMax"].IsDouble()) SpecMax = _Config["SpecMax"].GetFloat(); else logger.log(L"[Warn] Missing Field \"SpecMax\", Use Default Value (2)"); if (_Config.HasMember("SpecMin") && _Config["SpecMin"].IsDouble()) SpecMin = _Config["SpecMin"].GetFloat(); else logger.log(L"[Warn] Missing Field \"SpecMin\", Use Default Value (-12)"); _callback = _ProgressCallback; if (_Config["Cluster"].IsString()) { const auto clus = to_wide_string(_Config["Cluster"].GetString()); if (!(_Config["KMeansLength"].IsInt() || _Config["KMeansLength"].IsInt64())) logger.log(L"[Warn] Missing Field \"KMeansLength\", Use Default Value (10000)"); else ClusterCenterSize = _Config["KMeansLength"].GetInt(); try { Cluster = MoeVoiceStudioCluster::GetMoeVSCluster(clus, _PathDict.at("Cluster"), HiddenUnitKDims, ClusterCenterSize); EnableCluster = true; } catch (std::exception& e) { logger.error(e.what()); EnableCluster = false; } } //LoadModels try { logger.log(L"[Info] loading DiffSvc Models"); hubert = new Ort::Session(*env, _PathDict.at("DiffHubert").c_str(), *session_options); if (_PathDict.find("Encoder")!= _PathDict.end() && _waccess(_PathDict.at("Encoder").c_str(), 0) != -1) { encoder = new Ort::Session(*env, _PathDict.at("Encoder").c_str(), *session_options); denoise = new Ort::Session(*env, _PathDict.at("DenoiseFn").c_str(), *session_options); pred = new Ort::Session(*env, _PathDict.at("NoisePredictor").c_str(), *session_options); after = new Ort::Session(*env, _PathDict.at("AfterProcess").c_str(), *session_options); if (_PathDict.find("Alphas") != _PathDict.end() && _waccess(_PathDict.at("Alphas").c_str(), 0) != -1) alpha = new Ort::Session(*env, _PathDict.at("Alphas").c_str(), *session_options); } else diffSvc = new Ort::Session(*env, _PathDict.at("DiffSvc").c_str(), *session_options); if (_PathDict.find("Naive") != _PathDict.end() && _waccess(_PathDict.at("Naive").c_str(), 0) != -1) naive = new Ort::Session(*env, _PathDict.at("Naive").c_str(), *session_options); logger.log(L"[Info] DiffSvc Models loaded"); } catch (Ort::Exception& _exception) { Destory(); LibDLVoiceCodecThrow(_exception.what()) } if (_Config["TensorExtractor"].IsString()) DiffSvcVersion = to_wide_string(_Config["TensorExtractor"].GetString()); if (_Config["MaxStep"].IsInt()) MaxStep = _Config["MaxStep"].GetInt(); MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others _others_param; _others_param.Memory = *memory_info; try { _TensorExtractor = GetTensorExtractor(DiffSvcVersion, 48000, _samplingRate, HopSize, EnableCharaMix, EnableVolume, HiddenUnitKDims, SpeakerCount, _others_param); } catch (std::exception& e) { Destory(); LibDLVoiceCodecThrow(e.what()) } } std::vector DiffusionSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Start!"); std::vector _data; size_t total_audio_size = 0; for (const auto& data_size : _Slice.Slices) total_audio_size += data_size.OrgLen; _data.reserve(size_t(double(total_audio_size) * 1.5)); auto speedup = (int64_t)_InferParams.Pndm; auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; if (speedup >= step) speedup = step / 5; if (speedup == 0) speedup = 1; const auto RealDiffSteps = step % speedup ? step / speedup + 1 : step / speedup; if (diffSvc) _callback(0, _Slice.Slices.size()); else _callback(0, _Slice.Slices.size() * RealDiffSteps); size_t process = 0; for (const auto& CurSlice : _Slice.Slices) { const auto InferDurTime = clock(); const auto CurRtn = SliceInference(CurSlice, _InferParams, process); _data.insert(_data.end(), CurRtn.data(), CurRtn.data() + CurRtn.size()); if (CurSlice.IsNotMute) logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Segment[" + std::to_wstring(process) + L"] Finished! Segment Use Time: " + std::to_wstring(clock() - InferDurTime) + L"ms, Segment Duration: " + std::to_wstring((size_t)CurSlice.OrgLen * 1000ull / _InferParams.SrcSamplingRate) + L"ms"); else { if (!diffSvc) { process += RealDiffSteps; _callback(process, _Slice.Slices.size() * RealDiffSteps); } logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Jump Empty Segment[" + std::to_wstring(process) + L"]!"); } if (diffSvc) _callback(++process, _Slice.Slices.size()); } logger.log(L"[Inferring] \"" + _Slice.Path + L"\" Finished"); return _data; } std::vector DiffusionSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); auto speedup = (int64_t)_InferParams.Pndm; auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; if (speedup >= step) speedup = step / 5; if (speedup == 0) speedup = 1; if (_Slice.IsNotMute) { auto RawWav = InferTools::InterpResample(_Slice.Audio, (int)(_InferParams.SrcSamplingRate), 16000, 32768.0f); const auto src_audio_length = RawWav.size(); bool NeedPadding = false; if (_cur_execution_provider == ExecutionProviders::CUDA && !diffSvc) { NeedPadding = RawWav.size() % 16000; const size_t WavPaddedSize = RawWav.size() / 16000 + 1; if (NeedPadding) RawWav.resize(WavPaddedSize * 16000, 0.f); } const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)RawWav.size() }; std::vector HubertInputTensors, HubertOutPuts; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RawWav.data(), RawWav.size(), HubertInputShape, 3)); try { HubertOutPuts = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } const auto HubertSize = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto HubertOutPutData = HubertOutPuts[0].GetTensorMutableData(); auto HubertOutPutShape = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetShape(); HubertInputTensors.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector srcHiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; const auto max_cluster_size = int64_t((size_t)HubertOutPutShape[1] * src_audio_length / RawWav.size()); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto pts = Cluster->find(srcHiddenUnits.data(), long(SpeakerIdx), max_cluster_size); for (int64_t indexs = 0; indexs < max_cluster_size * HiddenUnitKDims; ++indexs) srcHiddenUnits[indexs] = srcHiddenUnits[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } std::vector finaOut; std::vector DiffOut; if (diffSvc) { const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; const int64_t F0Shape[] = { 1, int64_t(_Slice.Audio.size() * _samplingRate / (int)(_InferParams.SrcSamplingRate) / HopSize) }; const int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t CharaEmbShape[] = { 1 }; int64_t speedData[] = { Pndms }; auto srcF0Data = InferTools::InterpFunc(_Slice.F0, long(_Slice.F0.size()), long(F0Shape[1])); for (auto& it : srcF0Data) it *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); auto InterpedF0 = MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::GetInterpedF0log(srcF0Data, true); auto alignment = MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::GetAligments(F0Shape[1], HubertLen); std::vector TensorsInp; int64_t Chara[] = { SpeakerIdx }; TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, srcHiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, alignment.data(), F0Shape[1], F0Shape, 2)); TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, Chara, 1, CharaEmbShape, 1)); TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), F0Shape[1], F0Shape, 2)); std::vector initial_noise(melBins * F0Shape[1], 0.0); long long noise_shape[4] = { 1,1,melBins,F0Shape[1] }; if (!naive) { for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4)); } else MoeVSNotImplementedError TensorsInp.emplace_back(Ort::Value::CreateTensor(*memory_info, speedData, 1, CharaEmbShape, 1)); try { DiffOut = diffSvc->Run(Ort::RunOptions{ nullptr }, DiffInput.data(), TensorsInp.data(), TensorsInp.size(), DiffOutput.data(), DiffOutput.size()); } catch (Ort::Exception& e2) { LibDLVoiceCodecThrow((std::string("Locate: Diff\n") + e2.what())) } Ort::Session* Vocoder = GlobalVocoder; if (_InferParams._VocoderModel) Vocoder = static_cast(_InferParams._VocoderModel); try { finaOut = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), DiffOut.data(), Vocoder->GetInputCount(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } } else { MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::InferParams _Inference_Params; _Inference_Params.AudioSize = _Slice.Audio.size(); _Inference_Params.Chara = SpeakerIdx; _Inference_Params.NoiseScale = _InferParams.NoiseScale; _Inference_Params.DDSPNoiseScale = _InferParams.DDSPNoiseScale; _Inference_Params.Seed = int(_InferParams.Seed); _Inference_Params.upKeys = _InferParams.Keys; MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Inputs InputTensors; if (_cur_execution_provider == ExecutionProviders::CUDA && NeedPadding) { auto CUDAF0 = _Slice.F0; auto CUDAVolume = _Slice.Volume; auto CUDASpeaker = _Slice.Speaker; const auto src_src_audio_length = _Slice.Audio.size(); const size_t WavPaddedSize = ((src_src_audio_length / (int)(_InferParams.SrcSamplingRate)) + 1) * (int)(_InferParams.SrcSamplingRate); const size_t AudioPadSize = WavPaddedSize - src_src_audio_length; const size_t PaddedF0Size = CUDAF0.size() + (CUDAF0.size() * AudioPadSize / src_src_audio_length); if (!CUDAF0.empty()) CUDAF0.resize(PaddedF0Size, 0.f); if (!CUDAVolume.empty()) CUDAVolume.resize(PaddedF0Size, 0.f); for (auto iSpeaker : CUDASpeaker) { if (!iSpeaker.empty()) iSpeaker.resize(PaddedF0Size, 0.f); } _Inference_Params.AudioSize = WavPaddedSize; InputTensors = _TensorExtractor->Extract(srcHiddenUnits, CUDAF0, CUDAVolume, CUDASpeaker, _Inference_Params); } else InputTensors = _TensorExtractor->Extract(srcHiddenUnits, _Slice.F0, _Slice.Volume, _Slice.Speaker, _Inference_Params); std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputTensors.InputNames, InputTensors.Tensor.data(), min(InputTensors.Tensor.size(), encoder->GetInputCount()), InputTensors.OutputNames, encoder->GetOutputCount()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } if (EncoderOut.size() == 1) EncoderOut.emplace_back(Ort::Value::CreateTensor(*memory_info, InputTensors.Data.F0.data(), InputTensors.Data.FrameShape[1], InputTensors.Data.FrameShape.data(), 2)); std::vector DenoiseInTensors; DenoiseInTensors.emplace_back(std::move(EncoderOut[0])); std::vector initial_noise(melBins * InputTensors.Data.FrameShape[1], 0.0); long long noise_shape[4] = { 1,1,melBins,InputTensors.Data.FrameShape[1] }; if (EncoderOut.size() == 3) DenoiseInTensors.emplace_back(std::move(EncoderOut[2])); else if (!naive) { for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; DenoiseInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4)); } else { std::vector NaiveOut; try { NaiveOut = naive->Run(Ort::RunOptions{ nullptr }, InputTensors.InputNames, InputTensors.Tensor.data(), min(InputTensors.Tensor.size(), naive->GetInputCount()), naiveOutput.data(), 1); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: naive\n") + e1.what())) } DenoiseInTensors.emplace_back(std::move(NaiveOut[0])); } auto PredOut = MoeVSSampler::GetMoeVSSampler((!alpha ? L"Pndm" : _InferParams.Sampler), alpha, denoise, pred, melBins, _callback, memory_info)->Sample(DenoiseInTensors, step, speedup, _InferParams.NoiseScale, _InferParams.Seed, _Process); try { DiffOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), PredOut.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } DiffOut.emplace_back(std::move(EncoderOut[1])); Ort::Session* Vocoder = GlobalVocoder; if (_InferParams._VocoderModel) Vocoder = static_cast(_InferParams._VocoderModel); try { finaOut = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), DiffOut.data(), Vocoder->GetInputCount(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } } auto DiffOutputAudioSize = finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); std::vector DiffPCMOutput(DiffOutputAudioSize); { auto DiffOutputAudioData = finaOut[0].GetTensorData(); auto OutputAudioData = DiffPCMOutput.data(); const auto OutputAudioEnd = OutputAudioData + DiffPCMOutput.size(); while (OutputAudioData != OutputAudioEnd) *(OutputAudioData++) = (int16_t)(Clamp(*(DiffOutputAudioData++)) * 32766.f); } const auto dstWavLen = (_Slice.OrgLen * int64_t(_samplingRate)) / (int)(_InferParams.SrcSamplingRate); DiffPCMOutput.resize(dstWavLen); return DiffPCMOutput; } const auto len = size_t(_Slice.OrgLen * int64_t(_samplingRate) / (int)(_InferParams.SrcSamplingRate)); return { len, 0i16, std::allocator() }; } std::vector DiffusionSvc::Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); std::vector _Lens = GetOpenFileNameMoeVS(); std::vector AudioFolders; for (auto& path : _Lens) { path = std::regex_replace(path, std::wregex(L"\\\\"), L"/"); auto PCMData = AudioPreprocess().codec(path, (int)(_InferParams.SrcSamplingRate)); auto SlicePos = SliceAudio(PCMData, _SlicerSettings); auto Audio = GetAudioSlice(PCMData, SlicePos, _SlicerSettings); Audio.Path = path; PreProcessAudio(Audio); std::vector _data = SliceInference(Audio, _InferParams); std::wstring OutFolder = GetCurrentFolder() + L"/Outputs/" + path.substr(path.rfind(L'/') + 1, path.rfind(L'.') - path.rfind(L'/') - 1); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; OutFolder += L"-Params-(-NoiseScale=" + std::to_wstring(_InferParams.NoiseScale) + L"-Speaker=" + (EnableCharaMix ? std::wstring(L"SpeakerMix") : std::to_wstring(SpeakerIdx)) + L"-Seed=" + std::to_wstring(_InferParams.Seed) + L"-Sampler=" + _InferParams.Sampler + L"-F0Method=" + _InferParams.F0Method + L")"; if (_waccess((OutFolder + L".wav").c_str(), 0) != -1) { for (size_t idx = 0; idx < 99999999; ++idx) if (_waccess((OutFolder + L" (" + std::to_wstring(idx) + L").wav").c_str(), 0) == -1) { OutFolder += L" (" + std::to_wstring(idx) + L").wav"; break; } } else OutFolder += L".wav"; AudioFolders.emplace_back(OutFolder); InferTools::Wav::WritePCMData(_samplingRate, 1, _data, OutFolder); } return AudioFolders; } std::vector DiffusionSvc::InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); if (diffSvc || DiffSvcVersion != L"DiffusionSvc") return PCMData; auto hubertin = InferTools::InterpResample(PCMData, srcSr, 16000); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); const int64_t inputShape[3] = { 1i64,1i64,(int64_t)hubertin.size() }; std::vector inputTensorshu; inputTensorshu.emplace_back(Ort::Value::CreateTensor(*memory_info, hubertin.data(), hubertin.size(), inputShape, 3)); std::vector hubertOut; auto speedup = (int64_t)_InferParams.Pndm; auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; if (speedup >= step) speedup = step / 5; if (speedup == 0) speedup = 1; const auto RealDiffSteps = step % speedup ? step / speedup + 1 : step / speedup; _callback(0, RealDiffSteps); try { hubertOut = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), inputTensorshu.data(), inputTensorshu.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } const auto HubertSize = hubertOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto HubertOutPutData = hubertOut[0].GetTensorMutableData(); const auto HubertOutPutShape = hubertOut[0].GetTensorTypeAndShapeInfo().GetShape(); inputTensorshu.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector HiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto clus_size = HubertOutPutShape[1]; const auto pts = Cluster->find(HiddenUnits.data(), long(SpeakerIdx), clus_size); for (size_t indexs = 0; indexs < HiddenUnits.size(); ++indexs) HiddenUnits[indexs] = HiddenUnits[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; const int64_t F0Shape[] = { 1, int64_t(PCMData.size() / HopSize) }; const int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t CharaEmbShape[] = { 1 }; const int64_t CharaMixShape[] = { F0Shape[1], SpeakerCount }; const auto F0Extractor = MoeVSF0Extractor::GetF0Extractor(_InferParams.F0Method, _samplingRate, HopSize); auto F0Data = F0Extractor->ExtractF0(PCMData, PCMData.size() / HopSize); for (auto& ifo : F0Data) ifo *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); F0Data = _TensorExtractor->GetInterpedF0(InferTools::InterpFunc(F0Data, long(F0Data.size()), long(F0Shape[1]))); std::vector Alignment = _TensorExtractor->GetAligments(F0Shape[1], HubertLen); int64_t CharaEmb[] = { SpeakerIdx }; std::vector EncoderTensors; EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Alignment.data(), F0Shape[1], F0Shape, 2 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, F0Data.data(), F0Shape[1], F0Shape, 2 )); std::vector InputNamesEncoder; std::vector Volume, SpkMap; if (EnableVolume) { InputNamesEncoder = { "hubert", "mel2ph", "f0", "volume", "spk_mix" }; Volume = ExtractVolume(PCMData, HopSize); if (abs(int64_t(Volume.size()) - int64_t(F0Data.size())) > 3) Volume = InferTools::InterpFunc(ExtractVolume(PCMData, HopSize), long(Volume.size()), long(F0Shape[1])); else Volume.resize(F0Data.size(), 0.f); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Volume.data(), F0Shape[1], F0Shape, 2 )); } else InputNamesEncoder = { "hubert", "mel2ph", "f0", "spk_mix" }; if (EnableCharaMix) { SpkMap = _TensorExtractor->GetCurrectSpkMixData(std::vector>(), F0Shape[1], SpeakerIdx); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, SpkMap.data(), SpkMap.size(), CharaMixShape, 2 )); } else { EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, CharaEmb, 1, CharaEmbShape, 1 )); } const std::vector OutputNamesEncoder = { "mel_pred", "f0_pred", "init_noise" }; std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputNamesEncoder.data(), EncoderTensors.data(), min(EncoderTensors.size(), encoder->GetInputCount()), OutputNamesEncoder.data(), encoder->GetOutputCount()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } if (EncoderOut.size() == 1) EncoderOut.emplace_back(Ort::Value::CreateTensor(*memory_info, F0Data.data(), F0Shape[1], F0Shape, 2)); std::vector DenoiseInTensors; DenoiseInTensors.emplace_back(std::move(EncoderOut[0])); std::vector initial_noise(melBins * F0Shape[1], 0.0); long long noise_shape[4] = { 1,1,melBins,F0Shape[1] }; if (EncoderOut.size() == 3) DenoiseInTensors.emplace_back(std::move(EncoderOut[2])); else if (!naive) { for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; DenoiseInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4)); } else { std::vector NaiveOut; try { NaiveOut = naive->Run(Ort::RunOptions{ nullptr }, InputNamesEncoder.data(), EncoderTensors.data(), min(EncoderTensors.size(), naive->GetInputCount()), naiveOutput.data(), 1); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: naive\n") + e1.what())) } DenoiseInTensors.emplace_back(std::move(NaiveOut[0])); } size_t process = 0; auto PredOut = MoeVSSampler::GetMoeVSSampler((!alpha ? L"Pndm" : _InferParams.Sampler), alpha, denoise, pred, melBins, _callback, memory_info)->Sample(DenoiseInTensors, step, speedup, _InferParams.NoiseScale, _InferParams.Seed, process); std::vector DiffOut, finaOut; try { DiffOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), PredOut.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } DiffOut.emplace_back(std::move(EncoderOut[1])); Ort::Session* Vocoder = GlobalVocoder; if (_InferParams._VocoderModel) Vocoder = static_cast(_InferParams._VocoderModel); try { finaOut = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), DiffOut.data(), Vocoder->GetInputCount(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } auto DiffOutputAudioSize = finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); std::vector DiffPCMOutput(DiffOutputAudioSize); { auto DiffOutputAudioData = finaOut[0].GetTensorData(); auto OutputAudioData = DiffPCMOutput.data(); const auto OutputAudioEnd = OutputAudioData + DiffPCMOutput.size(); while (OutputAudioData != OutputAudioEnd) *(OutputAudioData++) = (int16_t)(Clamp(*(DiffOutputAudioData++)) * 32766.f); } return DiffPCMOutput; } void DiffusionSvc::NormMel(std::vector& MelSpec) const { for (auto& it : MelSpec) it = (it - SpecMin) / (SpecMax - SpecMin) * 2 - 1; } std::vector DiffusionSvc::ShallowDiffusionInference( std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize ) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); if (diffSvc || DiffSvcVersion != L"DiffusionSvc") LibDLVoiceCodecThrow("ShallowDiffusion Only Support DiffusionSvc Model") auto speedup = (int64_t)_InferParams.Pndm; auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; if (speedup >= step) speedup = step / 5; if (speedup == 0) speedup = 1; std::vector InputNamesEncoder; const auto _Mel_Size = _Mel.second; std::vector HubertInputTensors, HubertOutputTensors; const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)_16KAudioHubert.size() }; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _16KAudioHubert.data(), _16KAudioHubert.size(), HubertInputShape, 3)); try { HubertOutputTensors = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; const auto HubertLength = HubertOutputTensors[0].GetTensorTypeAndShapeInfo().GetShape()[1]; const int64_t FrameShape[] = { 1, _Mel_Size }; const int64_t CharaMixShape[] = { _Mel_Size, SpeakerCount }; constexpr int64_t OneShape[] = { 1 }; int64_t CharaEmb[] = { SpeakerIdx }; auto Alignment = _TensorExtractor->GetAligments(_Mel_Size, HubertLength); Alignment.resize(FrameShape[1]); auto F0Data = InferTools::InterpFunc(_SrcF0, long(_SrcF0.size()), long(FrameShape[1])); std::vector Volume, SpkMap; std::vector EncoderTensors; EncoderTensors.emplace_back(std::move(HubertOutputTensors[0])); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Alignment.data(), FrameShape[1], FrameShape, 2 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, F0Data.data(), FrameShape[1], FrameShape, 2 )); if (EnableVolume) { InputNamesEncoder = { "hubert", "mel2ph", "f0", "volume", "spk_mix" }; Volume = InferTools::InterpFunc(_SrcVolume, long(_SrcVolume.size()), long(FrameShape[1])); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Volume.data(), FrameShape[1], FrameShape, 2 )); } else InputNamesEncoder = { "hubert", "mel2ph", "f0", "spk_mix" }; if (EnableCharaMix) { SpkMap = _TensorExtractor->GetCurrectSpkMixData(_SrcSpeakerMap, FrameShape[1], CharaEmb[0]); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, SpkMap.data(), SpkMap.size(), CharaMixShape, 2 )); } else { EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, CharaEmb, 1, OneShape, 1 )); } const std::vector OutputNamesEncoder = { "mel_pred" }; std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputNamesEncoder.data(), EncoderTensors.data(), min(EncoderTensors.size(), encoder->GetInputCount()), OutputNamesEncoder.data(), 1); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } std::vector DenoiseInTensors; DenoiseInTensors.emplace_back(std::move(EncoderOut[0])); long long noise_shape[4] = { 1,1,melBins,_Mel_Size }; NormMel(_Mel.first); /*std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); std::vector initial_noise(melBins * _Mel_Size, 0.0); for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; DenoiseInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4));*/ DenoiseInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _Mel.first.data(), _Mel.first.size(), noise_shape, 4)); auto PredOut = MoeVSSampler::GetMoeVSSampler((!alpha ? L"Pndm" : _InferParams.Sampler), alpha, denoise, pred, melBins, _callback, memory_info)->Sample(DenoiseInTensors, step, speedup, _InferParams.NoiseScale, _InferParams.Seed, Process); std::vector DiffOut, finaOut; try { DiffOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), PredOut.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } DiffOut.emplace_back(std::move(EncoderTensors[2])); Ort::Session* Vocoder = GlobalVocoder; if (_InferParams._VocoderModel) Vocoder = static_cast(_InferParams._VocoderModel); try { finaOut = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), DiffOut.data(), Vocoder->GetInputCount(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } auto DiffOutputAudioSize = finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); std::vector DiffPCMOutput(DiffOutputAudioSize); { auto DiffOutputAudioData = finaOut[0].GetTensorData(); auto OutputAudioData = DiffPCMOutput.data(); const auto OutputAudioEnd = OutputAudioData + DiffPCMOutput.size(); while (OutputAudioData != OutputAudioEnd) *(OutputAudioData++) = (int16_t)(Clamp(*(DiffOutputAudioData++)) * 32766.f); } const auto dstWavLen = (SrcSize * int64_t(_samplingRate)) / (int)(_InferParams.SrcSamplingRate); DiffPCMOutput.resize(dstWavLen); return DiffPCMOutput; } void StaticNormMel(std::vector& MelSpec, float SpecMin = -12, float SpecMax = 2) { for (auto& it : MelSpec) it = (it - SpecMin) / (SpecMax - SpecMin) * 2 - 1; } std::vector VocoderInfer(std::vector& Mel, std::vector& F0, int64_t MelBins, int64_t MelSize, const Ort::MemoryInfo* Mem, void* _VocoderModel) { const int64_t MelShape[] = { 1i64,MelBins,MelSize }; const int64_t FrameShape[] = { 1,MelSize }; std::vector Tensors; Tensors.emplace_back(Ort::Value::CreateTensor( *Mem, Mel.data(), Mel.size(), MelShape, 3) ); Tensors.emplace_back(Ort::Value::CreateTensor( *Mem, F0.data(), FrameShape[1], FrameShape, 2) ); const std::vector nsfInput = { "c", "f0" }; const std::vector nsfOutput = { "audio" }; Ort::Session* Vocoder = GlobalVocoder; if (_VocoderModel) Vocoder = static_cast(_VocoderModel); Tensors = Vocoder->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), Tensors.data(), Vocoder->GetInputCount(), nsfOutput.data(), nsfOutput.size()); const auto AudioSize = Tensors[0].GetTensorTypeAndShapeInfo().GetShape()[2]; std::vector Audio(AudioSize, 0); for (int64_t it = 0; it < AudioSize; it++) Audio[it] = static_cast(DiffusionSvc::Clamp(Tensors[0].GetTensorData()[it]) * 32766.0f); return Audio; } MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/src/Models/EnvManager.cpp ================================================ #include "../../header/Models/EnvManager.hpp" #ifdef _WIN32 #ifdef MOEVSDMLPROVIDER #include #endif #endif #include #include "../../header/InferTools/F0Extractor/NetF0Predictors.hpp" #include "../../header/Modules.hpp" MoeVoiceStudioCoreEnvManagerHeader bool SingleOrtApiEnv = false; bool SingleOrtApiEnvEnabled() { return SingleOrtApiEnv; } void UseSingleOrtApiEnv(bool _cond) { SingleOrtApiEnv = _cond; } const char* logger_id = "libdlvoicecodec"; void MoeVSOrtLoggingFn(void* param, OrtLoggingLevel severity, const char* category, const char* logid, const char* code_location, const char* message) { std::string ort_message = "["; ort_message += category; ort_message += "; In "; ort_message += code_location; ort_message += "; By"; ort_message += logger_id; ort_message += "] "; ort_message += message; logger.log(ort_message.c_str()); } void MoeVoiceStudioEnv::Destory() { MoeVSF0Extractor::EmptyCache(); logger.log(L"[Info] Removing Env & Release Memory"); delete GlobalOrtSessionOptions; delete GlobalOrtEnv; delete GlobalOrtMemoryInfo; GlobalOrtSessionOptions = nullptr; GlobalOrtEnv = nullptr; GlobalOrtMemoryInfo = nullptr; if (cuda_option_v2) Ort::GetApi().ReleaseCUDAProviderOptions(cuda_option_v2); cuda_option_v2 = nullptr; logger.log(L"[Info] Complete!"); } void MoeVoiceStudioEnv::Load(unsigned ThreadCount, unsigned DeviceID, unsigned Provider) { if (((Provider != CurProvider) || (Provider == 0 && ThreadCount != CurThreadCount) || ((Provider == 1 || Provider == 2) && DeviceID != CurDeviceID)) && (MoeVSModuleManager::GetUnionSvcModel() || MoeVSModuleManager::GetVitsSvcModel() || MoeVSModuleManager::VocoderEnabled())) LibDLVoiceCodecThrow("A Model Has Been Loaded, You Cannot Change Env When A Model Has Been Loaded"); try { if (Provider != CurProvider) Create(ThreadCount, DeviceID, Provider); if (Provider == 0 && ThreadCount != CurThreadCount) Create(ThreadCount, DeviceID, Provider); if ((Provider == 1 || Provider == 2) && DeviceID != CurDeviceID) Create(ThreadCount, DeviceID, Provider); CurProvider = Provider; } catch(std::exception& e) { Destory(); CurThreadCount = unsigned(-1); CurDeviceID = unsigned(-1); CurProvider = unsigned(-1); logger.log(to_wide_string(e.what())); LibDLVoiceCodecThrow(e.what()); } } void MoeVoiceStudioEnv::Create(unsigned ThreadCount_, unsigned DeviceID_, unsigned ExecutionProvider_) { Destory(); logger.log(L"[Info] Creating Env"); switch (ExecutionProvider_) { case 1: { const auto AvailableProviders = Ort::GetAvailableProviders(); bool ret = true; for (const auto& it : AvailableProviders) if (it.find("CUDA") != std::string::npos) ret = false; if (ret) LibDLVoiceCodecThrow("CUDA Provider Not Found"); GlobalOrtSessionOptions = new Ort::SessionOptions; #ifdef MoeVSCUDAProviderV1 OrtCUDAProviderOptions cuda_option; cuda_option.device_id = int(DeviceID_); cuda_option.do_copy_in_default_stream = false; GlobalOrtSessionOptions->AppendExecutionProvider_CUDA(cuda_option); #else const OrtApi& ortApi = Ort::GetApi(); if (cuda_option_v2) ortApi.ReleaseCUDAProviderOptions(cuda_option_v2); ortApi.CreateCUDAProviderOptions(&cuda_option_v2); const std::vector keys{ "device_id", "gpu_mem_limit", "arena_extend_strategy", "cudnn_conv_algo_search", "do_copy_in_default_stream", "cudnn_conv_use_max_workspace", "cudnn_conv1d_pad_to_nc1d", "enable_cuda_graph", "enable_skip_layer_norm_strict_mode" }; const std::vector values{ std::to_string(DeviceID_).c_str(), "2147483648", "kNextPowerOfTwo", "EXHAUSTIVE", "1", "1", "1", "0", "0" }; ortApi.UpdateCUDAProviderOptions(cuda_option_v2, keys.data(), values.data(), keys.size()); GlobalOrtSessionOptions->AppendExecutionProvider_CUDA_V2(*cuda_option_v2); //ortApi.ReleaseCUDAProviderOptions(cuda_option_v2); #endif GlobalOrtEnv = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, logger_id, MoeVSOrtLoggingFn, nullptr); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtSessionOptions->SetIntraOpNumThreads((int)std::thread::hardware_concurrency()); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); CurDeviceID = DeviceID_; break; } #ifdef MOEVSDMLPROVIDER case 2: { const auto AvailableProviders = Ort::GetAvailableProviders(); std::string ret; for (const auto& it : AvailableProviders) if (it.find("Dml") != std::string::npos) ret = it; if (ret.empty()) LibDLVoiceCodecThrow("DML Provider Not Found"); const OrtApi& ortApi = Ort::GetApi(); const OrtDmlApi* ortDmlApi = nullptr; ortApi.GetExecutionProviderApi("DML", ORT_API_VERSION, reinterpret_cast(&ortDmlApi)); Ort::ThreadingOptions threading_options; threading_options.SetGlobalInterOpNumThreads((int)std::thread::hardware_concurrency()); GlobalOrtEnv = new Ort::Env(threading_options, MoeVSOrtLoggingFn, nullptr, ORT_LOGGING_LEVEL_WARNING, logger_id); GlobalOrtEnv->DisableTelemetryEvents(); GlobalOrtSessionOptions = new Ort::SessionOptions; ortDmlApi->SessionOptionsAppendExecutionProvider_DML(*GlobalOrtSessionOptions, int(DeviceID_)); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtSessionOptions->DisablePerSessionThreads(); GlobalOrtSessionOptions->SetExecutionMode(ORT_SEQUENTIAL); GlobalOrtSessionOptions->DisableMemPattern(); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU)); CurDeviceID = DeviceID_; break; } #endif default: { if (ThreadCount_ == 0) ThreadCount_ = std::thread::hardware_concurrency(); GlobalOrtSessionOptions = new Ort::SessionOptions; GlobalOrtEnv = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, logger_id, MoeVSOrtLoggingFn, nullptr); GlobalOrtSessionOptions->SetIntraOpNumThreads(static_cast(ThreadCount_)); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); CurThreadCount = ThreadCount_; break; } } logger.log(L"[Info] Env Created"); } bool MoeVoiceStudioEnv::IsEnabled() const { return GlobalOrtEnv && GlobalOrtMemoryInfo && GlobalOrtSessionOptions; } MoeVoiceStudioEnv GlobalMoeVSEnv; MoeVoiceStudioEnv& GetGlobalMoeVSEnv() { return GlobalMoeVSEnv; } MoeVoiceStudioCoreEnvManagerEnd ================================================ FILE: libsvc/Modules/src/Models/ModelBase.cpp ================================================ #include "../../header/Models/ModelBase.hpp" #include MoeVoiceStudioCoreHeader MoeVoiceStudioModule::MoeVoiceStudioModule(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) { if (moevsenv::SingleOrtApiEnvEnabled()) { OrtApiEnv.Load(ThreadCount_, DeviceID_, (unsigned)ExecutionProvider_); _cur_execution_provider = ExecutionProvider_; env = OrtApiEnv.GetEnv(); memory_info = OrtApiEnv.GetMemoryInfo(); session_options = OrtApiEnv.GetSessionOptions(); } else { moevsenv::GetGlobalMoeVSEnv().Load(ThreadCount_, DeviceID_, (unsigned)ExecutionProvider_); _cur_execution_provider = ExecutionProvider_; env = moevsenv::GetGlobalMoeVSEnv().GetEnv(); memory_info = moevsenv::GetGlobalMoeVSEnv().GetMemoryInfo(); session_options = moevsenv::GetGlobalMoeVSEnv().GetSessionOptions(); } } MoeVoiceStudioModule::~MoeVoiceStudioModule() { env = nullptr; memory_info = nullptr; session_options = nullptr; } std::vector MoeVoiceStudioModule::CutLens(const std::wstring& input) { std::vector _Lens; std::wstring _tmpLen; for (const auto& chari : input) { if ((chari == L'\n') || (chari == L'\r')) { if (!_tmpLen.empty()) { _Lens.push_back(_tmpLen); _tmpLen = L""; } } else { _tmpLen += chari; } } return _Lens; } std::vector MoeVoiceStudioModule::GetOpenFileNameMoeVS() { constexpr long MaxPath = 8000; std::vector OFNLIST; #ifdef WIN32 std::vector szFileName(MaxPath); std::vector szTitleName(MaxPath); OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lpstrFile = szFileName.data(); ofn.nMaxFile = MaxPath; ofn.lpstrFileTitle = szTitleName.data(); ofn.nMaxFileTitle = MaxPath; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = nullptr; constexpr TCHAR szFilter[] = TEXT("Audio (*.wav;*.mp3;*.ogg;*.flac;*.aac)\0*.wav;*.mp3;*.ogg;*.flac;*.aac\0"); ofn.lpstrFilter = szFilter; ofn.lpstrTitle = nullptr; ofn.lpstrDefExt = TEXT("wav"); ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER; if (GetOpenFileName(&ofn)) { auto filePtr = szFileName.data(); std::wstring preFix = filePtr; filePtr += preFix.length() + 1; if (!*filePtr) OFNLIST.emplace_back(preFix); else { preFix += L'\\'; while (*filePtr != 0) { std::wstring thisPath(filePtr); OFNLIST.emplace_back(preFix + thisPath); filePtr += thisPath.length() + 1; } } } if(OFNLIST.empty()) LibDLVoiceCodecThrow("Please Select Files"); return OFNLIST; #else #endif } std::vector MoeVoiceStudioModule::Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { MoeVSNotImplementedError; } /* int OnnxModule::InsertMessageToEmptyEditBox(std::wstring& _inputLens) { #ifdef WIN32 std::vector szFileName(MaxPath); std::vector szTitleName(MaxPath); OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lpstrFile = szFileName.data(); ofn.nMaxFile = MaxPath; ofn.lpstrFileTitle = szTitleName.data(); ofn.nMaxFileTitle = MaxPath; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = nullptr; constexpr TCHAR szFilter[] = TEXT("Audio (*.wav;*.mp3;*.ogg;*.flac;*.aac)\0*.wav;*.mp3;*.ogg;*.flac;*.aac\0"); ofn.lpstrFilter = szFilter; ofn.lpstrTitle = nullptr; ofn.lpstrDefExt = TEXT("wav"); ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER; if (GetOpenFileName(&ofn)) { auto filePtr = szFileName.data(); std::wstring preFix = filePtr; filePtr += preFix.length() + 1; if (!*filePtr) _inputLens = preFix; else { preFix += L'\\'; while (*filePtr != 0) { std::wstring thisPath(filePtr); _inputLens += preFix + thisPath + L'\n'; filePtr += thisPath.length() + 1; } } } else return -2; return 0; #else #endif } */ /* void OnnxModule::ChangeDevice(Device _dev) { if (_dev == device_) return; device_ = _dev; delete session_options; delete env; delete memory_info; env = nullptr; session_options = nullptr; memory_info = nullptr; switch (_dev) { case Device::CUDA: { const auto AvailableProviders = Ort::GetAvailableProviders(); bool ret = true; for (const auto& it : AvailableProviders) if (it.find("CUDA") != std::string::npos) ret = false; if (ret) LibDLVoiceCodecThrow("CUDA Provider Not Found"); OrtCUDAProviderOptions cuda_option; cuda_option.device_id = int(__MoeVSGPUID); session_options = new Ort::SessionOptions; env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); session_options->AppendExecutionProvider_CUDA(cuda_option); session_options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); session_options->SetIntraOpNumThreads(1); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); break; } #ifdef MOEVSDMLPROVIDER case Device::DML: { const auto AvailableProviders = Ort::GetAvailableProviders(); std::string ret; for (const auto& it : AvailableProviders) if (it.find("Dml") != std::string::npos) ret = it; if (ret.empty()) LibDLVoiceCodecThrow("DML Provider Not Found"); const OrtApi& ortApi = Ort::GetApi(); const OrtDmlApi* ortDmlApi = nullptr; ortApi.GetExecutionProviderApi("DML", ORT_API_VERSION, reinterpret_cast(&ortDmlApi)); const Ort::ThreadingOptions threadingOptions; env = new Ort::Env(threadingOptions, ORT_LOGGING_LEVEL_VERBOSE, ""); env->DisableTelemetryEvents(); session_options = new Ort::SessionOptions; ortDmlApi->SessionOptionsAppendExecutionProvider_DML(*session_options, int(__MoeVSGPUID)); session_options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); session_options->DisablePerSessionThreads(); session_options->SetExecutionMode(ORT_SEQUENTIAL); session_options->DisableMemPattern(); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU)); break; } #endif default: { session_options = new Ort::SessionOptions; env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); session_options->SetIntraOpNumThreads(static_cast(__MoeVSNumThreads)); session_options->SetGraphOptimizationLevel(ORT_ENABLE_ALL); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); break; } } } */ MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/src/Models/MoeVSProject.cpp ================================================ #include "../../header/Models/MoeVSProject.hpp" #include "../../header/InferTools/inferTools.hpp" #include namespace MoeVSProjectSpace { MoeVSProject::MoeVSProject(const std::wstring& _path) { FileWrapper project_file(_path.c_str(), L"rb"); if (!project_file.IsOpen()) LibDLVoiceCodecThrow("File Doesn't Exists"); fseek(project_file, 0, SEEK_SET); if (fread(&moevs_proj_header_, 1, sizeof(Header), project_file) != sizeof(Header)) LibDLVoiceCodecThrow("Unexpected EOF"); if (!(moevs_proj_header_.ChunkSymbol[0] == 'M' && moevs_proj_header_.ChunkSymbol[1] == 'O' && moevs_proj_header_.ChunkSymbol[2] == 'E' && moevs_proj_header_.ChunkSymbol[3] == 'V' && moevs_proj_header_.ChunkSymbol[4] == 'S' && moevs_proj_header_.ChunkSymbol[5] == 'P' && moevs_proj_header_.ChunkSymbol[6] == 'R' && moevs_proj_header_.ChunkSymbol[7] == 'J')) LibDLVoiceCodecThrow("Unrecognized File"); if (moevs_proj_header_.DataHeaderAmount == 0) LibDLVoiceCodecThrow("Empty Project"); data_pos_ = std::vector(moevs_proj_header_.DataHeaderAmount); if (fread(data_pos_.data(), 1, sizeof(size_type) * (moevs_proj_header_.DataHeaderAmount), project_file) != sizeof(size_type) * (moevs_proj_header_.DataHeaderAmount)) LibDLVoiceCodecThrow("Unexpected EOF"); data_chunk_begin_ = sizeof(Header) + sizeof(size_type) * (moevs_proj_header_.DataHeaderAmount); size_type _n_bytes = 0; const size_type _data_begin = data_chunk_begin_; fseek(project_file, long(_data_begin), SEEK_SET); for (const auto& _pos_index : data_pos_) { Data _datas; //Header if (fread(&_datas.Header, 1, sizeof(DataHeader), project_file) != sizeof(DataHeader)) LibDLVoiceCodecThrow("Unexpected EOF"); if (!(_datas.Header.ChunkSymbol[0] == 'D' && _datas.Header.ChunkSymbol[1] == 'A' && _datas.Header.ChunkSymbol[2] == 'T' && _datas.Header.ChunkSymbol[3] == 'A')) LibDLVoiceCodecThrow("Unrecognized File"); _datas.ParamData.Slices.resize(_datas.Header.OrgLenSize); //Audio if (_datas.Header.OrgAudioOffsetPosSize != 0) { _datas.Offset.OrgAudio = std::vector(_datas.Header.OrgAudioOffsetPosSize); _n_bytes = sizeof(size_type) * _datas.Header.OrgAudioOffsetPosSize; if (fread(_datas.Offset.OrgAudio.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); size_t _data_idx = 0; for (const auto& j : _datas.Offset.OrgAudio) { if (!j) continue; std::vector hs_vector(j); _n_bytes = sizeof(int16_t) * j; if (fread(hs_vector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); _datas.ParamData.Slices[_data_idx].Audio = std::move(hs_vector); _data_idx += 1; } } //F0 if (_datas.Header.F0OffsetPosSize != 0) { _datas.Offset.F0 = std::vector(_datas.Header.F0OffsetPosSize); _n_bytes = sizeof(size_type) * _datas.Header.F0OffsetPosSize; if (fread(_datas.Offset.F0.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); size_t _data_idx = 0; for (const auto& j : _datas.Offset.F0) { if (!j) continue; std::vector f0_vector(j); _n_bytes = sizeof(float) * j; if (fread(f0_vector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); _datas.ParamData.Slices[_data_idx].F0 = std::move(f0_vector); _data_idx += 1; } } //Volume if (_datas.Header.VolumeOffsetPosSize != 0) { _datas.Offset.Volume = std::vector(_datas.Header.VolumeOffsetPosSize); _n_bytes = sizeof(size_type) * _datas.Header.VolumeOffsetPosSize; if (fread(_datas.Offset.Volume.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); size_t _data_idx = 0; for (const auto& j : _datas.Offset.Volume) { if (!j) continue; std::vector Volume_vector(j); _n_bytes = sizeof(float) * j; if (fread(Volume_vector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); _datas.ParamData.Slices[_data_idx].Volume = std::move(Volume_vector); _data_idx += 1; } } //ChrarcterMix if (_datas.Header.CharacterOffsetPosSize != 0) { _datas.Offset.Speaker = std::vector(_datas.Header.CharacterOffsetPosSize); _n_bytes = sizeof(size_type) * _datas.Header.CharacterOffsetPosSize; if (fread(_datas.Offset.Speaker.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); size_t _data_idx = 0; for (const auto& j : _datas.Offset.Speaker) { if (!j) continue; size_type NSpeaker = 0; if (fread(&NSpeaker, 1, sizeof(size_type), project_file) != sizeof(size_type)) LibDLVoiceCodecThrow("Unexpected EOF"); if (!NSpeaker) continue; std::vector Speaker_vector(j); _n_bytes = sizeof(float) * j; if (fread(Speaker_vector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); std::vector> SpkVec; if (!Speaker_vector.empty()) { const auto frames = Speaker_vector.size() / NSpeaker; for (size_t idxs = 0; idxs < NSpeaker; ++idxs) SpkVec.emplace_back(Speaker_vector.data() + idxs * frames, Speaker_vector.data() + (idxs + 1) * frames); } _datas.ParamData.Slices[_data_idx].Speaker = std::move(SpkVec); _data_idx += 1; } } //OrgLen if (_datas.Header.OrgLenSize != 0) { std::vector OrgLen(_datas.Header.OrgLenSize); _n_bytes = sizeof(long) * _datas.Header.OrgLenSize; if (fread(OrgLen.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); for (size_t _data_idx = 0; _data_idx < OrgLen.size(); ++_data_idx) _datas.ParamData.Slices[_data_idx].OrgLen = OrgLen[_data_idx]; } //Symbol if (_datas.Header.SymbolSize != 0) { std::vector BooleanVector(_datas.Header.SymbolSize); _n_bytes = _datas.Header.SymbolSize; if (fread(BooleanVector.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); for (size_t _data_idx = 0; _data_idx < BooleanVector.size(); ++_data_idx) _datas.ParamData.Slices[_data_idx].IsNotMute = BooleanVector[_data_idx]; } //path if (_datas.Header.PathSize != 0) { std::vector PathStr(_datas.Header.PathSize); _n_bytes = _datas.Header.PathSize; if (fread(PathStr.data(), 1, _n_bytes, project_file) != _n_bytes) LibDLVoiceCodecThrow("Unexpected EOF"); _datas.ParamData.Path = to_wide_string(PathStr.data()); } data_.emplace_back(std::move(_datas)); } } MoeVSProject::MoeVSProject(const std::vector& _params) { moevs_proj_header_.DataHeaderAmount = size_type(_params.size()); data_chunk_begin_ = sizeof(Header) + sizeof(size_type) * (moevs_proj_header_.DataHeaderAmount); data_pos_.push_back(0); size_type _offset = 0; for (const auto& i : _params) { Data _data; _data.ParamData = i; for (const auto& SliceData : i.Slices) { _data.Offset.OrgAudio.push_back(SliceData.Audio.size()); _data.Offset.F0.push_back(SliceData.F0.size()); _data.Offset.Volume.push_back(SliceData.Volume.size()); size_t size__ = 0; for (auto& Speaker : SliceData.Speaker) { size__ += Speaker.size(); } _data.Offset.Speaker.push_back(size__); } _data.Header.OrgAudioOffsetPosSize = _data.Offset.OrgAudio.size(); _data.Header.F0OffsetPosSize = _data.Offset.F0.size(); _data.Header.VolumeOffsetPosSize = _data.Offset.Volume.size(); _data.Header.CharacterOffsetPosSize = _data.Offset.Speaker.size(); _data.Header.OrgLenSize = i.Slices.size(); _data.Header.SymbolSize = i.Slices.size(); const std::string bytePath = to_byte_string(i.Path); _data.Header.PathSize = bytePath.length() + 1; _offset += _data.Size(); data_pos_.push_back(_offset); data_.emplace_back(std::move(_data)); } data_pos_.pop_back(); } void MoeVSProject::Write(const std::wstring& _path) const { FILE* project_file = nullptr; _wfopen_s(&project_file, _path.c_str(), L"wb"); if (!project_file) LibDLVoiceCodecThrow("Cannot Create File"); fwrite(&moevs_proj_header_, 1, sizeof(Header), project_file); fwrite(data_pos_.data(), 1, data_pos_.size() * sizeof(size_type), project_file); for (const auto& i : data_) { fwrite(&i.Header, 1, sizeof(DataHeader), project_file); fwrite(i.Offset.OrgAudio.data(), 1, sizeof(size_type) * i.Offset.OrgAudio.size(), project_file); for (const auto& orgaudio : i.ParamData.Slices) fwrite(orgaudio.Audio.data(), 1, orgaudio.Audio.size() * sizeof(int16_t), project_file); fwrite(i.Offset.F0.data(), 1, sizeof(size_type) * i.Offset.F0.size(), project_file); for (const auto& f0 : i.ParamData.Slices) fwrite(f0.F0.data(), 1, f0.F0.size() * sizeof(float), project_file); if (i.Header.VolumeOffsetPosSize != 0) { fwrite(i.Offset.Volume.data(), 1, sizeof(size_type) * i.Offset.Volume.size(), project_file); for (const auto& volume : i.ParamData.Slices) fwrite(volume.Volume.data(), 1, volume.Volume.size() * sizeof(float), project_file); } if (i.Header.CharacterOffsetPosSize != 0) { fwrite(i.Offset.Speaker.data(), 1, sizeof(size_type) * i.Offset.Speaker.size(), project_file); for (const auto& Speaker : i.ParamData.Slices) { if (Speaker.Speaker.empty()) continue; const size_type NSPK = Speaker.Speaker.size(); fwrite(&NSPK, 1, sizeof(size_type), project_file); for (const auto& Spkk : Speaker.Speaker) fwrite(Spkk.data(), 1, Spkk.size() * sizeof(float), project_file); } } assert(i.ParamData.Slices.size() == i.Header.OrgLenSize); std::vector CurOrgLen(i.Header.OrgLenSize); for (size_t index = 0; index < i.ParamData.Slices.size(); ++index) CurOrgLen[index] = i.ParamData.Slices[index].OrgLen; fwrite(CurOrgLen.data(), 1, sizeof(long) * CurOrgLen.size(), project_file); assert(i.ParamData.Slices.size() == i.Header.SymbolSize); std::vector BooleanVector(i.Header.SymbolSize); for (size_t index = 0; index < i.ParamData.Slices.size(); ++index) BooleanVector[index] = i.ParamData.Slices[index].IsNotMute ? 1 : 0; fwrite(BooleanVector.data(), 1, i.Header.SymbolSize, project_file); const std::string bytePath = to_byte_string(i.ParamData.Path); fwrite(bytePath.data(), 1, i.Header.PathSize, project_file); } fclose(project_file); } std::wstring MoeVSTTSToken::Serialization() const { if (Text.empty()) return L"\t\t\t{ }"; std::wstring rtn = L"\t\t\t{\n"; rtn += L"\t\t\t\t\"Text\": \"" + Text + L"\",\n"; rtn += L"\t\t\t\t\"Phonemes\": " + wstring_vector_to_string(Phonemes) + L",\n"; rtn += L"\t\t\t\t\"Tones\": " + vector_to_string(Tones) + L",\n"; rtn += L"\t\t\t\t\"Durations\": " + vector_to_string(Durations) + L",\n"; rtn += L"\t\t\t\t\"Language\": " + string_vector_to_string(Language) + L"\n\t\t\t}"; return rtn; } MoeVSTTSToken::MoeVSTTSToken(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams) { if (_JsonDocument.HasMember("Text") && _JsonDocument["Text"].IsString() && !_JsonDocument["Text"].Empty()) Text = to_wide_string(_JsonDocument["Text"].GetString()); else LibDLVoiceCodecThrow("Field \"Text\" Should Not Be Empty") if (_JsonDocument.HasMember("Phonemes") && _JsonDocument["Phonemes"].IsArray()) for (const auto& j : _JsonDocument["Phonemes"].GetArray()) Phonemes.emplace_back(j.IsString() ? to_wide_string(j.GetString()) : L"[UNK]"); if (_JsonDocument.HasMember("Tones") && _JsonDocument["Tones"].IsArray()) for (const auto& j : _JsonDocument["Tones"].GetArray()) Tones.emplace_back(j.IsInt() ? j.GetInt() : 0); if (_JsonDocument.HasMember("Durations") && _JsonDocument["Durations"].IsArray()) for (const auto& j : _JsonDocument["Durations"].GetArray()) Durations.emplace_back(j.IsInt() ? j.GetInt() : 0); if (_JsonDocument.HasMember("Language") && _JsonDocument["Language"].IsArray()) { const auto LanguageArr = _JsonDocument["Language"].GetArray(); if (!LanguageArr.empty() && LanguageArr[0].IsString()) for (const auto& j : LanguageArr) Language.emplace_back(j.GetString()); } } std::wstring MoeVSTTSSeq::Serialization() const { if (TextSeq.empty()) return L""; std::wstring rtn = L"\t{\n"; rtn += L"\t\t\"TextSeq\": \"" + TextSeq + L"\",\n"; rtn += L"\t\t\"SlicedTokens\": [\n"; for (const auto& iter : SlicedTokens) rtn += iter.Serialization() + L",\n"; if (!SlicedTokens.empty()) rtn.erase(rtn.end() - 2); rtn += L"\t\t],\n"; rtn += L"\t\t\"SpeakerMix\": " + vector_to_string(SpeakerMix) + L",\n"; rtn += L"\t\t\"EmotionPrompt\": " + wstring_vector_to_string(EmotionPrompt) + L",\n"; rtn += L"\t\t\"NoiseScale\": " + std::to_wstring(NoiseScale) + L",\n"; rtn += L"\t\t\"LengthScale\": " + std::to_wstring(LengthScale) + L",\n"; rtn += L"\t\t\"DurationPredictorNoiseScale\": " + std::to_wstring(DurationPredictorNoiseScale) + L",\n"; rtn += L"\t\t\"FactorDpSdp\": " + std::to_wstring(FactorDpSdp) + L",\n"; rtn += L"\t\t\"GateThreshold\": " + std::to_wstring(GateThreshold) + L",\n"; rtn += L"\t\t\"MaxDecodeStep\": " + std::to_wstring(MaxDecodeStep) + L",\n"; rtn += L"\t\t\"Seed\": " + std::to_wstring(Seed) + L",\n"; rtn += L"\t\t\"SpeakerName\": \"" + SpeakerName + L"\",\n"; rtn += L"\t\t\"RestTime\": " + std::to_wstring(RestTime) + L",\n"; rtn += L"\t\t\"PlaceHolderSymbol\": \"" + PlaceHolderSymbol + L"\",\n"; rtn += L"\t\t\"LanguageSymbol\": \"" + to_wide_string(LanguageSymbol) + L"\",\n"; rtn += L"\t\t\"G2PAdditionalInfo\": \"" + AdditionalInfo + L"\"\n\t}"; return rtn; } MoeVSTTSSeq::MoeVSTTSSeq(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams) { if (_JsonDocument.HasMember("LanguageSymbol") && _JsonDocument["LanguageSymbol"].IsString() && !_JsonDocument["LanguageSymbol"].Empty()) LanguageSymbol = _JsonDocument["LanguageSymbol"].GetString(); else LanguageSymbol = _InitParams.LanguageSymbol; if (_JsonDocument.HasMember("G2PAdditionalInfo") && _JsonDocument["G2PAdditionalInfo"].IsString() && !_JsonDocument["G2PAdditionalInfo"].Empty()) AdditionalInfo = to_wide_string(_JsonDocument["G2PAdditionalInfo"].GetString()); else AdditionalInfo = _InitParams.AdditionalInfo; if (_JsonDocument.HasMember("PlaceHolderSymbol") && _JsonDocument["PlaceHolderSymbol"].IsString() && !_JsonDocument["PlaceHolderSymbol"].Empty()) PlaceHolderSymbol = to_wide_string(_JsonDocument["PlaceHolderSymbol"].GetString()); else PlaceHolderSymbol = _InitParams.PlaceHolderSymbol; if (_JsonDocument.HasMember("TextSeq") && _JsonDocument["TextSeq"].IsString() && !_JsonDocument["TextSeq"].Empty()) TextSeq = to_wide_string(_JsonDocument["TextSeq"].GetString()); else LibDLVoiceCodecThrow("Field \"TextSeq\" Should Not Be Empty") if (_JsonDocument.HasMember("SlicedTokens") && _JsonDocument["SlicedTokens"].IsArray()) { const auto TokensArrayObject = _JsonDocument["SlicedTokens"].GetArray(); for (const auto& iter : TokensArrayObject) SlicedTokens.emplace_back(iter, _InitParams); } if (_JsonDocument.HasMember("SpeakerMix") && _JsonDocument["SpeakerMix"].IsArray()) for (const auto& j : _JsonDocument["SpeakerMix"].GetArray()) SpeakerMix.emplace_back(j.IsFloat() ? j.GetFloat() : 0.f); else SpeakerMix = _InitParams.SpeakerMix; if (_JsonDocument.HasMember("EmotionPrompt") && _JsonDocument["EmotionPrompt"].IsArray()) for (const auto& j : _JsonDocument["EmotionPrompt"].GetArray()) EmotionPrompt.emplace_back(j.IsString() ? to_wide_string(j.GetString()) : std::wstring()); else EmotionPrompt = _InitParams.EmotionPrompt; if (_JsonDocument.HasMember("NoiseScale") && _JsonDocument["NoiseScale"].IsFloat()) NoiseScale = _JsonDocument["NoiseScale"].GetFloat(); else NoiseScale = _InitParams.NoiseScale; if (_JsonDocument.HasMember("LengthScale") && _JsonDocument["LengthScale"].IsFloat()) LengthScale = _JsonDocument["LengthScale"].GetFloat(); else LengthScale = _InitParams.LengthScale; if (_JsonDocument.HasMember("RestTime") && _JsonDocument["RestTime"].IsFloat()) RestTime = _JsonDocument["RestTime"].GetFloat(); else RestTime = _InitParams.RestTime; if (_JsonDocument.HasMember("DurationPredictorNoiseScale") && _JsonDocument["DurationPredictorNoiseScale"].IsFloat()) DurationPredictorNoiseScale = _JsonDocument["DurationPredictorNoiseScale"].GetFloat(); else DurationPredictorNoiseScale = _InitParams.DurationPredictorNoiseScale; if (_JsonDocument.HasMember("FactorDpSdp") && _JsonDocument["FactorDpSdp"].IsFloat()) FactorDpSdp = _JsonDocument["FactorDpSdp"].GetFloat(); else FactorDpSdp = _InitParams.FactorDpSdp; if (_JsonDocument.HasMember("GateThreshold") && _JsonDocument["GateThreshold"].IsFloat()) GateThreshold = _JsonDocument["GateThreshold"].GetFloat(); else GateThreshold = _InitParams.GateThreshold; if (_JsonDocument.HasMember("MaxDecodeStep") && _JsonDocument["MaxDecodeStep"].IsFloat()) MaxDecodeStep = _JsonDocument["MaxDecodeStep"].GetInt(); else MaxDecodeStep = _InitParams.MaxDecodeStep; if (_JsonDocument.HasMember("Seed") && _JsonDocument["Seed"].IsInt()) Seed = _JsonDocument["Seed"].GetInt(); else Seed = _InitParams.Seed; if (_JsonDocument.HasMember("SpeakerName") && _JsonDocument["SpeakerName"].IsString()) SpeakerName = to_wide_string(_JsonDocument["SpeakerName"].GetString()); else SpeakerName = _InitParams.SpeakerName; if (MaxDecodeStep < 2000) MaxDecodeStep = 2000; if (MaxDecodeStep > 20000) MaxDecodeStep = 20000; if (GateThreshold > 0.90f) GateThreshold = 0.90f; if (GateThreshold < 0.2f) GateThreshold = 0.2f; if (FactorDpSdp > 1.f) FactorDpSdp = 1.f; if (FactorDpSdp < 0.f) FactorDpSdp = 0.f; if (NoiseScale > 10.f) NoiseScale = 10.f; if (NoiseScale < 0.f) NoiseScale = 0.f; if (DurationPredictorNoiseScale > 10.f) DurationPredictorNoiseScale = 10.f; if (DurationPredictorNoiseScale < 0.f) DurationPredictorNoiseScale = 0.f; if (RestTime > 30.f) RestTime = 30.f; if (LengthScale > 10.f) LengthScale = 10.f; if (LengthScale < 0.1f) LengthScale = 0.1f; } bool MoeVSTTSSeq::operator==(const MoeVSTTSSeq& right) const { return Serialization() == right.Serialization(); } } ================================================ FILE: libsvc/Modules/src/Models/ReflowSvc.cpp ================================================ #include "../../header/Models/ReflowSvc.hpp" #include "../../header/Models/DiffSvc.hpp" #include "../../header/InferTools/AvCodec/AvCodeResample.h" #include "../../header/InferTools/Sampler/MoeVSSamplerManager.hpp" #include "../../header/InferTools/F0Extractor/F0ExtractorManager.hpp" #include #include MoeVoiceStudioCoreHeader void ReflowSvc::Destory() { //AudioEncoder delete hubert; hubert = nullptr; //ReflowSvcModel delete encoder; //Encoder encoder = nullptr; delete velocity; //WaveNet velocity = nullptr; delete after; //AfterProcess after = nullptr; } ReflowSvc::~ReflowSvc() { logger.log(L"[Info] unloading ReflowSvc Models"); Destory(); logger.log(L"[Info] ReflowSvc Models unloaded"); } ReflowSvc::ReflowSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_): SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioReflowSingingVoiceConversion"); //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)") if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String") const auto _folder = to_wide_string(_Config["Folder"].GetString()); if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty") const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; const auto cluster_folder = GetCurrentFolder() + L"/Models/" + _folder; if (_Config["Hubert"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Hubert\" (Hubert Folder)") if (!_Config["Hubert"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Must Be String") const std::wstring HuPath = to_wide_string(_Config["Hubert"].GetString()); if (HuPath.empty()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Can Not Be Empty") std::map _PathDict; _PathDict["Cluster"] = cluster_folder; _PathDict["Hubert"] = GetCurrentFolder() + L"/hubert/" + HuPath + L".onnx"; _PathDict["Encoder"] = _path + L"_encoder.onnx"; _PathDict["VelocityFn"] = _path + L"_velocity.onnx"; _PathDict["AfterProcess"] = _path + L"_after.onnx"; logger.log("[Model Loader] Prepeocess Complete!"); load(_PathDict, _Config, _ProgressCallback); } ReflowSvc::ReflowSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioReflowSingingVoiceConversion"); load(_PathDict, _Config, _ProgressCallback); } ReflowSvc::ReflowSvc(const Hparams& _Hps, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioReflowSingingVoiceConversion"); _samplingRate = max(_Hps.SamplingRate, 2000); melBins = max(_Hps.MelBins, 1); HopSize = max(_Hps.HopSize, 1); HiddenUnitKDims = max(_Hps.HiddenUnitKDims, 1); SpeakerCount = max(_Hps.SpeakerCount, 1); EnableVolume = _Hps.EnableVolume; EnableCharaMix = _Hps.EnableCharaMix; ReflowSvcVersion = _Hps.TensorExtractor; SpecMax = _Hps.SpecMax; SpecMin = _Hps.SpecMin; MaxStep = max(_Hps.MaxStep, 1); Scale = _Hps.Scale; VaeMode = _Hps.VaeMode; _callback = _ProgressCallback; if (!_Hps.Cluster.Type.empty()) { ClusterCenterSize = _Hps.Cluster.ClusterCenterSize; try { Cluster = MoeVoiceStudioCluster::GetMoeVSCluster(_Hps.Cluster.Type, _Hps.Cluster.Path, HiddenUnitKDims, ClusterCenterSize); EnableCluster = true; } catch (std::exception& e) { logger.error(e.what()); EnableCluster = false; } } //LoadModels try { logger.log(L"[Info] loading ReflowSvc Models"); hubert = new Ort::Session(*env, _Hps.HubertPath.c_str(), *session_options); encoder = new Ort::Session(*env, _Hps.ReflowSvc.Encoder.c_str(), *session_options); velocity = new Ort::Session(*env, _Hps.ReflowSvc.VelocityFn.c_str(), *session_options); after = new Ort::Session(*env, _Hps.ReflowSvc.After.c_str(), *session_options); logger.log(L"[Info] ReflowSvc Models loaded"); } catch (Ort::Exception& _exception) { Destory(); LibDLVoiceCodecThrow(_exception.what()) } MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others _others_param; _others_param.Memory = *memory_info; try { _TensorExtractor = GetTensorExtractor(ReflowSvcVersion, 48000, _samplingRate, HopSize, EnableCharaMix, EnableVolume, HiddenUnitKDims, SpeakerCount, _others_param); } catch (std::exception& e) { Destory(); LibDLVoiceCodecThrow(e.what()) } } void ReflowSvc::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback) { //Check SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)") if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64") logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); if (_Config["MelBins"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"MelBins\" (MelBins)") if (_Config["MelBins"].IsInt() || _Config["MelBins"].IsInt64()) melBins = _Config["MelBins"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"MelBins\" (MelBins) Must Be Int/Int64") if (!(_Config["Hop"].IsInt() || _Config["Hop"].IsInt64())) LibDLVoiceCodecThrow("[Error] Hop Must Be Int") HopSize = _Config["Hop"].GetInt(); if (HopSize < 1) LibDLVoiceCodecThrow("[Error] Hop Must > 0") if (!(_Config["HiddenSize"].IsInt() || _Config["HiddenSize"].IsInt64())) logger.log(L"[Warn] Missing Field \"HiddenSize\", Use Default Value (256)"); else HiddenUnitKDims = _Config["HiddenSize"].GetInt(); if (!_Config["Scale"].IsFloat()) logger.log(L"[Warn] Missing Field \"Scale\", Use Default Value (1000.f)"); else Scale = _Config["Scale"].GetFloat(); if (_Config["Characters"].IsArray()) SpeakerCount = (int64_t)_Config["Characters"].Size(); if (_Config["Volume"].IsBool()) EnableVolume = _Config["Volume"].GetBool(); else logger.log(L"[Warn] Missing Field \"Volume\", Use Default Value (False)"); if (!_Config["CharaMix"].IsBool()) logger.log(L"[Warn] Missing Field \"CharaMix\", Use Default Value (False)"); else EnableCharaMix = _Config["CharaMix"].GetBool(); if (!_Config["VaeMode"].IsBool()) logger.log(L"[Warn] Missing Field \"VaeMode\", Use Default Value (True)"); else VaeMode = _Config["VaeMode"].GetBool(); if (_Config.HasMember("SpecMax") && _Config["SpecMax"].IsDouble()) SpecMax = _Config["SpecMax"].GetFloat(); else logger.log(L"[Warn] Missing Field \"SpecMax\", Use Default Value (2)"); if (_Config.HasMember("SpecMin") && _Config["SpecMin"].IsDouble()) SpecMin = _Config["SpecMin"].GetFloat(); else logger.log(L"[Warn] Missing Field \"SpecMin\", Use Default Value (-12)"); _callback = _ProgressCallback; if (_Config["Cluster"].IsString()) { const auto clus = to_wide_string(_Config["Cluster"].GetString()); if (!(_Config["KMeansLength"].IsInt() || _Config["KMeansLength"].IsInt64())) logger.log(L"[Warn] Missing Field \"KMeansLength\", Use Default Value (10000)"); else ClusterCenterSize = _Config["KMeansLength"].GetInt(); try { Cluster = MoeVoiceStudioCluster::GetMoeVSCluster(clus, _PathDict.at("Cluster"), HiddenUnitKDims, ClusterCenterSize); EnableCluster = true; } catch (std::exception& e) { logger.error(e.what()); EnableCluster = false; } } //LoadModels try { logger.log(L"[Info] loading ReflowSvc Models"); hubert = new Ort::Session(*env, _PathDict.at("Hubert").c_str(), *session_options); encoder = new Ort::Session(*env, _PathDict.at("Encoder").c_str(), *session_options); velocity = new Ort::Session(*env, _PathDict.at("VelocityFn").c_str(), *session_options); after = new Ort::Session(*env, _PathDict.at("AfterProcess").c_str(), *session_options); logger.log(L"[Info] ReflowSvc Models loaded"); } catch (Ort::Exception& _exception) { Destory(); LibDLVoiceCodecThrow(_exception.what()) } if (_Config["TensorExtractor"].IsString()) ReflowSvcVersion = to_wide_string(_Config["TensorExtractor"].GetString()); if (_Config["MaxStep"].IsInt()) MaxStep = _Config["MaxStep"].GetInt(); MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others _others_param; _others_param.Memory = *memory_info; try { _TensorExtractor = GetTensorExtractor(ReflowSvcVersion, 48000, _samplingRate, HopSize, EnableCharaMix, EnableVolume, HiddenUnitKDims, SpeakerCount, _others_param); } catch (std::exception& e) { Destory(); LibDLVoiceCodecThrow(e.what()) } } std::vector ReflowSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Start!"); std::vector _data; size_t total_audio_size = 0; for (const auto& data_size : _Slice.Slices) total_audio_size += data_size.OrgLen; _data.reserve(size_t(double(total_audio_size) * 1.5)); auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; const auto RealSteps = step; _callback(0, _Slice.Slices.size() * RealSteps); size_t process = 0; for (const auto& CurSlice : _Slice.Slices) { const auto InferDurTime = clock(); const auto CurRtn = SliceInference(CurSlice, _InferParams, process); _data.insert(_data.end(), CurRtn.data(), CurRtn.data() + CurRtn.size()); if (CurSlice.IsNotMute) logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Segment[" + std::to_wstring(process) + L"] Finished! Segment Use Time: " + std::to_wstring(clock() - InferDurTime) + L"ms, Segment Duration: " + std::to_wstring((size_t)CurSlice.OrgLen * 1000ull / _InferParams.SrcSamplingRate) + L"ms"); else { process += RealSteps; _callback(process, _Slice.Slices.size() * RealSteps); logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Jump Empty Segment[" + std::to_wstring(process) + L"]!"); } } logger.log(L"[Inferring] \"" + _Slice.Path + L"\" Finished"); return _data; } std::vector ReflowSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; if (_Slice.IsNotMute) { auto RawWav = InferTools::InterpResample(_Slice.Audio, (int)(_InferParams.SrcSamplingRate), 16000, 32768.0f); const auto src_audio_length = RawWav.size(); bool NeedPadding = false; if (_cur_execution_provider == ExecutionProviders::CUDA) { NeedPadding = RawWav.size() % 16000; const size_t WavPaddedSize = RawWav.size() / 16000 + 1; if (NeedPadding) RawWav.resize(WavPaddedSize * 16000, 0.f); } const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)RawWav.size() }; std::vector HubertInputTensors, HubertOutPuts; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RawWav.data(), RawWav.size(), HubertInputShape, 3)); try { HubertOutPuts = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } const auto HubertSize = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto HubertOutPutData = HubertOutPuts[0].GetTensorMutableData(); auto HubertOutPutShape = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetShape(); HubertInputTensors.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector srcHiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; const auto max_cluster_size = int64_t((size_t)HubertOutPutShape[1] * src_audio_length / RawWav.size()); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto pts = Cluster->find(srcHiddenUnits.data(), long(SpeakerIdx), max_cluster_size); for (int64_t indexs = 0; indexs < max_cluster_size * HiddenUnitKDims; ++indexs) srcHiddenUnits[indexs] = srcHiddenUnits[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } std::vector finaOut; std::vector ReflowOut; MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::InferParams _Inference_Params; _Inference_Params.AudioSize = _Slice.Audio.size(); _Inference_Params.Chara = SpeakerIdx; _Inference_Params.NoiseScale = _InferParams.NoiseScale; _Inference_Params.DDSPNoiseScale = _InferParams.DDSPNoiseScale; _Inference_Params.Seed = int(_InferParams.Seed); _Inference_Params.upKeys = _InferParams.Keys; MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Inputs InputTensors; if (_cur_execution_provider == ExecutionProviders::CUDA && NeedPadding) { auto CUDAF0 = _Slice.F0; auto CUDAVolume = _Slice.Volume; auto CUDASpeaker = _Slice.Speaker; const auto src_src_audio_length = _Slice.Audio.size(); const size_t WavPaddedSize = ((src_src_audio_length / (int)(_InferParams.SrcSamplingRate)) + 1) * (int)(_InferParams.SrcSamplingRate); const size_t AudioPadSize = WavPaddedSize - src_src_audio_length; const size_t PaddedF0Size = CUDAF0.size() + (CUDAF0.size() * AudioPadSize / src_src_audio_length); if (!CUDAF0.empty()) CUDAF0.resize(PaddedF0Size, 0.f); if (!CUDAVolume.empty()) CUDAVolume.resize(PaddedF0Size, 0.f); for (auto iSpeaker : CUDASpeaker) { if (!iSpeaker.empty()) iSpeaker.resize(PaddedF0Size, 0.f); } _Inference_Params.AudioSize = WavPaddedSize; InputTensors = _TensorExtractor->Extract(srcHiddenUnits, CUDAF0, CUDAVolume, CUDASpeaker, _Inference_Params); } else InputTensors = _TensorExtractor->Extract(srcHiddenUnits, _Slice.F0, _Slice.Volume, _Slice.Speaker, _Inference_Params); std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputTensors.InputNames, InputTensors.Tensor.data(), min(InputTensors.Tensor.size(), encoder->GetInputCount()), OutputNamesEncoder.data(), encoder->GetOutputCount()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } std::vector SamplerInTensors; std::vector initial_noise(melBins * InputTensors.Data.FrameShape[1], 0.0); long long noise_shape[4] = { 1,1,melBins,InputTensors.Data.FrameShape[1] }; const auto x_size = EncoderOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); float t_end = max(min(1.f, _InferParams.TEnd), 0.002f); float t_start = max(min(_InferParams.TBegin, t_end - 0.001f), 0.f); if(x_size != 1) { auto x_it = EncoderOut[0].GetTensorMutableData(); auto x_end = EncoderOut[0].GetTensorMutableData() + x_size; while (x_it != x_end) { (*(x_it++) *= t_start) += ((t_end - t_start) * normal(gen) * _InferParams.NoiseScale); } SamplerInTensors.emplace_back(std::move(EncoderOut[0])); } else { for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; SamplerInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4)); } float Time[] = { t_start }; int64_t OneShape[] = { 1 }; SamplerInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Time, 1, OneShape, 1)); SamplerInTensors.emplace_back(std::move(EncoderOut[1])); const auto dt = (t_end - t_start) / float(step); auto PredOut = MoeVSSampler::GetMoeVSReflowSampler(_InferParams.ReflowSampler, velocity, melBins, _callback, memory_info)->Sample(SamplerInTensors, step, dt, Scale, _Process); try { ReflowOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), afterInput.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } ReflowOut.emplace_back(std::move(EncoderOut[2])); try { finaOut = GetCurrentVocoder()->Run(Ort::RunOptions{nullptr}, nsfInput.data(), ReflowOut.data(), GetCurrentVocoder()->GetInputCount(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } auto DiffOutputAudioSize = finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); std::vector DiffPCMOutput(DiffOutputAudioSize); { auto DiffOutputAudioData = finaOut[0].GetTensorData(); auto OutputAudioData = DiffPCMOutput.data(); const auto OutputAudioEnd = OutputAudioData + DiffPCMOutput.size(); while (OutputAudioData != OutputAudioEnd) *(OutputAudioData++) = (int16_t)(Clamp(*(DiffOutputAudioData++)) * 32766.f); } const auto dstWavLen = (_Slice.OrgLen * int64_t(_samplingRate)) / (int)(_InferParams.SrcSamplingRate); DiffPCMOutput.resize(dstWavLen); return DiffPCMOutput; } const auto len = size_t(_Slice.OrgLen * int64_t(_samplingRate) / (int)(_InferParams.SrcSamplingRate)); return { len, 0i16, std::allocator() }; } std::vector ReflowSvc::Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); std::vector _Lens = GetOpenFileNameMoeVS(); std::vector AudioFolders; for (auto& path : _Lens) { path = std::regex_replace(path, std::wregex(L"\\\\"), L"/"); auto PCMData = AudioPreprocess().codec(path, (int)(_InferParams.SrcSamplingRate)); auto SlicePos = SliceAudio(PCMData, _SlicerSettings); auto Audio = GetAudioSlice(PCMData, SlicePos, _SlicerSettings); Audio.Path = path; PreProcessAudio(Audio); std::vector _data = SliceInference(Audio, _InferParams); std::wstring OutFolder = GetCurrentFolder() + L"/Outputs/" + path.substr(path.rfind(L'/') + 1, path.rfind(L'.') - path.rfind(L'/') - 1); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; OutFolder += L"-Params-(-NoiseScale=" + std::to_wstring(_InferParams.NoiseScale) + L"-Speaker=" + (EnableCharaMix ? std::wstring(L"SpeakerMix") : std::to_wstring(SpeakerIdx)) + L"-Seed=" + std::to_wstring(_InferParams.Seed) + L"-Sampler=" + _InferParams.Sampler + L"-F0Method=" + _InferParams.F0Method + L")"; if (_waccess((OutFolder + L".wav").c_str(), 0) != -1) { for (size_t idx = 0; idx < 99999999; ++idx) if (_waccess((OutFolder + L" (" + std::to_wstring(idx) + L").wav").c_str(), 0) == -1) { OutFolder += L" (" + std::to_wstring(idx) + L").wav"; break; } } else OutFolder += L".wav"; AudioFolders.emplace_back(OutFolder); InferTools::Wav::WritePCMData(_samplingRate, 1, _data, OutFolder); } return AudioFolders; } std::vector ReflowSvc::InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; auto hubertin = InferTools::InterpResample(PCMData, srcSr, 16000); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); const int64_t inputShape[3] = { 1i64,1i64,(int64_t)hubertin.size() }; std::vector inputTensorshu; inputTensorshu.emplace_back(Ort::Value::CreateTensor(*memory_info, hubertin.data(), hubertin.size(), inputShape, 3)); std::vector hubertOut; const auto RealSteps = step; _callback(0, RealSteps); try { hubertOut = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), inputTensorshu.data(), inputTensorshu.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } const auto HubertSize = hubertOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto HubertOutPutData = hubertOut[0].GetTensorMutableData(); const auto HubertOutPutShape = hubertOut[0].GetTensorTypeAndShapeInfo().GetShape(); inputTensorshu.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector HiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto clus_size = HubertOutPutShape[1]; const auto pts = Cluster->find(HiddenUnits.data(), long(SpeakerIdx), clus_size); for (size_t indexs = 0; indexs < HiddenUnits.size(); ++indexs) HiddenUnits[indexs] = HiddenUnits[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; const int64_t F0Shape[] = { 1, int64_t(PCMData.size() / HopSize) }; const int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t CharaEmbShape[] = { 1 }; const int64_t CharaMixShape[] = { F0Shape[1], SpeakerCount }; const auto F0Extractor = MoeVSF0Extractor::GetF0Extractor(_InferParams.F0Method, _samplingRate, HopSize); auto F0Data = F0Extractor->ExtractF0(PCMData, PCMData.size() / HopSize); for (auto& ifo : F0Data) ifo *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); F0Data = _TensorExtractor->GetInterpedF0(InferTools::InterpFunc(F0Data, long(F0Data.size()), long(F0Shape[1]))); std::vector Alignment = _TensorExtractor->GetAligments(F0Shape[1], HubertLen); int64_t CharaEmb[] = { SpeakerIdx }; std::vector EncoderTensors; EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Alignment.data(), F0Shape[1], F0Shape, 2 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, F0Data.data(), F0Shape[1], F0Shape, 2 )); std::vector InputNamesEncoder; std::vector Volume, SpkMap; if (EnableVolume) { InputNamesEncoder = { "hubert", "mel2ph", "f0", "volume", "spk_mix" }; Volume = ExtractVolume(PCMData, HopSize); if (abs(int64_t(Volume.size()) - int64_t(F0Data.size())) > 3) Volume = InferTools::InterpFunc(ExtractVolume(PCMData, HopSize), long(Volume.size()), long(F0Shape[1])); else Volume.resize(F0Data.size(), 0.f); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Volume.data(), F0Shape[1], F0Shape, 2 )); } else InputNamesEncoder = { "hubert", "mel2ph", "f0", "spk_mix" }; if (EnableCharaMix) { SpkMap = _TensorExtractor->GetCurrectSpkMixData(std::vector>(), F0Shape[1], SpeakerIdx); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, SpkMap.data(), SpkMap.size(), CharaMixShape, 2 )); } else { EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, CharaEmb, 1, CharaEmbShape, 1 )); } std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputNamesEncoder.data(), EncoderTensors.data(), min(EncoderTensors.size(), encoder->GetInputCount()), OutputNamesEncoder.data(), encoder->GetOutputCount()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } size_t _Process = 0; std::vector SamplerInTensors; std::vector initial_noise(melBins * F0Shape[1], 0.0); long long noise_shape[4] = { 1,1,melBins,F0Shape[1] }; const auto x_size = EncoderOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); float t_end = max(min(1.f, _InferParams.TEnd), 0.002f); float t_start = max(min(_InferParams.TBegin, t_end - 0.001f), 0.f); if (x_size != 1) { auto x_it = EncoderOut[0].GetTensorMutableData(); auto x_end = EncoderOut[0].GetTensorMutableData() + x_size; while (x_it != x_end) { (*(x_it++) *= t_start) += ((t_end - t_start) * normal(gen) * _InferParams.NoiseScale); } SamplerInTensors.emplace_back(std::move(EncoderOut[0])); } else { for (auto& it : initial_noise) it = normal(gen) * _InferParams.NoiseScale; SamplerInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, initial_noise.data(), initial_noise.size(), noise_shape, 4)); } float Time[] = { t_start }; int64_t OneShape[] = { 1 }; SamplerInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Time, 1, OneShape, 1)); SamplerInTensors.emplace_back(std::move(EncoderOut[1])); const auto dt = (t_end - t_start) / float(step); auto PredOut = MoeVSSampler::GetMoeVSReflowSampler(_InferParams.ReflowSampler, velocity, melBins, _callback, memory_info)->Sample(SamplerInTensors, step, dt, Scale, _Process); std::vector ReflowOut, finaOut; try { ReflowOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), afterInput.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } ReflowOut.emplace_back(std::move(EncoderOut[2])); try { finaOut = GetCurrentVocoder()->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), ReflowOut.data(), GetCurrentVocoder()->GetInputCount(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } auto DiffOutputAudioSize = finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); std::vector DiffOutput(DiffOutputAudioSize); { auto DiffOutputAudioData = finaOut[0].GetTensorData(); auto OutputAudioData = DiffOutput.data(); const auto OutputAudioEnd = OutputAudioData + DiffOutput.size(); while (OutputAudioData != OutputAudioEnd) *(OutputAudioData++) = (int16_t)(Clamp(*(DiffOutputAudioData++)) * 32766.f); } return DiffOutput; } void ReflowSvc::NormMel(std::vector& MelSpec) const { for (auto& it : MelSpec) it = (it - SpecMin) / (SpecMax - SpecMin) * 2 - 1; } std::vector ReflowSvc::ShallowDiffusionInference( std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize ) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); auto step = (int64_t)_InferParams.Step; if (step > MaxStep) step = MaxStep; std::vector InputNamesEncoder; const auto _Mel_Size = _Mel.second; std::vector HubertInputTensors, HubertOutputTensors; const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)_16KAudioHubert.size() }; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _16KAudioHubert.data(), _16KAudioHubert.size(), HubertInputShape, 3)); try { HubertOutputTensors = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; const auto HubertLength = HubertOutputTensors[0].GetTensorTypeAndShapeInfo().GetShape()[1]; const int64_t FrameShape[] = { 1, _Mel_Size }; const int64_t CharaMixShape[] = { _Mel_Size, SpeakerCount }; constexpr int64_t OneShape[] = { 1 }; int64_t CharaEmb[] = { SpeakerIdx }; auto Alignment = _TensorExtractor->GetAligments(_Mel_Size, HubertLength); Alignment.resize(FrameShape[1]); auto F0Data = InferTools::InterpFunc(_SrcF0, long(_SrcF0.size()), long(FrameShape[1])); std::vector Volume, SpkMap; std::vector EncoderTensors; EncoderTensors.emplace_back(std::move(HubertOutputTensors[0])); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Alignment.data(), FrameShape[1], FrameShape, 2 )); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, F0Data.data(), FrameShape[1], FrameShape, 2 )); if (EnableVolume) { InputNamesEncoder = { "hubert", "mel2ph", "f0", "volume", "spk_mix" }; Volume = InferTools::InterpFunc(_SrcVolume, long(_SrcVolume.size()), long(FrameShape[1])); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, Volume.data(), FrameShape[1], FrameShape, 2 )); } else InputNamesEncoder = { "hubert", "mel2ph", "f0", "spk_mix" }; if (EnableCharaMix) { SpkMap = _TensorExtractor->GetCurrectSpkMixData(_SrcSpeakerMap, FrameShape[1], CharaEmb[0]); EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, SpkMap.data(), SpkMap.size(), CharaMixShape, 2 )); } else { EncoderTensors.emplace_back(Ort::Value::CreateTensor( *memory_info, CharaEmb, 1, OneShape, 1 )); } std::vector EncoderOut; try { EncoderOut = encoder->Run(Ort::RunOptions{ nullptr }, InputNamesEncoder.data(), EncoderTensors.data(), min(EncoderTensors.size(), encoder->GetInputCount()), OutputNamesEncoder.data(), encoder->GetOutputCount()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: encoder\n") + e1.what())) } NormMel(_Mel.first); long long noise_shape[4] = { 1,1,melBins,_Mel_Size }; std::vector SamplerInTensors; float t_end = max(min(1.f, _InferParams.TEnd), 0.002f); float t_start = max(min(_InferParams.TBegin, t_end - 0.001f), 0.f); SamplerInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _Mel.first.data(), _Mel.first.size(), noise_shape, 4)); auto x_it = SamplerInTensors[0].GetTensorMutableData(); auto x_end = SamplerInTensors[0].GetTensorMutableData() + _Mel.first.size(); while (x_it != x_end) { (*(x_it++) *= t_start) += ((t_end - t_start) * normal(gen) * _InferParams.NoiseScale); } float Time[] = { t_start }; SamplerInTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Time, 1, OneShape, 1)); SamplerInTensors.emplace_back(std::move(EncoderOut[1])); const auto dt = (t_end - t_start) / float(step); auto PredOut = MoeVSSampler::GetMoeVSReflowSampler(_InferParams.ReflowSampler, velocity, melBins, _callback, memory_info)->Sample(SamplerInTensors, step, dt, Scale, Process); std::vector ReflowOut, finaOut; try { ReflowOut = after->Run(Ort::RunOptions{ nullptr }, afterInput.data(), PredOut.data(), afterInput.size(), afterOutput.data(), afterOutput.size()); } catch (Ort::Exception& e1) { LibDLVoiceCodecThrow((std::string("Locate: pred\n") + e1.what())) } ReflowOut.emplace_back(std::move(EncoderTensors[2])); try { finaOut = GetCurrentVocoder()->Run(Ort::RunOptions{ nullptr }, nsfInput.data(), ReflowOut.data(), GetCurrentVocoder()->GetInputCount(), nsfOutput.data(), nsfOutput.size()); } catch (Ort::Exception& e3) { LibDLVoiceCodecThrow((std::string("Locate: Nsf\n") + e3.what())) } auto DiffOutputAudioSize = finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); std::vector DiffOutput(DiffOutputAudioSize); { auto DiffOutputAudioData = finaOut[0].GetTensorData(); auto OutputAudioData = DiffOutput.data(); const auto OutputAudioEnd = OutputAudioData + DiffOutput.size(); while (OutputAudioData != OutputAudioEnd) *(OutputAudioData++) = (int16_t)(Clamp(*(DiffOutputAudioData++)) * 32766.f); } const auto dstWavLen = (SrcSize * int64_t(_samplingRate)) / (int)(_InferParams.SrcSamplingRate); DiffOutput.resize(dstWavLen); return DiffOutput; } MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/src/Models/SVC.cpp ================================================ #include "../../header/Models/SVC.hpp" #include "../../header/InferTools/F0Extractor/F0ExtractorManager.hpp" MoeVoiceStudioCoreHeader SingingVoiceConversion::SingingVoiceConversion(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : MoeVoiceStudioModule(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioSingingVoiceConversion"); } SingingVoiceConversion::~SingingVoiceConversion() { delete hubert; hubert = nullptr; } std::vector SingingVoiceConversion::Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { MoeVSNotImplementedError; } std::vector SingingVoiceConversion::InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { MoeVSNotImplementedError; } std::vector SingingVoiceConversion::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { MoeVSNotImplementedError; } std::vector SingingVoiceConversion::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const { MoeVSNotImplementedError; } std::vector SingingVoiceConversion::ExtractVolume(const std::vector& OrgAudio, int hop_size) { std::vector Audio; Audio.reserve(OrgAudio.size() * 2); Audio.insert(Audio.end(), hop_size, double(OrgAudio[0]) / 32768.); for (const auto i : OrgAudio) Audio.emplace_back((double)i / 32768.); Audio.insert(Audio.end(), hop_size, double(OrgAudio[OrgAudio.size() - 1]) / 32768.); const size_t n_frames = (OrgAudio.size() / hop_size) + 1; std::vector volume(n_frames); for (auto& i : Audio) i = pow(i, 2); int64_t index = 0; for (auto& i : volume) { i = sqrt((float)InferTools::getAvg(Audio.begin()._Ptr + index * hop_size, Audio.begin()._Ptr + (index + 1) * hop_size)); ++index; } return volume; } std::vector SingingVoiceConversion::ExtractVolume(const std::vector& OrgAudio) const { std::vector Audio; Audio.reserve(OrgAudio.size() * 2); Audio.insert(Audio.end(), HopSize, OrgAudio[0]); Audio.insert(Audio.end(), OrgAudio.begin(), OrgAudio.end()); Audio.insert(Audio.end(), HopSize, OrgAudio[OrgAudio.size() - 1]); const size_t n_frames = (OrgAudio.size() / HopSize) + 1; std::vector volume(n_frames); for (auto& i : Audio) i = pow(i, 2); int64_t index = 0; for (auto& i : volume) { i = sqrt((float)InferTools::getAvg(Audio.begin()._Ptr + index * HopSize, Audio.begin()._Ptr + (index + 1) * HopSize)); ++index; } return volume; } MoeVSProjectSpace::MoeVoiceStudioSvcData SingingVoiceConversion::GetAudioSlice(const std::vector& input, const std::vector& _slice_pos, const InferTools::SlicerSettings& _slicer) { MoeVSProjectSpace::MoeVoiceStudioSvcData audio_slice; for (size_t i = 1; i < _slice_pos.size(); i++) { MoeVSProjectSpace::MoeVoiceStudioSvcSlice _CurSlice; const bool is_not_mute = abs(InferTools::getAvg((input.data() + _slice_pos[i - 1]), (input.data() + _slice_pos[i]))) > _slicer.Threshold; _CurSlice.IsNotMute = is_not_mute; _CurSlice.OrgLen = long(_slice_pos[i] - _slice_pos[i - 1]); if (is_not_mute) _CurSlice.Audio = { (input.data() + _slice_pos[i - 1]), (input.data() + _slice_pos[i]) }; else _CurSlice.Audio.clear(); audio_slice.Slices.emplace_back(std::move(_CurSlice)); } return audio_slice; } void SingingVoiceConversion::PreProcessAudio(MoeVSProjectSpace::MoeVoiceStudioSvcData& input, int __SamplingRate, int __HopSize, const std::wstring& _f0_method) { const auto F0Extractor = MoeVSF0Extractor::GetF0Extractor(_f0_method, __SamplingRate, __HopSize); const auto num_slice = input.Slices.size(); for (size_t i = 0; i < num_slice; ++i) { if (input.Slices[i].IsNotMute) { input.Slices[i].F0 = F0Extractor->ExtractF0(input.Slices[i].Audio, input.Slices[i].Audio.size() / __HopSize); input.Slices[i].Volume = ExtractVolume(input.Slices[i].Audio, __HopSize); } else { input.Slices[i].F0.clear(); input.Slices[i].Volume.clear(); } input.Slices[i].Speaker.clear(); } } MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/src/Models/VitsSvc.cpp ================================================ #include "../../header/Models/VitsSvc.hpp" #include "../../header/InferTools/AvCodec/AvCodeResample.h" #include "../../header/InferTools/F0Extractor/F0ExtractorManager.hpp" #include #include "../../header/Logger/MoeSSLogger.hpp" #include "../../header/InferTools/TensorExtractor/TensorExtractorManager.hpp" #include #include "../../header/Modules.hpp" MoeVoiceStudioCoreHeader void VitsSvc::Destory() { delete hubert; hubert = nullptr; delete VitsSvcModel; VitsSvcModel = nullptr; } VitsSvc::~VitsSvc() { logger.log(L"[Info] unloading VitsSvc Models"); Destory(); logger.log(L"[Info] VitsSvc Models unloaded"); } VitsSvc::VitsSvc(const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_): SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioVitsSingingVoiceConversion"); //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)") if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String") const auto _folder = to_wide_string(_Config["Folder"].GetString()); const auto cluster_folder = GetCurrentFolder() + L"/Models/" + _folder; if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty") const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; if (_Config["Hubert"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Hubert\" (Hubert Folder)") if (!_Config["Hubert"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Must Be String") const std::wstring HuPath = to_wide_string(_Config["Hubert"].GetString()); if (HuPath.empty()) LibDLVoiceCodecThrow("[Error] Field \"Hubert\" (Hubert Folder) Can Not Be Empty") std::map _PathDict; _PathDict["Cluster"] = cluster_folder; _PathDict["Hubert"] = (GetCurrentFolder() + L"/hubert/" + HuPath + L".onnx"); _PathDict["RVC"] = (_path + L"_RVC.onnx"); _PathDict["SoVits"] = (_path + L"_SoVits.onnx"); if (_Config["ShallowDiffusion"].IsString()) { const std::wstring ShallowDiffusionConf = GetCurrentFolder() + L"/Models/" + to_wide_string(_Config["ShallowDiffusion"].GetString()) + L".json"; _PathDict["ShallowDiffusionConfig"] = ShallowDiffusionConf; if (_Config["MelOperator"].IsString()) _PathDict["MelOperator"] = GetCurrentFolder() + L"/MelOps" + to_wide_string(_Config["MelOperator"].GetString()) + L".onnx"; else _PathDict["MelOperator"] = GetCurrentFolder() + L"/MelOps.onnx"; } logger.log("[Model Loader] Prepeocess Complete!"); load(_PathDict, _Config, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_, true); } VitsSvc::VitsSvc(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioVitsSingingVoiceConversion"); load(_PathDict, _Config, _ProgressCallback, ExecutionProvider_, DeviceID_, ThreadCount_, false); } VitsSvc::VitsSvc(const Hparams& _Hps, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : SingingVoiceConversion(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioVitsSingingVoiceConversion"); _samplingRate = max(_Hps.SamplingRate, 2000); HopSize = max(_Hps.HopSize, 1); HiddenUnitKDims = max(_Hps.HiddenUnitKDims, 1); SpeakerCount = max(_Hps.SpeakerCount, 1); EnableVolume = _Hps.EnableVolume; EnableCharaMix = _Hps.EnableCharaMix; VitsSvcVersion = _Hps.TensorExtractor; #ifdef MOEVSDMLPROVIDER if (ExecutionProvider_ == ExecutionProviders::DML && VitsSvcVersion == L"SoVits4.0-DDSP") LibDLVoiceCodecThrow("[Error] DirectXMl Not Support SoVits4.0V2, Please Use Cuda Or Cpu") #endif _callback = _ProgressCallback; if (!_Hps.Cluster.Type.empty()) { ClusterCenterSize = _Hps.Cluster.ClusterCenterSize; try { Cluster = MoeVoiceStudioCluster::GetMoeVSCluster(_Hps.Cluster.Type, _Hps.Cluster.Path, HiddenUnitKDims, ClusterCenterSize); EnableCluster = true; } catch (std::exception& e) { logger.error(e.what()); EnableCluster = false; } } try { logger.log(L"[Info] loading VitsSvcModel Models"); hubert = new Ort::Session(*env, _Hps.HubertPath.c_str(), *session_options); VitsSvcModel = new Ort::Session(*env, _Hps.VitsSvc.VitsSvc.c_str(), *session_options); logger.log(L"[Info] VitsSvcModel Models loaded"); } catch (Ort::Exception& _exception) { Destory(); LibDLVoiceCodecThrow(_exception.what()) } if (VitsSvcModel->GetInputCount() == 4 && VitsSvcVersion != L"SoVits3.0") VitsSvcVersion = L"SoVits2.0"; MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others _others_param; _others_param.Memory = *memory_info; try { _TensorExtractor = GetTensorExtractor(VitsSvcVersion, 48000, _samplingRate, HopSize, EnableCharaMix, EnableVolume, HiddenUnitKDims, SpeakerCount, _others_param); } catch (std::exception& e) { Destory(); LibDLVoiceCodecThrow(e.what()) } } void VitsSvc::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_, bool MoeVoiceStudioFrontEnd) { //Check SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)") if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64") logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); if (!_Config["SoVits3"].IsNull() && _Config["SoVits3"].GetBool()) VitsSvcVersion = L"SoVits3.0"; else if (!_Config["SoVits2"].IsNull() && _Config["SoVits2"].GetBool()) VitsSvcVersion = L"SoVits2.0"; else if (!_Config["SoVits2.0"].IsNull() && _Config["SoVits2.0"].GetBool()) VitsSvcVersion = L"SoVits2.0"; else if (!_Config["SoVits3.0"].IsNull() && _Config["SoVits3.0"].GetBool()) VitsSvcVersion = L"SoVits3.0"; else if (_Config["Type"].GetString() == std::string("RVC")) VitsSvcVersion = L"RVC"; if (!_Config["SoVits4.0V2"].IsNull() && _Config["SoVits4.0V2"].GetBool()) VitsSvcVersion = L"SoVits4.0-DDSP"; #ifdef MOEVSDMLPROVIDER if (ExecutionProvider_ == ExecutionProviders::DML && VitsSvcVersion == L"SoVits4.0-DDSP") LibDLVoiceCodecThrow("[Error] DirectXMl Not Support SoVits4.0V2, Please Use Cuda Or Cpu") #endif if (!(_Config["Hop"].IsInt() || _Config["Hop"].IsInt64())) LibDLVoiceCodecThrow("[Error] Hop Must Exist And Must Be Int") HopSize = _Config["Hop"].GetInt(); if (!(_Config["HiddenSize"].IsInt() || _Config["HiddenSize"].IsInt64())) logger.log(L"[Warn] Missing Field \"HiddenSize\", Use Default Value (256)"); else HiddenUnitKDims = _Config["HiddenSize"].GetInt(); if (!_Config["CharaMix"].IsBool()) logger.log(L"[Warn] Missing Field \"CharaMix\", Use Default Value (False)"); else EnableCharaMix = _Config["CharaMix"].GetBool(); if (_Config["Cluster"].IsString()) { const auto clus = to_wide_string(_Config["Cluster"].GetString()); if (!(_Config["KMeansLength"].IsInt() || _Config["KMeansLength"].IsInt64())) logger.log(L"[Warn] Missing Field \"KMeansLength\", Use Default Value (10000)"); else ClusterCenterSize = _Config["KMeansLength"].GetInt(); try { Cluster = MoeVoiceStudioCluster::GetMoeVSCluster(clus, _PathDict.at("Cluster"), HiddenUnitKDims, ClusterCenterSize); EnableCluster = true; } catch (std::exception& e) { logger.error(e.what()); EnableCluster = false; } } if (HopSize < 1) LibDLVoiceCodecThrow("[Error] Hop Must > 0") if (_Config["Volume"].IsBool()) EnableVolume = _Config["Volume"].GetBool(); else logger.log(L"[Warn] Missing Field \"Volume\", Use Default Value (False)"); if (_Config["Characters"].IsArray()) SpeakerCount = int64_t(_Config["Characters"].Size()); _callback = _ProgressCallback; //LoadModels try { logger.log(L"[Info] loading VitsSvcModel Models"); hubert = new Ort::Session(*env, _PathDict.at("Hubert").c_str(), *session_options); if (VitsSvcVersion == L"RVC") VitsSvcModel = new Ort::Session(*env, _PathDict.at("RVC").c_str(), *session_options); else VitsSvcModel = new Ort::Session(*env, _PathDict.at("SoVits").c_str(), *session_options); logger.log(L"[Info] VitsSvcModel Models loaded"); } catch (Ort::Exception& _exception) { Destory(); LibDLVoiceCodecThrow(_exception.what()) } if (VitsSvcModel->GetInputCount() == 4 && VitsSvcVersion != L"SoVits3.0") VitsSvcVersion = L"SoVits2.0"; if (_Config["TensorExtractor"].IsString()) VitsSvcVersion = to_wide_string(_Config["TensorExtractor"].GetString()); MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others _others_param; _others_param.Memory = *memory_info; try { _TensorExtractor = GetTensorExtractor(VitsSvcVersion, 48000, _samplingRate, HopSize, EnableCharaMix, EnableVolume, HiddenUnitKDims, SpeakerCount, _others_param); } catch (std::exception& e) { Destory(); LibDLVoiceCodecThrow(e.what()) } } std::vector VitsSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Start!"); std::vector _data; size_t total_audio_size = 0; for (const auto& data_size : _Slice.Slices) total_audio_size += data_size.OrgLen; _data.reserve(size_t(double(total_audio_size) * 1.5)); _callback(0, _Slice.Slices.size()); size_t process = 0; for (auto& CurSlice : _Slice.Slices) { const auto InferDurTime = clock(); const auto CurRtn = SliceInference(CurSlice, _InferParams, process); _data.insert(_data.end(), CurRtn.data(), CurRtn.data() + CurRtn.size()); if(CurSlice.IsNotMute) logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Segment[" + std::to_wstring(process) + L"] Finished! Segment Use Time: " + std::to_wstring(clock() - InferDurTime) + L"ms, Segment Duration: " + std::to_wstring((size_t)CurSlice.OrgLen * 1000ull / (uint64_t)(_InferParams.SrcSamplingRate)) + L"ms"); else logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Jump Empty Segment[" + std::to_wstring(process) + L"]!"); _callback(++process, _Slice.Slices.size()); } logger.log(L"[Inferring] \"" + _Slice.Path + L"\" Finished"); return _data; } std::vector VitsSvc::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); if (_Slice.IsNotMute) { std::vector _16KAudio, CUDAF0, CUDAVolume; std::vector> CUDASpeaker; _16KAudio = InferTools::InterpResample(_Slice.Audio, (int)(_InferParams.SrcSamplingRate), 16000, 32768.0f); const auto src_audio_length = _16KAudio.size(); bool NeedPadding = false; if (_cur_execution_provider == ExecutionProviders::CUDA) { NeedPadding = _16KAudio.size() % 16000; const size_t WavPaddedSize = _16KAudio.size() / 16000 + 1; if (NeedPadding) _16KAudio.resize(WavPaddedSize * 16000, 0.f); } const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)_16KAudio.size() }; std::vector HubertInputTensors, HubertOutPuts; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _16KAudio.data(), _16KAudio.size(), HubertInputShape, 3)); try { HubertOutPuts = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } const auto HubertSize = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetElementCount(); const auto HubertOutPutData = HubertOutPuts[0].GetTensorMutableData(); auto HubertOutPutShape = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetShape(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector SrcHiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; const auto max_cluster_size = int64_t((size_t)HubertOutPutShape[1] * src_audio_length / _16KAudio.size()); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto pts = Cluster->find(SrcHiddenUnits.data(), long(SpeakerIdx), max_cluster_size); for (int64_t indexs = 0; indexs < max_cluster_size * HiddenUnitKDims; ++indexs) SrcHiddenUnits[indexs] = SrcHiddenUnits[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::InferParams _Inference_Params; _Inference_Params.AudioSize = _Slice.Audio.size(); _Inference_Params.Chara = SpeakerIdx; _Inference_Params.NoiseScale = _InferParams.NoiseScale; _Inference_Params.DDSPNoiseScale = _InferParams.DDSPNoiseScale; _Inference_Params.Seed = int(_InferParams.Seed); _Inference_Params.upKeys = _InferParams.Keys; MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Inputs InputTensors; if (NeedPadding) { CUDAF0 = _Slice.F0; CUDAVolume = _Slice.Volume; CUDASpeaker = _Slice.Speaker; const auto src_src_audio_length = _Slice.Audio.size(); const size_t WavPaddedSize = ((src_src_audio_length / (int)(_InferParams.SrcSamplingRate)) + 1) * (int)(_InferParams.SrcSamplingRate); const size_t AudioPadSize = WavPaddedSize - src_src_audio_length; const size_t PaddedF0Size = CUDAF0.size() + (CUDAF0.size() * AudioPadSize / src_src_audio_length); if (!CUDAF0.empty()) CUDAF0.resize(PaddedF0Size, 0.f); if (!CUDAVolume.empty()) CUDAVolume.resize(PaddedF0Size, 0.f); for (auto iSpeaker : CUDASpeaker) { if (!iSpeaker.empty()) iSpeaker.resize(PaddedF0Size, 0.f); } _Inference_Params.AudioSize = WavPaddedSize; InputTensors = _TensorExtractor->Extract(SrcHiddenUnits, CUDAF0, CUDAVolume, CUDASpeaker, _Inference_Params); } else InputTensors = _TensorExtractor->Extract(SrcHiddenUnits, _Slice.F0, _Slice.Volume, _Slice.Speaker, _Inference_Params); std::vector finaOut; try { finaOut = VitsSvcModel->Run(Ort::RunOptions{ nullptr }, InputTensors.InputNames, InputTensors.Tensor.data(), InputTensors.Tensor.size(), soVitsOutput.data(), soVitsOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: VitsSvc\n") + e.what())) } auto VitsOutputAudioSize = finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); std::vector VitsOutput(VitsOutputAudioSize); { auto VitsOutputAudioData = finaOut[0].GetTensorData(); auto OutputAudioData = VitsOutput.data(); const auto OutputAudioEnd = OutputAudioData + VitsOutput.size(); while (OutputAudioData != OutputAudioEnd) *(OutputAudioData++) = (int16_t)(Clamp(*(VitsOutputAudioData++)) * 32766.f); } if(_InferParams.UseShallowDiffusion) { MoeVSModuleManager::ReloadMelOps( _InferParams.VocoderSamplingRate, _InferParams.VocoderHopSize, _InferParams.VocoderMelBins ); const auto TempAudio = InferTools::InterpResample( VitsOutput, _samplingRate, _InferParams.VocoderSamplingRate, 32768. ); auto Mel = MoeVSModuleManager::GetMelOperator()(TempAudio); if(_InferParams._ShallowDiffusionModel) { if(!_InferParams.ShallowDiffusionUseSrcAudio) { auto VitsOutputAudioData = finaOut[0].GetTensorData(); _16KAudio = { VitsOutputAudioData , VitsOutputAudioData + VitsOutputAudioSize }; } auto SpcParams = _InferParams; std::swap(SpcParams.SpeakerId, SpcParams.ShallowDiffuisonSpeaker); VitsOutput = ((MoeVSModuleManager::UnionSvcModel*)_InferParams._ShallowDiffusionModel)-> ShallowDiffusionInference( _16KAudio, SpcParams, Mel, NeedPadding ? CUDAF0 : _Slice.F0, NeedPadding ? CUDAVolume : _Slice.Volume, NeedPadding ? CUDASpeaker : _Slice.Speaker, _Process, (int64_t)TempAudio.size() ); } else { auto Rf0 = NeedPadding ? CUDAF0 : _Slice.F0; if (Rf0.size() != (size_t)Mel.second) Rf0 = InferTools::InterpFunc(Rf0, (long)Rf0.size(), (long)Mel.second); VitsOutput = VocoderInfer( Mel.first, Rf0, _InferParams.VocoderMelBins, Mel.second, memory_info, _InferParams._VocoderModel ); } } /*if (shallow_diffusion && stft_operator && _InferParams.UseShallowDiffusion) { auto PCMAudioBegin = finaOut[0].GetTensorData(); auto PCMAudioEnd = PCMAudioBegin + finaOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto MelSpec = MelExtractor(PCMAudioBegin, PCMAudioEnd); auto ShallowParam = _InferParams; ShallowParam.SrcSamplingRate = _samplingRate; auto ShallowDiffusionOutput = shallow_diffusion->ShallowDiffusionInference( RawWav, ShallowParam, std::move(MelSpec[0]), NeedPadding ? CUDAF0 : _Slice.F0, NeedPadding ? CUDAVolume : _Slice.Volume, NeedPadding ? CUDASpeaker : _Slice.Speaker ); ShallowDiffusionOutput.resize(dstWavLen, 0); return ShallowDiffusionOutput; }*/ const auto dstWavLen = (_Slice.OrgLen * int64_t(_samplingRate)) / (int)(_InferParams.SrcSamplingRate); VitsOutput.resize(dstWavLen); return VitsOutput; } //Mute clips const auto len = size_t(_Slice.OrgLen * int64_t(_samplingRate) / (int)(_InferParams.SrcSamplingRate)); return { len, 0i16, std::allocator() }; } std::vector VitsSvc::Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); std::vector _Lens = GetOpenFileNameMoeVS(); std::vector AudioFolders; for (auto& path : _Lens) { path = std::regex_replace(path, std::wregex(L"\\\\"), L"/"); auto PCMData = AudioPreprocess().codec(path, (int)(_InferParams.SrcSamplingRate)); auto slicer_setting = _SlicerSettings; slicer_setting.SamplingRate = (int)(_InferParams.SrcSamplingRate); auto SlicePos = SliceAudio(PCMData, slicer_setting); auto Audio = GetAudioSlice(PCMData, SlicePos, slicer_setting); Audio.Path = path; PreProcessAudio(Audio, (int)(_InferParams.SrcSamplingRate), 512, _InferParams.F0Method); std::vector _data = SliceInference(Audio, _InferParams); std::wstring OutFolder = GetCurrentFolder() + L"/Outputs/" + path.substr(path.rfind(L'/') + 1, path.rfind(L'.') - path.rfind(L'/') - 1); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; OutFolder += L"-Params-(-NoiseScale=" + std::to_wstring(_InferParams.NoiseScale) + L"-Speaker=" + (EnableCharaMix ? std::wstring(L"SpeakerMix") : std::to_wstring(SpeakerIdx)) + L"-Seed=" + std::to_wstring(_InferParams.Seed) + L"-F0Method=" + _InferParams.F0Method + L")"; if (_waccess((OutFolder + L".wav").c_str(), 0) != -1) { for (size_t idx = 0; idx < 99999999; ++idx) if (_waccess((OutFolder + L" (" + std::to_wstring(idx) + L").wav").c_str(), 0) == -1) { OutFolder += L" (" + std::to_wstring(idx) + L").wav"; break; } } else OutFolder += L".wav"; AudioFolders.emplace_back(OutFolder); _data = InferTools::InterpResample(_data, _samplingRate, (int)(_InferParams.SrcSamplingRate), 1i16); InferTools::Wav::WritePCMData((int)(_InferParams.SrcSamplingRate), 1, _data, OutFolder); } return AudioFolders; } std::vector VitsSvc::InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { _TensorExtractor->SetSrcSamplingRates(_InferParams.SrcSamplingRate); auto hubertin = InferTools::InterpResample(PCMData, srcSr, 16000); int64_t SpeakerIdx = _InferParams.SpeakerId; if (SpeakerIdx >= SpeakerCount) SpeakerIdx = SpeakerCount; if (SpeakerIdx < 0) SpeakerIdx = 0; std::mt19937 gen(int(_InferParams.Seed)); std::normal_distribution normal(0, 1); float noise_scale = _InferParams.NoiseScale; float ddsp_noise_scale = _InferParams.DDSPNoiseScale; const int64_t inputShape[3] = { 1i64,1i64,(int64_t)hubertin.size() }; std::vector inputTensorshu; inputTensorshu.emplace_back(Ort::Value::CreateTensor(*memory_info, hubertin.data(), hubertin.size(), inputShape, 3)); std::vector hubertOut; try { hubertOut = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), inputTensorshu.data(), inputTensorshu.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what())) } auto HubertSize = hubertOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto HubertOutPutData = hubertOut[0].GetTensorMutableData(); auto HubertOutPutShape = hubertOut[0].GetTensorTypeAndShapeInfo().GetShape(); inputTensorshu.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch") std::vector HiddenUnitsSrc(HubertOutPutData, HubertOutPutData + HubertSize); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { const auto clus_size = HubertOutPutShape[1]; const auto pts = Cluster->find(HiddenUnitsSrc.data(), long(SpeakerIdx), clus_size); for (size_t indexs = 0; indexs < HiddenUnitsSrc.size(); ++indexs) HiddenUnitsSrc[indexs] = HiddenUnitsSrc[indexs] * (1.f - _InferParams.ClusterRate) + pts[indexs] * _InferParams.ClusterRate; } const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; int64_t F0Shape[] = { 1, int64_t(PCMData.size() / HopSize) }; int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t LengthShape[] = { 1 }; int64_t CharaEmbShape[] = { 1 }; int64_t CharaMixShape[] = { F0Shape[1], SpeakerCount }; int64_t RandnShape[] = { 1, 192, F0Shape[1] }; const int64_t IstftShape[] = { 1, 2048, F0Shape[1] }; int64_t RandnCount = F0Shape[1] * 192; const int64_t IstftCount = F0Shape[1] * 2048; std::vector RandnInput, IstftInput, UV, InterpedF0; std::vector alignment; int64_t XLength[1] = { HubertLen }; std::vector Nsff0; //auto SoVitsInput = soVitsInput; int64_t Chara[] = { SpeakerIdx }; std::vector charaMix; const auto F0Extractor = MoeVSF0Extractor::GetF0Extractor(_InferParams.F0Method, _samplingRate, HopSize); auto srcF0Data = F0Extractor->ExtractF0(PCMData, PCMData.size() / HopSize); for (auto& ifo : srcF0Data) ifo *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); std::vector HiddenUnits; std::vector F0Data; std::vector _Tensors; std::vector SoVitsInput = soVitsInput; //Compatible with all versions if (VitsSvcVersion == L"SoVits3.0") { int64_t upSample = _samplingRate / 16000; HiddenUnits.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < HiddenUnitShape[1]; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) HiddenUnits.insert(HiddenUnits.end(), HiddenUnitsSrc.begin() + itS * HiddenUnitKDims, HiddenUnitsSrc.begin() + (itS + 1) * HiddenUnitKDims); HiddenUnitShape[1] *= upSample; HubertSize *= upSample; F0Data = _TensorExtractor->GetInterpedF0(InferTools::InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1]))); F0Shape[1] = HiddenUnitShape[1]; XLength[0] = HiddenUnitShape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, F0Data.data(), F0Data.size(), F0Shape, 2)); } else if (VitsSvcVersion == L"SoVits2.0") { HiddenUnits = std::move(HiddenUnitsSrc); F0Shape[1] = HiddenUnitShape[1]; F0Data = InferTools::InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1])); XLength[0] = HiddenUnitShape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); Nsff0 = _TensorExtractor->GetNSFF0(F0Data); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Nsff0.data(), Nsff0.size(), F0Shape, 2)); } else if (VitsSvcVersion == L"RVC") { constexpr int64_t upSample = 2; HiddenUnits.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < HiddenUnitShape[1]; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) HiddenUnits.insert(HiddenUnits.end(), HiddenUnitsSrc.begin() + itS * HiddenUnitKDims, HiddenUnitsSrc.begin() + (itS + 1) * HiddenUnitKDims); HiddenUnitShape[1] *= upSample; HubertSize *= upSample; F0Data = InferTools::InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1])); F0Shape[1] = HiddenUnitShape[1]; XLength[0] = HiddenUnitShape[1]; RandnCount = 192 * F0Shape[1]; RandnShape[2] = F0Shape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); InterpedF0 = _TensorExtractor->GetInterpedF0(F0Data); Nsff0 = _TensorExtractor->GetNSFF0(InterpedF0); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Nsff0.data(), Nsff0.size(), F0Shape, 2)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), InterpedF0.size(), F0Shape, 2)); SoVitsInput = RVCInput; RandnInput = std::vector(RandnCount, 0.f); for (auto& it : RandnInput) it = normal(gen) * noise_scale; } else { HiddenUnits = std::move(HiddenUnitsSrc); F0Data = InferTools::InterpFunc(srcF0Data, long(srcF0Data.size()), long(F0Shape[1])); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); InterpedF0 = _TensorExtractor->GetInterpedF0(F0Data); alignment = _TensorExtractor->GetAligments(F0Shape[1], HubertLen); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), InterpedF0.size(), F0Shape, 2)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, alignment.data(), InterpedF0.size(), F0Shape, 2)); if (VitsSvcVersion != L"SoVits4.0-DDSP") { UV = _TensorExtractor->GetUV(F0Data); SoVitsInput = { "c", "f0", "mel2ph", "uv", "noise", "sid" }; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, UV.data(), UV.size(), F0Shape, 2)); } else { SoVitsInput = { "c", "f0", "mel2ph", "t_window", "noise", "sid" }; IstftInput = std::vector(IstftCount, ddsp_noise_scale); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, IstftInput.data(), IstftInput.size(), IstftShape, 3)); } RandnInput = std::vector(RandnCount, 0.f); for (auto& it : RandnInput) it = normal(gen) * noise_scale; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RandnInput.data(), RandnCount, RandnShape, 3)); } if (EnableCharaMix) { CharaMixShape[0] = F0Shape[1]; std::vector charaMap(SpeakerCount, 0.f); charaMap[SpeakerIdx] = 1.f; charaMix.reserve((SpeakerCount + 1) * F0Shape[1]); for (int64_t index = 0; index < F0Shape[1]; ++index) charaMix.insert(charaMix.end(), charaMap.begin(), charaMap.end()); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, charaMix.data(), charaMix.size(), CharaMixShape, 2)); } else _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Chara, 1, CharaEmbShape, 1)); if (VitsSvcVersion == L"RVC") _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RandnInput.data(), RandnCount, RandnShape, 3)); std::vector VolumeData; if (EnableVolume) { SoVitsInput.emplace_back("vol"); VolumeData = ExtractVolume(PCMData, HopSize); VolumeData.resize(F0Shape[1], 0.f); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, VolumeData.data(), F0Shape[1], F0Shape, 2)); } std::vector finaOut; finaOut = VitsSvcModel->Run(Ort::RunOptions{ nullptr }, SoVitsInput.data(), _Tensors.data(), _Tensors.size(), soVitsOutput.data(), soVitsOutput.size()); const auto dstWavLen = finaOut[0].GetTensorTypeAndShapeInfo().GetShape()[2]; auto retdata = finaOut[0].GetTensorData(); std::vector TempVecWav(dstWavLen, 0); auto TempVecWavData = TempVecWav.data(); for (int64_t bbb = 0; bbb < dstWavLen; bbb++) *(TempVecWavData++) = static_cast(Clamp(*(retdata++)) * 32766.0f); if(VitsSvcVersion == L"RVC") TempVecWav = InferTools::InterpResample(TempVecWav, _samplingRate, (int)(_InferParams.SrcSamplingRate), 1i16); return TempVecWav; } /*std::vector VitsSvc::MelExtractor(const float* PCMAudioBegin, const float* PCMAudioEnd) const { std::vector _SRAudio{PCMAudioBegin, PCMAudioEnd}; _SRAudio = InferTools::InterpResample(_SRAudio, _samplingRate, 16000, 1.f); const auto _MelLength = int64_t(_SRAudio.size() * shallow_diffusion->GetSamplingRate() / 16000ull / shallow_diffusion->GetHopSize()); const auto _SpecLength = (int64_t)ceil(double(_SRAudio.size()) / 16000. * 100.); auto Alignment = _TensorExtractor->GetAligments(_MelLength, _SpecLength); Alignment.resize(_MelLength); std::vector AudioTensors; const int64_t AudioInputShape[] = { 1,1,int64_t(_SRAudio.size()) }; const int64_t AligShape[] = { 1,_MelLength }; AudioTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, _SRAudio.data(), _SRAudio.size(), AudioInputShape, 3)); AudioTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Alignment.data(), Alignment.size(), AligShape, 2)); try { return stft_operator->Run(Ort::RunOptions{ nullptr }, StftInput.data(), AudioTensors.data(), AudioTensors.size(), StftOutput.data(), StftOutput.size() ); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: ShallowDiffusionStftOperator\n") + e.what()).c_str()); } }*/ //已弃用(旧MoeSS的推理函数) #ifdef MOESSDFN std::vector VitsSvc::InferBatch() const { std::wstring RawPath; int ret = InsertMessageToEmptyEditBox(RawPath); if (ret == -1) LibDLVoiceCodecThrow("TTS Does Not Support Automatic Completion"); if (ret == -2) LibDLVoiceCodecThrow("Please Select Files"); RawPath += L'\n'; std::vector _Lens = CutLens(RawPath); const auto params = _get_init_params(); auto tran = static_cast(params.keys); auto threshold = static_cast(params.threshold); auto minLen = static_cast(params.minLen); auto frame_len = static_cast(params.frame_len); auto frame_shift = static_cast(params.frame_shift); if (frame_shift < 512 || frame_shift > 10240) frame_shift = 512; if (frame_len < 1024 || frame_len > 20480) frame_len = 1024; if (frame_shift > frame_len) { frame_shift = 512; frame_len = 4 * 1024; } if (minLen < 3 || minLen > 30) minLen = 3; if (threshold < 10.0 || threshold > 2000.0) threshold = 30.0; int64_t charEmb = params.chara; std::mt19937 gen(int(params.seed)); std::normal_distribution normal(0, 1); float noise_scale = params.noise_scale; float ddsp_noise_scale = params.noise_scale_w; if (noise_scale > 50.0f) noise_scale = 1.0f; if (ddsp_noise_scale > 50.0f) ddsp_noise_scale = 1.0f; for (auto& path : _Lens) { logger.log(L"[Inferring] Inferring \"" + path + L'\"'); size_t proc = 0; if (path[0] == L'\"') path = path.substr(1); if (path[path.length() - 1] == L'\"') path.pop_back(); std::vector _data; //Audio logger.log(L"[Inferring] PreProcessing \"" + path + L"\" Encoder"); auto RawWav = AudioPreprocess().codec(path, _samplingRate); auto HubertWav = AudioPreprocess().codec(path, 16000); auto info = cutWav(RawWav, threshold, minLen, static_cast(frame_len), static_cast(frame_shift)); for (size_t i = 1; i < info.cutOffset.size(); ++i) if ((info.cutOffset[i] - info.cutOffset[i - 1]) / RawWav.getHeader().bytesPerSec > 90) LibDLVoiceCodecThrow("Reached max slice length, please change slicer param"); const auto LenFactor = ((double)16000 / (double)_samplingRate); _callback(proc, info.cutTag.size()); logger.log(L"[Inferring] Inferring \"" + path + L"\" Svc"); for (size_t i = 1; i < info.cutOffset.size(); ++i) { if (info.cutTag[i - 1]) { auto featureInput = F0PreProcess(_samplingRate, (short)hop); const auto len = (info.cutOffset[i] - info.cutOffset[i - 1]) / 2; const auto srcPos = info.cutOffset[i - 1] / 2; std::vector source(len, 0.0); for (unsigned long long j = 0; j < len; ++j) source[j] = (double)RawWav[srcPos + j] / 32768.0; //hubertIn const auto hubertInLen = (size_t)((double)len * LenFactor); std::vector hubertin(hubertInLen, 0.0); const auto startPos = (size_t)(((double)info.cutOffset[i - 1] / 2.0) * LenFactor); for (size_t j = 0; j < hubertInLen; ++j) hubertin[j] = (float)HubertWav[startPos + j] / 32768.0f; //hubert const int64_t inputShape[3] = { 1i64,1i64,(int64_t)hubertInLen }; std::vector inputTensors; inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, hubertin.data(), hubertInLen, inputShape, 3)); std::vector hubertOut; try { hubertOut = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), inputTensors.data(), inputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what()).c_str()); } auto hubertOutData = hubertOut[0].GetTensorMutableData(); auto hubertOutLen = hubertOut[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto hubertOutShape = hubertOut[0].GetTensorTypeAndShapeInfo().GetShape(); std::vector inputPitch1, alignment; std::vector inputPitch2; F0PreProcess::V4Return v4_return; std::vector hubOutData(hubertOutData, hubertOutData + hubertOutLen); if (SV3) { if (_samplingRate / 16000 == 2) { for (int64_t itS = hubertOutShape[1] - 1; itS + 1; --itS) { hubOutData.insert(hubOutData.begin() + itS * 256, hubOutData.begin() + itS * 256, hubOutData.begin() + (itS + 1) * 256); } hubertOutShape[1] *= 2; hubertOutLen *= 2; inputPitch2 = featureInput.GetF0AndOtherInput3(source.data(), (long long)len, (long long)hubertOutShape[1], (long long)tran); } else if (_samplingRate / 16000 == 3) { for (int64_t itS = hubertOutShape[1] - 1; itS + 1; --itS) { hubOutData.insert(hubOutData.begin() + itS * 256, hubOutData.begin() + itS * 256, hubOutData.begin() + (itS + 1) * 256); hubOutData.insert(hubOutData.begin() + itS * 256, hubOutData.begin() + itS * 256, hubOutData.begin() + (itS + 1) * 256); } hubertOutShape[1] *= 3; hubertOutLen *= 3; inputPitch2 = featureInput.GetF0AndOtherInput3(source.data(), (long long)len, (long long)hubertOutShape[1], (long long)tran); } else LibDLVoiceCodecThrow("SoVits3.0 Only Support Sr: 48K,32K"); } else if (SV4) { alignment = getAligments(len / hop, hubertOutShape[1]); v4_return = featureInput.GetF0AndOtherInput4(source.data(), (long long)len, tran); } else if (_modelType == modelType::RVC) { for (int64_t itS = hubertOutShape[1] - 1; itS + 1; --itS) { hubOutData.insert(hubOutData.begin() + itS * 256, hubOutData.begin() + itS * 256, hubOutData.begin() + (itS + 1) * 256); } hubertOutShape[1] *= 2; hubertOutLen *= 2; auto f0data = featureInput.GetF0AndOtherInputR(source.data(), (long long)len, (long long)hubertOutShape[1], (long long)tran); inputPitch1 = std::move(f0data.f0); inputPitch2 = std::move(f0data.f0f); } else { inputPitch1 = featureInput.GetF0AndOtherInput(source.data(), (long long)len, (long long)hubertOutShape[1], (long long)tran); } inputTensors.clear(); auto SoVitsInput = soVitsInput; //vits constexpr long long ashape[1] = { 1 }; long long ainput[1] = { hubertOutShape[1] }; const long long bshape[2] = { 1, featureInput.getLen() }; long long cdata[1] = { charEmb }; constexpr long long cshape[1] = { 1 }; const int64 zinputShape[3] = { 1,192,featureInput.getLen() }; const int64 zinputCount = featureInput.getLen() * 192; std::vector zinput(zinputCount, 0.0); inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, hubOutData.data(), hubertOutLen, hubertOutShape.data(), 3)); std::vector T_Window(2048 * featureInput.getLen(), ddsp_noise_scale); int64_t T_WindowShape[] = { 1, 2048, featureInput.getLen() }; if (!SV4) inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, ainput, 1, ashape, 1)); if (SV3) inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, inputPitch2.data(), featureInput.getLen(), bshape, 2)); else if (SV4) { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, v4_return.f0.data(), featureInput.getLen(), bshape, 2)); inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, alignment.data(), featureInput.getLen(), bshape, 2)); if (!SVV2) { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, v4_return.uv.data(), featureInput.getLen(), bshape, 2)); SoVitsInput = { "c", "f0", "mel2ph", "uv", "noise", "sid" }; } else { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, T_Window.data(), T_Window.size(), T_WindowShape, 3)); SoVitsInput = { "c", "f0", "mel2ph", "t_window", "noise", "sid" }; } for (auto& it : zinput) it = normal(gen) * noise_scale; inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, zinput.data(), zinputCount, zinputShape, 3)); } else { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, inputPitch1.data(), featureInput.getLen(), bshape, 2)); if (_modelType == modelType::RVC) { inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, inputPitch2.data(), featureInput.getLen(), bshape, 2)); SoVitsInput = RVCInput; for (auto& it : zinput) it = normal(gen) * noise_scale; } } inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, cdata, 1, cshape, 1)); std::vector finaOut; if (_modelType == modelType::RVC) inputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, zinput.data(), zinputCount, zinputShape, 3)); try { finaOut = VitsSvcModel->Run(Ort::RunOptions{ nullptr }, SoVitsInput.data(), inputTensors.data(), inputTensors.size(), soVitsOutput.data(), soVitsOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: sovits\n") + e.what()).c_str()); } const auto shapeOut = finaOut[0].GetTensorTypeAndShapeInfo().GetShape(); const auto dstWavLen = int64_t(len); std::vector TempVecWav(dstWavLen, 0); if (shapeOut[2] < dstWavLen) { for (int64_t bbb = 0; bbb < shapeOut[2]; bbb++) TempVecWav[bbb] = static_cast(finaOut[0].GetTensorData()[bbb] * 32768.0f); } else { for (int64_t bbb = 0; bbb < dstWavLen; bbb++) TempVecWav[bbb] = static_cast(finaOut[0].GetTensorData()[bbb] * 32768.0f); } _data.insert(_data.end(), TempVecWav.data(), TempVecWav.data() + (dstWavLen)); } else { const auto len = (info.cutOffset[i] - info.cutOffset[i - 1]) / 2; const auto data = new int16_t[len]; memset(data, 0, len * 2); _data.insert(_data.end(), data, data + len); delete[] data; } _callback(++proc, info.cutTag.size()); } logger.log(L"[Inferring] \"" + path + L"\" Finished"); if (_Lens.size() == 1) { logger.log(L"[Info] Finished, Send To FrontEnd"); return _data; } std::wstring outPutPath = GetCurrentFolder() + L"\\OutPuts\\" + path.substr(path.rfind(L'\\') + 1, path.rfind(L'.')) + L'-' + std::to_wstring(uint64_t(path.data())) + L".wav"; logger.log(L"[Inferring] Write To \"" + outPutPath + L'\"'); Wav(_samplingRate, long(_data.size()) * 2, _data.data()).Writef(outPutPath); } logger.log(L"[Info] Finished"); return {}; } #endif /* std::vector VitsSvc::InferSliceTensor(const MoeVSProjectSpace::MoeVSAudioSlice& _Slice, size_t SliceIdx, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::vector& _Tensors, std::vector& SoVitsInput) const { int64_t charEmb = _InferParams.SpeakerId; float noise_scale = _InferParams.NoiseScale; float ddsp_noise_scale = _InferParams.DDSPNoiseScale; auto RawWav = TensorPreprocess::MoeVoiceStudioTensorExtractor::InterpResample(_Slice.Audio[SliceIdx], 48000, 16000, 32768.0f); const int64_t HubertInputShape[3] = { 1i64,1i64,(int64_t)RawWav.size() }; std::vector HubertInputTensors, HubertOutPuts; HubertInputTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RawWav.data(), RawWav.size(), HubertInputShape, 3)); try { HubertOutPuts = hubert->Run(Ort::RunOptions{ nullptr }, hubertInput.data(), HubertInputTensors.data(), HubertInputTensors.size(), hubertOutput.data(), hubertOutput.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: hubert\n") + e.what()).c_str()); } auto HubertSize = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetElementCount(); auto HubertOutPutData = HubertOutPuts[0].GetTensorMutableData(); auto HubertOutPutShape = HubertOutPuts[0].GetTensorTypeAndShapeInfo().GetShape(); HubertInputTensors.clear(); if (HubertOutPutShape[2] != HiddenUnitKDims) LibDLVoiceCodecThrow("HiddenUnitKDims UnMatch"); std::vector srcHiddenUnits(HubertOutPutData, HubertOutPutData + HubertSize); if (EnableCluster && _InferParams.ClusterRate > 0.001f) { for (int64_t indexs = 0; indexs < HubertOutPutShape[1]; ++indexs) { const auto curbeg = srcHiddenUnits.data() + indexs * HubertOutPutShape[2]; const auto curend = srcHiddenUnits.data() + (indexs + 1) * HubertOutPutShape[2]; const auto hu = Cluster->find({ curbeg ,curend }, long(charEmb)); for (int64_t ind = 0; ind < HubertOutPutShape[2]; ++ind) *(curbeg + ind) = *(curbeg + ind) * (1.f - _InferParams.ClusterRate) + hu[ind] * _InferParams.ClusterRate; } } const auto HubertLen = int64_t(HubertSize) / HiddenUnitKDims; int64_t F0Shape[] = { 1, int64_t(_Slice.Audio[SliceIdx].size() * _samplingRate / 48000 / HopSize) }; int64_t HiddenUnitShape[] = { 1, HubertLen, HiddenUnitKDims }; constexpr int64_t LengthShape[] = { 1 }; int64_t CharaEmbShape[] = { 1 }; int64_t CharaMixShape[] = { F0Shape[1], SpeakerCount }; int64_t RandnShape[] = { 1, 192, F0Shape[1] }; const int64_t IstftShape[] = { 1, 2048, F0Shape[1] }; int64_t RandnCount = F0Shape[1] * 192; const int64_t IstftCount = F0Shape[1] * 2048; std::vector RandnInput, IstftInput, UV, InterpedF0; std::vector alignment; int64_t XLength[1] = { HubertLen }; std::vector Nsff0; //auto SoVitsInput = soVitsInput; int64_t Chara[] = { charEmb }; std::vector charaMix; auto srcF0Data = _Slice.F0[SliceIdx]; for (auto& ifo : srcF0Data) ifo *= (float)pow(2.0, static_cast(_InferParams.Keys) / 12.0); std::vector HiddenUnits; std::vector F0Data; //Compatible with all versions if (SoVits3) { int64_t upSample = _samplingRate / 16000; HiddenUnits.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < HiddenUnitShape[1]; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) HiddenUnits.insert(HiddenUnits.end(), srcHiddenUnits.begin() + itS * HiddenUnitKDims, srcHiddenUnits.begin() + (itS + 1) * HiddenUnitKDims); HiddenUnitShape[1] *= upSample; HubertSize *= upSample; F0Data = GetInterpedF0(InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1]))); F0Shape[1] = HiddenUnitShape[1]; XLength[0] = HiddenUnitShape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, F0Data.data(), F0Data.size(), F0Shape, 2)); } else if (SoVits2) { HiddenUnits = std::move(srcHiddenUnits); F0Shape[1] = HiddenUnitShape[1]; F0Data = InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1])); XLength[0] = HiddenUnitShape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); Nsff0 = GetNSFF0(F0Data); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Nsff0.data(), Nsff0.size(), F0Shape, 2)); } else if (_modelType == modelType::RVC) { constexpr int64_t upSample = 2; HiddenUnits.reserve(HubertSize * (upSample + 1)); for (int64_t itS = 0; itS < HiddenUnitShape[1]; ++itS) for (int64_t itSS = 0; itSS < upSample; ++itSS) HiddenUnits.insert(HiddenUnits.end(), srcHiddenUnits.begin() + itS * HiddenUnitKDims, srcHiddenUnits.begin() + (itS + 1) * HiddenUnitKDims); HiddenUnitShape[1] *= upSample; HubertSize *= upSample; F0Data = InterpFunc(srcF0Data, long(srcF0Data.size()), long(HiddenUnitShape[1])); F0Shape[1] = HiddenUnitShape[1]; XLength[0] = HiddenUnitShape[1]; RandnCount = 192 * F0Shape[1]; RandnShape[2] = F0Shape[1]; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, XLength, 1, LengthShape, 1)); InterpedF0 = GetInterpedF0(F0Data); Nsff0 = GetNSFF0(InterpedF0); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Nsff0.data(), Nsff0.size(), F0Shape, 2)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), InterpedF0.size(), F0Shape, 2)); SoVitsInput = RVCInput; RandnInput = std::vector(RandnCount, 0.f); for (auto& it : RandnInput) it = normal(gen) * noise_scale; } else { HiddenUnits = std::move(srcHiddenUnits); F0Data = InterpFunc(srcF0Data, long(srcF0Data.size()), long(F0Shape[1])); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, HiddenUnits.data(), HubertSize, HiddenUnitShape, 3)); InterpedF0 = GetInterpedF0(F0Data); alignment = GetAligments(F0Shape[1], HubertLen); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, InterpedF0.data(), InterpedF0.size(), F0Shape, 2)); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, alignment.data(), InterpedF0.size(), F0Shape, 2)); if (!SoVitsDDSP) { UV = GetUV(F0Data); SoVitsInput = { "c", "f0", "mel2ph", "uv", "noise", "sid" }; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, UV.data(), UV.size(), F0Shape, 2)); } else { SoVitsInput = { "c", "f0", "mel2ph", "t_window", "noise", "sid" }; IstftInput = std::vector(IstftCount, ddsp_noise_scale); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, IstftInput.data(), IstftInput.size(), IstftShape, 3)); } RandnInput = std::vector(RandnCount, 0.f); for (auto& it : RandnInput) it = normal(gen) * noise_scale; _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RandnInput.data(), RandnCount, RandnShape, 3)); } if (EnableCharaMix) { if (SpeakerCount > 1) charaMix = GetCurrectSpkMixData(_Slice.Speaker[SliceIdx], F0Shape[1]); CharaMixShape[0] = F0Shape[1]; if (charaMix.empty()) { std::vector charaMap(SpeakerCount, 0.f); charaMap[charEmb] = 1.f; charaMix.reserve((SpeakerCount + 1) * F0Shape[1]); for (int64_t index = 0; index < F0Shape[1]; ++index) charaMix.insert(charaMix.end(), charaMap.begin(), charaMap.end()); } _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, charaMix.data(), charaMix.size(), CharaMixShape, 2)); } else _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, Chara, 1, CharaEmbShape, 1)); if (_modelType == modelType::RVC) _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RandnInput.data(), RandnCount, RandnShape, 3)); std::vector VolumeData; if (EnableVolume) { SoVitsInput.emplace_back("vol"); VolumeData = InterpFunc(_Slice.Volume[SliceIdx], long(_Slice.Volume[SliceIdx].size()), long(F0Shape[1])); _Tensors.emplace_back(Ort::Value::CreateTensor(*memory_info, VolumeData.data(), F0Shape[1], F0Shape, 2)); } return VitsSvcModel->Run(Ort::RunOptions{ nullptr }, SoVitsInput.data(), _Tensors.data(), _Tensors.size(), soVitsOutput.data(), soVitsOutput.size()); } */ #ifdef WIN32 #ifdef MoeVSMui void VitsSvc::StartRT(Mui::Window::UIWindowBasic* window, const MoeVSProjectSpace::MoeVSSvcParams& _Params) { if (RTSTAT) return; std::wstring error; recoder = new MRecorder(); recoder->InitRecorder(error, _samplingRate, 1, 16, Mui::_m_uint(_samplingRate * 0.5)); recoder->Start(); audio_player = new Mui::Render::MDS_AudioPlayer(window); audio_player->InitAudioPlayer(error); audio_stream = audio_player->CreateStreamPCM(recoder->GetFrameSize(), recoder->GetSampleRate(), recoder->GetChannels(), recoder->GetBitRate(), recoder->GetBlockAlign()); audio_player->PlayTrack(audio_stream); emptyLen = InferPCMData(std::vector(recoder->GetFrameSize() / 4 * 3), _samplingRate, _Params).size(); std::thread RT_RECORD_THREAD = std::thread([&]() { logger.log(L"[RTInference] Recording Thread Start!"); while (RTSTAT) { const auto PCM = recoder->GetStreamData(); if (!PCM) continue; rawInputBuffer.emplace_back((int16_t*)PCM->data, (int16_t*)(PCM->data + PCM->size)); delete PCM; } logger.log(L"[RTInference] Recording Thread End!"); }); std::thread RT_INPUT_CROSSFADE_THREAD = std::thread([&]() { logger.log(L"[RTInference] Input Crossfade Thread Start!"); //const auto config = _get_init_params(); while (RTSTAT) { if (rawInputBuffer.size() > 1) { std::vector pBuffer; pBuffer.reserve(2 * rawInputBuffer[0].size()); pBuffer.insert(pBuffer.end(), rawInputBuffer[0].begin(), rawInputBuffer[0].end()); pBuffer.insert(pBuffer.end(), rawInputBuffer[1].begin(), rawInputBuffer[1].begin() + int64_t(rawInputBuffer[1].size()) / 2); inputBuffer.emplace_back(std::move(pBuffer)); rawInputBuffer.pop_front(); } if (rawInputBuffer.size() > 100) { logger.log(L"[RTInferenceWarn] Raw Input Buffer Is Too Large"); } } logger.log(L"[RTInference] Input Crossfade Thread End!"); }); std::thread RT_INFERENCE_THREAD = std::thread([&]() { logger.log(L"[RTInference] Inferencing Thread Start!"); const auto PCMSIZE = recoder->GetFrameSize() / 2; while (RTSTAT) { //const auto configs = _get_init_params(); if (!inputBuffer.empty()) { try { bool zeroVector = true; for(const auto& i16data : inputBuffer[0]) { if(i16data> 1600) { zeroVector = false; break; } } if(zeroVector) rawOutputBuffer.emplace_back(std::vector(emptyLen, 0)); else { auto RtRES = InferPCMData(inputBuffer[0], _samplingRate, _Params); rawOutputBuffer.emplace_back(std::move(RtRES)); } inputBuffer.pop_front(); } catch (std::exception& e) { RTSTAT = false; inputBuffer.clear(); outputBuffer.clear(); rawInputBuffer.clear(); rawOutputBuffer.clear(); LibDLVoiceCodecThrow(e.what()); } } if (inputBuffer.size() > 100) { logger.log(L"[RTInferenceWarn] Input Buffer Is Too Large"); } } logger.log(L"[RTInference] Inferencing Thread End!"); }); std::thread RT_OUTPUT_CROSSFADE_THREAD = std::thread([&]() { logger.log(L"[RTInference] OutPut Crossfade Thread Start!"); while (RTSTAT) { if (rawOutputBuffer.size() > 1) { const auto cross_fade_size = int64_t(rawOutputBuffer[0].size()) / 3; const auto PCMSIZE = cross_fade_size * 2; for (int64_t i = 0; i < cross_fade_size; ++i) { rawOutputBuffer[0][PCMSIZE + i] = int16_t(((double)rawOutputBuffer[0][PCMSIZE + i] * (1.0 - (double(i) / double(cross_fade_size)))) + ((double)rawOutputBuffer[1][i] * (double(i) / double(cross_fade_size)))); rawOutputBuffer[1][PCMSIZE + i] = int16_t(((double)rawOutputBuffer[0][PCMSIZE + i] * (1.0 - (double(i) / double(cross_fade_size)))) + ((double)rawOutputBuffer[1][i] * (double(i) / double(cross_fade_size)))); } std::vector pBuffer(rawOutputBuffer[0].data() + cross_fade_size / 2, rawOutputBuffer[0].data() + 2 * cross_fade_size + cross_fade_size / 2); outputBuffer.emplace_back(std::move(pBuffer)); rawOutputBuffer.pop_front(); } } logger.log(L"[RTInference] OutPut Crossfade Thread End!"); }); std::thread RT_OUTPUT_THREAD = std::thread([&]() { logger.log(L"[RTInference] OutPut Thread Start!"); const auto PCMSIZE = recoder->GetFrameSize(); std::vector pBuffer(PCMSIZE); Mui::_m_size lastSize = 0; while (RTSTAT) { if (!outputBuffer.empty()) { //audio_player->WriteStreamPCM(audio_stream, (Mui::_m_byte*)outputBuffer.front().data(), Mui::_m_size(RTAudioSize)); //outputBuffer.pop_front(); auto queue_data = (Mui::_m_byte*)outputBuffer[0].data(); auto queue_dataSize = Mui::_m_size(outputBuffer[0].size() * 2); while (queue_dataSize + lastSize >= PCMSIZE) { //每次从队列中拿走帧大小的数据 const auto dataSize = PCMSIZE - lastSize; memcpy(pBuffer.data() + lastSize, queue_data, dataSize); //调用WriteStream 播放 audio_player->WriteStreamPCM(audio_stream, pBuffer.data(), PCMSIZE); //指针偏移 queue_data += dataSize; queue_dataSize -= dataSize; lastSize = 0; } //如果剩余数据不足PCMLength if (queue_dataSize > 0) { //检查本次queue能否把缓冲区填满 if (lastSize + queue_dataSize >= PCMSIZE) { //计算剩余空间 const auto dataSize = PCMSIZE - lastSize; //复制数据到buffer memcpy(pBuffer.data() + lastSize, queue_data, dataSize); audio_player->WriteStreamPCM(audio_stream, pBuffer.data(), PCMSIZE); queue_data += dataSize; queue_dataSize -= dataSize; lastSize = 0; } //如果剩余空间仍然不足PCMLength,将剩余数据复制到buffer中 等待下次循环 if (queue_dataSize > 0) { memcpy(pBuffer.data() + lastSize, queue_data, queue_dataSize); lastSize += queue_dataSize; } } logger.log(L"OUTPUTBUFFERLEN:" + std::to_wstring(outputBuffer.size())); logger.log(L"INPUTBUFFERLEN:" + std::to_wstring(inputBuffer.size())); outputBuffer.pop_front(); } } logger.log(L"[RTInference] OutPut Thread End!"); }); logger.log(L"[RTInference] Start RTInference!"); for (uint64_t idx = 0; idx < 1; ++idx) rawInputBuffer.emplace_back(recoder->GetFrameSize() / 2, 0); RTSTAT = true; RT_RECORD_THREAD.detach(); RT_INPUT_CROSSFADE_THREAD.detach(); RT_INFERENCE_THREAD.detach(); RT_OUTPUT_CROSSFADE_THREAD.detach(); RT_OUTPUT_THREAD.detach(); while (true); } void VitsSvc::EndRT() { recoder->Stop(); audio_player->StopTrack(audio_stream); audio_player->DeleteTrack(audio_stream); delete audio_stream; delete audio_player; delete recoder; audio_stream = nullptr; audio_player = nullptr; recoder = nullptr; if (RTSTAT) RTSTAT = false; inputBuffer.clear(); outputBuffer.clear(); rawInputBuffer.clear(); rawOutputBuffer.clear(); } #endif #endif MoeVoiceStudioCoreEnd ================================================ FILE: libsvc/Modules/src/Modules.cpp ================================================ #include "../header/Modules.hpp" #include "../header/InferTools/F0Extractor/DioF0Extractor.hpp" #include "../header/InferTools/F0Extractor/F0ExtractorManager.hpp" #include "../header/InferTools/TensorExtractor/MoeVSCoreTensorExtractor.hpp" #include "../header/InferTools/Cluster/MoeVSClusterManager.hpp" #include "../header/InferTools/Cluster/MoeVSKmeansCluster.hpp" #include "../header/InferTools/F0Extractor/HarvestF0Extractor.hpp" #include "../header/InferTools/Sampler/MoeVSSamplerManager.hpp" #include "../header/InferTools/Sampler/MoeVSSamplers.hpp" #include "../header/InferTools/F0Extractor/NetF0Predictors.hpp" #ifdef MoeVoiceStudioIndexCluster #ifdef max #undef max #endif #include "../header/InferTools/Cluster/MoeVSIndexCluster.hpp" #endif #define MoeVSRegisterF0Constructor(__RegisterName, __ClassName) MoeVSF0Extractor::RegisterF0Extractor(__RegisterName, \ [](int32_t sampling_rate, int32_t hop_size, \ int32_t n_f0_bins, double max_f0, double min_f0) \ -> MoeVSF0Extractor::F0Extractor \ { \ return new MoeVSF0Extractor::__ClassName(sampling_rate, hop_size, n_f0_bins, max_f0, min_f0); \ }) #define MoeVSRegisterTensorConstructor(__RegisterName, __ClassName) MoeVSTensorPreprocess::RegisterTensorExtractor(__RegisterName,\ [](uint64_t _srcsr, uint64_t _sr, uint64_t _hop, \ bool _smix, bool _volume, uint64_t _hidden_size, \ uint64_t _nspeaker, \ const MoeVSTensorPreprocess::MoeVoiceStudioTensorExtractor::Others& _other) \ ->MoeVSTensorPreprocess::TensorExtractor \ { \ return new MoeVSTensorPreprocess::__ClassName(_srcsr, _sr, _hop, _smix, _volume, \ _hidden_size, _nspeaker, _other); \ }) #define MoeVSRegisterCluster(__RegisterName, __ClassName) MoeVoiceStudioCluster::RegisterMoeVSCluster(__RegisterName,\ [](const std::wstring& _path, size_t hidden_size, size_t KmeansLen) \ ->MoeVoiceStudioCluster::MoeVSCluster \ { \ return new MoeVoiceStudioCluster::__ClassName(_path, hidden_size, KmeansLen); \ }) #define MoeVSRegisterSampler(__RegisterName, __ClassName) MoeVSSampler::RegisterMoeVSSampler(__RegisterName, \ [](Ort::Session* alpha, Ort::Session* dfn, Ort::Session* pred, int64_t Mel_Bins, \ const MoeVSSampler::MoeVSBaseSampler::ProgressCallback& _ProgressCallback, \ Ort::MemoryInfo* memory) -> MoeVSSampler::MoeVSSampler \ { \ return new MoeVSSampler::__ClassName(alpha, dfn, pred, Mel_Bins, _ProgressCallback, memory); \ }) #define MoeVSRegisterReflowSampler(__RegisterName, __ClassName) MoeVSSampler::RegisterMoeVSReflowSampler(__RegisterName, \ [](Ort::Session* velocity, int64_t Mel_Bins, \ const MoeVSSampler::MoeVSBaseSampler::ProgressCallback& _ProgressCallback, \ Ort::MemoryInfo* memory) -> MoeVSSampler::MoeVSReflowSampler \ { \ return new MoeVSSampler::__ClassName(velocity, Mel_Bins, _ProgressCallback, memory); \ }) namespace MoeVSModuleManager { MoeVoiceStudioCore::SingingVoiceConversion* UnionSvcModel::GetPtr() const { if (Diffusion_) return Diffusion_; return Reflow_; } std::vector UnionSvcModel::Inference(std::wstring& _Paths, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { if (Diffusion_) return Diffusion_->Inference(_Paths, _InferParams, _SlicerSettings); return Reflow_->Inference(_Paths, _InferParams, _SlicerSettings); } std::vector UnionSvcModel::InferPCMData(const std::vector& PCMData, long srcSr, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { if (Diffusion_) return Diffusion_->InferPCMData(PCMData, srcSr, _InferParams); return Reflow_->InferPCMData(PCMData, srcSr, _InferParams); } std::vector UnionSvcModel::ShallowDiffusionInference(std::vector& _16KAudioHubert, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, std::pair, int64_t>& _Mel, const std::vector& _SrcF0, const std::vector& _SrcVolume, const std::vector>& _SrcSpeakerMap, size_t& Process, int64_t SrcSize) const { if (Diffusion_) return Diffusion_->ShallowDiffusionInference(_16KAudioHubert, _InferParams, _Mel, _SrcF0, _SrcVolume, _SrcSpeakerMap, Process, SrcSize); return Reflow_->ShallowDiffusionInference(_16KAudioHubert, _InferParams, _Mel, _SrcF0, _SrcVolume, _SrcSpeakerMap, Process, SrcSize); } std::vector UnionSvcModel::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) const { if (Diffusion_) return Diffusion_->SliceInference(_Slice,_InferParams); return Reflow_->SliceInference(_Slice, _InferParams); } std::vector UnionSvcModel::SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) const { if (Diffusion_) return Diffusion_->SliceInference(_Slice, _InferParams, _Process); return Reflow_->SliceInference(_Slice, _InferParams, _Process); } UnionSvcModel::UnionSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID) { if (Config["Type"].GetString() == "DiffSvc") Diffusion_ = new MoeVoiceStudioCore::DiffusionSvc( Config, Callback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ); else if (Config["Type"].GetString() == "ReflowSvc") Reflow_ = new MoeVoiceStudioCore::ReflowSvc( Config, Callback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ); else LibDLVoiceCodecThrow("Trying To Load VitsSvc Model As Union Model!") } UnionSvcModel::UnionSvcModel(const MoeVoiceStudioCore::Hparams& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID) { if ((Config.TensorExtractor.find(L"Diff") != std::wstring::npos) || Config.TensorExtractor.find(L"diff") != std::wstring::npos) Diffusion_ = new MoeVoiceStudioCore::DiffusionSvc( Config, Callback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ); else Reflow_ = new MoeVoiceStudioCore::ReflowSvc( Config, Callback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ); } UnionSvcModel::~UnionSvcModel() { delete Diffusion_; delete Reflow_; Diffusion_ = nullptr; Reflow_ = nullptr; } int64_t UnionSvcModel::GetMaxStep() const { if (Diffusion_) return Diffusion_->GetMaxStep(); return Reflow_->GetMaxStep(); } bool UnionSvcModel::OldVersion() const { if (Diffusion_) return Diffusion_->OldVersion(); return false; } const std::wstring& UnionSvcModel::GetDiffSvcVer() const { if (Diffusion_) return Diffusion_->GetDiffSvcVer(); return Reflow_->GetReflowSvcVer(); } int64_t UnionSvcModel::GetMelBins() const { if (Diffusion_) return Diffusion_->GetMelBins(); return Reflow_->GetMelBins(); } int UnionSvcModel::GetHopSize() const { if (Diffusion_) return Diffusion_->GetHopSize(); return Reflow_->GetHopSize(); } int64_t UnionSvcModel::GetHiddenUnitKDims() const { if (Diffusion_) return Diffusion_->GetHiddenUnitKDims(); return Reflow_->GetHiddenUnitKDims(); } int64_t UnionSvcModel::GetSpeakerCount() const { if (Diffusion_) return Diffusion_->GetSpeakerCount(); return Reflow_->GetSpeakerCount(); } bool UnionSvcModel::CharaMixEnabled() const { if (Diffusion_) return Diffusion_->CharaMixEnabled(); return Reflow_->CharaMixEnabled(); } long UnionSvcModel::GetSamplingRate() const { if (Diffusion_) return Diffusion_->GetSamplingRate(); return Reflow_->GetSamplingRate(); } void UnionSvcModel::NormMel(std::vector& MelSpec) const { if (Diffusion_) return Diffusion_->NormMel(MelSpec); return Reflow_->NormMel(MelSpec); } bool UnionSvcModel::IsDiffusion() const { return Diffusion_; } } namespace MoeVSModuleManager { bool MoeVoiceStudioCoreInitStat = false; MoeVoiceStudioCore::VitsSvc* GlobalVitsSvcModel = nullptr; UnionSvcModel* GlobalUnionSvcModel = nullptr; MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback ProgessBar; int64_t SpeakerCount = 0; int64_t SamplingRate = 32000; int32_t VocoderHopSize = 512; int32_t VocoderMelBins = 128; int64_t VitsSamplingRate = 32000; int64_t& GetSamplingRate() { return SamplingRate; } int64_t& GetSpeakerCount() { return SpeakerCount; } int32_t& GetVocoderHopSize() { return VocoderHopSize; } int32_t& GetVocoderMelBins() { return VocoderMelBins; } void MoeVoiceStudioCoreInitSetup() { if (MoeVoiceStudioCoreInitStat) return; MoeVSRegisterF0Constructor(L"Dio", DioF0Extractor); MoeVSRegisterF0Constructor(L"Harvest", HarvestF0Extractor); MoeVSRegisterF0Constructor(L"RMVPE", RMVPEF0Extractor); MoeVSRegisterF0Constructor(L"FCPE", MELPEF0Extractor); MoeVSRegisterTensorConstructor(L"SoVits2.0", SoVits2TensorExtractor); MoeVSRegisterTensorConstructor(L"SoVits3.0", SoVits3TensorExtractor); MoeVSRegisterTensorConstructor(L"SoVits4.0", SoVits4TensorExtractor); MoeVSRegisterTensorConstructor(L"SoVits4.0-DDSP", SoVits4DDSPTensorExtractor); MoeVSRegisterTensorConstructor(L"RVC", RVCTensorExtractor); MoeVSRegisterTensorConstructor(L"DiffSvc", DiffSvcTensorExtractor); MoeVSRegisterTensorConstructor(L"DiffusionSvc", DiffusionSvcTensorExtractor); MoeVSRegisterCluster(L"KMeans", KMeansCluster); #ifdef MoeVoiceStudioIndexCluster MoeVSRegisterCluster(L"Index", IndexCluster); #endif MoeVSRegisterSampler(L"Pndm", PndmSampler); MoeVSRegisterSampler(L"DDim", DDimSampler); MoeVSRegisterReflowSampler(L"Eular", ReflowEularSampler); MoeVSRegisterReflowSampler(L"Rk4", ReflowRk4Sampler); MoeVSRegisterReflowSampler(L"Heun", ReflowHeunSampler); MoeVSRegisterReflowSampler(L"Pecece", ReflowPececeSampler); MoeVoiceStudioCoreInitStat = true; } MoeVoiceStudioCore::VitsSvc* GetVitsSvcModel() { return GlobalVitsSvcModel; } UnionSvcModel* GetUnionSvcModel() { return GlobalUnionSvcModel; } void UnloadVitsSvcModel() { delete GlobalVitsSvcModel; GlobalVitsSvcModel = nullptr; } void UnloadUnionSvcModel() { delete GlobalUnionSvcModel; GlobalUnionSvcModel = nullptr; } void LoadVitsSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID) { logger.log("[Model Loader] Bonding Progress Event"); ProgessBar = Callback; logger.log("[Model Loader] Progress Event Bonded"); UnloadVitsSvcModel(); logger.log("[Model Loader] Empty Cache!"); if (Config["Type"].GetString() == "DiffSvc") LibDLVoiceCodecThrow("Trying To Load Diffusion Model As VitsSvc Model!") GlobalVitsSvcModel = new MoeVoiceStudioCore::VitsSvc( Config, Callback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ); VitsSamplingRate = GlobalVitsSvcModel->GetSamplingRate(); SamplingRate = VitsSamplingRate; } void LoadUnionSvcModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID) { logger.log("[Model Loader] Bonding Progress Event"); ProgessBar = Callback; logger.log("[Model Loader] Progress Event Bonded"); UnloadUnionSvcModel(); logger.log("[Model Loader] Empty Cache!"); GlobalUnionSvcModel = new UnionSvcModel( Config, Callback, ProviderID, NumThread, DeviceID ); if (VocoderEnabled()) if (!GetVitsSvcModel() || (!GlobalUnionSvcModel->OldVersion() && GlobalUnionSvcModel->GetDiffSvcVer() == L"DiffusionSvc")) SamplingRate = GlobalUnionSvcModel->GetSamplingRate(); } void LoadVocoderModel(const std::wstring& VocoderPath) { MoeVoiceStudioCore::LoadVocoderModel(VocoderPath); } void UnloadVocoderModel() { MoeVoiceStudioCore::UnLoadVocoderModel(); } bool VocoderEnabled() { return MoeVoiceStudioCore::VocoderEnabled(); } std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcData& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams) { const bool DiffusionModelEnabled = GetUnionSvcModel() && VocoderEnabled(); std::vector RtnAudio; size_t TotalAudioSize = 0; for (const auto& data_size : _Slice.Slices) TotalAudioSize += data_size.OrgLen; RtnAudio.reserve(size_t(double(TotalAudioSize) * 1.5)); //VitsSteps int64_t GlobalSteps = 0; if (GlobalVitsSvcModel) GlobalSteps = 1; //DiffusionSteps auto SkipDiffusionStep = (int64_t)_InferParams.Pndm; auto DiffusionTotalStep = (int64_t)_InferParams.Step; if (DiffusionModelEnabled && DiffusionTotalStep > GetUnionSvcModel()->GetMaxStep()) DiffusionTotalStep = GetUnionSvcModel()->GetMaxStep(); if (SkipDiffusionStep >= DiffusionTotalStep) SkipDiffusionStep = DiffusionTotalStep / 5; if (SkipDiffusionStep == 0) SkipDiffusionStep = 1; auto RealDiffSteps = DiffusionTotalStep; if (GetUnionSvcModel() && GetUnionSvcModel()->IsDiffusion()) RealDiffSteps = DiffusionTotalStep % SkipDiffusionStep ? DiffusionTotalStep / SkipDiffusionStep + 1 : DiffusionTotalStep / SkipDiffusionStep; if((DiffusionModelEnabled && !GlobalVitsSvcModel) || (DiffusionModelEnabled && ShallowDiffusionEnabled())) { if (GetUnionSvcModel()->OldVersion()) GlobalSteps += 1; else GlobalSteps += RealDiffSteps; } //TotalSteps const int64_t TotalSteps = GlobalSteps * int64_t(_Slice.Slices.size()); size_t ProgressVal = 0; size_t SliceIndex = 0; ProgessBar(0, TotalSteps); for (const auto& CurSlice : _Slice.Slices) { const auto InferBeginTime = clock(); const auto CurRtn = SliceInference(CurSlice, _InferParams, ProgressVal); RtnAudio.insert(RtnAudio.end(), CurRtn.data(), CurRtn.data() + CurRtn.size()); if (CurSlice.IsNotMute) logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Segment[" + std::to_wstring(SliceIndex++) + L"] Finished! Segment Use Time: " + std::to_wstring(clock() - InferBeginTime) + L"ms, Segment Duration: " + std::to_wstring((size_t)CurSlice.OrgLen * 1000ull / 48000ull) + L"ms"); else { if (DiffusionModelEnabled && !GetUnionSvcModel()->OldVersion()) { ProgressVal += RealDiffSteps; ProgessBar(ProgressVal, TotalSteps); } logger.log(L"[Inferring] Inferring \"" + _Slice.Path + L"\", Jump Empty Segment[" + std::to_wstring(SliceIndex++) + L"]!"); } if (DiffusionModelEnabled && GetUnionSvcModel()->OldVersion()) ProgessBar(++ProgressVal, TotalSteps); if (GlobalVitsSvcModel) ProgessBar(++ProgressVal, TotalSteps); } logger.log(L"[Inferring] \"" + _Slice.Path + L"\" Finished"); return RtnAudio; } int CurStftSr = -1, CurHopSize = -1, CurMelBins = -1; DlCodecStft::Mel* MelOperator = nullptr; void ReloadMelOps(int SamplingRate_I64, int Hopsize_I64, int MelBins_I64) { if (CurStftSr != SamplingRate_I64 || CurHopSize != Hopsize_I64 || CurMelBins != MelBins_I64) { delete MelOperator; CurStftSr = SamplingRate_I64; CurHopSize = Hopsize_I64; CurMelBins = MelBins_I64; MelOperator = new DlCodecStft::Mel(Hopsize_I64 * 4, CurHopSize, CurStftSr, CurMelBins); } } DlCodecStft::Mel& GetMelOperator() { return *MelOperator; } std::vector Enhancer(std::vector& Mel, const std::vector& F0, size_t MelSize) { auto Rf0 = F0; if (Rf0.size() != MelSize) Rf0 = InferTools::InterpFunc(Rf0, (long)Rf0.size(), (long)MelSize); return MoeVoiceStudioCore::VocoderInfer( Mel, Rf0, VocoderMelBins, (int64_t)MelSize, GlobalVitsSvcModel->GetMemoryInfo() ); } std::vector SliceInference(const MoeVSProjectSpace::MoeVoiceStudioSvcSlice& _Slice, const MoeVSProjectSpace::MoeVSSvcParams& _InferParams, size_t& _Process) { const bool DiffusionModelEnabled = GetUnionSvcModel() && VocoderEnabled(); int64_t SamplingRate_I64 = VitsSamplingRate; SamplingRate = VitsSamplingRate; if ((DiffusionModelEnabled && !GlobalVitsSvcModel) || (_InferParams.UseShallowDiffusion && DiffusionModelEnabled && ShallowDiffusionEnabled())) { SamplingRate_I64 = GetUnionSvcModel()->GetSamplingRate(); SamplingRate = GetUnionSvcModel()->GetSamplingRate(); } if (!_Slice.IsNotMute) return { size_t(_Slice.OrgLen * SamplingRate_I64 / 48000), 0i16, std::allocator() }; std::vector RtnAudio; RtnAudio.reserve(size_t(double(_Slice.Audio.size()) * 1.5)); if (GlobalVitsSvcModel) { auto BgnTime = clock(); if(_InferParams.UseShallowDiffusion && DiffusionModelEnabled && !GetUnionSvcModel()->OldVersion() && GetUnionSvcModel()->GetDiffSvcVer() == L"DiffusionSvc") { auto SpcParams = _InferParams; SpcParams._ShallowDiffusionModel = GetUnionSvcModel(); SpcParams.VocoderSamplingRate = (int)SamplingRate_I64; SpcParams.VocoderHopSize = GetUnionSvcModel()->GetHopSize(); SpcParams.VocoderMelBins = (int)GetUnionSvcModel()->GetMelBins(); std::swap(SpcParams.SpeakerId, SpcParams.ShallowDiffuisonSpeaker); RtnAudio = GlobalVitsSvcModel->SliceInference(_Slice, SpcParams, _Process); } else if(_InferParams.UseShallowDiffusion && VocoderEnabled() && !GetUnionSvcModel()) { auto SpcParams = _InferParams; SpcParams.VocoderSamplingRate = (int)SamplingRate_I64; SpcParams.VocoderHopSize = VocoderHopSize; SpcParams.VocoderMelBins = VocoderMelBins; SpcParams._VocoderModel = MoeVoiceStudioCore::GetCurrentVocoder(); RtnAudio = GlobalVitsSvcModel->SliceInference(_Slice, SpcParams, _Process); } else RtnAudio = GlobalVitsSvcModel->SliceInference(_Slice, _InferParams, _Process); logger.log(("[Inference] Slice Vits Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); } else if (DiffusionModelEnabled) { const auto BgnTime = clock(); RtnAudio = GetUnionSvcModel()->SliceInference(_Slice, _InferParams, _Process); logger.log(("[Inference] Slice Diffusion Use Time " + std::to_string(clock() - BgnTime) + "ms").c_str()); } else LibDLVoiceCodecThrow("You Must Load A Model To Inference!"); return RtnAudio; } bool ShallowDiffusionEnabled() { const bool DiffusionModelEnabled = GetUnionSvcModel() && VocoderEnabled(); return DiffusionModelEnabled && !GetUnionSvcModel()->OldVersion() && GetUnionSvcModel()->GetDiffSvcVer() == L"DiffusionSvc"; } } ================================================ FILE: libsvc/Modules/src/StringPreprocess.cpp ================================================ #include "../header/StringPreprocess.hpp" #ifdef _WIN32 #include #else #error #endif std::string to_byte_string(const std::wstring& input) { std::vector ByteString(input.length() * 6); WideCharToMultiByte( CP_UTF8, 0, input.c_str(), int(input.length()), ByteString.data(), int(ByteString.size()), nullptr, nullptr ); return ByteString.data(); } std::string to_ansi_string(const std::wstring& input) { std::vector ByteString(input.length() * 6); WideCharToMultiByte( CP_ACP, 0, input.c_str(), int(input.length()), ByteString.data(), int(ByteString.size()), nullptr, nullptr ); return ByteString.data(); } std::wstring to_wide_string(const std::string& input) { std::vector WideString(input.length() * 2); MultiByteToWideChar( CP_UTF8, 0, input.c_str(), int(input.length()), WideString.data(), int(WideString.size()) ); return WideString.data(); } std::wstring string_vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) if (!it.empty()) vecstr += L'\"' + to_wide_string(it) + L"\", "; if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } std::wstring wstring_vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) if (!it.empty()) vecstr += L'\"' + it + L"\", "; if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } ================================================ FILE: libsvc/README.md ================================================ # 使用方法 ### 构建 - 1、配置以下依赖: - [ffmpeg](https://ffmpeg.org/) - [onnxruntime](https://github.com/microsoft/onnxruntime) - [fftw](http://fftw.org/) - [openblas](https://github.com/OpenMathLib/OpenBLAS) - [faiss](https://github.com/facebookresearch/faiss) - [liblapack](https://netlib.org/lapack/) - 2、编译 --- ### 使用动态库 - 1、链接libsvc - 2、#include "libsvc/Api/header/libsvc.h" - 3、调用libsvc::Init() - 4、调用libsvc名称空间中的函数 ================================================ FILE: libsvc/dllmain.cpp ================================================ // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "Windows.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } ================================================ FILE: libsvc/libsvc.vcxproj ================================================ DebugLib Win32 DebugLib x64 Debug Win32 ReleaseLib Win32 ReleaseLib x64 Release Win32 Debug x64 Release x64 16.0 Win32Proj {dc31109b-1984-41db-bd9f-4261675c3962} libsvc 10.0 DynamicLibrary true v143 Unicode DynamicLibrary true v143 Unicode DynamicLibrary false v143 true Unicode DynamicLibrary false v143 true Unicode DynamicLibrary true v143 Unicode StaticLibrary true v143 Unicode DynamicLibrary false v143 true Unicode true StaticLibrary false v143 true Unicode true $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)libsvc\Modules\Lib\World\src\world;$(SolutionDir)Lib\ffmpeg-4.2.1\include;$(SolutionDir)libsvc\Modules\Lib\MJson;$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)Lib\faiss;$(SolutionDir)Lib\openblas\include;$(SolutionDir)Lib\stft;$(IncludePath) $(SolutionDir)$(Platform)\libsvc\$(Configuration)\ $(Platform)\libsvc\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)libsvc\Modules\Lib\World\src\world;$(SolutionDir)Lib\ffmpeg-4.2.1\include;$(SolutionDir)libsvc\Modules\Lib\MJson;$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)Lib\faiss;$(SolutionDir)Lib\openblas\include;$(SolutionDir)Lib\stft;$(IncludePath) $(SolutionDir)$(Platform)\libsvc\$(Configuration)\ $(Platform)\libsvc\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)libsvc\Modules\Lib\World\src\world;$(SolutionDir)Lib\ffmpeg-4.2.1\include;$(SolutionDir)libsvc\Modules\Lib\MJson;$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)Lib\faiss;$(SolutionDir)Lib\openblas\include;$(SolutionDir)Lib\stft;$(IncludePath) $(SolutionDir)$(Platform)\libsvc\$(Configuration)\ $(Platform)\libsvc\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)libsvc\Modules\Lib\World\src\world;$(SolutionDir)Lib\ffmpeg-4.2.1\include;$(SolutionDir)libsvc\Modules\Lib\MJson;$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)Lib\faiss;$(SolutionDir)Lib\openblas\include;$(SolutionDir)Lib\stft;$(IncludePath) $(SolutionDir)$(Platform)\libsvc\$(Configuration)\ $(Platform)\libsvc\$(Configuration)\ Level3 true WIN32;_DEBUG;LIBSVC_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true Use pch.h Windows true false Level3 true WIN32;_DEBUG;LIBSVC_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true Use pch.h Windows true false Level3 true true true WIN32;NDEBUG;LIBSVC_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true Use pch.h Windows true true true false Level3 true true true WIN32;NDEBUG;LIBSVC_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true Use pch.h Windows true true true false Level3 true _DEBUG;LIBSVC_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;MoeVoiceStudioIndexCluster;LibSvcDll;YYJSON_EXPORTS;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 $(SolutionDir)Lib;%(AdditionalIncludeDirectories) MultiThreadedDebug Windows true false $(SolutionDir)Lib\ffmpeg-4.2.1\Lib;$(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native;$(SolutionDir)Lib\;$(SolutionDir)Lib\openblas\lib;$(SolutionDir)Lib\stft;%(AdditionalLibraryDirectories) avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;onnxruntime.lib;fftw3.lib;libopenblas.lib;%(AdditionalDependencies) Level3 true _DEBUG;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;MoeVoiceStudioIndexCluster;LibSvcStaticLib;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 $(SolutionDir)Lib;%(AdditionalIncludeDirectories) MultiThreadedDebug Windows true false $(SolutionDir)Lib\ffmpeg-4.2.1\Lib;$(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native;$(SolutionDir)Lib\;$(SolutionDir)Lib\openblas\lib;$(SolutionDir)Lib\stft;%(AdditionalLibraryDirectories) avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;onnxruntime.lib;fftw3.lib;libopenblas.lib;%(AdditionalDependencies) Level3 true true true NDEBUG;LIBSVC_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;MoeVoiceStudioIndexCluster;LibSvcDll;YYJSON_EXPORTS;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 $(SolutionDir)Lib;%(AdditionalIncludeDirectories) MultiThreaded Windows true true true false $(SolutionDir)Lib\ffmpeg-4.2.1\Lib;$(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native;$(SolutionDir)Lib\;$(SolutionDir)Lib\openblas\lib;$(SolutionDir)Lib\stft;%(AdditionalLibraryDirectories) avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;onnxruntime.lib;fftw3.lib;libopenblas.lib;%(AdditionalDependencies) Level3 true true true NDEBUG;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;MoeVoiceStudioIndexCluster;LibSvcStaticLib;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 $(SolutionDir)Lib;%(AdditionalIncludeDirectories) MultiThreaded Windows true true true false $(SolutionDir)Lib\ffmpeg-4.2.1\Lib;$(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native;$(SolutionDir)Lib\;$(SolutionDir)Lib\openblas\lib;$(SolutionDir)Lib\stft;%(AdditionalLibraryDirectories) avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;onnxruntime.lib;fftw3.lib;libopenblas.lib;%(AdditionalDependencies) 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 ================================================ FILE: libsvc/libsvc.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {fb0b5757-fc04-4d88-8597-2d94fe79e2cc} {54cbaedb-ecbf-4fb3-87b5-36ebc8c6cfce} {9b0ef72f-b6a6-40a5-b235-1976820fe35c} {aad5c051-397f-436b-9b11-fec3ca01aa9c} {6cfaac44-b900-49e1-8fc9-35f8f9ab6e18} {9e2f1339-c577-45aa-a509-5dddb4d9d542} {eb24584c-3751-4dbe-823e-90d25c93772e} {c4adc16a-e759-4f1c-b5e6-3d76f4505e02} {c7deefd2-d55c-4b5a-80d8-1cac74f545cc} {e99697a0-cd74-43bc-ae4c-bfa1299311f4} {df45b238-81cd-49bf-bf84-ec6e97b35b83} {d98ecef8-77c5-4e4a-915c-4d71f0ea665d} {4a90fefb-d821-42c0-aba2-b31ba87ffaaa} {8c7cf0e0-76ea-40a0-82de-2e020b44c65f} {c579373a-26a1-4979-b8ba-93b8aee12708} {94e998a7-0897-4c87-9ee0-1426f372b6b0} {3d85cc85-c9e7-4d29-92a2-57b044c10fc8} {7ce28dec-70cd-445a-9a99-b11ebfc0635e} {65e1efd6-d194-4317-abb3-fa252719bef8} {d60edd1b-50d6-4880-a09e-6f1a1d8b4f70} {cfa6e269-3e22-43ed-8f28-fd50b9bf9d18} {965d3ac6-1a15-45bf-890e-af0cf1e0e3c4} {01dc10ac-ad67-4d10-b7a7-92cb14cf5fe3} {c1060cbd-4688-4a7d-88f7-d81f38533cb8} {7e0d0066-c7ce-4445-a80c-d93cda1fc5fe} {6c8a8d59-2b2b-4b2f-8dbb-3ccc3f802e9a} {bc3612f1-00b0-4d01-97b0-2eb66f7b33be} {3405ef93-0ba8-495b-9110-22b821411ce9} {e5b4addf-6f94-41ac-8186-49efa1f37d72} {c1f11d2a-5fb5-4480-b895-2e26036943b5} 头文件\Modules\Models 头文件\Modules\Models 头文件\Modules\Models 头文件\Modules\Models 头文件\Modules\Models 头文件\Modules\Models 头文件\Modules 头文件\Modules 头文件\Modules\Logger 头文件\Modules\InferTools\AVCodec 头文件\Modules\InferTools\Cluster 头文件\Modules\InferTools\Cluster 头文件\Modules\InferTools\Cluster 头文件\Modules\InferTools\Cluster 头文件\Modules\InferTools\DataStruct 头文件\Modules\InferTools\F0Extractor 头文件\Modules\InferTools\F0Extractor 头文件\Modules\InferTools\F0Extractor 头文件\Modules\InferTools\F0Extractor 头文件\Modules\InferTools\F0Extractor 头文件\Modules\InferTools\Sampler 头文件\Modules\InferTools\Sampler 头文件\Modules\InferTools\Sampler 头文件\Modules\InferTools\Stft 头文件\Modules\InferTools\TensorExtractor 头文件\Modules\InferTools\TensorExtractor 头文件\Modules\InferTools\TensorExtractor 头文件\Modules\InferTools 头文件 头文件\Lib\Json 头文件\Lib\Json 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\Lib\World 头文件\API 头文件\Modules\Models 头文件\API 源文件 源文件\Modules\Models 源文件\Modules\Models 源文件\Modules\Models 源文件\Modules\Models 源文件\Modules\Models 源文件\Modules\Models 源文件\Modules\Logger 源文件\Modules\InferTools 源文件\Modules\InferTools\TensorExtractor 源文件\Modules\InferTools\TensorExtractor 源文件\Modules\InferTools\TensorExtractor 源文件\Modules\InferTools\Stft 源文件\Modules\InferTools\Sampler 源文件\Modules\InferTools\Sampler 源文件\Modules\InferTools\Sampler 源文件\Modules\InferTools\F0Extractor 源文件\Modules\InferTools\F0Extractor 源文件\Modules\InferTools\F0Extractor 源文件\Modules\InferTools\F0Extractor 源文件\Modules\InferTools\F0Extractor 源文件\Modules\InferTools\DataStruct 源文件\Modules\InferTools\Cluster 源文件\Modules\InferTools\Cluster 源文件\Modules\InferTools\Cluster 源文件\Modules\InferTools\Cluster 源文件\Modules\InferTools\AVCodec 源文件\Modules 源文件\Modules 源文件\Lib\Json 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\World 源文件\Lib\Json 源文件\API 源文件\Modules\Models 源文件\API ================================================ FILE: libsvc/packages.config ================================================  ================================================ FILE: libtts/Api/NativeApi.cpp ================================================ #include "NativeApi.h" #include #include "../Modules/Modules.hpp" #include "../Modules/Models/EnvManager.hpp" struct LibTTSParams { float NoiseScale = 0.3f; // 0-10 int64_t Seed = 52468; // int64_t SpeakerId = 0; //ɫID uint64_t SrcSamplingRate = 48000; //Դ int64_t SpkCount = 2; //ģͽɫ std::vector SpeakerMix; //ɫϱ float LengthScale = 1.0f; //ʱ float DurationPredictorNoiseScale = 0.8f; //ʱԤ float FactorDpSdp = 0.f; //ʱԤʱԤϱ float RestTime = 0.5f; //ͣʱ䣬ΪֱӶϿƵƵ float GateThreshold = 0.66666f; //Tacotron2EOSֵ int64_t MaxDecodeStep = 2000; //Tacotron2벽 std::vector EmotionPrompt; //б std::wstring PlaceHolderSymbol = L"|"; //طָ std::string LanguageSymbol = "JP"; // std::wstring AdditionalInfo = L""; //G2PϢ std::wstring SpeakerName = L"0"; //ɫ }; struct LibTTSToken { std::wstring Text; //ı std::vector Phonemes; // std::vector Tones; // std::vector Durations; //ʱ std::vector Language; // }; struct LibTTSSeq { std::wstring TextSeq; std::vector SlicedTokens; std::vector SpeakerMix; //ɫϱ std::vector EmotionPrompt; //б std::wstring PlaceHolderSymbol = L"|"; //طָ float NoiseScale = 0.3f; // 0-10 float LengthScale = 1.0f; //ʱ float DurationPredictorNoiseScale = 0.3f; //ʱԤ float FactorDpSdp = 0.3f; //ʱԤʱԤϱ float GateThreshold = 0.66666f; //Tacotron2EOSֵ int64_t MaxDecodeStep = 2000; //Tacotron2벽 int64_t Seed = 52468; // float RestTime = 0.5f; //ͣʱ䣬ΪֱӶϿƵƵ std::string LanguageSymbol = "ZH"; //Ա std::wstring SpeakerName = L"0"; //ɫID std::wstring AdditionalInfo = L""; //G2PϢ }; const wchar_t* LibTTSNullString = L""; #define LibTTSNullStrCheck(Str) ((Str)?(Str):(LibTTSNullString)) std::deque ErrorQueue; size_t MaxErrorCount = 20; std::mutex ErrorMx; void RaiseError(const std::wstring& _Msg) { logger.log(_Msg); ErrorMx.lock(); ErrorQueue.emplace_front(_Msg); if (ErrorQueue.size() > MaxErrorCount) ErrorQueue.pop_back(); } void LibTTSInit() { MoeVSModuleManager::MoeVoiceStudioCoreInitSetup(); } INT32 LibTTSSetGlobalEnv(UINT32 ThreadCount, UINT32 DeviceID, UINT32 Provider) { try { moevsenv::GetGlobalMoeVSEnv().Load(ThreadCount, DeviceID, Provider); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } BSTR LibTTSGetError(size_t Index) { const auto& Ref = ErrorQueue.at(Index); auto Ret = SysAllocString(Ref.c_str()); ErrorQueue.erase(ErrorQueue.begin() + ptrdiff_t(Index)); ErrorMx.unlock(); return Ret; } void* LibTTSLoadVocoder(LPWSTR VocoderPath) { if (!VocoderPath) { RaiseError(L"VocoderPath Could Not Be Null"); return nullptr; } const auto& Env = moevsenv::GetGlobalMoeVSEnv(); try { return new Ort::Session(*Env.GetEnv(), VocoderPath, *Env.GetSessionOptions()); } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return nullptr; } } INT32 LibTTSUnloadVocoder(void* _Model) { try { delete (Ort::Session*)_Model; } catch (std::exception& e) { RaiseError(to_wide_string(e.what())); return 1; } return 0; } void LibTTSEnableFileLogger(bool _Cond) { MoeSSLogger::GetLogger().enable(_Cond); } void LibTTSWriteAudioFile(void* _PCMData, LPWSTR _OutputPath, INT32 _SamplingRate) { InferTools::Wav::WritePCMData(_SamplingRate, 1, *(std::vector*)(_PCMData), _OutputPath); } ================================================ FILE: libtts/Api/NativeApi.h ================================================ #pragma once #include "../../framework.h" #include "windows.h" #ifdef __cplusplus extern "C" { #endif typedef void(*LibTTSProgCallback)(size_t, size_t); enum LibTTSExecutionProviders { CPU = 0, CUDA = 1, DML = 2 }; enum LibTTSModelType { Vits, GptSoVits }; #ifdef _MSC_VER #pragma pack(push, 4) #else #pragma pack(4) #endif struct LibTTSParams; struct LibTTSToken; struct LibTTSSeq; struct DiffusionSvcPaths { LPWSTR Encoder = nullptr; LPWSTR Denoise = nullptr; LPWSTR Pred = nullptr; LPWSTR After = nullptr; LPWSTR Alpha = nullptr; LPWSTR Naive = nullptr; LPWSTR DiffSvc = nullptr; }; struct ReflowSvcPaths { LPWSTR Encoder = nullptr; LPWSTR VelocityFn = nullptr; LPWSTR After = nullptr; }; struct LibTTSHparams { LPWSTR TensorExtractor = nullptr; DiffusionSvcPaths DiffusionSvc; ReflowSvcPaths ReflowSvc; INT32 SamplingRate = 22050; INT32 HopSize = 320; INT64 HiddenUnitKDims = 256; INT64 SpeakerCount = 1; INT32 EnableCharaMix = false; INT32 EnableVolume = false; INT32 VaeMode = true; INT64 MelBins = 128; INT64 Pndms = 100; INT64 MaxStep = 1000; float SpecMin = -12; float SpecMax = 2; float Scale = 1000.f; }; #ifdef _MSC_VER #pragma pack(pop) #else #pragma pack() #endif /******************************************Fun**********************************************/ LibTTSApi void LibTTSInit(); LibTTSApi INT32 LibTTSSetGlobalEnv(UINT32 ThreadCount, UINT32 DeviceID, UINT32 Provider); LibTTSApi void LibTTSSetMaxErrorCount(size_t Count); LibTTSApi BSTR LibTTSGetError(size_t Index); LibTTSApi void* LibTTSLoadModel( UINT32 _T, const void* _Config, LibTTSProgCallback _ProgressCallback, UINT32 _ExecutionProvider = CPU, UINT32 _DeviceID = 0, UINT32 _ThreadCount = 0 ); LibTTSApi INT32 LibTTSUnloadModel( UINT32 _T, void* _Model ); LibTTSApi void* LibTTSLoadVocoder(LPWSTR VocoderPath); LibTTSApi INT32 LibTTSUnloadVocoder(void* _Model); LibTTSApi void LibTTSEnableFileLogger(bool _Cond); LibTTSApi void LibTTSWriteAudioFile(void* _PCMData, LPWSTR _OutputPath, INT32 _SamplingRate); #ifdef __cplusplus } #endif ================================================ FILE: libtts/Modules/AvCodec/AvCodeResample.h ================================================ #pragma once #include #include #include "../StringPreprocess.hpp" #include "matlabfunctions.h" #include "../InferTools/inferTools.hpp" extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "libswresample/swresample.h" #include "libavutil/samplefmt.h" } class AudioPreprocess { public: struct WAV_HEADER { char RIFF[4] = { 'R','I','F','F' }; //RIFF标识 unsigned long ChunkSize; //文件大小-8 char WAVE[4] = { 'W','A','V','E' }; //WAVE块 char fmt[4] = { 'f','m','t',' ' }; //fmt块 unsigned long Subchunk1Size; //fmt块大小 unsigned short AudioFormat; //编码格式 unsigned short NumOfChan; //声道数 WAV_HEADER(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1) :ChunkSize(cs), Subchunk1Size(sc1s), AudioFormat(af), NumOfChan(nc) {} }; static WAV_HEADER GetHeader(const std::wstring& path) { WAV_HEADER header; char buf[1024]; FILE* stream; _wfreopen_s(&stream, path.c_str(), L"rb", stderr); if (stream == nullptr) { throw (std::exception("Wav Load Error")); } fread(buf, 1, 1024, stream); int pos = 0; while (pos < InferTools::Wav::HEAD_LENGTH) { if ((buf[pos] == 'R') && (buf[pos + 1] == 'I') && (buf[pos + 2] == 'F') && (buf[pos + 3] == 'F')) { pos += 4; break; } ++pos; } if (pos >= InferTools::Wav::HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.ChunkSize = *(int*)&buf[pos]; pos += 8; while (pos < InferTools::Wav::HEAD_LENGTH) { if ((buf[pos] == 'f') && (buf[pos + 1] == 'm') && (buf[pos + 2] == 't')) { pos += 4; break; } ++pos; } if (pos >= InferTools::Wav::HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk1Size = *(int*)&buf[pos]; pos += 4; header.AudioFormat = *(short*)&buf[pos]; pos += 2; header.NumOfChan = *(short*)&buf[pos]; if (stream != nullptr) { fclose(stream); } return header; } static std::vector arange(double start, double end, double step = 1.0, double div = 1.0) { std::vector output; while (start < end) { output.push_back(start / div); start += step; } return output; } std::vector codec(const std::wstring& path, int sr) { //if (path.substr(path.rfind(L'.')) == L".wav") // return resample(path, sr); std::vector outData; int ret = avformat_open_input(&avFormatContext, to_byte_string(path).c_str(), nullptr, nullptr); if (ret != 0) { LibDLVoiceCodecThrow((std::string("Can't Open Audio File [ErrCode]")+std::to_string(ret)).c_str()) } ret = avformat_find_stream_info(avFormatContext, nullptr); if (ret < 0) { LibDLVoiceCodecThrow("Can't Get Audio Info") } int streamIndex = 0; for (unsigned i = 0; i < avFormatContext->nb_streams; ++i) { const AVMediaType avMediaType = avFormatContext->streams[i]->codecpar->codec_type; if (avMediaType == AVMEDIA_TYPE_AUDIO) { streamIndex = static_cast(i); } } const AVCodecParameters* avCodecParameters = avFormatContext->streams[streamIndex]->codecpar; const AVCodecID avCodecId = avCodecParameters->codec_id; const AVCodec* avCodec = avcodec_find_decoder(avCodecId); if (avCodec == nullptr) LibDLVoiceCodecThrow("Don't order fried rice (annoyed)") if (avCodecContext == nullptr) { LibDLVoiceCodecThrow("Can't Get Decoder Info") } avcodec_parameters_to_context(avCodecContext, avCodecParameters); ret = avcodec_open2(avCodecContext, avCodec, nullptr); if (ret < 0) { LibDLVoiceCodecThrow("Can't Open Decoder") } packet = (AVPacket*)av_malloc(sizeof(AVPacket)); const AVSampleFormat inFormat = avCodecContext->sample_fmt; constexpr AVSampleFormat outFormat = AV_SAMPLE_FMT_S16; const int inSampleRate = avCodecContext->sample_rate; const int outSampleRate = sr; const auto nSample = static_cast(avFormatContext->duration * sr / AV_TIME_BASE); uint64_t in_ch_layout = avCodecContext->channel_layout; if (path.substr(path.rfind(L'.')) == L".wav") { const auto head = GetHeader(path); if (head.NumOfChan == 1) in_ch_layout = AV_CH_LAYOUT_MONO; else if (head.NumOfChan == 2) in_ch_layout = AV_CH_LAYOUT_STEREO; else LibDLVoiceCodecThrow("unsupported Channel Num") } constexpr uint64_t out_ch_layout = AV_CH_LAYOUT_MONO; swr_alloc_set_opts(swrContext, out_ch_layout, outFormat, outSampleRate, static_cast(in_ch_layout), inFormat, inSampleRate, 0, nullptr ); swr_init(swrContext); const int outChannelCount = av_get_channel_layout_nb_channels(out_ch_layout); int currentIndex = 0; out_buffer = (uint8_t*)av_malloc(2ull * sr); while (av_read_frame(avFormatContext, packet) >= 0) { if (packet->stream_index == streamIndex) { avcodec_send_packet(avCodecContext, packet); ret = avcodec_receive_frame(avCodecContext, inFrame); if (ret == 0) { swr_convert(swrContext, &out_buffer, 2ull * sr, (const uint8_t**)inFrame->data, inFrame->nb_samples); const int out_buffer_size = av_samples_get_buffer_size(nullptr, outChannelCount, (inFrame->nb_samples * sr / inSampleRate) - 1, outFormat, 1); outData.insert(outData.end(), out_buffer, out_buffer + out_buffer_size); } ++currentIndex; av_packet_unref(packet); } } //Wav outWav(static_cast(sr), static_cast(outData.size()), outData.data()); auto outWav = reinterpret_cast(outData.data()); const auto RawWavLen = int64_t(outData.size()) / 2; if (nSample != static_cast(RawWavLen)) { const double interpOff = static_cast(RawWavLen) / static_cast(nSample); const auto x0 = arange(0.0, static_cast(RawWavLen), 1.0, 1.0); std::vector y0(RawWavLen); for (int64_t i = 0; i < RawWavLen; ++i) y0[i] = outWav[i] ? static_cast(outWav[i]) : NAN; const auto yi = new double[nSample]; auto xi = arange(0.0, static_cast(RawWavLen), interpOff, 1.0); while (xi.size() < nSample) xi.push_back(*(xi.end() - 1) + interpOff); while (xi.size() > nSample) xi.pop_back(); interp1(x0.data(), y0.data(), static_cast(RawWavLen), xi.data(), static_cast(nSample), yi); std::vector DataChun(nSample); for (size_t i = 0; i < nSample; ++i) DataChun[i] = isnan(yi[i]) ? 0i16 : static_cast(yi[i]); delete[] yi; return DataChun; } release(); return { outWav , outWav + RawWavLen }; } void release() { if (packet) av_packet_free(&packet); if (inFrame) av_frame_free(&inFrame); if (out_buffer) av_free(out_buffer); if (swrContext) swr_free(&swrContext); if (avCodecContext) avcodec_close(avCodecContext); if (avFormatContext) avformat_close_input(&avFormatContext); inFrame = nullptr; out_buffer = nullptr; swrContext = nullptr; avCodecContext = nullptr; avFormatContext = nullptr; packet = nullptr; } void init() { inFrame = av_frame_alloc(); out_buffer = nullptr; swrContext = swr_alloc(); avCodecContext = avcodec_alloc_context3(nullptr); avFormatContext = avformat_alloc_context(); packet = nullptr; } AudioPreprocess() { inFrame = av_frame_alloc(); out_buffer = nullptr; swrContext = swr_alloc(); avCodecContext = avcodec_alloc_context3(nullptr); avFormatContext = avformat_alloc_context(); packet = nullptr; } ~AudioPreprocess() { release(); } private: AVFrame* inFrame; uint8_t* out_buffer; SwrContext* swrContext; AVCodecContext* avCodecContext; AVFormatContext* avFormatContext; AVPacket* packet; }; ================================================ FILE: libtts/Modules/AvCodec/Recorder.cpp ================================================ #include "Recorder.h" MRecorder::~MRecorder() { //释放录制线程 m_runing = false; m_iscapture = true; if (m_thread) { m_signal.notify_all(); m_thread->join(); delete m_thread; } //释放设备资源 if (m_event[0]) { for (Mui::_m_byte i = 0; i < 2; i++) { SetEvent(m_event[i]); CloseHandle(m_event[i]); } } if (m_captureBuffer) m_captureBuffer->Release(); if (m_captureDriver) m_captureDriver->Release(); //释放队列数据 while (true) { const auto data = GetStreamData(); delete data; if (!data) break; } } bool MRecorder::InitRecorder(std::wstring& error, Mui::_m_uint sampleRate, Mui::_m_byte channels, Mui::_m_byte bit, Mui::_m_uint fs) { if (m_captureDriver && m_captureBuffer) { error = L"Initialized"; return false; } CoInitializeEx(nullptr, COINIT_MULTITHREADED); //创建录音设备 HRESULT hr = DirectSoundCaptureCreate(nullptr, &m_captureDriver, nullptr); if (FAILED(hr)) { error = L"DirectSoundCaptureCreate failed!"; return false; } if(sampleRate != 0) m_sampleRate = sampleRate; if(channels != 0) m_channels = channels; if(bit != 0) m_bit = bit; //创建录音缓冲区 m_blockAlign = 2 * m_channels; WAVEFORMATEX wavFormatEx; wavFormatEx.wFormatTag = WAVE_FORMAT_PCM; wavFormatEx.nChannels = m_channels; wavFormatEx.nSamplesPerSec = m_sampleRate; wavFormatEx.nAvgBytesPerSec = m_sampleRate * m_blockAlign; wavFormatEx.nBlockAlign = WORD(m_blockAlign); wavFormatEx.wBitsPerSample = m_bit; m_frameSize = fs*2; DSCBUFFERDESC dsBufferDesc = { sizeof(DSCBUFFERDESC) }; dsBufferDesc.lpwfxFormat = &wavFormatEx; dsBufferDesc.dwBufferBytes = m_frameSize * 2; //dsBufferDesc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY; hr = m_captureDriver->CreateCaptureBuffer(&dsBufferDesc, &m_captureBuffer, nullptr); if (FAILED(hr)) { error = L"DirectSoundCaptureCreate failed!"; m_captureDriver->Release(); m_captureDriver = nullptr; return false; } //创建通知事件 IDirectSoundNotify* Notify = nullptr; m_captureBuffer->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&Notify); DSBPOSITIONNOTIFY notify[2] = { 0 }; int offset = int(m_frameSize - 1); for (int i = 0; i < 2; i++) { notify[i].dwOffset = offset; m_event[i] = CreateEventW(nullptr, false, false, nullptr); notify[i].hEventNotify = m_event[i]; offset += (int)m_frameSize; } Notify->SetNotificationPositions(2, notify); Notify->Release(); //创建录制线程 m_runing = true; m_iscapture = false; m_thread = new std::thread(&MRecorder::CaptureThread, this); return true; } bool MRecorder::Start() { if(m_captureBuffer) { if (m_iscapture) return true; m_iscapture = true; m_signal.notify_all(); return SUCCEEDED(m_captureBuffer->Start(DSBPLAY_LOOPING)); } return false; } bool MRecorder::Stop() { if(m_captureBuffer) { if (!m_iscapture) return true; m_iscapture = false; return SUCCEEDED(m_captureBuffer->Stop()); } return false; } MRecorder::PCMData* MRecorder::GetStreamData() { PCMData* ret = nullptr; m_queue.dequeue(ret); return ret; } Mui::_m_size MRecorder::GetDataSize() { return Mui::_m_size(m_queue.size() * m_frameSize); } void MRecorder::CaptureThread() { while (m_runing) { //休眠线程 if (!m_iscapture) { std::unique_lock lock(m_lock); while (!m_iscapture) m_signal.wait(lock); } //等待通知事件 const DWORD res = WaitForMultipleObjects(2, m_event, FALSE, INFINITE); if (!m_iscapture) continue; if (res >= WAIT_OBJECT_0 && res <= WAIT_OBJECT_0 + 1) { auto data = new PCMData(); UCHAR* buffer = nullptr; DWORD dwBufferSize = 0; if (FAILED(m_captureBuffer->Lock(m_offsetNum * m_frameSize, m_frameSize, (LPVOID*)&buffer, &dwBufferSize, nullptr, nullptr, 0))) continue; data->data = new Mui::_m_byte[dwBufferSize]; data->size = dwBufferSize; memcpy(data->data, buffer, dwBufferSize); m_queue.enqueue(data); m_captureBuffer->Unlock(buffer, dwBufferSize, nullptr, 0); m_offsetNum++; if (m_offsetNum == 2) m_offsetNum = 0; } } } ================================================ FILE: libtts/Modules/AvCodec/Recorder.h ================================================ #pragma once #include #include #include #pragma comment(lib, "dsound.lib") class MRecorder { public: struct PCMData { Mui::_m_lpbyte data = nullptr; Mui::_m_uint size = 0; ~PCMData() { delete data; } }; MRecorder() = default; ~MRecorder(); /*初始化录音器 * @param out error - 错误信息输出 * @param sampleRate - 采样率 为0则默认 44100 (最大支持44100) * @param channels - 声道数 为0则默认 2 (最大2声道立体声) * @param bit - 位数 为0则默认 16 (最大支持16位) */ bool InitRecorder(std::wstring& error, Mui::_m_uint sampleRate = 0, Mui::_m_byte channels = 0, Mui::_m_byte bit = 0, Mui::_m_uint fs = 0); bool Start(); bool Stop(); //获取一段已录制的PCM音频数据 nullptr则没有数据 PCMData* GetStreamData(); //获取总dataSize Mui::_m_size GetDataSize(); //获取采样率 Mui::_m_uint GetSampleRate() const { return m_sampleRate; } //获取声道数 Mui::_m_byte GetChannels() const { return m_channels; } //获取位数 Mui::_m_byte GetBitRate() const { return m_bit; } //获取音频帧尺寸 Mui::_m_uint GetFrameSize() const { return m_frameSize; } //获取BlockAlign Mui::_m_uint GetBlockAlign() const { return m_blockAlign; } private: //音频参数设置 Mui::_m_uint m_sampleRate = 44100; Mui::_m_byte m_channels = 2; Mui::_m_byte m_bit = 16; Mui::_m_uint m_frameSize = 0; Mui::_m_uint m_blockAlign = 0; HANDLE m_event[2] = { nullptr }; IDirectSoundCapture* m_captureDriver = nullptr; IDirectSoundCaptureBuffer* m_captureBuffer = nullptr; //录音线程相关 std::mutex m_lock; std::condition_variable m_signal; std::atomic_bool m_runing; std::atomic_bool m_iscapture; std::thread* m_thread = nullptr; Mui::_m_uint m_offsetNum = 0; void CaptureThread(); //录音数据 template class Queue { std::deque m_queue; std::mutex m_mutex; public: Queue() = default; bool empty() { std::unique_lock lock(m_mutex); return m_queue.empty(); } auto size() { std::unique_lock lock(m_mutex); return m_queue.size(); } void enqueue(T& t) { std::unique_lock lock(m_mutex); m_queue.push_back(t); } bool dequeue(T& t) { std::unique_lock lock(m_mutex); if (m_queue.empty()) return false; t = std::move(m_queue.front()); m_queue.pop_front(); return true; } void clear() { std::unique_lock lock(m_mutex); m_queue.clear(); } }; Queue m_queue; }; ================================================ FILE: libtts/Modules/InferTools/G2P/MoeVSG2P.cpp ================================================ #include "MoeVSG2P.hpp" #include "MJson.h" #include "../../StringPreprocess.hpp" #include "../../InferTools/inferTools.hpp" #include MoeVoiceStudioG2PHeader std::wregex SignRegex(L"[!@#$%^&*()_+\\-=`~,./;'\\[\\]<>?:\"{}|\\\\。?!,、;:“”‘’『』「」()〔〕【】─…·—~《》〈〉]+"); std::wregex WordRegex(L"[^!@#$%^&*()_+\\-=`~,./;'\\[\\]<>?:\"{}|\\\\。?!,、;:“”‘’『』「」()〔〕【】─…·—~《》〈〉]+"); std::wregex BlankRegex(L"[ ]+"); std::wregex ChineseRegex(L"^[\\u4e00-\\u9fa5]{0,}$"); std::wregex NumberRegex(L"\\d+(?:\\.?\\d+)?"); std::wstring ChineseNumber[] = { L"零",L"一",L"二",L"三",L"四",L"五",L"六",L"七",L"八",L"九",L"十" }; std::wstring ChineseNumberDigit[] = { L"",L"十",L"百",L"千",L"万",L"十万",L"百万",L"千万",L"亿" }; std::wstring JapaneseNumber[] = { L"零",L"一",L"ニ",L"三",L"四",L"五",L"六",L"七",L"八",L"九",L"十" }; std::wstring JapaneseNumberDigit[] = { L"",L"十",L"百",L"千",L"万",L"十万",L"百万",L"千万",L"億" }; std::unordered_map _PUNCTUATION_MAP{ { L":", L"," }, { L";", L"," }, { L",", L"," }, { L"。", L"." }, { L"!", L"!" }, { L"?", L"?" }, { L"·", L"," }, { L"、", L"," }, { L"...", L"…" }, { L"$", L"." }, { L"“", L"'" }, { L"”", L"'" }, { L"‘", L"'" }, { L"’", L"'" }, { L"(", L"'" }, { L")", L"'" }, { L"(", L"'" }, { L")", L"'" }, { L"《", L"'" }, { L"》", L"'" }, { L"【", L"'" }, { L"】", L"'" }, { L"[", L"'" }, { L"]", L"'" }, { L"—", L"-" }, { L"~", L"-" }, { L"~", L"-" }, { L"「", L"'" }, { L"」", L"'" } }; std::unordered_map _ALPHASYMBOL_MAP{ {L"#", L"シャープ"}, { L"%", L"パーセント" }, { L"&", L"アンド" }, { L"+", L"プラス" }, { L"-", L"マイナス" }, { L":", L"コロン" }, { L";", L"セミコロン" }, { L"<", L"小なり" }, { L"=", L"イコール" }, { L">", L"大なり" }, { L"@", L"アット" }, { L"a", L"エー" }, { L"b", L"ビー" }, { L"c", L"シー" }, { L"d", L"ディー" }, { L"e", L"イー" }, { L"f", L"エフ" }, { L"g", L"ジー" }, { L"h", L"エイチ" }, { L"i", L"アイ" }, { L"j", L"ジェー" }, { L"k", L"ケー" }, { L"l", L"エル" }, { L"m", L"エム" }, { L"n", L"エヌ" }, { L"o", L"オー" }, { L"p", L"ピー" }, { L"q", L"キュー" }, { L"r", L"アール" }, { L"s", L"エス" }, { L"t", L"ティー" }, { L"u", L"ユー" }, { L"v", L"ブイ" }, { L"w", L"ダブリュー" }, { L"x", L"エックス" }, { L"y", L"ワイ" }, { L"z", L"ゼット" }, { L"α", L"アルファ" }, { L"β", L"ベータ" }, { L"γ", L"ガンマ" }, { L"δ", L"デルタ" }, { L"ε", L"イプシロン" }, { L"ζ", L"ゼータ" }, { L"η", L"イータ" }, { L"θ", L"シータ" }, { L"ι", L"イオタ" }, { L"κ", L"カッパ" }, { L"λ", L"ラムダ" }, { L"μ", L"ミュー" }, { L"ν", L"ニュー" }, { L"ξ", L"クサイ" }, { L"ο", L"オミクロン" }, { L"π", L"パイ" }, { L"ρ", L"ロー" }, { L"σ", L"シグマ" }, { L"τ", L"タウ" }, { L"υ", L"ウプシロン" }, { L"φ", L"ファイ" }, { L"χ", L"カイ" }, { L"ψ", L"プサイ" }, { L"ω", L"オメガ", }}; std::vector> _CURRENCY_MAP{{L"\\$", L"ドル"}, { L"¥", L"円" }, { L"£", L"ポンド" }, { L"€", L"ユーロ" }}; MVSCleaner DefaultCleaner; MVSCleaner* GetDefCleaner() { return &DefaultCleaner; } #ifdef WIN32 MoeVoiceStudioG2PApi::~MoeVoiceStudioG2PApi() { unLoad(); } MoeVoiceStudioG2PApi& MoeVoiceStudioG2PApi::operator=(MoeVoiceStudioG2PApi&& move) noexcept { func = move.func; m_hDynLib = move.m_hDynLib; move.func = nullptr; move.m_hDynLib = nullptr; return *this; } bool MoeVoiceStudioG2PApi::enabled() const { return m_hDynLib != nullptr; } MoeVoiceStudioG2PApi::SplitData MoeVoiceStudioG2PApi::GetSplitWords(const std::wstring& inputLen) const { SplitData TempData; if (getvocab) TempData = (*(SplitData*)getvocab(inputLen.c_str())); return TempData; } void MoeVoiceStudioG2PApi::LoadDict(const std::wstring& Path) const { if (loaddic) loaddic(Path.c_str()); } char MoeVoiceStudioG2PApi::Load(const std::wstring& PluginName) { func = nullptr; frel = nullptr; if (m_hDynLib) { FreeLibrary(m_hDynLib); m_hDynLib = nullptr; } m_hDynLib = LoadLibrary((PluginName).c_str()); if (m_hDynLib == nullptr) return -1; func = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "PluginMain") ) ); frel = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "Release") ) ); getvocab = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "GetSplitData") ) ); vocabrel = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "RefreshTokenizer") ) ); loaddic = reinterpret_cast( reinterpret_cast( GetProcAddress(m_hDynLib, "LoadDict") ) ); if (func == nullptr) return 1; return 0; } std::wstring MoeVoiceStudioG2PApi::functionAPI(const std::wstring& inputLen, const std::wstring& placeholderSymbol, const std::wstring& extraInfo, const std::string& languageID) const { if (func) { const auto tmp = func(inputLen.c_str(), placeholderSymbol.c_str(), extraInfo.c_str(), languageID.c_str()); std::wstring ret = tmp; return ret; } return inputLen; } void MoeVoiceStudioG2PApi::unLoad() { if (frel) frel(); if (vocabrel) vocabrel(); vocabrel = nullptr; getvocab = nullptr; loaddic = nullptr; func = nullptr; frel = nullptr; if (m_hDynLib) FreeLibrary(m_hDynLib); m_hDynLib = nullptr; } #endif void MVSDict::GetDict(const std::wstring& path) { if (path.empty()) { _Dict.clear(); return; } PlaceholderSymbol = L"|"; std::string phoneInfo, phoneInfoAll; std::ifstream phonefile(path.c_str()); if (!phonefile.is_open()) LibDLVoiceCodecThrow("phone file not found") while (std::getline(phonefile, phoneInfo)) phoneInfoAll += phoneInfo; phonefile.close(); MJson PhoneJson; PhoneJson.Parse(phoneInfoAll); if (PhoneJson.HasParseError()) LibDLVoiceCodecThrow("json file error") for (const auto& itr : PhoneJson.GetMemberArray()) { std::wstring Key = to_wide_string(itr.first); if (Key == L"PlaceholderSymbol") { if (itr.second.IsString() && itr.second.GetStringLength()) PlaceholderSymbol = to_wide_string(itr.second.GetString()); if (PlaceholderSymbol.length() > 1) PlaceholderSymbol = L"|"; continue; } const auto Value = itr.second.GetArray(); _Dict[Key] = std::vector(); for (const auto& it : Value) _Dict[Key].push_back(to_wide_string(it.GetString())); } } std::vector MVSDict::DictReplace(const std::vector& input) const { std::vector _out; for (const auto& i : input) if (_Dict.find(i) != _Dict.end()) { const auto& Value = _Dict.at(i); _out.insert(_out.end(), Value.begin(), Value.end()); } else _out.emplace_back(i); return _out; } std::vector MVSDict::DictReplace(const std::wstring& input, const std::wstring& tPlaceholderSymbol) const { std::vector _output; auto tmp = input; tmp += tPlaceholderSymbol; while (!tmp.empty()) { const size_t pos = tmp.find(tPlaceholderSymbol); const auto Key = tmp.substr(0, pos); tmp = tmp.substr(pos + 1); if (_Dict.find(Key) != _Dict.end()) { const auto& Value = _Dict.at(Key); _output.insert(_output.end(), Value.begin(), Value.end()); } else _output.emplace_back(Key); } for (int64_t i = int64_t(_output.size()) - 1; i >= 0; --i) if (_output[i].empty()) _output.erase(_output.begin() + i); return _output; } std::wstring MVSDict::DictReplaceGetStr(const std::wstring& input, const std::wstring& tPlaceholderSymbol, bool usePlaceholderSymbol) const { const auto tmp = DictReplace(input, tPlaceholderSymbol); std::wstring output; for (const auto& i : tmp) if (usePlaceholderSymbol) output += i + tPlaceholderSymbol; else output += i; return output; } void Tokenizer::load(const std::wstring& _Path) { const MJson _VocabJson(_Path); if (!_VocabJson.HasMember("ContinuingSubwordPrefix") || !_VocabJson.HasMember("Type") || !_VocabJson.HasMember("Vocab") || _VocabJson["ContinuingSubwordPrefix"].Empty() || _VocabJson["Type"].Empty() || !_VocabJson["ContinuingSubwordPrefix"].IsString() || !_VocabJson["Type"].IsString()) LibDLVoiceCodecThrow("Vocab.json Error") const std::string Type = _VocabJson["Type"].GetString(); if (Type == "Unigram") Model = TokenizerModel::Unigram; Symbol = to_wide_string(_VocabJson["ContinuingSubwordPrefix"].GetString()); if (_VocabJson["Vocab"].IsArray()) { const auto _VocabArray = _VocabJson["Vocab"].GetArray(); int64_t Index = 0; for (const auto& Object : _VocabArray) { if (!(Object.IsString() || Object.IsArray())) { auto Beg = Object.MemberBegin(); if (Beg.first.empty()) continue; Vocab[to_wide_string(Beg.first)] = Beg.second.GetInt64(); } else Vocab[to_wide_string(Object.IsString() ? Object.GetString() : Object.GetArray()[0].GetString())] = Index++; } } else { const auto _VocabDict = _VocabJson["Vocab"].GetMemberArray(); for (const auto& Pair : _VocabDict) { if (Pair.second.IsInt()) Vocab[to_wide_string(Pair.first)] = TokenizerType(Pair.second.GetInt()); else if (Pair.second.IsFloat()) Vocab[to_wide_string(Pair.first)] = TokenizerType(Pair.second.GetFloat()); } } if (_VocabJson.HasMember("UseSplit") && _VocabJson["UseSplit"].IsBool()) UseSplit = _VocabJson["UseSplit"].GetBool(); } void Tokenizer::loadCleaner(const std::wstring& _Path) const { if (Cleaner) Cleaner->loadG2p(_Path); } void Tokenizer::loadDict(const std::wstring& _Path) const { if (Cleaner) Cleaner->loadDict(_Path); } std::vector Tokenizer::UnigramMethod(const std::wstring& Seq, size_t MaxWordLength, TokenizerMethod Method) const { if (Seq.empty()) return {}; //auto SeqVector = SplitString(Seq, SignRegex); std::vector Tokens; Tokens.emplace_back(L"[CLS]"); std::wstring SeqWord = Seq; if (Method == TokenizerMethod::Left) { bool FirstTime = true; while (!SeqWord.empty()) { for (size_t SearchLength = min(MaxWordLength, SeqWord.length()); SearchLength > 0; --SearchLength) { if (FirstTime) { size_t SubVal = 0; if (SearchLength > Symbol.length()) SubVal = Symbol.length(); const auto SearchResult = Vocab.find(Symbol + SeqWord.substr(0, SearchLength - SubVal)); if (SearchResult != Vocab.end()) { Tokens.emplace_back(SearchResult->first); SeqWord = SeqWord.substr(SearchLength - SubVal); FirstTime = false; break; } } const auto SearchResult = Vocab.find(SeqWord.substr(0, SearchLength)); if (SearchResult != Vocab.end()) { Tokens.emplace_back(SearchResult->first); SeqWord = SeqWord.substr(SearchLength); if (FirstTime) FirstTime = false; break; } if (SearchLength == 1) { const auto SubStr = SeqWord.substr(0, SearchLength); const auto SearchRes = _PUNCTUATION_MAP.find(SubStr); if (SearchRes != _PUNCTUATION_MAP.end()) { const auto SearchR = Vocab.find(SearchRes->second); if (SearchR != Vocab.end()) Tokens.emplace_back(SearchR->first); SeqWord = SeqWord.substr(1); break; } if (Tokens.empty() || Tokens.back() != L"[UNK]") Tokens.emplace_back(SubStr); SeqWord = SeqWord.substr(1); } } } } else LibDLVoiceCodecThrow("NotImplementedError") Tokens.emplace_back(L"[SEP]"); return Tokens; } std::vector Tokenizer::WordPieceMethod(const std::wstring& Seq, size_t MaxWordLength, TokenizerMethod Method) const { if (Seq.empty()) return {}; auto SeqVector = SplitString(Seq, SignRegex); std::vector Tokens; Tokens.emplace_back(L"[CLS]"); if (Method == TokenizerMethod::Left) { for (auto& SeqWord : SeqVector) { bool FirstTime = true; while (!SeqWord.empty()) { if (regex_match(SeqWord.substr(0, 1), ChineseRegex)) { const auto SearchResult = Vocab.find(SeqWord.substr(0, 1)); if (SearchResult != Vocab.end()) Tokens.emplace_back(SearchResult->first); else Tokens.emplace_back(SeqWord.substr(0, 1)); SeqWord = SeqWord.substr(1); continue; } for (size_t SearchLength = min(MaxWordLength, SeqWord.length()); SearchLength > 0; --SearchLength) { if (!FirstTime) { size_t SubVal = 0; if (SearchLength > Symbol.length()) SubVal = Symbol.length(); const auto SearchResult = Vocab.find(Symbol + SeqWord.substr(0, SearchLength - SubVal)); if (SearchResult != Vocab.end()) { Tokens.emplace_back(SearchResult->first); SeqWord = SeqWord.substr(SearchLength - SubVal); break; } } const auto SearchResult = Vocab.find(SeqWord.substr(0, SearchLength)); if (SearchResult != Vocab.end()) { Tokens.emplace_back(SearchResult->first); SeqWord = SeqWord.substr(SearchLength); if (FirstTime) FirstTime = false; break; } if (SearchLength == 1) { const auto SubStr = SeqWord.substr(0, SearchLength); const auto SearchRes = _PUNCTUATION_MAP.find(SubStr); if (SearchRes != _PUNCTUATION_MAP.end()) { const auto SearchR = Vocab.find(SearchRes->second); if (SearchR != Vocab.end()) Tokens.emplace_back(SearchR->first); SeqWord = SeqWord.substr(1); break; } if (Tokens.empty() || Tokens.back() != L"[UNK]") Tokens.emplace_back(SubStr); SeqWord = SeqWord.substr(1); } } } } } else LibDLVoiceCodecThrow("NotImplementedError") Tokens.emplace_back(L"[SEP]"); return Tokens; } std::vector Tokenizer::operator()(const std::vector& Seq, bool SkipBlank) const { std::vector Tokens; const auto UNKID = Vocab.at(L"[UNK]"); for (const auto& iter : Seq) { const auto res = Vocab.find(iter); if (res != Vocab.end()) Tokens.emplace_back(res->second); else if(iter.empty() || Tokens.back() != UNKID) { if (SkipBlank && std::regex_match(iter, BlankRegex)) continue; Tokens.emplace_back(UNKID); } } return Tokens; } std::vector SplitWordsFromStr(const std::wstring& Seq) { std::vector rtn; for (const auto i : Seq) rtn.emplace_back(std::wstring() + i); return rtn; } std::vector Tokenizer::Tokenize(const std::wstring& Seq, size_t MaxWordLength, TokenizerMethod Method) const { if (Vocab.empty()) return SplitWordsFromStr(Seq); if (Model == TokenizerModel::WordPiece) return WordPieceMethod(Seq, MaxWordLength, Method); return UnigramMethod(Seq, MaxWordLength, Method); } std::vector Tokenizer::SplitString(const std::wstring& _InputRef, const std::wregex & _SignRegex) { if (_InputRef.empty()) return {}; std::wstring InputStr = _InputRef; std::vector TmpStrVec, StrVec; std::wsmatch MatchedSign; while (std::regex_search(InputStr, MatchedSign, _SignRegex)) { if (MatchedSign.prefix().matched) TmpStrVec.push_back(MatchedSign.prefix()); TmpStrVec.push_back(MatchedSign.str()); InputStr = MatchedSign.suffix(); } if (!InputStr.empty()) TmpStrVec.emplace_back(InputStr); for(const auto& i : TmpStrVec) { std::wsregex_token_iterator TokenIter(i.begin(), i.end(), BlankRegex, -1); decltype(TokenIter) TokenIterEnd; for (; TokenIter != TokenIterEnd; ++TokenIter) if (!TokenIter->str().empty()) StrVec.push_back(TokenIter->str()); } return StrVec; } std::vector Tokenizer::SplitWithPlugin(const std::vector& _Inputs) const { std::vector SeqVec; for(const auto& Seq : _Inputs) { const auto SplitedWords = GetCleaner().GetCleaner().GetSplitWords(Seq); for (size_t i = 0; i < SplitedWords.Size; ++i) { auto TmpString = to_wide_string(SplitedWords.Data[i]); TmpString = TmpString.substr(0, TmpString.find(L',')); SeqVec.emplace_back(std::move(TmpString)); } } return SeqVec; } std::wstring NumberToChinese(double Number) { std::wstring StrRtn; std::wstring InputStr = std::to_wstring(Number); const size_t PIndex = InputStr.find(L'.'); std::wstring IntegerStr, FractionStr; if (PIndex != std::wstring::npos) { IntegerStr = InputStr.substr(0, PIndex); FractionStr = InputStr.substr(PIndex + 1); while (!FractionStr.empty() && FractionStr.back() == L'0') FractionStr.pop_back(); } else IntegerStr = std::move(InputStr); if (IntegerStr != L"0") { size_t MaxIntegerStrLength = IntegerStr.length(); for (; MaxIntegerStrLength > 0; --MaxIntegerStrLength) if (IntegerStr[MaxIntegerStrLength - 1] != L'0') break; if (MaxIntegerStrLength < 1) MaxIntegerStrLength = 1; const auto DigitNum = IntegerStr.length(); for (size_t i = 0; i < MaxIntegerStrLength; i++) { const auto NumberIndex = IntegerStr[i] - L'0'; const auto DigitIndex = DigitNum - i - 1; if (0 == NumberIndex) { if ((i > 0 && L'0' == IntegerStr[i - 1]) || i == IntegerStr.length() - 1) continue; if (DigitIndex >= 4 && 0 == DigitIndex % 4) StrRtn += ChineseNumberDigit[DigitIndex]; else StrRtn += ChineseNumber[NumberIndex]; } else { StrRtn += ChineseNumber[NumberIndex]; if (IntegerStr.length() == 2 && IntegerStr[0] == '1' && i == 0) StrRtn.erase(0); if (0 == DigitIndex % 4) StrRtn += ChineseNumberDigit[DigitIndex]; else StrRtn += ChineseNumberDigit[DigitIndex % 4]; } } } else StrRtn += L"零"; if (!FractionStr.empty()) StrRtn += L"点"; for(const auto FractionI : FractionStr) { const auto NumberIndex = FractionI - L'0'; StrRtn += ChineseNumber[NumberIndex]; } return StrRtn; } std::wstring NumberToJapanese(double Number) { std::wstring StrRtn; std::wstring InputStr = std::to_wstring(Number); const size_t PIndex = InputStr.find(L'.'); std::wstring IntegerStr, FractionStr; if (PIndex != std::wstring::npos) { IntegerStr = InputStr.substr(0, PIndex); FractionStr = InputStr.substr(PIndex + 1); while (!FractionStr.empty() && FractionStr.back() == L'0') FractionStr.pop_back(); } else IntegerStr = std::move(InputStr); if (IntegerStr != L"0") { size_t MaxIntegerStrLength = IntegerStr.length(); for (; MaxIntegerStrLength > 0; --MaxIntegerStrLength) if (IntegerStr[MaxIntegerStrLength - 1] != L'0') break; if (MaxIntegerStrLength < 1) MaxIntegerStrLength = 1; const auto DigitNum = IntegerStr.length(); for (size_t i = 0; i < MaxIntegerStrLength; i++) { const auto NumberIndex = IntegerStr[i] - L'0'; const auto DigitIndex = DigitNum - i - 1; if (0 == NumberIndex) { if ((i > 0 && L'0' == IntegerStr[i - 1]) || i == IntegerStr.length() - 1) continue; if (DigitIndex >= 4 && 0 == DigitIndex % 4) StrRtn += JapaneseNumberDigit[DigitIndex]; else StrRtn += JapaneseNumber[NumberIndex]; } else { StrRtn += JapaneseNumber[NumberIndex]; if (IntegerStr.length() == 2 && IntegerStr[0] == '1' && i == 0) StrRtn.erase(0); if (0 == DigitIndex % 4) StrRtn += JapaneseNumberDigit[DigitIndex]; else StrRtn += JapaneseNumberDigit[DigitIndex % 4]; } } } else StrRtn += L"零"; if (!FractionStr.empty()) StrRtn += L"点"; for (const auto FractionI : FractionStr) { const auto NumberIndex = FractionI - L'0'; StrRtn += JapaneseNumber[NumberIndex]; } return StrRtn; } std::wstring ChineseNormalize(const std::wstring& _Input) { std::wstring RtnStr; const auto StrVec = Tokenizer::SplitString(_Input, NumberRegex); for(const auto& Str : StrVec) { if (std::regex_match(Str, NumberRegex)) RtnStr += NumberToChinese(_wtof(Str.c_str())); else RtnStr += Str; } RtnStr = std::regex_replace(RtnStr, std::wregex(L"嗯"), L"恩"); RtnStr = std::regex_replace(RtnStr, std::wregex(L"呣"), L"母"); return RtnStr; } std::wstring JapaneseNormalize(const std::wstring& _Input) { std::wstring RtnStr; const auto StrVec = Tokenizer::SplitString(_Input, NumberRegex); for (const auto& Str : StrVec) { if (std::regex_match(Str, NumberRegex)) RtnStr += NumberToJapanese(_wtof(Str.c_str())); else RtnStr += Str; } for (const auto& PunPair : _CURRENCY_MAP) RtnStr = std::regex_replace(RtnStr, std::wregex(PunPair.first), PunPair.second); return RtnStr; } std::wstring NormalizeText(const std::wstring& _Input, const std::string& _Language) { if (_Language == "ZH") return ChineseNormalize(_Input); if (_Language == "JP") return JapaneseNormalize(_Input); return _Input; } Tokenizer EmptyTokenizer; Tokenizer& GetEmptyVocabTokenizer() { return EmptyTokenizer; } MoeVoiceStudioG2PEnd ================================================ FILE: libtts/Modules/InferTools/G2P/MoeVSG2P.hpp ================================================ /** * FileName: MoeVSG2P.hpp * Note: MoeVoiceStudioCore G2P及字典(TTS用) * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2023-11-9 Create */ #pragma once #include #ifdef _WIN32 #ifndef UNICODE #define UNICODE #endif #include #endif #include #include #include #include #define MoeVoiceStudioG2PHeader namespace MoeVSG2P { #define MoeVoiceStudioG2PEnd } MoeVoiceStudioG2PHeader class MoeVoiceStudioG2PApi { public: struct SplitData { char** Data = nullptr; size_t Size = 0; }; using funTy = const wchar_t* (*)(const wchar_t*, const wchar_t*, const wchar_t*, const char*); using freTy = void (*)(); using vocabFn = void* (*)(const wchar_t*); using loadFn = void (*)(const wchar_t*); MoeVoiceStudioG2PApi() = default; ~MoeVoiceStudioG2PApi(); char Load(const std::wstring& PluginName); void unLoad(); void ReleaseVoc() const { if (vocabrel) vocabrel(); } [[nodiscard]] SplitData GetSplitWords(const std::wstring& inputLen) const; [[nodiscard]] std::wstring functionAPI(const std::wstring& inputLen, const std::wstring& placeholderSymbol, const std::wstring& extraInfo, const std::string& languageID) const; MoeVoiceStudioG2PApi(const MoeVoiceStudioG2PApi&) = delete; MoeVoiceStudioG2PApi(MoeVoiceStudioG2PApi&&) = delete; MoeVoiceStudioG2PApi& operator=(MoeVoiceStudioG2PApi&& move) noexcept; [[nodiscard]] bool enabled() const; MoeVoiceStudioG2PApi& operator=(const MoeVoiceStudioG2PApi&) = delete; void LoadDict(const std::wstring& Path) const; private: #ifdef WIN32 const wchar_t*(*func)(const wchar_t*, const wchar_t*, const wchar_t*, const char*) = nullptr; void (*frel)() = nullptr; void* (*getvocab)(const wchar_t*) = nullptr; void (*vocabrel)() = nullptr; void (*loaddic)(const wchar_t*) = nullptr; HINSTANCE m_hDynLib = nullptr; #endif }; class MVSDict { public: MVSDict() = default; ~MVSDict() = default; [[nodiscard]] bool enabled() const { return !_Dict.empty(); } void unload() { _Dict.clear(); } [[nodiscard]] std::vector DictReplace(const std::vector& input) const; [[nodiscard]] std::vector DictReplace(const std::wstring& input, const std::wstring& tPlaceholderSymbol) const; [[nodiscard]] std::wstring DictReplaceGetStr(const std::wstring& input, const std::wstring& tPlaceholderSymbol, bool usePlaceholderSymbol = true) const; void GetDict(const std::wstring& path); [[nodiscard]] std::wstring getPlaceholderSymbol() const { return PlaceholderSymbol; } private: std::map> _Dict; std::wstring PlaceholderSymbol = L"|"; }; class MVSCleaner { public: MVSCleaner() = default; ~MVSCleaner() { unloadDict(); unloadG2p(); } void unloadDict() { _Dict.unload(); } void unloadG2p() { _G2p.unLoad(); } void loadDict(const std::wstring& _path) { if (_Dict.enabled()) unloadDict(); _Dict.GetDict(_path); } void loadG2p(const std::wstring& _path) { if (_G2p.enabled()) unloadG2p(); _G2p.Load(_path); } [[nodiscard]] bool G2pEnabled() const { return _G2p.enabled(); } [[nodiscard]] bool DictEnabled() const { return _Dict.enabled(); } [[nodiscard]] std::wstring G2p(const std::wstring& _text, const std::wstring& placeholderSymbol, const std::wstring& extraInfo, const std::string& languageID) const { return _G2p.functionAPI(_text, placeholderSymbol, extraInfo, languageID); } [[nodiscard]] const MoeVoiceStudioG2PApi& GetCleaner() const { return _G2p; } [[nodiscard]] auto DictReplace(const std::vector& input) const { return _Dict.DictReplace(input); } [[nodiscard]] auto DictReplace(const std::wstring& input, const std::wstring& tPlaceholderSymbol) const { return _Dict.DictReplace(input, tPlaceholderSymbol); } [[nodiscard]] auto DictReplaceGetStr(const std::wstring& input, const std::wstring& tPlaceholderSymbol, bool usePlaceholderSymbol = true) const { return _Dict.DictReplaceGetStr(input, tPlaceholderSymbol, usePlaceholderSymbol); } [[nodiscard]] std::wstring getPlaceholderSymbol() const { return _Dict.getPlaceholderSymbol(); } protected: MoeVoiceStudioG2PApi _G2p; MVSDict _Dict; }; class Tokenizer { public: using TokenizerType = int64_t; enum class TokenizerMethod { Left, Right }; enum class TokenizerModel { Unigram, WordPiece }; Tokenizer() = default; Tokenizer(const std::wstring& _Path) { load(_Path); } void BondCleaner(MVSCleaner* MCleaner) { Cleaner = MCleaner; } void load(const std::wstring& _Path); void loadCleaner(const std::wstring& _Path) const; void loadDict(const std::wstring& _Path) const; [[nodiscard]] const MVSCleaner& GetCleaner() const { return *Cleaner; } const MVSCleaner* operator->() const { return Cleaner; } [[nodiscard]] std::vector WordPieceMethod(const std::wstring& Seq, size_t MaxWordLength = 25, TokenizerMethod Method = TokenizerMethod::Left) const; [[nodiscard]] std::vector UnigramMethod(const std::wstring& Seq, size_t MaxWordLength = 25, TokenizerMethod Method = TokenizerMethod::Left) const; std::vector operator()(const std::vector& Seq, bool SkipBlank = false) const; [[nodiscard]] std::vector Tokenize(const std::wstring& Seq, size_t MaxWordLength = 25, TokenizerMethod Method = TokenizerMethod::Left) const; [[nodiscard]] std::vector SplitWithPlugin(const std::vector& _Inputs) const; static std::vector SplitString(const std::wstring& _InputRef, const std::wregex& _SignRegex); private: std::unordered_map Vocab; std::wstring Symbol = L"##"; TokenizerModel Model = TokenizerModel::WordPiece; MVSCleaner* Cleaner = nullptr; bool UseSplit = false; }; Tokenizer& GetEmptyVocabTokenizer(); MVSCleaner* GetDefCleaner(); std::wstring JapaneseNormalize(const std::wstring& _Input); std::wstring ChineseNormalize(const std::wstring& _Input); std::wstring NormalizeText(const std::wstring& _Input, const std::string& _Language); std::wstring NumberToChinese(double Number); std::wstring NumberToJapanese(double Number); MoeVoiceStudioG2PEnd ================================================ FILE: libtts/Modules/InferTools/inferTools.cpp ================================================ #include "inferTools.hpp" #include "string" #ifdef MoeVoiceStudioAvxAcc #include #endif InferTools::Wav::Wav(const wchar_t* Path) :header(WAV_HEADER()) { char buf[1024]; FILE* stream; _wfreopen_s(&stream, Path, L"rb", stderr); if (stream == nullptr) { throw (std::exception("File not exists")); } fread(buf, 1, HEAD_LENGTH, stream); int pos = 0; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'R') && (buf[pos + 1] == 'I') && (buf[pos + 2] == 'F') && (buf[pos + 3] == 'F')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.ChunkSize = *(int*)&buf[pos]; pos += 8; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'f') && (buf[pos + 1] == 'm') && (buf[pos + 2] == 't')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk1Size = *(int*)&buf[pos]; pos += 4; header.AudioFormat = *(short*)&buf[pos]; pos += 2; header.NumOfChan = *(short*)&buf[pos]; pos += 2; header.SamplesPerSec = *(int*)&buf[pos]; pos += 4; header.bytesPerSec = *(int*)&buf[pos]; pos += 4; header.blockAlign = *(short*)&buf[pos]; pos += 2; header.bitsPerSample = *(short*)&buf[pos]; pos += 2; while (pos < HEAD_LENGTH) { if ((buf[pos] == 'd') && (buf[pos + 1] == 'a') && (buf[pos + 2] == 't') && (buf[pos + 3] == 'a')) { pos += 4; break; } ++pos; } if (pos >= HEAD_LENGTH) throw (std::exception("Don't order fried rice (annoyed)")); header.Subchunk2Size = *(int*)&buf[pos]; pos += 4; StartPos = pos; Data = new char[header.Subchunk2Size + 1]; fseek(stream, StartPos, SEEK_SET); fread(Data, 1, header.Subchunk2Size, stream); if (stream != nullptr) { fclose(stream); } SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav::Wav(const Wav& input) :header(WAV_HEADER()) { Data = new char[(input.header.Subchunk2Size + 1)]; if (Data == nullptr) { LibDLVoiceCodecThrow("OOM") } memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; memcpy(Data, input.Data, input.header.Subchunk2Size); SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav::Wav(Wav&& input) noexcept { Data = input.Data; input.Data = nullptr; memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; } InferTools::Wav& InferTools::Wav::operator=(Wav&& input) noexcept { destory(); Data = input.Data; input.Data = nullptr; memcpy(header.RIFF, input.header.RIFF, 4); memcpy(header.fmt, input.header.fmt, 4); memcpy(header.WAVE, input.header.WAVE, 4); memcpy(header.Subchunk2ID, input.header.Subchunk2ID, 4); header.ChunkSize = input.header.ChunkSize; header.Subchunk1Size = input.header.Subchunk1Size; header.AudioFormat = input.header.AudioFormat; header.NumOfChan = input.header.NumOfChan; header.SamplesPerSec = input.header.SamplesPerSec; header.bytesPerSec = input.header.bytesPerSec; header.blockAlign = input.header.blockAlign; header.bitsPerSample = input.header.bitsPerSample; header.Subchunk2Size = input.header.Subchunk2Size; StartPos = input.StartPos; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; return *this; } InferTools::Wav& InferTools::Wav::cat(const Wav& input) { if (header.AudioFormat != 1) return *this; if (header.SamplesPerSec != input.header.bitsPerSample || header.NumOfChan != input.header.NumOfChan) return *this; char* buffer = new char[(int64_t)header.Subchunk2Size + (int64_t)input.header.Subchunk2Size + 1]; if (buffer == nullptr)return *this; memcpy(buffer, Data, header.Subchunk2Size); memcpy(buffer + header.Subchunk2Size, input.Data, input.header.Subchunk2Size); header.ChunkSize += input.header.Subchunk2Size; header.Subchunk2Size += input.header.Subchunk2Size; delete[] Data; Data = buffer; SData = reinterpret_cast(Data); dataSize = header.Subchunk2Size / 2; return *this; } std::vector InferTools::SliceAudio(const std::vector& input, const SlicerSettings& _slicer) { if (input.size() < size_t(_slicer.MinLength) * _slicer.SamplingRate) return {0, input.size()}; std::vector slice_point; bool slice_tag = true; slice_point.emplace_back(0); unsigned long CurLength = 0; for (size_t i = 0; i + _slicer.WindowLength < input.size(); i += _slicer.HopSize) { if (slice_tag) { const auto vol = abs(getAvg(input.data() + i, input.data() + i + _slicer.WindowLength)); if (vol < _slicer.Threshold) { slice_tag = false; if (CurLength > _slicer.MinLength * _slicer.SamplingRate) { CurLength = 0; slice_point.emplace_back(i + (_slicer.WindowLength / 2)); } } else slice_tag = true; } else { const auto vol = abs(getAvg(input.data() + i, input.data() + i + _slicer.WindowLength)); if (vol < _slicer.Threshold) slice_tag = false; else { slice_tag = true; if (CurLength > _slicer.MinLength * _slicer.SamplingRate) { CurLength = 0; slice_point.emplace_back(i + (_slicer.WindowLength / 2)); } } } CurLength += _slicer.HopSize; } slice_point.push_back(input.size()); return slice_point; } std::vector InferTools::arange(double start, double end, double step, double div) { std::vector output; while (start < end) { output.push_back(start / div); start += step; } return output; } std::vector InferTools::mean_filter(const std::vector& vec, size_t window_size) { std::vector result; if (window_size > vec.size() || window_size < 2) return vec; const size_t half = window_size / 2; // 窗口半径,向下取整 for (size_t i = half; i < vec.size() - half; i++) { float sum = 0.0f; for (size_t j = i - half; j <= i + half; j++) { sum += vec[j]; } result.push_back(sum / (float)(window_size % 2 ? window_size : window_size + 1)); } return result; } #ifdef MoeVoiceStudioAvxAcc InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator+=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_add_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] += _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator-=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_sub_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] -= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator*=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_mul_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] *= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator/=(const FloatTensorWrapper& _right) { if (_data_size != _right._data_size) LibDLVoiceCodecThrow("Vector Size MisMatch"); const size_t num_avx2_elements = _data_size / 8; for (size_t i = 0; i < num_avx2_elements; i++) { const __m256 a_avx2 = _mm256_load_ps(&_data_ptr[i * 8]); const __m256 b_avx2 = _mm256_load_ps(&_right[i * 8]); const __m256 result_avx2 = _mm256_div_ps(a_avx2, b_avx2); _mm256_store_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] /= _right[i]; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator+=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_add_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] += _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator-=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_sub_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] -= _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator*=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_mul_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] *= _right; return *this; } InferTools::FloatTensorWrapper& InferTools::FloatTensorWrapper::operator/=(float _right) { const size_t num_avx2_elements = _data_size / 8; const __m256 value_avx2 = _mm256_set1_ps(_right); for (size_t i = 0; i < num_avx2_elements; ++i) { const __m256 vec_avx2 = _mm256_loadu_ps(&_data_ptr[i * 8]); const __m256 result_avx2 = _mm256_div_ps(vec_avx2, value_avx2); _mm256_storeu_ps(&_data_ptr[i * 8], result_avx2); } for (size_t i = num_avx2_elements * 8; i < _data_size; ++i) _data_ptr[i] /= _right; return *this; } #endif ================================================ FILE: libtts/Modules/InferTools/inferTools.hpp ================================================ /** * FileName: InferTools.hpp * Note: MoeVoiceStudioCore 推理工具的定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include #include #include #define MOEVSINFERTOOLSHEADER namespace InferTools { #define MOEVSINFERTOOLSEND } #define LibDLVoiceCodecThrow(message) { \ const std::string LibDlCodecThrowMessage = message;\ const std::string LibDlCodecThrowMessagePrefix = std::string("[In \"") + std::filesystem::path(__FILE__).filename().string() + "\" Line " + std::to_string(__LINE__) + "] "; \ if(LibDlCodecThrowMessage.substr(0, LibDlCodecThrowMessagePrefix.length()) != LibDlCodecThrowMessagePrefix) \ throw std::exception((LibDlCodecThrowMessagePrefix + LibDlCodecThrowMessage).c_str()); \ else \ throw std::exception(LibDlCodecThrowMessage.c_str()); \ } MOEVSINFERTOOLSHEADER struct SlicerSettings { int32_t SamplingRate = 48000; double Threshold = 30.; double MinLength = 3.; int32_t WindowLength = 2048; int32_t HopSize = 512; }; class Wav { public: static constexpr int HEAD_LENGTH = 1024; struct WAV_HEADER { char RIFF[4] = { 'R','I','F','F' }; unsigned long ChunkSize; char WAVE[4] = { 'W','A','V','E' }; char fmt[4] = { 'f','m','t',' ' }; unsigned long Subchunk1Size; unsigned short AudioFormat; unsigned short NumOfChan; unsigned long SamplesPerSec; unsigned long bytesPerSec; unsigned short blockAlign; unsigned short bitsPerSample; char Subchunk2ID[4] = { 'd','a','t','a' }; unsigned long Subchunk2Size; WAV_HEADER(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1, unsigned long sr = 22050, unsigned long bps = 44100, unsigned short ba = 2, unsigned short bips = 16, unsigned long sc2s = 0) :ChunkSize(cs), Subchunk1Size(sc1s), AudioFormat(af), NumOfChan(nc), SamplesPerSec(sr), bytesPerSec(bps), blockAlign(ba), bitsPerSample(bips), Subchunk2Size(sc2s) {} }; using iterator = int16_t*; Wav(unsigned long cs = 36, unsigned long sc1s = 16, unsigned short af = 1, unsigned short nc = 1, unsigned long sr = 22050, unsigned long bps = 44100, unsigned short ba = 2, unsigned short bips = 16, unsigned long sc2s = 0) :header({ cs, sc1s, af, nc, sr, bps, ba, bips, sc2s }), Data(nullptr), StartPos(44) { dataSize = 0; SData = nullptr; } Wav(unsigned long sr, unsigned long length, const void* data) :header({ 36, 16, 1, 1, sr, sr * 2, 2, 16, length }), Data(new char[length + 1]), StartPos(44) { header.ChunkSize = 36 + length; memcpy(Data, data, length); SData = reinterpret_cast(Data); dataSize = length / 2; } Wav(const wchar_t* Path); Wav(const Wav& input); Wav(Wav&& input) noexcept; Wav& operator=(const Wav& input) = delete; Wav& operator=(Wav&& input) noexcept; ~Wav() { destory(); } Wav& cat(const Wav& input); [[nodiscard]] bool isEmpty() const { return this->header.Subchunk2Size == 0; } [[nodiscard]] const char* getData() const { return Data; } char* getData() { return Data; } [[nodiscard]] WAV_HEADER getHeader() const { return header; } WAV_HEADER& Header() { return header; } void destory() const { delete[] Data; } void changeData(const void* indata, long length, int sr) { delete[] Data; Data = new char[length]; memcpy(Data, indata, length); header.ChunkSize = 36 + length; header.Subchunk2Size = length; header.SamplesPerSec = sr; header.bytesPerSec = 2 * sr; } int16_t& operator[](const size_t index) const { if (index < dataSize) return *(SData + index); return *(SData + dataSize - 1); } [[nodiscard]] iterator begin() const { return reinterpret_cast(Data); } [[nodiscard]] iterator end() const { return reinterpret_cast(Data + header.Subchunk2Size); } [[nodiscard]] int64_t getDataLen()const { return static_cast(dataSize); } void Writef(const std::wstring& filepath) const { FILE* FOut = nullptr; _wfopen_s(&FOut, filepath.c_str(), L"wb"); if (!FOut) return; fwrite(&header, 1, sizeof(header), FOut); fwrite(Data, 1, dataSize * 2, FOut); fclose(FOut); FOut = nullptr; } static void WritePCMData(int samplingrate, int channel, const std::vector& PCMDATA, const std::wstring& filepath) { const WAV_HEADER TmpHeader(long(36 + 2 * PCMDATA.size()), 16, 1, short(channel), samplingrate, samplingrate * 2 * channel, short(2 * channel), short(16), long(2 * PCMDATA.size())); FILE* FOut = nullptr; _wfopen_s(&FOut, filepath.c_str(), L"wb"); if (!FOut) return; fwrite(&TmpHeader, 1, sizeof(TmpHeader), FOut); fwrite(PCMDATA.data(), 1, PCMDATA.size() * 2, FOut); fclose(FOut); FOut = nullptr; } private: WAV_HEADER header; char* Data; int16_t* SData; size_t dataSize; int StartPos; }; /** * \brief 切片机切片(获取切片位置) * \param input PCM数据(SignedInt16) * \param _slicer 切片机设置 * \return 切片位置 */ std::vector SliceAudio(const std::vector& input, const SlicerSettings& _slicer); /** * \brief 均值滤波器 * \param vec 待滤波的数据 * \param window_size 窗口大小 * \return 滤波后数据 */ std::vector mean_filter(const std::vector& vec, size_t window_size); template double getAvg(const T* start, const T* end) { const auto size = end - start + 1; auto avg = (double)(*start); for (auto i = 1; i < size; i++) avg = avg + (abs((double)start[i]) - avg) / (double)(i + 1ull); return avg; } std::vector arange(double start, double end, double step = 1.0, double div = 1.0); /** * \brief 重采样(插值) * \tparam TOut 输出类型 * \tparam TIn 输入类型 * \param _Data 输入数据 * \param src 输入采样率 * \param dst 输出采样率 * \param n_Div 给输出的数据统一除以这个数 * \return 输出数据 */ template static std::vector InterpResample(const std::vector& _Data, long src, long dst, TOut n_Div = TOut(1)) { if (src != dst) { const double intstep = double(src) / double(dst); const auto xi = InferTools::arange(0, double(_Data.size()), intstep); auto x0 = InferTools::arange(0, double(_Data.size())); while (x0.size() < _Data.size()) x0.emplace_back(x0[x0.size() - 1] + 1.0); while (x0.size() > _Data.size()) x0.pop_back(); std::vector y0(_Data.size()); for (size_t i = 0; i < _Data.size(); ++i) y0[i] = double(_Data[i]) / double(n_Div); std::vector yi(xi.size()); interp1(x0.data(), y0.data(), long(x0.size()), xi.data(), long(xi.size()), yi.data()); std::vector out(xi.size()); for (size_t i = 0; i < yi.size(); ++i) out[i] = TOut(yi[i]); return out; } std::vector out(_Data.size()); for (size_t i = 0; i < _Data.size(); ++i) out[i] = TOut(_Data[i]) / n_Div; return out; } /** * \brief 重采样(插值) * \tparam T 数据类型 * \param Data 输入数据 * \param src 输入采样率 * \param dst 输出采样率 * \return 输出数据 */ template static std::vector InterpFunc(const std::vector& Data, long src, long dst) { if (src != dst) { const double intstep = double(src) / double(dst); auto xi = InferTools::arange(0, double(Data.size()), intstep); while (xi.size() < size_t(dst)) xi.emplace_back(xi[xi.size() - 1] + 1.0); while (xi.size() > size_t(dst)) xi.pop_back(); auto x0 = InferTools::arange(0, double(Data.size())); while (x0.size() < Data.size()) x0.emplace_back(x0[x0.size() - 1] + 1.0); while (x0.size() > Data.size()) x0.pop_back(); std::vector y0(Data.size()); for (size_t i = 0; i < Data.size(); ++i) y0[i] = Data[i] <= T(0.0001) ? NAN : double(Data[i]); std::vector yi(xi.size()); interp1(x0.data(), y0.data(), long(x0.size()), xi.data(), long(xi.size()), yi.data()); std::vector out(xi.size()); for (size_t i = 0; i < yi.size(); ++i) out[i] = isnan(yi[i]) ? T(0.0) : T(yi[i]); return out; } return Data; } #ifdef MoeVoiceStudioAvxAcc class FloatTensorWrapper { public: FloatTensorWrapper() = delete; ~FloatTensorWrapper() { _data_ptr = nullptr; } FloatTensorWrapper(float* const data_p, size_t _size) : _data_ptr(data_p), _data_size(_size) {} FloatTensorWrapper(const FloatTensorWrapper& _copy) = delete; FloatTensorWrapper& operator=(const FloatTensorWrapper&) = delete; FloatTensorWrapper(FloatTensorWrapper&& _move) noexcept:_data_ptr(_move._data_ptr), _data_size(_move._data_size) {} FloatTensorWrapper& operator=(FloatTensorWrapper&& _move) noexcept { _data_ptr = _move._data_ptr; _data_size = _move._data_size; return *this; } template static const T& Min(const T& a, const T& b) { return (a > b) ? b : a; } float& operator[](size_t index) const { return *(_data_ptr + Min(index, _data_size)); } FloatTensorWrapper& operator+=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator-=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator*=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator/=(const FloatTensorWrapper& _right); FloatTensorWrapper& operator+=(float _right); FloatTensorWrapper& operator-=(float _right); FloatTensorWrapper& operator*=(float _right); FloatTensorWrapper& operator/=(float _right); private: float* _data_ptr = nullptr; size_t _data_size = 0; }; #endif MOEVSINFERTOOLSEND ================================================ FILE: libtts/Modules/Lib/MJson/MJson.cpp ================================================ #include "MJson.h" class FileGuard { public: FileGuard() = delete; ~FileGuard() { if (_fp) fclose(_fp); _fp = nullptr; } FileGuard(const char* _path) { if (_fp) fclose(_fp); _wfopen_s(&_fp, to_wide_string(_path).c_str(), L"rb"); } FileGuard(const std::wstring& _path) { if (_fp) fclose(_fp); _wfopen_s(&_fp, _path.c_str(), L"rb"); } operator FILE* () const { return _fp; } private: FILE* _fp = nullptr; static std::wstring to_wide_string(const std::string& input) { std::vector WideString(input.length() * 2); MultiByteToWideChar( CP_UTF8, 0, input.c_str(), int(input.length()), WideString.data(), int(WideString.size()) ); return WideString.data(); } }; MJson::MJson(const char* _path) { const auto file = FileGuard(_path); _document = yyjson_read_file(_path, YYJSON_READ_NOFLAG, nullptr, nullptr); if (!_document) throw std::exception("Json Parse Error !"); root = yyjson_doc_get_root(_document); } MJson::MJson(const std::wstring& _path) { const FileGuard fp(_path); _document = yyjson_read_fp(fp, YYJSON_READ_NOFLAG, nullptr, nullptr); if (!_document) throw std::exception("File Not Exists!"); root = yyjson_doc_get_root(_document); } MJson::MJson(const std::string& _data, bool _read_from_string) { if (_read_from_string) _document = yyjson_read(_data.c_str(), _data.length(), YYJSON_READ_NOFLAG); else { const auto file = FileGuard(_data.c_str()); _document = yyjson_read_fp(file, YYJSON_READ_NOFLAG, nullptr, nullptr); } if (!_document) throw std::exception("Json Parse Error !"); root = yyjson_doc_get_root(_document); } ================================================ FILE: libtts/Modules/Lib/MJson/MJson.h ================================================ #pragma once #include "../../framework.h" #include #include "yyjson.h" #include #ifdef _WIN32 #include #else #error #endif class MJsonValue { public: MJsonValue() = default; MJsonValue(yyjson_val* _val) : _Ptr(_val) {} ~MJsonValue() = default; MJsonValue(MJsonValue&& _val) noexcept { _Ptr = _val._Ptr; _val._Ptr = nullptr; } MJsonValue(const MJsonValue& _val) = delete; MJsonValue& operator=(MJsonValue&& _val) noexcept { _Ptr = _val._Ptr; _val._Ptr = nullptr; return *this; } MJsonValue& operator=(const MJsonValue& _val) = delete; [[nodiscard]] bool IsNull() const { return yyjson_is_null(_Ptr); } [[nodiscard]] bool IsBoolean() const { return yyjson_is_bool(_Ptr); } [[nodiscard]] bool IsBool() const { return yyjson_is_bool(_Ptr); } [[nodiscard]] bool IsInt() const { return yyjson_is_num(_Ptr); } [[nodiscard]] bool IsFloat() const { return yyjson_is_num(_Ptr); } [[nodiscard]] bool IsInt64() const { return yyjson_is_num(_Ptr); } [[nodiscard]] bool IsDouble() const { return yyjson_is_num(_Ptr); } [[nodiscard]] bool IsString() const { return yyjson_is_str(_Ptr); } [[nodiscard]] bool IsArray() const { return yyjson_is_arr(_Ptr); } [[nodiscard]] bool GetBool() const { return yyjson_get_bool(_Ptr); } [[nodiscard]] bool GetBoolean() const { return yyjson_get_bool(_Ptr); } [[nodiscard]] int GetInt() const { return int(yyjson_get_num(_Ptr)); } [[nodiscard]] int64_t GetInt64() const { return int64_t(yyjson_get_num(_Ptr)); } [[nodiscard]] float GetFloat() const { return float(yyjson_get_num(_Ptr)); } [[nodiscard]] double GetDouble() const { return yyjson_get_num(_Ptr); } [[nodiscard]] std::string GetString() const { if (const auto _str = yyjson_get_str(_Ptr)) return _str; return ""; } [[nodiscard]] std::vector GetArray() const { std::vector _ret; if (!IsArray()) return {}; const auto _PArray = _Ptr; size_t idx, max; yyjson_val* _Object; yyjson_arr_foreach(_PArray, idx, max, _Object) _ret.emplace_back(_Object); return _ret; } [[nodiscard]] size_t GetSize() const { return yyjson_get_len(_Ptr); } [[nodiscard]] size_t Size() const { return yyjson_get_len(_Ptr); } [[nodiscard]] size_t GetStringLength() const { return yyjson_get_len(_Ptr); } [[nodiscard]] MJsonValue Get(const std::string& _key) const { return yyjson_obj_get(_Ptr, _key.c_str()); } [[nodiscard]] MJsonValue operator[](const std::string& _key) const { return yyjson_obj_get(_Ptr, _key.c_str()); } [[nodiscard]] MJsonValue operator[](size_t _idx) const { if (!IsArray()) return _Ptr; const auto _max = yyjson_arr_size(_Ptr); const auto _val = yyjson_arr_get_first(_Ptr); return _idx < _max ? _val + _idx : _val + _max - 1; } [[nodiscard]] bool Empty() const { if (!IsArray() && !IsString()) return true; auto _max = yyjson_arr_size(_Ptr); if (IsString()) _max = yyjson_get_len(_Ptr); return !_max; } [[nodiscard]] size_t GetMemberCount() const { return yyjson_obj_size(_Ptr); } [[nodiscard]] std::vector> GetMemberArray() const { std::vector> ret; yyjson_val* key; yyjson_obj_iter iter = yyjson_obj_iter_with(_Ptr); while ((key = yyjson_obj_iter_next(&iter))) { const auto val = yyjson_obj_iter_get_val(key); ret.emplace_back(MJsonValue(key).GetString(), val); } return ret; } [[nodiscard]] std::pair MemberBegin() const { yyjson_obj_iter iter = yyjson_obj_iter_with(_Ptr); yyjson_val* key = yyjson_obj_iter_next(&iter); return { MJsonValue(key).GetString(), yyjson_obj_iter_get_val(key) }; } [[nodiscard]] bool HasMember(const std::string& _key) const { return yyjson_obj_get(_Ptr, _key.c_str()); } private: yyjson_val* _Ptr = nullptr; }; class MJson { public: MJson() = default; MJson(const char* _path); MJson(const std::string& _data, bool _read_from_string); MJson(const std::wstring& _path); ~MJson() { if(_document) { yyjson_doc_free(_document); _document = nullptr; root = nullptr; } } MJson(MJson&& _Right) noexcept { _document = _Right._document; _Right._document = nullptr; root = yyjson_doc_get_root(_document); } MJson(const MJson& _Right) = delete; MJson& operator=(MJson&& _Right) noexcept { if (_document) yyjson_doc_free(_document); _document = _Right._document; _Right._document = nullptr; root = yyjson_doc_get_root(_document); return *this; } MJson& operator=(const MJson& _Right) = delete; void Parse(const std::string& _str) { _document = yyjson_read(_str.c_str(), _str.length(), YYJSON_READ_NOFLAG); if (!_document) throw std::exception("Json Parse Error !"); root = yyjson_doc_get_root(_document); } [[nodiscard]] bool HasMember(const std::string& _key) const { return yyjson_obj_get(root, _key.c_str()); } [[nodiscard]] MJsonValue Get(const std::string& _key) const { return yyjson_obj_get(root, _key.c_str()); } [[nodiscard]] MJsonValue operator[](const std::string& _key) const { return yyjson_obj_get(root, _key.c_str()); } [[nodiscard]] MJsonValue operator[](size_t _idx) const { if (MJsonValue(root).IsArray()) return root; const auto _max = yyjson_arr_size(root); const auto _val = yyjson_arr_get_first(root); return _idx < _max ? _val + _idx : _val + _max - 1; } [[nodiscard]] bool HasParseError() const { return _document == nullptr; } [[nodiscard]] bool IsNull() const { return yyjson_is_null(root); } [[nodiscard]] bool IsBoolean() const { return yyjson_is_bool(root); } [[nodiscard]] bool IsBool() const { return yyjson_is_bool(root); } [[nodiscard]] bool IsInt() const { return yyjson_is_num(root); } [[nodiscard]] bool IsFloat() const { return yyjson_is_num(root); } [[nodiscard]] bool IsInt64() const { return yyjson_is_num(root); } [[nodiscard]] bool IsDouble() const { return yyjson_is_num(root); } [[nodiscard]] bool IsString() const { return yyjson_is_str(root); } [[nodiscard]] bool IsArray() const { return yyjson_is_arr(root); } [[nodiscard]] bool GetBool() const { return yyjson_get_bool(root); } [[nodiscard]] bool GetBoolean() const { return yyjson_get_bool(root); } [[nodiscard]] int GetInt() const { return int(yyjson_get_num(root)); } [[nodiscard]] int64_t GetInt64() const { return int64_t(yyjson_get_num(root)); } [[nodiscard]] float GetFloat() const { return float(yyjson_get_num(root)); } [[nodiscard]] double GetDouble() const { return yyjson_get_num(root); } [[nodiscard]] std::string GetString() const { if (const auto _str = yyjson_get_str(root)) return _str; return ""; } [[nodiscard]] std::vector GetArray() const { std::vector _ret; if (!IsArray()) return {}; const auto _PArray = root; size_t idx, max; yyjson_val* _Object; yyjson_arr_foreach(_PArray, idx, max, _Object) _ret.emplace_back(_Object); return _ret; } [[nodiscard]] size_t GetSize() const { return yyjson_get_len(root); } [[nodiscard]] size_t Size() const { return yyjson_get_len(root); } [[nodiscard]] size_t GetStringLength() const { return yyjson_get_len(root); } [[nodiscard]] size_t GetMemberCount() const { return yyjson_obj_size(root); } [[nodiscard]] std::vector> GetMemberArray() const { std::vector> ret; yyjson_val* key; yyjson_obj_iter iter = yyjson_obj_iter_with(root); while ((key = yyjson_obj_iter_next(&iter))) { const auto val = yyjson_obj_iter_get_val(key); ret.emplace_back(MJsonValue(key).GetString(), val); } return ret; } private: yyjson_doc* _document = nullptr; yyjson_val* root = nullptr; }; ================================================ FILE: libtts/Modules/Lib/MJson/yyjson.c ================================================ /*============================================================================== * Created by Yaoyuan on 2019/3/9. * Copyright (C) 2019 Yaoyuan . * * Released under the MIT License: * https://github.com/ibireme/yyjson/blob/master/LICENSE *============================================================================*/ #include "yyjson.h" #include /*============================================================================== * Compile Hint Begin *============================================================================*/ /* warning suppress begin */ #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunused-function" # pragma clang diagnostic ignored "-Wunused-parameter" # pragma clang diagnostic ignored "-Wunused-label" # pragma clang diagnostic ignored "-Wunused-macros" #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-function" # pragma GCC diagnostic ignored "-Wunused-parameter" # pragma GCC diagnostic ignored "-Wunused-label" # pragma GCC diagnostic ignored "-Wunused-macros" #elif defined(_MSC_VER) # pragma warning(push) # pragma warning(disable:4100) /* unreferenced formal parameter */ # pragma warning(disable:4102) /* unreferenced label */ # pragma warning(disable:4127) /* conditional expression is constant */ # pragma warning(disable:4706) /* assignment within conditional expression */ #endif /*============================================================================== * Version *============================================================================*/ uint32_t yyjson_version(void) { return YYJSON_VERSION_HEX; } /*============================================================================== * Flags *============================================================================*/ /* gcc version check */ #if defined(__GNUC__) # if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) # define yyjson_gcc_available(major, minor, patch) \ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \ >= (major * 10000 + minor * 100 + patch)) # elif defined(__GNUC_MINOR__) # define yyjson_gcc_available(major, minor, patch) \ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) \ >= (major * 10000 + minor * 100 + patch)) # else # define yyjson_gcc_available(major, minor, patch) \ ((__GNUC__ * 10000) >= (major * 10000 + minor * 100 + patch)) # endif #else # define yyjson_gcc_available(major, minor, patch) 0 #endif /* real gcc check */ #if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__ICC) && \ defined(__GNUC__) && defined(__GNUC_MINOR__) # define YYJSON_IS_REAL_GCC 1 #else # define YYJSON_IS_REAL_GCC 0 #endif /* msvc intrinsic */ #if YYJSON_MSC_VER >= 1400 # include # if defined(_M_AMD64) || defined(_M_ARM64) # define MSC_HAS_BIT_SCAN_64 1 # pragma intrinsic(_BitScanForward64) # pragma intrinsic(_BitScanReverse64) # else # define MSC_HAS_BIT_SCAN_64 0 # endif # if defined(_M_AMD64) || defined(_M_ARM64) || \ defined(_M_IX86) || defined(_M_ARM) # define MSC_HAS_BIT_SCAN 1 # pragma intrinsic(_BitScanForward) # pragma intrinsic(_BitScanReverse) # else # define MSC_HAS_BIT_SCAN 0 # endif # if defined(_M_AMD64) # define MSC_HAS_UMUL128 1 # pragma intrinsic(_umul128) # else # define MSC_HAS_UMUL128 0 # endif #else # define MSC_HAS_BIT_SCAN_64 0 # define MSC_HAS_BIT_SCAN 0 # define MSC_HAS_UMUL128 0 #endif /* gcc builtin */ #if yyjson_has_builtin(__builtin_clzll) || yyjson_gcc_available(3, 4, 0) # define GCC_HAS_CLZLL 1 #else # define GCC_HAS_CLZLL 0 #endif #if yyjson_has_builtin(__builtin_ctzll) || yyjson_gcc_available(3, 4, 0) # define GCC_HAS_CTZLL 1 #else # define GCC_HAS_CTZLL 0 #endif /* int128 type */ #if defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16) && \ (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)) # define YYJSON_HAS_INT128 1 #else # define YYJSON_HAS_INT128 0 #endif /* IEEE 754 floating-point binary representation */ #if defined(__STDC_IEC_559__) || defined(__STDC_IEC_60559_BFP__) # define YYJSON_HAS_IEEE_754 1 #elif (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_DIG == 15) && \ (DBL_MIN_EXP == -1021) && (DBL_MAX_EXP == 1024) && \ (DBL_MIN_10_EXP == -307) && (DBL_MAX_10_EXP == 308) # define YYJSON_HAS_IEEE_754 1 #else # define YYJSON_HAS_IEEE_754 0 #endif /* Correct rounding in double number computations. On the x86 architecture, some compilers may use x87 FPU instructions for floating-point arithmetic. The x87 FPU loads all floating point number as 80-bit double-extended precision internally, then rounds the result to original precision, which may produce inaccurate results. For a more detailed explanation, see the paper: https://arxiv.org/abs/cs/0701192 Here are some examples of double precision calculation error: 2877.0 / 1e6 == 0.002877, but x87 returns 0.0028770000000000002 43683.0 * 1e21 == 4.3683e25, but x87 returns 4.3683000000000004e25 Here are some examples of compiler flags to generate x87 instructions on x86: clang -m32 -mno-sse gcc/icc -m32 -mfpmath=387 msvc /arch:SSE or /arch:IA32 If we are sure that there's no similar error described above, we can define the YYJSON_DOUBLE_MATH_CORRECT as 1 to enable the fast path calculation. This is not an accurate detection, it's just try to avoid the error at compile-time. An accurate detection can be done at run-time: bool is_double_math_correct(void) { volatile double r = 43683.0; r *= 1e21; return r == 4.3683e25; } See also: utils.h in https://github.com/google/double-conversion/ */ #if !defined(FLT_EVAL_METHOD) && defined(__FLT_EVAL_METHOD__) # define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ #endif #if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1 # define YYJSON_DOUBLE_MATH_CORRECT 0 #elif defined(i386) || defined(__i386) || defined(__i386__) || \ defined(_X86_) || defined(__X86__) || defined(_M_IX86) || \ defined(__I86__) || defined(__IA32__) || defined(__THW_INTEL) # if (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 2) || \ (defined(__SSE2_MATH__) && __SSE2_MATH__) # define YYJSON_DOUBLE_MATH_CORRECT 1 # else # define YYJSON_DOUBLE_MATH_CORRECT 0 # endif #elif defined(__mc68000__) || defined(__pnacl__) || defined(__native_client__) # define YYJSON_DOUBLE_MATH_CORRECT 0 #else # define YYJSON_DOUBLE_MATH_CORRECT 1 #endif /* endian */ #if yyjson_has_include() # include #endif #if yyjson_has_include() # include #elif yyjson_has_include() # include #elif yyjson_has_include() # include #endif #define YYJSON_BIG_ENDIAN 4321 #define YYJSON_LITTLE_ENDIAN 1234 #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN # elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif #elif defined(__BYTE_ORDER) && __BYTE_ORDER # if __BYTE_ORDER == __BIG_ENDIAN # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN # elif __BYTE_ORDER == __LITTLE_ENDIAN # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif #elif defined(BYTE_ORDER) && BYTE_ORDER # if BYTE_ORDER == BIG_ENDIAN # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN # elif BYTE_ORDER == LITTLE_ENDIAN # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN # endif #elif (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \ defined(__i386) || defined(__i386__) || \ defined(_X86_) || defined(__X86__) || \ defined(_M_IX86) || defined(__THW_INTEL__) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(__amd64) || defined(__amd64__) || \ defined(_M_AMD64) || defined(_M_X64) || \ defined(__ia64) || defined(_IA64) || defined(__IA64__) || \ defined(__ia64__) || defined(_M_IA64) || defined(__itanium__) || \ defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ defined(__alpha) || defined(__alpha__) || defined(_M_ALPHA) || \ defined(__riscv) || defined(__riscv__) || \ defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \ defined(__EMSCRIPTEN__) || defined(__wasm__) || \ defined(__loongarch__) # define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN #elif (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ defined(__ppc) || defined(__ppc__) || \ defined(__sparc) || defined(__sparc__) || defined(__sparc64__) || \ defined(__or1k__) || defined(__OR1K__) # define YYJSON_ENDIAN YYJSON_BIG_ENDIAN #else # define YYJSON_ENDIAN 0 /* unknown endian, detect at run-time */ #endif /* Unaligned memory access detection. Some architectures cannot perform unaligned memory access, or unaligned memory accesses can have a large performance penalty. Modern compilers can make some optimizations for unaligned access. For example: https://godbolt.org/z/Ejo3Pa typedef struct { char c[2] } vec2; void copy_vec2(vec2 *dst, vec2 *src) { *dst = *src; } Compiler may generate `load/store` or `move` instruction if target architecture supports unaligned access, otherwise it may generate `call memcpy` instruction. We want to avoid `memcpy` calls, so we should disable unaligned access by define `YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS` as 1 on these architectures. */ #ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS # if defined(i386) || defined(__i386) || defined(__i386__) || \ defined(__i486__) || defined(__i586__) || defined(__i686__) || \ defined(_X86_) || defined(__X86__) || defined(_M_IX86) || \ defined(__I86__) || defined(__IA32__) || \ defined(__THW_INTEL) || defined(__THW_INTEL__) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(__amd64) || defined(__amd64__) || \ defined(_M_AMD64) || defined(_M_X64) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* x86 */ # elif defined(__ia64) || defined(_IA64) || defined(__IA64__) || \ defined(__ia64__) || defined(_M_IA64) || defined(__itanium__) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* Itanium */ # elif defined(__arm64) || defined(__arm64__) || \ defined(__AARCH64EL__) || defined(__AARCH64EB__) || \ defined(__aarch64__) || defined(_M_ARM64) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* ARM64 */ # elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || \ defined(__ARM_ARCH_5TEJ__) || defined(__ARM_ARCH_5TE__) || \ defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6KZ__) || \ defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6K__) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* ARM */ # elif defined(__ppc64__) || defined(__PPC64__) || \ defined(__powerpc64__) || defined(_ARCH_PPC64) || \ defined(__ppc) || defined(__ppc__) || defined(__PPC__) || \ defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || \ defined(_ARCH_PPC) || defined(_M_PPC) || \ defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || defined(_XENON) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* PowerPC */ # elif defined(__loongarch__) # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* loongarch */ # else # define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0 /* Unknown */ # endif #endif /* Estimated initial ratio of the JSON data (data_size / value_count). For example: data: {"id":12345678,"name":"Harry"} data_size: 30 value_count: 5 ratio: 6 yyjson uses dynamic memory with a growth factor of 1.5 when reading and writing JSON, the ratios below are used to determine the initial memory size. A too large ratio will waste memory, and a too small ratio will cause multiple memory growths and degrade performance. Currently, these ratios are generated with some commonly used JSON datasets. */ #define YYJSON_READER_ESTIMATED_PRETTY_RATIO 16 #define YYJSON_READER_ESTIMATED_MINIFY_RATIO 6 #define YYJSON_WRITER_ESTIMATED_PRETTY_RATIO 32 #define YYJSON_WRITER_ESTIMATED_MINIFY_RATIO 18 /* The initial and maximum size of the memory pool's chunk in yyjson_mut_doc. */ #define YYJSON_MUT_DOC_STR_POOL_INIT_SIZE 0x100 #define YYJSON_MUT_DOC_STR_POOL_MAX_SIZE 0x10000000 #define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val)) #define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val)) /* Default value for compile-time options. */ #ifndef YYJSON_DISABLE_READER #define YYJSON_DISABLE_READER 0 #endif #ifndef YYJSON_DISABLE_WRITER #define YYJSON_DISABLE_WRITER 0 #endif #ifndef YYJSON_DISABLE_UTILS #define YYJSON_DISABLE_UTILS 0 #endif #ifndef YYJSON_DISABLE_FAST_FP_CONV #define YYJSON_DISABLE_FAST_FP_CONV 0 #endif #ifndef YYJSON_DISABLE_NON_STANDARD #define YYJSON_DISABLE_NON_STANDARD 0 #endif /*============================================================================== * Macros *============================================================================*/ /* Macros used for loop unrolling and other purpose. */ #define repeat2(x) { x x } #define repeat3(x) { x x x } #define repeat4(x) { x x x x } #define repeat8(x) { x x x x x x x x } #define repeat16(x) { x x x x x x x x x x x x x x x x } #define repeat2_incr(x) { x(0) x(1) } #define repeat4_incr(x) { x(0) x(1) x(2) x(3) } #define repeat8_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) } #define repeat16_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) } #define repeat_in_1_18(x) { x(1) x(2) x(3) x(4) x(5) x(6) x(7) \ x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) \ x(16) x(17) x(18) } /* Macros used to provide branch prediction information for compiler. */ #undef likely #define likely(x) yyjson_likely(x) #undef unlikely #define unlikely(x) yyjson_unlikely(x) /* Macros used to provide inline information for compiler. */ #undef static_inline #define static_inline static yyjson_inline #undef static_noinline #define static_noinline static yyjson_noinline /* Macros for min and max. */ #undef yyjson_min #define yyjson_min(x, y) ((x) < (y) ? (x) : (y)) #undef yyjson_max #define yyjson_max(x, y) ((x) > (y) ? (x) : (y)) /* Used to write u64 literal for C89 which doesn't support "ULL" suffix. */ #undef U64 #define U64(hi, lo) ((((u64)hi##UL) << 32U) + lo##UL) /* Used to cast away (remove) const qualifier. */ #define constcast(type) (type)(void *)(size_t)(const void *) /*============================================================================== * Integer Constants *============================================================================*/ /* U64 constant values */ #undef U64_MAX #define U64_MAX U64(0xFFFFFFFF, 0xFFFFFFFF) #undef I64_MAX #define I64_MAX U64(0x7FFFFFFF, 0xFFFFFFFF) #undef USIZE_MAX #define USIZE_MAX ((usize)(~(usize)0)) /* Maximum number of digits for reading u32/u64/usize safety (not overflow). */ #undef U32_SAFE_DIG #define U32_SAFE_DIG 9 /* u32 max is 4294967295, 10 digits */ #undef U64_SAFE_DIG #define U64_SAFE_DIG 19 /* u64 max is 18446744073709551615, 20 digits */ #undef USIZE_SAFE_DIG #define USIZE_SAFE_DIG (sizeof(usize) == 64 ? U64_SAFE_DIG : U32_SAFE_DIG) /*============================================================================== * IEEE-754 Double Number Constants *============================================================================*/ /* Inf raw value (positive) */ #define F64_RAW_INF U64(0x7FF00000, 0x00000000) /* NaN raw value (quiet NaN, no payload, no sign) */ #if defined(__hppa__) || (defined(__mips__) && !defined(__mips_nan2008)) #define F64_RAW_NAN U64(0x7FF7FFFF, 0xFFFFFFFF) #else #define F64_RAW_NAN U64(0x7FF80000, 0x00000000) #endif /* double number bits */ #define F64_BITS 64 /* double number exponent part bits */ #define F64_EXP_BITS 11 /* double number significand part bits */ #define F64_SIG_BITS 52 /* double number significand part bits (with 1 hidden bit) */ #define F64_SIG_FULL_BITS 53 /* double number significand bit mask */ #define F64_SIG_MASK U64(0x000FFFFF, 0xFFFFFFFF) /* double number exponent bit mask */ #define F64_EXP_MASK U64(0x7FF00000, 0x00000000) /* double number exponent bias */ #define F64_EXP_BIAS 1023 /* double number significant digits count in decimal */ #define F64_DEC_DIG 17 /* max significant digits count in decimal when reading double number */ #define F64_MAX_DEC_DIG 768 /* maximum decimal power of double number (1.7976931348623157e308) */ #define F64_MAX_DEC_EXP 308 /* minimum decimal power of double number (4.9406564584124654e-324) */ #define F64_MIN_DEC_EXP (-324) /* maximum binary power of double number */ #define F64_MAX_BIN_EXP 1024 /* minimum binary power of double number */ #define F64_MIN_BIN_EXP (-1021) /*============================================================================== * Types *============================================================================*/ /** Type define for primitive types. */ typedef float f32; typedef double f64; typedef int8_t i8; typedef uint8_t u8; typedef int16_t i16; typedef uint16_t u16; typedef int32_t i32; typedef uint32_t u32; typedef int64_t i64; typedef uint64_t u64; typedef size_t usize; /** 128-bit integer, used by floating-point number reader and writer. */ #if YYJSON_HAS_INT128 __extension__ typedef __int128 i128; __extension__ typedef unsigned __int128 u128; #endif /** 16/32/64-bit vector */ typedef struct v16 { char c1, c2; } v16; typedef struct v32 { char c1, c2, c3, c4; } v32; typedef struct v64 { char c1, c2, c3, c4, c5, c6, c7, c8; } v64; /** 16/32/64-bit vector union, used for unaligned memory access on modern CPU */ typedef union v16_uni { v16 v; u16 u; } v16_uni; typedef union v32_uni { v32 v; u32 u; } v32_uni; typedef union v64_uni { v64 v; u64 u; } v64_uni; /*============================================================================== * Load/Store Utils *============================================================================*/ #define byte_move_idx(x) ((u8 *)dst)[x] = ((u8 *)src)[x]; static_inline void byte_move_2(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat2_incr(byte_move_idx) #else memmove(dst, src, 2); #endif } static_inline void byte_move_4(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat4_incr(byte_move_idx) #else memmove(dst, src, 4); #endif } static_inline void byte_move_8(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat8_incr(byte_move_idx) #else memmove(dst, src, 8); #endif } static_inline void byte_move_16(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat16_incr(byte_move_idx) #else memmove(dst, src, 16); #endif } static_inline void byte_copy_2(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat2_incr(byte_move_idx) #else memcpy(dst, src, 2); #endif } static_inline void byte_copy_4(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat4_incr(byte_move_idx) #else memcpy(dst, src, 4); #endif } static_inline void byte_copy_8(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat8_incr(byte_move_idx) #else memcpy(dst, src, 8); #endif } static_inline void byte_copy_16(void *dst, const void *src) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS repeat16_incr(byte_move_idx) #else memcpy(dst, src, 16); #endif } static_inline bool byte_match_2(void *buf, const char *pat) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS return ((u8 *)buf)[0] == ((const u8 *)pat)[0] && ((u8 *)buf)[1] == ((const u8 *)pat)[1]; #else v16_uni u1, u2; u1.v = *(const v16 *)pat; u2.v = *(const v16 *)buf; return u1.u == u2.u; #endif } static_inline bool byte_match_4(void *buf, const char *pat) { #if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS return ((u8 *)buf)[0] == ((const u8 *)pat)[0] && ((u8 *)buf)[1] == ((const u8 *)pat)[1] && ((u8 *)buf)[2] == ((const u8 *)pat)[2] && ((u8 *)buf)[3] == ((const u8 *)pat)[3]; #else v32_uni u1, u2; u1.v = *(const v32 *)pat; u2.v = *(const v32 *)buf; return u1.u == u2.u; #endif } static_inline u16 byte_load_2(const void *src) { v16_uni uni; uni.v = *(const v16 *)src; return uni.u; } static_inline u32 byte_load_3(const void *src) { v32_uni uni; ((v16_uni *)&uni)->v = *(const v16 *)src; uni.v.c3 = ((const char *)src)[2]; uni.v.c4 = 0; return uni.u; } static_inline u32 byte_load_4(const void *src) { v32_uni uni; uni.v = *(const v32 *)src; return uni.u; } #undef byte_move_expr /*============================================================================== * Number Utils * These functions are used to detect and convert NaN and Inf numbers. *============================================================================*/ /** This union is used to avoid violating the strict aliasing rule in C. `memcpy` can be used in both C and C++, but it may reduce performance without compiler optimization. */ typedef union { u64 u; f64 f; } f64_uni; /** Convert raw binary to double. */ static_inline f64 f64_from_raw(u64 u) { #ifndef __cplusplus f64_uni uni; uni.u = u; return uni.f; #else f64 f; memcpy(&f, &u, 8); return f; #endif } /** Convert double to raw binary. */ static_inline u64 f64_to_raw(f64 f) { #ifndef __cplusplus f64_uni uni; uni.f = f; return uni.u; #else u64 u; memcpy(&u, &f, 8); return u; #endif } /** Get raw 'infinity' with sign. */ static_inline u64 f64_raw_get_inf(bool sign) { #if YYJSON_HAS_IEEE_754 return F64_RAW_INF | ((u64)sign << 63); #elif defined(INFINITY) return f64_to_raw(sign ? -INFINITY : INFINITY); #else return f64_to_raw(sign ? -HUGE_VAL : HUGE_VAL); #endif } /** Get raw 'nan' with sign. */ static_inline u64 f64_raw_get_nan(bool sign) { #if YYJSON_HAS_IEEE_754 return F64_RAW_NAN | ((u64)sign << 63); #elif defined(NAN) return f64_to_raw(sign ? (f64)-NAN : (f64)NAN); #else return f64_to_raw((sign ? -0.0 : 0.0) / 0.0); #endif } /** Convert normalized u64 (highest bit is 1) to f64. Some compiler (such as Microsoft Visual C++ 6.0) do not support converting number from u64 to f64. This function will first convert u64 to i64 and then to f64, with `to nearest` rounding mode. */ static_inline f64 normalized_u64_to_f64(u64 val) { #if YYJSON_U64_TO_F64_NO_IMPL i64 sig = (i64)((val >> 1) | (val & 1)); return ((f64)sig) * (f64)2.0; #else return (f64)val; #endif } /*============================================================================== * Size Utils * These functions are used for memory allocation. *============================================================================*/ /** Returns whether the size is overflow after increment. */ static_inline bool size_add_is_overflow(usize size, usize add) { return size > (size + add); } /** Returns whether the size is power of 2 (size should not be 0). */ static_inline bool size_is_pow2(usize size) { return (size & (size - 1)) == 0; } /** Align size upwards (may overflow). */ static_inline usize size_align_up(usize size, usize align) { if (size_is_pow2(align)) { return (size + (align - 1)) & ~(align - 1); } else { return size + align - (size + align - 1) % align - 1; } } /** Align size downwards. */ static_inline usize size_align_down(usize size, usize align) { if (size_is_pow2(align)) { return size & ~(align - 1); } else { return size - (size % align); } } /** Align address upwards (may overflow). */ static_inline void *mem_align_up(void *mem, usize align) { usize size; memcpy(&size, &mem, sizeof(usize)); size = size_align_up(size, align); memcpy(&mem, &size, sizeof(usize)); return mem; } /*============================================================================== * Bits Utils * These functions are used by the floating-point number reader and writer. *============================================================================*/ /** Returns the number of leading 0-bits in value (input should not be 0). */ static_inline u32 u64_lz_bits(u64 v) { #if GCC_HAS_CLZLL return (u32)__builtin_clzll(v); #elif MSC_HAS_BIT_SCAN_64 unsigned long r; _BitScanReverse64(&r, v); return (u32)63 - (u32)r; #elif MSC_HAS_BIT_SCAN unsigned long hi, lo; bool hi_set = _BitScanReverse(&hi, (u32)(v >> 32)) != 0; _BitScanReverse(&lo, (u32)v); hi |= 32; return (u32)63 - (u32)(hi_set ? hi : lo); #else /* branchless, use de Bruijn sequences see: https://www.chessprogramming.org/BitScan */ const u8 table[64] = { 63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2, 9, 5, 28, 11, 13, 21, 42, 19, 25, 31, 34, 40, 46, 52, 59, 1, 17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41, 53, 18, 38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0 }; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v |= v >> 32; return table[(v * U64(0x03F79D71, 0xB4CB0A89)) >> 58]; #endif } /** Returns the number of trailing 0-bits in value (input should not be 0). */ static_inline u32 u64_tz_bits(u64 v) { #if GCC_HAS_CTZLL return (u32)__builtin_ctzll(v); #elif MSC_HAS_BIT_SCAN_64 unsigned long r; _BitScanForward64(&r, v); return (u32)r; #elif MSC_HAS_BIT_SCAN unsigned long lo, hi; bool lo_set = _BitScanForward(&lo, (u32)(v)) != 0; _BitScanForward(&hi, (u32)(v >> 32)); hi += 32; return lo_set ? lo : hi; #else /* branchless, use de Bruijn sequences see: https://www.chessprogramming.org/BitScan */ const u8 table[64] = { 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10, 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12 }; return table[((v & (~v + 1)) * U64(0x022FDD63, 0xCC95386D)) >> 58]; #endif } /*============================================================================== * 128-bit Integer Utils * These functions are used by the floating-point number reader and writer. *============================================================================*/ /** Multiplies two 64-bit unsigned integers (a * b), returns the 128-bit result as 'hi' and 'lo'. */ static_inline void u128_mul(u64 a, u64 b, u64 *hi, u64 *lo) { #if YYJSON_HAS_INT128 u128 m = (u128)a * b; *hi = (u64)(m >> 64); *lo = (u64)(m); #elif MSC_HAS_UMUL128 *lo = _umul128(a, b, hi); #else u32 a0 = (u32)(a), a1 = (u32)(a >> 32); u32 b0 = (u32)(b), b1 = (u32)(b >> 32); u64 p00 = (u64)a0 * b0, p01 = (u64)a0 * b1; u64 p10 = (u64)a1 * b0, p11 = (u64)a1 * b1; u64 m0 = p01 + (p00 >> 32); u32 m00 = (u32)(m0), m01 = (u32)(m0 >> 32); u64 m1 = p10 + m00; u32 m10 = (u32)(m1), m11 = (u32)(m1 >> 32); *hi = p11 + m01 + m11; *lo = ((u64)m10 << 32) | (u32)p00; #endif } /** Multiplies two 64-bit unsigned integers and add a value (a * b + c), returns the 128-bit result as 'hi' and 'lo'. */ static_inline void u128_mul_add(u64 a, u64 b, u64 c, u64 *hi, u64 *lo) { #if YYJSON_HAS_INT128 u128 m = (u128)a * b + c; *hi = (u64)(m >> 64); *lo = (u64)(m); #else u64 h, l, t; u128_mul(a, b, &h, &l); t = l + c; h += (u64)(((t < l) | (t < c))); *hi = h; *lo = t; #endif } /*============================================================================== * File Utils * These functions are used to read and write JSON files. *============================================================================*/ #define YYJSON_FOPEN_EXT #if !defined(_MSC_VER) && defined(__GLIBC__) && defined(__GLIBC_PREREQ) # if __GLIBC_PREREQ(2, 7) # undef YYJSON_FOPEN_EXT # define YYJSON_FOPEN_EXT "e" /* glibc extension to enable O_CLOEXEC */ # endif #endif static_inline FILE *fopen_safe(const char *path, const char *mode) { #if YYJSON_MSC_VER >= 1400 FILE *file = NULL; if (fopen_s(&file, path, mode) != 0) return NULL; return file; #else return fopen(path, mode); #endif } static_inline FILE *fopen_readonly(const char *path) { return fopen_safe(path, "rb" YYJSON_FOPEN_EXT); } static_inline FILE *fopen_writeonly(const char *path) { return fopen_safe(path, "wb" YYJSON_FOPEN_EXT); } static_inline usize fread_safe(void *buf, usize size, FILE *file) { #if YYJSON_MSC_VER >= 1400 return fread_s(buf, size, 1, size, file); #else return fread(buf, 1, size, file); #endif } /*============================================================================== * Default Memory Allocator * This is a simple libc memory allocator wrapper. *============================================================================*/ static void *default_malloc(void *ctx, usize size) { return malloc(size); } static void *default_realloc(void *ctx, void *ptr, usize old_size, usize size) { return realloc(ptr, size); } static void default_free(void *ctx, void *ptr) { free(ptr); } static const yyjson_alc YYJSON_DEFAULT_ALC = { default_malloc, default_realloc, default_free, NULL }; static void *null_malloc(void *ctx, usize size) { return NULL; } static void *null_realloc(void *ctx, void *ptr, usize old_size, usize size) { return NULL; } static void null_free(void *ctx, void *ptr) { return; } static const yyjson_alc YYJSON_NULL_ALC = { null_malloc, null_realloc, null_free, NULL }; /*============================================================================== * Pool Memory Allocator * This is a simple memory allocator that uses linked list memory chunk. * The following code will be executed only when the library user creates * this allocator manually. *============================================================================*/ /** chunk header */ typedef struct pool_chunk { usize size; /* chunk memory size (include chunk header) */ struct pool_chunk *next; } pool_chunk; /** ctx header */ typedef struct pool_ctx { usize size; /* total memory size (include ctx header) */ pool_chunk *free_list; } pool_ctx; static void *pool_malloc(void *ctx_ptr, usize size) { pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *next, *prev = NULL, *cur = ctx->free_list; if (unlikely(size == 0 || size >= ctx->size)) return NULL; size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk); while (cur) { if (cur->size < size) { /* not enough space, try next chunk */ prev = cur; cur = cur->next; continue; } if (cur->size >= size + sizeof(pool_chunk) * 2) { /* too much space, split this chunk */ next = (pool_chunk *)(void *)((u8 *)cur + size); next->size = cur->size - size; next->next = cur->next; cur->size = size; } else { /* just enough space, use whole chunk */ next = cur->next; } if (prev) prev->next = next; else ctx->free_list = next; return (void *)(cur + 1); } return NULL; } static void pool_free(void *ctx_ptr, void *ptr) { pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *cur = ((pool_chunk *)ptr) - 1; pool_chunk *prev = NULL, *next = ctx->free_list; while (next && next < cur) { prev = next; next = next->next; } if (prev) prev->next = cur; else ctx->free_list = cur; cur->next = next; if (next && ((u8 *)cur + cur->size) == (u8 *)next) { /* merge cur to higher chunk */ cur->size += next->size; cur->next = next->next; } if (prev && ((u8 *)prev + prev->size) == (u8 *)cur) { /* merge cur to lower chunk */ prev->size += cur->size; prev->next = cur->next; } } static void *pool_realloc(void *ctx_ptr, void *ptr, usize old_size, usize size) { pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *cur = ((pool_chunk *)ptr) - 1, *prev, *next, *tmp; usize free_size; void *new_ptr; if (unlikely(size == 0 || size >= ctx->size)) return NULL; size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk); /* reduce size */ if (unlikely(size <= cur->size)) { free_size = cur->size - size; if (free_size >= sizeof(pool_chunk) * 2) { tmp = (pool_chunk *)(void *)((u8 *)cur + cur->size - free_size); tmp->size = free_size; pool_free(ctx_ptr, (void *)(tmp + 1)); cur->size -= free_size; } return ptr; } /* find next and prev chunk */ prev = NULL; next = ctx->free_list; while (next && next < cur) { prev = next; next = next->next; } /* merge to higher chunk if they are contiguous */ if ((u8 *)cur + cur->size == (u8 *)next && cur->size + next->size >= size) { free_size = cur->size + next->size - size; if (free_size > sizeof(pool_chunk) * 2) { tmp = (pool_chunk *)(void *)((u8 *)cur + size); if (prev) prev->next = tmp; else ctx->free_list = tmp; tmp->next = next->next; tmp->size = free_size; cur->size = size; } else { if (prev) prev->next = next->next; else ctx->free_list = next->next; cur->size += next->size; } return ptr; } /* fallback to malloc and memcpy */ new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk)); if (new_ptr) { memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk)); pool_free(ctx_ptr, ptr); } return new_ptr; } bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) { pool_chunk *chunk; pool_ctx *ctx; if (unlikely(!alc)) return false; *alc = YYJSON_NULL_ALC; if (size < sizeof(pool_ctx) * 4) return false; ctx = (pool_ctx *)mem_align_up(buf, sizeof(pool_ctx)); if (unlikely(!ctx)) return false; size -= (usize)((u8 *)ctx - (u8 *)buf); size = size_align_down(size, sizeof(pool_ctx)); chunk = (pool_chunk *)(ctx + 1); chunk->size = size - sizeof(pool_ctx); chunk->next = NULL; ctx->size = size; ctx->free_list = chunk; alc->malloc = pool_malloc; alc->realloc = pool_realloc; alc->free = pool_free; alc->ctx = (void *)ctx; return true; } /*============================================================================== * JSON document and value *============================================================================*/ static_inline void unsafe_yyjson_str_pool_release(yyjson_str_pool *pool, yyjson_alc *alc) { yyjson_str_chunk *chunk = pool->chunks, *next; while (chunk) { next = chunk->next; alc->free(alc->ctx, chunk); chunk = next; } } static_inline void unsafe_yyjson_val_pool_release(yyjson_val_pool *pool, yyjson_alc *alc) { yyjson_val_chunk *chunk = pool->chunks, *next; while (chunk) { next = chunk->next; alc->free(alc->ctx, chunk); chunk = next; } } bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool, const yyjson_alc *alc, usize len) { yyjson_str_chunk *chunk; usize size, max_len; /* create a new chunk */ max_len = USIZE_MAX - sizeof(yyjson_str_chunk); if (unlikely(len > max_len)) return false; size = len + sizeof(yyjson_str_chunk); size = yyjson_max(pool->chunk_size, size); chunk = (yyjson_str_chunk *)alc->malloc(alc->ctx, size); if (unlikely(!chunk)) return false; /* insert the new chunk as the head of the linked list */ chunk->next = pool->chunks; chunk->chunk_size = size; pool->chunks = chunk; pool->cur = (char *)chunk + sizeof(yyjson_str_chunk); pool->end = (char *)chunk + size; /* the next chunk is twice the size of the current one */ size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max); if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */ pool->chunk_size = size; return true; } bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool, const yyjson_alc *alc, usize count) { yyjson_val_chunk *chunk; usize size, max_count; /* create a new chunk */ max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1; if (unlikely(count > max_count)) return false; size = (count + 1) * sizeof(yyjson_mut_val); size = yyjson_max(pool->chunk_size, size); chunk = (yyjson_val_chunk *)alc->malloc(alc->ctx, size); if (unlikely(!chunk)) return false; /* insert the new chunk as the head of the linked list */ chunk->next = pool->chunks; chunk->chunk_size = size; pool->chunks = chunk; pool->cur = (yyjson_mut_val *)(void *)((u8 *)chunk) + 1; pool->end = (yyjson_mut_val *)(void *)((u8 *)chunk + size); /* the next chunk is twice the size of the current one */ size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max); if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */ pool->chunk_size = size; return true; } bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc, size_t len) { usize max_size = USIZE_MAX - sizeof(yyjson_str_chunk); if (!doc || !len || len > max_size) return false; doc->str_pool.chunk_size = len + sizeof(yyjson_str_chunk); return true; } bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count) { usize max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1; if (!doc || !count || count > max_count) return false; doc->val_pool.chunk_size = (count + 1) * sizeof(yyjson_mut_val); return true; } void yyjson_mut_doc_free(yyjson_mut_doc *doc) { if (doc) { yyjson_alc alc = doc->alc; unsafe_yyjson_str_pool_release(&doc->str_pool, &alc); unsafe_yyjson_val_pool_release(&doc->val_pool, &alc); alc.free(alc.ctx, doc); } } yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc) { yyjson_mut_doc *doc; if (!alc) alc = &YYJSON_DEFAULT_ALC; doc = (yyjson_mut_doc *)alc->malloc(alc->ctx, sizeof(yyjson_mut_doc)); if (!doc) return NULL; memset(doc, 0, sizeof(yyjson_mut_doc)); doc->alc = *alc; doc->str_pool.chunk_size = YYJSON_MUT_DOC_STR_POOL_INIT_SIZE; doc->str_pool.chunk_size_max = YYJSON_MUT_DOC_STR_POOL_MAX_SIZE; doc->val_pool.chunk_size = YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE; doc->val_pool.chunk_size_max = YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE; return doc; } yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, const yyjson_alc *alc) { yyjson_mut_doc *m_doc; yyjson_mut_val *m_val; if (!doc || !doc->root) return NULL; m_doc = yyjson_mut_doc_new(alc); if (!m_doc) return NULL; m_val = yyjson_val_mut_copy(m_doc, doc->root); if (!m_val) { yyjson_mut_doc_free(m_doc); return NULL; } yyjson_mut_doc_set_root(m_doc, m_val); return m_doc; } yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc, const yyjson_alc *alc) { yyjson_mut_doc *m_doc; yyjson_mut_val *m_val; if (!doc) return NULL; if (!doc->root) return yyjson_mut_doc_new(alc); m_doc = yyjson_mut_doc_new(alc); if (!m_doc) return NULL; m_val = yyjson_mut_val_mut_copy(m_doc, doc->root); if (!m_val) { yyjson_mut_doc_free(m_doc); return NULL; } yyjson_mut_doc_set_root(m_doc, m_val); return m_doc; } yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc, yyjson_val *i_vals) { /* The immutable object or array stores all sub-values in a contiguous memory, We copy them to another contiguous memory as mutable values, then reconnect the mutable values with the original relationship. */ usize i_vals_len; yyjson_mut_val *m_vals, *m_val; yyjson_val *i_val, *i_end; if (!m_doc || !i_vals) return NULL; i_end = unsafe_yyjson_get_next(i_vals); i_vals_len = (usize)(unsafe_yyjson_get_next(i_vals) - i_vals); m_vals = unsafe_yyjson_mut_val(m_doc, i_vals_len); if (!m_vals) return NULL; i_val = i_vals; m_val = m_vals; for (; i_val < i_end; i_val++, m_val++) { yyjson_type type = unsafe_yyjson_get_type(i_val); m_val->tag = i_val->tag; m_val->uni.u64 = i_val->uni.u64; if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { const char *str = i_val->uni.str; usize str_len = unsafe_yyjson_get_len(i_val); m_val->uni.str = unsafe_yyjson_mut_strncpy(m_doc, str, str_len); if (!m_val->uni.str) return NULL; } else if (type == YYJSON_TYPE_ARR) { usize len = unsafe_yyjson_get_len(i_val); if (len > 0) { yyjson_val *ii_val = i_val + 1, *ii_next; yyjson_mut_val *mm_val = m_val + 1, *mm_ctn = m_val, *mm_next; while (len-- > 1) { ii_next = unsafe_yyjson_get_next(ii_val); mm_next = mm_val + (ii_next - ii_val); mm_val->next = mm_next; ii_val = ii_next; mm_val = mm_next; } mm_val->next = mm_ctn + 1; mm_ctn->uni.ptr = mm_val; } } else if (type == YYJSON_TYPE_OBJ) { usize len = unsafe_yyjson_get_len(i_val); if (len > 0) { yyjson_val *ii_key = i_val + 1, *ii_nextkey; yyjson_mut_val *mm_key = m_val + 1, *mm_ctn = m_val; yyjson_mut_val *mm_nextkey; while (len-- > 1) { ii_nextkey = unsafe_yyjson_get_next(ii_key + 1); mm_nextkey = mm_key + (ii_nextkey - ii_key); mm_key->next = mm_key + 1; mm_key->next->next = mm_nextkey; ii_key = ii_nextkey; mm_key = mm_nextkey; } mm_key->next = mm_key + 1; mm_key->next->next = mm_ctn + 1; mm_ctn->uni.ptr = mm_key; } } } return m_vals; } static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc, yyjson_mut_val *m_vals) { /* The mutable object or array stores all sub-values in a circular linked list, so we can traverse them in the same loop. The traversal starts from the last item, continues with the first item in a list, and ends with the second to last item, which needs to be linked to the last item to close the circle. */ yyjson_mut_val *m_val = unsafe_yyjson_mut_val(m_doc, 1); if (unlikely(!m_val)) return NULL; m_val->tag = m_vals->tag; switch (unsafe_yyjson_get_type(m_vals)) { case YYJSON_TYPE_OBJ: case YYJSON_TYPE_ARR: if (unsafe_yyjson_get_len(m_vals) > 0) { yyjson_mut_val *last = (yyjson_mut_val *)m_vals->uni.ptr; yyjson_mut_val *next = last->next, *prev; prev = unsafe_yyjson_mut_val_mut_copy(m_doc, last); if (!prev) return NULL; m_val->uni.ptr = (void *)prev; while (next != last) { prev->next = unsafe_yyjson_mut_val_mut_copy(m_doc, next); if (!prev->next) return NULL; prev = prev->next; next = next->next; } prev->next = (yyjson_mut_val *)m_val->uni.ptr; } break; case YYJSON_TYPE_RAW: case YYJSON_TYPE_STR: { const char *str = m_vals->uni.str; usize str_len = unsafe_yyjson_get_len(m_vals); m_val->uni.str = unsafe_yyjson_mut_strncpy(m_doc, str, str_len); if (!m_val->uni.str) return NULL; break; } default: m_val->uni = m_vals->uni; break; } return m_val; } yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc, yyjson_mut_val *val) { if (doc && val) return unsafe_yyjson_mut_val_mut_copy(doc, val); return NULL; } /* Count the number of values and the total length of the strings. */ static void yyjson_mut_stat(yyjson_mut_val *val, usize *val_sum, usize *str_sum) { yyjson_type type = unsafe_yyjson_get_type(val); *val_sum += 1; if (type == YYJSON_TYPE_ARR || type == YYJSON_TYPE_OBJ) { yyjson_mut_val *child = (yyjson_mut_val *)val->uni.ptr; usize len = unsafe_yyjson_get_len(val), i; len <<= (u8)(type == YYJSON_TYPE_OBJ); *val_sum += len; for (i = 0; i < len; i++) { yyjson_type stype = unsafe_yyjson_get_type(child); if (stype == YYJSON_TYPE_STR || stype == YYJSON_TYPE_RAW) { *str_sum += unsafe_yyjson_get_len(child) + 1; } else if (stype == YYJSON_TYPE_ARR || stype == YYJSON_TYPE_OBJ) { yyjson_mut_stat(child, val_sum, str_sum); *val_sum -= 1; } child = child->next; } } else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { *str_sum += unsafe_yyjson_get_len(val) + 1; } } /* Copy mutable values to immutable value pool. */ static usize yyjson_imut_copy(yyjson_val **val_ptr, char **buf_ptr, yyjson_mut_val *mval) { yyjson_val *val = *val_ptr; yyjson_type type = unsafe_yyjson_get_type(mval); if (type == YYJSON_TYPE_ARR || type == YYJSON_TYPE_OBJ) { yyjson_mut_val *child = (yyjson_mut_val *)mval->uni.ptr; usize len = unsafe_yyjson_get_len(mval), i; usize val_sum = 1; if (type == YYJSON_TYPE_OBJ) { if (len) child = child->next->next; len <<= 1; } else { if (len) child = child->next; } *val_ptr = val + 1; for (i = 0; i < len; i++) { val_sum += yyjson_imut_copy(val_ptr, buf_ptr, child); child = child->next; } val->tag = mval->tag; val->uni.ofs = val_sum * sizeof(yyjson_val); return val_sum; } else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) { char *buf = *buf_ptr; usize len = unsafe_yyjson_get_len(mval); memcpy((void *)buf, (const void *)mval->uni.str, len); buf[len] = '\0'; val->tag = mval->tag; val->uni.str = buf; *val_ptr = val + 1; *buf_ptr = buf + len + 1; return 1; } else { val->tag = mval->tag; val->uni = mval->uni; *val_ptr = val + 1; return 1; } } yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *mdoc, const yyjson_alc *alc) { if (!mdoc) return NULL; return yyjson_mut_val_imut_copy(mdoc->root, alc); } yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *mval, const yyjson_alc *alc) { usize val_num = 0, str_sum = 0, hdr_size, buf_size; yyjson_doc *doc = NULL; yyjson_val *val_hdr = NULL; /* This value should be NULL here. Setting a non-null value suppresses warning from the clang analyzer. */ char *str_hdr = (char *)(void *)&str_sum; if (!mval) return NULL; if (!alc) alc = &YYJSON_DEFAULT_ALC; /* traverse the input value to get pool size */ yyjson_mut_stat(mval, &val_num, &str_sum); /* create doc and val pool */ hdr_size = size_align_up(sizeof(yyjson_doc), sizeof(yyjson_val)); buf_size = hdr_size + val_num * sizeof(yyjson_val); doc = (yyjson_doc *)alc->malloc(alc->ctx, buf_size); if (!doc) return NULL; memset(doc, 0, sizeof(yyjson_doc)); val_hdr = (yyjson_val *)(void *)((char *)(void *)doc + hdr_size); doc->root = val_hdr; doc->alc = *alc; /* create str pool */ if (str_sum > 0) { str_hdr = (char *)alc->malloc(alc->ctx, str_sum); doc->str_pool = str_hdr; if (!str_hdr) { alc->free(alc->ctx, (void *)doc); return NULL; } } /* copy vals and strs */ doc->val_read = yyjson_imut_copy(&val_hdr, &str_hdr, mval); doc->dat_read = str_sum + 1; return doc; } static_inline bool unsafe_yyjson_num_equals(void *lhs, void *rhs) { yyjson_val_uni *luni = &((yyjson_val *)lhs)->uni; yyjson_val_uni *runi = &((yyjson_val *)rhs)->uni; yyjson_subtype lt = unsafe_yyjson_get_subtype(lhs); yyjson_subtype rt = unsafe_yyjson_get_subtype(rhs); if (lt == rt) return luni->u64 == runi->u64; if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) return luni->i64 >= 0 && luni->u64 == runi->u64; if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) return runi->i64 >= 0 && luni->u64 == runi->u64; return false; } static_inline bool unsafe_yyjson_str_equals(void *lhs, void *rhs) { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; return !memcmp(unsafe_yyjson_get_str(lhs), unsafe_yyjson_get_str(rhs), len); } bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { yyjson_type type = unsafe_yyjson_get_type(lhs); if (type != unsafe_yyjson_get_type(rhs)) return false; switch (type) { case YYJSON_TYPE_OBJ: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; if (len > 0) { yyjson_obj_iter iter; yyjson_obj_iter_init(rhs, &iter); lhs = unsafe_yyjson_get_first(lhs); while (len-- > 0) { rhs = yyjson_obj_iter_getn(&iter, lhs->uni.str, unsafe_yyjson_get_len(lhs)); if (!rhs || !unsafe_yyjson_equals(lhs + 1, rhs)) return false; lhs = unsafe_yyjson_get_next(lhs + 1); } } /* yyjson allows duplicate keys, so the check may be inaccurate */ return true; } case YYJSON_TYPE_ARR: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; if (len > 0) { lhs = unsafe_yyjson_get_first(lhs); rhs = unsafe_yyjson_get_first(rhs); while (len-- > 0) { if (!unsafe_yyjson_equals(lhs, rhs)) return false; lhs = unsafe_yyjson_get_next(lhs); rhs = unsafe_yyjson_get_next(rhs); } } return true; } case YYJSON_TYPE_NUM: return unsafe_yyjson_num_equals(lhs, rhs); case YYJSON_TYPE_RAW: case YYJSON_TYPE_STR: return unsafe_yyjson_str_equals(lhs, rhs); case YYJSON_TYPE_NULL: case YYJSON_TYPE_BOOL: return lhs->tag == rhs->tag; default: return false; } } bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { yyjson_type type = unsafe_yyjson_get_type(lhs); if (type != unsafe_yyjson_get_type(rhs)) return false; switch (type) { case YYJSON_TYPE_OBJ: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; if (len > 0) { yyjson_mut_obj_iter iter; yyjson_mut_obj_iter_init(rhs, &iter); lhs = (yyjson_mut_val *)lhs->uni.ptr; while (len-- > 0) { rhs = yyjson_mut_obj_iter_getn(&iter, lhs->uni.str, unsafe_yyjson_get_len(lhs)); if (!rhs || !unsafe_yyjson_mut_equals(lhs->next, rhs)) return false; lhs = lhs->next->next; } } /* yyjson allows duplicate keys, so the check may be inaccurate */ return true; } case YYJSON_TYPE_ARR: { usize len = unsafe_yyjson_get_len(lhs); if (len != unsafe_yyjson_get_len(rhs)) return false; if (len > 0) { lhs = (yyjson_mut_val *)lhs->uni.ptr; rhs = (yyjson_mut_val *)rhs->uni.ptr; while (len-- > 0) { if (!unsafe_yyjson_mut_equals(lhs, rhs)) return false; lhs = lhs->next; rhs = rhs->next; } } return true; } case YYJSON_TYPE_NUM: return unsafe_yyjson_num_equals(lhs, rhs); case YYJSON_TYPE_RAW: case YYJSON_TYPE_STR: return unsafe_yyjson_str_equals(lhs, rhs); case YYJSON_TYPE_NULL: case YYJSON_TYPE_BOOL: return lhs->tag == rhs->tag; default: return false; } } #if !YYJSON_DISABLE_UTILS /*============================================================================== * JSON Pointer API (RFC 6901) *============================================================================*/ /** Get a token from JSON pointer string. @param ptr [in,out] in: string that points to current token prefix `/` out: string that points to next token prefix `/`, or string end @param end [in] end of the entire JSON Pointer string @param len [out] unescaped token length @param esc [out] number of escaped characters in this token @return head of the token, or NULL if syntax error */ static_inline const char *ptr_next_token(const char **ptr, const char *end, usize *len, usize *esc) { const char *hdr = *ptr + 1; const char *cur = hdr; /* skip unescaped characters */ while (cur < end && *cur != '/' && *cur != '~') cur++; if (likely(cur == end || *cur != '~')) { /* no escaped characters, return */ *ptr = cur; *len = (usize)(cur - hdr); *esc = 0; return hdr; } else { /* handle escaped characters */ usize esc_num = 0; while (cur < end && *cur != '/') { if (*cur++ == '~') { if (cur == end || (*cur != '0' && *cur != '1')) { *ptr = cur - 1; return NULL; } esc_num++; } } *ptr = cur; *len = (usize)(cur - hdr) - esc_num; *esc = esc_num; return hdr; } } /** Convert token string to index. @param cur [in] token head @param len [in] token length @param idx [out] the index number, or USIZE_MAX if token is '-' @return true if token is a valid array index */ static_inline bool ptr_token_to_idx(const char *cur, usize len, usize *idx) { const char *end = cur + len; usize num = 0, add; if (unlikely(len == 0 || len > USIZE_SAFE_DIG)) return false; if (*cur == '0') { if (unlikely(len > 1)) return false; *idx = 0; return true; } if (*cur == '-') { if (unlikely(len > 1)) return false; *idx = USIZE_MAX; return true; } for (; cur < end && (add = (usize)((u8)*cur - (u8)'0')) <= 9; cur++) { num = num * 10 + add; } if (unlikely(num == 0 || cur < end)) return false; *idx = num; return true; } /** Compare JSON key with token. @param key a string key (yyjson_val or yyjson_mut_val) @param tag the expected string key tag @param token a JSON pointer token @param len unescaped token length @param esc number of escaped characters in this token @return true if `str` is equals to `token` */ static_inline bool ptr_token_eq(void *key, u64 tag, const char *token, usize len, usize esc) { yyjson_val *val = (yyjson_val *)key; if (val->tag != tag) return false; if (likely(!esc)) { return memcmp(val->uni.str, token, len) == 0; } else { const char *str = val->uni.str; for (; len-- > 0; token++, str++) { if (*token == '~') { if (*str != (*++token == '0' ? '~' : '/')) return false; } else { if (*str != *token) return false; } } return true; } } /** Get a value from array by token. @param arr an array, should not be NULL or non-array type @param token a JSON pointer token @param len unescaped token length @param esc number of escaped characters in this token @return value at index, or NULL if token is not index or index is out of range */ static_inline yyjson_val *ptr_arr_get(yyjson_val *arr, const char *token, usize len, usize esc) { yyjson_val *val = unsafe_yyjson_get_first(arr); usize num = unsafe_yyjson_get_len(arr), idx; if (unlikely(num == 0)) return NULL; if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL; if (unlikely(idx >= num)) return NULL; if (unsafe_yyjson_arr_is_flat(arr)) { return val + idx; } else { while (idx-- > 0) val = unsafe_yyjson_get_next(val); return val; } } /** Get a value from object by token. @param obj [in] an object, should not be NULL or non-object type @param token [in] a JSON pointer token @param len [in] unescaped token length @param esc [in] number of escaped characters in this token @return value associated with the token, or NULL if no value */ static_inline yyjson_val *ptr_obj_get(yyjson_val *obj, const char *token, usize len, usize esc) { u64 tag = (((u64)len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; yyjson_val *key = unsafe_yyjson_get_first(obj); usize num = unsafe_yyjson_get_len(obj); if (unlikely(num == 0)) return NULL; for (; num > 0; num--, key = unsafe_yyjson_get_next(key + 1)) { if (ptr_token_eq(key, tag, token, len, esc)) return key + 1; } return NULL; } /** Get a value from array by token. @param arr [in] an array, should not be NULL or non-array type @param token [in] a JSON pointer token @param len [in] unescaped token length @param esc [in] number of escaped characters in this token @param pre [out] previous (sibling) value of the returned value @param last [out] whether index is last @return value at index, or NULL if token is not index or index is out of range */ static_inline yyjson_mut_val *ptr_mut_arr_get(yyjson_mut_val *arr, const char *token, usize len, usize esc, yyjson_mut_val **pre, bool *last) { yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; /* last (tail) */ usize num = unsafe_yyjson_get_len(arr), idx; if (last) *last = false; if (pre) *pre = NULL; if (unlikely(num == 0)) { if (last && len == 1 && (*token == '0' || *token == '-')) *last = true; return NULL; } if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL; if (last) *last = (idx == num || idx == USIZE_MAX); if (unlikely(idx >= num)) return NULL; while (idx-- > 0) val = val->next; *pre = val; return val->next; } /** Get a value from object by token. @param obj [in] an object, should not be NULL or non-object type @param token [in] a JSON pointer token @param len [in] unescaped token length @param esc [in] number of escaped characters in this token @param pre [out] previous (sibling) key of the returned value's key @return value associated with the token, or NULL if no value */ static_inline yyjson_mut_val *ptr_mut_obj_get(yyjson_mut_val *obj, const char *token, usize len, usize esc, yyjson_mut_val **pre) { u64 tag = (((u64)len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr, *key; usize num = unsafe_yyjson_get_len(obj); if (pre) *pre = NULL; if (unlikely(num == 0)) return NULL; for (; num > 0; num--, pre_key = key) { key = pre_key->next->next; if (ptr_token_eq(key, tag, token, len, esc)) { *pre = pre_key; return key->next; } } return NULL; } /** Create a string value with JSON pointer token. @param token [in] a JSON pointer token @param len [in] unescaped token length @param esc [in] number of escaped characters in this token @param doc [in] used for memory allocation when creating value @return new string value, or NULL if memory allocation failed */ static_inline yyjson_mut_val *ptr_new_key(const char *token, usize len, usize esc, yyjson_mut_doc *doc) { const char *src = token; if (likely(!esc)) { return yyjson_mut_strncpy(doc, src, len); } else { const char *end = src + len + esc; char *dst = unsafe_yyjson_mut_str_alc(doc, len + esc); char *str = dst; if (unlikely(!dst)) return NULL; for (; src < end; src++, dst++) { if (*src != '~') *dst = *src; else *dst = (*++src == '0' ? '~' : '/'); } *dst = '\0'; return yyjson_mut_strn(doc, str, len); } } /* macros for yyjson_ptr */ #define return_err(_ret, _code, _pos, _msg) do { \ if (err) { \ err->code = YYJSON_PTR_ERR_##_code; \ err->msg = _msg; \ err->pos = (usize)(_pos); \ } \ return _ret; \ } while (false) #define return_err_resolve(_ret, _pos) \ return_err(_ret, RESOLVE, _pos, "JSON pointer cannot be resolved") #define return_err_syntax(_ret, _pos) \ return_err(_ret, SYNTAX, _pos, "invalid escaped character") #define return_err_alloc(_ret) \ return_err(_ret, MEMORY_ALLOCATION, 0, "failed to create value") yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val, const char *ptr, size_t ptr_len, yyjson_ptr_err *err) { const char *hdr = ptr, *end = ptr + ptr_len, *token; usize len, esc; yyjson_type type; while (true) { token = ptr_next_token(&ptr, end, &len, &esc); if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr); type = unsafe_yyjson_get_type(val); if (type == YYJSON_TYPE_OBJ) { val = ptr_obj_get(val, token, len, esc); } else if (type == YYJSON_TYPE_ARR) { val = ptr_arr_get(val, token, len, esc); } else { val = NULL; } if (!val) return_err_resolve(NULL, token - hdr); if (ptr == end) return val; } } yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val, const char *ptr, size_t ptr_len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { const char *hdr = ptr, *end = ptr + ptr_len, *token; usize len, esc; yyjson_mut_val *ctn, *pre = NULL; yyjson_type type; bool idx_is_last = false; while (true) { token = ptr_next_token(&ptr, end, &len, &esc); if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr); ctn = val; type = unsafe_yyjson_get_type(val); if (type == YYJSON_TYPE_OBJ) { val = ptr_mut_obj_get(val, token, len, esc, &pre); } else if (type == YYJSON_TYPE_ARR) { val = ptr_mut_arr_get(val, token, len, esc, &pre, &idx_is_last); } else { val = NULL; } if (ctx && (ptr == end)) { if (type == YYJSON_TYPE_OBJ || (type == YYJSON_TYPE_ARR && (val || idx_is_last))) { ctx->ctn = ctn; ctx->pre = pre; } } if (!val) return_err_resolve(NULL, token - hdr); if (ptr == end) return val; } } bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val, const char *ptr, size_t ptr_len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, bool insert_new, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { const char *hdr = ptr, *end = ptr + ptr_len, *token; usize token_len, esc, ctn_len; yyjson_mut_val *ctn, *key, *pre = NULL; yyjson_mut_val *sep_ctn = NULL, *sep_key = NULL, *sep_val = NULL; yyjson_type ctn_type; bool idx_is_last = false; /* skip exist parent nodes */ while (true) { token = ptr_next_token(&ptr, end, &token_len, &esc); if (unlikely(!token)) return_err_syntax(false, ptr - hdr); ctn = val; ctn_type = unsafe_yyjson_get_type(ctn); if (ctn_type == YYJSON_TYPE_OBJ) { val = ptr_mut_obj_get(ctn, token, token_len, esc, &pre); } else if (ctn_type == YYJSON_TYPE_ARR) { val = ptr_mut_arr_get(ctn, token, token_len, esc, &pre, &idx_is_last); } else return_err_resolve(false, token - hdr); if (!val) break; if (ptr == end) break; /* is last token */ } /* create parent nodes if not exist */ if (unlikely(ptr != end)) { /* not last token */ if (!create_parent) return_err_resolve(false, token - hdr); /* add value at last index if container is array */ if (ctn_type == YYJSON_TYPE_ARR) { if (!idx_is_last || !insert_new) { return_err_resolve(false, token - hdr); } val = yyjson_mut_obj(doc); if (!val) return_err_alloc(false); /* delay attaching until all operations are completed */ sep_ctn = ctn; sep_key = NULL; sep_val = val; /* move to next token */ ctn = val; val = NULL; ctn_type = YYJSON_TYPE_OBJ; token = ptr_next_token(&ptr, end, &token_len, &esc); if (unlikely(!token)) return_err_resolve(false, token - hdr); } /* container is object, create parent nodes */ while (ptr != end) { /* not last token */ key = ptr_new_key(token, token_len, esc, doc); if (!key) return_err_alloc(false); val = yyjson_mut_obj(doc); if (!val) return_err_alloc(false); /* delay attaching until all operations are completed */ if (!sep_ctn) { sep_ctn = ctn; sep_key = key; sep_val = val; } else { yyjson_mut_obj_add(ctn, key, val); } /* move to next token */ ctn = val; val = NULL; token = ptr_next_token(&ptr, end, &token_len, &esc); if (unlikely(!token)) return_err_syntax(false, ptr - hdr); } } /* JSON pointer is resolved, insert or replace target value */ ctn_len = unsafe_yyjson_get_len(ctn); if (ctn_type == YYJSON_TYPE_OBJ) { if (ctx) ctx->ctn = ctn; if (!val || insert_new) { /* insert new key-value pair */ key = ptr_new_key(token, token_len, esc, doc); if (unlikely(!key)) return_err_alloc(false); if (ctx) ctx->pre = ctn_len ? (yyjson_mut_val *)ctn->uni.ptr : key; unsafe_yyjson_mut_obj_add(ctn, key, new_val, ctn_len); } else { /* replace exist value */ key = pre->next->next; if (ctx) ctx->pre = pre; if (ctx) ctx->old = val; yyjson_mut_obj_put(ctn, key, new_val); } } else { /* array */ if (ctx && (val || idx_is_last)) ctx->ctn = ctn; if (insert_new) { /* append new value */ if (val) { pre->next = new_val; new_val->next = val; if (ctx) ctx->pre = pre; unsafe_yyjson_set_len(ctn, ctn_len + 1); } else if (idx_is_last) { if (ctx) ctx->pre = ctn_len ? (yyjson_mut_val *)ctn->uni.ptr : new_val; yyjson_mut_arr_append(ctn, new_val); } else { return_err_resolve(false, token - hdr); } } else { /* replace exist value */ if (!val) return_err_resolve(false, token - hdr); if (ctn_len > 1) { new_val->next = val->next; pre->next = new_val; if (ctn->uni.ptr == val) ctn->uni.ptr = new_val; } else { new_val->next = new_val; ctn->uni.ptr = new_val; pre = new_val; } if (ctx) ctx->pre = pre; if (ctx) ctx->old = val; } } /* all operations are completed, attach the new components to the target */ if (unlikely(sep_ctn)) { if (sep_key) yyjson_mut_obj_add(sep_ctn, sep_key, sep_val); else yyjson_mut_arr_append(sep_ctn, sep_val); } return true; } yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_mut_val *cur_val; yyjson_ptr_ctx cur_ctx; memset(&cur_ctx, 0, sizeof(cur_ctx)); if (!ctx) ctx = &cur_ctx; cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); if (!cur_val) return NULL; if (yyjson_mut_is_obj(ctx->ctn)) { yyjson_mut_val *key = ctx->pre->next->next; yyjson_mut_obj_put(ctx->ctn, key, new_val); } else { yyjson_ptr_ctx_replace(ctx, new_val); } ctx->old = cur_val; return cur_val; } yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_mut_val *cur_val; yyjson_ptr_ctx cur_ctx; memset(&cur_ctx, 0, sizeof(cur_ctx)); if (!ctx) ctx = &cur_ctx; cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); if (cur_val) { if (yyjson_mut_is_obj(ctx->ctn)) { yyjson_mut_val *key = ctx->pre->next->next; yyjson_mut_obj_put(ctx->ctn, key, NULL); } else { yyjson_ptr_ctx_remove(ctx); } ctx->pre = NULL; ctx->old = cur_val; } return cur_val; } /* macros for yyjson_ptr */ #undef return_err #undef return_err_resolve #undef return_err_syntax #undef return_err_alloc /*============================================================================== * JSON Patch API (RFC 6902) *============================================================================*/ /* JSON Patch operation */ typedef enum patch_op { PATCH_OP_ADD, /* path, value */ PATCH_OP_REMOVE, /* path */ PATCH_OP_REPLACE, /* path, value */ PATCH_OP_MOVE, /* from, path */ PATCH_OP_COPY, /* from, path */ PATCH_OP_TEST, /* path, value */ PATCH_OP_NONE /* invalid */ } patch_op; static patch_op patch_op_get(yyjson_val *op) { const char *str = op->uni.str; switch (unsafe_yyjson_get_len(op)) { case 3: if (!memcmp(str, "add", 3)) return PATCH_OP_ADD; return PATCH_OP_NONE; case 4: if (!memcmp(str, "move", 4)) return PATCH_OP_MOVE; if (!memcmp(str, "copy", 4)) return PATCH_OP_COPY; if (!memcmp(str, "test", 4)) return PATCH_OP_TEST; return PATCH_OP_NONE; case 6: if (!memcmp(str, "remove", 6)) return PATCH_OP_REMOVE; return PATCH_OP_NONE; case 7: if (!memcmp(str, "replace", 7)) return PATCH_OP_REPLACE; return PATCH_OP_NONE; default: return PATCH_OP_NONE; } } /* macros for yyjson_patch */ #define return_err(_code, _msg) do { \ if (err->ptr.code == YYJSON_PTR_ERR_MEMORY_ALLOCATION) { \ err->code = YYJSON_PATCH_ERROR_MEMORY_ALLOCATION; \ err->msg = _msg; \ memset(&err->ptr, 0, sizeof(yyjson_ptr_err)); \ } else { \ err->code = YYJSON_PATCH_ERROR_##_code; \ err->msg = _msg; \ err->idx = iter.idx ? iter.idx - 1 : 0; \ } \ return NULL; \ } while (false) #define return_err_copy() \ return_err(MEMORY_ALLOCATION, "failed to copy value") #define return_err_key(_key) \ return_err(MISSING_KEY, "missing key " _key) #define return_err_val(_key) \ return_err(INVALID_MEMBER, "invalid member " _key) #define ptr_get(_ptr) yyjson_mut_ptr_getx( \ root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr) #define ptr_add(_ptr, _val) yyjson_mut_ptr_addx( \ root, _ptr->uni.str, _ptr##_len, _val, doc, false, NULL, &err->ptr) #define ptr_remove(_ptr) yyjson_mut_ptr_removex( \ root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr) #define ptr_replace(_ptr, _val)yyjson_mut_ptr_replacex( \ root, _ptr->uni.str, _ptr##_len, _val, NULL, &err->ptr) yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch, yyjson_patch_err *err) { yyjson_mut_val *root; yyjson_val *obj; yyjson_arr_iter iter; yyjson_patch_err err_tmp; if (!err) err = &err_tmp; memset(err, 0, sizeof(*err)); memset(&iter, 0, sizeof(iter)); if (unlikely(!doc || !orig || !patch)) { return_err(INVALID_PARAMETER, "input parameter is NULL"); } if (unlikely(!yyjson_is_arr(patch))) { return_err(INVALID_PARAMETER, "input patch is not array"); } root = yyjson_val_mut_copy(doc, orig); if (unlikely(!root)) return_err_copy(); /* iterate through the patch array */ yyjson_arr_iter_init(patch, &iter); while ((obj = yyjson_arr_iter_next(&iter))) { patch_op op_enum; yyjson_val *op, *path, *from = NULL, *value; yyjson_mut_val *val = NULL, *test; usize path_len, from_len = 0; if (unlikely(!unsafe_yyjson_is_obj(obj))) { return_err(INVALID_OPERATION, "JSON patch operation is not object"); } /* get required member: op */ op = yyjson_obj_get(obj, "op"); if (unlikely(!op)) return_err_key("`op`"); if (unlikely(!yyjson_is_str(op))) return_err_val("`op`"); op_enum = patch_op_get(op); /* get required member: path */ path = yyjson_obj_get(obj, "path"); if (unlikely(!path)) return_err_key("`path`"); if (unlikely(!yyjson_is_str(path))) return_err_val("`path`"); path_len = unsafe_yyjson_get_len(path); /* get required member: value, from */ switch (op_enum) { case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST: value = yyjson_obj_get(obj, "value"); if (unlikely(!value)) return_err_key("`value`"); val = yyjson_val_mut_copy(doc, value); if (unlikely(!val)) return_err_copy(); break; case PATCH_OP_MOVE: case PATCH_OP_COPY: from = yyjson_obj_get(obj, "from"); if (unlikely(!from)) return_err_key("`from`"); if (unlikely(!yyjson_is_str(from))) return_err_val("`from`"); from_len = unsafe_yyjson_get_len(from); break; default: break; } /* perform an operation */ switch (op_enum) { case PATCH_OP_ADD: /* add(path, val) */ if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_REMOVE: /* remove(path) */ if (unlikely(!ptr_remove(path))) { return_err(POINTER, "failed to remove `path`"); } break; case PATCH_OP_REPLACE: /* replace(path, val) */ if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_replace(path, val))) { return_err(POINTER, "failed to replace `path`"); } break; case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */ if (unlikely(from_len == 0 && path_len == 0)) break; val = ptr_remove(from); if (unlikely(!val)) { return_err(POINTER, "failed to remove `from`"); } if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */ val = ptr_get(from); if (unlikely(!val)) { return_err(POINTER, "failed to get `from`"); } if (unlikely(path_len == 0)) { root = val; break; } val = yyjson_mut_val_mut_copy(doc, val); if (unlikely(!val)) return_err_copy(); if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_TEST: /* test = get(path), test.eq(val) */ test = ptr_get(path); if (unlikely(!test)) { return_err(POINTER, "failed to get `path`"); } if (unlikely(!yyjson_mut_equals(val, test))) { return_err(EQUAL, "failed to test equal"); } break; default: return_err(INVALID_MEMBER, "unsupported `op`"); } } return root; } yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch, yyjson_patch_err *err) { yyjson_mut_val *root, *obj; yyjson_mut_arr_iter iter; yyjson_patch_err err_tmp; if (!err) err = &err_tmp; memset(err, 0, sizeof(*err)); memset(&iter, 0, sizeof(iter)); if (unlikely(!doc || !orig || !patch)) { return_err(INVALID_PARAMETER, "input parameter is NULL"); } if (unlikely(!yyjson_mut_is_arr(patch))) { return_err(INVALID_PARAMETER, "input patch is not array"); } root = yyjson_mut_val_mut_copy(doc, orig); if (unlikely(!root)) return_err_copy(); /* iterate through the patch array */ yyjson_mut_arr_iter_init(patch, &iter); while ((obj = yyjson_mut_arr_iter_next(&iter))) { patch_op op_enum; yyjson_mut_val *op, *path, *from = NULL, *value; yyjson_mut_val *val = NULL, *test; usize path_len, from_len = 0; if (!unsafe_yyjson_is_obj(obj)) { return_err(INVALID_OPERATION, "JSON patch operation is not object"); } /* get required member: op */ op = yyjson_mut_obj_get(obj, "op"); if (unlikely(!op)) return_err_key("`op`"); if (unlikely(!yyjson_mut_is_str(op))) return_err_val("`op`"); op_enum = patch_op_get((yyjson_val *)(void *)op); /* get required member: path */ path = yyjson_mut_obj_get(obj, "path"); if (unlikely(!path)) return_err_key("`path`"); if (unlikely(!yyjson_mut_is_str(path))) return_err_val("`path`"); path_len = unsafe_yyjson_get_len(path); /* get required member: value, from */ switch (op_enum) { case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST: value = yyjson_mut_obj_get(obj, "value"); if (unlikely(!value)) return_err_key("`value`"); val = yyjson_mut_val_mut_copy(doc, value); if (unlikely(!val)) return_err_copy(); break; case PATCH_OP_MOVE: case PATCH_OP_COPY: from = yyjson_mut_obj_get(obj, "from"); if (unlikely(!from)) return_err_key("`from`"); if (unlikely(!yyjson_mut_is_str(from))) { return_err_val("`from`"); } from_len = unsafe_yyjson_get_len(from); break; default: break; } /* perform an operation */ switch (op_enum) { case PATCH_OP_ADD: /* add(path, val) */ if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_REMOVE: /* remove(path) */ if (unlikely(!ptr_remove(path))) { return_err(POINTER, "failed to remove `path`"); } break; case PATCH_OP_REPLACE: /* replace(path, val) */ if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_replace(path, val))) { return_err(POINTER, "failed to replace `path`"); } break; case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */ if (unlikely(from_len == 0 && path_len == 0)) break; val = ptr_remove(from); if (unlikely(!val)) { return_err(POINTER, "failed to remove `from`"); } if (unlikely(path_len == 0)) { root = val; break; } if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */ val = ptr_get(from); if (unlikely(!val)) { return_err(POINTER, "failed to get `from`"); } if (unlikely(path_len == 0)) { root = val; break; } val = yyjson_mut_val_mut_copy(doc, val); if (unlikely(!val)) return_err_copy(); if (unlikely(!ptr_add(path, val))) { return_err(POINTER, "failed to add `path`"); } break; case PATCH_OP_TEST: /* test = get(path), test.eq(val) */ test = ptr_get(path); if (unlikely(!test)) { return_err(POINTER, "failed to get `path`"); } if (unlikely(!yyjson_mut_equals(val, test))) { return_err(EQUAL, "failed to test equal"); } break; default: return_err(INVALID_MEMBER, "unsupported `op`"); } } return root; } /* macros for yyjson_patch */ #undef return_err #undef return_err_copy #undef return_err_key #undef return_err_val #undef ptr_get #undef ptr_add #undef ptr_remove #undef ptr_replace /*============================================================================== * JSON Merge-Patch API (RFC 7386) *============================================================================*/ yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch) { usize idx, max; yyjson_val *key, *orig_val, *patch_val, local_orig; yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val; if (unlikely(!yyjson_is_obj(patch))) { return yyjson_val_mut_copy(doc, patch); } builder = yyjson_mut_obj(doc); if (unlikely(!builder)) return NULL; if (!yyjson_is_obj(orig)) { orig = &local_orig; orig->tag = builder->tag; orig->uni = builder->uni; } /* If orig is contributing, copy any items not modified by the patch */ if (orig != &local_orig) { yyjson_obj_foreach(orig, idx, max, key, orig_val) { patch_val = yyjson_obj_getn(patch, unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); if (!patch_val) { mut_key = yyjson_val_mut_copy(doc, key); mut_val = yyjson_val_mut_copy(doc, orig_val); if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; } } } /* Merge items modified by the patch. */ yyjson_obj_foreach(patch, idx, max, key, patch_val) { /* null indicates the field is removed. */ if (unsafe_yyjson_is_null(patch_val)) { continue; } mut_key = yyjson_val_mut_copy(doc, key); orig_val = yyjson_obj_getn(orig, unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); merged_val = yyjson_merge_patch(doc, orig_val, patch_val); if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL; } return builder; } yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch) { usize idx, max; yyjson_mut_val *key, *orig_val, *patch_val, local_orig; yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val; if (unlikely(!yyjson_mut_is_obj(patch))) { return yyjson_mut_val_mut_copy(doc, patch); } builder = yyjson_mut_obj(doc); if (unlikely(!builder)) return NULL; if (!yyjson_mut_is_obj(orig)) { orig = &local_orig; orig->tag = builder->tag; orig->uni = builder->uni; } /* If orig is contributing, copy any items not modified by the patch */ if (orig != &local_orig) { yyjson_mut_obj_foreach(orig, idx, max, key, orig_val) { patch_val = yyjson_mut_obj_getn(patch, unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); if (!patch_val) { mut_key = yyjson_mut_val_mut_copy(doc, key); mut_val = yyjson_mut_val_mut_copy(doc, orig_val); if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL; } } } /* Merge items modified by the patch. */ yyjson_mut_obj_foreach(patch, idx, max, key, patch_val) { /* null indicates the field is removed. */ if (unsafe_yyjson_is_null(patch_val)) { continue; } mut_key = yyjson_mut_val_mut_copy(doc, key); orig_val = yyjson_mut_obj_getn(orig, unsafe_yyjson_get_str(key), unsafe_yyjson_get_len(key)); merged_val = yyjson_mut_merge_patch(doc, orig_val, patch_val); if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL; } return builder; } #endif /* YYJSON_DISABLE_UTILS */ /*============================================================================== * Power10 Lookup Table * These data are used by the floating-point number reader and writer. *============================================================================*/ #if (!YYJSON_DISABLE_READER || !YYJSON_DISABLE_WRITER) && \ (!YYJSON_DISABLE_FAST_FP_CONV) /** Minimum decimal exponent in pow10_sig_table. */ #define POW10_SIG_TABLE_MIN_EXP -343 /** Maximum decimal exponent in pow10_sig_table. */ #define POW10_SIG_TABLE_MAX_EXP 324 /** Minimum exact decimal exponent in pow10_sig_table */ #define POW10_SIG_TABLE_MIN_EXACT_EXP 0 /** Maximum exact decimal exponent in pow10_sig_table */ #define POW10_SIG_TABLE_MAX_EXACT_EXP 55 /** Normalized significant 128 bits of pow10, no rounded up (size: 10.4KB). This lookup table is used by both the double number reader and writer. (generate with misc/make_tables.c) */ static const u64 pow10_sig_table[] = { U64(0xBF29DCAB, 0xA82FDEAE), U64(0x7432EE87, 0x3880FC33), /* ~= 10^-343 */ U64(0xEEF453D6, 0x923BD65A), U64(0x113FAA29, 0x06A13B3F), /* ~= 10^-342 */ U64(0x9558B466, 0x1B6565F8), U64(0x4AC7CA59, 0xA424C507), /* ~= 10^-341 */ U64(0xBAAEE17F, 0xA23EBF76), U64(0x5D79BCF0, 0x0D2DF649), /* ~= 10^-340 */ U64(0xE95A99DF, 0x8ACE6F53), U64(0xF4D82C2C, 0x107973DC), /* ~= 10^-339 */ U64(0x91D8A02B, 0xB6C10594), U64(0x79071B9B, 0x8A4BE869), /* ~= 10^-338 */ U64(0xB64EC836, 0xA47146F9), U64(0x9748E282, 0x6CDEE284), /* ~= 10^-337 */ U64(0xE3E27A44, 0x4D8D98B7), U64(0xFD1B1B23, 0x08169B25), /* ~= 10^-336 */ U64(0x8E6D8C6A, 0xB0787F72), U64(0xFE30F0F5, 0xE50E20F7), /* ~= 10^-335 */ U64(0xB208EF85, 0x5C969F4F), U64(0xBDBD2D33, 0x5E51A935), /* ~= 10^-334 */ U64(0xDE8B2B66, 0xB3BC4723), U64(0xAD2C7880, 0x35E61382), /* ~= 10^-333 */ U64(0x8B16FB20, 0x3055AC76), U64(0x4C3BCB50, 0x21AFCC31), /* ~= 10^-332 */ U64(0xADDCB9E8, 0x3C6B1793), U64(0xDF4ABE24, 0x2A1BBF3D), /* ~= 10^-331 */ U64(0xD953E862, 0x4B85DD78), U64(0xD71D6DAD, 0x34A2AF0D), /* ~= 10^-330 */ U64(0x87D4713D, 0x6F33AA6B), U64(0x8672648C, 0x40E5AD68), /* ~= 10^-329 */ U64(0xA9C98D8C, 0xCB009506), U64(0x680EFDAF, 0x511F18C2), /* ~= 10^-328 */ U64(0xD43BF0EF, 0xFDC0BA48), U64(0x0212BD1B, 0x2566DEF2), /* ~= 10^-327 */ U64(0x84A57695, 0xFE98746D), U64(0x014BB630, 0xF7604B57), /* ~= 10^-326 */ U64(0xA5CED43B, 0x7E3E9188), U64(0x419EA3BD, 0x35385E2D), /* ~= 10^-325 */ U64(0xCF42894A, 0x5DCE35EA), U64(0x52064CAC, 0x828675B9), /* ~= 10^-324 */ U64(0x818995CE, 0x7AA0E1B2), U64(0x7343EFEB, 0xD1940993), /* ~= 10^-323 */ U64(0xA1EBFB42, 0x19491A1F), U64(0x1014EBE6, 0xC5F90BF8), /* ~= 10^-322 */ U64(0xCA66FA12, 0x9F9B60A6), U64(0xD41A26E0, 0x77774EF6), /* ~= 10^-321 */ U64(0xFD00B897, 0x478238D0), U64(0x8920B098, 0x955522B4), /* ~= 10^-320 */ U64(0x9E20735E, 0x8CB16382), U64(0x55B46E5F, 0x5D5535B0), /* ~= 10^-319 */ U64(0xC5A89036, 0x2FDDBC62), U64(0xEB2189F7, 0x34AA831D), /* ~= 10^-318 */ U64(0xF712B443, 0xBBD52B7B), U64(0xA5E9EC75, 0x01D523E4), /* ~= 10^-317 */ U64(0x9A6BB0AA, 0x55653B2D), U64(0x47B233C9, 0x2125366E), /* ~= 10^-316 */ U64(0xC1069CD4, 0xEABE89F8), U64(0x999EC0BB, 0x696E840A), /* ~= 10^-315 */ U64(0xF148440A, 0x256E2C76), U64(0xC00670EA, 0x43CA250D), /* ~= 10^-314 */ U64(0x96CD2A86, 0x5764DBCA), U64(0x38040692, 0x6A5E5728), /* ~= 10^-313 */ U64(0xBC807527, 0xED3E12BC), U64(0xC6050837, 0x04F5ECF2), /* ~= 10^-312 */ U64(0xEBA09271, 0xE88D976B), U64(0xF7864A44, 0xC633682E), /* ~= 10^-311 */ U64(0x93445B87, 0x31587EA3), U64(0x7AB3EE6A, 0xFBE0211D), /* ~= 10^-310 */ U64(0xB8157268, 0xFDAE9E4C), U64(0x5960EA05, 0xBAD82964), /* ~= 10^-309 */ U64(0xE61ACF03, 0x3D1A45DF), U64(0x6FB92487, 0x298E33BD), /* ~= 10^-308 */ U64(0x8FD0C162, 0x06306BAB), U64(0xA5D3B6D4, 0x79F8E056), /* ~= 10^-307 */ U64(0xB3C4F1BA, 0x87BC8696), U64(0x8F48A489, 0x9877186C), /* ~= 10^-306 */ U64(0xE0B62E29, 0x29ABA83C), U64(0x331ACDAB, 0xFE94DE87), /* ~= 10^-305 */ U64(0x8C71DCD9, 0xBA0B4925), U64(0x9FF0C08B, 0x7F1D0B14), /* ~= 10^-304 */ U64(0xAF8E5410, 0x288E1B6F), U64(0x07ECF0AE, 0x5EE44DD9), /* ~= 10^-303 */ U64(0xDB71E914, 0x32B1A24A), U64(0xC9E82CD9, 0xF69D6150), /* ~= 10^-302 */ U64(0x892731AC, 0x9FAF056E), U64(0xBE311C08, 0x3A225CD2), /* ~= 10^-301 */ U64(0xAB70FE17, 0xC79AC6CA), U64(0x6DBD630A, 0x48AAF406), /* ~= 10^-300 */ U64(0xD64D3D9D, 0xB981787D), U64(0x092CBBCC, 0xDAD5B108), /* ~= 10^-299 */ U64(0x85F04682, 0x93F0EB4E), U64(0x25BBF560, 0x08C58EA5), /* ~= 10^-298 */ U64(0xA76C5823, 0x38ED2621), U64(0xAF2AF2B8, 0x0AF6F24E), /* ~= 10^-297 */ U64(0xD1476E2C, 0x07286FAA), U64(0x1AF5AF66, 0x0DB4AEE1), /* ~= 10^-296 */ U64(0x82CCA4DB, 0x847945CA), U64(0x50D98D9F, 0xC890ED4D), /* ~= 10^-295 */ U64(0xA37FCE12, 0x6597973C), U64(0xE50FF107, 0xBAB528A0), /* ~= 10^-294 */ U64(0xCC5FC196, 0xFEFD7D0C), U64(0x1E53ED49, 0xA96272C8), /* ~= 10^-293 */ U64(0xFF77B1FC, 0xBEBCDC4F), U64(0x25E8E89C, 0x13BB0F7A), /* ~= 10^-292 */ U64(0x9FAACF3D, 0xF73609B1), U64(0x77B19161, 0x8C54E9AC), /* ~= 10^-291 */ U64(0xC795830D, 0x75038C1D), U64(0xD59DF5B9, 0xEF6A2417), /* ~= 10^-290 */ U64(0xF97AE3D0, 0xD2446F25), U64(0x4B057328, 0x6B44AD1D), /* ~= 10^-289 */ U64(0x9BECCE62, 0x836AC577), U64(0x4EE367F9, 0x430AEC32), /* ~= 10^-288 */ U64(0xC2E801FB, 0x244576D5), U64(0x229C41F7, 0x93CDA73F), /* ~= 10^-287 */ U64(0xF3A20279, 0xED56D48A), U64(0x6B435275, 0x78C1110F), /* ~= 10^-286 */ U64(0x9845418C, 0x345644D6), U64(0x830A1389, 0x6B78AAA9), /* ~= 10^-285 */ U64(0xBE5691EF, 0x416BD60C), U64(0x23CC986B, 0xC656D553), /* ~= 10^-284 */ U64(0xEDEC366B, 0x11C6CB8F), U64(0x2CBFBE86, 0xB7EC8AA8), /* ~= 10^-283 */ U64(0x94B3A202, 0xEB1C3F39), U64(0x7BF7D714, 0x32F3D6A9), /* ~= 10^-282 */ U64(0xB9E08A83, 0xA5E34F07), U64(0xDAF5CCD9, 0x3FB0CC53), /* ~= 10^-281 */ U64(0xE858AD24, 0x8F5C22C9), U64(0xD1B3400F, 0x8F9CFF68), /* ~= 10^-280 */ U64(0x91376C36, 0xD99995BE), U64(0x23100809, 0xB9C21FA1), /* ~= 10^-279 */ U64(0xB5854744, 0x8FFFFB2D), U64(0xABD40A0C, 0x2832A78A), /* ~= 10^-278 */ U64(0xE2E69915, 0xB3FFF9F9), U64(0x16C90C8F, 0x323F516C), /* ~= 10^-277 */ U64(0x8DD01FAD, 0x907FFC3B), U64(0xAE3DA7D9, 0x7F6792E3), /* ~= 10^-276 */ U64(0xB1442798, 0xF49FFB4A), U64(0x99CD11CF, 0xDF41779C), /* ~= 10^-275 */ U64(0xDD95317F, 0x31C7FA1D), U64(0x40405643, 0xD711D583), /* ~= 10^-274 */ U64(0x8A7D3EEF, 0x7F1CFC52), U64(0x482835EA, 0x666B2572), /* ~= 10^-273 */ U64(0xAD1C8EAB, 0x5EE43B66), U64(0xDA324365, 0x0005EECF), /* ~= 10^-272 */ U64(0xD863B256, 0x369D4A40), U64(0x90BED43E, 0x40076A82), /* ~= 10^-271 */ U64(0x873E4F75, 0xE2224E68), U64(0x5A7744A6, 0xE804A291), /* ~= 10^-270 */ U64(0xA90DE353, 0x5AAAE202), U64(0x711515D0, 0xA205CB36), /* ~= 10^-269 */ U64(0xD3515C28, 0x31559A83), U64(0x0D5A5B44, 0xCA873E03), /* ~= 10^-268 */ U64(0x8412D999, 0x1ED58091), U64(0xE858790A, 0xFE9486C2), /* ~= 10^-267 */ U64(0xA5178FFF, 0x668AE0B6), U64(0x626E974D, 0xBE39A872), /* ~= 10^-266 */ U64(0xCE5D73FF, 0x402D98E3), U64(0xFB0A3D21, 0x2DC8128F), /* ~= 10^-265 */ U64(0x80FA687F, 0x881C7F8E), U64(0x7CE66634, 0xBC9D0B99), /* ~= 10^-264 */ U64(0xA139029F, 0x6A239F72), U64(0x1C1FFFC1, 0xEBC44E80), /* ~= 10^-263 */ U64(0xC9874347, 0x44AC874E), U64(0xA327FFB2, 0x66B56220), /* ~= 10^-262 */ U64(0xFBE91419, 0x15D7A922), U64(0x4BF1FF9F, 0x0062BAA8), /* ~= 10^-261 */ U64(0x9D71AC8F, 0xADA6C9B5), U64(0x6F773FC3, 0x603DB4A9), /* ~= 10^-260 */ U64(0xC4CE17B3, 0x99107C22), U64(0xCB550FB4, 0x384D21D3), /* ~= 10^-259 */ U64(0xF6019DA0, 0x7F549B2B), U64(0x7E2A53A1, 0x46606A48), /* ~= 10^-258 */ U64(0x99C10284, 0x4F94E0FB), U64(0x2EDA7444, 0xCBFC426D), /* ~= 10^-257 */ U64(0xC0314325, 0x637A1939), U64(0xFA911155, 0xFEFB5308), /* ~= 10^-256 */ U64(0xF03D93EE, 0xBC589F88), U64(0x793555AB, 0x7EBA27CA), /* ~= 10^-255 */ U64(0x96267C75, 0x35B763B5), U64(0x4BC1558B, 0x2F3458DE), /* ~= 10^-254 */ U64(0xBBB01B92, 0x83253CA2), U64(0x9EB1AAED, 0xFB016F16), /* ~= 10^-253 */ U64(0xEA9C2277, 0x23EE8BCB), U64(0x465E15A9, 0x79C1CADC), /* ~= 10^-252 */ U64(0x92A1958A, 0x7675175F), U64(0x0BFACD89, 0xEC191EC9), /* ~= 10^-251 */ U64(0xB749FAED, 0x14125D36), U64(0xCEF980EC, 0x671F667B), /* ~= 10^-250 */ U64(0xE51C79A8, 0x5916F484), U64(0x82B7E127, 0x80E7401A), /* ~= 10^-249 */ U64(0x8F31CC09, 0x37AE58D2), U64(0xD1B2ECB8, 0xB0908810), /* ~= 10^-248 */ U64(0xB2FE3F0B, 0x8599EF07), U64(0x861FA7E6, 0xDCB4AA15), /* ~= 10^-247 */ U64(0xDFBDCECE, 0x67006AC9), U64(0x67A791E0, 0x93E1D49A), /* ~= 10^-246 */ U64(0x8BD6A141, 0x006042BD), U64(0xE0C8BB2C, 0x5C6D24E0), /* ~= 10^-245 */ U64(0xAECC4991, 0x4078536D), U64(0x58FAE9F7, 0x73886E18), /* ~= 10^-244 */ U64(0xDA7F5BF5, 0x90966848), U64(0xAF39A475, 0x506A899E), /* ~= 10^-243 */ U64(0x888F9979, 0x7A5E012D), U64(0x6D8406C9, 0x52429603), /* ~= 10^-242 */ U64(0xAAB37FD7, 0xD8F58178), U64(0xC8E5087B, 0xA6D33B83), /* ~= 10^-241 */ U64(0xD5605FCD, 0xCF32E1D6), U64(0xFB1E4A9A, 0x90880A64), /* ~= 10^-240 */ U64(0x855C3BE0, 0xA17FCD26), U64(0x5CF2EEA0, 0x9A55067F), /* ~= 10^-239 */ U64(0xA6B34AD8, 0xC9DFC06F), U64(0xF42FAA48, 0xC0EA481E), /* ~= 10^-238 */ U64(0xD0601D8E, 0xFC57B08B), U64(0xF13B94DA, 0xF124DA26), /* ~= 10^-237 */ U64(0x823C1279, 0x5DB6CE57), U64(0x76C53D08, 0xD6B70858), /* ~= 10^-236 */ U64(0xA2CB1717, 0xB52481ED), U64(0x54768C4B, 0x0C64CA6E), /* ~= 10^-235 */ U64(0xCB7DDCDD, 0xA26DA268), U64(0xA9942F5D, 0xCF7DFD09), /* ~= 10^-234 */ U64(0xFE5D5415, 0x0B090B02), U64(0xD3F93B35, 0x435D7C4C), /* ~= 10^-233 */ U64(0x9EFA548D, 0x26E5A6E1), U64(0xC47BC501, 0x4A1A6DAF), /* ~= 10^-232 */ U64(0xC6B8E9B0, 0x709F109A), U64(0x359AB641, 0x9CA1091B), /* ~= 10^-231 */ U64(0xF867241C, 0x8CC6D4C0), U64(0xC30163D2, 0x03C94B62), /* ~= 10^-230 */ U64(0x9B407691, 0xD7FC44F8), U64(0x79E0DE63, 0x425DCF1D), /* ~= 10^-229 */ U64(0xC2109436, 0x4DFB5636), U64(0x985915FC, 0x12F542E4), /* ~= 10^-228 */ U64(0xF294B943, 0xE17A2BC4), U64(0x3E6F5B7B, 0x17B2939D), /* ~= 10^-227 */ U64(0x979CF3CA, 0x6CEC5B5A), U64(0xA705992C, 0xEECF9C42), /* ~= 10^-226 */ U64(0xBD8430BD, 0x08277231), U64(0x50C6FF78, 0x2A838353), /* ~= 10^-225 */ U64(0xECE53CEC, 0x4A314EBD), U64(0xA4F8BF56, 0x35246428), /* ~= 10^-224 */ U64(0x940F4613, 0xAE5ED136), U64(0x871B7795, 0xE136BE99), /* ~= 10^-223 */ U64(0xB9131798, 0x99F68584), U64(0x28E2557B, 0x59846E3F), /* ~= 10^-222 */ U64(0xE757DD7E, 0xC07426E5), U64(0x331AEADA, 0x2FE589CF), /* ~= 10^-221 */ U64(0x9096EA6F, 0x3848984F), U64(0x3FF0D2C8, 0x5DEF7621), /* ~= 10^-220 */ U64(0xB4BCA50B, 0x065ABE63), U64(0x0FED077A, 0x756B53A9), /* ~= 10^-219 */ U64(0xE1EBCE4D, 0xC7F16DFB), U64(0xD3E84959, 0x12C62894), /* ~= 10^-218 */ U64(0x8D3360F0, 0x9CF6E4BD), U64(0x64712DD7, 0xABBBD95C), /* ~= 10^-217 */ U64(0xB080392C, 0xC4349DEC), U64(0xBD8D794D, 0x96AACFB3), /* ~= 10^-216 */ U64(0xDCA04777, 0xF541C567), U64(0xECF0D7A0, 0xFC5583A0), /* ~= 10^-215 */ U64(0x89E42CAA, 0xF9491B60), U64(0xF41686C4, 0x9DB57244), /* ~= 10^-214 */ U64(0xAC5D37D5, 0xB79B6239), U64(0x311C2875, 0xC522CED5), /* ~= 10^-213 */ U64(0xD77485CB, 0x25823AC7), U64(0x7D633293, 0x366B828B), /* ~= 10^-212 */ U64(0x86A8D39E, 0xF77164BC), U64(0xAE5DFF9C, 0x02033197), /* ~= 10^-211 */ U64(0xA8530886, 0xB54DBDEB), U64(0xD9F57F83, 0x0283FDFC), /* ~= 10^-210 */ U64(0xD267CAA8, 0x62A12D66), U64(0xD072DF63, 0xC324FD7B), /* ~= 10^-209 */ U64(0x8380DEA9, 0x3DA4BC60), U64(0x4247CB9E, 0x59F71E6D), /* ~= 10^-208 */ U64(0xA4611653, 0x8D0DEB78), U64(0x52D9BE85, 0xF074E608), /* ~= 10^-207 */ U64(0xCD795BE8, 0x70516656), U64(0x67902E27, 0x6C921F8B), /* ~= 10^-206 */ U64(0x806BD971, 0x4632DFF6), U64(0x00BA1CD8, 0xA3DB53B6), /* ~= 10^-205 */ U64(0xA086CFCD, 0x97BF97F3), U64(0x80E8A40E, 0xCCD228A4), /* ~= 10^-204 */ U64(0xC8A883C0, 0xFDAF7DF0), U64(0x6122CD12, 0x8006B2CD), /* ~= 10^-203 */ U64(0xFAD2A4B1, 0x3D1B5D6C), U64(0x796B8057, 0x20085F81), /* ~= 10^-202 */ U64(0x9CC3A6EE, 0xC6311A63), U64(0xCBE33036, 0x74053BB0), /* ~= 10^-201 */ U64(0xC3F490AA, 0x77BD60FC), U64(0xBEDBFC44, 0x11068A9C), /* ~= 10^-200 */ U64(0xF4F1B4D5, 0x15ACB93B), U64(0xEE92FB55, 0x15482D44), /* ~= 10^-199 */ U64(0x99171105, 0x2D8BF3C5), U64(0x751BDD15, 0x2D4D1C4A), /* ~= 10^-198 */ U64(0xBF5CD546, 0x78EEF0B6), U64(0xD262D45A, 0x78A0635D), /* ~= 10^-197 */ U64(0xEF340A98, 0x172AACE4), U64(0x86FB8971, 0x16C87C34), /* ~= 10^-196 */ U64(0x9580869F, 0x0E7AAC0E), U64(0xD45D35E6, 0xAE3D4DA0), /* ~= 10^-195 */ U64(0xBAE0A846, 0xD2195712), U64(0x89748360, 0x59CCA109), /* ~= 10^-194 */ U64(0xE998D258, 0x869FACD7), U64(0x2BD1A438, 0x703FC94B), /* ~= 10^-193 */ U64(0x91FF8377, 0x5423CC06), U64(0x7B6306A3, 0x4627DDCF), /* ~= 10^-192 */ U64(0xB67F6455, 0x292CBF08), U64(0x1A3BC84C, 0x17B1D542), /* ~= 10^-191 */ U64(0xE41F3D6A, 0x7377EECA), U64(0x20CABA5F, 0x1D9E4A93), /* ~= 10^-190 */ U64(0x8E938662, 0x882AF53E), U64(0x547EB47B, 0x7282EE9C), /* ~= 10^-189 */ U64(0xB23867FB, 0x2A35B28D), U64(0xE99E619A, 0x4F23AA43), /* ~= 10^-188 */ U64(0xDEC681F9, 0xF4C31F31), U64(0x6405FA00, 0xE2EC94D4), /* ~= 10^-187 */ U64(0x8B3C113C, 0x38F9F37E), U64(0xDE83BC40, 0x8DD3DD04), /* ~= 10^-186 */ U64(0xAE0B158B, 0x4738705E), U64(0x9624AB50, 0xB148D445), /* ~= 10^-185 */ U64(0xD98DDAEE, 0x19068C76), U64(0x3BADD624, 0xDD9B0957), /* ~= 10^-184 */ U64(0x87F8A8D4, 0xCFA417C9), U64(0xE54CA5D7, 0x0A80E5D6), /* ~= 10^-183 */ U64(0xA9F6D30A, 0x038D1DBC), U64(0x5E9FCF4C, 0xCD211F4C), /* ~= 10^-182 */ U64(0xD47487CC, 0x8470652B), U64(0x7647C320, 0x0069671F), /* ~= 10^-181 */ U64(0x84C8D4DF, 0xD2C63F3B), U64(0x29ECD9F4, 0x0041E073), /* ~= 10^-180 */ U64(0xA5FB0A17, 0xC777CF09), U64(0xF4681071, 0x00525890), /* ~= 10^-179 */ U64(0xCF79CC9D, 0xB955C2CC), U64(0x7182148D, 0x4066EEB4), /* ~= 10^-178 */ U64(0x81AC1FE2, 0x93D599BF), U64(0xC6F14CD8, 0x48405530), /* ~= 10^-177 */ U64(0xA21727DB, 0x38CB002F), U64(0xB8ADA00E, 0x5A506A7C), /* ~= 10^-176 */ U64(0xCA9CF1D2, 0x06FDC03B), U64(0xA6D90811, 0xF0E4851C), /* ~= 10^-175 */ U64(0xFD442E46, 0x88BD304A), U64(0x908F4A16, 0x6D1DA663), /* ~= 10^-174 */ U64(0x9E4A9CEC, 0x15763E2E), U64(0x9A598E4E, 0x043287FE), /* ~= 10^-173 */ U64(0xC5DD4427, 0x1AD3CDBA), U64(0x40EFF1E1, 0x853F29FD), /* ~= 10^-172 */ U64(0xF7549530, 0xE188C128), U64(0xD12BEE59, 0xE68EF47C), /* ~= 10^-171 */ U64(0x9A94DD3E, 0x8CF578B9), U64(0x82BB74F8, 0x301958CE), /* ~= 10^-170 */ U64(0xC13A148E, 0x3032D6E7), U64(0xE36A5236, 0x3C1FAF01), /* ~= 10^-169 */ U64(0xF18899B1, 0xBC3F8CA1), U64(0xDC44E6C3, 0xCB279AC1), /* ~= 10^-168 */ U64(0x96F5600F, 0x15A7B7E5), U64(0x29AB103A, 0x5EF8C0B9), /* ~= 10^-167 */ U64(0xBCB2B812, 0xDB11A5DE), U64(0x7415D448, 0xF6B6F0E7), /* ~= 10^-166 */ U64(0xEBDF6617, 0x91D60F56), U64(0x111B495B, 0x3464AD21), /* ~= 10^-165 */ U64(0x936B9FCE, 0xBB25C995), U64(0xCAB10DD9, 0x00BEEC34), /* ~= 10^-164 */ U64(0xB84687C2, 0x69EF3BFB), U64(0x3D5D514F, 0x40EEA742), /* ~= 10^-163 */ U64(0xE65829B3, 0x046B0AFA), U64(0x0CB4A5A3, 0x112A5112), /* ~= 10^-162 */ U64(0x8FF71A0F, 0xE2C2E6DC), U64(0x47F0E785, 0xEABA72AB), /* ~= 10^-161 */ U64(0xB3F4E093, 0xDB73A093), U64(0x59ED2167, 0x65690F56), /* ~= 10^-160 */ U64(0xE0F218B8, 0xD25088B8), U64(0x306869C1, 0x3EC3532C), /* ~= 10^-159 */ U64(0x8C974F73, 0x83725573), U64(0x1E414218, 0xC73A13FB), /* ~= 10^-158 */ U64(0xAFBD2350, 0x644EEACF), U64(0xE5D1929E, 0xF90898FA), /* ~= 10^-157 */ U64(0xDBAC6C24, 0x7D62A583), U64(0xDF45F746, 0xB74ABF39), /* ~= 10^-156 */ U64(0x894BC396, 0xCE5DA772), U64(0x6B8BBA8C, 0x328EB783), /* ~= 10^-155 */ U64(0xAB9EB47C, 0x81F5114F), U64(0x066EA92F, 0x3F326564), /* ~= 10^-154 */ U64(0xD686619B, 0xA27255A2), U64(0xC80A537B, 0x0EFEFEBD), /* ~= 10^-153 */ U64(0x8613FD01, 0x45877585), U64(0xBD06742C, 0xE95F5F36), /* ~= 10^-152 */ U64(0xA798FC41, 0x96E952E7), U64(0x2C481138, 0x23B73704), /* ~= 10^-151 */ U64(0xD17F3B51, 0xFCA3A7A0), U64(0xF75A1586, 0x2CA504C5), /* ~= 10^-150 */ U64(0x82EF8513, 0x3DE648C4), U64(0x9A984D73, 0xDBE722FB), /* ~= 10^-149 */ U64(0xA3AB6658, 0x0D5FDAF5), U64(0xC13E60D0, 0xD2E0EBBA), /* ~= 10^-148 */ U64(0xCC963FEE, 0x10B7D1B3), U64(0x318DF905, 0x079926A8), /* ~= 10^-147 */ U64(0xFFBBCFE9, 0x94E5C61F), U64(0xFDF17746, 0x497F7052), /* ~= 10^-146 */ U64(0x9FD561F1, 0xFD0F9BD3), U64(0xFEB6EA8B, 0xEDEFA633), /* ~= 10^-145 */ U64(0xC7CABA6E, 0x7C5382C8), U64(0xFE64A52E, 0xE96B8FC0), /* ~= 10^-144 */ U64(0xF9BD690A, 0x1B68637B), U64(0x3DFDCE7A, 0xA3C673B0), /* ~= 10^-143 */ U64(0x9C1661A6, 0x51213E2D), U64(0x06BEA10C, 0xA65C084E), /* ~= 10^-142 */ U64(0xC31BFA0F, 0xE5698DB8), U64(0x486E494F, 0xCFF30A62), /* ~= 10^-141 */ U64(0xF3E2F893, 0xDEC3F126), U64(0x5A89DBA3, 0xC3EFCCFA), /* ~= 10^-140 */ U64(0x986DDB5C, 0x6B3A76B7), U64(0xF8962946, 0x5A75E01C), /* ~= 10^-139 */ U64(0xBE895233, 0x86091465), U64(0xF6BBB397, 0xF1135823), /* ~= 10^-138 */ U64(0xEE2BA6C0, 0x678B597F), U64(0x746AA07D, 0xED582E2C), /* ~= 10^-137 */ U64(0x94DB4838, 0x40B717EF), U64(0xA8C2A44E, 0xB4571CDC), /* ~= 10^-136 */ U64(0xBA121A46, 0x50E4DDEB), U64(0x92F34D62, 0x616CE413), /* ~= 10^-135 */ U64(0xE896A0D7, 0xE51E1566), U64(0x77B020BA, 0xF9C81D17), /* ~= 10^-134 */ U64(0x915E2486, 0xEF32CD60), U64(0x0ACE1474, 0xDC1D122E), /* ~= 10^-133 */ U64(0xB5B5ADA8, 0xAAFF80B8), U64(0x0D819992, 0x132456BA), /* ~= 10^-132 */ U64(0xE3231912, 0xD5BF60E6), U64(0x10E1FFF6, 0x97ED6C69), /* ~= 10^-131 */ U64(0x8DF5EFAB, 0xC5979C8F), U64(0xCA8D3FFA, 0x1EF463C1), /* ~= 10^-130 */ U64(0xB1736B96, 0xB6FD83B3), U64(0xBD308FF8, 0xA6B17CB2), /* ~= 10^-129 */ U64(0xDDD0467C, 0x64BCE4A0), U64(0xAC7CB3F6, 0xD05DDBDE), /* ~= 10^-128 */ U64(0x8AA22C0D, 0xBEF60EE4), U64(0x6BCDF07A, 0x423AA96B), /* ~= 10^-127 */ U64(0xAD4AB711, 0x2EB3929D), U64(0x86C16C98, 0xD2C953C6), /* ~= 10^-126 */ U64(0xD89D64D5, 0x7A607744), U64(0xE871C7BF, 0x077BA8B7), /* ~= 10^-125 */ U64(0x87625F05, 0x6C7C4A8B), U64(0x11471CD7, 0x64AD4972), /* ~= 10^-124 */ U64(0xA93AF6C6, 0xC79B5D2D), U64(0xD598E40D, 0x3DD89BCF), /* ~= 10^-123 */ U64(0xD389B478, 0x79823479), U64(0x4AFF1D10, 0x8D4EC2C3), /* ~= 10^-122 */ U64(0x843610CB, 0x4BF160CB), U64(0xCEDF722A, 0x585139BA), /* ~= 10^-121 */ U64(0xA54394FE, 0x1EEDB8FE), U64(0xC2974EB4, 0xEE658828), /* ~= 10^-120 */ U64(0xCE947A3D, 0xA6A9273E), U64(0x733D2262, 0x29FEEA32), /* ~= 10^-119 */ U64(0x811CCC66, 0x8829B887), U64(0x0806357D, 0x5A3F525F), /* ~= 10^-118 */ U64(0xA163FF80, 0x2A3426A8), U64(0xCA07C2DC, 0xB0CF26F7), /* ~= 10^-117 */ U64(0xC9BCFF60, 0x34C13052), U64(0xFC89B393, 0xDD02F0B5), /* ~= 10^-116 */ U64(0xFC2C3F38, 0x41F17C67), U64(0xBBAC2078, 0xD443ACE2), /* ~= 10^-115 */ U64(0x9D9BA783, 0x2936EDC0), U64(0xD54B944B, 0x84AA4C0D), /* ~= 10^-114 */ U64(0xC5029163, 0xF384A931), U64(0x0A9E795E, 0x65D4DF11), /* ~= 10^-113 */ U64(0xF64335BC, 0xF065D37D), U64(0x4D4617B5, 0xFF4A16D5), /* ~= 10^-112 */ U64(0x99EA0196, 0x163FA42E), U64(0x504BCED1, 0xBF8E4E45), /* ~= 10^-111 */ U64(0xC06481FB, 0x9BCF8D39), U64(0xE45EC286, 0x2F71E1D6), /* ~= 10^-110 */ U64(0xF07DA27A, 0x82C37088), U64(0x5D767327, 0xBB4E5A4C), /* ~= 10^-109 */ U64(0x964E858C, 0x91BA2655), U64(0x3A6A07F8, 0xD510F86F), /* ~= 10^-108 */ U64(0xBBE226EF, 0xB628AFEA), U64(0x890489F7, 0x0A55368B), /* ~= 10^-107 */ U64(0xEADAB0AB, 0xA3B2DBE5), U64(0x2B45AC74, 0xCCEA842E), /* ~= 10^-106 */ U64(0x92C8AE6B, 0x464FC96F), U64(0x3B0B8BC9, 0x0012929D), /* ~= 10^-105 */ U64(0xB77ADA06, 0x17E3BBCB), U64(0x09CE6EBB, 0x40173744), /* ~= 10^-104 */ U64(0xE5599087, 0x9DDCAABD), U64(0xCC420A6A, 0x101D0515), /* ~= 10^-103 */ U64(0x8F57FA54, 0xC2A9EAB6), U64(0x9FA94682, 0x4A12232D), /* ~= 10^-102 */ U64(0xB32DF8E9, 0xF3546564), U64(0x47939822, 0xDC96ABF9), /* ~= 10^-101 */ U64(0xDFF97724, 0x70297EBD), U64(0x59787E2B, 0x93BC56F7), /* ~= 10^-100 */ U64(0x8BFBEA76, 0xC619EF36), U64(0x57EB4EDB, 0x3C55B65A), /* ~= 10^-99 */ U64(0xAEFAE514, 0x77A06B03), U64(0xEDE62292, 0x0B6B23F1), /* ~= 10^-98 */ U64(0xDAB99E59, 0x958885C4), U64(0xE95FAB36, 0x8E45ECED), /* ~= 10^-97 */ U64(0x88B402F7, 0xFD75539B), U64(0x11DBCB02, 0x18EBB414), /* ~= 10^-96 */ U64(0xAAE103B5, 0xFCD2A881), U64(0xD652BDC2, 0x9F26A119), /* ~= 10^-95 */ U64(0xD59944A3, 0x7C0752A2), U64(0x4BE76D33, 0x46F0495F), /* ~= 10^-94 */ U64(0x857FCAE6, 0x2D8493A5), U64(0x6F70A440, 0x0C562DDB), /* ~= 10^-93 */ U64(0xA6DFBD9F, 0xB8E5B88E), U64(0xCB4CCD50, 0x0F6BB952), /* ~= 10^-92 */ U64(0xD097AD07, 0xA71F26B2), U64(0x7E2000A4, 0x1346A7A7), /* ~= 10^-91 */ U64(0x825ECC24, 0xC873782F), U64(0x8ED40066, 0x8C0C28C8), /* ~= 10^-90 */ U64(0xA2F67F2D, 0xFA90563B), U64(0x72890080, 0x2F0F32FA), /* ~= 10^-89 */ U64(0xCBB41EF9, 0x79346BCA), U64(0x4F2B40A0, 0x3AD2FFB9), /* ~= 10^-88 */ U64(0xFEA126B7, 0xD78186BC), U64(0xE2F610C8, 0x4987BFA8), /* ~= 10^-87 */ U64(0x9F24B832, 0xE6B0F436), U64(0x0DD9CA7D, 0x2DF4D7C9), /* ~= 10^-86 */ U64(0xC6EDE63F, 0xA05D3143), U64(0x91503D1C, 0x79720DBB), /* ~= 10^-85 */ U64(0xF8A95FCF, 0x88747D94), U64(0x75A44C63, 0x97CE912A), /* ~= 10^-84 */ U64(0x9B69DBE1, 0xB548CE7C), U64(0xC986AFBE, 0x3EE11ABA), /* ~= 10^-83 */ U64(0xC24452DA, 0x229B021B), U64(0xFBE85BAD, 0xCE996168), /* ~= 10^-82 */ U64(0xF2D56790, 0xAB41C2A2), U64(0xFAE27299, 0x423FB9C3), /* ~= 10^-81 */ U64(0x97C560BA, 0x6B0919A5), U64(0xDCCD879F, 0xC967D41A), /* ~= 10^-80 */ U64(0xBDB6B8E9, 0x05CB600F), U64(0x5400E987, 0xBBC1C920), /* ~= 10^-79 */ U64(0xED246723, 0x473E3813), U64(0x290123E9, 0xAAB23B68), /* ~= 10^-78 */ U64(0x9436C076, 0x0C86E30B), U64(0xF9A0B672, 0x0AAF6521), /* ~= 10^-77 */ U64(0xB9447093, 0x8FA89BCE), U64(0xF808E40E, 0x8D5B3E69), /* ~= 10^-76 */ U64(0xE7958CB8, 0x7392C2C2), U64(0xB60B1D12, 0x30B20E04), /* ~= 10^-75 */ U64(0x90BD77F3, 0x483BB9B9), U64(0xB1C6F22B, 0x5E6F48C2), /* ~= 10^-74 */ U64(0xB4ECD5F0, 0x1A4AA828), U64(0x1E38AEB6, 0x360B1AF3), /* ~= 10^-73 */ U64(0xE2280B6C, 0x20DD5232), U64(0x25C6DA63, 0xC38DE1B0), /* ~= 10^-72 */ U64(0x8D590723, 0x948A535F), U64(0x579C487E, 0x5A38AD0E), /* ~= 10^-71 */ U64(0xB0AF48EC, 0x79ACE837), U64(0x2D835A9D, 0xF0C6D851), /* ~= 10^-70 */ U64(0xDCDB1B27, 0x98182244), U64(0xF8E43145, 0x6CF88E65), /* ~= 10^-69 */ U64(0x8A08F0F8, 0xBF0F156B), U64(0x1B8E9ECB, 0x641B58FF), /* ~= 10^-68 */ U64(0xAC8B2D36, 0xEED2DAC5), U64(0xE272467E, 0x3D222F3F), /* ~= 10^-67 */ U64(0xD7ADF884, 0xAA879177), U64(0x5B0ED81D, 0xCC6ABB0F), /* ~= 10^-66 */ U64(0x86CCBB52, 0xEA94BAEA), U64(0x98E94712, 0x9FC2B4E9), /* ~= 10^-65 */ U64(0xA87FEA27, 0xA539E9A5), U64(0x3F2398D7, 0x47B36224), /* ~= 10^-64 */ U64(0xD29FE4B1, 0x8E88640E), U64(0x8EEC7F0D, 0x19A03AAD), /* ~= 10^-63 */ U64(0x83A3EEEE, 0xF9153E89), U64(0x1953CF68, 0x300424AC), /* ~= 10^-62 */ U64(0xA48CEAAA, 0xB75A8E2B), U64(0x5FA8C342, 0x3C052DD7), /* ~= 10^-61 */ U64(0xCDB02555, 0x653131B6), U64(0x3792F412, 0xCB06794D), /* ~= 10^-60 */ U64(0x808E1755, 0x5F3EBF11), U64(0xE2BBD88B, 0xBEE40BD0), /* ~= 10^-59 */ U64(0xA0B19D2A, 0xB70E6ED6), U64(0x5B6ACEAE, 0xAE9D0EC4), /* ~= 10^-58 */ U64(0xC8DE0475, 0x64D20A8B), U64(0xF245825A, 0x5A445275), /* ~= 10^-57 */ U64(0xFB158592, 0xBE068D2E), U64(0xEED6E2F0, 0xF0D56712), /* ~= 10^-56 */ U64(0x9CED737B, 0xB6C4183D), U64(0x55464DD6, 0x9685606B), /* ~= 10^-55 */ U64(0xC428D05A, 0xA4751E4C), U64(0xAA97E14C, 0x3C26B886), /* ~= 10^-54 */ U64(0xF5330471, 0x4D9265DF), U64(0xD53DD99F, 0x4B3066A8), /* ~= 10^-53 */ U64(0x993FE2C6, 0xD07B7FAB), U64(0xE546A803, 0x8EFE4029), /* ~= 10^-52 */ U64(0xBF8FDB78, 0x849A5F96), U64(0xDE985204, 0x72BDD033), /* ~= 10^-51 */ U64(0xEF73D256, 0xA5C0F77C), U64(0x963E6685, 0x8F6D4440), /* ~= 10^-50 */ U64(0x95A86376, 0x27989AAD), U64(0xDDE70013, 0x79A44AA8), /* ~= 10^-49 */ U64(0xBB127C53, 0xB17EC159), U64(0x5560C018, 0x580D5D52), /* ~= 10^-48 */ U64(0xE9D71B68, 0x9DDE71AF), U64(0xAAB8F01E, 0x6E10B4A6), /* ~= 10^-47 */ U64(0x92267121, 0x62AB070D), U64(0xCAB39613, 0x04CA70E8), /* ~= 10^-46 */ U64(0xB6B00D69, 0xBB55C8D1), U64(0x3D607B97, 0xC5FD0D22), /* ~= 10^-45 */ U64(0xE45C10C4, 0x2A2B3B05), U64(0x8CB89A7D, 0xB77C506A), /* ~= 10^-44 */ U64(0x8EB98A7A, 0x9A5B04E3), U64(0x77F3608E, 0x92ADB242), /* ~= 10^-43 */ U64(0xB267ED19, 0x40F1C61C), U64(0x55F038B2, 0x37591ED3), /* ~= 10^-42 */ U64(0xDF01E85F, 0x912E37A3), U64(0x6B6C46DE, 0xC52F6688), /* ~= 10^-41 */ U64(0x8B61313B, 0xBABCE2C6), U64(0x2323AC4B, 0x3B3DA015), /* ~= 10^-40 */ U64(0xAE397D8A, 0xA96C1B77), U64(0xABEC975E, 0x0A0D081A), /* ~= 10^-39 */ U64(0xD9C7DCED, 0x53C72255), U64(0x96E7BD35, 0x8C904A21), /* ~= 10^-38 */ U64(0x881CEA14, 0x545C7575), U64(0x7E50D641, 0x77DA2E54), /* ~= 10^-37 */ U64(0xAA242499, 0x697392D2), U64(0xDDE50BD1, 0xD5D0B9E9), /* ~= 10^-36 */ U64(0xD4AD2DBF, 0xC3D07787), U64(0x955E4EC6, 0x4B44E864), /* ~= 10^-35 */ U64(0x84EC3C97, 0xDA624AB4), U64(0xBD5AF13B, 0xEF0B113E), /* ~= 10^-34 */ U64(0xA6274BBD, 0xD0FADD61), U64(0xECB1AD8A, 0xEACDD58E), /* ~= 10^-33 */ U64(0xCFB11EAD, 0x453994BA), U64(0x67DE18ED, 0xA5814AF2), /* ~= 10^-32 */ U64(0x81CEB32C, 0x4B43FCF4), U64(0x80EACF94, 0x8770CED7), /* ~= 10^-31 */ U64(0xA2425FF7, 0x5E14FC31), U64(0xA1258379, 0xA94D028D), /* ~= 10^-30 */ U64(0xCAD2F7F5, 0x359A3B3E), U64(0x096EE458, 0x13A04330), /* ~= 10^-29 */ U64(0xFD87B5F2, 0x8300CA0D), U64(0x8BCA9D6E, 0x188853FC), /* ~= 10^-28 */ U64(0x9E74D1B7, 0x91E07E48), U64(0x775EA264, 0xCF55347D), /* ~= 10^-27 */ U64(0xC6120625, 0x76589DDA), U64(0x95364AFE, 0x032A819D), /* ~= 10^-26 */ U64(0xF79687AE, 0xD3EEC551), U64(0x3A83DDBD, 0x83F52204), /* ~= 10^-25 */ U64(0x9ABE14CD, 0x44753B52), U64(0xC4926A96, 0x72793542), /* ~= 10^-24 */ U64(0xC16D9A00, 0x95928A27), U64(0x75B7053C, 0x0F178293), /* ~= 10^-23 */ U64(0xF1C90080, 0xBAF72CB1), U64(0x5324C68B, 0x12DD6338), /* ~= 10^-22 */ U64(0x971DA050, 0x74DA7BEE), U64(0xD3F6FC16, 0xEBCA5E03), /* ~= 10^-21 */ U64(0xBCE50864, 0x92111AEA), U64(0x88F4BB1C, 0xA6BCF584), /* ~= 10^-20 */ U64(0xEC1E4A7D, 0xB69561A5), U64(0x2B31E9E3, 0xD06C32E5), /* ~= 10^-19 */ U64(0x9392EE8E, 0x921D5D07), U64(0x3AFF322E, 0x62439FCF), /* ~= 10^-18 */ U64(0xB877AA32, 0x36A4B449), U64(0x09BEFEB9, 0xFAD487C2), /* ~= 10^-17 */ U64(0xE69594BE, 0xC44DE15B), U64(0x4C2EBE68, 0x7989A9B3), /* ~= 10^-16 */ U64(0x901D7CF7, 0x3AB0ACD9), U64(0x0F9D3701, 0x4BF60A10), /* ~= 10^-15 */ U64(0xB424DC35, 0x095CD80F), U64(0x538484C1, 0x9EF38C94), /* ~= 10^-14 */ U64(0xE12E1342, 0x4BB40E13), U64(0x2865A5F2, 0x06B06FB9), /* ~= 10^-13 */ U64(0x8CBCCC09, 0x6F5088CB), U64(0xF93F87B7, 0x442E45D3), /* ~= 10^-12 */ U64(0xAFEBFF0B, 0xCB24AAFE), U64(0xF78F69A5, 0x1539D748), /* ~= 10^-11 */ U64(0xDBE6FECE, 0xBDEDD5BE), U64(0xB573440E, 0x5A884D1B), /* ~= 10^-10 */ U64(0x89705F41, 0x36B4A597), U64(0x31680A88, 0xF8953030), /* ~= 10^-9 */ U64(0xABCC7711, 0x8461CEFC), U64(0xFDC20D2B, 0x36BA7C3D), /* ~= 10^-8 */ U64(0xD6BF94D5, 0xE57A42BC), U64(0x3D329076, 0x04691B4C), /* ~= 10^-7 */ U64(0x8637BD05, 0xAF6C69B5), U64(0xA63F9A49, 0xC2C1B10F), /* ~= 10^-6 */ U64(0xA7C5AC47, 0x1B478423), U64(0x0FCF80DC, 0x33721D53), /* ~= 10^-5 */ U64(0xD1B71758, 0xE219652B), U64(0xD3C36113, 0x404EA4A8), /* ~= 10^-4 */ U64(0x83126E97, 0x8D4FDF3B), U64(0x645A1CAC, 0x083126E9), /* ~= 10^-3 */ U64(0xA3D70A3D, 0x70A3D70A), U64(0x3D70A3D7, 0x0A3D70A3), /* ~= 10^-2 */ U64(0xCCCCCCCC, 0xCCCCCCCC), U64(0xCCCCCCCC, 0xCCCCCCCC), /* ~= 10^-1 */ U64(0x80000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^0 */ U64(0xA0000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^1 */ U64(0xC8000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^2 */ U64(0xFA000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^3 */ U64(0x9C400000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^4 */ U64(0xC3500000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^5 */ U64(0xF4240000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^6 */ U64(0x98968000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^7 */ U64(0xBEBC2000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^8 */ U64(0xEE6B2800, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^9 */ U64(0x9502F900, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^10 */ U64(0xBA43B740, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^11 */ U64(0xE8D4A510, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^12 */ U64(0x9184E72A, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^13 */ U64(0xB5E620F4, 0x80000000), U64(0x00000000, 0x00000000), /* == 10^14 */ U64(0xE35FA931, 0xA0000000), U64(0x00000000, 0x00000000), /* == 10^15 */ U64(0x8E1BC9BF, 0x04000000), U64(0x00000000, 0x00000000), /* == 10^16 */ U64(0xB1A2BC2E, 0xC5000000), U64(0x00000000, 0x00000000), /* == 10^17 */ U64(0xDE0B6B3A, 0x76400000), U64(0x00000000, 0x00000000), /* == 10^18 */ U64(0x8AC72304, 0x89E80000), U64(0x00000000, 0x00000000), /* == 10^19 */ U64(0xAD78EBC5, 0xAC620000), U64(0x00000000, 0x00000000), /* == 10^20 */ U64(0xD8D726B7, 0x177A8000), U64(0x00000000, 0x00000000), /* == 10^21 */ U64(0x87867832, 0x6EAC9000), U64(0x00000000, 0x00000000), /* == 10^22 */ U64(0xA968163F, 0x0A57B400), U64(0x00000000, 0x00000000), /* == 10^23 */ U64(0xD3C21BCE, 0xCCEDA100), U64(0x00000000, 0x00000000), /* == 10^24 */ U64(0x84595161, 0x401484A0), U64(0x00000000, 0x00000000), /* == 10^25 */ U64(0xA56FA5B9, 0x9019A5C8), U64(0x00000000, 0x00000000), /* == 10^26 */ U64(0xCECB8F27, 0xF4200F3A), U64(0x00000000, 0x00000000), /* == 10^27 */ U64(0x813F3978, 0xF8940984), U64(0x40000000, 0x00000000), /* == 10^28 */ U64(0xA18F07D7, 0x36B90BE5), U64(0x50000000, 0x00000000), /* == 10^29 */ U64(0xC9F2C9CD, 0x04674EDE), U64(0xA4000000, 0x00000000), /* == 10^30 */ U64(0xFC6F7C40, 0x45812296), U64(0x4D000000, 0x00000000), /* == 10^31 */ U64(0x9DC5ADA8, 0x2B70B59D), U64(0xF0200000, 0x00000000), /* == 10^32 */ U64(0xC5371912, 0x364CE305), U64(0x6C280000, 0x00000000), /* == 10^33 */ U64(0xF684DF56, 0xC3E01BC6), U64(0xC7320000, 0x00000000), /* == 10^34 */ U64(0x9A130B96, 0x3A6C115C), U64(0x3C7F4000, 0x00000000), /* == 10^35 */ U64(0xC097CE7B, 0xC90715B3), U64(0x4B9F1000, 0x00000000), /* == 10^36 */ U64(0xF0BDC21A, 0xBB48DB20), U64(0x1E86D400, 0x00000000), /* == 10^37 */ U64(0x96769950, 0xB50D88F4), U64(0x13144480, 0x00000000), /* == 10^38 */ U64(0xBC143FA4, 0xE250EB31), U64(0x17D955A0, 0x00000000), /* == 10^39 */ U64(0xEB194F8E, 0x1AE525FD), U64(0x5DCFAB08, 0x00000000), /* == 10^40 */ U64(0x92EFD1B8, 0xD0CF37BE), U64(0x5AA1CAE5, 0x00000000), /* == 10^41 */ U64(0xB7ABC627, 0x050305AD), U64(0xF14A3D9E, 0x40000000), /* == 10^42 */ U64(0xE596B7B0, 0xC643C719), U64(0x6D9CCD05, 0xD0000000), /* == 10^43 */ U64(0x8F7E32CE, 0x7BEA5C6F), U64(0xE4820023, 0xA2000000), /* == 10^44 */ U64(0xB35DBF82, 0x1AE4F38B), U64(0xDDA2802C, 0x8A800000), /* == 10^45 */ U64(0xE0352F62, 0xA19E306E), U64(0xD50B2037, 0xAD200000), /* == 10^46 */ U64(0x8C213D9D, 0xA502DE45), U64(0x4526F422, 0xCC340000), /* == 10^47 */ U64(0xAF298D05, 0x0E4395D6), U64(0x9670B12B, 0x7F410000), /* == 10^48 */ U64(0xDAF3F046, 0x51D47B4C), U64(0x3C0CDD76, 0x5F114000), /* == 10^49 */ U64(0x88D8762B, 0xF324CD0F), U64(0xA5880A69, 0xFB6AC800), /* == 10^50 */ U64(0xAB0E93B6, 0xEFEE0053), U64(0x8EEA0D04, 0x7A457A00), /* == 10^51 */ U64(0xD5D238A4, 0xABE98068), U64(0x72A49045, 0x98D6D880), /* == 10^52 */ U64(0x85A36366, 0xEB71F041), U64(0x47A6DA2B, 0x7F864750), /* == 10^53 */ U64(0xA70C3C40, 0xA64E6C51), U64(0x999090B6, 0x5F67D924), /* == 10^54 */ U64(0xD0CF4B50, 0xCFE20765), U64(0xFFF4B4E3, 0xF741CF6D), /* == 10^55 */ U64(0x82818F12, 0x81ED449F), U64(0xBFF8F10E, 0x7A8921A4), /* ~= 10^56 */ U64(0xA321F2D7, 0x226895C7), U64(0xAFF72D52, 0x192B6A0D), /* ~= 10^57 */ U64(0xCBEA6F8C, 0xEB02BB39), U64(0x9BF4F8A6, 0x9F764490), /* ~= 10^58 */ U64(0xFEE50B70, 0x25C36A08), U64(0x02F236D0, 0x4753D5B4), /* ~= 10^59 */ U64(0x9F4F2726, 0x179A2245), U64(0x01D76242, 0x2C946590), /* ~= 10^60 */ U64(0xC722F0EF, 0x9D80AAD6), U64(0x424D3AD2, 0xB7B97EF5), /* ~= 10^61 */ U64(0xF8EBAD2B, 0x84E0D58B), U64(0xD2E08987, 0x65A7DEB2), /* ~= 10^62 */ U64(0x9B934C3B, 0x330C8577), U64(0x63CC55F4, 0x9F88EB2F), /* ~= 10^63 */ U64(0xC2781F49, 0xFFCFA6D5), U64(0x3CBF6B71, 0xC76B25FB), /* ~= 10^64 */ U64(0xF316271C, 0x7FC3908A), U64(0x8BEF464E, 0x3945EF7A), /* ~= 10^65 */ U64(0x97EDD871, 0xCFDA3A56), U64(0x97758BF0, 0xE3CBB5AC), /* ~= 10^66 */ U64(0xBDE94E8E, 0x43D0C8EC), U64(0x3D52EEED, 0x1CBEA317), /* ~= 10^67 */ U64(0xED63A231, 0xD4C4FB27), U64(0x4CA7AAA8, 0x63EE4BDD), /* ~= 10^68 */ U64(0x945E455F, 0x24FB1CF8), U64(0x8FE8CAA9, 0x3E74EF6A), /* ~= 10^69 */ U64(0xB975D6B6, 0xEE39E436), U64(0xB3E2FD53, 0x8E122B44), /* ~= 10^70 */ U64(0xE7D34C64, 0xA9C85D44), U64(0x60DBBCA8, 0x7196B616), /* ~= 10^71 */ U64(0x90E40FBE, 0xEA1D3A4A), U64(0xBC8955E9, 0x46FE31CD), /* ~= 10^72 */ U64(0xB51D13AE, 0xA4A488DD), U64(0x6BABAB63, 0x98BDBE41), /* ~= 10^73 */ U64(0xE264589A, 0x4DCDAB14), U64(0xC696963C, 0x7EED2DD1), /* ~= 10^74 */ U64(0x8D7EB760, 0x70A08AEC), U64(0xFC1E1DE5, 0xCF543CA2), /* ~= 10^75 */ U64(0xB0DE6538, 0x8CC8ADA8), U64(0x3B25A55F, 0x43294BCB), /* ~= 10^76 */ U64(0xDD15FE86, 0xAFFAD912), U64(0x49EF0EB7, 0x13F39EBE), /* ~= 10^77 */ U64(0x8A2DBF14, 0x2DFCC7AB), U64(0x6E356932, 0x6C784337), /* ~= 10^78 */ U64(0xACB92ED9, 0x397BF996), U64(0x49C2C37F, 0x07965404), /* ~= 10^79 */ U64(0xD7E77A8F, 0x87DAF7FB), U64(0xDC33745E, 0xC97BE906), /* ~= 10^80 */ U64(0x86F0AC99, 0xB4E8DAFD), U64(0x69A028BB, 0x3DED71A3), /* ~= 10^81 */ U64(0xA8ACD7C0, 0x222311BC), U64(0xC40832EA, 0x0D68CE0C), /* ~= 10^82 */ U64(0xD2D80DB0, 0x2AABD62B), U64(0xF50A3FA4, 0x90C30190), /* ~= 10^83 */ U64(0x83C7088E, 0x1AAB65DB), U64(0x792667C6, 0xDA79E0FA), /* ~= 10^84 */ U64(0xA4B8CAB1, 0xA1563F52), U64(0x577001B8, 0x91185938), /* ~= 10^85 */ U64(0xCDE6FD5E, 0x09ABCF26), U64(0xED4C0226, 0xB55E6F86), /* ~= 10^86 */ U64(0x80B05E5A, 0xC60B6178), U64(0x544F8158, 0x315B05B4), /* ~= 10^87 */ U64(0xA0DC75F1, 0x778E39D6), U64(0x696361AE, 0x3DB1C721), /* ~= 10^88 */ U64(0xC913936D, 0xD571C84C), U64(0x03BC3A19, 0xCD1E38E9), /* ~= 10^89 */ U64(0xFB587849, 0x4ACE3A5F), U64(0x04AB48A0, 0x4065C723), /* ~= 10^90 */ U64(0x9D174B2D, 0xCEC0E47B), U64(0x62EB0D64, 0x283F9C76), /* ~= 10^91 */ U64(0xC45D1DF9, 0x42711D9A), U64(0x3BA5D0BD, 0x324F8394), /* ~= 10^92 */ U64(0xF5746577, 0x930D6500), U64(0xCA8F44EC, 0x7EE36479), /* ~= 10^93 */ U64(0x9968BF6A, 0xBBE85F20), U64(0x7E998B13, 0xCF4E1ECB), /* ~= 10^94 */ U64(0xBFC2EF45, 0x6AE276E8), U64(0x9E3FEDD8, 0xC321A67E), /* ~= 10^95 */ U64(0xEFB3AB16, 0xC59B14A2), U64(0xC5CFE94E, 0xF3EA101E), /* ~= 10^96 */ U64(0x95D04AEE, 0x3B80ECE5), U64(0xBBA1F1D1, 0x58724A12), /* ~= 10^97 */ U64(0xBB445DA9, 0xCA61281F), U64(0x2A8A6E45, 0xAE8EDC97), /* ~= 10^98 */ U64(0xEA157514, 0x3CF97226), U64(0xF52D09D7, 0x1A3293BD), /* ~= 10^99 */ U64(0x924D692C, 0xA61BE758), U64(0x593C2626, 0x705F9C56), /* ~= 10^100 */ U64(0xB6E0C377, 0xCFA2E12E), U64(0x6F8B2FB0, 0x0C77836C), /* ~= 10^101 */ U64(0xE498F455, 0xC38B997A), U64(0x0B6DFB9C, 0x0F956447), /* ~= 10^102 */ U64(0x8EDF98B5, 0x9A373FEC), U64(0x4724BD41, 0x89BD5EAC), /* ~= 10^103 */ U64(0xB2977EE3, 0x00C50FE7), U64(0x58EDEC91, 0xEC2CB657), /* ~= 10^104 */ U64(0xDF3D5E9B, 0xC0F653E1), U64(0x2F2967B6, 0x6737E3ED), /* ~= 10^105 */ U64(0x8B865B21, 0x5899F46C), U64(0xBD79E0D2, 0x0082EE74), /* ~= 10^106 */ U64(0xAE67F1E9, 0xAEC07187), U64(0xECD85906, 0x80A3AA11), /* ~= 10^107 */ U64(0xDA01EE64, 0x1A708DE9), U64(0xE80E6F48, 0x20CC9495), /* ~= 10^108 */ U64(0x884134FE, 0x908658B2), U64(0x3109058D, 0x147FDCDD), /* ~= 10^109 */ U64(0xAA51823E, 0x34A7EEDE), U64(0xBD4B46F0, 0x599FD415), /* ~= 10^110 */ U64(0xD4E5E2CD, 0xC1D1EA96), U64(0x6C9E18AC, 0x7007C91A), /* ~= 10^111 */ U64(0x850FADC0, 0x9923329E), U64(0x03E2CF6B, 0xC604DDB0), /* ~= 10^112 */ U64(0xA6539930, 0xBF6BFF45), U64(0x84DB8346, 0xB786151C), /* ~= 10^113 */ U64(0xCFE87F7C, 0xEF46FF16), U64(0xE6126418, 0x65679A63), /* ~= 10^114 */ U64(0x81F14FAE, 0x158C5F6E), U64(0x4FCB7E8F, 0x3F60C07E), /* ~= 10^115 */ U64(0xA26DA399, 0x9AEF7749), U64(0xE3BE5E33, 0x0F38F09D), /* ~= 10^116 */ U64(0xCB090C80, 0x01AB551C), U64(0x5CADF5BF, 0xD3072CC5), /* ~= 10^117 */ U64(0xFDCB4FA0, 0x02162A63), U64(0x73D9732F, 0xC7C8F7F6), /* ~= 10^118 */ U64(0x9E9F11C4, 0x014DDA7E), U64(0x2867E7FD, 0xDCDD9AFA), /* ~= 10^119 */ U64(0xC646D635, 0x01A1511D), U64(0xB281E1FD, 0x541501B8), /* ~= 10^120 */ U64(0xF7D88BC2, 0x4209A565), U64(0x1F225A7C, 0xA91A4226), /* ~= 10^121 */ U64(0x9AE75759, 0x6946075F), U64(0x3375788D, 0xE9B06958), /* ~= 10^122 */ U64(0xC1A12D2F, 0xC3978937), U64(0x0052D6B1, 0x641C83AE), /* ~= 10^123 */ U64(0xF209787B, 0xB47D6B84), U64(0xC0678C5D, 0xBD23A49A), /* ~= 10^124 */ U64(0x9745EB4D, 0x50CE6332), U64(0xF840B7BA, 0x963646E0), /* ~= 10^125 */ U64(0xBD176620, 0xA501FBFF), U64(0xB650E5A9, 0x3BC3D898), /* ~= 10^126 */ U64(0xEC5D3FA8, 0xCE427AFF), U64(0xA3E51F13, 0x8AB4CEBE), /* ~= 10^127 */ U64(0x93BA47C9, 0x80E98CDF), U64(0xC66F336C, 0x36B10137), /* ~= 10^128 */ U64(0xB8A8D9BB, 0xE123F017), U64(0xB80B0047, 0x445D4184), /* ~= 10^129 */ U64(0xE6D3102A, 0xD96CEC1D), U64(0xA60DC059, 0x157491E5), /* ~= 10^130 */ U64(0x9043EA1A, 0xC7E41392), U64(0x87C89837, 0xAD68DB2F), /* ~= 10^131 */ U64(0xB454E4A1, 0x79DD1877), U64(0x29BABE45, 0x98C311FB), /* ~= 10^132 */ U64(0xE16A1DC9, 0xD8545E94), U64(0xF4296DD6, 0xFEF3D67A), /* ~= 10^133 */ U64(0x8CE2529E, 0x2734BB1D), U64(0x1899E4A6, 0x5F58660C), /* ~= 10^134 */ U64(0xB01AE745, 0xB101E9E4), U64(0x5EC05DCF, 0xF72E7F8F), /* ~= 10^135 */ U64(0xDC21A117, 0x1D42645D), U64(0x76707543, 0xF4FA1F73), /* ~= 10^136 */ U64(0x899504AE, 0x72497EBA), U64(0x6A06494A, 0x791C53A8), /* ~= 10^137 */ U64(0xABFA45DA, 0x0EDBDE69), U64(0x0487DB9D, 0x17636892), /* ~= 10^138 */ U64(0xD6F8D750, 0x9292D603), U64(0x45A9D284, 0x5D3C42B6), /* ~= 10^139 */ U64(0x865B8692, 0x5B9BC5C2), U64(0x0B8A2392, 0xBA45A9B2), /* ~= 10^140 */ U64(0xA7F26836, 0xF282B732), U64(0x8E6CAC77, 0x68D7141E), /* ~= 10^141 */ U64(0xD1EF0244, 0xAF2364FF), U64(0x3207D795, 0x430CD926), /* ~= 10^142 */ U64(0x8335616A, 0xED761F1F), U64(0x7F44E6BD, 0x49E807B8), /* ~= 10^143 */ U64(0xA402B9C5, 0xA8D3A6E7), U64(0x5F16206C, 0x9C6209A6), /* ~= 10^144 */ U64(0xCD036837, 0x130890A1), U64(0x36DBA887, 0xC37A8C0F), /* ~= 10^145 */ U64(0x80222122, 0x6BE55A64), U64(0xC2494954, 0xDA2C9789), /* ~= 10^146 */ U64(0xA02AA96B, 0x06DEB0FD), U64(0xF2DB9BAA, 0x10B7BD6C), /* ~= 10^147 */ U64(0xC83553C5, 0xC8965D3D), U64(0x6F928294, 0x94E5ACC7), /* ~= 10^148 */ U64(0xFA42A8B7, 0x3ABBF48C), U64(0xCB772339, 0xBA1F17F9), /* ~= 10^149 */ U64(0x9C69A972, 0x84B578D7), U64(0xFF2A7604, 0x14536EFB), /* ~= 10^150 */ U64(0xC38413CF, 0x25E2D70D), U64(0xFEF51385, 0x19684ABA), /* ~= 10^151 */ U64(0xF46518C2, 0xEF5B8CD1), U64(0x7EB25866, 0x5FC25D69), /* ~= 10^152 */ U64(0x98BF2F79, 0xD5993802), U64(0xEF2F773F, 0xFBD97A61), /* ~= 10^153 */ U64(0xBEEEFB58, 0x4AFF8603), U64(0xAAFB550F, 0xFACFD8FA), /* ~= 10^154 */ U64(0xEEAABA2E, 0x5DBF6784), U64(0x95BA2A53, 0xF983CF38), /* ~= 10^155 */ U64(0x952AB45C, 0xFA97A0B2), U64(0xDD945A74, 0x7BF26183), /* ~= 10^156 */ U64(0xBA756174, 0x393D88DF), U64(0x94F97111, 0x9AEEF9E4), /* ~= 10^157 */ U64(0xE912B9D1, 0x478CEB17), U64(0x7A37CD56, 0x01AAB85D), /* ~= 10^158 */ U64(0x91ABB422, 0xCCB812EE), U64(0xAC62E055, 0xC10AB33A), /* ~= 10^159 */ U64(0xB616A12B, 0x7FE617AA), U64(0x577B986B, 0x314D6009), /* ~= 10^160 */ U64(0xE39C4976, 0x5FDF9D94), U64(0xED5A7E85, 0xFDA0B80B), /* ~= 10^161 */ U64(0x8E41ADE9, 0xFBEBC27D), U64(0x14588F13, 0xBE847307), /* ~= 10^162 */ U64(0xB1D21964, 0x7AE6B31C), U64(0x596EB2D8, 0xAE258FC8), /* ~= 10^163 */ U64(0xDE469FBD, 0x99A05FE3), U64(0x6FCA5F8E, 0xD9AEF3BB), /* ~= 10^164 */ U64(0x8AEC23D6, 0x80043BEE), U64(0x25DE7BB9, 0x480D5854), /* ~= 10^165 */ U64(0xADA72CCC, 0x20054AE9), U64(0xAF561AA7, 0x9A10AE6A), /* ~= 10^166 */ U64(0xD910F7FF, 0x28069DA4), U64(0x1B2BA151, 0x8094DA04), /* ~= 10^167 */ U64(0x87AA9AFF, 0x79042286), U64(0x90FB44D2, 0xF05D0842), /* ~= 10^168 */ U64(0xA99541BF, 0x57452B28), U64(0x353A1607, 0xAC744A53), /* ~= 10^169 */ U64(0xD3FA922F, 0x2D1675F2), U64(0x42889B89, 0x97915CE8), /* ~= 10^170 */ U64(0x847C9B5D, 0x7C2E09B7), U64(0x69956135, 0xFEBADA11), /* ~= 10^171 */ U64(0xA59BC234, 0xDB398C25), U64(0x43FAB983, 0x7E699095), /* ~= 10^172 */ U64(0xCF02B2C2, 0x1207EF2E), U64(0x94F967E4, 0x5E03F4BB), /* ~= 10^173 */ U64(0x8161AFB9, 0x4B44F57D), U64(0x1D1BE0EE, 0xBAC278F5), /* ~= 10^174 */ U64(0xA1BA1BA7, 0x9E1632DC), U64(0x6462D92A, 0x69731732), /* ~= 10^175 */ U64(0xCA28A291, 0x859BBF93), U64(0x7D7B8F75, 0x03CFDCFE), /* ~= 10^176 */ U64(0xFCB2CB35, 0xE702AF78), U64(0x5CDA7352, 0x44C3D43E), /* ~= 10^177 */ U64(0x9DEFBF01, 0xB061ADAB), U64(0x3A088813, 0x6AFA64A7), /* ~= 10^178 */ U64(0xC56BAEC2, 0x1C7A1916), U64(0x088AAA18, 0x45B8FDD0), /* ~= 10^179 */ U64(0xF6C69A72, 0xA3989F5B), U64(0x8AAD549E, 0x57273D45), /* ~= 10^180 */ U64(0x9A3C2087, 0xA63F6399), U64(0x36AC54E2, 0xF678864B), /* ~= 10^181 */ U64(0xC0CB28A9, 0x8FCF3C7F), U64(0x84576A1B, 0xB416A7DD), /* ~= 10^182 */ U64(0xF0FDF2D3, 0xF3C30B9F), U64(0x656D44A2, 0xA11C51D5), /* ~= 10^183 */ U64(0x969EB7C4, 0x7859E743), U64(0x9F644AE5, 0xA4B1B325), /* ~= 10^184 */ U64(0xBC4665B5, 0x96706114), U64(0x873D5D9F, 0x0DDE1FEE), /* ~= 10^185 */ U64(0xEB57FF22, 0xFC0C7959), U64(0xA90CB506, 0xD155A7EA), /* ~= 10^186 */ U64(0x9316FF75, 0xDD87CBD8), U64(0x09A7F124, 0x42D588F2), /* ~= 10^187 */ U64(0xB7DCBF53, 0x54E9BECE), U64(0x0C11ED6D, 0x538AEB2F), /* ~= 10^188 */ U64(0xE5D3EF28, 0x2A242E81), U64(0x8F1668C8, 0xA86DA5FA), /* ~= 10^189 */ U64(0x8FA47579, 0x1A569D10), U64(0xF96E017D, 0x694487BC), /* ~= 10^190 */ U64(0xB38D92D7, 0x60EC4455), U64(0x37C981DC, 0xC395A9AC), /* ~= 10^191 */ U64(0xE070F78D, 0x3927556A), U64(0x85BBE253, 0xF47B1417), /* ~= 10^192 */ U64(0x8C469AB8, 0x43B89562), U64(0x93956D74, 0x78CCEC8E), /* ~= 10^193 */ U64(0xAF584166, 0x54A6BABB), U64(0x387AC8D1, 0x970027B2), /* ~= 10^194 */ U64(0xDB2E51BF, 0xE9D0696A), U64(0x06997B05, 0xFCC0319E), /* ~= 10^195 */ U64(0x88FCF317, 0xF22241E2), U64(0x441FECE3, 0xBDF81F03), /* ~= 10^196 */ U64(0xAB3C2FDD, 0xEEAAD25A), U64(0xD527E81C, 0xAD7626C3), /* ~= 10^197 */ U64(0xD60B3BD5, 0x6A5586F1), U64(0x8A71E223, 0xD8D3B074), /* ~= 10^198 */ U64(0x85C70565, 0x62757456), U64(0xF6872D56, 0x67844E49), /* ~= 10^199 */ U64(0xA738C6BE, 0xBB12D16C), U64(0xB428F8AC, 0x016561DB), /* ~= 10^200 */ U64(0xD106F86E, 0x69D785C7), U64(0xE13336D7, 0x01BEBA52), /* ~= 10^201 */ U64(0x82A45B45, 0x0226B39C), U64(0xECC00246, 0x61173473), /* ~= 10^202 */ U64(0xA34D7216, 0x42B06084), U64(0x27F002D7, 0xF95D0190), /* ~= 10^203 */ U64(0xCC20CE9B, 0xD35C78A5), U64(0x31EC038D, 0xF7B441F4), /* ~= 10^204 */ U64(0xFF290242, 0xC83396CE), U64(0x7E670471, 0x75A15271), /* ~= 10^205 */ U64(0x9F79A169, 0xBD203E41), U64(0x0F0062C6, 0xE984D386), /* ~= 10^206 */ U64(0xC75809C4, 0x2C684DD1), U64(0x52C07B78, 0xA3E60868), /* ~= 10^207 */ U64(0xF92E0C35, 0x37826145), U64(0xA7709A56, 0xCCDF8A82), /* ~= 10^208 */ U64(0x9BBCC7A1, 0x42B17CCB), U64(0x88A66076, 0x400BB691), /* ~= 10^209 */ U64(0xC2ABF989, 0x935DDBFE), U64(0x6ACFF893, 0xD00EA435), /* ~= 10^210 */ U64(0xF356F7EB, 0xF83552FE), U64(0x0583F6B8, 0xC4124D43), /* ~= 10^211 */ U64(0x98165AF3, 0x7B2153DE), U64(0xC3727A33, 0x7A8B704A), /* ~= 10^212 */ U64(0xBE1BF1B0, 0x59E9A8D6), U64(0x744F18C0, 0x592E4C5C), /* ~= 10^213 */ U64(0xEDA2EE1C, 0x7064130C), U64(0x1162DEF0, 0x6F79DF73), /* ~= 10^214 */ U64(0x9485D4D1, 0xC63E8BE7), U64(0x8ADDCB56, 0x45AC2BA8), /* ~= 10^215 */ U64(0xB9A74A06, 0x37CE2EE1), U64(0x6D953E2B, 0xD7173692), /* ~= 10^216 */ U64(0xE8111C87, 0xC5C1BA99), U64(0xC8FA8DB6, 0xCCDD0437), /* ~= 10^217 */ U64(0x910AB1D4, 0xDB9914A0), U64(0x1D9C9892, 0x400A22A2), /* ~= 10^218 */ U64(0xB54D5E4A, 0x127F59C8), U64(0x2503BEB6, 0xD00CAB4B), /* ~= 10^219 */ U64(0xE2A0B5DC, 0x971F303A), U64(0x2E44AE64, 0x840FD61D), /* ~= 10^220 */ U64(0x8DA471A9, 0xDE737E24), U64(0x5CEAECFE, 0xD289E5D2), /* ~= 10^221 */ U64(0xB10D8E14, 0x56105DAD), U64(0x7425A83E, 0x872C5F47), /* ~= 10^222 */ U64(0xDD50F199, 0x6B947518), U64(0xD12F124E, 0x28F77719), /* ~= 10^223 */ U64(0x8A5296FF, 0xE33CC92F), U64(0x82BD6B70, 0xD99AAA6F), /* ~= 10^224 */ U64(0xACE73CBF, 0xDC0BFB7B), U64(0x636CC64D, 0x1001550B), /* ~= 10^225 */ U64(0xD8210BEF, 0xD30EFA5A), U64(0x3C47F7E0, 0x5401AA4E), /* ~= 10^226 */ U64(0x8714A775, 0xE3E95C78), U64(0x65ACFAEC, 0x34810A71), /* ~= 10^227 */ U64(0xA8D9D153, 0x5CE3B396), U64(0x7F1839A7, 0x41A14D0D), /* ~= 10^228 */ U64(0xD31045A8, 0x341CA07C), U64(0x1EDE4811, 0x1209A050), /* ~= 10^229 */ U64(0x83EA2B89, 0x2091E44D), U64(0x934AED0A, 0xAB460432), /* ~= 10^230 */ U64(0xA4E4B66B, 0x68B65D60), U64(0xF81DA84D, 0x5617853F), /* ~= 10^231 */ U64(0xCE1DE406, 0x42E3F4B9), U64(0x36251260, 0xAB9D668E), /* ~= 10^232 */ U64(0x80D2AE83, 0xE9CE78F3), U64(0xC1D72B7C, 0x6B426019), /* ~= 10^233 */ U64(0xA1075A24, 0xE4421730), U64(0xB24CF65B, 0x8612F81F), /* ~= 10^234 */ U64(0xC94930AE, 0x1D529CFC), U64(0xDEE033F2, 0x6797B627), /* ~= 10^235 */ U64(0xFB9B7CD9, 0xA4A7443C), U64(0x169840EF, 0x017DA3B1), /* ~= 10^236 */ U64(0x9D412E08, 0x06E88AA5), U64(0x8E1F2895, 0x60EE864E), /* ~= 10^237 */ U64(0xC491798A, 0x08A2AD4E), U64(0xF1A6F2BA, 0xB92A27E2), /* ~= 10^238 */ U64(0xF5B5D7EC, 0x8ACB58A2), U64(0xAE10AF69, 0x6774B1DB), /* ~= 10^239 */ U64(0x9991A6F3, 0xD6BF1765), U64(0xACCA6DA1, 0xE0A8EF29), /* ~= 10^240 */ U64(0xBFF610B0, 0xCC6EDD3F), U64(0x17FD090A, 0x58D32AF3), /* ~= 10^241 */ U64(0xEFF394DC, 0xFF8A948E), U64(0xDDFC4B4C, 0xEF07F5B0), /* ~= 10^242 */ U64(0x95F83D0A, 0x1FB69CD9), U64(0x4ABDAF10, 0x1564F98E), /* ~= 10^243 */ U64(0xBB764C4C, 0xA7A4440F), U64(0x9D6D1AD4, 0x1ABE37F1), /* ~= 10^244 */ U64(0xEA53DF5F, 0xD18D5513), U64(0x84C86189, 0x216DC5ED), /* ~= 10^245 */ U64(0x92746B9B, 0xE2F8552C), U64(0x32FD3CF5, 0xB4E49BB4), /* ~= 10^246 */ U64(0xB7118682, 0xDBB66A77), U64(0x3FBC8C33, 0x221DC2A1), /* ~= 10^247 */ U64(0xE4D5E823, 0x92A40515), U64(0x0FABAF3F, 0xEAA5334A), /* ~= 10^248 */ U64(0x8F05B116, 0x3BA6832D), U64(0x29CB4D87, 0xF2A7400E), /* ~= 10^249 */ U64(0xB2C71D5B, 0xCA9023F8), U64(0x743E20E9, 0xEF511012), /* ~= 10^250 */ U64(0xDF78E4B2, 0xBD342CF6), U64(0x914DA924, 0x6B255416), /* ~= 10^251 */ U64(0x8BAB8EEF, 0xB6409C1A), U64(0x1AD089B6, 0xC2F7548E), /* ~= 10^252 */ U64(0xAE9672AB, 0xA3D0C320), U64(0xA184AC24, 0x73B529B1), /* ~= 10^253 */ U64(0xDA3C0F56, 0x8CC4F3E8), U64(0xC9E5D72D, 0x90A2741E), /* ~= 10^254 */ U64(0x88658996, 0x17FB1871), U64(0x7E2FA67C, 0x7A658892), /* ~= 10^255 */ U64(0xAA7EEBFB, 0x9DF9DE8D), U64(0xDDBB901B, 0x98FEEAB7), /* ~= 10^256 */ U64(0xD51EA6FA, 0x85785631), U64(0x552A7422, 0x7F3EA565), /* ~= 10^257 */ U64(0x8533285C, 0x936B35DE), U64(0xD53A8895, 0x8F87275F), /* ~= 10^258 */ U64(0xA67FF273, 0xB8460356), U64(0x8A892ABA, 0xF368F137), /* ~= 10^259 */ U64(0xD01FEF10, 0xA657842C), U64(0x2D2B7569, 0xB0432D85), /* ~= 10^260 */ U64(0x8213F56A, 0x67F6B29B), U64(0x9C3B2962, 0x0E29FC73), /* ~= 10^261 */ U64(0xA298F2C5, 0x01F45F42), U64(0x8349F3BA, 0x91B47B8F), /* ~= 10^262 */ U64(0xCB3F2F76, 0x42717713), U64(0x241C70A9, 0x36219A73), /* ~= 10^263 */ U64(0xFE0EFB53, 0xD30DD4D7), U64(0xED238CD3, 0x83AA0110), /* ~= 10^264 */ U64(0x9EC95D14, 0x63E8A506), U64(0xF4363804, 0x324A40AA), /* ~= 10^265 */ U64(0xC67BB459, 0x7CE2CE48), U64(0xB143C605, 0x3EDCD0D5), /* ~= 10^266 */ U64(0xF81AA16F, 0xDC1B81DA), U64(0xDD94B786, 0x8E94050A), /* ~= 10^267 */ U64(0x9B10A4E5, 0xE9913128), U64(0xCA7CF2B4, 0x191C8326), /* ~= 10^268 */ U64(0xC1D4CE1F, 0x63F57D72), U64(0xFD1C2F61, 0x1F63A3F0), /* ~= 10^269 */ U64(0xF24A01A7, 0x3CF2DCCF), U64(0xBC633B39, 0x673C8CEC), /* ~= 10^270 */ U64(0x976E4108, 0x8617CA01), U64(0xD5BE0503, 0xE085D813), /* ~= 10^271 */ U64(0xBD49D14A, 0xA79DBC82), U64(0x4B2D8644, 0xD8A74E18), /* ~= 10^272 */ U64(0xEC9C459D, 0x51852BA2), U64(0xDDF8E7D6, 0x0ED1219E), /* ~= 10^273 */ U64(0x93E1AB82, 0x52F33B45), U64(0xCABB90E5, 0xC942B503), /* ~= 10^274 */ U64(0xB8DA1662, 0xE7B00A17), U64(0x3D6A751F, 0x3B936243), /* ~= 10^275 */ U64(0xE7109BFB, 0xA19C0C9D), U64(0x0CC51267, 0x0A783AD4), /* ~= 10^276 */ U64(0x906A617D, 0x450187E2), U64(0x27FB2B80, 0x668B24C5), /* ~= 10^277 */ U64(0xB484F9DC, 0x9641E9DA), U64(0xB1F9F660, 0x802DEDF6), /* ~= 10^278 */ U64(0xE1A63853, 0xBBD26451), U64(0x5E7873F8, 0xA0396973), /* ~= 10^279 */ U64(0x8D07E334, 0x55637EB2), U64(0xDB0B487B, 0x6423E1E8), /* ~= 10^280 */ U64(0xB049DC01, 0x6ABC5E5F), U64(0x91CE1A9A, 0x3D2CDA62), /* ~= 10^281 */ U64(0xDC5C5301, 0xC56B75F7), U64(0x7641A140, 0xCC7810FB), /* ~= 10^282 */ U64(0x89B9B3E1, 0x1B6329BA), U64(0xA9E904C8, 0x7FCB0A9D), /* ~= 10^283 */ U64(0xAC2820D9, 0x623BF429), U64(0x546345FA, 0x9FBDCD44), /* ~= 10^284 */ U64(0xD732290F, 0xBACAF133), U64(0xA97C1779, 0x47AD4095), /* ~= 10^285 */ U64(0x867F59A9, 0xD4BED6C0), U64(0x49ED8EAB, 0xCCCC485D), /* ~= 10^286 */ U64(0xA81F3014, 0x49EE8C70), U64(0x5C68F256, 0xBFFF5A74), /* ~= 10^287 */ U64(0xD226FC19, 0x5C6A2F8C), U64(0x73832EEC, 0x6FFF3111), /* ~= 10^288 */ U64(0x83585D8F, 0xD9C25DB7), U64(0xC831FD53, 0xC5FF7EAB), /* ~= 10^289 */ U64(0xA42E74F3, 0xD032F525), U64(0xBA3E7CA8, 0xB77F5E55), /* ~= 10^290 */ U64(0xCD3A1230, 0xC43FB26F), U64(0x28CE1BD2, 0xE55F35EB), /* ~= 10^291 */ U64(0x80444B5E, 0x7AA7CF85), U64(0x7980D163, 0xCF5B81B3), /* ~= 10^292 */ U64(0xA0555E36, 0x1951C366), U64(0xD7E105BC, 0xC332621F), /* ~= 10^293 */ U64(0xC86AB5C3, 0x9FA63440), U64(0x8DD9472B, 0xF3FEFAA7), /* ~= 10^294 */ U64(0xFA856334, 0x878FC150), U64(0xB14F98F6, 0xF0FEB951), /* ~= 10^295 */ U64(0x9C935E00, 0xD4B9D8D2), U64(0x6ED1BF9A, 0x569F33D3), /* ~= 10^296 */ U64(0xC3B83581, 0x09E84F07), U64(0x0A862F80, 0xEC4700C8), /* ~= 10^297 */ U64(0xF4A642E1, 0x4C6262C8), U64(0xCD27BB61, 0x2758C0FA), /* ~= 10^298 */ U64(0x98E7E9CC, 0xCFBD7DBD), U64(0x8038D51C, 0xB897789C), /* ~= 10^299 */ U64(0xBF21E440, 0x03ACDD2C), U64(0xE0470A63, 0xE6BD56C3), /* ~= 10^300 */ U64(0xEEEA5D50, 0x04981478), U64(0x1858CCFC, 0xE06CAC74), /* ~= 10^301 */ U64(0x95527A52, 0x02DF0CCB), U64(0x0F37801E, 0x0C43EBC8), /* ~= 10^302 */ U64(0xBAA718E6, 0x8396CFFD), U64(0xD3056025, 0x8F54E6BA), /* ~= 10^303 */ U64(0xE950DF20, 0x247C83FD), U64(0x47C6B82E, 0xF32A2069), /* ~= 10^304 */ U64(0x91D28B74, 0x16CDD27E), U64(0x4CDC331D, 0x57FA5441), /* ~= 10^305 */ U64(0xB6472E51, 0x1C81471D), U64(0xE0133FE4, 0xADF8E952), /* ~= 10^306 */ U64(0xE3D8F9E5, 0x63A198E5), U64(0x58180FDD, 0xD97723A6), /* ~= 10^307 */ U64(0x8E679C2F, 0x5E44FF8F), U64(0x570F09EA, 0xA7EA7648), /* ~= 10^308 */ U64(0xB201833B, 0x35D63F73), U64(0x2CD2CC65, 0x51E513DA), /* ~= 10^309 */ U64(0xDE81E40A, 0x034BCF4F), U64(0xF8077F7E, 0xA65E58D1), /* ~= 10^310 */ U64(0x8B112E86, 0x420F6191), U64(0xFB04AFAF, 0x27FAF782), /* ~= 10^311 */ U64(0xADD57A27, 0xD29339F6), U64(0x79C5DB9A, 0xF1F9B563), /* ~= 10^312 */ U64(0xD94AD8B1, 0xC7380874), U64(0x18375281, 0xAE7822BC), /* ~= 10^313 */ U64(0x87CEC76F, 0x1C830548), U64(0x8F229391, 0x0D0B15B5), /* ~= 10^314 */ U64(0xA9C2794A, 0xE3A3C69A), U64(0xB2EB3875, 0x504DDB22), /* ~= 10^315 */ U64(0xD433179D, 0x9C8CB841), U64(0x5FA60692, 0xA46151EB), /* ~= 10^316 */ U64(0x849FEEC2, 0x81D7F328), U64(0xDBC7C41B, 0xA6BCD333), /* ~= 10^317 */ U64(0xA5C7EA73, 0x224DEFF3), U64(0x12B9B522, 0x906C0800), /* ~= 10^318 */ U64(0xCF39E50F, 0xEAE16BEF), U64(0xD768226B, 0x34870A00), /* ~= 10^319 */ U64(0x81842F29, 0xF2CCE375), U64(0xE6A11583, 0x00D46640), /* ~= 10^320 */ U64(0xA1E53AF4, 0x6F801C53), U64(0x60495AE3, 0xC1097FD0), /* ~= 10^321 */ U64(0xCA5E89B1, 0x8B602368), U64(0x385BB19C, 0xB14BDFC4), /* ~= 10^322 */ U64(0xFCF62C1D, 0xEE382C42), U64(0x46729E03, 0xDD9ED7B5), /* ~= 10^323 */ U64(0x9E19DB92, 0xB4E31BA9), U64(0x6C07A2C2, 0x6A8346D1) /* ~= 10^324 */ }; /** Get the cached pow10 value from pow10_sig_table. @param exp10 The exponent of pow(10, e). This value must in range POW10_SIG_TABLE_MIN_EXP to POW10_SIG_TABLE_MAX_EXP. @param hi The highest 64 bits of pow(10, e). @param lo The lower 64 bits after `hi`. */ static_inline void pow10_table_get_sig(i32 exp10, u64 *hi, u64 *lo) { i32 idx = exp10 - (POW10_SIG_TABLE_MIN_EXP); *hi = pow10_sig_table[idx * 2]; *lo = pow10_sig_table[idx * 2 + 1]; } /** Get the exponent (base 2) for highest 64 bits significand in pow10_sig_table. */ static_inline void pow10_table_get_exp(i32 exp10, i32 *exp2) { /* e2 = floor(log2(pow(10, e))) - 64 + 1 */ /* = floor(e * log2(10) - 63) */ *exp2 = (exp10 * 217706 - 4128768) >> 16; } #endif #if !YYJSON_DISABLE_READER /*============================================================================== * JSON Character Matcher *============================================================================*/ /** Character type */ typedef u8 char_type; /** Whitespace character: ' ', '\\t', '\\n', '\\r'. */ static const char_type CHAR_TYPE_SPACE = 1 << 0; /** Number character: '-', [0-9]. */ static const char_type CHAR_TYPE_NUMBER = 1 << 1; /** JSON Escaped character: '"', '\', [0x00-0x1F]. */ static const char_type CHAR_TYPE_ESC_ASCII = 1 << 2; /** Non-ASCII character: [0x80-0xFF]. */ static const char_type CHAR_TYPE_NON_ASCII = 1 << 3; /** JSON container character: '{', '['. */ static const char_type CHAR_TYPE_CONTAINER = 1 << 4; /** Comment character: '/'. */ static const char_type CHAR_TYPE_COMMENT = 1 << 5; /** Line end character: '\\n', '\\r', '\0'. */ static const char_type CHAR_TYPE_LINE_END = 1 << 6; /** Hexadecimal numeric character: [0-9a-fA-F]. */ static const char_type CHAR_TYPE_HEX = 1 << 7; /** Character type table (generate with misc/make_tables.c) */ static const char_type char_table[256] = { 0x44, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x45, 0x04, 0x04, 0x45, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }; /** Match a character with specified type. */ static_inline bool char_is_type(u8 c, char_type type) { return (char_table[c] & type) != 0; } /** Match a whitespace: ' ', '\\t', '\\n', '\\r'. */ static_inline bool char_is_space(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_SPACE); } /** Match a whitespace or comment: ' ', '\\t', '\\n', '\\r', '/'. */ static_inline bool char_is_space_or_comment(u8 c) { return char_is_type(c, (char_type)(CHAR_TYPE_SPACE | CHAR_TYPE_COMMENT)); } /** Match a JSON number: '-', [0-9]. */ static_inline bool char_is_number(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_NUMBER); } /** Match a JSON container: '{', '['. */ static_inline bool char_is_container(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_CONTAINER); } /** Match a stop character in ASCII string: '"', '\', [0x00-0x1F,0x80-0xFF]. */ static_inline bool char_is_ascii_stop(u8 c) { return char_is_type(c, (char_type)(CHAR_TYPE_ESC_ASCII | CHAR_TYPE_NON_ASCII)); } /** Match a line end character: '\\n', '\\r', '\0'. */ static_inline bool char_is_line_end(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_LINE_END); } /** Match a hexadecimal numeric character: [0-9a-fA-F]. */ static_inline bool char_is_hex(u8 c) { return char_is_type(c, (char_type)CHAR_TYPE_HEX); } /*============================================================================== * Digit Character Matcher *============================================================================*/ /** Digit type */ typedef u8 digi_type; /** Digit: '0'. */ static const digi_type DIGI_TYPE_ZERO = 1 << 0; /** Digit: [1-9]. */ static const digi_type DIGI_TYPE_NONZERO = 1 << 1; /** Plus sign (positive): '+'. */ static const digi_type DIGI_TYPE_POS = 1 << 2; /** Minus sign (negative): '-'. */ static const digi_type DIGI_TYPE_NEG = 1 << 3; /** Decimal point: '.' */ static const digi_type DIGI_TYPE_DOT = 1 << 4; /** Exponent sign: 'e, 'E'. */ static const digi_type DIGI_TYPE_EXP = 1 << 5; /** Digit type table (generate with misc/make_tables.c) */ static const digi_type digi_table[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x10, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /** Match a character with specified type. */ static_inline bool digi_is_type(u8 d, digi_type type) { return (digi_table[d] & type) != 0; } /** Match a sign: '+', '-' */ static_inline bool digi_is_sign(u8 d) { return digi_is_type(d, (digi_type)(DIGI_TYPE_POS | DIGI_TYPE_NEG)); } /** Match a none zero digit: [1-9] */ static_inline bool digi_is_nonzero(u8 d) { return digi_is_type(d, (digi_type)DIGI_TYPE_NONZERO); } /** Match a digit: [0-9] */ static_inline bool digi_is_digit(u8 d) { return digi_is_type(d, (digi_type)(DIGI_TYPE_ZERO | DIGI_TYPE_NONZERO)); } /** Match an exponent sign: 'e', 'E'. */ static_inline bool digi_is_exp(u8 d) { return digi_is_type(d, (digi_type)DIGI_TYPE_EXP); } /** Match a floating point indicator: '.', 'e', 'E'. */ static_inline bool digi_is_fp(u8 d) { return digi_is_type(d, (digi_type)(DIGI_TYPE_DOT | DIGI_TYPE_EXP)); } /** Match a digit or floating point indicator: [0-9], '.', 'e', 'E'. */ static_inline bool digi_is_digit_or_fp(u8 d) { return digi_is_type(d, (digi_type)(DIGI_TYPE_ZERO | DIGI_TYPE_NONZERO | DIGI_TYPE_DOT | DIGI_TYPE_EXP)); } /*============================================================================== * Hex Character Reader * This function is used by JSON reader to read escaped characters. *============================================================================*/ /** This table is used to convert 4 hex character sequence to a number. A valid hex character [0-9A-Fa-f] will mapped to it's raw number [0x00, 0x0F], an invalid hex character will mapped to [0xF0]. (generate with misc/make_tables.c) */ static const u8 hex_conv_table[256] = { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0 }; /** Scans an escaped character sequence as a UTF-16 code unit (branchless). e.g. "\\u005C" should pass "005C" as `cur`. This requires the string has 4-byte zero padding. */ static_inline bool read_hex_u16(const u8 *cur, u16 *val) { u16 c0, c1, c2, c3, t0, t1; c0 = hex_conv_table[cur[0]]; c1 = hex_conv_table[cur[1]]; c2 = hex_conv_table[cur[2]]; c3 = hex_conv_table[cur[3]]; t0 = (u16)((c0 << 8) | c2); t1 = (u16)((c1 << 8) | c3); *val = (u16)((t0 << 4) | t1); return ((t0 | t1) & (u16)0xF0F0) == 0; } /*============================================================================== * JSON Reader Utils * These functions are used by JSON reader to read literals and comments. *============================================================================*/ /** Read 'true' literal, '*cur' should be 't'. */ static_inline bool read_true(u8 **ptr, yyjson_val *val) { u8 *cur = *ptr; u8 **end = ptr; if (likely(byte_match_4(cur, "true"))) { val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; *end = cur + 4; return true; } return false; } /** Read 'false' literal, '*cur' should be 'f'. */ static_inline bool read_false(u8 **ptr, yyjson_val *val) { u8 *cur = *ptr; u8 **end = ptr; if (likely(byte_match_4(cur + 1, "alse"))) { val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; *end = cur + 5; return true; } return false; } /** Read 'null' literal, '*cur' should be 'n'. */ static_inline bool read_null(u8 **ptr, yyjson_val *val) { u8 *cur = *ptr; u8 **end = ptr; if (likely(byte_match_4(cur, "null"))) { val->tag = YYJSON_TYPE_NULL; *end = cur + 4; return true; } return false; } /** Read 'Inf' or 'Infinity' literal (ignoring case). */ static_inline bool read_inf(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { #if !YYJSON_DISABLE_NON_STANDARD u8 *hdr = *ptr - sign; u8 *cur = *ptr; u8 **end = ptr; if ((cur[0] == 'I' || cur[0] == 'i') && (cur[1] == 'N' || cur[1] == 'n') && (cur[2] == 'F' || cur[2] == 'f')) { if ((cur[3] == 'I' || cur[3] == 'i') && (cur[4] == 'N' || cur[4] == 'n') && (cur[5] == 'I' || cur[5] == 'i') && (cur[6] == 'T' || cur[6] == 't') && (cur[7] == 'Y' || cur[7] == 'y')) { cur += 8; } else { cur += 3; } *end = cur; if (pre) { /* add null-terminator for previous raw string */ if (*pre) **pre = '\0'; *pre = cur; val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; val->uni.str = (const char *)hdr; } else { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.u64 = f64_raw_get_inf(sign); } return true; } #endif return false; } /** Read 'NaN' literal (ignoring case). */ static_inline bool read_nan(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { #if !YYJSON_DISABLE_NON_STANDARD u8 *hdr = *ptr - sign; u8 *cur = *ptr; u8 **end = ptr; if ((cur[0] == 'N' || cur[0] == 'n') && (cur[1] == 'A' || cur[1] == 'a') && (cur[2] == 'N' || cur[2] == 'n')) { cur += 3; *end = cur; if (pre) { /* add null-terminator for previous raw string */ if (*pre) **pre = '\0'; *pre = cur; val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; val->uni.str = (const char *)hdr; } else { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.u64 = f64_raw_get_nan(sign); } return true; } #endif return false; } /** Read 'Inf', 'Infinity' or 'NaN' literal (ignoring case). */ static_inline bool read_inf_or_nan(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) { if (read_inf(sign, ptr, pre, val)) return true; if (read_nan(sign, ptr, pre, val)) return true; return false; } /** Read a JSON number as raw string. */ static_noinline bool read_number_raw(u8 **ptr, u8 **pre, yyjson_read_flag flg, yyjson_val *val, const char **msg) { #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) #define return_raw() do { \ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ val->uni.str = (const char *)hdr; \ *pre = cur; *end = cur; return true; \ } while (false) u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; /* add null-terminator for previous raw string */ if (*pre) **pre = '\0'; /* skip sign */ cur += (*cur == '-'); /* read first digit, check leading zero */ if (unlikely(!digi_is_digit(*cur))) { if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) { if (read_inf_or_nan(*hdr == '-', &cur, pre, val)) return_raw(); } return_err(cur, "no digit after minus sign"); } /* read integral part */ if (*cur == '0') { cur++; if (unlikely(digi_is_digit(*cur))) { return_err(cur - 1, "number with leading zero is not allowed"); } if (!digi_is_fp(*cur)) return_raw(); } else { while (digi_is_digit(*cur)) cur++; if (!digi_is_fp(*cur)) return_raw(); } /* read fraction part */ if (*cur == '.') { cur++; if (!digi_is_digit(*cur++)) { return_err(cur, "no digit after decimal point"); } while (digi_is_digit(*cur)) cur++; } /* read exponent part */ if (digi_is_exp(*cur)) { cur += 1 + digi_is_sign(cur[1]); if (!digi_is_digit(*cur++)) { return_err(cur, "no digit after exponent sign"); } while (digi_is_digit(*cur)) cur++; } return_raw(); #undef return_err #undef return_raw } /** Skips spaces and comments as many as possible. It will return false in these cases: 1. No character is skipped. The 'end' pointer is set as input cursor. 2. A multiline comment is not closed. The 'end' pointer is set as the head of this comment block. */ static_noinline bool skip_spaces_and_comments(u8 **ptr) { u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; while (true) { if (byte_match_2(cur, "/*")) { hdr = cur; cur += 2; while (true) { if (byte_match_2(cur, "*/")) { cur += 2; break; } if (*cur == 0) { *end = hdr; return false; } cur++; } continue; } if (byte_match_2(cur, "//")) { cur += 2; while (!char_is_line_end(*cur)) cur++; continue; } if (char_is_space(*cur)) { cur += 1; while (char_is_space(*cur)) cur++; continue; } break; } *end = cur; return hdr != cur; } /** Check truncated string. Returns true if `cur` match `str` but is truncated. */ static_inline bool is_truncated_str(u8 *cur, u8 *end, const char *str, bool case_sensitive) { usize len = strlen(str); if (cur + len <= end || end <= cur) return false; if (case_sensitive) { return memcmp(cur, str, (usize)(end - cur)) == 0; } for (; cur < end; cur++, str++) { if ((*cur != (u8)*str) && (*cur != (u8)*str - 'a' + 'A')) { return false; } } return true; } /** Check truncated JSON on parsing errors. Returns true if the input is valid but truncated. */ static_noinline bool is_truncated_end(u8 *hdr, u8 *cur, u8 *end, yyjson_read_code code, yyjson_read_flag flg) { if (cur >= end) return true; if (code == YYJSON_READ_ERROR_LITERAL) { if (is_truncated_str(cur, end, "true", true) || is_truncated_str(cur, end, "false", true) || is_truncated_str(cur, end, "null", true)) { return true; } } if (code == YYJSON_READ_ERROR_UNEXPECTED_CHARACTER || code == YYJSON_READ_ERROR_INVALID_NUMBER || code == YYJSON_READ_ERROR_LITERAL) { if ((flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (*cur == '-') cur++; if (is_truncated_str(cur, end, "infinity", false) || is_truncated_str(cur, end, "nan", false)) { return true; } } } if (code == YYJSON_READ_ERROR_UNEXPECTED_CONTENT) { if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) { if (hdr + 3 <= cur && is_truncated_str(cur - 3, end, "infinity", false)) { return true; /* e.g. infin would be read as inf + in */ } } } if (code == YYJSON_READ_ERROR_INVALID_STRING) { usize len = (usize)(end - cur); /* unicode escape sequence */ if (*cur == '\\') { if (len == 1) return true; if (len <= 5) { if (*++cur != 'u') return false; for (++cur; cur < end; cur++) { if (!char_is_hex(*cur)) return false; } return true; } return false; } /* 2 to 4 bytes UTF-8, see `read_string()` for details. */ if (*cur & 0x80) { u8 c0 = cur[0], c1 = cur[1], c2 = cur[2]; if (len == 1) { /* 2 bytes UTF-8, truncated */ if ((c0 & 0xE0) == 0xC0 && (c0 & 0x1E) != 0x00) return true; /* 3 bytes UTF-8, truncated */ if ((c0 & 0xF0) == 0xE0) return true; /* 4 bytes UTF-8, truncated */ if ((c0 & 0xF8) == 0xF0 && (c0 & 0x07) <= 0x04) return true; } if (len == 2) { /* 3 bytes UTF-8, truncated */ if ((c0 & 0xF0) == 0xE0 && (c1 & 0xC0) == 0x80) { u8 pat = (u8)(((c0 & 0x0F) << 1) | ((c1 & 0x20) >> 5)); return 0x01 <= pat && pat != 0x1B; } /* 4 bytes UTF-8, truncated */ if ((c0 & 0xF8) == 0xF0 && (c1 & 0xC0) == 0x80) { u8 pat = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4)); return 0x01 <= pat && pat <= 0x10; } } if (len == 3) { /* 4 bytes UTF-8, truncated */ if ((c0 & 0xF8) == 0xF0 && (c1 & 0xC0) == 0x80 && (c2 & 0xC0) == 0x80) { u8 pat = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4)); return 0x01 <= pat && pat <= 0x10; } } } } return false; } #if YYJSON_HAS_IEEE_754 && !YYJSON_DISABLE_FAST_FP_CONV /* FP_READER */ /*============================================================================== * BigInt For Floating Point Number Reader * * The bigint algorithm is used by floating-point number reader to get correctly * rounded result for numbers with lots of digits. This part of code is rarely * used for common numbers. *============================================================================*/ /** Maximum exponent of exact pow10 */ #define U64_POW10_MAX_EXP 19 /** Table: [ 10^0, ..., 10^19 ] (generate with misc/make_tables.c) */ static const u64 u64_pow10_table[U64_POW10_MAX_EXP + 1] = { U64(0x00000000, 0x00000001), U64(0x00000000, 0x0000000A), U64(0x00000000, 0x00000064), U64(0x00000000, 0x000003E8), U64(0x00000000, 0x00002710), U64(0x00000000, 0x000186A0), U64(0x00000000, 0x000F4240), U64(0x00000000, 0x00989680), U64(0x00000000, 0x05F5E100), U64(0x00000000, 0x3B9ACA00), U64(0x00000002, 0x540BE400), U64(0x00000017, 0x4876E800), U64(0x000000E8, 0xD4A51000), U64(0x00000918, 0x4E72A000), U64(0x00005AF3, 0x107A4000), U64(0x00038D7E, 0xA4C68000), U64(0x002386F2, 0x6FC10000), U64(0x01634578, 0x5D8A0000), U64(0x0DE0B6B3, 0xA7640000), U64(0x8AC72304, 0x89E80000) }; /** Maximum numbers of chunks used by a bigint (58 is enough here). */ #define BIGINT_MAX_CHUNKS 64 /** Unsigned arbitrarily large integer */ typedef struct bigint { u32 used; /* used chunks count, should not be 0 */ u64 bits[BIGINT_MAX_CHUNKS]; /* chunks */ } bigint; /** Evaluate 'big += val'. @param big A big number (can be 0). @param val An unsigned integer (can be 0). */ static_inline void bigint_add_u64(bigint *big, u64 val) { u32 idx, max; u64 num = big->bits[0]; u64 add = num + val; big->bits[0] = add; if (likely((add >= num) || (add >= val))) return; for ((void)(idx = 1), max = big->used; idx < max; idx++) { if (likely(big->bits[idx] != U64_MAX)) { big->bits[idx] += 1; return; } big->bits[idx] = 0; } big->bits[big->used++] = 1; } /** Evaluate 'big *= val'. @param big A big number (can be 0). @param val An unsigned integer (cannot be 0). */ static_inline void bigint_mul_u64(bigint *big, u64 val) { u32 idx = 0, max = big->used; u64 hi, lo, carry = 0; for (; idx < max; idx++) { if (big->bits[idx]) break; } for (; idx < max; idx++) { u128_mul_add(big->bits[idx], val, carry, &hi, &lo); big->bits[idx] = lo; carry = hi; } if (carry) big->bits[big->used++] = carry; } /** Evaluate 'big *= 2^exp'. @param big A big number (can be 0). @param exp An exponent integer (can be 0). */ static_inline void bigint_mul_pow2(bigint *big, u32 exp) { u32 shft = exp % 64; u32 move = exp / 64; u32 idx = big->used; if (unlikely(shft == 0)) { for (; idx > 0; idx--) { big->bits[idx + move - 1] = big->bits[idx - 1]; } big->used += move; while (move) big->bits[--move] = 0; } else { big->bits[idx] = 0; for (; idx > 0; idx--) { u64 num = big->bits[idx] << shft; num |= big->bits[idx - 1] >> (64 - shft); big->bits[idx + move] = num; } big->bits[move] = big->bits[0] << shft; big->used += move + (big->bits[big->used + move] > 0); while (move) big->bits[--move] = 0; } } /** Evaluate 'big *= 10^exp'. @param big A big number (can be 0). @param exp An exponent integer (cannot be 0). */ static_inline void bigint_mul_pow10(bigint *big, i32 exp) { for (; exp >= U64_POW10_MAX_EXP; exp -= U64_POW10_MAX_EXP) { bigint_mul_u64(big, u64_pow10_table[U64_POW10_MAX_EXP]); } if (exp) { bigint_mul_u64(big, u64_pow10_table[exp]); } } /** Compare two bigint. @return -1 if 'a < b', +1 if 'a > b', 0 if 'a == b'. */ static_inline i32 bigint_cmp(bigint *a, bigint *b) { u32 idx = a->used; if (a->used < b->used) return -1; if (a->used > b->used) return +1; while (idx-- > 0) { u64 av = a->bits[idx]; u64 bv = b->bits[idx]; if (av < bv) return -1; if (av > bv) return +1; } return 0; } /** Evaluate 'big = val'. @param big A big number (can be 0). @param val An unsigned integer (can be 0). */ static_inline void bigint_set_u64(bigint *big, u64 val) { big->used = 1; big->bits[0] = val; } /** Set a bigint with floating point number string. */ static_noinline void bigint_set_buf(bigint *big, u64 sig, i32 *exp, u8 *sig_cut, u8 *sig_end, u8 *dot_pos) { if (unlikely(!sig_cut)) { /* no digit cut, set significant part only */ bigint_set_u64(big, sig); return; } else { /* some digits were cut, read them from 'sig_cut' to 'sig_end' */ u8 *hdr = sig_cut; u8 *cur = hdr; u32 len = 0; u64 val = 0; bool dig_big_cut = false; bool has_dot = (hdr < dot_pos) & (dot_pos < sig_end); u32 dig_len_total = U64_SAFE_DIG + (u32)(sig_end - hdr) - has_dot; sig -= (*sig_cut >= '5'); /* sig was rounded before */ if (dig_len_total > F64_MAX_DEC_DIG) { dig_big_cut = true; sig_end -= dig_len_total - (F64_MAX_DEC_DIG + 1); sig_end -= (dot_pos + 1 == sig_end); dig_len_total = (F64_MAX_DEC_DIG + 1); } *exp -= (i32)dig_len_total - U64_SAFE_DIG; big->used = 1; big->bits[0] = sig; while (cur < sig_end) { if (likely(cur != dot_pos)) { val = val * 10 + (u8)(*cur++ - '0'); len++; if (unlikely(cur == sig_end && dig_big_cut)) { /* The last digit must be non-zero, */ /* set it to '1' for correct rounding. */ val = val - (val % 10) + 1; } if (len == U64_SAFE_DIG || cur == sig_end) { bigint_mul_pow10(big, (i32)len); bigint_add_u64(big, val); val = 0; len = 0; } } else { cur++; } } } } /*============================================================================== * Diy Floating Point *============================================================================*/ /** "Do It Yourself Floating Point" struct. */ typedef struct diy_fp { u64 sig; /* significand */ i32 exp; /* exponent, base 2 */ i32 pad; /* padding, useless */ } diy_fp; /** Get cached rounded diy_fp with pow(10, e) The input value must in range [POW10_SIG_TABLE_MIN_EXP, POW10_SIG_TABLE_MAX_EXP]. */ static_inline diy_fp diy_fp_get_cached_pow10(i32 exp10) { diy_fp fp; u64 sig_ext; pow10_table_get_sig(exp10, &fp.sig, &sig_ext); pow10_table_get_exp(exp10, &fp.exp); fp.sig += (sig_ext >> 63); return fp; } /** Returns fp * fp2. */ static_inline diy_fp diy_fp_mul(diy_fp fp, diy_fp fp2) { u64 hi, lo; u128_mul(fp.sig, fp2.sig, &hi, &lo); fp.sig = hi + (lo >> 63); fp.exp += fp2.exp + 64; return fp; } /** Convert diy_fp to IEEE-754 raw value. */ static_inline u64 diy_fp_to_ieee_raw(diy_fp fp) { u64 sig = fp.sig; i32 exp = fp.exp; u32 lz_bits; if (unlikely(fp.sig == 0)) return 0; lz_bits = u64_lz_bits(sig); sig <<= lz_bits; sig >>= F64_BITS - F64_SIG_FULL_BITS; exp -= (i32)lz_bits; exp += F64_BITS - F64_SIG_FULL_BITS; exp += F64_SIG_BITS; if (unlikely(exp >= F64_MAX_BIN_EXP)) { /* overflow */ return F64_RAW_INF; } else if (likely(exp >= F64_MIN_BIN_EXP - 1)) { /* normal */ exp += F64_EXP_BIAS; return ((u64)exp << F64_SIG_BITS) | (sig & F64_SIG_MASK); } else if (likely(exp >= F64_MIN_BIN_EXP - F64_SIG_FULL_BITS)) { /* subnormal */ return sig >> (F64_MIN_BIN_EXP - exp - 1); } else { /* underflow */ return 0; } } /*============================================================================== * JSON Number Reader (IEEE-754) *============================================================================*/ /** Maximum exact pow10 exponent for double value. */ #define F64_POW10_EXP_MAX_EXACT 22 /** Cached pow10 table. */ static const f64 f64_pow10_table[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 }; /** Read a JSON number. 1. This function assume that the floating-point number is in IEEE-754 format. 2. This function support uint64/int64/double number. If an integer number cannot fit in uint64/int64, it will returns as a double number. If a double number is infinite, the return value is based on flag. 3. This function (with inline attribute) may generate a lot of instructions. */ static_inline bool read_number(u8 **ptr, u8 **pre, yyjson_read_flag flg, yyjson_val *val, const char **msg) { #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) #define return_0() do { \ val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \ val->uni.u64 = 0; \ *end = cur; return true; \ } while (false) #define return_i64(_v) do { \ val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \ val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \ *end = cur; return true; \ } while (false) #define return_f64(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \ *end = cur; return true; \ } while (false) #define return_f64_bin(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \ *end = cur; return true; \ } while (false) #define return_inf() do { \ if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); \ if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) return_f64_bin(F64_RAW_INF); \ else return_err(hdr, "number is infinity when parsed as double"); \ } while (false) #define return_raw() do { \ if (*pre) **pre = '\0'; /* add null-terminator for previous raw string */ \ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ val->uni.str = (const char *)hdr; \ *pre = cur; *end = cur; return true; \ } while (false) u8 *sig_cut = NULL; /* significant part cutting position for long number */ u8 *sig_end = NULL; /* significant part ending position */ u8 *dot_pos = NULL; /* decimal point position */ u64 sig = 0; /* significant part of the number */ i32 exp = 0; /* exponent part of the number */ bool exp_sign; /* temporary exponent sign from literal part */ i64 exp_sig = 0; /* temporary exponent number from significant part */ i64 exp_lit = 0; /* temporary exponent number from exponent literal part */ u64 num; /* temporary number for reading */ u8 *tmp; /* temporary cursor for reading */ u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; bool sign; /* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */ if (unlikely(pre && !(flg & YYJSON_READ_BIGNUM_AS_RAW))) { return read_number_raw(ptr, pre, flg, val, msg); } sign = (*hdr == '-'); cur += sign; /* begin with a leading zero or non-digit */ if (unlikely(!digi_is_nonzero(*cur))) { /* 0 or non-digit char */ if (unlikely(*cur != '0')) { /* non-digit char */ if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) { if (read_inf_or_nan(sign, &cur, pre, val)) { *end = cur; return true; } } return_err(cur, "no digit after minus sign"); } /* begin with 0 */ if (likely(!digi_is_digit_or_fp(*++cur))) return_0(); if (likely(*cur == '.')) { dot_pos = cur++; if (unlikely(!digi_is_digit(*cur))) { return_err(cur, "no digit after decimal point"); } while (unlikely(*cur == '0')) cur++; if (likely(digi_is_digit(*cur))) { /* first non-zero digit after decimal point */ sig = (u64)(*cur - '0'); /* read first digit */ cur--; goto digi_frac_1; /* continue read fraction part */ } } if (unlikely(digi_is_digit(*cur))) { return_err(cur - 1, "number with leading zero is not allowed"); } if (unlikely(digi_is_exp(*cur))) { /* 0 with any exponent is still 0 */ cur += (usize)1 + digi_is_sign(cur[1]); if (unlikely(!digi_is_digit(*cur))) { return_err(cur, "no digit after exponent sign"); } while (digi_is_digit(*++cur)); } return_f64_bin(0); } /* begin with non-zero digit */ sig = (u64)(*cur - '0'); /* Read integral part, same as the following code. for (int i = 1; i <= 18; i++) { num = cur[i] - '0'; if (num <= 9) sig = num + sig * 10; else goto digi_sepr_i; } */ #define expr_intg(i) \ if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \ else { goto digi_sepr_##i; } repeat_in_1_18(expr_intg) #undef expr_intg cur += 19; /* skip continuous 19 digits */ if (!digi_is_digit_or_fp(*cur)) { /* this number is an integer consisting of 19 digits */ if (sign && (sig > ((u64)1 << 63))) { /* overflow */ if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } goto digi_intg_more; /* read more digits in integral part */ /* process first non-digit character */ #define expr_sepr(i) \ digi_sepr_##i: \ if (likely(!digi_is_fp(cur[i]))) { cur += i; return_i64(sig); } \ dot_pos = cur + i; \ if (likely(cur[i] == '.')) goto digi_frac_##i; \ cur += i; sig_end = cur; goto digi_exp_more; repeat_in_1_18(expr_sepr) #undef expr_sepr /* read fraction part */ #define expr_frac(i) \ digi_frac_##i: \ if (likely((num = (u64)(cur[i + 1] - (u8)'0')) <= 9)) \ sig = num + sig * 10; \ else { goto digi_stop_##i; } repeat_in_1_18(expr_frac) #undef expr_frac cur += 20; /* skip 19 digits and 1 decimal point */ if (!digi_is_digit(*cur)) goto digi_frac_end; /* fraction part end */ goto digi_frac_more; /* read more digits in fraction part */ /* significant part end */ #define expr_stop(i) \ digi_stop_##i: \ cur += i + 1; \ goto digi_frac_end; repeat_in_1_18(expr_stop) #undef expr_stop /* read more digits in integral part */ digi_intg_more: if (digi_is_digit(*cur)) { if (!digi_is_digit_or_fp(cur[1])) { /* this number is an integer consisting of 20 digits */ num = (u64)(*cur - '0'); if ((sig < (U64_MAX / 10)) || (sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) { sig = num + sig * 10; cur++; /* convert to double if overflow */ if (sign) { if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } } } if (digi_is_exp(*cur)) { dot_pos = cur; goto digi_exp_more; } if (*cur == '.') { dot_pos = cur++; if (!digi_is_digit(*cur)) { return_err(cur, "no digit after decimal point"); } } /* read more digits in fraction part */ digi_frac_more: sig_cut = cur; /* too large to fit in u64, excess digits need to be cut */ sig += (*cur >= '5'); /* round */ while (digi_is_digit(*++cur)); if (!dot_pos) { if (!digi_is_fp(*cur) && (flg & YYJSON_READ_BIGNUM_AS_RAW)) { return_raw(); /* it's a large integer */ } dot_pos = cur; if (*cur == '.') { if (!digi_is_digit(*++cur)) { return_err(cur, "no digit after decimal point"); } while (digi_is_digit(*cur)) cur++; } } exp_sig = (i64)(dot_pos - sig_cut); exp_sig += (dot_pos < sig_cut); /* ignore trailing zeros */ tmp = cur - 1; while (*tmp == '0' || *tmp == '.') tmp--; if (tmp < sig_cut) { sig_cut = NULL; } else { sig_end = cur; } if (digi_is_exp(*cur)) goto digi_exp_more; goto digi_exp_finish; /* fraction part end */ digi_frac_end: if (unlikely(dot_pos + 1 == cur)) { return_err(cur, "no digit after decimal point"); } sig_end = cur; exp_sig = -(i64)((u64)(cur - dot_pos) - 1); if (likely(!digi_is_exp(*cur))) { if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) { return_f64_bin(0); /* underflow */ } exp = (i32)exp_sig; goto digi_finish; } else { goto digi_exp_more; } /* read exponent part */ digi_exp_more: exp_sign = (*++cur == '-'); cur += digi_is_sign(*cur); if (unlikely(!digi_is_digit(*cur))) { return_err(cur, "no digit after exponent sign"); } while (*cur == '0') cur++; /* read exponent literal */ tmp = cur; while (digi_is_digit(*cur)) { exp_lit = (i64)((u8)(*cur++ - '0') + (u64)exp_lit * 10); } if (unlikely(cur - tmp >= U64_SAFE_DIG)) { if (exp_sign) { return_f64_bin(0); /* underflow */ } else { return_inf(); /* overflow */ } } exp_sig += exp_sign ? -exp_lit : exp_lit; /* validate exponent value */ digi_exp_finish: if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) { return_f64_bin(0); /* underflow */ } if (unlikely(exp_sig > F64_MAX_DEC_EXP)) { return_inf(); /* overflow */ } exp = (i32)exp_sig; /* all digit read finished */ digi_finish: /* Fast path 1: 1. The floating-point number calculation should be accurate, see the comments of macro `YYJSON_DOUBLE_MATH_CORRECT`. 2. Correct rounding should be performed (fegetround() == FE_TONEAREST). 3. The input of floating point number calculation does not lose precision, which means: 64 - leading_zero(input) - trailing_zero(input) < 53. We don't check all available inputs here, because that would make the code more complicated, and not friendly to branch predictor. */ #if YYJSON_DOUBLE_MATH_CORRECT if (sig < ((u64)1 << 53) && exp >= -F64_POW10_EXP_MAX_EXACT && exp <= +F64_POW10_EXP_MAX_EXACT) { f64 dbl = (f64)sig; if (exp < 0) { dbl /= f64_pow10_table[-exp]; } else { dbl *= f64_pow10_table[+exp]; } return_f64(dbl); } #endif /* Fast path 2: To keep it simple, we only accept normal number here, let the slow path to handle subnormal and infinity number. */ if (likely(!sig_cut && exp > -F64_MAX_DEC_EXP + 1 && exp < +F64_MAX_DEC_EXP - 20)) { /* The result value is exactly equal to (sig * 10^exp), the exponent part (10^exp) can be converted to (sig2 * 2^exp2). The sig2 can be an infinite length number, only the highest 128 bits is cached in the pow10_sig_table. Now we have these bits: sig1 (normalized 64bit) : aaaaaaaa sig2 (higher 64bit) : bbbbbbbb sig2_ext (lower 64bit) : cccccccc sig2_cut (extra unknown bits) : dddddddddddd.... And the calculation process is: ---------------------------------------- aaaaaaaa * bbbbbbbbccccccccdddddddddddd.... ---------------------------------------- abababababababab + acacacacacacacac + adadadadadadadadadad.... ---------------------------------------- [hi____][lo____] + [hi2___][lo2___] + [unknown___________....] ---------------------------------------- The addition with carry may affect higher bits, but if there is a 0 in higher bits, the bits higher than 0 will not be affected. `lo2` + `unknown` may get a carry bit and may affect `hi2`, the max value of `hi2` is 0xFFFFFFFFFFFFFFFE, so `hi2` will not overflow. `lo` + `hi2` may also get a carry bit and may affect `hi`, but only the highest significant 53 bits of `hi` is needed. If there is a 0 in the lower bits of `hi`, then all the following bits can be dropped. To convert the result to IEEE-754 double number, we need to perform correct rounding: 1. if bit 54 is 0, round down, 2. if bit 54 is 1 and any bit beyond bit 54 is 1, round up, 3. if bit 54 is 1 and all bits beyond bit 54 are 0, round to even, as the extra bits is unknown, this case will not be handled here. */ u64 raw; u64 sig1, sig2, sig2_ext, hi, lo, hi2, lo2, add, bits; i32 exp2; u32 lz; bool exact = false, carry, round_up; /* convert (10^exp) to (sig2 * 2^exp2) */ pow10_table_get_sig(exp, &sig2, &sig2_ext); pow10_table_get_exp(exp, &exp2); /* normalize and multiply */ lz = u64_lz_bits(sig); sig1 = sig << lz; exp2 -= (i32)lz; u128_mul(sig1, sig2, &hi, &lo); /* The `hi` is in range [0x4000000000000000, 0xFFFFFFFFFFFFFFFE], To get normalized value, `hi` should be shifted to the left by 0 or 1. The highest significant 53 bits is used by IEEE-754 double number, and the bit 54 is used to detect rounding direction. The lowest (64 - 54 - 1) bits is used to check whether it contains 0. */ bits = hi & (((u64)1 << (64 - 54 - 1)) - 1); if (bits - 1 < (((u64)1 << (64 - 54 - 1)) - 2)) { /* (bits != 0 && bits != 0x1FF) => (bits - 1 < 0x1FF - 1) The `bits` is not zero, so we don't need to check `round to even` case. The `bits` contains bit `0`, so we can drop the extra bits after `0`. */ exact = true; } else { /* (bits == 0 || bits == 0x1FF) The `bits` is filled with all `0` or all `1`, so we need to check lower bits with another 64-bit multiplication. */ u128_mul(sig1, sig2_ext, &hi2, &lo2); add = lo + hi2; if (add + 1 > (u64)1) { /* (add != 0 && add != U64_MAX) => (add + 1 > 1) The `add` is not zero, so we don't need to check `round to even` case. The `add` contains bit `0`, so we can drop the extra bits after `0`. The `hi` cannot be U64_MAX, so it will not overflow. */ carry = add < lo || add < hi2; hi += carry; exact = true; } } if (exact) { /* normalize */ lz = hi < ((u64)1 << 63); hi <<= lz; exp2 -= (i32)lz; exp2 += 64; /* test the bit 54 and get rounding direction */ round_up = (hi & ((u64)1 << (64 - 54))) > (u64)0; hi += (round_up ? ((u64)1 << (64 - 54)) : (u64)0); /* test overflow */ if (hi < ((u64)1 << (64 - 54))) { hi = ((u64)1 << 63); exp2 += 1; } /* This is a normal number, convert it to IEEE-754 format. */ hi >>= F64_BITS - F64_SIG_FULL_BITS; exp2 += F64_BITS - F64_SIG_FULL_BITS + F64_SIG_BITS; exp2 += F64_EXP_BIAS; raw = ((u64)exp2 << F64_SIG_BITS) | (hi & F64_SIG_MASK); return_f64_bin(raw); } } /* Slow path: read double number exactly with diyfp. 1. Use cached diyfp to get an approximation value. 2. Use bigcomp to check the approximation value if needed. This algorithm refers to google's double-conversion project: https://github.com/google/double-conversion */ { const i32 ERR_ULP_LOG = 3; const i32 ERR_ULP = 1 << ERR_ULP_LOG; const i32 ERR_CACHED_POW = ERR_ULP / 2; const i32 ERR_MUL_FIXED = ERR_ULP / 2; const i32 DIY_SIG_BITS = 64; const i32 EXP_BIAS = F64_EXP_BIAS + F64_SIG_BITS; const i32 EXP_SUBNORMAL = -EXP_BIAS + 1; u64 fp_err; u32 bits; i32 order_of_magnitude; i32 effective_significand_size; i32 precision_digits_count; u64 precision_bits; u64 half_way; u64 raw; diy_fp fp, fp_upper; bigint big_full, big_comp; i32 cmp; fp.sig = sig; fp.exp = 0; fp_err = sig_cut ? (u64)(ERR_ULP / 2) : (u64)0; /* normalize */ bits = u64_lz_bits(fp.sig); fp.sig <<= bits; fp.exp -= (i32)bits; fp_err <<= bits; /* multiply and add error */ fp = diy_fp_mul(fp, diy_fp_get_cached_pow10(exp)); fp_err += (u64)ERR_CACHED_POW + (fp_err != 0) + (u64)ERR_MUL_FIXED; /* normalize */ bits = u64_lz_bits(fp.sig); fp.sig <<= bits; fp.exp -= (i32)bits; fp_err <<= bits; /* effective significand */ order_of_magnitude = DIY_SIG_BITS + fp.exp; if (likely(order_of_magnitude >= EXP_SUBNORMAL + F64_SIG_FULL_BITS)) { effective_significand_size = F64_SIG_FULL_BITS; } else if (order_of_magnitude <= EXP_SUBNORMAL) { effective_significand_size = 0; } else { effective_significand_size = order_of_magnitude - EXP_SUBNORMAL; } /* precision digits count */ precision_digits_count = DIY_SIG_BITS - effective_significand_size; if (unlikely(precision_digits_count + ERR_ULP_LOG >= DIY_SIG_BITS)) { i32 shr = (precision_digits_count + ERR_ULP_LOG) - DIY_SIG_BITS + 1; fp.sig >>= shr; fp.exp += shr; fp_err = (fp_err >> shr) + 1 + (u32)ERR_ULP; precision_digits_count -= shr; } /* half way */ precision_bits = fp.sig & (((u64)1 << precision_digits_count) - 1); precision_bits *= (u32)ERR_ULP; half_way = (u64)1 << (precision_digits_count - 1); half_way *= (u32)ERR_ULP; /* rounding */ fp.sig >>= precision_digits_count; fp.sig += (precision_bits >= half_way + fp_err); fp.exp += precision_digits_count; /* get IEEE double raw value */ raw = diy_fp_to_ieee_raw(fp); if (unlikely(raw == F64_RAW_INF)) return_inf(); if (likely(precision_bits <= half_way - fp_err || precision_bits >= half_way + fp_err)) { return_f64_bin(raw); /* number is accurate */ } /* now the number is the correct value, or the next lower value */ /* upper boundary */ if (raw & F64_EXP_MASK) { fp_upper.sig = (raw & F64_SIG_MASK) + ((u64)1 << F64_SIG_BITS); fp_upper.exp = (i32)((raw & F64_EXP_MASK) >> F64_SIG_BITS); } else { fp_upper.sig = (raw & F64_SIG_MASK); fp_upper.exp = 1; } fp_upper.exp -= F64_EXP_BIAS + F64_SIG_BITS; fp_upper.sig <<= 1; fp_upper.exp -= 1; fp_upper.sig += 1; /* add half ulp */ /* compare with bigint */ bigint_set_buf(&big_full, sig, &exp, sig_cut, sig_end, dot_pos); bigint_set_u64(&big_comp, fp_upper.sig); if (exp >= 0) { bigint_mul_pow10(&big_full, +exp); } else { bigint_mul_pow10(&big_comp, -exp); } if (fp_upper.exp > 0) { bigint_mul_pow2(&big_comp, (u32)+fp_upper.exp); } else { bigint_mul_pow2(&big_full, (u32)-fp_upper.exp); } cmp = bigint_cmp(&big_full, &big_comp); if (likely(cmp != 0)) { /* round down or round up */ raw += (cmp > 0); } else { /* falls midway, round to even */ raw += (raw & 1); } if (unlikely(raw == F64_RAW_INF)) return_inf(); return_f64_bin(raw); } #undef return_err #undef return_inf #undef return_0 #undef return_i64 #undef return_f64 #undef return_f64_bin #undef return_raw } #else /* FP_READER */ /** Read a JSON number. This is a fallback function if the custom number reader is disabled. This function use libc's strtod() to read floating-point number. */ static_noinline bool read_number(u8 **ptr, u8 **pre, yyjson_read_flag flg, yyjson_val *val, const char **msg) { #define return_err(_pos, _msg) do { \ *msg = _msg; \ *end = _pos; \ return false; \ } while (false) #define return_0() do { \ val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \ val->uni.u64 = 0; \ *end = cur; return true; \ } while (false) #define return_i64(_v) do { \ val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \ val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \ *end = cur; return true; \ } while (false) #define return_f64(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \ *end = cur; return true; \ } while (false) #define return_f64_bin(_v) do { \ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \ val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \ *end = cur; return true; \ } while (false) #define return_inf() do { \ if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); \ if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) return_f64_bin(F64_RAW_INF); \ else return_err(hdr, "number is infinity when parsed as double"); \ } while (false) #define return_raw() do { \ if (*pre) **pre = '\0'; /* add null-terminator for previous raw string */ \ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \ val->uni.str = (const char *)hdr; \ *pre = cur; *end = cur; return true; \ } while (false) u64 sig, num; u8 *hdr = *ptr; u8 *cur = *ptr; u8 **end = ptr; u8 *dot = NULL; u8 *f64_end = NULL; bool sign; /* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */ if (unlikely(pre && !(flg & YYJSON_READ_BIGNUM_AS_RAW))) { return read_number_raw(ptr, pre, flg, val, msg); } sign = (*hdr == '-'); cur += sign; sig = (u8)(*cur - '0'); /* read first digit, check leading zero */ if (unlikely(!digi_is_digit(*cur))) { if (flg & YYJSON_READ_ALLOW_INF_AND_NAN) { if (read_inf_or_nan(sign, &cur, pre, val)) { *end = cur; return true; } } return_err(cur, "no digit after minus sign"); } if (*cur == '0') { cur++; if (unlikely(digi_is_digit(*cur))) { return_err(cur - 1, "number with leading zero is not allowed"); } if (!digi_is_fp(*cur)) return_0(); goto read_double; } /* read continuous digits, up to 19 characters */ #define expr_intg(i) \ if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \ else { cur += i; goto intg_end; } repeat_in_1_18(expr_intg) #undef expr_intg /* here are 19 continuous digits, skip them */ cur += 19; if (digi_is_digit(cur[0]) && !digi_is_digit_or_fp(cur[1])) { /* this number is an integer consisting of 20 digits */ num = (u8)(*cur - '0'); if ((sig < (U64_MAX / 10)) || (sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) { sig = num + sig * 10; cur++; if (sign) { if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } } intg_end: /* continuous digits ended */ if (!digi_is_digit_or_fp(*cur)) { /* this number is an integer consisting of 1 to 19 digits */ if (sign && (sig > ((u64)1 << 63))) { if (flg & YYJSON_READ_BIGNUM_AS_RAW) return_raw(); return_f64(normalized_u64_to_f64(sig)); } return_i64(sig); } read_double: /* this number should be read as double */ while (digi_is_digit(*cur)) cur++; if (!digi_is_fp(*cur) && (flg & YYJSON_READ_BIGNUM_AS_RAW)) { return_raw(); /* it's a large integer */ } if (*cur == '.') { /* skip fraction part */ dot = cur; cur++; if (!digi_is_digit(*cur)) { return_err(cur, "no digit after decimal point"); } cur++; while (digi_is_digit(*cur)) cur++; } if (digi_is_exp(*cur)) { /* skip exponent part */ cur += 1 + digi_is_sign(cur[1]); if (!digi_is_digit(*cur)) { return_err(cur, "no digit after exponent sign"); } cur++; while (digi_is_digit(*cur)) cur++; } /* libc's strtod() is used to parse the floating-point number. Note that the decimal point character used by strtod() is locale-dependent, and the rounding direction may affected by fesetround(). For currently known locales, (en, zh, ja, ko, am, he, hi) use '.' as the decimal point, while other locales use ',' as the decimal point. Here strtod() is called twice for different locales, but if another thread happens calls setlocale() between two strtod(), parsing may still fail. */ val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end); if (unlikely(f64_end != cur)) { /* replace '.' with ',' for locale */ bool cut = (*cur == ','); if (cut) *cur = ' '; if (dot) *dot = ','; val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end); /* restore ',' to '.' */ if (cut) *cur = ','; if (dot) *dot = '.'; if (unlikely(f64_end != cur)) { return_err(hdr, "strtod() failed to parse the number"); } } if (unlikely(val->uni.f64 >= HUGE_VAL || val->uni.f64 <= -HUGE_VAL)) { return_inf(); } val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; *end = cur; return true; #undef return_err #undef return_0 #undef return_i64 #undef return_f64 #undef return_f64_bin #undef return_inf #undef return_raw } #endif /* FP_READER */ /*============================================================================== * JSON String Reader *============================================================================*/ /** Read a JSON string. @param ptr The head pointer of string before '"' prefix (inout). @param lst JSON last position. @param inv Allow invalid unicode. @param val The string value to be written. @param msg The error message pointer. @return Whether success. */ static_inline bool read_string(u8 **ptr, u8 *lst, bool inv, yyjson_val *val, const char **msg) { /* Each unicode code point is encoded as 1 to 4 bytes in UTF-8 encoding, we use 4-byte mask and pattern value to validate UTF-8 byte sequence, this requires the input data to have 4-byte zero padding. --------------------------------------------------- 1 byte unicode range [U+0000, U+007F] unicode min [.......0] unicode max [.1111111] bit pattern [0.......] --------------------------------------------------- 2 byte unicode range [U+0080, U+07FF] unicode min [......10 ..000000] unicode max [...11111 ..111111] bit require [...xxxx. ........] (1E 00) bit mask [xxx..... xx......] (E0 C0) bit pattern [110..... 10......] (C0 80) --------------------------------------------------- 3 byte unicode range [U+0800, U+FFFF] unicode min [........ ..100000 ..000000] unicode max [....1111 ..111111 ..111111] bit require [....xxxx ..x..... ........] (0F 20 00) bit mask [xxxx.... xx...... xx......] (F0 C0 C0) bit pattern [1110.... 10...... 10......] (E0 80 80) --------------------------------------------------- 3 byte invalid (reserved for surrogate halves) unicode range [U+D800, U+DFFF] unicode min [....1101 ..100000 ..000000] unicode max [....1101 ..111111 ..111111] bit mask [....xxxx ..x..... ........] (0F 20 00) bit pattern [....1101 ..1..... ........] (0D 20 00) --------------------------------------------------- 4 byte unicode range [U+10000, U+10FFFF] unicode min [........ ...10000 ..000000 ..000000] unicode max [.....100 ..001111 ..111111 ..111111] bit require [.....xxx ..xx.... ........ ........] (07 30 00 00) bit mask [xxxxx... xx...... xx...... xx......] (F8 C0 C0 C0) bit pattern [11110... 10...... 10...... 10......] (F0 80 80 80) --------------------------------------------------- */ #if YYJSON_ENDIAN == YYJSON_BIG_ENDIAN const u32 b1_mask = 0x80000000UL; const u32 b1_patt = 0x00000000UL; const u32 b2_mask = 0xE0C00000UL; const u32 b2_patt = 0xC0800000UL; const u32 b2_requ = 0x1E000000UL; const u32 b3_mask = 0xF0C0C000UL; const u32 b3_patt = 0xE0808000UL; const u32 b3_requ = 0x0F200000UL; const u32 b3_erro = 0x0D200000UL; const u32 b4_mask = 0xF8C0C0C0UL; const u32 b4_patt = 0xF0808080UL; const u32 b4_requ = 0x07300000UL; const u32 b4_err0 = 0x04000000UL; const u32 b4_err1 = 0x03300000UL; #elif YYJSON_ENDIAN == YYJSON_LITTLE_ENDIAN const u32 b1_mask = 0x00000080UL; const u32 b1_patt = 0x00000000UL; const u32 b2_mask = 0x0000C0E0UL; const u32 b2_patt = 0x000080C0UL; const u32 b2_requ = 0x0000001EUL; const u32 b3_mask = 0x00C0C0F0UL; const u32 b3_patt = 0x008080E0UL; const u32 b3_requ = 0x0000200FUL; const u32 b3_erro = 0x0000200DUL; const u32 b4_mask = 0xC0C0C0F8UL; const u32 b4_patt = 0x808080F0UL; const u32 b4_requ = 0x00003007UL; const u32 b4_err0 = 0x00000004UL; const u32 b4_err1 = 0x00003003UL; #else v32_uni b1_mask_uni = {{ 0x80, 0x00, 0x00, 0x00 }}; v32_uni b1_patt_uni = {{ 0x00, 0x00, 0x00, 0x00 }}; v32_uni b2_mask_uni = {{ 0xE0, 0xC0, 0x00, 0x00 }}; v32_uni b2_patt_uni = {{ 0xC0, 0x80, 0x00, 0x00 }}; v32_uni b2_requ_uni = {{ 0x1E, 0x00, 0x00, 0x00 }}; v32_uni b3_mask_uni = {{ 0xF0, 0xC0, 0xC0, 0x00 }}; v32_uni b3_patt_uni = {{ 0xE0, 0x80, 0x80, 0x00 }}; v32_uni b3_requ_uni = {{ 0x0F, 0x20, 0x00, 0x00 }}; v32_uni b3_erro_uni = {{ 0x0D, 0x20, 0x00, 0x00 }}; v32_uni b4_mask_uni = {{ 0xF8, 0xC0, 0xC0, 0xC0 }}; v32_uni b4_patt_uni = {{ 0xF0, 0x80, 0x80, 0x80 }}; v32_uni b4_requ_uni = {{ 0x07, 0x30, 0x00, 0x00 }}; v32_uni b4_err0_uni = {{ 0x04, 0x00, 0x00, 0x00 }}; v32_uni b4_err1_uni = {{ 0x03, 0x30, 0x00, 0x00 }}; u32 b1_mask = b1_mask_uni.u; u32 b1_patt = b1_patt_uni.u; u32 b2_mask = b2_mask_uni.u; u32 b2_patt = b2_patt_uni.u; u32 b2_requ = b2_requ_uni.u; u32 b3_mask = b3_mask_uni.u; u32 b3_patt = b3_patt_uni.u; u32 b3_requ = b3_requ_uni.u; u32 b3_erro = b3_erro_uni.u; u32 b4_mask = b4_mask_uni.u; u32 b4_patt = b4_patt_uni.u; u32 b4_requ = b4_requ_uni.u; u32 b4_err0 = b4_err0_uni.u; u32 b4_err1 = b4_err1_uni.u; #endif #define is_valid_seq_1(uni) ( \ ((uni & b1_mask) == b1_patt) \ ) #define is_valid_seq_2(uni) ( \ ((uni & b2_mask) == b2_patt) && \ ((uni & b2_requ)) \ ) #define is_valid_seq_3(uni) ( \ ((uni & b3_mask) == b3_patt) && \ ((tmp = (uni & b3_requ))) && \ ((tmp != b3_erro)) \ ) #define is_valid_seq_4(uni) ( \ ((uni & b4_mask) == b4_patt) && \ ((tmp = (uni & b4_requ))) && \ ((tmp & b4_err0) == 0 || (tmp & b4_err1) == 0) \ ) #define return_err(_end, _msg) do { \ *msg = _msg; \ *end = _end; \ return false; \ } while (false) u8 *cur = *ptr; u8 **end = ptr; u8 *src = ++cur, *dst, *pos; u16 hi, lo; u32 uni, tmp; skip_ascii: /* Most strings have no escaped characters, so we can jump them quickly. */ skip_ascii_begin: /* We want to make loop unrolling, as shown in the following code. Some compiler may not generate instructions as expected, so we rewrite it with explicit goto statements. We hope the compiler can generate instructions like this: https://godbolt.org/z/8vjsYq while (true) repeat16({ if (likely(!(char_is_ascii_stop(*src)))) src++; else break; }) */ #define expr_jump(i) \ if (likely(!char_is_ascii_stop(src[i]))) {} \ else goto skip_ascii_stop##i; #define expr_stop(i) \ skip_ascii_stop##i: \ src += i; \ goto skip_ascii_end; repeat16_incr(expr_jump) src += 16; goto skip_ascii_begin; repeat16_incr(expr_stop) #undef expr_jump #undef expr_stop skip_ascii_end: /* GCC may store src[i] in a register at each line of expr_jump(i) above. These instructions are useless and will degrade performance. This inline asm is a hint for gcc: "the memory has been modified, do not cache it". MSVC, Clang, ICC can generate expected instructions without this hint. */ #if YYJSON_IS_REAL_GCC __asm__ volatile("":"=m"(*src)); #endif if (likely(*src == '"')) { val->tag = ((u64)(src - cur) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = (const char *)cur; *src = '\0'; *end = src + 1; return true; } skip_utf8: if (*src & 0x80) { /* non-ASCII character */ /* Non-ASCII character appears here, which means that the text is likely to be written in non-English or emoticons. According to some common data set statistics, byte sequences of the same length may appear consecutively. We process the byte sequences of the same length in each loop, which is more friendly to branch prediction. */ pos = src; uni = byte_load_4(src); while (is_valid_seq_3(uni)) { src += 3; uni = byte_load_4(src); } if (is_valid_seq_1(uni)) goto skip_ascii; while (is_valid_seq_2(uni)) { src += 2; uni = byte_load_4(src); } while (is_valid_seq_4(uni)) { src += 4; uni = byte_load_4(src); } if (unlikely(pos == src)) { if (!inv) return_err(src, "invalid UTF-8 encoding in string"); ++src; } goto skip_ascii; } /* The escape character appears, we need to copy it. */ dst = src; copy_escape: if (likely(*src == '\\')) { switch (*++src) { case '"': *dst++ = '"'; src++; break; case '\\': *dst++ = '\\'; src++; break; case '/': *dst++ = '/'; src++; break; case 'b': *dst++ = '\b'; src++; break; case 'f': *dst++ = '\f'; src++; break; case 'n': *dst++ = '\n'; src++; break; case 'r': *dst++ = '\r'; src++; break; case 't': *dst++ = '\t'; src++; break; case 'u': if (unlikely(!read_hex_u16(++src, &hi))) { return_err(src - 2, "invalid escaped sequence in string"); } src += 4; if (likely((hi & 0xF800) != 0xD800)) { /* a BMP character */ if (hi >= 0x800) { *dst++ = (u8)(0xE0 | (hi >> 12)); *dst++ = (u8)(0x80 | ((hi >> 6) & 0x3F)); *dst++ = (u8)(0x80 | (hi & 0x3F)); } else if (hi >= 0x80) { *dst++ = (u8)(0xC0 | (hi >> 6)); *dst++ = (u8)(0x80 | (hi & 0x3F)); } else { *dst++ = (u8)hi; } } else { /* a non-BMP character, represented as a surrogate pair */ if (unlikely((hi & 0xFC00) != 0xD800)) { return_err(src - 6, "invalid high surrogate in string"); } if (unlikely(!byte_match_2(src, "\\u"))) { return_err(src, "no low surrogate in string"); } if (unlikely(!read_hex_u16(src + 2, &lo))) { return_err(src, "invalid escaped sequence in string"); } if (unlikely((lo & 0xFC00) != 0xDC00)) { return_err(src, "invalid low surrogate in string"); } uni = ((((u32)hi - 0xD800) << 10) | ((u32)lo - 0xDC00)) + 0x10000; *dst++ = (u8)(0xF0 | (uni >> 18)); *dst++ = (u8)(0x80 | ((uni >> 12) & 0x3F)); *dst++ = (u8)(0x80 | ((uni >> 6) & 0x3F)); *dst++ = (u8)(0x80 | (uni & 0x3F)); src += 6; } break; default: return_err(src, "invalid escaped character in string"); } } else if (likely(*src == '"')) { val->tag = ((u64)(dst - cur) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = (const char *)cur; *dst = '\0'; *end = src + 1; return true; } else { if (!inv) return_err(src, "unexpected control character in string"); if (src >= lst) return_err(src, "unclosed string"); *dst++ = *src++; } copy_ascii: /* Copy continuous ASCII, loop unrolling, same as the following code: while (true) repeat16({ if (unlikely(char_is_ascii_stop(*src))) break; *dst++ = *src++; }) */ #if YYJSON_IS_REAL_GCC # define expr_jump(i) \ if (likely(!(char_is_ascii_stop(src[i])))) {} \ else { __asm__ volatile("":"=m"(src[i])); goto copy_ascii_stop_##i; } #else # define expr_jump(i) \ if (likely(!(char_is_ascii_stop(src[i])))) {} \ else { goto copy_ascii_stop_##i; } #endif repeat16_incr(expr_jump) #undef expr_jump byte_move_16(dst, src); src += 16; dst += 16; goto copy_ascii; copy_ascii_stop_0: goto copy_utf8; copy_ascii_stop_1: byte_move_2(dst, src); src += 1; dst += 1; goto copy_utf8; copy_ascii_stop_2: byte_move_2(dst, src); src += 2; dst += 2; goto copy_utf8; copy_ascii_stop_3: byte_move_4(dst, src); src += 3; dst += 3; goto copy_utf8; copy_ascii_stop_4: byte_move_4(dst, src); src += 4; dst += 4; goto copy_utf8; copy_ascii_stop_5: byte_move_4(dst, src); byte_move_2(dst + 4, src + 4); src += 5; dst += 5; goto copy_utf8; copy_ascii_stop_6: byte_move_4(dst, src); byte_move_2(dst + 4, src + 4); src += 6; dst += 6; goto copy_utf8; copy_ascii_stop_7: byte_move_8(dst, src); src += 7; dst += 7; goto copy_utf8; copy_ascii_stop_8: byte_move_8(dst, src); src += 8; dst += 8; goto copy_utf8; copy_ascii_stop_9: byte_move_8(dst, src); byte_move_2(dst + 8, src + 8); src += 9; dst += 9; goto copy_utf8; copy_ascii_stop_10: byte_move_8(dst, src); byte_move_2(dst + 8, src + 8); src += 10; dst += 10; goto copy_utf8; copy_ascii_stop_11: byte_move_8(dst, src); byte_move_4(dst + 8, src + 8); src += 11; dst += 11; goto copy_utf8; copy_ascii_stop_12: byte_move_8(dst, src); byte_move_4(dst + 8, src + 8); src += 12; dst += 12; goto copy_utf8; copy_ascii_stop_13: byte_move_8(dst, src); byte_move_4(dst + 8, src + 8); byte_move_2(dst + 12, src + 12); src += 13; dst += 13; goto copy_utf8; copy_ascii_stop_14: byte_move_8(dst, src); byte_move_4(dst + 8, src + 8); byte_move_2(dst + 12, src + 12); src += 14; dst += 14; goto copy_utf8; copy_ascii_stop_15: byte_move_16(dst, src); src += 15; dst += 15; goto copy_utf8; copy_utf8: if (*src & 0x80) { /* non-ASCII character */ pos = src; uni = byte_load_4(src); while (is_valid_seq_3(uni)) { byte_move_4(dst, &uni); dst += 3; src += 3; uni = byte_load_4(src); } if (is_valid_seq_1(uni)) goto copy_ascii; while (is_valid_seq_2(uni)) { byte_move_2(dst, &uni); dst += 2; src += 2; uni = byte_load_4(src); } while (is_valid_seq_4(uni)) { byte_move_4(dst, &uni); dst += 4; src += 4; uni = byte_load_4(src); } if (unlikely(pos == src)) { if (!inv) return_err(src, "invalid UTF-8 encoding in string"); goto copy_ascii_stop_1; } goto copy_ascii; } goto copy_escape; #undef return_err #undef is_valid_seq_1 #undef is_valid_seq_2 #undef is_valid_seq_3 #undef is_valid_seq_4 } /*============================================================================== * JSON Reader Implementation * * We use goto statements to build the finite state machine (FSM). * The FSM's state was held by program counter (PC) and the 'goto' make the * state transitions. *============================================================================*/ /** Read single value JSON document. */ static_noinline yyjson_doc *read_root_single(u8 *hdr, u8 *cur, u8 *end, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { #define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) #define return_err(_pos, _code, _msg) do { \ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ } else { \ err->pos = (usize)(_pos - hdr); \ err->code = YYJSON_READ_ERROR_##_code; \ err->msg = _msg; \ } \ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) usize hdr_len; /* value count used by doc */ usize alc_num; /* value count capacity */ yyjson_val *val_hdr; /* the head of allocated values */ yyjson_val *val; /* current value */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ bool raw; /* read number as raw */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_num = hdr_len + 1; /* single value */ val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_num * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val = val_hdr + hdr_len; raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; if (char_is_number(*cur)) { if (likely(read_number(&cur, pre, flg, val, &msg))) goto doc_end; goto fail_number; } if (*cur == '"') { if (likely(read_string(&cur, end, inv, val, &msg))) goto doc_end; goto fail_string; } if (*cur == 't') { if (likely(read_true(&cur, val))) goto doc_end; goto fail_literal; } if (*cur == 'f') { if (likely(read_false(&cur, val))) goto doc_end; goto fail_literal; } if (*cur == 'n') { if (likely(read_null(&cur, val))) goto doc_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto doc_end; } goto fail_literal; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_inf_or_nan(false, &cur, pre, val)) goto doc_end; } goto fail_character; doc_end: /* check invalid contents after json document */ if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { if (has_flag(ALLOW_COMMENTS)) { if (!skip_spaces_and_comments(&cur)) { if (byte_match_2(cur, "/*")) goto fail_comment; } } else { while (char_is_space(*cur)) cur++; } if (unlikely(cur < end)) goto fail_garbage; } if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = 1; doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; return doc; fail_string: return_err(cur, INVALID_STRING, msg); fail_number: return_err(cur, INVALID_NUMBER, msg); fail_alloc: return_err(cur, MEMORY_ALLOCATION, "memory allocation failed"); fail_literal: return_err(cur, LITERAL, "invalid literal"); fail_comment: return_err(cur, INVALID_COMMENT, "unclosed multiline comment"); fail_character: return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); #undef has_flag #undef return_err } /** Read JSON document (accept all style, but optimized for minify). */ static_inline yyjson_doc *read_root_minify(u8 *hdr, u8 *cur, u8 *end, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { #define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) #define return_err(_pos, _code, _msg) do { \ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ } else { \ err->pos = (usize)(_pos - hdr); \ err->code = YYJSON_READ_ERROR_##_code; \ err->msg = _msg; \ } \ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) #define val_incr() do { \ val++; \ if (unlikely(val >= val_end)) { \ usize alc_old = alc_len; \ alc_len += alc_len / 2; \ if ((alc_len >= alc_max)) goto fail_alloc; \ val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ alc_old * sizeof(yyjson_val), \ alc_len * sizeof(yyjson_val)); \ if ((!val_tmp)) goto fail_alloc; \ val = val_tmp + (usize)(val - val_hdr); \ ctn = val_tmp + (usize)(ctn - val_hdr); \ val_hdr = val_tmp; \ val_end = val_tmp + (alc_len - 2); \ } \ } while (false) usize dat_len; /* data length in bytes, hint for allocator */ usize hdr_len; /* value count used by yyjson_doc */ usize alc_len; /* value count allocated */ usize alc_max; /* maximum value count for allocator */ usize ctn_len; /* the number of elements in current container */ yyjson_val *val_hdr; /* the head of allocated values */ yyjson_val *val_end; /* the end of allocated values */ yyjson_val *val_tmp; /* temporary pointer for realloc */ yyjson_val *val; /* current JSON value */ yyjson_val *ctn; /* current container */ yyjson_val *ctn_parent; /* parent of current container */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ bool raw; /* read number as raw */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ dat_len = has_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur); hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_max = USIZE_MAX / sizeof(yyjson_val); alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_MINIFY_RATIO) + 4; alc_len = yyjson_min(alc_len, alc_max); val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */ val = val_hdr + hdr_len; ctn = val; ctn_len = 0; raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; if (*cur++ == '{') { ctn->tag = YYJSON_TYPE_OBJ; ctn->uni.ofs = 0; goto obj_key_begin; } else { ctn->tag = YYJSON_TYPE_ARR; ctn->uni.ofs = 0; goto arr_val_begin; } arr_begin: /* save current container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); /* create a new array value, save parent container offset */ val_incr(); val->tag = YYJSON_TYPE_ARR; val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); /* push the new array value as current container */ ctn = val; ctn_len = 0; arr_val_begin: if (*cur == '{') { cur++; goto obj_begin; } if (*cur == '[') { cur++; goto arr_begin; } if (char_is_number(*cur)) { val_incr(); ctn_len++; if (likely(read_number(&cur, pre, flg, val, &msg))) goto arr_val_end; goto fail_number; } if (*cur == '"') { val_incr(); ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto arr_val_end; goto fail_string; } if (*cur == 't') { val_incr(); ctn_len++; if (likely(read_true(&cur, val))) goto arr_val_end; goto fail_literal; } if (*cur == 'f') { val_incr(); ctn_len++; if (likely(read_false(&cur, val))) goto arr_val_end; goto fail_literal; } if (*cur == 'n') { val_incr(); ctn_len++; if (likely(read_null(&cur, val))) goto arr_val_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto arr_val_end; } goto fail_literal; } if (*cur == ']') { cur++; if (likely(ctn_len == 0)) goto arr_end; if (has_flag(ALLOW_TRAILING_COMMAS)) goto arr_end; while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_begin; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val_incr(); ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end; goto fail_character; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; arr_val_end: if (*cur == ',') { cur++; goto arr_val_begin; } if (*cur == ']') { cur++; goto arr_end; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; arr_end: /* get parent container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); /* save the next sibling value offset */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; if (unlikely(ctn == ctn_parent)) goto doc_end; /* pop parent as current container */ ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { goto obj_val_end; } else { goto arr_val_end; } obj_begin: /* push container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); val_incr(); val->tag = YYJSON_TYPE_OBJ; /* offset to the parent */ val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); ctn = val; ctn_len = 0; obj_key_begin: if (likely(*cur == '"')) { val_incr(); ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_key_end; goto fail_string; } if (likely(*cur == '}')) { cur++; if (likely(ctn_len == 0)) goto obj_end; if (has_flag(ALLOW_TRAILING_COMMAS)) goto obj_end; while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_begin; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_key_end: if (*cur == ':') { cur++; goto obj_val_begin; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_val_begin: if (*cur == '"') { val++; ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_val_end; goto fail_string; } if (char_is_number(*cur)) { val++; ctn_len++; if (likely(read_number(&cur, pre, flg, val, &msg))) goto obj_val_end; goto fail_number; } if (*cur == '{') { cur++; goto obj_begin; } if (*cur == '[') { cur++; goto arr_begin; } if (*cur == 't') { val++; ctn_len++; if (likely(read_true(&cur, val))) goto obj_val_end; goto fail_literal; } if (*cur == 'f') { val++; ctn_len++; if (likely(read_false(&cur, val))) goto obj_val_end; goto fail_literal; } if (*cur == 'n') { val++; ctn_len++; if (likely(read_null(&cur, val))) goto obj_val_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto obj_val_end; } goto fail_literal; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_val_begin; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val++; ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end; goto fail_character; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_val_end: if (likely(*cur == ',')) { cur++; goto obj_key_begin; } if (likely(*cur == '}')) { cur++; goto obj_end; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_val_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_end: /* pop container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); /* point to the next value */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ; if (unlikely(ctn == ctn_parent)) goto doc_end; ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { goto obj_val_end; } else { goto arr_val_end; } doc_end: /* check invalid contents after json document */ if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { if (has_flag(ALLOW_COMMENTS)) { skip_spaces_and_comments(&cur); if (byte_match_2(cur, "/*")) goto fail_comment; } else while (char_is_space(*cur)) cur++; if (unlikely(cur < end)) goto fail_garbage; } if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = (usize)((val - doc->root) + 1); doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; return doc; fail_string: return_err(cur, INVALID_STRING, msg); fail_number: return_err(cur, INVALID_NUMBER, msg); fail_alloc: return_err(cur, MEMORY_ALLOCATION, "memory allocation failed"); fail_trailing_comma: return_err(cur, JSON_STRUCTURE, "trailing comma is not allowed"); fail_literal: return_err(cur, LITERAL, "invalid literal"); fail_comment: return_err(cur, INVALID_COMMENT, "unclosed multiline comment"); fail_character: return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); #undef has_flag #undef val_incr #undef return_err } /** Read JSON document (accept all style, but optimized for pretty). */ static_inline yyjson_doc *read_root_pretty(u8 *hdr, u8 *cur, u8 *end, yyjson_alc alc, yyjson_read_flag flg, yyjson_read_err *err) { #define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) #define return_err(_pos, _code, _msg) do { \ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \ err->pos = (usize)(end - hdr); \ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \ err->msg = "unexpected end of data"; \ } else { \ err->pos = (usize)(_pos - hdr); \ err->code = YYJSON_READ_ERROR_##_code; \ err->msg = _msg; \ } \ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \ return NULL; \ } while (false) #define val_incr() do { \ val++; \ if (unlikely(val >= val_end)) { \ usize alc_old = alc_len; \ alc_len += alc_len / 2; \ if ((alc_len >= alc_max)) goto fail_alloc; \ val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \ alc_old * sizeof(yyjson_val), \ alc_len * sizeof(yyjson_val)); \ if ((!val_tmp)) goto fail_alloc; \ val = val_tmp + (usize)(val - val_hdr); \ ctn = val_tmp + (usize)(ctn - val_hdr); \ val_hdr = val_tmp; \ val_end = val_tmp + (alc_len - 2); \ } \ } while (false) usize dat_len; /* data length in bytes, hint for allocator */ usize hdr_len; /* value count used by yyjson_doc */ usize alc_len; /* value count allocated */ usize alc_max; /* maximum value count for allocator */ usize ctn_len; /* the number of elements in current container */ yyjson_val *val_hdr; /* the head of allocated values */ yyjson_val *val_end; /* the end of allocated values */ yyjson_val *val_tmp; /* temporary pointer for realloc */ yyjson_val *val; /* current JSON value */ yyjson_val *ctn; /* current container */ yyjson_val *ctn_parent; /* parent of current container */ yyjson_doc *doc; /* the JSON document, equals to val_hdr */ const char *msg; /* error message */ bool raw; /* read number as raw */ bool inv; /* allow invalid unicode */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ dat_len = has_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur); hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val); hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0; alc_max = USIZE_MAX / sizeof(yyjson_val); alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_PRETTY_RATIO) + 4; alc_len = yyjson_min(alc_len, alc_max); val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val)); if (unlikely(!val_hdr)) goto fail_alloc; val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */ val = val_hdr + hdr_len; ctn = val; ctn_len = 0; raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; inv = (flg & YYJSON_READ_ALLOW_INVALID_UNICODE) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; if (*cur++ == '{') { ctn->tag = YYJSON_TYPE_OBJ; ctn->uni.ofs = 0; if (*cur == '\n') cur++; goto obj_key_begin; } else { ctn->tag = YYJSON_TYPE_ARR; ctn->uni.ofs = 0; if (*cur == '\n') cur++; goto arr_val_begin; } arr_begin: /* save current container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); /* create a new array value, save parent container offset */ val_incr(); val->tag = YYJSON_TYPE_ARR; val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); /* push the new array value as current container */ ctn = val; ctn_len = 0; if (*cur == '\n') cur++; arr_val_begin: #if YYJSON_IS_REAL_GCC while (true) repeat16({ if (byte_match_2(cur, " ")) cur += 2; else break; }) #else while (true) repeat16({ if (likely(byte_match_2(cur, " "))) cur += 2; else break; }) #endif if (*cur == '{') { cur++; goto obj_begin; } if (*cur == '[') { cur++; goto arr_begin; } if (char_is_number(*cur)) { val_incr(); ctn_len++; if (likely(read_number(&cur, pre, flg, val, &msg))) goto arr_val_end; goto fail_number; } if (*cur == '"') { val_incr(); ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto arr_val_end; goto fail_string; } if (*cur == 't') { val_incr(); ctn_len++; if (likely(read_true(&cur, val))) goto arr_val_end; goto fail_literal; } if (*cur == 'f') { val_incr(); ctn_len++; if (likely(read_false(&cur, val))) goto arr_val_end; goto fail_literal; } if (*cur == 'n') { val_incr(); ctn_len++; if (likely(read_null(&cur, val))) goto arr_val_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto arr_val_end; } goto fail_literal; } if (*cur == ']') { cur++; if (likely(ctn_len == 0)) goto arr_end; if (has_flag(ALLOW_TRAILING_COMMAS)) goto arr_end; while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_begin; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val_incr(); ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end; goto fail_character; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; arr_val_end: if (byte_match_2(cur, ",\n")) { cur += 2; goto arr_val_begin; } if (*cur == ',') { cur++; goto arr_val_begin; } if (*cur == ']') { cur++; goto arr_end; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto arr_val_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto arr_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; arr_end: /* get parent container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); /* save the next sibling value offset */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; if (unlikely(ctn == ctn_parent)) goto doc_end; /* pop parent as current container */ ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); if (*cur == '\n') cur++; if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { goto obj_val_end; } else { goto arr_val_end; } obj_begin: /* push container */ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) | (ctn->tag & YYJSON_TAG_MASK); val_incr(); val->tag = YYJSON_TYPE_OBJ; /* offset to the parent */ val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn); ctn = val; ctn_len = 0; if (*cur == '\n') cur++; obj_key_begin: #if YYJSON_IS_REAL_GCC while (true) repeat16({ if (byte_match_2(cur, " ")) cur += 2; else break; }) #else while (true) repeat16({ if (likely(byte_match_2(cur, " "))) cur += 2; else break; }) #endif if (likely(*cur == '"')) { val_incr(); ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_key_end; goto fail_string; } if (likely(*cur == '}')) { cur++; if (likely(ctn_len == 0)) goto obj_end; if (has_flag(ALLOW_TRAILING_COMMAS)) goto obj_end; while (*cur != ',') cur--; goto fail_trailing_comma; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_begin; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_key_end: if (byte_match_2(cur, ": ")) { cur += 2; goto obj_val_begin; } if (*cur == ':') { cur++; goto obj_val_begin; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_key_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_key_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_val_begin: if (*cur == '"') { val++; ctn_len++; if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_val_end; goto fail_string; } if (char_is_number(*cur)) { val++; ctn_len++; if (likely(read_number(&cur, pre, flg, val, &msg))) goto obj_val_end; goto fail_number; } if (*cur == '{') { cur++; goto obj_begin; } if (*cur == '[') { cur++; goto arr_begin; } if (*cur == 't') { val++; ctn_len++; if (likely(read_true(&cur, val))) goto obj_val_end; goto fail_literal; } if (*cur == 'f') { val++; ctn_len++; if (likely(read_false(&cur, val))) goto obj_val_end; goto fail_literal; } if (*cur == 'n') { val++; ctn_len++; if (likely(read_null(&cur, val))) goto obj_val_end; if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN)) { if (read_nan(false, &cur, pre, val)) goto obj_val_end; } goto fail_literal; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_val_begin; } if (unlikely(flg & YYJSON_READ_ALLOW_INF_AND_NAN) && (*cur == 'i' || *cur == 'I' || *cur == 'N')) { val++; ctn_len++; if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end; goto fail_character; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_begin; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_val_end: if (byte_match_2(cur, ",\n")) { cur += 2; goto obj_key_begin; } if (likely(*cur == ',')) { cur++; goto obj_key_begin; } if (likely(*cur == '}')) { cur++; goto obj_end; } if (char_is_space(*cur)) { while (char_is_space(*++cur)); goto obj_val_end; } if (has_flag(ALLOW_COMMENTS)) { if (skip_spaces_and_comments(&cur)) goto obj_val_end; if (byte_match_2(cur, "/*")) goto fail_comment; } goto fail_character; obj_end: /* pop container */ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs); /* point to the next value */ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val); ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ; if (unlikely(ctn == ctn_parent)) goto doc_end; ctn = ctn_parent; ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT); if (*cur == '\n') cur++; if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) { goto obj_val_end; } else { goto arr_val_end; } doc_end: /* check invalid contents after json document */ if (unlikely(cur < end) && !has_flag(STOP_WHEN_DONE)) { if (has_flag(ALLOW_COMMENTS)) { skip_spaces_and_comments(&cur); if (byte_match_2(cur, "/*")) goto fail_comment; } else while (char_is_space(*cur)) cur++; if (unlikely(cur < end)) goto fail_garbage; } if (pre && *pre) **pre = '\0'; doc = (yyjson_doc *)val_hdr; doc->root = val_hdr + hdr_len; doc->alc = alc; doc->dat_read = (usize)(cur - hdr); doc->val_read = (usize)((val - val_hdr)) - hdr_len + 1; doc->str_pool = has_flag(INSITU) ? NULL : (char *)hdr; return doc; fail_string: return_err(cur, INVALID_STRING, msg); fail_number: return_err(cur, INVALID_NUMBER, msg); fail_alloc: return_err(cur, MEMORY_ALLOCATION, "memory allocation failed"); fail_trailing_comma: return_err(cur, JSON_STRUCTURE, "trailing comma is not allowed"); fail_literal: return_err(cur, LITERAL, "invalid literal"); fail_comment: return_err(cur, INVALID_COMMENT, "unclosed multiline comment"); fail_character: return_err(cur, UNEXPECTED_CHARACTER, "unexpected character"); fail_garbage: return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document"); #undef has_flag #undef val_incr #undef return_err } /*============================================================================== * JSON Reader Entrance *============================================================================*/ yyjson_doc *yyjson_read_opts(char *dat, usize len, yyjson_read_flag flg, const yyjson_alc *alc_ptr, yyjson_read_err *err) { #define has_flag(_flag) unlikely((flg & YYJSON_READ_##_flag) != 0) #define return_err(_pos, _code, _msg) do { \ err->pos = (usize)(_pos); \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ if (!has_flag(INSITU) && hdr) alc.free(alc.ctx, (void *)hdr); \ return NULL; \ } while (false) yyjson_read_err dummy_err; yyjson_alc alc; yyjson_doc *doc; u8 *hdr = NULL, *end, *cur; #if YYJSON_DISABLE_NON_STANDARD flg &= ~YYJSON_READ_ALLOW_TRAILING_COMMAS; flg &= ~YYJSON_READ_ALLOW_COMMENTS; flg &= ~YYJSON_READ_ALLOW_INF_AND_NAN; flg &= ~YYJSON_READ_ALLOW_INVALID_UNICODE; #endif /* validate input parameters */ if (!err) err = &dummy_err; if (likely(!alc_ptr)) { alc = YYJSON_DEFAULT_ALC; } else { alc = *alc_ptr; } if (unlikely(!dat)) { return_err(0, INVALID_PARAMETER, "input data is NULL"); } if (unlikely(!len)) { return_err(0, INVALID_PARAMETER, "input length is 0"); } /* add 4-byte zero padding for input data if necessary */ if (has_flag(INSITU)) { hdr = (u8 *)dat; end = (u8 *)dat + len; cur = (u8 *)dat; } else { if (unlikely(len >= USIZE_MAX - YYJSON_PADDING_SIZE)) { return_err(0, MEMORY_ALLOCATION, "memory allocation failed"); } hdr = (u8 *)alc.malloc(alc.ctx, len + YYJSON_PADDING_SIZE); if (unlikely(!hdr)) { return_err(0, MEMORY_ALLOCATION, "memory allocation failed"); } end = hdr + len; cur = hdr; memcpy(hdr, dat, len); memset(end, 0, YYJSON_PADDING_SIZE); } /* skip empty contents before json document */ if (unlikely(char_is_space_or_comment(*cur))) { if (has_flag(ALLOW_COMMENTS)) { if (!skip_spaces_and_comments(&cur)) { return_err(cur - hdr, INVALID_COMMENT, "unclosed multiline comment"); } } else { if (likely(char_is_space(*cur))) { while (char_is_space(*++cur)); } } if (unlikely(cur >= end)) { return_err(0, EMPTY_CONTENT, "input data is empty"); } } /* read json document */ if (likely(char_is_container(*cur))) { if (char_is_space(cur[1]) && char_is_space(cur[2])) { doc = read_root_pretty(hdr, cur, end, alc, flg, err); } else { doc = read_root_minify(hdr, cur, end, alc, flg, err); } } else { doc = read_root_single(hdr, cur, end, alc, flg, err); } /* check result */ if (likely(doc)) { memset(err, 0, sizeof(yyjson_read_err)); } else { /* RFC 8259: JSON text MUST be encoded using UTF-8 */ if (err->pos == 0 && err->code != YYJSON_READ_ERROR_MEMORY_ALLOCATION) { if ((hdr[0] == 0xEF && hdr[1] == 0xBB && hdr[2] == 0xBF)) { err->msg = "byte order mark (BOM) is not supported"; } else if (len >= 4 && ((hdr[0] == 0x00 && hdr[1] == 0x00 && hdr[2] == 0xFE && hdr[3] == 0xFF) || (hdr[0] == 0xFF && hdr[1] == 0xFE && hdr[2] == 0x00 && hdr[3] == 0x00))) { err->msg = "UTF-32 encoding is not supported"; } else if (len >= 2 && ((hdr[0] == 0xFE && hdr[1] == 0xFF) || (hdr[0] == 0xFF && hdr[1] == 0xFE))) { err->msg = "UTF-16 encoding is not supported"; } } if (!has_flag(INSITU)) alc.free(alc.ctx, (void *)hdr); } return doc; #undef has_flag #undef return_err } yyjson_doc *yyjson_read_file(const char *path, yyjson_read_flag flg, const yyjson_alc *alc_ptr, yyjson_read_err *err) { #define return_err(_code, _msg) do { \ err->pos = 0; \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ return NULL; \ } while (false) yyjson_read_err dummy_err; yyjson_doc *doc; FILE *file; if (!err) err = &dummy_err; if (unlikely(!path)) return_err(INVALID_PARAMETER, "input path is NULL"); file = fopen_readonly(path); if (unlikely(!file)) return_err(FILE_OPEN, "file opening failed"); doc = yyjson_read_fp(file, flg, alc_ptr, err); fclose(file); return doc; #undef return_err } yyjson_doc *yyjson_read_fp(FILE *file, yyjson_read_flag flg, const yyjson_alc *alc_ptr, yyjson_read_err *err) { #define return_err(_code, _msg) do { \ err->pos = 0; \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ if (buf) alc.free(alc.ctx, buf); \ return NULL; \ } while (false) yyjson_read_err dummy_err; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; yyjson_doc *doc; long file_size = 0, file_pos; void *buf = NULL; usize buf_size = 0; /* validate input parameters */ if (!err) err = &dummy_err; if (unlikely(!file)) return_err(INVALID_PARAMETER, "input file is NULL"); /* get current position */ file_pos = ftell(file); if (file_pos != -1) { /* get total file size, may fail */ if (fseek(file, 0, SEEK_END) == 0) file_size = ftell(file); /* reset to original position, may fail */ if (fseek(file, file_pos, SEEK_SET) != 0) file_size = 0; /* get file size from current postion to end */ if (file_size > 0) file_size -= file_pos; } /* read file */ if (file_size > 0) { /* read the entire file in one call */ buf_size = (usize)file_size + YYJSON_PADDING_SIZE; buf = alc.malloc(alc.ctx, buf_size); if (buf == NULL) { return_err(MEMORY_ALLOCATION, "fail to alloc memory"); } if (fread_safe(buf, (usize)file_size, file) != (usize)file_size) { return_err(FILE_READ, "file reading failed"); } } else { /* failed to get file size, read it as a stream */ usize chunk_min = (usize)64; usize chunk_max = (usize)512 * 1024 * 1024; usize chunk_now = chunk_min; usize read_size; void *tmp; buf_size = YYJSON_PADDING_SIZE; while (true) { if (buf_size + chunk_now < buf_size) { /* overflow */ return_err(MEMORY_ALLOCATION, "fail to alloc memory"); } buf_size += chunk_now; if (!buf) { buf = alc.malloc(alc.ctx, buf_size); if (!buf) return_err(MEMORY_ALLOCATION, "fail to alloc memory"); } else { tmp = alc.realloc(alc.ctx, buf, buf_size - chunk_now, buf_size); if (!tmp) return_err(MEMORY_ALLOCATION, "fail to alloc memory"); buf = tmp; } tmp = ((u8 *)buf) + buf_size - YYJSON_PADDING_SIZE - chunk_now; read_size = fread_safe(tmp, chunk_now, file); file_size += (long)read_size; if (read_size != chunk_now) break; chunk_now *= 2; if (chunk_now > chunk_max) chunk_now = chunk_max; } } /* read JSON */ memset((u8 *)buf + file_size, 0, YYJSON_PADDING_SIZE); flg |= YYJSON_READ_INSITU; doc = yyjson_read_opts((char *)buf, (usize)file_size, flg, &alc, err); if (doc) { doc->str_pool = (char *)buf; return doc; } else { alc.free(alc.ctx, buf); return NULL; } #undef return_err } const char *yyjson_read_number(const char *dat, yyjson_val *val, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err) { #define return_err(_pos, _code, _msg) do { \ err->pos = _pos > hdr ? (usize)(_pos - hdr) : 0; \ err->msg = _msg; \ err->code = YYJSON_READ_ERROR_##_code; \ return NULL; \ } while (false) u8 *hdr = constcast(u8 *)dat, *cur = hdr; bool raw; /* read number as raw */ u8 *raw_end; /* raw end for null-terminator */ u8 **pre; /* previous raw end pointer */ const char *msg; yyjson_read_err dummy_err; #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV u8 buf[128]; usize dat_len; #endif if (!err) err = &dummy_err; if (unlikely(!dat)) { return_err(cur, INVALID_PARAMETER, "input data is NULL"); } if (unlikely(!val)) { return_err(cur, INVALID_PARAMETER, "output value is NULL"); } #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV if (!alc) alc = &YYJSON_DEFAULT_ALC; dat_len = strlen(dat); if (dat_len < sizeof(buf)) { memcpy(buf, dat, dat_len + 1); hdr = buf; cur = hdr; } else { hdr = (u8 *)alc->malloc(alc->ctx, dat_len + 1); cur = hdr; if (unlikely(!hdr)) { return_err(cur, MEMORY_ALLOCATION, "memory allocation failed"); } memcpy(hdr, dat, dat_len + 1); } hdr[dat_len] = 0; #endif #if YYJSON_DISABLE_NON_STANDARD flg &= ~YYJSON_READ_ALLOW_INF_AND_NAN; #endif raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0; raw_end = NULL; pre = raw ? &raw_end : NULL; #if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV if (!read_number(&cur, pre, flg, val, &msg)) { if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr); return_err(cur, INVALID_NUMBER, msg); } if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr); if (yyjson_is_raw(val)) val->uni.str = dat; return dat + (cur - hdr); #else if (!read_number(&cur, pre, flg, val, &msg)) { return_err(cur, INVALID_NUMBER, msg); } return (const char *)cur; #endif #undef return_err } #endif /* YYJSON_DISABLE_READER */ #if !YYJSON_DISABLE_WRITER /*============================================================================== * Integer Writer * * The maximum value of uint32_t is 4294967295 (10 digits), * these digits are named as 'aabbccddee' here. * * Although most compilers may convert the "division by constant value" into * "multiply and shift", manual conversion can still help some compilers * generate fewer and better instructions. * * Reference: * Division by Invariant Integers using Multiplication, 1994. * https://gmplib.org/~tege/divcnst-pldi94.pdf * Improved division by invariant integers, 2011. * https://gmplib.org/~tege/division-paper.pdf *============================================================================*/ /** Digit table from 00 to 99. */ yyjson_align(2) static const char digit_table[200] = { '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' }; static_inline u8 *write_u32_len_8(u32 val, u8 *buf) { u32 aa, bb, cc, dd, aabb, ccdd; /* 8 digits: aabbccdd */ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ ccdd = val - aabb * 10000; /* (val % 10000) */ aa = (aabb * 5243) >> 19; /* (aabb / 100) */ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ ((v16 *)buf)[0] = ((const v16 *)digit_table)[aa]; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; return buf + 8; } static_inline u8 *write_u32_len_4(u32 val, u8 *buf) { u32 aa, bb; /* 4 digits: aabb */ aa = (val * 5243) >> 19; /* (val / 100) */ bb = val - aa * 100; /* (val % 100) */ ((v16 *)buf)[0] = ((const v16 *)digit_table)[aa]; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; return buf + 4; } static_inline u8 *write_u32_len_1_8(u32 val, u8 *buf) { u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz; if (val < 100) { /* 1-2 digits: aa */ lz = val < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (val * 2 + lz)); buf -= lz; return buf + 2; } else if (val < 10000) { /* 3-4 digits: aabb */ aa = (val * 5243) >> 19; /* (val / 100) */ bb = val - aa * 100; /* (val % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; return buf + 4; } else if (val < 1000000) { /* 5-6 digits: aabbcc */ aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */ bbcc = val - aa * 10000; /* (val % 10000) */ bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */ cc = bbcc - bb * 100; /* (bbcc % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; return buf + 6; } else { /* 7-8 digits: aabbccdd */ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ ccdd = val - aabb * 10000; /* (val % 10000) */ aa = (aabb * 5243) >> 19; /* (aabb / 100) */ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; return buf + 8; } } static_inline u8 *write_u64_len_5_8(u32 val, u8 *buf) { u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz; if (val < 1000000) { /* 5-6 digits: aabbcc */ aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */ bbcc = val - aa * 10000; /* (val % 10000) */ bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */ cc = bbcc - bb * 100; /* (bbcc % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; return buf + 6; } else { /* 7-8 digits: aabbccdd */ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */ ccdd = val - aabb * 10000; /* (val % 10000) */ aa = (aabb * 5243) >> 19; /* (aabb / 100) */ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */ bb = aabb - aa * 100; /* (aabb % 100) */ dd = ccdd - cc * 100; /* (ccdd % 100) */ lz = aa < 10; /* leading zero: 0 or 1 */ ((v16 *)buf)[0] = *(const v16 *)(digit_table + (aa * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[bb]; ((v16 *)buf)[2] = ((const v16 *)digit_table)[cc]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[dd]; return buf + 8; } } static_inline u8 *write_u64(u64 val, u8 *buf) { u64 tmp, hgh; u32 mid, low; if (val < 100000000) { /* 1-8 digits */ buf = write_u32_len_1_8((u32)val, buf); return buf; } else if (val < (u64)100000000 * 100000000) { /* 9-16 digits */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ buf = write_u32_len_1_8((u32)hgh, buf); buf = write_u32_len_8(low, buf); return buf; } else { /* 17-20 digits */ tmp = val / 100000000; /* (val / 100000000) */ low = (u32)(val - tmp * 100000000); /* (val % 100000000) */ hgh = (u32)(tmp / 10000); /* (tmp / 10000) */ mid = (u32)(tmp - hgh * 10000); /* (tmp % 10000) */ buf = write_u64_len_5_8((u32)hgh, buf); buf = write_u32_len_4(mid, buf); buf = write_u32_len_8(low, buf); return buf; } } /*============================================================================== * Number Writer *============================================================================*/ #if YYJSON_HAS_IEEE_754 && !YYJSON_DISABLE_FAST_FP_CONV /* FP_WRITER */ /** Trailing zero count table for number 0 to 99. (generate with misc/make_tables.c) */ static const u8 dec_trailing_zero_table[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /** Write an unsigned integer with a length of 1 to 16. */ static_inline u8 *write_u64_len_1_to_16(u64 val, u8 *buf) { u64 hgh; u32 low; if (val < 100000000) { /* 1-8 digits */ buf = write_u32_len_1_8((u32)val, buf); return buf; } else { /* 9-16 digits */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ buf = write_u32_len_1_8((u32)hgh, buf); buf = write_u32_len_8(low, buf); return buf; } } /** Write an unsigned integer with a length of 1 to 17. */ static_inline u8 *write_u64_len_1_to_17(u64 val, u8 *buf) { u64 hgh; u32 mid, low, one; if (val >= (u64)100000000 * 10000000) { /* len: 16 to 17 */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ one = (u32)(hgh / 100000000); /* (hgh / 100000000) */ mid = (u32)(hgh - (u64)one * 100000000); /* (hgh % 100000000) */ *buf = (u8)((u8)one + (u8)'0'); buf += one > 0; buf = write_u32_len_8(mid, buf); buf = write_u32_len_8(low, buf); return buf; } else if (val >= (u64)100000000){ /* len: 9 to 15 */ hgh = val / 100000000; /* (val / 100000000) */ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */ buf = write_u32_len_1_8((u32)hgh, buf); buf = write_u32_len_8(low, buf); return buf; } else { /* len: 1 to 8 */ buf = write_u32_len_1_8((u32)val, buf); return buf; } } /** Write an unsigned integer with a length of 15 to 17 with trailing zero trimmed. These digits are named as "aabbccddeeffgghhii" here. For example, input 1234567890123000, output "1234567890123". */ static_inline u8 *write_u64_len_15_to_17_trim(u8 *buf, u64 sig) { bool lz; /* leading zero */ u32 tz1, tz2, tz; /* trailing zero */ u32 abbccddee = (u32)(sig / 100000000); u32 ffgghhii = (u32)(sig - (u64)abbccddee * 100000000); u32 abbcc = abbccddee / 10000; /* (abbccddee / 10000) */ u32 ddee = abbccddee - abbcc * 10000; /* (abbccddee % 10000) */ u32 abb = (u32)(((u64)abbcc * 167773) >> 24); /* (abbcc / 100) */ u32 a = (abb * 41) >> 12; /* (abb / 100) */ u32 bb = abb - a * 100; /* (abb % 100) */ u32 cc = abbcc - abb * 100; /* (abbcc % 100) */ /* write abbcc */ buf[0] = (u8)(a + '0'); buf += a > 0; lz = bb < 10 && a == 0; ((v16 *)buf)[0] = *(const v16 *)(digit_table + (bb * 2 + lz)); buf -= lz; ((v16 *)buf)[1] = ((const v16 *)digit_table)[cc]; if (ffgghhii) { u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ u32 ee = ddee - dd * 100; /* (ddee % 100) */ u32 ffgg = (u32)(((u64)ffgghhii * 109951163) >> 40); /* (val / 10000) */ u32 hhii = ffgghhii - ffgg * 10000; /* (val % 10000) */ u32 ff = (ffgg * 5243) >> 19; /* (aabb / 100) */ u32 gg = ffgg - ff * 100; /* (aabb % 100) */ ((v16 *)buf)[2] = ((const v16 *)digit_table)[dd]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[ee]; ((v16 *)buf)[4] = ((const v16 *)digit_table)[ff]; ((v16 *)buf)[5] = ((const v16 *)digit_table)[gg]; if (hhii) { u32 hh = (hhii * 5243) >> 19; /* (ccdd / 100) */ u32 ii = hhii - hh * 100; /* (ccdd % 100) */ ((v16 *)buf)[6] = ((const v16 *)digit_table)[hh]; ((v16 *)buf)[7] = ((const v16 *)digit_table)[ii]; tz1 = dec_trailing_zero_table[hh]; tz2 = dec_trailing_zero_table[ii]; tz = ii ? tz2 : (tz1 + 2); buf += 16 - tz; return buf; } else { tz1 = dec_trailing_zero_table[ff]; tz2 = dec_trailing_zero_table[gg]; tz = gg ? tz2 : (tz1 + 2); buf += 12 - tz; return buf; } } else { if (ddee) { u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */ u32 ee = ddee - dd * 100; /* (ddee % 100) */ ((v16 *)buf)[2] = ((const v16 *)digit_table)[dd]; ((v16 *)buf)[3] = ((const v16 *)digit_table)[ee]; tz1 = dec_trailing_zero_table[dd]; tz2 = dec_trailing_zero_table[ee]; tz = ee ? tz2 : (tz1 + 2); buf += 8 - tz; return buf; } else { tz1 = dec_trailing_zero_table[bb]; tz2 = dec_trailing_zero_table[cc]; tz = cc ? tz2 : (tz1 + tz2); buf += 4 - tz; return buf; } } } /** Write a signed integer in the range -324 to 308. */ static_inline u8 *write_f64_exp(i32 exp, u8 *buf) { buf[0] = '-'; buf += exp < 0; exp = exp < 0 ? -exp : exp; if (exp < 100) { u32 lz = exp < 10; *(v16 *)&buf[0] = *(const v16 *)(digit_table + ((u32)exp * 2 + lz)); return buf + 2 - lz; } else { u32 hi = ((u32)exp * 656) >> 16; /* exp / 100 */ u32 lo = (u32)exp - hi * 100; /* exp % 100 */ buf[0] = (u8)((u8)hi + (u8)'0'); *(v16 *)&buf[1] = *(const v16 *)(digit_table + (lo * 2)); return buf + 3; } } /** Multiplies 128-bit integer and returns highest 64-bit rounded value. */ static_inline u64 round_to_odd(u64 hi, u64 lo, u64 cp) { u64 x_hi, x_lo, y_hi, y_lo; u128_mul(cp, lo, &x_hi, &x_lo); u128_mul_add(cp, hi, x_hi, &y_hi, &y_lo); return y_hi | (y_lo > 1); } /** Convert double number from binary to decimal. The output significand is shortest decimal but may have trailing zeros. This function use the Schubfach algorithm: Raffaello Giulietti, The Schubfach way to render doubles (5th version), 2022. https://drive.google.com/file/d/1gp5xv4CAa78SVgCeWfGqqI4FfYYYuNFb https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-November/083536.html https://github.com/openjdk/jdk/pull/3402 (Java implementation) https://github.com/abolz/Drachennest (C++ implementation) See also: Dragonbox: A New Floating-Point Binary-to-Decimal Conversion Algorithm, 2022. https://github.com/jk-jeon/dragonbox/blob/master/other_files/Dragonbox.pdf https://github.com/jk-jeon/dragonbox @param sig_raw The raw value of significand in IEEE 754 format. @param exp_raw The raw value of exponent in IEEE 754 format. @param sig_bin The decoded value of significand in binary. @param exp_bin The decoded value of exponent in binary. @param sig_dec The output value of significand in decimal. @param exp_dec The output value of exponent in decimal. @warning The input double number should not be 0, inf, nan. */ static_inline void f64_bin_to_dec(u64 sig_raw, u32 exp_raw, u64 sig_bin, i32 exp_bin, u64 *sig_dec, i32 *exp_dec) { bool is_even, regular_spacing, u_inside, w_inside, round_up; u64 s, sp, cb, cbl, cbr, vb, vbl, vbr, pow10hi, pow10lo, upper, lower, mid; i32 k, h, exp10; is_even = !(sig_bin & 1); regular_spacing = (sig_raw == 0 && exp_raw > 1); cbl = 4 * sig_bin - 2 + regular_spacing; cb = 4 * sig_bin; cbr = 4 * sig_bin + 2; /* exp_bin: [-1074, 971] */ /* k = regular_spacing ? floor(log10(pow(2, exp_bin))) */ /* : floor(log10(pow(2, exp_bin) * 3.0 / 4.0)) */ /* = regular_spacing ? floor(exp_bin * log10(2)) */ /* : floor(exp_bin * log10(2) + log10(3.0 / 4.0)) */ k = (i32)(exp_bin * 315653 - (regular_spacing ? 131237 : 0)) >> 20; /* k: [-324, 292] */ /* h = exp_bin + floor(log2(pow(10, e))) */ /* = exp_bin + floor(log2(10) * e) */ exp10 = -k; h = exp_bin + ((exp10 * 217707) >> 16) + 1; pow10_table_get_sig(exp10, &pow10hi, &pow10lo); pow10lo += (exp10 < POW10_SIG_TABLE_MIN_EXACT_EXP || exp10 > POW10_SIG_TABLE_MAX_EXACT_EXP); vbl = round_to_odd(pow10hi, pow10lo, cbl << h); vb = round_to_odd(pow10hi, pow10lo, cb << h); vbr = round_to_odd(pow10hi, pow10lo, cbr << h); lower = vbl + !is_even; upper = vbr - !is_even; s = vb / 4; if (s >= 10) { sp = s / 10; u_inside = (lower <= 40 * sp); w_inside = (upper >= 40 * sp + 40); if (u_inside != w_inside) { *sig_dec = sp + w_inside; *exp_dec = k + 1; return; } } u_inside = (lower <= 4 * s); w_inside = (upper >= 4 * s + 4); mid = 4 * s + 2; round_up = (vb > mid) || (vb == mid && (s & 1) != 0); *sig_dec = s + ((u_inside != w_inside) ? w_inside : round_up); *exp_dec = k; } /** Write a double number (requires 32 bytes buffer). We follows the ECMAScript specification to print floating point numbers, but with the following changes: 1. Keep the negative sign of 0.0 to preserve input information. 2. Keep decimal point to indicate the number is floating point. 3. Remove positive sign of exponent part. */ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { u64 sig_bin, sig_dec, sig_raw; i32 exp_bin, exp_dec, sig_len, dot_pos, i, max; u32 exp_raw, hi, lo; u8 *hdr, *num_hdr, *num_end, *dot_end; bool sign; /* decode raw bytes from IEEE-754 double format. */ sign = (bool)(raw >> (F64_BITS - 1)); sig_raw = raw & F64_SIG_MASK; exp_raw = (u32)((raw & F64_EXP_MASK) >> F64_SIG_BITS); /* return inf and nan */ if (unlikely(exp_raw == ((u32)1 << F64_EXP_BITS) - 1)) { if (flg & YYJSON_WRITE_INF_AND_NAN_AS_NULL) { byte_copy_4(buf, "null"); return buf + 4; } else if (flg & YYJSON_WRITE_ALLOW_INF_AND_NAN) { if (sig_raw == 0) { buf[0] = '-'; buf += sign; byte_copy_8(buf, "Infinity"); buf += 8; return buf; } else { byte_copy_4(buf, "NaN"); return buf + 3; } } else { return NULL; } } /* add sign for all finite double value, including 0.0 and inf */ buf[0] = '-'; buf += sign; hdr = buf; /* return zero */ if ((raw << 1) == 0) { byte_copy_4(buf, "0.0"); buf += 3; return buf; } if (likely(exp_raw != 0)) { /* normal number */ sig_bin = sig_raw | ((u64)1 << F64_SIG_BITS); exp_bin = (i32)exp_raw - F64_EXP_BIAS - F64_SIG_BITS; /* fast path for small integer number without fraction */ if (-F64_SIG_BITS <= exp_bin && exp_bin <= 0) { if (u64_tz_bits(sig_bin) >= (u32)-exp_bin) { /* number is integer in range 1 to 0x1FFFFFFFFFFFFF */ sig_dec = sig_bin >> -exp_bin; buf = write_u64_len_1_to_16(sig_dec, buf); byte_copy_2(buf, ".0"); buf += 2; return buf; } } /* binary to decimal */ f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); /* the sig length is 15 to 17 */ sig_len = 17; sig_len -= (sig_dec < (u64)100000000 * 100000000); sig_len -= (sig_dec < (u64)100000000 * 10000000); /* the decimal point position relative to the first digit */ dot_pos = sig_len + exp_dec; if (-6 < dot_pos && dot_pos <= 21) { /* no need to write exponent part */ if (dot_pos <= 0) { /* dot before first digit */ /* such as 0.1234, 0.000001234 */ num_hdr = hdr + (2 - dot_pos); num_end = write_u64_len_15_to_17_trim(num_hdr, sig_dec); hdr[0] = '0'; hdr[1] = '.'; hdr += 2; max = -dot_pos; for (i = 0; i < max; i++) hdr[i] = '0'; return num_end; } else { /* dot after first digit */ /* such as 1.234, 1234.0, 123400000000000000000.0 */ memset(hdr + 0, '0', 8); memset(hdr + 8, '0', 8); memset(hdr + 16, '0', 8); num_hdr = hdr + 1; num_end = write_u64_len_15_to_17_trim(num_hdr, sig_dec); for (i = 0; i < dot_pos; i++) hdr[i] = hdr[i + 1]; hdr[dot_pos] = '.'; dot_end = hdr + dot_pos + 2; return dot_end < num_end ? num_end : dot_end; } } else { /* write with scientific notation */ /* such as 1.234e56 */ u8 *end = write_u64_len_15_to_17_trim(buf + 1, sig_dec); end -= (end == buf + 2); /* remove '.0', e.g. 2.0e34 -> 2e34 */ exp_dec += sig_len - 1; hdr[0] = hdr[1]; hdr[1] = '.'; end[0] = 'e'; buf = write_f64_exp(exp_dec, end + 1); return buf; } } else { /* subnormal number */ sig_bin = sig_raw; exp_bin = 1 - F64_EXP_BIAS - F64_SIG_BITS; /* binary to decimal */ f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec); /* write significand part */ buf = write_u64_len_1_to_17(sig_dec, buf + 1); hdr[0] = hdr[1]; hdr[1] = '.'; do { buf--; exp_dec++; } while (*buf == '0'); exp_dec += (i32)(buf - hdr - 2); buf += (*buf != '.'); buf[0] = 'e'; buf++; /* write exponent part */ buf[0] = '-'; buf++; exp_dec = -exp_dec; hi = ((u32)exp_dec * 656) >> 16; /* exp / 100 */ lo = (u32)exp_dec - hi * 100; /* exp % 100 */ buf[0] = (u8)((u8)hi + (u8)'0'); *(v16 *)&buf[1] = *(const v16 *)(digit_table + (lo * 2)); buf += 3; return buf; } } #else /* FP_WRITER */ /** Write a double number (requires 32 bytes buffer). */ static_noinline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) { /* For IEEE 754, `DBL_DECIMAL_DIG` is 17 for round-trip. For non-IEEE formats, 17 is used to avoid buffer overflow, round-trip is not guaranteed. */ #if defined(DBL_DECIMAL_DIG) && DBL_DECIMAL_DIG != 17 int dig = DBL_DECIMAL_DIG > 17 ? 17 : DBL_DECIMAL_DIG; #else int dig = 17; #endif /* The snprintf() function is locale-dependent. For currently known locales, (en, zh, ja, ko, am, he, hi) use '.' as the decimal point, while other locales use ',' as the decimal point. we need to replace ',' with '.' to avoid the locale setting. */ f64 val = f64_from_raw(raw); #if YYJSON_MSC_VER >= 1400 int len = sprintf_s((char *)buf, 32, "%.*g", dig, val); #elif defined(snprintf) || (YYJSON_STDC_VER >= 199901L) int len = snprintf((char *)buf, 32, "%.*g", dig, val); #else int len = sprintf((char *)buf, "%.*g", dig, val); #endif u8 *cur = buf; if (unlikely(len < 1)) return NULL; cur += (*cur == '-'); if (unlikely(!digi_is_digit(*cur))) { /* nan, inf, or bad output */ if (flg & YYJSON_WRITE_INF_AND_NAN_AS_NULL) { byte_copy_4(buf, "null"); return buf + 4; } else if (flg & YYJSON_WRITE_ALLOW_INF_AND_NAN) { if (*cur == 'i') { byte_copy_8(cur, "Infinity"); cur += 8; return cur; } else if (*cur == 'n') { byte_copy_4(buf, "NaN"); return buf + 3; } } return NULL; } else { /* finite number */ int i = 0; bool fp = false; for (; i < len; i++) { if (buf[i] == ',') buf[i] = '.'; if (digi_is_fp((u8)buf[i])) fp = true; } if (!fp) { buf[len++] = '.'; buf[len++] = '0'; } } return buf + len; } #endif /* FP_WRITER */ /** Write a JSON number (requires 32 bytes buffer). */ static_inline u8 *write_number(u8 *cur, yyjson_val *val, yyjson_write_flag flg) { if (val->tag & YYJSON_SUBTYPE_REAL) { u64 raw = val->uni.u64; return write_f64_raw(cur, raw, flg); } else { u64 pos = val->uni.u64; u64 neg = ~pos + 1; usize sgn = ((val->tag & YYJSON_SUBTYPE_SINT) > 0) & ((i64)pos < 0); *cur = '-'; return write_u64(sgn ? neg : pos, cur + sgn); } } /*============================================================================== * String Writer *============================================================================*/ /** Character encode type, if (type > CHAR_ENC_ERR_1) bytes = type / 2; */ typedef u8 char_enc_type; #define CHAR_ENC_CPY_1 0 /* 1-byte UTF-8, copy. */ #define CHAR_ENC_ERR_1 1 /* 1-byte UTF-8, error. */ #define CHAR_ENC_ESC_A 2 /* 1-byte ASCII, escaped as '\x'. */ #define CHAR_ENC_ESC_1 3 /* 1-byte UTF-8, escaped as '\uXXXX'. */ #define CHAR_ENC_CPY_2 4 /* 2-byte UTF-8, copy. */ #define CHAR_ENC_ESC_2 5 /* 2-byte UTF-8, escaped as '\uXXXX'. */ #define CHAR_ENC_CPY_3 6 /* 3-byte UTF-8, copy. */ #define CHAR_ENC_ESC_3 7 /* 3-byte UTF-8, escaped as '\uXXXX'. */ #define CHAR_ENC_CPY_4 8 /* 4-byte UTF-8, copy. */ #define CHAR_ENC_ESC_4 9 /* 4-byte UTF-8, escaped as '\uXXXX\uXXXX'. */ /** Character encode type table: don't escape unicode, don't escape '/'. (generate with misc/make_tables.c) */ static const char_enc_type enc_table_cpy[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1 }; /** Character encode type table: don't escape unicode, escape '/'. (generate with misc/make_tables.c) */ static const char_enc_type enc_table_cpy_slash[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1 }; /** Character encode type table: escape unicode, don't escape '/'. (generate with misc/make_tables.c) */ static const char_enc_type enc_table_esc[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1 }; /** Character encode type table: escape unicode, escape '/'. (generate with misc/make_tables.c) */ static const char_enc_type enc_table_esc_slash[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1 }; /** Escaped hex character table: ["00" "01" "02" ... "FD" "FE" "FF"]. (generate with misc/make_tables.c) */ yyjson_align(2) static const u8 esc_hex_char_table[512] = { '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '0', 'A', '0', 'B', '0', 'C', '0', 'D', '0', 'E', '0', 'F', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '1', 'A', '1', 'B', '1', 'C', '1', 'D', '1', 'E', '1', 'F', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '2', 'A', '2', 'B', '2', 'C', '2', 'D', '2', 'E', '2', 'F', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '3', 'A', '3', 'B', '3', 'C', '3', 'D', '3', 'E', '3', 'F', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '4', 'A', '4', 'B', '4', 'C', '4', 'D', '4', 'E', '4', 'F', '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', '5', 'A', '5', 'B', '5', 'C', '5', 'D', '5', 'E', '5', 'F', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', '6', 'A', '6', 'B', '6', 'C', '6', 'D', '6', 'E', '6', 'F', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '7', 'A', '7', 'B', '7', 'C', '7', 'D', '7', 'E', '7', 'F', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '8', 'A', '8', 'B', '8', 'C', '8', 'D', '8', 'E', '8', 'F', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9', '9', 'A', '9', 'B', '9', 'C', '9', 'D', '9', 'E', '9', 'F', 'A', '0', 'A', '1', 'A', '2', 'A', '3', 'A', '4', 'A', '5', 'A', '6', 'A', '7', 'A', '8', 'A', '9', 'A', 'A', 'A', 'B', 'A', 'C', 'A', 'D', 'A', 'E', 'A', 'F', 'B', '0', 'B', '1', 'B', '2', 'B', '3', 'B', '4', 'B', '5', 'B', '6', 'B', '7', 'B', '8', 'B', '9', 'B', 'A', 'B', 'B', 'B', 'C', 'B', 'D', 'B', 'E', 'B', 'F', 'C', '0', 'C', '1', 'C', '2', 'C', '3', 'C', '4', 'C', '5', 'C', '6', 'C', '7', 'C', '8', 'C', '9', 'C', 'A', 'C', 'B', 'C', 'C', 'C', 'D', 'C', 'E', 'C', 'F', 'D', '0', 'D', '1', 'D', '2', 'D', '3', 'D', '4', 'D', '5', 'D', '6', 'D', '7', 'D', '8', 'D', '9', 'D', 'A', 'D', 'B', 'D', 'C', 'D', 'D', 'D', 'E', 'D', 'F', 'E', '0', 'E', '1', 'E', '2', 'E', '3', 'E', '4', 'E', '5', 'E', '6', 'E', '7', 'E', '8', 'E', '9', 'E', 'A', 'E', 'B', 'E', 'C', 'E', 'D', 'E', 'E', 'E', 'F', 'F', '0', 'F', '1', 'F', '2', 'F', '3', 'F', '4', 'F', '5', 'F', '6', 'F', '7', 'F', '8', 'F', '9', 'F', 'A', 'F', 'B', 'F', 'C', 'F', 'D', 'F', 'E', 'F', 'F' }; /** Escaped single character table. (generate with misc/make_tables.c) */ yyjson_align(2) static const u8 esc_single_char_table[512] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\\', 'b', '\\', 't', '\\', 'n', ' ', ' ', '\\', 'f', '\\', 'r', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\\', '"', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\\', '/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\\', '\\', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; /** Returns the encode table with options. */ static_inline const char_enc_type *get_enc_table_with_flag( yyjson_read_flag flg) { if (unlikely(flg & YYJSON_WRITE_ESCAPE_UNICODE)) { if (unlikely(flg & YYJSON_WRITE_ESCAPE_SLASHES)) { return enc_table_esc_slash; } else { return enc_table_esc; } } else { if (unlikely(flg & YYJSON_WRITE_ESCAPE_SLASHES)) { return enc_table_cpy_slash; } else { return enc_table_cpy; } } } /** Write raw string. */ static_inline u8 *write_raw(u8 *cur, const u8 *raw, usize raw_len) { memcpy(cur, raw, raw_len); return cur + raw_len; } /** Write UTF-8 string (requires len * 6 + 2 bytes buffer). @param cur Buffer cursor. @param esc Escape unicode. @param inv Allow invalid unicode. @param str A UTF-8 string, null-terminator is not required. @param str_len Length of string in bytes. @param enc_table Encode type table for character. @return The buffer cursor after string, or NULL on invalid unicode. */ static_inline u8 *write_string(u8 *cur, bool esc, bool inv, const u8 *str, usize str_len, const char_enc_type *enc_table) { /* UTF-8 character mask and pattern, see `read_string()` for details. */ #if YYJSON_ENDIAN == YYJSON_BIG_ENDIAN const u16 b2_mask = 0xE0C0UL; const u16 b2_patt = 0xC080UL; const u16 b2_requ = 0x1E00UL; const u32 b3_mask = 0xF0C0C000UL; const u32 b3_patt = 0xE0808000UL; const u32 b3_requ = 0x0F200000UL; const u32 b3_erro = 0x0D200000UL; const u32 b4_mask = 0xF8C0C0C0UL; const u32 b4_patt = 0xF0808080UL; const u32 b4_requ = 0x07300000UL; const u32 b4_err0 = 0x04000000UL; const u32 b4_err1 = 0x03300000UL; #elif YYJSON_ENDIAN == YYJSON_LITTLE_ENDIAN const u16 b2_mask = 0xC0E0UL; const u16 b2_patt = 0x80C0UL; const u16 b2_requ = 0x001EUL; const u32 b3_mask = 0x00C0C0F0UL; const u32 b3_patt = 0x008080E0UL; const u32 b3_requ = 0x0000200FUL; const u32 b3_erro = 0x0000200DUL; const u32 b4_mask = 0xC0C0C0F8UL; const u32 b4_patt = 0x808080F0UL; const u32 b4_requ = 0x00003007UL; const u32 b4_err0 = 0x00000004UL; const u32 b4_err1 = 0x00003003UL; #else v16_uni b2_mask_uni = {{ 0xE0, 0xC0 }}; v16_uni b2_patt_uni = {{ 0xC0, 0x80 }}; v16_uni b2_requ_uni = {{ 0x1E, 0x00 }}; v32_uni b3_mask_uni = {{ 0xF0, 0xC0, 0xC0, 0x00 }}; v32_uni b3_patt_uni = {{ 0xE0, 0x80, 0x80, 0x00 }}; v32_uni b3_requ_uni = {{ 0x0F, 0x20, 0x00, 0x00 }}; v32_uni b3_erro_uni = {{ 0x0D, 0x20, 0x00, 0x00 }}; v32_uni b4_mask_uni = {{ 0xF8, 0xC0, 0xC0, 0xC0 }}; v32_uni b4_patt_uni = {{ 0xF0, 0x80, 0x80, 0x80 }}; v32_uni b4_requ_uni = {{ 0x07, 0x30, 0x00, 0x00 }}; v32_uni b4_err0_uni = {{ 0x04, 0x00, 0x00, 0x00 }}; v32_uni b4_err1_uni = {{ 0x03, 0x30, 0x00, 0x00 }}; u16 b2_mask = b2_mask_uni.u; u16 b2_patt = b2_patt_uni.u; u16 b2_requ = b2_requ_uni.u; u32 b3_mask = b3_mask_uni.u; u32 b3_patt = b3_patt_uni.u; u32 b3_requ = b3_requ_uni.u; u32 b3_erro = b3_erro_uni.u; u32 b4_mask = b4_mask_uni.u; u32 b4_patt = b4_patt_uni.u; u32 b4_requ = b4_requ_uni.u; u32 b4_err0 = b4_err0_uni.u; u32 b4_err1 = b4_err1_uni.u; #endif #define is_valid_seq_2(uni) ( \ ((uni & b2_mask) == b2_patt) && \ ((uni & b2_requ)) \ ) #define is_valid_seq_3(uni) ( \ ((uni & b3_mask) == b3_patt) && \ ((tmp = (uni & b3_requ))) && \ ((tmp != b3_erro)) \ ) #define is_valid_seq_4(uni) ( \ ((uni & b4_mask) == b4_patt) && \ ((tmp = (uni & b4_requ))) && \ ((tmp & b4_err0) == 0 || (tmp & b4_err1) == 0) \ ) /* The replacement character U+FFFD, used to indicate invalid character. */ const v32 rep = { 'F', 'F', 'F', 'D' }; const v32 pre = { '\\', 'u', '0', '0' }; const u8 *src = str; const u8 *end = str + str_len; *cur++ = '"'; copy_ascii: /* Copy continuous ASCII, loop unrolling, same as the following code: while (end > src) ( if (unlikely(enc_table[*src])) break; *cur++ = *src++; ); */ #define expr_jump(i) \ if (unlikely(enc_table[src[i]])) goto stop_char_##i; #define expr_stop(i) \ stop_char_##i: \ memcpy(cur, src, i); \ cur += i; src += i; goto copy_utf8; while (end - src >= 16) { repeat16_incr(expr_jump) byte_copy_16(cur, src); cur += 16; src += 16; } while (end - src >= 4) { repeat4_incr(expr_jump) byte_copy_4(cur, src); cur += 4; src += 4; } while (end > src) { expr_jump(0) *cur++ = *src++; } *cur++ = '"'; return cur; repeat16_incr(expr_stop) #undef expr_jump #undef expr_stop copy_utf8: if (unlikely(src + 4 > end)) { if (end == src) goto copy_end; if (end - src < enc_table[*src] / 2) goto err_one; } switch (enc_table[*src]) { case CHAR_ENC_CPY_1: { *cur++ = *src++; goto copy_ascii; } case CHAR_ENC_CPY_2: { u16 v; v = byte_load_2(src); if (unlikely(!is_valid_seq_2(v))) goto err_cpy; byte_copy_2(cur, src); cur += 2; src += 2; goto copy_utf8; } case CHAR_ENC_CPY_3: { u32 v, tmp; if (likely(src + 4 <= end)) { v = byte_load_4(src); if (unlikely(!is_valid_seq_3(v))) goto err_cpy; byte_copy_4(cur, src); } else { v = byte_load_3(src); if (unlikely(!is_valid_seq_3(v))) goto err_cpy; byte_copy_4(cur, &v); } cur += 3; src += 3; goto copy_utf8; } case CHAR_ENC_CPY_4: { u32 v, tmp; v = byte_load_4(src); if (unlikely(!is_valid_seq_4(v))) goto err_cpy; byte_copy_4(cur, src); cur += 4; src += 4; goto copy_utf8; } case CHAR_ENC_ESC_A: { byte_move_2(cur, &esc_single_char_table[*src * 2]); cur += 2; src += 1; goto copy_utf8; } case CHAR_ENC_ESC_1: { byte_copy_4(cur + 0, &pre); byte_copy_2(cur + 4, &esc_hex_char_table[*src * 2]); cur += 6; src += 1; goto copy_utf8; } case CHAR_ENC_ESC_2: { u16 u, v; v = byte_load_2(src); if (unlikely(!is_valid_seq_2(v))) goto err_esc; u = (u16)(((u16)(src[0] & 0x1F) << 6) | ((u16)(src[1] & 0x3F) << 0)); byte_copy_2(cur + 0, &pre); byte_copy_2(cur + 2, &esc_hex_char_table[(u >> 8) * 2]); byte_copy_2(cur + 4, &esc_hex_char_table[(u & 0xFF) * 2]); cur += 6; src += 2; goto copy_utf8; } case CHAR_ENC_ESC_3: { u16 u; u32 v, tmp; v = byte_load_3(src); if (unlikely(!is_valid_seq_3(v))) goto err_esc; u = (u16)(((u16)(src[0] & 0x0F) << 12) | ((u16)(src[1] & 0x3F) << 6) | ((u16)(src[2] & 0x3F) << 0)); byte_copy_2(cur + 0, &pre); byte_copy_2(cur + 2, &esc_hex_char_table[(u >> 8) * 2]); byte_copy_2(cur + 4, &esc_hex_char_table[(u & 0xFF) * 2]); cur += 6; src += 3; goto copy_utf8; } case CHAR_ENC_ESC_4: { u32 hi, lo, u, v, tmp; v = byte_load_4(src); if (unlikely(!is_valid_seq_4(v))) goto err_esc; u = ((u32)(src[0] & 0x07) << 18) | ((u32)(src[1] & 0x3F) << 12) | ((u32)(src[2] & 0x3F) << 6) | ((u32)(src[3] & 0x3F) << 0); u -= 0x10000; hi = (u >> 10) + 0xD800; lo = (u & 0x3FF) + 0xDC00; byte_copy_2(cur + 0, &pre); byte_copy_2(cur + 2, &esc_hex_char_table[(hi >> 8) * 2]); byte_copy_2(cur + 4, &esc_hex_char_table[(hi & 0xFF) * 2]); byte_copy_2(cur + 6, &pre); byte_copy_2(cur + 8, &esc_hex_char_table[(lo >> 8) * 2]); byte_copy_2(cur + 10, &esc_hex_char_table[(lo & 0xFF) * 2]); cur += 12; src += 4; goto copy_utf8; } case CHAR_ENC_ERR_1: { goto err_one; } default: break; } copy_end: *cur++ = '"'; return cur; err_one: if (esc) goto err_esc; else goto err_cpy; err_cpy: if (!inv) return NULL; *cur++ = *src++; goto copy_utf8; err_esc: if (!inv) return NULL; byte_copy_2(cur + 0, &pre); byte_copy_4(cur + 2, &rep); cur += 6; src += 1; goto copy_utf8; #undef is_valid_seq_2 #undef is_valid_seq_3 #undef is_valid_seq_4 } /*============================================================================== * Writer Utilities *============================================================================*/ /** Write null (requires 8 bytes buffer). */ static_inline u8 *write_null(u8 *cur) { v64 v = { 'n', 'u', 'l', 'l', ',', '\n', 0, 0 }; byte_copy_8(cur, &v); return cur + 4; } /** Write bool (requires 8 bytes buffer). */ static_inline u8 *write_bool(u8 *cur, bool val) { v64 v0 = { 'f', 'a', 'l', 's', 'e', ',', '\n', 0 }; v64 v1 = { 't', 'r', 'u', 'e', ',', '\n', 0, 0 }; if (val) { byte_copy_8(cur, &v1); } else { byte_copy_8(cur, &v0); } return cur + 5 - val; } /** Write indent (requires level x 4 bytes buffer). Param spaces should not larger than 4. */ static_inline u8 *write_indent(u8 *cur, usize level, usize spaces) { while (level-- > 0) { byte_copy_4(cur, " "); cur += spaces; } return cur; } /** Write data to file pointer. */ static bool write_dat_to_fp(FILE *fp, u8 *dat, usize len, yyjson_write_err *err) { if (fwrite(dat, len, 1, fp) != 1) { err->msg = "file writing failed"; err->code = YYJSON_WRITE_ERROR_FILE_WRITE; return false; } return true; } /** Write data to file. */ static bool write_dat_to_file(const char *path, u8 *dat, usize len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ err->msg = _msg; \ err->code = YYJSON_WRITE_ERROR_##_code; \ if (file) fclose(file); \ return false; \ } while (false) FILE *file = fopen_writeonly(path); if (file == NULL) { return_err(FILE_OPEN, "file opening failed"); } if (fwrite(dat, len, 1, file) != 1) { return_err(FILE_WRITE, "file writing failed"); } if (fclose(file) != 0) { file = NULL; return_err(FILE_WRITE, "file closing failed"); } return true; #undef return_err } /*============================================================================== * JSON Writer Implementation *============================================================================*/ typedef struct yyjson_write_ctx { usize tag; } yyjson_write_ctx; static_inline void yyjson_write_ctx_set(yyjson_write_ctx *ctx, usize size, bool is_obj) { ctx->tag = (size << 1) | (usize)is_obj; } static_inline void yyjson_write_ctx_get(yyjson_write_ctx *ctx, usize *size, bool *is_obj) { usize tag = ctx->tag; *size = tag >> 1; *is_obj = (bool)(tag & 1); } /** Write single JSON value. */ static_inline u8 *yyjson_write_single(yyjson_val *val, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ if (hdr) alc.free(alc.ctx, (void *)hdr); \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ return NULL; \ } while (false) #define incr_len(_len) do { \ hdr = (u8 *)alc.malloc(alc.ctx, _len); \ if (!hdr) goto fail_alloc; \ cur = hdr; \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) u8 *hdr = NULL, *cur; usize str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; switch (unsafe_yyjson_get_type(val)) { case YYJSON_TYPE_RAW: str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 1); cur = write_raw(cur, str_ptr, str_len); break; case YYJSON_TYPE_STR: str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 4); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; break; case YYJSON_TYPE_NUM: incr_len(32); cur = write_number(cur, val, flg); if (unlikely(!cur)) goto fail_num; break; case YYJSON_TYPE_BOOL: incr_len(8); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); break; case YYJSON_TYPE_NULL: incr_len(8); cur = write_null(cur); break; case YYJSON_TYPE_ARR: incr_len(4); byte_copy_2(cur, "[]"); cur += 2; break; case YYJSON_TYPE_OBJ: incr_len(4); byte_copy_2(cur, "{}"); cur += 2; break; default: goto fail_type; } *cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef check_str_len #undef incr_len } /** Write JSON document minify. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_write_minify(const yyjson_val *root, const yyjson_write_flag flg, const yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \ if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ ctx_len = (usize)(end - (u8 *)ctx); \ ctx_tmp = (yyjson_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \ ctx = ctx_tmp; \ cur = tmp + (cur - hdr); \ end = tmp + alc_len; \ hdr = tmp; \ } \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) yyjson_val *val; yyjson_type val_type; usize ctn_len, ctn_len_tmp; bool ctn_obj, ctn_obj_tmp, is_key; u8 *hdr, *cur, *end, *tmp; yyjson_write_ctx *ctx, *ctx_tmp; usize alc_len, alc_inc, ctx_len, ext_len, str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; alc_len = root->uni.ofs / sizeof(yyjson_val); alc_len = alc_len * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_write_ctx *)(void *)end; doc_begin: val = constcast(yyjson_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); val++; val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { is_key = ((u8)ctn_obj & (u8)~ctn_len); str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; *cur++ = is_key ? ':' : ','; goto val_end; } if (val_type == YYJSON_TYPE_NUM) { incr_len(32); cur = write_number(cur, val, flg); if (unlikely(!cur)) goto fail_num; *cur++ = ','; goto val_end; } if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { ctn_len_tmp = unsafe_yyjson_get_len(val); ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); incr_len(16); if (unlikely(ctn_len_tmp == 0)) { /* write empty container */ *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); *cur++ = ','; goto val_end; } else { /* push context, setup new container */ yyjson_write_ctx_set(--ctx, ctn_len, ctn_obj); ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; ctn_obj = ctn_obj_tmp; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); val++; goto val_begin; } } if (val_type == YYJSON_TYPE_BOOL) { incr_len(16); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); cur++; goto val_end; } if (val_type == YYJSON_TYPE_NULL) { incr_len(16); cur = write_null(cur); cur++; goto val_end; } if (val_type == YYJSON_TYPE_RAW) { str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 2); cur = write_raw(cur, str_ptr, str_len); *cur++ = ','; goto val_end; } goto fail_type; val_end: val++; ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; goto val_begin; ctn_end: cur--; *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); *cur++ = ','; if (unlikely((u8 *)ctx >= end)) goto doc_end; yyjson_write_ctx_get(ctx++, &ctn_len, &ctn_obj); ctn_len--; if (likely(ctn_len > 0)) { goto val_begin; } else { goto ctn_end; } doc_end: *--cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef incr_len #undef check_str_len } /** Write JSON document pretty. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_write_pretty(const yyjson_val *root, const yyjson_write_flag flg, const yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \ if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ ctx_len = (usize)(end - (u8 *)ctx); \ ctx_tmp = (yyjson_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \ ctx = ctx_tmp; \ cur = tmp + (cur - hdr); \ end = tmp + alc_len; \ hdr = tmp; \ } \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) yyjson_val *val; yyjson_type val_type; usize ctn_len, ctn_len_tmp; bool ctn_obj, ctn_obj_tmp, is_key, no_indent; u8 *hdr, *cur, *end, *tmp; yyjson_write_ctx *ctx, *ctx_tmp; usize alc_len, alc_inc, ctx_len, ext_len, str_len, level; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; usize spaces = (flg & YYJSON_WRITE_PRETTY_TWO_SPACES) ? 2 : 4; alc_len = root->uni.ofs / sizeof(yyjson_val); alc_len = alc_len * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_write_ctx *)(void *)end; doc_begin: val = constcast(yyjson_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); *cur++ = '\n'; val++; level = 1; val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { is_key = (bool)((u8)ctn_obj & (u8)~ctn_len); no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; *cur++ = is_key ? ':' : ','; *cur++ = is_key ? ' ' : '\n'; goto val_end; } if (val_type == YYJSON_TYPE_NUM) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(32 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_number(cur, val, flg); if (unlikely(!cur)) goto fail_num; *cur++ = ','; *cur++ = '\n'; goto val_end; } if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); ctn_len_tmp = unsafe_yyjson_get_len(val); ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); if (unlikely(ctn_len_tmp == 0)) { /* write empty container */ incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); *cur++ = ','; *cur++ = '\n'; goto val_end; } else { /* push context, setup new container */ incr_len(32 + (no_indent ? 0 : level * 4)); yyjson_write_ctx_set(--ctx, ctn_len, ctn_obj); ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; ctn_obj = ctn_obj_tmp; cur = write_indent(cur, no_indent ? 0 : level, spaces); level++; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); *cur++ = '\n'; val++; goto val_begin; } } if (val_type == YYJSON_TYPE_BOOL) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); cur += 2; goto val_end; } if (val_type == YYJSON_TYPE_NULL) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_null(cur); cur += 2; goto val_end; } if (val_type == YYJSON_TYPE_RAW) { str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 3); cur = write_raw(cur, str_ptr, str_len); *cur++ = ','; *cur++ = '\n'; goto val_end; } goto fail_type; val_end: val++; ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; goto val_begin; ctn_end: cur -= 2; *cur++ = '\n'; incr_len(level * 4); cur = write_indent(cur, --level, spaces); *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); if (unlikely((u8 *)ctx >= end)) goto doc_end; yyjson_write_ctx_get(ctx++, &ctn_len, &ctn_obj); ctn_len--; *cur++ = ','; *cur++ = '\n'; if (likely(ctn_len > 0)) { goto val_begin; } else { goto ctn_end; } doc_end: *cur = '\0'; *dat_len = (usize)(cur - hdr); memset(err, 0, sizeof(yyjson_write_err)); return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef incr_len #undef check_str_len } char *yyjson_val_write_opts(const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { yyjson_write_err dummy_err; usize dummy_dat_len; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; yyjson_val *root = constcast(yyjson_val *)val; err = err ? err : &dummy_err; dat_len = dat_len ? dat_len : &dummy_dat_len; #if YYJSON_DISABLE_NON_STANDARD flg &= ~YYJSON_WRITE_ALLOW_INF_AND_NAN; flg &= ~YYJSON_WRITE_ALLOW_INVALID_UNICODE; #endif if (unlikely(!root)) { *dat_len = 0; err->msg = "input JSON is NULL"; err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; return NULL; } if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) { return (char *)yyjson_write_single(root, flg, alc, dat_len, err); } else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) { return (char *)yyjson_write_pretty(root, flg, alc, dat_len, err); } else { return (char *)yyjson_write_minify(root, flg, alc, dat_len, err); } } char *yyjson_write_opts(const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { yyjson_val *root = doc ? doc->root : NULL; return yyjson_val_write_opts(root, flg, alc_ptr, dat_len, err); } bool yyjson_val_write_file(const char *path, const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; yyjson_val *root = constcast(yyjson_val *)val; bool suc; alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!path || !*path)) { err->msg = "input path is invalid"; err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; return false; } dat = (u8 *)yyjson_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_file(path, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; } bool yyjson_val_write_fp(FILE *fp, const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; yyjson_val *root = constcast(yyjson_val *)val; bool suc; alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!fp)) { err->msg = "input fp is invalid"; err->code = YYJSON_READ_ERROR_INVALID_PARAMETER; return false; } dat = (u8 *)yyjson_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_fp(fp, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; } bool yyjson_write_file(const char *path, const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_val *root = doc ? doc->root : NULL; return yyjson_val_write_file(path, root, flg, alc_ptr, err); } bool yyjson_write_fp(FILE *fp, const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_val *root = doc ? doc->root : NULL; return yyjson_val_write_fp(fp, root, flg, alc_ptr, err); } /*============================================================================== * Mutable JSON Writer Implementation *============================================================================*/ typedef struct yyjson_mut_write_ctx { usize tag; yyjson_mut_val *ctn; } yyjson_mut_write_ctx; static_inline void yyjson_mut_write_ctx_set(yyjson_mut_write_ctx *ctx, yyjson_mut_val *ctn, usize size, bool is_obj) { ctx->tag = (size << 1) | (usize)is_obj; ctx->ctn = ctn; } static_inline void yyjson_mut_write_ctx_get(yyjson_mut_write_ctx *ctx, yyjson_mut_val **ctn, usize *size, bool *is_obj) { usize tag = ctx->tag; *size = tag >> 1; *is_obj = (bool)(tag & 1); *ctn = ctx->ctn; } /** Get the estimated number of values for the mutable JSON document. */ static_inline usize yyjson_mut_doc_estimated_val_num( const yyjson_mut_doc *doc) { usize sum = 0; yyjson_val_chunk *chunk = doc->val_pool.chunks; while (chunk) { sum += chunk->chunk_size / sizeof(yyjson_mut_val) - 1; if (chunk == doc->val_pool.chunks) { sum -= (usize)(doc->val_pool.end - doc->val_pool.cur); } chunk = chunk->next; } return sum; } /** Write single JSON value. */ static_inline u8 *yyjson_mut_write_single(yyjson_mut_val *val, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { return yyjson_write_single((yyjson_val *)val, flg, alc, dat_len, err); } /** Write JSON document minify. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root, usize estimated_val_num, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \ if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ ctx_len = (usize)(end - (u8 *)ctx); \ ctx_tmp = (yyjson_mut_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \ ctx = ctx_tmp; \ cur = tmp + (cur - hdr); \ end = tmp + alc_len; \ hdr = tmp; \ } \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) yyjson_mut_val *val, *ctn; yyjson_type val_type; usize ctn_len, ctn_len_tmp; bool ctn_obj, ctn_obj_tmp, is_key; u8 *hdr, *cur, *end, *tmp; yyjson_mut_write_ctx *ctx, *ctx_tmp; usize alc_len, alc_inc, ctx_len, ext_len, str_len; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_mut_write_ctx *)(void *)end; doc_begin: val = constcast(yyjson_mut_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); ctn = val; val = (yyjson_mut_val *)val->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { is_key = ((u8)ctn_obj & (u8)~ctn_len); str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; *cur++ = is_key ? ':' : ','; goto val_end; } if (val_type == YYJSON_TYPE_NUM) { incr_len(32); cur = write_number(cur, (yyjson_val *)val, flg); if (unlikely(!cur)) goto fail_num; *cur++ = ','; goto val_end; } if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { ctn_len_tmp = unsafe_yyjson_get_len(val); ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); incr_len(16); if (unlikely(ctn_len_tmp == 0)) { /* write empty container */ *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); *cur++ = ','; goto val_end; } else { /* push context, setup new container */ yyjson_mut_write_ctx_set(--ctx, ctn, ctn_len, ctn_obj); ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; ctn_obj = ctn_obj_tmp; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); ctn = val; val = (yyjson_mut_val *)ctn->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; goto val_begin; } } if (val_type == YYJSON_TYPE_BOOL) { incr_len(16); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); cur++; goto val_end; } if (val_type == YYJSON_TYPE_NULL) { incr_len(16); cur = write_null(cur); cur++; goto val_end; } if (val_type == YYJSON_TYPE_RAW) { str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 2); cur = write_raw(cur, str_ptr, str_len); *cur++ = ','; goto val_end; } goto fail_type; val_end: ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; val = val->next; goto val_begin; ctn_end: cur--; *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); *cur++ = ','; if (unlikely((u8 *)ctx >= end)) goto doc_end; val = ctn->next; yyjson_mut_write_ctx_get(ctx++, &ctn, &ctn_len, &ctn_obj); ctn_len--; if (likely(ctn_len > 0)) { goto val_begin; } else { goto ctn_end; } doc_end: *--cur = '\0'; *dat_len = (usize)(cur - hdr); err->code = YYJSON_WRITE_SUCCESS; err->msg = "success"; return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef incr_len #undef check_str_len } /** Write JSON document pretty. The root of this document should be a non-empty container. */ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root, usize estimated_val_num, yyjson_write_flag flg, yyjson_alc alc, usize *dat_len, yyjson_write_err *err) { #define return_err(_code, _msg) do { \ *dat_len = 0; \ err->code = YYJSON_WRITE_ERROR_##_code; \ err->msg = _msg; \ if (hdr) alc.free(alc.ctx, hdr); \ return NULL; \ } while (false) #define incr_len(_len) do { \ ext_len = (usize)(_len); \ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \ alc_inc = yyjson_max(alc_len / 2, ext_len); \ alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \ if (size_add_is_overflow(alc_len, alc_inc)) goto fail_alloc; \ alc_len += alc_inc; \ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \ if (unlikely(!tmp)) goto fail_alloc; \ ctx_len = (usize)(end - (u8 *)ctx); \ ctx_tmp = (yyjson_mut_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \ ctx = ctx_tmp; \ cur = tmp + (cur - hdr); \ end = tmp + alc_len; \ hdr = tmp; \ } \ } while (false) #define check_str_len(_len) do { \ if ((USIZE_MAX < U64_MAX) && (_len >= (USIZE_MAX - 16) / 6)) \ goto fail_alloc; \ } while (false) yyjson_mut_val *val, *ctn; yyjson_type val_type; usize ctn_len, ctn_len_tmp; bool ctn_obj, ctn_obj_tmp, is_key, no_indent; u8 *hdr, *cur, *end, *tmp; yyjson_mut_write_ctx *ctx, *ctx_tmp; usize alc_len, alc_inc, ctx_len, ext_len, str_len, level; const u8 *str_ptr; const char_enc_type *enc_table = get_enc_table_with_flag(flg); bool esc = (flg & YYJSON_WRITE_ESCAPE_UNICODE) != 0; bool inv = (flg & YYJSON_WRITE_ALLOW_INVALID_UNICODE) != 0; usize spaces = (flg & YYJSON_WRITE_PRETTY_TWO_SPACES) ? 2 : 4; alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64; alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx)); hdr = (u8 *)alc.malloc(alc.ctx, alc_len); if (!hdr) goto fail_alloc; cur = hdr; end = hdr + alc_len; ctx = (yyjson_mut_write_ctx *)(void *)end; doc_begin: val = constcast(yyjson_mut_val *)root; val_type = unsafe_yyjson_get_type(val); ctn_obj = (val_type == YYJSON_TYPE_OBJ); ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); *cur++ = '\n'; ctn = val; val = (yyjson_mut_val *)val->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; level = 1; val_begin: val_type = unsafe_yyjson_get_type(val); if (val_type == YYJSON_TYPE_STR) { is_key = (bool)((u8)ctn_obj & (u8)~ctn_len); no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table); if (unlikely(!cur)) goto fail_str; *cur++ = is_key ? ':' : ','; *cur++ = is_key ? ' ' : '\n'; goto val_end; } if (val_type == YYJSON_TYPE_NUM) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(32 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_number(cur, (yyjson_val *)val, flg); if (unlikely(!cur)) goto fail_num; *cur++ = ','; *cur++ = '\n'; goto val_end; } if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) == (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); ctn_len_tmp = unsafe_yyjson_get_len(val); ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ); if (unlikely(ctn_len_tmp == 0)) { /* write empty container */ incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5)); *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5)); *cur++ = ','; *cur++ = '\n'; goto val_end; } else { /* push context, setup new container */ incr_len(32 + (no_indent ? 0 : level * 4)); yyjson_mut_write_ctx_set(--ctx, ctn, ctn_len, ctn_obj); ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp; ctn_obj = ctn_obj_tmp; cur = write_indent(cur, no_indent ? 0 : level, spaces); level++; *cur++ = (u8)('[' | ((u8)ctn_obj << 5)); *cur++ = '\n'; ctn = val; val = (yyjson_mut_val *)ctn->uni.ptr; /* tail */ val = ctn_obj ? val->next->next : val->next; goto val_begin; } } if (val_type == YYJSON_TYPE_BOOL) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_bool(cur, unsafe_yyjson_get_bool(val)); cur += 2; goto val_end; } if (val_type == YYJSON_TYPE_NULL) { no_indent = (bool)((u8)ctn_obj & (u8)ctn_len); incr_len(16 + (no_indent ? 0 : level * 4)); cur = write_indent(cur, no_indent ? 0 : level, spaces); cur = write_null(cur); cur += 2; goto val_end; } if (val_type == YYJSON_TYPE_RAW) { str_len = unsafe_yyjson_get_len(val); str_ptr = (const u8 *)unsafe_yyjson_get_str(val); check_str_len(str_len); incr_len(str_len + 3); cur = write_raw(cur, str_ptr, str_len); *cur++ = ','; *cur++ = '\n'; goto val_end; } goto fail_type; val_end: ctn_len--; if (unlikely(ctn_len == 0)) goto ctn_end; val = val->next; goto val_begin; ctn_end: cur -= 2; *cur++ = '\n'; incr_len(level * 4); cur = write_indent(cur, --level, spaces); *cur++ = (u8)(']' | ((u8)ctn_obj << 5)); if (unlikely((u8 *)ctx >= end)) goto doc_end; val = ctn->next; yyjson_mut_write_ctx_get(ctx++, &ctn, &ctn_len, &ctn_obj); ctn_len--; *cur++ = ','; *cur++ = '\n'; if (likely(ctn_len > 0)) { goto val_begin; } else { goto ctn_end; } doc_end: *cur = '\0'; *dat_len = (usize)(cur - hdr); err->code = YYJSON_WRITE_SUCCESS; err->msg = "success"; return hdr; fail_alloc: return_err(MEMORY_ALLOCATION, "memory allocation failed"); fail_type: return_err(INVALID_VALUE_TYPE, "invalid JSON value type"); fail_num: return_err(NAN_OR_INF, "nan or inf number is not allowed"); fail_str: return_err(INVALID_STRING, "invalid utf-8 encoding in string"); #undef return_err #undef incr_len #undef check_str_len } static char *yyjson_mut_write_opts_impl(const yyjson_mut_val *val, usize estimated_val_num, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { yyjson_write_err dummy_err; usize dummy_dat_len; yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC; yyjson_mut_val *root = constcast(yyjson_mut_val *)val; err = err ? err : &dummy_err; dat_len = dat_len ? dat_len : &dummy_dat_len; #if YYJSON_DISABLE_NON_STANDARD flg &= ~YYJSON_WRITE_ALLOW_INF_AND_NAN; flg &= ~YYJSON_WRITE_ALLOW_INVALID_UNICODE; #endif if (unlikely(!root)) { *dat_len = 0; err->msg = "input JSON is NULL"; err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; return NULL; } if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) { return (char *)yyjson_mut_write_single(root, flg, alc, dat_len, err); } else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) { return (char *)yyjson_mut_write_pretty(root, estimated_val_num, flg, alc, dat_len, err); } else { return (char *)yyjson_mut_write_minify(root, estimated_val_num, flg, alc, dat_len, err); } } char *yyjson_mut_val_write_opts(const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { return yyjson_mut_write_opts_impl(val, 0, flg, alc_ptr, dat_len, err); } char *yyjson_mut_write_opts(const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, usize *dat_len, yyjson_write_err *err) { yyjson_mut_val *root; usize estimated_val_num; if (likely(doc)) { root = doc->root; estimated_val_num = yyjson_mut_doc_estimated_val_num(doc); } else { root = NULL; estimated_val_num = 0; } return yyjson_mut_write_opts_impl(root, estimated_val_num, flg, alc_ptr, dat_len, err); } bool yyjson_mut_val_write_file(const char *path, const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; yyjson_mut_val *root = constcast(yyjson_mut_val *)val; bool suc; alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!path || !*path)) { err->msg = "input path is invalid"; err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; return false; } dat = (u8 *)yyjson_mut_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_file(path, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; } bool yyjson_mut_val_write_fp(FILE *fp, const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_write_err dummy_err; u8 *dat; usize dat_len = 0; yyjson_mut_val *root = constcast(yyjson_mut_val *)val; bool suc; alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC; err = err ? err : &dummy_err; if (unlikely(!fp)) { err->msg = "input fp is invalid"; err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER; return false; } dat = (u8 *)yyjson_mut_val_write_opts(root, flg, alc_ptr, &dat_len, err); if (unlikely(!dat)) return false; suc = write_dat_to_fp(fp, dat, dat_len, err); alc_ptr->free(alc_ptr->ctx, dat); return suc; } bool yyjson_mut_write_file(const char *path, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_mut_val *root = doc ? doc->root : NULL; return yyjson_mut_val_write_file(path, root, flg, alc_ptr, err); } bool yyjson_mut_write_fp(FILE *fp, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc_ptr, yyjson_write_err *err) { yyjson_mut_val *root = doc ? doc->root : NULL; return yyjson_mut_val_write_fp(fp, root, flg, alc_ptr, err); } #endif /* YYJSON_DISABLE_WRITER */ /*============================================================================== * Compiler Hint End *============================================================================*/ #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic pop # endif #elif defined(_MSC_VER) # pragma warning(pop) #endif /* warning suppress end */ ================================================ FILE: libtts/Modules/Lib/MJson/yyjson.h ================================================ /*============================================================================== * Created by Yaoyuan on 2019/3/9. * Copyright (C) 2019 Yaoyuan . * * Released under the MIT License: * https://github.com/ibireme/yyjson/blob/master/LICENSE *============================================================================*/ /** @file yyjson.h */ #ifndef YYJSON_H #define YYJSON_H /*============================================================================== * Header Files *============================================================================*/ #include #include #include #include #include #include /*============================================================================== * Compile-time Options *============================================================================*/ /* Define as 1 to disable JSON reader if JSON parsing is not required. This will disable these functions at compile-time: - yyjson_read_opts() - yyjson_read_file() - yyjson_read() - yyjson_read_number() - yyjson_mut_read_number() This will reduce the binary size by about 60%. */ #ifndef YYJSON_DISABLE_READER #endif /* Define as 1 to disable JSON writer if JSON serialization is not required. This will disable these functions at compile-time: - yyjson_write() - yyjson_write_file() - yyjson_write_opts() - yyjson_val_write() - yyjson_val_write_file() - yyjson_val_write_opts() - yyjson_mut_write() - yyjson_mut_write_file() - yyjson_mut_write_opts() - yyjson_mut_val_write() - yyjson_mut_val_write_file() - yyjson_mut_val_write_opts() This will reduce the binary size by about 30%. */ #ifndef YYJSON_DISABLE_WRITER #endif /* Define as 1 to disable JSON Pointer, JSON Patch and JSON Merge Patch supports. This will disable these functions at compile-time: - yyjson_ptr_xxx() - yyjson_mut_ptr_xxx() - yyjson_doc_ptr_xxx() - yyjson_mut_doc_ptr_xxx() - yyjson_patch() - yyjson_mut_patch() - yyjson_merge_patch() - yyjson_mut_merge_patch() */ #ifndef YYJSON_DISABLE_UTILS #endif /* Define as 1 to disable the fast floating-point number conversion in yyjson, and use libc's `strtod/snprintf` instead. This will reduce the binary size by about 30%, but significantly slow down the floating-point read/write speed. */ #ifndef YYJSON_DISABLE_FAST_FP_CONV #endif /* Define as 1 to disable non-standard JSON support at compile-time: - Reading and writing inf/nan literal, such as `NaN`, `-Infinity`. - Single line and multiple line comments. - Single trailing comma at the end of an object or array. - Invalid unicode in string value. This will also invalidate these run-time options: - YYJSON_READ_ALLOW_INF_AND_NAN - YYJSON_READ_ALLOW_COMMENTS - YYJSON_READ_ALLOW_TRAILING_COMMAS - YYJSON_READ_ALLOW_INVALID_UNICODE - YYJSON_WRITE_ALLOW_INF_AND_NAN - YYJSON_WRITE_ALLOW_INVALID_UNICODE This will reduce the binary size by about 10%, and slightly improve the JSON read/write speed. */ #ifndef YYJSON_DISABLE_NON_STANDARD #endif /* Define as 1 to disable unaligned memory access if target architecture does not support unaligned memory access (such as some embedded processors). If this value is not defined, yyjson will perform some automatic detection. The wrong definition of this option may cause some performance degradation, but will not cause any run-time errors. */ #ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS #endif /* Define as 1 to export symbols when building this library as Windows DLL. */ #ifndef YYJSON_EXPORTS #endif /* Define as 1 to import symbols when using this library as Windows DLL. */ #ifndef YYJSON_IMPORTS #endif /* Define as 1 to include for compiler which doesn't support C99. */ #ifndef YYJSON_HAS_STDINT_H #endif /* Define as 1 to include for compiler which doesn't support C99. */ #ifndef YYJSON_HAS_STDBOOL_H #endif /*============================================================================== * Compiler Macros *============================================================================*/ /** compiler version (MSVC) */ #ifdef _MSC_VER # define YYJSON_MSC_VER _MSC_VER #else # define YYJSON_MSC_VER 0 #endif /** compiler version (GCC) */ #ifdef __GNUC__ # define YYJSON_GCC_VER __GNUC__ #else # define YYJSON_GCC_VER 0 #endif /** C version (STDC) */ #if defined(__STDC__) && (__STDC__ >= 1) && defined(__STDC_VERSION__) # define YYJSON_STDC_VER __STDC_VERSION__ #else # define YYJSON_STDC_VER 0 #endif /** C++ version */ #if defined(__cplusplus) # define YYJSON_CPP_VER __cplusplus #else # define YYJSON_CPP_VER 0 #endif /** compiler builtin check (since gcc 10.0, clang 2.6, icc 2021) */ #ifndef yyjson_has_builtin # ifdef __has_builtin # define yyjson_has_builtin(x) __has_builtin(x) # else # define yyjson_has_builtin(x) 0 # endif #endif /** compiler attribute check (since gcc 5.0, clang 2.9, icc 17) */ #ifndef yyjson_has_attribute # ifdef __has_attribute # define yyjson_has_attribute(x) __has_attribute(x) # else # define yyjson_has_attribute(x) 0 # endif #endif /** compiler feature check (since clang 2.6, icc 17) */ #ifndef yyjson_has_feature # ifdef __has_feature # define yyjson_has_feature(x) __has_feature(x) # else # define yyjson_has_feature(x) 0 # endif #endif /** include check (since gcc 5.0, clang 2.7, icc 16, msvc 2017 15.3) */ #ifndef yyjson_has_include # ifdef __has_include # define yyjson_has_include(x) __has_include(x) # else # define yyjson_has_include(x) 0 # endif #endif /** inline for compiler */ #ifndef yyjson_inline # if YYJSON_MSC_VER >= 1200 # define yyjson_inline __forceinline # elif defined(_MSC_VER) # define yyjson_inline __inline # elif yyjson_has_attribute(always_inline) || YYJSON_GCC_VER >= 4 # define yyjson_inline __inline__ __attribute__((always_inline)) # elif defined(__clang__) || defined(__GNUC__) # define yyjson_inline __inline__ # elif defined(__cplusplus) || YYJSON_STDC_VER >= 199901L # define yyjson_inline inline # else # define yyjson_inline # endif #endif /** noinline for compiler */ #ifndef yyjson_noinline # if YYJSON_MSC_VER >= 1400 # define yyjson_noinline __declspec(noinline) # elif yyjson_has_attribute(noinline) || YYJSON_GCC_VER >= 4 # define yyjson_noinline __attribute__((noinline)) # else # define yyjson_noinline # endif #endif /** align for compiler */ #ifndef yyjson_align # if YYJSON_MSC_VER >= 1300 # define yyjson_align(x) __declspec(align(x)) # elif yyjson_has_attribute(aligned) || defined(__GNUC__) # define yyjson_align(x) __attribute__((aligned(x))) # elif YYJSON_CPP_VER >= 201103L # define yyjson_align(x) alignas(x) # else # define yyjson_align(x) # endif #endif /** likely for compiler */ #ifndef yyjson_likely # if yyjson_has_builtin(__builtin_expect) || \ (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5) # define yyjson_likely(expr) __builtin_expect(!!(expr), 1) # else # define yyjson_likely(expr) (expr) # endif #endif /** unlikely for compiler */ #ifndef yyjson_unlikely # if yyjson_has_builtin(__builtin_expect) || \ (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5) # define yyjson_unlikely(expr) __builtin_expect(!!(expr), 0) # else # define yyjson_unlikely(expr) (expr) # endif #endif /** deprecate warning */ #ifndef yyjson_deprecated # if YYJSON_MSC_VER >= 1400 # define yyjson_deprecated(msg) __declspec(deprecated(msg)) # elif yyjson_has_feature(attribute_deprecated_with_message) || \ (YYJSON_GCC_VER > 4 || (YYJSON_GCC_VER == 4 && __GNUC_MINOR__ >= 5)) # define yyjson_deprecated(msg) __attribute__((deprecated(msg))) # elif YYJSON_GCC_VER >= 3 # define yyjson_deprecated(msg) __attribute__((deprecated)) # else # define yyjson_deprecated(msg) # endif #endif /** function export */ #ifndef yyjson_api # if defined(_WIN32) # if defined(YYJSON_EXPORTS) && YYJSON_EXPORTS # define yyjson_api __declspec(dllexport) # elif defined(YYJSON_IMPORTS) && YYJSON_IMPORTS # define yyjson_api __declspec(dllimport) # else # define yyjson_api # endif # elif yyjson_has_attribute(visibility) || YYJSON_GCC_VER >= 4 # define yyjson_api __attribute__((visibility("default"))) # else # define yyjson_api # endif #endif /** inline function export */ #ifndef yyjson_api_inline # define yyjson_api_inline static yyjson_inline #endif /** stdint (C89 compatible) */ #if (defined(YYJSON_HAS_STDINT_H) && YYJSON_HAS_STDINT_H) || \ YYJSON_MSC_VER >= 1600 || YYJSON_STDC_VER >= 199901L || \ defined(_STDINT_H) || defined(_STDINT_H_) || \ defined(__CLANG_STDINT_H) || defined(_STDINT_H_INCLUDED) || \ yyjson_has_include() # include #elif defined(_MSC_VER) # if _MSC_VER < 1300 typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; # else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; # endif #else # if UCHAR_MAX == 0xFFU typedef signed char int8_t; typedef unsigned char uint8_t; # else # error cannot find 8-bit integer type # endif # if USHRT_MAX == 0xFFFFU typedef unsigned short uint16_t; typedef signed short int16_t; # elif UINT_MAX == 0xFFFFU typedef unsigned int uint16_t; typedef signed int int16_t; # else # error cannot find 16-bit integer type # endif # if UINT_MAX == 0xFFFFFFFFUL typedef unsigned int uint32_t; typedef signed int int32_t; # elif ULONG_MAX == 0xFFFFFFFFUL typedef unsigned long uint32_t; typedef signed long int32_t; # elif USHRT_MAX == 0xFFFFFFFFUL typedef unsigned short uint32_t; typedef signed short int32_t; # else # error cannot find 32-bit integer type # endif # if defined(__INT64_TYPE__) && defined(__UINT64_TYPE__) typedef __INT64_TYPE__ int64_t; typedef __UINT64_TYPE__ uint64_t; # elif defined(__GNUC__) || defined(__clang__) # if !defined(_SYS_TYPES_H) && !defined(__int8_t_defined) __extension__ typedef long long int64_t; # endif __extension__ typedef unsigned long long uint64_t; # elif defined(_LONG_LONG) || defined(__MWERKS__) || defined(_CRAYC) || \ defined(__SUNPRO_C) || defined(__SUNPRO_CC) typedef long long int64_t; typedef unsigned long long uint64_t; # elif (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || \ defined(__WATCOM_INT64__) || defined (__alpha) || defined (__DECC) typedef __int64 int64_t; typedef unsigned __int64 uint64_t; # else # error cannot find 64-bit integer type # endif #endif /** stdbool (C89 compatible) */ #if (defined(YYJSON_HAS_STDBOOL_H) && YYJSON_HAS_STDBOOL_H) || \ (yyjson_has_include() && !defined(__STRICT_ANSI__)) || \ YYJSON_MSC_VER >= 1800 || YYJSON_STDC_VER >= 199901L # include #elif !defined(__bool_true_false_are_defined) # define __bool_true_false_are_defined 1 # if defined(__cplusplus) # if defined(__GNUC__) && !defined(__STRICT_ANSI__) # define _Bool bool # if __cplusplus < 201103L # define bool bool # define false false # define true true # endif # endif # else # define bool unsigned char # define true 1 # define false 0 # endif #endif /** char bit check */ #if defined(CHAR_BIT) # if CHAR_BIT != 8 # error non 8-bit char is not supported # endif #endif /** Microsoft Visual C++ 6.0 doesn't support converting number from u64 to f64: error C2520: conversion from unsigned __int64 to double not implemented. */ #ifndef YYJSON_U64_TO_F64_NO_IMPL # if (0 < YYJSON_MSC_VER) && (YYJSON_MSC_VER <= 1200) # define YYJSON_U64_TO_F64_NO_IMPL 1 # else # define YYJSON_U64_TO_F64_NO_IMPL 0 # endif #endif /*============================================================================== * Compile Hint Begin *============================================================================*/ /* extern "C" begin */ #ifdef __cplusplus extern "C" { #endif /* warning suppress begin */ #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunused-function" # pragma clang diagnostic ignored "-Wunused-parameter" #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-function" # pragma GCC diagnostic ignored "-Wunused-parameter" #elif defined(_MSC_VER) # pragma warning(push) # pragma warning(disable:4800) /* 'int': forcing value to 'true' or 'false' */ #endif /*============================================================================== * Version *============================================================================*/ /** The major version of yyjson. */ #define YYJSON_VERSION_MAJOR 0 /** The minor version of yyjson. */ #define YYJSON_VERSION_MINOR 7 /** The patch version of yyjson. */ #define YYJSON_VERSION_PATCH 0 /** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */ #define YYJSON_VERSION_HEX 0x000700 /** The version string of yyjson. */ #define YYJSON_VERSION_STRING "0.7.0" /** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */ yyjson_api uint32_t yyjson_version(void); /*============================================================================== * JSON Types *============================================================================*/ /** Type of JSON value (3 bit). */ typedef uint8_t yyjson_type; #define YYJSON_TYPE_NONE ((uint8_t)0) /* _____000 */ #define YYJSON_TYPE_RAW ((uint8_t)1) /* _____001 */ #define YYJSON_TYPE_NULL ((uint8_t)2) /* _____010 */ #define YYJSON_TYPE_BOOL ((uint8_t)3) /* _____011 */ #define YYJSON_TYPE_NUM ((uint8_t)4) /* _____100 */ #define YYJSON_TYPE_STR ((uint8_t)5) /* _____101 */ #define YYJSON_TYPE_ARR ((uint8_t)6) /* _____110 */ #define YYJSON_TYPE_OBJ ((uint8_t)7) /* _____111 */ /** Subtype of JSON value (2 bit). */ typedef uint8_t yyjson_subtype; #define YYJSON_SUBTYPE_NONE ((uint8_t)(0 << 3)) /* ___00___ */ #define YYJSON_SUBTYPE_FALSE ((uint8_t)(0 << 3)) /* ___00___ */ #define YYJSON_SUBTYPE_TRUE ((uint8_t)(1 << 3)) /* ___01___ */ #define YYJSON_SUBTYPE_UINT ((uint8_t)(0 << 3)) /* ___00___ */ #define YYJSON_SUBTYPE_SINT ((uint8_t)(1 << 3)) /* ___01___ */ #define YYJSON_SUBTYPE_REAL ((uint8_t)(2 << 3)) /* ___10___ */ /** Mask and bits of JSON value tag. */ #define YYJSON_TYPE_MASK ((uint8_t)0x07) /* _____111 */ #define YYJSON_TYPE_BIT ((uint8_t)3) #define YYJSON_SUBTYPE_MASK ((uint8_t)0x18) /* ___11___ */ #define YYJSON_SUBTYPE_BIT ((uint8_t)2) #define YYJSON_RESERVED_MASK ((uint8_t)0xE0) /* 111_____ */ #define YYJSON_RESERVED_BIT ((uint8_t)3) #define YYJSON_TAG_MASK ((uint8_t)0xFF) /* 11111111 */ #define YYJSON_TAG_BIT ((uint8_t)8) /** Padding size for JSON reader. */ #define YYJSON_PADDING_SIZE 4 /*============================================================================== * Allocator *============================================================================*/ /** A memory allocator. Typically you don't need to use it, unless you want to customize your own memory allocator. */ typedef struct yyjson_alc { /** Same as libc's malloc(size), should not be NULL. */ void *(*malloc)(void *ctx, size_t size); /** Same as libc's realloc(ptr, size), should not be NULL. */ void *(*realloc)(void *ctx, void *ptr, size_t old_size, size_t size); /** Same as libc's free(ptr), should not be NULL. */ void (*free)(void *ctx, void *ptr); /** A context for malloc/realloc/free, can be NULL. */ void *ctx; } yyjson_alc; /** A pool allocator uses fixed length pre-allocated memory. This allocator may be used to avoid malloc/realloc calls. The pre-allocated memory should be held by the caller. The maximum amount of memory required to read a JSON can be calculated using the `yyjson_read_max_memory_usage()` function, but the amount of memory required to write a JSON cannot be directly calculated. This is not a general-purpose allocator. If used to read multiple JSON documents and only some of them are released, it may cause memory fragmentation, leading to performance degradation and memory waste. Therefore, it is recommended to use this allocator only for reading or writing a single JSON document. @param alc The allocator to be initialized. If this parameter is NULL, the function will fail and return false. If `buf` or `size` is invalid, this will be set to an empty allocator. @param buf The buffer memory for this allocator. If this parameter is NULL, the function will fail and return false. @param size The size of `buf`, in bytes. If this parameter is less than 8 words (32/64 bytes on 32/64-bit OS), the function will fail and return false. @return true if the `alc` has been successfully initialized. @par Example @code // parse JSON with stack memory char buf[1024]; yyjson_alc alc; yyjson_alc_pool_init(&alc, buf, 1024); const char *json = "{\"name\":\"Helvetica\",\"size\":16}" yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL); // the memory of `doc` is on the stack @endcode */ yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size); /*============================================================================== * JSON Structure *============================================================================*/ /** An immutable document for reading JSON. This document holds memory for all its JSON values and strings. When it is no longer used, the user should call `yyjson_doc_free()` to free its memory. */ typedef struct yyjson_doc yyjson_doc; /** An immutable value for reading JSON. A JSON Value has the same lifetime as its document. The memory is held by its document and and cannot be freed alone. */ typedef struct yyjson_val yyjson_val; /** A mutable document for building JSON. This document holds memory for all its JSON values and strings. When it is no longer used, the user should call `yyjson_mut_doc_free()` to free its memory. */ typedef struct yyjson_mut_doc yyjson_mut_doc; /** A mutable value for building JSON. A JSON Value has the same lifetime as its document. The memory is held by its document and and cannot be freed alone. */ typedef struct yyjson_mut_val yyjson_mut_val; /*============================================================================== * JSON Reader API *============================================================================*/ /** Run-time options for JSON reader. */ typedef uint32_t yyjson_read_flag; /** Default option (RFC 8259 compliant): - Read positive integer as uint64_t. - Read negative integer as int64_t. - Read floating-point number as double with round-to-nearest mode. - Read integer which cannot fit in uint64_t or int64_t as double. - Report error if double number is infinity. - Report error if string contains invalid UTF-8 character or BOM. - Report error on trailing commas, comments, inf and nan literals. */ static const yyjson_read_flag YYJSON_READ_NOFLAG = 0 << 0; /** Read the input data in-situ. This option allows the reader to modify and use input data to store string values, which can increase reading speed slightly. The caller should hold the input data before free the document. The input data must be padded by at least `YYJSON_PADDING_SIZE` bytes. For example: `[1,2]` should be `[1,2]\0\0\0\0`, input length should be 5. */ static const yyjson_read_flag YYJSON_READ_INSITU = 1 << 0; /** Stop when done instead of issuing an error if there's additional content after a JSON document. This option may be used to parse small pieces of JSON in larger data, such as `NDJSON`. */ static const yyjson_read_flag YYJSON_READ_STOP_WHEN_DONE = 1 << 1; /** Allow single trailing comma at the end of an object or array, such as `[1,2,3,]`, `{"a":1,"b":2,}` (non-standard). */ static const yyjson_read_flag YYJSON_READ_ALLOW_TRAILING_COMMAS = 1 << 2; /** Allow C-style single line and multiple line comments (non-standard). */ static const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS = 1 << 3; /** Allow inf/nan number and literal, case-insensitive, such as 1e999, NaN, inf, -Infinity (non-standard). */ static const yyjson_read_flag YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4; /** Read all numbers as raw strings (value with `YYJSON_TYPE_RAW` type), inf/nan literal is also read as raw with `ALLOW_INF_AND_NAN` flag. */ static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5; /** Allow reading invalid unicode when parsing string values (non-standard). Invalid characters will be allowed to appear in the string values, but invalid escape sequences will still be reported as errors. This flag does not affect the performance of correctly encoded strings. @warning Strings in JSON values may contain incorrect encoding when this option is used, you need to handle these strings carefully to avoid security risks. */ static const yyjson_read_flag YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6; /** Read big numbers as raw strings. These big numbers include integers that cannot be represented by `int64_t` and `uint64_t`, and floating-point numbers that cannot be represented by finite `double`. The flag will be overridden by `YYJSON_READ_NUMBER_AS_RAW` flag. */ static const yyjson_read_flag YYJSON_READ_BIGNUM_AS_RAW = 1 << 7; /** Result code for JSON reader. */ typedef uint32_t yyjson_read_code; /** Success, no error. */ static const yyjson_read_code YYJSON_READ_SUCCESS = 0; /** Invalid parameter, such as NULL input string or 0 input length. */ static const yyjson_read_code YYJSON_READ_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failure occurs. */ static const yyjson_read_code YYJSON_READ_ERROR_MEMORY_ALLOCATION = 2; /** Input JSON string is empty. */ static const yyjson_read_code YYJSON_READ_ERROR_EMPTY_CONTENT = 3; /** Unexpected content after document, such as `[123]abc`. */ static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CONTENT = 4; /** Unexpected ending, such as `[123`. */ static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_END = 5; /** Unexpected character inside the document, such as `[abc]`. */ static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CHARACTER = 6; /** Invalid JSON structure, such as `[1,]`. */ static const yyjson_read_code YYJSON_READ_ERROR_JSON_STRUCTURE = 7; /** Invalid comment, such as unclosed multi-line comment. */ static const yyjson_read_code YYJSON_READ_ERROR_INVALID_COMMENT = 8; /** Invalid number, such as `123.e12`, `000`. */ static const yyjson_read_code YYJSON_READ_ERROR_INVALID_NUMBER = 9; /** Invalid string, such as invalid escaped character inside a string. */ static const yyjson_read_code YYJSON_READ_ERROR_INVALID_STRING = 10; /** Invalid JSON literal, such as `truu`. */ static const yyjson_read_code YYJSON_READ_ERROR_LITERAL = 11; /** Failed to open a file. */ static const yyjson_read_code YYJSON_READ_ERROR_FILE_OPEN = 12; /** Failed to read a file. */ static const yyjson_read_code YYJSON_READ_ERROR_FILE_READ = 13; /** Error information for JSON reader. */ typedef struct yyjson_read_err { /** Error code, see `yyjson_read_code` for all possible values. */ yyjson_read_code code; /** Error message, constant, no need to free (NULL if success). */ const char *msg; /** Error byte position for input data (0 if success). */ size_t pos; } yyjson_read_err; /** Read JSON with options. This function is thread-safe when: 1. The `dat` is not modified by other threads. 2. The `alc` is thread-safe or NULL. @param dat The JSON data (UTF-8 without BOM), null-terminator is not required. If this parameter is NULL, the function will fail and return NULL. The `dat` will not be modified without the flag `YYJSON_READ_INSITU`, so you can pass a `const char *` string and case it to `char *` if you don't use the `YYJSON_READ_INSITU` flag. @param len The length of JSON data in bytes. If this parameter is 0, the function will fail and return NULL. @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON reader. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON document, or NULL if an error occurs. When it's no longer needed, it should be freed with `yyjson_doc_free()`. */ yyjson_api yyjson_doc *yyjson_read_opts(char *dat, size_t len, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err); /** Read a JSON file. This function is thread-safe when: 1. The file is not modified by other threads. 2. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return NULL. @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON reader. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON document, or NULL if an error occurs. When it's no longer needed, it should be freed with `yyjson_doc_free()`. @warning On 32-bit operating system, files larger than 2GB may fail to read. */ yyjson_api yyjson_doc *yyjson_read_file(const char *path, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err); /** Read JSON from a file pointer. @param fp The file pointer. The data will be read from the current position of the FILE to the end. If this fp is NULL or invalid, the function will fail and return NULL. @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON reader. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON document, or NULL if an error occurs. When it's no longer needed, it should be freed with `yyjson_doc_free()`. @warning On 32-bit operating system, files larger than 2GB may fail to read. */ yyjson_api yyjson_doc *yyjson_read_fp(FILE *fp, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err); /** Read a JSON string. This function is thread-safe. @param dat The JSON data (UTF-8 without BOM), null-terminator is not required. If this parameter is NULL, the function will fail and return NULL. @param len The length of JSON data in bytes. If this parameter is 0, the function will fail and return NULL. @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. @return A new JSON document, or NULL if an error occurs. When it's no longer needed, it should be freed with `yyjson_doc_free()`. */ yyjson_api_inline yyjson_doc *yyjson_read(const char *dat, size_t len, yyjson_read_flag flg) { flg &= ~YYJSON_READ_INSITU; /* const string cannot be modified */ return yyjson_read_opts((char *)(void *)(size_t)(const void *)dat, len, flg, NULL, NULL); } /** Returns the size of maximum memory usage to read a JSON data. You may use this value to avoid malloc() or calloc() call inside the reader to get better performance, or read multiple JSON with one piece of memory. @param len The length of JSON data in bytes. @param flg The JSON read options. @return The maximum memory size to read this JSON, or 0 if overflow. @par Example @code // read multiple JSON with same pre-allocated memory char *dat1, *dat2, *dat3; // JSON data size_t len1, len2, len3; // JSON length size_t max_len = MAX(len1, MAX(len2, len3)); yyjson_doc *doc; // use one allocator for multiple JSON size_t size = yyjson_read_max_memory_usage(max_len, 0); void *buf = malloc(size); yyjson_alc alc; yyjson_alc_pool_init(&alc, buf, size); // no more alloc() or realloc() call during reading doc = yyjson_read_opts(dat1, len1, 0, &alc, NULL); yyjson_doc_free(doc); doc = yyjson_read_opts(dat2, len2, 0, &alc, NULL); yyjson_doc_free(doc); doc = yyjson_read_opts(dat3, len3, 0, &alc, NULL); yyjson_doc_free(doc); free(buf); @endcode @see yyjson_alc_pool_init() */ yyjson_api_inline size_t yyjson_read_max_memory_usage(size_t len, yyjson_read_flag flg) { /* 1. The max value count is (json_size / 2 + 1), for example: "[1,2,3,4]" size is 9, value count is 5. 2. Some broken JSON may cost more memory during reading, but fail at end, for example: "[[[[[[[[". 3. yyjson use 16 bytes per value, see struct yyjson_val. 4. yyjson use dynamic memory with a growth factor of 1.5. The max memory size is (json_size / 2 * 16 * 1.5 + padding). */ size_t mul = (size_t)12 + !(flg & YYJSON_READ_INSITU); size_t pad = 256; size_t max = (size_t)(~(size_t)0); if (flg & YYJSON_READ_STOP_WHEN_DONE) len = len < 256 ? 256 : len; if (len >= (max - pad - mul) / mul) return 0; return len * mul + pad; } /** Read a JSON number. This function is thread-safe when data is not modified by other threads. @param dat The JSON data (UTF-8 without BOM), null-terminator is required. If this parameter is NULL, the function will fail and return NULL. @param val The output value where result is stored. If this parameter is NULL, the function will fail and return NULL. The value will hold either UINT or SINT or REAL number; @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`. @param alc The memory allocator used for long number. It is only used when the built-in floating point reader is disabled. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return If successful, a pointer to the character after the last character used in the conversion, NULL if an error occurs. */ yyjson_api const char *yyjson_read_number(const char *dat, yyjson_val *val, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err); /** Read a JSON number. This function is thread-safe when data is not modified by other threads. @param dat The JSON data (UTF-8 without BOM), null-terminator is required. If this parameter is NULL, the function will fail and return NULL. @param val The output value where result is stored. If this parameter is NULL, the function will fail and return NULL. The value will hold either UINT or SINT or REAL number; @param flg The JSON read options. Multiple options can be combined with `|` operator. 0 means no options. Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`. @param alc The memory allocator used for long number. It is only used when the built-in floating point reader is disabled. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return If successful, a pointer to the character after the last character used in the conversion, NULL if an error occurs. */ yyjson_api_inline const char *yyjson_mut_read_number(const char *dat, yyjson_mut_val *val, yyjson_read_flag flg, const yyjson_alc *alc, yyjson_read_err *err) { return yyjson_read_number(dat, (yyjson_val *)val, flg, alc, err); } /*============================================================================== * JSON Writer API *============================================================================*/ /** Run-time options for JSON writer. */ typedef uint32_t yyjson_write_flag; /** Default option: - Write JSON minify. - Report error on inf or nan number. - Report error on invalid UTF-8 string. - Do not escape unicode or slash. */ static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0 << 0; /** Write JSON pretty with 4 space indent. */ static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0; /** Escape unicode as `uXXXX`, make the output ASCII only. */ static const yyjson_write_flag YYJSON_WRITE_ESCAPE_UNICODE = 1 << 1; /** Escape '/' as '\/'. */ static const yyjson_write_flag YYJSON_WRITE_ESCAPE_SLASHES = 1 << 2; /** Write inf and nan number as 'Infinity' and 'NaN' literal (non-standard). */ static const yyjson_write_flag YYJSON_WRITE_ALLOW_INF_AND_NAN = 1 << 3; /** Write inf and nan number as null literal. This flag will override `YYJSON_WRITE_ALLOW_INF_AND_NAN` flag. */ static const yyjson_write_flag YYJSON_WRITE_INF_AND_NAN_AS_NULL = 1 << 4; /** Allow invalid unicode when encoding string values (non-standard). Invalid characters in string value will be copied byte by byte. If `YYJSON_WRITE_ESCAPE_UNICODE` flag is also set, invalid character will be escaped as `U+FFFD` (replacement character). This flag does not affect the performance of correctly encoded strings. */ static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5; /** Write JSON pretty with 2 space indent. This flag will override `YYJSON_WRITE_PRETTY` flag. */ static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6; /** Result code for JSON writer */ typedef uint32_t yyjson_write_code; /** Success, no error. */ static const yyjson_write_code YYJSON_WRITE_SUCCESS = 0; /** Invalid parameter, such as NULL document. */ static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failure occurs. */ static const yyjson_write_code YYJSON_WRITE_ERROR_MEMORY_ALLOCATION = 2; /** Invalid value type in JSON document. */ static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_VALUE_TYPE = 3; /** NaN or Infinity number occurs. */ static const yyjson_write_code YYJSON_WRITE_ERROR_NAN_OR_INF = 4; /** Failed to open a file. */ static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_OPEN = 5; /** Failed to write a file. */ static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_WRITE = 6; /** Invalid unicode in string. */ static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_STRING = 7; /** Error information for JSON writer. */ typedef struct yyjson_write_err { /** Error code, see `yyjson_write_code` for all possible values. */ yyjson_write_code code; /** Error message, constant, no need to free (NULL if success). */ const char *msg; } yyjson_write_err; /*============================================================================== * JSON Document Writer API *============================================================================*/ /** Write a document to JSON string with options. This function is thread-safe when: The `alc` is thread-safe or NULL. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free() or alc->free(). */ yyjson_api char *yyjson_write_opts(const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, size_t *len, yyjson_write_err *err); /** Write a document to JSON file with options. This function is thread-safe when: 1. The file is not accessed by other threads. 2. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return false. If this file is not empty, the content will be discarded. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_write_file(const char *path, const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a document to file pointer with options. @param fp The file pointer. The data will be written to the current position of the file. If this fp is NULL or invalid, the function will fail and return false. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_write_fp(FILE *fp, const yyjson_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a document to JSON string. This function is thread-safe. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). */ yyjson_api_inline char *yyjson_write(const yyjson_doc *doc, yyjson_write_flag flg, size_t *len) { return yyjson_write_opts(doc, flg, NULL, len, NULL); } /** Write a document to JSON string with options. This function is thread-safe when: 1. The `doc` is not modified by other threads. 2. The `alc` is thread-safe or NULL. @param doc The mutable JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free() or alc->free(). */ yyjson_api char *yyjson_mut_write_opts(const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, size_t *len, yyjson_write_err *err); /** Write a document to JSON file with options. This function is thread-safe when: 1. The file is not accessed by other threads. 2. The `doc` is not modified by other threads. 3. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return false. If this file is not empty, the content will be discarded. @param doc The mutable JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_mut_write_file(const char *path, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a document to file pointer with options. @param fp The file pointer. The data will be written to the current position of the file. If this fp is NULL or invalid, the function will fail and return false. @param doc The mutable JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_mut_write_fp(FILE *fp, const yyjson_mut_doc *doc, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a document to JSON string. This function is thread-safe when: The `doc` is not modified by other threads. @param doc The JSON document. If this doc is NULL or has no root, the function will fail and return false. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). */ yyjson_api_inline char *yyjson_mut_write(const yyjson_mut_doc *doc, yyjson_write_flag flg, size_t *len) { return yyjson_mut_write_opts(doc, flg, NULL, len, NULL); } /*============================================================================== * JSON Value Writer API *============================================================================*/ /** Write a value to JSON string with options. This function is thread-safe when: The `alc` is thread-safe or NULL. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free() or alc->free(). */ yyjson_api char *yyjson_val_write_opts(const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc, size_t *len, yyjson_write_err *err); /** Write a value to JSON file with options. This function is thread-safe when: 1. The file is not accessed by other threads. 2. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return false. If this file is not empty, the content will be discarded. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_val_write_file(const char *path, const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a value to file pointer with options. @param fp The file pointer. The data will be written to the current position of the file. If this path is NULL or invalid, the function will fail and return false. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_val_write_fp(FILE *fp, const yyjson_val *val, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a value to JSON string. This function is thread-safe. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). */ yyjson_api_inline char *yyjson_val_write(const yyjson_val *val, yyjson_write_flag flg, size_t *len) { return yyjson_val_write_opts(val, flg, NULL, len, NULL); } /** Write a value to JSON string with options. This function is thread-safe when: 1. The `val` is not modified by other threads. 2. The `alc` is thread-safe or NULL. @param val The mutable JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free() or alc->free(). */ yyjson_api char *yyjson_mut_val_write_opts(const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc, size_t *len, yyjson_write_err *err); /** Write a value to JSON file with options. This function is thread-safe when: 1. The file is not accessed by other threads. 2. The `val` is not modified by other threads. 3. The `alc` is thread-safe or NULL. @param path The JSON file's path. If this path is NULL or invalid, the function will fail and return false. If this file is not empty, the content will be discarded. @param val The mutable JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_mut_val_write_file(const char *path, const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a value to JSON file with options. @param fp The file pointer. The data will be written to the current position of the file. If this path is NULL or invalid, the function will fail and return false. @param val The mutable JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param alc The memory allocator used by JSON writer. Pass NULL to use the libc's default allocator. @param err A pointer to receive error information. Pass NULL if you don't need error information. @return true if successful, false if an error occurs. @warning On 32-bit operating system, files larger than 2GB may fail to write. */ yyjson_api bool yyjson_mut_val_write_fp(FILE *fp, const yyjson_mut_val *val, yyjson_write_flag flg, const yyjson_alc *alc, yyjson_write_err *err); /** Write a value to JSON string. This function is thread-safe when: The `val` is not modified by other threads. @param val The JSON root value. If this parameter is NULL, the function will fail and return NULL. @param flg The JSON write options. Multiple options can be combined with `|` operator. 0 means no options. @param len A pointer to receive output length in bytes (not including the null-terminator). Pass NULL if you don't need length information. @return A new JSON string, or NULL if an error occurs. This string is encoded as UTF-8 with a null-terminator. When it's no longer needed, it should be freed with free(). */ yyjson_api_inline char *yyjson_mut_val_write(const yyjson_mut_val *val, yyjson_write_flag flg, size_t *len) { return yyjson_mut_val_write_opts(val, flg, NULL, len, NULL); } /*============================================================================== * JSON Document API *============================================================================*/ /** Returns the root value of this JSON document. Returns NULL if `doc` is NULL. */ yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc); /** Returns read size of input JSON data. Returns 0 if `doc` is NULL. For example: the read size of `[1,2,3]` is 7 bytes. */ yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc); /** Returns total value count in this JSON document. Returns 0 if `doc` is NULL. For example: the value count of `[1,2,3]` is 4. */ yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc); /** Release the JSON document and free the memory. After calling this function, the `doc` and all values from the `doc` are no longer available. This function will do nothing if the `doc` is NULL. */ yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc); /*============================================================================== * JSON Value Type API *============================================================================*/ /** Returns whether the JSON value is raw. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_raw(yyjson_val *val); /** Returns whether the JSON value is `null`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_null(yyjson_val *val); /** Returns whether the JSON value is `true`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_true(yyjson_val *val); /** Returns whether the JSON value is `false`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_false(yyjson_val *val); /** Returns whether the JSON value is bool (true/false). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_bool(yyjson_val *val); /** Returns whether the JSON value is unsigned integer (uint64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_uint(yyjson_val *val); /** Returns whether the JSON value is signed integer (int64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_sint(yyjson_val *val); /** Returns whether the JSON value is integer (uint64_t/int64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_int(yyjson_val *val); /** Returns whether the JSON value is real number (double). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_real(yyjson_val *val); /** Returns whether the JSON value is number (uint64_t/int64_t/double). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_num(yyjson_val *val); /** Returns whether the JSON value is string. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_str(yyjson_val *val); /** Returns whether the JSON value is array. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_arr(yyjson_val *val); /** Returns whether the JSON value is object. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_obj(yyjson_val *val); /** Returns whether the JSON value is container (array/object). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val); /*============================================================================== * JSON Value Content API *============================================================================*/ /** Returns the JSON value's type. Returns YYJSON_TYPE_NONE if `val` is NULL. */ yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val); /** Returns the JSON value's subtype. Returns YYJSON_SUBTYPE_NONE if `val` is NULL. */ yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val); /** Returns the JSON value's tag. Returns 0 if `val` is NULL. */ yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val); /** Returns the JSON value's type description. The return value should be one of these strings: "raw", "null", "string", "array", "object", "true", "false", "uint", "sint", "real", "unknown". */ yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val); /** Returns the content if the value is raw. Returns NULL if `val` is NULL or type is not raw. */ yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val); /** Returns the content if the value is bool. Returns NULL if `val` is NULL or type is not bool. */ yyjson_api_inline bool yyjson_get_bool(yyjson_val *val); /** Returns the content and cast to uint64_t. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val); /** Returns the content and cast to int64_t. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val); /** Returns the content and cast to int. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline int yyjson_get_int(yyjson_val *val); /** Returns the content if the value is real number, or 0.0 on error. Returns 0.0 if `val` is NULL or type is not real(double). */ yyjson_api_inline double yyjson_get_real(yyjson_val *val); /** Returns the content and typecast to `double` if the value is number. Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */ yyjson_api_inline double yyjson_get_num(yyjson_val *val); /** Returns the content if the value is string. Returns NULL if `val` is NULL or type is not string. */ yyjson_api_inline const char *yyjson_get_str(yyjson_val *val); /** Returns the content length (string length, array size, object size. Returns 0 if `val` is NULL or type is not string/array/object. */ yyjson_api_inline size_t yyjson_get_len(yyjson_val *val); /** Returns whether the JSON value is equals to a string. Returns false if input is NULL or type is not string. */ yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str); /** Returns whether the JSON value is equals to a string. The `str` should be a UTF-8 string, null-terminator is not required. Returns false if input is NULL or type is not string. */ yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str, size_t len); /** Returns whether two JSON values are equal (deep compare). Returns false if input is NULL. @note the result may be inaccurate if object has duplicate keys. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs); /** Set the value to raw. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_raw(yyjson_val *val, const char *raw, size_t len); /** Set the value to null. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_null(yyjson_val *val); /** Set the value to bool. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num); /** Set the value to uint. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num); /** Set the value to sint. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num); /** Set the value to int. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num); /** Set the value to real. Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num); /** Set the value to string (null-terminated). Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str); /** Set the value to string (with length). Returns false if input is NULL or `val` is object or array. @warning This will modify the `immutable` value, use with caution. */ yyjson_api_inline bool yyjson_set_strn(yyjson_val *val, const char *str, size_t len); /*============================================================================== * JSON Array API *============================================================================*/ /** Returns the number of elements in this array. Returns 0 if `arr` is NULL or type is not array. */ yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr); /** Returns the element at the specified position in this array. Returns NULL if array is NULL/empty or the index is out of bounds. @warning This function takes a linear search time if array is not flat. For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat. */ yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx); /** Returns the first element of this array. Returns NULL if `arr` is NULL/empty or type is not array. */ yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr); /** Returns the last element of this array. Returns NULL if `arr` is NULL/empty or type is not array. @warning This function takes a linear search time if array is not flat. For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat.*/ yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr); /*============================================================================== * JSON Array Iterator API *============================================================================*/ /** A JSON array iterator. @par Example @code yyjson_val *val; yyjson_arr_iter iter = yyjson_arr_iter_with(arr); while ((val = yyjson_arr_iter_next(&iter))) { your_func(val); } @endcode */ typedef struct yyjson_arr_iter { size_t idx; /**< next value's index */ size_t max; /**< maximum index (arr.size) */ yyjson_val *cur; /**< next value */ } yyjson_arr_iter; /** Initialize an iterator for this array. @param arr The array to be iterated over. If this parameter is NULL or not an array, `iter` will be set to empty. @param iter The iterator to be initialized. If this parameter is NULL, the function will fail and return false. @return true if the `iter` has been successfully initialized. @note The iterator does not need to be destroyed. */ yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr, yyjson_arr_iter *iter); /** Create an iterator with an array , same as `yyjson_arr_iter_init()`. @param arr The array to be iterated over. If this parameter is NULL or not an array, an empty iterator will returned. @return A new iterator for the array. @note The iterator does not need to be destroyed. */ yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr); /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. */ yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter); /** Returns the next element in the iteration, or NULL on end. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter); /** Macro for iterating over an array. It works like iterator, but with a more intuitive API. @par Example @code size_t idx, max; yyjson_val *val; yyjson_arr_foreach(arr, idx, max, val) { your_func(idx, val); } @endcode */ #define yyjson_arr_foreach(arr, idx, max, val) \ for ((idx) = 0, \ (max) = yyjson_arr_size(arr), \ (val) = yyjson_arr_get_first(arr); \ (idx) < (max); \ (idx)++, \ (val) = unsafe_yyjson_get_next(val)) /*============================================================================== * JSON Object API *============================================================================*/ /** Returns the number of key-value pairs in this object. Returns 0 if `obj` is NULL or type is not object. */ yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj); /** Returns the value to which the specified key is mapped. Returns NULL if this object contains no mapping for the key. Returns NULL if `obj/key` is NULL, or type is not object. The `key` should be a null-terminated UTF-8 string. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj, const char *key); /** Returns the value to which the specified key is mapped. Returns NULL if this object contains no mapping for the key. Returns NULL if `obj/key` is NULL, or type is not object. The `key` should be a UTF-8 string, null-terminator is not required. The `key_len` should be the length of the key, in bytes. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *key, size_t key_len); /*============================================================================== * JSON Object Iterator API *============================================================================*/ /** A JSON object iterator. @par Example @code yyjson_val *key, *val; yyjson_obj_iter iter = yyjson_obj_iter_with(obj); while ((key = yyjson_obj_iter_next(&iter))) { val = yyjson_obj_iter_get_val(key); your_func(key, val); } @endcode If the ordering of the keys is known at compile-time, you can use this method to speed up value lookups: @code // {"k1":1, "k2": 3, "k3": 3} yyjson_val *key, *val; yyjson_obj_iter iter = yyjson_obj_iter_with(obj); yyjson_val *v1 = yyjson_obj_iter_get(&iter, "k1"); yyjson_val *v3 = yyjson_obj_iter_get(&iter, "k3"); @endcode @see yyjson_obj_iter_get() and yyjson_obj_iter_getn() */ typedef struct yyjson_obj_iter { size_t idx; /**< next key's index */ size_t max; /**< maximum key index (obj.size) */ yyjson_val *cur; /**< next key */ yyjson_val *obj; /**< the object being iterated */ } yyjson_obj_iter; /** Initialize an iterator for this object. @param obj The object to be iterated over. If this parameter is NULL or not an object, `iter` will be set to empty. @param iter The iterator to be initialized. If this parameter is NULL, the function will fail and return false. @return true if the `iter` has been successfully initialized. @note The iterator does not need to be destroyed. */ yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj, yyjson_obj_iter *iter); /** Create an iterator with an object, same as `yyjson_obj_iter_init()`. @param obj The object to be iterated over. If this parameter is NULL or not an object, an empty iterator will returned. @return A new iterator for the object. @note The iterator does not need to be destroyed. */ yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj); /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. */ yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter); /** Returns the next key in the iteration, or NULL on end. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter); /** Returns the value for key inside the iteration. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key); /** Iterates to a specified key and returns the value. This function does the same thing as `yyjson_obj_get()`, but is much faster if the ordering of the keys is known at compile-time and you are using the same order to look up the values. If the key exists in this object, then the iterator will stop at the next key, otherwise the iterator will not change and NULL is returned. @param iter The object iterator, should not be NULL. @param key The key, should be a UTF-8 string with null-terminator. @return The value to which the specified key is mapped. NULL if this object contains no mapping for the key or input is invalid. @warning This function takes a linear search time if the key is not nearby. */ yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter, const char *key); /** Iterates to a specified key and returns the value. This function does the same thing as `yyjson_obj_getn()`, but is much faster if the ordering of the keys is known at compile-time and you are using the same order to look up the values. If the key exists in this object, then the iterator will stop at the next key, otherwise the iterator will not change and NULL is returned. @param iter The object iterator, should not be NULL. @param key The key, should be a UTF-8 string, null-terminator is not required. @param key_len The the length of `key`, in bytes. @return The value to which the specified key is mapped. NULL if this object contains no mapping for the key or input is invalid. @warning This function takes a linear search time if the key is not nearby. */ yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter, const char *key, size_t key_len); /** Macro for iterating over an object. It works like iterator, but with a more intuitive API. @par Example @code size_t idx, max; yyjson_val *key, *val; yyjson_obj_foreach(obj, idx, max, key, val) { your_func(key, val); } @endcode */ #define yyjson_obj_foreach(obj, idx, max, key, val) \ for ((idx) = 0, \ (max) = yyjson_obj_size(obj), \ (key) = (obj) ? unsafe_yyjson_get_first(obj) : NULL, \ (val) = (key) + 1; \ (idx) < (max); \ (idx)++, \ (key) = unsafe_yyjson_get_next(val), \ (val) = (key) + 1) /*============================================================================== * Mutable JSON Document API *============================================================================*/ /** Returns the root value of this JSON document. Returns NULL if `doc` is NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc); /** Sets the root value of this JSON document. Pass NULL to clear root value of the document. */ yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc, yyjson_mut_val *root); /** Set the string pool size for a mutable document. This function does not allocate memory immediately, but uses the size when the next memory allocation is needed. If the caller knows the approximate bytes of strings that the document needs to store (e.g. copy string with `yyjson_mut_strcpy` function), setting a larger size can avoid multiple memory allocations and improve performance. @param doc The mutable document. @param len The desired string pool size in bytes (total string length). @return true if successful, false if size is 0 or overflow. */ yyjson_api bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc, size_t len); /** Set the value pool size for a mutable document. This function does not allocate memory immediately, but uses the size when the next memory allocation is needed. If the caller knows the approximate number of values that the document needs to store (e.g. create new value with `yyjson_mut_xxx` functions), setting a larger size can avoid multiple memory allocations and improve performance. @param doc The mutable document. @param count The desired value pool size (number of `yyjson_mut_val`). @return true if successful, false if size is 0 or overflow. */ yyjson_api bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count); /** Release the JSON document and free the memory. After calling this function, the `doc` and all values from the `doc` are no longer available. This function will do nothing if the `doc` is NULL. */ yyjson_api void yyjson_mut_doc_free(yyjson_mut_doc *doc); /** Creates and returns a new mutable JSON document, returns NULL on error. If allocator is NULL, the default allocator will be used. */ yyjson_api yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc); /** Copies and returns a new mutable document from input, returns NULL on error. This makes a `deep-copy` on the immutable document. If allocator is NULL, the default allocator will be used. @note `imut_doc` -> `mut_doc`. */ yyjson_api yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, const yyjson_alc *alc); /** Copies and returns a new mutable document from input, returns NULL on error. This makes a `deep-copy` on the mutable document. If allocator is NULL, the default allocator will be used. @note `mut_doc` -> `mut_doc`. */ yyjson_api yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc, const yyjson_alc *alc); /** Copies and returns a new mutable value from input, returns NULL on error. This makes a `deep-copy` on the immutable value. The memory was managed by mutable document. @note `imut_val` -> `mut_val`. */ yyjson_api yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *doc, yyjson_val *val); /** Copies and returns a new mutable value from input, returns NULL on error. This makes a `deep-copy` on the mutable value. The memory was managed by mutable document. @note `mut_val` -> `mut_val`. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc, yyjson_mut_val *val); /** Copies and returns a new immutable document from input, returns NULL on error. This makes a `deep-copy` on the mutable document. The returned document should be freed with `yyjson_doc_free()`. @note `mut_doc` -> `imut_doc`. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *doc, const yyjson_alc *alc); /** Copies and returns a new immutable document from input, returns NULL on error. This makes a `deep-copy` on the mutable value. The returned document should be freed with `yyjson_doc_free()`. @note `mut_val` -> `imut_doc`. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *val, const yyjson_alc *alc); /*============================================================================== * Mutable JSON Value Type API *============================================================================*/ /** Returns whether the JSON value is raw. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val); /** Returns whether the JSON value is `null`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val); /** Returns whether the JSON value is `true`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val); /** Returns whether the JSON value is `false`. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val); /** Returns whether the JSON value is bool (true/false). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val); /** Returns whether the JSON value is unsigned integer (uint64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val); /** Returns whether the JSON value is signed integer (int64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val); /** Returns whether the JSON value is integer (uint64_t/int64_t). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val); /** Returns whether the JSON value is real number (double). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val); /** Returns whether the JSON value is number (uint/sint/real). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val); /** Returns whether the JSON value is string. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val); /** Returns whether the JSON value is array. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val); /** Returns whether the JSON value is object. Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val); /** Returns whether the JSON value is container (array/object). Returns false if `val` is NULL. */ yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val); /*============================================================================== * Mutable JSON Value Content API *============================================================================*/ /** Returns the JSON value's type. Returns `YYJSON_TYPE_NONE` if `val` is NULL. */ yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val); /** Returns the JSON value's subtype. Returns `YYJSON_SUBTYPE_NONE` if `val` is NULL. */ yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val); /** Returns the JSON value's tag. Returns 0 if `val` is NULL. */ yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val); /** Returns the JSON value's type description. The return value should be one of these strings: "raw", "null", "string", "array", "object", "true", "false", "uint", "sint", "real", "unknown". */ yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val); /** Returns the content if the value is raw. Returns NULL if `val` is NULL or type is not raw. */ yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val); /** Returns the content if the value is bool. Returns NULL if `val` is NULL or type is not bool. */ yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val); /** Returns the content and cast to uint64_t. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val); /** Returns the content and cast to int64_t. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val); /** Returns the content and cast to int. Returns 0 if `val` is NULL or type is not integer(sint/uint). */ yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val); /** Returns the content if the value is real number. Returns 0.0 if `val` is NULL or type is not real(double). */ yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val); /** Returns the content and typecast to `double` if the value is number. Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */ yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val); /** Returns the content if the value is string. Returns NULL if `val` is NULL or type is not string. */ yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val); /** Returns the content length (string length, array size, object size. Returns 0 if `val` is NULL or type is not string/array/object. */ yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val); /** Returns whether the JSON value is equals to a string. The `str` should be a null-terminated UTF-8 string. Returns false if input is NULL or type is not string. */ yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val, const char *str); /** Returns whether the JSON value is equals to a string. The `str` should be a UTF-8 string, null-terminator is not required. Returns false if input is NULL or type is not string. */ yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val, const char *str, size_t len); /** Returns whether two JSON values are equal (deep compare). Returns false if input is NULL. @note the result may be inaccurate if object has duplicate keys. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs); /** Set the value to raw. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val, const char *raw, size_t len); /** Set the value to null. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val); /** Set the value to bool. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num); /** Set the value to uint. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num); /** Set the value to sint. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num); /** Set the value to int. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num); /** Set the value to real. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num); /** Set the value to string (null-terminated). Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val, const char *str); /** Set the value to string (with length). Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val, const char *str, size_t len); /** Set the value to array. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val); /** Set the value to array. Returns false if input is NULL. @warning This function should not be used on an existing object or array. */ yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val); /*============================================================================== * Mutable JSON Value Creation API *============================================================================*/ /** Creates and returns a raw value, returns NULL on error. The `str` should be a null-terminated UTF-8 string. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc, const char *str); /** Creates and returns a raw value, returns NULL on error. The `str` should be a UTF-8 string, null-terminator is not required. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc, const char *str, size_t len); /** Creates and returns a raw value, returns NULL on error. The `str` should be a null-terminated UTF-8 string. The input string is copied and held by the document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc, const char *str); /** Creates and returns a raw value, returns NULL on error. The `str` should be a UTF-8 string, null-terminator is not required. The input string is copied and held by the document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc, const char *str, size_t len); /** Creates and returns a null value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc); /** Creates and returns a true value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc); /** Creates and returns a false value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc); /** Creates and returns a bool value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc, bool val); /** Creates and returns an unsigned integer value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc, uint64_t num); /** Creates and returns a signed integer value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc, int64_t num); /** Creates and returns a signed integer value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc, int64_t num); /** Creates and returns an real number value, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc, double num); /** Creates and returns a string value, returns NULL on error. The `str` should be a null-terminated UTF-8 string. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc, const char *str); /** Creates and returns a string value, returns NULL on error. The `str` should be a UTF-8 string, null-terminator is not required. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc, const char *str, size_t len); /** Creates and returns a string value, returns NULL on error. The `str` should be a null-terminated UTF-8 string. The input string is copied and held by the document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc, const char *str); /** Creates and returns a string value, returns NULL on error. The `str` should be a UTF-8 string, null-terminator is not required. The input string is copied and held by the document. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc, const char *str, size_t len); /*============================================================================== * Mutable JSON Array API *============================================================================*/ /** Returns the number of elements in this array. Returns 0 if `arr` is NULL or type is not array. */ yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr); /** Returns the element at the specified position in this array. Returns NULL if array is NULL/empty or the index is out of bounds. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr, size_t idx); /** Returns the first element of this array. Returns NULL if `arr` is NULL/empty or type is not array. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first(yyjson_mut_val *arr); /** Returns the last element of this array. Returns NULL if `arr` is NULL/empty or type is not array. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(yyjson_mut_val *arr); /*============================================================================== * Mutable JSON Array Iterator API *============================================================================*/ /** A mutable JSON array iterator. @warning You should not modify the array while iterating over it, but you can use `yyjson_mut_arr_iter_remove()` to remove current value. @par Example @code yyjson_mut_val *val; yyjson_mut_arr_iter iter = yyjson_mut_arr_iter_with(arr); while ((val = yyjson_mut_arr_iter_next(&iter))) { your_func(val); if (your_val_is_unused(val)) { yyjson_mut_arr_iter_remove(&iter); } } @endcode */ typedef struct yyjson_mut_arr_iter { size_t idx; /**< next value's index */ size_t max; /**< maximum index (arr.size) */ yyjson_mut_val *cur; /**< current value */ yyjson_mut_val *pre; /**< previous value */ yyjson_mut_val *arr; /**< the array being iterated */ } yyjson_mut_arr_iter; /** Initialize an iterator for this array. @param arr The array to be iterated over. If this parameter is NULL or not an array, `iter` will be set to empty. @param iter The iterator to be initialized. If this parameter is NULL, the function will fail and return false. @return true if the `iter` has been successfully initialized. @note The iterator does not need to be destroyed. */ yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr, yyjson_mut_arr_iter *iter); /** Create an iterator with an array , same as `yyjson_mut_arr_iter_init()`. @param arr The array to be iterated over. If this parameter is NULL or not an array, an empty iterator will returned. @return A new iterator for the array. @note The iterator does not need to be destroyed. */ yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with( yyjson_mut_val *arr); /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. */ yyjson_api_inline bool yyjson_mut_arr_iter_has_next( yyjson_mut_arr_iter *iter); /** Returns the next element in the iteration, or NULL on end. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next( yyjson_mut_arr_iter *iter); /** Removes and returns current element in the iteration. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove( yyjson_mut_arr_iter *iter); /** Macro for iterating over an array. It works like iterator, but with a more intuitive API. @warning You should not modify the array while iterating over it. @par Example @code size_t idx, max; yyjson_mut_val *val; yyjson_mut_arr_foreach(arr, idx, max, val) { your_func(idx, val); } @endcode */ #define yyjson_mut_arr_foreach(arr, idx, max, val) \ for ((idx) = 0, \ (max) = yyjson_mut_arr_size(arr), \ (val) = yyjson_mut_arr_get_first(arr); \ (idx) < (max); \ (idx)++, \ (val) = (val)->next) /*============================================================================== * Mutable JSON Array Creation API *============================================================================*/ /** Creates and returns an empty mutable array. @param doc A mutable document, used for memory allocation only. @return The new array. NULL if input is NULL or memory allocation failed. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc); /** Creates and returns a new mutable array with the given boolean values. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of boolean values. @param count The value count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const bool vals[3] = { true, false, true }; yyjson_mut_val *arr = yyjson_mut_arr_with_bool(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool( yyjson_mut_doc *doc, const bool *vals, size_t count); /** Creates and returns a new mutable array with the given sint numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of sint numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int64_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint( yyjson_mut_doc *doc, const int64_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint64_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint( yyjson_mut_doc *doc, const uint64_t *vals, size_t count); /** Creates and returns a new mutable array with the given real numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of real numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const double vals[3] = { 0.1, 0.2, 0.3 }; yyjson_mut_val *arr = yyjson_mut_arr_with_real(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real( yyjson_mut_doc *doc, const double *vals, size_t count); /** Creates and returns a new mutable array with the given int8 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of int8 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int8_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint8(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8( yyjson_mut_doc *doc, const int8_t *vals, size_t count); /** Creates and returns a new mutable array with the given int16 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of int16 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int16_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint16(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16( yyjson_mut_doc *doc, const int16_t *vals, size_t count); /** Creates and returns a new mutable array with the given int32 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of int32 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int32_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint32(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32( yyjson_mut_doc *doc, const int32_t *vals, size_t count); /** Creates and returns a new mutable array with the given int64 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of int64 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const int64_t vals[3] = { -1, 0, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64( yyjson_mut_doc *doc, const int64_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint8 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint8 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint8_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint8(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8( yyjson_mut_doc *doc, const uint8_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint16 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint16 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint16_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint16(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16( yyjson_mut_doc *doc, const uint16_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint32 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint32 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint32_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint32(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32( yyjson_mut_doc *doc, const uint32_t *vals, size_t count); /** Creates and returns a new mutable array with the given uint64 numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of uint64 numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const uint64_t vals[3] = { 0, 1, 0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_uint64(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64( yyjson_mut_doc *doc, const uint64_t *vals, size_t count); /** Creates and returns a new mutable array with the given float numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of float numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const float vals[3] = { -1.0f, 0.0f, 1.0f }; yyjson_mut_val *arr = yyjson_mut_arr_with_float(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float( yyjson_mut_doc *doc, const float *vals, size_t count); /** Creates and returns a new mutable array with the given double numbers. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of double numbers. @param count The number count. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const double vals[3] = { -1.0, 0.0, 1.0 }; yyjson_mut_val *arr = yyjson_mut_arr_with_double(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double( yyjson_mut_doc *doc, const double *vals, size_t count); /** Creates and returns a new mutable array with the given strings, these strings will not be copied. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of UTF-8 null-terminator strings. If this array contains NULL, the function will fail and return NULL. @param count The number of values in `vals`. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @warning The input strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. If these strings will be modified, you should use `yyjson_mut_arr_with_strcpy()` instead. @par Example @code const char *vals[3] = { "a", "b", "c" }; yyjson_mut_val *arr = yyjson_mut_arr_with_str(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str( yyjson_mut_doc *doc, const char **vals, size_t count); /** Creates and returns a new mutable array with the given strings and string lengths, these strings will not be copied. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of UTF-8 strings, null-terminator is not required. If this array contains NULL, the function will fail and return NULL. @param lens A C array of string lengths, in bytes. @param count The number of strings in `vals`. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @warning The input strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. If these strings will be modified, you should use `yyjson_mut_arr_with_strncpy()` instead. @par Example @code const char *vals[3] = { "a", "bb", "c" }; const size_t lens[3] = { 1, 2, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn( yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count); /** Creates and returns a new mutable array with the given strings, these strings will be copied. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of UTF-8 null-terminator strings. If this array contains NULL, the function will fail and return NULL. @param count The number of values in `vals`. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const char *vals[3] = { "a", "b", "c" }; yyjson_mut_val *arr = yyjson_mut_arr_with_strcpy(doc, vals, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy( yyjson_mut_doc *doc, const char **vals, size_t count); /** Creates and returns a new mutable array with the given strings and string lengths, these strings will be copied. @param doc A mutable document, used for memory allocation only. If this parameter is NULL, the function will fail and return NULL. @param vals A C array of UTF-8 strings, null-terminator is not required. If this array contains NULL, the function will fail and return NULL. @param lens A C array of string lengths, in bytes. @param count The number of strings in `vals`. If this value is 0, an empty array will return. @return The new array. NULL if input is invalid or memory allocation failed. @par Example @code const char *vals[3] = { "a", "bb", "c" }; const size_t lens[3] = { 1, 2, 1 }; yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy( yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count); /*============================================================================== * Mutable JSON Array Modification API *============================================================================*/ /** Inserts a value into an array at a given index. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The value to be inserted. Returns false if it is NULL. @param idx The index to which to insert the new value. Returns false if the index is out of range. @return Whether successful. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr, yyjson_mut_val *val, size_t idx); /** Inserts a value at the end of the array. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The value to be inserted. Returns false if it is NULL. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr, yyjson_mut_val *val); /** Inserts a value at the head of the array. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The value to be inserted. Returns false if it is NULL. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr, yyjson_mut_val *val); /** Replaces a value at index and returns old value. @param arr The array to which the value is to be replaced. Returns false if it is NULL or not an array. @param idx The index to which to replace the value. Returns false if the index is out of range. @param val The new value to replace. Returns false if it is NULL. @return Old value, or NULL on error. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr, size_t idx, yyjson_mut_val *val); /** Removes and returns a value at index. @param arr The array from which the value is to be removed. Returns false if it is NULL or not an array. @param idx The index from which to remove the value. Returns false if the index is out of range. @return Old value, or NULL on error. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr, size_t idx); /** Removes and returns the first value in this array. @param arr The array from which the value is to be removed. Returns false if it is NULL or not an array. @return The first value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first( yyjson_mut_val *arr); /** Removes and returns the last value in this array. @param arr The array from which the value is to be removed. Returns false if it is NULL or not an array. @return The last value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last( yyjson_mut_val *arr); /** Removes all values within a specified range in the array. @param arr The array from which the value is to be removed. Returns false if it is NULL or not an array. @param idx The start index of the range (0 is the first). @param len The number of items in the range (can be 0). @return Whether successful. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr, size_t idx, size_t len); /** Removes all values in this array. @param arr The array from which all of the values are to be removed. Returns false if it is NULL or not an array. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr); /** Rotates values in this array for the given number of times. For example: `[1,2,3,4,5]` rotate 2 is `[3,4,5,1,2]`. @param arr The array to be rotated. @param idx Index (or times) to rotate. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr, size_t idx); /*============================================================================== * Mutable JSON Array Modification Convenience API *============================================================================*/ /** Adds a value at the end of the array. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The value to be inserted. Returns false if it is NULL. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr, yyjson_mut_val *val); /** Adds a `null` value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc, yyjson_mut_val *arr); /** Adds a `true` value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc, yyjson_mut_val *arr); /** Adds a `false` value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc, yyjson_mut_val *arr); /** Adds a bool value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param val The bool value to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *arr, bool val); /** Adds an unsigned integer value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param num The number to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *arr, uint64_t num); /** Adds a signed integer value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param num The number to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *arr, int64_t num); /** Adds a integer value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param num The number to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc, yyjson_mut_val *arr, int64_t num); /** Adds a double value at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param num The number to be added. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc, yyjson_mut_val *arr, double num); /** Adds a string value at the end of the array (no copy). @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param str A null-terminated UTF-8 string. @return Whether successful. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str); /** Adds a string value at the end of the array (no copy). @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param str A UTF-8 string, null-terminator is not required. @param len The length of the string, in bytes. @return Whether successful. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str, size_t len); /** Adds a string value at the end of the array (copied). @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param str A null-terminated UTF-8 string. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str); /** Adds a string value at the end of the array (copied). @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @param str A UTF-8 string, null-terminator is not required. @param len The length of the string, in bytes. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str, size_t len); /** Creates and adds a new array at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return The new array, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc, yyjson_mut_val *arr); /** Creates and adds a new object at the end of the array. @param doc The `doc` is only used for memory allocation. @param arr The array to which the value is to be inserted. Returns false if it is NULL or not an array. @return The new object, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc, yyjson_mut_val *arr); /*============================================================================== * Mutable JSON Object API *============================================================================*/ /** Returns the number of key-value pairs in this object. Returns 0 if `obj` is NULL or type is not object. */ yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj); /** Returns the value to which the specified key is mapped. Returns NULL if this object contains no mapping for the key. Returns NULL if `obj/key` is NULL, or type is not object. The `key` should be a null-terminated UTF-8 string. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj, const char *key); /** Returns the value to which the specified key is mapped. Returns NULL if this object contains no mapping for the key. Returns NULL if `obj/key` is NULL, or type is not object. The `key` should be a UTF-8 string, null-terminator is not required. The `key_len` should be the length of the key, in bytes. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj, const char *key, size_t key_len); /*============================================================================== * Mutable JSON Object Iterator API *============================================================================*/ /** A mutable JSON object iterator. @warning You should not modify the object while iterating over it, but you can use `yyjson_mut_obj_iter_remove()` to remove current value. @par Example @code yyjson_mut_val *key, *val; yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj); while ((key = yyjson_mut_obj_iter_next(&iter))) { val = yyjson_mut_obj_iter_get_val(key); your_func(key, val); if (your_val_is_unused(key, val)) { yyjson_mut_obj_iter_remove(&iter); } } @endcode If the ordering of the keys is known at compile-time, you can use this method to speed up value lookups: @code // {"k1":1, "k2": 3, "k3": 3} yyjson_mut_val *key, *val; yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj); yyjson_mut_val *v1 = yyjson_mut_obj_iter_get(&iter, "k1"); yyjson_mut_val *v3 = yyjson_mut_obj_iter_get(&iter, "k3"); @endcode @see `yyjson_mut_obj_iter_get()` and `yyjson_mut_obj_iter_getn()` */ typedef struct yyjson_mut_obj_iter { size_t idx; /**< next key's index */ size_t max; /**< maximum key index (obj.size) */ yyjson_mut_val *cur; /**< current key */ yyjson_mut_val *pre; /**< previous key */ yyjson_mut_val *obj; /**< the object being iterated */ } yyjson_mut_obj_iter; /** Initialize an iterator for this object. @param obj The object to be iterated over. If this parameter is NULL or not an array, `iter` will be set to empty. @param iter The iterator to be initialized. If this parameter is NULL, the function will fail and return false. @return true if the `iter` has been successfully initialized. @note The iterator does not need to be destroyed. */ yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj, yyjson_mut_obj_iter *iter); /** Create an iterator with an object, same as `yyjson_obj_iter_init()`. @param obj The object to be iterated over. If this parameter is NULL or not an object, an empty iterator will returned. @return A new iterator for the object. @note The iterator does not need to be destroyed. */ yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with( yyjson_mut_val *obj); /** Returns whether the iteration has more elements. If `iter` is NULL, this function will return false. */ yyjson_api_inline bool yyjson_mut_obj_iter_has_next( yyjson_mut_obj_iter *iter); /** Returns the next key in the iteration, or NULL on end. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next( yyjson_mut_obj_iter *iter); /** Returns the value for key inside the iteration. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val( yyjson_mut_val *key); /** Removes current key-value pair in the iteration, returns the removed value. If `iter` is NULL, this function will return NULL. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove( yyjson_mut_obj_iter *iter); /** Iterates to a specified key and returns the value. This function does the same thing as `yyjson_mut_obj_get()`, but is much faster if the ordering of the keys is known at compile-time and you are using the same order to look up the values. If the key exists in this object, then the iterator will stop at the next key, otherwise the iterator will not change and NULL is returned. @param iter The object iterator, should not be NULL. @param key The key, should be a UTF-8 string with null-terminator. @return The value to which the specified key is mapped. NULL if this object contains no mapping for the key or input is invalid. @warning This function takes a linear search time if the key is not nearby. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get( yyjson_mut_obj_iter *iter, const char *key); /** Iterates to a specified key and returns the value. This function does the same thing as `yyjson_mut_obj_getn()` but is much faster if the ordering of the keys is known at compile-time and you are using the same order to look up the values. If the key exists in this object, then the iterator will stop at the next key, otherwise the iterator will not change and NULL is returned. @param iter The object iterator, should not be NULL. @param key The key, should be a UTF-8 string, null-terminator is not required. @param key_len The the length of `key`, in bytes. @return The value to which the specified key is mapped. NULL if this object contains no mapping for the key or input is invalid. @warning This function takes a linear search time if the key is not nearby. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn( yyjson_mut_obj_iter *iter, const char *key, size_t key_len); /** Macro for iterating over an object. It works like iterator, but with a more intuitive API. @warning You should not modify the object while iterating over it. @par Example @code size_t idx, max; yyjson_val *key, *val; yyjson_obj_foreach(obj, idx, max, key, val) { your_func(key, val); } @endcode */ #define yyjson_mut_obj_foreach(obj, idx, max, key, val) \ for ((idx) = 0, \ (max) = yyjson_mut_obj_size(obj), \ (key) = (max) ? ((yyjson_mut_val *)(obj)->uni.ptr)->next->next : NULL, \ (val) = (key) ? (key)->next : NULL; \ (idx) < (max); \ (idx)++, \ (key) = (val)->next, \ (val) = (key)->next) /*============================================================================== * Mutable JSON Object Creation API *============================================================================*/ /** Creates and returns a mutable object, returns NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc); /** Creates and returns a mutable object with keys and values, returns NULL on error. The keys and values are not copied. The strings should be a null-terminated UTF-8 string. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. @par Example @code const char *keys[2] = { "id", "name" }; const char *vals[2] = { "01", "Harry" }; yyjson_mut_val *obj = yyjson_mut_obj_with_str(doc, keys, vals, 2); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc, const char **keys, const char **vals, size_t count); /** Creates and returns a mutable object with key-value pairs and pair count, returns NULL on error. The keys and values are not copied. The strings should be a null-terminated UTF-8 string. @warning The input string is not copied, you should keep this string unmodified for the lifetime of this JSON document. @par Example @code const char *kv_pairs[4] = { "id", "01", "name", "Harry" }; yyjson_mut_val *obj = yyjson_mut_obj_with_kv(doc, kv_pairs, 2); @endcode */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc, const char **kv_pairs, size_t pair_count); /*============================================================================== * Mutable JSON Object Modification API *============================================================================*/ /** Adds a key-value pair at the end of the object. This function allows duplicated key in one object. @param obj The object to which the new key-value pair is to be added. @param key The key, should be a string which is created by `yyjson_mut_str()`, `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`. @param val The value to add to the object. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val); /** Sets a key-value pair at the end of the object. This function may remove all key-value pairs for the given key before add. @param obj The object to which the new key-value pair is to be added. @param key The key, should be a string which is created by `yyjson_mut_str()`, `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`. @param val The value to add to the object. If this value is null, the behavior is same as `yyjson_mut_obj_remove()`. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val); /** Inserts a key-value pair to the object at the given position. This function allows duplicated key in one object. @param obj The object to which the new key-value pair is to be added. @param key The key, should be a string which is created by `yyjson_mut_str()`, `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`. @param val The value to add to the object. @param idx The index to which to insert the new pair. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val, size_t idx); /** Removes all key-value pair from the object with given key. @param obj The object from which the key-value pair is to be removed. @param key The key, should be a string value. @return The first matched value, or NULL if no matched value. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj, yyjson_mut_val *key); /** Removes all key-value pair from the object with given key. @param obj The object from which the key-value pair is to be removed. @param key The key, should be a UTF-8 string with null-terminator. @return The first matched value, or NULL if no matched value. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key( yyjson_mut_val *obj, const char *key); /** Removes all key-value pair from the object with given key. @param obj The object from which the key-value pair is to be removed. @param key The key, should be a UTF-8 string, null-terminator is not required. @param key_len The length of the key. @return The first matched value, or NULL if no matched value. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn( yyjson_mut_val *obj, const char *key, size_t key_len); /** Removes all key-value pairs in this object. @param obj The object from which all of the values are to be removed. @return Whether successful. */ yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj); /** Replaces value from the object with given key. If the key is not exist, or the value is NULL, it will fail. @param obj The object to which the value is to be replaced. @param key The key, should be a string value. @param val The value to replace into the object. @return Whether successful. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val); /** Rotates key-value pairs in the object for the given number of times. For example: `{"a":1,"b":2,"c":3,"d":4}` rotate 1 is `{"b":2,"c":3,"d":4,"a":1}`. @param obj The object to be rotated. @param idx Index (or times) to rotate. @return Whether successful. @warning This function takes a linear search time. */ yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj, size_t idx); /*============================================================================== * Mutable JSON Object Modification Convenience API *============================================================================*/ /** Adds a `null` value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key); /** Adds a `true` value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key); /** Adds a `false` value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key); /** Adds a bool value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, bool val); /** Adds an unsigned integer value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, uint64_t val); /** Adds a signed integer value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, int64_t val); /** Adds an int value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, int64_t val); /** Adds a double value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, double val); /** Adds a string value at the end of the object. The `key` and `val` should be null-terminated UTF-8 strings. This function allows duplicated key in one object. @warning The key/value string are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val); /** Adds a string value at the end of the object. The `key` should be a null-terminated UTF-8 string. The `val` should be a UTF-8 string, null-terminator is not required. The `len` should be the length of the `val`, in bytes. This function allows duplicated key in one object. @warning The key/value string are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val, size_t len); /** Adds a string value at the end of the object. The `key` and `val` should be null-terminated UTF-8 strings. The value string is copied. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val); /** Adds a string value at the end of the object. The `key` should be a null-terminated UTF-8 string. The `val` should be a UTF-8 string, null-terminator is not required. The `len` should be the length of the `val`, in bytes. This function allows duplicated key in one object. @warning The key/value string are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val, size_t len); /** Adds a JSON value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. @warning The key string are not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, yyjson_mut_val *val); /** Removes all key-value pairs for the given key. Returns the first value to which the specified key is mapped or NULL if this object contains no mapping for the key. The `key` should be a null-terminated UTF-8 string. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str( yyjson_mut_val *obj, const char *key); /** Removes all key-value pairs for the given key. Returns the first value to which the specified key is mapped or NULL if this object contains no mapping for the key. The `key` should be a UTF-8 string, null-terminator is not required. The `len` should be the length of the key, in bytes. @warning This function takes a linear search time. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn( yyjson_mut_val *obj, const char *key, size_t len); /** Replaces all matching keys with the new key. Returns true if at least one key was renamed. The `key` and `new_key` should be a null-terminated UTF-8 string. The `new_key` is copied and held by doc. @warning This function takes a linear search time. If `new_key` already exists, it will cause duplicate keys. */ yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *new_key); /** Replaces all matching keys with the new key. Returns true if at least one key was renamed. The `key` and `new_key` should be a UTF-8 string, null-terminator is not required. The `new_key` is copied and held by doc. @warning This function takes a linear search time. If `new_key` already exists, it will cause duplicate keys. */ yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, size_t len, const char *new_key, size_t new_len); /*============================================================================== * JSON Pointer API (RFC 6901) * https://tools.ietf.org/html/rfc6901 *============================================================================*/ /** JSON Pointer error code. */ typedef uint32_t yyjson_ptr_code; /** No JSON pointer error. */ static const yyjson_ptr_code YYJSON_PTR_ERR_NONE = 0; /** Invalid input parameter, such as NULL input. */ static const yyjson_ptr_code YYJSON_PTR_ERR_PARAMETER = 1; /** JSON pointer syntax error, such as invalid escape, token no prefix. */ static const yyjson_ptr_code YYJSON_PTR_ERR_SYNTAX = 2; /** JSON pointer resolve failed, such as index out of range, key not found. */ static const yyjson_ptr_code YYJSON_PTR_ERR_RESOLVE = 3; /** Document's root is NULL, but it is required for the function call. */ static const yyjson_ptr_code YYJSON_PTR_ERR_NULL_ROOT = 4; /** Cannot set root as the target is not a document. */ static const yyjson_ptr_code YYJSON_PTR_ERR_SET_ROOT = 5; /** The memory allocation failed and a new value could not be created. */ static const yyjson_ptr_code YYJSON_PTR_ERR_MEMORY_ALLOCATION = 6; /** Error information for JSON pointer. */ typedef struct yyjson_ptr_err { /** Error code, see `yyjson_ptr_code` for all possible values. */ yyjson_ptr_code code; /** Error message, constant, no need to free (NULL if no error). */ const char *msg; /** Error byte position for input JSON pointer (0 if no error). */ size_t pos; } yyjson_ptr_err; /** A context for JSON pointer operation. This struct stores the context of JSON Pointer operation result. The struct can be used with three helper functions: `ctx_append()`, `ctx_replace()`, and `ctx_remove()`, which perform the corresponding operations on the container without re-parsing the JSON Pointer. For example: @code // doc before: {"a":[0,1,null]} // ptr: "/a/2" val = yyjson_mut_doc_ptr_getx(doc, ptr, strlen(ptr), &ctx, &err); if (yyjson_is_null(val)) { yyjson_ptr_ctx_remove(&ctx); } // doc after: {"a":[0,1]} @endcode */ typedef struct yyjson_ptr_ctx { /** The container (parent) of the target value. It can be either an array or an object. If the target location has no value, but all its parent containers exist, and the target location can be used to insert a new value, then `ctn` is the parent container of the target location. Otherwise, `ctn` is NULL. */ yyjson_mut_val *ctn; /** The previous sibling of the target value. It can be either a value in an array or a key in an object. As the container is a `circular linked list` of elements, `pre` is the previous node of the target value. If the operation is `add` or `set`, then `pre` is the previous node of the new value, not the original target value. If the target value does not exist, `pre` is NULL. */ yyjson_mut_val *pre; /** The removed value if the operation is `set`, `replace` or `remove`. It can be used to restore the original state of the document if needed. */ yyjson_mut_val *old; } yyjson_ptr_ctx; /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc, const char *ptr); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc, const char *ptr, size_t len); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param err A pointer to store the error information, or NULL if not needed. @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc, const char *ptr, size_t len, yyjson_ptr_err *err); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val, const char *ptr); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val, const char *ptr, size_t len); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param err A pointer to store the error information, or NULL if not needed. @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val, const char *ptr, size_t len, yyjson_ptr_err *err); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc, const char *ptr); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc, const char *ptr, size_t len); /** Get value by a JSON Pointer. @param doc The JSON document to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The value referenced by the JSON pointer. NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val, const char *ptr); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val, const char *ptr, size_t len); /** Get value by a JSON Pointer. @param val The JSON value to be queried. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The value referenced by the JSON pointer. NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Add (insert) value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The value to be added. @return true if JSON pointer is valid and new value is added, false otherwise. @note The parent nodes will be created if they do not exist. */ yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val); /** Add (insert) value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be added. @return true if JSON pointer is valid and new value is added, false otherwise. @note The parent nodes will be created if they do not exist. */ yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val); /** Add (insert) value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be added. @param create_parent Whether to create parent nodes if not exist. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return true if JSON pointer is valid and new value is added, false otherwise. */ yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Add (insert) value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param doc Only used to create new values when needed. @param new_val The value to be added. @return true if JSON pointer is valid and new value is added, false otherwise. @note The parent nodes will be created if they do not exist. */ yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val, yyjson_mut_doc *doc); /** Add (insert) value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param doc Only used to create new values when needed. @param new_val The value to be added. @return true if JSON pointer is valid and new value is added, false otherwise. @note The parent nodes will be created if they do not exist. */ yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc); /** Add (insert) value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param doc Only used to create new values when needed. @param new_val The value to be added. @param create_parent Whether to create parent nodes if not exist. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return true if JSON pointer is valid and new value is added, false otherwise. */ yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Set value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The value to be set, pass NULL to remove. @return true if JSON pointer is valid and new value is set, false otherwise. @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val); /** Set value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be set, pass NULL to remove. @return true if JSON pointer is valid and new value is set, false otherwise. @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val); /** Set value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be set, pass NULL to remove. @param create_parent Whether to create parent nodes if not exist. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return true if JSON pointer is valid and new value is set, false otherwise. @note If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Set value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The value to be set, pass NULL to remove. @param doc Only used to create new values when needed. @return true if JSON pointer is valid and new value is set, false otherwise. @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val, yyjson_mut_doc *doc); /** Set value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be set, pass NULL to remove. @param doc Only used to create new values when needed. @return true if JSON pointer is valid and new value is set, false otherwise. @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc); /** Set value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The value to be set, pass NULL to remove. @param doc Only used to create new values when needed. @param create_parent Whether to create parent nodes if not exist. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return true if JSON pointer is valid and new value is set, false otherwise. @note If the target value already exists, it will be replaced by the new value. */ yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Replace value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The new value to replace the old one. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace( yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val); /** Replace value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The new value to replace the old one. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val); /** Replace value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The new value to replace the old one. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Replace value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8 with null-terminator). @param new_val The new value to replace the old one. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace( yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val); /** Replace value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The new value to replace the old one. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val); /** Replace value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param new_val The new value to replace the old one. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The old value that was replaced, or NULL if not found. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Remove value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove( yyjson_mut_doc *doc, const char *ptr); /** Remove value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen( yyjson_mut_doc *doc, const char *ptr, size_t len); /** Remove value by a JSON pointer. @param doc The target JSON document. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Remove value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8 with null-terminator). @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val, const char *ptr); /** Remove value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val, const char *ptr, size_t len); /** Remove value by a JSON pointer. @param val The target JSON value. @param ptr The JSON pointer string (UTF-8, null-terminator is not required). @param len The length of `ptr` in bytes. @param ctx A pointer to store the result context, or NULL if not needed. @param err A pointer to store the error information, or NULL if not needed. @return The removed value, or NULL on error. */ yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /** Append value by JSON pointer context. @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. @param key New key if `ctx->ctn` is object, or NULL if `ctx->ctn` is array. @param val New value to be added. @return true on success or false on fail. */ yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx, yyjson_mut_val *key, yyjson_mut_val *val); /** Replace value by JSON pointer context. @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. @param val New value to be replaced. @return true on success or false on fail. @note If success, the old value will be returned via `ctx->old`. */ yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx, yyjson_mut_val *val); /** Remove value by JSON pointer context. @param ctx The context from the `yyjson_mut_ptr_xxx()` calls. @return true on success or false on fail. @note If success, the old value will be returned via `ctx->old`. */ yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx); /*============================================================================== * JSON Patch API (RFC 6902) * https://tools.ietf.org/html/rfc6902 *============================================================================*/ /** Result code for JSON patch. */ typedef uint32_t yyjson_patch_code; /** Success, no error. */ static const yyjson_patch_code YYJSON_PATCH_SUCCESS = 0; /** Invalid parameter, such as NULL input or non-array patch. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_PARAMETER = 1; /** Memory allocation failure occurs. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_MEMORY_ALLOCATION = 2; /** JSON patch operation is not object type. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_OPERATION = 3; /** JSON patch operation is missing a required key. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_MISSING_KEY = 4; /** JSON patch operation member is invalid. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_MEMBER = 5; /** JSON patch operation `test` not equal. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_EQUAL = 6; /** JSON patch operation failed on JSON pointer. */ static const yyjson_patch_code YYJSON_PATCH_ERROR_POINTER = 7; /** Error information for JSON patch. */ typedef struct yyjson_patch_err { /** Error code, see `yyjson_patch_code` for all possible values. */ yyjson_patch_code code; /** Index of the error operation (0 if no error). */ size_t idx; /** Error message, constant, no need to free (NULL if no error). */ const char *msg; /** JSON pointer error if `code == YYJSON_PATCH_ERROR_POINTER`. */ yyjson_ptr_err ptr; } yyjson_patch_err; /** Creates and returns a patched JSON value (RFC 6902). The memory of the returned value is allocated by the `doc`. The `err` is used to receive error information, pass NULL if not needed. Returns NULL if the patch could not be applied. */ yyjson_api yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch, yyjson_patch_err *err); /** Creates and returns a patched JSON value (RFC 6902). The memory of the returned value is allocated by the `doc`. The `err` is used to receive error information, pass NULL if not needed. Returns NULL if the patch could not be applied. */ yyjson_api yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch, yyjson_patch_err *err); /*============================================================================== * JSON Merge-Patch API (RFC 7386) * https://tools.ietf.org/html/rfc7386 *============================================================================*/ /** Creates and returns a merge-patched JSON value (RFC 7386). The memory of the returned value is allocated by the `doc`. Returns NULL if the patch could not be applied. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, yyjson_val *orig, yyjson_val *patch); /** Creates and returns a merge-patched JSON value (RFC 7386). The memory of the returned value is allocated by the `doc`. Returns NULL if the patch could not be applied. @warning This function is recursive and may cause a stack overflow if the object level is too deep. */ yyjson_api yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, yyjson_mut_val *orig, yyjson_mut_val *patch); /*============================================================================== * JSON Structure (Implementation) *============================================================================*/ /** Payload of a JSON value (8 bytes). */ typedef union yyjson_val_uni { uint64_t u64; int64_t i64; double f64; const char *str; void *ptr; size_t ofs; } yyjson_val_uni; /** Immutable JSON value, 16 bytes. */ struct yyjson_val { uint64_t tag; /**< type, subtype and length */ yyjson_val_uni uni; /**< payload */ }; struct yyjson_doc { /** Root value of the document (nonnull). */ yyjson_val *root; /** Allocator used by document (nonnull). */ yyjson_alc alc; /** The total number of bytes read when parsing JSON (nonzero). */ size_t dat_read; /** The total number of value read when parsing JSON (nonzero). */ size_t val_read; /** The string pool used by JSON values (nullable). */ char *str_pool; }; /*============================================================================== * Unsafe JSON Value API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_type unsafe_yyjson_get_type(void *val) { uint8_t tag = (uint8_t)((yyjson_val *)val)->tag; return (yyjson_type)(tag & YYJSON_TYPE_MASK); } yyjson_api_inline yyjson_subtype unsafe_yyjson_get_subtype(void *val) { uint8_t tag = (uint8_t)((yyjson_val *)val)->tag; return (yyjson_subtype)(tag & YYJSON_SUBTYPE_MASK); } yyjson_api_inline uint8_t unsafe_yyjson_get_tag(void *val) { uint8_t tag = (uint8_t)((yyjson_val *)val)->tag; return (uint8_t)(tag & YYJSON_TAG_MASK); } yyjson_api_inline bool unsafe_yyjson_is_raw(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_RAW; } yyjson_api_inline bool unsafe_yyjson_is_null(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NULL; } yyjson_api_inline bool unsafe_yyjson_is_bool(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_BOOL; } yyjson_api_inline bool unsafe_yyjson_is_num(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NUM; } yyjson_api_inline bool unsafe_yyjson_is_str(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_STR; } yyjson_api_inline bool unsafe_yyjson_is_arr(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_ARR; } yyjson_api_inline bool unsafe_yyjson_is_obj(void *val) { return unsafe_yyjson_get_type(val) == YYJSON_TYPE_OBJ; } yyjson_api_inline bool unsafe_yyjson_is_ctn(void *val) { uint8_t mask = YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ; return (unsafe_yyjson_get_tag(val) & mask) == mask; } yyjson_api_inline bool unsafe_yyjson_is_uint(void *val) { const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_is_sint(void *val) { const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_is_int(void *val) { const uint8_t mask = YYJSON_TAG_MASK & (~YYJSON_SUBTYPE_SINT); const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; return (unsafe_yyjson_get_tag(val) & mask) == patt; } yyjson_api_inline bool unsafe_yyjson_is_real(void *val) { const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_is_true(void *val) { const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_is_false(void *val) { const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; return unsafe_yyjson_get_tag(val) == patt; } yyjson_api_inline bool unsafe_yyjson_arr_is_flat(yyjson_val *val) { size_t ofs = val->uni.ofs; size_t len = (size_t)(val->tag >> YYJSON_TAG_BIT); return len * sizeof(yyjson_val) + sizeof(yyjson_val) == ofs; } yyjson_api_inline const char *unsafe_yyjson_get_raw(void *val) { return ((yyjson_val *)val)->uni.str; } yyjson_api_inline bool unsafe_yyjson_get_bool(void *val) { uint8_t tag = unsafe_yyjson_get_tag(val); return (bool)((tag & YYJSON_SUBTYPE_MASK) >> YYJSON_TYPE_BIT); } yyjson_api_inline uint64_t unsafe_yyjson_get_uint(void *val) { return ((yyjson_val *)val)->uni.u64; } yyjson_api_inline int64_t unsafe_yyjson_get_sint(void *val) { return ((yyjson_val *)val)->uni.i64; } yyjson_api_inline int unsafe_yyjson_get_int(void *val) { return (int)((yyjson_val *)val)->uni.i64; } yyjson_api_inline double unsafe_yyjson_get_real(void *val) { return ((yyjson_val *)val)->uni.f64; } yyjson_api_inline double unsafe_yyjson_get_num(void *val) { uint8_t tag = unsafe_yyjson_get_tag(val); if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL)) { return ((yyjson_val *)val)->uni.f64; } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT)) { return (double)((yyjson_val *)val)->uni.i64; } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT)) { #if YYJSON_U64_TO_F64_NO_IMPL uint64_t msb = ((uint64_t)1) << 63; uint64_t num = ((yyjson_val *)val)->uni.u64; if ((num & msb) == 0) { return (double)(int64_t)num; } else { return ((double)(int64_t)((num >> 1) | (num & 1))) * (double)2.0; } #else return (double)((yyjson_val *)val)->uni.u64; #endif } return 0.0; } yyjson_api_inline const char *unsafe_yyjson_get_str(void *val) { return ((yyjson_val *)val)->uni.str; } yyjson_api_inline size_t unsafe_yyjson_get_len(void *val) { return (size_t)(((yyjson_val *)val)->tag >> YYJSON_TAG_BIT); } yyjson_api_inline yyjson_val *unsafe_yyjson_get_first(yyjson_val *ctn) { return ctn + 1; } yyjson_api_inline yyjson_val *unsafe_yyjson_get_next(yyjson_val *val) { bool is_ctn = unsafe_yyjson_is_ctn(val); size_t ctn_ofs = val->uni.ofs; size_t ofs = (is_ctn ? ctn_ofs : sizeof(yyjson_val)); return (yyjson_val *)(void *)((uint8_t *)val + ofs); } yyjson_api_inline bool unsafe_yyjson_equals_strn(void *val, const char *str, size_t len) { uint64_t tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; return ((yyjson_val *)val)->tag == tag && memcmp(((yyjson_val *)val)->uni.str, str, len) == 0; } yyjson_api_inline bool unsafe_yyjson_equals_str(void *val, const char *str) { return unsafe_yyjson_equals_strn(val, str, strlen(str)); } yyjson_api_inline void unsafe_yyjson_set_type(void *val, yyjson_type type, yyjson_subtype subtype) { uint8_t tag = (type | subtype); uint64_t new_tag = ((yyjson_val *)val)->tag; new_tag = (new_tag & (~(uint64_t)YYJSON_TAG_MASK)) | (uint64_t)tag; ((yyjson_val *)val)->tag = new_tag; } yyjson_api_inline void unsafe_yyjson_set_len(void *val, size_t len) { uint64_t tag = ((yyjson_val *)val)->tag & YYJSON_TAG_MASK; tag |= (uint64_t)len << YYJSON_TAG_BIT; ((yyjson_val *)val)->tag = tag; } yyjson_api_inline void unsafe_yyjson_inc_len(void *val) { uint64_t tag = ((yyjson_val *)val)->tag; tag += (uint64_t)(1 << YYJSON_TAG_BIT); ((yyjson_val *)val)->tag = tag; } yyjson_api_inline void unsafe_yyjson_set_raw(void *val, const char *raw, size_t len) { unsafe_yyjson_set_type(val, YYJSON_TYPE_RAW, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, len); ((yyjson_val *)val)->uni.str = raw; } yyjson_api_inline void unsafe_yyjson_set_null(void *val) { unsafe_yyjson_set_type(val, YYJSON_TYPE_NULL, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, 0); } yyjson_api_inline void unsafe_yyjson_set_bool(void *val, bool num) { yyjson_subtype subtype = num ? YYJSON_SUBTYPE_TRUE : YYJSON_SUBTYPE_FALSE; unsafe_yyjson_set_type(val, YYJSON_TYPE_BOOL, subtype); unsafe_yyjson_set_len(val, 0); } yyjson_api_inline void unsafe_yyjson_set_uint(void *val, uint64_t num) { unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_UINT); unsafe_yyjson_set_len(val, 0); ((yyjson_val *)val)->uni.u64 = num; } yyjson_api_inline void unsafe_yyjson_set_sint(void *val, int64_t num) { unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_SINT); unsafe_yyjson_set_len(val, 0); ((yyjson_val *)val)->uni.i64 = num; } yyjson_api_inline void unsafe_yyjson_set_real(void *val, double num) { unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_REAL); unsafe_yyjson_set_len(val, 0); ((yyjson_val *)val)->uni.f64 = num; } yyjson_api_inline void unsafe_yyjson_set_str(void *val, const char *str) { unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, strlen(str)); ((yyjson_val *)val)->uni.str = str; } yyjson_api_inline void unsafe_yyjson_set_strn(void *val, const char *str, size_t len) { unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, len); ((yyjson_val *)val)->uni.str = str; } yyjson_api_inline void unsafe_yyjson_set_arr(void *val, size_t size) { unsafe_yyjson_set_type(val, YYJSON_TYPE_ARR, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, size); } yyjson_api_inline void unsafe_yyjson_set_obj(void *val, size_t size) { unsafe_yyjson_set_type(val, YYJSON_TYPE_OBJ, YYJSON_SUBTYPE_NONE); unsafe_yyjson_set_len(val, size); } /*============================================================================== * JSON Document API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc) { return doc ? doc->root : NULL; } yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc) { return doc ? doc->dat_read : 0; } yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc) { return doc ? doc->val_read : 0; } yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc) { if (doc) { yyjson_alc alc = doc->alc; if (doc->str_pool) alc.free(alc.ctx, doc->str_pool); alc.free(alc.ctx, doc); } } /*============================================================================== * JSON Value Type API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_is_raw(yyjson_val *val) { return val ? unsafe_yyjson_is_raw(val) : false; } yyjson_api_inline bool yyjson_is_null(yyjson_val *val) { return val ? unsafe_yyjson_is_null(val) : false; } yyjson_api_inline bool yyjson_is_true(yyjson_val *val) { return val ? unsafe_yyjson_is_true(val) : false; } yyjson_api_inline bool yyjson_is_false(yyjson_val *val) { return val ? unsafe_yyjson_is_false(val) : false; } yyjson_api_inline bool yyjson_is_bool(yyjson_val *val) { return val ? unsafe_yyjson_is_bool(val) : false; } yyjson_api_inline bool yyjson_is_uint(yyjson_val *val) { return val ? unsafe_yyjson_is_uint(val) : false; } yyjson_api_inline bool yyjson_is_sint(yyjson_val *val) { return val ? unsafe_yyjson_is_sint(val) : false; } yyjson_api_inline bool yyjson_is_int(yyjson_val *val) { return val ? unsafe_yyjson_is_int(val) : false; } yyjson_api_inline bool yyjson_is_real(yyjson_val *val) { return val ? unsafe_yyjson_is_real(val) : false; } yyjson_api_inline bool yyjson_is_num(yyjson_val *val) { return val ? unsafe_yyjson_is_num(val) : false; } yyjson_api_inline bool yyjson_is_str(yyjson_val *val) { return val ? unsafe_yyjson_is_str(val) : false; } yyjson_api_inline bool yyjson_is_arr(yyjson_val *val) { return val ? unsafe_yyjson_is_arr(val) : false; } yyjson_api_inline bool yyjson_is_obj(yyjson_val *val) { return val ? unsafe_yyjson_is_obj(val) : false; } yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val) { return val ? unsafe_yyjson_is_ctn(val) : false; } /*============================================================================== * JSON Value Content API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val) { return val ? unsafe_yyjson_get_type(val) : YYJSON_TYPE_NONE; } yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val) { return val ? unsafe_yyjson_get_subtype(val) : YYJSON_SUBTYPE_NONE; } yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val) { return val ? unsafe_yyjson_get_tag(val) : 0; } yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val) { switch (yyjson_get_tag(val)) { case YYJSON_TYPE_RAW | YYJSON_SUBTYPE_NONE: return "raw"; case YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE: return "null"; case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return "string"; case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: return "array"; case YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE: return "object"; case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE: return "true"; case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE: return "false"; case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT: return "uint"; case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT: return "sint"; case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL: return "real"; default: return "unknown"; } } yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val) { return yyjson_is_raw(val) ? unsafe_yyjson_get_raw(val) : NULL; } yyjson_api_inline bool yyjson_get_bool(yyjson_val *val) { return yyjson_is_bool(val) ? unsafe_yyjson_get_bool(val) : false; } yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val) { return yyjson_is_int(val) ? unsafe_yyjson_get_uint(val) : 0; } yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val) { return yyjson_is_int(val) ? unsafe_yyjson_get_sint(val) : 0; } yyjson_api_inline int yyjson_get_int(yyjson_val *val) { return yyjson_is_int(val) ? unsafe_yyjson_get_int(val) : 0; } yyjson_api_inline double yyjson_get_real(yyjson_val *val) { return yyjson_is_real(val) ? unsafe_yyjson_get_real(val) : 0.0; } yyjson_api_inline double yyjson_get_num(yyjson_val *val) { return val ? unsafe_yyjson_get_num(val) : 0.0; } yyjson_api_inline const char *yyjson_get_str(yyjson_val *val) { return yyjson_is_str(val) ? unsafe_yyjson_get_str(val) : NULL; } yyjson_api_inline size_t yyjson_get_len(yyjson_val *val) { return val ? unsafe_yyjson_get_len(val) : 0; } yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str) { if (yyjson_likely(val && str)) { return unsafe_yyjson_equals_str(val, str); } return false; } yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str, size_t len) { if (yyjson_likely(val && str)) { return unsafe_yyjson_equals_strn(val, str, len); } return false; } yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs); yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { if (yyjson_unlikely(!lhs || !rhs)) return false; return unsafe_yyjson_equals(lhs, rhs); } yyjson_api_inline bool yyjson_set_raw(yyjson_val *val, const char *raw, size_t len) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_raw(val, raw, len); return true; } yyjson_api_inline bool yyjson_set_null(yyjson_val *val) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_null(val); return true; } yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_bool(val, num); return true; } yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_uint(val, num); return true; } yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_sint(val, num); return true; } yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_sint(val, (int64_t)num); return true; } yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; unsafe_yyjson_set_real(val, num); return true; } yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; if (yyjson_unlikely(!str)) return false; unsafe_yyjson_set_str(val, str); return true; } yyjson_api_inline bool yyjson_set_strn(yyjson_val *val, const char *str, size_t len) { if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false; if (yyjson_unlikely(!str)) return false; unsafe_yyjson_set_strn(val, str, len); return true; } /*============================================================================== * JSON Array API (Implementation) *============================================================================*/ yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr) { return yyjson_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0; } yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx) { if (yyjson_likely(yyjson_is_arr(arr))) { if (yyjson_likely(unsafe_yyjson_get_len(arr) > idx)) { yyjson_val *val = unsafe_yyjson_get_first(arr); if (unsafe_yyjson_arr_is_flat(arr)) { return val + idx; } else { while (idx-- > 0) val = unsafe_yyjson_get_next(val); return val; } } } return NULL; } yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr) { if (yyjson_likely(yyjson_is_arr(arr))) { if (yyjson_likely(unsafe_yyjson_get_len(arr) > 0)) { return unsafe_yyjson_get_first(arr); } } return NULL; } yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr) { if (yyjson_likely(yyjson_is_arr(arr))) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(len > 0)) { yyjson_val *val = unsafe_yyjson_get_first(arr); if (unsafe_yyjson_arr_is_flat(arr)) { return val + (len - 1); } else { while (len-- > 1) val = unsafe_yyjson_get_next(val); return val; } } } return NULL; } /*============================================================================== * JSON Array Iterator API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr, yyjson_arr_iter *iter) { if (yyjson_likely(yyjson_is_arr(arr) && iter)) { iter->idx = 0; iter->max = unsafe_yyjson_get_len(arr); iter->cur = unsafe_yyjson_get_first(arr); return true; } if (iter) memset(iter, 0, sizeof(yyjson_arr_iter)); return false; } yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr) { yyjson_arr_iter iter; yyjson_arr_iter_init(arr, &iter); return iter; } yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter) { return iter ? iter->idx < iter->max : false; } yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter) { yyjson_val *val; if (iter && iter->idx < iter->max) { val = iter->cur; iter->cur = unsafe_yyjson_get_next(val); iter->idx++; return val; } return NULL; } /*============================================================================== * JSON Object API (Implementation) *============================================================================*/ yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj) { return yyjson_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0; } yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj, const char *key) { return yyjson_obj_getn(obj, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *_key, size_t key_len) { uint64_t tag = (((uint64_t)key_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; if (yyjson_likely(yyjson_is_obj(obj) && _key)) { size_t len = unsafe_yyjson_get_len(obj); yyjson_val *key = unsafe_yyjson_get_first(obj); while (len-- > 0) { if (key->tag == tag && memcmp(key->uni.ptr, _key, key_len) == 0) { return key + 1; } key = unsafe_yyjson_get_next(key + 1); } } return NULL; } /*============================================================================== * JSON Object Iterator API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj, yyjson_obj_iter *iter) { if (yyjson_likely(yyjson_is_obj(obj) && iter)) { iter->idx = 0; iter->max = unsafe_yyjson_get_len(obj); iter->cur = unsafe_yyjson_get_first(obj); iter->obj = obj; return true; } if (iter) memset(iter, 0, sizeof(yyjson_obj_iter)); return false; } yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj) { yyjson_obj_iter iter; yyjson_obj_iter_init(obj, &iter); return iter; } yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter) { return iter ? iter->idx < iter->max : false; } yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter) { if (iter && iter->idx < iter->max) { yyjson_val *key = iter->cur; iter->idx++; iter->cur = unsafe_yyjson_get_next(key + 1); return key; } return NULL; } yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key) { return key ? key + 1 : NULL; } yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter, const char *key) { return yyjson_obj_iter_getn(iter, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter, const char *key, size_t key_len) { if (iter && key) { size_t idx = iter->idx; size_t max = iter->max; yyjson_val *cur = iter->cur; if (yyjson_unlikely(idx == max)) { idx = 0; cur = unsafe_yyjson_get_first(iter->obj); } while (idx++ < max) { yyjson_val *next = unsafe_yyjson_get_next(cur + 1); if (unsafe_yyjson_get_len(cur) == key_len && memcmp(cur->uni.str, key, key_len) == 0) { iter->idx = idx; iter->cur = next; return cur + 1; } cur = next; if (idx == iter->max && iter->idx < iter->max) { idx = 0; max = iter->idx; cur = unsafe_yyjson_get_first(iter->obj); } } } return NULL; } /*============================================================================== * Mutable JSON Structure (Implementation) *============================================================================*/ /** Mutable JSON value, 24 bytes. The 'tag' and 'uni' field is same as immutable value. The 'next' field links all elements inside the container to be a cycle. */ struct yyjson_mut_val { uint64_t tag; /**< type, subtype and length */ yyjson_val_uni uni; /**< payload */ yyjson_mut_val *next; /**< the next value in circular linked list */ }; /** A memory chunk in string memory pool. */ typedef struct yyjson_str_chunk { struct yyjson_str_chunk *next; /* next chunk linked list */ size_t chunk_size; /* chunk size in bytes */ /* char str[]; flexible array member */ } yyjson_str_chunk; /** A memory pool to hold all strings in a mutable document. */ typedef struct yyjson_str_pool { char *cur; /* cursor inside current chunk */ char *end; /* the end of current chunk */ size_t chunk_size; /* chunk size in bytes while creating new chunk */ size_t chunk_size_max; /* maximum chunk size in bytes */ yyjson_str_chunk *chunks; /* a linked list of chunks, nullable */ } yyjson_str_pool; /** A memory chunk in value memory pool. `sizeof(yyjson_val_chunk)` should not larger than `sizeof(yyjson_mut_val)`. */ typedef struct yyjson_val_chunk { struct yyjson_val_chunk *next; /* next chunk linked list */ size_t chunk_size; /* chunk size in bytes */ /* char pad[sizeof(yyjson_mut_val) - sizeof(yyjson_val_chunk)]; padding */ /* yyjson_mut_val vals[]; flexible array member */ } yyjson_val_chunk; /** A memory pool to hold all values in a mutable document. */ typedef struct yyjson_val_pool { yyjson_mut_val *cur; /* cursor inside current chunk */ yyjson_mut_val *end; /* the end of current chunk */ size_t chunk_size; /* chunk size in bytes while creating new chunk */ size_t chunk_size_max; /* maximum chunk size in bytes */ yyjson_val_chunk *chunks; /* a linked list of chunks, nullable */ } yyjson_val_pool; struct yyjson_mut_doc { yyjson_mut_val *root; /**< root value of the JSON document, nullable */ yyjson_alc alc; /**< a valid allocator, nonnull */ yyjson_str_pool str_pool; /**< string memory pool */ yyjson_val_pool val_pool; /**< value memory pool */ }; /* Ensures the capacity to at least equal to the specified byte length. */ yyjson_api bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool, const yyjson_alc *alc, size_t len); /* Ensures the capacity to at least equal to the specified value count. */ yyjson_api bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool, const yyjson_alc *alc, size_t count); /* Allocate memory for string. */ yyjson_api_inline char *unsafe_yyjson_mut_str_alc(yyjson_mut_doc *doc, size_t len) { char *mem; const yyjson_alc *alc = &doc->alc; yyjson_str_pool *pool = &doc->str_pool; if (yyjson_unlikely((size_t)(pool->end - pool->cur) <= len)) { if (yyjson_unlikely(!unsafe_yyjson_str_pool_grow(pool, alc, len + 1))) { return NULL; } } mem = pool->cur; pool->cur = mem + len + 1; return mem; } yyjson_api_inline char *unsafe_yyjson_mut_strncpy(yyjson_mut_doc *doc, const char *str, size_t len) { char *mem = unsafe_yyjson_mut_str_alc(doc, len); if (yyjson_unlikely(!mem)) return NULL; memcpy((void *)mem, (const void *)str, len); mem[len] = '\0'; return mem; } yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_val(yyjson_mut_doc *doc, size_t count) { yyjson_mut_val *val; yyjson_alc *alc = &doc->alc; yyjson_val_pool *pool = &doc->val_pool; if (yyjson_unlikely((size_t)(pool->end - pool->cur) < count)) { if (yyjson_unlikely(!unsafe_yyjson_val_pool_grow(pool, alc, count))) { return NULL; } } val = pool->cur; pool->cur += count; return val; } /*============================================================================== * Mutable JSON Document API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc) { return doc ? doc->root : NULL; } yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc, yyjson_mut_val *root) { if (doc) doc->root = root; } /*============================================================================== * Mutable JSON Value Type API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_raw(val) : false; } yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_null(val) : false; } yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_true(val) : false; } yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_false(val) : false; } yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_bool(val) : false; } yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_uint(val) : false; } yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_sint(val) : false; } yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_int(val) : false; } yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_real(val) : false; } yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_num(val) : false; } yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_str(val) : false; } yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_arr(val) : false; } yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_obj(val) : false; } yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val) { return val ? unsafe_yyjson_is_ctn(val) : false; } /*============================================================================== * Mutable JSON Value Content API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val) { return yyjson_get_type((yyjson_val *)val); } yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val) { return yyjson_get_subtype((yyjson_val *)val); } yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val) { return yyjson_get_tag((yyjson_val *)val); } yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val) { return yyjson_get_type_desc((yyjson_val *)val); } yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val) { return yyjson_get_raw((yyjson_val *)val); } yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val) { return yyjson_get_bool((yyjson_val *)val); } yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val) { return yyjson_get_uint((yyjson_val *)val); } yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val) { return yyjson_get_sint((yyjson_val *)val); } yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val) { return yyjson_get_int((yyjson_val *)val); } yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val) { return yyjson_get_real((yyjson_val *)val); } yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val) { return yyjson_get_num((yyjson_val *)val); } yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val) { return yyjson_get_str((yyjson_val *)val); } yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val) { return yyjson_get_len((yyjson_val *)val); } yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val, const char *str) { return yyjson_equals_str((yyjson_val *)val, str); } yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val, const char *str, size_t len) { return yyjson_equals_strn((yyjson_val *)val, str, len); } yyjson_api bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs); yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { if (yyjson_unlikely(!lhs || !rhs)) return false; return unsafe_yyjson_mut_equals(lhs, rhs); } yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val, const char *raw, size_t len) { if (yyjson_unlikely(!val || !raw)) return false; unsafe_yyjson_set_raw(val, raw, len); return true; } yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_null(val); return true; } yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_bool(val, num); return true; } yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_uint(val, num); return true; } yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_sint(val, num); return true; } yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_sint(val, (int64_t)num); return true; } yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_real(val, num); return true; } yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val, const char *str) { if (yyjson_unlikely(!val || !str)) return false; unsafe_yyjson_set_str(val, str); return true; } yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val, const char *str, size_t len) { if (yyjson_unlikely(!val || !str)) return false; unsafe_yyjson_set_strn(val, str, len); return true; } yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_arr(val, 0); return true; } yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val) { if (yyjson_unlikely(!val)) return false; unsafe_yyjson_set_obj(val, 0); return true; } /*============================================================================== * Mutable JSON Value Creation API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc, const char *str) { if (yyjson_likely(str)) return yyjson_mut_rawn(doc, str, strlen(str)); return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc, const char *str, size_t len) { if (yyjson_likely(doc && str)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; val->uni.str = str; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc, const char *str) { if (yyjson_likely(str)) return yyjson_mut_rawncpy(doc, str, strlen(str)); return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc, const char *str, size_t len) { if (yyjson_likely(doc && str)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len); if (yyjson_likely(val && new_str)) { val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; val->uni.str = new_str; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc, bool _val) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3); return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc, uint64_t num) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = num; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc, int64_t num) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = num; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc, int64_t num) { return yyjson_mut_sint(doc, num); } yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc, double num) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.f64 = num; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc, const char *str) { if (yyjson_likely(str)) return yyjson_mut_strn(doc, str, strlen(str)); return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc, const char *str, size_t len) { if (yyjson_likely(doc && str)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = str; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc, const char *str) { if (yyjson_likely(str)) return yyjson_mut_strncpy(doc, str, strlen(str)); return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc, const char *str, size_t len) { if (yyjson_likely(doc && str)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len); if (yyjson_likely(val && new_str)) { val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = new_str; return val; } } return NULL; } /*============================================================================== * Mutable JSON Array API (Implementation) *============================================================================*/ yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr) { return yyjson_mut_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr, size_t idx) { if (yyjson_likely(idx < yyjson_mut_arr_size(arr))) { yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; while (idx-- > 0) val = val->next; return val->next; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first( yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) { return ((yyjson_mut_val *)arr->uni.ptr)->next; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last( yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) { return ((yyjson_mut_val *)arr->uni.ptr); } return NULL; } /*============================================================================== * Mutable JSON Array Iterator API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr, yyjson_mut_arr_iter *iter) { if (yyjson_likely(yyjson_mut_is_arr(arr) && iter)) { iter->idx = 0; iter->max = unsafe_yyjson_get_len(arr); iter->cur = iter->max ? (yyjson_mut_val *)arr->uni.ptr : NULL; iter->pre = NULL; iter->arr = arr; return true; } if (iter) memset(iter, 0, sizeof(yyjson_mut_arr_iter)); return false; } yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with( yyjson_mut_val *arr) { yyjson_mut_arr_iter iter; yyjson_mut_arr_iter_init(arr, &iter); return iter; } yyjson_api_inline bool yyjson_mut_arr_iter_has_next(yyjson_mut_arr_iter *iter) { return iter ? iter->idx < iter->max : false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next( yyjson_mut_arr_iter *iter) { if (iter && iter->idx < iter->max) { yyjson_mut_val *val = iter->cur; iter->pre = val; iter->cur = val->next; iter->idx++; return iter->cur; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove( yyjson_mut_arr_iter *iter) { if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) { yyjson_mut_val *prev = iter->pre; yyjson_mut_val *cur = iter->cur; yyjson_mut_val *next = cur->next; if (yyjson_unlikely(iter->idx == iter->max)) iter->arr->uni.ptr = prev; iter->idx--; iter->max--; unsafe_yyjson_set_len(iter->arr, iter->max); prev->next = next; iter->cur = next; return cur; } return NULL; } /*============================================================================== * Mutable JSON Array Creation API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE; return val; } } return NULL; } #define yyjson_mut_arr_with_func(func) \ if (yyjson_likely(doc && ((0 < count && count < \ (~(size_t)0) / sizeof(yyjson_mut_val) && vals) || count == 0))) { \ yyjson_mut_val *arr = unsafe_yyjson_mut_val(doc, 1 + count); \ if (yyjson_likely(arr)) { \ arr->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; \ if (count > 0) { \ size_t i; \ for (i = 0; i < count; i++) { \ yyjson_mut_val *val = arr + i + 1; \ func \ val->next = val + 1; \ } \ arr[count].next = arr + 1; \ arr->uni.ptr = arr + count; \ } \ return arr; \ } \ } \ return NULL yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool( yyjson_mut_doc *doc, const bool *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)vals[i] << 3); }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint( yyjson_mut_doc *doc, const int64_t *vals, size_t count) { return yyjson_mut_arr_with_sint64(doc, vals, count); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint( yyjson_mut_doc *doc, const uint64_t *vals, size_t count) { return yyjson_mut_arr_with_uint64(doc, vals, count); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real( yyjson_mut_doc *doc, const double *vals, size_t count) { return yyjson_mut_arr_with_double(doc, vals, count); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8( yyjson_mut_doc *doc, const int8_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = (int64_t)vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16( yyjson_mut_doc *doc, const int16_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32( yyjson_mut_doc *doc, const int32_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64( yyjson_mut_doc *doc, const int64_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8( yyjson_mut_doc *doc, const uint8_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16( yyjson_mut_doc *doc, const uint16_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32( yyjson_mut_doc *doc, const uint32_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64( yyjson_mut_doc *doc, const uint64_t *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float( yyjson_mut_doc *doc, const float *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.f64 = (double)vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double( yyjson_mut_doc *doc, const double *vals, size_t count) { yyjson_mut_arr_with_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.f64 = vals[i]; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str( yyjson_mut_doc *doc, const char **vals, size_t count) { yyjson_mut_arr_with_func({ uint64_t len = (uint64_t)strlen(vals[i]); val->tag = (len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = vals[i]; if (yyjson_unlikely(!val->uni.str)) return NULL; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn( yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) { if (yyjson_unlikely(count > 0 && !lens)) return NULL; yyjson_mut_arr_with_func({ val->tag = ((uint64_t)lens[i] << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = vals[i]; if (yyjson_unlikely(!val->uni.str)) return NULL; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy( yyjson_mut_doc *doc, const char **vals, size_t count) { size_t len; const char *str; yyjson_mut_arr_with_func({ str = vals[i]; if (!str) return NULL; len = strlen(str); val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = unsafe_yyjson_mut_strncpy(doc, str, len); if (yyjson_unlikely(!val->uni.str)) return NULL; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy( yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) { size_t len; const char *str; if (yyjson_unlikely(count > 0 && !lens)) return NULL; yyjson_mut_arr_with_func({ str = vals[i]; len = lens[i]; val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = unsafe_yyjson_mut_strncpy(doc, str, len); if (yyjson_unlikely(!val->uni.str)) return NULL; }); } #undef yyjson_mut_arr_with_func /*============================================================================== * Mutable JSON Array Modification API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr, yyjson_mut_val *val, size_t idx) { if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(idx <= len)) { unsafe_yyjson_set_len(arr, len + 1); if (len == 0) { val->next = val; arr->uni.ptr = val; } else { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; if (idx == len) { prev->next = val; val->next = next; arr->uni.ptr = val; } else { while (idx-- > 0) { prev = next; next = next->next; } prev->next = val; val->next = next; } } return true; } } return false; } yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) { size_t len = unsafe_yyjson_get_len(arr); unsafe_yyjson_set_len(arr, len + 1); if (len == 0) { val->next = val; } else { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; prev->next = val; val->next = next; } arr->uni.ptr = val; return true; } return false; } yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) { size_t len = unsafe_yyjson_get_len(arr); unsafe_yyjson_set_len(arr, len + 1); if (len == 0) { val->next = val; arr->uni.ptr = val; } else { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; prev->next = val; val->next = next; } return true; } return false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr, size_t idx, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(idx < len)) { if (yyjson_likely(len > 1)) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; while (idx-- > 0) { prev = next; next = next->next; } prev->next = val; val->next = next->next; if ((void *)next == arr->uni.ptr) arr->uni.ptr = val; return next; } else { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); val->next = val; arr->uni.ptr = val; return prev; } } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr, size_t idx) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(idx < len)) { unsafe_yyjson_set_len(arr, len - 1); if (yyjson_likely(len > 1)) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; while (idx-- > 0) { prev = next; next = next->next; } prev->next = next->next; if ((void *)next == arr->uni.ptr) arr->uni.ptr = prev; return next; } else { return ((yyjson_mut_val *)arr->uni.ptr); } } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first( yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { size_t len = unsafe_yyjson_get_len(arr); if (len > 1) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; prev->next = next->next; unsafe_yyjson_set_len(arr, len - 1); return next; } else if (len == 1) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); unsafe_yyjson_set_len(arr, 0); return prev; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last( yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { size_t len = unsafe_yyjson_get_len(arr); if (yyjson_likely(len > 1)) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); yyjson_mut_val *next = prev->next; unsafe_yyjson_set_len(arr, len - 1); while (--len > 0) prev = prev->next; prev->next = next; next = (yyjson_mut_val *)arr->uni.ptr; arr->uni.ptr = prev; return next; } else if (len == 1) { yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr); unsafe_yyjson_set_len(arr, 0); return prev; } } return NULL; } yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr, size_t _idx, size_t _len) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { yyjson_mut_val *prev, *next; bool tail_removed; size_t len = unsafe_yyjson_get_len(arr); if (yyjson_unlikely(_idx + _len > len)) return false; if (yyjson_unlikely(_len == 0)) return true; unsafe_yyjson_set_len(arr, len - _len); if (yyjson_unlikely(len == _len)) return true; tail_removed = (_idx + _len == len); prev = ((yyjson_mut_val *)arr->uni.ptr); while (_idx-- > 0) prev = prev->next; next = prev->next; while (_len-- > 0) next = next->next; prev->next = next; if (yyjson_unlikely(tail_removed)) arr->uni.ptr = prev; return true; } return false; } yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr) { if (yyjson_likely(yyjson_mut_is_arr(arr))) { unsafe_yyjson_set_len(arr, 0); return true; } return false; } yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr, size_t idx) { if (yyjson_likely(yyjson_mut_is_arr(arr) && unsafe_yyjson_get_len(arr) > idx)) { yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; while (idx-- > 0) val = val->next; arr->uni.ptr = (void *)val; return true; } return false; } /*============================================================================== * Mutable JSON Array Modification Convenience API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr, yyjson_mut_val *val) { return yyjson_mut_arr_append(arr, val); } yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_null(doc); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_true(doc); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_false(doc); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *arr, bool _val) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_bool(doc, _val); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *arr, uint64_t num) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_uint(doc, num); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *arr, int64_t num) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_sint(doc, num); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc, yyjson_mut_val *arr, int64_t num) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_sint(doc, num); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc, yyjson_mut_val *arr, double num) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_real(doc, num); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_str(doc, str); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str, size_t len) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_strn(doc, str, len); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_strcpy(doc, str); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *arr, const char *str, size_t len) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_strncpy(doc, str, len); return yyjson_mut_arr_append(arr, val); } return false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_arr(doc); return yyjson_mut_arr_append(arr, val) ? val : NULL; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc, yyjson_mut_val *arr) { if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) { yyjson_mut_val *val = yyjson_mut_obj(doc); return yyjson_mut_arr_append(arr, val) ? val : NULL; } return NULL; } /*============================================================================== * Mutable JSON Object API (Implementation) *============================================================================*/ yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj) { return yyjson_mut_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj, const char *key) { return yyjson_mut_obj_getn(obj, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj, const char *_key, size_t key_len) { uint64_t tag = (((uint64_t)key_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; size_t len = yyjson_mut_obj_size(obj); if (yyjson_likely(len && _key)) { yyjson_mut_val *key = ((yyjson_mut_val *)obj->uni.ptr)->next->next; while (len-- > 0) { if (key->tag == tag && memcmp(key->uni.ptr, _key, key_len) == 0) { return key->next; } key = key->next->next; } } return NULL; } /*============================================================================== * Mutable JSON Object Iterator API (Implementation) *============================================================================*/ yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj, yyjson_mut_obj_iter *iter) { if (yyjson_likely(yyjson_mut_is_obj(obj) && iter)) { iter->idx = 0; iter->max = unsafe_yyjson_get_len(obj); iter->cur = iter->max ? (yyjson_mut_val *)obj->uni.ptr : NULL; iter->pre = NULL; iter->obj = obj; return true; } if (iter) memset(iter, 0, sizeof(yyjson_mut_obj_iter)); return false; } yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with( yyjson_mut_val *obj) { yyjson_mut_obj_iter iter; yyjson_mut_obj_iter_init(obj, &iter); return iter; } yyjson_api_inline bool yyjson_mut_obj_iter_has_next(yyjson_mut_obj_iter *iter) { return iter ? iter->idx < iter->max : false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next( yyjson_mut_obj_iter *iter) { if (iter && iter->idx < iter->max) { yyjson_mut_val *key = iter->cur; iter->pre = key; iter->cur = key->next->next; iter->idx++; return iter->cur; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val( yyjson_mut_val *key) { return key ? key->next : NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove( yyjson_mut_obj_iter *iter) { if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) { yyjson_mut_val *prev = iter->pre; yyjson_mut_val *cur = iter->cur; yyjson_mut_val *next = cur->next->next; if (yyjson_unlikely(iter->idx == iter->max)) iter->obj->uni.ptr = prev; iter->idx--; iter->max--; unsafe_yyjson_set_len(iter->obj, iter->max); prev->next->next = next; iter->cur = prev; return cur->next; } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get( yyjson_mut_obj_iter *iter, const char *key) { return yyjson_mut_obj_iter_getn(iter, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn( yyjson_mut_obj_iter *iter, const char *key, size_t key_len) { if (iter && key) { size_t idx = 0; size_t max = iter->max; yyjson_mut_val *pre, *cur = iter->cur; while (idx++ < max) { pre = cur; cur = cur->next->next; if (unsafe_yyjson_get_len(cur) == key_len && memcmp(cur->uni.str, key, key_len) == 0) { iter->idx += idx; if (iter->idx > max) iter->idx -= max + 1; iter->pre = pre; iter->cur = cur; return cur->next; } } } return NULL; } /*============================================================================== * Mutable JSON Object Creation API (Implementation) *============================================================================*/ yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc) { if (yyjson_likely(doc)) { yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1); if (yyjson_likely(val)) { val->tag = YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE; return val; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc, const char **keys, const char **vals, size_t count) { if (yyjson_likely(doc && ((count > 0 && keys && vals) || (count == 0)))) { yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2); if (yyjson_likely(obj)) { obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ; if (count > 0) { size_t i; for (i = 0; i < count; i++) { yyjson_mut_val *key = obj + (i * 2 + 1); yyjson_mut_val *val = obj + (i * 2 + 2); uint64_t key_len = (uint64_t)strlen(keys[i]); uint64_t val_len = (uint64_t)strlen(vals[i]); key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; key->uni.str = keys[i]; val->uni.str = vals[i]; key->next = val; val->next = val + 1; } obj[count * 2].next = obj + 1; obj->uni.ptr = obj + (count * 2 - 1); } return obj; } } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc, const char **pairs, size_t count) { if (yyjson_likely(doc && ((count > 0 && pairs) || (count == 0)))) { yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2); if (yyjson_likely(obj)) { obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ; if (count > 0) { size_t i; for (i = 0; i < count; i++) { yyjson_mut_val *key = obj + (i * 2 + 1); yyjson_mut_val *val = obj + (i * 2 + 2); const char *key_str = pairs[i * 2 + 0]; const char *val_str = pairs[i * 2 + 1]; uint64_t key_len = (uint64_t)strlen(key_str); uint64_t val_len = (uint64_t)strlen(val_str); key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; key->uni.str = key_str; val->uni.str = val_str; key->next = val; val->next = val + 1; } obj[count * 2].next = obj + 1; obj->uni.ptr = obj + (count * 2 - 1); } return obj; } } return NULL; } /*============================================================================== * Mutable JSON Object Modification API (Implementation) *============================================================================*/ yyjson_api_inline void unsafe_yyjson_mut_obj_add(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val, size_t len) { if (yyjson_likely(len)) { yyjson_mut_val *prev_val = ((yyjson_mut_val *)obj->uni.ptr)->next; yyjson_mut_val *next_key = prev_val->next; prev_val->next = key; val->next = next_key; } else { val->next = key; } key->next = val; obj->uni.ptr = (void *)key; unsafe_yyjson_set_len(obj, len + 1); } yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_obj_remove( yyjson_mut_val *obj, const char *key, size_t key_len, uint64_t key_tag) { size_t obj_len = unsafe_yyjson_get_len(obj); if (obj_len) { yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr; yyjson_mut_val *cur_key = pre_key->next->next; yyjson_mut_val *removed_item = NULL; size_t i; for (i = 0; i < obj_len; i++) { if (key_tag == cur_key->tag && memcmp(key, cur_key->uni.ptr, key_len) == 0) { if (!removed_item) removed_item = cur_key->next; cur_key = cur_key->next->next; pre_key->next->next = cur_key; if (i + 1 == obj_len) obj->uni.ptr = pre_key; i--; obj_len--; } else { pre_key = cur_key; cur_key = cur_key->next->next; } } unsafe_yyjson_set_len(obj, obj_len); return removed_item; } else { return NULL; } } yyjson_api_inline bool unsafe_yyjson_mut_obj_replace(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { size_t key_len = unsafe_yyjson_get_len(key); size_t obj_len = unsafe_yyjson_get_len(obj); if (obj_len) { yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr; yyjson_mut_val *cur_key = pre_key->next->next; size_t i; for (i = 0; i < obj_len; i++) { if (key->tag == cur_key->tag && memcmp(key->uni.str, cur_key->uni.ptr, key_len) == 0) { cur_key->next->tag = val->tag; cur_key->next->uni.u64 = val->uni.u64; return true; } else { cur_key = cur_key->next->next; } } } return false; } yyjson_api_inline void unsafe_yyjson_mut_obj_rotate(yyjson_mut_val *obj, size_t idx) { yyjson_mut_val *key = (yyjson_mut_val *)obj->uni.ptr; while (idx-- > 0) key = key->next->next; obj->uni.ptr = (void *)key; } yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key) && val)) { unsafe_yyjson_mut_obj_add(obj, key, val, unsafe_yyjson_get_len(obj)); return true; } return false; } yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { bool replaced = false; size_t key_len; yyjson_mut_obj_iter iter; yyjson_mut_val *cur_key; if (yyjson_unlikely(!yyjson_mut_is_obj(obj) || !yyjson_mut_is_str(key))) return false; key_len = unsafe_yyjson_get_len(key); yyjson_mut_obj_iter_init(obj, &iter); while ((cur_key = yyjson_mut_obj_iter_next(&iter))) { if (key->tag == cur_key->tag && memcmp(key->uni.str, cur_key->uni.ptr, key_len) == 0) { if (!replaced && val) { replaced = true; val->next = cur_key->next->next; cur_key->next = val; } else { yyjson_mut_obj_iter_remove(&iter); } } } if (!replaced && val) unsafe_yyjson_mut_obj_add(obj, key, val, iter.max); return true; } yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val, size_t idx) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key) && val)) { size_t len = unsafe_yyjson_get_len(obj); if (yyjson_likely(len >= idx)) { if (len > idx) { void *ptr = obj->uni.ptr; unsafe_yyjson_mut_obj_rotate(obj, idx); unsafe_yyjson_mut_obj_add(obj, key, val, len); obj->uni.ptr = ptr; } else { unsafe_yyjson_mut_obj_add(obj, key, val, len); } return true; } } return false; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj, yyjson_mut_val *key) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key))) { return unsafe_yyjson_mut_obj_remove(obj, key->uni.str, unsafe_yyjson_get_len(key), key->tag); } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key( yyjson_mut_val *obj, const char *key) { if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) { size_t key_len = strlen(key); uint64_t tag = ((uint64_t)key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; return unsafe_yyjson_mut_obj_remove(obj, key, key_len, tag); } return NULL; } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn( yyjson_mut_val *obj, const char *key, size_t key_len) { if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) { uint64_t tag = ((uint64_t)key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; return unsafe_yyjson_mut_obj_remove(obj, key, key_len, tag); } return NULL; } yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj) { if (yyjson_likely(yyjson_mut_is_obj(obj))) { unsafe_yyjson_set_len(obj, 0); return true; } return false; } yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj, yyjson_mut_val *key, yyjson_mut_val *val) { if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key) && val)) { return unsafe_yyjson_mut_obj_replace(obj, key, val); } return false; } yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj, size_t idx) { if (yyjson_likely(yyjson_mut_is_obj(obj) && unsafe_yyjson_get_len(obj) > idx)) { unsafe_yyjson_mut_obj_rotate(obj, idx); return true; } return false; } /*============================================================================== * Mutable JSON Object Modification Convenience API (Implementation) *============================================================================*/ #define yyjson_mut_obj_add_func(func) \ if (yyjson_likely(doc && yyjson_mut_is_obj(obj) && _key)) { \ yyjson_mut_val *key = unsafe_yyjson_mut_val(doc, 2); \ if (yyjson_likely(key)) { \ size_t len = unsafe_yyjson_get_len(obj); \ yyjson_mut_val *val = key + 1; \ key->tag = YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE; \ key->tag |= (uint64_t)strlen(_key) << YYJSON_TAG_BIT; \ key->uni.str = _key; \ func \ unsafe_yyjson_mut_obj_add(obj, key, val, len); \ return true; \ } \ } \ return false yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE; }); } yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE; }); } yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE; }); } yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, bool _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)(_val) << 3); }); } yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, uint64_t _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT; val->uni.u64 = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, int64_t _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, int64_t _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT; val->uni.i64 = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, double _val) { yyjson_mut_obj_add_func({ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; val->uni.f64 = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, const char *_val) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ val->tag = ((uint64_t)strlen(_val) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, const char *_val, size_t _len) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; val->uni.str = _val; }); } yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, const char *_val) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ size_t _len = strlen(_val); val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len); if (yyjson_unlikely(!val->uni.str)) return false; val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; }); } yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, const char *_val, size_t _len) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len); if (yyjson_unlikely(!val->uni.str)) return false; val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR; }); } yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, yyjson_mut_val *_val) { if (yyjson_unlikely(!_val)) return false; yyjson_mut_obj_add_func({ val = _val; }); } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str(yyjson_mut_val *obj, const char *key) { return yyjson_mut_obj_remove_strn(obj, key, key ? strlen(key) : 0); } yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn( yyjson_mut_val *obj, const char *_key, size_t _len) { if (yyjson_likely(yyjson_mut_is_obj(obj) && _key)) { yyjson_mut_val *key; yyjson_mut_obj_iter iter; yyjson_mut_val *val_removed = NULL; yyjson_mut_obj_iter_init(obj, &iter); while ((key = yyjson_mut_obj_iter_next(&iter)) != NULL) { if (unsafe_yyjson_get_len(key) == _len && memcmp(key->uni.str, _key, _len) == 0) { if (!val_removed) val_removed = key->next; yyjson_mut_obj_iter_remove(&iter); } } return val_removed; } return NULL; } yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *new_key) { if (!key || !new_key) return false; return yyjson_mut_obj_rename_keyn(doc, obj, key, strlen(key), new_key, strlen(new_key)); } yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, size_t len, const char *new_key, size_t new_len) { char *cpy_key = NULL; yyjson_mut_val *old_key; yyjson_mut_obj_iter iter; if (!doc || !obj || !key || !new_key) return false; yyjson_mut_obj_iter_init(obj, &iter); while ((old_key = yyjson_mut_obj_iter_next(&iter))) { if (unsafe_yyjson_equals_strn((void *)old_key, key, len)) { if (!cpy_key) { cpy_key = unsafe_yyjson_mut_strncpy(doc, new_key, new_len); if (!cpy_key) return false; } yyjson_mut_set_strn(old_key, cpy_key, new_len); } } return cpy_key != NULL; } /*============================================================================== * JSON Pointer API (Implementation) *============================================================================*/ #define yyjson_ptr_set_err(_code, _msg) do { \ if (err) { \ err->code = YYJSON_PTR_ERR_##_code; \ err->msg = _msg; \ err->pos = 0; \ } \ } while(false) /* require: val != NULL, *ptr == '/', len > 0 */ yyjson_api yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val, const char *ptr, size_t len, yyjson_ptr_err *err); /* require: val != NULL, *ptr == '/', len > 0 */ yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /* require: val/new_val/doc != NULL, *ptr == '/', len > 0 */ yyjson_api bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, bool insert_new, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /* require: val/err != NULL, *ptr == '/', len > 0 */ yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); /* require: val/err != NULL, *ptr == '/', len > 0 */ yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err); yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc, const char *ptr) { if (yyjson_unlikely(!ptr)) return NULL; return yyjson_doc_ptr_getn(doc, ptr, strlen(ptr)); } yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc, const char *ptr, size_t len) { return yyjson_doc_ptr_getx(doc, ptr, len, NULL); } yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc, const char *ptr, size_t len, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (yyjson_unlikely(!doc || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(!doc->root)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { return doc->root; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_ptr_getx(doc->root, ptr, len, err); } yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val, const char *ptr) { if (yyjson_unlikely(!ptr)) return NULL; return yyjson_ptr_getn(val, ptr, strlen(ptr)); } yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val, const char *ptr, size_t len) { return yyjson_ptr_getx(val, ptr, len, NULL); } yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val, const char *ptr, size_t len, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (yyjson_unlikely(!val || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { return val; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_ptr_getx(val, ptr, len, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc, const char *ptr) { if (!ptr) return NULL; return yyjson_mut_doc_ptr_getn(doc, ptr, strlen(ptr)); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc, const char *ptr, size_t len) { return yyjson_mut_doc_ptr_getx(doc, ptr, len, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(!doc->root)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { return doc->root; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_getx(doc->root, ptr, len, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val, const char *ptr) { if (!ptr) return NULL; return yyjson_mut_ptr_getn(val, ptr, strlen(ptr)); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val, const char *ptr, size_t len) { return yyjson_mut_ptr_getx(val, ptr, len, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { return val; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err); } yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) { if (yyjson_unlikely(!ptr)) return false; return yyjson_mut_doc_ptr_addn(doc, ptr, strlen(ptr), new_val); } yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) { return yyjson_mut_doc_ptr_addx(doc, ptr, len, new_val, true, NULL, NULL); } yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr || !new_val)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return false; } if (yyjson_unlikely(len == 0)) { if (doc->root) { yyjson_ptr_set_err(SET_ROOT, "cannot set document's root"); return false; } else { doc->root = new_val; return true; } } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return false; } if (yyjson_unlikely(!doc->root && !create_parent)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return false; } if (yyjson_unlikely(!doc->root)) { yyjson_mut_val *root = yyjson_mut_obj(doc); if (yyjson_unlikely(!root)) { yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value"); return false; } if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc, create_parent, true, ctx, err)) { doc->root = root; return true; } return false; } return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc, create_parent, true, ctx, err); } yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val, yyjson_mut_doc *doc) { if (yyjson_unlikely(!ptr)) return false; return yyjson_mut_ptr_addn(val, ptr, strlen(ptr), new_val, doc); } yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc) { return yyjson_mut_ptr_addx(val, ptr, len, new_val, doc, true, NULL, NULL); } yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr || !new_val || !doc)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return false; } if (yyjson_unlikely(len == 0)) { yyjson_ptr_set_err(SET_ROOT, "cannot set root"); return false; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return false; } return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, doc, create_parent, true, ctx, err); } yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) { if (yyjson_unlikely(!ptr)) return false; return yyjson_mut_doc_ptr_setn(doc, ptr, strlen(ptr), new_val); } yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) { return yyjson_mut_doc_ptr_setx(doc, ptr, len, new_val, true, NULL, NULL); } yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return false; } if (yyjson_unlikely(len == 0)) { if (ctx) ctx->old = doc->root; doc->root = new_val; return true; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return false; } if (!new_val) { if (!doc->root) { yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved"); return false; } return !!unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err); } if (yyjson_unlikely(!doc->root && !create_parent)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return false; } if (yyjson_unlikely(!doc->root)) { yyjson_mut_val *root = yyjson_mut_obj(doc); if (yyjson_unlikely(!root)) { yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value"); return false; } if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc, create_parent, false, ctx, err)) { doc->root = root; return true; } return false; } return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc, create_parent, false, ctx, err); } yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val, yyjson_mut_doc *doc) { if (yyjson_unlikely(!ptr)) return false; return yyjson_mut_ptr_setn(val, ptr, strlen(ptr), new_val, doc); } yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc) { return yyjson_mut_ptr_setx(val, ptr, len, new_val, doc, true, NULL, NULL); } yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_mut_doc *doc, bool create_parent, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr || !doc)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return false; } if (yyjson_unlikely(len == 0)) { yyjson_ptr_set_err(SET_ROOT, "cannot set root"); return false; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return false; } if (!new_val) { return !!unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err); } return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, doc, create_parent, false, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace( yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) { if (!ptr) return NULL; return yyjson_mut_doc_ptr_replacen(doc, ptr, strlen(ptr), new_val); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) { return yyjson_mut_doc_ptr_replacex(doc, ptr, len, new_val, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr || !new_val)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { yyjson_mut_val *root = doc->root; if (yyjson_unlikely(!root)) { yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved"); return NULL; } if (ctx) ctx->old = root; doc->root = new_val; return root; } if (yyjson_unlikely(!doc->root)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return NULL; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_replacex(doc->root, ptr, len, new_val, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace( yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val) { if (!ptr) return NULL; return yyjson_mut_ptr_replacen(val, ptr, strlen(ptr), new_val); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val) { return yyjson_mut_ptr_replacex(val, ptr, len, new_val, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex( yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr || !new_val)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { yyjson_ptr_set_err(SET_ROOT, "cannot set root"); return NULL; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_replacex(val, ptr, len, new_val, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove( yyjson_mut_doc *doc, const char *ptr) { if (!ptr) return NULL; return yyjson_mut_doc_ptr_removen(doc, ptr, strlen(ptr)); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen( yyjson_mut_doc *doc, const char *ptr, size_t len) { return yyjson_mut_doc_ptr_removex(doc, ptr, len, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex( yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!doc || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(!doc->root)) { yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { yyjson_mut_val *root = doc->root; if (ctx) ctx->old = root; doc->root = NULL; return root; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val, const char *ptr) { if (!ptr) return NULL; return yyjson_mut_ptr_removen(val, ptr, strlen(ptr)); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val, const char *ptr, size_t len) { return yyjson_mut_ptr_removex(val, ptr, len, NULL, NULL); } yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val, const char *ptr, size_t len, yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) { yyjson_ptr_set_err(NONE, NULL); if (ctx) memset(ctx, 0, sizeof(*ctx)); if (yyjson_unlikely(!val || !ptr)) { yyjson_ptr_set_err(PARAMETER, "input parameter is NULL"); return NULL; } if (yyjson_unlikely(len == 0)) { yyjson_ptr_set_err(SET_ROOT, "cannot set root"); return NULL; } if (yyjson_unlikely(*ptr != '/')) { yyjson_ptr_set_err(SYNTAX, "no prefix '/'"); return NULL; } return unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err); } yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx, yyjson_mut_val *key, yyjson_mut_val *val) { yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val; if (!ctx || !ctx->ctn || !val) return false; ctn = ctx->ctn; if (yyjson_mut_is_obj(ctn)) { if (!key) return false; key->next = val; pre_key = ctx->pre; if (unsafe_yyjson_get_len(ctn) == 0) { val->next = key; ctn->uni.ptr = key; ctx->pre = key; } else if (!pre_key) { pre_key = (yyjson_mut_val *)ctn->uni.ptr; pre_val = pre_key->next; val->next = pre_val->next; pre_val->next = key; ctn->uni.ptr = key; ctx->pre = pre_key; } else { cur_key = pre_key->next->next; cur_val = cur_key->next; val->next = cur_val->next; cur_val->next = key; if (ctn->uni.ptr == cur_key) ctn->uni.ptr = key; ctx->pre = cur_key; } } else { pre_val = ctx->pre; if (unsafe_yyjson_get_len(ctn) == 0) { val->next = val; ctn->uni.ptr = val; ctx->pre = val; } else if (!pre_val) { pre_val = (yyjson_mut_val *)ctn->uni.ptr; val->next = pre_val->next; pre_val->next = val; ctn->uni.ptr = val; ctx->pre = pre_val; } else { cur_val = pre_val->next; val->next = cur_val->next; cur_val->next = val; if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val; ctx->pre = cur_val; } } unsafe_yyjson_inc_len(ctn); return true; } yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx, yyjson_mut_val *val) { yyjson_mut_val *ctn, *pre_key, *cur_key, *pre_val, *cur_val; if (!ctx || !ctx->ctn || !ctx->pre || !val) return false; ctn = ctx->ctn; if (yyjson_mut_is_obj(ctn)) { pre_key = ctx->pre; pre_val = pre_key->next; cur_key = pre_val->next; cur_val = cur_key->next; /* replace current value */ cur_key->next = val; val->next = cur_val->next; ctx->old = cur_val; } else { pre_val = ctx->pre; cur_val = pre_val->next; /* replace current value */ if (pre_val != cur_val) { val->next = cur_val->next; pre_val->next = val; if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val; } else { val->next = val; ctn->uni.ptr = val; ctx->pre = val; } ctx->old = cur_val; } return true; } yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx) { yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val; size_t len; if (!ctx || !ctx->ctn || !ctx->pre) return false; ctn = ctx->ctn; if (yyjson_mut_is_obj(ctn)) { pre_key = ctx->pre; pre_val = pre_key->next; cur_key = pre_val->next; cur_val = cur_key->next; /* remove current key-value */ pre_val->next = cur_val->next; if (ctn->uni.ptr == cur_key) ctn->uni.ptr = pre_key; ctx->pre = NULL; ctx->old = cur_val; } else { pre_val = ctx->pre; cur_val = pre_val->next; /* remove current key-value */ pre_val->next = cur_val->next; if (ctn->uni.ptr == cur_val) ctn->uni.ptr = pre_val; ctx->pre = NULL; ctx->old = cur_val; } len = unsafe_yyjson_get_len(ctn) - 1; if (len == 0) ctn->uni.ptr = NULL; unsafe_yyjson_set_len(ctn, len); return true; } #undef yyjson_ptr_set_err /*============================================================================== * JSON Value at Pointer API (Implementation) *============================================================================*/ /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type bool. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_bool( yyjson_val *root, const char *ptr, bool *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_bool(val)) { *value = unsafe_yyjson_get_bool(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type uint. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_uint( yyjson_val *root, const char *ptr, uint64_t *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_uint(val)) { *value = unsafe_yyjson_get_uint(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_sint( yyjson_val *root, const char *ptr, int64_t *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_sint(val)) { *value = unsafe_yyjson_get_sint(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type real. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_real( yyjson_val *root, const char *ptr, double *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_real(val)) { *value = unsafe_yyjson_get_real(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint, uint or real. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_num( yyjson_val *root, const char *ptr, double *value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_num(val)) { *value = unsafe_yyjson_get_num(val); return true; } else { return false; } } /** Set provided `value` if the JSON Pointer (RFC 6901) exists and is type string. Returns true if value at `ptr` exists and is the correct type, otherwise false. */ yyjson_api_inline bool yyjson_ptr_get_str( yyjson_val *root, const char *ptr, const char **value) { yyjson_val *val = yyjson_ptr_get(root, ptr); if (value && yyjson_is_str(val)) { *value = unsafe_yyjson_get_str(val); return true; } else { return false; } } /*============================================================================== * Deprecated *============================================================================*/ /** @deprecated renamed to `yyjson_doc_ptr_get` */ yyjson_deprecated("renamed to yyjson_doc_ptr_get") yyjson_api_inline yyjson_val *yyjson_doc_get_pointer(yyjson_doc *doc, const char *ptr) { return yyjson_doc_ptr_get(doc, ptr); } /** @deprecated renamed to `yyjson_doc_ptr_getn` */ yyjson_deprecated("renamed to yyjson_doc_ptr_getn") yyjson_api_inline yyjson_val *yyjson_doc_get_pointern(yyjson_doc *doc, const char *ptr, size_t len) { return yyjson_doc_ptr_getn(doc, ptr, len); } /** @deprecated renamed to `yyjson_mut_doc_ptr_get` */ yyjson_deprecated("renamed to yyjson_mut_doc_ptr_get") yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer( yyjson_mut_doc *doc, const char *ptr) { return yyjson_mut_doc_ptr_get(doc, ptr); } /** @deprecated renamed to `yyjson_mut_doc_ptr_getn` */ yyjson_deprecated("renamed to yyjson_mut_doc_ptr_getn") yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointern( yyjson_mut_doc *doc, const char *ptr, size_t len) { return yyjson_mut_doc_ptr_getn(doc, ptr, len); } /** @deprecated renamed to `yyjson_ptr_get` */ yyjson_deprecated("renamed to yyjson_ptr_get") yyjson_api_inline yyjson_val *yyjson_get_pointer(yyjson_val *val, const char *ptr) { return yyjson_ptr_get(val, ptr); } /** @deprecated renamed to `yyjson_ptr_getn` */ yyjson_deprecated("renamed to yyjson_ptr_getn") yyjson_api_inline yyjson_val *yyjson_get_pointern(yyjson_val *val, const char *ptr, size_t len) { return yyjson_ptr_getn(val, ptr, len); } /** @deprecated renamed to `yyjson_mut_ptr_get` */ yyjson_deprecated("renamed to yyjson_mut_ptr_get") yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointer(yyjson_mut_val *val, const char *ptr) { return yyjson_mut_ptr_get(val, ptr); } /** @deprecated renamed to `yyjson_mut_ptr_getn` */ yyjson_deprecated("renamed to yyjson_mut_ptr_getn") yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointern(yyjson_mut_val *val, const char *ptr, size_t len) { return yyjson_mut_ptr_getn(val, ptr, len); } /** @deprecated renamed to `yyjson_mut_ptr_getn` */ yyjson_deprecated("renamed to unsafe_yyjson_ptr_getn") yyjson_api_inline yyjson_val *unsafe_yyjson_get_pointer(yyjson_val *val, const char *ptr, size_t len) { yyjson_ptr_err err; return unsafe_yyjson_ptr_getx(val, ptr, len, &err); } /** @deprecated renamed to `unsafe_yyjson_mut_ptr_getx` */ yyjson_deprecated("renamed to unsafe_yyjson_mut_ptr_getx") yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_get_pointer( yyjson_mut_val *val, const char *ptr, size_t len) { yyjson_ptr_err err; return unsafe_yyjson_mut_ptr_getx(val, ptr, len, NULL, &err); } /*============================================================================== * Compiler Hint End *============================================================================*/ #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) # if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) # pragma GCC diagnostic pop # endif #elif defined(_MSC_VER) # pragma warning(pop) #endif /* warning suppress end */ #ifdef __cplusplus } #endif /* extern "C" end */ #endif /* YYJSON_H */ ================================================ FILE: libtts/Modules/Lib/World/LICENSE.txt ================================================ /* ----------------------------------------------------------------- */ /* WORLD: High-quality speech analysis, */ /* manipulation and synthesis system */ /* developed by M. Morise */ /* http://www.kisc.meiji.ac.jp/~mmorise/world/english/ */ /* ----------------------------------------------------------------- */ /* */ /* Copyright (c) 2010 M. Morise */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or */ /* without modification, are permitted provided that the following */ /* conditions are met: */ /* */ /* - Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* - Redistributions in binary form must reproduce the above */ /* copyright notice, this list of conditions and the following */ /* disclaimer in the documentation and/or other materials provided */ /* with the distribution. */ /* - Neither the name of the M. Morise nor the names of its */ /* contributors may be used to endorse or promote products derived */ /* from this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */ /* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */ /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS */ /* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */ /* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */ /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY */ /* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ /* POSSIBILITY OF SUCH DAMAGE. */ /* ----------------------------------------------------------------- */ ================================================ FILE: libtts/Modules/Lib/World/src/cheaptrick.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Spectral envelope estimation on the basis of the idea of CheapTrick. //----------------------------------------------------------------------------- #include "world/cheaptrick.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { //----------------------------------------------------------------------------- // SmoothingWithRecovery() carries out the spectral smoothing and spectral // recovery on the Cepstrum domain. //----------------------------------------------------------------------------- static void SmoothingWithRecovery(double f0, int fs, int fft_size, double q1, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, double *spectral_envelope) { double *smoothing_lifter = new double[fft_size]; double *compensation_lifter = new double[fft_size]; smoothing_lifter[0] = 1.0; compensation_lifter[0] = (1.0 - 2.0 * q1) + 2.0 * q1; double quefrency; for (int i = 1; i <= forward_real_fft->fft_size / 2; ++i) { quefrency = static_cast(i) / fs; smoothing_lifter[i] = sin(world::kPi * f0 * quefrency) / (world::kPi * f0 * quefrency); compensation_lifter[i] = (1.0 - 2.0 * q1) + 2.0 * q1 * cos(2.0 * world::kPi * quefrency * f0); } for (int i = 0; i <= fft_size / 2; ++i) forward_real_fft->waveform[i] = log(forward_real_fft->waveform[i]); for (int i = 1; i < fft_size / 2; ++i) forward_real_fft->waveform[fft_size - i] = forward_real_fft->waveform[i]; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = forward_real_fft->spectrum[i][0] * smoothing_lifter[i] * compensation_lifter[i] / fft_size; inverse_real_fft->spectrum[i][1] = 0.0; } fft_execute(inverse_real_fft->inverse_fft); for (int i = 0; i <= fft_size / 2; ++i) spectral_envelope[i] = exp(inverse_real_fft->waveform[i]); delete[] smoothing_lifter; delete[] compensation_lifter; } //----------------------------------------------------------------------------- // GetPowerSpectrum() calculates the power_spectrum with DC correction. // DC stands for Direct Current. In this case, the component from 0 to F0 Hz // is corrected. //----------------------------------------------------------------------------- static void GetPowerSpectrum(int fs, double f0, int fft_size, const ForwardRealFFT *forward_real_fft) { int half_window_length = matlab_round(1.5 * fs / f0); // FFT for (int i = half_window_length * 2 + 1; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); // Calculation of the power spectrum. double *power_spectrum = forward_real_fft->waveform; for (int i = 0; i <= fft_size / 2; ++i) power_spectrum[i] = forward_real_fft->spectrum[i][0] * forward_real_fft->spectrum[i][0] + forward_real_fft->spectrum[i][1] * forward_real_fft->spectrum[i][1]; // DC correction DCCorrection(power_spectrum, f0, fs, fft_size, power_spectrum); } //----------------------------------------------------------------------------- // SetParametersForGetWindowedWaveform() //----------------------------------------------------------------------------- static void SetParametersForGetWindowedWaveform(int half_window_length, int x_length, double currnet_position, int fs, double current_f0, int *base_index, int *safe_index, double *window) { for (int i = -half_window_length; i <= half_window_length; ++i) base_index[i + half_window_length] = i; int origin = matlab_round(currnet_position * fs + 0.001); for (int i = 0; i <= half_window_length * 2; ++i) safe_index[i] = MyMinInt(x_length - 1, MyMaxInt(0, origin + base_index[i])); // Designing of the window function double average = 0.0; double position; for (int i = 0; i <= half_window_length * 2; ++i) { position = base_index[i] / 1.5 / fs; window[i] = 0.5 * cos(world::kPi * position * current_f0) + 0.5; average += window[i] * window[i]; } average = sqrt(average); for (int i = 0; i <= half_window_length * 2; ++i) window[i] /= average; } //----------------------------------------------------------------------------- // GetWindowedWaveform() windows the waveform by F0-adaptive window //----------------------------------------------------------------------------- static void GetWindowedWaveform(const double *x, int x_length, int fs, double current_f0, double currnet_position, const ForwardRealFFT *forward_real_fft) { int half_window_length = matlab_round(1.5 * fs / current_f0); int *base_index = new int[half_window_length * 2 + 1]; int *safe_index = new int[half_window_length * 2 + 1]; double *window = new double[half_window_length * 2 + 1]; SetParametersForGetWindowedWaveform(half_window_length, x_length, currnet_position, fs, current_f0, base_index, safe_index, window); // F0-adaptive windowing double *waveform = forward_real_fft->waveform; for (int i = 0; i <= half_window_length * 2; ++i) waveform[i] = x[safe_index[i]] * window[i] + randn() * world::kMySafeGuardMinimum; double tmp_weight1 = 0; double tmp_weight2 = 0; for (int i = 0; i <= half_window_length * 2; ++i) { tmp_weight1 += waveform[i]; tmp_weight2 += window[i]; } double weighting_coefficient = tmp_weight1 / tmp_weight2; for (int i = 0; i <= half_window_length * 2; ++i) waveform[i] -= window[i] * weighting_coefficient; delete[] base_index; delete[] safe_index; delete[] window; } //----------------------------------------------------------------------------- // AddInfinitesimalNoise() //----------------------------------------------------------------------------- static void AddInfinitesimalNoise(const double *input_spectrum, int fft_size, double *output_spectrum) { for (int i = 0; i <= fft_size / 2; ++i) output_spectrum[i] = input_spectrum[i] + fabs(randn()) * world::kEps; } //----------------------------------------------------------------------------- // CheapTrickGeneralBody() calculates a spectral envelope at a temporal // position. This function is only used in CheapTrick(). // Caution: // forward_fft is allocated in advance to speed up the processing. //----------------------------------------------------------------------------- static void CheapTrickGeneralBody(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, double q1, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, double *spectral_envelope) { // F0-adaptive windowing GetWindowedWaveform(x, x_length, fs, current_f0, current_position, forward_real_fft); // Calculate power spectrum with DC correction // Note: The calculated power spectrum is stored in an array for waveform. // In this imprementation, power spectrum is transformed by FFT (NOT IFFT). // However, the same result is obtained. // This is tricky but important for simple implementation. GetPowerSpectrum(fs, current_f0, fft_size, forward_real_fft); // Smoothing of the power (linear axis) // forward_real_fft.waveform is the power spectrum. LinearSmoothing(forward_real_fft->waveform, current_f0 * 2.0 / 3.0, fs, fft_size, forward_real_fft->waveform); // Add infinitesimal noise // This is a safeguard to avoid including zero in the spectrum. AddInfinitesimalNoise(forward_real_fft->waveform, fft_size, forward_real_fft->waveform); // Smoothing (log axis) and spectral recovery on the cepstrum domain. SmoothingWithRecovery(current_f0, fs, fft_size, q1, forward_real_fft, inverse_real_fft, spectral_envelope); } } // namespace int GetFFTSizeForCheapTrick(int fs, const CheapTrickOption *option) { return static_cast(pow(2.0, 1.0 + static_cast(log(3.0 * fs / option->f0_floor + 1) / world::kLog2))); } double GetF0FloorForCheapTrick(int fs, int fft_size) { return 3.0 * fs / (fft_size - 3.0); } void CheapTrick(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, const CheapTrickOption *option, double **spectrogram) { int fft_size = option->fft_size; randn_reseed(); double f0_floor = GetF0FloorForCheapTrick(fs, fft_size); double *spectral_envelope = new double[fft_size]; ForwardRealFFT forward_real_fft = {0}; InitializeForwardRealFFT(fft_size, &forward_real_fft); InverseRealFFT inverse_real_fft = {0}; InitializeInverseRealFFT(fft_size, &inverse_real_fft); double current_f0; for (int i = 0; i < f0_length; ++i) { current_f0 = f0[i] <= f0_floor ? world::kDefaultF0 : f0[i]; CheapTrickGeneralBody(x, x_length, fs, current_f0, fft_size, temporal_positions[i], option->q1, &forward_real_fft, &inverse_real_fft, spectral_envelope); for (int j = 0; j <= fft_size / 2; ++j) spectrogram[i][j] = spectral_envelope[j]; } DestroyForwardRealFFT(&forward_real_fft); DestroyInverseRealFFT(&inverse_real_fft); delete[] spectral_envelope; } void InitializeCheapTrickOption(int fs, CheapTrickOption *option) { // q1 is the parameter used for the spectral recovery. // Since The parameter is optimized, you don't need to change the parameter. option->q1 = -0.15; // f0_floor and fs are used to determine fft_size; // We strongly recommend not to change this value unless you have enough // knowledge of the signal processing in CheapTrick. option->f0_floor = world::kFloorF0; option->fft_size = GetFFTSizeForCheapTrick(fs, option); } ================================================ FILE: libtts/Modules/Lib/World/src/codec.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2017 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Coder/decoder functions for the spectral envelope and aperiodicity. //----------------------------------------------------------------------------- #include "world/codec.h" #include #include "world/constantnumbers.h" #include "world/fft.h" #include "world/matlabfunctions.h" namespace { //----------------------------------------------------------------------------- // Aperiodicity is initialized by the value 1.0 - world::kMySafeGuardMinimum. // This value means the frame/frequency index is aperiodic. //----------------------------------------------------------------------------- static void InitializeAperiodicity(int f0_length, int fft_size, double **aperiodicity) { for (int i = 0; i < f0_length; ++i) for (int j = 0; j < fft_size / 2 + 1; ++j) aperiodicity[i][j] = 1.0 - world::kMySafeGuardMinimum; } //----------------------------------------------------------------------------- // This function identifies whether this frame is voiced or unvoiced. //----------------------------------------------------------------------------- static int CheckVUV(const double *coarse_aperiodicity, int number_of_aperiodicities, double *tmp_aperiodicity) { double tmp = 0.0; for (int i = 0; i < number_of_aperiodicities; ++i) { tmp += coarse_aperiodicity[i]; tmp_aperiodicity[i + 1] = coarse_aperiodicity[i]; } tmp /= number_of_aperiodicities; return tmp > -0.5 ? 1 : 0; // -0.5 is not optimized, but okay. } //----------------------------------------------------------------------------- // Aperiodicity is obtained from the coded aperiodicity. //----------------------------------------------------------------------------- static void GetAperiodicity(const double *coarse_frequency_axis, const double *coarse_aperiodicity, int number_of_aperiodicities, const double *frequency_axis, int fft_size, double *aperiodicity) { interp1(coarse_frequency_axis, coarse_aperiodicity, number_of_aperiodicities + 2, frequency_axis, fft_size / 2 + 1, aperiodicity); for (int i = 0; i <= fft_size / 2; ++i) aperiodicity[i] = pow(10.0, aperiodicity[i] / 20.0); } //----------------------------------------------------------------------------- // Frequency is converted into its mel representation. //----------------------------------------------------------------------------- static inline double FrequencyToMel(double frequency) { return world::kM0 * log(frequency / world::kF0 + 1.0); } //----------------------------------------------------------------------------- // Mel is converted into frequency. //----------------------------------------------------------------------------- static inline double MelToFrequency(double mel) { return world::kF0 * (exp(mel / world::kM0) - 1.0); } //----------------------------------------------------------------------------- // DCT for spectral envelope coding //----------------------------------------------------------------------------- static void DCTForCodec(const double *mel_spectrum, int max_dimension, const fft_complex *weight, const ForwardRealFFT *forward_real_fft, int number_of_dimensions, double *mel_cepstrum) { int bias = max_dimension / 2; for (int i = 0; i < max_dimension / 2; ++i) { forward_real_fft->waveform[i] = mel_spectrum[i * 2]; forward_real_fft->waveform[i + bias] = mel_spectrum[max_dimension - (i * 2) - 1]; } fft_execute(forward_real_fft->forward_fft); double normalization = sqrt(forward_real_fft->fft_size); for (int i = 0; i < number_of_dimensions; ++i) mel_cepstrum[i] = (forward_real_fft->spectrum[i][0] * weight[i][0] - forward_real_fft->spectrum[i][1] * weight[i][1]) / normalization; } //----------------------------------------------------------------------------- // IDCT for spectral envelope decoding //----------------------------------------------------------------------------- static void IDCTForCodec(const double *mel_cepstrum, int max_dimension, const fft_complex *weight, const InverseComplexFFT *inverse_complex_fft, int number_of_dimensions, double *mel_spectrum) { double normalization = sqrt(inverse_complex_fft->fft_size); for (int i = 0; i < number_of_dimensions; ++i) { inverse_complex_fft->input[i][0] = mel_cepstrum[i] * weight[i][0] * normalization; inverse_complex_fft->input[i][1] = -mel_cepstrum[i] * weight[i][1] * normalization; } for (int i = number_of_dimensions; i < max_dimension; ++i) { inverse_complex_fft->input[i][0] = 0.0; inverse_complex_fft->input[i][1] = 0.0; } fft_execute(inverse_complex_fft->inverse_fft); for (int i = 0; i < max_dimension / 2; ++i) { mel_spectrum[i * 2] = inverse_complex_fft->output[i][0]; mel_spectrum[(i * 2) + 1] = inverse_complex_fft->output[max_dimension - i - 1][0]; } } //----------------------------------------------------------------------------- // Spectral envelope in a frame is coded //----------------------------------------------------------------------------- static void CodeOneFrame(const double *log_spectral_envelope, const double *frequency_axis, int fft_size, const double *mel_axis, const fft_complex *weight, int max_dimension, int number_of_dimensions, const ForwardRealFFT *forward_real_fft, double *coded_spectral_envelope) { double *mel_spectrum = new double[max_dimension]; interp1(frequency_axis, log_spectral_envelope, fft_size / 2 + 1, mel_axis, max_dimension, mel_spectrum); // DCT DCTForCodec(mel_spectrum, max_dimension, weight, forward_real_fft, number_of_dimensions, coded_spectral_envelope); delete[] mel_spectrum; } //----------------------------------------------------------------------------- // Coded spectral envelope in a frame is decoded //----------------------------------------------------------------------------- static void DecodeOneFrame(const double *coded_spectral_envelope, const double *frequency_axis, int fft_size, const double *mel_axis, const fft_complex *weight, int max_dimension, int number_of_dimensions, const InverseComplexFFT *inverse_complex_fft, double *spectral_envelope) { double *mel_spectrum = new double[max_dimension + 2]; // IDCT IDCTForCodec(coded_spectral_envelope, max_dimension, weight, inverse_complex_fft, number_of_dimensions, &mel_spectrum[1]); mel_spectrum[0] = mel_spectrum[1]; mel_spectrum[max_dimension + 1] = mel_spectrum[max_dimension]; interp1(mel_axis, mel_spectrum, max_dimension + 2, frequency_axis, fft_size / 2 + 1, spectral_envelope); for (int i = 0; i < fft_size / 2 + 1; ++i) spectral_envelope[i] = exp(spectral_envelope[i] / max_dimension); delete[] mel_spectrum; } //----------------------------------------------------------------------------- // GetParameters() generates the required parameters. //----------------------------------------------------------------------------- static void GetParametersForCoding(double floor_frequency, double ceil_frequency, int fs, int fft_size, double *mel_axis, double *frequency_axis, fft_complex *weight) { int max_dimension = fft_size / 2; double floor_mel = FrequencyToMel(floor_frequency); double ceil_mel = FrequencyToMel(ceil_frequency); // Generate the mel axis and the weighting vector for DCT. for (int i = 0; i < max_dimension; ++i) { mel_axis[i] = (ceil_mel - floor_mel) * i / max_dimension + floor_mel; weight[i][0] = 2.0 * cos(i * world::kPi / fft_size) / sqrt(fft_size); weight[i][1] = 2.0 * sin(i * world::kPi / fft_size) / sqrt(fft_size); } weight[0][0] /= sqrt(2.0); // Generate the frequency axis on mel scale for (int i = 0; i <= max_dimension; ++i) frequency_axis[i] = FrequencyToMel(static_cast(i) * fs / fft_size); } //----------------------------------------------------------------------------- // GetParameters() generates the required parameters. //----------------------------------------------------------------------------- static void GetParametersForDecoding(double floor_frequency, double ceil_frequency, int fs, int fft_size, int number_of_dimensions, double *mel_axis, double *frequency_axis, fft_complex *weight) { int max_dimension = fft_size / 2; double floor_mel = FrequencyToMel(floor_frequency); double ceil_mel = FrequencyToMel(ceil_frequency); // Generate the weighting vector for IDCT. for (int i = 0; i < number_of_dimensions; ++i) { weight[i][0] = cos(i * world::kPi / fft_size) * sqrt(fft_size); weight[i][1] = sin(i * world::kPi / fft_size) * sqrt(fft_size); } weight[0][0] /= sqrt(2.0); // Generate the mel axis for IDCT. for (int i = 0; i < max_dimension; ++i) mel_axis[i + 1] = MelToFrequency((ceil_mel - floor_mel) * i / max_dimension + floor_mel); mel_axis[0] = 0; mel_axis[max_dimension + 1] = fs / 2.0; // Generate the frequency axis for (int i = 0; i < fft_size / 2 + 1; ++i) frequency_axis[i] = static_cast(i) * fs / fft_size; } } // namespace int GetNumberOfAperiodicities(int fs) { return static_cast(MyMinDouble(world::kUpperLimit, fs / 2.0 - world::kFrequencyInterval) / world::kFrequencyInterval); } void CodeAperiodicity(const double * const *aperiodicity, int f0_length, int fs, int fft_size, double **coded_aperiodicity) { int number_of_aperiodicities = GetNumberOfAperiodicities(fs); double *coarse_frequency_axis = new double[number_of_aperiodicities]; for (int i = 0; i < number_of_aperiodicities; ++i) coarse_frequency_axis[i] = world::kFrequencyInterval * (i + 1.0); double *log_aperiodicity = new double[fft_size / 2 + 1]; for (int i = 0; i < f0_length; ++i) { for (int j = 0; j < fft_size / 2 + 1; ++j) log_aperiodicity[j] = 20 * log10(aperiodicity[i][j]); interp1Q(0, static_cast(fs) / fft_size, log_aperiodicity, fft_size / 2 + 1, coarse_frequency_axis, number_of_aperiodicities, coded_aperiodicity[i]); } delete[] coarse_frequency_axis; delete[] log_aperiodicity; } void DecodeAperiodicity(const double * const *coded_aperiodicity, int f0_length, int fs, int fft_size, double **aperiodicity) { InitializeAperiodicity(f0_length, fft_size, aperiodicity); int number_of_aperiodicities = GetNumberOfAperiodicities(fs); double *frequency_axis = new double[fft_size / 2 + 1]; for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] = static_cast(fs) / fft_size * i; double *coarse_frequency_axis = new double[number_of_aperiodicities + 2]; for (int i = 0; i <= number_of_aperiodicities; ++i) coarse_frequency_axis[i] = i * world::kFrequencyInterval; coarse_frequency_axis[number_of_aperiodicities + 1] = fs / 2.0; double *coarse_aperiodicity = new double[number_of_aperiodicities + 2]; coarse_aperiodicity[0] = -60.0; coarse_aperiodicity[number_of_aperiodicities + 1] = -world::kMySafeGuardMinimum; for (int i = 0; i < f0_length; ++i) { if (CheckVUV(coded_aperiodicity[i], number_of_aperiodicities, coarse_aperiodicity) == 1) continue; GetAperiodicity(coarse_frequency_axis, coarse_aperiodicity, number_of_aperiodicities, frequency_axis, fft_size, aperiodicity[i]); } delete[] coarse_aperiodicity; delete[] coarse_frequency_axis; delete[] frequency_axis; } void CodeSpectralEnvelope(const double * const *spectrogram, int f0_length, int fs, int fft_size, int number_of_dimensions, double **coded_spectral_envelope) { double *mel_axis = new double[fft_size / 2]; double *frequency_axis = new double[fft_size / 2 + 1]; double *tmp_spectrum = new double[fft_size / 2 + 1]; fft_complex *weight = new fft_complex[fft_size / 2]; // Generation of the required parameters GetParametersForCoding(world::kFloorFrequency, MyMinDouble(fs / 2.0, world::kCeilFrequency), fs, fft_size, mel_axis, frequency_axis, weight); ForwardRealFFT forward_real_fft = { 0 }; InitializeForwardRealFFT(fft_size / 2, &forward_real_fft); for (int i = 0; i < f0_length; ++i) { for (int j = 0; j < fft_size / 2 + 1; ++j) tmp_spectrum[j] = log(spectrogram[i][j]); CodeOneFrame(tmp_spectrum, frequency_axis, fft_size, mel_axis, weight, fft_size / 2, number_of_dimensions, &forward_real_fft, coded_spectral_envelope[i]); } DestroyForwardRealFFT(&forward_real_fft); delete[] weight; delete[] tmp_spectrum; delete[] frequency_axis; delete[] mel_axis; } void DecodeSpectralEnvelope(const double * const *coded_spectral_envelope, int f0_length, int fs, int fft_size, int number_of_dimensions, double **spectrogram) { double *mel_axis = new double[fft_size / 2 + 2]; double *frequency_axis = new double[fft_size / 2 + 1]; fft_complex *weight = new fft_complex[fft_size / 2]; // Generation of the required parameters GetParametersForDecoding(world::kFloorFrequency, MyMinDouble(fs / 2.0, world::kCeilFrequency), fs, fft_size, number_of_dimensions, mel_axis, frequency_axis, weight); InverseComplexFFT inverse_complex_fft = { 0 }; InitializeInverseComplexFFT(fft_size / 2, &inverse_complex_fft); for (int i = 0; i < f0_length; ++i) { DecodeOneFrame(coded_spectral_envelope[i], frequency_axis, fft_size, mel_axis, weight, fft_size / 2, number_of_dimensions, &inverse_complex_fft, spectrogram[i]); } DestroyInverseComplexFFT(&inverse_complex_fft); delete[] weight; delete[] frequency_axis; delete[] mel_axis; } ================================================ FILE: libtts/Modules/Lib/World/src/common.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // common.cpp includes functions used in at least two files. // (1) Common functions // (2) FFT, IFFT and minimum phase analysis. // // In FFT analysis and minimum phase analysis, // Functions "Initialize*()" allocate the mamory. // Functions "Destroy*()" free the accolated memory. // FFT size is used for initialization, and structs are used to keep the memory. // Functions "GetMinimumPhaseSpectrum()" calculate minimum phase spectrum. // Forward and inverse FFT do not have the function "Get*()", // because forward FFT and inverse FFT can run in one step. // //----------------------------------------------------------------------------- #include "world/common.h" #include #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { static void SetParametersForLinearSmoothing(int boundary, int fft_size, int fs, double width, const double *power_spectrum, double *mirroring_spectrum, double *mirroring_segment, double *frequency_axis) { for (int i = 0; i < boundary; ++i) mirroring_spectrum[i] = power_spectrum[boundary - i]; for (int i = boundary; i < fft_size / 2 + boundary; ++i) mirroring_spectrum[i] = power_spectrum[i - boundary]; for (int i = fft_size / 2 + boundary; i <= fft_size / 2 + boundary * 2; ++i) mirroring_spectrum[i] = power_spectrum[fft_size / 2 - (i - (fft_size / 2 + boundary))]; mirroring_segment[0] = mirroring_spectrum[0] * fs / fft_size; for (int i = 1; i < fft_size / 2 + boundary * 2 + 1; ++i) mirroring_segment[i] = mirroring_spectrum[i] * fs / fft_size + mirroring_segment[i - 1]; for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] = static_cast(i) / fft_size * fs - width / 2.0; } } // namespace //----------------------------------------------------------------------------- int GetSuitableFFTSize(int sample) { return static_cast(pow(2.0, static_cast(log(static_cast(sample)) / world::kLog2) + 1.0)); } void DCCorrection(const double *input, double f0, int fs, int fft_size, double *output) { int upper_limit = 2 + static_cast(f0 * fft_size / fs); double *low_frequency_replica = new double[upper_limit]; double *low_frequency_axis = new double[upper_limit]; for (int i = 0; i < upper_limit; ++i) low_frequency_axis[i] = static_cast(i) * fs / fft_size; int upper_limit_replica = upper_limit - 1; interp1Q(f0 - low_frequency_axis[0], -static_cast(fs) / fft_size, input, upper_limit + 1, low_frequency_axis, upper_limit_replica, low_frequency_replica); for (int i = 0; i < upper_limit_replica; ++i) output[i] = input[i] + low_frequency_replica[i]; delete[] low_frequency_replica; delete[] low_frequency_axis; } void LinearSmoothing(const double *input, double width, int fs, int fft_size, double *output) { int boundary = static_cast(width * fft_size / fs) + 1; // These parameters are set by the other function. double *mirroring_spectrum = new double[fft_size / 2 + boundary * 2 + 1]; double *mirroring_segment = new double[fft_size / 2 + boundary * 2 + 1]; double *frequency_axis = new double[fft_size / 2 + 1]; SetParametersForLinearSmoothing(boundary, fft_size, fs, width, input, mirroring_spectrum, mirroring_segment, frequency_axis); double *low_levels = new double[fft_size / 2 + 1]; double *high_levels = new double[fft_size / 2 + 1]; double origin_of_mirroring_axis = -(boundary - 0.5) * fs / fft_size; double discrete_frequency_interval = static_cast(fs) / fft_size; interp1Q(origin_of_mirroring_axis, discrete_frequency_interval, mirroring_segment, fft_size / 2 + boundary * 2 + 1, frequency_axis, fft_size / 2 + 1, low_levels); for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] += width; interp1Q(origin_of_mirroring_axis, discrete_frequency_interval, mirroring_segment, fft_size / 2 + boundary * 2 + 1, frequency_axis, fft_size / 2 + 1, high_levels); for (int i = 0; i <= fft_size / 2; ++i) output[i] = (high_levels[i] - low_levels[i]) / width; delete[] mirroring_spectrum; delete[] mirroring_segment; delete[] frequency_axis; delete[] low_levels; delete[] high_levels; } void NuttallWindow(int y_length, double *y) { double tmp; for (int i = 0; i < y_length; ++i) { tmp = i / (y_length - 1.0); y[i] = 0.355768 - 0.487396 * cos(2.0 * world::kPi * tmp) + 0.144232 * cos(4.0 * world::kPi * tmp) - 0.012604 * cos(6.0 * world::kPi * tmp); } } //----------------------------------------------------------------------------- // FFT, IFFT and minimum phase analysis void InitializeForwardRealFFT(int fft_size, ForwardRealFFT *forward_real_fft) { forward_real_fft->fft_size = fft_size; forward_real_fft->waveform = new double[fft_size]; forward_real_fft->spectrum = new fft_complex[fft_size]; forward_real_fft->forward_fft = fft_plan_dft_r2c_1d(fft_size, forward_real_fft->waveform, forward_real_fft->spectrum, FFT_ESTIMATE); } void DestroyForwardRealFFT(ForwardRealFFT *forward_real_fft) { fft_destroy_plan(forward_real_fft->forward_fft); delete[] forward_real_fft->spectrum; delete[] forward_real_fft->waveform; } void InitializeInverseRealFFT(int fft_size, InverseRealFFT *inverse_real_fft) { inverse_real_fft->fft_size = fft_size; inverse_real_fft->waveform = new double[fft_size]; inverse_real_fft->spectrum = new fft_complex[fft_size]; inverse_real_fft->inverse_fft = fft_plan_dft_c2r_1d(fft_size, inverse_real_fft->spectrum, inverse_real_fft->waveform, FFT_ESTIMATE); } void DestroyInverseRealFFT(InverseRealFFT *inverse_real_fft) { fft_destroy_plan(inverse_real_fft->inverse_fft); delete[] inverse_real_fft->spectrum; delete[] inverse_real_fft->waveform; } void InitializeInverseComplexFFT(int fft_size, InverseComplexFFT *inverse_complex_fft) { inverse_complex_fft->fft_size = fft_size; inverse_complex_fft->input = new fft_complex[fft_size]; inverse_complex_fft->output = new fft_complex[fft_size]; inverse_complex_fft->inverse_fft = fft_plan_dft_1d(fft_size, inverse_complex_fft->input, inverse_complex_fft->output, FFT_BACKWARD, FFT_ESTIMATE); } void DestroyInverseComplexFFT(InverseComplexFFT *inverse_complex_fft) { fft_destroy_plan(inverse_complex_fft->inverse_fft); delete[] inverse_complex_fft->input; delete[] inverse_complex_fft->output; } void InitializeMinimumPhaseAnalysis(int fft_size, MinimumPhaseAnalysis *minimum_phase) { minimum_phase->fft_size = fft_size; minimum_phase->log_spectrum = new double[fft_size]; minimum_phase->minimum_phase_spectrum = new fft_complex[fft_size]; minimum_phase->cepstrum = new fft_complex[fft_size]; minimum_phase->inverse_fft = fft_plan_dft_r2c_1d(fft_size, minimum_phase->log_spectrum, minimum_phase->cepstrum, FFT_ESTIMATE); minimum_phase->forward_fft = fft_plan_dft_1d(fft_size, minimum_phase->cepstrum, minimum_phase->minimum_phase_spectrum, FFT_FORWARD, FFT_ESTIMATE); } void GetMinimumPhaseSpectrum(const MinimumPhaseAnalysis *minimum_phase) { // Mirroring for (int i = minimum_phase->fft_size / 2 + 1; i < minimum_phase->fft_size; ++i) minimum_phase->log_spectrum[i] = minimum_phase->log_spectrum[minimum_phase->fft_size - i]; // This fft_plan carries out "forward" FFT. // To carriy out the Inverse FFT, the sign of imaginary part // is inverted after FFT. fft_execute(minimum_phase->inverse_fft); minimum_phase->cepstrum[0][1] *= -1.0; for (int i = 1; i < minimum_phase->fft_size / 2; ++i) { minimum_phase->cepstrum[i][0] *= 2.0; minimum_phase->cepstrum[i][1] *= -2.0; } minimum_phase->cepstrum[minimum_phase->fft_size / 2][1] *= -1.0; for (int i = minimum_phase->fft_size / 2 + 1; i < minimum_phase->fft_size; ++i) { minimum_phase->cepstrum[i][0] = 0.0; minimum_phase->cepstrum[i][1] = 0.0; } fft_execute(minimum_phase->forward_fft); // Since x is complex number, calculation of exp(x) is as following. // Note: This FFT library does not keep the aliasing. double tmp; for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) { tmp = exp(minimum_phase->minimum_phase_spectrum[i][0] / minimum_phase->fft_size); minimum_phase->minimum_phase_spectrum[i][0] = tmp * cos(minimum_phase->minimum_phase_spectrum[i][1] / minimum_phase->fft_size); minimum_phase->minimum_phase_spectrum[i][1] = tmp * sin(minimum_phase->minimum_phase_spectrum[i][1] / minimum_phase->fft_size); } } void DestroyMinimumPhaseAnalysis(MinimumPhaseAnalysis *minimum_phase) { fft_destroy_plan(minimum_phase->forward_fft); fft_destroy_plan(minimum_phase->inverse_fft); delete[] minimum_phase->cepstrum; delete[] minimum_phase->log_spectrum; delete[] minimum_phase->minimum_phase_spectrum; } ================================================ FILE: libtts/Modules/Lib/World/src/d4c.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Band-aperiodicity estimation on the basis of the idea of D4C. //----------------------------------------------------------------------------- #include "world/d4c.h" #include #include // for std::sort() #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { //----------------------------------------------------------------------------- // SetParametersForGetWindowedWaveform() //----------------------------------------------------------------------------- static void SetParametersForGetWindowedWaveform(int half_window_length, int x_length, double current_position, int fs, double current_f0, int window_type, double window_length_ratio, int *base_index, int *safe_index, double *window) { for (int i = -half_window_length; i <= half_window_length; ++i) base_index[i + half_window_length] = i; int origin = matlab_round(current_position * fs + 0.001); for (int i = 0; i <= half_window_length * 2; ++i) safe_index[i] = MyMinInt(x_length - 1, MyMaxInt(0, origin + base_index[i])); // Designing of the window function double position; if (window_type == world::kHanning) { // Hanning window for (int i = 0; i <= half_window_length * 2; ++i) { position = (2.0 * base_index[i] / window_length_ratio) / fs; window[i] = 0.5 * cos(world::kPi * position * current_f0) + 0.5; } } else { // Blackman window for (int i = 0; i <= half_window_length * 2; ++i) { position = (2.0 * base_index[i] / window_length_ratio) / fs; window[i] = 0.42 + 0.5 * cos(world::kPi * position * current_f0) + 0.08 * cos(world::kPi * position * current_f0 * 2); } } } //----------------------------------------------------------------------------- // GetWindowedWaveform() windows the waveform by F0-adaptive window // In the variable window_type, 1: hanning, 2: blackman //----------------------------------------------------------------------------- static void GetWindowedWaveform(const double *x, int x_length, int fs, double current_f0, double current_position, int window_type, double window_length_ratio, double *waveform) { int half_window_length = matlab_round(window_length_ratio * fs / current_f0 / 2.0); int *base_index = new int[half_window_length * 2 + 1]; int *safe_index = new int[half_window_length * 2 + 1]; double *window = new double[half_window_length * 2 + 1]; SetParametersForGetWindowedWaveform(half_window_length, x_length, current_position, fs, current_f0, window_type, window_length_ratio, base_index, safe_index, window); // F0-adaptive windowing for (int i = 0; i <= half_window_length * 2; ++i) waveform[i] = x[safe_index[i]] * window[i] + randn() * world::kMySafeGuardMinimum; double tmp_weight1 = 0; double tmp_weight2 = 0; for (int i = 0; i <= half_window_length * 2; ++i) { tmp_weight1 += waveform[i]; tmp_weight2 += window[i]; } double weighting_coefficient = tmp_weight1 / tmp_weight2; for (int i = 0; i <= half_window_length * 2; ++i) waveform[i] -= window[i] * weighting_coefficient; delete[] base_index; delete[] safe_index; delete[] window; } //----------------------------------------------------------------------------- // GetCentroid() calculates the energy centroid (see the book, time-frequency // analysis written by L. Cohen). //----------------------------------------------------------------------------- static void GetCentroid(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, const ForwardRealFFT *forward_real_fft, double *centroid) { for (int i = 0; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; GetWindowedWaveform(x, x_length, fs, current_f0, current_position, world::kBlackman, 4.0, forward_real_fft->waveform); double power = 0.0; for (int i = 0; i <= matlab_round(2.0 * fs / current_f0) * 2; ++i) power += forward_real_fft->waveform[i] * forward_real_fft->waveform[i]; for (int i = 0; i <= matlab_round(2.0 * fs / current_f0) * 2; ++i) forward_real_fft->waveform[i] /= sqrt(power); fft_execute(forward_real_fft->forward_fft); double *tmp_real = new double[fft_size / 2 + 1]; double *tmp_imag = new double[fft_size / 2 + 1]; for (int i = 0; i <= fft_size / 2; ++i) { tmp_real[i] = forward_real_fft->spectrum[i][0]; tmp_imag[i] = forward_real_fft->spectrum[i][1]; } for (int i = 0; i < fft_size; ++i) forward_real_fft->waveform[i] *= i + 1.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) centroid[i] = forward_real_fft->spectrum[i][0] * tmp_real[i] + tmp_imag[i] * forward_real_fft->spectrum[i][1]; delete[] tmp_real; delete[] tmp_imag; } //----------------------------------------------------------------------------- // GetStaticCentroid() calculates the temporally static energy centroid. // Basic idea was proposed by H. Kawahara. //----------------------------------------------------------------------------- static void GetStaticCentroid(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, const ForwardRealFFT *forward_real_fft, double *static_centroid) { double *centroid1 = new double[fft_size / 2 + 1]; double *centroid2 = new double[fft_size / 2 + 1]; GetCentroid(x, x_length, fs, current_f0, fft_size, current_position - 0.25 / current_f0, forward_real_fft, centroid1); GetCentroid(x, x_length, fs, current_f0, fft_size, current_position + 0.25 / current_f0, forward_real_fft, centroid2); for (int i = 0; i <= fft_size / 2; ++i) static_centroid[i] = centroid1[i] + centroid2[i]; DCCorrection(static_centroid, current_f0, fs, fft_size, static_centroid); delete[] centroid1; delete[] centroid2; } //----------------------------------------------------------------------------- // GetSmoothedPowerSpectrum() calculates the smoothed power spectrum. // The parameters used for smoothing are optimized in davance. //----------------------------------------------------------------------------- static void GetSmoothedPowerSpectrum(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, const ForwardRealFFT *forward_real_fft, double *smoothed_power_spectrum) { for (int i = 0; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; GetWindowedWaveform(x, x_length, fs, current_f0, current_position, world::kHanning, 4.0, forward_real_fft->waveform); fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) smoothed_power_spectrum[i] = forward_real_fft->spectrum[i][0] * forward_real_fft->spectrum[i][0] + forward_real_fft->spectrum[i][1] * forward_real_fft->spectrum[i][1]; DCCorrection(smoothed_power_spectrum, current_f0, fs, fft_size, smoothed_power_spectrum); LinearSmoothing(smoothed_power_spectrum, current_f0, fs, fft_size, smoothed_power_spectrum); } //----------------------------------------------------------------------------- // GetStaticGroupDelay() calculates the temporally static group delay. // This is the fundamental parameter in D4C. //----------------------------------------------------------------------------- static void GetStaticGroupDelay(const double *static_centroid, const double *smoothed_power_spectrum, int fs, double f0, int fft_size, double *static_group_delay) { for (int i = 0; i <= fft_size / 2; ++i) static_group_delay[i] = static_centroid[i] / smoothed_power_spectrum[i]; LinearSmoothing(static_group_delay, f0 / 2.0, fs, fft_size, static_group_delay); double *smoothed_group_delay = new double[fft_size / 2 + 1]; LinearSmoothing(static_group_delay, f0, fs, fft_size, smoothed_group_delay); for (int i = 0; i <= fft_size / 2; ++i) static_group_delay[i] -= smoothed_group_delay[i]; delete[] smoothed_group_delay; } //----------------------------------------------------------------------------- // GetCoarseAperiodicity() calculates the aperiodicity in multiples of 3 kHz. // The upper limit is given based on the sampling frequency. //----------------------------------------------------------------------------- static void GetCoarseAperiodicity(const double *static_group_delay, int fs, int fft_size, int number_of_aperiodicities, const double *window, int window_length, const ForwardRealFFT *forward_real_fft, double *coarse_aperiodicity) { int boundary = matlab_round(fft_size * 8.0 / window_length); int half_window_length = window_length / 2; for (int i = 0; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; double *power_spectrum = new double[fft_size / 2 + 1]; int center; for (int i = 0; i < number_of_aperiodicities; ++i) { center = static_cast(world::kFrequencyInterval * (i + 1) * fft_size / fs); for (int j = 0; j <= half_window_length * 2; ++j) forward_real_fft->waveform[j] = static_group_delay[center - half_window_length + j] * window[j]; fft_execute(forward_real_fft->forward_fft); for (int j = 0 ; j <= fft_size / 2; ++j) power_spectrum[j] = forward_real_fft->spectrum[j][0] * forward_real_fft->spectrum[j][0] + forward_real_fft->spectrum[j][1] * forward_real_fft->spectrum[j][1]; std::sort(power_spectrum, power_spectrum + fft_size / 2 + 1); for (int j = 1 ; j <= fft_size / 2; ++j) power_spectrum[j] += power_spectrum[j - 1]; coarse_aperiodicity[i] = 10 * log10(power_spectrum[fft_size / 2 - boundary - 1] / power_spectrum[fft_size / 2]); } delete[] power_spectrum; } static double D4CLoveTrainSub(const double *x, int fs, int x_length, double current_f0, double current_position, int f0_length, int fft_size, int boundary0, int boundary1, int boundary2, ForwardRealFFT *forward_real_fft) { double *power_spectrum = new double[fft_size]; int window_length = matlab_round(1.5 * fs / current_f0) * 2 + 1; GetWindowedWaveform(x, x_length, fs, current_f0, current_position, world::kBlackman, 3.0, forward_real_fft->waveform); for (int i = window_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= boundary0; ++i) power_spectrum[i] = 0.0; for (int i = boundary0 + 1; i < fft_size / 2 + 1; ++i) power_spectrum[i] = forward_real_fft->spectrum[i][0] * forward_real_fft->spectrum[i][0] + forward_real_fft->spectrum[i][1] * forward_real_fft->spectrum[i][1]; for (int i = boundary0; i <= boundary2; ++i) power_spectrum[i] += +power_spectrum[i - 1]; double aperiodicity0 = power_spectrum[boundary1] / power_spectrum[boundary2]; delete[] power_spectrum; return aperiodicity0; } //----------------------------------------------------------------------------- // D4CLoveTrain() determines the aperiodicity with VUV detection. // If a frame was determined as the unvoiced section, aperiodicity is set to // very high value as the safeguard. // If it was voiced section, the aperiodicity of 0 Hz is set to -60 dB. //----------------------------------------------------------------------------- static void D4CLoveTrain(const double *x, int fs, int x_length, const double *f0, int f0_length, const double *temporal_positions, double *aperiodicity0) { double lowest_f0 = 40.0; int fft_size = static_cast(pow(2.0, 1.0 + static_cast(log(3.0 * fs / lowest_f0 + 1) / world::kLog2))); ForwardRealFFT forward_real_fft = { 0 }; InitializeForwardRealFFT(fft_size, &forward_real_fft); // Cumulative powers at 100, 4000, 7900 Hz are used for VUV identification. int boundary0 = static_cast(ceil(100.0 * fft_size / fs)); int boundary1 = static_cast(ceil(4000.0 * fft_size / fs)); int boundary2 = static_cast(ceil(7900.0 * fft_size / fs)); for (int i = 0; i < f0_length; ++i) { if (f0[i] == 0.0) { aperiodicity0[i] = 0.0; continue; } aperiodicity0[i] = D4CLoveTrainSub(x, fs, x_length, MyMaxDouble(f0[i], lowest_f0), temporal_positions[i], f0_length, fft_size, boundary0, boundary1, boundary2, &forward_real_fft); } DestroyForwardRealFFT(&forward_real_fft); } //----------------------------------------------------------------------------- // D4CGeneralBody() calculates a spectral envelope at a temporal // position. This function is only used in D4C(). // Caution: // forward_fft is allocated in advance to speed up the processing. //----------------------------------------------------------------------------- static void D4CGeneralBody(const double *x, int x_length, int fs, double current_f0, int fft_size, double current_position, int number_of_aperiodicities, const double *window, int window_length, const ForwardRealFFT *forward_real_fft, double *coarse_aperiodicity) { double *static_centroid = new double[fft_size / 2 + 1]; double *smoothed_power_spectrum = new double[fft_size / 2 + 1]; double *static_group_delay = new double[fft_size / 2 + 1]; GetStaticCentroid(x, x_length, fs, current_f0, fft_size, current_position, forward_real_fft, static_centroid); GetSmoothedPowerSpectrum(x, x_length, fs, current_f0, fft_size, current_position, forward_real_fft, smoothed_power_spectrum); GetStaticGroupDelay(static_centroid, smoothed_power_spectrum, fs, current_f0, fft_size, static_group_delay); GetCoarseAperiodicity(static_group_delay, fs, fft_size, number_of_aperiodicities, window, window_length, forward_real_fft, coarse_aperiodicity); // Revision of the result based on the F0 for (int i = 0; i < number_of_aperiodicities; ++i) coarse_aperiodicity[i] = MyMinDouble(0.0, coarse_aperiodicity[i] + (current_f0 - 100) / 50.0); delete[] static_centroid; delete[] smoothed_power_spectrum; delete[] static_group_delay; } static void InitializeAperiodicity(int f0_length, int fft_size, double **aperiodicity) { for (int i = 0; i < f0_length; ++i) for (int j = 0; j < fft_size / 2 + 1; ++j) aperiodicity[i][j] = 1.0 - world::kMySafeGuardMinimum; } static void GetAperiodicity(const double *coarse_frequency_axis, const double *coarse_aperiodicity, int number_of_aperiodicities, const double *frequency_axis, int fft_size, double *aperiodicity) { interp1(coarse_frequency_axis, coarse_aperiodicity, number_of_aperiodicities + 2, frequency_axis, fft_size / 2 + 1, aperiodicity); for (int i = 0; i <= fft_size / 2; ++i) aperiodicity[i] = pow(10.0, aperiodicity[i] / 20.0); } } // namespace void D4C(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, int fft_size, const D4COption *option, double **aperiodicity) { randn_reseed(); InitializeAperiodicity(f0_length, fft_size, aperiodicity); int fft_size_d4c = static_cast(pow(2.0, 1.0 + static_cast(log(4.0 * fs / world::kFloorF0D4C + 1) / world::kLog2))); ForwardRealFFT forward_real_fft = {0}; InitializeForwardRealFFT(fft_size_d4c, &forward_real_fft); int number_of_aperiodicities = static_cast(MyMinDouble(world::kUpperLimit, fs / 2.0 - world::kFrequencyInterval) / world::kFrequencyInterval); // Since the window function is common in D4CGeneralBody(), // it is designed here to speed up. int window_length = static_cast(world::kFrequencyInterval * fft_size_d4c / fs) * 2 + 1; double *window = new double[window_length]; NuttallWindow(window_length, window); // D4C Love Train (Aperiodicity of 0 Hz is given by the different algorithm) double *aperiodicity0 = new double[f0_length]; D4CLoveTrain(x, fs, x_length, f0, f0_length, temporal_positions, aperiodicity0); double *coarse_aperiodicity = new double[number_of_aperiodicities + 2]; coarse_aperiodicity[0] = -60.0; coarse_aperiodicity[number_of_aperiodicities + 1] = -world::kMySafeGuardMinimum; double *coarse_frequency_axis = new double[number_of_aperiodicities + 2]; for (int i = 0; i <= number_of_aperiodicities; ++i) coarse_frequency_axis[i] = i * world::kFrequencyInterval; coarse_frequency_axis[number_of_aperiodicities + 1] = fs / 2.0; double *frequency_axis = new double[fft_size / 2 + 1]; for (int i = 0; i <= fft_size / 2; ++i) frequency_axis[i] = static_cast(i) * fs / fft_size; for (int i = 0; i < f0_length; ++i) { if (f0[i] == 0 || aperiodicity0[i] <= option->threshold) continue; D4CGeneralBody(x, x_length, fs, MyMaxDouble(world::kFloorF0D4C, f0[i]), fft_size_d4c, temporal_positions[i], number_of_aperiodicities, window, window_length, &forward_real_fft, &coarse_aperiodicity[1]); // Linear interpolation to convert the coarse aperiodicity into its // spectral representation. GetAperiodicity(coarse_frequency_axis, coarse_aperiodicity, number_of_aperiodicities, frequency_axis, fft_size, aperiodicity[i]); } DestroyForwardRealFFT(&forward_real_fft); delete[] aperiodicity0; delete[] coarse_frequency_axis; delete[] coarse_aperiodicity; delete[] window; delete[] frequency_axis; } void InitializeD4COption(D4COption *option) { option->threshold = world::kThreshold; } ================================================ FILE: libtts/Modules/Lib/World/src/dio.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // F0 estimation based on DIO (Distributed Inline-filter Operation). //----------------------------------------------------------------------------- #include "world/dio.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" //----------------------------------------------------------------------------- // struct for GetFourZeroCrossingIntervals() // "negative" means "zero-crossing point going from positive to negative" // "positive" means "zero-crossing point going from negative to positive" //----------------------------------------------------------------------------- typedef struct { double *negative_interval_locations; double *negative_intervals; int number_of_negatives; double *positive_interval_locations; double *positive_intervals; int number_of_positives; double *peak_interval_locations; double *peak_intervals; int number_of_peaks; double *dip_interval_locations; double *dip_intervals; int number_of_dips; } ZeroCrossings; namespace { //----------------------------------------------------------------------------- // DesignLowCutFilter() calculates the coefficients the filter. //----------------------------------------------------------------------------- static void DesignLowCutFilter(int N, int fft_size, double *low_cut_filter) { for (int i = 1; i <= N; ++i) low_cut_filter[i - 1] = 0.5 - 0.5 * cos(i * 2.0 * world::kPi / (N + 1)); for (int i = N; i < fft_size; ++i) low_cut_filter[i] = 0.0; double sum_of_amplitude = 0.0; for (int i = 0; i < N; ++i) sum_of_amplitude += low_cut_filter[i]; for (int i = 0; i < N; ++i) low_cut_filter[i] = -low_cut_filter[i] / sum_of_amplitude; for (int i = 0; i < (N - 1) / 2; ++i) low_cut_filter[fft_size - (N - 1) / 2 + i] = low_cut_filter[i]; for (int i = 0; i < N; ++i) low_cut_filter[i] = low_cut_filter[i + (N - 1) / 2]; low_cut_filter[0] += 1.0; } //----------------------------------------------------------------------------- // GetSpectrumForEstimation() calculates the spectrum for estimation. // This function carries out downsampling to speed up the estimation process // and calculates the spectrum of the downsampled signal. //----------------------------------------------------------------------------- static void GetSpectrumForEstimation(const double *x, int x_length, int y_length, double actual_fs, int fft_size, int decimation_ratio, fft_complex *y_spectrum) { double *y = new double[fft_size]; // Initialization for (int i = 0; i < fft_size; ++i) y[i] = 0.0; // Downsampling if (decimation_ratio != 1) decimate(x, x_length, decimation_ratio, y); else for (int i = 0; i < x_length; ++i) y[i] = x[i]; // Removal of the DC component (y = y - mean value of y) double mean_y = 0.0; for (int i = 0; i < y_length; ++i) mean_y += y[i]; mean_y /= y_length; for (int i = 0; i < y_length; ++i) y[i] -= mean_y; for (int i = y_length; i < fft_size; ++i) y[i] = 0.0; fft_plan forwardFFT = fft_plan_dft_r2c_1d(fft_size, y, y_spectrum, FFT_ESTIMATE); fft_execute(forwardFFT); // Low cut filtering (from 0.1.4). Cut off frequency is 50.0 Hz. int cutoff_in_sample = matlab_round(actual_fs / world::kCutOff); DesignLowCutFilter(cutoff_in_sample * 2 + 1, fft_size, y); fft_complex *filter_spectrum = new fft_complex[fft_size]; forwardFFT.c_out = filter_spectrum; fft_execute(forwardFFT); double tmp = 0; for (int i = 0; i <= fft_size / 2; ++i) { // Complex number multiplications. tmp = y_spectrum[i][0] * filter_spectrum[i][0] - y_spectrum[i][1] * filter_spectrum[i][1]; y_spectrum[i][1] = y_spectrum[i][0] * filter_spectrum[i][1] + y_spectrum[i][1] * filter_spectrum[i][0]; y_spectrum[i][0] = tmp; } fft_destroy_plan(forwardFFT); delete[] y; delete[] filter_spectrum; } //----------------------------------------------------------------------------- // GetBestF0Contour() calculates the best f0 contour based on scores of // all candidates. The F0 with highest score is selected. //----------------------------------------------------------------------------- static void GetBestF0Contour(int f0_length, const double * const * f0_candidates, const double * const * f0_scores, int number_of_bands, double *best_f0_contour) { double tmp; for (int i = 0; i < f0_length; ++i) { tmp = f0_scores[0][i]; best_f0_contour[i] = f0_candidates[0][i]; for (int j = 1; j < number_of_bands; ++j) { if (tmp > f0_scores[j][i]) { tmp = f0_scores[j][i]; best_f0_contour[i] = f0_candidates[j][i]; } } } } //----------------------------------------------------------------------------- // FixStep1() is the 1st step of the postprocessing. // This function eliminates the unnatural change of f0 based on allowed_range. //----------------------------------------------------------------------------- static void FixStep1(const double *best_f0_contour, int f0_length, int voice_range_minimum, double allowed_range, double *f0_step1) { double *f0_base = new double[f0_length]; // Initialization for (int i = 0; i < voice_range_minimum; ++i) f0_base[i] = 0.0; for (int i = voice_range_minimum; i < f0_length - voice_range_minimum; ++i) f0_base[i] = best_f0_contour[i]; for (int i = f0_length - voice_range_minimum; i < f0_length; ++i) f0_base[i] = 0.0; // Processing to prevent the jumping of f0 for (int i = 0; i < voice_range_minimum; ++i) f0_step1[i] = 0.0; for (int i = voice_range_minimum; i < f0_length; ++i) f0_step1[i] = fabs((f0_base[i] - f0_base[i - 1]) / (world::kMySafeGuardMinimum + f0_base[i])) < allowed_range ? f0_base[i] : 0.0; delete[] f0_base; } //----------------------------------------------------------------------------- // FixStep2() is the 2nd step of the postprocessing. // This function eliminates the suspected f0 in the anlaut and auslaut. //----------------------------------------------------------------------------- static void FixStep2(const double *f0_step1, int f0_length, int voice_range_minimum, double *f0_step2) { for (int i = 0; i < f0_length; ++i) f0_step2[i] = f0_step1[i]; int center = (voice_range_minimum - 1) / 2; for (int i = center; i < f0_length - center; ++i) { for (int j = -center; j <= center; ++j) { if (f0_step1[i + j] == 0) { f0_step2[i] = 0.0; break; } } } } //----------------------------------------------------------------------------- // GetNumberOfVoicedSections() counts the number of voiced sections. //----------------------------------------------------------------------------- static void GetNumberOfVoicedSections(const double *f0, int f0_length, int *positive_index, int *negative_index, int *positive_count, int *negative_count) { *positive_count = *negative_count = 0; for (int i = 1; i < f0_length; ++i) if (f0[i] == 0 && f0[i - 1] != 0) negative_index[(*negative_count)++] = i - 1; else if (f0[i - 1] == 0 && f0[i] != 0) positive_index[(*positive_count)++] = i; } //----------------------------------------------------------------------------- // SelectOneF0() corrects the f0[current_index] based on // f0[current_index + sign]. //----------------------------------------------------------------------------- static double SelectBestF0(double current_f0, double past_f0, const double * const * f0_candidates, int number_of_candidates, int target_index, double allowed_range) { double reference_f0 = (current_f0 * 3.0 - past_f0) / 2.0; double minimum_error = fabs(reference_f0 - f0_candidates[0][target_index]); double best_f0 = f0_candidates[0][target_index]; double current_error; for (int i = 1; i < number_of_candidates; ++i) { current_error = fabs(reference_f0 - f0_candidates[i][target_index]); if (current_error < minimum_error) { minimum_error = current_error; best_f0 = f0_candidates[i][target_index]; } } if (fabs(1.0 - best_f0 / reference_f0) > allowed_range) return 0.0; return best_f0; } //----------------------------------------------------------------------------- // FixStep3() is the 3rd step of the postprocessing. // This function corrects the f0 candidates from backward to forward. //----------------------------------------------------------------------------- static void FixStep3(const double *f0_step2, int f0_length, const double * const * f0_candidates, int number_of_candidates, double allowed_range, const int *negative_index, int negative_count, double *f0_step3) { for (int i = 0; i < f0_length; i++) f0_step3[i] = f0_step2[i]; int limit; for (int i = 0; i < negative_count; ++i) { limit = i == negative_count - 1 ? f0_length - 1 : negative_index[i + 1]; for (int j = negative_index[i]; j < limit; ++j) { f0_step3[j + 1] = SelectBestF0(f0_step3[j], f0_step3[j - 1], f0_candidates, number_of_candidates, j + 1, allowed_range); if (f0_step3[j + 1] == 0) break; } } } //----------------------------------------------------------------------------- // FixStep4() is the 4th step of the postprocessing. // This function corrects the f0 candidates from forward to backward. //----------------------------------------------------------------------------- static void FixStep4(const double *f0_step3, int f0_length, const double * const * f0_candidates, int number_of_candidates, double allowed_range, const int *positive_index, int positive_count, double *f0_step4) { for (int i = 0; i < f0_length; ++i) f0_step4[i] = f0_step3[i]; int limit; for (int i = positive_count - 1; i >= 0; --i) { limit = i == 0 ? 1 : positive_index[i - 1]; for (int j = positive_index[i]; j > limit; --j) { f0_step4[j - 1] = SelectBestF0(f0_step4[j], f0_step4[j + 1], f0_candidates, number_of_candidates, j - 1, allowed_range); if (f0_step4[j - 1] == 0) break; } } } //----------------------------------------------------------------------------- // FixF0Contour() calculates the definitive f0 contour based on all f0 // candidates. There are four steps. //----------------------------------------------------------------------------- static void FixF0Contour(double frame_period, int number_of_candidates, int fs, const double * const * f0_candidates, const double *best_f0_contour, int f0_length, double f0_floor, double allowed_range, double *fixed_f0_contour) { int voice_range_minimum = static_cast(0.5 + 1000.0 / frame_period / f0_floor) * 2 + 1; if (f0_length <= voice_range_minimum) return; double *f0_tmp1 = new double[f0_length]; double *f0_tmp2 = new double[f0_length]; FixStep1(best_f0_contour, f0_length, voice_range_minimum, allowed_range, f0_tmp1); FixStep2(f0_tmp1, f0_length, voice_range_minimum, f0_tmp2); int positive_count, negative_count; int *positive_index = new int[f0_length]; int *negative_index = new int[f0_length]; GetNumberOfVoicedSections(f0_tmp2, f0_length, positive_index, negative_index, &positive_count, &negative_count); FixStep3(f0_tmp2, f0_length, f0_candidates, number_of_candidates, allowed_range, negative_index, negative_count, f0_tmp1); FixStep4(f0_tmp1, f0_length, f0_candidates, number_of_candidates, allowed_range, positive_index, positive_count, fixed_f0_contour); delete[] f0_tmp1; delete[] f0_tmp2; delete[] positive_index; delete[] negative_index; } //----------------------------------------------------------------------------- // GetFilteredSignal() calculates the signal that is the convolution of the // input signal and low-pass filter. // This function is only used in RawEventByDio() //----------------------------------------------------------------------------- static void GetFilteredSignal(int half_average_length, int fft_size, const fft_complex *y_spectrum, int y_length, double *filtered_signal) { double *low_pass_filter = new double[fft_size]; // Nuttall window is used as a low-pass filter. // Cutoff frequency depends on the window length. NuttallWindow(half_average_length * 4, low_pass_filter); for (int i = half_average_length * 4; i < fft_size; ++i) low_pass_filter[i] = 0.0; fft_complex *low_pass_filter_spectrum = new fft_complex[fft_size]; fft_plan forwardFFT = fft_plan_dft_r2c_1d(fft_size, low_pass_filter, low_pass_filter_spectrum, FFT_ESTIMATE); fft_execute(forwardFFT); // Convolution double tmp = y_spectrum[0][0] * low_pass_filter_spectrum[0][0] - y_spectrum[0][1] * low_pass_filter_spectrum[0][1]; low_pass_filter_spectrum[0][1] = y_spectrum[0][0] * low_pass_filter_spectrum[0][1] + y_spectrum[0][1] * low_pass_filter_spectrum[0][0]; low_pass_filter_spectrum[0][0] = tmp; for (int i = 1; i <= fft_size / 2; ++i) { tmp = y_spectrum[i][0] * low_pass_filter_spectrum[i][0] - y_spectrum[i][1] * low_pass_filter_spectrum[i][1]; low_pass_filter_spectrum[i][1] = y_spectrum[i][0] * low_pass_filter_spectrum[i][1] + y_spectrum[i][1] * low_pass_filter_spectrum[i][0]; low_pass_filter_spectrum[i][0] = tmp; low_pass_filter_spectrum[fft_size - i - 1][0] = low_pass_filter_spectrum[i][0]; low_pass_filter_spectrum[fft_size - i - 1][1] = low_pass_filter_spectrum[i][1]; } fft_plan inverseFFT = fft_plan_dft_c2r_1d(fft_size, low_pass_filter_spectrum, filtered_signal, FFT_ESTIMATE); fft_execute(inverseFFT); // Compensation of the delay. int index_bias = half_average_length * 2; for (int i = 0; i < y_length; ++i) filtered_signal[i] = filtered_signal[i + index_bias]; fft_destroy_plan(inverseFFT); fft_destroy_plan(forwardFFT); delete[] low_pass_filter_spectrum; delete[] low_pass_filter; } //----------------------------------------------------------------------------- // CheckEvent() returns 1, provided that the input value is over 1. // This function is for RawEventByDio(). //----------------------------------------------------------------------------- static inline int CheckEvent(int x) { return x > 0 ? 1 : 0; } //----------------------------------------------------------------------------- // ZeroCrossingEngine() calculates the zero crossing points from positive to // negative. Thanks to Custom.Maid http://custom-made.seesaa.net/ (2012/8/19) //----------------------------------------------------------------------------- static int ZeroCrossingEngine(const double *filtered_signal, int y_length, double fs, double *interval_locations, double *intervals) { int *negative_going_points = new int[y_length]; for (int i = 0; i < y_length - 1; ++i) negative_going_points[i] = 0.0 < filtered_signal[i] && filtered_signal[i + 1] <= 0.0 ? i + 1 : 0; negative_going_points[y_length - 1] = 0; int *edges = new int[y_length]; int count = 0; for (int i = 0; i < y_length; ++i) if (negative_going_points[i] > 0) edges[count++] = negative_going_points[i]; if (count < 2) { delete[] edges; delete[] negative_going_points; return 0; } double *fine_edges = new double[count]; for (int i = 0; i < count; ++i) fine_edges[i] = edges[i] - filtered_signal[edges[i] - 1] / (filtered_signal[edges[i]] - filtered_signal[edges[i] - 1]); for (int i = 0; i < count - 1; ++i) { intervals[i] = fs / (fine_edges[i + 1] - fine_edges[i]); interval_locations[i] = (fine_edges[i] + fine_edges[i + 1]) / 2.0 / fs; } delete[] fine_edges; delete[] edges; delete[] negative_going_points; return count - 1; } //----------------------------------------------------------------------------- // GetFourZeroCrossingIntervals() calculates four zero-crossing intervals. // (1) Zero-crossing going from negative to positive. // (2) Zero-crossing going from positive to negative. // (3) Peak, and (4) dip. (3) and (4) are calculated from the zero-crossings of // the differential of waveform. //----------------------------------------------------------------------------- static void GetFourZeroCrossingIntervals(double *filtered_signal, int y_length, double actual_fs, ZeroCrossings *zero_crossings) { // x_length / 4 (old version) is fixed at 2013/07/14 const int kMaximumNumber = y_length; zero_crossings->negative_interval_locations = new double[kMaximumNumber]; zero_crossings->positive_interval_locations = new double[kMaximumNumber]; zero_crossings->peak_interval_locations = new double[kMaximumNumber]; zero_crossings->dip_interval_locations = new double[kMaximumNumber]; zero_crossings->negative_intervals = new double[kMaximumNumber]; zero_crossings->positive_intervals = new double[kMaximumNumber]; zero_crossings->peak_intervals = new double[kMaximumNumber]; zero_crossings->dip_intervals = new double[kMaximumNumber]; zero_crossings->number_of_negatives = ZeroCrossingEngine(filtered_signal, y_length, actual_fs, zero_crossings->negative_interval_locations, zero_crossings->negative_intervals); for (int i = 0; i < y_length; ++i) filtered_signal[i] = -filtered_signal[i]; zero_crossings->number_of_positives = ZeroCrossingEngine(filtered_signal, y_length, actual_fs, zero_crossings->positive_interval_locations, zero_crossings->positive_intervals); for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] = filtered_signal[i] - filtered_signal[i + 1]; zero_crossings->number_of_peaks = ZeroCrossingEngine(filtered_signal, y_length - 1, actual_fs, zero_crossings->peak_interval_locations, zero_crossings->peak_intervals); for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] = -filtered_signal[i]; zero_crossings->number_of_dips = ZeroCrossingEngine(filtered_signal, y_length - 1, actual_fs, zero_crossings->dip_interval_locations, zero_crossings->dip_intervals); } //----------------------------------------------------------------------------- // GetF0CandidateContourSub() calculates the f0 candidates and deviations. // This is the sub-function of GetF0Candidates() and assumes the calculation. //----------------------------------------------------------------------------- static void GetF0CandidateContourSub( const double * const * interpolated_f0_set, int f0_length, double f0_floor, double f0_ceil, double boundary_f0, double *f0_candidate, double *f0_score) { for (int i = 0; i < f0_length; ++i) { f0_candidate[i] = (interpolated_f0_set[0][i] + interpolated_f0_set[1][i] + interpolated_f0_set[2][i] + interpolated_f0_set[3][i]) / 4.0; f0_score[i] = sqrt(((interpolated_f0_set[0][i] - f0_candidate[i]) * (interpolated_f0_set[0][i] - f0_candidate[i]) + (interpolated_f0_set[1][i] - f0_candidate[i]) * (interpolated_f0_set[1][i] - f0_candidate[i]) + (interpolated_f0_set[2][i] - f0_candidate[i]) * (interpolated_f0_set[2][i] - f0_candidate[i]) + (interpolated_f0_set[3][i] - f0_candidate[i]) * (interpolated_f0_set[3][i] - f0_candidate[i])) / 3.0); if (f0_candidate[i] > boundary_f0 || f0_candidate[i] < boundary_f0 / 2.0 || f0_candidate[i] > f0_ceil || f0_candidate[i] < f0_floor) { f0_candidate[i] = 0.0; f0_score[i] = world::kMaximumValue; } } } //----------------------------------------------------------------------------- // GetF0CandidateContour() calculates the F0 candidates based on the // zero-crossings. //----------------------------------------------------------------------------- static void GetF0CandidateContour(const ZeroCrossings *zero_crossings, double boundary_f0, double f0_floor, double f0_ceil, const double *temporal_positions, int f0_length, double *f0_candidate, double *f0_score) { if (0 == CheckEvent(zero_crossings->number_of_negatives - 2) * CheckEvent(zero_crossings->number_of_positives - 2) * CheckEvent(zero_crossings->number_of_peaks - 2) * CheckEvent(zero_crossings->number_of_dips - 2)) { for (int i = 0; i < f0_length; ++i) { f0_score[i] = world::kMaximumValue; f0_candidate[i] = 0.0; } return; } double *interpolated_f0_set[4]; for (int i = 0; i < 4; ++i) interpolated_f0_set[i] = new double[f0_length]; interp1(zero_crossings->negative_interval_locations, zero_crossings->negative_intervals, zero_crossings->number_of_negatives, temporal_positions, f0_length, interpolated_f0_set[0]); interp1(zero_crossings->positive_interval_locations, zero_crossings->positive_intervals, zero_crossings->number_of_positives, temporal_positions, f0_length, interpolated_f0_set[1]); interp1(zero_crossings->peak_interval_locations, zero_crossings->peak_intervals, zero_crossings->number_of_peaks, temporal_positions, f0_length, interpolated_f0_set[2]); interp1(zero_crossings->dip_interval_locations, zero_crossings->dip_intervals, zero_crossings->number_of_dips, temporal_positions, f0_length, interpolated_f0_set[3]); GetF0CandidateContourSub(interpolated_f0_set, f0_length, f0_floor, f0_ceil, boundary_f0, f0_candidate, f0_score); for (int i = 0; i < 4; ++i) delete[] interpolated_f0_set[i]; } //----------------------------------------------------------------------------- // DestroyZeroCrossings() frees the memory of array in the struct //----------------------------------------------------------------------------- static void DestroyZeroCrossings(ZeroCrossings *zero_crossings) { delete[] zero_crossings->negative_interval_locations; delete[] zero_crossings->positive_interval_locations; delete[] zero_crossings->peak_interval_locations; delete[] zero_crossings->dip_interval_locations; delete[] zero_crossings->negative_intervals; delete[] zero_crossings->positive_intervals; delete[] zero_crossings->peak_intervals; delete[] zero_crossings->dip_intervals; } //----------------------------------------------------------------------------- // GetF0CandidateFromRawEvent() calculates F0 candidate contour in 1-ch signal //----------------------------------------------------------------------------- static void GetF0CandidateFromRawEvent(double boundary_f0, double fs, const fft_complex *y_spectrum, int y_length, int fft_size, double f0_floor, double f0_ceil, const double *temporal_positions, int f0_length, double *f0_score, double *f0_candidate) { double *filtered_signal = new double[fft_size]; GetFilteredSignal(matlab_round(fs / boundary_f0 / 2.0), fft_size, y_spectrum, y_length, filtered_signal); ZeroCrossings zero_crossings = {0}; GetFourZeroCrossingIntervals(filtered_signal, y_length, fs, &zero_crossings); GetF0CandidateContour(&zero_crossings, boundary_f0, f0_floor, f0_ceil, temporal_positions, f0_length, f0_candidate, f0_score); DestroyZeroCrossings(&zero_crossings); delete[] filtered_signal; } //----------------------------------------------------------------------------- // GetF0CandidatesAndScores() calculates all f0 candidates and their scores. //----------------------------------------------------------------------------- static void GetF0CandidatesAndScores(const double *boundary_f0_list, int number_of_bands, double actual_fs, int y_length, const double *temporal_positions, int f0_length, const fft_complex *y_spectrum, int fft_size, double f0_floor, double f0_ceil, double **raw_f0_candidates, double **raw_f0_scores) { double *f0_candidate = new double[f0_length]; double *f0_score = new double[f0_length]; // Calculation of the acoustics events (zero-crossing) for (int i = 0; i < number_of_bands; ++i) { GetF0CandidateFromRawEvent(boundary_f0_list[i], actual_fs, y_spectrum, y_length, fft_size, f0_floor, f0_ceil, temporal_positions, f0_length, f0_score, f0_candidate); for (int j = 0; j < f0_length; ++j) { // A way to avoid zero division raw_f0_scores[i][j] = f0_score[j] / (f0_candidate[j] + world::kMySafeGuardMinimum); raw_f0_candidates[i][j] = f0_candidate[j]; } } delete[] f0_candidate; delete[] f0_score; } //----------------------------------------------------------------------------- // DioGeneralBody() estimates the F0 based on Distributed Inline-filter // Operation. //----------------------------------------------------------------------------- static void DioGeneralBody(const double *x, int x_length, int fs, double frame_period, double f0_floor, double f0_ceil, double channels_in_octave, int speed, double allowed_range, double *temporal_positions, double *f0) { int number_of_bands = 1 + static_cast(log(f0_ceil / f0_floor) / world::kLog2 * channels_in_octave); double *boundary_f0_list = new double[number_of_bands]; for (int i = 0; i < number_of_bands; ++i) boundary_f0_list[i] = f0_floor * pow(2.0, (i + 1) / channels_in_octave); // normalization int decimation_ratio = MyMaxInt(MyMinInt(speed, 12), 1); int y_length = (1 + static_cast(x_length / decimation_ratio)); double actual_fs = static_cast(fs) / decimation_ratio; int fft_size = GetSuitableFFTSize(y_length + matlab_round(actual_fs / world::kCutOff) * 2 + 1 + (4 * static_cast(1.0 + actual_fs / boundary_f0_list[0] / 2.0))); // Calculation of the spectrum used for the f0 estimation fft_complex *y_spectrum = new fft_complex[fft_size]; GetSpectrumForEstimation(x, x_length, y_length, actual_fs, fft_size, decimation_ratio, y_spectrum); double **f0_candidates = new double *[number_of_bands]; double **f0_scores = new double *[number_of_bands]; int f0_length = GetSamplesForDIO(fs, x_length, frame_period); for (int i = 0; i < number_of_bands; ++i) { f0_candidates[i] = new double[f0_length]; f0_scores[i] = new double[f0_length]; } for (int i = 0; i < f0_length; ++i) temporal_positions[i] = i * frame_period / 1000.0; GetF0CandidatesAndScores(boundary_f0_list, number_of_bands, actual_fs, y_length, temporal_positions, f0_length, y_spectrum, fft_size, f0_floor, f0_ceil, f0_candidates, f0_scores); // Selection of the best value based on fundamental-ness. // This function is related with SortCandidates() in MATLAB. double *best_f0_contour = new double[f0_length]; GetBestF0Contour(f0_length, f0_candidates, f0_scores, number_of_bands, best_f0_contour); // Postprocessing to find the best f0-contour. FixF0Contour(frame_period, number_of_bands, fs, f0_candidates, best_f0_contour, f0_length, f0_floor, allowed_range, f0); delete[] best_f0_contour; delete[] y_spectrum; for (int i = 0; i < number_of_bands; ++i) { delete[] f0_scores[i]; delete[] f0_candidates[i]; } delete[] f0_scores; delete[] f0_candidates; delete[] boundary_f0_list; } } // namespace int GetSamplesForDIO(int fs, int x_length, double frame_period) { return static_cast(1000.0 * x_length / fs / frame_period) + 1; } void Dio(const double *x, int x_length, int fs, const DioOption *option, double *temporal_positions, double *f0) { DioGeneralBody(x, x_length, fs, option->frame_period, option->f0_floor, option->f0_ceil, option->channels_in_octave, option->speed, option->allowed_range, temporal_positions, f0); } void InitializeDioOption(DioOption *option) { // You can change default parameters. option->channels_in_octave = 2.0; option->f0_ceil = world::kCeilF0; option->f0_floor = world::kFloorF0; option->frame_period = 5; // You can use the value from 1 to 12. // Default value 11 is for the fs of 44.1 kHz. // The lower value you use, the better performance you can obtain. option->speed = 1; // You can give a positive real number as the threshold. // The most strict value is 0, and there is no upper limit. // On the other hand, I think that the value from 0.02 to 0.2 is reasonable. option->allowed_range = 0.1; } ================================================ FILE: libtts/Modules/Lib/World/src/fft.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // This file represents the functions about FFT (Fast Fourier Transform) // implemented by Mr. Ooura, and wrapper functions implemented by M. Morise. // We can use these wrapper functions as well as the FFTW functions. // Please see the FFTW web-page to show the usage of the wrapper functions. // Ooura FFT: // (Japanese) http://www.kurims.kyoto-u.ac.jp/~ooura/index-j.html // (English) http://www.kurims.kyoto-u.ac.jp/~ooura/index.html // FFTW: // (English) http://www.fftw.org/ // 2012/08/24 by M. Morise //----------------------------------------------------------------------------- #include "world/fft.h" #include #include void cdft(int n, int isgn, double *a, int *ip, double *w); void rdft(int n, int isgn, double *a, int *ip, double *w); namespace { static void BackwardFFT(fft_plan p) { if (p.c_out == NULL) { // c2r p.input[0] = p.c_in[0][0]; p.input[1] = p.c_in[p.n / 2][0]; for (int i = 1; i < p.n / 2; ++i) { p.input[i * 2] = p.c_in[i][0]; p.input[i * 2 + 1] = -p.c_in[i][1]; } rdft(p.n, -1, p.input, p.ip, p.w); for (int i = 0; i < p.n; ++i) p.out[i] = p.input[i] * 2.0; } else { // c2c for (int i = 0; i < p.n; ++i) { p.input[i * 2] = p.c_in[i][0]; p.input[i * 2 + 1] = p.c_in[i][1]; } cdft(p.n * 2, -1, p.input, p.ip, p.w); for (int i = 0; i < p.n; ++i) { p.c_out[i][0] = p.input[i * 2]; p.c_out[i][1] = -p.input[i * 2 + 1]; } } } static void ForwardFFT(fft_plan p) { if (p.c_in == NULL) { // r2c for (int i = 0; i < p.n; ++i) p.input[i] = p.in[i]; rdft(p.n, 1, p.input, p.ip, p.w); p.c_out[0][0] = p.input[0]; p.c_out[0][1] = 0.0; for (int i = 1; i < p.n / 2; ++i) { p.c_out[i][0] = p.input[i * 2]; p.c_out[i][1] = -p.input[i * 2 + 1]; } p.c_out[p.n / 2][0] = p.input[1]; p.c_out[p.n / 2][1] = 0.0; } else { // c2c for (int i = 0; i < p.n; ++i) { p.input[i * 2] = p.c_in[i][0]; p.input[i * 2 + 1] = p.c_in[i][1]; } cdft(p.n * 2, 1, p.input, p.ip, p.w); for (int i = 0; i < p.n; ++i) { p.c_out[i][0] = p.input[i * 2]; p.c_out[i][1] = -p.input[i * 2 + 1]; } } } } // namespace fft_plan fft_plan_dft_1d(int n, fft_complex *in, fft_complex *out, int sign, unsigned int flags) { void makewt(int nw, int *ip, double *w); fft_plan output = {0}; output.n = n; output.in = NULL; output.c_in = in; output.out = NULL; output.c_out = out; output.sign = sign; output.flags = flags; output.input = new double[n * 2]; output.ip = new int[n]; output.w = new double[n * 5 / 4]; output.ip[0] = 0; makewt(output.n >> 1, output.ip, output.w); return output; } fft_plan fft_plan_dft_c2r_1d(int n, fft_complex *in, double *out, unsigned int flags) { void makewt(int nw, int *ip, double *w); void makect(int nc, int *ip, double *c); fft_plan output = {0}; output.n = n; output.in = NULL; output.c_in = in; output.out = out; output.c_out = NULL; output.sign = FFT_BACKWARD; output.flags = flags; output.input = new double[n]; output.ip = new int[n]; output.w = new double[n * 5 / 4]; output.ip[0] = 0; makewt(output.n >> 2, output.ip, output.w); makect(output.n >> 2, output.ip, output.w + (output.n >> 2)); return output; } fft_plan fft_plan_dft_r2c_1d(int n, double *in, fft_complex *out, unsigned int flags) { void makewt(int nw, int *ip, double *w); void makect(int nc, int *ip, double *c); fft_plan output = {0}; output.n = n; output.in = in; output.c_in = NULL; output.out = NULL; output.c_out = out; output.sign = FFT_FORWARD; output.flags = flags; output.input = new double[n]; output.ip = new int[n]; output.w = new double[n * 5 / 4]; output.ip[0] = 0; makewt(output.n >> 2, output.ip, output.w); makect(output.n >> 2, output.ip, output.w + (output.n >> 2)); return output; } void fft_execute(fft_plan p) { if (p.sign == FFT_FORWARD) { ForwardFFT(p); } else { // ifft BackwardFFT(p); } } void fft_destroy_plan(fft_plan p) { p.n = 0; p.in = NULL; p.c_in = NULL; p.out = NULL; p.c_out = NULL; p.sign = 0; p.flags = 0; delete[] p.input; delete[] p.ip; delete[] p.w; } //----------------------------------------------------------------------- // The following functions are reffered by // http://www.kurims.kyoto-u.ac.jp/~ooura/index.html void cdft(int n, int isgn, double *a, int *ip, double *w) { void cftfsub(int n, double *a, int *ip, int nw, double *w); void cftbsub(int n, double *a, int *ip, int nw, double *w); int nw; nw = ip[0]; if (isgn >= 0) { cftfsub(n, a, ip, nw, w); } else { cftbsub(n, a, ip, nw, w); } } void rdft(int n, int isgn, double *a, int *ip, double *w) { void cftfsub(int n, double *a, int *ip, int nw, double *w); void cftbsub(int n, double *a, int *ip, int nw, double *w); void rftfsub(int n, double *a, int nc, double *c); void rftbsub(int n, double *a, int nc, double *c); double xi; int nw = ip[0]; int nc = ip[1]; if (isgn >= 0) { if (n > 4) { cftfsub(n, a, ip, nw, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, ip, nw, w); } xi = a[0] - a[1]; a[0] += a[1]; a[1] = xi; } else { a[1] = 0.5 * (a[0] - a[1]); a[0] -= a[1]; if (n > 4) { rftbsub(n, a, nc, w + nw); cftbsub(n, a, ip, nw, w); } else if (n == 4) { cftbsub(n, a, ip, nw, w); } } } void makewt(int nw, int *ip, double *w) { void makeipt(int nw, int *ip); int j, nwh, nw0, nw1; double delta, wn4r, wk1r, wk1i, wk3r, wk3i; ip[0] = nw; ip[1] = 1; if (nw > 2) { nwh = nw >> 1; delta = atan(1.0) / nwh; wn4r = cos(delta * nwh); w[0] = 1; w[1] = wn4r; if (nwh == 4) { w[2] = cos(delta * 2); w[3] = sin(delta * 2); } else if (nwh > 4) { makeipt(nw, ip); w[2] = 0.5 / cos(delta * 2); w[3] = 0.5 / cos(delta * 6); for (j = 4; j < nwh; j += 4) { w[j] = cos(delta * j); w[j + 1] = sin(delta * j); w[j + 2] = cos(3 * delta * j); w[j + 3] = -sin(3 * delta * j); } } nw0 = 0; while (nwh > 2) { nw1 = nw0 + nwh; nwh >>= 1; w[nw1] = 1; w[nw1 + 1] = wn4r; if (nwh == 4) { wk1r = w[nw0 + 4]; wk1i = w[nw0 + 5]; w[nw1 + 2] = wk1r; w[nw1 + 3] = wk1i; } else if (nwh > 4) { wk1r = w[nw0 + 4]; wk3r = w[nw0 + 6]; w[nw1 + 2] = 0.5 / wk1r; w[nw1 + 3] = 0.5 / wk3r; for (j = 4; j < nwh; j += 4) { wk1r = w[nw0 + 2 * j]; wk1i = w[nw0 + 2 * j + 1]; wk3r = w[nw0 + 2 * j + 2]; wk3i = w[nw0 + 2 * j + 3]; w[nw1 + j] = wk1r; w[nw1 + j + 1] = wk1i; w[nw1 + j + 2] = wk3r; w[nw1 + j + 3] = wk3i; } } nw0 = nw1; } } } void makeipt(int nw, int *ip) { int j, l, m, m2, p, q; ip[2] = 0; ip[3] = 16; m = 2; for (l = nw; l > 32; l >>= 2) { m2 = m << 1; q = m2 << 3; for (j = m; j < m2; j++) { p = ip[j] << 2; ip[m + j] = p; ip[m2 + j] = p + q; } m = m2; } } void makect(int nc, int *ip, double *c) { int j, nch; double delta; ip[1] = nc; if (nc > 1) { nch = nc >> 1; delta = atan(1.0) / nch; c[0] = cos(delta * nch); c[nch] = 0.5 * c[0]; for (j = 1; j < nch; j++) { c[j] = 0.5 * cos(delta * j); c[nc - j] = 0.5 * sin(delta * j); } } } // -------- child routines -------- void cftfsub(int n, double *a, int *ip, int nw, double *w) { void bitrv2(int n, int *ip, double *a); void bitrv216(double *a); void bitrv208(double *a); void cftf1st(int n, double *a, double *w); void cftrec4(int n, double *a, int nw, double *w); void cftleaf(int n, int isplt, double *a, int nw, double *w); void cftfx41(int n, double *a, int nw, double *w); void cftf161(double *a, double *w); void cftf081(double *a, double *w); void cftf040(double *a); void cftx020(double *a); if (n > 8) { if (n > 32) { cftf1st(n, a, &w[nw - (n >> 2)]); if (n > 512) { cftrec4(n, a, nw, w); } else if (n > 128) { cftleaf(n, 1, a, nw, w); } else { cftfx41(n, a, nw, w); } bitrv2(n, ip, a); } else if (n == 32) { cftf161(a, &w[nw - 8]); bitrv216(a); } else { cftf081(a, w); bitrv208(a); } } else if (n == 8) { cftf040(a); } else if (n == 4) { cftx020(a); } } void cftbsub(int n, double *a, int *ip, int nw, double *w) { void bitrv2conj(int n, int *ip, double *a); void bitrv216neg(double *a); void bitrv208neg(double *a); void cftb1st(int n, double *a, double *w); void cftrec4(int n, double *a, int nw, double *w); void cftleaf(int n, int isplt, double *a, int nw, double *w); void cftfx41(int n, double *a, int nw, double *w); void cftf161(double *a, double *w); void cftf081(double *a, double *w); void cftb040(double *a); void cftx020(double *a); if (n > 8) { if (n > 32) { cftb1st(n, a, &w[nw - (n >> 2)]); if (n > 512) { cftrec4(n, a, nw, w); } else if (n > 128) { cftleaf(n, 1, a, nw, w); } else { cftfx41(n, a, nw, w); } bitrv2conj(n, ip, a); } else if (n == 32) { cftf161(a, &w[nw - 8]); bitrv216neg(a); } else { cftf081(a, w); bitrv208neg(a); } } else if (n == 8) { cftb040(a); } else if (n == 4) { cftx020(a); } } void bitrv2(int n, int *ip, double *a) { int j, j1, k, k1, l, m, nh, nm; double xr, xi, yr, yi; m = 1; for (l = n >> 2; l > 8; l >>= 2) { m <<= 1; } nh = n >> 1; nm = 4 * m; if (l == 8) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + 2 * ip[m + k]; k1 = 4 * k + 2 * ip[m + j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + 2 * ip[m + k]; j1 = k1 + 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= 2; k1 -= nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh + 2; k1 += nh + 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh - nm; k1 += 2 * nm - 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } else { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + ip[m + k]; k1 = 4 * k + ip[m + j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + ip[m + k]; j1 = k1 + 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } } void bitrv2conj(int n, int *ip, double *a) { int j, j1, k, k1, l, m, nh, nm; double xr, xi, yr, yi; m = 1; for (l = n >> 2; l > 8; l >>= 2) { m <<= 1; } nh = n >> 1; nm = 4 * m; if (l == 8) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + 2 * ip[m + k]; k1 = 4 * k + 2 * ip[m + j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + 2 * ip[m + k]; j1 = k1 + 2; k1 += nh; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= 2; k1 -= nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh + 2; k1 += nh + 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh - nm; k1 += 2 * nm - 2; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; } } else { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + ip[m + k]; k1 = 4 * k + ip[m + j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + ip[m + k]; j1 = k1 + 2; k1 += nh; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; j1 += nm; k1 += nm; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; } } } void bitrv216(double *a) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x7r = a[14]; x7i = a[15]; x8r = a[16]; x8i = a[17]; x10r = a[20]; x10i = a[21]; x11r = a[22]; x11i = a[23]; x12r = a[24]; x12i = a[25]; x13r = a[26]; x13i = a[27]; x14r = a[28]; x14i = a[29]; a[2] = x8r; a[3] = x8i; a[4] = x4r; a[5] = x4i; a[6] = x12r; a[7] = x12i; a[8] = x2r; a[9] = x2i; a[10] = x10r; a[11] = x10i; a[14] = x14r; a[15] = x14i; a[16] = x1r; a[17] = x1i; a[20] = x5r; a[21] = x5i; a[22] = x13r; a[23] = x13i; a[24] = x3r; a[25] = x3i; a[26] = x11r; a[27] = x11i; a[28] = x7r; a[29] = x7i; } void bitrv216neg(double *a) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i, x15r, x15i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x6r = a[12]; x6i = a[13]; x7r = a[14]; x7i = a[15]; x8r = a[16]; x8i = a[17]; x9r = a[18]; x9i = a[19]; x10r = a[20]; x10i = a[21]; x11r = a[22]; x11i = a[23]; x12r = a[24]; x12i = a[25]; x13r = a[26]; x13i = a[27]; x14r = a[28]; x14i = a[29]; x15r = a[30]; x15i = a[31]; a[2] = x15r; a[3] = x15i; a[4] = x7r; a[5] = x7i; a[6] = x11r; a[7] = x11i; a[8] = x3r; a[9] = x3i; a[10] = x13r; a[11] = x13i; a[12] = x5r; a[13] = x5i; a[14] = x9r; a[15] = x9i; a[16] = x1r; a[17] = x1i; a[18] = x14r; a[19] = x14i; a[20] = x6r; a[21] = x6i; a[22] = x10r; a[23] = x10i; a[24] = x2r; a[25] = x2i; a[26] = x12r; a[27] = x12i; a[28] = x4r; a[29] = x4i; a[30] = x8r; a[31] = x8i; } void bitrv208(double *a) { double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; x1r = a[2]; x1i = a[3]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x6r = a[12]; x6i = a[13]; a[2] = x4r; a[3] = x4i; a[6] = x6r; a[7] = x6i; a[8] = x1r; a[9] = x1i; a[12] = x3r; a[13] = x3i; } void bitrv208neg(double *a) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x6r = a[12]; x6i = a[13]; x7r = a[14]; x7i = a[15]; a[2] = x7r; a[3] = x7i; a[4] = x3r; a[5] = x3i; a[6] = x5r; a[7] = x5i; a[8] = x1r; a[9] = x1i; a[10] = x6r; a[11] = x6i; a[12] = x2r; a[13] = x2i; a[14] = x4r; a[15] = x4i; } void cftf1st(int n, double *a, double *w) { int j, j0, j1, j2, j3, k, m, mh; double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = a[1] + a[j2 + 1]; x1r = a[0] - a[j2]; x1i = a[1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j2] = x1r - x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; csc1 = w[2]; csc3 = w[3]; wd1r = 1; wd1i = 0; wd3r = 1; wd3i = 0; k = 0; for (j = 2; j < mh - 2; j += 4) { k += 4; wk1r = csc1 * (wd1r + w[k]); wk1i = csc1 * (wd1i + w[k + 1]); wk3r = csc3 * (wd3r + w[k + 2]); wk3i = csc3 * (wd3i + w[k + 3]); wd1r = w[k]; wd1i = w[k + 1]; wd3r = w[k + 2]; wd3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = a[j + 1] + a[j2 + 1]; x1r = a[j] - a[j2]; x1i = a[j + 1] - a[j2 + 1]; y0r = a[j + 2] + a[j2 + 2]; y0i = a[j + 3] + a[j2 + 3]; y1r = a[j + 2] - a[j2 + 2]; y1i = a[j + 3] - a[j2 + 3]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 + 2] + a[j3 + 2]; y2i = a[j1 + 3] + a[j3 + 3]; y3r = a[j1 + 2] - a[j3 + 2]; y3i = a[j1 + 3] - a[j3 + 3]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j + 2] = y0r + y2r; a[j + 3] = y0i + y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j1 + 2] = y0r - y2r; a[j1 + 3] = y0i - y2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = y1r - y3i; x0i = y1i + y3r; a[j2 + 2] = wd1r * x0r - wd1i * x0i; a[j2 + 3] = wd1r * x0i + wd1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; x0r = y1r + y3i; x0i = y1i - y3r; a[j3 + 2] = wd3r * x0r + wd3i * x0i; a[j3 + 3] = wd3r * x0i - wd3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; y0r = a[j0 - 2] + a[j2 - 2]; y0i = a[j0 - 1] + a[j2 - 1]; y1r = a[j0 - 2] - a[j2 - 2]; y1i = a[j0 - 1] - a[j2 - 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 - 2] + a[j3 - 2]; y2i = a[j1 - 1] + a[j3 - 1]; y3r = a[j1 - 2] - a[j3 - 2]; y3i = a[j1 - 1] - a[j3 - 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j0 - 2] = y0r + y2r; a[j0 - 1] = y0i + y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j1 - 2] = y0r - y2r; a[j1 - 1] = y0i - y2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = y1r - y3i; x0i = y1i + y3r; a[j2 - 2] = wd1i * x0r - wd1r * x0i; a[j2 - 1] = wd1i * x0i + wd1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; x0r = y1r + y3i; x0i = y1i - y3r; a[j3 - 2] = wd3i * x0r + wd3r * x0i; a[j3 - 1] = wd3i * x0i - wd3r * x0r; } wk1r = csc1 * (wd1r + wn4r); wk1i = csc1 * (wd1i + wn4r); wk3r = csc3 * (wd3r - wn4r); wk3i = csc3 * (wd3i - wn4r); j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] + a[j2 - 2]; x0i = a[j0 - 1] + a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = a[j0 - 1] - a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i + x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 - 2] = wk1r * x0r - wk1i * x0i; a[j2 - 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 - 2] = wk3r * x0r + wk3i * x0i; a[j3 - 1] = wk3r * x0i - wk3i * x0r; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); x0r = a[j0 + 2] + a[j2 + 2]; x0i = a[j0 + 3] + a[j2 + 3]; x1r = a[j0 + 2] - a[j2 + 2]; x1i = a[j0 + 3] - a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j0 + 2] = x0r + x2r; a[j0 + 3] = x0i + x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 + 2] = wk1i * x0r - wk1r * x0i; a[j2 + 3] = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 + 2] = wk3i * x0r + wk3r * x0i; a[j3 + 3] = wk3i * x0i - wk3r * x0r; } void cftb1st(int n, double *a, double *w) { int j, j0, j1, j2, j3, k, m, mh; double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = -a[1] - a[j2 + 1]; x1r = a[0] - a[j2]; x1i = -a[1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j2] = x1r + x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r - x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; csc1 = w[2]; csc3 = w[3]; wd1r = 1; wd1i = 0; wd3r = 1; wd3i = 0; k = 0; for (j = 2; j < mh - 2; j += 4) { k += 4; wk1r = csc1 * (wd1r + w[k]); wk1i = csc1 * (wd1i + w[k + 1]); wk3r = csc3 * (wd3r + w[k + 2]); wk3i = csc3 * (wd3i + w[k + 3]); wd1r = w[k]; wd1i = w[k + 1]; wd3r = w[k + 2]; wd3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = -a[j + 1] - a[j2 + 1]; x1r = a[j] - a[j2]; x1i = -a[j + 1] + a[j2 + 1]; y0r = a[j + 2] + a[j2 + 2]; y0i = -a[j + 3] - a[j2 + 3]; y1r = a[j + 2] - a[j2 + 2]; y1i = -a[j + 3] + a[j2 + 3]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 + 2] + a[j3 + 2]; y2i = a[j1 + 3] + a[j3 + 3]; y3r = a[j1 + 2] - a[j3 + 2]; y3i = a[j1 + 3] - a[j3 + 3]; a[j] = x0r + x2r; a[j + 1] = x0i - x2i; a[j + 2] = y0r + y2r; a[j + 3] = y0i - y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j1 + 2] = y0r - y2r; a[j1 + 3] = y0i + y2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = y1r + y3i; x0i = y1i + y3r; a[j2 + 2] = wd1r * x0r - wd1i * x0i; a[j2 + 3] = wd1r * x0i + wd1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; x0r = y1r - y3i; x0i = y1i - y3r; a[j3 + 2] = wd3r * x0r + wd3i * x0i; a[j3 + 3] = wd3r * x0i - wd3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = -a[j0 + 1] - a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = -a[j0 + 1] + a[j2 + 1]; y0r = a[j0 - 2] + a[j2 - 2]; y0i = -a[j0 - 1] - a[j2 - 1]; y1r = a[j0 - 2] - a[j2 - 2]; y1i = -a[j0 - 1] + a[j2 - 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 - 2] + a[j3 - 2]; y2i = a[j1 - 1] + a[j3 - 1]; y3r = a[j1 - 2] - a[j3 - 2]; y3i = a[j1 - 1] - a[j3 - 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i - x2i; a[j0 - 2] = y0r + y2r; a[j0 - 1] = y0i - y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j1 - 2] = y0r - y2r; a[j1 - 1] = y0i + y2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = y1r + y3i; x0i = y1i + y3r; a[j2 - 2] = wd1i * x0r - wd1r * x0i; a[j2 - 1] = wd1i * x0i + wd1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; x0r = y1r - y3i; x0i = y1i - y3r; a[j3 - 2] = wd3i * x0r + wd3r * x0i; a[j3 - 1] = wd3i * x0i - wd3r * x0r; } wk1r = csc1 * (wd1r + wn4r); wk1i = csc1 * (wd1i + wn4r); wk3r = csc3 * (wd3r - wn4r); wk3i = csc3 * (wd3i - wn4r); j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] + a[j2 - 2]; x0i = -a[j0 - 1] - a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = -a[j0 - 1] + a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i - x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 - 2] = wk1r * x0r - wk1i * x0i; a[j2 - 1] = wk1r * x0i + wk1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 - 2] = wk3r * x0r + wk3i * x0i; a[j3 - 1] = wk3r * x0i - wk3i * x0r; x0r = a[j0] + a[j2]; x0i = -a[j0 + 1] - a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = -a[j0 + 1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); x0r = a[j0 + 2] + a[j2 + 2]; x0i = -a[j0 + 3] - a[j2 + 3]; x1r = a[j0 + 2] - a[j2 + 2]; x1i = -a[j0 + 3] + a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j0 + 2] = x0r + x2r; a[j0 + 3] = x0i - x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 + 2] = wk1i * x0r - wk1r * x0i; a[j2 + 3] = wk1i * x0i + wk1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 + 2] = wk3i * x0r + wk3r * x0i; a[j3 + 3] = wk3i * x0i - wk3r * x0r; } void cftrec4(int n, double *a, int nw, double *w) { int cfttree(int n, int j, int k, double *a, int nw, double *w); void cftleaf(int n, int isplt, double *a, int nw, double *w); void cftmdl1(int n, double *a, double *w); int isplt, j, k, m; m = n; while (m > 512) { m >>= 2; cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]); } cftleaf(m, 1, &a[n - m], nw, w); k = 0; for (j = n - m; j > 0; j -= m) { k++; isplt = cfttree(m, j, k, a, nw, w); cftleaf(m, isplt, &a[j - m], nw, w); } } int cfttree(int n, int j, int k, double *a, int nw, double *w) { void cftmdl1(int n, double *a, double *w); void cftmdl2(int n, double *a, double *w); int i, isplt, m; if ((k & 3) != 0) { isplt = k & 1; if (isplt != 0) { cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]); } else { cftmdl2(n, &a[j - n], &w[nw - n]); } } else { m = n; for (i = k; (i & 3) == 0; i >>= 2) { m <<= 2; } isplt = i & 1; if (isplt != 0) { while (m > 128) { cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]); m >>= 2; } } else { while (m > 128) { cftmdl2(m, &a[j - m], &w[nw - m]); m >>= 2; } } } return isplt; } void cftleaf(int n, int isplt, double *a, int nw, double *w) { void cftmdl1(int n, double *a, double *w); void cftmdl2(int n, double *a, double *w); void cftf161(double *a, double *w); void cftf162(double *a, double *w); void cftf081(double *a, double *w); void cftf082(double *a, double *w); if (n == 512) { cftmdl1(128, a, &w[nw - 64]); cftf161(a, &w[nw - 8]); cftf162(&a[32], &w[nw - 32]); cftf161(&a[64], &w[nw - 8]); cftf161(&a[96], &w[nw - 8]); cftmdl2(128, &a[128], &w[nw - 128]); cftf161(&a[128], &w[nw - 8]); cftf162(&a[160], &w[nw - 32]); cftf161(&a[192], &w[nw - 8]); cftf162(&a[224], &w[nw - 32]); cftmdl1(128, &a[256], &w[nw - 64]); cftf161(&a[256], &w[nw - 8]); cftf162(&a[288], &w[nw - 32]); cftf161(&a[320], &w[nw - 8]); cftf161(&a[352], &w[nw - 8]); if (isplt != 0) { cftmdl1(128, &a[384], &w[nw - 64]); cftf161(&a[480], &w[nw - 8]); } else { cftmdl2(128, &a[384], &w[nw - 128]); cftf162(&a[480], &w[nw - 32]); } cftf161(&a[384], &w[nw - 8]); cftf162(&a[416], &w[nw - 32]); cftf161(&a[448], &w[nw - 8]); } else { cftmdl1(64, a, &w[nw - 32]); cftf081(a, &w[nw - 8]); cftf082(&a[16], &w[nw - 8]); cftf081(&a[32], &w[nw - 8]); cftf081(&a[48], &w[nw - 8]); cftmdl2(64, &a[64], &w[nw - 64]); cftf081(&a[64], &w[nw - 8]); cftf082(&a[80], &w[nw - 8]); cftf081(&a[96], &w[nw - 8]); cftf082(&a[112], &w[nw - 8]); cftmdl1(64, &a[128], &w[nw - 32]); cftf081(&a[128], &w[nw - 8]); cftf082(&a[144], &w[nw - 8]); cftf081(&a[160], &w[nw - 8]); cftf081(&a[176], &w[nw - 8]); if (isplt != 0) { cftmdl1(64, &a[192], &w[nw - 32]); cftf081(&a[240], &w[nw - 8]); } else { cftmdl2(64, &a[192], &w[nw - 64]); cftf082(&a[240], &w[nw - 8]); } cftf081(&a[192], &w[nw - 8]); cftf082(&a[208], &w[nw - 8]); cftf081(&a[224], &w[nw - 8]); } } void cftmdl1(int n, double *a, double *w) { int j, j0, j1, j2, j3, k, m, mh; double wn4r, wk1r, wk1i, wk3r, wk3i; double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = a[1] + a[j2 + 1]; x1r = a[0] - a[j2]; x1i = a[1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j2] = x1r - x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; k = 0; for (j = 2; j < mh; j += 2) { k += 4; wk1r = w[k]; wk1i = w[k + 1]; wk3r = w[k + 2]; wk3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = a[j + 1] + a[j2 + 1]; x1r = a[j] - a[j2]; x1i = a[j + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; } j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); } void cftmdl2(int n, double *a, double *w) { int j, j0, j1, j2, j3, k, kr, m, mh; double wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; mh = n >> 3; m = 2 * mh; wn4r = w[1]; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] - a[j2 + 1]; x0i = a[1] + a[j2]; x1r = a[0] + a[j2 + 1]; x1i = a[1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wn4r * (x2r - x2i); y0i = wn4r * (x2i + x2r); a[0] = x0r + y0r; a[1] = x0i + y0i; a[j1] = x0r - y0r; a[j1 + 1] = x0i - y0i; y0r = wn4r * (x3r - x3i); y0i = wn4r * (x3i + x3r); a[j2] = x1r - y0i; a[j2 + 1] = x1i + y0r; a[j3] = x1r + y0i; a[j3 + 1] = x1i - y0r; k = 0; kr = 2 * m; for (j = 2; j < mh; j += 2) { k += 4; wk1r = w[k]; wk1i = w[k + 1]; wk3r = w[k + 2]; wk3i = w[k + 3]; kr -= 4; wd1i = w[kr]; wd1r = w[kr + 1]; wd3i = w[kr + 2]; wd3r = w[kr + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] - a[j2 + 1]; x0i = a[j + 1] + a[j2]; x1r = a[j] + a[j2 + 1]; x1i = a[j + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wk1r * x0r - wk1i * x0i; y0i = wk1r * x0i + wk1i * x0r; y2r = wd1r * x2r - wd1i * x2i; y2i = wd1r * x2i + wd1i * x2r; a[j] = y0r + y2r; a[j + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wk3r * x1r + wk3i * x1i; y0i = wk3r * x1i - wk3i * x1r; y2r = wd3r * x3r + wd3i * x3i; y2i = wd3r * x3i - wd3i * x3r; a[j2] = y0r + y2r; a[j2 + 1] = y0i + y2i; a[j3] = y0r - y2r; a[j3 + 1] = y0i - y2i; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] - a[j2 + 1]; x0i = a[j0 + 1] + a[j2]; x1r = a[j0] + a[j2 + 1]; x1i = a[j0 + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wd1i * x0r - wd1r * x0i; y0i = wd1i * x0i + wd1r * x0r; y2r = wk1i * x2r - wk1r * x2i; y2i = wk1i * x2i + wk1r * x2r; a[j0] = y0r + y2r; a[j0 + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wd3i * x1r + wd3r * x1i; y0i = wd3i * x1i - wd3r * x1r; y2r = wk3i * x3r + wk3r * x3i; y2i = wk3i * x3i - wk3r * x3r; a[j2] = y0r + y2r; a[j2 + 1] = y0i + y2i; a[j3] = y0r - y2r; a[j3 + 1] = y0i - y2i; } wk1r = w[m]; wk1i = w[m + 1]; j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] - a[j2 + 1]; x0i = a[j0 + 1] + a[j2]; x1r = a[j0] + a[j2 + 1]; x1i = a[j0 + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wk1r * x0r - wk1i * x0i; y0i = wk1r * x0i + wk1i * x0r; y2r = wk1i * x2r - wk1r * x2i; y2i = wk1i * x2i + wk1r * x2r; a[j0] = y0r + y2r; a[j0 + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wk1i * x1r - wk1r * x1i; y0i = wk1i * x1i + wk1r * x1r; y2r = wk1r * x3r - wk1i * x3i; y2i = wk1r * x3i + wk1i * x3r; a[j2] = y0r - y2r; a[j2 + 1] = y0i - y2i; a[j3] = y0r + y2r; a[j3 + 1] = y0i + y2i; } void cftfx41(int n, double *a, int nw, double *w) { void cftf161(double *a, double *w); void cftf162(double *a, double *w); void cftf081(double *a, double *w); void cftf082(double *a, double *w); if (n == 128) { cftf161(a, &w[nw - 8]); cftf162(&a[32], &w[nw - 32]); cftf161(&a[64], &w[nw - 8]); cftf161(&a[96], &w[nw - 8]); } else { cftf081(a, &w[nw - 8]); cftf082(&a[16], &w[nw - 8]); cftf081(&a[32], &w[nw - 8]); cftf081(&a[48], &w[nw - 8]); } } void cftf161(double *a, double *w) { double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; wn4r = w[1]; wk1r = w[2]; wk1i = w[3]; x0r = a[0] + a[16]; x0i = a[1] + a[17]; x1r = a[0] - a[16]; x1i = a[1] - a[17]; x2r = a[8] + a[24]; x2i = a[9] + a[25]; x3r = a[8] - a[24]; x3i = a[9] - a[25]; y0r = x0r + x2r; y0i = x0i + x2i; y4r = x0r - x2r; y4i = x0i - x2i; y8r = x1r - x3i; y8i = x1i + x3r; y12r = x1r + x3i; y12i = x1i - x3r; x0r = a[2] + a[18]; x0i = a[3] + a[19]; x1r = a[2] - a[18]; x1i = a[3] - a[19]; x2r = a[10] + a[26]; x2i = a[11] + a[27]; x3r = a[10] - a[26]; x3i = a[11] - a[27]; y1r = x0r + x2r; y1i = x0i + x2i; y5r = x0r - x2r; y5i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y9r = wk1r * x0r - wk1i * x0i; y9i = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; y13r = wk1i * x0r - wk1r * x0i; y13i = wk1i * x0i + wk1r * x0r; x0r = a[4] + a[20]; x0i = a[5] + a[21]; x1r = a[4] - a[20]; x1i = a[5] - a[21]; x2r = a[12] + a[28]; x2i = a[13] + a[29]; x3r = a[12] - a[28]; x3i = a[13] - a[29]; y2r = x0r + x2r; y2i = x0i + x2i; y6r = x0r - x2r; y6i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y10r = wn4r * (x0r - x0i); y10i = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; y14r = wn4r * (x0r + x0i); y14i = wn4r * (x0i - x0r); x0r = a[6] + a[22]; x0i = a[7] + a[23]; x1r = a[6] - a[22]; x1i = a[7] - a[23]; x2r = a[14] + a[30]; x2i = a[15] + a[31]; x3r = a[14] - a[30]; x3i = a[15] - a[31]; y3r = x0r + x2r; y3i = x0i + x2i; y7r = x0r - x2r; y7i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y11r = wk1i * x0r - wk1r * x0i; y11i = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; y15r = wk1r * x0r - wk1i * x0i; y15i = wk1r * x0i + wk1i * x0r; x0r = y12r - y14r; x0i = y12i - y14i; x1r = y12r + y14r; x1i = y12i + y14i; x2r = y13r - y15r; x2i = y13i - y15i; x3r = y13r + y15r; x3i = y13i + y15i; a[24] = x0r + x2r; a[25] = x0i + x2i; a[26] = x0r - x2r; a[27] = x0i - x2i; a[28] = x1r - x3i; a[29] = x1i + x3r; a[30] = x1r + x3i; a[31] = x1i - x3r; x0r = y8r + y10r; x0i = y8i + y10i; x1r = y8r - y10r; x1i = y8i - y10i; x2r = y9r + y11r; x2i = y9i + y11i; x3r = y9r - y11r; x3i = y9i - y11i; a[16] = x0r + x2r; a[17] = x0i + x2i; a[18] = x0r - x2r; a[19] = x0i - x2i; a[20] = x1r - x3i; a[21] = x1i + x3r; a[22] = x1r + x3i; a[23] = x1i - x3r; x0r = y5r - y7i; x0i = y5i + y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); x0r = y5r + y7i; x0i = y5i - y7r; x3r = wn4r * (x0r - x0i); x3i = wn4r * (x0i + x0r); x0r = y4r - y6i; x0i = y4i + y6r; x1r = y4r + y6i; x1i = y4i - y6r; a[8] = x0r + x2r; a[9] = x0i + x2i; a[10] = x0r - x2r; a[11] = x0i - x2i; a[12] = x1r - x3i; a[13] = x1i + x3r; a[14] = x1r + x3i; a[15] = x1i - x3r; x0r = y0r + y2r; x0i = y0i + y2i; x1r = y0r - y2r; x1i = y0i - y2i; x2r = y1r + y3r; x2i = y1i + y3i; x3r = y1r - y3r; x3i = y1i - y3i; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x0r - x2r; a[3] = x0i - x2i; a[4] = x1r - x3i; a[5] = x1i + x3r; a[6] = x1r + x3i; a[7] = x1i - x3r; } void cftf162(double *a, double *w) { double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; wn4r = w[1]; wk1r = w[4]; wk1i = w[5]; wk3r = w[6]; wk3i = -w[7]; wk2r = w[8]; wk2i = w[9]; x1r = a[0] - a[17]; x1i = a[1] + a[16]; x0r = a[8] - a[25]; x0i = a[9] + a[24]; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); y0r = x1r + x2r; y0i = x1i + x2i; y4r = x1r - x2r; y4i = x1i - x2i; x1r = a[0] + a[17]; x1i = a[1] - a[16]; x0r = a[8] + a[25]; x0i = a[9] - a[24]; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); y8r = x1r - x2i; y8i = x1i + x2r; y12r = x1r + x2i; y12i = x1i - x2r; x0r = a[2] - a[19]; x0i = a[3] + a[18]; x1r = wk1r * x0r - wk1i * x0i; x1i = wk1r * x0i + wk1i * x0r; x0r = a[10] - a[27]; x0i = a[11] + a[26]; x2r = wk3i * x0r - wk3r * x0i; x2i = wk3i * x0i + wk3r * x0r; y1r = x1r + x2r; y1i = x1i + x2i; y5r = x1r - x2r; y5i = x1i - x2i; x0r = a[2] + a[19]; x0i = a[3] - a[18]; x1r = wk3r * x0r - wk3i * x0i; x1i = wk3r * x0i + wk3i * x0r; x0r = a[10] + a[27]; x0i = a[11] - a[26]; x2r = wk1r * x0r + wk1i * x0i; x2i = wk1r * x0i - wk1i * x0r; y9r = x1r - x2r; y9i = x1i - x2i; y13r = x1r + x2r; y13i = x1i + x2i; x0r = a[4] - a[21]; x0i = a[5] + a[20]; x1r = wk2r * x0r - wk2i * x0i; x1i = wk2r * x0i + wk2i * x0r; x0r = a[12] - a[29]; x0i = a[13] + a[28]; x2r = wk2i * x0r - wk2r * x0i; x2i = wk2i * x0i + wk2r * x0r; y2r = x1r + x2r; y2i = x1i + x2i; y6r = x1r - x2r; y6i = x1i - x2i; x0r = a[4] + a[21]; x0i = a[5] - a[20]; x1r = wk2i * x0r - wk2r * x0i; x1i = wk2i * x0i + wk2r * x0r; x0r = a[12] + a[29]; x0i = a[13] - a[28]; x2r = wk2r * x0r - wk2i * x0i; x2i = wk2r * x0i + wk2i * x0r; y10r = x1r - x2r; y10i = x1i - x2i; y14r = x1r + x2r; y14i = x1i + x2i; x0r = a[6] - a[23]; x0i = a[7] + a[22]; x1r = wk3r * x0r - wk3i * x0i; x1i = wk3r * x0i + wk3i * x0r; x0r = a[14] - a[31]; x0i = a[15] + a[30]; x2r = wk1i * x0r - wk1r * x0i; x2i = wk1i * x0i + wk1r * x0r; y3r = x1r + x2r; y3i = x1i + x2i; y7r = x1r - x2r; y7i = x1i - x2i; x0r = a[6] + a[23]; x0i = a[7] - a[22]; x1r = wk1i * x0r + wk1r * x0i; x1i = wk1i * x0i - wk1r * x0r; x0r = a[14] + a[31]; x0i = a[15] - a[30]; x2r = wk3i * x0r - wk3r * x0i; x2i = wk3i * x0i + wk3r * x0r; y11r = x1r + x2r; y11i = x1i + x2i; y15r = x1r - x2r; y15i = x1i - x2i; x1r = y0r + y2r; x1i = y0i + y2i; x2r = y1r + y3r; x2i = y1i + y3i; a[0] = x1r + x2r; a[1] = x1i + x2i; a[2] = x1r - x2r; a[3] = x1i - x2i; x1r = y0r - y2r; x1i = y0i - y2i; x2r = y1r - y3r; x2i = y1i - y3i; a[4] = x1r - x2i; a[5] = x1i + x2r; a[6] = x1r + x2i; a[7] = x1i - x2r; x1r = y4r - y6i; x1i = y4i + y6r; x0r = y5r - y7i; x0i = y5i + y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[8] = x1r + x2r; a[9] = x1i + x2i; a[10] = x1r - x2r; a[11] = x1i - x2i; x1r = y4r + y6i; x1i = y4i - y6r; x0r = y5r + y7i; x0i = y5i - y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[12] = x1r - x2i; a[13] = x1i + x2r; a[14] = x1r + x2i; a[15] = x1i - x2r; x1r = y8r + y10r; x1i = y8i + y10i; x2r = y9r - y11r; x2i = y9i - y11i; a[16] = x1r + x2r; a[17] = x1i + x2i; a[18] = x1r - x2r; a[19] = x1i - x2i; x1r = y8r - y10r; x1i = y8i - y10i; x2r = y9r + y11r; x2i = y9i + y11i; a[20] = x1r - x2i; a[21] = x1i + x2r; a[22] = x1r + x2i; a[23] = x1i - x2r; x1r = y12r - y14i; x1i = y12i + y14r; x0r = y13r + y15i; x0i = y13i - y15r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[24] = x1r + x2r; a[25] = x1i + x2i; a[26] = x1r - x2r; a[27] = x1i - x2i; x1r = y12r + y14i; x1i = y12i - y14r; x0r = y13r - y15i; x0i = y13i + y15r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[28] = x1r - x2i; a[29] = x1i + x2r; a[30] = x1r + x2i; a[31] = x1i - x2r; } void cftf081(double *a, double *w) { double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; wn4r = w[1]; x0r = a[0] + a[8]; x0i = a[1] + a[9]; x1r = a[0] - a[8]; x1i = a[1] - a[9]; x2r = a[4] + a[12]; x2i = a[5] + a[13]; x3r = a[4] - a[12]; x3i = a[5] - a[13]; y0r = x0r + x2r; y0i = x0i + x2i; y2r = x0r - x2r; y2i = x0i - x2i; y1r = x1r - x3i; y1i = x1i + x3r; y3r = x1r + x3i; y3i = x1i - x3r; x0r = a[2] + a[10]; x0i = a[3] + a[11]; x1r = a[2] - a[10]; x1i = a[3] - a[11]; x2r = a[6] + a[14]; x2i = a[7] + a[15]; x3r = a[6] - a[14]; x3i = a[7] - a[15]; y4r = x0r + x2r; y4i = x0i + x2i; y6r = x0r - x2r; y6i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; x2r = x1r + x3i; x2i = x1i - x3r; y5r = wn4r * (x0r - x0i); y5i = wn4r * (x0r + x0i); y7r = wn4r * (x2r - x2i); y7i = wn4r * (x2r + x2i); a[8] = y1r + y5r; a[9] = y1i + y5i; a[10] = y1r - y5r; a[11] = y1i - y5i; a[12] = y3r - y7i; a[13] = y3i + y7r; a[14] = y3r + y7i; a[15] = y3i - y7r; a[0] = y0r + y4r; a[1] = y0i + y4i; a[2] = y0r - y4r; a[3] = y0i - y4i; a[4] = y2r - y6i; a[5] = y2i + y6r; a[6] = y2r + y6i; a[7] = y2i - y6r; } void cftf082(double *a, double *w) { double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; wn4r = w[1]; wk1r = w[2]; wk1i = w[3]; y0r = a[0] - a[9]; y0i = a[1] + a[8]; y1r = a[0] + a[9]; y1i = a[1] - a[8]; x0r = a[4] - a[13]; x0i = a[5] + a[12]; y2r = wn4r * (x0r - x0i); y2i = wn4r * (x0i + x0r); x0r = a[4] + a[13]; x0i = a[5] - a[12]; y3r = wn4r * (x0r - x0i); y3i = wn4r * (x0i + x0r); x0r = a[2] - a[11]; x0i = a[3] + a[10]; y4r = wk1r * x0r - wk1i * x0i; y4i = wk1r * x0i + wk1i * x0r; x0r = a[2] + a[11]; x0i = a[3] - a[10]; y5r = wk1i * x0r - wk1r * x0i; y5i = wk1i * x0i + wk1r * x0r; x0r = a[6] - a[15]; x0i = a[7] + a[14]; y6r = wk1i * x0r - wk1r * x0i; y6i = wk1i * x0i + wk1r * x0r; x0r = a[6] + a[15]; x0i = a[7] - a[14]; y7r = wk1r * x0r - wk1i * x0i; y7i = wk1r * x0i + wk1i * x0r; x0r = y0r + y2r; x0i = y0i + y2i; x1r = y4r + y6r; x1i = y4i + y6i; a[0] = x0r + x1r; a[1] = x0i + x1i; a[2] = x0r - x1r; a[3] = x0i - x1i; x0r = y0r - y2r; x0i = y0i - y2i; x1r = y4r - y6r; x1i = y4i - y6i; a[4] = x0r - x1i; a[5] = x0i + x1r; a[6] = x0r + x1i; a[7] = x0i - x1r; x0r = y1r - y3i; x0i = y1i + y3r; x1r = y5r - y7r; x1i = y5i - y7i; a[8] = x0r + x1r; a[9] = x0i + x1i; a[10] = x0r - x1r; a[11] = x0i - x1i; x0r = y1r + y3i; x0i = y1i - y3r; x1r = y5r + y7r; x1i = y5i + y7i; a[12] = x0r - x1i; a[13] = x0i + x1r; a[14] = x0r + x1i; a[15] = x0i - x1r; } void cftf040(double *a) { double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[4]; x0i = a[1] + a[5]; x1r = a[0] - a[4]; x1i = a[1] - a[5]; x2r = a[2] + a[6]; x2i = a[3] + a[7]; x3r = a[2] - a[6]; x3i = a[3] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x1r - x3i; a[3] = x1i + x3r; a[4] = x0r - x2r; a[5] = x0i - x2i; a[6] = x1r + x3i; a[7] = x1i - x3r; } void cftb040(double *a) { double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[4]; x0i = a[1] + a[5]; x1r = a[0] - a[4]; x1i = a[1] - a[5]; x2r = a[2] + a[6]; x2i = a[3] + a[7]; x3r = a[2] - a[6]; x3i = a[3] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x1r + x3i; a[3] = x1i - x3r; a[4] = x0r - x2r; a[5] = x0i - x2i; a[6] = x1r - x3i; a[7] = x1i + x3r; } void cftx020(double *a) { double x0r, x0i; x0r = a[0] - a[2]; x0i = a[1] - a[3]; a[0] += a[2]; a[1] += a[3]; a[2] = x0r; a[3] = x0i; } void rftfsub(int n, double *a, int nc, double *c) { int j, k, kk, ks, m; double wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5 - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } void rftbsub(int n, double *a, int nc, double *c) { int j, k, kk, ks, m; double wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = 0.5 - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr + wki * xi; yi = wkr * xi - wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } void dctsub(int n, double *a, int nc, double *c) { int j, k, kk, ks, m; double wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[j] - wkr * a[k]; a[j] = wkr * a[j] + wki * a[k]; a[k] = xr; } a[m] *= c[0]; } void dstsub(int n, double *a, int nc, double *c) { int j, k, kk, ks, m; double wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[k] - wkr * a[j]; a[k] = wkr * a[k] + wki * a[j]; a[j] = xr; } a[m] *= c[0]; } ================================================ FILE: libtts/Modules/Lib/World/src/harvest.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // F0 estimation based on Harvest. //----------------------------------------------------------------------------- #include "world/harvest.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/fft.h" #include "world/matlabfunctions.h" //----------------------------------------------------------------------------- // struct for RawEventByHarvest() // "negative" means "zero-crossing point going from positive to negative" // "positive" means "zero-crossing point going from negative to positive" //----------------------------------------------------------------------------- typedef struct { double *negative_interval_locations; double *negative_intervals; int number_of_negatives; double *positive_interval_locations; double *positive_intervals; int number_of_positives; double *peak_interval_locations; double *peak_intervals; int number_of_peaks; double *dip_interval_locations; double *dip_intervals; int number_of_dips; } ZeroCrossings; namespace { //----------------------------------------------------------------------------- // Since the waveform of beginning and ending after decimate include noise, // the input waveform is extended. This is the processing for the // compatibility with MATLAB version. //----------------------------------------------------------------------------- static void GetWaveformAndSpectrumSub(const double *x, int x_length, int y_length, double actual_fs, int decimation_ratio, double *y) { if (decimation_ratio == 1) { for (int i = 0; i < x_length; ++i) y[i] = x[i]; return; } int lag = static_cast(ceil(140.0 / decimation_ratio) * decimation_ratio); int new_x_length = x_length + lag * 2; double *new_y = new double[new_x_length]; for (int i = 0; i < new_x_length; ++i) new_y[i] = 0.0; double *new_x = new double[new_x_length]; for (int i = 0; i < lag; ++i) new_x[i] = x[0]; for (int i = lag; i < lag + x_length; ++i) new_x[i] = x[i - lag]; for (int i = lag + x_length; i < new_x_length; ++i) new_x[i] = x[x_length - 1]; decimate(new_x, new_x_length, decimation_ratio, new_y); for (int i = 0; i < y_length; ++i) y[i] = new_y[lag / decimation_ratio + i]; delete[] new_x; delete[] new_y; } //----------------------------------------------------------------------------- // GetWaveformAndSpectrum() calculates the downsampled signal and its spectrum //----------------------------------------------------------------------------- static void GetWaveformAndSpectrum(const double *x, int x_length, int y_length, double actual_fs, int fft_size, int decimation_ratio, double *y, fft_complex *y_spectrum) { // Initialization for (int i = 0; i < fft_size; ++i) y[i] = 0.0; // Processing for the compatibility with MATLAB version GetWaveformAndSpectrumSub(x, x_length, y_length, actual_fs, decimation_ratio, y); // Removal of the DC component (y = y - mean value of y) double mean_y = 0.0; for (int i = 0; i < y_length; ++i) mean_y += y[i]; mean_y /= y_length; for (int i = 0; i < y_length; ++i) y[i] -= mean_y; for (int i = y_length; i < fft_size; ++i) y[i] = 0.0; fft_plan forwardFFT = fft_plan_dft_r2c_1d(fft_size, y, y_spectrum, FFT_ESTIMATE); fft_execute(forwardFFT); fft_destroy_plan(forwardFFT); } //----------------------------------------------------------------------------- // GetFilteredSignal() calculates the signal that is the convolution of the // input signal and band-pass filter. //----------------------------------------------------------------------------- static void GetFilteredSignal(double boundary_f0, int fft_size, double fs, const fft_complex *y_spectrum, int y_length, double *filtered_signal) { int filter_length_half = matlab_round(fs / boundary_f0 * 2.0); double *band_pass_filter = new double[fft_size]; NuttallWindow(filter_length_half * 2 + 1, band_pass_filter); for (int i = -filter_length_half; i <= filter_length_half; ++i) band_pass_filter[i + filter_length_half] *= cos(2 * world::kPi * boundary_f0 * i / fs); for (int i = filter_length_half * 2 + 1; i < fft_size; ++i) band_pass_filter[i] = 0.0; fft_complex *band_pass_filter_spectrum = new fft_complex[fft_size]; fft_plan forwardFFT = fft_plan_dft_r2c_1d(fft_size, band_pass_filter, band_pass_filter_spectrum, FFT_ESTIMATE); fft_execute(forwardFFT); // Convolution double tmp = y_spectrum[0][0] * band_pass_filter_spectrum[0][0] - y_spectrum[0][1] * band_pass_filter_spectrum[0][1]; band_pass_filter_spectrum[0][1] = y_spectrum[0][0] * band_pass_filter_spectrum[0][1] + y_spectrum[0][1] * band_pass_filter_spectrum[0][0]; band_pass_filter_spectrum[0][0] = tmp; for (int i = 1; i <= fft_size / 2; ++i) { tmp = y_spectrum[i][0] * band_pass_filter_spectrum[i][0] - y_spectrum[i][1] * band_pass_filter_spectrum[i][1]; band_pass_filter_spectrum[i][1] = y_spectrum[i][0] * band_pass_filter_spectrum[i][1] + y_spectrum[i][1] * band_pass_filter_spectrum[i][0]; band_pass_filter_spectrum[i][0] = tmp; band_pass_filter_spectrum[fft_size - i - 1][0] = band_pass_filter_spectrum[i][0]; band_pass_filter_spectrum[fft_size - i - 1][1] = band_pass_filter_spectrum[i][1]; } fft_plan inverseFFT = fft_plan_dft_c2r_1d(fft_size, band_pass_filter_spectrum, filtered_signal, FFT_ESTIMATE); fft_execute(inverseFFT); // Compensation of the delay. int index_bias = filter_length_half + 1; for (int i = 0; i < y_length; ++i) filtered_signal[i] = filtered_signal[i + index_bias]; fft_destroy_plan(inverseFFT); fft_destroy_plan(forwardFFT); delete[] band_pass_filter_spectrum; delete[] band_pass_filter; } //----------------------------------------------------------------------------- // CheckEvent() returns 1, provided that the input value is over 1. // This function is for RawEventByDio(). //----------------------------------------------------------------------------- static inline int CheckEvent(int x) { return x > 0 ? 1 : 0; } //----------------------------------------------------------------------------- // ZeroCrossingEngine() calculates the zero crossing points from positive to // negative. //----------------------------------------------------------------------------- static int ZeroCrossingEngine(const double *filtered_signal, int y_length, double fs, double *interval_locations, double *intervals) { int *negative_going_points = new int[y_length]; for (int i = 0; i < y_length - 1; ++i) negative_going_points[i] = 0.0 < filtered_signal[i] && filtered_signal[i + 1] <= 0.0 ? i + 1 : 0; negative_going_points[y_length - 1] = 0; int *edges = new int[y_length]; int count = 0; for (int i = 0; i < y_length; ++i) if (negative_going_points[i] > 0) edges[count++] = negative_going_points[i]; if (count < 2) { delete[] edges; delete[] negative_going_points; return 0; } double *fine_edges = new double[count]; for (int i = 0; i < count; ++i) fine_edges[i] = edges[i] - filtered_signal[edges[i] - 1] / (filtered_signal[edges[i]] - filtered_signal[edges[i] - 1]); for (int i = 0; i < count - 1; ++i) { intervals[i] = fs / (fine_edges[i + 1] - fine_edges[i]); interval_locations[i] = (fine_edges[i] + fine_edges[i + 1]) / 2.0 / fs; } delete[] fine_edges; delete[] edges; delete[] negative_going_points; return count - 1; } //----------------------------------------------------------------------------- // GetFourZeroCrossingIntervals() calculates four zero-crossing intervals. // (1) Zero-crossing going from negative to positive. // (2) Zero-crossing going from positive to negative. // (3) Peak, and (4) dip. (3) and (4) are calculated from the zero-crossings of // the differential of waveform. //----------------------------------------------------------------------------- static void GetFourZeroCrossingIntervals(double *filtered_signal, int y_length, double actual_fs, ZeroCrossings *zero_crossings) { int maximum_number = y_length; zero_crossings->negative_interval_locations = new double[maximum_number]; zero_crossings->positive_interval_locations = new double[maximum_number]; zero_crossings->peak_interval_locations = new double[maximum_number]; zero_crossings->dip_interval_locations = new double[maximum_number]; zero_crossings->negative_intervals = new double[maximum_number]; zero_crossings->positive_intervals = new double[maximum_number]; zero_crossings->peak_intervals = new double[maximum_number]; zero_crossings->dip_intervals = new double[maximum_number]; zero_crossings->number_of_negatives = ZeroCrossingEngine(filtered_signal, y_length, actual_fs, zero_crossings->negative_interval_locations, zero_crossings->negative_intervals); for (int i = 0; i < y_length; ++i) filtered_signal[i] = -filtered_signal[i]; zero_crossings->number_of_positives = ZeroCrossingEngine(filtered_signal, y_length, actual_fs, zero_crossings->positive_interval_locations, zero_crossings->positive_intervals); for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] = filtered_signal[i] - filtered_signal[i + 1]; zero_crossings->number_of_peaks = ZeroCrossingEngine(filtered_signal, y_length - 1, actual_fs, zero_crossings->peak_interval_locations, zero_crossings->peak_intervals); for (int i = 0; i < y_length - 1; ++i) filtered_signal[i] = -filtered_signal[i]; zero_crossings->number_of_dips = ZeroCrossingEngine(filtered_signal, y_length - 1, actual_fs, zero_crossings->dip_interval_locations, zero_crossings->dip_intervals); } static void GetF0CandidateContourSub(const double * const *interpolated_f0_set, int f0_length, double f0_floor, double f0_ceil, double boundary_f0, double *f0_candidate) { double upper = boundary_f0 * 1.1; double lower = boundary_f0 * 0.9; for (int i = 0; i < f0_length; ++i) { f0_candidate[i] = (interpolated_f0_set[0][i] + interpolated_f0_set[1][i] + interpolated_f0_set[2][i] + interpolated_f0_set[3][i]) / 4.0; if (f0_candidate[i] > upper || f0_candidate[i] < lower || f0_candidate[i] > f0_ceil || f0_candidate[i] < f0_floor) f0_candidate[i] = 0.0; } } //----------------------------------------------------------------------------- // GetF0CandidateContour() calculates the F0 candidate contour in 1-ch signal. // Calculation of F0 candidates is carried out in GetF0CandidatesSub(). //----------------------------------------------------------------------------- static void GetF0CandidateContour(const ZeroCrossings *zero_crossings, double boundary_f0, double f0_floor, double f0_ceil, const double *temporal_positions, int f0_length, double *f0_candidate) { if (0 == CheckEvent(zero_crossings->number_of_negatives - 2) * CheckEvent(zero_crossings->number_of_positives - 2) * CheckEvent(zero_crossings->number_of_peaks - 2) * CheckEvent(zero_crossings->number_of_dips - 2)) { for (int i = 0; i < f0_length; ++i) f0_candidate[i] = 0.0; return; } double *interpolated_f0_set[4]; for (int i = 0; i < 4; ++i) interpolated_f0_set[i] = new double[f0_length]; interp1(zero_crossings->negative_interval_locations, zero_crossings->negative_intervals, zero_crossings->number_of_negatives, temporal_positions, f0_length, interpolated_f0_set[0]); interp1(zero_crossings->positive_interval_locations, zero_crossings->positive_intervals, zero_crossings->number_of_positives, temporal_positions, f0_length, interpolated_f0_set[1]); interp1(zero_crossings->peak_interval_locations, zero_crossings->peak_intervals, zero_crossings->number_of_peaks, temporal_positions, f0_length, interpolated_f0_set[2]); interp1(zero_crossings->dip_interval_locations, zero_crossings->dip_intervals, zero_crossings->number_of_dips, temporal_positions, f0_length, interpolated_f0_set[3]); GetF0CandidateContourSub(interpolated_f0_set, f0_length, f0_floor, f0_ceil, boundary_f0, f0_candidate); for (int i = 0; i < 4; ++i) delete[] interpolated_f0_set[i]; } //----------------------------------------------------------------------------- // DestroyZeroCrossings() frees the memory of array in the struct //----------------------------------------------------------------------------- static void DestroyZeroCrossings(ZeroCrossings *zero_crossings) { delete[] zero_crossings->negative_interval_locations; delete[] zero_crossings->positive_interval_locations; delete[] zero_crossings->peak_interval_locations; delete[] zero_crossings->dip_interval_locations; delete[] zero_crossings->negative_intervals; delete[] zero_crossings->positive_intervals; delete[] zero_crossings->peak_intervals; delete[] zero_crossings->dip_intervals; } //----------------------------------------------------------------------------- // GetF0CandidateFromRawEvent() f0 candidate contour in 1-ch signal //----------------------------------------------------------------------------- static void GetF0CandidateFromRawEvent(double boundary_f0, double fs, const fft_complex *y_spectrum, int y_length, int fft_size, double f0_floor, double f0_ceil, const double *temporal_positions, int f0_length, double *f0_candidate) { double *filtered_signal = new double[fft_size]; GetFilteredSignal(boundary_f0, fft_size, fs, y_spectrum, y_length, filtered_signal); ZeroCrossings zero_crossings = { 0 }; GetFourZeroCrossingIntervals(filtered_signal, y_length, fs, &zero_crossings); GetF0CandidateContour(&zero_crossings, boundary_f0, f0_floor, f0_ceil, temporal_positions, f0_length, f0_candidate); DestroyZeroCrossings(&zero_crossings); delete[] filtered_signal; } //----------------------------------------------------------------------------- // GetRawF0Candidates() calculates f0 candidates in all channels. //----------------------------------------------------------------------------- static void GetRawF0Candidates(const double *boundary_f0_list, int number_of_bands, double actual_fs, int y_length, const double *temporal_positions, int f0_length, const fft_complex *y_spectrum, int fft_size, double f0_floor, double f0_ceil, double **raw_f0_candidates) { for (int i = 0; i < number_of_bands; ++i) GetF0CandidateFromRawEvent(boundary_f0_list[i], actual_fs, y_spectrum, y_length, fft_size, f0_floor, f0_ceil, temporal_positions, f0_length, raw_f0_candidates[i]); } //----------------------------------------------------------------------------- // DetectF0CandidatesSub1() calculates VUV areas. //----------------------------------------------------------------------------- static int DetectOfficialF0CandidatesSub1(const int *vuv, int number_of_channels, int *st, int *ed) { int number_of_voiced_sections = 0; int tmp; for (int i = 1; i < number_of_channels; ++i) { tmp = vuv[i] - vuv[i - 1]; if (tmp == 1) st[number_of_voiced_sections] = i; if (tmp == -1) ed[number_of_voiced_sections++] = i; } return number_of_voiced_sections; } //----------------------------------------------------------------------------- // DetectOfficialF0CandidatesSub2() calculates F0 candidates in a frame //----------------------------------------------------------------------------- static int DetectOfficialF0CandidatesSub2(const int *vuv, const double * const *raw_f0_candidates, int index, int number_of_voiced_sections, const int *st, const int *ed, int max_candidates, double *f0_list) { int number_of_candidates = 0; double tmp_f0; for (int i = 0; i < number_of_voiced_sections; ++i) { if (ed[i] - st[i] < 10) continue; tmp_f0 = 0.0; for (int j = st[i]; j < ed[i]; ++j) tmp_f0 += raw_f0_candidates[j][index]; tmp_f0 /= (ed[i] - st[i]); f0_list[number_of_candidates++] = tmp_f0; } for (int i = number_of_candidates; i < max_candidates; ++i) f0_list[i] = 0.0; return number_of_candidates; } //----------------------------------------------------------------------------- // DetectOfficialF0Candidates() detectes F0 candidates from multi-channel // candidates. //----------------------------------------------------------------------------- static int DetectOfficialF0Candidates(const double * const * raw_f0_candidates, int number_of_channels, int f0_length, int max_candidates, double **f0_candidates) { int number_of_candidates = 0; int *vuv = new int[number_of_channels]; int *st = new int[number_of_channels]; int *ed = new int[number_of_channels]; int number_of_voiced_sections; for (int i = 0; i < f0_length; ++i) { for (int j = 0; j < number_of_channels; ++j) vuv[j] = raw_f0_candidates[j][i] > 0 ? 1 : 0; vuv[0] = vuv[number_of_channels - 1] = 0; number_of_voiced_sections = DetectOfficialF0CandidatesSub1(vuv, number_of_channels, st, ed); number_of_candidates = MyMaxInt(number_of_candidates, DetectOfficialF0CandidatesSub2(vuv, raw_f0_candidates, i, number_of_voiced_sections, st, ed, max_candidates, f0_candidates[i])); } delete[] vuv; delete[] st; delete[] ed; return number_of_candidates; } //----------------------------------------------------------------------------- // OverlapF0Candidates() spreads the candidates to anteroposterior frames. //----------------------------------------------------------------------------- static void OverlapF0Candidates(int f0_length, int number_of_candidates, double **f0_candidates) { int n = 3; for (int i = 1; i <= n; ++i) for (int j = 0; j < number_of_candidates; ++j) { for (int k = i; k < f0_length; ++k) f0_candidates[k][j + (number_of_candidates * i)] = f0_candidates[k - i][j]; for (int k = 0; k < f0_length - i; ++k) f0_candidates[k][j + (number_of_candidates * (i + n))] = f0_candidates[k + i][j]; } } //----------------------------------------------------------------------------- // GetBaseIndex() calculates the temporal positions for windowing. //----------------------------------------------------------------------------- static void GetBaseIndex(double current_position, const double *base_time, int base_time_length, double fs, int *base_index) { // First-aid treatment int basic_index = matlab_round((current_position + base_time[0]) * fs + 0.001); for (int i = 0; i < base_time_length; ++i) base_index[i] = basic_index + i; } //----------------------------------------------------------------------------- // GetMainWindow() generates the window function. //----------------------------------------------------------------------------- static void GetMainWindow(double current_position, const int *base_index, int base_time_length, double fs, double window_length_in_time, double *main_window) { double tmp = 0.0; for (int i = 0; i < base_time_length; ++i) { tmp = (base_index[i] - 1.0) / fs - current_position; main_window[i] = 0.42 + 0.5 * cos(2.0 * world::kPi * tmp / window_length_in_time) + 0.08 * cos(4.0 * world::kPi * tmp / window_length_in_time); } } //----------------------------------------------------------------------------- // GetDiffWindow() generates the differentiated window. // Diff means differential. //----------------------------------------------------------------------------- static void GetDiffWindow(const double *main_window, int base_time_length, double *diff_window) { diff_window[0] = -main_window[1] / 2.0; for (int i = 1; i < base_time_length - 1; ++i) diff_window[i] = -(main_window[i + 1] - main_window[i - 1]) / 2.0; diff_window[base_time_length - 1] = main_window[base_time_length - 2] / 2.0; } //----------------------------------------------------------------------------- // GetSpectra() calculates two spectra of the waveform windowed by windows // (main window and diff window). //----------------------------------------------------------------------------- static void GetSpectra(const double *x, int x_length, int fft_size, const int *base_index, const double *main_window, const double *diff_window, int base_time_length, const ForwardRealFFT *forward_real_fft, fft_complex *main_spectrum, fft_complex *diff_spectrum) { int *safe_index = new int[base_time_length]; for (int i = 0; i < base_time_length; ++i) safe_index[i] = MyMaxInt(0, MyMinInt(x_length - 1, base_index[i] - 1)); for (int i = 0; i < base_time_length; ++i) forward_real_fft->waveform[i] = x[safe_index[i]] * main_window[i]; for (int i = base_time_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { main_spectrum[i][0] = forward_real_fft->spectrum[i][0]; main_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } for (int i = 0; i < base_time_length; ++i) forward_real_fft->waveform[i] = x[safe_index[i]] * diff_window[i]; for (int i = base_time_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { diff_spectrum[i][0] = forward_real_fft->spectrum[i][0]; diff_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } delete[] safe_index; } static void FixF0(const double *power_spectrum, const double *numerator_i, int fft_size, double fs, double current_f0, int number_of_harmonics, double *refined_f0, double *score) { double *amplitude_list = new double[number_of_harmonics]; double *instantaneous_frequency_list = new double[number_of_harmonics]; int index; for (int i = 0; i < number_of_harmonics; ++i) { index = matlab_round(current_f0 * fft_size / fs * (i + 1)); instantaneous_frequency_list[i] = power_spectrum[index] == 0.0 ? 0.0 : static_cast(index) * fs / fft_size + numerator_i[index] / power_spectrum[index] * fs / 2.0 / world::kPi; amplitude_list[i] = sqrt(power_spectrum[index]); } double denominator = 0.0; double numerator = 0.0; *score = 0.0; for (int i = 0; i < number_of_harmonics; ++i) { numerator += amplitude_list[i] * instantaneous_frequency_list[i]; denominator += amplitude_list[i] * (i + 1.0); *score += fabs((instantaneous_frequency_list[i] / (i + 1.0) - current_f0) / current_f0); } *refined_f0 = numerator / (denominator + world::kMySafeGuardMinimum); *score = 1.0 / (*score / number_of_harmonics + world::kMySafeGuardMinimum); delete[] amplitude_list; delete[] instantaneous_frequency_list; } //----------------------------------------------------------------------------- // GetMeanF0() calculates the instantaneous frequency. //----------------------------------------------------------------------------- static void GetMeanF0(const double *x, int x_length, double fs, double current_position, double current_f0, int fft_size, double window_length_in_time, const double *base_time, int base_time_length, double *refined_f0, double *refined_score) { ForwardRealFFT forward_real_fft = { 0 }; InitializeForwardRealFFT(fft_size, &forward_real_fft); fft_complex *main_spectrum = new fft_complex[fft_size]; fft_complex *diff_spectrum = new fft_complex[fft_size]; int *base_index = new int[base_time_length]; double *main_window = new double[base_time_length]; double *diff_window = new double[base_time_length]; GetBaseIndex(current_position, base_time, base_time_length, fs, base_index); GetMainWindow(current_position, base_index, base_time_length, fs, window_length_in_time, main_window); GetDiffWindow(main_window, base_time_length, diff_window); GetSpectra(x, x_length, fft_size, base_index, main_window, diff_window, base_time_length, &forward_real_fft, main_spectrum, diff_spectrum); double *power_spectrum = new double[fft_size / 2 + 1]; double *numerator_i = new double[fft_size / 2 + 1]; for (int j = 0; j <= fft_size / 2; ++j) { numerator_i[j] = main_spectrum[j][0] * diff_spectrum[j][1] - main_spectrum[j][1] * diff_spectrum[j][0]; power_spectrum[j] = main_spectrum[j][0] * main_spectrum[j][0] + main_spectrum[j][1] * main_spectrum[j][1]; } int number_of_harmonics = MyMinInt(static_cast(fs / 2.0 / current_f0), 6); FixF0(power_spectrum, numerator_i, fft_size, fs, current_f0, number_of_harmonics, refined_f0, refined_score); delete[] diff_spectrum; delete[] diff_window; delete[] main_window; delete[] base_index; delete[] numerator_i; delete[] power_spectrum; delete[] main_spectrum; DestroyForwardRealFFT(&forward_real_fft); } //----------------------------------------------------------------------------- // GetRefinedF0() calculates F0 and its score based on instantaneous frequency. //----------------------------------------------------------------------------- static void GetRefinedF0(const double *x, int x_length, double fs, double current_position, double current_f0, double f0_floor, double f0_ceil, double *refined_f0, double *refined_score) { if (current_f0 <= 0.0) { *refined_f0 = 0.0; *refined_score = 0.0; return; } int half_window_length = static_cast(1.5 * fs / current_f0 + 1.0); double window_length_in_time = (2.0 * half_window_length + 1.0) / fs; double *base_time = new double[half_window_length * 2 + 1]; for (int i = 0; i < half_window_length * 2 + 1; i++) base_time[i] = (-half_window_length + i) / fs; int fft_size = static_cast(pow(2.0, 2.0 + static_cast(log(half_window_length * 2.0 + 1.0) / world::kLog2))); GetMeanF0(x, x_length, fs, current_position, current_f0, fft_size, window_length_in_time, base_time, half_window_length * 2 + 1, refined_f0, refined_score); if (*refined_f0 < f0_floor || *refined_f0 > f0_ceil || *refined_score < 2.5) { *refined_f0 = 0.0; *refined_score = 0.0; } delete[] base_time; } //----------------------------------------------------------------------------- // RefineF0() modifies the F0 by instantaneous frequency. //----------------------------------------------------------------------------- static void RefineF0Candidates(const double *x, int x_length, double fs, const double *temporal_positions, int f0_length, int max_candidates, double f0_floor, double f0_ceil, double **refined_f0_candidates, double **f0_scores) { for (int i = 0; i < f0_length; i++) for (int j = 0; j < max_candidates; ++j) GetRefinedF0(x, x_length, fs, temporal_positions[i], refined_f0_candidates[i][j], f0_floor, f0_ceil, &refined_f0_candidates[i][j], &f0_scores[i][j]); } //----------------------------------------------------------------------------- // SelectBestF0() obtains the nearlest F0 in reference_f0. //----------------------------------------------------------------------------- static double SelectBestF0(double reference_f0, const double *f0_candidates, int number_of_candidates, double allowed_range, double *best_error) { double best_f0 = 0.0; *best_error = allowed_range; double tmp; for (int i = 0; i < number_of_candidates; ++i) { tmp = fabs(reference_f0 - f0_candidates[i]) / reference_f0; if (tmp > *best_error) continue; best_f0 = f0_candidates[i]; *best_error = tmp; } return best_f0; } static void RemoveUnreliableCandidatesSub(int i, int j, const double * const *tmp_f0_candidates, int number_of_candidates, double **f0_candidates, double **f0_scores) { double reference_f0 = f0_candidates[i][j]; double error1, error2, min_error; double threshold = 0.05; if (reference_f0 == 0) return; SelectBestF0(reference_f0, tmp_f0_candidates[i + 1], number_of_candidates, 1.0, &error1); SelectBestF0(reference_f0, tmp_f0_candidates[i - 1], number_of_candidates, 1.0, &error2); min_error = MyMinDouble(error1, error2); if (min_error <= threshold) return; f0_candidates[i][j] = 0; f0_scores[i][j] = 0; } //----------------------------------------------------------------------------- // RemoveUnreliableCandidates(). //----------------------------------------------------------------------------- static void RemoveUnreliableCandidates(int f0_length, int number_of_candidates, double **f0_candidates, double **f0_scores) { double **tmp_f0_candidates = new double *[f0_length]; for (int i = 0; i < f0_length; ++i) tmp_f0_candidates[i] = new double[number_of_candidates]; for (int i = 0; i < f0_length; ++i) for (int j = 0; j < number_of_candidates; ++j) tmp_f0_candidates[i][j] = f0_candidates[i][j]; for (int i = 1; i < f0_length - 1; ++i) for (int j = 0; j < number_of_candidates; ++j) RemoveUnreliableCandidatesSub(i, j, tmp_f0_candidates, number_of_candidates, f0_candidates, f0_scores); for (int i = 0; i < f0_length; ++i) delete[] tmp_f0_candidates[i]; delete[] tmp_f0_candidates; } //----------------------------------------------------------------------------- // SearchF0Base() gets the F0 with the highest score. //----------------------------------------------------------------------------- static void SearchF0Base(const double * const *f0_candidates, const double * const *f0_scores, int f0_length, int number_of_candidates, double *base_f0_contour) { double tmp_best_score; for (int i = 0; i < f0_length; ++i) { base_f0_contour[i] = tmp_best_score = 0.0; for (int j = 0; j < number_of_candidates; ++j) if (f0_scores[i][j] > tmp_best_score) { base_f0_contour[i] = f0_candidates[i][j]; tmp_best_score = f0_scores[i][j]; } } } //----------------------------------------------------------------------------- // Step 1: Rapid change of F0 contour is replaced by 0. //----------------------------------------------------------------------------- static void FixStep1(const double *f0_base, int f0_length, double allowed_range, double *f0_step1) { for (int i = 0; i < f0_length; ++i) f0_step1[i] = 0.0; double reference_f0; for (int i = 2; i < f0_length; ++i) { if (f0_base[i] == 0.0) continue; reference_f0 = f0_base[i - 1] * 2 - f0_base[i - 2]; f0_step1[i] = fabs((f0_base[i] - reference_f0) / reference_f0) > allowed_range && fabs((f0_base[i] - f0_base[i - 1])) / f0_base[i - 1] > allowed_range ? 0.0 : f0_base[i]; } } //----------------------------------------------------------------------------- // GetBoundaryList() detects boundaries between voiced and unvoiced sections. //----------------------------------------------------------------------------- static int GetBoundaryList(const double *f0, int f0_length, int *boundary_list) { int number_of_boundaries = 0; int *vuv = new int[f0_length]; for (int i = 0; i < f0_length; ++i) vuv[i] = f0[i] > 0 ? 1 : 0; vuv[0] = vuv[f0_length - 1] = 0; for (int i = 1; i < f0_length; ++i) if (vuv[i] - vuv[i - 1] != 0) { boundary_list[number_of_boundaries] = i - number_of_boundaries % 2; number_of_boundaries++; } delete[] vuv; return number_of_boundaries; } //----------------------------------------------------------------------------- // Step 2: Voiced sections with a short period are removed. //----------------------------------------------------------------------------- static void FixStep2(const double *f0_step1, int f0_length, int voice_range_minimum, double *f0_step2) { for (int i = 0; i < f0_length; ++i) f0_step2[i] = f0_step1[i]; int *boundary_list = new int[f0_length]; int number_of_boundaries = GetBoundaryList(f0_step1, f0_length, boundary_list); for (int i = 0; i < number_of_boundaries / 2; ++i) { if (boundary_list[i * 2 + 1] - boundary_list[i * 2] >= voice_range_minimum) continue; for (int j = boundary_list[i * 2]; j <= boundary_list[(i * 2) + 1]; ++j) f0_step2[j] = 0.0; } delete[] boundary_list; } //----------------------------------------------------------------------------- // GetMultiChannelF0() separates each voiced section into independent channel. //----------------------------------------------------------------------------- static void GetMultiChannelF0(const double *f0, int f0_length, const int *boundary_list, int number_of_boundaries, double **multi_channel_f0) { for (int i = 0; i < number_of_boundaries / 2; ++i) { for (int j = 0; j < boundary_list[i * 2]; ++j) multi_channel_f0[i][j] = 0.0; for (int j = boundary_list[i * 2]; j <= boundary_list[i * 2 + 1]; ++j) multi_channel_f0[i][j] = f0[j]; for (int j = boundary_list[i * 2 + 1] + 1; j < f0_length; ++j) multi_channel_f0[i][j] = 0.0; } } //----------------------------------------------------------------------------- // abs() often causes bugs, an original function is used. //----------------------------------------------------------------------------- static inline int MyAbsInt(int x) { return x > 0 ? x : -x; } //----------------------------------------------------------------------------- // ExtendF0() : The Hand erasing the Space. // The subfunction of Extend(). //----------------------------------------------------------------------------- static int ExtendF0(const double *f0, int f0_length, int origin, int last_point, int shift, const double * const *f0_candidates, int number_of_candidates, double allowed_range, double *extended_f0) { int threshold = 4; double tmp_f0 = extended_f0[origin]; int shifted_origin = origin; int distance = MyAbsInt(last_point - origin); int *index_list = new int[distance + 1]; for (int i = 0; i <= distance; ++i) index_list[i] = origin + shift * i; int count = 0; double dammy; for (int i = 0; i <= distance; ++i) { extended_f0[index_list[i] + shift] = SelectBestF0(tmp_f0, f0_candidates[index_list[i] + shift], number_of_candidates, allowed_range, &dammy); if (extended_f0[index_list[i] + shift] == 0.0) { count++; } else { tmp_f0 = extended_f0[index_list[i] + shift]; count = 0; shifted_origin = index_list[i] + shift; } if (count == threshold) break; } delete[] index_list; return shifted_origin; } //----------------------------------------------------------------------------- // Swap the f0 contour and boundary. // It is used in ExtendSub() and MergeF0(); //----------------------------------------------------------------------------- static void Swap(int index1, int index2, double **f0, int *boundary) { double *tmp_pointer; int tmp_index; tmp_pointer = f0[index1]; f0[index1] = f0[index2]; f0[index2] = tmp_pointer; tmp_index = boundary[index1 * 2]; boundary[index1 * 2] = boundary[index2 * 2]; boundary[index2 * 2] = tmp_index; tmp_index = boundary[index1 * 2 + 1]; boundary[index1 * 2 + 1] = boundary[index2 * 2 + 1]; boundary[index2 * 2 + 1] = tmp_index; } static int ExtendSub(const double * const *extended_f0, const int *boundary_list, int number_of_sections, double **selected_extended_f0, int *selected_boundary_list) { double threshold = 2200.0; int count = 0; double mean_f0 = 0.0; int st, ed; for (int i = 0; i < number_of_sections; ++i) { st = boundary_list[i * 2]; ed = boundary_list[i * 2 + 1]; for (int j = st; j < ed; ++j) mean_f0 += extended_f0[i][j]; mean_f0 /= ed - st; if (threshold / mean_f0 < ed - st) Swap(count++, i, selected_extended_f0, selected_boundary_list); } return count; } //----------------------------------------------------------------------------- // Extend() : The Hand erasing the Space. //----------------------------------------------------------------------------- static int Extend(const double * const *multi_channel_f0, int number_of_sections, int f0_length, const int *boundary_list, const double * const *f0_candidates, int number_of_candidates, double allowed_range, double **extended_f0, int *shifted_boundary_list) { int threshold = 100; for (int i = 0; i < number_of_sections; ++i) { shifted_boundary_list[i * 2 + 1] = ExtendF0(multi_channel_f0[i], f0_length, boundary_list[i * 2 + 1], MyMinInt(f0_length - 2, boundary_list[i * 2 + 1] + threshold), 1, f0_candidates, number_of_candidates, allowed_range, extended_f0[i]); shifted_boundary_list[i * 2] = ExtendF0(multi_channel_f0[i], f0_length, boundary_list[i * 2], MyMaxInt(1, boundary_list[i * 2] - threshold), -1, f0_candidates, number_of_candidates, allowed_range, extended_f0[i]); } return ExtendSub(multi_channel_f0, shifted_boundary_list, number_of_sections, extended_f0, shifted_boundary_list); } //----------------------------------------------------------------------------- // Indices are sorted. //----------------------------------------------------------------------------- static void MakeSortedOrder(const int *boundary_list, int number_of_sections, int *order) { for (int i = 0; i < number_of_sections; ++i) order[i] = i; int tmp; for (int i = 1; i < number_of_sections; ++i) for (int j = i - 1; j >= 0; --j) if (boundary_list[order[j] * 2] > boundary_list[order[i] * 2]) { tmp = order[i]; order[i] = order[j]; order[j] = tmp; } else { break; } } //----------------------------------------------------------------------------- // Serach the highest score with the candidate F0. //----------------------------------------------------------------------------- static double SearchScore(double f0, const double *f0_candidates, const double *f0_scores, int number_of_candidates) { double score = 0.0; for (int i = 0; i < number_of_candidates; ++i) if (f0 == f0_candidates[i] && score < f0_scores[i]) score = f0_scores[i]; return score; } //----------------------------------------------------------------------------- // Subfunction of MergeF0() //----------------------------------------------------------------------------- static int MergeF0Sub(const double *f0_1, int f0_length, int st1, int ed1, const double *f0_2, int st2, int ed2, const double * const *f0_candidates, const double * const *f0_scores, int number_of_candidates, double *merged_f0) { if (st1 <= st2 && ed1 >= ed2) return ed1; double score1 = 0.0; double score2 = 0.0; for (int i = st2; i <= ed1; ++i) { score1 += SearchScore(f0_1[i], f0_candidates[i], f0_scores[i], number_of_candidates); score2 += SearchScore(f0_2[i], f0_candidates[i], f0_scores[i], number_of_candidates); } if (score1 > score2) for (int i = ed1; i <= ed2; ++i) merged_f0[i] = f0_2[i]; else for (int i = st2; i <= ed2; ++i) merged_f0[i] = f0_2[i]; return ed2; } //----------------------------------------------------------------------------- // Overlapped F0 contours are merged by the likability score. //----------------------------------------------------------------------------- static void MergeF0(const double * const *multi_channel_f0, int *boundary_list, int number_of_channels, int f0_length, const double * const *f0_candidates, const double * const *f0_scores, int number_of_candidates, double *merged_f0) { int *order = new int[number_of_channels]; MakeSortedOrder(boundary_list, number_of_channels, order); for (int i = 0; i < f0_length; ++i) merged_f0[i] = multi_channel_f0[0][i]; for (int i = 1; i < number_of_channels; ++i) if (boundary_list[order[i] * 2] - boundary_list[1] > 0) { for (int j = boundary_list[order[i] * 2]; j <= boundary_list[order[i] * 2 + 1]; ++j) merged_f0[j] = multi_channel_f0[order[i]][j]; boundary_list[0] = boundary_list[order[i] * 2]; boundary_list[1] = boundary_list[order[i] * 2 + 1]; } else { boundary_list[1] = MergeF0Sub(merged_f0, f0_length, boundary_list[0], boundary_list[1], multi_channel_f0[order[i]], boundary_list[order[i] * 2], boundary_list[order[i] * 2 + 1], f0_candidates, f0_scores, number_of_candidates, merged_f0); } delete[] order; } //----------------------------------------------------------------------------- // Step 3: Voiced sections are extended based on the continuity of F0 contour //----------------------------------------------------------------------------- static void FixStep3(const double *f0_step2, int f0_length, int number_of_candidates, const double * const *f0_candidates, double allowed_range, const double * const *f0_scores, double *f0_step3) { for (int i = 0; i < f0_length; ++i) f0_step3[i] = f0_step2[i]; int *boundary_list = new int[f0_length]; int number_of_boundaries = GetBoundaryList(f0_step2, f0_length, boundary_list); double **multi_channel_f0 = new double *[number_of_boundaries / 2]; for (int i = 0; i < number_of_boundaries / 2; ++i) multi_channel_f0[i] = new double[f0_length]; GetMultiChannelF0(f0_step2, f0_length, boundary_list, number_of_boundaries, multi_channel_f0); int number_of_channels = Extend(multi_channel_f0, number_of_boundaries / 2, f0_length, boundary_list, f0_candidates, number_of_candidates, allowed_range, multi_channel_f0, boundary_list); if (number_of_channels != 0) MergeF0(multi_channel_f0, boundary_list, number_of_channels, f0_length, f0_candidates, f0_scores, number_of_candidates, f0_step3); for (int i = 0; i < number_of_boundaries / 2; ++i) delete[] multi_channel_f0[i]; delete[] multi_channel_f0; delete[] boundary_list; } //----------------------------------------------------------------------------- // Step 4: F0s in short unvoiced section are faked //----------------------------------------------------------------------------- static void FixStep4(const double *f0_step3, int f0_length, int threshold, double *f0_step4) { for (int i = 0; i < f0_length; ++i) f0_step4[i] = f0_step3[i]; int *boundary_list = new int[f0_length]; int number_of_boundaries = GetBoundaryList(f0_step3, f0_length, boundary_list); int distance; double tmp0, tmp1, coefficient; int count; for (int i = 0; i < number_of_boundaries / 2 - 1; ++i) { distance = boundary_list[(i + 1) * 2] - boundary_list[i * 2 + 1] - 1; if (distance >= threshold) continue; tmp0 = f0_step3[boundary_list[i * 2 + 1]] + 1; tmp1 = f0_step3[boundary_list[(i + 1) * 2]] - 1; coefficient = (tmp1 - tmp0) / (distance + 1.0); count = 1; for (int j = boundary_list[i * 2 + 1] + 1; j <= boundary_list[(i + 1) * 2] - 1; ++j) f0_step4[j] = tmp0 + coefficient * count++; } delete[] boundary_list; } //----------------------------------------------------------------------------- // FixF0Contour() obtains the likely F0 contour. //----------------------------------------------------------------------------- static void FixF0Contour(const double * const *f0_candidates, const double * const *f0_scores, int f0_length, int number_of_candidates, double *best_f0_contour) { double *tmp_f0_contour1 = new double[f0_length]; double *tmp_f0_contour2 = new double[f0_length]; // These parameters are optimized by speech databases. SearchF0Base(f0_candidates, f0_scores, f0_length, number_of_candidates, tmp_f0_contour1); FixStep1(tmp_f0_contour1, f0_length, 0.008, tmp_f0_contour2); FixStep2(tmp_f0_contour2, f0_length, 6, tmp_f0_contour1); FixStep3(tmp_f0_contour1, f0_length, number_of_candidates, f0_candidates, 0.18, f0_scores, tmp_f0_contour2); FixStep4(tmp_f0_contour2, f0_length, 9, best_f0_contour); delete[] tmp_f0_contour1; delete[] tmp_f0_contour2; } //----------------------------------------------------------------------------- // This function uses zero-lag Butterworth filter. //----------------------------------------------------------------------------- static void FilteringF0(const double *a, const double *b, double *x, int x_length, int st, int ed, double *y) { double w[2] = { 0.0, 0.0 }; double wt; double *tmp_x = new double[x_length]; for (int i = 0; i < st; ++i) x[i] = x[st]; for (int i = ed + 1; i < x_length; ++i) x[i] = x[ed]; for (int i = 0; i < x_length; ++i) { wt = x[i] + a[0] * w[0] + a[1] * w[1]; tmp_x[x_length - i - 1] = b[0] * wt + b[1] * w[0] + b[0] * w[1]; w[1] = w[0]; w[0] = wt; } w[0] = w[1] = 0.0; for (int i = 0; i < x_length; ++i) { wt = tmp_x[i] + a[0] * w[0] + a[1] * w[1]; y[x_length - i - 1] = b[0] * wt + b[1] * w[0] + b[0] * w[1]; w[1] = w[0]; w[0] = wt; } delete[] tmp_x; } //----------------------------------------------------------------------------- // SmoothF0Contour() uses the zero-lag Butterworth filter for smoothing. //----------------------------------------------------------------------------- static void SmoothF0Contour(const double *f0, int f0_length, double *smoothed_f0) { const double b[2] = { 0.0078202080334971724, 0.015640416066994345 }; const double a[2] = { 1.7347257688092754, -0.76600660094326412 }; int lag = 300; int new_f0_length = f0_length + lag * 2; double *f0_contour = new double[new_f0_length]; for (int i = 0; i < lag; ++i) f0_contour[i] = 0.0; for (int i = lag; i < lag + f0_length; ++i) f0_contour[i] = f0[i - lag]; for (int i = lag + f0_length; i < new_f0_length; ++i) f0_contour[i] = 0.0; int *boundary_list = new int[new_f0_length]; int number_of_boundaries = GetBoundaryList(f0_contour, new_f0_length, boundary_list); double **multi_channel_f0 = new double *[number_of_boundaries / 2]; for (int i = 0; i < number_of_boundaries / 2; ++i) multi_channel_f0[i] = new double[new_f0_length]; GetMultiChannelF0(f0_contour, new_f0_length, boundary_list, number_of_boundaries, multi_channel_f0); for (int i = 0; i < number_of_boundaries / 2; ++i) { FilteringF0(a, b, multi_channel_f0[i], new_f0_length, boundary_list[i * 2], boundary_list[i * 2 + 1], f0_contour); for (int j = boundary_list[i * 2]; j <= boundary_list[i * 2 + 1]; ++j) smoothed_f0[j - lag] = f0_contour[j]; } for (int i = 0; i < number_of_boundaries / 2; ++i) delete[] multi_channel_f0[i]; delete[] multi_channel_f0; delete[] f0_contour; delete[] boundary_list; } //----------------------------------------------------------------------------- // HarvestGeneralBodySub() is the subfunction of HarvestGeneralBody() //----------------------------------------------------------------------------- static int HarvestGeneralBodySub(const double *boundary_f0_list, int number_of_channels, int f0_length, double actual_fs, int y_length, const double *temporal_positions, const fft_complex *y_spectrum, int fft_size, double f0_floor, double f0_ceil, int max_candidates, double **f0_candidates) { double **raw_f0_candidates = new double *[number_of_channels]; for (int i = 0; i < number_of_channels; ++i) raw_f0_candidates[i] = new double[f0_length]; GetRawF0Candidates(boundary_f0_list, number_of_channels, actual_fs, y_length, temporal_positions, f0_length, y_spectrum, fft_size, f0_floor, f0_ceil, raw_f0_candidates); int number_of_candidates = DetectOfficialF0Candidates(raw_f0_candidates, number_of_channels, f0_length, max_candidates, f0_candidates); OverlapF0Candidates(f0_length, number_of_candidates, f0_candidates); for (int i = 0; i < number_of_channels; ++i) delete[] raw_f0_candidates[i]; delete[] raw_f0_candidates; return number_of_candidates; } //----------------------------------------------------------------------------- // HarvestGeneralBody() estimates the F0 contour based on Harvest. //----------------------------------------------------------------------------- static void HarvestGeneralBody(const double *x, int x_length, int fs, int frame_period, double f0_floor, double f0_ceil, double channels_in_octave, int speed, double *temporal_positions, double *f0) { double adjusted_f0_floor = f0_floor * 0.9; double adjusted_f0_ceil = f0_ceil * 1.1; int number_of_channels = 1 + static_cast(log(adjusted_f0_ceil / adjusted_f0_floor) / world::kLog2 * channels_in_octave); double *boundary_f0_list = new double[number_of_channels]; for (int i = 0; i < number_of_channels; ++i) boundary_f0_list[i] = adjusted_f0_floor * pow(2.0, (i + 1) / channels_in_octave); // normalization int decimation_ratio = MyMaxInt(MyMinInt(speed, 12), 1); int y_length = static_cast(ceil(static_cast(x_length) / decimation_ratio)); double actual_fs = static_cast(fs) / decimation_ratio; int fft_size = GetSuitableFFTSize(y_length + 5 + 2 * static_cast(2.0 * actual_fs / boundary_f0_list[0])); // Calculation of the spectrum used for the f0 estimation double *y = new double[fft_size]; fft_complex *y_spectrum = new fft_complex[fft_size]; GetWaveformAndSpectrum(x, x_length, y_length, actual_fs, fft_size, decimation_ratio, y, y_spectrum); int f0_length = GetSamplesForHarvest(fs, x_length, frame_period); for (int i = 0; i < f0_length; ++i) { temporal_positions[i] = i * frame_period / 1000.0; f0[i] = 0.0; } int overlap_parameter = 7; int max_candidates = matlab_round(number_of_channels / 10.0) * overlap_parameter; double **f0_candidates = new double *[f0_length]; double **f0_candidates_score = new double *[f0_length]; for (int i = 0; i < f0_length; ++i) { f0_candidates[i] = new double[max_candidates]; f0_candidates_score[i] = new double[max_candidates]; } int number_of_candidates = HarvestGeneralBodySub(boundary_f0_list, number_of_channels, f0_length, actual_fs, y_length, temporal_positions, y_spectrum, fft_size, f0_floor, f0_ceil, max_candidates, f0_candidates) * overlap_parameter; RefineF0Candidates(y, y_length, actual_fs, temporal_positions, f0_length, number_of_candidates, f0_floor, f0_ceil, f0_candidates, f0_candidates_score); RemoveUnreliableCandidates(f0_length, number_of_candidates, f0_candidates, f0_candidates_score); double *best_f0_contour = new double[f0_length]; FixF0Contour(f0_candidates, f0_candidates_score, f0_length, number_of_candidates, best_f0_contour); SmoothF0Contour(best_f0_contour, f0_length, f0); delete[] y; delete[] best_f0_contour; delete[] y_spectrum; for (int i = 0; i < f0_length; ++i) { delete[] f0_candidates[i]; delete[] f0_candidates_score[i]; } delete[] f0_candidates; delete[] f0_candidates_score; delete[] boundary_f0_list; } } // namespace int GetSamplesForHarvest(int fs, int x_length, double frame_period) { return static_cast(1000.0 * x_length / fs / frame_period) + 1; } void Harvest(const double *x, int x_length, int fs, const HarvestOption *option, double *temporal_positions, double *f0) { // Several parameters will be controllable for debug. double target_fs = 8000.0; int dimension_ratio = matlab_round(fs / target_fs); double channels_in_octave = 40; if (option->frame_period == 1.0) { HarvestGeneralBody(x, x_length, fs, 1, option->f0_floor, option->f0_ceil, channels_in_octave, dimension_ratio, temporal_positions, f0); return; } int basic_frame_period = 1; int basic_f0_length = GetSamplesForHarvest(fs, x_length, basic_frame_period); double *basic_f0 = new double[basic_f0_length]; double *basic_temporal_positions = new double[basic_f0_length]; HarvestGeneralBody(x, x_length, fs, basic_frame_period, option->f0_floor, option->f0_ceil, channels_in_octave, dimension_ratio, basic_temporal_positions, basic_f0); int f0_length = GetSamplesForHarvest(fs, x_length, option->frame_period); for (int i = 0; i < f0_length; ++i) { temporal_positions[i] = i * option->frame_period / 1000.0; f0[i] = basic_f0[MyMinInt(basic_f0_length - 1, matlab_round(temporal_positions[i] * 1000.0))]; } delete[] basic_f0; delete[] basic_temporal_positions; } void InitializeHarvestOption(HarvestOption *option) { // You can change default parameters. option->f0_ceil = world::kCeilF0; option->f0_floor = world::kFloorF0; option->frame_period = 5; } ================================================ FILE: libtts/Modules/Lib/World/src/matlabfunctions.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Matlab functions implemented for WORLD // Since these functions are implemented as the same function of Matlab, // the source code does not follow the style guide (Names of variables // and functions). // Please see the reference of Matlab to show the usage of functions. // Caution: // The functions wavread() and wavwrite() were removed to the /src. // they were moved to the test/audioio.cpp. (2016/01/28) //----------------------------------------------------------------------------- #include "world/matlabfunctions.h" #include #include #include "world/constantnumbers.h" namespace { //----------------------------------------------------------------------------- // FilterForDecimate() calculates the coefficients of low-pass filter and // carries out the filtering. This function is only used for decimate(). //----------------------------------------------------------------------------- static void FilterForDecimate(const double *x, int x_length, int r, double *y) { double a[3], b[2]; // filter Coefficients switch (r) { case 11: // fs : 44100 (default) a[0] = 2.450743295230728; a[1] = -2.06794904601978; a[2] = 0.59574774438332101; b[0] = 0.0026822508007163792; b[1] = 0.0080467524021491377; break; case 12: // fs : 48000 a[0] = 2.4981398605924205; a[1] = -2.1368928194784025; a[2] = 0.62187513816221485; b[0] = 0.0021097275904709001; b[1] = 0.0063291827714127002; break; case 10: a[0] = 2.3936475118069387; a[1] = -1.9873904075111861; a[2] = 0.5658879979027055; b[0] = 0.0034818622251927556; b[1] = 0.010445586675578267; break; case 9: a[0] = 2.3236003491759578; a[1] = -1.8921545617463598; a[2] = 0.53148928133729068; b[0] = 0.0046331164041389372; b[1] = 0.013899349212416812; break; case 8: // fs : 32000 a[0] = 2.2357462340187593; a[1] = -1.7780899984041358; a[2] = 0.49152555365968692; b[0] = 0.0063522763407111993; b[1] = 0.019056829022133598; break; case 7: a[0] = 2.1225239019534703; a[1] = -1.6395144861046302; a[2] = 0.44469707800587366; b[0] = 0.0090366882681608418; b[1] = 0.027110064804482525; break; case 6: // fs : 24000 and 22050 a[0] = 1.9715352749512141; a[1] = -1.4686795689225347; a[2] = 0.3893908434965701; b[0] = 0.013469181309343825; b[1] = 0.040407543928031475; break; case 5: a[0] = 1.7610939654280557; a[1] = -1.2554914843859768; a[2] = 0.3237186507788215; b[0] = 0.021334858522387423; b[1] = 0.06400457556716227; break; case 4: // fs : 16000 a[0] = 1.4499664446880227; a[1] = -0.98943497080950582; a[2] = 0.24578252340690215; b[0] = 0.036710750339322612; b[1] = 0.11013225101796784; break; case 3: a[0] = 0.95039378983237421; a[1] = -0.67429146741526791; a[2] = 0.15412211621346475; b[0] = 0.071221945171178636; b[1] = 0.21366583551353591; break; case 2: // fs : 8000 a[0] = 0.041156734567757189; a[1] = -0.42599112459189636; a[2] = 0.041037215479961225; b[0] = 0.16797464681802227; b[1] = 0.50392394045406674; break; default: a[0] = 0.0; a[1] = 0.0; a[2] = 0.0; b[0] = 0.0; b[1] = 0.0; } // Filtering on time domain. double w[3] = {0.0, 0.0, 0.0}; double wt; for (int i = 0; i < x_length; ++i) { wt = x[i] + a[0] * w[0] + a[1] * w[1] + a[2] * w[2]; y[i] = b[0] * wt + b[1] * w[0] + b[1] * w[1] + b[0] * w[2]; w[2] = w[1]; w[1] = w[0]; w[0] = wt; } } } // namespace void fftshift(const double *x, int x_length, double *y) { for (int i = 0; i < x_length / 2; ++i) { y[i] = x[i + x_length / 2]; y[i + x_length / 2] = x[i]; } } void histc(const double *x, int x_length, const double *edges, int edges_length, int *index) { int count = 1; int i = 0; for (; i < edges_length; ++i) { index[i] = 1; if (edges[i] >= x[0]) break; } for (; i < edges_length; ++i) { if (edges[i] < x[count]) { index[i] = count; } else { index[i--] = count++; } if (count == x_length) break; } count--; for (i++; i < edges_length; ++i) index[i] = count; } void interp1(const double *x, const double *y, int x_length, const double *xi, int xi_length, double *yi) { double *h = new double[x_length - 1]; int *k = new int[xi_length]; for (int i = 0; i < x_length - 1; ++i) h[i] = x[i + 1] - x[i]; for (int i = 0; i < xi_length; ++i) { k[i] = 0; } histc(x, x_length, xi, xi_length, k); for (int i = 0; i < xi_length; ++i) { double s = (xi[i] - x[k[i] - 1]) / h[k[i] - 1]; yi[i] = y[k[i] - 1] + s * (y[k[i]] - y[k[i] - 1]); } delete[] k; delete[] h; } void decimate(const double *x, int x_length, int r, double *y) { const int kNFact = 9; double *tmp1 = new double[x_length + kNFact * 2]; double *tmp2 = new double[x_length + kNFact * 2]; for (int i = 0; i < kNFact; ++i) tmp1[i] = 2 * x[0] - x[kNFact - i]; for (int i = kNFact; i < kNFact + x_length; ++i) tmp1[i] = x[i - kNFact]; for (int i = kNFact + x_length; i < 2 * kNFact + x_length; ++i) tmp1[i] = 2 * x[x_length - 1] - x[x_length - 2 - (i - (kNFact + x_length))]; FilterForDecimate(tmp1, 2 * kNFact + x_length, r, tmp2); for (int i = 0; i < 2 * kNFact + x_length; ++i) tmp1[i] = tmp2[2 * kNFact + x_length - i - 1]; FilterForDecimate(tmp1, 2 * kNFact + x_length, r, tmp2); for (int i = 0; i < 2 * kNFact + x_length; ++i) tmp1[i] = tmp2[2 * kNFact + x_length - i - 1]; int nout = (x_length - 1) / r + 1; int nbeg = r - r * nout + x_length; int count = 0; for (int i = nbeg; i < x_length + kNFact; i += r) y[count++] = tmp1[i + kNFact - 1]; delete[] tmp1; delete[] tmp2; } int matlab_round(double x) { return x > 0 ? static_cast(x + 0.5) : static_cast(x - 0.5); } void diff(const double *x, int x_length, double *y) { for (int i = 0; i < x_length - 1; ++i) y[i] = x[i + 1] - x[i]; } void interp1Q(double x, double shift, const double *y, int x_length, const double *xi, int xi_length, double *yi) { double *xi_fraction = new double[xi_length]; double *delta_y = new double[x_length]; int *xi_base = new int[xi_length]; double delta_x = shift; for (int i = 0; i < xi_length; ++i) { xi_base[i] = static_cast((xi[i] - x) / delta_x); xi_fraction[i] = (xi[i] - x) / delta_x - xi_base[i]; } diff(y, x_length, delta_y); delta_y[x_length - 1] = 0.0; for (int i = 0; i < xi_length; ++i) yi[i] = y[xi_base[i]] + delta_y[xi_base[i]] * xi_fraction[i]; // Bug was fixed at 2013/07/14 by M. Morise delete[] xi_fraction; delete[] xi_base; delete[] delta_y; } // You must not use these variables. // Note: // I have no idea to implement the randn() and randn_reseed() without the // global variables. If you have a good idea, please give me the information. static uint32_t g_randn_x = 123456789; static uint32_t g_randn_y = 362436069; static uint32_t g_randn_z = 521288629; static uint32_t g_randn_w = 88675123; void randn_reseed() { g_randn_x = 123456789; g_randn_y = 362436069; g_randn_z = 521288629; g_randn_w = 88675123; } double randn(void) { uint32_t t; t = g_randn_x ^ (g_randn_x << 11); g_randn_x = g_randn_y; g_randn_y = g_randn_z; g_randn_z = g_randn_w; g_randn_w = (g_randn_w ^ (g_randn_w >> 19)) ^ (t ^ (t >> 8)); uint32_t tmp = g_randn_w >> 4; for (int i = 0; i < 11; ++i) { t = g_randn_x ^ (g_randn_x << 11); g_randn_x = g_randn_y; g_randn_y = g_randn_z; g_randn_z = g_randn_w; g_randn_w = (g_randn_w ^ (g_randn_w >> 19)) ^ (t ^ (t >> 8)); tmp += g_randn_w >> 4; } return tmp / 268435456.0 - 6.0; } void fast_fftfilt(const double *x, int x_length, const double *h, int h_length, int fft_size, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, double *y) { fft_complex *x_spectrum = new fft_complex[fft_size]; for (int i = 0; i < x_length; ++i) forward_real_fft->waveform[i] = x[i] / fft_size; for (int i = x_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { x_spectrum[i][0] = forward_real_fft->spectrum[i][0]; x_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } for (int i = 0; i < h_length; ++i) forward_real_fft->waveform[i] = h[i] / fft_size; for (int i = h_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = x_spectrum[i][0] * forward_real_fft->spectrum[i][0] - x_spectrum[i][1] * forward_real_fft->spectrum[i][1]; inverse_real_fft->spectrum[i][1] = x_spectrum[i][0] * forward_real_fft->spectrum[i][1] + x_spectrum[i][1] * forward_real_fft->spectrum[i][0]; } fft_execute(inverse_real_fft->inverse_fft); for (int i = 0; i < fft_size; ++i) y[i] = inverse_real_fft->waveform[i]; delete[] x_spectrum; } double matlab_std(const double *x, int x_length) { double average = 0.0; for (int i = 0; i < x_length; ++i) average += x[i]; average /= x_length; double s = 0.0; for (int i = 0; i < x_length; ++i) s += pow(x[i] - average, 2.0); s /= (x_length - 1); return sqrt(s); } ================================================ FILE: libtts/Modules/Lib/World/src/stonemask.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // F0 estimation based on instantaneous frequency. // This method is carried out by using the output of Dio(). //----------------------------------------------------------------------------- #include "world/stonemask.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/fft.h" #include "world/matlabfunctions.h" namespace { //----------------------------------------------------------------------------- // GetBaseIndex() calculates the temporal positions for windowing. // Since the result includes negative value and the value that exceeds the // length of the input signal, it must be modified appropriately. //----------------------------------------------------------------------------- static void GetBaseIndex(double current_position, const double *base_time, int base_time_length, int fs, int *index_raw) { for (int i = 0; i < base_time_length; ++i) index_raw[i] = matlab_round((current_position + base_time[i]) * fs); } //----------------------------------------------------------------------------- // GetMainWindow() generates the window function. //----------------------------------------------------------------------------- static void GetMainWindow(double current_position, const int *index_raw, int base_time_length, int fs, double window_length_in_time, double *main_window) { double tmp = 0.0; for (int i = 0; i < base_time_length; ++i) { tmp = (index_raw[i] - 1.0) / fs - current_position; main_window[i] = 0.42 + 0.5 * cos(2.0 * world::kPi * tmp / window_length_in_time) + 0.08 * cos(4.0 * world::kPi * tmp / window_length_in_time); } } //----------------------------------------------------------------------------- // GetDiffWindow() generates the differentiated window. // Diff means differential. //----------------------------------------------------------------------------- static void GetDiffWindow(const double *main_window, int base_time_length, double *diff_window) { diff_window[0] = -main_window[1] / 2.0; for (int i = 1; i < base_time_length - 1; ++i) diff_window[i] = -(main_window[i + 1] - main_window[i - 1]) / 2.0; diff_window[base_time_length - 1] = main_window[base_time_length - 2] / 2.0; } //----------------------------------------------------------------------------- // GetSpectra() calculates two spectra of the waveform windowed by windows // (main window and diff window). //----------------------------------------------------------------------------- static void GetSpectra(const double *x, int x_length, int fft_size, const int *index_raw, const double *main_window, const double *diff_window, int base_time_length, const ForwardRealFFT *forward_real_fft, fft_complex *main_spectrum, fft_complex *diff_spectrum) { int *index = new int[base_time_length]; for (int i = 0; i < base_time_length; ++i) index[i] = MyMaxInt(0, MyMinInt(x_length - 1, index_raw[i] - 1)); for (int i = 0; i < base_time_length; ++i) forward_real_fft->waveform[i] = x[index[i]] * main_window[i]; for (int i = base_time_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { main_spectrum[i][0] = forward_real_fft->spectrum[i][0]; main_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } for (int i = 0; i < base_time_length; ++i) forward_real_fft->waveform[i] = x[index[i]] * diff_window[i]; for (int i = base_time_length; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); for (int i = 0; i <= fft_size / 2; ++i) { diff_spectrum[i][0] = forward_real_fft->spectrum[i][0]; diff_spectrum[i][1] = forward_real_fft->spectrum[i][1]; } delete[] index; } //----------------------------------------------------------------------------- // FixF0() fixed the F0 by instantaneous frequency. //----------------------------------------------------------------------------- static double FixF0(const double *power_spectrum, const double *numerator_i, int fft_size, int fs, double initial_f0, int number_of_harmonics) { double *amplitude_list = new double[number_of_harmonics]; double *instantaneous_frequency_list = new double[number_of_harmonics]; int index; for (int i = 0; i < number_of_harmonics; ++i) { index = MyMinInt(matlab_round(initial_f0 * fft_size / fs * (i + 1)), fft_size / 2); instantaneous_frequency_list[i] = power_spectrum[index] == 0.0 ? 0.0 : static_cast(index) * fs / fft_size + numerator_i[index] / power_spectrum[index] * fs / 2.0 / world::kPi; amplitude_list[i] = sqrt(power_spectrum[index]); } double denominator = 0.0; double numerator = 0.0; for (int i = 0; i < number_of_harmonics; ++i) { numerator += amplitude_list[i] * instantaneous_frequency_list[i]; denominator += amplitude_list[i] * (i + 1); } delete[] amplitude_list; delete[] instantaneous_frequency_list; return numerator / (denominator + world::kMySafeGuardMinimum); } //----------------------------------------------------------------------------- // GetTentativeF0() calculates the F0 based on the instantaneous frequency. //----------------------------------------------------------------------------- static double GetTentativeF0(const double *power_spectrum, const double *numerator_i, int fft_size, int fs, double initial_f0) { double tentative_f0 = FixF0(power_spectrum, numerator_i, fft_size, fs, initial_f0, 2); // If the fixed value is too large, the result will be rejected. if (tentative_f0 <= 0.0 || tentative_f0 > initial_f0 * 2) return 0.0; return FixF0(power_spectrum, numerator_i, fft_size, fs, tentative_f0, 6); } //----------------------------------------------------------------------------- // GetMeanF0() calculates the instantaneous frequency. //----------------------------------------------------------------------------- static double GetMeanF0(const double *x, int x_length, int fs, double current_position, double initial_f0, int fft_size, double window_length_in_time, const double *base_time, int base_time_length) { ForwardRealFFT forward_real_fft = {0}; InitializeForwardRealFFT(fft_size, &forward_real_fft); fft_complex *main_spectrum = new fft_complex[fft_size]; fft_complex *diff_spectrum = new fft_complex[fft_size]; int *index_raw = new int[base_time_length]; double *main_window = new double[base_time_length]; double *diff_window = new double[base_time_length]; GetBaseIndex(current_position, base_time, base_time_length, fs, index_raw); GetMainWindow(current_position, index_raw, base_time_length, fs, window_length_in_time, main_window); GetDiffWindow(main_window, base_time_length, diff_window); GetSpectra(x, x_length, fft_size, index_raw, main_window, diff_window, base_time_length, &forward_real_fft, main_spectrum, diff_spectrum); double *power_spectrum = new double[fft_size / 2 + 1]; double *numerator_i = new double[fft_size / 2 + 1]; for (int j = 0; j <= fft_size / 2; ++j) { numerator_i[j] = main_spectrum[j][0] * diff_spectrum[j][1] - main_spectrum[j][1] * diff_spectrum[j][0]; power_spectrum[j] = main_spectrum[j][0] * main_spectrum[j][0] + main_spectrum[j][1] * main_spectrum[j][1]; } double tentative_f0 = GetTentativeF0(power_spectrum, numerator_i, fft_size, fs, initial_f0); delete[] diff_spectrum; delete[] diff_window; delete[] main_window; delete[] index_raw; delete[] numerator_i; delete[] power_spectrum; delete[] main_spectrum; DestroyForwardRealFFT(&forward_real_fft); return tentative_f0; } //----------------------------------------------------------------------------- // GetRefinedF0() fixes the F0 estimated by Dio(). This function uses // instantaneous frequency. //----------------------------------------------------------------------------- static double GetRefinedF0(const double *x, int x_length, int fs, double current_potision, double initial_f0) { if (initial_f0 <= world::kFloorF0StoneMask || initial_f0 > fs / 12.0) return 0.0; int half_window_length = static_cast(1.5 * fs / initial_f0 + 1.0); double window_length_in_time = (2.0 * half_window_length + 1.0) / fs; double *base_time = new double[half_window_length * 2 + 1]; for (int i = 0; i < half_window_length * 2 + 1; i++) base_time[i] = static_cast(-half_window_length + i) / fs; int fft_size = static_cast(pow(2.0, 2.0 + static_cast(log(half_window_length * 2.0 + 1.0) / world::kLog2))); double mean_f0 = GetMeanF0(x, x_length, fs, current_potision, initial_f0, fft_size, window_length_in_time, base_time, half_window_length * 2 + 1); // If amount of correction is overlarge (20 %), initial F0 is employed. if (fabs(mean_f0 - initial_f0) > initial_f0 * 0.2) mean_f0 = initial_f0; delete[] base_time; return mean_f0; } } // namespace void StoneMask(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, double *refined_f0) { for (int i = 0; i < f0_length; i++) refined_f0[i] = GetRefinedF0(x, x_length, fs, temporal_positions[i], f0[i]); } ================================================ FILE: libtts/Modules/Lib/World/src/synthesis.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Voice synthesis based on f0, spectrogram and aperiodicity. // forward_real_fft, inverse_real_fft and minimum_phase are used to speed up. //----------------------------------------------------------------------------- #include "world/synthesis.h" #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { static void GetNoiseSpectrum(int noise_size, int fft_size, const ForwardRealFFT *forward_real_fft) { double average = 0.0; for (int i = 0; i < noise_size; ++i) { forward_real_fft->waveform[i] = randn(); average += forward_real_fft->waveform[i]; } average /= noise_size; for (int i = 0; i < noise_size; ++i) forward_real_fft->waveform[i] -= average; for (int i = noise_size; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); } //----------------------------------------------------------------------------- // GetAperiodicResponse() calculates an aperiodic response. //----------------------------------------------------------------------------- static void GetAperiodicResponse(int noise_size, int fft_size, const double *spectrum, const double *aperiodic_ratio, double current_vuv, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, double *aperiodic_response) { GetNoiseSpectrum(noise_size, fft_size, forward_real_fft); if (current_vuv != 0.0) for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i] * aperiodic_ratio[i]) / 2.0; else for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i]) / 2.0; GetMinimumPhaseSpectrum(minimum_phase); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = minimum_phase->minimum_phase_spectrum[i][0] * forward_real_fft->spectrum[i][0] - minimum_phase->minimum_phase_spectrum[i][1] * forward_real_fft->spectrum[i][1]; inverse_real_fft->spectrum[i][1] = minimum_phase->minimum_phase_spectrum[i][0] * forward_real_fft->spectrum[i][1] + minimum_phase->minimum_phase_spectrum[i][1] * forward_real_fft->spectrum[i][0]; } fft_execute(inverse_real_fft->inverse_fft); fftshift(inverse_real_fft->waveform, fft_size, aperiodic_response); } //----------------------------------------------------------------------------- // RemoveDCComponent() //----------------------------------------------------------------------------- static void RemoveDCComponent(const double *periodic_response, int fft_size, const double *dc_remover, double *new_periodic_response) { double dc_component = 0.0; for (int i = fft_size / 2; i < fft_size; ++i) dc_component += periodic_response[i]; for (int i = 0; i < fft_size / 2; ++i) new_periodic_response[i] = -dc_component * dc_remover[i]; for (int i = fft_size / 2; i < fft_size; ++i) new_periodic_response[i] -= dc_component * dc_remover[i]; } //----------------------------------------------------------------------------- // GetSpectrumWithFractionalTimeShift() calculates a periodic spectrum with // the fractional time shift under 1/fs. //----------------------------------------------------------------------------- static void GetSpectrumWithFractionalTimeShift(int fft_size, double coefficient, const InverseRealFFT *inverse_real_fft) { double re, im, re2, im2; for (int i = 0; i <= fft_size / 2; ++i) { re = inverse_real_fft->spectrum[i][0]; im = inverse_real_fft->spectrum[i][1]; re2 = cos(coefficient * i); im2 = sqrt(1.0 - re2 * re2); // sin(pshift) inverse_real_fft->spectrum[i][0] = re * re2 + im * im2; inverse_real_fft->spectrum[i][1] = im * re2 - re * im2; } } //----------------------------------------------------------------------------- // GetPeriodicResponse() calculates a periodic response. //----------------------------------------------------------------------------- static void GetPeriodicResponse(int fft_size, const double *spectrum, const double *aperiodic_ratio, double current_vuv, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, const double *dc_remover, double fractional_time_shift, int fs, double *periodic_response) { if (current_vuv <= 0.5 || aperiodic_ratio[0] > 0.999) { for (int i = 0; i < fft_size; ++i) periodic_response[i] = 0.0; return; } for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i] * (1.0 - aperiodic_ratio[i]) + world::kMySafeGuardMinimum) / 2.0; GetMinimumPhaseSpectrum(minimum_phase); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = minimum_phase->minimum_phase_spectrum[i][0]; inverse_real_fft->spectrum[i][1] = minimum_phase->minimum_phase_spectrum[i][1]; } // apply fractional time delay of fractional_time_shift seconds // using linear phase shift double coefficient = 2.0 * world::kPi * fractional_time_shift * fs / fft_size; GetSpectrumWithFractionalTimeShift(fft_size, coefficient, inverse_real_fft); fft_execute(inverse_real_fft->inverse_fft); fftshift(inverse_real_fft->waveform, fft_size, periodic_response); RemoveDCComponent(periodic_response, fft_size, dc_remover, periodic_response); } static void GetSpectralEnvelope(double current_time, double frame_period, int f0_length, const double * const *spectrogram, int fft_size, double *spectral_envelope) { int current_frame_floor = MyMinInt(f0_length - 1, static_cast(floor(current_time / frame_period))); int current_frame_ceil = MyMinInt(f0_length - 1, static_cast(ceil(current_time / frame_period))); double interpolation = current_time / frame_period - current_frame_floor; if (current_frame_floor == current_frame_ceil) for (int i = 0; i <= fft_size / 2; ++i) spectral_envelope[i] = fabs(spectrogram[current_frame_floor][i]); else for (int i = 0; i <= fft_size / 2; ++i) spectral_envelope[i] = (1.0 - interpolation) * fabs(spectrogram[current_frame_floor][i]) + interpolation * fabs(spectrogram[current_frame_ceil][i]); } static void GetAperiodicRatio(double current_time, double frame_period, int f0_length, const double * const *aperiodicity, int fft_size, double *aperiodic_spectrum) { int current_frame_floor = MyMinInt(f0_length - 1, static_cast(floor(current_time / frame_period))); int current_frame_ceil = MyMinInt(f0_length - 1, static_cast(ceil(current_time / frame_period))); double interpolation = current_time / frame_period - current_frame_floor; if (current_frame_floor == current_frame_ceil) for (int i = 0; i <= fft_size / 2; ++i) aperiodic_spectrum[i] = pow(GetSafeAperiodicity(aperiodicity[current_frame_floor][i]), 2.0); else for (int i = 0; i <= fft_size / 2; ++i) aperiodic_spectrum[i] = pow((1.0 - interpolation) * GetSafeAperiodicity(aperiodicity[current_frame_floor][i]) + interpolation * GetSafeAperiodicity(aperiodicity[current_frame_ceil][i]), 2.0); } //----------------------------------------------------------------------------- // GetOneFrameSegment() calculates a periodic and aperiodic response at a time. //----------------------------------------------------------------------------- static void GetOneFrameSegment(double current_vuv, int noise_size, const double * const *spectrogram, int fft_size, const double * const *aperiodicity, int f0_length, double frame_period, double current_time, double fractional_time_shift, int fs, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, const double *dc_remover, double *response) { double *aperiodic_response = new double[fft_size]; double *periodic_response = new double[fft_size]; double *spectral_envelope = new double[fft_size]; double *aperiodic_ratio = new double[fft_size]; GetSpectralEnvelope(current_time, frame_period, f0_length, spectrogram, fft_size, spectral_envelope); GetAperiodicRatio(current_time, frame_period, f0_length, aperiodicity, fft_size, aperiodic_ratio); // Synthesis of the periodic response GetPeriodicResponse(fft_size, spectral_envelope, aperiodic_ratio, current_vuv, inverse_real_fft, minimum_phase, dc_remover, fractional_time_shift, fs, periodic_response); // Synthesis of the aperiodic response GetAperiodicResponse(noise_size, fft_size, spectral_envelope, aperiodic_ratio, current_vuv, forward_real_fft, inverse_real_fft, minimum_phase, aperiodic_response); double sqrt_noise_size = sqrt(static_cast(noise_size)); for (int i = 0; i < fft_size; ++i) response[i] = (periodic_response[i] * sqrt_noise_size + aperiodic_response[i]) / fft_size; delete[] spectral_envelope; delete[] aperiodic_ratio; delete[] periodic_response; delete[] aperiodic_response; } static void GetTemporalParametersForTimeBase(const double *f0, int f0_length, int fs, int y_length, double frame_period, double lowest_f0, double *time_axis, double *coarse_time_axis, double *coarse_f0, double *coarse_vuv) { for (int i = 0; i < y_length; ++i) time_axis[i] = i / static_cast(fs); // the array 'coarse_time_axis' is supposed to have 'f0_length + 1' positions for (int i = 0; i < f0_length; ++i) { coarse_time_axis[i] = i * frame_period; coarse_f0[i] = f0[i] < lowest_f0 ? 0.0 : f0[i]; coarse_vuv[i] = coarse_f0[i] == 0.0 ? 0.0 : 1.0; } coarse_time_axis[f0_length] = f0_length * frame_period; coarse_f0[f0_length] = coarse_f0[f0_length - 1] * 2 - coarse_f0[f0_length - 2]; coarse_vuv[f0_length] = coarse_vuv[f0_length - 1] * 2 - coarse_vuv[f0_length - 2]; } static int GetPulseLocationsForTimeBase(const double *interpolated_f0, const double *time_axis, int y_length, int fs, double *pulse_locations, int *pulse_locations_index, double *pulse_locations_time_shift) { double *total_phase = new double[y_length]; double *wrap_phase = new double[y_length]; double *wrap_phase_abs = new double[y_length - 1]; total_phase[0] = 2.0 * world::kPi * interpolated_f0[0] / fs; wrap_phase[0] = fmod(total_phase[0], 2.0 * world::kPi); for (int i = 1; i < y_length; ++i) { total_phase[i] = total_phase[i - 1] + 2.0 * world::kPi * interpolated_f0[i] / fs; wrap_phase[i] = fmod(total_phase[i], 2.0 * world::kPi); wrap_phase_abs[i - 1] = fabs(wrap_phase[i] - wrap_phase[i - 1]); } int number_of_pulses = 0; for (int i = 0; i < y_length - 1; ++i) { if (wrap_phase_abs[i] > world::kPi) { pulse_locations[number_of_pulses] = time_axis[i]; pulse_locations_index[number_of_pulses] = i; // calculate the time shift in seconds between exact fractional pulse // position and the integer pulse position (sample i) // as we don't have access to the exact pulse position, we infer it // from the point between sample i and sample i + 1 where the // accummulated phase cross a multiple of 2pi // this point is found by solving y1 + x * (y2 - y1) = 0 for x, where y1 // and y2 are the phases corresponding to sample i and i + 1, offset so // they cross zero; x >= 0 double y1 = wrap_phase[i] - 2.0 * world::kPi; double y2 = wrap_phase[i + 1]; double x = -y1 / (y2 - y1); pulse_locations_time_shift[number_of_pulses] = x / fs; ++number_of_pulses; } } delete[] wrap_phase_abs; delete[] wrap_phase; delete[] total_phase; return number_of_pulses; } static int GetTimeBase(const double *f0, int f0_length, int fs, double frame_period, int y_length, double lowest_f0, double *pulse_locations, int *pulse_locations_index, double *pulse_locations_time_shift, double *interpolated_vuv) { double *time_axis = new double[y_length]; double *coarse_time_axis = new double[f0_length + 1]; double *coarse_f0 = new double[f0_length + 1]; double *coarse_vuv = new double[f0_length + 1]; GetTemporalParametersForTimeBase(f0, f0_length, fs, y_length, frame_period, lowest_f0, time_axis, coarse_time_axis, coarse_f0, coarse_vuv); double *interpolated_f0 = new double[y_length]; interp1(coarse_time_axis, coarse_f0, f0_length + 1, time_axis, y_length, interpolated_f0); interp1(coarse_time_axis, coarse_vuv, f0_length + 1, time_axis, y_length, interpolated_vuv); for (int i = 0; i < y_length; ++i) { interpolated_vuv[i] = interpolated_vuv[i] > 0.5 ? 1.0 : 0.0; interpolated_f0[i] = interpolated_vuv[i] == 0.0 ? world::kDefaultF0 : interpolated_f0[i]; } int number_of_pulses = GetPulseLocationsForTimeBase(interpolated_f0, time_axis, y_length, fs, pulse_locations, pulse_locations_index, pulse_locations_time_shift); delete[] coarse_vuv; delete[] coarse_f0; delete[] coarse_time_axis; delete[] time_axis; delete[] interpolated_f0; return number_of_pulses; } static void GetDCRemover(int fft_size, double *dc_remover) { double dc_component = 0.0; for (int i = 0; i < fft_size / 2; ++i) { dc_remover[i] = 0.5 - 0.5 * cos(2.0 * world::kPi * (i + 1.0) / (1.0 + fft_size)); dc_remover[fft_size - i - 1] = dc_remover[i]; dc_component += dc_remover[i] * 2.0; } for (int i = 0; i < fft_size / 2; ++i) { dc_remover[i] /= dc_component; dc_remover[fft_size - i - 1] = dc_remover[i]; } } } // namespace void Synthesis(const double *f0, int f0_length, const double * const *spectrogram, const double * const *aperiodicity, int fft_size, double frame_period, int fs, int y_length, double *y) { randn_reseed(); double *impulse_response = new double[fft_size]; for (int i = 0; i < y_length; ++i) y[i] = 0.0; MinimumPhaseAnalysis minimum_phase = {0}; InitializeMinimumPhaseAnalysis(fft_size, &minimum_phase); InverseRealFFT inverse_real_fft = {0}; InitializeInverseRealFFT(fft_size, &inverse_real_fft); ForwardRealFFT forward_real_fft = {0}; InitializeForwardRealFFT(fft_size, &forward_real_fft); double *pulse_locations = new double[y_length]; int *pulse_locations_index = new int[y_length]; double *pulse_locations_time_shift = new double[y_length]; double *interpolated_vuv = new double[y_length]; int number_of_pulses = GetTimeBase(f0, f0_length, fs, frame_period / 1000.0, y_length, fs / fft_size + 1.0, pulse_locations, pulse_locations_index, pulse_locations_time_shift, interpolated_vuv); double *dc_remover = new double[fft_size]; GetDCRemover(fft_size, dc_remover); frame_period /= 1000.0; int noise_size; int index, offset, lower_limit, upper_limit; for (int i = 0; i < number_of_pulses; ++i) { noise_size = pulse_locations_index[MyMinInt(number_of_pulses - 1, i + 1)] - pulse_locations_index[i]; GetOneFrameSegment(interpolated_vuv[pulse_locations_index[i]], noise_size, spectrogram, fft_size, aperiodicity, f0_length, frame_period, pulse_locations[i], pulse_locations_time_shift[i], fs, &forward_real_fft, &inverse_real_fft, &minimum_phase, dc_remover, impulse_response); offset = pulse_locations_index[i] - fft_size / 2 + 1; lower_limit = MyMaxInt(0, -offset); upper_limit = MyMinInt(fft_size, y_length - offset); for (int j = lower_limit; j < upper_limit; ++j) { index = j + offset; y[index] += impulse_response[j]; } } delete[] dc_remover; delete[] pulse_locations; delete[] pulse_locations_index; delete[] pulse_locations_time_shift; delete[] interpolated_vuv; DestroyMinimumPhaseAnalysis(&minimum_phase); DestroyInverseRealFFT(&inverse_real_fft); DestroyForwardRealFFT(&forward_real_fft); delete[] impulse_response; } ================================================ FILE: libtts/Modules/Lib/World/src/synthesisrealtime.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Voice synthesis based on f0, spectrogram and aperiodicity. // This is an implementation for real-time applications. // Note: Several functions are same as those of synthesis.cpp. // // Caution: This is an implementation as a prototype. // Specifications may change. There may be a bug. // // Caution: DC removal was re-implemented. However, this implementation is // different from the implementation in synthesis.cpp. The sound // quality is almost all the same in both implementations. //----------------------------------------------------------------------------- #include "world/synthesisrealtime.h" #include #include #include "world/common.h" #include "world/constantnumbers.h" #include "world/matlabfunctions.h" namespace { static void GetNoiseSpectrum(int noise_size, int fft_size, const ForwardRealFFT *forward_real_fft) { double average = 0.0; for (int i = 0; i < noise_size; ++i) { forward_real_fft->waveform[i] = randn(); average += forward_real_fft->waveform[i]; } average /= noise_size; for (int i = 0; i < noise_size; ++i) forward_real_fft->waveform[i] -= average; for (int i = noise_size; i < fft_size; ++i) forward_real_fft->waveform[i] = 0.0; fft_execute(forward_real_fft->forward_fft); } //----------------------------------------------------------------------------- // GetAperiodicResponse() calculates an aperiodic response. //----------------------------------------------------------------------------- static void GetAperiodicResponse(int noise_size, int fft_size, const double *spectrum, const double *aperiodic_ratio, double current_vuv, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, double *aperiodic_response) { GetNoiseSpectrum(noise_size, fft_size, forward_real_fft); if (current_vuv != 0.0) for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i] * aperiodic_ratio[i] + world::kMySafeGuardMinimum) / 2.0; else for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i]) / 2.0; GetMinimumPhaseSpectrum(minimum_phase); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = minimum_phase->minimum_phase_spectrum[i][0] * forward_real_fft->spectrum[i][0] - minimum_phase->minimum_phase_spectrum[i][1] * forward_real_fft->spectrum[i][1]; inverse_real_fft->spectrum[i][1] = minimum_phase->minimum_phase_spectrum[i][0] * forward_real_fft->spectrum[i][1] + minimum_phase->minimum_phase_spectrum[i][1] * forward_real_fft->spectrum[i][0]; } fft_execute(inverse_real_fft->inverse_fft); fftshift(inverse_real_fft->waveform, fft_size, aperiodic_response); } static void ClearRingBuffer(int start, int end, WorldSynthesizer *synth) { int pointer; for (int i = start; i < end; ++i) { pointer = i % synth->number_of_pointers; synth->number_of_pulses[pointer] = 0; if (synth->pulse_locations[pointer] != NULL) { delete[] synth->pulse_locations[pointer]; synth->pulse_locations[pointer] = NULL; } if (synth->interpolated_vuv[pointer] != NULL) { delete[] synth->interpolated_vuv[pointer]; synth->interpolated_vuv[pointer] = NULL; } if (synth->pulse_locations_index[pointer] != NULL) { delete[] synth->pulse_locations_index[pointer]; synth->pulse_locations_index[pointer] = NULL; } } } static int SeekSynthesizer(double current_location, WorldSynthesizer *synth) { int frame_number = static_cast(current_location / synth->frame_period); int tmp_pointer = synth->current_pointer2; int tmp; for (int i = 0; i < synth->head_pointer - synth->current_pointer2; ++i) { tmp = (tmp_pointer + i) % synth->number_of_pointers; if (synth->f0_origin[tmp] <= frame_number && frame_number < synth->f0_origin[tmp] + synth->f0_length[tmp]) { tmp_pointer += i; break; } } ClearRingBuffer(synth->current_pointer2, tmp_pointer, synth); synth->current_pointer2 = tmp_pointer; return 1; } static void SearchPointer(int frame, WorldSynthesizer *synth, int flag, double **front, double **next) { int pointer = synth->current_pointer2 % synth->number_of_pointers; int index = -1; for (int i = 0; i < synth->f0_length[pointer]; ++i) if (synth->f0_origin[pointer] + i == frame) { index = i; break; } double ***tmp_pointer = flag == 0 ? synth->spectrogram : synth->aperiodicity; *front = tmp_pointer[pointer][index]; *next = index == synth->f0_length[pointer] - 1 ? tmp_pointer[(synth->current_pointer2 + 1) % synth->number_of_pointers][0] : tmp_pointer[pointer][index + 1]; } //----------------------------------------------------------------------------- // RemoveDCComponent() //----------------------------------------------------------------------------- static void RemoveDCComponent(const double *periodic_response, int fft_size, const double *dc_remover, double *new_periodic_response) { double dc_component = 0.0; for (int i = fft_size / 2; i < fft_size; ++i) dc_component += periodic_response[i]; for (int i = 0; i < fft_size / 2; ++i) new_periodic_response[i] = 0.0; for (int i = fft_size / 2; i < fft_size; ++i) new_periodic_response[i] -= dc_component * dc_remover[i - fft_size / 2]; } //----------------------------------------------------------------------------- // GetPeriodicResponse() calculates an aperiodic response. //----------------------------------------------------------------------------- static void GetPeriodicResponse(int fft_size, const double *spectrum, const double *aperiodic_ratio, double current_vuv, const InverseRealFFT *inverse_real_fft, const MinimumPhaseAnalysis *minimum_phase, const double *dc_remover, double *periodic_response) { if (current_vuv <= 0.5 || aperiodic_ratio[0] > 0.999) { for (int i = 0; i < fft_size; ++i) periodic_response[i] = 0.0; return; } for (int i = 0; i <= minimum_phase->fft_size / 2; ++i) minimum_phase->log_spectrum[i] = log(spectrum[i] * (1.0 - aperiodic_ratio[i]) + world::kMySafeGuardMinimum) / 2.0; GetMinimumPhaseSpectrum(minimum_phase); for (int i = 0; i <= fft_size / 2; ++i) { inverse_real_fft->spectrum[i][0] = minimum_phase->minimum_phase_spectrum[i][0]; inverse_real_fft->spectrum[i][1] = minimum_phase->minimum_phase_spectrum[i][1]; } fft_execute(inverse_real_fft->inverse_fft); fftshift(inverse_real_fft->waveform, fft_size, periodic_response); RemoveDCComponent(periodic_response, fft_size, dc_remover, periodic_response); } static void GetSpectralEnvelope(double current_location, WorldSynthesizer *synth, double *spectral_envelope) { int current_frame_floor = static_cast(current_location / synth->frame_period); int current_frame_ceil = static_cast(ceil(current_location / synth->frame_period)); double interpolation = current_location / synth->frame_period - current_frame_floor; double *front = NULL; double *next = NULL; SearchPointer(current_frame_floor, synth, 0, &front, &next); if (current_frame_floor == current_frame_ceil) for (int i = 0; i <= synth->fft_size / 2; ++i) spectral_envelope[i] = fabs(front[i]); else for (int i = 0; i <= synth->fft_size / 2; ++i) spectral_envelope[i] = (1.0 - interpolation) * fabs(front[i]) + interpolation * fabs(next[i]); } static void GetAperiodicRatio(double current_location, WorldSynthesizer *synth, double *aperiodic_spectrum) { int current_frame_floor = static_cast(current_location / synth->frame_period); int current_frame_ceil = static_cast(ceil(current_location / synth->frame_period)); double interpolation = current_location / synth->frame_period - current_frame_floor; double *front = NULL; double *next = NULL; SearchPointer(current_frame_floor, synth, 1, &front, &next); if (current_frame_floor == current_frame_ceil) for (int i = 0; i <= synth->fft_size / 2; ++i) aperiodic_spectrum[i] = pow(GetSafeAperiodicity(front[i]), 2.0); else for (int i = 0; i <= synth->fft_size / 2; ++i) aperiodic_spectrum[i] = pow((1.0 - interpolation) * GetSafeAperiodicity(front[i]) + interpolation * GetSafeAperiodicity(next[i]), 2.0); } static double GetCurrentVUV(int current_location, WorldSynthesizer *synth) { double current_vuv = 0.0; int pointer = synth->current_pointer % synth->number_of_pointers; int start_sample = MyMaxInt(0, static_cast(ceil((synth->f0_origin[pointer] - 1) * synth->frame_period * synth->fs))); current_vuv = synth->interpolated_vuv[pointer][current_location - start_sample + 1]; return current_vuv; } //----------------------------------------------------------------------------- // GetOneFrameSegment() calculates a periodic and aperiodic response at a time. //----------------------------------------------------------------------------- static void GetOneFrameSegment(int noise_size, int current_location, WorldSynthesizer *synth) { double *aperiodic_response = new double[synth->fft_size]; double *periodic_response = new double[synth->fft_size]; double *spectral_envelope = new double[synth->fft_size]; double *aperiodic_ratio = new double[synth->fft_size]; double tmp_location = static_cast(current_location) / synth->fs; SeekSynthesizer(tmp_location, synth); GetSpectralEnvelope(tmp_location, synth, spectral_envelope); GetAperiodicRatio(tmp_location, synth, aperiodic_ratio); double current_vuv = GetCurrentVUV(current_location, synth); // Synthesis of the periodic response GetPeriodicResponse(synth->fft_size, spectral_envelope, aperiodic_ratio, current_vuv, &synth->inverse_real_fft, &synth->minimum_phase, synth->dc_remover, periodic_response); // Synthesis of the aperiodic response GetAperiodicResponse(noise_size, synth->fft_size, spectral_envelope, aperiodic_ratio, current_vuv, &synth->forward_real_fft, &synth->inverse_real_fft, &synth->minimum_phase, aperiodic_response); double sqrt_noise_size = sqrt(static_cast(noise_size)); for (int i = 0; i < synth->fft_size; ++i) synth->impulse_response[i] = (periodic_response[i] * sqrt_noise_size + aperiodic_response[i]) / synth->fft_size; delete[] spectral_envelope; delete[] aperiodic_ratio; delete[] periodic_response; delete[] aperiodic_response; } static void GetTemporalParametersForTimeBase(const double *f0, int f0_length, WorldSynthesizer *synth, double *coarse_time_axis, double *coarse_f0, double *coarse_vuv) { int cumulative_frame = MyMaxInt(0, synth->cumulative_frame - f0_length); coarse_f0[0] = synth->handoff_f0; coarse_time_axis[0] = cumulative_frame * synth->frame_period; coarse_vuv[0] = synth->handoff_f0 == 0 ? 0.0 : 1.0; for (int i = 0; i < f0_length; ++i) { coarse_time_axis[i + synth->handoff] = (i + cumulative_frame + synth->handoff) * synth->frame_period; coarse_f0[i + synth->handoff] = f0[i]; coarse_vuv[i + synth->handoff] = f0[i] == 0.0 ? 0.0 : 1.0; } } static void GetPulseLocationsForTimeBase(const double *interpolated_f0, const double *time_axis, int number_of_samples, double origin, WorldSynthesizer *synth) { double *total_phase = new double[number_of_samples + synth->handoff]; total_phase[0] = synth->handoff == 1 ? synth->handoff_phase : 2.0 * world::kPi * interpolated_f0[0] / synth->fs; total_phase[1] = total_phase[0] + 2.0 * world::kPi * interpolated_f0[0] / synth->fs; for (int i = 1 + synth->handoff; i < number_of_samples + synth->handoff; ++i) total_phase[i] = total_phase[i - 1] + 2.0 * world::kPi * interpolated_f0[i - synth->handoff] / synth->fs; synth->handoff_phase = total_phase[number_of_samples - 1 + synth->handoff]; double *wrap_phase = new double[number_of_samples + synth->handoff]; for (int i = 0; i < number_of_samples + synth->handoff; ++i) wrap_phase[i] = fmod(total_phase[i], 2.0 * world::kPi); double *wrap_phase_abs = new double[number_of_samples + synth->handoff]; for (int i = 0; i < number_of_samples - 1 + synth->handoff; ++i) wrap_phase_abs[i] = fabs(wrap_phase[i + 1] - wrap_phase[i]); int pointer = synth->head_pointer % synth->number_of_pointers; int number_of_pulses = 0; for (int i = 0; i < number_of_samples - 1 + synth->handoff; ++i) if (wrap_phase_abs[i] > world::kPi) { synth->pulse_locations[pointer][number_of_pulses] = time_axis[i] - static_cast(synth->handoff) / synth->fs; synth->pulse_locations_index[pointer][number_of_pulses] = matlab_round(synth->pulse_locations[pointer][number_of_pulses] * synth->fs); ++number_of_pulses; } synth->number_of_pulses[pointer] = number_of_pulses; if (number_of_pulses != 0) synth->last_location = synth->pulse_locations_index[pointer][number_of_pulses - 1]; delete[] wrap_phase_abs; delete[] wrap_phase; delete[] total_phase; } static void GetTimeBase(const double *f0, int f0_length, int start_sample, int number_of_samples, WorldSynthesizer *synth) { double *coarse_time_axis = new double[f0_length + synth->handoff]; double *coarse_f0 = new double[f0_length + synth->handoff]; double *coarse_vuv = new double[f0_length + synth->handoff]; GetTemporalParametersForTimeBase(f0, f0_length, synth, coarse_time_axis, coarse_f0, coarse_vuv); double *interpolated_f0 = new double[number_of_samples]; double *time_axis = new double[number_of_samples]; for (int i = 0; i < number_of_samples; ++i) time_axis[i] = (i + start_sample) / static_cast(synth->fs); int pointer = synth->head_pointer % synth->number_of_pointers; interp1(coarse_time_axis, coarse_f0, f0_length + synth->handoff, time_axis, number_of_samples, interpolated_f0); interp1(coarse_time_axis, coarse_vuv, f0_length + synth->handoff, time_axis, number_of_samples, synth->interpolated_vuv[pointer]); for (int i = 0; i < number_of_samples; ++i) { synth->interpolated_vuv[pointer][i] = synth->interpolated_vuv[pointer][i] > 0.5 ? 1.0 : 0.0; interpolated_f0[i] = synth->interpolated_vuv[pointer][i] == 0.0 ? world::kDefaultF0 : interpolated_f0[i]; } GetPulseLocationsForTimeBase(interpolated_f0, time_axis, number_of_samples, coarse_time_axis[0], synth); synth->handoff_f0 = interpolated_f0[number_of_samples - 1]; delete[] time_axis; delete[] interpolated_f0; delete[] coarse_time_axis; delete[] coarse_f0; delete[] coarse_vuv; } static int GetNextPulseLocationIndex(WorldSynthesizer *synth) { int pointer = synth->current_pointer % synth->number_of_pointers; if (synth->i < synth->number_of_pulses[pointer] - 1) return synth->pulse_locations_index[pointer][synth->i + 1]; else if (synth->current_pointer == synth->head_pointer - 1) return 0; for (int i = 1; i < synth->number_of_pointers; ++i) { pointer = (i + synth->current_pointer) % synth->number_of_pointers; if (synth->number_of_pulses[pointer] != 0) return synth->pulse_locations_index[pointer][0]; } return 0; } static int UpdateSynthesizer(int current_location, WorldSynthesizer *synth) { int pointer = synth->current_pointer % synth->number_of_pointers; if (synth->i < synth->number_of_pulses[pointer] - 1) { synth->i++; return 1; } else { if (synth->current_pointer == synth->head_pointer - 1) return 0; } for (int i = 1; i < synth->number_of_pointers; ++i) { pointer = (i + synth->current_pointer) % synth->number_of_pointers; if (synth->number_of_pulses[pointer] != 0) { synth->i = 0; synth->current_pointer += i; return 1; } } return 0; } static int CheckSynthesizer(WorldSynthesizer *synth) { if (synth->synthesized_sample + synth->buffer_size >= synth->last_location) return 0; int pointer = synth->current_pointer % synth->number_of_pointers; while (synth->number_of_pulses[pointer] == 0) { if (synth->current_pointer == synth->head_pointer) break; synth->current_pointer++; pointer = synth->current_pointer % synth->number_of_pointers; } return 1; } static void GetDCRemover(int fft_size, double *dc_remover) { double dc_component = 0.0; for (int i = 0; i < fft_size / 2; ++i) { dc_remover[i] = 0.5 - 0.5 * cos(2.0 * world::kPi * (i + 1.0) / (1.0 + fft_size)); dc_remover[fft_size - i - 1] = dc_remover[i]; dc_component += dc_remover[i] * 2.0; } for (int i = 0; i < fft_size / 2; ++i) { dc_remover[i] /= dc_component; dc_remover[fft_size - i - 1] = dc_remover[i]; } } } // namespace void InitializeSynthesizer(int fs, double frame_period, int fft_size, int buffer_size, int number_of_pointers, WorldSynthesizer *synth) { // Set basic parameters synth->fs = fs; synth->frame_period = frame_period / 1000.0; synth->buffer_size = buffer_size; synth->number_of_pointers = number_of_pointers; synth->fft_size = fft_size; // Memory allocations synth->f0_length = new int[number_of_pointers]; synth->spectrogram = new double**[number_of_pointers]; synth->aperiodicity = new double**[number_of_pointers]; synth->interpolated_vuv = new double*[number_of_pointers]; synth->pulse_locations = new double*[number_of_pointers]; synth->pulse_locations_index = new int*[number_of_pointers]; synth->number_of_pulses = new int[number_of_pointers]; synth->f0_origin = new int[number_of_pointers]; for (int i = 0; i < synth->number_of_pointers; ++i) { synth->interpolated_vuv[i] = NULL; synth->pulse_locations[i] = NULL; synth->pulse_locations_index[i] = NULL; } synth->buffer = new double[buffer_size * 2 + fft_size]; synth->impulse_response = new double[synth->fft_size]; synth->dc_remover = new double[synth->fft_size / 2]; // Initilize internal parameters RefreshSynthesizer(synth); InitializeMinimumPhaseAnalysis(fft_size, &synth->minimum_phase); InitializeInverseRealFFT(fft_size, &synth->inverse_real_fft); InitializeForwardRealFFT(fft_size, &synth->forward_real_fft); } int AddParameters(double *f0, int f0_length, double **spectrogram, double **aperiodicity, WorldSynthesizer *synth) { if (synth->head_pointer - synth->current_pointer2 == synth->number_of_pointers) return 0; // Since the queue is full, we cannot add the parameters. int pointer = synth->head_pointer % synth->number_of_pointers; synth->f0_length[pointer] = f0_length; synth->f0_origin[pointer] = synth->cumulative_frame + 1; synth->cumulative_frame += f0_length; synth->spectrogram[pointer] = spectrogram; synth->aperiodicity[pointer] = aperiodicity; if (synth->cumulative_frame < 1) { synth->handoff_f0 = f0[f0_length - 1]; synth->number_of_pulses[pointer] = 0; synth->head_pointer++; synth->handoff = 1; return 1; } int start_sample = MyMaxInt(0, static_cast(ceil((synth->cumulative_frame - f0_length) * synth->frame_period * synth->fs))); int end_sample = static_cast(ceil((synth->cumulative_frame) * synth->frame_period * synth->fs)); int number_of_samples = end_sample - start_sample; // Memory allocation synth->interpolated_vuv[pointer] = new double[number_of_samples + 1]; synth->pulse_locations[pointer] = new double[number_of_samples]; synth->pulse_locations_index[pointer] = new int[number_of_samples]; GetTimeBase(f0, f0_length, start_sample, number_of_samples, synth); synth->handoff_f0 = f0[f0_length - 1]; synth->head_pointer++; synth->handoff = 1; return 1; } void RefreshSynthesizer(WorldSynthesizer *synth) { ClearRingBuffer(0, synth->number_of_pointers, synth); synth->handoff_phase = 0; synth->handoff_f0 = 0; synth->cumulative_frame = -1; synth->last_location = 0; synth->current_pointer = 0; synth->current_pointer2 = 0; synth->head_pointer = 0; synth->handoff = 0; synth->i = 0; synth->current_frame = 0; synth->synthesized_sample = 0; for (int i = 0; i < synth->buffer_size * 2 + synth->fft_size; ++i) synth->buffer[i] = 0; GetDCRemover(synth->fft_size / 2, synth->dc_remover); } void DestroySynthesizer(WorldSynthesizer *synth) { RefreshSynthesizer(synth); delete[] synth->f0_length; delete[] synth->spectrogram; delete[] synth->aperiodicity; delete[] synth->buffer; delete[] synth->impulse_response; delete[] synth->dc_remover; delete[] synth->interpolated_vuv; delete[] synth->pulse_locations; delete[] synth->pulse_locations_index; delete[] synth->number_of_pulses; delete[] synth->f0_origin; DestroyMinimumPhaseAnalysis(&synth->minimum_phase); DestroyInverseRealFFT(&synth->inverse_real_fft); DestroyForwardRealFFT(&synth->forward_real_fft); } int IsLocked(WorldSynthesizer *synth) { int judge = 0; if (synth->head_pointer - synth->current_pointer2 == synth->number_of_pointers) judge++; if (synth->synthesized_sample + synth->buffer_size >= synth->last_location) judge++; return judge == 2 ? 1 : 0; } int Synthesis2(WorldSynthesizer *synth) { if (CheckSynthesizer(synth) == 0) return 0; for (int i = 0; i < synth->buffer_size + synth->fft_size; ++i) synth->buffer[i] = synth->buffer[i + synth->buffer_size]; int pointer = synth->current_pointer % synth->number_of_pointers; int noise_size, offset, tmp, index; int current_location = synth->pulse_locations_index[pointer][synth->i]; while (current_location < synth->synthesized_sample + synth->buffer_size) { tmp = GetNextPulseLocationIndex(synth); noise_size = tmp - current_location; GetOneFrameSegment(noise_size, current_location, synth); offset = current_location - synth->synthesized_sample - synth->fft_size / 2 + 1; for (int i = MyMaxInt(0, -offset); i < synth->fft_size; ++i) { index = i + offset; synth->buffer[index] += synth->impulse_response[i]; } current_location = tmp; UpdateSynthesizer(current_location, synth); } synth->synthesized_sample += synth->buffer_size; SeekSynthesizer(synth->synthesized_sample, synth); return 1; } ================================================ FILE: libtts/Modules/Lib/World/src/world/cheaptrick.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_CHEAPTRICK_H_ #define WORLD_CHEAPTRICK_H_ #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Struct for CheapTrick //----------------------------------------------------------------------------- typedef struct { double q1; double f0_floor; int fft_size; } CheapTrickOption; //----------------------------------------------------------------------------- // CheapTrick() calculates the spectrogram that consists of spectral envelopes // estimated by CheapTrick. // // Input: // x : Input signal // x_length : Length of x // fs : Sampling frequency // temporal_positions : Time axis // f0 : F0 contour // f0_length : Length of F0 contour // option : Struct to order the parameter for CheapTrick // // Output: // spectrogram : Spectrogram estimated by CheapTrick. //----------------------------------------------------------------------------- void CheapTrick(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, const CheapTrickOption *option, double **spectrogram); //----------------------------------------------------------------------------- // InitializeCheapTrickOption allocates the memory to the struct and sets the // default parameters. // // Input: // fs : Sampling frequency // // Output: // option : Struct for the optional parameter //----------------------------------------------------------------------------- void InitializeCheapTrickOption(int fs, CheapTrickOption *option); //----------------------------------------------------------------------------- // GetFFTSizeForCheapTrick() calculates the FFT size based on the sampling // frequency and the lower limit of f0 (kFloorF0 defined in constantnumbers.h). // // Input: // fs : Sampling frequency // option : Option struct containing the lower f0 limit // // Output: // FFT size //----------------------------------------------------------------------------- int GetFFTSizeForCheapTrick(int fs, const CheapTrickOption *option); //----------------------------------------------------------------------------- // GetF0FloorForCheapTrick() calculates actual lower f0 limit for CheapTrick // based on the sampling frequency and FFT size used. Whenever f0 is below // this threshold the spectrum will be analyzed as if the frame is unvoiced // (using kDefaultF0 defined in constantnumbers.h). // // Input: // fs : Sampling frequency // fft_size : FFT size // // Output: // Lower f0 limit (Hz) //----------------------------------------------------------------------------- double GetF0FloorForCheapTrick(int fs, int fft_size); WORLD_END_C_DECLS #endif // WORLD_CHEAPTRICK_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/codec.h ================================================ //----------------------------------------------------------------------------- // Copyright 2017 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_CODEC_H_ #define WORLD_CODEC_H_ #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // GetNumberOfAperiodicities provides the number of dimensions for aperiodicity // coding. It is determined by only fs. // // Input: // fs : Sampling frequency // // Output: // Number of aperiodicities //----------------------------------------------------------------------------- int GetNumberOfAperiodicities(int fs); //----------------------------------------------------------------------------- // CodeAperiodicity codes the aperiodicity. The number of dimensions is // determined by fs. // // Input: // aperiodicity : Aperiodicity before coding // f0_length : Length of F0 contour // fs : Sampling frequency // fft_size : FFT size // // Output: // coded_aperiodicity : Coded aperiodicity //----------------------------------------------------------------------------- void CodeAperiodicity(const double * const *aperiodicity, int f0_length, int fs, int fft_size, double **coded_aperiodicity); //----------------------------------------------------------------------------- // DecodeAperiodicity decodes the coded aperiodicity. // // Input: // coded_aperiodicity : Coded aperiodicity // f0_length : Length of F0 contour // fs : Sampling frequency // fft_size : FFT size // // Output: // aperiodicity : Decoded aperiodicity //----------------------------------------------------------------------------- void DecodeAperiodicity(const double * const *coded_aperiodicity, int f0_length, int fs, int fft_size, double **aperiodicity); //----------------------------------------------------------------------------- // CodeSpectralEnvelope codes the spectral envelope. // // Input: // aperiodicity : Aperiodicity before coding // f0_length : Length of F0 contour // fs : Sampling frequency // fft_size : FFT size // number_of_dimensions : Parameter for compression // // Output: // coded_spectral_envelope //----------------------------------------------------------------------------- void CodeSpectralEnvelope(const double * const *spectrogram, int f0_length, int fs, int fft_size, int number_of_dimensions, double **coded_spectral_envelope); //----------------------------------------------------------------------------- // DecodeSpectralEnvelope decodes the coded spectral envelope. // // Input: // coded_aperiodicity : Coded aperiodicity // f0_length : Length of F0 contour // fs : Sampling frequency // fft_size : FFT size // number_of_dimensions : Parameter for compression // // Output: // spectrogram //----------------------------------------------------------------------------- void DecodeSpectralEnvelope(const double * const *coded_spectral_envelope, int f0_length, int fs, int fft_size, int number_of_dimensions, double **spectrogram); WORLD_END_C_DECLS #endif // WORLD_CODEC_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/common.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_COMMON_H_ #define WORLD_COMMON_H_ #include "fft.h" #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Structs on FFT //----------------------------------------------------------------------------- // Forward FFT in the real sequence typedef struct { int fft_size; double *waveform; fft_complex *spectrum; fft_plan forward_fft; } ForwardRealFFT; // Inverse FFT in the real sequence typedef struct { int fft_size; double *waveform; fft_complex *spectrum; fft_plan inverse_fft; } InverseRealFFT; // Inverse FFT in the complex sequence typedef struct { int fft_size; fft_complex *input; fft_complex *output; fft_plan inverse_fft; } InverseComplexFFT; // Minimum phase analysis from logarithmic power spectrum typedef struct { int fft_size; double *log_spectrum; fft_complex *minimum_phase_spectrum; fft_complex *cepstrum; fft_plan inverse_fft; fft_plan forward_fft; } MinimumPhaseAnalysis; //----------------------------------------------------------------------------- // GetSuitableFFTSize() calculates the suitable FFT size. // The size is defined as the minimum length whose length is longer than // the input sample. // // Input: // sample : Length of the input signal // // Output: // Suitable FFT size //----------------------------------------------------------------------------- int GetSuitableFFTSize(int sample); //----------------------------------------------------------------------------- // These four functions are simple max() and min() function // for "int" and "double" type. //----------------------------------------------------------------------------- inline int MyMaxInt(int x, int y) { return x > y ? x : y; } inline double MyMaxDouble(double x, double y) { return x > y ? x : y; } inline int MyMinInt(int x, int y) { return x < y ? x : y; } inline double MyMinDouble(double x, double y) { return x < y ? x : y; } //----------------------------------------------------------------------------- // These functions are used in at least two different .cpp files //----------------------------------------------------------------------------- // DCCorrection interpolates the power under f0 Hz // and is used in CheapTrick() and D4C(). //----------------------------------------------------------------------------- void DCCorrection(const double *input, double current_f0, int fs, int fft_size, double *output); //----------------------------------------------------------------------------- // LinearSmoothing() carries out the spectral smoothing by rectangular window // whose length is width Hz and is used in CheapTrick() and D4C(). //----------------------------------------------------------------------------- void LinearSmoothing(const double *input, double width, int fs, int fft_size, double *output); //----------------------------------------------------------------------------- // NuttallWindow() calculates the coefficients of Nuttall window whose length // is y_length and is used in Dio(), Harvest() and D4C(). //----------------------------------------------------------------------------- void NuttallWindow(int y_length, double *y); //----------------------------------------------------------------------------- // GetSafeAperiodicity() limit the range of aperiodicity from 0.001 to // 0.999999999999 (1 - world::kMySafeGuardMinimum). //----------------------------------------------------------------------------- inline double GetSafeAperiodicity(double x) { return MyMaxDouble(0.001, MyMinDouble(0.999999999999, x)); } //----------------------------------------------------------------------------- // These functions are used to speed up the processing. // Forward FFT void InitializeForwardRealFFT(int fft_size, ForwardRealFFT *forward_real_fft); void DestroyForwardRealFFT(ForwardRealFFT *forward_real_fft); // Inverse FFT void InitializeInverseRealFFT(int fft_size, InverseRealFFT *inverse_real_fft); void DestroyInverseRealFFT(InverseRealFFT *inverse_real_fft); // Inverse FFT (Complex) void InitializeInverseComplexFFT(int fft_size, InverseComplexFFT *inverse_complex_fft); void DestroyInverseComplexFFT(InverseComplexFFT *inverse_complex_fft); // Minimum phase analysis (This analysis uses FFT) void InitializeMinimumPhaseAnalysis(int fft_size, MinimumPhaseAnalysis *minimum_phase); void GetMinimumPhaseSpectrum(const MinimumPhaseAnalysis *minimum_phase); void DestroyMinimumPhaseAnalysis(MinimumPhaseAnalysis *minimum_phase); WORLD_END_C_DECLS #endif // WORLD_COMMON_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/constantnumbers.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // This header file only defines constant numbers used for several function. //----------------------------------------------------------------------------- #ifndef WORLD_CONSTANT_NUMBERS_H_ #define WORLD_CONSTANT_NUMBERS_H_ namespace world { // for Dio() const double kCutOff = 50.0; // for StoneMask() const double kFloorF0StoneMask = 40.0; const double kPi = 3.1415926535897932384; const double kMySafeGuardMinimum = 0.000000000001; const double kEps = 0.00000000000000022204460492503131; const double kFloorF0 = 71.0; const double kCeilF0 = 800.0; const double kDefaultF0 = 500.0; const double kLog2 = 0.69314718055994529; // Maximum standard deviation not to be selected as a best f0. const double kMaximumValue = 100000.0; // Note to me (fs: 48000) // 71 Hz is the limit to maintain the FFT size at 2048. // If we use 70 Hz as FLOOR_F0, the FFT size of 4096 is required. // for D4C() const int kHanning = 1; const int kBlackman = 2; const double kFrequencyInterval = 3000.0; const double kUpperLimit = 15000.0; const double kThreshold = 0.85; const double kFloorF0D4C = 47.0; // for Codec (Mel scale) // S. Stevens & J. Volkmann, // The Relation of Pitch to Frequency: A Revised Scale, // American Journal of Psychology, vol. 53, no. 3, pp. 329-353, 1940. const double kM0 = 1127.01048; const double kF0 = 700.0; const double kFloorFrequency = 40.0; const double kCeilFrequency = 20000.0; } // namespace world #endif // WORLD_CONSTANT_NUMBERS_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/d4c.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_D4C_H_ #define WORLD_D4C_H_ #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Struct for D4C //----------------------------------------------------------------------------- typedef struct { double threshold; } D4COption; //----------------------------------------------------------------------------- // D4C() calculates the aperiodicity estimated by D4C. // // Input: // x : Input signal // x_length : Length of x // fs : Sampling frequency // temporal_positions : Time axis // f0 : F0 contour // f0_length : Length of F0 contour // fft_size : Number of samples of the aperiodicity in one frame. // : It is given by the equation fft_size / 2 + 1. // Output: // aperiodicity : Aperiodicity estimated by D4C. //----------------------------------------------------------------------------- void D4C(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, int fft_size, const D4COption *option, double **aperiodicity); //----------------------------------------------------------------------------- // InitializeD4COption allocates the memory to the struct and sets the // default parameters. // // Output: // option : Struct for the optional parameter. //----------------------------------------------------------------------------- void InitializeD4COption(D4COption *option); WORLD_END_C_DECLS #endif // WORLD_D4C_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/dio.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_DIO_H_ #define WORLD_DIO_H_ #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Struct for DIO //----------------------------------------------------------------------------- typedef struct { double f0_floor; double f0_ceil; double channels_in_octave; double frame_period; // msec int speed; // (1, 2, ..., 12) double allowed_range; // Threshold used for fixing the F0 contour. } DioOption; //----------------------------------------------------------------------------- // DIO // // Input: // x : Input signal // x_length : Length of x // fs : Sampling frequency // option : Struct to order the parameter for DIO // // Output: // temporal_positions : Temporal positions. // f0 : F0 contour. //----------------------------------------------------------------------------- void Dio(const double *x, int x_length, int fs, const DioOption *option, double *temporal_positions, double *f0); //----------------------------------------------------------------------------- // InitializeDioOption allocates the memory to the struct and sets the // default parameters. // // Output: // option : Struct for the optional parameter. //----------------------------------------------------------------------------- void InitializeDioOption(DioOption *option); //----------------------------------------------------------------------------- // GetSamplesForDIO() calculates the number of samples required for Dio(). // // Input: // fs : Sampling frequency [Hz] // x_length : Length of the input signal [Sample]. // frame_period : Frame shift [msec] // // Output: // The number of samples required to store the results of Dio() //----------------------------------------------------------------------------- int GetSamplesForDIO(int fs, int x_length, double frame_period); WORLD_END_C_DECLS #endif // WORLD_DIO_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/fft.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // These functions and variables are defined to use FFT as well as FFTW // Please see fft.cpp to show the detailed information //----------------------------------------------------------------------------- #ifndef WORLD_FFT_H_ #define WORLD_FFT_H_ #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS // Commands for FFT (This is the same as FFTW) #define FFT_FORWARD 1 #define FFT_BACKWARD 2 #define FFT_ESTIMATE 3 // Complex number for FFT typedef double fft_complex[2]; // Struct used for FFT typedef struct { int n; int sign; unsigned int flags; fft_complex *c_in; double *in; fft_complex *c_out; double *out; double *input; int *ip; double *w; } fft_plan; fft_plan fft_plan_dft_1d(int n, fft_complex *in, fft_complex *out, int sign, unsigned int flags); fft_plan fft_plan_dft_c2r_1d(int n, fft_complex *in, double *out, unsigned int flags); fft_plan fft_plan_dft_r2c_1d(int n, double *in, fft_complex *out, unsigned int flags); void fft_execute(fft_plan p); void fft_destroy_plan(fft_plan p); WORLD_END_C_DECLS #endif // WORLD_FFT_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/harvest.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_HARVEST_H_ #define WORLD_HARVEST_H_ #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Struct for Harvest //----------------------------------------------------------------------------- typedef struct { double f0_floor; double f0_ceil; double frame_period; } HarvestOption; //----------------------------------------------------------------------------- // Harvest // // Input: // x : Input signal // x_length : Length of x // fs : Sampling frequency // option : Struct to order the parameter for Harvest // // Output: // temporal_positions : Temporal positions. // f0 : F0 contour. //----------------------------------------------------------------------------- void Harvest(const double *x, int x_length, int fs, const HarvestOption *option, double *temporal_positions, double *f0); //----------------------------------------------------------------------------- // InitializeHarvestOption allocates the memory to the struct and sets the // default parameters. // // Output: // option : Struct for the optional parameter. //----------------------------------------------------------------------------- void InitializeHarvestOption(HarvestOption *option); //----------------------------------------------------------------------------- // GetSamplesForHarvest() calculates the number of samples required for // Harvest(). // // Input: // fs : Sampling frequency [Hz] // x_length : Length of the input signal [Sample] // frame_period : Frame shift [msec] // // Output: // The number of samples required to store the results of Harvest(). //----------------------------------------------------------------------------- int GetSamplesForHarvest(int fs, int x_length, double frame_period); WORLD_END_C_DECLS #endif // WORLD_HARVEST_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/macrodefinitions.h ================================================ //----------------------------------------------------------------------------- // Copyright (c) 2008-2011 The Department of Arts and Culture, // The Government of the Republic of South Africa. // // Contributors: Meraka Institute, CSIR, South Africa. // Giulio Paci. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // // MODIFIED: Giulio Paci // DATE : 22 January 2016 // // Some usefull macros and defines. //----------------------------------------------------------------------------- #ifndef WORLD_MACRODEFINITIONS_H_ #define WORLD_MACRODEFINITIONS_H_ // // @file macrodefinitions.h // Definitions of macros that are common to the whole World engine. // // // @ingroup WorldDefines // @defgroup WorldMacros System Macros // Definitions of macros that are common to the whole World engine. // @{ // // // Defines // // // @def WORLD_BEGIN_C_DECLS // Start block for enclosing C code for inclusion in C++ programs. // This allows C++ programs to include the C header files of the World // engine. @code extern "C" { @endcode // @hideinitializer // // // @def WORLD_END_C_DECLS // End block for enclosing C code for inclusion in C++ programs. // This allows C++ programs to include the C header files of the World // engine. @code } @endcode // @hideinitializer // #undef WORLD_BEGIN_C_DECLS #undef WORLD_END_C_DECLS #ifdef __cplusplus # define WORLD_BEGIN_C_DECLS extern "C" { # define WORLD_END_C_DECLS } #else // !__cplusplus # define WORLD_BEGIN_C_DECLS # define WORLD_END_C_DECLS #endif // __cplusplus // // @def WORLD_API // @hideinitializer // Declares a symbol to be exported for shared library usage. // // // @def WORLD_LOCAL // @hideinitializer // Declares a symbol hidden from other libraries. // // // @def WORLD_PLUGIN_API // @hideinitializer // Declares a symbol to be exported for plug-in usage. // // Generic helper definitions for shared library support #if defined _WIN32 || defined __CYGWIN__ # define WORLD_HELPER_DLL_IMPORT __declspec(dllimport) # define WORLD_HELPER_DLL_EXPORT __declspec(dllexport) # define WORLD_HELPER_DLL_LOCAL #else // ! defined _WIN32 || defined __CYGWIN__ || defined WORLD_WIN32 # if __GNUC__ >= 4 # define WORLD_HELPER_DLL_IMPORT __attribute__ ((visibility("default"))) # define WORLD_HELPER_DLL_EXPORT __attribute__ ((visibility("default"))) # define WORLD_HELPER_DLL_LOCAL __attribute__ ((visibility("hidden"))) # else // ! __GNUC__ >= 4 # define WORLD_HELPER_DLL_IMPORT # define WORLD_HELPER_DLL_EXPORT # define WORLD_HELPER_DLL_LOCAL # endif // __GNUC__ >= 4 #endif // defined _WIN32 || defined __CYGWIN__ || defined WORLD_WIN32 // // WORLD_LIBRARIES_EXPORTS // ---------------------- // WORLD_LIBRARIES_EXPORTS should be defined when compiling a // shared/dynamic library. // // Now we use the generic helper definitions above to define // WORLD_API and WORLD_LOCAL. WORLD_API is used for the public API symbols. // It's either DLL imports or DLL exports (or does nothing for static build) // WORLD_LOCAL is used for non-api symbols. // // WORLD_SRC // ------------------ // WORLD_SRC should be defined when building World (instead of just using it). // #ifdef WORLD_LIBRARIES_EXPORTS # ifdef WORLD_SRC # define WORLD_API WORLD_HELPER_DLL_EXPORT # else // !WORLD_SRC # define WORLD_API WORLD_HELPER_DLL_IMPORT # endif // WORLD_SRC # define WORLD_LOCAL WORLD_HELPER_DLL_LOCAL #else // !WORLD_LIBRARIES_EXPORTS (static library) # define WORLD_API # define WORLD_LOCAL #endif // WORLD_LIBRARIES_EXPORTS // // @} // end documentation // #endif // WORLD_MACRODEFINITIONS_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/matlabfunctions.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_MATLABFUNCTIONS_H_ #define WORLD_MATLABFUNCTIONS_H_ #include "common.h" #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // fftshift() swaps the left and right halves of input vector. // http://www.mathworks.com/help/matlab/ref/fftshift.html // // Input: // x : Input vector // x_length : Length of x // // Output: // y : Swapped vector x // // Caution: // Lengths of index and edges must be the same. //----------------------------------------------------------------------------- void fftshift(const double *x, int x_length, double *y); //----------------------------------------------------------------------------- // histc() counts the number of values in vector x that fall between the // elements in the edges vector (which must contain monotonically // nondecreasing values). n is a length(edges) vector containing these counts. // No elements of x can be complex. // http://www.mathworks.co.jp/help/techdoc/ref/histc.html // // Input: // x : Input vector // x_length : Length of x // edges : Input matrix (1-dimension) // edges_length : Length of edges // // Output: // index : Result counted in vector x // Caution: // Lengths of index and edges must be the same. //----------------------------------------------------------------------------- void histc(const double *x, int x_length, const double *edges, int edges_length, int *index); //----------------------------------------------------------------------------- // interp1() interpolates to find yi, the values of the underlying function Y // at the points in the vector or array xi. x must be a vector. // http://www.mathworks.co.jp/help/techdoc/ref/interp1.html // // Input: // x : Input vector (Time axis) // y : Values at x[n] // x_length : Length of x (Length of y must be the same) // xi : Required vector // xi_length : Length of xi (Length of yi must be the same) // // Output: // yi : Interpolated vector //----------------------------------------------------------------------------- void interp1(const double *x, const double *y, int x_length, const double *xi, int xi_length, double *yi); //----------------------------------------------------------------------------- // decimate() carries out down sampling by both IIR and FIR filters. // Filter coeffiencts are based on FilterForDecimate(). // // Input: // x : Input signal // x_length : Length of x // r : Coefficient used for down sampling // (fs after down sampling is fs/r) // Output: // y : Output signal //----------------------------------------------------------------------------- void decimate(const double *x, int x_length, int r, double *y); //----------------------------------------------------------------------------- // matlab_round() calculates rounding. // // Input: // x : Input value // // Output: // y : Rounded value //----------------------------------------------------------------------------- int matlab_round(double x); //----------------------------------------------------------------------------- // diff() calculates differences and approximate derivatives // http://www.mathworks.co.jp/help/techdoc/ref/diff.html // // Input: // x : Input signal // x_length : Length of x // // Output: // y : Output signal //----------------------------------------------------------------------------- void diff(const double *x, int x_length, double *y); //----------------------------------------------------------------------------- // interp1Q() is the special case of interp1(). // We can use this function, provided that All periods of x-axis is the same. // // Input: // x : Origin of the x-axis // shift : Period of the x-axis // y : Values at x[n] // x_length : Length of x (Length of y must be the same) // xi : Required vector // xi_length : Length of xi (Length of yi must be the same) // // Output: // yi : Interpolated vector // // Caution: // Length of xi and yi must be the same. //----------------------------------------------------------------------------- void interp1Q(double x, double shift, const double *y, int x_length, const double *xi, int xi_length, double *yi); //----------------------------------------------------------------------------- // randn() generates pseudorandom numbers based on xorshift method. // // Output: // A generated pseudorandom number //----------------------------------------------------------------------------- double randn(void); //----------------------------------------------------------------------------- // randn_reseed() forces to seed the pseudorandom generator using initial // values. //----------------------------------------------------------------------------- void randn_reseed(void); //----------------------------------------------------------------------------- // fast_fftfilt() carries out the convolution on the frequency domain. // // Input: // x : Input signal // x_length : Length of x // h : Impulse response // h_length : Length of h // fft_size : Length of FFT // forward_real_fft : Struct to speed up the forward FFT // inverse_real_fft : Struct to speed up the inverse FFT // // Output: // y : Calculated result. //----------------------------------------------------------------------------- void fast_fftfilt(const double *x, int x_length, const double *h, int h_length, int fft_size, const ForwardRealFFT *forward_real_fft, const InverseRealFFT *inverse_real_fft, double *y); //----------------------------------------------------------------------------- // matlab_std() calculates the standard deviation of the input vector. // // Input: // x : Input vector // x_length : Length of x // // Output: // Calculated standard deviation //----------------------------------------------------------------------------- double matlab_std(const double *x, int x_length); WORLD_END_C_DECLS #endif // WORLD_MATLABFUNCTIONS_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/stonemask.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_STONEMASK_H_ #define WORLD_STONEMASK_H_ #include "macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // StoneMask() refines the estimated F0 by Dio() // // Input: // x : Input signal // x_length : Length of the input signal // fs : Sampling frequency // time_axis : Temporal information // f0 : f0 contour // f0_length : Length of f0 // // Output: // refined_f0 : Refined F0 //----------------------------------------------------------------------------- void StoneMask(const double *x, int x_length, int fs, const double *temporal_positions, const double *f0, int f0_length, double *refined_f0); WORLD_END_C_DECLS #endif // WORLD_STONEMASK_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/synthesis.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_SYNTHESIS_H_ #define WORLD_SYNTHESIS_H_ #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // Synthesis() synthesize the voice based on f0, spectrogram and // aperiodicity (not excitation signal). // // Input: // f0 : f0 contour // f0_length : Length of f0 // spectrogram : Spectrogram estimated by CheapTrick // fft_size : FFT size // aperiodicity : Aperiodicity spectrogram based on D4C // frame_period : Temporal period used for the analysis // fs : Sampling frequency // y_length : Length of the output signal (Memory of y has been // allocated in advance) // Output: // y : Calculated speech //----------------------------------------------------------------------------- void Synthesis(const double *f0, int f0_length, const double * const *spectrogram, const double * const *aperiodicity, int fft_size, double frame_period, int fs, int y_length, double *y); WORLD_END_C_DECLS #endif // WORLD_SYNTHESIS_H_ ================================================ FILE: libtts/Modules/Lib/World/src/world/synthesisrealtime.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_SYNTHESISREALTIME_H_ #define WORLD_SYNTHESISREALTIME_H_ #include "world/common.h" #include "world/macrodefinitions.h" WORLD_BEGIN_C_DECLS //----------------------------------------------------------------------------- // A struct for real-time synthesis. // I use no class for compatibility in C language. // Please make a class for encapsulating it as needed. // This synthesizer uses a ring buffer. //----------------------------------------------------------------------------- typedef struct { // Basic parameters int fs; double frame_period; int buffer_size; int number_of_pointers; int fft_size; // Sound buffer for output. The length is buffer_size [sample]. double *buffer; int current_pointer; int i; // For DC removal double *dc_remover; //--------------------------------------------------------------------------- // Followings are internal parameters. // You should not modify them if you are not expert. // Speech parameters in each pointer. int *f0_length; int *f0_origin; double ***spectrogram; double ***aperiodicity; // Note: // This is an extremely rough implementation. // I should optimize this implementation. int current_pointer2; int head_pointer; int synthesized_sample; // Internal parameters. int handoff; double handoff_phase; double handoff_f0; int last_location; int cumulative_frame; int current_frame; double **interpolated_vuv; double **pulse_locations; int **pulse_locations_index; int *number_of_pulses; double *impulse_response; // FFT MinimumPhaseAnalysis minimum_phase; InverseRealFFT inverse_real_fft; ForwardRealFFT forward_real_fft; } WorldSynthesizer; //----------------------------------------------------------------------------- // InitializeSynthesizer() initializes the synthesizer based on basic // parameters. // // Input: // fs : Sampling frequency // frame_period : Frame period (ms) // fft_size : FFT size // buffer_size : Buffer size (sample) // number_of_pointers : The number of elements in the ring buffer // // Output: // synth : Initialized synthesizer //----------------------------------------------------------------------------- void InitializeSynthesizer(int fs, double frame_period, int fft_size, int buffer_size, int number_of_pointers, WorldSynthesizer *synth); //----------------------------------------------------------------------------- // AddParameters() attempts to add speech parameters. // You can add several frames at the same time. // // Input: // f0 : F0 contour with length of f0_length // f0_length : This is associated with the number of frames // spectrogram : Spectrogram // aperiodicity : Aperiodicity // // Output: // synth : Synthesizer // // Return value: // 1: True, 0: False. //----------------------------------------------------------------------------- int AddParameters(double *f0, int f0_length, double **spectrogram, double **aperiodicity, WorldSynthesizer *synth); //----------------------------------------------------------------------------- // RefreshSynthesizer() sets the parameters to default. //----------------------------------------------------------------------------- void RefreshSynthesizer(WorldSynthesizer *synth); //----------------------------------------------------------------------------- // DestroySynthesizer() release the memory. //----------------------------------------------------------------------------- void DestroySynthesizer(WorldSynthesizer *synth); //----------------------------------------------------------------------------- // IsLocked() checks whether the synthesizer is locked or not. // "Lock" is defined as the situation that the ring buffer cannot add // parameters and cannot synthesize the waveform. // It will be caused when the duration calculated by the number of added frames // is below 1 / F0 + buffer_size / fs. // If this function returns True, please refresh the synthesizer. // // Input: // Synth : Synthesizer (pointer) // // Output: // 1: True, 0: False. //----------------------------------------------------------------------------- int IsLocked(WorldSynthesizer *synth); //----------------------------------------------------------------------------- // Synthesis2() generates speech with length of synth->buffer_size sample. // The parameters are automatially updated, and memory is also released. // // Input: // Synth : Synthesizer (pointer) // // Output: // 1: True, 0: False. //----------------------------------------------------------------------------- int Synthesis2(WorldSynthesizer *synth); WORLD_END_C_DECLS #endif // WORLD_SYNTHESISREALTIME_H_ ================================================ FILE: libtts/Modules/Lib/World/tools/audioio.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // .wav input/output functions were modified for compatibility with C language. // Since these functions (wavread() and wavwrite()) are roughly implemented, // we recommend more suitable functions provided by other organizations. // This file is independent of WORLD project and for the test.cpp. //----------------------------------------------------------------------------- #include "./audioio.h" #include #include #include #include #if (defined (__WIN32__) || defined (_WIN32)) && !defined (__MINGW32__) #pragma warning(disable : 4996) #endif namespace { static inline int MyMaxInt(int x, int y) { return x > y ? x : y; } static inline int MyMinInt(int x, int y) { return x < y ? x : y; } //----------------------------------------------------------------------------- // CheckHeader() checks the .wav header. This function can only support the // monaural wave file. This function is only used in waveread(). //----------------------------------------------------------------------------- static int CheckHeader(FILE *fp) { char data_check[5]; fread(data_check, 1, 4, fp); // "RIFF" data_check[4] = '\0'; if (0 != strcmp(data_check, "RIFF")) { printf("RIFF error.\n"); return 0; } fseek(fp, 4, SEEK_CUR); fread(data_check, 1, 4, fp); // "WAVE" if (0 != strcmp(data_check, "WAVE")) { printf("WAVE error.\n"); return 0; } fread(data_check, 1, 4, fp); // "fmt " if (0 != strcmp(data_check, "fmt ")) { printf("fmt error.\n"); return 0; } fread(data_check, 1, 4, fp); // 1 0 0 0 if (!(16 == data_check[0] && 0 == data_check[1] && 0 == data_check[2] && 0 == data_check[3])) { printf("fmt (2) error.\n"); return 0; } fread(data_check, 1, 2, fp); // 1 0 if (!(1 == data_check[0] && 0 == data_check[1])) { printf("Format ID error.\n"); return 0; } fread(data_check, 1, 2, fp); // 1 0 if (!(1 == data_check[0] && 0 == data_check[1])) { printf("This function cannot support stereo file\n"); return 0; } return 1; } //----------------------------------------------------------------------------- // GetParameters() extracts fp, nbit, wav_length from the .wav file // This function is only used in wavread(). //----------------------------------------------------------------------------- static int GetParameters(FILE *fp, int *fs, int *nbit, int *wav_length) { char data_check[5] = {0}; data_check[4] = '\0'; unsigned char for_int_number[4]; fread(for_int_number, 1, 4, fp); *fs = 0; for (int i = 3; i >= 0; --i) *fs = *fs * 256 + for_int_number[i]; // Quantization fseek(fp, 6, SEEK_CUR); fread(for_int_number, 1, 2, fp); *nbit = for_int_number[0]; // Skip until "data" is found. 2011/03/28 while (0 != fread(data_check, 1, 1, fp)) { if (data_check[0] == 'd') { fread(&data_check[1], 1, 3, fp); if (0 != strcmp(data_check, "data")) fseek(fp, -3, SEEK_CUR); else break; } } if (0 != strcmp(data_check, "data")) { printf("data error.\n"); return 0; } fread(for_int_number, 1, 4, fp); // "data" *wav_length = 0; for (int i = 3; i >= 0; --i) *wav_length = *wav_length * 256 + for_int_number[i]; *wav_length /= (*nbit / 8); return 1; } } // namespace void wavwrite(const double *x, int x_length, int fs, int nbit, const char *filename) { FILE *fp = fopen(filename, "wb"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } char text[4] = {'R', 'I', 'F', 'F'}; uint32_t long_number = 36 + x_length * 2; fwrite(text, 1, 4, fp); fwrite(&long_number, 4, 1, fp); text[0] = 'W'; text[1] = 'A'; text[2] = 'V'; text[3] = 'E'; fwrite(text, 1, 4, fp); text[0] = 'f'; text[1] = 'm'; text[2] = 't'; text[3] = ' '; fwrite(text, 1, 4, fp); long_number = 16; fwrite(&long_number, 4, 1, fp); int16_t short_number = 1; fwrite(&short_number, 2, 1, fp); short_number = 1; fwrite(&short_number, 2, 1, fp); long_number = fs; fwrite(&long_number, 4, 1, fp); long_number = fs * 2; fwrite(&long_number, 4, 1, fp); short_number = 2; fwrite(&short_number, 2, 1, fp); short_number = 16; fwrite(&short_number, 2, 1, fp); text[0] = 'd'; text[1] = 'a'; text[2] = 't'; text[3] = 'a'; fwrite(text, 1, 4, fp); long_number = x_length * 2; fwrite(&long_number, 4, 1, fp); int16_t tmp_signal; for (int i = 0; i < x_length; ++i) { tmp_signal = static_cast(MyMaxInt(-32768, MyMinInt(32767, static_cast(x[i] * 32767)))); fwrite(&tmp_signal, 2, 1, fp); } fclose(fp); } int GetAudioLength(const char *filename) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { return 0; } if (0 == CheckHeader(fp)) { fclose(fp); return -1; } char data_check[5] = { 0 }; data_check[4] = '\0'; unsigned char for_int_number[4]; // Quantization fseek(fp, 10, SEEK_CUR); fread(for_int_number, 1, 2, fp); int nbit = for_int_number[0]; while (0 != fread(data_check, 1, 1, fp)) { if ('d' == data_check[0]) { fread(&data_check[1], 1, 3, fp); if (0 != strcmp(data_check, "data")) fseek(fp, -3, SEEK_CUR); else break; } } if (0 != strcmp(data_check, "data")) { fclose(fp); return -1; } fread(for_int_number, 1, 4, fp); // "data" fclose(fp); int wav_length = 0; for (int i = 3; i >= 0; --i) wav_length = wav_length * 256 + for_int_number[i]; wav_length /= (nbit / 8); return wav_length; } void wavread(const char* filename, int *fs, int *nbit, double *x) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File not found.\n"); return; } if (0 == CheckHeader(fp)) { fclose(fp); return; } int x_length; if (0 == GetParameters(fp, fs, nbit, &x_length)) { fclose(fp); return; } int quantization_byte = *nbit / 8; double zero_line = pow(2.0, *nbit - 1); double tmp, sign_bias; unsigned char for_int_number[4]; for (int i = 0; i < x_length; ++i) { sign_bias = tmp = 0.0; fread(for_int_number, 1, quantization_byte, fp); // "data" if (for_int_number[quantization_byte-1] >= 128) { sign_bias = pow(2.0, *nbit - 1); for_int_number[quantization_byte - 1] = for_int_number[quantization_byte - 1] & 0x7F; } for (int j = quantization_byte - 1; j >= 0; --j) tmp = tmp * 256.0 + for_int_number[j]; x[i] = (tmp - sign_bias) / zero_line; } fclose(fp); } ================================================ FILE: libtts/Modules/Lib/World/tools/audioio.h ================================================ //----------------------------------------------------------------------------- // Copyright 2012 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_AUDIOIO_H_ #define WORLD_AUDIOIO_H_ #ifdef __cplusplus extern "C" { #endif //----------------------------------------------------------------------------- // wavwrite() write a .wav file. // Input: // x : Input signal // x_ength : Signal length of x [sample] // fs : Sampling frequency [Hz] // nbit : Quantization bit [bit] // filename : Name of the output signal. // Caution: // The variable nbit is not used in this function. // This function only supports the 16 bit. //----------------------------------------------------------------------------- void wavwrite(const double *x, int x_length, int fs, int nbit, const char *filename); //----------------------------------------------------------------------------- // GetAudioLength() returns the length of .wav file. // Input: // filename : Filename of a .wav file. // Output: // The number of samples of the file .wav //----------------------------------------------------------------------------- int GetAudioLength(const char *filename); //----------------------------------------------------------------------------- // wavread() read a .wav file. // The memory of output x must be allocated in advance. // Input: // filename : Filename of the input file. // Output: // fs : Sampling frequency [Hz] // nbit : Quantization bit [bit] // x : The output waveform. //----------------------------------------------------------------------------- void wavread(const char* filename, int *fs, int *nbit, double *x); #ifdef __cplusplus } #endif #endif // WORLD_AUDIOIO_H_ ================================================ FILE: libtts/Modules/Lib/World/tools/parameterio.cpp ================================================ //----------------------------------------------------------------------------- // Copyright 2017 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 // // Save/Load functions for three speech parameters. //----------------------------------------------------------------------------- #include "./parameterio.h" #include #include #include namespace { static void WriteOneParameter(FILE *fp, const char *text, double parameter, int size) { fwrite(text, 1, 4, fp); if (size == 4) { int parameter_int = static_cast(parameter); fwrite(¶meter_int, 4, 1, fp); } else { fwrite(¶meter, 8, 1, fp); } } static void LoadParameters(FILE *fp, int *number_of_frames, int *fft_size, int *number_of_dimensions) { char data_check[12]; fread(&data_check, 1, 4, fp); // NOF fread(number_of_frames, 4, 1, fp); fread(&data_check, 1, 12, fp); // FP (skipped) fread(&data_check, 1, 4, fp); // FFT fread(fft_size, 4, 1, fp); fread(&data_check, 1, 4, fp); // NOD fread(number_of_dimensions, 4, 1, fp); *number_of_dimensions = *number_of_dimensions == 0 ? *fft_size / 2 + 1 : *number_of_dimensions; fread(&data_check, 1, 8, fp); // FS (skipped) } static int CheckHeader(FILE *fp, const char *text) { char data_check[5]; fread(data_check, 1, 4, fp); // "F0 " data_check[4] = '\0'; if (0 != strcmp(data_check, text)) { printf("Header error.\n"); fclose(fp); return 0; } return 1; } } // namespace void WriteF0(const char *filename, int f0_length, double frame_period, const double *temporal_positions, const double *f0, int text_flag) { if (text_flag == 1) { FILE *fp = fopen(filename, "w"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } for (int i = 0; i < f0_length; ++i) fprintf(fp, "%.5f %.5f\r\n", temporal_positions[i], f0[i]); fclose(fp); } else { FILE *fp = fopen(filename, "wb"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } // Header fwrite("F0 ", 1, 4, fp); // Parameters WriteOneParameter(fp, "NOF ", f0_length, 4); WriteOneParameter(fp, "FP ", frame_period, 8); // Data fwrite(f0, 8, f0_length, fp); fclose(fp); } } int ReadF0(const char *filename, double *temporal_positions, double *f0) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File cannot be opened.\n"); return 0; } // Header if (CheckHeader(fp, "F0 ") == 0) return 0; // Parameters char data_check[5]; fread(data_check, 1, 4, fp); // "NOF " int number_of_frames; fread(&number_of_frames, 4, 1, fp); fread(data_check, 1, 4, fp); // "FP " double frame_period; fread(&frame_period, 8, 1, fp); // Data fread(f0, 8, number_of_frames, fp); fclose(fp); for (int i = 0; i < number_of_frames; ++i) temporal_positions[i] = i / 1000.0 * frame_period; return 1; } double GetHeaderInformation(const char *filename, const char *parameter) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File cannot be opened.\n"); return 0; } char data_check[5]; data_check[4] = '\0'; for (int i = 0; i < 13; ++i) { fread(data_check, 1, 4, fp); if (0 != strcmp(data_check, parameter)) continue; if (0 == strcmp(parameter, "FP ")) { double answer; fread(&answer, 8, 1, fp); fclose(fp); return answer; } else { int answer; fread(&answer, 4, 1, fp); fclose(fp); return static_cast(answer); } } return 0; } void WriteSpectralEnvelope(const char *filename, int fs, int f0_length, double frame_period, int fft_size, int number_of_dimensions, const double * const *spectrogram) { FILE *fp = fopen(filename, "wb"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } // Header fwrite("SPEC", 1, 4, fp); // Parameters WriteOneParameter(fp, "NOF ", f0_length, 4); WriteOneParameter(fp, "FP ", frame_period, 8); WriteOneParameter(fp, "FFT ", fft_size, 4); WriteOneParameter(fp, "NOD ", number_of_dimensions, 4); WriteOneParameter(fp, "FS ", fs, 4); number_of_dimensions = number_of_dimensions == 0 ? fft_size / 2 + 1 : number_of_dimensions; // Data for (int i = 0; i < f0_length; ++i) fwrite(spectrogram[i], 8, number_of_dimensions, fp); fclose(fp); } int ReadSpectralEnvelope(const char *filename, double **spectrogram) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File cannot be opened.\n"); return 0; } // Header if (CheckHeader(fp, "SPEC") == 0) return 0; // Parameters int number_of_frames, fft_size, number_of_dimensions; LoadParameters(fp, &number_of_frames, &fft_size, &number_of_dimensions); // Data for (int i = 0; i < number_of_frames; ++i) fread(spectrogram[i], 8, number_of_dimensions, fp); fclose(fp); return 1; } void WriteAperiodicity(const char *filename, int fs, int f0_length, double frame_period, int fft_size, int number_of_dimensions, const double * const *aperiodicity) { FILE *fp = fopen(filename, "wb"); if (NULL == fp) { printf("File cannot be opened.\n"); return; } // Header fwrite("AP ", 1, 4, fp); // Parameters WriteOneParameter(fp, "NOF ", f0_length, 4); WriteOneParameter(fp, "FP ", frame_period, 8); WriteOneParameter(fp, "FFT ", fft_size, 4); WriteOneParameter(fp, "NOD ", number_of_dimensions, 4); WriteOneParameter(fp, "FS ", fs, 4); number_of_dimensions = number_of_dimensions == 0 ? fft_size / 2 + 1 : number_of_dimensions; // Data for (int i = 0; i < f0_length; ++i) fwrite(aperiodicity[i], 8, number_of_dimensions, fp); fclose(fp); } int ReadAperiodicity(const char *filename, double **aperiodicity) { FILE *fp = fopen(filename, "rb"); if (NULL == fp) { printf("File cannot be opened.\n"); return 0; } // Header if (CheckHeader(fp, "AP ") == 0) return 0; // Parameters int number_of_frames, fft_size, number_of_dimensions; LoadParameters(fp, &number_of_frames, &fft_size, &number_of_dimensions); // Data for (int i = 0; i < number_of_frames; ++i) fread(aperiodicity[i], 8, number_of_dimensions, fp); fclose(fp); return 1; } ================================================ FILE: libtts/Modules/Lib/World/tools/parameterio.h ================================================ //----------------------------------------------------------------------------- // Copyright 2017 Masanori Morise // Author: mmorise [at] meiji.ac.jp (Masanori Morise) // Last update: 2021/02/15 //----------------------------------------------------------------------------- #ifndef WORLD_PARAMETERIO_H_ #define WORLD_PARAMETERIO_H_ #ifdef __cplusplus extern "C" { #endif //----------------------------------------------------------------------------- // WriteF0() writes the F0 contour. // // Input: // filename : Filename used for file output // f0_length : Length of F0 contour // frame_period : Frame shift used for analysis // temporal_positions : Time axis // f0 : F0 contour // text_flag : The file is written as text (NOT binary). //----------------------------------------------------------------------------- void WriteF0(const char *filename, int f0_length, double frame_period, const double *temporal_positions, const double *f0, int text_flag); //----------------------------------------------------------------------------- // ReadF0() reads the F0 contour from a file.. // // Input: // filename : Filename used for file output // // Output: // temporal_positions : Time axis // f0 : F0 contour // // Note: Memory must be allocated before calling this function. //----------------------------------------------------------------------------- int ReadF0(const char *filename, double *temporal_positions, double *f0); //----------------------------------------------------------------------------- // GetHeaderInformation() reads a parameter from a file. // // Input: // filename : Filename used for file output // parameter : Required parameter // : "NOF ": number of samples (int) // : "FP ": frame shift (double) // : "FFT ": FFT size (int) // : "NOD ": number of dimensions (int) // : "FS ": sampling frequency // // Note: F0 does not include "FFT ", "NOD ", and "FS ". // These are ignored in cases where they are used for F0 file. //----------------------------------------------------------------------------- double GetHeaderInformation(const char *filename, const char *parameter); //----------------------------------------------------------------------------- // WriteSpectralEnvelope() writes the spectral envelope. // // Input: // filename : Filename used for file output // fs : Sampling frequency // f0_length : Length of F0 contour // frame_period : Frame shift used for analysis // fft_size : FFT size used for analysis // number_of_dimensions : Number of dimensions per frame // spectrogram : Spectral envelope estimated by CheapTrick //----------------------------------------------------------------------------- void WriteSpectralEnvelope(const char *filename, int fs, int f0_length, double frame_period, int fft_size, int number_of_dimensions, const double * const *spectrogram); //----------------------------------------------------------------------------- // ReadSpectralEnvelope() reads the spectral envelope from a file. // // Input: // filename : Filename used for file output // // Output: // spectrogram : Spectral envelope estimated by CheapTrick // // Note: Memory must be allocated before calling this function. //----------------------------------------------------------------------------- int ReadSpectralEnvelope(const char *filename, double **spectrogram); //----------------------------------------------------------------------------- // WriteAperiodicity() writes the aperiodicity. // // Input: // filename : Filename used for file output // fs : Sampling frequency // f0_length : Length of F0 contour // frame_period : Frame shift used for analysis // fft_size : FFT size used for analysis // number_of_dimensions : Number of dimensions per frame // spectrogram : Spectral envelope estimated by CheapTrick //----------------------------------------------------------------------------- void WriteAperiodicity(const char *filename, int fs, int f0_length, double frame_period, int fft_size, int number_of_dimensions, const double * const *aperiodicity); //----------------------------------------------------------------------------- // ReadAperiodicity() reads the aperiodicity from a file. // // Input: // filename : Filename used for file output // // Output: // spectrogram : Spectral envelope estimated by CheapTrick // // Note: Memory must be allocated before calling this function. //----------------------------------------------------------------------------- int ReadAperiodicity(const char *filename, double **aperiodicity); #ifdef __cplusplus } #endif #endif // WORLD_PARAMETERIO_H_ ================================================ FILE: libtts/Modules/Logger/MoeSSLogger.cpp ================================================ #include "MoeSSLogger.hpp" #include #include "../StringPreprocess.hpp" #include namespace MoeSSLogger { Logger MoeVsLogger; inline std::wstring GetCurrentFolder(const std::wstring& defualt = L"") { wchar_t path[1024]; #ifdef _WIN32 GetModuleFileName(nullptr, path, 1024); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); return _curPath; #else //TODO Other System #error Other System ToDO #endif } void RemoveDir(const std::filesystem::directory_entry& dir) { if (!dir.exists()) return; if (dir.is_directory() && !is_empty(dir)) { const std::filesystem::directory_iterator dirs(dir); for (const auto& i : dirs) RemoveDir(i); } remove(dir); } Logger::~Logger() { if (log_file) fclose(log_file); if (error_file) fclose(error_file); log_file = nullptr; error_file = nullptr; } Logger::Logger() { const std::wstring LogPath = GetCurrentFolder() + L"/log"; const std::filesystem::path logger_path(LogPath); if (!exists(logger_path)) create_directory(logger_path); const std::filesystem::directory_entry logger_path_entry(LogPath); if (logger_path_entry.is_directory()) { time_t curtime; time(&curtime); tm nowtime{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }; localtime_s(&nowtime, &curtime); const std::wstring dir_name = L"libsvc " + std::to_wstring(nowtime.tm_year + 1900) + L'-' + std::to_wstring(nowtime.tm_mon) + L'-' + std::to_wstring(nowtime.tm_mday) + L'-' + std::to_wstring(nowtime.tm_hour) + L'-' + std::to_wstring(nowtime.tm_min) + L'-' + std::to_wstring(nowtime.tm_sec); cur_log_dir = LogPath + L'/' + dir_name; const std::filesystem::directory_iterator logger_path_list(LogPath); std::filesystem::directory_entry remove_dir; size_t log_count = 0; for (const auto& i : logger_path_list) if (i.is_directory() && i.path().filename().wstring().substr(0, 6) == L"libsvc") { if (!log_count || i.last_write_time() < remove_dir.last_write_time()) remove_dir = i; ++log_count; } if (log_count > 10) RemoveDir(remove_dir); if (!exists(cur_log_dir)) create_directory(cur_log_dir); logpath = cur_log_dir; logpath.append("log.txt"); errorpath = cur_log_dir; errorpath.append("error.txt"); } } Logger::Logger(logger_fn error_fn, logger_fn log_fn) { custom_logger_fn = true; cerror_fn = error_fn; cloggerfn = log_fn; } void Logger::log(const std::wstring& format) { std::lock_guard mtx(mx); if (custom_logger_fn) { cloggerfn(format.c_str(), nullptr); return; } if (filelogger) { _wfopen_s(&log_file, logpath.c_str(), L"a+"); if (log_file) { fprintf_s(log_file, "%s\n", to_byte_string(format).c_str()); fclose(log_file); log_file = nullptr; } } else fprintf_s(stdout, "%s\n", to_byte_string(format).c_str()); } void Logger::log(const char* format) { std::lock_guard mtx(mx); if (custom_logger_fn) { cloggerfn(nullptr, format); return; } if (filelogger) { _wfopen_s(&log_file, logpath.c_str(), L"a+"); if (log_file) { fprintf_s(log_file, "%s\n", format); fclose(log_file); log_file = nullptr; } } else fprintf_s(stdout, "%s\n", format); } void Logger::error(const std::wstring& format) { std::lock_guard mtx(mx); if (custom_logger_fn) { cloggerfn(format.c_str(), nullptr); cerror_fn(format.c_str(), nullptr); return; } if (filelogger) { _wfopen_s(&log_file, logpath.c_str(), L"a+"); _wfopen_s(&error_file, errorpath.c_str(), L"a+"); if (log_file) { fprintf(log_file, "[ERROR]%s\n", to_byte_string(format).c_str()); fclose(log_file); log_file = nullptr; } if (error_file) { fprintf(error_file, "[ERROR]%s\n", to_byte_string(format).c_str()); fclose(error_file); error_file = nullptr; } } else fprintf(stdout, "[ERROR]%s\n", to_byte_string(format).c_str()); } void Logger::error(const char* format) { std::lock_guard mtx(mx); if (custom_logger_fn) { cloggerfn(nullptr, format); cerror_fn(nullptr, format); return; } if (filelogger) { _wfopen_s(&log_file, logpath.c_str(), L"a+"); _wfopen_s(&error_file, errorpath.c_str(), L"a+"); if (log_file) { fprintf(log_file, "[ERROR]%s\n", format); fclose(log_file); log_file = nullptr; } if (error_file) { fprintf(error_file, "[ERROR]%s\n", format); fclose(error_file); error_file = nullptr; } } else fprintf(stdout, "[ERROR]%s\n", format); } Logger& GetLogger() { return MoeVsLogger; } } ================================================ FILE: libtts/Modules/Logger/MoeSSLogger.hpp ================================================ #pragma once #include #include "../StringPreprocess.hpp" #include #include #define __MOEVS_DEBUG_MESSAGE(msg) __MOEVS_DEBUG_INFO(__FILE__, __LINE__, msg) #define logger MoeSSLogger::GetLogger() inline std::string __MOEVS_DEBUG_INFO(const char* filename, int line, const char* msg) { return std::string("[In \"") + std::filesystem::path(filename).filename().string() + "\" Line " + std::to_string(line) + "] " + msg; } inline std::wstring __MOEVS_DEBUG_INFO(const char* filename, int line, const wchar_t* msg) { return std::wstring(L"[In \"") + std::filesystem::path(filename).filename().wstring() + L"\" Line " + std::to_wstring(line) + L"] " + msg; } namespace MoeSSLogger { class Logger { public: using logger_fn = void(*)(const wchar_t*, const char*); Logger(); ~Logger(); Logger(logger_fn error_fn, logger_fn log_fn); void log(const std::wstring&); void log(const char*); void error(const std::wstring&); void error(const char*); void enable(bool _filelogger) { filelogger = _filelogger; } private: bool custom_logger_fn = false; std::filesystem::path cur_log_dir, logpath, errorpath; logger_fn cerror_fn = nullptr, cloggerfn = nullptr; FILE* log_file = nullptr, * error_file = nullptr; bool filelogger = true; std::mutex mx; }; Logger& GetLogger(); } ================================================ FILE: libtts/Modules/Models/EnvManager.cpp ================================================ #include "EnvManager.hpp" #ifdef _WIN32 #ifdef MOEVSDMLPROVIDER #include #endif #endif #include #include "../Logger/MoeSSLogger.hpp" #include "../Modules.hpp" MoeVoiceStudioCoreEnvManagerHeader const char* logger_id = "MoeVoiceStudioCore"; void MoeVSOrtLoggingFn(void* param, OrtLoggingLevel severity, const char* category, const char* logid, const char* code_location, const char* message) { std::string ort_message = "["; ort_message += category; ort_message += "; In "; ort_message += code_location; ort_message += "; By"; ort_message += logger_id; ort_message += "] "; ort_message += message; logger.log(ort_message.c_str()); } void MoeVoiceStudioEnv::Destory() { logger.log(L"[Info] Removing Env & Release Memory"); delete GlobalOrtSessionOptions; delete GlobalOrtEnv; delete GlobalOrtMemoryInfo; GlobalOrtSessionOptions = nullptr; GlobalOrtEnv = nullptr; GlobalOrtMemoryInfo = nullptr; if (cuda_option_v2) Ort::GetApi().ReleaseCUDAProviderOptions(cuda_option_v2); cuda_option_v2 = nullptr; logger.log(L"[Info] Complete!"); } void MoeVoiceStudioEnv::Load(unsigned ThreadCount, unsigned DeviceID, unsigned Provider) { if (((Provider != CurProvider) || (Provider == 0 && ThreadCount != CurThreadCount) || ((Provider == 1 || Provider == 2) && DeviceID != CurDeviceID)) && MoeVSModuleManager::GetCurTTSModel()) LibDLVoiceCodecThrow("A Model Has Been Loaded, You Cannot Change Env When A Model Has Been Loaded"); try { if (Provider != CurProvider) Create(ThreadCount, DeviceID, Provider); if (Provider == 0 && ThreadCount != CurThreadCount) Create(ThreadCount, DeviceID, Provider); if ((Provider == 1 || Provider == 2) && DeviceID != CurDeviceID) Create(ThreadCount, DeviceID, Provider); CurProvider = Provider; } catch(std::exception& e) { Destory(); CurThreadCount = unsigned(-1); CurDeviceID = unsigned(-1); CurProvider = unsigned(-1); logger.log(to_wide_string(e.what())); LibDLVoiceCodecThrow(e.what()) } } void MoeVoiceStudioEnv::Create(unsigned ThreadCount_, unsigned DeviceID_, unsigned ExecutionProvider_) { Destory(); logger.log(L"[Info] Creating Env"); switch (ExecutionProvider_) { case 1: { const auto AvailableProviders = Ort::GetAvailableProviders(); bool ret = true; for (const auto& it : AvailableProviders) if (it.find("CUDA") != std::string::npos) ret = false; if (ret) LibDLVoiceCodecThrow("CUDA Provider Not Found") GlobalOrtSessionOptions = new Ort::SessionOptions; #ifdef MoeVSCUDAProviderV1 OrtCUDAProviderOptions cuda_option; cuda_option.device_id = int(DeviceID_); cuda_option.do_copy_in_default_stream = false; GlobalOrtSessionOptions->AppendExecutionProvider_CUDA(cuda_option); #else const OrtApi& ortApi = Ort::GetApi(); if (cuda_option_v2) ortApi.ReleaseCUDAProviderOptions(cuda_option_v2); ortApi.CreateCUDAProviderOptions(&cuda_option_v2); const std::vector keys{ "device_id", "gpu_mem_limit", "arena_extend_strategy", "cudnn_conv_algo_search", "do_copy_in_default_stream", "cudnn_conv_use_max_workspace", "cudnn_conv1d_pad_to_nc1d", "enable_cuda_graph", "enable_skip_layer_norm_strict_mode" }; const std::vector values{ std::to_string(DeviceID_).c_str(), "2147483648", "kNextPowerOfTwo", "EXHAUSTIVE", "1", "1", "1", "0", "0" }; ortApi.UpdateCUDAProviderOptions(cuda_option_v2, keys.data(), values.data(), keys.size()); GlobalOrtSessionOptions->AppendExecutionProvider_CUDA_V2(*cuda_option_v2); //ortApi.ReleaseCUDAProviderOptions(cuda_option_v2); #endif GlobalOrtEnv = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, logger_id, MoeVSOrtLoggingFn, nullptr); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtSessionOptions->SetIntraOpNumThreads((int)std::thread::hardware_concurrency()); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); CurDeviceID = DeviceID_; break; } #ifdef MOEVSDMLPROVIDER case 2: { const auto AvailableProviders = Ort::GetAvailableProviders(); std::string ret; for (const auto& it : AvailableProviders) if (it.find("Dml") != std::string::npos) ret = it; if (ret.empty()) LibDLVoiceCodecThrow("DML Provider Not Found") const OrtApi& ortApi = Ort::GetApi(); const OrtDmlApi* ortDmlApi = nullptr; ortApi.GetExecutionProviderApi("DML", ORT_API_VERSION, reinterpret_cast(&ortDmlApi)); Ort::ThreadingOptions threading_options; threading_options.SetGlobalInterOpNumThreads((int)std::thread::hardware_concurrency()); GlobalOrtEnv = new Ort::Env(threading_options, MoeVSOrtLoggingFn, nullptr, ORT_LOGGING_LEVEL_WARNING, logger_id); GlobalOrtEnv->DisableTelemetryEvents(); GlobalOrtSessionOptions = new Ort::SessionOptions; ortDmlApi->SessionOptionsAppendExecutionProvider_DML(*GlobalOrtSessionOptions, int(DeviceID_)); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtSessionOptions->DisablePerSessionThreads(); GlobalOrtSessionOptions->SetExecutionMode(ORT_SEQUENTIAL); GlobalOrtSessionOptions->DisableMemPattern(); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU)); CurDeviceID = DeviceID_; break; } #endif default: { if (ThreadCount_ == 0) ThreadCount_ = std::thread::hardware_concurrency(); GlobalOrtSessionOptions = new Ort::SessionOptions; GlobalOrtEnv = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, logger_id, MoeVSOrtLoggingFn, nullptr); GlobalOrtSessionOptions->SetIntraOpNumThreads(static_cast(ThreadCount_)); GlobalOrtSessionOptions->SetGraphOptimizationLevel(ORT_ENABLE_ALL); GlobalOrtMemoryInfo = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); CurThreadCount = ThreadCount_; break; } } logger.log(L"[Info] Env Created"); } bool MoeVoiceStudioEnv::IsEnabled() const { return GlobalOrtEnv && GlobalOrtMemoryInfo && GlobalOrtSessionOptions; } MoeVoiceStudioEnv GlobalMoeVSEnv; MoeVoiceStudioEnv& GetGlobalMoeVSEnv() { return GlobalMoeVSEnv; } MoeVoiceStudioCoreEnvManagerEnd ================================================ FILE: libtts/Modules/Models/EnvManager.hpp ================================================ /** * FileName: EnvManager.hpp * Note: MoeVoiceStudioCore 环境管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #define MoeVoiceStudioCoreEnvManagerHeader namespace moevsenv{ #define MoeVoiceStudioCoreEnvManagerEnd } MoeVoiceStudioCoreEnvManagerHeader class MoeVoiceStudioEnv { public: MoeVoiceStudioEnv() = default; ~MoeVoiceStudioEnv() { Destory(); } void Load(unsigned ThreadCount, unsigned DeviceID, unsigned Provider); void Destory(); [[nodiscard]] bool IsEnabled() const; [[nodiscard]] Ort::Env* GetEnv() const { return GlobalOrtEnv; } [[nodiscard]] Ort::SessionOptions* GetSessionOptions() const { return GlobalOrtSessionOptions; } [[nodiscard]] Ort::MemoryInfo* GetMemoryInfo() const { return GlobalOrtMemoryInfo; } [[nodiscard]] int GetCurThreadCount() const { return (int)CurThreadCount; } [[nodiscard]] int GetCurDeviceID() const { return (int)CurDeviceID; } [[nodiscard]] int GetCurProvider() const { return (int)CurProvider; } private: void Create(unsigned ThreadCount_, unsigned DeviceID_, unsigned ExecutionProvider_); Ort::Env* GlobalOrtEnv = nullptr; Ort::SessionOptions* GlobalOrtSessionOptions = nullptr; Ort::MemoryInfo* GlobalOrtMemoryInfo = nullptr; unsigned CurThreadCount = unsigned(-1); unsigned CurDeviceID = unsigned(-1); unsigned CurProvider = unsigned(-1); OrtCUDAProviderOptionsV2* cuda_option_v2 = nullptr; }; MoeVoiceStudioEnv& GetGlobalMoeVSEnv(); MoeVoiceStudioCoreEnvManagerEnd ================================================ FILE: libtts/Modules/Models/header/GPT-SoVits.hpp ================================================ /** * FileName: GPT-SoVits.hpp * Note: MoeVoiceStudioCore GPT-SoVits模型类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2023-11-9 Create */ #pragma once #include "TTS.hpp" MoeVoiceStudioCoreHeader class GptSoVits : public TextToSpeech { public: GptSoVits(const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); GptSoVits(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); void load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback); ~GptSoVits() override; void destory() { delete sessionBert; delete sessionVits; delete sessionSSL; sessionBert = nullptr; sessionVits = nullptr; sessionSSL = nullptr; delete sessionEncoder; delete sessionFDecoder; delete sessionDecoder; sessionEncoder = nullptr; sessionFDecoder = nullptr; sessionDecoder = nullptr; } [[nodiscard]] std::tuple, std::vector> GetBertPhs(const MoeVSProjectSpace::MoeVSTTSSeq& Seq, const MoeVSG2P::Tokenizer& Tokenizer) const; [[nodiscard]] std::vector> Inference(const std::vector& _Input) const override; private: Ort::Session* sessionBert = nullptr; Ort::Session* sessionVits = nullptr; Ort::Session* sessionSSL = nullptr; Ort::Session* sessionEncoder = nullptr; Ort::Session* sessionFDecoder = nullptr; Ort::Session* sessionDecoder = nullptr; int64_t NumLayers = 24; int64_t EmbeddingDim = 512; int64_t EOSId = 1024; std::vector VitsInputNames = { "text_seq", "pred_semantic", "ref_audio" }; const std::vector VitsOutputNames = { "audio" }; std::vector EncoderInputNames = { "ref_seq", "text_seq", "ref_bert", "text_bert", "ssl_content" }; const std::vector EncoderOutputNames = { "x", "prompts" }; std::vector DecoderInputNames = { "iy", "ik", "iv", "iy_emb", "ix_example" }; const std::vector DecoderOutputNames = { "y", "k", "v", "y_emb", "logits", "samples" }; std::vector FDecoderInputNames = { "x", "prompts" }; const std::vector FDecoderOutputNames = { "y", "k", "v", "y_emb", "x_example" }; std::vector SSLInputNames = { "audio" }; const std::vector SSLOutputNames = { "last_hidden_state" }; const std::vector BertInputNames = { "input_ids", "attention_mask", "token_type_ids" }; const std::vector BertInputNames2 = { "input_ids", "attention_mask" }; const std::vector BertInputNames3 = { "input_ids" }; const std::vector BertOutputNames = { "last_hidden_state" }; }; MoeVoiceStudioCoreEnd ================================================ FILE: libtts/Modules/Models/header/ModelBase.hpp ================================================ /** * FileName: ModelBase.hpp * Note: MoeVoiceStudioCore Onnx 模型基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #endif #include "MoeVSProject.hpp" #include "../../InferTools/inferTools.hpp" #define MoeVoiceStudioCoreHeader namespace MoeVoiceStudioCore{ #define MoeVoiceStudioCoreEnd } #define MoeVSNotImplementedError LibDLVoiceCodecThrow("NotImplementedError") #define MoeVSClassName(__Moe__VSClassName) __NAME__CLASS__.emplace_back((__Moe__VSClassName)) #define MoeVSMaxPath 1024 static std::wstring GetCurrentFolder(const std::wstring& defualt = L"") { wchar_t path[MoeVSMaxPath]; #ifdef _WIN32 GetModuleFileName(nullptr, path, MoeVSMaxPath); std::wstring _curPath = path; _curPath = _curPath.substr(0, _curPath.rfind(L'\\')); return _curPath; #else //TODO Other System #error Other System ToDO #endif } MoeVoiceStudioCoreHeader class MoeVoiceStudioModule { public: //进度条回调 using ProgressCallback = std::function; //Provicer enum class ExecutionProviders { CPU = 0, CUDA = 1, #ifdef MOEVSDMLPROVIDER DML = 2 #endif }; static [[nodiscard]] std::vector GetOpenFileNameMoeVS(); static std::vector CutLens(const std::wstring& input); /** * \brief 构造Onnx模型基类 * \param ExecutionProvider_ ExecutionProvider(可以理解为设备) * \param DeviceID_ 设备ID * \param ThreadCount_ 线程数 */ MoeVoiceStudioModule(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_ = 0); virtual ~MoeVoiceStudioModule(); /** * \brief 输入路径推理 * \param _Datas [路径,多个路径使用换行符隔开, 推理文本] * \param _InferParams 推理参数 * \param _SlicerSettings 切片机配置 * \return 输出路径 */ [[nodiscard]] virtual std::vector Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const; /** * \brief 获取采样率 * \return 采样率 */ [[nodiscard]] long GetSamplingRate() const { return _samplingRate; } static float Clamp(float in, float min = -1.f, float max = 1.f) { if (in > max) return max; if (in < min) return min; return in; } protected: //采样率 long _samplingRate = 22050; Ort::Env* env = nullptr; Ort::SessionOptions* session_options = nullptr; Ort::MemoryInfo* memory_info = nullptr; ExecutionProviders _cur_execution_provider = ExecutionProviders::CPU; ProgressCallback _callback; std::vector __NAME__CLASS__ = { L"MoeVoiceStudioModule" }; public: //*******************删除的函数********************// MoeVoiceStudioModule& operator=(MoeVoiceStudioModule&&) = delete; MoeVoiceStudioModule& operator=(const MoeVoiceStudioModule&) = delete; MoeVoiceStudioModule(const MoeVoiceStudioModule&) = delete; MoeVoiceStudioModule(MoeVoiceStudioModule&&) = delete; }; MoeVoiceStudioCoreEnd ================================================ FILE: libtts/Modules/Models/header/MoeVSProject.hpp ================================================ /** * FileName: MoeVSProject.hpp * Note: MoeVoiceStudioCore 项目相关的定义 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include #include #include "../../StringPreprocess.hpp" #include "MJson.h" namespace MoeVSProjectSpace { class FileWrapper { public: FileWrapper() = delete; FileWrapper(const wchar_t* _path, const wchar_t* _mode) { _wfopen_s(&file_, _path, _mode); } ~FileWrapper() { if (file_) fclose(file_); file_ = nullptr; } operator FILE*() const { return file_; } [[nodiscard]] bool IsOpen() const { return file_; } private: FILE* file_ = nullptr; }; using size_type = size_t; struct MoeVSParams { //通用 float NoiseScale = 0.3f; //噪声修正因子 0-10 int64_t Seed = 52468; //种子 int64_t SpeakerId = 0; //角色ID uint64_t SrcSamplingRate = 48000; //源采样率 int64_t SpkCount = 2; //模型角色数 //SVC float IndexRate = 0.f; //索引比 0-1 float ClusterRate = 0.f; //聚类比 0-1 float DDSPNoiseScale = 0.8f; //DDSP噪声修正因子 0-10 float Keys = 0.f; //升降调 -64-64 size_t MeanWindowLength = 2; //均值滤波器窗口大小 1-20 size_t Pndm = 100; //Diffusion加速倍数 2-200 size_t Step = 1000; //Diffusion总步数 200-1000 std::wstring Sampler = L"Pndm"; //Diffusion采样器 std::wstring F0Method = L"Dio"; //F0提取算法 bool UseShallowDiffusion = false; //使用浅扩散 //SVCRTInfer int64_t RTSampleSize = 44100; int64_t CrossFadeLength = 320; //TTS std::vector SpeakerMix; //角色混合比例 float LengthScale = 1.0f; //时长修正因子 float DurationPredictorNoiseScale = 0.8f; //随机时长预测器噪声修正因子 float FactorDpSdp = 0.f; //随机时长预测器与时长预测器混合比例 float GateThreshold = 0.66666f; //Tacotron2解码器EOS阈值 int64_t MaxDecodeStep = 2000; //Tacotron2最大解码步数 std::vector EmotionPrompt; //情感标记 std::wstring PlaceHolderSymbol = L"|"; //音素分隔符 float RestTime = 0.5f; //停顿时间,为负数则直接断开音频并创建新音频 std::string LanguageSymbol = "JP"; //语言 std::wstring AdditionalInfo; //G2P额外信息 std::wstring SpeakerName = L"0"; //角色名 }; struct MoeVSTTSToken { std::wstring Text; //输入文本 std::vector Phonemes; //音素序列 std::vector Tones; //音调序列 std::vector Durations; //时长序列 std::vector Language; //语言序列 MoeVSTTSToken() = default; MoeVSTTSToken(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams); [[nodiscard]] std::wstring Serialization() const; }; struct MoeVSTTSSeq { std::wstring TextSeq; std::vector SlicedTokens; std::vector SpeakerMix; //角色混合比例 std::vector EmotionPrompt; //情感标记 std::wstring PlaceHolderSymbol = L"|"; //音素分隔符 float NoiseScale = 0.3f; //噪声修正因子 0-10 float LengthScale = 1.0f; //时长修正因子 float DurationPredictorNoiseScale = 0.3f; //随机时长预测器噪声修正因子 float FactorDpSdp = 0.3f; //随机时长预测器与时长预测器混合比例 float GateThreshold = 0.66666f; //Tacotron2解码器EOS阈值 int64_t MaxDecodeStep = 2000; //Tacotron2最大解码步数 int64_t Seed = 52468; //种子 float RestTime = 0.5f; //停顿时间,为负数则直接断开音频并创建新音频 std::string LanguageSymbol = "ZH"; //语言标记 std::wstring SpeakerName = L"0"; //角色或名称ID std::wstring AdditionalInfo; //G2P额外信息 MoeVSTTSSeq() = default; MoeVSTTSSeq(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams); [[nodiscard]] std::wstring Serialization() const; bool operator==(const MoeVSTTSSeq& right) const; }; using MoeVSSvcParams = MoeVSParams; using MoeVSTTSParams = MoeVSParams; struct ParamsOffset { std::vector OrgAudio; //std::vector Hidden_Unit; std::vector F0; std::vector Volume; std::vector Speaker; [[nodiscard]] size_type Size() const { return size_type(OrgAudio.size() + F0.size() + Volume.size() + Speaker.size()) * sizeof(size_type); } ParamsOffset() = default; }; } ================================================ FILE: libtts/Modules/Models/header/TTS.hpp ================================================ /** * FileName: TTS.hpp * Note: MoeVoiceStudioCore TTS基类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2023-11-9 Create */ #pragma once #include #include "ModelBase.hpp" #include "../../Logger/MoeSSLogger.hpp" #include "../../InferTools/G2P/MoeVSG2P.hpp" #include "MJson.h" MoeVoiceStudioCoreHeader class TextToSpeech : public MoeVoiceStudioModule { public: using DurationCallback = std::function&)>; TextToSpeech(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_ = 0); /**Preprocess**/ [[nodiscard]] std::vector GetInputSeqs(const MJson& _Input, const MoeVSProjectSpace::MoeVSParams& _InitParams) const; [[nodiscard]] static std::vector GetInputSeqsStatic(const MJson& _Input, const MoeVSProjectSpace::MoeVSParams& _InitParams); [[nodiscard]] std::vector& SpecializeInputSeqs(std::vector& _Seq) const; /**Infer**/ [[nodiscard]] std::vector> Inference(const std::wstring& _Seq, const MoeVSProjectSpace::MoeVSParams& _InferParams = MoeVSProjectSpace::MoeVSParams()) const; [[nodiscard]] std::vector Inference(const std::wstring& _Seq, const MoeVSProjectSpace::MoeVSParams& _InferParams, bool T) const; [[nodiscard]] std::vector> Inference(const MJson& _Inputs, const MoeVSProjectSpace::MoeVSParams& _InferParams = MoeVSProjectSpace::MoeVSParams()) const; [[nodiscard]] virtual std::vector> Inference(const std::vector& _Input) const; [[nodiscard]] std::vector Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const override; [[nodiscard]] std::vector AligPhoneAttn(const std::string& LanguageStr, const std::vector& PhoneSeq, size_t BertSize) const; [[nodiscard]] std::wstring TextNormalize(const std::wstring& _Input, int64_t LanguageId) const; /**MapCast**/ [[nodiscard]] const std::wstring& GetTokenizerNameWithLanguageSymbol(const std::string& LanguageSymbol) const; [[nodiscard]] const MoeVSG2P::Tokenizer& GetTokenizerWithLanguageSymbol(const std::string& LanguageSymbol) const; [[nodiscard]] const MoeVSG2P::Tokenizer& GetTokenizer(const std::wstring& TokenizerName) const; [[nodiscard]] const std::string& GetLanguageSymbolWithLanguageId(int64_t LanguageId) const; [[nodiscard]] int64_t GetLanguageIdWithLanguageSymbol(const std::string& LanguageSymbol) const; [[nodiscard]] int64_t GetBertIdWithLanguageSymbol(const std::string& LanguageSymbol) const; [[nodiscard]] int64_t GetTonesBegin(const std::string& LanguageSymbol) const; [[nodiscard]] int64_t GetTonesBegin(int64_t LanguageId) const; [[nodiscard]] int64_t GetSpeakerIdWithSpeakerName(const std::wstring& SpeakerName) const; [[nodiscard]] int64_t GetBertIndexWithName(const std::wstring& BertName) const; [[nodiscard]] const std::wstring& GetBertNameWithIndex(int64_t Index) const; [[nodiscard]] const std::wstring& GetSpeakerNameWithSpeakerId(int64_t SpeakerID) const; [[nodiscard]] std::vector CleanText(const std::wstring& SrcText, const std::wstring& PlaceholderSymbol, const std::wstring& ExtraInfo, const std::string& LanguageSymbol) const; [[nodiscard]] std::vector CleanedSeq2Indices(const std::vector& Seq) const; ~TextToSpeech() override = default; protected: std::unordered_map SpeakerName2ID; std::unordered_map SpeakerID2Name; std::unordered_map LanguageSymbol2ID = { {"ZH", 0}, {"JP", 1}, {"EN", 2} }; std::unordered_map LanguageID2Symbol = { {0, "ZH"}, {1, "JP"}, {2, "EN"} }; std::unordered_map LanguageSymbol2TonesBegin = { {"ZH", 0}, {"JP", 0}, {"EN", 0} }; std::unordered_map Symbols; std::unordered_map Tokenizers; std::unordered_map Index2BertName; std::unordered_map BertName2Index; std::unordered_map LanguageSymbol2TokenizerName; std::unordered_map LanguageSymbol2BertID; MoeVSG2P::MVSCleaner* Cleaner = nullptr; std::wstring NoneString = L"None"; std::string NoneAString = "None"; std::vector EncoderBertInputNames; public: template void LinearCombination(std::vector& _data, T Value = T(1.0)) const { _data.resize(SpeakerCount, 0.f); if (_data.empty()) { _data = std::vector(1, Value); return; } T Sum = T(0.0); for (const auto& i : _data) Sum += i; if (Sum < T(0.0001)) { _data = std::vector(_data.size(), T(0.0)); _data[0] = Value; return; } Sum *= T(Value); for (auto& i : _data) i /= Sum; } [[nodiscard]] static std::vector> generatePath(float* duration, size_t durationSize, size_t maskSize); [[nodiscard]] static std::vector GetAligments(size_t DstLen, size_t SrcLen); [[nodiscard]] static std::tuple, std::vector> SplitTonesFromTokens(const std::vector& _Src, const std::vector& _ToneRef, int64_t FirstToneIdx, const std::string& LanguageSymbol); [[nodiscard]] static std::vector CleanText(const MoeVSG2P::MVSCleaner* TextCleaner, const std::wstring& SrcText, const std::wstring& PlaceholderSymbol, const std::wstring& ExtraInfo, const std::string& LanguageSymbol); protected: bool AddBlank = true; int64_t SpeakerCount = 1; int64_t UNKID = 0; DurationCallback CustomDurationCallback; }; MoeVoiceStudioCoreEnd ================================================ FILE: libtts/Modules/Models/header/Tacotron.hpp ================================================ #pragma once #include "ModelBase.hpp" INFERCLASSHEADER class Tacotron2 : public TTS { public: Tacotron2(const MJson&, const callback&, const callback_params&, const DurationCallback&, Device _dev = Device::CPU); ~Tacotron2() override; std::vector Inference(std::wstring& _inputLens) const override; [[nodiscard]] std::vector Inference(const MoeVSProject::TTSParams& _input) const override; static void cat(std::vector& tensorA, std::vector& Shape, const MTensor& tensorB) { const int64 n = Shape[1]; for (int64 i = n; i > 0; --i) tensorA.insert(tensorA.begin() + (i * Shape[2]), tensorB.GetTensorData()[i - 1]); ++Shape[2]; } private: Ort::Session* sessionEncoder = nullptr; Ort::Session* sessionDecoderIter = nullptr; Ort::Session* sessionPostNet = nullptr; Ort::Session* sessionGan = nullptr; const std::vector ganIn = { "x" }; const std::vector ganOut = { "audio" }; const std::vector inputNodeNamesSessionEncoder = { "sequences","sequence_lengths" }; const std::vector outputNodeNamesSessionEncoder = { "memory","processed_memory","lens" }; const std::vector inputNodeNamesSessionDecoderIter = { "decoder_input","attention_hidden","attention_cell","decoder_hidden","decoder_cell","attention_weights","attention_weights_cum","attention_context","memory","processed_memory","mask" }; const std::vector outputNodeNamesSessionDecoderIter = { "decoder_output","gate_prediction","out_attention_hidden","out_attention_cell","out_decoder_hidden","out_decoder_cell","out_attention_weights","out_attention_weights_cum","out_attention_context" }; const std::vector inputNodeNamesSessionPostNet = { "mel_outputs" }; const std::vector outputNodeNamesSessionPostNet = { "mel_outputs_postnet" }; }; INFERCLASSEND ================================================ FILE: libtts/Modules/Models/header/Vits.hpp ================================================ /** * FileName: Vits.hpp * Note: MoeVoiceStudioCore Vits模型类 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2023-11-9 Create */ #pragma once #include "TTS.hpp" #include MoeVoiceStudioCoreHeader void SetBertEnabled(bool cond); void DestoryAllBerts(); class EmoLoader { public: static constexpr long startPos = 128; EmoLoader() = default; EmoLoader(const std::wstring& path) { if (emofile) fclose(emofile); emofile = nullptr; _wfopen_s(&emofile, path.c_str(), L"r"); if (!emofile) LibDLVoiceCodecThrow("emoFile not exists") } ~EmoLoader() { if (emofile) fclose(emofile); emofile = nullptr; } void close() { if (emofile) fclose(emofile); emofile = nullptr; } void open(const std::wstring& path) { if (emofile) fclose(emofile); emofile = nullptr; _wfopen_s(&emofile, path.c_str(), L"rb"); if (!emofile) LibDLVoiceCodecThrow("emoFile not exists") } std::vector operator[](long index) const { if (emofile) { fseek(emofile, index * 4096 + startPos, SEEK_SET); char buffer[4096]; const auto buf = reinterpret_cast(buffer); const auto bufread = fread_s(buffer, 4096, 1, 4096, emofile); if (bufread == 4096) return { buf ,buf + 1024 }; LibDLVoiceCodecThrow("emo index out of range") } LibDLVoiceCodecThrow("emo file not opened") } private: FILE* emofile = nullptr; }; class Vits : public TextToSpeech { public: Vits(const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); Vits(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, const std::vector& _BertPaths, ExecutionProviders ExecutionProvider_ = ExecutionProviders::CPU, unsigned DeviceID_ = 0, unsigned ThreadCount_ = 0); void load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, const std::vector& _BertPaths = {}); ~Vits() override; void destory() { delete sessionDec; delete sessionSdp; delete sessionDp; delete sessionEnc_p; delete sessionFlow; delete sessionEmb; sessionDec = nullptr; sessionSdp = nullptr; sessionEnc_p = nullptr; sessionFlow = nullptr; sessionEmb = nullptr; sessionDp = nullptr; } [[nodiscard]] std::vector GetEmotionVector(const std::vector& src) const; [[nodiscard]] std::tuple, std::vector, std::vector, std::vector, std::vector, std::vector, bool> PreProcessSeq(const MoeVSProjectSpace::MoeVSTTSSeq& Seq, int64_t CurLanguageIdx) const; [[nodiscard]] std::vector> Inference(const std::vector& _Input) const override; [[nodiscard]] std::vector Infer(const MoeVSProjectSpace::MoeVSTTSSeq& Seq) const; std::vector GetBertFeature(size_t IndexOfBert, const std::vector& TokenSeq, Ort::Session* CurBertSession) const; protected: Ort::Session* sessionDec = nullptr; Ort::Session* sessionSdp = nullptr; Ort::Session* sessionDp = nullptr; Ort::Session* sessionEnc_p = nullptr; Ort::Session* sessionFlow = nullptr; Ort::Session* sessionEmb = nullptr; std::string VitsType; int64_t DefBertSize = 1024; int64_t VQCodeBookSize = 10; bool UseTone = false; bool UseBert = false; bool UseLength = true; bool UseLanguage = false; bool EncoderG = false; bool ReferenceBert = false; bool UseVQ = false; bool UseClap = false; bool Emotion = false; std::wstring ClapName; private: EmoLoader EmoLoader; std::unordered_map Emo2Id; std::vector EncoderInputNames = { "x" }; const std::vector EncoderOutputNames = { "xout", "m_p", "logs_p", "x_mask" }; std::vector SdpInputNames = { "x", "x_mask", "zin" }; const std::vector SdpOutputNames = { "logw" }; std::vector DpInputNames = { "x", "x_mask" }; const std::vector DpOutputNames = { "logw" }; std::vector FlowInputNames = { "z_p", "y_mask" }; const std::vector FlowOutputNames = { "z" }; std::vector DecInputNames = { "z_in" }; const std::vector DecOutputNames = { "o" }; const std::vector EmbiddingInputNames = { "sid" }; const std::vector EmbiddingOutputNames = { "g" }; const std::vector BertInputNames = { "input_ids", "attention_mask", "token_type_ids" }; const std::vector BertOutputNames = { "last_hidden_state" }; }; MoeVoiceStudioCoreEnd ================================================ FILE: libtts/Modules/Models/src/GPT-SoVits.cpp ================================================ #include "../header/GPT-SoVits.hpp" #include "../../InferTools/inferTools.hpp" #include #include MoeVoiceStudioCoreHeader GptSoVits::~GptSoVits() { logger.log(L"[Info] unloading GptSoVits Models"); destory(); logger.log(L"[Info] GptSoVits Models unloaded"); } GptSoVits::GptSoVits(const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : TextToSpeech(ExecutionProvider_, DeviceID_, ThreadCount_) { //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)"); if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String"); const auto _folder = to_wide_string(_Config["Folder"].GetString()); if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty"); const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; std::map _PathDict; _PathDict["SSL"] = GetCurrentFolder() + L"/Bert/" + L"SSLModel.onnx"; _PathDict["Vits"] = _path + L"_vits.onnx"; _PathDict["Encoder"] = _path + L"_t2s_encoder.onnx"; _PathDict["FDecoder"] = _path + L"_t2s_fsdec.onnx"; _PathDict["Decoder"] = _path + L"_t2s_sdec.onnx"; if (_Config.HasMember("Dict") && _Config["Dict"].IsString() && !_Config["Dict"].Empty()) _PathDict["Dict"] = GetCurrentFolder() + L"/Dict/" + to_wide_string(_Config["Dict"].GetString()) + L".json"; if (_Config.HasMember("BertPath") && _Config["BertPath"].IsString() && !_Config["BertPath"].Empty()) _PathDict["Bert"] = GetCurrentFolder() + L"/Bert/" + to_wide_string(_Config["BertPath"].GetString()); else LibDLVoiceCodecThrow("[Error] Missing field \"BertPath\" (Bert Folder)"); load(_PathDict, _Config, _ProgressCallback, _DurationCallback); } void GptSoVits::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback) { Cleaner = MoeVSG2P::GetDefCleaner(); if (_PathDict.find("Dict") != _PathDict.end() && (_waccess(_PathDict.at("Dict").c_str(), 0) != -1)) Cleaner->loadDict(_PathDict.at("Dict")); else Cleaner->loadDict(L""); if (_Config.HasMember("LanguageMap") && !_Config["LanguageMap"].IsNull()) { for (const auto& CMember : _Config["LanguageMap"].GetMemberArray()) { LanguageSymbol2ID[CMember.first] = CMember.second.GetInt(); LanguageID2Symbol[CMember.second.GetInt()] = CMember.first; } } else logger.log("[Warn] Field \"LanguageMap\" Is Missing, Use Default Value"); //Check SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)"); if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64"); logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); //Check Symbol if (!_Config.HasMember("Symbol") || _Config["Symbol"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Symbol\" (PhSymbol)"); if (_Config.HasMember("AddBlank") && !_Config["AddBlank"].IsNull()) AddBlank = _Config["AddBlank"].GetBool(); else logger.log(L"[Warn] Field \"AddBlank\" Is Missing, Use Default Value"); if (_Config.HasMember("NumLayers") && _Config["NumLayers"].IsInt()) NumLayers = _Config["NumLayers"].GetInt(); else logger.log(L"[Warn] Field \"NumLayers\" Is Missing, Use Default Value"); if (_Config.HasMember("EmbeddingDim") && _Config["EmbeddingDim"].IsInt()) EmbeddingDim = _Config["EmbeddingDim"].GetInt(); else logger.log(L"[Warn] Field \"EmbeddingDim\" Is Missing, Use Default Value"); if (_Config.HasMember("EOSId") && _Config["EOSId"].IsInt()) EOSId = _Config["EOSId"].GetInt(); else logger.log(L"[Warn] Field \"EOSId\" Is Missing, Use Default Value"); //Load Symbol int64_t iter_symb = 0; if (_Config["Symbol"].IsArray()) { logger.log(L"[Info] Use Phs"); if (_Config["Symbol"].Empty()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Can Not Be Empty"); const auto SymbolArr = _Config["Symbol"].GetArray(); if (!SymbolArr[0].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Must Be Array or String"); for (const auto& it : SymbolArr) Symbols.insert({ to_wide_string(it.GetString()), iter_symb++ }); } else { if (!_Config["Symbol"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Must Be Array or String"); logger.log(L"[Info] Use Symbols"); const std::wstring SymbolsStr = to_wide_string(_Config["Symbol"].GetString()); if (SymbolsStr.empty()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Can Not Be Empty"); for (size_t i = 0; i < SymbolsStr.length(); ++i) Symbols.insert({ SymbolsStr.substr(i,1) , iter_symb++ }); } if (_Config.HasMember("Characters") && _Config["Characters"].IsArray()) { SpeakerCount = (int64_t)_Config["Characters"].Size(); int64_t SpkIdx = 0; for (const auto& iterator : _Config["Characters"].GetArray()) SpeakerName2ID[to_wide_string(iterator.GetString())] = SpkIdx++; } try { sessionBert = new Ort::Session(*env, (_PathDict.at("Bert") + L"/model.onnx").c_str(), *session_options); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow(e.what()); } if (_waccess((_PathDict.at("Bert") + L"/Tokenizer.json").c_str(), 0) != -1) { Tokenizers.insert({ L"0" ,_PathDict.at("Bert") + L"/Tokenizer.json" }); Tokenizers[L"0"].BondCleaner(Cleaner); } else if (sessionBert) { delete sessionBert; sessionBert = nullptr; LibDLVoiceCodecThrow("Bert Must Have a Tokenizer"); } _callback = _ProgressCallback; CustomDurationCallback = _DurationCallback; //LoadModels try { logger.log(L"[Info] loading GptSoVits Models"); sessionVits = new Ort::Session(*env, _PathDict.at("Vits").c_str(), *session_options); sessionSSL = new Ort::Session(*env, _PathDict.at("SSL").c_str(), *session_options); sessionEncoder = new Ort::Session(*env, _PathDict.at("Encoder").c_str(), *session_options); sessionDecoder = new Ort::Session(*env, _PathDict.at("Decoder").c_str(), *session_options); sessionFDecoder = new Ort::Session(*env, _PathDict.at("FDecoder").c_str(), *session_options); logger.log(L"[Info] GptSoVits Models loaded"); } catch (Ort::Exception& _exception) { destory(); LibDLVoiceCodecThrow(_exception.what()); } SpeakerCount = 0; } GptSoVits::GptSoVits(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : TextToSpeech(ExecutionProvider_, DeviceID_, ThreadCount_) { load(_PathDict, _Config, _ProgressCallback, _DurationCallback); } std::wregex NCH_Regex(L"[^\\u4e00-\\u9fa5 !@#$%^&*()_+\\-=`~,./;'\\[\\]<>?:\"{}|\\\\。?!,、;:“”‘’『』「」()〔〕【】─…·—~《》〈〉]+"); std::set ZH_Vowel{L'a', L'e', L'i', L'o', L'u', L'A', L'E', L'I', L'O', L'U'}; std::set Byte_Symbol{L',', L'.', L'?', L'/', L'\"', L'\'', L';', L':', L'!', L' ', L'…' }; std::unordered_map ToneRepMap{ { L"[acc_6]", 6 }, { L"[acc_5]", 5 }, { L"[acc_4]", 4 }, { L"[acc_3]", 3 }, { L"[acc_2]", 2 }, { L"[acc_1]", 1 }, { L"[acc_-4]", -4 }, { L"[acc_-3]", -3 }, { L"[acc_-2]", -2 }, { L"[acc_-1]", -1 }, }; std::tuple, std::vector> GptSoVits::GetBertPhs(const MoeVSProjectSpace::MoeVSTTSSeq& Seq, const MoeVSG2P::Tokenizer& Tokenizer) const { std::vector Phonemes; std::vector OutBert; if (sessionBert && Seq.LanguageSymbol == "ZH") { std::vector Bert2Ph; std::vector BertSeq; std::vector GlobalTonesSeq; if (Seq.SlicedTokens.empty()) { std::wstring TextSeq = MoeVSG2P::NormalizeText(Seq.TextSeq, "ZH"); if (std::regex_search(TextSeq, NCH_Regex)) LibDLVoiceCodecThrow("Chinese Sentence ShouldNot Have NonChinese Symbols"); Phonemes = MoeVSG2P::GetDefCleaner()->DictReplace(MoeVSG2P::GetDefCleaner()->G2p(TextSeq, Seq.PlaceHolderSymbol, L"wt", "ZH"), Seq.PlaceHolderSymbol); std::vector LocalTonesSeq; std::vector LocalPhonemeSeq; for (const auto& it : Phonemes) { if (ToneRepMap.find(it) == ToneRepMap.end()) { LocalPhonemeSeq.emplace_back(it); LocalTonesSeq.emplace_back(0); } else if (!LocalTonesSeq.empty()) *(LocalTonesSeq.end() - 1) = ToneRepMap.at(it); } if (LocalTonesSeq.size() != LocalPhonemeSeq.size()) LocalTonesSeq.resize(LocalPhonemeSeq.size(), 0); Phonemes = std::move(LocalPhonemeSeq); GlobalTonesSeq = std::move(LocalTonesSeq); const size_t BertSize = TextSeq.length() + 2, PhoneSize = Phonemes.size(); Bert2Ph.resize(PhoneSize, 0); size_t startFrame = 1; for (size_t iph = 0; iph < Phonemes.size(); ++iph) { if (startFrame == BertSize) LibDLVoiceCodecThrow("AligError"); Bert2Ph[iph] = startFrame; if (!Phonemes[iph].empty() && ZH_Vowel.find(Phonemes[iph][0]) != ZH_Vowel.end()) ++startFrame; else if (Byte_Symbol.find(Phonemes[iph][0]) != Byte_Symbol.end()) ++startFrame; else if (Phonemes[iph] == L"[UNK]") ++startFrame; } BertSeq.resize(BertSize); BertSeq[0] = L"[CLS]"; for (size_t iph = 0; iph < Phonemes.size(); ++iph) if (BertSeq[Bert2Ph[iph]].empty()) BertSeq[Bert2Ph[iph]] = TextSeq[Bert2Ph[iph] - 1]; BertSeq[BertSeq.size() - 1] = L"[SEP]"; } else { size_t startFrame = 1; for(const auto& i : Seq.SlicedTokens) { BertSeq.emplace_back(i.Text); if (i.Text == L"[CLS]") continue; if (i.Text == L"[SEP]") break; if(i.Phonemes.empty()) { if(i.Text.empty()) continue; auto TmpPhonemes = MoeVSG2P::GetDefCleaner()->DictReplace(MoeVSG2P::GetDefCleaner()->G2p(i.Text, Seq.PlaceHolderSymbol, L"wt", "ZH"), Seq.PlaceHolderSymbol); std::vector LocalTonesSeq; std::vector LocalPhonemeSeq; for (const auto& it : TmpPhonemes) { if (ToneRepMap.find(it) == ToneRepMap.end()) { LocalPhonemeSeq.emplace_back(it); LocalTonesSeq.emplace_back(0); } else if (!LocalTonesSeq.empty()) *(LocalTonesSeq.end() - 1) = ToneRepMap.at(it); } if (LocalTonesSeq.size() != LocalPhonemeSeq.size()) LocalTonesSeq.resize(LocalPhonemeSeq.size(), 0); for (auto& ph : LocalPhonemeSeq) { Phonemes.emplace_back(std::move(ph)); Bert2Ph.emplace_back(startFrame); } for (const auto& tones : LocalTonesSeq) GlobalTonesSeq.emplace_back(tones); } else { for (const auto& ph : i.Phonemes) { Phonemes.emplace_back(ph); Bert2Ph.emplace_back(startFrame); } auto LocalTonesSeq = i.Tones; LocalTonesSeq.resize(i.Phonemes.size(), 0); for (const auto& tones : LocalTonesSeq) GlobalTonesSeq.emplace_back(tones); } ++startFrame; } } for (size_t i = 0; i < Phonemes.size(); ++i) { if (GlobalTonesSeq[i] == 5) continue; auto NewPh = Phonemes[i] + std::to_wstring(GlobalTonesSeq[i]); if (GlobalTonesSeq[i] != 0 && Symbols.find(NewPh) != Symbols.end()) Phonemes[i] = std::move(NewPh); } //PromptSeq To Bert Features auto input_ids = Tokenizer(BertSeq); std::vector attention_mask(input_ids.size(), 1), token_type_ids(input_ids.size(), 0); int64_t AttentionShape[2] = { 1, (int64_t)input_ids.size() }; std::vector AttentionInput, AttentionOutput; AttentionInput.emplace_back(Ort::Value::CreateTensor( *memory_info, input_ids.data(), input_ids.size(), AttentionShape, 2)); if (sessionBert->GetInputCount() == 3) AttentionInput.emplace_back(Ort::Value::CreateTensor(*memory_info, attention_mask.data(), attention_mask.size(), AttentionShape, 2)); AttentionInput.emplace_back(Ort::Value::CreateTensor( *memory_info, token_type_ids.data(), token_type_ids.size(), AttentionShape, 2)); logger.log("[Inference] Infer Bert"); try { if (sessionBert->GetInputCount() == 3) { AttentionOutput = sessionBert->Run(Ort::RunOptions{ nullptr }, BertInputNames.data(), AttentionInput.data(), 3, BertOutputNames.data(), 1); } else if (sessionBert->GetInputCount() == 2) { AttentionOutput = sessionBert->Run(Ort::RunOptions{ nullptr }, BertInputNames2.data(), AttentionInput.data(), 2, BertOutputNames.data(), 1); } else { AttentionOutput = sessionBert->Run(Ort::RunOptions{ nullptr }, BertInputNames3.data(), AttentionInput.data(), 1, BertOutputNames.data(), 1); } } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Bert\n") + e.what())) } std::vector BertAligSeq; if (AddBlank) BertAligSeq.emplace_back(0); for(auto i : Bert2Ph) { BertAligSeq.emplace_back(i); if (AddBlank) BertAligSeq.emplace_back(i); } const auto AttnData = AttentionOutput[0].GetTensorData(); for (size_t IndexOfSrcVector = 0; IndexOfSrcVector < BertAligSeq.size(); ++IndexOfSrcVector) OutBert.insert(OutBert.end(), AttnData + BertAligSeq[IndexOfSrcVector] * 1024, AttnData + (BertAligSeq[IndexOfSrcVector] + 1) * 1024); } else { if (Seq.SlicedTokens.empty()) { if (Seq.TextSeq.empty()) return {}; Phonemes = MoeVSG2P::GetDefCleaner()->DictReplace(MoeVSG2P::GetDefCleaner()->G2p(Seq.TextSeq, Seq.PlaceHolderSymbol, Seq.AdditionalInfo, Seq.LanguageSymbol), Seq.PlaceHolderSymbol); } else { for (const auto& i : Seq.SlicedTokens) { if (i.Text == L"[CLS]") continue; if (i.Text == L"[SEP]") break; auto TmpPhonemes = i.Phonemes; if (TmpPhonemes.empty()) { if (i.Text.empty()) continue; TmpPhonemes = MoeVSG2P::GetDefCleaner()->DictReplace(MoeVSG2P::GetDefCleaner()->G2p(i.Text, Seq.PlaceHolderSymbol, Seq.AdditionalInfo, Seq.LanguageSymbol), Seq.PlaceHolderSymbol); } for (auto& ph : TmpPhonemes) Phonemes.emplace_back(ph); } } } //Phoneme To InputSeq std::vector OutPhonemes; if (AddBlank) OutPhonemes.emplace_back(0); for (const auto& i : Phonemes) { if (Symbols.find(i) != Symbols.end()) OutPhonemes.emplace_back(Symbols.at(i)); else OutPhonemes.emplace_back(0); if(AddBlank) OutPhonemes.emplace_back(0); } if (OutBert.empty()) OutBert = std::vector(OutPhonemes.size() * 1024, 0.f); //OutBert = std::vector(OutPhonemes.size() * 1024, 0.f); return { std::move(OutBert), std::move(OutPhonemes) }; } std::vector> GptSoVits::Inference(const std::vector& _Input) const { if (_Input.size() < 3 || _Input[0].TextSeq.empty() || _Input[1].TextSeq.empty()) LibDLVoiceCodecThrow("Input[0] Should Be Reference Text, Input[1] Should Be Reference Path, Input[2:n] Should Be TTS Text"); const auto RefAudio = InferTools::Wav(_Input[1].TextSeq.c_str()); if (RefAudio.getHeader().bitsPerSample != 16 || RefAudio.getHeader().NumOfChan != 1) LibDLVoiceCodecThrow("RefAudio Should Be signed-int16 and mono"); std::vector> PCM; PCM.reserve(_Input.size()); std::vector> _Audio(1); logger.log("[Inference] GptSoVits Inference Begin"); size_t proc = 0; const size_t max_proc = _Input.size() + 2; _callback(proc, max_proc); const auto& Tokenizer = GetTokenizer(L"0"); const auto RefSize = RefAudio.getHeader().Subchunk2Size / 2; const auto RefData = (const int16_t*)RefAudio.getData(); std::vector RefAudioSrc(RefSize); for (size_t i = 0; i < RefSize; ++i) RefAudioSrc[i] = float(*(RefData + i)) / 32768.f; auto RefAudio16K = InferTools::InterpResample(RefAudioSrc, (int)RefAudio.getHeader().SamplesPerSec, 16000, 1.f); auto RefAudioSr = InferTools::InterpResample(RefAudioSrc, (int)RefAudio.getHeader().SamplesPerSec, _samplingRate, 1.f); //Reference SSL logger.log("[Inference] Infer SSL"); const int64_t SSLShape[] = { 1, (int64_t)RefAudio16K.size() }; std::vector SSLInput, SSLOutPut; SSLInput.emplace_back(Ort::Value::CreateTensor(*memory_info, RefAudio16K.data(), RefAudio16K.size(), SSLShape, 2)); try { SSLOutPut = sessionSSL->Run(Ort::RunOptions{ nullptr }, SSLInputNames.data(), SSLInput.data(), SSLInputNames.size(), SSLOutputNames.data(), SSLOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: SSL\n") + e.what())) } _callback(++proc, max_proc); logger.log("[Inference] Infer Ref Data"); auto RefDat = GetBertPhs(_Input[0], Tokenizer); std::vector RefBert = std::move(std::get<0>(RefDat)); std::vector RefSeq = std::move(std::get<1>(RefDat)); int64_t RefSeqShape[] = { 1, (int64_t)RefSeq.size() }; int64_t RefBertShape[] = { RefSeqShape[1], 1024 }; int64_t TempData[] = { 1 }; _callback(++proc, max_proc); std::vector EncoderInpTensor; EncoderInpTensor.emplace_back(Ort::Value::CreateTensor(*memory_info, RefSeq.data(), RefSeq.size(), RefSeqShape, 2)); EncoderInpTensor.emplace_back(Ort::Value::CreateTensor(*memory_info, TempData, 1, TempData, 1)); EncoderInpTensor.emplace_back(Ort::Value::CreateTensor(*memory_info, RefBert.data(), RefBert.size(), RefBertShape, 2)); EncoderInpTensor.emplace_back(Ort::Value::CreateTensor(*memory_info, TempData, 1, TempData, 1)); EncoderInpTensor.emplace_back(std::move(SSLOutPut[0])); for (size_t i = 2; i < _Input.size(); ++i) { const auto& InferSeq = _Input[i]; auto SeqAndBert = GetBertPhs(InferSeq, Tokenizer); std::vector InputBert = std::move(std::get<0>(SeqAndBert)); std::vector InputSeq = std::move(std::get<1>(SeqAndBert)); int64_t SeqShape[] = { 1, (int64_t)InputSeq.size() }; int64_t BertShape[] = { SeqShape[1], 1024 }; EncoderInpTensor[1] = Ort::Value::CreateTensor(*memory_info, InputSeq.data(), InputSeq.size(), SeqShape, 2); EncoderInpTensor[3] = Ort::Value::CreateTensor(*memory_info, InputBert.data(), InputBert.size(), BertShape, 2); std::vector EncoderOutput, FDecoderOutput, DecoderOutput; try { EncoderOutput = sessionEncoder->Run(Ort::RunOptions{ nullptr }, EncoderInputNames.data(), EncoderInpTensor.data(), EncoderInputNames.size(), EncoderOutputNames.data(), EncoderOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Encoder\n") + e.what())) } try { FDecoderOutput = sessionFDecoder->Run(Ort::RunOptions{ nullptr }, FDecoderInputNames.data(), EncoderOutput.data(), FDecoderInputNames.size(), FDecoderOutputNames.data(), FDecoderOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: FDecoder\n") + e.what())) } int64_t idx = 1; for (; idx < InferSeq.MaxDecodeStep; ++idx) { try { DecoderOutput = sessionDecoder->Run(Ort::RunOptions{ nullptr }, DecoderInputNames.data(), FDecoderOutput.data(), DecoderInputNames.size(), DecoderOutputNames.data(), DecoderOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Decoder\n") + e.what())) } const auto Logit = DecoderOutput[4].GetTensorData(); int64_t MaxIdx = 0; for (int64_t midx = 0; midx < EOSId + 1; ++midx) if (Logit[midx] > Logit[MaxIdx]) MaxIdx = midx; if (MaxIdx == EOSId) break; if (*DecoderOutput[5].GetTensorData() == EOSId) break; FDecoderOutput[0] = std::move(DecoderOutput[0]); FDecoderOutput[1] = std::move(DecoderOutput[1]); FDecoderOutput[2] = std::move(DecoderOutput[2]); FDecoderOutput[3] = std::move(DecoderOutput[3]); } auto PredSemanticPtr = DecoderOutput[0].GetTensorData(); auto PredSemanticShape = DecoderOutput[0].GetTensorTypeAndShapeInfo().GetShape(); PredSemanticShape.insert(PredSemanticShape.begin(), 1); std::vector PredSemantic(PredSemanticPtr + max((PredSemanticShape[2] - idx - 1), 0), PredSemanticPtr + PredSemanticShape[2]); if (PredSemantic[PredSemantic.size() - 1] == EOSId) PredSemantic[PredSemantic.size() - 1] = 0; PredSemanticShape[2] = int64_t(PredSemantic.size()); logger.log(L"Size Of PredSemantic: " + std::to_wstring(PredSemantic.size())); std::vector VitsTensors; VitsTensors.emplace_back(std::move(EncoderInpTensor[1])); VitsTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, PredSemantic.data(), PredSemantic.size(), PredSemanticShape.data(), PredSemanticShape.size())); int64_t AudioShape[] = { 1, (int64_t)RefAudioSr.size() }; VitsTensors.emplace_back(Ort::Value::CreateTensor(*memory_info, RefAudioSr.data(), RefAudioSr.size(), AudioShape, 2)); try { VitsTensors = sessionVits->Run(Ort::RunOptions{ nullptr }, VitsInputNames.data(), VitsTensors.data(), VitsInputNames.size(), VitsOutputNames.data(), VitsOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: SoVits\n") + e.what())) } if (!_Audio[0].empty()) { if (InferSeq.RestTime < 0.f) { _Audio[0].insert(_Audio[0].end(), size_t(_samplingRate), 0); PCM.emplace_back(std::move(_Audio[0])); _Audio[0] = std::vector(); } else _Audio[0].insert(_Audio[0].end(), size_t(InferSeq.RestTime * float(_samplingRate)), 0); } const auto shapeOut = VitsTensors[0].GetTensorTypeAndShapeInfo().GetShape(); const auto outData = VitsTensors[0].GetTensorData(); for (int bbb = 0; bbb < shapeOut[0]; bbb++) _Audio[0].emplace_back(static_cast(outData[bbb] * 32768.0f)); _callback(++proc, max_proc); } if (!_Audio[0].empty()) { _Audio[0].insert(_Audio[0].end(), size_t(_samplingRate), 0); PCM.emplace_back(std::move(_Audio[0])); } return PCM; } MoeVoiceStudioCoreEnd ================================================ FILE: libtts/Modules/Models/src/ModelBase.cpp ================================================ #include "../header/ModelBase.hpp" #include #include #include "../EnvManager.hpp" MoeVoiceStudioCoreHeader MoeVoiceStudioModule::MoeVoiceStudioModule(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) { moevsenv::GetGlobalMoeVSEnv().Load(ThreadCount_, DeviceID_, (unsigned)ExecutionProvider_); _cur_execution_provider = ExecutionProvider_; env = moevsenv::GetGlobalMoeVSEnv().GetEnv(); memory_info = moevsenv::GetGlobalMoeVSEnv().GetMemoryInfo(); session_options = moevsenv::GetGlobalMoeVSEnv().GetSessionOptions(); } MoeVoiceStudioModule::~MoeVoiceStudioModule() { env = nullptr; memory_info = nullptr; session_options = nullptr; } std::vector MoeVoiceStudioModule::CutLens(const std::wstring& input) { std::vector _Lens; std::wstring _tmpLen; for (const auto& chari : input) { if ((chari == L'\n') || (chari == L'\r')) { if (!_tmpLen.empty()) { _Lens.push_back(_tmpLen); _tmpLen = L""; } } else { _tmpLen += chari; } } return _Lens; } std::vector MoeVoiceStudioModule::GetOpenFileNameMoeVS() { constexpr long MaxPath = 8000; std::vector OFNLIST; #ifdef WIN32 std::vector szFileName(MaxPath); std::vector szTitleName(MaxPath); OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lpstrFile = szFileName.data(); ofn.nMaxFile = MaxPath; ofn.lpstrFileTitle = szTitleName.data(); ofn.nMaxFileTitle = MaxPath; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = nullptr; constexpr TCHAR szFilter[] = TEXT("Audio (*.wav;*.mp3;*.ogg;*.flac;*.aac)\0*.wav;*.mp3;*.ogg;*.flac;*.aac\0"); ofn.lpstrFilter = szFilter; ofn.lpstrTitle = nullptr; ofn.lpstrDefExt = TEXT("wav"); ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER; if (GetOpenFileName(&ofn)) { auto filePtr = szFileName.data(); std::wstring preFix = filePtr; filePtr += preFix.length() + 1; if (!*filePtr) OFNLIST.emplace_back(preFix); else { preFix += L'\\'; while (*filePtr != 0) { std::wstring thisPath(filePtr); OFNLIST.emplace_back(preFix + thisPath); filePtr += thisPath.length() + 1; } } } if(OFNLIST.empty()) LibDLVoiceCodecThrow("Please Select Files") return OFNLIST; #else #endif } std::vector MoeVoiceStudioModule::Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { MoeVSNotImplementedError } /* int OnnxModule::InsertMessageToEmptyEditBox(std::wstring& _inputLens) { #ifdef WIN32 std::vector szFileName(MaxPath); std::vector szTitleName(MaxPath); OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lpstrFile = szFileName.data(); ofn.nMaxFile = MaxPath; ofn.lpstrFileTitle = szTitleName.data(); ofn.nMaxFileTitle = MaxPath; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = nullptr; constexpr TCHAR szFilter[] = TEXT("Audio (*.wav;*.mp3;*.ogg;*.flac;*.aac)\0*.wav;*.mp3;*.ogg;*.flac;*.aac\0"); ofn.lpstrFilter = szFilter; ofn.lpstrTitle = nullptr; ofn.lpstrDefExt = TEXT("wav"); ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER; if (GetOpenFileName(&ofn)) { auto filePtr = szFileName.data(); std::wstring preFix = filePtr; filePtr += preFix.length() + 1; if (!*filePtr) _inputLens = preFix; else { preFix += L'\\'; while (*filePtr != 0) { std::wstring thisPath(filePtr); _inputLens += preFix + thisPath + L'\n'; filePtr += thisPath.length() + 1; } } } else return -2; return 0; #else #endif } */ /* void OnnxModule::ChangeDevice(Device _dev) { if (_dev == device_) return; device_ = _dev; delete session_options; delete env; delete memory_info; env = nullptr; session_options = nullptr; memory_info = nullptr; switch (_dev) { case Device::CUDA: { const auto AvailableProviders = Ort::GetAvailableProviders(); bool ret = true; for (const auto& it : AvailableProviders) if (it.find("CUDA") != std::string::npos) ret = false; if (ret) LibDLVoiceCodecThrow("CUDA Provider Not Found"); OrtCUDAProviderOptions cuda_option; cuda_option.device_id = int(__MoeVSGPUID); session_options = new Ort::SessionOptions; env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); session_options->AppendExecutionProvider_CUDA(cuda_option); session_options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); session_options->SetIntraOpNumThreads(1); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); break; } #ifdef MOEVSDMLPROVIDER case Device::DML: { const auto AvailableProviders = Ort::GetAvailableProviders(); std::string ret; for (const auto& it : AvailableProviders) if (it.find("Dml") != std::string::npos) ret = it; if (ret.empty()) LibDLVoiceCodecThrow("DML Provider Not Found"); const OrtApi& ortApi = Ort::GetApi(); const OrtDmlApi* ortDmlApi = nullptr; ortApi.GetExecutionProviderApi("DML", ORT_API_VERSION, reinterpret_cast(&ortDmlApi)); const Ort::ThreadingOptions threadingOptions; env = new Ort::Env(threadingOptions, ORT_LOGGING_LEVEL_VERBOSE, ""); env->DisableTelemetryEvents(); session_options = new Ort::SessionOptions; ortDmlApi->SessionOptionsAppendExecutionProvider_DML(*session_options, int(__MoeVSGPUID)); session_options->SetGraphOptimizationLevel(ORT_ENABLE_BASIC); session_options->DisablePerSessionThreads(); session_options->SetExecutionMode(ORT_SEQUENTIAL); session_options->DisableMemPattern(); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU)); break; } #endif default: { session_options = new Ort::SessionOptions; env = new Ort::Env(ORT_LOGGING_LEVEL_WARNING, "OnnxModel"); session_options->SetIntraOpNumThreads(static_cast(__MoeVSNumThreads)); session_options->SetGraphOptimizationLevel(ORT_ENABLE_ALL); memory_info = new Ort::MemoryInfo(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)); break; } } } */ MoeVoiceStudioCoreEnd ================================================ FILE: libtts/Modules/Models/src/MoeVSProject.cpp ================================================ #include "../header/MoeVSProject.hpp" #include #include "../../InferTools/inferTools.hpp" namespace MoeVSProjectSpace { std::wregex _REP_REG_1(L"\\\\"), _REP_REG_2(L"\\\""), _REP_REG_3(L"\r"), _REP_REG_4(L"\n"), _REP_REG_5(L"\t"), _REP_REG_6(L"\b"), _REP_REG_7(L"\f"); std::wstring ReplaceSpecialTokens(const std::wstring& input) { auto output = input; output = std::regex_replace(output, _REP_REG_1, L"\\\\"); output = std::regex_replace(output, _REP_REG_2, L"\\\""); output = std::regex_replace(output, _REP_REG_3, L"\\r"); output = std::regex_replace(output, _REP_REG_4, L"\\b"); output = std::regex_replace(output, _REP_REG_5, L"\\t"); output = std::regex_replace(output, _REP_REG_6, L"\\b"); output = std::regex_replace(output, _REP_REG_7, L"\\f"); return output; } std::vector ReplaceSpecialTokens(const std::vector& input) { std::vector output; output.reserve(input.size()); for (const auto& i : input) output.emplace_back(ReplaceSpecialTokens(i)); return output; } std::vector ReplaceSpecialTokens(const std::vector& input) { std::vector output; output.reserve(input.size()); for (const auto& i : input) output.emplace_back(to_byte_string(ReplaceSpecialTokens(to_wide_string(i)))); return output; } std::wstring MoeVSTTSToken::Serialization() const { if (Text.empty()) return L"\t\t\t{ }"; std::wstring rtn = L"\t\t\t{\n"; rtn += L"\t\t\t\t\"Text\": \"" + ReplaceSpecialTokens(Text) + L"\",\n"; rtn += L"\t\t\t\t\"Phonemes\": " + wstring_vector_to_string(ReplaceSpecialTokens(Phonemes)) + L",\n"; rtn += L"\t\t\t\t\"Tones\": " + vector_to_string(Tones) + L",\n"; rtn += L"\t\t\t\t\"Durations\": " + vector_to_string(Durations) + L",\n"; rtn += L"\t\t\t\t\"Language\": " + string_vector_to_string(ReplaceSpecialTokens(Language)) + L"\n\t\t\t}"; return rtn; } MoeVSTTSToken::MoeVSTTSToken(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams) { if (_JsonDocument.HasMember("Text") && _JsonDocument["Text"].IsString() && !_JsonDocument["Text"].Empty()) Text = to_wide_string(_JsonDocument["Text"].GetString()); else LibDLVoiceCodecThrow("Field \"Text\" Should Not Be Empty") if (_JsonDocument.HasMember("Phonemes") && _JsonDocument["Phonemes"].IsArray()) for (const auto& j : _JsonDocument["Phonemes"].GetArray()) Phonemes.emplace_back(j.IsString() ? to_wide_string(j.GetString()) : L"[UNK]"); if (_JsonDocument.HasMember("Tones") && _JsonDocument["Tones"].IsArray()) for (const auto& j : _JsonDocument["Tones"].GetArray()) Tones.emplace_back(j.IsInt() ? j.GetInt() : 0); if (_JsonDocument.HasMember("Durations") && _JsonDocument["Durations"].IsArray()) for (const auto& j : _JsonDocument["Durations"].GetArray()) Durations.emplace_back(j.IsInt() ? j.GetInt() : 0); if (_JsonDocument.HasMember("Language") && _JsonDocument["Language"].IsArray()) { const auto LanguageArr = _JsonDocument["Language"].GetArray(); if (!LanguageArr.empty() && LanguageArr[0].IsString()) for (const auto& j : LanguageArr) Language.emplace_back(j.GetString()); } } std::wstring MoeVSTTSSeq::Serialization() const { if (TextSeq.empty()) return L""; std::wstring rtn = L"\t{\n"; rtn += L"\t\t\"TextSeq\": \"" + ReplaceSpecialTokens(TextSeq) + L"\",\n"; rtn += L"\t\t\"SlicedTokens\": [\n"; for(const auto& iter : SlicedTokens) rtn += iter.Serialization() + L",\n"; if (!SlicedTokens.empty()) rtn.erase(rtn.end() - 2); rtn += L"\t\t],\n"; rtn += L"\t\t\"SpeakerMix\": " + vector_to_string(SpeakerMix) + L",\n"; rtn += L"\t\t\"EmotionPrompt\": " + wstring_vector_to_string(ReplaceSpecialTokens(EmotionPrompt)) + L",\n"; rtn += L"\t\t\"NoiseScale\": " + std::to_wstring(NoiseScale) + L",\n"; rtn += L"\t\t\"LengthScale\": " + std::to_wstring(LengthScale) + L",\n"; rtn += L"\t\t\"DurationPredictorNoiseScale\": " + std::to_wstring(DurationPredictorNoiseScale) + L",\n"; rtn += L"\t\t\"FactorDpSdp\": " + std::to_wstring(FactorDpSdp) + L",\n"; rtn += L"\t\t\"GateThreshold\": " + std::to_wstring(GateThreshold) + L",\n"; rtn += L"\t\t\"MaxDecodeStep\": " + std::to_wstring(MaxDecodeStep) + L",\n"; rtn += L"\t\t\"Seed\": " + std::to_wstring(Seed) + L",\n"; rtn += L"\t\t\"SpeakerName\": \"" + ReplaceSpecialTokens(SpeakerName) + L"\",\n"; rtn += L"\t\t\"RestTime\": " + std::to_wstring(RestTime) + L",\n"; rtn += L"\t\t\"PlaceHolderSymbol\": \"" + ReplaceSpecialTokens(PlaceHolderSymbol) + L"\",\n"; rtn += L"\t\t\"LanguageSymbol\": \"" + ReplaceSpecialTokens(to_wide_string(LanguageSymbol)) + L"\",\n"; rtn += L"\t\t\"G2PAdditionalInfo\": \"" + ReplaceSpecialTokens(AdditionalInfo) + L"\"\n\t}"; return rtn; } MoeVSTTSSeq::MoeVSTTSSeq(const MJsonValue& _JsonDocument, const MoeVSParams& _InitParams) { if (_JsonDocument.HasMember("LanguageSymbol") && _JsonDocument["LanguageSymbol"].IsString() && !_JsonDocument["LanguageSymbol"].Empty()) LanguageSymbol = _JsonDocument["LanguageSymbol"].GetString(); else LanguageSymbol = _InitParams.LanguageSymbol; if (_JsonDocument.HasMember("G2PAdditionalInfo") && _JsonDocument["G2PAdditionalInfo"].IsString() && !_JsonDocument["G2PAdditionalInfo"].Empty()) AdditionalInfo = to_wide_string(_JsonDocument["G2PAdditionalInfo"].GetString()); else AdditionalInfo = _InitParams.AdditionalInfo; if (_JsonDocument.HasMember("PlaceHolderSymbol") && _JsonDocument["PlaceHolderSymbol"].IsString() && !_JsonDocument["PlaceHolderSymbol"].Empty()) PlaceHolderSymbol = to_wide_string(_JsonDocument["PlaceHolderSymbol"].GetString()); else PlaceHolderSymbol = _InitParams.PlaceHolderSymbol; if (_JsonDocument.HasMember("TextSeq") && _JsonDocument["TextSeq"].IsString() && !_JsonDocument["TextSeq"].Empty()) TextSeq = to_wide_string(_JsonDocument["TextSeq"].GetString()); else LibDLVoiceCodecThrow("Field \"TextSeq\" Should Not Be Empty") if (_JsonDocument.HasMember("SlicedTokens") && _JsonDocument["SlicedTokens"].IsArray()) { const auto TokensArrayObject = _JsonDocument["SlicedTokens"].GetArray(); for (const auto& iter : TokensArrayObject) SlicedTokens.emplace_back(iter, _InitParams); } if (_JsonDocument.HasMember("SpeakerMix") && _JsonDocument["SpeakerMix"].IsArray()) for (const auto& j : _JsonDocument["SpeakerMix"].GetArray()) SpeakerMix.emplace_back(j.IsFloat() ? j.GetFloat() : 0.f); else SpeakerMix = _InitParams.SpeakerMix; if (_JsonDocument.HasMember("EmotionPrompt") && _JsonDocument["EmotionPrompt"].IsArray()) for (const auto& j : _JsonDocument["EmotionPrompt"].GetArray()) EmotionPrompt.emplace_back(j.IsString() ? to_wide_string(j.GetString()) : std::wstring()); else EmotionPrompt = _InitParams.EmotionPrompt; if (_JsonDocument.HasMember("NoiseScale") && _JsonDocument["NoiseScale"].IsFloat()) NoiseScale = _JsonDocument["NoiseScale"].GetFloat(); else NoiseScale = _InitParams.NoiseScale; if (_JsonDocument.HasMember("LengthScale") && _JsonDocument["LengthScale"].IsFloat()) LengthScale = _JsonDocument["LengthScale"].GetFloat(); else LengthScale = _InitParams.LengthScale; if (_JsonDocument.HasMember("RestTime") && _JsonDocument["RestTime"].IsFloat()) RestTime = _JsonDocument["RestTime"].GetFloat(); else RestTime = _InitParams.RestTime; if (_JsonDocument.HasMember("DurationPredictorNoiseScale") && _JsonDocument["DurationPredictorNoiseScale"].IsFloat()) DurationPredictorNoiseScale = _JsonDocument["DurationPredictorNoiseScale"].GetFloat(); else DurationPredictorNoiseScale = _InitParams.DurationPredictorNoiseScale; if (_JsonDocument.HasMember("FactorDpSdp") && _JsonDocument["FactorDpSdp"].IsFloat()) FactorDpSdp = _JsonDocument["FactorDpSdp"].GetFloat(); else FactorDpSdp = _InitParams.FactorDpSdp; if (_JsonDocument.HasMember("GateThreshold") && _JsonDocument["GateThreshold"].IsFloat()) GateThreshold = _JsonDocument["GateThreshold"].GetFloat(); else GateThreshold = _InitParams.GateThreshold; if (_JsonDocument.HasMember("MaxDecodeStep") && _JsonDocument["MaxDecodeStep"].IsFloat()) MaxDecodeStep = _JsonDocument["MaxDecodeStep"].GetInt(); else MaxDecodeStep = _InitParams.MaxDecodeStep; if (_JsonDocument.HasMember("Seed") && _JsonDocument["Seed"].IsInt()) Seed = _JsonDocument["Seed"].GetInt(); else Seed = _InitParams.Seed; if (_JsonDocument.HasMember("SpeakerName") && _JsonDocument["SpeakerName"].IsString()) SpeakerName = to_wide_string(_JsonDocument["SpeakerName"].GetString()); else SpeakerName = _InitParams.SpeakerName; if (MaxDecodeStep < 2000) MaxDecodeStep = 2000; if (MaxDecodeStep > 20000) MaxDecodeStep = 20000; if (GateThreshold > 0.90f) GateThreshold = 0.90f; if (GateThreshold < 0.2f) GateThreshold = 0.2f; if (FactorDpSdp > 1.f) FactorDpSdp = 1.f; if (FactorDpSdp < 0.f) FactorDpSdp = 0.f; if (NoiseScale > 10.f) NoiseScale = 10.f; if (NoiseScale < 0.f) NoiseScale = 0.f; if (DurationPredictorNoiseScale > 10.f) DurationPredictorNoiseScale = 10.f; if (DurationPredictorNoiseScale < 0.f) DurationPredictorNoiseScale = 0.f; if (RestTime > 30.f) RestTime = 30.f; if (LengthScale > 10.f) LengthScale = 10.f; if (LengthScale < 0.1f) LengthScale = 0.1f; } bool MoeVSTTSSeq::operator==(const MoeVSTTSSeq& right) const { return Serialization() == right.Serialization(); } } ================================================ FILE: libtts/Modules/Models/src/TTS.cpp ================================================ #include "../header/TTS.hpp" #include MoeVoiceStudioCoreHeader std::unordered_map _ACCMAP{ { L"[acc_6]", 6 }, { L"[acc_5]", 5 }, { L"[acc_4]", 4 }, { L"[acc_3]", 3 }, { L"[acc_2]", 2 }, { L"[acc_1]", 1 }, { L"[acc_-4]", -4 }, { L"[acc_-3]", -3 }, { L"[acc_-2]", -2 }, { L"[acc_-1]", -1 }, }; std::unordered_map _LANGREPMAP{ {"CHINESE", "ZH"}, { "CHINA", "ZH" }, { "JAPAN", "JP" }, { "JAPANESE", "JP" }, { "JA", "JP" }, { "ENGLISH", "EN" } }; std::set ChineseVowel{L'a', L'e', L'i', L'o', L'u', L'A', L'E', L'I', L'O', L'U'}; std::set ByteSymbol{L',', L'.', L'?', L'/', L'\"', L'\'', L';', L':', L'!', L' ', L'…' }; void PreventNoobsInputErrors(std::string& _Src) { for (auto& i : _Src) i = char(toupper(i)); const auto res = _LANGREPMAP.find(_Src); if (res != _LANGREPMAP.end()) _Src = res->second; } TextToSpeech::TextToSpeech(const ExecutionProviders& ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : MoeVoiceStudioModule(ExecutionProvider_, DeviceID_, ThreadCount_) { MoeVSClassName(L"MoeVoiceStudioTextToSpeech"); } /**Preprocess**/ std::vector TextToSpeech::GetInputSeqs(const MJson& _Input, const MoeVSProjectSpace::MoeVSParams& _InitParams) const { auto InputSeq = GetInputSeqsStatic(_Input, _InitParams); return SpecializeInputSeqs(InputSeq); } std::vector TextToSpeech::GetInputSeqsStatic(const MJson& _Input, const MoeVSProjectSpace::MoeVSParams& _InitParams) { if (!_Input.IsArray()) LibDLVoiceCodecThrow("JSON Type Must Be Array") const auto _InpArr = _Input.GetArray(); std::vector _TTSInputSeqs; _TTSInputSeqs.reserve(_InpArr.size()); for (const auto& iter : _InpArr) _TTSInputSeqs.emplace_back(iter, _InitParams); return _TTSInputSeqs; } std::vector& TextToSpeech::SpecializeInputSeqs(std::vector& _Seq) const { for (auto& _Temp : _Seq) { PreventNoobsInputErrors(_Temp.LanguageSymbol); if (LanguageSymbol2ID.find(_Temp.LanguageSymbol) == LanguageSymbol2ID.end()) _Temp.LanguageSymbol = LanguageSymbol2ID.begin()->first; const int64_t FirstToneIdx = LanguageSymbol2TonesBegin.at(_Temp.LanguageSymbol); for(auto& _iter : _Temp.SlicedTokens) { if (!_iter.Phonemes.empty()) { auto RtnData = SplitTonesFromTokens(_iter.Phonemes, _iter.Tones, FirstToneIdx, _Temp.LanguageSymbol); _iter.Phonemes = std::move(std::get<0>(RtnData)); _iter.Tones = std::move(std::get<1>(RtnData)); } else if (FirstToneIdx) for (auto& it : _iter.Tones) it += FirstToneIdx; } } return _Seq; } /**Infer**/ std::vector> TextToSpeech::Inference(const std::wstring& _Seq, const MoeVSProjectSpace::MoeVSParams& _InferParams) const { if (_Seq.empty()) return {}; return Inference(GetInputSeqs({ to_byte_string(_Seq), true }, _InferParams)); } std::vector> TextToSpeech::Inference(const MJson& _Inputs, const MoeVSProjectSpace::MoeVSParams& _InferParams) const { return Inference(GetInputSeqs(_Inputs, _InferParams)); } std::vector TextToSpeech::Inference(std::wstring& _Datas, const MoeVSProjectSpace::MoeVSParams& _InferParams, const InferTools::SlicerSettings& _SlicerSettings) const { return Inference(_Datas, _InferParams,false); } std::vector TextToSpeech::Inference(const std::wstring& _Seq, const MoeVSProjectSpace::MoeVSParams& _InferParams, bool T) const { const std::vector> PCM = Inference(GetInputSeqs({ to_byte_string(_Seq), true }, _InferParams)); std::vector AudioFolders; if (_Seq.empty()) return {}; AudioFolders.reserve(PCM.size()); for (const auto& i : PCM) { std::wstring OutFolder = GetCurrentFolder() + L"/Outputs/BatchInference"; if (_waccess((OutFolder + L".wav").c_str(), 0) != -1) { for (size_t idx = 0; idx < 99999999; ++idx) if (_waccess((OutFolder + L" (" + std::to_wstring(idx) + L").wav").c_str(), 0) == -1) { OutFolder += L" (" + std::to_wstring(idx) + L").wav"; break; } } else OutFolder += L".wav"; AudioFolders.emplace_back(OutFolder); InferTools::Wav::WritePCMData(_samplingRate, 1, i, OutFolder); } return AudioFolders; } std::vector> TextToSpeech::Inference(const std::vector& _Input) const { MoeVSNotImplementedError } std::vector TextToSpeech::AligPhoneAttn(const std::string& LanguageStr, const std::vector& PhoneSeq, size_t BertSize) const { size_t PhoneSize = PhoneSeq.size(); if (AddBlank) PhoneSize = PhoneSize * 2 + 1; if(LanguageStr == "ZH") { std::vector bert2ph(PhoneSize, 0); size_t startFrame = 1; for (size_t iph = 0; iph < PhoneSeq.size(); ++iph) { if (startFrame == BertSize) LibDLVoiceCodecThrow("AligError") if (AddBlank) { bert2ph[(iph + 1) * 2] = startFrame; bert2ph[(iph + 1) * 2 - 1] = startFrame; } else bert2ph[iph] = startFrame; if (!PhoneSeq[iph].empty() && ChineseVowel.find(PhoneSeq[iph][0]) != ChineseVowel.end()) ++startFrame; else if (ByteSymbol.find(PhoneSeq[iph][0]) != ByteSymbol.end()) ++startFrame; else if (Symbols.find(PhoneSeq[iph]) == Symbols.end()) ++startFrame; else if (PhoneSeq[iph] == L"UNK") ++startFrame; } bert2ph.back() = startFrame; return bert2ph; } return GetAligments(PhoneSize, BertSize); } std::wstring TextToSpeech::TextNormalize(const std::wstring& _Input, int64_t LanguageId) const { return MoeVSG2P::NormalizeText(_Input, GetLanguageSymbolWithLanguageId(LanguageId)); } /**MapCast**/ const std::wstring& TextToSpeech::GetTokenizerNameWithLanguageSymbol(const std::string& LanguageSymbol) const { const auto TokenizerNamePair = LanguageSymbol2TokenizerName.find(LanguageSymbol); if (TokenizerNamePair != LanguageSymbol2TokenizerName.end()) return TokenizerNamePair->second; return NoneString; } const MoeVSG2P::Tokenizer& TextToSpeech::GetTokenizer(const std::wstring& TokenizerName) const { const auto TokenizerPair = Tokenizers.find(TokenizerName); if (TokenizerPair != Tokenizers.end()) return TokenizerPair->second; return MoeVSG2P::GetEmptyVocabTokenizer(); } const MoeVSG2P::Tokenizer& TextToSpeech::GetTokenizerWithLanguageSymbol(const std::string& LanguageSymbol) const { const auto& TokenizerName = GetTokenizerNameWithLanguageSymbol(LanguageSymbol); return GetTokenizer(TokenizerName); } const std::string& TextToSpeech::GetLanguageSymbolWithLanguageId(int64_t LanguageId) const { const auto LanguageIDPair = LanguageID2Symbol.find(LanguageId); if (LanguageIDPair != LanguageID2Symbol.end()) return LanguageIDPair->second; return NoneAString; } int64_t TextToSpeech::GetLanguageIdWithLanguageSymbol(const std::string& LanguageSymbol) const { const auto LanguageIDPair = LanguageSymbol2ID.find(LanguageSymbol); if (LanguageIDPair != LanguageSymbol2ID.end()) return LanguageIDPair->second; return _atoi64(LanguageSymbol.c_str()); } int64_t TextToSpeech::GetBertIdWithLanguageSymbol(const std::string& LanguageSymbol) const { const auto LanguageIDPair = LanguageSymbol2BertID.find(LanguageSymbol); if (LanguageIDPair != LanguageSymbol2BertID.end()) return LanguageIDPair->second; return -1; } int64_t TextToSpeech::GetTonesBegin(const std::string& LanguageSymbol) const { const auto LanguageIDPair = LanguageSymbol2TonesBegin.find(LanguageSymbol); if (LanguageIDPair != LanguageSymbol2TonesBegin.end()) return LanguageIDPair->second; return _atoi64(LanguageSymbol.c_str()); } int64_t TextToSpeech::GetTonesBegin(int64_t LanguageId) const { const auto& LanguageSymbol = GetLanguageSymbolWithLanguageId(LanguageId); return GetTonesBegin(LanguageSymbol); } int64_t TextToSpeech::GetSpeakerIdWithSpeakerName(const std::wstring& SpeakerName) const { const auto SpeakerIDPair = SpeakerName2ID.find(SpeakerName); if (SpeakerIDPair != SpeakerName2ID.end()) return SpeakerIDPair->second; return _wtoi64(SpeakerName.c_str()); } const std::wstring& TextToSpeech::GetSpeakerNameWithSpeakerId(int64_t SpeakerID) const { const auto SpeakerIDPair = SpeakerID2Name.find(SpeakerID); if (SpeakerIDPair != SpeakerID2Name.end()) return SpeakerIDPair->second; return NoneString; } int64_t TextToSpeech::GetBertIndexWithName(const std::wstring& BertName) const { const auto BertIDPair = BertName2Index.find(BertName); if (BertIDPair != BertName2Index.end()) return BertIDPair->second; return _wtoi64(BertName.c_str()); } const std::wstring& TextToSpeech::GetBertNameWithIndex(int64_t Index) const { const auto BertIDPair = Index2BertName.find(Index); if (BertIDPair != Index2BertName.end()) return BertIDPair->second; return NoneString; } std::vector TextToSpeech::CleanText(const std::wstring& SrcText, const std::wstring& PlaceholderSymbol, const std::wstring& ExtraInfo, const std::string& LanguageSymbol) const { return CleanText(Cleaner, SrcText, PlaceholderSymbol, ExtraInfo, LanguageSymbol); } std::vector TextToSpeech::CleanedSeq2Indices(const std::vector& Seq) const { std::vector Indices; Indices.reserve(Seq.size() * 3); for (const auto& i : Seq) { if (AddBlank) Indices.emplace_back(0); const auto Res = Symbols.find(i); if (Res != Symbols.end()) Indices.emplace_back(Res->second); else Indices.emplace_back(UNKID); } if (AddBlank) Indices.emplace_back(0); return Indices; } /**STATIC**/ std::vector TextToSpeech::GetAligments(size_t DstLen, size_t SrcLen) { std::vector bert2ph(DstLen + 1, 0); size_t startFrame = 0; const double ph_durs = static_cast(DstLen) / static_cast(SrcLen); for (size_t iph = 0; iph < SrcLen; ++iph) { const auto endFrame = static_cast(round(static_cast(iph) * ph_durs + ph_durs)); for (auto j = startFrame; j < endFrame + 1; ++j) bert2ph[j] = static_cast(iph) + 1; startFrame = endFrame + 1; } return bert2ph; } std::vector> TextToSpeech::generatePath(float* duration, size_t durationSize, size_t maskSize) { for (size_t i = 1; i < maskSize; ++i) duration[i] = duration[i - 1] + duration[i]; std::vector> path(durationSize, std::vector(maskSize, false)); //const auto path = new float[maskSize * durationSize]; /* for (size_t i = 0; i < maskSize; ++i) for (size_t j = 0; j < durationSize; ++j) path[i][j] = (j < (size_t)duration[i] ? 1.0f : 0.0f); for (size_t i = maskSize - 1; i > 0ull; --i) for (size_t j = 0; j < durationSize; ++j) path[i][j] -= path[i-1][j]; */ auto dur = (size_t)duration[0]; for (size_t j = 0; j < dur; ++j) path[j][0] = true; /* for (size_t i = maskSize - 1; i > 0ull; --i) for (size_t j = 0; j < durationSize; ++j) path[i][j] = (j < (size_t)duration[i] && j >= (size_t)duration[i - 1]); std::vector> tpath(durationSize, std::vector(maskSize)); for (size_t i = 0; i < maskSize; ++i) for (size_t j = 0; j < durationSize; ++j) tpath[j][i] = path[i][j]; */ for (size_t j = maskSize - 1; j > 0ull; --j) { dur = (size_t)duration[j]; for (auto i = (size_t)duration[j - 1]; i < dur && i < durationSize; ++i) path[i][j] = true; } return path; } std::tuple, std::vector> TextToSpeech::SplitTonesFromTokens(const std::vector& SrcSeq, const std::vector& TonesRef, int64_t TonesBegin, const std::string& LanguageSymbol) { if (SrcSeq.empty()) return{ {},{} }; std::vector TempSeqVec; std::vector TempToneVec; TempSeqVec.reserve(SrcSeq.size()); TempToneVec.reserve(SrcSeq.size()); for (const auto& it : SrcSeq) { if (_ACCMAP.find(it) == _ACCMAP.end()) { TempSeqVec.emplace_back(it); TempToneVec.emplace_back(0); } else { if (TempToneVec.empty()) continue; *(TempToneVec.end() - 1) = _ACCMAP.at(it); if (TempToneVec.size() > 1 && *(TempToneVec.end() - 2) == 0 && LanguageSymbol == "ZH") *(TempToneVec.end() - 2) = *(TempToneVec.end() - 1); } } if (TempToneVec.size() == TonesRef.size()) { for (size_t i = 0; i < TonesRef.size(); ++i) if (TonesRef[i] != 0) TempToneVec[i] = TonesRef[i]; } if (TonesBegin) for (auto& it : TempToneVec) it += TonesBegin; return { std::move(TempSeqVec) ,std::move(TempToneVec) }; } std::wregex PhonemeRegex(LR"((.*))"); std::vector TextToSpeech::CleanText(const MoeVSG2P::MVSCleaner* TextCleaner, const std::wstring& SrcText, const std::wstring& PlaceholderSymbol, const std::wstring& ExtraInfo, const std::string& LanguageSymbol) { std::wsmatch mat; if(TextCleaner) { if (std::regex_match(SrcText, mat, PhonemeRegex)) return TextCleaner->DictReplace(mat[1].str(), PlaceholderSymbol); if (TextCleaner->G2pEnabled()) return TextCleaner->DictReplace(TextCleaner->G2p(SrcText, PlaceholderSymbol, ExtraInfo, LanguageSymbol), PlaceholderSymbol); return TextCleaner->DictReplace(SrcText, PlaceholderSymbol); } return { SrcText }; } MoeVoiceStudioCoreEnd ================================================ FILE: libtts/Modules/Models/src/Vits.cpp ================================================ #include "../header/Vits.hpp" #include "../../InferTools/inferTools.hpp" #include MoeVoiceStudioCoreHeader bool BertEnabled = false; namespace BertSpace { std::unordered_map sessionBert; std::unordered_map sessionClap; } Ort::Session* GetBertModel(const std::wstring& Name) { const auto fd = BertSpace::sessionBert.find(Name); if (fd != BertSpace::sessionBert.end()) return fd->second; return nullptr; } Ort::Session* GetClapModel(const std::wstring& Name) { const auto fd = BertSpace::sessionClap.find(Name); if (fd != BertSpace::sessionClap.end()) return fd->second; return nullptr; } void SetBertEnabled(bool cond) { BertEnabled = cond; } void DestoryAllBerts() { for (const auto& it : BertSpace::sessionBert) delete it.second; for (const auto& it : BertSpace::sessionClap) delete it.second; BertSpace::sessionBert.clear(); BertSpace::sessionClap.clear(); } Vits::~Vits() { logger.log(L"[Info] unloading Vits Models"); destory(); logger.log(L"[Info] Vits Models unloaded"); } Vits::Vits(const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : TextToSpeech(ExecutionProvider_, DeviceID_, ThreadCount_) { //Check Folder if (_Config["Folder"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"folder\" (Model Folder)") if (!_Config["Folder"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Must Be String") const auto _folder = to_wide_string(_Config["Folder"].GetString()); if (_folder.empty()) LibDLVoiceCodecThrow("[Error] Field \"folder\" (Model Folder) Can Not Be Empty") const std::wstring _path = GetCurrentFolder() + L"/Models/" + _folder + L"/" + _folder; std::map _PathDict; if(_Config.HasMember("EmotionalPath") && _Config["EmotionalPath"].IsString()) { const auto emoStringload = to_wide_string(_Config["EmotionalPath"].GetString()); if(!emoStringload.empty()) { _PathDict["EmotionalPath"] = GetCurrentFolder() + L"/emotion/" + emoStringload + L".npy"; _PathDict["EmotionalDictPath"] = GetCurrentFolder() + L"/emotion/" + emoStringload + L".json"; } } if(_Config.HasMember("Clap") && _Config["Clap"].IsString()) { const auto ClapStringload = to_wide_string(_Config["Clap"].GetString()); if (!ClapStringload.empty()) _PathDict["Clap"] = GetCurrentFolder() + L"/clap/" + ClapStringload; } _PathDict["Decoder"] = _path + L"_dec.onnx"; _PathDict["StochasticDurationPredictor"] = _path + L"_sdp.onnx"; _PathDict["DurationPredictor"] = _path + L"_dp.onnx"; _PathDict["Encoder"] = _path + L"_enc_p.onnx"; _PathDict["FlowNet"] = _path + L"_flow.onnx"; _PathDict["Embidding"] = _path + L"_emb.onnx"; if (_Config.HasMember("Dict") && _Config["Dict"].IsString() && !_Config["Dict"].Empty()) _PathDict["Dict"] = GetCurrentFolder() + L"/Dict/" + to_wide_string(_Config["Dict"].GetString()) + L".json"; std::vector _BertPaths; if (_Config.HasMember("BertPath") && _Config["BertPath"].IsArray() && !_Config["BertPath"].Empty()) { for(const auto& BPH : _Config["BertPath"].GetArray()) { const auto BertPath = to_wide_string(BPH.GetString()); if(!BertPath.empty()) _BertPaths.emplace_back(GetCurrentFolder() + L"/Bert/" + BertPath); } } load(_PathDict, _Config, _ProgressCallback, _DurationCallback, _BertPaths); } void Vits::load(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, const std::vector& _BertPaths) { if (_Config["Type"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Type\" (ModelType)"); if (!_Config["Type"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Type\" (ModelType) Must Be String"); VitsType = _Config["Type"].GetString(); if (VitsType == "Pits") { UseTone = true; UseLength = false; } else if (VitsType == "BertVits") { UseLength = false; UseTone = true; UseBert = true; UseLanguage = true; EncoderG = true; } //Load Cleaner Cleaner = MoeVSG2P::GetDefCleaner(); if (_PathDict.find("Dict") != _PathDict.end() && (_waccess(_PathDict.at("Dict").c_str(), 0) != -1)) Cleaner->loadDict(_PathDict.at("Dict")); else Cleaner->loadDict(L""); //Load Speaker Map if (_Config.HasMember("Characters")) { const auto Characters = _Config["Characters"]; if(Characters.IsArray()) { SpeakerCount = (int64_t)Characters.Size(); int64_t SpkIdx = 0; for (const auto& iterator : Characters.GetArray()) { const auto SpeakerName = to_wide_string(iterator.GetString()); SpeakerName2ID[SpeakerName] = SpkIdx; SpeakerID2Name[SpkIdx] = SpeakerName; ++SpkIdx; } } else if(Characters.GetMemberCount()) { const auto Members = Characters.GetMemberArray(); for (const auto& pair : Members) { const auto SpeakerName = to_wide_string(pair.first); const int64_t SpkIdx = pair.second.GetInt64(); SpeakerName2ID[SpeakerName] = SpkIdx; SpeakerID2Name[SpkIdx] = SpeakerName; } } } //Load Language Map if (UseLanguage && (_Config["LanguageMap"].IsNull() || !_Config.HasMember("LanguageMap"))) LibDLVoiceCodecThrow("[Error] Missing field \"LanguageMap\" (LanguageMap)"); if (_Config.HasMember("LanguageMap")) { const auto LanguageMap = _Config["LanguageMap"]; if (LanguageMap.GetMemberCount()) for (const auto& Item : LanguageMap.GetMemberArray()) { if (!Item.second.IsArray()) continue; const auto LangArr = Item.second.GetArray(); if (LangArr.size() < 2) continue; LanguageSymbol2ID[Item.first] = LangArr[0].GetInt(); LanguageID2Symbol[LangArr[0].GetInt()] = Item.first; LanguageSymbol2TonesBegin[Item.first] = LangArr[1].GetInt(); } else logger.log("[Warn] Field \"LanguageMap\" Is Empty, Use Default Value"); } else logger.log("[Warn] Field \"LanguageMap\" Is Missing, Use Default Value"); //Load Default Bert Dim if (_Config.HasMember("BertSize") && _Config["BertSize"].IsInt64()) DefBertSize = _Config["BertSize"].GetInt64(); else logger.log(L"[Warn] Field \"BertSize\" Is Missing, Use Default Value"); //Enable Bert Reference if (_Config.HasMember("ReferenceBert") && _Config["ReferenceBert"].IsBool()) ReferenceBert = _Config["ReferenceBert"].GetBool(); else logger.log(L"[Warn] Field \"ReferenceBert\" Is Missing, Use Default Value"); //Load SamplingRate if (_Config["Rate"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Rate\" (SamplingRate)"); if (_Config["Rate"].IsInt() || _Config["Rate"].IsInt64()) _samplingRate = _Config["Rate"].GetInt(); else LibDLVoiceCodecThrow("[Error] Field \"Rate\" (SamplingRate) Must Be Int/Int64"); logger.log(L"[Info] Current Sampling Rate is" + std::to_wstring(_samplingRate)); //Check Symbol & AddBlank if (!_Config.HasMember("Symbol") || _Config["Symbol"].IsNull()) LibDLVoiceCodecThrow("[Error] Missing field \"Symbol\" (PhSymbol)"); if (_Config.HasMember("AddBlank") && !_Config["AddBlank"].IsNull()) AddBlank = _Config["AddBlank"].GetBool(); else logger.log(L"[Warn] Field \"AddBlank\" Is Missing, Use Default Value"); //Load Symbols int64_t iter_symb = 0; if (_Config["Symbol"].IsArray()) { logger.log(L"[Info] Use Phs"); if (_Config["Symbol"].Empty()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Can Not Be Empty"); const auto SymbolArr = _Config["Symbol"].GetArray(); if (!SymbolArr[0].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Must Be Array or String"); for (const auto& it : SymbolArr) Symbols.insert({ to_wide_string(it.GetString()), iter_symb++ }); } else { if (!_Config["Symbol"].IsString()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Must Be Array or String"); logger.log(L"[Info] Use Symbols"); const std::wstring SymbolsStr = to_wide_string(_Config["Symbol"].GetString()); if (SymbolsStr.empty()) LibDLVoiceCodecThrow("[Error] Field \"Symbol\" (PhSymbol) Can Not Be Empty"); for (size_t i = 0; i < SymbolsStr.length(); ++i) Symbols.insert({ SymbolsStr.substr(i,1) , iter_symb++ }); } for (const auto& iter : Symbols) if (iter.first.find(L"UNK") != std::wstring::npos || iter.first.find(L"unk") != std::wstring::npos) UNKID = iter.second; if (_Config.HasMember("VQSize") && _Config["VQSize"].IsInt64()) VQCodeBookSize = _Config["VQSize"].GetInt64(); else logger.log(L"[Warn] Field \"VQSize\" Is Missing, Use Default Value"); //Load Emo-Vector try { if (_PathDict.find("EmotionalPath") != _PathDict.end()) { const auto EmotionPath = _PathDict.at("EmotionalPath"); if (!EmotionPath.empty()) { logger.log(L"[Info] Loading EmotionVector"); EmoLoader.open(EmotionPath); logger.log(L"[Info] EmotionVector Loaded"); Emotion = true; } } if (_PathDict.find("EmotionalDictPath") != _PathDict.end()) { const auto EmotionPath = _PathDict.at("EmotionalDictPath"); if (!EmotionPath.empty()) { MJson EmoJson = { EmotionPath }; for (const auto& Member : EmoJson.GetMemberArray()) Emo2Id[to_wide_string(Member.first)] = Member.second.GetInt(); } } } catch (std::exception& e) { logger.log((std::string("[Warn] EmotionPath Error ") + e.what()).c_str()); } //InputNames if (UseLength) EncoderInputNames.emplace_back("x_lengths"); if (UseTone) EncoderInputNames.emplace_back("t"); if (Emotion) EncoderInputNames.emplace_back("emotion"); if (UseLanguage) EncoderInputNames.emplace_back("language"); //Load Bert if (UseBert) { size_t BertInputCount = _BertPaths.size(); if (_Config.HasMember("BertInputs") && _Config["BertInputs"].IsArray() && _Config["BertInputs"].Size() != BertInputCount) { BertInputCount = _Config["BertInputs"].Size(); int64_t Index = 0; for (const auto& Member : _Config["BertInputs"].GetArray()) { const auto BertName = to_wide_string(Member.GetString()); Index2BertName[Index] = BertName; BertName2Index[BertName] = Index; ++Index; } } else { int64_t Index = 0; for (const auto& Path : _BertPaths) { const auto BertName = Path.substr(Path.rfind(L'/') + 1); Index2BertName[Index] = BertName; BertName2Index[BertName] = Index; ++Index; } } if (_Config.HasMember("Lang2BertId") && _Config["Lang2BertId"].GetMemberCount() == LanguageSymbol2ID.size()) { for (const auto& Member : _Config["Lang2BertId"].GetMemberArray()) { LanguageSymbol2TokenizerName[Member.first] = GetBertNameWithIndex(Member.second.GetInt64()); LanguageSymbol2BertID[Member.first] = Member.second.GetInt64(); } } else if(LanguageSymbol2ID.size() <= BertInputCount) { for(const auto& Pair : LanguageSymbol2ID) { LanguageSymbol2TokenizerName[Pair.first] = GetBertNameWithIndex(Pair.second); LanguageSymbol2BertID[Pair.first] = Pair.second; } } else if(BertInputCount == 1) { for (const auto& Pair : LanguageSymbol2ID) { LanguageSymbol2TokenizerName[Pair.first] = GetBertNameWithIndex(0); LanguageSymbol2BertID[Pair.first] = 0; } } else LibDLVoiceCodecThrow("You Must Have Field \"Lang2BertId\"") EncoderBertInputNames.reserve(BertInputCount * 2); for (size_t i = 0; i < BertInputCount; ++i) EncoderBertInputNames.emplace_back("bert_" + std::to_string(i)); for (const auto& NameInp : EncoderBertInputNames) EncoderInputNames.emplace_back(NameInp.data()); for(const auto& Path : _BertPaths) { const auto BertName = Path.substr(Path.rfind(L'/') + 1); Ort::Session* SessionBert = nullptr; if (BertSpace::sessionBert.find(BertName) != BertSpace::sessionBert.end() && BertSpace::sessionBert.at(BertName) != nullptr) SessionBert = BertSpace::sessionBert.at(BertName); if (_waccess(Path.c_str(), 0) != -1) { if(!SessionBert) { try { SessionBert = new Ort::Session(*env, (Path + L"/model.onnx").c_str(), *session_options); } catch(Ort::Exception& e) { logger.log(L"[Warn] " + to_wide_string(e.what())); delete SessionBert; SessionBert = nullptr; } } if (_waccess((Path + L"/Tokenizer.json").c_str(), 0) != -1) { Tokenizers.insert({ BertName ,Path + L"/Tokenizer.json" }); Tokenizers[BertName].BondCleaner(Cleaner); } else if (SessionBert) { delete SessionBert; LibDLVoiceCodecThrow("Bert Must Have a Tokenizer"); } } BertSpace::sessionBert[BertName] = SessionBert; } for (auto& iter : BertSpace::sessionBert) if (BertName2Index.find(iter.first) == BertName2Index.end()) { delete iter.second; iter.second = nullptr; } } if(_BertPaths.empty()) { for (const auto& iter : BertSpace::sessionBert) delete iter.second; BertSpace::sessionBert.clear(); } if (VitsType == "BertVits" && _PathDict.find("Clap") != _PathDict.end()) { EncoderInputNames.emplace_back("emo"); UseClap = true; const auto& Path = _PathDict.at("Clap"); ClapName = Path.substr(Path.rfind(L'/') + 1); Ort::Session* SessionClap = nullptr; if ((BertSpace::sessionClap.find(ClapName) != BertSpace::sessionClap.end() && BertSpace::sessionClap.at(ClapName) != nullptr)) SessionClap = BertSpace::sessionClap.at(ClapName); if (!SessionClap) { try { SessionClap = new Ort::Session(*env, (Path + L".onnx").c_str(), *session_options); } catch (Ort::Exception& e) { logger.log(L"[Warn] " + to_wide_string(e.what())); delete SessionClap; SessionClap = nullptr; } } if (_waccess((Path + L".json").c_str(), 0) != -1) { Tokenizers.insert({ ClapName , Path + L".json" }); Tokenizers[ClapName].BondCleaner(Cleaner); } else if (SessionClap) { delete SessionClap; LibDLVoiceCodecThrow("Clap Must Have a Tokenizer"); } BertSpace::sessionClap[ClapName] = SessionClap; for (auto& iter : BertSpace::sessionClap) if (ClapName != iter.first) { delete iter.second; iter.second = nullptr; } } else { for (auto& iter : BertSpace::sessionClap) delete iter.second; BertSpace::sessionClap.clear(); UseClap = false; } _callback = _ProgressCallback; CustomDurationCallback = _DurationCallback; //LoadModels try { logger.log(L"[Info] loading Vits Models"); sessionDec = new Ort::Session(*env, _PathDict.at("Decoder").c_str(), *session_options); sessionEnc_p = new Ort::Session(*env, _PathDict.at("Encoder").c_str(), *session_options); sessionFlow = new Ort::Session(*env, _PathDict.at("FlowNet").c_str(), *session_options); if (_waccess(_PathDict.at("Embidding").c_str(), 0) != -1) sessionEmb = new Ort::Session(*env, _PathDict.at("Embidding").c_str(), *session_options); else sessionEmb = nullptr; if (_waccess(_PathDict.at("DurationPredictor").c_str(), 0) != -1) sessionDp = new Ort::Session(*env, _PathDict.at("DurationPredictor").c_str(), *session_options); else sessionDp = nullptr; if (_waccess(_PathDict.at("StochasticDurationPredictor").c_str(), 0) != -1) sessionSdp = new Ort::Session(*env, _PathDict.at("StochasticDurationPredictor").c_str(), *session_options); else sessionSdp = nullptr; if (!sessionDp && !sessionSdp) { destory(); LibDLVoiceCodecThrow("You must have a duration predictor"); } logger.log(L"[Info] Vits Models loaded"); } catch (Ort::Exception& _exception) { destory(); LibDLVoiceCodecThrow(_exception.what()); } if (sessionEmb) { if(EncoderG) EncoderInputNames.emplace_back("g"); SdpInputNames.emplace_back("g"); DpInputNames.emplace_back("g"); FlowInputNames.emplace_back("g"); DecInputNames.emplace_back("g"); } if(VitsType == "BertVits" && sessionEnc_p->GetInputCount() == EncoderInputNames.size() + 2) { EncoderInputNames.emplace_back("vqidx"); EncoderInputNames.emplace_back("sid"); UseVQ = true; } } Vits::Vits(const std::map& _PathDict, const MJson& _Config, const ProgressCallback& _ProgressCallback, const DurationCallback& _DurationCallback, const std::vector& _BertPaths, ExecutionProviders ExecutionProvider_, unsigned DeviceID_, unsigned ThreadCount_) : TextToSpeech(ExecutionProvider_, DeviceID_, ThreadCount_) { load(_PathDict, _Config, _ProgressCallback, _DurationCallback, _BertPaths); } std::vector Vits::GetEmotionVector(const std::vector& src) const { if (src.empty()) return EmoLoader[0]; std::vector dst(1024, 0.0); uint64_t mul = 0; for (const auto& iter : src) { long emoId; if (Emo2Id.find(iter) != Emo2Id.end()) emoId = Emo2Id.at(iter); else emoId = _wtoi(iter.c_str()); auto emoVec = EmoLoader[emoId]; for (size_t i = 0; i < 1024; ++i) dst[i] = dst[i] + (emoVec[i] - dst[i]) / (float)(mul + 1ull); ++mul; } return dst; } std::tuple, std::vector, std::vector, std::vector, std::vector, std::vector, bool> Vits::PreProcessSeq(const MoeVSProjectSpace::MoeVSTTSSeq& Seq, int64_t CurLanguageIdx) const { std::vector PhonemeSeq, TokenSeq; std::vector ToneSeq; std::vector LanguageSeq; std::vector DurationSeq; std::vector BertAligSeq; bool HasBertSeq = false; bool Skip = false; if (AddBlank) BertAligSeq.emplace_back(0); std::vector TmpToken; const std::vector* TokensPtr = &Seq.SlicedTokens; if (BertEnabled && UseBert && Seq.SlicedTokens.empty()) { HasBertSeq = true; if (Seq.LanguageSymbol != "ZH") TokenSeq = GetTokenizerWithLanguageSymbol(Seq.LanguageSymbol).Tokenize(Seq.TextSeq); else { auto NewData = GetTokenizerWithLanguageSymbol(Seq.LanguageSymbol).Tokenize(Seq.TextSeq); if (NewData.empty()) { Skip = true; return { Skip, std::move(PhonemeSeq), std::move(TokenSeq), std::move(ToneSeq), std::move(LanguageSeq), std::move(DurationSeq), std::move(BertAligSeq), HasBertSeq }; } TmpToken.reserve(NewData.size()); for (const auto& it : NewData) { MoeVSProjectSpace::MoeVSTTSToken Tok; Tok.Text = it; TmpToken.emplace_back(std::move(Tok)); } TokensPtr = &TmpToken; } } if (UseBert && TokensPtr && !TokensPtr->empty()) { size_t TokensIndex = 1; for (const auto& iter : *TokensPtr) { if (iter.Text.empty()) { logger.log("[Info] Skip Empty Slice"); continue; } TokenSeq.emplace_back(iter.Text); if (iter.Text == L"[CLS]") continue; if (iter.Text == L"[SEP]") break; std::vector const* PhonemesPtr; std::vector TempPhonemes; std::vector TempToneVec; if (iter.Phonemes.empty()) { std::vector TempSeqVec; auto TempText = iter.Text; if (TempText == L"[UNK]") TempPhonemes = { L"[UNK]" }; else { if (TempText.find(L"##") == 0) TempText = TempText.substr(2); if (TempText.find(L'▁') == 0) TempText = TempText.substr(1); TempPhonemes = CleanText(TempText, Seq.PlaceHolderSymbol, L"/[WithTone]" + Seq.AdditionalInfo, Seq.LanguageSymbol); } const int64_t FirstToneIdx = GetTonesBegin(Seq.LanguageSymbol); auto RtnData = SplitTonesFromTokens(TempPhonemes, iter.Tones, FirstToneIdx, Seq.LanguageSymbol); TempPhonemes = std::move(std::get<0>(RtnData)); TempToneVec = std::move(std::get<1>(RtnData)); PhonemesPtr = &TempPhonemes; } else PhonemesPtr = &iter.Phonemes; PhonemeSeq.insert(PhonemeSeq.end(), PhonemesPtr->begin(), PhonemesPtr->end()); if (PhonemesPtr->size() == iter.Language.size()) for (const auto& LanguageSymbol : iter.Language) LanguageSeq.emplace_back(GetLanguageIdWithLanguageSymbol(LanguageSymbol)); else LanguageSeq.insert(LanguageSeq.end(), PhonemesPtr->size(), CurLanguageIdx); if (PhonemesPtr->size() == iter.Durations.size()) DurationSeq.insert(DurationSeq.end(), iter.Durations.begin(), iter.Durations.end()); if (PhonemesPtr->size() == iter.Tones.size()) ToneSeq.insert(ToneSeq.end(), iter.Tones.begin(), iter.Tones.end()); else if (PhonemesPtr->size() == TempToneVec.size()) ToneSeq.insert(ToneSeq.end(), TempToneVec.begin(), TempToneVec.end()); else ToneSeq.insert(ToneSeq.end(), PhonemesPtr->size(), GetTonesBegin(Seq.LanguageSymbol)); for (size_t idxl = 0; idxl < PhonemesPtr->size(); ++idxl) { BertAligSeq.emplace_back(TokensIndex); if (AddBlank) BertAligSeq.emplace_back(TokensIndex); } ++TokensIndex; } if ((AddBlank && BertAligSeq.size() == PhonemeSeq.size() * 2 + 1) || (!AddBlank && BertAligSeq.size() == PhonemeSeq.size())) HasBertSeq = true; else HasBertSeq = false; } else if (!Seq.TextSeq.empty()) { PhonemeSeq = CleanText(Seq.TextSeq, Seq.PlaceHolderSymbol, L"/[WithTone]" + Seq.AdditionalInfo, Seq.LanguageSymbol); LanguageSeq = std::vector(PhonemeSeq.size(), CurLanguageIdx); auto RtnVal = SplitTonesFromTokens(PhonemeSeq, {}, GetTonesBegin(Seq.LanguageSymbol), Seq.LanguageSymbol); PhonemeSeq = std::move(std::get<0>(RtnVal)); ToneSeq = std::move(std::get<1>(RtnVal)); } else { logger.log("[Info] Skip Empty TextSeq"); Skip = true; } return { Skip, std::move(PhonemeSeq), std::move(TokenSeq), std::move(ToneSeq), std::move(LanguageSeq), std::move(DurationSeq), std::move(BertAligSeq), HasBertSeq }; } std::vector Vits::GetBertFeature(size_t IndexOfBert, const std::vector& TokenSeq, Ort::Session* CurBertSession) const { auto input_ids = GetTokenizer(GetBertNameWithIndex((int64_t)IndexOfBert))(TokenSeq); std::vector attention_mask(input_ids.size(), 1), token_type_ids(input_ids.size(), 0); const int64_t AttentionShape[2] = { 1, (int64_t)input_ids.size() }; std::vector AttentionInput, AttentionOutput; AttentionInput.emplace_back(Ort::Value::CreateTensor( *memory_info, input_ids.data(), input_ids.size(), AttentionShape, 2)); if (CurBertSession->GetInputCount() == 3) AttentionInput.emplace_back(Ort::Value::CreateTensor(*memory_info, attention_mask.data(), attention_mask.size(), AttentionShape, 2)); AttentionInput.emplace_back(Ort::Value::CreateTensor( *memory_info, token_type_ids.data(), token_type_ids.size(), AttentionShape, 2)); try { AttentionOutput = CurBertSession->Run(Ort::RunOptions{ nullptr }, BertInputNames.data(), AttentionInput.data(), CurBertSession->GetInputCount(), BertOutputNames.data(), 1); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Bert\n") + e.what())) } return AttentionOutput; } std::vector Vits::Infer(const MoeVSProjectSpace::MoeVSTTSSeq& Seq) const { std::vector PCMDATA; auto CurLanguageIdx = GetLanguageIdWithLanguageSymbol(Seq.LanguageSymbol); auto PreprocessedSeq = PreProcessSeq(Seq, CurLanguageIdx); bool Skip = std::get<0>(PreprocessedSeq); auto PhonemeSeq = std::move(std::get<1>(PreprocessedSeq)); auto TokenSeq = std::move(std::get<2>(PreprocessedSeq)); std::vector ToneSeq = std::move(std::get<3>(PreprocessedSeq)); auto LanguageSeq = std::move(std::get<4>(PreprocessedSeq)); auto DurationSeq = std::move(std::get<5>(PreprocessedSeq)); auto BertAligSeq = std::move(std::get<6>(PreprocessedSeq)); bool HasBertSeq = std::get<7>(PreprocessedSeq); if (PhonemeSeq.empty() || Skip) { logger.log("[Info] Skip Empty Seq"); return {}; } std::vector EncoderInputs, EncoderOutputs; std::mt19937 gen(static_cast(Seq.Seed)); std::normal_distribution FloatRandFn(0.f, 1.f); std::vector TextSeq = CleanedSeq2Indices(PhonemeSeq); const int64_t TextSeqShape[2] = { 1,(int64_t)TextSeq.size() }; int64_t TextSeqLength[] = { TextSeqShape[1] }; constexpr int64_t LengthShape[1] = { 1 }; //Indices Seq EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, TextSeq.data(), TextSeqLength[0], TextSeqShape, 2)); //Indices Length if (UseLength) EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, TextSeqLength, 1, LengthShape, 1)); //Emotional Vits std::vector EmotionVector; constexpr int64_t EmotionShape[1] = { 1024 }; if (Emotion) { EmotionVector = GetEmotionVector(Seq.EmotionPrompt); EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, EmotionVector.data(), 1024, EmotionShape, 1)); } //Tone Seq std::vector ToneIn(TextSeq.size(), 0i64); if (UseTone) { if (ToneIn.size() == ToneSeq.size()) ToneIn = ToneSeq; else if (AddBlank && ToneIn.size() == ToneSeq.size() * 2 + 1) for (size_t i = 1; i < ToneIn.size(); i += 2) ToneIn[i] = ToneSeq[i / 2]; else if (ToneIn.size() * 2 + 1 == ToneSeq.size()) for (size_t i = 1; i < ToneSeq.size(); i += 2) ToneIn[i / 2] = ToneSeq[i]; EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, ToneIn.data(), TextSeqLength[0], TextSeqShape, 2)); } //Language Seq std::vector LanguageIn(TextSeq.size(), CurLanguageIdx); if (UseLanguage) { if (LanguageIn.size() == LanguageSeq.size()) LanguageIn = LanguageSeq; else if (AddBlank && LanguageIn.size() == LanguageSeq.size() * 2 + 1) for (size_t i = 1; i < LanguageIn.size(); i += 2) { LanguageIn[i] = LanguageSeq[i / 2]; LanguageIn[i - 1] = LanguageSeq[i / 2]; } else if (LanguageIn.size() * 2 + 1 == LanguageSeq.size()) for (size_t i = 1; i < LanguageSeq.size(); i += 2) LanguageIn[i / 2] = LanguageSeq[i]; EncoderInputs.push_back(Ort::Value::CreateTensor( *memory_info, LanguageIn.data(), TextSeqLength[0], TextSeqShape, 2)); } //Bert Seqs std::vector BertVecs(Index2BertName.size(), std::vector(0)); std::vector BertShapes(Index2BertName.size()); if (UseBert) { for (size_t IndexOfBert = 0; IndexOfBert < Index2BertName.size(); ++IndexOfBert) { auto& BertData = BertVecs[IndexOfBert]; auto& BertShape = BertShapes[IndexOfBert]; BertShape[0] = TextSeqLength[0]; const auto CurBertSession = GetBertModel(GetBertNameWithIndex((int64_t)IndexOfBert)); if (CurBertSession && IndexOfBert == size_t(GetBertIdWithLanguageSymbol(Seq.LanguageSymbol)) && BertEnabled && HasBertSeq) { const auto SeqBert = GetBertFeature(IndexOfBert, TokenSeq, CurBertSession); int64_t BertSize = SeqBert[0].GetTensorTypeAndShapeInfo().GetShape().back(); BertShape[1] = BertSize; BertData.resize(BertShape[1] * BertShape[0]); const auto AttnData = SeqBert[0].GetTensorData(); if (BertAligSeq.size() == 1) BertAligSeq = GetAligments(TextSeqLength[0], SeqBert[0].GetTensorTypeAndShapeInfo().GetShape()[0] - 2); for (int64_t IndexOfSrcVector = 0; IndexOfSrcVector < TextSeqLength[0]; ++IndexOfSrcVector) memcpy(BertData.data() + IndexOfSrcVector * BertSize, AttnData + (BertAligSeq[IndexOfSrcVector]) * BertSize, BertSize * sizeof(float)); } else { BertShape[1] = DefBertSize; BertData.resize(BertShape[1] * BertShape[0], 0.f); } EncoderInputs.emplace_back(Ort::Value::CreateTensor( *memory_info, BertData.data(), BertData.size(), BertShape, 2)); } } //Clap Emotion Seq auto ClapData = std::vector(512, 0.f); int64_t ClapShape[2] = { 512, 1 }; if (UseClap) { const auto CurClapSession = GetClapModel(ClapName); std::vector ClapInput; std::wstring ClapSeq; if (CurClapSession && !ClapSeq.empty()) { for (const auto& itt : Seq.EmotionPrompt) ClapSeq += itt + L" "; std::vector ClapOutput; const auto& CurClapTokenizer = GetTokenizer(ClapName); auto input_ids = CurClapTokenizer(CurClapTokenizer.Tokenize(ClapSeq), true); std::vector attention_mask(input_ids.size(), 1); int64_t AttentionShape[2] = { 1, (int64_t)input_ids.size() }; ClapInput.emplace_back(Ort::Value::CreateTensor( *memory_info, input_ids.data(), input_ids.size(), AttentionShape, 2)); ClapInput.emplace_back(Ort::Value::CreateTensor( *memory_info, attention_mask.data(), attention_mask.size(), AttentionShape, 2)); try { ClapOutput = CurClapSession->Run(Ort::RunOptions{ nullptr }, BertInputNames.data(), ClapInput.data(), CurClapSession->GetInputCount(), BertOutputNames.data(), 1); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: Clap\n") + e.what())) } ClapData = { ClapOutput[0].GetTensorData(),ClapOutput[0].GetTensorData() + 512 }; } EncoderInputs.emplace_back(Ort::Value::CreateTensor(*memory_info, ClapData.data(), ClapData.size(), ClapShape, 2)); } int64_t VQIndices[] = { 0 }; int64_t SidIndices[] = { GetSpeakerIdWithSpeakerName(Seq.SpeakerName)}; std::vector GEmbidding; std::vector GOutShape; if (sessionEmb) { auto SpeakerMixData = Seq.SpeakerMix; if (!SpeakerMixData.empty() && SpeakerCount > 1) { LinearCombination(SpeakerMixData); int64_t csid = 0; for (const auto& CharaP : SpeakerMixData) { std::vector EmbiddingInput; std::vector EmbiddingOutput; if (csid >= SpeakerCount) break; if (CharaP < 0.0001f) { ++csid; continue; } int64_t Character[1] = { csid }; EmbiddingInput.push_back(Ort::Value::CreateTensor( *memory_info, Character, 1, LengthShape, 1)); try { EmbiddingOutput = sessionEmb->Run(Ort::RunOptions{ nullptr }, EmbiddingInputNames.data(), EmbiddingInput.data(), EmbiddingInput.size(), EmbiddingOutputNames.data(), EmbiddingOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: emb\n") + e.what())) } const auto GOutCount = EmbiddingOutput[0].GetTensorTypeAndShapeInfo().GetElementCount(); if (GOutShape.empty()) { GEmbidding = std::vector(EmbiddingOutput[0].GetTensorData(), EmbiddingOutput[0].GetTensorData() + GOutCount); GOutShape = EmbiddingOutput[0].GetTensorTypeAndShapeInfo().GetShape(); GOutShape.emplace_back(1); for (auto idx : GEmbidding) idx *= float(CharaP); } else for (size_t i = 0; i < GOutCount; ++i) GEmbidding[i] += EmbiddingOutput[0].GetTensorData()[i] * float(CharaP); ++csid; } } else { std::vector EmbiddingInput; std::vector EmbiddingOutput; EmbiddingInput.push_back(Ort::Value::CreateTensor( *memory_info, SidIndices, 1, LengthShape, 1)); try { EmbiddingOutput = sessionEmb->Run(Ort::RunOptions{ nullptr }, EmbiddingInputNames.data(), EmbiddingInput.data(), EmbiddingInput.size(), EmbiddingOutputNames.data(), EmbiddingOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: emb\n") + e.what())) } const auto GOutCount = EmbiddingOutput[0].GetTensorTypeAndShapeInfo().GetElementCount(); GEmbidding = std::vector(EmbiddingOutput[0].GetTensorData(), EmbiddingOutput[0].GetTensorData() + GOutCount); GOutShape = EmbiddingOutput[0].GetTensorTypeAndShapeInfo().GetShape(); GOutShape.emplace_back(1); } if (EncoderG) EncoderInputs.push_back(Ort::Value::CreateTensor(*memory_info, GEmbidding.data(), GEmbidding.size(), GOutShape.data(), 3)); } if (UseVQ) { if (!Seq.EmotionPrompt.empty()) VQIndices[0] = _wtoi64(Seq.EmotionPrompt[0].c_str()); EncoderInputs.push_back(Ort::Value::CreateTensor(*memory_info, VQIndices, 1, LengthShape, 1)); EncoderInputs.push_back(Ort::Value::CreateTensor(*memory_info, SidIndices, 1, LengthShape, 1)); } try { EncoderOutputs = sessionEnc_p->Run(Ort::RunOptions{ nullptr }, EncoderInputNames.data(), EncoderInputs.data(), EncoderInputs.size(), EncoderOutputNames.data(), EncoderOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: enc_p\n") + e.what())) } std::vector m_p(EncoderOutputs[1].GetTensorData(), EncoderOutputs[1].GetTensorData() + EncoderOutputs[1].GetTensorTypeAndShapeInfo().GetElementCount()), logs_p(EncoderOutputs[2].GetTensorData(), EncoderOutputs[2].GetTensorData() + EncoderOutputs[2].GetTensorTypeAndShapeInfo().GetElementCount()), x_mask(EncoderOutputs[3].GetTensorData(), EncoderOutputs[3].GetTensorData() + EncoderOutputs[3].GetTensorTypeAndShapeInfo().GetElementCount()); const auto xshape = EncoderOutputs[0].GetTensorTypeAndShapeInfo().GetShape(); std::vector w_ceil(TextSeqLength[0], 1.f); bool enable_dp = false; if (DurationSeq.size() == w_ceil.size() || DurationSeq.size() == w_ceil.size() / 2) enable_dp = true; const int64_t zinputShape[3] = { xshape[0],2,xshape[2] }; const int64_t zinputCount = xshape[0] * xshape[2] * 2; std::vector zinput(zinputCount, 0.0); for (auto& it : zinput) it = FloatRandFn(gen) * Seq.DurationPredictorNoiseScale; std::vector DurationPredictorInput; DurationPredictorInput.push_back(std::move(EncoderOutputs[0])); DurationPredictorInput.push_back(std::move(EncoderOutputs[3])); DurationPredictorInput.push_back(Ort::Value::CreateTensor( *memory_info, zinput.data(), zinputCount, zinputShape, 3)); if (sessionEmb) DurationPredictorInput.push_back(Ort::Value::CreateTensor(*memory_info, GEmbidding.data(), GEmbidding.size(), GOutShape.data(), 3)); if (sessionSdp) { std::vector StochasticDurationPredictorOutput; try { StochasticDurationPredictorOutput = sessionSdp->Run(Ort::RunOptions{ nullptr }, SdpInputNames.data(), DurationPredictorInput.data(), DurationPredictorInput.size(), SdpOutputNames.data(), SdpOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: dp\n") + e.what())) } const auto w_data = StochasticDurationPredictorOutput[0].GetTensorMutableData(); const auto w_data_length = StochasticDurationPredictorOutput[0].GetTensorTypeAndShapeInfo().GetElementCount(); if (w_data_length != w_ceil.size()) w_ceil.resize(w_data_length, 0.f); float SdpFactor = 1.f - Seq.FactorDpSdp; if (sessionDp) for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] = ceil(exp(w_data[i] * SdpFactor) * x_mask[i] * Seq.LengthScale); else for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] = ceil(exp(w_data[i]) * x_mask[i] * Seq.LengthScale); } if (sessionDp) { std::vector DurationPredictorOutput; DurationPredictorInput.erase(DurationPredictorInput.begin() + 2); try { DurationPredictorOutput = sessionDp->Run(Ort::RunOptions{ nullptr }, DpInputNames.data(), DurationPredictorInput.data(), DurationPredictorInput.size(), DpOutputNames.data(), DpOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: dp\n") + e.what())) } const auto w_data = DurationPredictorOutput[0].GetTensorMutableData(); const auto w_data_length = DurationPredictorOutput[0].GetTensorTypeAndShapeInfo().GetElementCount(); if (w_data_length != w_ceil.size()) w_ceil.resize(w_data_length, 0.f); if (sessionSdp) for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] += ceil(exp(w_data[i] * Seq.FactorDpSdp) * x_mask[i] * Seq.LengthScale); else for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] = ceil(exp(w_data[i]) * x_mask[i] * Seq.LengthScale); } if (enable_dp) { if (DurationSeq.size() == TextSeq.size()) for (size_t i = 0; i < w_ceil.size(); ++i) w_ceil[i] = float(DurationSeq[i]); else if (AddBlank && DurationSeq.size() == TextSeq.size() / 2ull) for (size_t i = 0; i < DurationSeq.size(); ++i) w_ceil[1 + i * 2] = float(DurationSeq[i]); } CustomDurationCallback(w_ceil); const auto maskSize = x_mask.size(); float y_length_f = 0.0; int64_t y_length; for (size_t i = 0; i < w_ceil.size(); ++i) y_length_f += w_ceil[i]; if (y_length_f < 1.0f) y_length = 1; else y_length = (int64_t)y_length_f; auto attn = generatePath(w_ceil.data(), y_length, maskSize); std::vector logVec(192, std::vector(y_length, 0.0f)); std::vector mpVec(192, std::vector(y_length, 0.0f)); std::vector nlogs_pData(192 * y_length); for (size_t i = 0; i < static_cast(y_length); ++i) { for (size_t j = 0; j < 192; ++j) { for (size_t k = 0; k < maskSize; k++) { if (attn[i][k]) { mpVec[j][i] += m_p[j * maskSize + k]; logVec[j][i] += logs_p[j * maskSize + k]; } } nlogs_pData[j * y_length + i] = mpVec[j][i] + FloatRandFn(gen) * exp(logVec[j][i]) * Seq.NoiseScale; } } std::vector y_mask(y_length, 1.0f); const int64_t zshape[3] = { 1,192,y_length }; const int64_t yshape[3] = { 1,1,y_length }; std::vector FlowDecInputs, FlowDecOutputs; FlowDecInputs.push_back(Ort::Value::CreateTensor( *memory_info, nlogs_pData.data(), 192 * y_length, zshape, 3)); FlowDecInputs.push_back(Ort::Value::CreateTensor( *memory_info, y_mask.data(), y_length, yshape, 3)); if (sessionEmb) FlowDecInputs.push_back(Ort::Value::CreateTensor( *memory_info, GEmbidding.data(), GEmbidding.size(), GOutShape.data(), 3)); try { FlowDecOutputs = sessionFlow->Run(Ort::RunOptions{ nullptr }, FlowInputNames.data(), FlowDecInputs.data(), FlowDecInputs.size(), FlowOutputNames.data(), FlowOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: dec & flow\n") + e.what())) } FlowDecInputs[0] = std::move(FlowDecOutputs[0]); if (sessionEmb) FlowDecInputs[1] = std::move(FlowDecInputs[2]); FlowDecInputs.pop_back(); try { FlowDecOutputs = sessionDec->Run(Ort::RunOptions{ nullptr }, DecInputNames.data(), FlowDecInputs.data(), FlowDecInputs.size(), DecOutputNames.data(), DecOutputNames.size()); } catch (Ort::Exception& e) { LibDLVoiceCodecThrow((std::string("Locate: dec & flow\n") + e.what())) } const auto shapeOut = FlowDecOutputs[0].GetTensorTypeAndShapeInfo().GetShape(); const auto outData = FlowDecOutputs[0].GetTensorData(); PCMDATA.reserve(shapeOut[2] * 2); for (int bbb = 0; bbb < shapeOut[2]; bbb++) PCMDATA.emplace_back(static_cast(outData[bbb] * 32768.0f)); return PCMDATA; } std::vector> Vits::Inference(const std::vector& _Input) const { std::vector> PCM; PCM.reserve(_Input.size()); logger.log("[Inference] Vits Inference Begin"); size_t proc = 0; _callback(proc, _Input.size()); for (const auto& Seq : _Input) { _callback(proc++, _Input.size()); if (Seq.RestTime < 0.f || &Seq == &_Input.front()) PCM.emplace_back(); const auto _Audio = Infer(Seq); auto& BackOfPCMDatas = PCM.back(); if (Seq.RestTime > 0.f) BackOfPCMDatas.insert(BackOfPCMDatas.end(), size_t(double(Seq.RestTime) * double(_samplingRate)), 0); BackOfPCMDatas.insert(BackOfPCMDatas.end(), _Audio.begin(), _Audio.end()); } _callback(proc, _Input.size()); logger.log("[Inference] Vits Inference Fin"); return PCM; } MoeVoiceStudioCoreEnd ================================================ FILE: libtts/Modules/Modules.cpp ================================================ #include "Modules.hpp" namespace MoeVSModuleManager { bool MoeVoiceStudioCoreInitStat = false; MoeVoiceStudioCore::TextToSpeech* CurTextToSpeechModel = nullptr; void MoeVoiceStudioCoreInitSetup() { if (MoeVoiceStudioCoreInitStat) return; const auto BasicCleanerDir = GetCurrentFolder() + L"/G2P/BasicCleaner.dll"; if (_waccess(BasicCleanerDir.c_str(), 0) != -1) { const auto Cleaner = MoeVSG2P::GetDefCleaner(); Cleaner->loadG2p(BasicCleanerDir); Cleaner->GetCleaner().LoadDict(GetCurrentFolder() + L"/G2P"); Cleaner->loadDict(GetCurrentFolder() + L"/Dict/BasicDict.json"); } MoeVoiceStudioCoreInitStat = true; } MoeVoiceStudioCore::TextToSpeech* GetCurTTSModel() { return CurTextToSpeechModel; } void UnloadTTSModel() { delete CurTextToSpeechModel; CurTextToSpeechModel = nullptr; SamplingRate = 32000; SpeakerCount = 0; } void LoadTTSModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID, const MoeVoiceStudioCore::TextToSpeech::DurationCallback& DurationCallback) { UnloadTTSModel(); if (Config["Type"].GetString() == "Tacotron" || Config["Type"].GetString() == "Tacotron2") throw std::exception("Tacotron Not Support Yet"); if (Config["Type"].GetString() == "GPT-SoVits") { MoeVoiceStudioCore::DestoryAllBerts(); CurTextToSpeechModel = dynamic_cast( new MoeVoiceStudioCore::GptSoVits( Config, Callback, DurationCallback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ) ); } else { CurTextToSpeechModel = dynamic_cast( new MoeVoiceStudioCore::Vits( Config, Callback, DurationCallback, MoeVoiceStudioCore::MoeVoiceStudioModule::ExecutionProviders(ProviderID), DeviceID, NumThread ) ); } SamplingRate = CurTextToSpeechModel->GetSamplingRate(); } } ================================================ FILE: libtts/Modules/Modules.hpp ================================================ /** * FileName: Modules.hpp * Note: MoeVoiceStudioCore组件管理 * * Copyright (C) 2022-2023 NaruseMioShirakana (shirakanamio@foxmail.com) * * This file is part of MoeVoiceStudioCore library. * MoeVoiceStudioCore library is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or any later version. * * MoeVoiceStudioCore library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with Foobar. * If not, see . * * date: 2022-10-17 Create */ #pragma once #include "Models/header/Vits.hpp" #include "Models/header/GPT-SoVits.hpp" namespace MoeVSModuleManager { inline int64_t SamplingRate = 32000; inline int64_t SpeakerCount = 0; /** * \brief 初始化所有组件 */ void MoeVoiceStudioCoreInitSetup(); /** * \brief 获取当前模型 * \return 当前模型的指针 */ MoeVoiceStudioCore::TextToSpeech* GetCurTTSModel(); /** * \brief 卸载模型 */ void UnloadTTSModel(); /** * \brief 载入模型 * \param Config 一个MJson类的实例(配置文件的JSON) * \param Callback 进度条回调函数 * \param ProviderID Provider在所有Provider中的ID(遵循Enum Class的定义) * \param NumThread CPU推理时的线程数(最好设置高一点,GPU不支持的算子可能也会Fallback到CPU) * \param DeviceID GPU设备ID * \param DurationCallback 时长回调 */ void LoadTTSModel(const MJson& Config, const MoeVoiceStudioCore::MoeVoiceStudioModule::ProgressCallback& Callback, int ProviderID, int NumThread, int DeviceID, const MoeVoiceStudioCore::TextToSpeech::DurationCallback& DurationCallback = [&](std::vector&) {}); } namespace MoeVSRename { using Vits = MoeVoiceStudioCore::Vits; } ================================================ FILE: libtts/Modules/README.md ================================================ # Example ```c++ #include "Modules/Models/header/Vits.hpp" int main(){ rapidjson::Document Config; Config.Parse("Your Config"); //Progress bar InferClass::BaseModelType::callback a_callback = [](size_t a, size_t b) {std::cout << std::to_string((float)a * 100.f / (float)b) << "%\n"; }; //return params for inference InferClass::BaseModelType::callback_params b_callback = []() { auto cbaaa = InferClass::InferConfigs(); cbaaa.kmeans_rate = 0.5; cbaaa.keys = 0; return cbaaa; }; //modify duration per phoneme InferClass::TTS::DurationCallback c_callback = [](std::vector&) {}; std::vector output; try { std::wstring inp("watashinoonaniomitekudasai"); auto model = dynamic_cast(new InferClass::VitsSvc(modConfigJson, a_callback, b_callback)); output = model->Inference(inp); Wav outWav(model->GetSamplingRate(), output.size() * 2, output.data()); outWav.Writef(L"test.wav"); delete model; } catch(std::exception& e) { std::cout << e.what(); } } ``` ================================================ FILE: libtts/Modules/StringPreprocess.hpp ================================================ #pragma once #include #include #include #ifdef _WIN32 #include #else #error #endif inline std::string to_utf8_string(const std::wstring& input) { std::vector ByteString(input.length() * 6); WideCharToMultiByte( CP_UTF8, 0, input.c_str(), int(input.length()), ByteString.data(), int(ByteString.size()), nullptr, nullptr ); return ByteString.data(); } inline std::string to_ansi_string(const std::wstring& input) { std::vector ByteString(input.length() * 6); WideCharToMultiByte( CP_ACP, 0, input.c_str(), int(input.length()), ByteString.data(), int(ByteString.size()), nullptr, nullptr ); return ByteString.data(); } inline std::wstring to_wide_string(const std::string& input) { std::vector WideString(input.length() * 2); MultiByteToWideChar( CP_UTF8, 0, input.c_str(), int(input.length()), WideString.data(), int(WideString.size()) ); return WideString.data(); } inline std::string to_byte_string(const std::wstring& input) { return to_utf8_string(input); } template std::wstring vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) { std::wstring TmpStr = std::to_wstring(it); if ((std::is_same_v || std::is_same_v) && TmpStr.find(L'.') != std::string::npos) { while (TmpStr.back() == L'0') TmpStr.pop_back(); if (TmpStr.back() == L'.') TmpStr += L"0"; } vecstr += TmpStr + L", "; } if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } inline std::wstring string_vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) if (!it.empty()) vecstr += L'\"' + to_wide_string(it) + L"\", "; if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } inline std::wstring wstring_vector_to_string(const std::vector& vector) { std::wstring vecstr = L"["; for (const auto& it : vector) if (!it.empty()) vecstr += L'\"' + it + L"\", "; if (vecstr.length() > 2) vecstr = vecstr.substr(0, vecstr.length() - 2); vecstr += L']'; return vecstr; } ================================================ FILE: libtts/dllmain.cpp ================================================ // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "windows.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } ================================================ FILE: libtts/framework.h ================================================ #pragma once #ifdef LIBTTS_EXPORTS #define LibTTSApi __declspec(dllexport) #else #define LibTTSApi __declspec(dllimport) #endif ================================================ FILE: libtts/libtts.vcxproj ================================================ DebugLib Win32 DebugLib x64 Debug Win32 ReleaseLib Win32 ReleaseLib x64 Release Win32 Debug x64 Release x64 16.0 Win32Proj {3ca188f3-e511-486c-ac28-ccfc6d893861} libtts 10.0 DynamicLibrary true v143 Unicode DynamicLibrary true v143 Unicode DynamicLibrary false v143 true Unicode DynamicLibrary false v143 true Unicode DynamicLibrary true v143 Unicode StaticLibrary true v143 Unicode DynamicLibrary true v143 Unicode DynamicLibrary true v143 Unicode DynamicLibrary true v143 Unicode DynamicLibrary true v143 Unicode StaticLibrary true v143 Unicode DynamicLibrary false v143 true Unicode StaticLibrary false v143 true Unicode $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)Lib\OnnxRuntimeDmlProvider\build\native\include;$(SolutionDir)libtts\Modules\Lib\World\src\world;$(SolutionDir)libtts\Modules\Lib\MJson $(SolutionDir)$(Platform)\libtts\$(Configuration)\ Level3 true WIN32;_DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true Use pch.h Windows true false Level3 true WIN32;_DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true Use pch.h Windows true false Level3 true true true WIN32;NDEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true Use pch.h Windows true true true false Level3 true true true WIN32;NDEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true Use pch.h Windows true true true false Level3 true _DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp17 Windows true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) Level3 true _DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 Windows true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) Level3 true _DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 Windows true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) Level3 true _DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 Windows true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) Level3 true _DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 Windows true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) Level3 true _DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 Windows true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) Level3 true _DEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp17 Windows true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) Level3 true true true NDEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp17 Windows true true true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) Level3 true true true NDEBUG;LIBTTS_EXPORTS;_WINDOWS;_USRDLL;MOEVSDMLPROVIDER;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp17 Windows true true true false $(SolutionDir)Lib\OnnxRuntimeDmlProvider\runtimes\win-x64\native onnxruntime.lib;%(AdditionalDependencies) ================================================ FILE: libtts/libtts.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {78781af4-e3e2-4221-a154-66b35a25e8e1} {e7aebf36-79a7-4eeb-9160-eb766cd45777} {68b44bd5-6d9a-45b6-93fd-159704b20e49} {4ae442dd-0ced-40c1-92fb-78b171577cd2} {95907600-9031-43ba-b3ac-20dd1d9f39fe} {d9fd3421-73d0-40ce-8069-dfb762113415} 头文件 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Core 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Lib 头文件\Api 源文件 源文件\Core 源文件\Core 源文件\Core 源文件\Core 源文件\Core 源文件\Core 源文件\Core 源文件\Core 源文件\Core 源文件\Core 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Lib 源文件\Api ================================================ FILE: test.json ================================================ [ { "Tokens": "私は誰?", "Seq": ["w", "a", "t", "a", "s", "h", "i", "w", "a", "d", "a", "r", "e", "?"], "Tones": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "Durations": [2, 5, 2, 5, 2, 2, 5, 2, 5, 2, 5, 2, 5], "Language": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "SpeakerMix": [1.000000, 0.000000, 0.000000], "EmotionPrompt": ["sad", "happy"], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 114514, "SpeakerId": 2, "RestTime": 1.000000, "Seed": 1919810, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は鳴瀬しろは", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [], "EmotionPrompt": [], "NoiseScale": 0.666000, "LengthScale": 1.000000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 1145147, "Seed": 1919810, "SpeakerId": 0, "RestTime": 1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は誰?", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [0.666000, 0.233000, 0.444000], "EmotionPrompt": ["sad", "happy"], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 1145145, "Seed": 19198101, "SpeakerId": 1, "RestTime": -1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は誰?", "Seq": ["w", "a", "t", "a", "s", "h", "i", "w", "a", "d", "a", "r", "e", "?"], "Tones": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "Durations": [2, 5, 2, 5, 2, 2, 5, 2, 5, 2, 5, 2, 5], "Language": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "SpeakerMix": [1.000000, 0.000000, 0.000000], "EmotionPrompt": ["sad", "happy"], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 114514, "Seed": 1919810, "SpeakerId": 2, "RestTime": 1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は鷗です、くみの名前は?", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [], "EmotionPrompt": [], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.222000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 114514, "Seed": 1919810, "SpeakerId": 3, "RestTime": 1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は鳴瀬しろは", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [], "EmotionPrompt": [], "NoiseScale": 0.666000, "LengthScale": 1.000000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 1145147, "Seed": 1919810, "SpeakerId": 0, "RestTime": 1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は誰?", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [0.666000, 0.233000, 0.444000], "EmotionPrompt": ["sad", "happy"], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.333000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 1145145, "Seed": 19198101, "SpeakerId": 1, "RestTime": -1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" }, { "Tokens": "私は鷗です、くみの名前は?", "Seq": [], "Tones": [], "Durations": [], "Language": [], "SpeakerMix": [], "EmotionPrompt": [], "NoiseScale": 0.666000, "LengthScale": 1.100000, "DurationPredictorNoiseScale": 0.222000, "FactorDpSdp": 0.600000, "GateThreshold": 0.777000, "MaxDecodeStep": 114514, "Seed": 1919810, "SpeakerId": 3, "RestTime": 1.000000, "PlaceHolderSymbol": "|", "LanguageID": "JP", "G2PAdditionalInfo": "/[Japanese2]" } ]